Project import generated by Copybara. GitOrigin-RevId: 2eacec50a75dba903a1f592d753e2fbbf61ec06e
diff --git a/.pre-commit-config.beta.yaml b/.pre-commit-config.beta.yaml new file mode 100644 index 0000000..0b9d17f --- /dev/null +++ b/.pre-commit-config.beta.yaml
@@ -0,0 +1,71 @@ +# See go/cast-pre-commit for details +default_language_version: + python: python3 +repos: +- hooks: + - args: [--root, ../chromium/src, --target, chromecast/internal, --extra-repos, chromecast/internal] + + id: check-deps + name: chromium-src-check-deps + - args: [--root, ../chromium/src, --target, libinteraction, --extra-repos, libinteraction, + --extra-repos, libinteraction/shared] + + id: check-deps + name: libinteraction-check-deps + repo: sso://nest-source-internal.git.corp.google.com/hooks/check-deps + rev: '1.2' +- hooks: + - args: [--chromium-buildtools-path, ../chromium/src/buildtools] + + id: clang-format + repo: sso://nest-source-internal.git.corp.google.com/hooks/clang-format + rev: '2.4' +- hooks: + - args: [--diff-only] + + id: cpp-blacklist + repo: sso://nest-source-internal.git.corp.google.com/hooks/cpp-blacklist + rev: '1.2' +- hooks: + - args: [] + + id: cpplint + repo: sso://nest-source-internal.git.corp.google.com/hooks/cpplint + rev: '1.2' +- hooks: + - id: eureka-commit-message-check + stages: + - commit-msg + repo: sso://nest-source-internal.git.corp.google.com/hooks/eureka-commit-message-check + rev: '1.4' +- hooks: + - id: eureka-prepare-commit-message + stages: + - prepare-commit-msg + repo: sso://nest-source-internal.git.corp.google.com/hooks/eureka-prepare-commit-message + rev: '1.4' +- hooks: + - id: json-format-check + - id: xml-format-check + repo: sso://nest-source-internal.git.corp.google.com/hooks/file-format-check + rev: '0.2' +- hooks: + - args: [../chromium/src] + + id: gn-check + name: gn-check-default + - args: [--args, is_chromecast=true chromecast_branding="internal" is_cast_audio_only=true, + ../chromium/src] + + id: gn-check + name: gn-check-audioonly + repo: sso://nest-source-internal.git.corp.google.com/hooks/gn-check + rev: '0.2' +- hooks: + - id: gn-format + repo: sso://nest-source-internal.git.corp.google.com/hooks/gn-format + rev: '1.6' +- hooks: + - id: pylint + repo: sso://nest-source-internal.git.corp.google.com/hooks/pylint + rev: '2.0'
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 0000000..d4b5249 --- /dev/null +++ b/.pre-commit-config.yaml
@@ -0,0 +1,78 @@ +# See go/cast-pre-commit for details +default_language_version: + python: python3 +repos: +- hooks: + - args: [--root, ../chromium/src, --target, chromecast/internal, --extra-repos, chromecast/internal] + + id: check-deps + name: chromium-src-check-deps + stages: + - push + repo: sso://nest-source-internal.git.corp.google.com/hooks/check-deps + rev: '1.3' +- hooks: + - args: [] + + id: clang-format + repo: sso://nest-source-internal.git.corp.google.com/hooks/clang-format + rev: '3.4' +- hooks: + - args: [] + + id: cpp-blacklist + repo: sso://nest-source-internal.git.corp.google.com/hooks/cpp-blacklist + rev: '2.4' +- hooks: + - args: [] + + id: cpplint + repo: sso://nest-source-internal.git.corp.google.com/hooks/cpplint + rev: '1.4' +- hooks: + - id: eureka-commit-message-check + stages: + - commit-msg + repo: sso://nest-source-internal.git.corp.google.com/hooks/eureka-commit-message-check + rev: '1.9' +- hooks: + - id: eureka-prepare-commit-message + stages: + - prepare-commit-msg + repo: sso://nest-source-internal.git.corp.google.com/hooks/eureka-prepare-commit-message + rev: '1.5' +- hooks: + - id: json-format-check + - id: xml-format-check + repo: sso://nest-source-internal.git.corp.google.com/hooks/file-format-check + rev: '0.4' +- hooks: + - args: [--args, import("//chromecast/internal/build/args/config/precommit/all.gni"), ../chromium/src] + + id: gn-check + name: gn-check-default + stages: + - push + - args: [--args, import("//chromecast/internal/build/args/config/precommit/audio-only.gni"), + ../chromium/src] + + id: gn-check + name: gn-check-audioonly + stages: + - push + repo: sso://nest-source-internal.git.corp.google.com/hooks/gn-check + rev: '2.2' +- hooks: + - id: gn-format + repo: sso://nest-source-internal.git.corp.google.com/hooks/gn-format + rev: '2.0' +- hooks: + - id: pylint + repo: sso://nest-source-internal.git.corp.google.com/hooks/pylint + rev: '2.2' +- hooks: + - id: precommit-message-preservation + stages: + - prepare-commit-msg + repo: sso://nest-source-internal.git.corp.google.com/hooks/precommit-message-preservation + rev: '1.3'
diff --git a/__init__.py b/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/__init__.py
diff --git a/build/__init__.py b/build/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/build/__init__.py
diff --git a/build/get_latest_build.py b/build/get_latest_build.py new file mode 100755 index 0000000..a38d2cd --- /dev/null +++ b/build/get_latest_build.py
@@ -0,0 +1,905 @@ +"""Script to identify the latest build number for testing. + +This script is called before each test to identify the latest build number and +path to the latest build zip file. + +By default, we find the common set of two build flavors (eng and user) and then +search for a good build hint from the greatest build number, once such hint is +found, the build number will be returned. + +Two types of build hints are currently in-place: +1. (post-unit-test) good_to_test hint is created after unit test completion +(regardless test pass or fail). It is used by regular test. +2. (pre-unit-test) test_deps.zip hint is created when OTA and test binaries are +successfully produced. It is used by unit test. + +Typical usages: +1. Get good build for regular test: + get_latest_build.py --output_mode="number" --branch=1.8 --product=anchovy +2. Get a good build for unit test: + get_latest_build.py --output_mode="number" --branch=1.8 --product=anchovy +--flavor=eng --build_triangulation_list=eng --use_unit_test_hint +3. Get a good build for unit test and claim it (no one will get this build) + get_latest_build.py --output_mode="number" --branch=1.8 --product=anchovy +--flavor=eng --build_triangulation_list=eng --use_unit_test_hint +--claim_unit_test_hint + +One the build is clained, the hint file name will change and will not be +discovered by another build searcher. +""" + +import datetime +import optparse +import os +import random +import re +import subprocess +import sys +import tempfile +import time + +__author__ = 'billiani@google.com (Leonardo Billiani)' + +# Commands to list the build zip files: +# Eg. path: gs://gtv-te/internal/gtv-3.0/cosmo-tests/32908/cosmo-tests-32908.zip +GS_LIST_BUILDS_CMD = 'gsutil ls gs://%s/%s/%s-%s/%s/%s' +# gs://gtv-eureka/internal/1.28f/biggie-eng/100872/factory/biggie-fct-100872.zip +GS_LIST_FCT_BUILDS_CMD = 'gsutil ls gs://%s/%s/%s-%s/%s/factory/%s' +OTA_FILE_PATTERN = '%s-%s-%s.zip' +OTA_FILE_PATTERN_WITH_BOARD = '%s-%s-%s-%s.zip' +GS_COPY_BUILD_CMD = 'gsutil cp %s %s' + +# Path to marker file +GS_LIST_FILE = 'gsutil ls gs://%s/%s/%s-%s/%s/%s' + +# Rename marker file +GS_MV_MARKER_CMD = 'gsutil mv %s %s' + +# Regex to extract build number from a build zip path: +# Eg. 32 from gs://gtv-te/internal/gtv-3.0/cosmo-tests/32/cosmo-tests-32.zip +BUILD_NUMBER_RE = re.compile(r'\/(\d+)\/') + +# Supported "flavors" and "output type" of build: +BUILD_FLAVORS = { + 'darcy': 'arm', + 'eng': 'eng', + 'eng-clang': 'eng-clang', + 'fugu': 'x86', + 'imx7d_pico': 'arm', + 'molly': 'arm', + 'tests': 'tests', + 'user': 'user'} + +BUILD_OUTPUT_TYPES = { + 'fct': 'fct', + 'ota': 'ota', + 'symbols': 'symbols', + 'tests': 'tests'} + +# Chromecast Product Cloud Storage Bucket +PRODUCT_GCS_BUCKET = 'gtv-eureka' + +# Chromecast Unit Test Binary Cloud Storage Bucket +UNIT_TEST_GCS_BUCKET = 'chromecast-unit-test' + +# Root repositories for different products +PRODUCT_ROOT_REPOSITORY = { + 'anchovy': '%s/internal' % PRODUCT_GCS_BUCKET, + 'androidtv': '%s/internal' % PRODUCT_GCS_BUCKET, + 'androidthings': '%s/internal' % PRODUCT_GCS_BUCKET, + 'assistantdefault': '%s/internal' % PRODUCT_GCS_BUCKET, + 'audiodefault': '%s/cast_audio_reference' % PRODUCT_GCS_BUCKET, + 'biggie': '%s/internal' % PRODUCT_GCS_BUCKET, + 'bubbletea': '%s/cast_tv_mstar' % PRODUCT_GCS_BUCKET, + 'chorizo': '%s/internal' % PRODUCT_GCS_BUCKET, + 'dragonfly': '%s/cast_tv' % PRODUCT_GCS_BUCKET, + 'estelle': '%s/internal' % PRODUCT_GCS_BUCKET, + 'firefly': '%s/cast_tv' % PRODUCT_GCS_BUCKET, + 'guabao': '%s/cast_tv_mstar' % PRODUCT_GCS_BUCKET, + 'Mars_US': '%s/cast_tv_mediatek' % PRODUCT_GCS_BUCKET, + 'mozart': '%s/cast_audio_new' % PRODUCT_GCS_BUCKET, + 'mushroom': '%s/internal' % PRODUCT_GCS_BUCKET, + 'N00007': '%s/cast_tv_novatek' % PRODUCT_GCS_BUCKET, + 'np8340': '%s/cast_audio_new' % PRODUCT_GCS_BUCKET, + 'pepperoni': '%s/internal' % PRODUCT_GCS_BUCKET, + 'pineapple': '%s/internal' % PRODUCT_GCS_BUCKET, + 'redwood': '%s/cast_tv_marvell' % PRODUCT_GCS_BUCKET, + 'salami': '%s/internal' % PRODUCT_GCS_BUCKET, + 'steak': '%s/internal' % PRODUCT_GCS_BUCKET, + 'sullivan': '%s/cast_audio_new' % PRODUCT_GCS_BUCKET, + 'suncake': '%s/cast_tv_mstar' % PRODUCT_GCS_BUCKET, + 'taroball': '%s/cast_tv_mstar' % PRODUCT_GCS_BUCKET, + 'wutang': '%s/cast_audio_new' % PRODUCT_GCS_BUCKET} +UNIT_TEST_ROOT_REPOSITORY = { + 'anchovy': '%s/internal' % UNIT_TEST_GCS_BUCKET, + 'assistantdefault': '%s/internal' % UNIT_TEST_GCS_BUCKET, + 'audiodefault': '%s/cast_audio_reference' % UNIT_TEST_GCS_BUCKET, + 'biggie': '%s/internal' % UNIT_TEST_GCS_BUCKET, + 'bubbletea': '%s/cast_tv_mstar' % UNIT_TEST_GCS_BUCKET, + 'chorizo': '%s/internal' % UNIT_TEST_GCS_BUCKET, + 'default': '%s/internal' % UNIT_TEST_GCS_BUCKET, + 'dragonfly': '%s/cast_tv' % UNIT_TEST_GCS_BUCKET, + 'estelle': '%s/internal' % UNIT_TEST_GCS_BUCKET, + 'firefly': '%s/cast_tv' % UNIT_TEST_GCS_BUCKET, + 'guabao': '%s/cast_tv_mstar' % UNIT_TEST_GCS_BUCKET, + 'Mars_US': '%s/cast_tv_mediatek' % UNIT_TEST_GCS_BUCKET, + 'mozart': '%s/cast_audio_new' % UNIT_TEST_GCS_BUCKET, + 'mushroom': '%s/internal' % UNIT_TEST_GCS_BUCKET, + 'N00007': '%s/cast_tv_novatek' % UNIT_TEST_GCS_BUCKET, + 'np8340': '%s/cast_audio_new' % UNIT_TEST_GCS_BUCKET, + 'pepperoni': '%s/internal' % UNIT_TEST_GCS_BUCKET, + 'pineapple': '%s/internal' % UNIT_TEST_GCS_BUCKET, + 'redwood': '%s/cast_tv2' % UNIT_TEST_GCS_BUCKET, + 'salami': '%s/internal' % UNIT_TEST_GCS_BUCKET, + 'steak': '%s/internal' % UNIT_TEST_GCS_BUCKET, + 'sullivan': '%s/cast_audio_new' % UNIT_TEST_GCS_BUCKET, + 'suncake': '%s/cast_tv_mstar' % UNIT_TEST_GCS_BUCKET, + 'taroball': '%s/cast_tv_mstar' % UNIT_TEST_GCS_BUCKET, + 'wutang': '%s/cast_audio_new' % UNIT_TEST_GCS_BUCKET} + +STD_ROOT_REPOSITORY = 'gtv-te' + +# Run modes for this script: +OUTPUT_MODES = {'path': 'path', 'number': 'number'} + +# Supported tablet models: +TABLETS = ['xoomtablet', 'nexus10tablet'] + +# Supported Android products: +ANDROID_PRODUCTS = ['androidtv', 'androidthings', 'soba'] + +# Build flavor list is used to triangulate a good build. For example, by +# default, we get the greatest common build number from both eng and user +# build. +DEFAULT_TRIANGULATION_LIST = ( + ' '.join([BUILD_FLAVORS['eng'], BUILD_FLAVORS['user']])) + +# List of repositories that only build eng flavor +ENG_ONLY_REPOSITORY_LIST = ['chromium_tot'] + +# A good build marker file is generated when a build can finish unit test. +GOOD_BUILD_MARKER = 'good_to_test' + +# Directory with all the test identifiers +TEST_IDENTIFIER_DIR = 'run_identifiers' + +# Run identifiers path +IDS_REPOSITORY = 'fragglerock/%s' % TEST_IDENTIFIER_DIR + +# Unit test marker is the zip file which is used for unit test slaves. +UNIT_TEST_MARKER_DIR = 'gs://%s/%s/%s-%s/%s/' +UNIT_TEST_MARKER = 'test_deps.tar.gz' +CLAIMED_UNIT_TEST_MARKER = 'test_deps_claimed.tar.gz' + +BAD_BUILD_NUMBER = '0' +RANDOM_BACKOFF_SECS = 60 +DEFAULT_MAX_BUILD_LIST_LEN = 50 + +# Cast OTA file name override +# Key=hardware-type, Value=OTA-file-name +CAST_OTA_OVERRIDE_DICT = { + 'bubbletea': 'usb.bin', + 'guabao': 'usb.bin', + 'Mars_US': 'upgrade_loader_no_perm_data.pkg', + 'mozart': 'mozart-b2-ota.zip', + 'N00007': 'update.img', + 'np8340': '8506_linux_demo_dbg.bin', + 'sullivan': '8580_linux_demo_dbg.bin', + 'suncake': 'usb.bin', + 'taroball': 'usb.bin', + 'wutang': '8507_linux_demo_dbg.bin'} + +# Assumption: all products should have eng builds +# Overrides the triangulation list for products without user builds. +TRIANGULATION_OVERRIDE_DICT = { + 'bubbletea': 'eng', + 'dragonfly': 'eng', + 'guabao': 'eng', + 'Mars_US': 'eng', + 'mozart': 'eng', + 'N00007': 'eng', + 'np8340': 'eng', + 'sullivan': 'eng', + 'suncake': 'eng', + 'taroball': 'eng', + 'wutang': 'eng'} + +# Options for the build selection policy. +ALWAYS_USE_LATEST = 'always_use_latest' +BACKTRACK_THEN_LATEST = 'backtrack_then_latest' +ONLY_BACKTRACK = 'only_backtrack' +SECOND_TO_LATEST = 'second_to_latest' +BUILD_SELECTION_POLICIES = [ + ALWAYS_USE_LATEST, + BACKTRACK_THEN_LATEST, + ONLY_BACKTRACK, + SECOND_TO_LATEST +] +DEFAULT_BUILD_SELECTION_POLICY = ONLY_BACKTRACK + + +def ParseFlags(): + """Parses command line flags.""" + parser = optparse.OptionParser() + parser.add_option('--branch', + default='master', + help='branch to get latest build number') + parser.add_option('--product', + help='product to get latest build number') + parser.add_option('--build_output_type', + default=BUILD_OUTPUT_TYPES['ota'], + type='choice', + choices=list(BUILD_OUTPUT_TYPES.keys()), + help=str(list(BUILD_OUTPUT_TYPES.keys()))) + parser.add_option('--build_number', + help='build number') + parser.add_option('--build_output_path', + default='', + help=('Complete path to where the build file is copied')) + parser.add_option('--output_mode', + type='choice', + choices=list(OUTPUT_MODES.keys()), + help=str(list(OUTPUT_MODES.keys()))) + parser.add_option('--flavor', + default=BUILD_FLAVORS['eng'], + type='choice', + choices=list(BUILD_FLAVORS.keys()), + help=str(list(BUILD_FLAVORS.keys()))) + parser.add_option('--build_triangulation_list', + default=DEFAULT_TRIANGULATION_LIST, + help='list of flavors used to determine latest build') + parser.add_option('--use_unit_test_hint', + action='store_true', + default=False, + help='Use unit test zip file as marker for a good build') + parser.add_option('--claim_unit_test_hint', + action='store_true', + default=False, + help='Change the unit test marker file name if True') + parser.add_option('--board_type', + default='none', + help='Chromecast device board type, e.g. lexx-b3') + parser.add_option('--repo_alias', + default='', + help='Repository alias, e.g. internal or partner') + parser.add_option('--test_identifier', + default='', + help=('Test identifier from buildbot. If specified, ' + 'it gets the latest non tested build.')) + parser.add_option('--use_gn', + default=1, + type=int, + help=('Positive integers for using GN; otherwise, no GN.')) + parser.add_option('--build_selection_policy', + type='choice', + choices=[ALWAYS_USE_LATEST, + BACKTRACK_THEN_LATEST, + ONLY_BACKTRACK, + SECOND_TO_LATEST], + default=ONLY_BACKTRACK, + help=('Defines the policy to select a build depending ' + 'on if it\'s been tested or not. ' + '"%s" chooses the latest build, whether it\'s ' + 'been tested or not. ' + '"%s" chooses that latest non-tested build ' + 'or the latest available if all have been tested. ' + '"%s" chooses that latest non-tested build ' + 'and exits with failure if all have been tested. ' + '"%s" chooses the second to latest good build. ' + 'Default: %%default' + % (ALWAYS_USE_LATEST, + BACKTRACK_THEN_LATEST, + ONLY_BACKTRACK, + SECOND_TO_LATEST))) + parser.add_option('--max_build_selection_range', + default=DEFAULT_MAX_BUILD_LIST_LEN, + type=int, + help=('Maximum number of builds to be used in build ' + 'selection process. This flag is used in conjunction ' + 'with build_selection_policy')) + parser.add_option('-v', + action='store_true', + default=False, + help='Run in unit test mode') + (flags, _) = parser.parse_args() + if flags.v: + return None + if not flags.output_mode: + parser.print_help() + sys.exit() + if flags.build_number and flags.output_mode == 'build': + parser.print_help() + sys.exit() + return flags + + +test_exit = subprocess.call('gsutil ls &> /dev/null', shell=True) +if test_exit: + print('gsutil not available') + sys.exit() + + +class AndroidTvBuildHelper(object): + """Class to handle Android TV builds.""" + # Cloud Storage location (this is pre-defined) + GS_PREFIX = 'gs://%s' % UNIT_TEST_ROOT_REPOSITORY['default'] + # Product Cast Shell APK location + GS_APK_PREFIX = 'gs://%s' % PRODUCT_ROOT_REPOSITORY['androidtv'] + # Cast Shell APK file pattern + CAST_SHELL_APK = 'CastShellInternal-*-%s.apk' + # List command + GS_LIST_CMD = 'gsutil ls' + + # Supported flavors: x86 for Fugu and arm for Molly. + SUPPORTED_FLAVOR = ['x86', 'arm'] + # Supported scope: internal or public + SUPPORTED_SCOPE = ['internal', 'public'] + + def __init__(self, product='androidtv', use_gn=1): + """Constructor.""" + self._product = product + self._gn_dir_suffix = self._GetGnDirSuffix(use_gn) + + def _GetGnDirSuffix(self, use_gn): + """Returns gn directory suffix.""" + if use_gn <= 0: + return '' + return '_gn' + + def _GetGsDirPattern(self): + """Returns GCS directory pattern.""" + return '%s/%s/content_shell_'+ self._product + '_%s_%s%s/*/%s' + + def GetLatestBuildNumber(self, + branch, + flavor, + claim_hint=True, + test_identifier='', + scope='internal'): + """Returns the most recent un-test build number. + + Args: + branch: String of branch name, e.g. unfork_m37. + flavor: String for device flavor, e.g. fugu or molly. + claim_hint: Optional boolean if a hint needs to be claimed. + test_identifier: Optional string for test complete hint. + scope: Optional string for scope defined, interna or public. + + Returns: + String: of the most recent build number. + """ + build_to_return = 0 + if claim_hint: + gs_prefix = self.GS_PREFIX + marker = UNIT_TEST_MARKER + else: + gs_prefix = self.GS_APK_PREFIX + marker = GOOD_BUILD_MARKER + search_dir = self._GetGsDirPattern() % (gs_prefix, + branch, + BUILD_FLAVORS[flavor], + scope, + self._gn_dir_suffix, + marker) + gs_list_cmd = ' '.join([self.GS_LIST_CMD, search_dir]) + output = _Execute(gs_list_cmd) + get_build_num_regex = re.compile(search_dir.replace('*', r'(\d+)')) + search_dir_list = sorted( + output.split(), reverse=True)[:DEFAULT_MAX_BUILD_LIST_LEN] + for line in search_dir_list: # pylint: disable=too-many-nested-blocks + match = get_build_num_regex.search(line) + if match: + if match.group(1) > build_to_return: + if not test_identifier: + build_to_return = match.group(1) + else: + # Check if the test was completed already + if test_identifier and not claim_hint: + test_name = test_identifier.split('#')[0] + is_tested_cmd = GS_LIST_FILE % ( + IDS_REPOSITORY, + branch, + flavor, + 'eng', + match.group(1), + os.path.join(TEST_IDENTIFIER_DIR, test_name + '*')) + if not _Execute(is_tested_cmd): + build_to_return = match.group(1) + + return str(build_to_return) + + def ClaimBuildNumber(self, + build_number, + branch, + flavor='fugu', + scope='internal'): + """Renames the test zip file. + + Args: + build_number: String containing a build number. + branch: String of branch name, e.g. unfork_m37. + flavor: String for device flavor, e.g. arm or x86. + scope: String for scope defined, interna or public. + """ + path_pattern = self._GetGsDirPattern().replace('*', build_number) + original_test_file = ( + path_pattern % (self.GS_PREFIX, + branch, + BUILD_FLAVORS[flavor], + scope, + self._gn_dir_suffix, + UNIT_TEST_MARKER)) + claimed_test_file = ( + path_pattern % (self.GS_PREFIX, + branch, + BUILD_FLAVORS[flavor], + scope, + self._gn_dir_suffix, + CLAIMED_UNIT_TEST_MARKER)) + _Execute(GS_MV_MARKER_CMD % (original_test_file, claimed_test_file)) + + def GetBuildPath(self, + build_number, + branch, + flavor='fugu', + scope='internal', + claim_hint=True): + """Renames the test zip file. + + Args: + build_number: String containing a build number. + branch: String of branch name, e.g. unfork_m37. + flavor: Optional string for device flavor, e.g. fugu or molly. + scope: Optional string for scope defined, interna or public. + claim_hint: Optional boolean if build hint needs to be claimed. + + Returns: + String: of path to the claimed test zip file. + """ + if claim_hint: + gs_prefix = self.GS_PREFIX + marker = CLAIMED_UNIT_TEST_MARKER + else: + gs_prefix = self.GS_APK_PREFIX + marker = self.CAST_SHELL_APK % BUILD_FLAVORS[flavor] + path_pattern = self._GetGsDirPattern() % (gs_prefix, + branch, + BUILD_FLAVORS[flavor], + scope, + self._gn_dir_suffix, + marker) + + return path_pattern.replace('*', build_number) + + +def _Execute(command, exit_on_stderr=False): + """Executes given command and returns stdout string.""" + proc = subprocess.Popen( + command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + stdoutdata, stderrdata = proc.communicate() + if exit_on_stderr: + error_message_list = ( + ['CommandException', + 'InvalidUriError', + 'GSResponseError']) + for error_message in error_message_list: + if error_message in stderrdata: + raise IOError('%s: %s' % (command, stderrdata)) + return stdoutdata + + +def GetRepoGcsRootPath(product, repo_alias=''): + """Returns Cloud Storage root path for a given product.""" + # If repository alias is provided, use it for the GCS root + # Otherwise, look it up from the pre-defined product list + if repo_alias: + root_path = '%s/%s' % (PRODUCT_GCS_BUCKET, repo_alias) + else: + root_path = PRODUCT_ROOT_REPOSITORY.get(product, STD_ROOT_REPOSITORY) + + return root_path + + +def GetUnitTestGcsRootPath(product, repo_alias=''): + """Returns Unit Test Cloud Storage root path for a given product.""" + # If repository alias is provided, use it for the GCS root + # Otherwise, look it up from the pre-defined product list + if repo_alias: + root_path = '%s/%s' % (UNIT_TEST_GCS_BUCKET, repo_alias) + else: + root_path = UNIT_TEST_ROOT_REPOSITORY.get(product, + UNIT_TEST_ROOT_REPOSITORY['default']) + + return root_path + + +def GetListBuildsCommand(**kwargs): + """Returns command to list builds matching the given parameters. + + Args: + **kwargs: Key/Value dictionary containing values for: + branch, product, build_number, flavor, build_output_type. + + Returns: + String containing command to list the builds. + """ + if not kwargs.get('build_number'): + kwargs['build_number'] = '[0-9]*' + + kwargs['root_path'] = GetRepoGcsRootPath( + kwargs['product'], + kwargs.get('repo_alias')) + ota_file_name = '' + if kwargs and kwargs.get('board_type') != 'none': + ota_file_name = OTA_FILE_PATTERN_WITH_BOARD % ( + kwargs['product'], + kwargs['build_output_type'], + kwargs.get('board_type'), + kwargs['build_number']) + else: + ota_file_name = OTA_FILE_PATTERN % ( + kwargs['product'], + kwargs['build_output_type'], + kwargs['build_number']) + # Override the OTA file name for specific devices (which don't use OTA zip). + if kwargs.get('product') in CAST_OTA_OVERRIDE_DICT.keys(): + ota_file_name = CAST_OTA_OVERRIDE_DICT[kwargs['product']] + + list_cmd_fmt = GS_LIST_BUILDS_CMD + # Override the command when OTA output type is fct for factory build. + if kwargs and kwargs.get('build_output_type') == 'fct': + list_cmd_fmt = GS_LIST_FCT_BUILDS_CMD + list_cmd = list_cmd_fmt % ( + kwargs['root_path'], + kwargs['branch'], + kwargs['product'], + kwargs['flavor'], + kwargs['build_number'], + ota_file_name) + + return list_cmd + + +def GetBuildsListByFlavor(repo_alias, branch, product, flavor, board_type): + """Returns list of eng build paths matching the specified parameters.""" + return _Execute( + GetListBuildsCommand( + repo_alias=repo_alias, + branch=branch, + product=product, + flavor=flavor, + build_output_type=BUILD_OUTPUT_TYPES['ota'], + board_type=board_type)).split() + + +def ToBuildNumber(build_path): + """Returns a build number for the build zip at build_path. + + If a build number can not be parsed, 0 is returned. + + Args: + build_path: String containing build file path. + + Returns: + String containing the build number. + """ + match = BUILD_NUMBER_RE.search(build_path) + if match: + return match.group(1) + return '0' + + +def _IsBuildMarked(command_pattern, build_num, marker_file_name): + """Executes the command and returns if the marker is in stdout.""" + command = command_pattern % (build_num, marker_file_name) + stdout = _Execute(command) + return marker_file_name in stdout + + +def _IsBuildTested(has_been_tested_cmd, build_num): + """Executes the command and returns if the test ID is in stdout.""" + if not has_been_tested_cmd: + return False + command = has_been_tested_cmd % (build_num) + stdout = _Execute(command) + # Only match the first part of the test_identifier + test_name = FLAGS.test_identifier.split('#')[0] + return test_name in stdout + + +def GetBuildNumberWithMarker( + build_number_list, + command_pattern, + marker_file_name=GOOD_BUILD_MARKER, + has_been_tested_cmd='', + build_selection_policy=DEFAULT_BUILD_SELECTION_POLICY, + max_build_selection_range=DEFAULT_MAX_BUILD_LIST_LEN): + """Iterates all the builds and returns the greatest number. + + Examine the build number list from high to low, if a marker file is found, + return that build number. + + Args: + build_number_list: List containing builds in integers. + command_pattern: String containing command with build number to replace. + marker_file_name: Optional string containing the marker file name. + has_been_tested_cmd: String with the command to verify the test did not run. + build_selection_policy: The policy used to select the build. + max_build_selection_range: The maximum number of builds to be used for + build selection process. + + Returns: + String: build number found or zero if not found. + """ + is_good = lambda n: _IsBuildMarked(command_pattern, n, marker_file_name) + is_tested = lambda n: _IsBuildTested(has_been_tested_cmd, n) + if isinstance(build_number_list, list): + build_nums = sorted( + build_number_list, reverse=True)[:max_build_selection_range] + first_good = None + for build_num in build_nums: + if not is_good(build_num): + continue + tested = is_tested(build_num) + if first_good: + if not tested and build_selection_policy == SECOND_TO_LATEST: + return str(build_num) + else: + first_good = build_num + if build_selection_policy == ALWAYS_USE_LATEST: + return str(build_num) + if not tested and build_selection_policy != SECOND_TO_LATEST: + return str(build_num) + if build_selection_policy == BACKTRACK_THEN_LATEST and first_good: + return str(first_good) + return str(BAD_BUILD_NUMBER) + + +def ClaimBuildNumber(repo_alias, branch, product, flavor, build_number): + """Returns the good build number after claimed; or zero if fails to claim. + + Claim the build by changing the zip file name + However, if the claim fails, we will return 0 to indicate an error. + + Args: + repo_alias: String containing repository alias (e.g. internal/partner). + branch: String containing branch name (e.g. unfork_m37). + product: String containing product name (e.g. anchovy). + flavor: String containing one particular build flavor (e.g. eng). + build_number: String containing the build number (e.g. 19219). + + Returns: + String: build_number value if claim is successful; otherwise, zero. + """ + good_build_num = build_number + unit_test_root_repo = GetUnitTestGcsRootPath(product, repo_alias) + hint_path_pattern = UNIT_TEST_MARKER_DIR % ( + unit_test_root_repo, + branch, + product, + flavor, + good_build_num) + '%s' + original_hint_path = hint_path_pattern % UNIT_TEST_MARKER + claimed_hint_path = hint_path_pattern % CLAIMED_UNIT_TEST_MARKER + mv_cmd = GS_MV_MARKER_CMD % (original_hint_path, claimed_hint_path) + try: + _Execute(mv_cmd, exit_on_stderr=True) + except IOError: + good_build_num = '0' + return good_build_num + + +def GetLatestBuildNumber(repo_alias, branch, product, + triangulation_list=DEFAULT_TRIANGULATION_LIST, + flavor=BUILD_FLAVORS['eng'], board_type='', + build_selection_policy=DEFAULT_BUILD_SELECTION_POLICY, + max_build_selection_range=DEFAULT_MAX_BUILD_LIST_LEN): + """Prints latest successful build number for given branch and product. + + By default, take pre-cautions by cross examining two flavors (eng and user) + to determine a common latest build. However, it allows to use one flavor. + + Args: + repo_alias: String containing repository alias (e.g. internal/partner). + branch: String containing branch name (e.g. unfork_m37). + product: String containing product name (e.g. anchovy). + triangulation_list: Optional string containing flavor names separated + by spaces. + flavor: Optional string containing one particular build flavor (e.g. eng). + board_type: Optional string for device board type. + build_selection_policy: The policy used to select the build. + max_build_selection_range: The maximum number of builds to be used for + build selection process. + + Returns: + String: build number value or 0 if no build found. + """ + common_build_numbers = [] + + if product in TRIANGULATION_OVERRIDE_DICT: # pylint: disable=consider-using-get + triangulation_list = TRIANGULATION_OVERRIDE_DICT[product] + + # Special treat eng only repositories + if repo_alias in ENG_ONLY_REPOSITORY_LIST: + triangulation_list = BUILD_FLAVORS['eng'] + + for internal_flavor in triangulation_list.split(): + build_numbers = list(map( + ToBuildNumber, + GetBuildsListByFlavor( + repo_alias, branch, product, internal_flavor, board_type))) + if common_build_numbers: + common_build_numbers = ( + list(set(common_build_numbers) & set(build_numbers))) + else: + common_build_numbers = build_numbers + int_build_numbers = list(map(int, common_build_numbers)) + try: + # A good build should have good_to_test file in bigstore + if product in PRODUCT_ROOT_REPOSITORY: + cloud_storage = GetRepoGcsRootPath(product, repo_alias) + marker_file_name = GOOD_BUILD_MARKER + if FLAGS.use_unit_test_hint: + # Wait for random seconds (0-20) to avoid file operation collision + time.sleep(random.randint(0, RANDOM_BACKOFF_SECS)) + cloud_storage = GetUnitTestGcsRootPath(product, repo_alias) + marker_file_name = UNIT_TEST_MARKER + cmd_pattern = GS_LIST_FILE % (cloud_storage, + branch, + product, + flavor, + '%s', + '%s') + has_been_tested_cmd = '' + + # Only get latest non tested build + if FLAGS.test_identifier: + # Only match the first part of the test_identifier + test_name = FLAGS.test_identifier.split('#')[0] + has_been_tested_cmd = GS_LIST_FILE % (IDS_REPOSITORY, + branch, + product, + flavor, + '%s', + os.path.join( + TEST_IDENTIFIER_DIR, + test_name + '*')) + + good_build_num = GetBuildNumberWithMarker( + int_build_numbers, + cmd_pattern, + marker_file_name, + has_been_tested_cmd, + build_selection_policy=build_selection_policy, + max_build_selection_range=max_build_selection_range) + + if FLAGS.claim_unit_test_hint and good_build_num != BAD_BUILD_NUMBER: + ClaimBuildNumber( + repo_alias, branch, product, flavor, good_build_num) + return good_build_num + return str(int_build_numbers[-1]) + except TypeError: + return BAD_BUILD_NUMBER + + +def GetBuildPath(repo_alias, branch, product, build_number, build_output_type, + flavor, board_type): + """Prints the build path for build number in branch and product specified.""" + build_paths = _Execute( + GetListBuildsCommand( + repo_alias=repo_alias, + branch=branch, product=product, build_number=build_number, + flavor=flavor, build_output_type=build_output_type, + board_type=board_type)).split() + return build_paths[-1] + + +def GetOutputPath(build_path, output_path): + """Returns the output path where the build file is copied. + + Args: + build_path: String containing the bigstore build path (Eg. gs://gtv-te/...). + output_path: String optionally containing location to copy the build to. If + empty, a temp directory path is used. + + Returns: + String containing the correct path where the build should be copied. + + Raises: + IOError: when the path is empty or does not exist + """ + if output_path: + if os.path.isdir(output_path): + raise IOError('Path (%s) must include file name.' % output_path) + return output_path + temp_dir = tempfile.mkdtemp() + return os.path.join(temp_dir, os.path.basename(build_path)) + + +def CopyToDir(build_path, output_path, cp_cmd_template=GS_COPY_BUILD_CMD): + """Copies the given bigstore build_path to the given output_path. + + Args: + build_path: String containing the bigstore build path (Eg. gs://gtv-te/...). + output_path: String containing the location to copy the build to. + cp_cmd_template: Formatting string to interpolate to build the cp command + + Returns: + String containing the location to copy the build to. + """ + _Execute(cp_cmd_template % (build_path, output_path)) + return output_path + + +def main(): + # For tablets, there's not really a valid buildnumber that's useful + # so instead we use a datetime string to specify unique runs + if FLAGS.product in TABLETS: + print(str(datetime.datetime.now().strftime('%d%B%Y%I%M%p'))) + + # TODO(kevinfei): we have too many products and each does not fall into the + # same way to retrieve build. Re-organize this script for the readability + # and long-term maintainability. + # Android TV is a prodcut which needs unit test coverage. Once a build is + # available, test hint (test_deps.zip) will be available in the Cloud + # Storage (e.g. gs://chromecast-unit-test/internal/content_shell_androidtv_ + # x86_internal_gn/19912/test_deps.zip. + # To claim this build, rename the file name to test_deps_claimed.zip. + # When the functional test (e.g. Cast Compliance) starts, the marker file + # will be storage in the Cloud Storage (different bucket though) and the + # test will check for the existence of that file to determine if that build + # should be tested. + elif FLAGS.product in ANDROID_PRODUCTS: + atv_helper = AndroidTvBuildHelper(FLAGS.product, FLAGS.use_gn) + if FLAGS.output_mode == 'path': + claimed_file_path = atv_helper.GetBuildPath( + FLAGS.build_number, + FLAGS.branch, + FLAGS.flavor, + claim_hint=FLAGS.claim_unit_test_hint) + print(CopyToDir(claimed_file_path, FLAGS.build_output_path)) + else: + latest_build = ( + atv_helper.GetLatestBuildNumber( + FLAGS.branch, + FLAGS.flavor, + claim_hint=FLAGS.claim_unit_test_hint, + test_identifier=FLAGS.test_identifier)) + if FLAGS.claim_unit_test_hint and latest_build != BAD_BUILD_NUMBER: + try: + atv_helper.ClaimBuildNumber(latest_build, + FLAGS.branch, + FLAGS.flavor) + except IOError: + latest_build = BAD_BUILD_NUMBER + if latest_build == BAD_BUILD_NUMBER: + exit(1) + else: + print(latest_build) + + else: + if FLAGS.output_mode == 'path': + build_path = GetBuildPath(FLAGS.repo_alias, FLAGS.branch, FLAGS.product, + FLAGS.build_number, FLAGS.build_output_type, + FLAGS.flavor, FLAGS.board_type) + output_path = GetOutputPath(build_path, FLAGS.build_output_path) + print(CopyToDir(build_path, output_path)) + else: + latest_build = GetLatestBuildNumber( + FLAGS.repo_alias, + FLAGS.branch, + FLAGS.product, + triangulation_list=FLAGS.build_triangulation_list, + flavor=FLAGS.flavor, + board_type=FLAGS.board_type, + build_selection_policy=FLAGS.build_selection_policy, + max_build_selection_range=FLAGS.max_build_selection_range) + if latest_build == BAD_BUILD_NUMBER: + exit(1) + else: + print(latest_build) + + +if __name__ == '__main__': + FLAGS = ParseFlags() + main()
diff --git a/build/get_latest_build_test.py b/build/get_latest_build_test.py new file mode 100755 index 0000000..a4d4432 --- /dev/null +++ b/build/get_latest_build_test.py
@@ -0,0 +1,144 @@ +"""Tests for get_latest_build.""" +import unittest + +from build import get_latest_build +from gunittest import gtestcase + +from unittest import mock + + +class GetLatestBuildTest(gtestcase.GTestCase): + + def setUp(self): + self._orig_get_builds = get_latest_build.GetBuildsListByFlavor + self._orig_execute = get_latest_build._Execute + + def tearDown(self): + get_latest_build.GetBuildsListByFlavor = self._orig_get_builds + get_latest_build._Execute = self._orig_execute + + def testToBuildNumber(self): + """Ensures build numbers can be parsed.""" + self.assertEqual( + get_latest_build.ToBuildNumber( + 'gs://gtv-te/internal/gtv-3.0/cosmo-tests/32908/' + 'cosmo-tests-32908.zip'), + '32908') + self.assertEqual( + get_latest_build.ToBuildNumber( + 'gs://gtv-te/internal/gtv-3.0/cosmo-eng/1234/' + 'cosmo-eng-1234.zip'), + '1234') + + def testGetLatestBuild(self): + """Ensures the latest build is returned.""" + fmt = ('gs://gtv-eureka/internal/unfork_m37/anchovy-{1}/{0}' + '/anchovy-ota-{0}.zip') + + get_latest_build.FLAGS = mock.Mock(test_identifier='', + use_unit_test_hint=False, + claim_unit_test_hint=False) + mock_build_output = { + 'eng': [fmt.format(i, 'eng') for i in range(18307, 183012, 2)], + 'user': [fmt.format(i, 'user') for i in [18304, 18305, 18307, 18309]] + } + get_latest_build.GetBuildsListByFlavor = ( + lambda *args: mock_build_output.get(args[3])) + get_latest_build._Execute = mock.Mock( + side_effect=get_latest_build.GOOD_BUILD_MARKER) + get_latest_build.GetBuildNumberWithMarker = lambda x, *_, **__: str(max(x)) + self.assertEqual( + get_latest_build.GetLatestBuildNumber('', 'unfork_m37', 'anchovy'), + '18309') + expected_build = fmt.format(18309, 'user') + get_latest_build._Execute = lambda x: expected_build + self.assertEqual( + get_latest_build.GetBuildPath( + '', 'unfork_m37', 'anchovy', '18309', 'ota', 'user', ''), + expected_build) + + def testExecute(self): + """Ensures execute works.""" + self.assertEqual('foo bar\n', get_latest_build._Execute('echo foo bar')) + + def testGetListCmd(self): + """Ensures the correct list command is built.""" + kwargs = { + 'product': 'anchovy', + 'build_output_type': 'w', + 'board_type': 'x', + 'branch': 'y', + 'flavor': 'z' + } + + self.assertEqual( + get_latest_build.GetListBuildsCommand(**kwargs), + ('gsutil ls gs://gtv-eureka/internal/y/anchovy-z/[0-9]*/' + 'anchovy-w-x-[0-9]*.zip')) + kwargs['build_number'] = 'A' + self.assertEqual( + get_latest_build.GetListBuildsCommand(**kwargs), + 'gsutil ls gs://gtv-eureka/internal/y/anchovy-z/A/anchovy-w-x-A.zip') + kwargs['build_output_type'] = 'fct' + self.assertEqual( + get_latest_build.GetListBuildsCommand(**kwargs), + 'gsutil ls gs://gtv-eureka/internal/y/anchovy-z/A/factory/' + 'anchovy-fct-x-A.zip') + + +class GetBuildNumberWithMarkerTest(gtestcase.GTestCase): + """Tests for the GetBuildNumberWithMarker() function.""" + + def _TestBuildNumberWithMarker( + self, build_numbers, expected_build, build_selection_policy, + build_marked_mock=None, build_tested_mock=None): + """Helper to test GetBuildNumberWithMarker().""" + if build_marked_mock: + get_latest_build._IsBuildMarked = build_marked_mock + if build_tested_mock: + get_latest_build._IsBuildTested = build_tested_mock + latest_build = get_latest_build.GetBuildNumberWithMarker( + build_numbers, 'MOCK_COMMAND_PATTERN', + has_been_tested_cmd='MOCK_TESTED_COMMAND', + build_selection_policy=build_selection_policy) + self.assertEqual(expected_build, latest_build) + + def testBacktrackThenLatestPolicy(self): + """Tests the first untested build is returned.""" + self._TestBuildNumberWithMarker( + [3, 2, 1], '1', get_latest_build.BACKTRACK_THEN_LATEST, + lambda *_: True, mock.Mock(side_effect=[True, True, False])) + self._TestBuildNumberWithMarker( + [3, 2, 1], '3', get_latest_build.BACKTRACK_THEN_LATEST, + lambda *_: True, lambda *_: True) + self._TestBuildNumberWithMarker( + [3, 2, 1], '0', get_latest_build.BACKTRACK_THEN_LATEST, + lambda *_: False) + + def testBacktrackOnlyPolicy(self): + """Tests that no build is returned when the flag is not specified.""" + self._TestBuildNumberWithMarker( + [3, 2, 1], '0', get_latest_build.ONLY_BACKTRACK, + lambda *_: True, lambda *_: True) + self._TestBuildNumberWithMarker( + [1, 2, 3], '1', get_latest_build.ONLY_BACKTRACK, + lambda *_: True, mock.Mock(side_effect=[True, True, False])) + self._TestBuildNumberWithMarker( + [3, 2, 1], '0', get_latest_build.BACKTRACK_THEN_LATEST, + lambda *_: False) + + def testAlwaysLatestPolicy(self): + """Tests the always return latest policy.""" + self._TestBuildNumberWithMarker( + [1, 2, 3], '3', get_latest_build.ALWAYS_USE_LATEST, + lambda *_: True, lambda *_: False) + self._TestBuildNumberWithMarker( + [1, 2, 3], '3', get_latest_build.ALWAYS_USE_LATEST, + lambda *_: True, lambda *_: True) + self._TestBuildNumberWithMarker( + [3, 2, 1], '0', get_latest_build.ALWAYS_USE_LATEST, + lambda *_: False) + + +if __name__ == '__main__': + unittest.main()
diff --git a/build_server/get_ota_size.py b/build_server/get_ota_size.py new file mode 100755 index 0000000..4399ec4 --- /dev/null +++ b/build_server/get_ota_size.py
@@ -0,0 +1,50 @@ +#!/usr/bin/env python +# +# Copyright 2014 Google Inc. All Rights Reserved. + +"""Utility to get the ota size for all Chromecast builds. + +It will fetch the ota stored in bigstore and report the size of them in a csv. +""" + +import optparse +import re +import subprocess + +# Command to list all builds. +GET_OTA_INFO_CMD = ('gsutil ls -l gs://gtv-eureka/internal/%s/anchovy-eng/*/' + 'anchovy-ota-*.zip') +GET_OTA_RE = re.compile(r'\s+([0-9]+)\s+.*anchovy-ota-([0-9]+)\.zip') + + +def ParseArgs(): + """Parse args.""" + parser = optparse.OptionParser() + parser.add_option('--branch', default='merge29', help=('Branch to get ota')) + parser.add_option('--output_csv', default='build_size.csv', help=('Csv')) + options = parser.parse_args()[0] + return options + + +def GetOtaInfo(branch, output_csv): + """Returns the ota size and build number in a csv file.""" + ota_info_list = [] + with open('/tmp/ota_info.txt', 'w') as f: + subprocess.call(GET_OTA_INFO_CMD % branch, shell=True, stdout=f) + with open('/tmp/ota_info.txt', 'r') as f: + ota_info_list = f.readlines() + if ota_info_list: + with open(output_csv, 'w') as f: + for ota in ota_info_list: + info = GET_OTA_RE.search(ota) + if info: + f.write(','.join((info.group(2), info.group(1)))+'\n') + +FLAGS = ParseArgs() + + +def main(): + GetOtaInfo(FLAGS.branch, FLAGS.output_csv) + +if __name__ == '__main__': + main()
diff --git a/build_server/push_symbols.par b/build_server/push_symbols.par new file mode 100755 index 0000000..396a183 --- /dev/null +++ b/build_server/push_symbols.par Binary files differ
diff --git a/catatester/Makefile b/catatester/Makefile new file mode 100644 index 0000000..dc9f0bf --- /dev/null +++ b/catatester/Makefile
@@ -0,0 +1,23 @@ +# Makefile to update protobuf objects +# +# Every time the protos are updated, just run: +# $ make + +CWD=$(shell pwd) + +PROTOFOLDER=$(CWD)/proto +IMPORTSFOLDER=$(CWD)/proto/imported +OUTPUT_FOLDER=$(CWD)/genfiles + +.PHONY: proto + +all: proto + +gen_proto: + protoc -I$(PROTOFOLDER) --python_out=$(OUTPUT_FOLDER) $(PROTOFOLDER)/*.proto + protoc -I$(IMPORTSFOLDER) --python_out=$(OUTPUT_FOLDER) $(IMPORTSFOLDER)/*.proto + +gen_init: + touch $(OUTPUT_FOLDER)/__init__.py + +proto: gen_proto gen_init
diff --git a/catatester/README.md b/catatester/README.md new file mode 100644 index 0000000..4c6a215 --- /dev/null +++ b/catatester/README.md
@@ -0,0 +1,66 @@ +# Updating the protos + +Just run `make` and the generated protos will be updated. + +If the protoc compiler is confused by the map type, you are probably +running version of protoc < v3.0. You can check with `protoc --version`. See +below for updating your protoc version. + +# Installing protoc v3 compiler + +Grab protoc-3.2.0-linux-x86_64.zip release from +https://github.com/google/protobuf/releases/tag/v3.2.0 + +Newer releases of protoc are not compatible with the current version of protobuf python package +installed in requirements.txt at the time of this writing. + +Extract `bin/protoc` from the release and copy it into /usr/bin/protoc. Give it execute permissions. + +Check the new version with `protoc --version`. + +# Running unittests + +This section covers the process for executing Python3 unittests located under this directory. + +## Configuring Virtualenv + +1. Download CQ package mirror. + + ``` + mkdir -p ~/envs/mirror/python_packages + gsutil rsync \ + "gs://nest-build-dependencies/common/python_packages" \ + ~/envs/mirror/python_packages + ``` + +1. Create a new virtual environment. + + ``` + python3 -m venv ~/envs/cq_venv + ``` + +1. Upgrade common modules. + + ``` + ~/envs/cq_venv/bin/pip install \ + --no-index \ + --find-links=file:///<PATH_TO_HOME>/envs/mirror/python_packages \ + --upgrade pip wheel setuptools + ``` + +1. Install requirements. + + ``` + ~/envs/cq_venv/bin/pip install \ + --no-index \ + --find-links=file:///<PATH_TO_HOME>/envs/mirror/python_packages \ + -r <REPO_ROOT>/continuous-tests/cq/requirements_recipe3.txt + ``` + +1. Run tests. + + ``` + ~/envs/cq_venv/bin/python3 -m unittest discover \ + -s ~/gazoo_repo/continuous-tests/catatester \ + -p '*_test.py' + ```
diff --git a/catatester/__init__.py b/catatester/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/catatester/__init__.py
diff --git a/catatester/cipd/cipd_packages.yaml b/catatester/cipd/cipd_packages.yaml new file mode 100644 index 0000000..a96a24d --- /dev/null +++ b/catatester/cipd/cipd_packages.yaml
@@ -0,0 +1,17 @@ +# This file specifies the cipd package installation root directory relative to +# the root directory. +# +# devicemap package contains the devices associated with each host server. +- 'package': 'home_internal/devicemap' + 'relative_path': 'swarm_home/devicemap' +# swarm_puppet package contains the puppet configuration used for swarming +# bot setup and host server monitoring. +- 'package': 'home_internal/swarm_puppet' + 'relative_path': 'puppet' +# test_binaries package contains the test run binaries +- 'package': 'home_internal/test_binaries' + 'relative_path': 'swarm_home/eurtest_binaries/home_binaries/tests' +# tool_binaries package contains miscellaneous binaries for device health +# check, host monitoring and etc. +- 'package': 'home_internal/tool_binaries' + 'relative_path': 'swarm_home/eurtest_binaries/home_binaries/tools'
diff --git a/catatester/config_expectations_test.py b/catatester/config_expectations_test.py new file mode 100644 index 0000000..8c9a345 --- /dev/null +++ b/catatester/config_expectations_test.py
@@ -0,0 +1,39 @@ +"""Expectation diff tests for continuous_tests.protoascii configs.""" + +import unittest + +from catatester import config_utils + + +_FAILURE_MSG = ( + '{} config does not match expectation!\n\n' + + 'To update expectations, run:\n' + + '```\n' + + 'python continuous-tests/catatester/config_expectations_update.py\n' + + '```') + + +def _read_expectation(path): + with open(path) as f: + return f.read() + + +class ConfigExpectationsTest(unittest.TestCase): + + def testVerifyProdExpectation(self): + """Verify prod config matches expectation.""" + message = config_utils.parse_continuous_tests_protoascii( + config_utils.PROD_CONFIG_PATH) + expectation = _read_expectation(config_utils.PROD_EXPECTATION_PATH) + self.assertEqual(expectation, str(message), _FAILURE_MSG.format('Prod')) + + def testVerifyStagingExpectation(self): + """Verify staging config matches expectation.""" + message = config_utils.parse_continuous_tests_protoascii( + config_utils.STAGING_CONFIG_PATH) + expectation = _read_expectation(config_utils.STAGING_EXPECTATION_PATH) + self.assertEqual(expectation, str(message), _FAILURE_MSG.format('Staging')) + + +if __name__ == '__main__': + unittest.main()
diff --git a/catatester/config_expectations_update.py b/catatester/config_expectations_update.py new file mode 100644 index 0000000..ef14e2c --- /dev/null +++ b/catatester/config_expectations_update.py
@@ -0,0 +1,31 @@ +"""Update continuous_tests config expected content. + +Expectation files will be updated with the parsed versions of the staging and +production continuous_tests.protoascii files. + +These files should be used to verify config changes have had the expected +effect. +""" + +from catatester import config_utils + + +def _write_expectation(message, path): + with open(path, 'w') as f: + f.write(str(message)) + + +def main(): + print('Updating prod config expectation.') + prod_message = config_utils.parse_continuous_tests_protoascii( + config_utils.PROD_CONFIG_PATH) + _write_expectation(prod_message, config_utils.PROD_EXPECTATION_PATH) + + print('Updating staging config expectation.') + staging_message = config_utils.parse_continuous_tests_protoascii( + config_utils.STAGING_CONFIG_PATH) + _write_expectation(staging_message, config_utils.STAGING_EXPECTATION_PATH) + + +if __name__ == '__main__': + main()
diff --git a/catatester/config_test.py b/catatester/config_test.py new file mode 100644 index 0000000..55b3f0f --- /dev/null +++ b/catatester/config_test.py
@@ -0,0 +1,304 @@ +"""Tests for tests.protoascii configs.""" + +import abc +import collections +import itertools +import os +import re +import unittest + +from catatester.genfiles import continuous_tests_pb2 +from catatester import config_utils + +# Import from eureka-internal/builder/masters project. +# pylint: disable=ungrouped-imports +try: + from src.genfiles import build_config_pb2 +except ImportError: + from catatester.genfiles import build_config_pb2 + +import google.protobuf.text_format + +_CATATESTER_ROOT_PATH = os.path.dirname(os.path.abspath(__file__)) +_CONTINUOUS_TESTS_ROOT_PATH = os.path.dirname(_CATATESTER_ROOT_PATH) + +_SKIP_UNIT_TEST_RE = re.compile(r'unit_test.*') +_REQUIRED_FIELDS = ['TEST_CASE_CLASS', 'TEST_CASE_MODULE', + 'TEST_SEQUENCE_CLASS', 'TEST_SEQUENCE_MODULE'] + +# Cap the execution_timeout to 23 hours (b/176174164) +_MAX_EXECUTION_TIMEOUT_MINS = 23 * 60 + +# Assumes full test manifest repo checkout. +_BUILD_CONFIG_FILEPATH = os.path.join( + os.path.dirname(_CONTINUOUS_TESTS_ROOT_PATH), 'builder', 'masters', + 'configs', 'eureka', 'build_config.protoascii') + + +def _GetBuildConfig(): + """Returns the build_config protoascii from the builder/masters project. + + Returns: + Ingested build_config. + """ + build_config = build_config_pb2.BuildConfig() + with open(_BUILD_CONFIG_FILEPATH) as f: + google.protobuf.text_format.Merge(f.read(), build_config) + return build_config + + +# pylint: disable=no-member +# Test is not directly derived from UnitTest base class. +class ConfigTest(object): + """A class to test a continuous_tests config. + + Note: This class will be tested twice, once with the staging config + and once with the prod config. + """ + ASSISTANT = build_config_pb2.OtaBuild.Capability.Value( + 'ASSISTANT') + CAST_VIDEO_RECEIVER = build_config_pb2.OtaBuild.Capability.Value( + 'CAST_VIDEO_RECEIVER') + CAST_AUDIO_RECEIVER = build_config_pb2.OtaBuild.Capability.Value( + 'CAST_AUDIO_RECEIVER') + + def __init__(self): + self.__metaclass__ = abc.ABCMeta + + @abc.abstractproperty + def tests_proto(self): + pass + + @property + def build_config_proto(self): + return _GetBuildConfig() + + @property + def all_tests(self): + return ( + list(self.tests_proto.continuous_test) + + list(self.tests_proto.scheduled_test)) + + def testContinuousTestsConfig_IsValidProto(self): + """Tests the continuous_tests config is a valid proto.""" + self.assertTrue(self.tests_proto) + + def testEveryTestTarget_hasTestConfigOrTestBinary(self): + """Test that every test_target has a test_config or test_binary_name.""" + for test in self.all_tests: + self.assertTrue( + test.test_target.binary_name or + test.test_target.config) + + def testEveryScheduledTestsBuildTargetsHasProductsOrProductTypes(self): + """Test that scheduled test build_target has products or product types.""" + for test in self.tests_proto.scheduled_test: + for target in test.build_targets: + msg = ('Scheduled tests require build_target.products or' + 'build_target.product_types: %s' % test) + self.assertTrue( + target.products or + target.product_types, msg) + + def testEveryScheduledTestHasSetACron(self): + """Verify every scheduled test has set a cron string.""" + for test in self.tests_proto.scheduled_test: + self.assertTrue(test.schedule.cron, + 'scheduled_test is missing cron string: %s' % test) + + def testEveryTestTargetGroupIsDefined(self): + """Test that all test target groups are defined in test_group_tags.""" + for test in self.all_tests: + for test_group in test.test_target.test_groups: + self.assertIn(test_group, self.tests_proto.test_group_tags) + + def testEveryTestContainsGroup(self): + """Ensures group is included in every test.""" + for test in self.all_tests: + groups = [dim for dim in test.test_target.testbed_requirements if + dim.bot_dimension.lower() == 'group'] + self.assertTrue(groups, + 'Missing group in target: %s' % test.test_target.config) + + def testEveryTestHasValidTestTimeout(self): + """Ensures test_timeout_mins is under the max allowed value.""" + for test in self.all_tests: + self.assertLessEqual( + test.test_target.test_timeout_mins, + _MAX_EXECUTION_TIMEOUT_MINS, + 'Timeout mins > %s in target: %s' % (_MAX_EXECUTION_TIMEOUT_MINS, + test.test_target.config)) + + def testEveryTargetedTestConfigFileExists(self): + """Test that every targeted test_config file exists.""" + catatester_path = os.path.abspath(os.path.dirname(__file__)) + root_path = os.path.dirname(catatester_path) + test_configs_root = os.path.join( + root_path, self.tests_proto.test_configs_root) + for test in self.all_tests: + if test.test_target.config: + config_abspath = os.path.join( + test_configs_root, + test.test_target.config) + self.assertTrue( + os.path.isfile(config_abspath), + 'test_target.config does not exist: %s' % config_abspath) + + def testEveryTestConfigFileContainsRequiredFields(self): + """Test that every test_config file contains required fields.""" + + for test in self.all_tests: + if (not test.test_target.config + or re.match(_SKIP_UNIT_TEST_RE, test.test_target.config)): + continue + + fname = os.path.join(_CONTINUOUS_TESTS_ROOT_PATH, + self.tests_proto.test_configs_root, test.test_target.config) + with open(fname) as f: + lines = f.readlines() + + found_fields = [] + for field in _REQUIRED_FIELDS: + for line in lines: + if not re.match('^%s.*' % field, line, re.I): + continue + _, value = re.split('=', line, 2) + self.assertIsNotNone( value.strip(), + '%s in %s must have a value.' % (field, fname)) + found_fields.append(field) + + self.assertEqual(_REQUIRED_FIELDS, sorted(found_fields), + '%s must contain all of %s.' % (fname, _REQUIRED_FIELDS)) + + def testTarget_ValidCipdRefsKey(self): + """Tests targets provide valid cipd refs.""" + cipd_ref_keys = self.tests_proto.cipd_refs.keys() + for test in self.all_tests: + msg = 'cipd_ref_key should be one of %s but got %s' % ( + cipd_ref_keys, test.test_target.cipd_refs_key) + self.assertIn(test.test_target.cipd_refs_key, cipd_ref_keys, msg) + + def testContinuousTestsConfigDuplicates(self): + """Tests there are no duplicated definitions for continuous_tests.""" + dict_continuous_tests = collections.defaultdict(list) + for continuous_test in self.tests_proto.continuous_test: + products_set = self._GetProductsForContinuousTest(continuous_test) + config_variants = list(continuous_test.build_targets)[0].variants + testbed_reqs = self._GetTestbedRequirementsForContinuousTest( + continuous_test) + config_key = '%s-%s-%s' % ( + continuous_test.test_target.config, + continuous_tests_pb2.BuildTargets.Variant.Name(config_variants), + ';'.join(testbed_reqs)) + if not continuous_test.test_target.test_cases: + dict_continuous_tests[config_key].append(products_set) + else: + for test_case in continuous_test.test_target.test_cases: + config_test_case_key = '%s-%s' % (config_key, test_case) + dict_continuous_tests[config_test_case_key].append(products_set) + for config in dict_continuous_tests: + combinations = itertools.combinations(dict_continuous_tests[config], 2) + duplicates = next((c for c in combinations if set.intersection(*c)), None) + msg = 'Overlapping config found for %s, products %s' % (config, + duplicates) + self.assertIsNone(duplicates, msg) + + def _GetDevicesByCapability(self, capability_index): + """Getting sets of devices filtered by the index received. + + Args: + capability_index: Number provided to filter the capabilities of devices + + Returns: + returns the set of filtered devices + For example, if capability_index is CAST_VIDEO_RECEIVER: + {'chorizo', 'steak', 'salami'} + """ + ota_dict = self.build_config_proto.ota_build + set_cast_products = set() + for key in ota_dict: + if ota_dict[key].capabilities: + if capability_index in list(ota_dict[key].capabilities): + set_cast_products.add(ota_dict[key].product) + return set_cast_products + + def _GetProductsForContinuousTest(self, continuous_test): + """Getting set of products for the specified continuous_test. + + Args: + continuous_test: continuous test object. + + Returns: + returns a set with products of the continuous test + """ + assistant_devices = self._GetDevicesByCapability(self.ASSISTANT) + cast_video_receiver = self._GetDevicesByCapability( + self.CAST_VIDEO_RECEIVER) + cast_audio_receiver = self._GetDevicesByCapability( + self.CAST_AUDIO_RECEIVER) + set_products = set() + set_product_types = set() + for build_target in continuous_test.build_targets: + if build_target.products: + set_products.update(list(build_target.products)) + if build_target.product_types: + product_types = list(build_target.product_types) + if 'ASSISTANT' in product_types: + set_product_types |= assistant_devices + if 'CAST_AUDIO_RECEIVER' in product_types: + set_product_types |= cast_audio_receiver + if 'CAST_VIDEO_RECEIVER' in product_types: + set_product_types |= cast_video_receiver + products = set_products | set_product_types + return products + + def _GetTestbedRequirementsForContinuousTest(self, continuous_test): + """Returns a list of bot dimensions required for the test.""" + test_target = continuous_test.test_target + if not test_target.skip_default_dimensions: + return ['dims:default'] + requirements = [] + for req in test_target.testbed_requirements: + requirements.append(':'.join([req.bot_dimension, req.value])) + return requirements + + def testEveryTestTargetBinaryNameExists(self): + """Test that every test_target.binary_name does exist as subdir. + + Except for test_target with recipe as recipe defines subdir. + """ + binaries_and_recipes = {(test.test_target.binary_name, + test.test_target.recipe) + for test in self.all_tests + if test.test_target.binary_name} + for binary_name, recipe in binaries_and_recipes: + subdir = os.path.join(_CONTINUOUS_TESTS_ROOT_PATH, + 'lab_system', 'master', 'config', 'tests', + binary_name) + subdir = os.path.abspath(subdir) + self.assertTrue(os.path.isdir(subdir) or recipe, + msg='%s does not exist.' % subdir) + + +class ProdConfigTest(unittest.TestCase, ConfigTest): + + @property + def tests_proto(self): + return config_utils.parse_continuous_tests_protoascii( + config_utils.PROD_CONFIG_PATH) + + @property + def build_restrictions(self): + return self.tests_proto.build_restrictions + + +class StagingConfigTest(unittest.TestCase, ConfigTest): + + @property + def tests_proto(self): + return config_utils.parse_continuous_tests_protoascii( + config_utils.STAGING_CONFIG_PATH) + + +if __name__ == '__main__': + unittest.main()
diff --git a/catatester/config_utils.py b/catatester/config_utils.py new file mode 100644 index 0000000..36085ec --- /dev/null +++ b/catatester/config_utils.py
@@ -0,0 +1,29 @@ +"""Reusable utility methods for working with continuous_test configs.""" + +import os + +from catatester.genfiles import continuous_tests_pb2 +from google.protobuf import text_format + +_ROOT_DIR = os.path.dirname(os.path.realpath(__file__)) + +# Path to the production continuous_tests.protoascii file. +PROD_CONFIG_PATH = os.path.join( + _ROOT_DIR, 'configs', 'prod', 'continuous_tests.protoascii') +# Path to the staging continuous_tests.protoascii file. +STAGING_CONFIG_PATH = os.path.join( + _ROOT_DIR, 'configs', 'staging', 'continuous_tests.protoascii') +# Path to the expectation file for the production config. +PROD_EXPECTATION_PATH = os.path.join( + _ROOT_DIR, 'configs', 'expectations', 'prod_continuous_tests.expected') +# Path to the expectation file for the staging config. +STAGING_EXPECTATION_PATH = os.path.join( + _ROOT_DIR, 'configs', 'expectations', 'staging_continuous_tests.expected') + + +def parse_continuous_tests_protoascii(path): + """Parse a continuous_tests config from protoascii into a proto message.""" + message = continuous_tests_pb2.ContinuousTestsConfig() + with open(path) as f: + text_format.Merge(f.read(), message) + return message
diff --git a/catatester/configs/README.md b/catatester/configs/README.md new file mode 100644 index 0000000..5765041 --- /dev/null +++ b/catatester/configs/README.md
@@ -0,0 +1,8 @@ +# NOTE + +After updating the continuous_test protoascii file, a new expectation file needs +to be generated and uploaded along with the protoascii changes. + +``` +$ python $DEV_HOME/continuous-tests/catatester/config_expectations_update.py +```
diff --git a/catatester/configs/expectations/prod_continuous_tests.expected b/catatester/configs/expectations/prod_continuous_tests.expected new file mode 100644 index 0000000..da4ef21 --- /dev/null +++ b/catatester/configs/expectations/prod_continuous_tests.expected
@@ -0,0 +1,654 @@ +test_configs_root: "lab_system/master/config/tests/" +continuous_test { + test_target { + config: "cycle_bitrates/fuchsia_cycle_bitrates.cfg" + binary_name: "cycle_bitrates" + recipe: FUCHSIA_RUNNER + testbed_requirements { + bot_dimension: "product" + value: "nelson" + } + testbed_requirements { + bot_dimension: "device_type" + value: "nelson" + } + testbed_requirements { + bot_dimension: "group" + value: "COMMON" + } + bot_pool: "gazoo-prod" + skip_default_dimensions: true + } + build_targets { + products: "astro" + branches { + name: "1.52f" + } + branches { + name: "master" + } + } +} +continuous_test { + test_target { + config: "cycle_bitrates/fuchsia_cycle_bitrates.cfg" + binary_name: "cycle_bitrates" + recipe: FUCHSIA_RUNNER + testbed_requirements { + bot_dimension: "product" + value: "sherlock" + } + testbed_requirements { + bot_dimension: "device_type" + value: "sherlock" + } + testbed_requirements { + bot_dimension: "group" + value: "COMMON" + } + bot_pool: "gazoo-prod" + skip_default_dimensions: true + } + build_targets { + products: "astro" + branches { + name: "1.52f" + } + branches { + name: "master" + } + } +} +continuous_test { + test_target { + config: "gqnq_contract_executor/gqnq_contract_executor_unpaired.cfg" + binary_name: "gqnq_contract_executor" + enabled: false + testbed_requirements { + bot_dimension: "GROUP" + value: "camie" + } + bot_pool: "gazoo-prod" + } + build_targets { + products: "gq" + products: "nq" + products: "spencer" + variants: ENG + } +} +continuous_test { + test_target { + config: "gqnq_contract_executor/gqnq_contract_executor_virtual_presubmit.cfg" + binary_name: "gqnq_contract_executor" + enabled: false + recipe: VIRTUAL_DEVICE_RUNNER + test_groups: "GQNQ_VIRTUAL_PRESUBMIT" + testbed_requirements { + bot_dimension: "GROUP" + value: "COMMON" + } + testbed_requirements { + bot_dimension: "testbed_type" + value: "vdm-cq" + } + bot_pool: "gazoo-staging" + skip_default_dimensions: true + } + build_targets { + products: "gq_x86_64" + products: "nq_x86_64" + products: "spencer_x86_64" + variants: ENG + branches { + name: "master" + } + } +} +continuous_test { + test_target { + config: "gqnq_contract_executor/gqnq_contract_executor_presubmit.cfg" + binary_name: "gqnq_contract_executor" + enabled: false + test_groups: "GQNQ_CAMERA_ENGPROD_PRESUBMIT" + testbed_requirements { + bot_dimension: "GROUP" + value: "camie-cq" + } + bot_pool: "gazoo-prod" + } + build_targets { + products: "gq" + products: "nq" + variants: ENG + branches { + name: "master" + } + } +} +continuous_test { + test_target { + test_cases: "testOnArm" + binary_name: "libassistant-integration-test" + priority: CRITICAL + recipe: LIBASSISTANT_RUNNER + test_timeout_mins: 120 + testbed_requirements { + bot_dimension: "GROUP" + value: "COMMON" + } + cipd_refs_key: "libassistant" + } + build_targets { + branch_types: MASTER + products: "assistant" + variants: ARM + } +} +continuous_test { + test_target { + test_cases: "testOnX64" + binary_name: "libassistant-integration-test" + priority: CRITICAL + recipe: LIBASSISTANT_RUNNER + test_timeout_mins: 120 + testbed_requirements { + bot_dimension: "GROUP" + value: "COMMON" + } + cipd_refs_key: "libassistant" + } + build_targets { + branch_types: MASTER + products: "assistant" + variants: X64 + } +} +scheduled_test { + test_target { + config: "perception_latency/perception_latency.cfg" + test_cases: "PerceptionLatencyTestCaseMotion" + binary_name: "perception_latency" + test_timeout_mins: 120 + testbed_requirements { + bot_dimension: "GROUP" + value: "perception_latency" + } + bot_pool: "gazoo-prod" + } + build_targets { + products: "newman" + variants: USER + } + schedule { + cron: "0 * * * *" + policy: LATEST_UNTESTED + } + branches: "1.44" + branches: "1.45" + branches: "1.42" + branches: "master" +} +scheduled_test { + test_target { + config: "selina/gesture_data_injection.cfg" + binary_name: "selina" + enabled: true + test_timeout_mins: 180 + testbed_requirements { + bot_dimension: "GROUP" + value: "selina_data_injection" + } + bot_pool: "gazoo-prod" + } + build_targets { + products: "elaine" + variants: ENG + } + schedule { + cron: "30 */2 * * *" + policy: LATEST + } + branches: "master" + branches: "1.56" + branches: "1.56.1" +} +scheduled_test { + test_target { + config: "selina/sleep_data_injection.cfg" + binary_name: "selina" + enabled: true + test_timeout_mins: 780 + testbed_requirements { + bot_dimension: "GROUP" + value: "sleep_ext4" + } + bot_pool: "gazoo-prod" + } + build_targets { + products: "elaine" + variants: ENG + } + schedule { + cron: "45 */4 * * *" + policy: LATEST + } + branches: "master" + branches: "1.56" + branches: "1.56.1" +} +scheduled_test { + test_target { + config: "sound_sensing/sound_sensing_mic_writer.cfg" + binary_name: "sound_sensing" + enabled: false + test_timeout_mins: 1380 + testbed_requirements { + bot_dimension: "GROUP" + value: "sound_sensing_mic_writer" + } + bot_pool: "gazoo-prod" + } + build_targets { + products: "biggie" + products: "elaine" + products: "mushroom" + products: "newman" + products: "pineapple" + products: "valens" + products: "vento" + variants: ENG + } + schedule { + cron: "30 */8 * * *" + policy: LATEST + } + branches: "master" + branches: "1.54" +} +scheduled_test { + test_target { + config: "sound_sensing/sound_sensing_mic_writer_p1.cfg" + binary_name: "sound_sensing" + enabled: false + test_timeout_mins: 1380 + testbed_requirements { + bot_dimension: "GROUP" + value: "sound_sensing_mic_writer" + } + bot_pool: "gazoo-prod" + } + build_targets { + products: "biggie" + products: "elaine" + products: "mushroom" + products: "newman" + products: "pineapple" + products: "valens" + products: "vento" + variants: ENG + } + schedule { + cron: "0 */12 * * *" + policy: LATEST + } + branches: "master" + branches: "1.54" +} +scheduled_test { + test_target { + config: "sound_sensing/sound_sensing_mic_writer_p2.cfg" + binary_name: "sound_sensing" + enabled: false + test_timeout_mins: 1380 + testbed_requirements { + bot_dimension: "GROUP" + value: "sound_sensing_mic_writer" + } + bot_pool: "gazoo-prod" + } + build_targets { + products: "biggie" + products: "elaine" + products: "mushroom" + products: "newman" + products: "pineapple" + products: "valens" + products: "vento" + variants: ENG + } + schedule { + cron: "0 */12 * * *" + policy: LATEST + } + branches: "master" + branches: "1.54" +} +scheduled_test { + test_target { + config: "selina/sleep_chester.cfg" + binary_name: "selina" + enabled: false + test_timeout_mins: 780 + testbed_requirements { + bot_dimension: "GROUP" + value: "sleep_positive" + } + bot_pool: "gazoo-prod" + } + build_targets { + products: "elaine" + variants: ENG + } + schedule { + cron: "30 0,12 * * *" + policy: LATEST + } + branches: "1.56.2" +} +scheduled_test { + test_target { + config: "selina/sleep_chester_1_1.cfg" + binary_name: "selina" + enabled: false + test_timeout_mins: 780 + testbed_requirements { + bot_dimension: "GROUP" + value: "sleep_positive" + } + bot_pool: "gazoo-prod" + } + build_targets { + products: "elaine" + variants: ENG + } + schedule { + cron: "30 6,18 * * *" + policy: LATEST + } + branches: "1.56.2" +} +scheduled_test { + test_target { + config: "selina/sleep_chester_2_1.cfg" + binary_name: "selina" + enabled: false + test_timeout_mins: 780 + testbed_requirements { + bot_dimension: "GROUP" + value: "sleep_positive" + } + bot_pool: "gazoo-prod" + } + build_targets { + products: "elaine" + variants: ENG + } + schedule { + cron: "30 3,15 * * *" + policy: LATEST + } + branches: "1.56.2" +} +disabled_branches: "1.39nf" +disabled_branches: "1.39nfct" +disabled_branches: "1.42rd" +disabled_branches: "1.46rd" +disabled_branches: "1.49qfct" +build_restrictions { + key: "stellar_v2" + value { + allowed_branch_types: MASTER + allowed_branch_types: RELEASE + allowed_variants: USER + } +} +test_group_tags: "OTA_SMOKE" +test_group_tags: "UNIT_TESTS" +test_group_tags: "RECONNECT_TEST" +test_group_tags: "GQNQ_CAMERA_ENGPROD_PRESUBMIT" +test_group_tags: "GQNQ_VIRTUAL_PRESUBMIT" +device_modules { + key: "anchovy" + value { + device_module: "eurtest.device.device" + device_class: "Device" + } +} +device_modules { + key: "assistant_arm" + value { + device_module: "udm.device.raspberry_pi" + device_class: "RaspberryPi" + } +} +device_modules { + key: "assistant_x64" + value { + device_module: "udm.device.assistant_x64" + device_class: "AssistantX64" + } +} +device_modules { + key: "assistantdefault" + value { + device_module: "eurtest.device.assistant_device" + device_class: "Assistant" + } +} +device_modules { + key: "astro" + value { + device_module: "udm.device.astro" + device_class: "Astro" + } +} +device_modules { + key: "astro-assistant" + value { + device_module: "eurtest.device.fuchsia_assistant_device" + device_class: "FuchsiaAssistant" + } +} +device_modules { + key: "astro-migration" + value { + device_module: "udm.device.astro_migration" + device_class: "AstroMigration" + } +} +device_modules { + key: "biggie" + value { + device_module: "eurtest.device.assistant_device" + device_class: "Assistant" + } +} +device_modules { + key: "caprica" + value { + device_module: "eurtest.device.device" + device_class: "Device" + } +} +device_modules { + key: "chorizo" + value { + device_module: "eurtest.device.device" + device_class: "Device" + } +} +device_modules { + key: "elaine" + value { + device_module: "eurtest.device.assistant_device" + device_class: "Assistant" + } +} +device_modules { + key: "gq" + value { + device_module: "udm.device.gq_nq" + device_class: "GqNqDevice" + } +} +device_modules { + key: "gq_x86_64" + value { + device_module: "udm.device.virtual_device" + device_class: "VirtualDevice" + } +} +device_modules { + key: "mushroom" + value { + device_module: "eurtest.device.assistant_device" + device_class: "Assistant" + } +} +device_modules { + key: "nelson" + value { + device_module: "udm.device.sherlock" + device_class: "Sherlock" + } +} +device_modules { + key: "newman" + value { + device_module: "eurtest.device.assistant_device" + device_class: "Assistant" + } +} +device_modules { + key: "nq" + value { + device_module: "udm.device.gq_nq" + device_class: "GqNqDevice" + } +} +device_modules { + key: "nq_x86_64" + value { + device_module: "udm.device.virtual_device" + device_class: "VirtualDevice" + } +} +device_modules { + key: "pepperoni" + value { + device_module: "eurtest.device.chromecast_audio" + device_class: "ChromecastAudio" + } +} +device_modules { + key: "pineapple" + value { + device_module: "eurtest.device.assistant_device" + device_class: "Assistant" + } +} +device_modules { + key: "prince" + value { + device_module: "eurtest.device.assistant_device" + device_class: "Assistant" + } +} +device_modules { + key: "salami" + value { + device_module: "eurtest.device.device" + device_class: "Device" + } +} +device_modules { + key: "sherlock" + value { + device_module: "udm.device.sherlock" + device_class: "Sherlock" + } +} +device_modules { + key: "sherlock-assistant" + value { + device_module: "eurtest.device.fuchsia_assistant_device" + device_class: "FuchsiaAssistant" + } +} +device_modules { + key: "soba_emulator" + value { + device_module: "udm.device.soba" + device_class: "Soba" + } +} +device_modules { + key: "spencer" + value { + device_module: "udm.device.nest_iot_device" + device_class: "SpencerDevice" + } +} +device_modules { + key: "spencer_x86_64" + value { + device_module: "udm.device.virtual_device" + device_class: "VirtualDevice" + } +} +device_modules { + key: "steak" + value { + device_module: "eurtest.device.device" + device_class: "Device" + } +} +device_modules { + key: "udon_emulator" + value { + device_module: "udm.device.udon" + device_class: "Udon" + } +} +device_modules { + key: "valens" + value { + device_module: "eurtest.device.assistant_device" + device_class: "Assistant" + } +} +device_modules { + key: "vento" + value { + device_module: "eurtest.device.assistant_device" + device_class: "Assistant" + } +} +device_modules { + key: "venus" + value { + device_module: "udm.device.nest_iot_device" + device_class: "SpencerDevice" + } +} +cipd_refs { + key: "internal" + value { + refs { + package_name: "home_internal/recipes" + version: "" + path: "." + } + } +} +cipd_refs { + key: "libassistant" + value { + refs { + package_name: "home_internal/libassistant_tools" + version: "" + path: "." + } + } +}
diff --git a/catatester/configs/expectations/staging_continuous_tests.expected b/catatester/configs/expectations/staging_continuous_tests.expected new file mode 100644 index 0000000..a56007f --- /dev/null +++ b/catatester/configs/expectations/staging_continuous_tests.expected
@@ -0,0 +1,318 @@ +test_configs_root: "lab_system/master/config/tests/" +continuous_test { + test_target { + config: "ota_installable/ota_installable.cfg" + binary_name: "ota_installable" + priority: CRITICAL + recipe: OTA_INSTALLABLE_RUNNER + test_groups: "OTA_SMOKE" + testbed_requirements { + bot_dimension: "GROUP" + value: "COMMON" + } + } + build_targets { + branch_types: MASTER + products: "prince" + products: "valens" + variants: ENG + } +} +continuous_test { + test_target { + config: "crash_loop/crash_loop.cfg" + binary_name: "crash_loop" + priority: CRITICAL + recipe: OTA_INSTALLABLE_RUNNER + test_groups: "OTA_SMOKE" + testbed_requirements { + bot_dimension: "GROUP" + value: "COMMON" + } + } + build_targets { + branch_types: MASTER + products: "prince" + products: "valens" + variants: ENG + } +} +continuous_test { + test_target { + config: "cast/receiver.cfg" + test_cases: "CastReceiverCapabilityTestCase" + binary_name: "cast" + enabled: false + testbed_requirements { + bot_dimension: "GROUP" + value: "COMMON" + } + } + build_targets { + branch_types: MASTER + variants: USER + builder_names: "steak-yeti-user" + } +} +continuous_test { + test_target { + config: "reconnect_test/reconnect_test.cfg" + binary_name: "reconnect_test" + testbed_requirements { + bot_dimension: "GROUP" + value: "COMMON" + } + } + build_targets { + branch_types: MASTER + products: "newman" + variants: ENG + } +} +continuous_test { + test_target { + config: "ndm_integration/ndm_integration.cfg" + binary_name: "ndm_integration" + testbed_requirements { + bot_dimension: "GROUP" + value: "COMMON" + } + } + build_targets { + branch_types: MASTER + products: "newman" + variants: USER + } +} +continuous_test { + test_target { + config: "fakeoculus_reconnect_proxy/fakeoculus_reconnect_proxy.cfg" + binary_name: "fakeoculus_reconnect_proxy" + testbed_requirements { + bot_dimension: "GROUP" + value: "COMMON" + } + } + build_targets { + branch_types: MASTER + products: "newman" + variants: USER + } +} +continuous_test { + test_target { + config: "cast_video/video_encode_accelerator.cfg" + binary_name: "cast_video" + test_timeout_mins: 120 + testbed_requirements { + bot_dimension: "GROUP" + value: "COMMON" + } + } + build_targets { + branch_types: MASTER + products: "newman" + variants: USER + } +} +continuous_test { + test_target { + config: "cast_video/video_decode_accelerator.cfg" + binary_name: "cast_video" + test_timeout_mins: 120 + testbed_requirements { + bot_dimension: "GROUP" + value: "COMMON" + } + } + build_targets { + branch_types: MASTER + products: "newman" + variants: USER + } +} +continuous_test { + test_target { + test_cases: "testOnX64" + binary_name: "libassistant-integration-test" + priority: CRITICAL + recipe: LIBASSISTANT_RUNNER + test_timeout_mins: 120 + testbed_requirements { + bot_dimension: "GROUP" + value: "COMMON" + } + cipd_refs_key: "libassistant" + } + build_targets { + branch_types: MASTER + products: "assistant" + variants: X64 + } +} +continuous_test { + test_target { + config: "thread/thread.cfg" + binary_name: "thread" + testbed_requirements { + bot_dimension: "GROUP" + value: "COMMON" + } + } + build_targets { + branch_types: MASTER + products: "newman" + variants: USER + } +} +scheduled_test { + test_target { + config: "assistant_query_latency/canonical_queries_latency_dogfood.cfg" + binary_name: "assistant_query_latency" + enabled: false + testbed_requirements { + bot_dimension: "GROUP" + value: "chirp_latency" + } + } + build_targets { + branch_types: MASTER + products: "pineapple" + variants: USER + } + schedule { + cron: "*/30 * * * *" + policy: LATEST + } +} +scheduled_test { + test_target { + config: "manhattan_ui_perf/opal_back_gestures.cfg" + binary_name: "manhattan_ui_perf" + test_timeout_mins: 30 + testbed_requirements { + bot_dimension: "GROUP" + value: "COMMON" + } + cipd_refs_key: "internal_with_opal_dart" + } + build_targets { + branch_types: MASTER + products: "newman" + variants: USER + } + schedule { + cron: "0 0 * * *" + policy: LATEST + } +} +branch_type_priorities: RELEASE +branch_type_priorities: MASTER +disabled_branches: "1.39nf" +disabled_branches: "1.39nfct" +disabled_branches: "1.42rd" +test_group_tags: "OTA_SMOKE" +test_group_tags: "UNIT_TESTS" +device_modules { + key: "assistant_arm" + value { + device_module: "udm.device.raspberry_pi" + device_class: "RaspberryPi" + } +} +device_modules { + key: "assistant_x64" + value { + device_module: "udm.device.assistant_x64" + device_class: "AssistantX64" + } +} +device_modules { + key: "caprica" + value { + device_module: "eurtest.device.device" + device_class: "Device" + } +} +device_modules { + key: "mushroom" + value { + device_module: "eurtest.device.assistant_device" + device_class: "Assistant" + } +} +device_modules { + key: "newman" + value { + device_module: "eurtest.device.assistant_device" + device_class: "Assistant" + } +} +device_modules { + key: "pepperoni" + value { + device_module: "eurtest.device.chromecast_audio" + device_class: "ChromecastAudio" + } +} +device_modules { + key: "pineapple" + value { + device_module: "eurtest.device.assistant_device" + device_class: "Assistant" + } +} +device_modules { + key: "sabrina" + value { + device_module: "eurtest.device.android" + device_class: "Android" + } +} +device_modules { + key: "vento" + value { + device_module: "eurtest.device.assistant_device" + device_class: "Assistant" + } +} +device_modules { + key: "x86_worker" + value { + } +} +cipd_refs { + key: "internal" + value { + refs { + package_name: "home_internal/recipes" + version: "" + path: "." + } + } +} +cipd_refs { + key: "internal_with_opal_dart" + value { + refs { + package_name: "home_internal/recipes" + version: "" + path: "." + } + refs { + package_name: "home_internal/experimental/flutter_bridge" + version: "latest" + path: "." + } + } +} +cipd_refs { + key: "libassistant" + value { + refs { + package_name: "home_internal/libassistant_tools" + version: "" + path: "." + } + } +}
diff --git a/catatester/configs/imported/README.md b/catatester/configs/imported/README.md new file mode 100644 index 0000000..dbd771d --- /dev/null +++ b/catatester/configs/imported/README.md
@@ -0,0 +1,11 @@ +# Usage + +build_config.protoascii is an imported file used only for config validation unittesting. + +It is imported using copybara: +https://eureka-internal.git.corp.google.com/continuous-tests/+/master/catatester/proto/copy.bara.sky + +All updates should instead be made to the original file located at: +https://eureka-internal.git.corp.google.com/builder/masters/+/refs/heads/master/configs/eureka/build_config.protoascii + +Changes made under builder/master will take effect shortly after the commit is merged
diff --git a/catatester/configs/imported/build_config.protoascii b/catatester/configs/imported/build_config.protoascii new file mode 100644 index 0000000..59b916d --- /dev/null +++ b/catatester/configs/imported/build_config.protoascii
@@ -0,0 +1,709 @@ +# -*- mode: protobuffer; -*- +# proto-file: src/proto/build_config.proto +# proto-message: BuildConfig +# +# Warning: +# Do not record capabilities for unreleased products, after a product is released +# it's safe to use capabilities. + +# Removing capabilities for anchovy devices to run only Push on Green tests +# on this platform b/79264258 +ota_build { + key: "anchovy-eng" + value: { + build_target: "anchovy-eng" + product: "anchovy" + variant: "eng" + platform: "eureka" + test: true + } +} + +# Removing capabilities for anchovy devices to run only Push on Green tests +# on this platform b/79264258 +ota_build { + key: "anchovy-user" + value: { + build_target: "anchovy-user" + product: "anchovy" + variant: "user" + platform: "eureka" + test: true + } +} + +ota_build { + key: "assistantdefault-eng" + value: { + build_target: "assistantdefault-eng" + product: "assistantdefault" + variant: "eng" + platform: "assistantdefault" + test: true + } +} + +ota_build { + key: "assistantdefault-user" + value: { + build_target: "assistantdefault-user" + product: "assistantdefault" + variant: "user" + platform: "assistantdefault" + test: true + } +} + +ota_build { + key: "assistant-arm" + value: { + build_target: "assistant-arm" + product: "assistant" + variant: "arm" + platform: "assistant" + test: true + } +} + +ota_build { + key: "assistant-x64" + value: { + build_target: "assistant-x64" + product: "assistant" + variant: "x64" + platform: "assistant" + test: true + } +} + +ota_build: { + key: "biggie-eng" + value: { + build_target: "biggie-eng" + product: "biggie" + variant: "eng" + platform: "biggie" + capabilities: [CAST_AUDIO_RECEIVER, ASSISTANT, WIFI_2GHZ, WIFI_5GHZ] + test: true + } +} + +ota_build: { + key: "biggie-user" + value: { + build_target: "biggie-user" + product: "biggie" + variant: "user" + platform: "biggie" + capabilities: [CAST_AUDIO_RECEIVER, ASSISTANT, WIFI_2GHZ, WIFI_5GHZ] + test: true + } +} + +ota_build: { + key: "biggie-mesh-eng" + value: { + build_target: "biggie-eng" + product: "biggie" + variant: "eng" + platform: "biggie" + partner_bucket: "cast-partner-amlogic-internal" + capabilities: [CAST_AUDIO_RECEIVER, ASSISTANT, WIFI_2GHZ, WIFI_5GHZ] + } +} + +ota_build: { + key: "biggie-mesh-user" + value: { + build_target: "biggie-user" + product: "biggie" + variant: "user" + platform: "biggie" + partner_bucket: "cast-partner-amlogic-internal" + capabilities: [CAST_AUDIO_RECEIVER, ASSISTANT, WIFI_2GHZ, WIFI_5GHZ] + } +} + +ota_build: { + key: "caprica-eng" + value: { + build_target: "caprica-eng" + product: "caprica" + variant: "eng" + platform: "caprica" + capabilities: [CAST_VIDEO_RECEIVER, WIFI_2GHZ, WIFI_5GHZ] + test: true + } +} + +ota_build: { + key: "caprica-user" + value: { + build_target: "caprica-user" + product: "caprica" + variant: "user" + platform: "caprica" + capabilities: [CAST_VIDEO_RECEIVER, WIFI_2GHZ, WIFI_5GHZ] + test: true + } +} + +ota_build: { + key: "caprica-yeti-eng" + value: { + build_target: "caprica-eng" + product: "caprica" + variant: "eng" + platform: "caprica" + capabilities: [CAST_VIDEO_RECEIVER, WIFI_2GHZ, WIFI_5GHZ] + } +} + +ota_build: { + key: "caprica-yeti-user" + value: { + build_target: "caprica-user" + product: "caprica" + variant: "user" + platform: "caprica" + capabilities: [CAST_VIDEO_RECEIVER, WIFI_2GHZ, WIFI_5GHZ] + } +} + +ota_build: { + key: "chorizo-eng" + value: { + build_target: "chorizo-eng" + product: "chorizo" + variant: "eng" + platform: "earth" + capabilities: [CAST_VIDEO_RECEIVER, WIFI_2GHZ, WIFI_5GHZ] + test: true + } +} + +ota_build: { + key: "chorizo-user" + value: { + build_target: "chorizo-user" + product: "chorizo" + variant: "user" + platform: "earth" + capabilities: [CAST_VIDEO_RECEIVER, WIFI_2GHZ, WIFI_5GHZ] + test: true + } +} + +ota_build: { + key: "elaine-eng" + value: { + build_target: "elaine-eng" + product: "elaine" + variant: "eng" + platform: "elaine" + capabilities: [CAST_VIDEO_RECEIVER, ASSISTANT, WIFI_2GHZ, WIFI_5GHZ] + test: true + } +} + +ota_build: { + key: "elaine-user" + value: { + build_target: "elaine-user" + product: "elaine" + variant: "user" + platform: "elaine" + capabilities: [CAST_VIDEO_RECEIVER, ASSISTANT, WIFI_2GHZ, WIFI_5GHZ] + test: true + } +} + +ota_build: { + key: "estelle-eng" + value: { + build_target: "estelle-eng" + product: "estelle" + variant: "eng" + platform: "estelle" + capabilities: [CAST_VIDEO_RECEIVER, ASSISTANT, WIFI_2GHZ, WIFI_5GHZ] + test: true + } +} + +ota_build: { + key: "estelle-user" + value: { + build_target: "estelle-user" + product: "estelle" + variant: "user" + platform: "estelle" + capabilities: [CAST_VIDEO_RECEIVER, ASSISTANT, WIFI_2GHZ, WIFI_5GHZ] + test: true + } +} + +ota_build: { + key: "estelle-fuchsia-eng" + value: { + build_target: "estelle-fuchsia-eng" + product: "astro-migration" + variant: "eng" + platform: "fuchsia" + test: true + } +} + +ota_build: { + key: "estelle-gallium-eng" + value: { + build_target: "estelle-eng" + product: "estelle" + variant: "eng" + platform: "estelle" + capabilities: [CAST_VIDEO_RECEIVER, ASSISTANT, WIFI_2GHZ, WIFI_5GHZ] + } +} + +ota_build: { + key: "estelle-gallium-user" + value: { + build_target: "estelle-user" + product: "estelle" + variant: "user" + platform: "estelle" + capabilities: [CAST_VIDEO_RECEIVER, ASSISTANT, WIFI_2GHZ, WIFI_5GHZ] + } +} + +ota_build: { + key: "estelle-opal-eng" + value: { + build_target: "estelle-eng" + product: "estelle" + variant: "eng" + platform: "estelle" + capabilities: [CAST_VIDEO_RECEIVER, ASSISTANT, WIFI_2GHZ, WIFI_5GHZ] + test: true + } +} + +ota_build: { + key: "estelle-opal-user" + value: { + build_target: "estelle-user" + product: "estelle" + variant: "user" + platform: "estelle" + capabilities: [CAST_VIDEO_RECEIVER, ASSISTANT, WIFI_2GHZ, WIFI_5GHZ] + test: true + } +} + +ota_build: { + key: "arm64_fuchsia" + value: { + build_target: "arm64_fuchsia" + product: "astro" + variant: "arm64" + platform: "fuchsia" + test: true + } +} + +ota_build: { + key: "gq-eng" + value: { + build_target: "gq-eng" + product: "gq" + variant: "eng" + platform: "gq" + test: false + } +} + +ota_build: { + key: "gq-user" + value: { + build_target: "gq-user" + product: "gq" + variant: "user" + platform: "gq" + test: false + } +} + +ota_build: { + key: "mushroom-eng" + value: { + build_target: "mushroom-eng" + product: "mushroom" + variant: "eng" + platform: "joplin" + capabilities: [CAST_AUDIO_RECEIVER, ASSISTANT, WIFI_2GHZ, WIFI_5GHZ] + test: true + } +} + +ota_build: { + key: "mushroom-user" + value: { + build_target: "mushroom-user" + product: "mushroom" + variant: "user" + platform: "joplin" + capabilities: [CAST_AUDIO_RECEIVER, ASSISTANT, WIFI_2GHZ, WIFI_5GHZ] + test: true + } +} + +ota_build: { + key: "mushroom-concierge-user" + value: { + build_target: "mushroom-concierge-user" + product: "mushroom" + variant: "user" + platform: "joplin" + capabilities: [CAST_AUDIO_RECEIVER, ASSISTANT, WIFI_2GHZ, WIFI_5GHZ] + test: true + } +} + +ota_build: { + key: "mushroom-sdm-eng" + value: { + build_target: "mushroom-eng" + product: "mushroom" + variant: "eng" + platform: "joplin" + capabilities: [CAST_AUDIO_RECEIVER, ASSISTANT, WIFI_2GHZ, WIFI_5GHZ] + } +} + +ota_build: { + key: "mushroom-sdm-user" + value: { + build_target: "mushroom-user" + product: "mushroom" + variant: "user" + platform: "joplin" + capabilities: [CAST_AUDIO_RECEIVER, ASSISTANT, WIFI_2GHZ, WIFI_5GHZ] + } +} + +ota_build: { + key: "newman-eng" + value: { + build_target: "newman-eng" + product: "newman" + variant: "eng" + platform: "newman" + capabilities: [CAST_VIDEO_RECEIVER, ASSISTANT, WIFI_2GHZ, WIFI_5GHZ] + test: true + } +} + +ota_build: { + key: "newman-user" + value: { + build_target: "newman-user" + product: "newman" + variant: "user" + platform: "newman" + capabilities: [CAST_VIDEO_RECEIVER, ASSISTANT, WIFI_2GHZ, WIFI_5GHZ] + test: true + } +} + +ota_build: { + key: "newman-opal-eng" + value: { + build_target: "newman-eng" + product: "newman" + variant: "eng" + platform: "newman" + test: true + } +} + +ota_build: { + key: "newman-opal-user" + value: { + build_target: "newman-user" + product: "newman" + variant: "user" + platform: "newman" + test: true + } +} + +ota_build: { + key: "newman-mesh-eng" + value: { + build_target: "newman-eng" + product: "newman" + variant: "eng" + platform: "newman" + } +} + +ota_build: { + key: "newman-mesh-user" + value: { + build_target: "newman-user" + product: "newman" + variant: "user" + platform: "newman" + } +} + +ota_build: { + key: "nq-eng" + value: { + build_target: "nq-eng" + product: "nq" + variant: "eng" + platform: "nq" + test: false + } +} + +ota_build: { + key: "nq-user" + value: { + build_target: "nq-user" + product: "nq" + variant: "user" + platform: "nq" + test: false + } +} + +ota_build: { + key: "pepperoni-eng" + value: { + build_target: "pepperoni-eng" + product: "pepperoni" + variant: "eng" + platform: "hendrix" + capabilities: [CAST_AUDIO_RECEIVER, WIFI_2GHZ, WIFI_5GHZ] + test: true + } +} + +ota_build: { + key: "pepperoni-user" + value: { + build_target: "pepperoni-user" + product: "pepperoni" + variant: "user" + platform: "hendrix" + capabilities: [CAST_AUDIO_RECEIVER, WIFI_2GHZ, WIFI_5GHZ] + test: true + } +} + +ota_build: { + key: "pineapple-eng" + value: { + build_target: "pineapple-eng" + product: "pineapple" + variant: "eng" + platform: "chirp" + capabilities: [CAST_AUDIO_RECEIVER, ASSISTANT, WIFI_2GHZ, WIFI_5GHZ] + test: true + } +} + +ota_build: { + key: "pineapple-user" + value: { + build_target: "pineapple-user" + product: "pineapple" + variant: "user" + platform: "chirp" + capabilities: [CAST_AUDIO_RECEIVER, ASSISTANT, WIFI_2GHZ, WIFI_5GHZ] + test: true + } +} + +ota_build: { + key: "pineapple-sdm-eng" + value: { + build_target: "pineapple-eng" + product: "pineapple" + variant: "eng" + platform: "chirp" + capabilities: [CAST_AUDIO_RECEIVER, ASSISTANT, WIFI_2GHZ, WIFI_5GHZ] + } +} + +ota_build: { + key: "pineapple-sdm-user" + value: { + build_target: "pineapple-user" + product: "pineapple" + variant: "user" + platform: "chirp" + capabilities: [CAST_AUDIO_RECEIVER, ASSISTANT, WIFI_2GHZ, WIFI_5GHZ] + } +} + +ota_build { + key: "prince-eng" + value: { + build_target: "prince-eng" + product: "prince" + variant: "eng" + platform: "prince" + test: true + } +} + +ota_build { + key: "prince-user" + value: { + build_target: "prince-user" + product: "prince" + variant: "user" + platform: "prince" + test: true + } +} + +ota_build: { + key: "salami-eng" + value: { + build_target: "salami-eng" + product: "salami" + variant: "eng" + platform: "lexx" + capabilities: [CAST_VIDEO_RECEIVER, WIFI_2GHZ] + test: true + } +} + +ota_build: { + key: "salami-user" + value: { + build_target: "salami-user" + product: "salami" + variant: "user" + platform: "lexx" + capabilities: [CAST_VIDEO_RECEIVER, WIFI_2GHZ] + test: true + } +} + +ota_build: { + key: "steak-eng" + value: { + build_target: "steak-eng" + product: "steak" + variant: "eng" + platform: "luther" + capabilities: [CAST_VIDEO_RECEIVER, WIFI_2GHZ, WIFI_5GHZ] + test: true + } +} + +ota_build: { + key: "steak-user" + value: { + build_target: "steak-user" + product: "steak" + variant: "user" + platform: "luther" + capabilities: [CAST_VIDEO_RECEIVER, WIFI_2GHZ, WIFI_5GHZ] + test: true + } +} + +ota_build: { + key: "stellar_v2-eng" + value: { + build_target: "stellar_v2-eng" + product: "stellar_v2" + variant: "eng" + platform: "mt85xx" + } +} + +ota_build: { + key: "stellar_v2-user" + value: { + build_target: "stellar_v2-user" + product: "stellar_v2" + variant: "user" + platform: "mt85xx" + } +} + +ota_build: { + key: "tvdefault-eng" + value: { + build_target: "tvdefault-eng" + product: "tvdefault" + variant: "eng" + platform: "tvdefault" + test: false + } +} + +ota_build: { + key: "tvdefault-user" + value: { + build_target: "tvdefault-user" + product: "tvdefault" + variant: "user" + platform: "tvdefault" + test: false + } +} + +ota_build { + key: "valens-eng" + value: { + build_target: "valens-eng" + product: "valens" + variant: "eng" + platform: "valens" + capabilities: [CAST_AUDIO_RECEIVER, ASSISTANT, WIFI_2GHZ, WIFI_5GHZ] + test: true + } +} + +ota_build { + key: "valens-user" + value: { + build_target: "valens-user" + product: "valens" + variant: "user" + platform: "valens" + capabilities: [CAST_AUDIO_RECEIVER, ASSISTANT, WIFI_2GHZ, WIFI_5GHZ] + test: true + } +} + +ota_build { + key: "vento-eng" + value: { + build_target: "vento-eng" + product: "vento" + variant: "eng" + platform: "vento" + capabilities: [CAST_AUDIO_RECEIVER, ASSISTANT, WIFI_2GHZ, WIFI_5GHZ] + test: true + } +} + +ota_build { + key: "vento-user" + value: { + build_target: "vento-user" + product: "vento" + variant: "user" + platform: "vento" + capabilities: [CAST_AUDIO_RECEIVER, ASSISTANT, WIFI_2GHZ, WIFI_5GHZ] + test: true + } +}
diff --git a/catatester/configs/prod/continuous_tests.protoascii b/catatester/configs/prod/continuous_tests.protoascii new file mode 100644 index 0000000..1197c88 --- /dev/null +++ b/catatester/configs/prod/continuous_tests.protoascii
@@ -0,0 +1,682 @@ +# -*- mode: protobuffer; -*- +# +# proto-file: catatester/proto/continuous_tests.proto +# proto-message: ContinuousTestsConfig + +############################################# +## CIPD packages associated with a repo ## +############################################# +# Different repos require different recipes +# bundled in cipd packages. If version is empty +# then it will replaced by the reference tag +# provided by the controller. +cipd_refs { + key: "libassistant" + value: { + refs: [ + { + package_name: "home_internal/libassistant_tools" + version: "" + path: "." + } + ] + } +} +cipd_refs { + key: "internal" + value: { + refs: [ + { + package_name: "home_internal/recipes" + version: "" + path: "." + } + ] + } +} + +############################################### +## Build Restrictions for specific products ## +############################################### +# Useful for new products where we don't have enough inventory to test every +# build_target permutation desired by the tests. +# Use this to set which branch_types and variants you want to allow testing +# for a given product. + +build_restrictions { + key: "stellar_v2" + value: { + allowed_branch_types: [MASTER, RELEASE] + allowed_variants: USER + } +} + +##################### +## Device modules ## +##################### +# Different devices require different classes to control them. If the device +# product is not defined in this map the following defaults will be used: +# device_module = eurtest.device.device +# device_class = Device +device_modules { + key: "anchovy" + value: { + device_module: 'eurtest.device.device' + device_class: 'Device' + } +} + +device_modules { + key: "assistantdefault" + value: { + device_module: 'eurtest.device.assistant_device' + device_class: 'Assistant' + } +} + +device_modules { + key: "assistant_arm" + value: { + device_module: 'udm.device.raspberry_pi' + device_class: 'RaspberryPi' + } +} + +device_modules { + key: "assistant_x64" + value: { + device_module: 'udm.device.assistant_x64' + device_class: 'AssistantX64' + } +} + +device_modules { + key: "astro" + value: { + device_module: 'udm.device.astro' + device_class: 'Astro' + } +} + +device_modules { + key: "astro-assistant" + value: { + device_module: 'eurtest.device.fuchsia_assistant_device' + device_class: 'FuchsiaAssistant' + } +} + +device_modules { + key: "astro-migration" + value: { + device_module: 'udm.device.astro_migration' + device_class: 'AstroMigration' + } +} + +device_modules { + key: "biggie" + value: { + device_module: 'eurtest.device.assistant_device' + device_class: 'Assistant' + } +} + +device_modules { + key: "caprica" + value: { + device_module: 'eurtest.device.device' + device_class: 'Device' + } +} + +device_modules { + key: "chorizo" + value: { + device_module: 'eurtest.device.device' + device_class: 'Device' + } +} + +device_modules { + key: "elaine" + value: { + device_module: 'eurtest.device.assistant_device' + device_class: 'Assistant' + } +} + +device_modules { + key: "gq" + value: { + device_module: 'udm.device.gq_nq' + device_class: 'GqNqDevice' + } +} + +device_modules { + key: "gq_x86_64" + value: { + device_module: 'udm.device.virtual_device' + device_class: 'VirtualDevice' + } +} + +device_modules { + key: "mushroom" + value: { + device_module: 'eurtest.device.assistant_device' + device_class: 'Assistant' + } +} + +device_modules { + key: "newman" + value: { + device_module: 'eurtest.device.assistant_device' + device_class: 'Assistant' + } +} + +device_modules { + key: "nq" + value: { + device_module: 'udm.device.gq_nq' + device_class: 'GqNqDevice' + } +} + +device_modules { + key: "nq_x86_64" + value: { + device_module: 'udm.device.virtual_device' + device_class: 'VirtualDevice' + } +} + +device_modules { + key: "pepperoni" + value: { + device_module: 'eurtest.device.chromecast_audio' + device_class: 'ChromecastAudio' + } +} + +device_modules { + key: "pineapple" + value: { + device_module: 'eurtest.device.assistant_device' + device_class: 'Assistant' + } +} + +device_modules { + key: "prince" + value: { + device_module: 'eurtest.device.assistant_device' + device_class: 'Assistant' + } +} + +device_modules { + key: "salami" + value: { + device_module: 'eurtest.device.device' + device_class: 'Device' + } +} + +device_modules { + key: "sherlock" + value: { + device_module: 'udm.device.sherlock' + device_class: 'Sherlock' + } +} + +device_modules { + key: "nelson" + value: { + device_module: 'udm.device.sherlock' + device_class: 'Sherlock' + } +} + +device_modules { + key: "sherlock-assistant" + value: { + device_module: 'eurtest.device.fuchsia_assistant_device' + device_class: 'FuchsiaAssistant' + } +} + +device_modules { + key: "soba_emulator" + value: { + device_module: 'udm.device.soba' + device_class: 'Soba' + } +} + +device_modules { + key: "spencer" + value: { + device_module: 'udm.device.nest_iot_device' + device_class: 'SpencerDevice' + } +} + +device_modules { + key: "spencer_x86_64" + value: { + device_module: 'udm.device.virtual_device' + device_class: 'VirtualDevice' + } +} + +device_modules { + key: "steak" + value: { + device_module: 'eurtest.device.device' + device_class: 'Device' + } +} + +device_modules { + key: "udon_emulator" + value: { + device_module: 'udm.device.udon' + device_class: 'Udon' + } +} + +device_modules { + key: "valens" + value: { + device_module: 'eurtest.device.assistant_device' + device_class: 'Assistant' + } +} + +device_modules { + key: "vento" + value: { + device_module: 'eurtest.device.assistant_device' + device_class: 'Assistant' + } +} + +device_modules { + key: "venus" + value: { + device_module: 'udm.device.nest_iot_device' + device_class: 'SpencerDevice' + } +} + +##################### +## Test Group Tags ## +##################### +# Defines common test group tags. + +test_group_tags: [ + # Tests that verify OTA installs successfully and doesn't brick the device. + # No other tests will be run for a given build if any test in OTA_SMOKE fails. + "OTA_SMOKE", + "UNIT_TESTS", + "RECONNECT_TEST", + "GQNQ_CAMERA_ENGPROD_PRESUBMIT", + "GQNQ_VIRTUAL_PRESUBMIT" +] + +############################# +## Continuous Test Targets ## +############################# + +disabled_branches: "1.39nf" +disabled_branches: "1.39nfct" +disabled_branches: "1.42rd" +disabled_branches: "1.46rd" +disabled_branches: "1.49qfct" + +test_configs_root: "lab_system/master/config/tests/" + +# AudioPassthroughFormats + +#################### Fuchsia ##################################### +# Please keep tests ordered by binary name within this section. # +################################################################## +continuous_test: { + test_target: { + binary_name: "cycle_bitrates" + config: "cycle_bitrates/fuchsia_cycle_bitrates.cfg" + bot_pool : "gazoo-prod" + recipe: FUCHSIA_RUNNER + skip_default_dimensions: true + testbed_requirements: [ + {bot_dimension: "product", value: "nelson"}, + {bot_dimension: "device_type", value: "nelson"}, + {bot_dimension: "group", value: "COMMON"} + ] + } + build_targets: { + products: ["astro"] + branches: [{name: "1.52f"} , {name: "master"}] + } +} + +continuous_test: { + test_target: { + binary_name: "cycle_bitrates" + config: "cycle_bitrates/fuchsia_cycle_bitrates.cfg" + bot_pool : "gazoo-prod" + recipe: FUCHSIA_RUNNER + skip_default_dimensions: true + testbed_requirements: [ + {bot_dimension: "product", value: "sherlock"}, + {bot_dimension: "device_type", value: "sherlock"}, + {bot_dimension: "group", value: "COMMON"} + ] + } + build_targets: { + products: ["astro"] + branches: [{name: "1.52f"} , {name: "master"}] + } +} +#################### End of Fuchsia configurations ################# + +scheduled_test: { + test_target: { + config: "perception_latency/perception_latency.cfg" + binary_name: "perception_latency" + bot_pool : "gazoo-prod" + test_cases: ["PerceptionLatencyTestCaseMotion"] + test_timeout_mins: 120 + testbed_requirements: [ + {bot_dimension: "GROUP", value: "perception_latency"} + ] + } + schedule: { + cron: "0 * * * *" # Every 60 mins. + policy: LATEST_UNTESTED + } + build_targets: { + products: ["newman"] + variants: USER + } + branches: ["1.44", "1.45", "1.42", "master"] +} + +scheduled_test: { + test_target: { + config: "selina/gesture_data_injection.cfg" + binary_name: "selina" + bot_pool: "gazoo-prod" + enabled: true + test_timeout_mins: 180 + testbed_requirements: [ + {bot_dimension: "GROUP", value: "selina_data_injection"} + ] + } + schedule: { + cron: "30 */2 * * *" # Every 2 hour + policy: LATEST + } + build_targets: { + products: ["elaine"] + variants: ENG + } + branches: ["master", "1.56", "1.56.1"] +} + +scheduled_test: { + test_target: { + config: "selina/sleep_data_injection.cfg" + binary_name: "selina" + bot_pool: "gazoo-prod" + enabled: true + test_timeout_mins: 780 + testbed_requirements: [ + {bot_dimension: "GROUP", value: "sleep_ext4"} + ] + } + schedule: { + cron: "45 */4 * * *" # Every 4 hour + policy: LATEST + } + build_targets: { + products: ["elaine"] + variants: ENG + } + branches: ["master", "1.56", "1.56.1"] +} + +scheduled_test: { + test_target: { + config: "sound_sensing/sound_sensing_mic_writer.cfg" + binary_name: "sound_sensing" + bot_pool: "gazoo-prod" + enabled: false + test_timeout_mins: 1380 + testbed_requirements: [ + {bot_dimension: "GROUP", value: "sound_sensing_mic_writer"} + ] + } + schedule: { + cron: "30 */8 * * *" # Every 8 hour + policy: LATEST + } + build_targets: { + products: ["biggie", "elaine", "mushroom", "newman", "pineapple", "valens", "vento"] + variants: ENG + } + branches: ["master", "1.54"] +} + +scheduled_test: { + test_target: { + config: "sound_sensing/sound_sensing_mic_writer_p1.cfg" + binary_name: "sound_sensing" + bot_pool: "gazoo-prod" + enabled: false + test_timeout_mins: 1380 + testbed_requirements: [ + {bot_dimension: "GROUP", value: "sound_sensing_mic_writer"} + ] + } + schedule: { + cron: "0 */12 * * *" # Every 12th hour + policy: LATEST + } + build_targets: { + products: ["biggie", "elaine", "mushroom", "newman", "pineapple", "valens", "vento"] + variants: ENG + } + branches: ["master", "1.54"] +} + +scheduled_test: { + test_target: { + config: "sound_sensing/sound_sensing_mic_writer_p2.cfg" + binary_name: "sound_sensing" + bot_pool: "gazoo-prod" + enabled: false + test_timeout_mins: 1380 + testbed_requirements: [ + {bot_dimension: "GROUP", value: "sound_sensing_mic_writer"} + ] + } + schedule: { + cron: "0 */12 * * *" # Every 12th hour + policy: LATEST + } + build_targets: { + products: ["biggie", "elaine", "mushroom", "newman", "pineapple", "valens", "vento"] + variants: ENG + } + branches: ["master", "1.54"] +} + +continuous_test: { + test_target: { + enabled: false + config: "gqnq_contract_executor/gqnq_contract_executor_unpaired.cfg" + binary_name: "gqnq_contract_executor" + bot_pool: "gazoo-prod" + testbed_requirements: [ + {bot_dimension: "GROUP", value: "camie"} + ] + } + build_targets: { + products: ["gq", "nq", "spencer"] + variants: ENG + } +} + +continuous_test: { + test_target: { + config: "gqnq_contract_executor/gqnq_contract_executor_virtual_presubmit.cfg" + enabled: false + binary_name: "gqnq_contract_executor" + bot_pool: "gazoo-staging" + skip_default_dimensions: true + recipe: VIRTUAL_DEVICE_RUNNER + test_groups: ["GQNQ_VIRTUAL_PRESUBMIT"] + testbed_requirements: [ + {bot_dimension: "GROUP", value: "COMMON"}, + {bot_dimension: "testbed_type", value: "vdm-cq"} + ] + } + build_targets: { + products: ["gq_x86_64", "nq_x86_64", "spencer_x86_64"] + variants: ENG + branches: [ { name: "master" } ] + } +} + +continuous_test: { + test_target: { + config: "gqnq_contract_executor/gqnq_contract_executor_presubmit.cfg" + enabled: false + binary_name: "gqnq_contract_executor" + test_groups: ["GQNQ_CAMERA_ENGPROD_PRESUBMIT"] + bot_pool: "gazoo-prod" + testbed_requirements: [ + {bot_dimension: "GROUP", value: "camie-cq"} + ] + } + build_targets: { + products: ["gq", "nq"] + variants: ENG + branches: [ { name: "master" } ] + } +} + +scheduled_test: { + test_target: { + config: "selina/sleep_chester.cfg" + binary_name: "selina" + bot_pool: "gazoo-prod" + enabled: false + test_timeout_mins: 780 + testbed_requirements: [ + {bot_dimension: "GROUP", value: "sleep_positive"} + ] + } + schedule: { + cron: "30 0,12 * * *" # Every 12 hour + policy: LATEST + } + build_targets: { + products: ["elaine"] + variants: ENG + } + branches: ["1.56.2"] +} + +scheduled_test: { + test_target: { + config: "selina/sleep_chester_1_1.cfg" + binary_name: "selina" + bot_pool: "gazoo-prod" + enabled: false + test_timeout_mins: 780 + testbed_requirements: [ + {bot_dimension: "GROUP", value: "sleep_positive"} + ] + } + schedule: { + cron: "30 6,18 * * *" # Every 12 hour + policy: LATEST + } + build_targets: { + products: ["elaine"] + variants: ENG + } + branches: ["1.56.2"] +} + +scheduled_test: { + test_target: { + config: "selina/sleep_chester_2_1.cfg" + binary_name: "selina" + bot_pool: "gazoo-prod" + enabled: false + test_timeout_mins: 780 + testbed_requirements: [ + {bot_dimension: "GROUP", value: "sleep_positive"} + ] + } + schedule: { + cron: "30 3,15 * * *" # Every 12 hour + policy: LATEST + } + build_targets: { + products: ["elaine"] + variants: ENG + } + branches: ["1.56.2"] +} + +###################################################### +# # +# Libassistant configs. # +# # +###################################################### +continuous_test: { + test_target: { + binary_name: "libassistant-integration-test" + priority: CRITICAL + recipe: LIBASSISTANT_RUNNER + test_timeout_mins: 120 # Two hours + cipd_refs_key: "libassistant" + test_cases: ["testOnArm"] + testbed_requirements: [ + {bot_dimension: "GROUP", value: "COMMON"} + ] + } + build_targets: { + branch_types: MASTER + products: ["assistant"] + variants: ARM + } +} + +continuous_test: { + test_target: { + binary_name: "libassistant-integration-test" + priority: CRITICAL + recipe: LIBASSISTANT_RUNNER + test_timeout_mins: 120 # Two hours + cipd_refs_key: "libassistant" + test_cases: ["testOnX64"] + testbed_requirements: [ + {bot_dimension: "GROUP", value: "COMMON"} + ] + } + build_targets: { + branch_types: MASTER + products: ["assistant"] + variants: X64 + } +}
diff --git a/catatester/configs/staging/continuous_tests.protoascii b/catatester/configs/staging/continuous_tests.protoascii new file mode 100644 index 0000000..bbae571 --- /dev/null +++ b/catatester/configs/staging/continuous_tests.protoascii
@@ -0,0 +1,395 @@ +# -*- mode: protobuffer; -*- +# proto-file: catatester/proto/continuous_tests.proto +# proto-message: ContinuousTestsConfig + +############################################# +## CIPD packages associated with a repo ## +############################################# +# Different repos require different recipes +# bundled in cipd packages. If version is empty +# then it will replaced by the reference tag +# provided by the controller. +cipd_refs { + key: "libassistant" + value: { + refs: [ + { + package_name: "home_internal/libassistant_tools" + version: "" + path: "." + } + ] + } +} +cipd_refs { + key: "internal" + value: { + refs: [ + { + package_name: "home_internal/recipes" + version: "" + path: "." + } + ] + } +} +cipd_refs { + key: "internal_with_opal_dart", + value: { + refs: [ + { + package_name: "home_internal/recipes" + version: "" + path: "." + }, + { + package_name: "home_internal/experimental/flutter_bridge" + version: "latest" + path: "." + } + ] + } +} +##################### +## Device modules ## +##################### +# Different devices require different classes to control them. If the device +# product is not defined in this map the following defaults will be used: +# device_module = eurtest.device.device +# device_class = Device +device_modules { + key: "assistant_arm" + value: { + device_module: 'udm.device.raspberry_pi' + device_class: 'RaspberryPi' + } +} + +device_modules { + key: "assistant_x64" + value: { + device_module: 'udm.device.assistant_x64' + device_class: 'AssistantX64' + } +} + +device_modules { + key: "caprica" + value: { + device_module: 'eurtest.device.device' + device_class: 'Device' + } +} + +device_modules { + key: "pepperoni" + value: { + device_module: 'eurtest.device.chromecast_audio' + device_class: 'ChromecastAudio' + } +} + +device_modules { + key: "mushroom" + value: { + device_module: 'eurtest.device.assistant_device' + device_class: 'Assistant' + } +} + +device_modules { + key: "newman" + value: { + device_module: 'eurtest.device.assistant_device' + device_class: 'Assistant' + } +} + +device_modules { + key: "pineapple" + value: { + device_module: 'eurtest.device.assistant_device' + device_class: 'Assistant' + } +} + +device_modules { + key: "sabrina" + value: { + device_module: 'eurtest.device.android' + device_class: 'Android' + } +} + +device_modules { + key: "vento" + value: { + device_module: 'eurtest.device.assistant_device' + device_class: 'Assistant' + } +} + +# Experiment bot type with no device associated with +device_modules { + key: "x86_worker" + value: {} +} + +###################### +## Build Priorities ## +###################### + +branch_type_priorities: [RELEASE, MASTER] + +############################# +## Continuous Test Targets ## +############################# +test_configs_root: "lab_system/master/config/tests/" + +test_group_tags: [ + # Tests that verify OTA installs successfully and doesn't brick the device. + # No other tests will be run for a given build if any test in OTA_SMOKE fails. + "OTA_SMOKE", + "UNIT_TESTS" +] + +disabled_branches: "1.39nf" +disabled_branches: "1.39nfct" +disabled_branches: "1.42rd" + +# Assistant end to end query latency tests. +scheduled_test: { + test_target: { + config: "assistant_query_latency/canonical_queries_latency_dogfood.cfg" + binary_name: "assistant_query_latency" + enabled: false + testbed_requirements: [ + {bot_dimension: "GROUP", value: "chirp_latency"} + ] + } + schedule: { + cron: "*/30 * * * *" # Every 30 mins + policy: LATEST + } + build_targets: { + branch_types: MASTER + products: ["pineapple"] + variants: USER + } +} + +continuous_test: { + test_target: { + config: "ota_installable/ota_installable.cfg" + binary_name: "ota_installable" + priority: CRITICAL + test_groups: ["OTA_SMOKE"] + testbed_requirements: [ + {bot_dimension: "GROUP", value: "COMMON"} + ] + recipe: OTA_INSTALLABLE_RUNNER + } + build_targets: { + branch_types: MASTER + products: ["prince", "valens"] + variants: ENG + } +} + +continuous_test: { + test_target: { + config: "crash_loop/crash_loop.cfg" + binary_name: "crash_loop" + priority: CRITICAL + test_groups: ["OTA_SMOKE"] + testbed_requirements: [ + {bot_dimension: "GROUP", value: "COMMON"} + ] + recipe: OTA_INSTALLABLE_RUNNER + } + build_targets: { + branch_types: MASTER + products: ["prince", "valens"] + variants: ENG + } +} + +# This config is here just as an example of a config that uses builder_names. +# Test is disabled. +continuous_test: { + test_target: { + config: "cast/receiver.cfg" + binary_name: "cast" + enabled: false + test_cases: [ + "CastReceiverCapabilityTestCase" + ] + testbed_requirements: [ + {bot_dimension: "GROUP", value: "COMMON"} + ] + } + build_targets: { + builder_names: ["steak-yeti-user"] + branch_types: MASTER + variants: USER + } +} + +continuous_test: { + test_target: { + config: "reconnect_test/reconnect_test.cfg" + binary_name: "reconnect_test" + testbed_requirements: [ + {bot_dimension: "GROUP", value: "COMMON"} + ] + } + build_targets: { + branch_types: MASTER + products: ["newman"] + variants: ENG + } +} + +continuous_test: { + test_target: { + config: "ndm_integration/ndm_integration.cfg" + binary_name: "ndm_integration" + testbed_requirements: [ + {bot_dimension: "GROUP", value: "COMMON"} + ] + } + build_targets: { + branch_types: MASTER + products: ["newman"] + variants: USER + } +} + +continuous_test: { + test_target: { + config: "fakeoculus_reconnect_proxy/fakeoculus_reconnect_proxy.cfg" + binary_name: "fakeoculus_reconnect_proxy" + testbed_requirements: [ + {bot_dimension: "GROUP", value: "COMMON"} + ] + } + build_targets: { + branch_types: MASTER + products: ["newman"] + variants: USER + } +} + +continuous_test: { + test_target: { + config: "cast_video/video_encode_accelerator.cfg" + binary_name: "cast_video" + test_timeout_mins: 120 + testbed_requirements: [ + {bot_dimension: "GROUP", value: "COMMON"} + ] + } + build_targets: { + branch_types: MASTER + products: ["newman"] + variants: USER + } +} + +continuous_test: { + test_target: { + config: "cast_video/video_decode_accelerator.cfg" + binary_name: "cast_video" + test_timeout_mins: 120 + testbed_requirements: [ + {bot_dimension: "GROUP", value: "COMMON"} + ] + } + build_targets: { + branch_types: MASTER + products: ["newman"] + variants: USER + } +} + +###################################################### +# # +# Libassistant configs. # +# # +###################################################### + +# Disable test for Gazoo libassistant experiment b/161898246. +# continuous_test: { +# test_target: { +# binary_name: "libassistant-integration-test" +# priority: CRITICAL +# recipe: LIBASSISTANT_RUNNER +# test_timeout_mins: 120 # Two hours +# cipd_refs_key: "libassistant" +# test_cases: ["testOnArm"] +# } +# build_targets: { +# branch_types: MASTER +# products: ["assistant"] +# variants: ARM +# } +# } + +continuous_test: { + test_target: { + binary_name: "libassistant-integration-test" + priority: CRITICAL + recipe: LIBASSISTANT_RUNNER + test_timeout_mins: 120 # Two hours + cipd_refs_key: "libassistant" + test_cases: ["testOnX64"] + testbed_requirements: [ + {bot_dimension: "GROUP", value: "COMMON"} + ] + } + build_targets: { + branch_types: MASTER + products: ["assistant"] + variants: X64 + } +} +###################################################### +# # +# Thread Unit Tests configs. # +# # +###################################################### +continuous_test: { + test_target: { + config: "thread/thread.cfg" + binary_name: "thread" + testbed_requirements: [ + {bot_dimension: "GROUP", value: "COMMON"} + ] + } + build_targets: { + branch_types: MASTER + products: ["newman"] + variants: USER + } +} + +scheduled_test: { + test_target: { + cipd_refs_key: "internal_with_opal_dart" + config: "manhattan_ui_perf/opal_back_gestures.cfg" + binary_name: "manhattan_ui_perf" + test_timeout_mins: 30 + testbed_requirements: [ + {bot_dimension: "GROUP", value: "COMMON"} + ] + } + schedule: { + cron: "0 0 * * *" # Every day at 00:00 hours + policy: LATEST + } + build_targets: { + branch_types: MASTER + products: ["newman"] + variants: USER + } +}
diff --git a/catatester/devicemap/__init__.py b/catatester/devicemap/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/catatester/devicemap/__init__.py
diff --git a/catatester/devicemap/bot_setup.py b/catatester/devicemap/bot_setup.py new file mode 100644 index 0000000..7b3bbf4 --- /dev/null +++ b/catatester/devicemap/bot_setup.py
@@ -0,0 +1,277 @@ +"""A helper script to setup and start bots on a host machine. + + This script does following: + - Parses devicemap.yaml and finds out how many bots are needed for a host. + - Check if bot directories exist and create bot directories as needed. + - Create systemd configs and bot startup script. + - Run systemctl start swarming_bot--<bot number> for any bots not currently + running + +NOTE: This script is being invoked from a puppet manifest and will not have +access to rest of the test code or python virtual environment. So keep in mind +to not use any non standard python libraries. + +Example usage: + python bot_setup.py bot_setup.py \ + --user gtvchrome --group gtvchrome --swarm-bots-home /home/bots_home \ + --gsutil-dir /home/gsutil_home --gsutil-boto /home/.boto \ + --fragglerock-key /home/fragglerock_service_key.json \ + --eurtest-binaries /home/eurtest_binaries --venv /home/bots-home/swarm_env +""" + +import argparse +import errno +import grp +import logging +import os +import pwd +import shutil +import socket +import string +import subprocess +import sys +import yaml + +# This code runs on catatester host and doesn't have whole code tree, hence +# do relative import. +try: + from catatester.devicemap import devicemap_lib +except ImportError: + import devicemap_lib # pylint: disable=relative-import + + +_BOT_FILE_MODE = 0o774 # permit owner group execution +_SYSTEMD_FILE_MODE = 0o644 # permit owner group write +_ROOT_USER = 'root' +# TODO(adrexler): Remove _DEVICEMAP_DIR once the arg is being passed from +# puppet. +_DEVICEMAP_DIR = os.path.dirname(os.path.realpath(__file__)) +_STARTUP_SCRIPT_TEMPLATE_PATH = os.path.join( + _DEVICEMAP_DIR, 'swarm_bot_startup.sh.template') +_STARTUP_SCRIPTS_PATH = 'startup_scripts' +_SWARM_BOT_PREFIX = 'swarming_bot--' +_SWARM_ZIP_RELATIVE_PATH_TO_BOT_HOME = '1/swarming_bot.zip' +_SYSTEMD_TEMPLATE_PATH = os.path.join( + _DEVICEMAP_DIR, 'swarm_bot.systemd.template') +_DEPOT_TOOLS_DIR = os.path.join(os.path.expanduser('~'), 'depot_tools') + + +class OSException(Exception): + """Exception class to handle OS Exceptions.""" + + +def _GetNumBotConfigs(hostname): + """Gets the number of bot configs assigned to the given hostname. + + Args: + hostname: (String) Catatester hostame. + + Returns: + An integer, The number of bot configs for given hostname. + """ + logging.debug('Finding bots needed for host [%s]', hostname) + configs = devicemap_lib.Configs() + return configs.GetNumBotConfigs(hostname) + + +def CreateStartupScript( + user, group, swarm_bots_home, bot_num, bot_name, gsutil_dir, + gsutil_boto, fragglerock_key, eurtest_binaries, venv, + devicemap_dir, depot_tools_dir): + """Create the bot startup script. + + This method loads tokenized swarm_bot_startup.sh.template file, replaces the + tokens with given param values and writes it into bot folder. + + Args: + user: (String) User name of the catatester host. + group: (String) Group name that is user is part of. + swarm_bots_home: (String) Root directory of all the bots. + bot_num: (Integer) The N-th bot to be created. + bot_name: (String) Bot service name. + gsutil_dir: (String) Path to gsutil installation in the host. + gsutil_boto: (String) Path to gsutil boto file in the host. + fragglerock_key: (String) Path to auth key file in the host. + eurtest_binaries: (String) Path to test binaries in the host. + venv: (String) Path to python virtual environment to be used. + devicemap_dir: (String) Path to devicemap directory on host. + depot_tools_dir: (String) Path to depot tools directory. + + Returns: + The path of newly created startup script. + """ + bot_dir_path = os.path.join(swarm_bots_home, str(bot_num)) + with open(_STARTUP_SCRIPT_TEMPLATE_PATH, 'r') as bot_startup: + bot_startup_template = bot_startup.read() + startup_script_content = string.Template(bot_startup_template).substitute( + bot_dir=bot_dir_path, + devicemap_dir=devicemap_dir, + eurtest_binaries=eurtest_binaries, + fragglerock_key=fragglerock_key, + gsutil_dir=gsutil_dir, + gsutil_boto=gsutil_boto, + venv=venv, + depot_tools_dir=depot_tools_dir + ) + startup_script_path = os.path.join(swarm_bots_home, _STARTUP_SCRIPTS_PATH, + '%s_startup.sh' % bot_name) + _CreateFile( + startup_script_path, startup_script_content, user, group, _BOT_FILE_MODE) + return startup_script_path + + +def CreateSystemdServiceFile( + bot_service_name, startup_script_path, user, group): + """Create the systemd service script for a bot. + + This method loads tokenized swarm_bot.systemd.template file, replaces the + tokens with given param values and writes it into systemd service folder. + + Args: + bot_service_name: (String) The systemd service name to be used. + startup_script_path: (String) Startup script path of the bot. + user: (String) User name of the catatester host. + group: (String) Group name that is user is part of. + """ + with open(_SYSTEMD_TEMPLATE_PATH, 'r') as bot_systemd: + bot_systemd_template = bot_systemd.read() + systemd_service_content = string.Template(bot_systemd_template).substitute( + bot_name=bot_service_name, + group=group, + user=user, + startup_script_path=startup_script_path) + systemd_service_path = '/etc/systemd/system/%s.service' % bot_service_name + _CreateFile( + systemd_service_path, systemd_service_content, _ROOT_USER, _ROOT_USER, + _SYSTEMD_FILE_MODE) + + +def SetupBot( + bot_num, user, group, swarm_bots_home, swarm_bot_prefix, swarm_zip_path, + gsutil_dir, gsutil_boto, fragglerock_key, eurtest_binaries, venv, + devicemap_dir, depot_tools_dir): + """Setup the swarming bot. + + This method : + 1. Creates bot directory. + 2. Copies the swarm binary to bot directory. + 3. Creates start up scripts and systemd configs the bot. + 4. Do a systemd config reload. + 5. And finally start the bot service, if its not up. + + Args: + bot_num: (Integer) The N-th bot to be created. + user: (String) User name of the catatester host. + group: (String) Group name that is user is part of. + swarm_bots_home: (String) Root directory of the bots. + swarm_bot_prefix: (String) Prefix to be used for bot service name. + swarm_zip_path: (String) Swarming binary path in the host. + gsutil_dir: (String) Path to gsutil installation in the host. + gsutil_boto: (String) Path to gsutil boto file in the host. + fragglerock_key: (String) Path to auth key file in the host. + eurtest_binaries: (String) Path to test binaries in the host. + venv: (String) Path to python virtual environment to be used. + devicemap_dir: (String) Path to the device map directory. + depot_tools_dir: (String) Path to depot tools directory. + """ + logging.debug('Working on bot #%s', bot_num) + # Create bot directory. + bot_dir_path = os.path.join(swarm_bots_home, str(bot_num)) + if not os.path.exists(bot_dir_path): + logging.info('Creating directory: %s', bot_dir_path) + os.makedirs(bot_dir_path) + _UpdateFilePermissions(bot_dir_path, user, group, _BOT_FILE_MODE) + # Copy swarm binary + if os.path.dirname(swarm_zip_path) != bot_dir_path: + shutil.copy(swarm_zip_path, bot_dir_path) + _UpdateFilePermissions(swarm_zip_path, user, group, _BOT_FILE_MODE) + # Create startup scripts. + bot_name = '%s%s' % (swarm_bot_prefix, bot_num) + startup_script_path = CreateStartupScript( + user, group, swarm_bots_home, bot_num, bot_name, gsutil_dir, gsutil_boto, + fragglerock_key, eurtest_binaries, venv, devicemap_dir, depot_tools_dir) + CreateSystemdServiceFile(bot_name, startup_script_path, user, group) + # Reload the daemon, check bot status and start service if needed. + if subprocess.call(['systemctl', 'daemon-reload']): + sys.exit('Failed to reload systemctl daemon for bot # %s' % bot_num) + if subprocess.call(['systemctl', 'is-active', '--quiet', bot_name]): + logging.debug('Bot number [%s] not running. Starting now.', bot_num) + if subprocess.call(['systemctl', 'start', bot_name]): + sys.exit('Failed to start bot # %s' % bot_num) + + +def _UpdateFilePermissions(file_path, owner, group, mode): + """Update file with specified mode and permissions.""" + uid = pwd.getpwnam(owner).pw_uid + gid = grp.getgrnam(group).gr_gid + os.chown(file_path, uid, gid) + os.chmod(file_path, mode) + + +def _CreateFile(file_path, content, owner, group, mode): + """Create file with specified content, mode and permissions.""" + if not os.path.exists(os.path.dirname(file_path)): + try: + os.makedirs(os.path.dirname(file_path)) + _UpdateFilePermissions(os.path.dirname(file_path), owner, group, mode) + except OSError as exc: + if exc.errno != errno.EEXIST: + raise OSException('Unable to create dir %s due to %s.' + % (os.path.dirname(file_path), exc)) + + with open(file_path, 'w') as f: + f.write(content) + _UpdateFilePermissions(file_path, owner, group, mode) + + +def _ParseArgs(): + """Parses command-line input.""" + parser = argparse.ArgumentParser() + parser.add_argument( + '--user', help='User name of the catatester host.', required=True) + parser.add_argument('--group', help='Group name to be used.', required=True) + parser.add_argument( + '--swarm_bots_home', help='Root directory of the bots.', required=True) + parser.add_argument( + '--gsutil_dir', help='Path to gsutil installation.', required=True) + parser.add_argument( + '--gsutil_boto', help='Path to gs util boto file.', required=True) + parser.add_argument( + '--fragglerock_key', help='Path to fragglerock auth key file.', + required=True) + parser.add_argument( + '--eurtest_binaries', help='Test binary path.', required=True) + parser.add_argument( + '--venv', help='Path to python to virtual environment.', required=True) + parser.add_argument( + '--devicemap_dir', help='Path to devicemap directory on the host.', + default=_DEVICEMAP_DIR) + parser.add_argument( + '--depot_tools_dir', help='Path to depot_tools in the host.', + default=_DEPOT_TOOLS_DIR) + args = parser.parse_args() + logging.debug('Executing with flags: %s', args) + return args + + +def main(): + flags = _ParseArgs() + bot_count = _GetNumBotConfigs(socket.gethostname().split('.')[0]) + swarm_bots_home = flags.swarm_bots_home + swarm_zip_path = os.path.join( + swarm_bots_home, _SWARM_ZIP_RELATIVE_PATH_TO_BOT_HOME) + if not os.path.exists(swarm_zip_path): + raise ValueError('Swarm binary does not exists at %s' % swarm_zip_path) + for bot_num in range(1, bot_count +1): + SetupBot( + bot_num=bot_num, user=flags.user, group=flags.group, + swarm_bots_home=swarm_bots_home, swarm_bot_prefix=_SWARM_BOT_PREFIX, + swarm_zip_path=swarm_zip_path, gsutil_dir=flags.gsutil_dir, + gsutil_boto=flags.gsutil_boto, fragglerock_key=flags.fragglerock_key, + eurtest_binaries=flags.eurtest_binaries, venv=flags.venv, + devicemap_dir=flags.devicemap_dir, + depot_tools_dir=flags.depot_tools_dir) + + +if __name__ == '__main__': + main()
diff --git a/catatester/devicemap/bot_setup_test.py b/catatester/devicemap/bot_setup_test.py new file mode 100644 index 0000000..2784650 --- /dev/null +++ b/catatester/devicemap/bot_setup_test.py
@@ -0,0 +1,111 @@ +"""Tests for the bot_setup module.""" +import os +import shutil +import subprocess +import tempfile +import unittest +from catatester.devicemap import bot_setup + +try: + from unittest import mock +except ImportError: + import mock + +_STARTUP_SCRIPTS_PATH = 'startup_scripts' + + +class BotSetupTest(unittest.TestCase): + """Tests for the methods in bot_setup module.""" + + def setUp(self): + self._swarm_bots_home = tempfile.mkdtemp() + self.addCleanup(self.cleanUp) + self.addCleanup(mock.patch.stopall) + self._mock_subprocess_call = mock.patch( + 'subprocess.call', autospec=True, spec_set=True).start() + self._mock_copy_file = mock.patch( + 'shutil.copy', autospec=True, spec_set=True).start() + self._mock_create_file = mock.patch( + 'catatester.devicemap.bot_setup._CreateFile', + autospec=True, spec_set=True).start() + self._mock_update_file_mode = mock.patch( + 'catatester.devicemap.bot_setup._UpdateFilePermissions', + autospec=True, spec_set=True).start() + + def cleanUp(self): + shutil.rmtree(self._swarm_bots_home) + + def testSetupBotsCreatesNewDirCopiesFileAndStartsService(self): + """Validates setup_bot method can successfully start bot service.""" + self._mock_subprocess_call.side_effect = [0, 1, 0] + bot_num = 2 + bot_setup.SetupBot( + bot_num=bot_num, + user='mock_user', + group='mock_group', + swarm_bots_home=self._swarm_bots_home, + swarm_bot_prefix='mock_swarm_bot_prefix', + swarm_zip_path='mock_swarm_zip_path', + gsutil_dir='mock_gsutil_dir', + gsutil_boto='mock_gsutil_boto', + fragglerock_key='mock_fragglerock_key', + eurtest_binaries='mock_eurtest_binaries', + venv='mock_venv', + devicemap_dir='mock_devicemap_dir', + depot_tools_dir='mock_depot_tools' + ) + self.assertEqual( + 1, len(os.listdir(self._swarm_bots_home)), 'Bot directory not created.') + self.assertTrue( + os.path.isdir(os.path.join(self._swarm_bots_home, str(bot_num))), + 'Bot directory not created.') + expected_systemd_file_path = ( + '/etc/systemd/system/mock_swarm_bot_prefix%s.service' % bot_num) + expected_sh_path = ( + os.path.join( + self._swarm_bots_home, _STARTUP_SCRIPTS_PATH, + 'mock_swarm_bot_prefix%s_startup.sh' % bot_num)) + self._mock_create_file.assert_has_calls([ + mock.call( + file_path=expected_sh_path, content=mock.ANY, + owner='mock_user', group='mock_group', mode=508), + mock.call( + file_path=expected_systemd_file_path, content=mock.ANY, + owner='root', group='root', mode=420) + ]) + self._mock_subprocess_call.assert_has_calls([ + mock.call(['systemctl', 'daemon-reload']), + mock.call([ + 'systemctl', 'is-active', '--quiet', + 'mock_swarm_bot_prefix%s' % bot_num + ]), + mock.call([ + 'systemctl', 'start', 'mock_swarm_bot_prefix%s' % bot_num]) + ]) + self._mock_update_file_mode.assert_has_calls([ + mock.call(mock.ANY, 'mock_user', 'mock_group', 508), + mock.call('mock_swarm_zip_path', 'mock_user', 'mock_group', 508) + ]) + + def testBotServiceNotRestartedIfItsRunning(self): + """Validates setup_bot doesn't restart an already running bot service.""" + self._mock_subprocess_call.side_effect = [0, 0] + bot_setup.SetupBot( + bot_num=1, + user='mock_user', + group='mock_group', + swarm_bots_home=self._swarm_bots_home, + swarm_bot_prefix='mock_swarm_bot_prefix', + swarm_zip_path='mock_swarm_zip_path', + gsutil_dir='mock_gsutil_dir', + gsutil_boto='mock_gsutil_boto', + fragglerock_key='mock_fragglerock_key', + eurtest_binaries='mock_eurtest_binaries', + venv='mock_venv', + devicemap_dir='mock_devicemap_dir', + depot_tools_dir='mock_depot_tools') + self._mock_subprocess_call.assert_called_with([ + 'systemctl', 'is-active', '--quiet', 'mock_swarm_bot_prefix1']) + +if __name__ == '__main__': + unittest.main()
diff --git a/catatester/devicemap/cipd.yaml b/catatester/devicemap/cipd.yaml new file mode 100644 index 0000000..c5d9af6 --- /dev/null +++ b/catatester/devicemap/cipd.yaml
@@ -0,0 +1,10 @@ +package: home_internal/devicemap +description: Device Configs for Swarming Bots +root: ./ + +data: + + - dir: ./ + exclude: + - .*\.pyc + - .*\/.* # no subdirectories needed
diff --git a/catatester/devicemap/devicemap.py b/catatester/devicemap/devicemap.py new file mode 100644 index 0000000..54e454b --- /dev/null +++ b/catatester/devicemap/devicemap.py
@@ -0,0 +1,66 @@ +"""CLI to query bot dimensions for the device(s) of a given bot. + +Example usage: + python devicemap.py home-swarming-bot-host-3--7 + (writes bot dimensions & state as python dict to stdout) +""" + +import argparse +import json +import logging +import os +import re +import yaml + +# This code runs on catatester host and doesn't have whole code tree, hence +# do relative import. +try: + from catatester.devicemap import devicemap_lib +except ImportError: + import devicemap_lib # pylint: disable=relative-import + + +_BOTNAME_PATTERN = r'(.*)--(\d*)' + + +def _ParseArgs(): + """Parses command-line input.""" + parser = argparse.ArgumentParser() + + parser.add_argument( + 'botname', + help='Name of the bot, in the format <hostname>--<bot #>', + ) + + parser.add_argument( + '--output_file', + help='Absolute path to the output file to write dimensions (as json).' + ) + + # Argument Validations + args = parser.parse_args() + match = re.match(_BOTNAME_PATTERN, args.botname) + if not match: + parser.error('invalid botname') + if not int(match.group(2)) > 0: + parser.error('bot # must be > 0') + logging.info('Running with: %s', args) + return args + + +def main(): + flags = _ParseArgs() + match = re.match(_BOTNAME_PATTERN, flags.botname) + hostname = match.group(1) + bot_num = int(match.group(2)) + + configs = devicemap_lib.Configs() + bot_config = configs.GetBotConfig(hostname, bot_num) + print(bot_config) + if flags.output_file: + with open(flags.output_file, 'w') as f: + f.write(json.dumps(bot_config.as_dict)) + + +if __name__ == '__main__': + main()
diff --git a/catatester/devicemap/devicemap.yaml b/catatester/devicemap/devicemap.yaml new file mode 100644 index 0000000..f4fc61f --- /dev/null +++ b/catatester/devicemap/devicemap.yaml
@@ -0,0 +1,271 @@ +#i Devicemap configuration file. Defines devices and maps them to a bot host. + +# Defines which dimensions are allowed for each type of config. +# This ensures consistency between configs and ensure no spelling mistakes. +allowed_dimensions: + +# organized by config type: Testbed, Device (i.e. salami, biggie, etc) + Testbed: + - device_ip + - device_type + - group + - location + Device: + - device_ip + - device_type + - group + - nic + - serial + - use_tunnel # String('true', 'false'). Default 'false' + - factory_reset # String('true', 'false'). Default 'true' + - location + +# Testbed & device configs, organized by hostname +hosts: + home-swarming-bot-host-1: + host_ip: 100.115.4.128 + hosted_devices: + - assistant_x64: {ip: assistant_x64_ip_2} + - assistant_x64: {ip: assistant_x64_ip_3} + location: us-mtv-946-1e3b + + home-swarming-bot-host-23: + host_ip: 100.127.32.3 + hosted_devices: + - assistant_x64: {ip: assistant_x64_ip_4} + - assistant_x64: {ip: assistant_x64_ip_5} + location: us-mtv-946-1e3b + + home-swarming-bot-host-30: + host_ip: 100.127.36.4 + hosted_devices: + - assistant_arm: {ip: 100.127.36.181} + - assistant_arm: {ip: 100.127.36.182} + location: us-mtv-1210-1f9 + + home-swarming-bot-host-33: + host_ip: 100.127.37.3 + hosted_devices: + - soba_emulator: + ip: 'gcloud_ip_3' + extra_state: + gce_image: 'androidthings-latest' + gce_instance_name: 'androidthings-emulator-003' + gce_instance_project: 'fragglerock' + gce_instance_zone: 'us-central1-c' + - soba_emulator: + ip: 'gcloud_ip_4' + extra_state: + gce_image: 'androidthings-latest' + gce_instance_name: 'androidthings-emulator-004' + gce_instance_project: 'fragglerock' + gce_instance_zone: 'us-central1-c' + - soba_emulator: + ip: 'gcloud_ip_5' + extra_state: + gce_image: 'androidthings-latest' + gce_instance_name: 'androidthings-emulator-005' + gce_instance_project: 'fragglerock' + gce_instance_zone: 'us-central1-c' + - soba_emulator: + ip: 'gcloud_ip_6' + extra_state: + gce_image: 'androidthings-latest' + gce_instance_name: 'androidthings-emulator-006' + gce_instance_project: 'fragglerock' + gce_instance_zone: 'us-central1-c' + - udon_emulator: + ip: 'gcloud_ip_7' + extra_state: + gce_image: 'androidthings-latest' + gce_instance_name: 'androidthings-emulator-007' + gce_instance_project: 'fragglerock' + gce_instance_zone: 'us-central1-c' + - udon_emulator: + ip: 'gcloud_ip_8' + extra_state: + gce_image: 'androidthings-latest' + gce_instance_name: 'androidthings-emulator-008' + gce_instance_project: 'fragglerock' + gce_instance_zone: 'us-central1-c' + - udon_emulator: + ip: 'gcloud_ip_9' + extra_state: + gce_image: 'androidthings-latest' + gce_instance_name: 'androidthings-emulator-009' + gce_instance_project: 'fragglerock' + gce_instance_zone: 'us-central1-c' + - udon_emulator: + ip: 'gcloud_ip_10' + extra_state: + gce_image: 'androidthings-latest' + gce_instance_name: 'androidthings-emulator-010' + gce_instance_project: 'fragglerock' + gce_instance_zone: 'us-central1-c' + - Testbed: + dimensions: + device_type: 'newman' + device_ip: ['100.127.37.28', '100.127.37.29'] + group: ['duo_multi_device'] + extra_state: + devices: ['100.127.37.28', '100.127.37.29'] + factory_reset: 'false' + location: us-mtv-1210-1f9 + + home-swarming-bot-host-34: + host_ip: 100.127.37.65 + hosted_devices: + - assistant_x64: {ip: assistant_x64_ip_6} + - assistant_x64: {ip: assistant_x64_ip_7} + - assistant_x64: {ip: assistant_x64_ip_8} + - assistant_x64: {ip: assistant_x64_ip_9} + - Testbed: + dimensions: + device_type: 'valens' + device_ip: ['100.127.37.96', '100.127.37.97'] + group: ['duo_multi_device'] + extra_state: + devices: ['100.127.37.96', '100.127.37.97'] + factory_reset: 'false' + - Testbed: + dimensions: + device_type: 'newman' + device_ip: ['100.127.37.56', '100.127.37.57'] + group: ['duo_enabled_multi_device_test'] + extra_state: + devices: ['100.127.37.56', '100.127.37.57'] + factory_reset: 'false' + location: us-mtv-1210-1f9 + + home-swarming-comm-host-11: + host_ip: 100.109.25.51 + hosted_devices: + - pineapple: + ip: 100.115.57.5 + group: ['chirp_call_quality'] + use_tunnel: 'true' + factory_reset: 'false' + - mushroom: + ip: 100.115.57.6 + group: ['chirp_call_quality'] + use_tunnel: 'true' + factory_reset: 'false' + - biggie: + ip: 100.115.57.7 + group: ['chirp_call_quality'] + use_tunnel: 'true' + factory_reset: 'false' + - pineapple: + ip: 100.127.18.115 + extra_state: + email: 'cast.test.dev24@gmail.com' + id: 523948437256 + gaia_id: 523948437256 + group: ['chirp_calls'] + use_tunnel: 'true' + factory_reset: 'false' + - pineapple: + ip: 100.127.18.116 + extra_state: + email: 'cast.test.dev25@gmail.com' + id: 946528234552 + gaia_id: 946528234552 + group: ['chirp_calls'] + use_tunnel: 'true' + factory_reset: 'false' + - pineapple: + ip: 100.127.18.124 + extra_state: + email: 'cast.test.dev41@gmail.com' + id: 725720652722 + gaia_id: 725720652722 + group: ['chirp_calls'] + use_tunnel: 'true' + factory_reset: 'false' + - pineapple: + ip: 100.127.18.132 + extra_state: + email: 'cast.test.dev52@gmail.com' + id: 981210082107 + gaia_id: 981210082107 + group: ['chirp_calls'] + use_tunnel: 'true' + factory_reset: 'false' + - pineapple: + ip: 100.127.18.133 + extra_state: + email: 'cast.test.dev53@gmail.com' + id: 725865104723 + gaia_id: 725865104723 + group: ['chirp_calls'] + use_tunnel: 'true' + factory_reset: 'false' + - mushroom: + ip: 100.127.19.26 + extra_state: + email: 'cast.test.dev128@gmail.com' + id: 751760269505 + gaia_id: 751760269505 + group: ['chirp_calls'] + use_tunnel: 'true' + factory_reset: 'false' + - mushroom: + ip: 100.127.19.27 + extra_state: + email: 'cast.test.dev129@gmail.com' + id: 679953433622 + gaia_id: 679953433622 + group: ['chirp_calls'] + use_tunnel: 'true' + factory_reset: 'false' + - mushroom: + ip: 100.127.19.28 + extra_state: + email: 'cast.test.dev130@gmail.com' + id: 441194473759 + gaia_id: 441194473759 + group: ['chirp_calls'] + use_tunnel: 'true' + factory_reset: 'false' + - mushroom: + ip: 100.127.19.29 + extra_state: + email: 'cast.test.dev131@gmail.com' + id: 773516650003 + gaia_id: 773516650003 + group: ['chirp_calls'] + use_tunnel: 'true' + factory_reset: 'false' + - mushroom: + ip: 100.127.19.30 + extra_state: + email: 'cast.test.dev132@gmail.com' + id: 275275875917 + gaia_id: 275275875917 + group: ['chirp_calls'] + use_tunnel: 'true' + factory_reset: 'false' + - biggie: + ip: 100.127.19.101 + extra_state: + email: 'cast.test.dev100@gmail.com' + id: 198087117950 + gaia_id: 198087117950 + group: ['chirp_calls'] + use_tunnel: 'true' + factory_reset: 'false' + location: corp-ganeti + + home-swarming-corp-host-3: + host_ip: 100.109.25.61 + hosted_devices: + - pineapple: + ip: 100.127.18.146 + extra_state: + email: 'cast.test.dev40@gmail.com' + id: 1039204980935 + gaia_id: 1039204980935 + group: ['signed_in'] + use_tunnel: 'true' + factory_reset: 'false' + location: corp-ganeti
diff --git a/catatester/devicemap/devicemap_config_test.py b/catatester/devicemap/devicemap_config_test.py new file mode 100644 index 0000000..92fea5f --- /dev/null +++ b/catatester/devicemap/devicemap_config_test.py
@@ -0,0 +1,89 @@ +"""Tests for devicemap.yaml config file.""" + +import unittest + +from catatester.devicemap import devicemap_lib + + +class DeviceMapConfigTest(unittest.TestCase): + """Tests for devicemap config file.""" + + def assertBotConfigMatchesSwarmingSchema(self, bot_config): + self.assertIn('dimensions', bot_config) + self.assertIn('state', bot_config) + for value in bot_config['dimensions'].values(): + self.assertTrue(hasattr(value, '__iter__')) + + def assertDimensionsAllowed(self, config, configs): + """Checks that all the given dimensions are in allowed_dimensions.""" + allowed_dimensions = configs.GetAllowedDimensions(config.type) + allowed_dimensions.add('extra_state') + dimensions = set(config.dimensions) + if not dimensions.issubset(allowed_dimensions): + raise devicemap_lib.DeviceMapError( + 'Dimensions not currently allowed: %s' % ', '.join( + dimensions - allowed_dimensions)) + + def testAllowedDimensionsAreDefined(self): + configs = devicemap_lib.Configs() + self.assertTrue(configs.GetAllowedDimensions('Testbed')) + self.assertTrue(configs.GetAllowedDimensions('Device')) + + def testEveryConfigIsValid(self): + configs = devicemap_lib.Configs() + for host in configs.hosts: + for bot_num in range(1, configs.GetNumBotConfigs(host) + 1): + try: + config = configs.GetBotConfig(host, bot_num) + self.assertIn('dimensions', config.as_dict) + self.assertDimensionsAllowed(config, configs) + except devicemap_lib.DeviceMapError as e: + raise AssertionError('config failure for %s--%s:\n%s\n%s' % ( + host, bot_num, config, e)) + + def testNoDuplicateDevices(self): + configs = devicemap_lib.Configs() + device_ips = set() + device_serials = set() + for host in configs.hosts: + for bot_num in range(1, configs.GetNumBotConfigs(host) + 1): + config = configs.GetBotConfig(host, bot_num) + if config.type == 'Device': + dimensions = config.dimensions + if 'device_ip' in dimensions: + ip = dimensions['device_ip'] + self.assertNotIn(ip, device_ips, 'duplicate ip found: %s' % ip) + device_ips.add(ip) + if 'serial' in dimensions: + serial = dimensions['serial'] + device_serials.add(serial) + self.assertNotIn(ip, device_serials, + 'duplicate serial found: %s' % serial) + + def testMultizoneHostConfig(self): + """Tests the configuration of multizone hosts.""" + configs = devicemap_lib.Configs() + for host in configs.hosts: + if 'multizone' not in host: + continue + for bot_num in range(1, configs.GetNumBotConfigs(host) + 1): + config = configs.GetBotConfig(host, bot_num) + self.assertIn('audio_card_id', config.state, + 'No "audio_card_id" in %r:%r.' % (host, bot_num)) + self.assertRegexpMatches( + config.state['audio_card_id'], r'hw:\d,\d', + '"audio_card_id" in %r:%r is invalid.' % (host, bot_num)) + self.assertIn('audio_card_ports', config.state, + 'No "audio_card_ports" in %r:%r.' % (host, bot_num)) + self.assertIsInstance( + config.state['audio_card_ports'], list, + '"audio_card_ports" in %r:%r is not a list.' % (host, bot_num)) + self.assertIn('devices', config.state, + 'No "devices" in %r:%r.' % (host, bot_num)) + self.assertIsInstance( + config.state['devices'], list, + '"devices" in %r:%r is not a list.' % (host, bot_num)) + + +if __name__ == '__main__': + unittest.main()
diff --git a/catatester/devicemap/devicemap_e2e_test.py b/catatester/devicemap/devicemap_e2e_test.py new file mode 100644 index 0000000..2f10d02 --- /dev/null +++ b/catatester/devicemap/devicemap_e2e_test.py
@@ -0,0 +1,99 @@ +"""E2E Tests for the devicemap.py script.""" + +import ast +import logging +import os +import subprocess +import sys +import unittest + +from catatester.devicemap import devicemap_lib +import yaml + + +_DEVICEMAP_DIR = os.path.dirname(os.path.abspath(__file__)) +_DEVICEMAP_SCRIPT = os.path.join(_DEVICEMAP_DIR, 'devicemap.py') +# Maximum allowed bots per host +_MAX_BOTS = 60 +_YAML_FILE = os.path.join(_DEVICEMAP_DIR, 'devicemap.yaml') + + +class DeviceMapE2ETest(unittest.TestCase): + """E2E Tests for the devicemap.py script.""" + + def setUp(self): + super(DeviceMapE2ETest, self).setUp() + self.configs = None + with open(_YAML_FILE, 'r') as f: + self.configs = devicemap_lib.Configs(yaml.safe_load(f)) + + def testGetBotConfig_fromStdout(self): + p = subprocess.Popen( + [sys.executable, _DEVICEMAP_SCRIPT, 'home-swarming-bot-host-1--1'], + env={'PYTHONPATH': ':'.join(sys.path)[1:]}, + stdin=subprocess.PIPE, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE) + output, err = p.communicate() + self.assertFalse(p.returncode, output or err) + botconfig = ast.literal_eval(output.decode()) + self.assertTrue(botconfig) + self.assertIsInstance(botconfig, dict) + + def testHost_maximumBots(self): + for host in self.configs.GetHosts(): + current_bots = self.configs.GetNumBotConfigs(host) + message = '%s has more than %s bots [%s]' % ( + host, _MAX_BOTS, current_bots) + self.assertLessEqual(current_bots, _MAX_BOTS, message) + + def testNoDuplicateHostIp(self): + self.assertEqual(len(self.configs.GetHostIps()), + len(set(self.configs.GetHostIps()))) + + def testNoDuplicateGaiaAccounts(self): + # We can use the same set for both the IDs and the Addresses + unique_gaia_accounts = set() + non_unique_gaia_accounts = {} + for host in self.configs.hosts: + for bot in self.configs.hosts[host]['hosted_devices']: + for surface in bot: + device = bot[surface] + if 'factory_reset' not in device: + continue + try: + extra_state = device['extra_state'] + email = extra_state.get('email') + gaia_id = extra_state.get('gaia_id') + # Need to have a pair of both or none of them + self.assertEqual( + bool(email), bool(gaia_id), + msg='email {} and gaia_id {}'.format(email, gaia_id)) + if not email and not gaia_id: + continue + if extra_state.get('allow_duplicate', False): + if email not in non_unique_gaia_accounts.keys(): + existing_gaia_ids = non_unique_gaia_accounts.values() + dup_gaia_id_msg = 'gaia_id {} is found in use already' + self.assertNotIn(gaia_id, existing_gaia_ids, + msg=dup_gaia_id_msg.format(gaia_id)) + non_unique_gaia_accounts[email] = gaia_id + else: + err_msg = 'gaia_id {} is inconsistent with this email {}' + self.assertEqual(gaia_id, non_unique_gaia_accounts[email], + msg=err_msg.format(gaia_id, email)) + else: + # Email/ID cannot be re-used when allow_duplicate is set to False + error_msg = 'Duplicate {} is found: {}' + self.assertNotIn(email, unique_gaia_accounts, + msg=error_msg.format('email', email)) + self.assertNotIn(gaia_id, unique_gaia_accounts, + msg=error_msg.format('gaia_id', gaia_id)) + unique_gaia_accounts.add(email) + unique_gaia_accounts.add(gaia_id) + except KeyError: + logging.warning('Need account info for %s', str(device)) + + +if __name__ == '__main__': + unittest.main()
diff --git a/catatester/devicemap/devicemap_lib.py b/catatester/devicemap/devicemap_lib.py new file mode 100644 index 0000000..58757e4 --- /dev/null +++ b/catatester/devicemap/devicemap_lib.py
@@ -0,0 +1,160 @@ +"""Utility methods to retrieve devicemap.yaml data.""" + +import json +import logging +import os +import yaml + + +class Error(Exception): + pass + + +class DeviceMapError(Error): + pass + + +class Configs(object): + """Represents all of the configs in the devicemap.""" + _DEVICE_NODE_NAME = 'hosted_devices' + _HOST_IP = 'host_ip' + + def __init__(self, configs_dict=None): + self._configs_dict = configs_dict or _ReadDeviceMap() + self.allowed_dimensions = self._configs_dict.get('allowed_dimensions') + self.hosts = self._configs_dict.get('hosts') + + def GetAllowedDimensions(self, config_type): + """Gets the set() of allowed dimensions for the given type of config.""" + if config_type not in self.allowed_dimensions: + raise DeviceMapError('config type not defined: %s' % config_type) + return set(self.allowed_dimensions[config_type]) + + def GetBotConfig(self, hostname, bot_num): + """Gets the bot config for the given hostname & bot_num (1-indexed).""" + host = self._GetHostConfig(hostname) + hosted_devices = host[self._DEVICE_NODE_NAME] + device_index = bot_num - 1 + if device_index >= len(hosted_devices): + raise DeviceMapError('Bot #%d is not defined under host %s' % ( + bot_num, hostname)) + config_dict = hosted_devices[device_index] + host_dimensions = self._GetHostDimensions(host) + return BotConfig(config_dict, host_dimensions) + + def GetNumBotConfigs(self, hostname): + """Gets the # of bot configs assigned to the given hostname.""" + return len(self._GetHostedDevices(hostname)) + + def _GetHostConfig(self, hostname): + """Returns the complete host config dict for a given hostname.""" + if hostname not in self.hosts: + raise DeviceMapError('host %s is not defined in devicemap' % hostname) + return self.hosts[hostname] + + def _GetHostDimensions(self, host_config): + """Returns a dict of bot dimensions, populated from the host. + + These dimensions can be overridden at the individual device level. + """ + return { + 'location': host_config.get('location', 'UNSPECIFIED') + } + + def _GetHostedDevices(self, hostname): + return self._GetHostConfig(hostname)[self._DEVICE_NODE_NAME] + + def GetHosts(self): + return self.hosts + + def GetHostIps(self): + # Implicitly making host_ip a mandatory field here + return [self.hosts[h][self._HOST_IP] for h in self.hosts.keys()] + + +class BotConfig(object): + """Represents a single bot config for a Testbed or Device.""" + + def __init__(self, bot_config_dict, host_dimensions=None): + """Initialize bot config object. + + Args: + bot_config_dict: Dict of bot info for a single device from devicemap. + host_dimensions: Bot dimensions populated from the host of the device. + """ + self.type = self._ParseConfigType(bot_config_dict) + self._raw_type = list(bot_config_dict.keys())[0] + self._data = bot_config_dict[self._raw_type] + self._host_dimensions = host_dimensions or {} + if self.type == 'Testbed': + self.dimensions, self.state = self._ParseTestbedConfig() + elif self.type == 'Device': + self.dimensions, self.state = self._ParseDeviceConfig() + else: + raise NotImplementedError('devicemap type "%s" not defined' % self.type) + + def __repr__(self): + return str(self.as_dict) + + @property + def as_dict(self): + # Transform dimensions & state to conform to swarming's schema for bots + for dimension, value in self.dimensions.items(): + if not value: + raise DeviceMapError('Dimensions must not be empty: %s' % dimension) + # Dimension values must be a list/tuple + if not hasattr(value, '__iter__'): + self.dimensions[dimension] = [value] + return { + 'dimensions': self.dimensions, + 'state': self.state, + } + + def _ParseConfigType(self, config_dict): + if not len(list(config_dict.keys())) == 1: + raise DeviceMapError( + ('Configuration invalid -- expected single entry for a "Testbed" ' + 'or a single device. Got: %s') % list(config_dict.keys())) + config_type = list(config_dict.keys())[0] + # Any configs that are named all in lowercase are assumed to be a device. + # (e.g. lexx, luther, biggie, joplin, etc). Any configs with a leading + # uppercase are a specified config type (e.g. Testbed). + if config_type.islower(): + config_type = 'Device' + return config_type + + def _ParseTestbedConfig(self): + """Get the bot config dict() for the given hostname & bot_num.""" + dimensions = self._host_dimensions + dimensions.update(self._data.get('dimensions')) + state = self._data.get('extra_state') + return dimensions, state + + def _ParseDeviceConfig(self): + """Get the bot config dict() for the given hostname & bot_num.""" + state = {} + dimensions = self._host_dimensions + dimensions.update(self._data) + dimensions['device_type'] = self._raw_type + dimensions['group'] = dimensions.get('group') or 'COMMON' + dimensions['nic'] = dimensions.get('nic') or 'ethernet' + dimensions['use_tunnel'] = dimensions.get('use_tunnel') or 'false' + # FDR device between tests unless in 'signed_in' group. + dimensions['factory_reset'] = ( + dimensions.get('factory_reset') or + str('signed_in' not in dimensions['group']).lower()) + # Rename 'ip' to 'device_ip' for convenience (keeps config file concise) + if 'ip' in dimensions: + dimensions['device_ip'] = dimensions['ip'] + del dimensions['ip'] + if 'extra_state' in dimensions: + state = dimensions.get('extra_state', {}) + del dimensions['extra_state'] + return dimensions, state + + +def _ReadDeviceMap(): + """Reads all configs from devicemap.yaml config file as a dict().""" + pwd = os.path.dirname(os.path.realpath(__file__)) + with open(os.path.join(pwd, 'devicemap.yaml'), 'r') as f: + return yaml.safe_load(f)
diff --git a/catatester/devicemap/devicemap_lib_test.py b/catatester/devicemap/devicemap_lib_test.py new file mode 100644 index 0000000..3e6a1fa --- /dev/null +++ b/catatester/devicemap/devicemap_lib_test.py
@@ -0,0 +1,230 @@ +"""Tests for devicemap_lib.py module.""" + +import unittest +import yaml + +from catatester.devicemap import devicemap_lib + +_SAMPLE_YAML = """ +allowed_dimensions: + Device: + - ip + - device_ip +hosts: + host-1: + host_ip: 1.2.3.4 + location: 'US-MTV-B47' + hosted_devices: + - device: {ip: 192.168.0.1} + - device: {ip: 192.168.0.2} + - device: + ip: 192.168.0.3 + location: 'NOT US-MTV-B47' +""" + + +class DeviceMapLibTest(unittest.TestCase): + """Tests for devicemap_lib.py module.""" + + def setUp(self): + self.sample_configs = devicemap_lib.Configs(yaml.safe_load(_SAMPLE_YAML)) + + def assertBotConfigMatchesSwarmingSchema(self, bot_config): + config_dict = bot_config.as_dict + self.assertTrue('dimensions' in config_dict) + self.assertTrue('state' in config_dict) + for value in config_dict['dimensions'].values(): + self.assertTrue(hasattr(value, '__iter__')) + + def testReadDeviceMap(self): + self.assertTrue( + devicemap_lib._ReadDeviceMap()) + + def testGetNumBotConfigs(self): + self.assertEqual(3, self.sample_configs.GetNumBotConfigs('host-1')) + with self.assertRaises(devicemap_lib.DeviceMapError): + self.sample_configs.GetNumBotConfigs('undefined-host') + + def testGetAllowedDimensions(self): + expected = set(['ip', 'device_ip']) + actual = self.sample_configs.GetAllowedDimensions('Device') + self.assertEqual(expected, actual) + with self.assertRaises(devicemap_lib.DeviceMapError): + self.sample_configs.GetAllowedDimensions('undefined-type') + + def testGetBotConfig_canGetDevice(self): + bot_config = self.sample_configs.GetBotConfig('host-1', 1) + self.assertTrue(bot_config) + self.assertBotConfigMatchesSwarmingSchema(bot_config) + self.assertIn('location', bot_config.dimensions) + self.assertEqual('US-MTV-B47', bot_config.dimensions['location']) + # Also verify works with a slightly different format (newline instead of {}) + bot_config = self.sample_configs.GetBotConfig('host-1', 3) + self.assertTrue(bot_config) + self.assertBotConfigMatchesSwarmingSchema(bot_config) + self.assertTrue('device_type' in bot_config.dimensions) + self.assertEqual('device', bot_config.dimensions['device_type']) + self.assertTrue('device_ip' in bot_config.dimensions) + self.assertEqual('192.168.0.3', bot_config.dimensions['device_ip']) + self.assertIn('location', bot_config.dimensions) + self.assertEqual('NOT US-MTV-B47', bot_config.dimensions['location']) + + def testGetBotConfig_canGetDeviceWithNewDimension(self): + sample_yaml = """ +hosts: + host-2: + host_ip: 2.2.2.2 + hosted_devices: + - device: {ip: 192.168.0.4, new_dimension: hello}""" + configs = devicemap_lib.Configs(yaml.safe_load(sample_yaml)) + bot_config = configs.GetBotConfig('host-2', 1) + self.assertTrue(bot_config) + self.assertBotConfigMatchesSwarmingSchema(bot_config) + expected = ('new_dimension', 'hello') + self.assertTrue(expected in bot_config.dimensions.items()) + + def testGetBotConfig_canGetDeviceWithDimensionContainingAList(self): + sample_yaml = """ +hosts: + host-2: + host_ip: 2.2.2.2 + hosted_devices: + - device: {ip: 192.168.0.4, new_dimension: ['hello']}""" + configs = devicemap_lib.Configs(yaml.safe_load(sample_yaml)) + bot_config = configs.GetBotConfig('host-2', 1) + self.assertTrue(bot_config) + self.assertBotConfigMatchesSwarmingSchema(bot_config) + expected = ('new_dimension', ['hello']) + self.assertTrue(expected in bot_config.dimensions.items()) + + def testGetBotConfig_canGetDeviceWithExtraState(self): + sample_yaml = """ +hosts: + host-2: + host_ip: 2.2.2.2 + hosted_devices: + - device: {ip: 192.168.0.5, extra_state: {eth_switch: 100.107.119.209}} + - device: + ip: 192.168.0.6 + extra_state: + eth_switch: 100.107.119.210 + example: 'something new'""" + configs = devicemap_lib.Configs(yaml.safe_load(sample_yaml)) + bot_config = configs.GetBotConfig('host-2', 1) + self.assertTrue(bot_config) + self.assertBotConfigMatchesSwarmingSchema(bot_config) + expected = ('eth_switch', '100.107.119.209') + self.assertTrue(expected in bot_config.state.items()) + + # Also verify works with a slightly different format (newline instead of {}) + bot_config = configs.GetBotConfig('host-2', 2) + self.assertTrue(bot_config) + self.assertBotConfigMatchesSwarmingSchema(bot_config) + expected = ('eth_switch', '100.107.119.210') + self.assertTrue(expected in bot_config.state.items()) + + def testGetBotConfig_canGetTestbed(self): + sample_yaml = """ +hosts: + host-2: + host_ip: 2.2.2.2 + location: 'US-MTV-B45' + hosted_devices: + - Testbed: + dimensions: + device_type: chaos_testbed + device_ip: 172.22.38.73 + group: ['chaos_lab'] + extra_state: + anchovy: ['172.22.38.69', '172.22.38.70'] + biggie: '172.22.38.73' + chorizo: ['172.22.38.66', '172.22.38.67'] + ethernet_switch: '172.22.38.80' + linux_client: '172.22.38.81' + mushroom: '172.22.38.72' + pepperoni: '172.22.38.71' + pineapple: ['172.22.38.78', '172.22.38.68'] + rpi: '172.22.38.79' + salami: ['172.22.38.65', '172.22.38.83'] + steak: ['172.22.38.74', '172.22.38.64']""" + configs = devicemap_lib.Configs(yaml.safe_load(sample_yaml)) + bot_config = configs.GetBotConfig('host-2', 1) + self.assertTrue(bot_config) + self.assertBotConfigMatchesSwarmingSchema(bot_config) + expected = ('biggie', '172.22.38.73') + self.assertTrue(expected in bot_config.state.items()) + expected = ('pineapple', ['172.22.38.78', '172.22.38.68']) + self.assertTrue(expected in bot_config.state.items()) + self.assertIn('location', bot_config.dimensions) + self.assertEqual('US-MTV-B45', bot_config.dimensions['location']) + + def testGetBotConfig_undefinedHostRaisesError(self): + with self.assertRaises(devicemap_lib.DeviceMapError): + self.sample_configs.GetBotConfig('host-doesnt-exist', 1) + + def testGetBotConfig_undefinedDeviceRaisesError(self): + with self.assertRaises(devicemap_lib.DeviceMapError): + self.sample_configs.GetBotConfig('host-1', 9999) + + def testFactoryResetNoSignedInGroup(self): + """Test that FDR flag is set when device is not in the group 'signed_in'.""" + sample_yaml = """ +hosts: + host-2: + host_ip: 2.2.2.2 + hosted_devices: + - device: + ip: 100.127.32.17 + group: ['device_performance']""" + configs = devicemap_lib.Configs(yaml.safe_load(sample_yaml)) + bot_config = configs.GetBotConfig('host-2', 1) + self.assertTrue(bot_config) + self.assertEqual('true', bot_config.dimensions['factory_reset']) + + def testFactoryResetNoGroup(self): + """Test that FDR flag is set when device is not explicitly in a group.""" + sample_yaml = """ +hosts: + host-2: + host_ip: 2.2.2.2 + hosted_devices: + - device: + ip: 100.127.32.17""" + configs = devicemap_lib.Configs(yaml.safe_load(sample_yaml)) + bot_config = configs.GetBotConfig('host-2', 1) + self.assertTrue(bot_config) + self.assertEqual('true', bot_config.dimensions['factory_reset']) + + def testFactoryResetSignedInGroup(self): + """Test that FDR flag is set when device is in the group 'signed_in'.""" + sample_yaml = """ +hosts: + host-2: + host_ip: 2.2.2.2 + hosted_devices: + - device: + ip: 100.127.32.17 + group: ['signed_in', 'device_performance']""" + configs = devicemap_lib.Configs(yaml.safe_load(sample_yaml)) + bot_config = configs.GetBotConfig('host-2', 1) + self.assertTrue(bot_config) + self.assertEqual('false', bot_config.dimensions['factory_reset']) + + def testFactoryResetExplicit(self): + """Test that FDR flag is set explicitly specified in config.""" + sample_yaml = """ +hosts: + host-2: + host_ip: 2.2.2.2 + hosted_devices: + - device: + ip: 100.127.32.17 + factory_reset: 'false'""" + configs = devicemap_lib.Configs(yaml.safe_load(sample_yaml)) + bot_config = configs.GetBotConfig('host-2', 1) + self.assertTrue(bot_config) + self.assertEqual('false', bot_config.dimensions['factory_reset']) + + +if __name__ == '__main__': + unittest.main()
diff --git a/catatester/devicemap/swarm_bot.systemd.template b/catatester/devicemap/swarm_bot.systemd.template new file mode 100644 index 0000000..47781f1 --- /dev/null +++ b/catatester/devicemap/swarm_bot.systemd.template
@@ -0,0 +1,10 @@ +[Unit] +Description=Startup swarming bot ${bot_name}. + +[Service] +User=${user} +Group=${group} +ExecStart=${startup_script_path} + +[Install] +WantedBy=multi-user.target \ No newline at end of file
diff --git a/catatester/devicemap/swarm_bot_startup.sh.template b/catatester/devicemap/swarm_bot_startup.sh.template new file mode 100644 index 0000000..7b78fc6 --- /dev/null +++ b/catatester/devicemap/swarm_bot_startup.sh.template
@@ -0,0 +1,9 @@ +#!/bin/sh + +export BOTO_CONFIG=${gsutil_boto} +export GOOGLE_APPLICATION_CREDENTIALS=${fragglerock_key} +export HOME_BINARY_DIR=${eurtest_binaries} +export DEVICEMAP=${devicemap_dir} +export PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:${eurtest_binaries}:${gsutil_dir}:${depot_tools_dir} +. ${venv}/bin/activate +/usr/bin/env python ${bot_dir}/swarming_bot.zip start_bot
diff --git a/catatester/expand_capabilities.py b/catatester/expand_capabilities.py new file mode 100644 index 0000000..3b18ec8 --- /dev/null +++ b/catatester/expand_capabilities.py
@@ -0,0 +1,66 @@ +"""Script to expand capabilities into products. + +Example usage: + python $0 --capability_list='CAST_AUDIO_RECEIVER,CAST_VIDEO_RECEIVER' +""" +import argparse +import os + +from catatester.genfiles import build_config_pb2 + +from google.protobuf import text_format + + +BUILD_CONFIG = os.path.join(os.path.dirname(__file__), + 'configs', + 'imported', + 'build_config.protoascii') + + +def ParseCmdOptions(): + """Parses command arguments.""" + parser = argparse.ArgumentParser() + parser.add_argument('--capability_list', + help='Comma-delimited capabilities', + required=True) + return parser.parse_args() + + +def GetProductsByCapability(capability): + """Returns set of products with the given capability.""" + print('Capability name: {}'.format(capability)) + product_set = set() + try: + capability_index = ( + build_config_pb2.OtaBuild.Capability.Value(capability)) + print('Capability Index: {}'.format(capability_index)) + except ValueError: + return product_set + + with open(BUILD_CONFIG) as build: + builds = text_format.Merge(build.read(), build_config_pb2.BuildConfig()) + assert builds + + for target in builds.ota_build: + build_target = builds.ota_build[target] + if build_target.capabilities: + if capability_index in list(build_target.capabilities): + product_set.add(build_target.product) + + return product_set + + +def main(): + assert os.path.isfile(BUILD_CONFIG) + + flags = ParseCmdOptions() + + total_product_set = set() + for cap in flags.capability_list.split(','): + total_product_set.update(GetProductsByCapability(cap)) + + print('All products: {}'.format(sorted(total_product_set))) + + +if __name__ == '__main__': + main()
diff --git a/catatester/genfiles/__init__.py b/catatester/genfiles/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/catatester/genfiles/__init__.py
diff --git a/catatester/genfiles/build_config_pb2.py b/catatester/genfiles/build_config_pb2.py new file mode 100644 index 0000000..d9e1618 --- /dev/null +++ b/catatester/genfiles/build_config_pb2.py
@@ -0,0 +1,239 @@ +# -*- coding: utf-8 -*- +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: build_config.proto + +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 +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + + + +DESCRIPTOR = _descriptor.FileDescriptor( + name='build_config.proto', + package='build_config', + syntax='proto2', + serialized_options=None, + serialized_pb=b'\n\x12\x62uild_config.proto\x12\x0c\x62uild_config\"\xb1\x02\n\x08OtaBuild\x12\x14\n\x0c\x62uild_target\x18\x01 \x01(\t\x12\x0f\n\x07product\x18\x02 \x01(\t\x12\x0f\n\x07variant\x18\x03 \x01(\t\x12\x10\n\x08platform\x18\x04 \x01(\t\x12\x16\n\x0epartner_bucket\x18\x05 \x03(\t\x12\x37\n\x0c\x63\x61pabilities\x18\x06 \x03(\x0e\x32!.build_config.OtaBuild.Capability\x12\x13\n\x04test\x18\x07 \x01(\x08:\x05\x66\x61lse\"u\n\nCapability\x12\x08\n\x04NONE\x10\x00\x12\r\n\tASSISTANT\x10\x01\x12\x17\n\x13\x43\x41ST_VIDEO_RECEIVER\x10\x02\x12\x17\n\x13\x43\x41ST_AUDIO_RECEIVER\x10\x03\x12\r\n\tWIFI_2GHZ\x10\x04\x12\r\n\tWIFI_5GHZ\x10\x05\"\x92\x01\n\x0b\x42uildConfig\x12:\n\tota_build\x18\x01 \x03(\x0b\x32\'.build_config.BuildConfig.OtaBuildEntry\x1aG\n\rOtaBuildEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12%\n\x05value\x18\x02 \x01(\x0b\x32\x16.build_config.OtaBuild:\x02\x38\x01' +) + + + +_OTABUILD_CAPABILITY = _descriptor.EnumDescriptor( + name='Capability', + full_name='build_config.OtaBuild.Capability', + filename=None, + file=DESCRIPTOR, + values=[ + _descriptor.EnumValueDescriptor( + name='NONE', index=0, number=0, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='ASSISTANT', index=1, number=1, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='CAST_VIDEO_RECEIVER', index=2, number=2, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='CAST_AUDIO_RECEIVER', index=3, number=3, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='WIFI_2GHZ', index=4, number=4, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='WIFI_5GHZ', index=5, number=5, + serialized_options=None, + type=None), + ], + containing_type=None, + serialized_options=None, + serialized_start=225, + serialized_end=342, +) +_sym_db.RegisterEnumDescriptor(_OTABUILD_CAPABILITY) + + +_OTABUILD = _descriptor.Descriptor( + name='OtaBuild', + full_name='build_config.OtaBuild', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='build_target', full_name='build_config.OtaBuild.build_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, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='product', full_name='build_config.OtaBuild.product', 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, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='variant', full_name='build_config.OtaBuild.variant', 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, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='platform', full_name='build_config.OtaBuild.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, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='partner_bucket', full_name='build_config.OtaBuild.partner_bucket', index=4, + number=5, 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, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='capabilities', full_name='build_config.OtaBuild.capabilities', index=5, + number=6, type=14, cpp_type=8, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='test', full_name='build_config.OtaBuild.test', index=6, + number=7, type=8, cpp_type=7, label=1, + has_default_value=True, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + _OTABUILD_CAPABILITY, + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=37, + serialized_end=342, +) + + +_BUILDCONFIG_OTABUILDENTRY = _descriptor.Descriptor( + name='OtaBuildEntry', + full_name='build_config.BuildConfig.OtaBuildEntry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='build_config.BuildConfig.OtaBuildEntry.key', 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, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='build_config.BuildConfig.OtaBuildEntry.value', index=1, + number=2, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=b'8\001', + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=420, + serialized_end=491, +) + +_BUILDCONFIG = _descriptor.Descriptor( + name='BuildConfig', + full_name='build_config.BuildConfig', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='ota_build', full_name='build_config.BuildConfig.ota_build', index=0, + number=1, 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, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[_BUILDCONFIG_OTABUILDENTRY, ], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=345, + serialized_end=491, +) + +_OTABUILD.fields_by_name['capabilities'].enum_type = _OTABUILD_CAPABILITY +_OTABUILD_CAPABILITY.containing_type = _OTABUILD +_BUILDCONFIG_OTABUILDENTRY.fields_by_name['value'].message_type = _OTABUILD +_BUILDCONFIG_OTABUILDENTRY.containing_type = _BUILDCONFIG +_BUILDCONFIG.fields_by_name['ota_build'].message_type = _BUILDCONFIG_OTABUILDENTRY +DESCRIPTOR.message_types_by_name['OtaBuild'] = _OTABUILD +DESCRIPTOR.message_types_by_name['BuildConfig'] = _BUILDCONFIG +_sym_db.RegisterFileDescriptor(DESCRIPTOR) + +OtaBuild = _reflection.GeneratedProtocolMessageType('OtaBuild', (_message.Message,), { + 'DESCRIPTOR' : _OTABUILD, + '__module__' : 'build_config_pb2' + # @@protoc_insertion_point(class_scope:build_config.OtaBuild) + }) +_sym_db.RegisterMessage(OtaBuild) + +BuildConfig = _reflection.GeneratedProtocolMessageType('BuildConfig', (_message.Message,), { + + 'OtaBuildEntry' : _reflection.GeneratedProtocolMessageType('OtaBuildEntry', (_message.Message,), { + 'DESCRIPTOR' : _BUILDCONFIG_OTABUILDENTRY, + '__module__' : 'build_config_pb2' + # @@protoc_insertion_point(class_scope:build_config.BuildConfig.OtaBuildEntry) + }) + , + 'DESCRIPTOR' : _BUILDCONFIG, + '__module__' : 'build_config_pb2' + # @@protoc_insertion_point(class_scope:build_config.BuildConfig) + }) +_sym_db.RegisterMessage(BuildConfig) +_sym_db.RegisterMessage(BuildConfig.OtaBuildEntry) + + +_BUILDCONFIG_OTABUILDENTRY._options = None +# @@protoc_insertion_point(module_scope)
diff --git a/catatester/genfiles/continuous_tests_pb2.py b/catatester/genfiles/continuous_tests_pb2.py new file mode 100644 index 0000000..2672ef0 --- /dev/null +++ b/catatester/genfiles/continuous_tests_pb2.py
@@ -0,0 +1,1206 @@ +# -*- coding: utf-8 -*- +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: continuous_tests.proto + +from google.protobuf.internal import enum_type_wrapper +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 +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + + + +DESCRIPTOR = _descriptor.FileDescriptor( + name='continuous_tests.proto', + package='continuous_tests', + syntax='proto2', + serialized_options=None, + serialized_pb=b'\n\x16\x63ontinuous_tests.proto\x12\x10\x63ontinuous_tests\"\xf5\x03\n\x0c\x42uildTargets\x12?\n\x0c\x62ranch_types\x18\x01 \x01(\x0e\x32).continuous_tests.BuildTargets.BranchType\x12\x15\n\rproduct_types\x18\x02 \x03(\t\x12\x10\n\x08products\x18\x03 \x03(\t\x12\x38\n\x08variants\x18\x04 \x01(\x0e\x32&.continuous_tests.BuildTargets.Variant\x12\x15\n\rbuilder_names\x18\x05 \x03(\t\x12\x37\n\x08\x62ranches\x18\x06 \x03(\x0b\x32%.continuous_tests.BuildTargets.Branch\x1a\x61\n\x06\x42ranch\x12\x39\n\x04type\x18\x01 \x01(\x0e\x32).continuous_tests.BuildTargets.BranchTypeH\x00\x12\x0e\n\x04name\x18\x02 \x01(\tH\x00\x42\x0c\n\nBranchSpec\".\n\nBranchType\x12\x07\n\x03\x41LL\x10\x00\x12\n\n\x06MASTER\x10\x01\x12\x0b\n\x07RELEASE\x10\x02\"^\n\x07Variant\x12\x0b\n\x07\x44\x45\x46\x41ULT\x10\x00\x12\x07\n\x03\x45NG\x10\x01\x12\x08\n\x04USER\x10\x02\x12\x07\n\x03\x41RM\x10\x03\x12\x07\n\x03X86\x10\x04\x12\x07\n\x03X64\x10\x05\x12\t\n\x05\x41RM64\x10\x06\x12\r\n\tUSERDEBUG\x10\x07\"\x99\x01\n\x08Schedule\x12\x0c\n\x04\x63ron\x18\x01 \x01(\t\x12\x31\n\x06policy\x18\x02 \x01(\x0e\x32!.continuous_tests.Schedule.Policy\"L\n\x06Policy\x12\x0b\n\x07\x44\x45\x46\x41ULT\x10\x00\x12\x13\n\x0fLATEST_UNTESTED\x10\x01\x12\n\n\x06LATEST\x10\x02\x12\x14\n\x10LATEST_MINUS_ONE\x10\x03\"6\n\x0e\x42otRequirement\x12\x15\n\rbot_dimension\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t\":\n\x0c\x43\x61stOsModule\x12\x14\n\x0c\x63ipd_package\x18\x01 \x01(\t\x12\x14\n\x0c\x63ipd_version\x18\x02 \x01(\t\"\xc7\x05\n\nTestTarget\x12\x0e\n\x06\x63onfig\x18\x01 \x01(\t\x12\x12\n\ntest_cases\x18\x02 \x03(\t\x12\x13\n\x0b\x62inary_name\x18\x03 \x01(\t\x12\x37\n\x08priority\x18\x04 \x01(\x0e\x32%.continuous_tests.TestTarget.Priority\x12\x15\n\x07\x65nabled\x18\x05 \x01(\x08:\x04true\x12\x33\n\x06recipe\x18\x06 \x01(\x0e\x32#.continuous_tests.TestTarget.Recipe\x12\x1d\n\x11test_timeout_mins\x18\x07 \x01(\x05:\x02\x36\x30\x12\x13\n\x0btest_groups\x18\x08 \x03(\t\x12>\n\x14testbed_requirements\x18\t \x03(\x0b\x32 .continuous_tests.BotRequirement\x12\x1f\n\rcipd_refs_key\x18\n \x01(\t:\x08internal\x12\x10\n\x08\x62ot_pool\x18\x0b \x01(\t\x12\x36\n\x0e\x63\x61stos_modules\x18\x0c \x03(\x0b\x32\x1e.continuous_tests.CastOsModule\x12\x1f\n\x17skip_default_dimensions\x18\r \x01(\x08\"\xb4\x01\n\x06Recipe\x12\x0f\n\x0bHOME_RUNNER\x10\x00\x12\x1b\n\x17\x44\x45VICE_UNIT_TEST_RUNNER\x10\x01\x12\x1a\n\x16OTA_INSTALLABLE_RUNNER\x10\x02\x12\x17\n\x13LIBASSISTANT_RUNNER\x10\x03\x12\x18\n\x14\x46UCHSIA_GUNIT_RUNNER\x10\x04\x12\x12\n\x0e\x46UCHSIA_RUNNER\x10\x05\x12\x19\n\x15VIRTUAL_DEVICE_RUNNER\x10\x06\"D\n\x08Priority\x12\x0b\n\x07\x44\x45\x46\x41ULT\x10\x00\x12\x0c\n\x08\x43RITICAL\x10\x01\x12\n\n\x06MEDIUM\x10\x02\x12\x08\n\x04HIGH\x10\x03\x12\x07\n\x03LOW\x10\x04\"z\n\x0e\x43ontinuousTest\x12\x31\n\x0btest_target\x18\x01 \x01(\x0b\x32\x1c.continuous_tests.TestTarget\x12\x35\n\rbuild_targets\x18\x02 \x03(\x0b\x32\x1e.continuous_tests.BuildTargets\"\x97\x02\n\rScheduledTest\x12\x31\n\x0btest_target\x18\x01 \x01(\x0b\x32\x1c.continuous_tests.TestTarget\x12\x35\n\rbuild_targets\x18\x02 \x03(\x0b\x32\x1e.continuous_tests.BuildTargets\x12,\n\x08schedule\x18\x03 \x01(\x0b\x32\x1a.continuous_tests.Schedule\x12\x10\n\x08\x62ranches\x18\x04 \x03(\t\x12\x16\n\x04repo\x18\x05 \x01(\t:\x08internal\x12\x44\n\x0e\x62uild_platform\x18\x06 \x01(\x0e\x32\x1f.continuous_tests.BuildPlatform:\x0b\x43\x41TABUILDER\"\xcc\t\n\x15\x43ontinuousTestsConfig\x12\x19\n\x11test_configs_root\x18\x01 \x01(\t\x12\x39\n\x0f\x63ontinuous_test\x18\x02 \x03(\x0b\x32 .continuous_tests.ContinuousTest\x12\x37\n\x0escheduled_test\x18\x03 \x03(\x0b\x32\x1f.continuous_tests.ScheduledTest\x12I\n\x16\x62ranch_type_priorities\x18\x04 \x03(\x0e\x32).continuous_tests.BuildTargets.BranchType\x12\x19\n\x11\x64isabled_branches\x18\x05 \x03(\t\x12Z\n\x12\x62uild_restrictions\x18\x06 \x03(\x0b\x32>.continuous_tests.ContinuousTestsConfig.BuildRestrictionsEntry\x12\x17\n\x0ftest_group_tags\x18\x07 \x03(\t\x12R\n\x0e\x64\x65vice_modules\x18\x08 \x03(\x0b\x32:.continuous_tests.ContinuousTestsConfig.DeviceModulesEntry\x12H\n\tcipd_refs\x18\t \x03(\x0b\x32\x35.continuous_tests.ContinuousTestsConfig.CipdRefsEntry\x1a\x9e\x01\n\x11\x42uildRestrictions\x12G\n\x14\x61llowed_branch_types\x18\x01 \x03(\x0e\x32).continuous_tests.BuildTargets.BranchType\x12@\n\x10\x61llowed_variants\x18\x02 \x03(\x0e\x32&.continuous_tests.BuildTargets.Variant\x1as\n\x16\x42uildRestrictionsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12H\n\x05value\x18\x02 \x01(\x0b\x32\x39.continuous_tests.ContinuousTestsConfig.BuildRestrictions:\x02\x38\x01\x1a;\n\x0c\x44\x65viceModule\x12\x15\n\rdevice_module\x18\x01 \x01(\t\x12\x14\n\x0c\x64\x65vice_class\x18\x02 \x01(\t\x1aj\n\x12\x44\x65viceModulesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x43\n\x05value\x18\x02 \x01(\x0b\x32\x34.continuous_tests.ContinuousTestsConfig.DeviceModule:\x02\x38\x01\x1a>\n\x07\x43ipdRef\x12\x14\n\x0cpackage_name\x18\x01 \x01(\t\x12\x0f\n\x07version\x18\x02 \x01(\t\x12\x0c\n\x04path\x18\x03 \x01(\t\x1aI\n\x08\x43ipdRefs\x12=\n\x04refs\x18\x01 \x03(\x0b\x32/.continuous_tests.ContinuousTestsConfig.CipdRef\x1a\x61\n\rCipdRefsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12?\n\x05value\x18\x02 \x01(\x0b\x32\x30.continuous_tests.ContinuousTestsConfig.CipdRefs:\x02\x38\x01*@\n\rBuildPlatform\x12\x0b\n\x07\x44\x45\x46\x41ULT\x10\x00\x12\x0f\n\x0b\x43\x41TABUILDER\x10\x01\x12\x11\n\rANDROID_BUILD\x10\x02' +) + +_BUILDPLATFORM = _descriptor.EnumDescriptor( + name='BuildPlatform', + full_name='continuous_tests.BuildPlatform', + filename=None, + file=DESCRIPTOR, + values=[ + _descriptor.EnumValueDescriptor( + name='DEFAULT', index=0, number=0, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='CATABUILDER', index=1, number=1, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='ANDROID_BUILD', index=2, number=2, + serialized_options=None, + type=None), + ], + containing_type=None, + serialized_options=None, + serialized_start=3171, + serialized_end=3235, +) +_sym_db.RegisterEnumDescriptor(_BUILDPLATFORM) + +BuildPlatform = enum_type_wrapper.EnumTypeWrapper(_BUILDPLATFORM) +DEFAULT = 0 +CATABUILDER = 1 +ANDROID_BUILD = 2 + + +_BUILDTARGETS_BRANCHTYPE = _descriptor.EnumDescriptor( + name='BranchType', + full_name='continuous_tests.BuildTargets.BranchType', + filename=None, + file=DESCRIPTOR, + values=[ + _descriptor.EnumValueDescriptor( + name='ALL', index=0, number=0, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='MASTER', index=1, number=1, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='RELEASE', index=2, number=2, + serialized_options=None, + type=None), + ], + containing_type=None, + serialized_options=None, + serialized_start=404, + serialized_end=450, +) +_sym_db.RegisterEnumDescriptor(_BUILDTARGETS_BRANCHTYPE) + +_BUILDTARGETS_VARIANT = _descriptor.EnumDescriptor( + name='Variant', + full_name='continuous_tests.BuildTargets.Variant', + filename=None, + file=DESCRIPTOR, + values=[ + _descriptor.EnumValueDescriptor( + name='DEFAULT', index=0, number=0, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='ENG', index=1, number=1, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='USER', index=2, number=2, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='ARM', index=3, number=3, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='X86', index=4, number=4, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='X64', index=5, number=5, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='ARM64', index=6, number=6, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='USERDEBUG', index=7, number=7, + serialized_options=None, + type=None), + ], + containing_type=None, + serialized_options=None, + serialized_start=452, + serialized_end=546, +) +_sym_db.RegisterEnumDescriptor(_BUILDTARGETS_VARIANT) + +_SCHEDULE_POLICY = _descriptor.EnumDescriptor( + name='Policy', + full_name='continuous_tests.Schedule.Policy', + filename=None, + file=DESCRIPTOR, + values=[ + _descriptor.EnumValueDescriptor( + name='DEFAULT', index=0, number=0, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='LATEST_UNTESTED', index=1, number=1, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='LATEST', index=2, number=2, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='LATEST_MINUS_ONE', index=3, number=3, + serialized_options=None, + type=None), + ], + containing_type=None, + serialized_options=None, + serialized_start=626, + serialized_end=702, +) +_sym_db.RegisterEnumDescriptor(_SCHEDULE_POLICY) + +_TESTTARGET_RECIPE = _descriptor.EnumDescriptor( + name='Recipe', + full_name='continuous_tests.TestTarget.Recipe', + filename=None, + file=DESCRIPTOR, + values=[ + _descriptor.EnumValueDescriptor( + name='HOME_RUNNER', index=0, number=0, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='DEVICE_UNIT_TEST_RUNNER', index=1, number=1, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='OTA_INSTALLABLE_RUNNER', index=2, number=2, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='LIBASSISTANT_RUNNER', index=3, number=3, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='FUCHSIA_GUNIT_RUNNER', index=4, number=4, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='FUCHSIA_RUNNER', index=5, number=5, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='VIRTUAL_DEVICE_RUNNER', index=6, number=6, + serialized_options=None, + type=None), + ], + containing_type=None, + serialized_options=None, + serialized_start=1282, + serialized_end=1462, +) +_sym_db.RegisterEnumDescriptor(_TESTTARGET_RECIPE) + +_TESTTARGET_PRIORITY = _descriptor.EnumDescriptor( + name='Priority', + full_name='continuous_tests.TestTarget.Priority', + filename=None, + file=DESCRIPTOR, + values=[ + _descriptor.EnumValueDescriptor( + name='DEFAULT', index=0, number=0, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='CRITICAL', index=1, number=1, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='MEDIUM', index=2, number=2, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='HIGH', index=3, number=3, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='LOW', index=4, number=4, + serialized_options=None, + type=None), + ], + containing_type=None, + serialized_options=None, + serialized_start=1464, + serialized_end=1532, +) +_sym_db.RegisterEnumDescriptor(_TESTTARGET_PRIORITY) + + +_BUILDTARGETS_BRANCH = _descriptor.Descriptor( + name='Branch', + full_name='continuous_tests.BuildTargets.Branch', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='type', full_name='continuous_tests.BuildTargets.Branch.type', index=0, + number=1, type=14, cpp_type=8, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='name', full_name='continuous_tests.BuildTargets.Branch.name', 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, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + _descriptor.OneofDescriptor( + name='BranchSpec', full_name='continuous_tests.BuildTargets.Branch.BranchSpec', + index=0, containing_type=None, fields=[]), + ], + serialized_start=305, + serialized_end=402, +) + +_BUILDTARGETS = _descriptor.Descriptor( + name='BuildTargets', + full_name='continuous_tests.BuildTargets', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='branch_types', full_name='continuous_tests.BuildTargets.branch_types', index=0, + number=1, type=14, cpp_type=8, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='product_types', full_name='continuous_tests.BuildTargets.product_types', index=1, + number=2, 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, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='products', full_name='continuous_tests.BuildTargets.products', index=2, + number=3, 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, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='variants', full_name='continuous_tests.BuildTargets.variants', index=3, + number=4, type=14, cpp_type=8, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='builder_names', full_name='continuous_tests.BuildTargets.builder_names', index=4, + number=5, 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, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='branches', full_name='continuous_tests.BuildTargets.branches', index=5, + number=6, 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, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[_BUILDTARGETS_BRANCH, ], + enum_types=[ + _BUILDTARGETS_BRANCHTYPE, + _BUILDTARGETS_VARIANT, + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=45, + serialized_end=546, +) + + +_SCHEDULE = _descriptor.Descriptor( + name='Schedule', + full_name='continuous_tests.Schedule', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='cron', full_name='continuous_tests.Schedule.cron', 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, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='policy', full_name='continuous_tests.Schedule.policy', index=1, + number=2, type=14, cpp_type=8, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + _SCHEDULE_POLICY, + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=549, + serialized_end=702, +) + + +_BOTREQUIREMENT = _descriptor.Descriptor( + name='BotRequirement', + full_name='continuous_tests.BotRequirement', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='bot_dimension', full_name='continuous_tests.BotRequirement.bot_dimension', 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, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='continuous_tests.BotRequirement.value', 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, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=704, + serialized_end=758, +) + + +_CASTOSMODULE = _descriptor.Descriptor( + name='CastOsModule', + full_name='continuous_tests.CastOsModule', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='cipd_package', full_name='continuous_tests.CastOsModule.cipd_package', 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, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='cipd_version', full_name='continuous_tests.CastOsModule.cipd_version', 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, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=760, + serialized_end=818, +) + + +_TESTTARGET = _descriptor.Descriptor( + name='TestTarget', + full_name='continuous_tests.TestTarget', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='config', full_name='continuous_tests.TestTarget.config', 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, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='test_cases', full_name='continuous_tests.TestTarget.test_cases', index=1, + number=2, 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, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='binary_name', full_name='continuous_tests.TestTarget.binary_name', 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, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='priority', full_name='continuous_tests.TestTarget.priority', index=3, + number=4, type=14, cpp_type=8, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='enabled', full_name='continuous_tests.TestTarget.enabled', index=4, + number=5, type=8, cpp_type=7, label=1, + has_default_value=True, default_value=True, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='recipe', full_name='continuous_tests.TestTarget.recipe', index=5, + number=6, type=14, cpp_type=8, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='test_timeout_mins', full_name='continuous_tests.TestTarget.test_timeout_mins', index=6, + number=7, type=5, cpp_type=1, label=1, + has_default_value=True, default_value=60, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='test_groups', full_name='continuous_tests.TestTarget.test_groups', 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, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='testbed_requirements', full_name='continuous_tests.TestTarget.testbed_requirements', index=8, + number=9, 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, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='cipd_refs_key', full_name='continuous_tests.TestTarget.cipd_refs_key', index=9, + number=10, type=9, cpp_type=9, label=1, + has_default_value=True, default_value=b"internal".decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='bot_pool', full_name='continuous_tests.TestTarget.bot_pool', 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, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='castos_modules', full_name='continuous_tests.TestTarget.castos_modules', index=11, + number=12, 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, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='skip_default_dimensions', full_name='continuous_tests.TestTarget.skip_default_dimensions', index=12, + number=13, 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, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + _TESTTARGET_RECIPE, + _TESTTARGET_PRIORITY, + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=821, + serialized_end=1532, +) + + +_CONTINUOUSTEST = _descriptor.Descriptor( + name='ContinuousTest', + full_name='continuous_tests.ContinuousTest', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='test_target', full_name='continuous_tests.ContinuousTest.test_target', index=0, + number=1, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='build_targets', full_name='continuous_tests.ContinuousTest.build_targets', index=1, + number=2, 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, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=1534, + serialized_end=1656, +) + + +_SCHEDULEDTEST = _descriptor.Descriptor( + name='ScheduledTest', + full_name='continuous_tests.ScheduledTest', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='test_target', full_name='continuous_tests.ScheduledTest.test_target', index=0, + number=1, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='build_targets', full_name='continuous_tests.ScheduledTest.build_targets', index=1, + number=2, 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, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='schedule', full_name='continuous_tests.ScheduledTest.schedule', index=2, + number=3, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='branches', full_name='continuous_tests.ScheduledTest.branches', index=3, + number=4, 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, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repo', full_name='continuous_tests.ScheduledTest.repo', index=4, + number=5, type=9, cpp_type=9, label=1, + has_default_value=True, default_value=b"internal".decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='build_platform', full_name='continuous_tests.ScheduledTest.build_platform', index=5, + number=6, type=14, cpp_type=8, label=1, + has_default_value=True, default_value=1, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=1659, + serialized_end=1938, +) + + +_CONTINUOUSTESTSCONFIG_BUILDRESTRICTIONS = _descriptor.Descriptor( + name='BuildRestrictions', + full_name='continuous_tests.ContinuousTestsConfig.BuildRestrictions', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='allowed_branch_types', full_name='continuous_tests.ContinuousTestsConfig.BuildRestrictions.allowed_branch_types', index=0, + number=1, type=14, cpp_type=8, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='allowed_variants', full_name='continuous_tests.ContinuousTestsConfig.BuildRestrictions.allowed_variants', index=1, + number=2, type=14, cpp_type=8, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=2487, + serialized_end=2645, +) + +_CONTINUOUSTESTSCONFIG_BUILDRESTRICTIONSENTRY = _descriptor.Descriptor( + name='BuildRestrictionsEntry', + full_name='continuous_tests.ContinuousTestsConfig.BuildRestrictionsEntry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='continuous_tests.ContinuousTestsConfig.BuildRestrictionsEntry.key', 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, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='continuous_tests.ContinuousTestsConfig.BuildRestrictionsEntry.value', index=1, + number=2, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=b'8\001', + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=2647, + serialized_end=2762, +) + +_CONTINUOUSTESTSCONFIG_DEVICEMODULE = _descriptor.Descriptor( + name='DeviceModule', + full_name='continuous_tests.ContinuousTestsConfig.DeviceModule', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='device_module', full_name='continuous_tests.ContinuousTestsConfig.DeviceModule.device_module', 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, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='device_class', full_name='continuous_tests.ContinuousTestsConfig.DeviceModule.device_class', 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, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=2764, + serialized_end=2823, +) + +_CONTINUOUSTESTSCONFIG_DEVICEMODULESENTRY = _descriptor.Descriptor( + name='DeviceModulesEntry', + full_name='continuous_tests.ContinuousTestsConfig.DeviceModulesEntry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='continuous_tests.ContinuousTestsConfig.DeviceModulesEntry.key', 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, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='continuous_tests.ContinuousTestsConfig.DeviceModulesEntry.value', index=1, + number=2, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=b'8\001', + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=2825, + serialized_end=2931, +) + +_CONTINUOUSTESTSCONFIG_CIPDREF = _descriptor.Descriptor( + name='CipdRef', + full_name='continuous_tests.ContinuousTestsConfig.CipdRef', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='package_name', full_name='continuous_tests.ContinuousTestsConfig.CipdRef.package_name', 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, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='version', full_name='continuous_tests.ContinuousTestsConfig.CipdRef.version', 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, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='path', full_name='continuous_tests.ContinuousTestsConfig.CipdRef.path', 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, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=2933, + serialized_end=2995, +) + +_CONTINUOUSTESTSCONFIG_CIPDREFS = _descriptor.Descriptor( + name='CipdRefs', + full_name='continuous_tests.ContinuousTestsConfig.CipdRefs', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='refs', full_name='continuous_tests.ContinuousTestsConfig.CipdRefs.refs', index=0, + number=1, 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, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=2997, + serialized_end=3070, +) + +_CONTINUOUSTESTSCONFIG_CIPDREFSENTRY = _descriptor.Descriptor( + name='CipdRefsEntry', + full_name='continuous_tests.ContinuousTestsConfig.CipdRefsEntry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='continuous_tests.ContinuousTestsConfig.CipdRefsEntry.key', 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, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='continuous_tests.ContinuousTestsConfig.CipdRefsEntry.value', index=1, + number=2, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=b'8\001', + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=3072, + serialized_end=3169, +) + +_CONTINUOUSTESTSCONFIG = _descriptor.Descriptor( + name='ContinuousTestsConfig', + full_name='continuous_tests.ContinuousTestsConfig', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='test_configs_root', full_name='continuous_tests.ContinuousTestsConfig.test_configs_root', 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, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='continuous_test', full_name='continuous_tests.ContinuousTestsConfig.continuous_test', index=1, + number=2, 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, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='scheduled_test', full_name='continuous_tests.ContinuousTestsConfig.scheduled_test', index=2, + number=3, 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, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='branch_type_priorities', full_name='continuous_tests.ContinuousTestsConfig.branch_type_priorities', index=3, + number=4, type=14, cpp_type=8, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='disabled_branches', full_name='continuous_tests.ContinuousTestsConfig.disabled_branches', index=4, + number=5, 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, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='build_restrictions', full_name='continuous_tests.ContinuousTestsConfig.build_restrictions', index=5, + number=6, 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, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='test_group_tags', full_name='continuous_tests.ContinuousTestsConfig.test_group_tags', index=6, + number=7, 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, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='device_modules', full_name='continuous_tests.ContinuousTestsConfig.device_modules', index=7, + number=8, 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, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='cipd_refs', full_name='continuous_tests.ContinuousTestsConfig.cipd_refs', index=8, + number=9, 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, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[_CONTINUOUSTESTSCONFIG_BUILDRESTRICTIONS, _CONTINUOUSTESTSCONFIG_BUILDRESTRICTIONSENTRY, _CONTINUOUSTESTSCONFIG_DEVICEMODULE, _CONTINUOUSTESTSCONFIG_DEVICEMODULESENTRY, _CONTINUOUSTESTSCONFIG_CIPDREF, _CONTINUOUSTESTSCONFIG_CIPDREFS, _CONTINUOUSTESTSCONFIG_CIPDREFSENTRY, ], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=1941, + serialized_end=3169, +) + +_BUILDTARGETS_BRANCH.fields_by_name['type'].enum_type = _BUILDTARGETS_BRANCHTYPE +_BUILDTARGETS_BRANCH.containing_type = _BUILDTARGETS +_BUILDTARGETS_BRANCH.oneofs_by_name['BranchSpec'].fields.append( + _BUILDTARGETS_BRANCH.fields_by_name['type']) +_BUILDTARGETS_BRANCH.fields_by_name['type'].containing_oneof = _BUILDTARGETS_BRANCH.oneofs_by_name['BranchSpec'] +_BUILDTARGETS_BRANCH.oneofs_by_name['BranchSpec'].fields.append( + _BUILDTARGETS_BRANCH.fields_by_name['name']) +_BUILDTARGETS_BRANCH.fields_by_name['name'].containing_oneof = _BUILDTARGETS_BRANCH.oneofs_by_name['BranchSpec'] +_BUILDTARGETS.fields_by_name['branch_types'].enum_type = _BUILDTARGETS_BRANCHTYPE +_BUILDTARGETS.fields_by_name['variants'].enum_type = _BUILDTARGETS_VARIANT +_BUILDTARGETS.fields_by_name['branches'].message_type = _BUILDTARGETS_BRANCH +_BUILDTARGETS_BRANCHTYPE.containing_type = _BUILDTARGETS +_BUILDTARGETS_VARIANT.containing_type = _BUILDTARGETS +_SCHEDULE.fields_by_name['policy'].enum_type = _SCHEDULE_POLICY +_SCHEDULE_POLICY.containing_type = _SCHEDULE +_TESTTARGET.fields_by_name['priority'].enum_type = _TESTTARGET_PRIORITY +_TESTTARGET.fields_by_name['recipe'].enum_type = _TESTTARGET_RECIPE +_TESTTARGET.fields_by_name['testbed_requirements'].message_type = _BOTREQUIREMENT +_TESTTARGET.fields_by_name['castos_modules'].message_type = _CASTOSMODULE +_TESTTARGET_RECIPE.containing_type = _TESTTARGET +_TESTTARGET_PRIORITY.containing_type = _TESTTARGET +_CONTINUOUSTEST.fields_by_name['test_target'].message_type = _TESTTARGET +_CONTINUOUSTEST.fields_by_name['build_targets'].message_type = _BUILDTARGETS +_SCHEDULEDTEST.fields_by_name['test_target'].message_type = _TESTTARGET +_SCHEDULEDTEST.fields_by_name['build_targets'].message_type = _BUILDTARGETS +_SCHEDULEDTEST.fields_by_name['schedule'].message_type = _SCHEDULE +_SCHEDULEDTEST.fields_by_name['build_platform'].enum_type = _BUILDPLATFORM +_CONTINUOUSTESTSCONFIG_BUILDRESTRICTIONS.fields_by_name['allowed_branch_types'].enum_type = _BUILDTARGETS_BRANCHTYPE +_CONTINUOUSTESTSCONFIG_BUILDRESTRICTIONS.fields_by_name['allowed_variants'].enum_type = _BUILDTARGETS_VARIANT +_CONTINUOUSTESTSCONFIG_BUILDRESTRICTIONS.containing_type = _CONTINUOUSTESTSCONFIG +_CONTINUOUSTESTSCONFIG_BUILDRESTRICTIONSENTRY.fields_by_name['value'].message_type = _CONTINUOUSTESTSCONFIG_BUILDRESTRICTIONS +_CONTINUOUSTESTSCONFIG_BUILDRESTRICTIONSENTRY.containing_type = _CONTINUOUSTESTSCONFIG +_CONTINUOUSTESTSCONFIG_DEVICEMODULE.containing_type = _CONTINUOUSTESTSCONFIG +_CONTINUOUSTESTSCONFIG_DEVICEMODULESENTRY.fields_by_name['value'].message_type = _CONTINUOUSTESTSCONFIG_DEVICEMODULE +_CONTINUOUSTESTSCONFIG_DEVICEMODULESENTRY.containing_type = _CONTINUOUSTESTSCONFIG +_CONTINUOUSTESTSCONFIG_CIPDREF.containing_type = _CONTINUOUSTESTSCONFIG +_CONTINUOUSTESTSCONFIG_CIPDREFS.fields_by_name['refs'].message_type = _CONTINUOUSTESTSCONFIG_CIPDREF +_CONTINUOUSTESTSCONFIG_CIPDREFS.containing_type = _CONTINUOUSTESTSCONFIG +_CONTINUOUSTESTSCONFIG_CIPDREFSENTRY.fields_by_name['value'].message_type = _CONTINUOUSTESTSCONFIG_CIPDREFS +_CONTINUOUSTESTSCONFIG_CIPDREFSENTRY.containing_type = _CONTINUOUSTESTSCONFIG +_CONTINUOUSTESTSCONFIG.fields_by_name['continuous_test'].message_type = _CONTINUOUSTEST +_CONTINUOUSTESTSCONFIG.fields_by_name['scheduled_test'].message_type = _SCHEDULEDTEST +_CONTINUOUSTESTSCONFIG.fields_by_name['branch_type_priorities'].enum_type = _BUILDTARGETS_BRANCHTYPE +_CONTINUOUSTESTSCONFIG.fields_by_name['build_restrictions'].message_type = _CONTINUOUSTESTSCONFIG_BUILDRESTRICTIONSENTRY +_CONTINUOUSTESTSCONFIG.fields_by_name['device_modules'].message_type = _CONTINUOUSTESTSCONFIG_DEVICEMODULESENTRY +_CONTINUOUSTESTSCONFIG.fields_by_name['cipd_refs'].message_type = _CONTINUOUSTESTSCONFIG_CIPDREFSENTRY +DESCRIPTOR.message_types_by_name['BuildTargets'] = _BUILDTARGETS +DESCRIPTOR.message_types_by_name['Schedule'] = _SCHEDULE +DESCRIPTOR.message_types_by_name['BotRequirement'] = _BOTREQUIREMENT +DESCRIPTOR.message_types_by_name['CastOsModule'] = _CASTOSMODULE +DESCRIPTOR.message_types_by_name['TestTarget'] = _TESTTARGET +DESCRIPTOR.message_types_by_name['ContinuousTest'] = _CONTINUOUSTEST +DESCRIPTOR.message_types_by_name['ScheduledTest'] = _SCHEDULEDTEST +DESCRIPTOR.message_types_by_name['ContinuousTestsConfig'] = _CONTINUOUSTESTSCONFIG +DESCRIPTOR.enum_types_by_name['BuildPlatform'] = _BUILDPLATFORM +_sym_db.RegisterFileDescriptor(DESCRIPTOR) + +BuildTargets = _reflection.GeneratedProtocolMessageType('BuildTargets', (_message.Message,), { + + 'Branch' : _reflection.GeneratedProtocolMessageType('Branch', (_message.Message,), { + 'DESCRIPTOR' : _BUILDTARGETS_BRANCH, + '__module__' : 'continuous_tests_pb2' + # @@protoc_insertion_point(class_scope:continuous_tests.BuildTargets.Branch) + }) + , + 'DESCRIPTOR' : _BUILDTARGETS, + '__module__' : 'continuous_tests_pb2' + # @@protoc_insertion_point(class_scope:continuous_tests.BuildTargets) + }) +_sym_db.RegisterMessage(BuildTargets) +_sym_db.RegisterMessage(BuildTargets.Branch) + +Schedule = _reflection.GeneratedProtocolMessageType('Schedule', (_message.Message,), { + 'DESCRIPTOR' : _SCHEDULE, + '__module__' : 'continuous_tests_pb2' + # @@protoc_insertion_point(class_scope:continuous_tests.Schedule) + }) +_sym_db.RegisterMessage(Schedule) + +BotRequirement = _reflection.GeneratedProtocolMessageType('BotRequirement', (_message.Message,), { + 'DESCRIPTOR' : _BOTREQUIREMENT, + '__module__' : 'continuous_tests_pb2' + # @@protoc_insertion_point(class_scope:continuous_tests.BotRequirement) + }) +_sym_db.RegisterMessage(BotRequirement) + +CastOsModule = _reflection.GeneratedProtocolMessageType('CastOsModule', (_message.Message,), { + 'DESCRIPTOR' : _CASTOSMODULE, + '__module__' : 'continuous_tests_pb2' + # @@protoc_insertion_point(class_scope:continuous_tests.CastOsModule) + }) +_sym_db.RegisterMessage(CastOsModule) + +TestTarget = _reflection.GeneratedProtocolMessageType('TestTarget', (_message.Message,), { + 'DESCRIPTOR' : _TESTTARGET, + '__module__' : 'continuous_tests_pb2' + # @@protoc_insertion_point(class_scope:continuous_tests.TestTarget) + }) +_sym_db.RegisterMessage(TestTarget) + +ContinuousTest = _reflection.GeneratedProtocolMessageType('ContinuousTest', (_message.Message,), { + 'DESCRIPTOR' : _CONTINUOUSTEST, + '__module__' : 'continuous_tests_pb2' + # @@protoc_insertion_point(class_scope:continuous_tests.ContinuousTest) + }) +_sym_db.RegisterMessage(ContinuousTest) + +ScheduledTest = _reflection.GeneratedProtocolMessageType('ScheduledTest', (_message.Message,), { + 'DESCRIPTOR' : _SCHEDULEDTEST, + '__module__' : 'continuous_tests_pb2' + # @@protoc_insertion_point(class_scope:continuous_tests.ScheduledTest) + }) +_sym_db.RegisterMessage(ScheduledTest) + +ContinuousTestsConfig = _reflection.GeneratedProtocolMessageType('ContinuousTestsConfig', (_message.Message,), { + + 'BuildRestrictions' : _reflection.GeneratedProtocolMessageType('BuildRestrictions', (_message.Message,), { + 'DESCRIPTOR' : _CONTINUOUSTESTSCONFIG_BUILDRESTRICTIONS, + '__module__' : 'continuous_tests_pb2' + # @@protoc_insertion_point(class_scope:continuous_tests.ContinuousTestsConfig.BuildRestrictions) + }) + , + + 'BuildRestrictionsEntry' : _reflection.GeneratedProtocolMessageType('BuildRestrictionsEntry', (_message.Message,), { + 'DESCRIPTOR' : _CONTINUOUSTESTSCONFIG_BUILDRESTRICTIONSENTRY, + '__module__' : 'continuous_tests_pb2' + # @@protoc_insertion_point(class_scope:continuous_tests.ContinuousTestsConfig.BuildRestrictionsEntry) + }) + , + + 'DeviceModule' : _reflection.GeneratedProtocolMessageType('DeviceModule', (_message.Message,), { + 'DESCRIPTOR' : _CONTINUOUSTESTSCONFIG_DEVICEMODULE, + '__module__' : 'continuous_tests_pb2' + # @@protoc_insertion_point(class_scope:continuous_tests.ContinuousTestsConfig.DeviceModule) + }) + , + + 'DeviceModulesEntry' : _reflection.GeneratedProtocolMessageType('DeviceModulesEntry', (_message.Message,), { + 'DESCRIPTOR' : _CONTINUOUSTESTSCONFIG_DEVICEMODULESENTRY, + '__module__' : 'continuous_tests_pb2' + # @@protoc_insertion_point(class_scope:continuous_tests.ContinuousTestsConfig.DeviceModulesEntry) + }) + , + + 'CipdRef' : _reflection.GeneratedProtocolMessageType('CipdRef', (_message.Message,), { + 'DESCRIPTOR' : _CONTINUOUSTESTSCONFIG_CIPDREF, + '__module__' : 'continuous_tests_pb2' + # @@protoc_insertion_point(class_scope:continuous_tests.ContinuousTestsConfig.CipdRef) + }) + , + + 'CipdRefs' : _reflection.GeneratedProtocolMessageType('CipdRefs', (_message.Message,), { + 'DESCRIPTOR' : _CONTINUOUSTESTSCONFIG_CIPDREFS, + '__module__' : 'continuous_tests_pb2' + # @@protoc_insertion_point(class_scope:continuous_tests.ContinuousTestsConfig.CipdRefs) + }) + , + + 'CipdRefsEntry' : _reflection.GeneratedProtocolMessageType('CipdRefsEntry', (_message.Message,), { + 'DESCRIPTOR' : _CONTINUOUSTESTSCONFIG_CIPDREFSENTRY, + '__module__' : 'continuous_tests_pb2' + # @@protoc_insertion_point(class_scope:continuous_tests.ContinuousTestsConfig.CipdRefsEntry) + }) + , + 'DESCRIPTOR' : _CONTINUOUSTESTSCONFIG, + '__module__' : 'continuous_tests_pb2' + # @@protoc_insertion_point(class_scope:continuous_tests.ContinuousTestsConfig) + }) +_sym_db.RegisterMessage(ContinuousTestsConfig) +_sym_db.RegisterMessage(ContinuousTestsConfig.BuildRestrictions) +_sym_db.RegisterMessage(ContinuousTestsConfig.BuildRestrictionsEntry) +_sym_db.RegisterMessage(ContinuousTestsConfig.DeviceModule) +_sym_db.RegisterMessage(ContinuousTestsConfig.DeviceModulesEntry) +_sym_db.RegisterMessage(ContinuousTestsConfig.CipdRef) +_sym_db.RegisterMessage(ContinuousTestsConfig.CipdRefs) +_sym_db.RegisterMessage(ContinuousTestsConfig.CipdRefsEntry) + + +_CONTINUOUSTESTSCONFIG_BUILDRESTRICTIONSENTRY._options = None +_CONTINUOUSTESTSCONFIG_DEVICEMODULESENTRY._options = None +_CONTINUOUSTESTSCONFIG_CIPDREFSENTRY._options = None +# @@protoc_insertion_point(module_scope)
diff --git a/catatester/genfiles/master_config_pb2.py b/catatester/genfiles/master_config_pb2.py new file mode 100644 index 0000000..eca5a3f --- /dev/null +++ b/catatester/genfiles/master_config_pb2.py
@@ -0,0 +1,429 @@ +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: master_config.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='master_config.proto', + package='', + syntax='proto2', + serialized_pb=_b('\n\x13master_config.proto\"\xae\x01\n\nMasterInfo\x12\x10\n\x08hostname\x18\x01 \x01(\t\x12\x0c\n\x04name\x18\x02 \x01(\t\x12\x19\n\nproduction\x18\x03 \x01(\x08:\x05\x66\x61lse\x12\x15\n\x07\x65nabled\x18\x04 \x01(\x08:\x04true\x12\x13\n\x0bmultimaster\x18\x05 \x01(\x08\x12\x0e\n\x06\x64\x62_url\x18\x06 \x01(\t\x12\x14\n\x0cproject_name\x18\x07 \x01(\t\x12\x13\n\x0blogger_name\x18\x08 \x01(\t\"F\n\x0fMasterScheduler\x12\x1c\n\x07\x64\x65tails\x18\x01 \x01(\x0b\x32\x0b.MasterInfo\x12\x15\n\rpoller_set_id\x18\x02 \x03(\t\"-\n\rMasterBuilder\x12\x1c\n\x07\x64\x65tails\x18\x01 \x01(\x0b\x32\x0b.MasterInfo\"^\n\x06Poller\x12\x14\n\x0cmanifest_url\x18\x01 \x01(\t\x12\x1f\n\x12poll_interval_secs\x18\x02 \x01(\x05:\x03\x36\x30\x30\x12\x1d\n\x06\x62ranch\x18\x03 \x03(\x0b\x32\r.PollerBranch\"\x7f\n\x0cPollerBranch\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x10\n\x08manifest\x18\x02 \x01(\t\x12\x1b\n\x13\x66ull_product_target\x18\x03 \x03(\t\x12\x1c\n\x14\x63ontent_shell_target\x18\x04 \x03(\t\x12\x14\n\x0c\x62uild_target\x18\x05 \x03(\t\"0\n\tPollerSet\x12\n\n\x02id\x18\x01 \x01(\t\x12\x17\n\x06poller\x18\x02 \x03(\x0b\x32\x07.Poller\"t\n\x0cMasterConfig\x12\x1f\n\x07\x62uilder\x18\x01 \x03(\x0b\x32\x0e.MasterBuilder\x12#\n\tscheduler\x18\x02 \x03(\x0b\x32\x10.MasterScheduler\x12\x1e\n\npoller_set\x18\x03 \x03(\x0b\x32\n.PollerSet') +) + + + + +_MASTERINFO = _descriptor.Descriptor( + name='MasterInfo', + full_name='MasterInfo', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='hostname', full_name='MasterInfo.hostname', 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), + _descriptor.FieldDescriptor( + name='name', full_name='MasterInfo.name', 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), + _descriptor.FieldDescriptor( + name='production', full_name='MasterInfo.production', index=2, + number=3, type=8, cpp_type=7, label=1, + has_default_value=True, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='enabled', full_name='MasterInfo.enabled', index=3, + number=4, type=8, cpp_type=7, label=1, + has_default_value=True, default_value=True, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='multimaster', full_name='MasterInfo.multimaster', 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), + _descriptor.FieldDescriptor( + name='db_url', full_name='MasterInfo.db_url', 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), + _descriptor.FieldDescriptor( + name='project_name', full_name='MasterInfo.project_name', 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), + _descriptor.FieldDescriptor( + name='logger_name', full_name='MasterInfo.logger_name', index=7, + number=8, 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), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=24, + serialized_end=198, +) + + +_MASTERSCHEDULER = _descriptor.Descriptor( + name='MasterScheduler', + full_name='MasterScheduler', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='details', full_name='MasterScheduler.details', index=0, + number=1, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='poller_set_id', full_name='MasterScheduler.poller_set_id', index=1, + number=2, 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), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=200, + serialized_end=270, +) + + +_MASTERBUILDER = _descriptor.Descriptor( + name='MasterBuilder', + full_name='MasterBuilder', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='details', full_name='MasterBuilder.details', index=0, + number=1, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=272, + serialized_end=317, +) + + +_POLLER = _descriptor.Descriptor( + name='Poller', + full_name='Poller', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='manifest_url', full_name='Poller.manifest_url', 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), + _descriptor.FieldDescriptor( + name='poll_interval_secs', full_name='Poller.poll_interval_secs', index=1, + number=2, type=5, cpp_type=1, label=1, + has_default_value=True, default_value=600, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='branch', full_name='Poller.branch', index=2, + number=3, 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), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=319, + serialized_end=413, +) + + +_POLLERBRANCH = _descriptor.Descriptor( + name='PollerBranch', + full_name='PollerBranch', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='name', full_name='PollerBranch.name', 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), + _descriptor.FieldDescriptor( + name='manifest', full_name='PollerBranch.manifest', 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), + _descriptor.FieldDescriptor( + name='full_product_target', full_name='PollerBranch.full_product_target', index=2, + number=3, 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), + _descriptor.FieldDescriptor( + name='content_shell_target', full_name='PollerBranch.content_shell_target', index=3, + number=4, 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), + _descriptor.FieldDescriptor( + name='build_target', full_name='PollerBranch.build_target', index=4, + number=5, 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), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=415, + serialized_end=542, +) + + +_POLLERSET = _descriptor.Descriptor( + name='PollerSet', + full_name='PollerSet', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='id', full_name='PollerSet.id', 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), + _descriptor.FieldDescriptor( + name='poller', full_name='PollerSet.poller', index=1, + number=2, 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), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=544, + serialized_end=592, +) + + +_MASTERCONFIG = _descriptor.Descriptor( + name='MasterConfig', + full_name='MasterConfig', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='builder', full_name='MasterConfig.builder', index=0, + number=1, 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), + _descriptor.FieldDescriptor( + name='scheduler', full_name='MasterConfig.scheduler', index=1, + number=2, 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), + _descriptor.FieldDescriptor( + name='poller_set', full_name='MasterConfig.poller_set', index=2, + number=3, 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), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=594, + serialized_end=710, +) + +_MASTERSCHEDULER.fields_by_name['details'].message_type = _MASTERINFO +_MASTERBUILDER.fields_by_name['details'].message_type = _MASTERINFO +_POLLER.fields_by_name['branch'].message_type = _POLLERBRANCH +_POLLERSET.fields_by_name['poller'].message_type = _POLLER +_MASTERCONFIG.fields_by_name['builder'].message_type = _MASTERBUILDER +_MASTERCONFIG.fields_by_name['scheduler'].message_type = _MASTERSCHEDULER +_MASTERCONFIG.fields_by_name['poller_set'].message_type = _POLLERSET +DESCRIPTOR.message_types_by_name['MasterInfo'] = _MASTERINFO +DESCRIPTOR.message_types_by_name['MasterScheduler'] = _MASTERSCHEDULER +DESCRIPTOR.message_types_by_name['MasterBuilder'] = _MASTERBUILDER +DESCRIPTOR.message_types_by_name['Poller'] = _POLLER +DESCRIPTOR.message_types_by_name['PollerBranch'] = _POLLERBRANCH +DESCRIPTOR.message_types_by_name['PollerSet'] = _POLLERSET +DESCRIPTOR.message_types_by_name['MasterConfig'] = _MASTERCONFIG +_sym_db.RegisterFileDescriptor(DESCRIPTOR) + +MasterInfo = _reflection.GeneratedProtocolMessageType('MasterInfo', (_message.Message,), dict( + DESCRIPTOR = _MASTERINFO, + __module__ = 'master_config_pb2' + # @@protoc_insertion_point(class_scope:MasterInfo) + )) +_sym_db.RegisterMessage(MasterInfo) + +MasterScheduler = _reflection.GeneratedProtocolMessageType('MasterScheduler', (_message.Message,), dict( + DESCRIPTOR = _MASTERSCHEDULER, + __module__ = 'master_config_pb2' + # @@protoc_insertion_point(class_scope:MasterScheduler) + )) +_sym_db.RegisterMessage(MasterScheduler) + +MasterBuilder = _reflection.GeneratedProtocolMessageType('MasterBuilder', (_message.Message,), dict( + DESCRIPTOR = _MASTERBUILDER, + __module__ = 'master_config_pb2' + # @@protoc_insertion_point(class_scope:MasterBuilder) + )) +_sym_db.RegisterMessage(MasterBuilder) + +Poller = _reflection.GeneratedProtocolMessageType('Poller', (_message.Message,), dict( + DESCRIPTOR = _POLLER, + __module__ = 'master_config_pb2' + # @@protoc_insertion_point(class_scope:Poller) + )) +_sym_db.RegisterMessage(Poller) + +PollerBranch = _reflection.GeneratedProtocolMessageType('PollerBranch', (_message.Message,), dict( + DESCRIPTOR = _POLLERBRANCH, + __module__ = 'master_config_pb2' + # @@protoc_insertion_point(class_scope:PollerBranch) + )) +_sym_db.RegisterMessage(PollerBranch) + +PollerSet = _reflection.GeneratedProtocolMessageType('PollerSet', (_message.Message,), dict( + DESCRIPTOR = _POLLERSET, + __module__ = 'master_config_pb2' + # @@protoc_insertion_point(class_scope:PollerSet) + )) +_sym_db.RegisterMessage(PollerSet) + +MasterConfig = _reflection.GeneratedProtocolMessageType('MasterConfig', (_message.Message,), dict( + DESCRIPTOR = _MASTERCONFIG, + __module__ = 'master_config_pb2' + # @@protoc_insertion_point(class_scope:MasterConfig) + )) +_sym_db.RegisterMessage(MasterConfig) + + +# @@protoc_insertion_point(module_scope)
diff --git a/catatester/proto/continuous_tests.proto b/catatester/proto/continuous_tests.proto new file mode 100644 index 0000000..5475972 --- /dev/null +++ b/catatester/proto/continuous_tests.proto
@@ -0,0 +1,201 @@ +syntax = "proto2"; + +package continuous_tests; + +// When building proto outside of google3, it fails to build if any +// enum values in the same message have the same name, because +// natively enum values in a message are all siblings instead of being +// local-scoped within their parent enum. As a result, we cannot +// follow the google3 best practice to have the 0th enum value by DEFAULT +// in all cases. These protos get copied to google3 via copybara, and in +// google3 we get linter warnings when any enum values have the same name. +// (-- api-linter: enum_default_value=disabled --) + +message BuildTargets { + enum BranchType { + ALL = 0; + MASTER = 1; + RELEASE = 2; + } + // Branch can be specified either by name or type. + message Branch { + oneof BranchSpec { + BranchType type = 1; + string name = 2; + } + } + enum Variant { + DEFAULT = 0; // all variants + ENG = 1; + USER = 2; + ARM = 3; + X86 = 4; + X64 = 5; + ARM64 = 6; + USERDEBUG = 7; + } + // Branch types under test (default = All branch types). + optional BranchType branch_types = 1; + // Strings of product capabilities for the types of products under test. + // Product capabilities are defined in: + // https://cs.corp.google.com/eureka_internal/builder/masters/configs/eureka/build_config.protoascii + repeated string product_types = 2; + // Specific product(s) under test. Prefer using product_types where possible. + repeated string products = 3; + // Variants under test. + optional Variant variants = 4; + // (Optional) The builder_name builds being targeted. + // When unused (default), catatester will target all builder_names that + // match every specified <product>-<variant> combination. + // Set this to explicitly set builder_names for targeting non-conventional + // builds: i.e. steak-yeti, biggie-mesh. + // This is additive to any branch_types specified. + repeated string builder_names = 5; + // Branches under test (default = All branches). + repeated Branch branches = 6; +} + +message Schedule { + // Cron-based scheduler string for how often to test new builds. + optional string cron = 1; + enum Policy { + DEFAULT = 0; // by default, LATEST_UNTESTED_BUILD + LATEST_UNTESTED = 1; // will backfill older untested builds + LATEST = 2; // will test latest even if already tested before + LATEST_MINUS_ONE = 3; // will test latest minus one untested OTA + } + // Scheduler policy for which build to test. + optional Policy policy = 2; +} + +message BotRequirement { + optional string bot_dimension = 1; + optional string value = 2; +} + +message CastOsModule { + optional string cipd_package = 1; + optional string cipd_version = 2; +} + +message TestTarget { + enum Recipe { + HOME_RUNNER = 0; + DEVICE_UNIT_TEST_RUNNER = 1; + OTA_INSTALLABLE_RUNNER = 2; + LIBASSISTANT_RUNNER = 3; + FUCHSIA_GUNIT_RUNNER = 4; // Deprecated + FUCHSIA_RUNNER = 5; + VIRTUAL_DEVICE_RUNNER = 6; + } + enum Priority { + DEFAULT = 0; // Controller currently interprets default == medium + CRITICAL = 1; + MEDIUM = 2; + HIGH = 3; + LOW = 4; + } + // Path to the test config file. (relative to test_configs_root). + optional string config = 1; + // By default, catatester will run all test cases in the test config. + // Set this if you wish to run only a specific subset of named test cases that + // are defined in the test config file. + repeated string test_cases = 2; + // Name of the binary to execute for this test config. + optional string binary_name = 3; + // Test priority. + optional Priority priority = 4; + // Whether this test target is enabled (default = true). + optional bool enabled = 5 [default = true]; + // The luci-py recipe to use for running the swarming task. + optional Recipe recipe = 6; + // The test timeout (mins). Does not include ota install time. + optional int32 test_timeout_mins = 7 [default = 60]; + // Names of test groups that this test belongs to. + // Test group tags must be defined in test_group_tags. + repeated string test_groups = 8; + // Optional list of testbed requirements that the test requires. + repeated BotRequirement testbed_requirements = 9; + // the key of the cipd_refs map to be used for this test. + optional string cipd_refs_key = 10 [default = 'internal']; + // Bot pool to use for allocation. Default value set by controller. + optional string bot_pool = 11; + // CastOs Modules to install before running the test. + repeated CastOsModule castos_modules = 12; + // Whether to skip setting default bot dimensions when scheduling the test. + // If True, all dimensions (other than pool) must be set in + // testbed_requirements. + optional bool skip_default_dimensions = 13; +} + +enum BuildPlatform { + DEFAULT = 0; + CATABUILDER = 1; + ANDROID_BUILD = 2; +} + +message ContinuousTest { + optional TestTarget test_target = 1; + repeated BuildTargets build_targets = 2; +} + +message ScheduledTest { + optional TestTarget test_target = 1; + repeated BuildTargets build_targets = 2; + // Set if you want a cron-based scheduler for running tests. + // When not set (by default), catatester will test every matching new build + // continuously. + optional Schedule schedule = 3; + repeated string branches = 4; + optional string repo = 5 [default = "internal"]; + // (Optional) The platform where the build comes from. + // By default, every build is from Catabuilder. + optional BuildPlatform build_platform = 6 [default = CATABUILDER]; +} + +message ContinuousTestsConfig { + // Relative path from continuous-tests repo to the test configs root dir. + optional string test_configs_root = 1; + + // Continuous test targets. + repeated ContinuousTest continuous_test = 2; + + // Scheduled test targets. + repeated ScheduledTest scheduled_test = 3; + + // Priority-Ordering of branch types. + repeated BuildTargets.BranchType branch_type_priorities = 4; + // Branch names that we no longer want to test. + repeated string disabled_branches = 5; + + // Build restrictions for certain products. + // Useful for new products where we don't have enough inventory to test every + // build_target permutation desired by the tests. + message BuildRestrictions { + repeated BuildTargets.BranchType allowed_branch_types = 1; + repeated BuildTargets.Variant allowed_variants = 2; + } + map<string, BuildRestrictions> build_restrictions = 6; + + // Defines common test group tags. + repeated string test_group_tags = 7; + + // Device modules passed to the test runner to instantiate the correct + // device class during the execution of tests. + message DeviceModule { + optional string device_module = 1; + optional string device_class = 2; + } + map<string, DeviceModule> device_modules = 8; + + // Per repo CIPD references + message CipdRef { + optional string package_name = 1; + optional string version = 2; + optional string path = 3; + } + message CipdRefs { + repeated CipdRef refs = 1; + } + map<string, CipdRefs> cipd_refs = 9; +}
diff --git a/catatester/proto/copy.bara.sky b/catatester/proto/copy.bara.sky new file mode 100644 index 0000000..14a33cf --- /dev/null +++ b/catatester/proto/copy.bara.sky
@@ -0,0 +1,51 @@ +"""Copybara config to auto import build_config protos to continuous-tests. + +Usage: + alias copybara='/google/data/ro/teams/copybara/copybara' + copybara catatester/proto/copy.bara.sky build_configs_import +""" + +git_origin = git.origin( + url = "https://eureka-internal.googlesource.com/builder/masters", + ref = "master", +) + +origin_files = glob( + include = [ + "src/proto/build_config.proto", + "src/genfiles/build_config_pb2.py", + "configs/eureka/build_config.protoascii" + ], + exclude = [], +) + +destination_files = glob( + include = [ + "catatester/proto/imported/build_config.proto", + "catatester/genfiles/build_config_pb2.py", + "catatester/configs/imported/build_config.protoascii"], + exclude = [], +) + +core.workflow( + name = "build_configs_import", + origin = git_origin, + origin_files = origin_files, + destination = git.gerrit_destination( + url = "https://eureka-internal.googlesource.com/continuous-tests", + fetch = "master", + push_to_refs_for = "master", + ), + destination_files = destination_files, + authoring = authoring.pass_thru("Home EngProd <no-reply@google.com>"), + transformations = [ + core.move("src/proto/build_config.proto", "catatester/proto/imported/build_config.proto"), + core.move("src/genfiles/build_config_pb2.py", "catatester/genfiles/build_config_pb2.py"), + core.move( + "configs/eureka/build_config.protoascii", + "catatester/configs/imported/build_config.protoascii"), + metadata.squash_notes( + prefix = "Imports from eureka_internal:builder/masters.\n\n", + ), + ], +)
diff --git a/catatester/proto/imported/build_config.proto b/catatester/proto/imported/build_config.proto new file mode 100644 index 0000000..2af9d83 --- /dev/null +++ b/catatester/proto/imported/build_config.proto
@@ -0,0 +1,36 @@ +syntax = "proto2"; + +package build_config; + +// Disable linter for copybara exports to google3 +// [NOLINT common_typos_disable] + +message OtaBuild { + // The meta build target to build for. For example steak-eng. + optional string build_target = 1; + // The product to build for. This is something like steak or anchovy. Note + // that on newer platforms this is the same as the platform. + optional string product = 2; + // The variant this is for. For example user or eng. + optional string variant = 3; + // The platform this is for. + optional string platform = 4; + // A list of partner buckets to archive artifacts to. + repeated string partner_bucket = 5; + // A list of capabilities that this product has. + enum Capability { + NONE = 0; + ASSISTANT = 1; + CAST_VIDEO_RECEIVER = 2; + CAST_AUDIO_RECEIVER = 3; + WIFI_2GHZ = 4; + WIFI_5GHZ = 5; + } + repeated Capability capabilities = 6; + // Whether or not this build is enabled for automated tests + optional bool test = 7 [default = false]; +} + +message BuildConfig { + map<string, OtaBuild> ota_build = 1; +}
diff --git a/catatester/puppet/README.md b/catatester/puppet/README.md new file mode 100644 index 0000000..c712ab0 --- /dev/null +++ b/catatester/puppet/README.md
@@ -0,0 +1,2 @@ +# DO NOT modify the puppet configuration files +The configuration (.pp) files are copied from google3 via copybara service.
diff --git a/catatester/puppet/cast_builder/files/swarm/lab_nodes/site.pp b/catatester/puppet/cast_builder/files/swarm/lab_nodes/site.pp new file mode 100644 index 0000000..01273d6 --- /dev/null +++ b/catatester/puppet/cast_builder/files/swarm/lab_nodes/site.pp
@@ -0,0 +1,58 @@ +# Node definitions for swarm lab hosts +# +# See go/catatester-hosts for host locations & static IP addresses + +$md5_cipd_key = 'f075d7d239f62829a2da23276990efbf' +$md5_gsutil_boto = 'defa9c638098738683e410a04320d8db' +$md5_fragglerock_key = '2c52eb278c88fdb7c993880fa2910109' +$md5_monitoring_key = '4886a0a7112098e2de658251269b30fe' +$md5_swarming_key = '1c997a30801f9b7b82dcb537227f7712' + +node /^home-staging-.*/ { + $cipd_env = 'staging' + class {'cast_builder::swarm_init': + env => 'lab_host', + } +} +node /^home-swarming-.*/ { + $cipd_env = 'live' + class {'cast_builder::swarm_init': + env => 'lab_host', + } +} +node /^home-cq-.*/ { + $cipd_env = 'live' + class {'cast_builder::swarm_init': + env => 'lab_host', + } +} +node /^gotham-1$/ { + $cipd_env = 'live' + class {'cast_builder::swarm_init': + env => 'gotham_host', + } +} +node /^gazoo-canary-.*/ { + $cipd_env = 'canary' + class {'cast_builder::swarm_init': + env => 'gazoo_canary_host', + } +} +node /^gazoo-staging-.*/ { + $cipd_env = 'staging' + class {'cast_builder::swarm_init': + env => 'gazoo_staging_host', + } +} +node /^gazoo-prod-.*/ { + $cipd_env = 'live' + class {'cast_builder::swarm_init': + env => 'gazoo_prod_host', + } +} +node default { + $cipd_env = 'live' + class {'cast_builder::swarm_init': + env => 'lab_host', + } +}
diff --git a/catatester/puppet/cast_builder/lib/facter/devices.rb b/catatester/puppet/cast_builder/lib/facter/devices.rb new file mode 100644 index 0000000..6e0934e --- /dev/null +++ b/catatester/puppet/cast_builder/lib/facter/devices.rb
@@ -0,0 +1,17 @@ +def ls(dir) + if File.directory?(dir) + Dir.entries(dir).reject { |entry| entry == '.' || entry == '..' } + else + Array.new + end +end + +Facter.add('usb_devices') do + confine :kernel => 'Linux' + + # udev rules configure the system to generate symlinks in this directory + # when devices are connected to the machine (see: 60-persistent-serial.rules) + setcode do + ls('/dev/serial/by-path/') + end +end
diff --git a/catatester/puppet/cast_builder/manifests/swarm_bot_gotham.pp b/catatester/puppet/cast_builder/manifests/swarm_bot_gotham.pp new file mode 100644 index 0000000..a1e0ff5 --- /dev/null +++ b/catatester/puppet/cast_builder/manifests/swarm_bot_gotham.pp
@@ -0,0 +1,124 @@ +# Setup for swarm bots in Gotham CI. +# Enumerates the connected Gothams, and bootstraps a Swarming bot for each. +# Uses Systemd to restart bots in case they or the host crashes. + +class cast_builder::swarm_bot_gotham ($user, $group, $home_dir) { + + $cipd_key = "${home_dir}/home-cipd-service-account.json" + $gsutil_dir = "${home_dir}/gsutil" + $gsutil_boto = "${home_dir}/.boto" + $fragglerock_key = "${home_dir}/fragglerock_service_key.json" + $swarm_home_dir = "${home_dir}/swarm_home" + $depot_tools_dir = "${home_dir}/depot_tools" + $swarm_bots_home = "${swarm_home_dir}/bots" + $venv = "${swarm_home_dir}/swarm_env" + $prefix = 'swarming_bot--' + + $packages = [ + 'libudev-dev', + 'libusb-1.0.0-dev', + 'virtualenv', + ] + + package { $packages: + ensure => latest, + } + + file { '/etc/udev/rules.d/99-nxpusb.rules': + ensure => file, + owner => $user, + group => $group, + mode => '0644', + content => ' +# Give non-superusers access to connected NXP boards + +# SDP protocol +KERNEL=="hidraw*", ATTRS{idVendor}=="1fc9", MODE="0666" +ACTION=="add", SUBSYSTEM=="usb", ATTR{idVendor}=="1fc9", MODE="666" +ACTION=="add", SUBSYSTEM=="usb", ATTR{idVendor}=="0d28", MODE="666" + +# Flashloader +KERNEL=="hidraw*", ATTRS{idVendor}=="15a2", MODE="0666"' + } + + file { '/etc/udev/rules.d/70-caraway.rules': + ensure => file, + owner => $user, + group => $group, + mode => '0644', + content => ' +# 0483:374b STMicroelectronics ST-LINK/V2.1 (Nucleo-F103RB) +# This grants rw to plugdev so that the usb device is accessible to tools (e.g. +# openocd) without sudo. +SUBSYSTEM=="usb", ATTR{idVendor}=="0483", ATTR{idProduct}=="374b", MODE="0664", GROUP="plugdev", SYMLINK+="stlink-latest", SYMLINK+="stlink%n", RUN+="/usr/bin/touch /tmp/A" + +# 0483:df11 STMicroelectronics STM Device in DFU Mode +# This grants rw to plugdev so that the usb device is accessible to tools (e.g. dfuse.py) without sudo. +SUBSYSTEM=="usb", ATTR{idVendor}=="0483", ATTR{idProduct}=="df11", MODE="0664", GROUP="plugdev" + +# 18d1:* Google Inc. +# Prevents modem-manager from probing for a modem on any serial ports with +# idVendor == Google, and grants rw to plugdev so that the usb device is +# accessible to tools without sudo. +SUBSYSTEM=="usb", ATTR{idVendor}=="18d1", ENV{ID_MM_DEVICE_IGNORE}="1", MODE="0664", GROUP="plugdev" + +# If you need to be more specific than just using idVendor == Google, i.e. you are also using +# separate rules for other Google devices, you can comment out the rule directly above this +# and uncomment the following rule, filling in the appropriate value for idProduct. Note the +# use of the plural "ATTRS" to match parents of the device being added. +# SUBSYSTEM=="usb", ATTR{idVendor}=="18d1", ATTRS{idProduct}=="", ENV{ID_MM_DEVICE_IGNORE}="1", MODE="0664", GROUP="plugdev"' + } + + # usb_devices is a Facter fact enumerating the connected Gothams. + # This is invoked at runtime and defined in lib/facter/devices.rb. + $::usb_devices.each |String $serial_port| { + $bot_id = sha1($serial_port)[0,6] + + file { [ "${swarm_bots_home}/${bot_id}/", + "${swarm_bots_home}/${bot_id}/bot_root/", ]: + ensure => directory, + owner => $user, + group => $group, + mode => '0755', + } -> + file { "${swarm_bots_home}/${bot_id}/bot_dimensions.json": + ensure => file, + owner => $user, + group => $group, + mode => '0644', + content => "{ \"gotham_serial_port\" : [\"${serial_port}\"] }", + } -> + # Note that bots routinely clear the directory in which they were started. + # Any file or directory other than swarming_bot.zip will be deleted. + file { "${swarm_bots_home}/${bot_id}/bot_root/swarming_bot.zip": + ensure => file, + owner => $user, + group => $group, + mode => '0755', + + # TODO(dustingadal) This is curled here by the host bootstrap script. + # It shouldn't be placed in the bot-specific directory bots/1/ + # See: //eureka_internal/test/lab_system/setup_swarm_host.sh + source => "file:${swarm_bots_home}/1/swarming_bot.zip", + } -> + # This will restart the bot if it or the host goes down. + file { "/etc/systemd/system/${prefix}${bot_id}.service": + ensure => file, + owner => 'root', + group => 'root', + mode => '0644', + content => template('cast_builder/swarm_bot.systemd.erb'), + } -> + service { "${prefix}${bot_id}": + ensure => running, + enable => true, + provider => 'systemd', + before => Exec['restart_systemd'], + } + } + + # The services previously registered are run as systemd restarts. + exec { 'restart_systemd': + command => '/bin/systemctl daemon-reload', + } +}
diff --git a/catatester/puppet/cast_builder/manifests/swarm_bot_home.pp b/catatester/puppet/cast_builder/manifests/swarm_bot_home.pp new file mode 100644 index 0000000..b151dc4 --- /dev/null +++ b/catatester/puppet/cast_builder/manifests/swarm_bot_home.pp
@@ -0,0 +1,125 @@ +# Setup for swarm bots in Home CI + +class cast_builder::swarm_bot_home ($user, $group, $home_dir) { + + # Save globals as in-scope class variables + $cipd_ref = $cipd_env # lint:ignore:variable_scope + + # Define class variables + $cipd_key = "${home_dir}/home-cipd-service-account.json" + $gsutil_dir = "${home_dir}/gsutil" + $gsutil_boto = "${home_dir}/.boto" + $fragglerock_key = "${home_dir}/fragglerock_service_key.json" + $swarm_home_dir = "${home_dir}/swarm_home" + $depot_tools_dir = "${home_dir}/depot_tools" + $swarm_bots_home = "${swarm_home_dir}/bots" + $eurtest_binaries = "${swarm_home_dir}/eurtest_binaries" + $cipd_ensure_eurtest_binaries_sh = "${home_dir}/cipd_ensure_eurtest_binaries.sh" + $cipd_ensure_eurtest_binaries = "${home_dir}/cipd_ensure_eurtest_binaries" + $devicemap_dir = "${swarm_home_dir}/devicemap" + $cipd_ensure_devicemap = "${home_dir}/cipd_ensure_devicemap" + $venv = "${swarm_home_dir}/swarm_env" + $good_builds_dir = "${swarm_home_dir}/good_builds" + $androidthings_keys_dir = "${swarm_home_dir}/androidthings_keys" + + ### Ensure packages retrieved via cipd + + File { + ensure => file, + owner => $user, + group => $group, + mode => '0750', + } + Exec { + user => $user, + } + + file { '/tmp/ensure_androidthings_keys': + ensure => file, + content => "home_internal/androidthings_keys ${cipd_ref}", + } -> + exec { 'cipd_ensure_androidthings_keys': + command => "${depot_tools_dir}/cipd ensure -ensure-file /tmp/ensure_androidthings_keys -root ${androidthings_keys_dir} -service-account-json ${cipd_key}", + require => Notify['has_cipd_key'], + timeout => 2700, + before => Exec['setup_bots'], + } + + file { '/tmp/ensure_good_builds': + ensure => file, + content => "home_internal/known_good_builds ${cipd_ref}", + } -> + exec { 'cipd_ensure_good_builds': + command => "${depot_tools_dir}/cipd ensure -ensure-file /tmp/ensure_good_builds -root ${good_builds_dir} -service-account-json ${cipd_key}", + require => Notify['has_cipd_key'], + timeout => 2700, + before => Exec['setup_bots'], + } + + file { $cipd_ensure_eurtest_binaries: + ensure => file, + content => template('cast_builder/ensure_eurtest_binaries.erb'), + } -> + file { $cipd_ensure_eurtest_binaries_sh: + ensure => file, + content => template('cast_builder/ensure_eurtest_binaries.sh.erb'), + } -> + # Ensure we always have a cron that downloads latest test binaries, which + # will always d/l even if currently-used puppet scripts are broken. + cron { 'cron_cipd_ensure_eurtest_binaries': + ensure => present, + command => "${cipd_ensure_eurtest_binaries_sh} 2>&1 | /usr/bin/logger -t ensure_eurtest_binaries", + minute => 0, + environment => [ + 'PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin', + ], + user => $user, + require => Notify['has_cipd_key'], + before => Exec['setup_bots'], + } -> + # Directly execute once, for first-time setup. This must happen before setup_bots. + exec { 'cipd_ensure_eurtest_binaries': + command => "${cipd_ensure_eurtest_binaries_sh} 2>&1 | /usr/bin/logger -t ensure_eurtest_binaries", + require => Notify['has_cipd_key'], + timeout => 3000, + before => Exec['setup_bots'], + } + + # Ensure we always have a cron that downloads latest devicemap scripts, which + # will always d/l even if currently-used puppet scripts are broken. + file { $cipd_ensure_devicemap: + content => "home_internal/devicemap ${cipd_ref}", + } -> + cron { 'cron_cipd_ensure_devicemap': + ensure => present, + command => "${depot_tools_dir}/cipd ensure -ensure-file ${cipd_ensure_devicemap} -root ${devicemap_dir} -service-account-json ${cipd_key} 2>&1 | /usr/bin/logger -t ensure_devicemap", + minute => '*/10', # every 10 mins + environment => [ + 'PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin', + ], + user => $user, + before => Exec['setup_bots'], + require => Notify['has_cipd_key'], + } -> + # Directly execute once, for first-time setup. This must happen before setup_bots. + exec { 'cipd_ensure_devicemap': + command => "${depot_tools_dir}/cipd ensure -ensure-file ${cipd_ensure_devicemap} -root ${devicemap_dir} -service-account-json ${cipd_key} 2>&1 | /usr/bin/logger -t ensure_devicemap", + require => Notify['has_cipd_key'], + timeout => 120, + before => Exec['setup_bots'], + } + + exec { 'setup_bots': + # TODO(jonesmi): fetch swarming token using _ahi/api/v1/swarming_token using gcloud APIs + cwd => $home_dir, + path => '/bin', + command => "bash -c 'source ${venv}/bin/activate && python ${devicemap_dir}/bot_setup.py --user ${user} --group ${group} --swarm_bots_home ${swarm_bots_home} --gsutil_dir ${gsutil_dir} --gsutil_boto ${gsutil_boto} --fragglerock_key ${fragglerock_key} --eurtest_binaries ${eurtest_binaries} --venv ${venv} --devicemap_dir ${devicemap_dir} --depot_tools_dir ${depot_tools_dir}'", + user => root, + require => [ + File[$swarm_bots_home], + Exec['cipd_ensure_eurtest_binaries', + 'pip_install_requirements', + 'install gsutil']] + } + # TODO(jonesmi): also add a script to auto-stop & delete upstarts for bots that get deleted from $bots_list +}
diff --git a/catatester/puppet/cast_builder/manifests/swarm_host_base.pp b/catatester/puppet/cast_builder/manifests/swarm_host_base.pp new file mode 100644 index 0000000..0bf22a8 --- /dev/null +++ b/catatester/puppet/cast_builder/manifests/swarm_host_base.pp
@@ -0,0 +1,202 @@ +# Common setup for all Swarming device-bot hosts for CI + +class cast_builder::swarm_host_base ($user, $group, $home_dir) { + + # save globals as in-scope class variables + $cipd_ref = $cipd_env # lint:ignore:variable_scope + + # define class variables + $cipd_key = "${home_dir}/home-cipd-service-account.json" + $gsutil_dir = "${home_dir}/gsutil" + $gsutil_boto = "${home_dir}/.boto" + $fragglerock_key = "${home_dir}/fragglerock_service_key.json" + $swarm_home_dir = "${home_dir}/swarm_home" + $depot_tools_dir = "${home_dir}/depot_tools" + $depot_tools_remote = 'https://chromium.googlesource.com/chromium/tools/depot_tools.git' + $swarm_bots_home = "${swarm_home_dir}/bots" + $venv = "${swarm_home_dir}/swarm_env" + $email = 'livingroom-releng+alerts+puppet@google.com' + + $common_packages = [ + 'alsa-utils', # Provides "arecord" and "amixer", used by MZ sync tests. + 'avahi-utils', # Provides "avahi-browse", for MZ discovery tests. + 'build-essential', + 'curl', + 'git', + 'libcurl4-gnutls-dev', + 'libffi-dev', + 'libfreetype6-dev', + 'libsox-fmt-mp3', + 'lm-sensors', + 'nodejs', + 'python-dev', + 'python-oauth2client', + 'python-setuptools', + 'python-virtualenv', + 'sox', + 'tar', + 'vim', + ] + + # For debian 10.0 libav-tools is replaced by ffmpeg + $major_os_release = 0.0 + $::operatingsystemmajrelease + if $major_os_release >= 10.0 { + $packages = $common_packages + ['ffmpeg'] + } + else { + $packages = $common_packages + ['libav-tools'] + } + + package { $packages: + ensure => present, + require => Exec['apt-get_update'], + } + + Exec { + # git needs HOME to know where to write the global config. + environment => ["HOME=${home_dir}"], + path => ['/usr/local/sbin', '/usr/local/bin', '/usr/sbin', '/usr/bin', '/sbin', '/bin', $depot_tools_dir], + user => $user, + } + + File { + owner => $user, + group => $group, + } + + exec { 'apt-get_update': + user => 'root', + group => 'root', + command => '/usr/bin/apt-get update', + timeout => 300, + } + + group { $group: + ensure => 'present', + } + + file { $home_dir: + ensure => directory, + mode => '0755' + } + + file { $swarm_bots_home: + ensure => directory, + mode => '0755' + } + + file { $cipd_key: + ensure => file, + mode => '0750' + } -> + cast_builder::test_md5 { $cipd_key: + md5 => $::md5_cipd_key, + } -> + notify { 'has_cipd_key': + message => "cipd file exists at ${cipd_key}", + } + + exec { 'clone_depot_tools_repo': + cwd => $home_dir, + command => "git clone ${depot_tools_remote}", + creates => $depot_tools_dir, + require => Package['git'], + } -> + exec { 'git_pull_depot_tools': + cwd => $depot_tools_dir, + command => 'git pull origin master', + } + + ### Pip & virtualenv setup + + file { $venv: + ensure => directory, + mode => '0755', + require => File[$home_dir], + } + + $pip_cmd = "${venv}/bin/pip" + exec { 'create_python_virtualenv': + command => "virtualenv ${venv}; ${pip_cmd} --log ${venv}/pip.log install --upgrade pip setuptools", + creates => "${venv}/bin/activate", + cwd => $home_dir, + # Unless activate exists and VIRTUAL_ENV is correct we re-create the virtualenv + unless => "grep '^[\\t ]*VIRTUAL_ENV=[\\\\'\\\"]*${venv}[\\\"\\\\'][\\t ]*$' ${venv}/bin/activate", + require => [ + Package['python-virtualenv'], + File[$venv] + ], + } -> + # Enable $user to write to its own .cache directory. + file { "${home_dir}/.cache": + ensure => 'directory', + owner => $user, + group => $group, + } -> + exec { 'pip_install_requirements': + command => "bash -c 'source ${venv}/bin/activate && ${pip_cmd} install -U pip wheel && + ${pip_cmd} install pyyaml'", + require => [ + Exec['create_python_virtualenv'], + Package['python-virtualenv'], + ], + timeout => 120, + } + + ### Ensure that gsutil is set up. Some tests use it to copy files to a media server. + # File with no source will be created with 0 size by puppet if missing + # Manual deployment of .boto and .p12 file required for new host + # (see instructions in swarm_init.pp) + file { $gsutil_boto: + ensure => file, + mode => '0755', + require => File[$home_dir], + } -> + cast_builder::test_md5 { $gsutil_boto: + md5 => $::md5_gsutil_boto, + } -> + notify { 'correct_boto': + message => "Successfully tested file ${home_dir}/.boto", + } + + # File with no source will be created with 0 size by puppet if missing + # Manual deployment of json key file required for new host + # (see instructions in swarm_init.pp) + file { $fragglerock_key: + ensure => file, + mode => '0755', + require => File[$home_dir], + } -> + cast_builder::test_md5 { $fragglerock_key: + md5 => $::md5_fragglerock_key, + } -> + notify { 'correct_fragglerock_key_file': + message => "Successfully tested file ${fragglerock_key}", + } + + # Get, install, update, and configure gsutil + file { $gsutil_dir: + ensure => directory, + mode => '0755', + require => Notify['correct_boto'], + } -> + exec { 'get gsutil': + cwd => $home_dir, + command => 'curl https://storage.googleapis.com/pub/gsutil.tar.gz -f -o gsutil.tar.gz', + require => Package['curl'], + } -> + exec { 'install gsutil': + cwd => $home_dir, + command => "tar --ungzip --extract --strip-components=2 --file=gsutil.tar.gz --directory=${gsutil_dir}", + require => Package['tar'], + } -> + file { "${home_dir}/gsutil.tar.gz": + ensure => absent, + # Disable gsutil update until a safe release is available. b/135462553 + # } -> + # # gsutil will not run but return 0 status with empty .boto file + # exec { 'update gsutil': + # cwd => $home_dir, + # command => "${gsutil_dir}/gsutil update -f -n", + } +}
diff --git a/catatester/puppet/cast_builder/manifests/swarm_host_ganeti.pp b/catatester/puppet/cast_builder/manifests/swarm_host_ganeti.pp new file mode 100644 index 0000000..479caae --- /dev/null +++ b/catatester/puppet/cast_builder/manifests/swarm_host_ganeti.pp
@@ -0,0 +1,32 @@ +# Setup Raspberry Pi swarm host in lab for Home CI + +class cast_builder::swarm_host_ganeti ($user, $home_dir) { + + $email = 'livingroom-releng+alerts+puppet@google.com' + $depot_tools_dir = "${home_dir}/depot_tools" + + $packages = [ + 'become', + ] + + package { $packages: + ensure => latest, + } + + apt::addon_repo { 'cast-builder-puppet': + repo_stage => $::cast_builder_track, + } + + # Until Goobuntu Team makes puppet frequency configurable (b/22848425) we need + # to manually ensure that Puppet runs hourly on all hosts. + cron::entry { 'goobuntu_run_puppet': + ensure => present, + command => '/usr/bin/apt-get update; /usr/bin/glinux-run-puppet', + minute => fqdn_rand(60), + user => 'root', + environment => { + 'PATH' => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin', + 'MAILTO' => $email, + }, + } +}
diff --git a/catatester/puppet/cast_builder/manifests/swarm_host_lab.pp b/catatester/puppet/cast_builder/manifests/swarm_host_lab.pp new file mode 100644 index 0000000..a176502 --- /dev/null +++ b/catatester/puppet/cast_builder/manifests/swarm_host_lab.pp
@@ -0,0 +1,126 @@ +# Set up common components for Swarming hosts in the lab + +class cast_builder::swarm_host_lab ($user, $group, $home_dir) { + + # save globals as in-scope class variables + $cipd_ref = $cipd_env # lint:ignore:variable_scope + + $swarm_home_dir = "${home_dir}/swarm_home" + $cipd_ensure_puppet = "${home_dir}/cipd_ensure_puppet" + $puppet_dir = "${home_dir}/puppet" + $puppet_manifest = "${puppet_dir}/cast_builder/files/swarm/lab_nodes/site.pp" + $puppet_run_sh = "${home_dir}/swarm_puppet_run.sh" + $depot_tools_dir = "${home_dir}/depot_tools" + $cipd_key = "${home_dir}/home-cipd-service-account.json" + # TODO(b/79684886): better service account key management. + $monitoring_key = "${home_dir}/home-ci-controller-staging.json" + $monitoring_tool = "${swarm_home_dir}/eurtest_binaries/home_binaries/tools/host_monitor" + $email = 'livingroom-releng+alerts+puppet@google.com' + $swarming_key = "${home_dir}/luci/swarming-key.json" + + $packages = [ + 'puppet', + ] + + File { + ensure => file, + owner => $user, + group => $group, + mode => '0755', + } + + package { $packages: + ensure => latest, + } + + file { $monitoring_key: + require => File[$home_dir], + } -> + cast_builder::test_md5 { $monitoring_key: + md5 => $::md5_monitoring_key, + } -> + notify { 'correct_monitoring_key_file': + message => "Successfully tested file ${monitoring_key}", + } + + file { $swarming_key: + require => File[$home_dir], + } -> + cast_builder::test_md5 { $swarming_key: + md5 => $::md5_swarming_key, + } -> + notify { 'correct_swarming_key_file': + message => "Successfully tested file ${monitoring_key}", + } + + + # Install ADB and Fastboot + exec { 'download_adb': + cwd => $swarm_home_dir, + command => "/usr/bin/wget https://dl.google.com/android/repository/platform-tools-latest-linux.zip -O ${swarm_home_dir}/platform-tools-latest-linux.zip", + } -> + exec { 'extract_adb': + cwd => $swarm_home_dir, + command => "/usr/bin/unzip -o -q ${swarm_home_dir}/platform-tools-latest-linux.zip -d ${swarm_home_dir}/", + } -> + file { '/usr/local/sbin/adb': + ensure => file, + mode => '0755', + source => "${swarm_home_dir}/platform-tools/adb", + checksum => md5, + backup => false + } -> + file { '/usr/local/sbin/fastboot': + ensure => file, + mode => '0755', + source => "${swarm_home_dir}/platform-tools/fastboot", + checksum => md5 + } -> + file { "${swarm_home_dir}/platform-tools-latest-linux.zip": + ensure => absent, + } -> + file { "${swarm_home_dir}/platform-tools": + ensure => absent, + recurse => true, + purge => true, + force => true, + } + + # (TODO:kevinfei) remove deleted cron once change is rolled out 100% + file { $puppet_run_sh: + ensure => file, + content => template('cast_builder/swarm_puppet_run.sh.erb'), + } -> + file { $cipd_ensure_puppet: + content => "home_internal/swarm_puppet ${cipd_ref}", + } -> + cron { 'cipd_ensure_puppet': + ensure => absent, + # Ensure we always have a cron that downloads latest puppet scripts before + # actually executing them, so that hosts can self-update even if their + # current copy of puppet scripts are broken. + command => "${depot_tools_dir}/cipd ensure -ensure-file ${cipd_ensure_puppet} -root ${puppet_dir} -service-account-json ${cipd_key} && /usr/bin/apt-get update; /usr/bin/puppet apply --modulepath ${puppet_dir} ${puppet_manifest} --logdest syslog; ${monitoring_tool} --service_account_json ${monitoring_key} --puppet_run_exit_code \$?", + minute => '*/30', # every 30 mins + require => [ + Package['puppet'], + ], + environment => [ + 'PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin', + ], + } -> + cron { 'cipd_ensure_puppet_monitoring': + ensure => present, + # Ensure we always have a cron that downloads latest puppet scripts before + # actually executing them, so that hosts can self-update even if their + # current copy of puppet scripts are broken. + command => "/bin/bash ${puppet_run_sh}", + hour => '*/2', # every 2 hours + minute => fqdn_rand(60), + require => [ + Package['puppet'], + ], + environment => [ + 'PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin', + ], + } +}
diff --git a/catatester/puppet/cast_builder/manifests/swarm_init.pp b/catatester/puppet/cast_builder/manifests/swarm_init.pp new file mode 100644 index 0000000..c2fa507 --- /dev/null +++ b/catatester/puppet/cast_builder/manifests/swarm_init.pp
@@ -0,0 +1,140 @@ +# Puppet config for Swarming device-bot hosts for CI +# +# Instructions to bootstrap/change swarming bot hosts at: +# https://g3doc.corp.google.com/chrome/dongle/test/catatester/g3doc/dev/lab_host_changes.md + +class cast_builder::swarm_init($env = '', $cipd_env = 'live') { + + # Set up Puppet execution stages + stage { 'last': } + Stage['main'] -> Stage['last'] + + case $env { + + 'lab_host': { + $user = 'gtvchrome' + $group = 'gtvchrome' + $home_dir = "/home/${user}" + + class { 'cast_builder::swarm_host_base': + user => $user, + group => $group, + home_dir => $home_dir, + } -> + class { 'cast_builder::swarm_host_lab': + user => $user, + group => $group, + home_dir => $home_dir, + } -> + class { 'cast_builder::swarm_bot_home': + user => $user, + group => $group, + home_dir => $home_dir, + } + } + + 'gazoo_canary_host' : { + $user = 'gtvchrome' + $group = 'gtvchrome' + $home_dir = "/home/${user}" + + class { 'cast_builder::gazoo_host_base': + user => $user, + group => $group, + home_dir => $home_dir, + }-> + class { 'cast_builder::gazoo_host_lab': + user => $user, + group => $group, + home_dir => $home_dir, + ref_puppet => 'gazoo-staging', + } + } + 'gazoo_staging_host' : { + $user = 'gtvchrome' + $group = 'gtvchrome' + $home_dir = "/home/${user}" + + class { 'cast_builder::gazoo_host_base': + user => $user, + group => $group, + home_dir => $home_dir, + }-> + class { 'cast_builder::gazoo_host_lab': + user => $user, + group => $group, + home_dir => $home_dir, + ref_puppet => 'gazoo-staging', + } + } + 'gazoo_prod_host' : { + $user = 'gtvchrome' + $group = 'gtvchrome' + $home_dir = "/home/${user}" + + class { 'cast_builder::gazoo_host_base': + user => $user, + group => $group, + home_dir => $home_dir, + }-> + class { 'cast_builder::gazoo_host_lab': + user => $user, + group => $group, + home_dir => $home_dir, + ref_puppet => 'gazoo-prod', + } + } + 'gotham_host': { + $user = 'gtvchrome' + $group = 'gtvchrome' + $home_dir = "/home/${user}" + + class { 'cast_builder::swarm_host_base': + user => $user, + group => $group, + home_dir => $home_dir, + } -> + class { 'cast_builder::swarm_host_lab': + user => $user, + group => $group, + home_dir => $home_dir, + } -> + class { 'cast_builder::swarm_bot_gotham': + user => $user, + group => $group, + home_dir => $home_dir, + } + } + + 'corp_ganeti': { + $user = 'mosaic-role' + $group = 'mosaic-role' + $home_dir = "/usr/local/google/home/${user}" + + class { 'cast_builder::swarm_host_base': + user => $user, + group => $group, + home_dir => $home_dir, + } -> + class { 'cast_builder::swarm_host_ganeti': + user => $user, + home_dir => $home_dir, + } -> + class { 'cast_builder::swarm_bot_home': + user => $user, + group => $group, + home_dir => $home_dir, + } + + # Save last Puppet execution state after all other steps + # (only for goobuntu machines). + class { 'cast_builder::puppet_state': + stage => last, + } + } + + default: { + fail "unknown host environment ${env}" + } + } +}
diff --git a/catatester/puppet/cast_builder/manifests/test_md5.pp b/catatester/puppet/cast_builder/manifests/test_md5.pp new file mode 100644 index 0000000..ffa3caa --- /dev/null +++ b/catatester/puppet/cast_builder/manifests/test_md5.pp
@@ -0,0 +1,9 @@ +# Testing file with md5 hash +# Each unique content file could be tested once per manifest +define cast_builder::test_md5 ($md5, $path = $title) { + exec { "test_${path}": + path => '/bin:/usr/bin', + command => "md5sum ${path} | grep ${md5}", + user => root, + } +}
diff --git a/catatester/puppet/cast_builder/templates/ensure_eurtest_binaries.erb b/catatester/puppet/cast_builder/templates/ensure_eurtest_binaries.erb new file mode 100644 index 0000000..6117f27 --- /dev/null +++ b/catatester/puppet/cast_builder/templates/ensure_eurtest_binaries.erb
@@ -0,0 +1,4 @@ +home_internal/test_binaries <%= @cipd_ref %> +home_internal/tool_binaries <%= @cipd_ref %> +home_internal/virtual_home/cast_shell_emulator_launcher latest +home_internal/virtual_home/device_linker latest
diff --git a/catatester/puppet/cast_builder/templates/ensure_eurtest_binaries.sh.erb b/catatester/puppet/cast_builder/templates/ensure_eurtest_binaries.sh.erb new file mode 100644 index 0000000..7559817 --- /dev/null +++ b/catatester/puppet/cast_builder/templates/ensure_eurtest_binaries.sh.erb
@@ -0,0 +1,8 @@ +#!/bin/bash + +if pidof -x -o %PPID "cipd_ensure_eurtest_binaries.sh"; then + echo "Eurtest binaries download already running. Skipping this run." + exit 0 +fi + +<%= @depot_tools_dir %>/cipd ensure -ensure-file <%= @cipd_ensure_eurtest_binaries %> -root <%= @eurtest_binaries %> -service-account-json <%= @cipd_key %>
diff --git a/catatester/puppet/cast_builder/templates/swarm_bot.systemd.erb b/catatester/puppet/cast_builder/templates/swarm_bot.systemd.erb new file mode 100644 index 0000000..ac3f5f6 --- /dev/null +++ b/catatester/puppet/cast_builder/templates/swarm_bot.systemd.erb
@@ -0,0 +1,17 @@ +[Unit] +Description=Startup swarming bot <%= @prefix %><%= @bot_id %>. + +[Service] +User=<%= @user %> +Group=<%= @group %> + +Environment=BOTO_CONFIG=<%= @gsutil_boto %> +Environment=GOOGLE_APPLICATION_CREDENTIALS=<%= @fragglerock_key %> +Environment=PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:<%= @gsutil_dir %> +Environment=SWARMING_BOT_ID=<%= @trusted['hostname'] %>-<%= @bot_id %> + +# Source: cs.corp.google.com/piper///depot/google3/third_party/luci_py/latest/appengine/swarming/swarming_bot/__main__.py +ExecStart=/usr/bin/env python <%= @swarm_bots_home %>/<%= @bot_id %>/bot_root/swarming_bot.zip start_bot + +[Install] +WantedBy=multi-user.target
diff --git a/catatester/puppet/cast_builder/templates/swarm_puppet_run.sh.erb b/catatester/puppet/cast_builder/templates/swarm_puppet_run.sh.erb new file mode 100644 index 0000000..85feb6b --- /dev/null +++ b/catatester/puppet/cast_builder/templates/swarm_puppet_run.sh.erb
@@ -0,0 +1,14 @@ +#!/bin/bash + +if pidof -x -o %PPID "swarm_puppet_run.sh"; then + echo "Puppet run is still in progress. Skipping this run." + exit 0 +fi + +START=$(date -d now +%s) +<%= @depot_tools_dir %>/cipd ensure -ensure-file <%= @cipd_ensure_puppet %> -root <%= @puppet_dir %> -service-account-json <%= @swarming_key %> && /usr/bin/apt-get update; /usr/bin/puppet apply --modulepath <%= @puppet_dir %> <%= @puppet_manifest %> +END=$(date -d now +%s) +logger PUPPET_RUN_TIME_IN_MINUTES $(( (END - START) / 60 )) +if (( (END - START) / 60 >= 20 )); + then logger PUPPET_RUN_TOO_LONG_WARNING; +fi
diff --git a/catatester/puppet_cipd_pkg.yaml b/catatester/puppet_cipd_pkg.yaml new file mode 100644 index 0000000..5491b95 --- /dev/null +++ b/catatester/puppet_cipd_pkg.yaml
@@ -0,0 +1,17 @@ +package: home_internal/swarm_puppet +description: puppet manifests and modules for swarm packaged in cipd +root: puppet +data: + - file: cast_builder/files/swarm/lab_nodes/site.pp + - file: cast_builder/lib/facter/devices.rb + - file: cast_builder/manifests/swarm_bot_gotham.pp + - file: cast_builder/manifests/swarm_bot_home.pp + - file: cast_builder/manifests/swarm_host_base.pp + - file: cast_builder/manifests/swarm_host_ganeti.pp + - file: cast_builder/manifests/swarm_host_lab.pp + - file: cast_builder/manifests/swarm_init.pp + - file: cast_builder/manifests/test_md5.pp + - file: cast_builder/templates/ensure_eurtest_binaries.erb + - file: cast_builder/templates/ensure_eurtest_binaries.sh.erb + - file: cast_builder/templates/swarm_bot.systemd.erb + - file: cast_builder/templates/swarm_puppet_run.sh.erb
diff --git a/catatester/scripts/collectd.conf.template b/catatester/scripts/collectd.conf.template new file mode 100755 index 0000000..c437594 --- /dev/null +++ b/catatester/scripts/collectd.conf.template
@@ -0,0 +1,134 @@ +Interval 60 + +# Explicitly set hostname to "" to indicate the default resource. +Hostname {{ fqdn }} + +# The Stackdriver agent does not use fully qualified domain names. +FQDNLookup false + +LoadPlugin syslog +<Plugin "syslog"> + LogLevel "info" +</Plugin> +# if you uncomment this, you will get collectd logs separate from syslog +#LoadPlugin logfile +#<Plugin "logfile"> +# LogLevel "info" +# File "/var/log/collectd.log" +# Timestamp true +#</Plugin> + +# LoadPlugin docker +LoadPlugin df +<Plugin "df"> + FSType "devfs" + IgnoreSelected true + ReportByDevice true + ValuesPercentage true +</Plugin> + +LoadPlugin cpu +<Plugin "cpu"> + ValuesPercentage true + ReportByCpu false +</Plugin> +LoadPlugin swap +<Plugin "swap"> + ValuesPercentage true +</Plugin> +LoadPlugin interface +LoadPlugin disk +LoadPlugin load +LoadPlugin memory +<Plugin "memory"> + ValuesPercentage true +</Plugin> +LoadPlugin processes +LoadPlugin tcpconns +LoadPlugin write_gcm +LoadPlugin match_regex +LoadPlugin match_throttle_metadata_keys +LoadPlugin stackdriver_agent + +<Plugin "processes"> + ProcessMatch "all" ".*" + Detail "ps_cputime" + Detail "ps_disk_octets" + Detail "ps_rss" + Detail "ps_vm" +</Plugin> + +<Plugin "disk"> + # No config - collectd fails parsing configuration if tag is empty. +</Plugin> + +<Plugin "tcpconns"> + AllPortsSummary true +</Plugin> + +LoadPlugin exec +# Monitor the Stackdriver Logging agent. This should fail gracefully if for any +# reason the metrics endpoint for the Logging agent isn't reachable. +<Plugin "exec"> + # The script doesn't need any privileges, so run as 'nobody'. + Exec "nobody" "/opt/stackdriver/collectd/bin/stackdriver-read_agent_logging" "http://localhost:24231/metrics" +</Plugin> + +LoadPlugin aggregation +LoadPlugin "match_regex" +<Plugin "memory"> + ValuesPercentage true +</Plugin> + +<Plugin "write_gcm"> + CloudProvider "gcp" + Instance {{ hostname }} + Project {{ project_name }} + Zone {{ zone_name }} + PrettyPrintJSON false + # EnableMetadataAgent true +</Plugin> + +PostCacheChain "PostCache" +<Chain "PostCache"> + <Rule "processes"> + <Match "regex"> + Plugin "^processes$" + Type "^(ps_cputime|disk_octets|ps_rss|ps_vm)$" + </Match> + <Target "jump"> + Chain "MaybeThrottleProcesses" + </Target> + Target "stop" + </Rule> + + <Rule "otherwise"> + <Match "throttle_metadata_keys"> + OKToThrottle false + </Match> + <Target "write"> + Plugin "write_gcm" + </Target> + </Rule> +</Chain> + +<Chain "MaybeThrottleProcesses"> + <Rule "default"> + <Match "throttle_metadata_keys"> + OKToThrottle true + TrackedMetadata "processes:pid" + TrackedMetadata "processes:command" + TrackedMetadata "processes:command_line" + TrackedMetadata "processes:owner" + </Match> + <Target "write"> + Plugin "write_gcm" + </Target> + </Rule> +</Chain> + +# if you have other config, especially for plugins, you can drop them +# into this directory +Include "/opt/stackdriver/collectd/etc/collectd.d" +Include "/etc/stackdriver/collectd.d" +
diff --git a/catatester/scripts/generate_monitoring_configs.py b/catatester/scripts/generate_monitoring_configs.py new file mode 100755 index 0000000..5e88028 --- /dev/null +++ b/catatester/scripts/generate_monitoring_configs.py
@@ -0,0 +1,127 @@ +"""Generates collectd and fluentd config from template.""" +import argparse +import logging +import os +import socket +import subprocess + +import jinja2 + + +_DEFAULT_PROJECT_ID = 'google.com:fragglerock' +_DEFAULT_ZONE_NAME = 'us-central1-c' +_UNINITIALIZED = 'uninitialized' + + +def _GetHostName(): + """Returns local machine's host name.""" + return socket.gethostname().split('.')[0] + + +def _GetFqdn(): + """Returns local machine's FQDN.""" + return socket.getfqdn() + + +def _GetIpAddress(): + """Returns IP address of the given interface.""" + output = subprocess.check_output(['hostname', '-i']) + return output.strip() + + +def ParseCmdOptions(): + """Parses command inputs.""" + parser = argparse.ArgumentParser( + description='Generates collectd and fluentd config.') + parser.add_argument('--hostname', help='Host name') + parser.add_argument('--fqdn', help='Host FQDN') + parser.add_argument('--ip', help='IPv4 address') + parser.add_argument( + '--project_id', help='Project ID, e.g. google.com:fragglerock') + parser.add_argument( + '--zone_name', help='Instance zone name, e.g. asia-east1-a') + parser.add_argument( + '--template_dir', help='Directory containing the templates.') + parser.add_argument( + '--debug', + action='store_true', + default=False, + help='Print extra debug information.') + + args = parser.parse_args() + if args.debug: + logging.basicConfig(level=logging.DEBUG) + else: + logging.basicConfig(level=logging.INFO) + + if not args.hostname or args.hostname == _UNINITIALIZED: + args.hostname = _GetHostName() + if not args.fqdn or args.fqdn == _UNINITIALIZED: + args.fqdn = _GetFqdn() + if not args.ip or args.ip == _UNINITIALIZED: + args.ip = _GetIpAddress() + if not args.project_id or args.project_id == _UNINITIALIZED: + args.project_id = _DEFAULT_PROJECT_ID + if not args.zone_name or args.zone_name == _UNINITIALIZED: + args.zone_name = _DEFAULT_ZONE_NAME + if not args.template_dir or not os.path.isdir(args.template_dir): + args.template_dir = os.path.dirname(__file__) + + return args + + +def _GenerateCollectdConfig(flags): + """Outputs collectd.conf. + + Args: + flags: argparse.Namespace instance containing config information. + """ + template_path = os.path.join(flags.template_dir, 'collectd.conf.template') + output_path = os.path.join(flags.template_dir, 'collectd.conf') + with open(template_path) as fn: + tm = jinja2.Template(fn.read()) + # Values demand double-quotes + conf = tm.render( + hostname='\"' + flags.hostname + '\"', + fqdn='\"' + flags.fqdn + '\"', + project_name='\"' + flags.project_id + '\"', + zone_name='\"' + flags.zone_name + '\"') + with open(output_path, 'w') as output: + output.write(conf) + + +def _GenerateFluentdConfig(flags): + """Outputs google-fluentd.conf. + + Args: + flags: argparse.Namespace instance containing config information. + """ + template_path = os.path.join(flags.template_dir, + 'google-fluentd.conf.template') + output_path = os.path.join(flags.template_dir, + 'google-fluentd.conf') + with open(template_path) as fn: + tm = jinja2.Template(fn.read()) + # Values demand double-quotes + conf = tm.render( + hostname=flags.hostname, + fqdn=flags.fqdn, + project_id=flags.project_id, + zone_name=flags.zone_name) + with open(output_path, 'w') as output: + output.write(conf) + + +def main(): + """Generates collectd and fluentd config from template.""" + flags = ParseCmdOptions() + logging.debug('hostname: %s', flags.hostname) + logging.debug('fqdn: %s', flags.fqdn) + logging.debug('project: %s', flags.project_id) + logging.debug('zone: %s', flags.zone_name) + _GenerateCollectdConfig(flags) + _GenerateFluentdConfig(flags) + + +if __name__ == '__main__': + main()
diff --git a/catatester/scripts/google-fluentd.conf.template b/catatester/scripts/google-fluentd.conf.template new file mode 100755 index 0000000..c5eaaf2 --- /dev/null +++ b/catatester/scripts/google-fluentd.conf.template
@@ -0,0 +1,64 @@ +# Master configuration file for google-fluentd + +# Include any configuration files in the config.d directory. +# +# An example "catch-all" configuration can be found at +# https://github.com/GoogleCloudPlatform/fluentd-catch-all-config +@include config.d/*.conf + +# Prometheus monitoring. +<source> + @type prometheus + port 24231 +</source> +<source> + @type prometheus_monitor +</source> + +# Do not collect fluentd's own logs to avoid infinite loops. +<match fluent.**> + @type null +</match> + +# Add a unique insertId to each log entry that doesn't already have it. +# This helps guarantee the order and prevent log duplication. +<filter **> + @type add_insert_ids +</filter> + +# Configure all sources to output to Google Cloud Logging +<match **> + @type google_cloud + # Set the chunk limit conservatively to avoid exceeding the recommended + # chunk size of 5MB per write request. + buffer_chunk_limit 1M + # Flush logs every 5 seconds, even if the buffer is not full. + flush_interval 5s + # Enforce some limit on the number of retries. + disable_retry_limit false + # After 3 retries, a given chunk will be discarded. + retry_limit 3 + # Wait 10 seconds before the first retry. The wait interval will be doubled on + # each following retry (20s, 40s...) until it hits the retry limit. + retry_wait 10 + # Never wait longer than 5 minutes between retries. If the wait interval + # reaches this limit, the exponentiation stops. + # Given the default config, this limit should never be reached, but if + # retry_limit and retry_wait are customized, this limit might take effect. + max_retry_wait 300 + # Use multiple threads for processing. + num_threads 8 + # Use the gRPC transport. + use_grpc true + # If a request is a mix of valid log entries and invalid ones, ingest the + # valid ones and drop the invalid ones instead of dropping everything. + partial_success true + # Enable monitoring via Prometheus integration. + enable_monitoring true + monitoring_type prometheus + project_id {{ project_id }} + vm_id {{ fqdn }} + vm_name {{ hostname }} + zone {{ zone_name }} +</match> +
diff --git a/catatester/scripts/install_stackdriver_agent.sh b/catatester/scripts/install_stackdriver_agent.sh new file mode 100755 index 0000000..b7f215b --- /dev/null +++ b/catatester/scripts/install_stackdriver_agent.sh
@@ -0,0 +1,78 @@ +#!/bin/bash +# +# Script to install Cloud Monitoring and Logging Agent on lab host. +# +# Assumptions: +# The Cloud Project service account key file ($HOME/luci/swarming-key.json) +# is available. This is used to upload metrics and logs to the Cloud Project. +# +# Prerequisites: +# All companion python modules are copied to same directory. + +set -e + +function print_help { + echo -e " + Usage: $0 -n <hostname> -f <fqdn> -p <project_id> -z <zone_name> + Available options: + \t-n\thostname + \t-f\tfully qualified domain name + \t-p\tproject id + \t-z\tzone name + \t-?,-h\tHelp + " +} + +hostname="uninitialized" +fqdn="uninitialized" +ip="uninitialized" +project_id="uninitialized" +zone_name="uninitialized" + +while getopts "?h:n:f:i:p:z:" opt +do + case $opt in + n) hostname=$OPTARG;; + f) fqdn=$OPTARG;; + i) ip=$OPTARG;; + p) project_id=$OPTARG;; + z) zone_name=$OPTARG;; + ?|h) print_help; exit 1;; + esac +done +shift $((OPTIND-1)) + +root_dir="$( cd "$(dirname "$0")" ; pwd -P )" +config_transformer="$root_dir/generate_monitoring_configs.py" + +# Install jinja2 +pip install jinja2 + +# Set up GCP service account credential +echo "Setting up GCP credentials - started" +APPLICATION_DEFAULT_CREDS="/etc/google/auth/application_default_credentials.json" +sudo mkdir -p /etc/google/auth +sudo cp "$HOME/luci/swarming-key.json" "$APPLICATION_DEFAULT_CREDS" +sudo chown root:root "$APPLICATION_DEFAULT_CREDS" +sudo chmod 0400 "$APPLICATION_DEFAULT_CREDS" +echo "Setting up GCP credentials - success" + +# Install Monitoring Agent +echo "Installing monitoring agent - started" +cd $HOME +curl -sSO https://dl.google.com/cloudagents/install-monitoring-agent.sh +sudo env REPO_SUFFIX=unstable bash install-monitoring-agent.sh +echo "installing monitoring agent - success" + +# Install Logging Agent +echo "Installing logging agent - started" +cd $HOME +curl -sSO https://dl.google.com/cloudagents/install-logging-agent.sh +sudo env REPO_SUFFIX=unstable bash install-logging-agent.sh +echo "Installing logging agent - success" + +/usr/bin/python $config_transformer --debug --hostname $hostname --fqdn $fqdn --ip $ip --project_id $project_id --zone_name $zone_name +sudo cp $root_dir/collectd.conf /etc/stackdriver/collectd.conf +sudo cp $root_dir/google-fluentd.conf /etc/google-fluentd/google-fluentd.conf +sudo service stackdriver-agent restart +sudo service google-fluentd restart
diff --git a/catatester/scripts/setup_swarm_host.sh b/catatester/scripts/setup_swarm_host.sh new file mode 100755 index 0000000..5cdebe8 --- /dev/null +++ b/catatester/scripts/setup_swarm_host.sh
@@ -0,0 +1,46 @@ +#!/bin/bash +# +# Script to setup a host for running in Home Swarming CI. +# +# Prereqs: +# this script and its dependencies are scp'd to the swarm lab host via: +# $ scp /google/data/ro/teams/cast-test/swarming/* gtvchrome@<lab-host-ip>:/home/gtvchrome/ +# (gtvchrome password in valentine) +# all of these shell scripts have chmod +x on the lab host: chmod +x *.sh +# you're ssh'd into the lab host and ready to run this script on it +# +# Usage: +# ./setup_swarm_host.sh + +# stop any bots that might be running already +for abspath in /etc/init/swarming*.conf; do + filename=$(basename "$abspath") + botname="${filename%.*}" + sudo stop "$botname" +done + +# our puppet config requires at least 1 bot dir set up already +echo -e "Visit the following URL to get the latest token code and copy-paste it below.\n" +echo -e "https://cast-swarming.appspot.com\n" +read -p "Token Code: " token +SWARM_HOME=~/swarm_home +if [ ! -d "$SWARM_HOME" ]; then + mkdir $SWARM_HOME +fi +cd $SWARM_HOME +rm -rf bots ; mkdir -p bots/1 ; cd bots/1 +curl -sSLOJ https://cast-swarming.appspot.com/bot_code?tok=$token + +# Fetch a temporary copy of our puppet configs from cipd and run it. +# The puppet config will set up a permanent puppet config dir and keep it up-to-date with cron. +source $HOME/install_cipd.sh $HOME/depot_tools/ + +# Init masterless puppet config only on gtvchrome lab hosts. +# Ganeti hosts are configured via ENC puppet (mosaic-role user, not gtvchrome) +if [[ "$PWD" =~ gtvchrome ]]; then + rm -rf /tmp/puppet; mkdir /tmp/puppet; cd /tmp/puppet + cipd install home_internal/swarm_puppet staging -service-account-json ~/luci/swarming-key.json + + sudo apt-get install --yes puppet + sudo /usr/bin/puppet apply --modulepath ./ ./cast_builder/files/swarm/lab_nodes/site.pp +fi
diff --git a/configs/pre-commit/confidential-terms.txt b/configs/pre-commit/confidential-terms.txt new file mode 100644 index 0000000..4a2e35c --- /dev/null +++ b/configs/pre-commit/confidential-terms.txt
@@ -0,0 +1,9 @@ +prince +gfiber +marvell +mstar +mediatek +jbl +sigma +vizio +amlogic
diff --git a/configs/pre-commit/cppcheck/cppcheck.cfg b/configs/pre-commit/cppcheck/cppcheck.cfg new file mode 100644 index 0000000..9027845 --- /dev/null +++ b/configs/pre-commit/cppcheck/cppcheck.cfg
@@ -0,0 +1,8 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- when cppcheck 1.82 is introduced, it is identified putting second macro with in the same named namespace causes problem. b/127266463. This customize cfg file is to work around this problem. Further details please see http://cppcheck.sourceforge.net/manual.pdf Chapter 10. --> + +<def version="2"> + <define name="TEST_F" value=""/> + <define name="MATCHER_P2" value=""/> + <define name="MATCHER_P" value=""/> +</def>
diff --git a/configs/pre-commit/requirements.in b/configs/pre-commit/requirements.in new file mode 100644 index 0000000..917f9d4 --- /dev/null +++ b/configs/pre-commit/requirements.in
@@ -0,0 +1 @@ +pre-commit==2.12.0
diff --git a/configs/pre-commit/requirements.txt b/configs/pre-commit/requirements.txt new file mode 100644 index 0000000..450fa14 --- /dev/null +++ b/configs/pre-commit/requirements.txt
@@ -0,0 +1,28 @@ +# +# This file is autogenerated by pip-compile +# To update, run: +# +# pip-compile requirements.in +# +appdirs==1.4.4 + # via virtualenv +cfgv==3.2.0 + # via pre-commit +distlib==0.3.1 + # via virtualenv +filelock==3.0.12 + # via virtualenv +identify==2.2.2 + # via pre-commit +nodeenv==1.5.0 + # via pre-commit +pre-commit==2.12.0 + # via -r requirements.in +pyyaml==5.4.1 + # via pre-commit +six==1.15.0 + # via virtualenv +toml==0.10.2 + # via pre-commit +virtualenv==20.4.3 + # via pre-commit
diff --git a/cq/__init__.py b/cq/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/cq/__init__.py
diff --git a/cq/appengine/Makefile b/cq/appengine/Makefile new file mode 100644 index 0000000..63ccf2f --- /dev/null +++ b/cq/appengine/Makefile
@@ -0,0 +1,21 @@ +# Makefile to update protobuf objects +# +# Every time the protos are updated, just run: +# $ make + +CWD=$(shell pwd) + +PROTOFOLDER=$(CWD)/proto +OUTPUT_FOLDER=$(CWD)/genfiles + +.PHONY: proto + +all: proto + +gen_proto: + protoc -I$(PROTOFOLDER) --python_out=$(OUTPUT_FOLDER) $(PROTOFOLDER)/*.proto + +gen_init: + touch $(OUTPUT_FOLDER)/__init__.py + +proto: gen_proto gen_init
diff --git a/cq/appengine/README.md b/cq/appengine/README.md new file mode 100644 index 0000000..103d43a --- /dev/null +++ b/cq/appengine/README.md
@@ -0,0 +1,19 @@ +# Updating the protos + +Just run `make` and the generated protos will be updated. + +If the protoc compiler is confused by the map type, you are probably +running version of protoc < v3.0. You can check with `protoc --version`. See +below for updating your protoc version. + +# Installing protoc v3 compiler + +Grab protoc-3.2.0-linux-x86_64.zip release from +https://github.com/google/protobuf/releases/tag/v3.2.0 + +Newer releases of protoc are not compatible with the current version of protobuf python package +installed in requirements.txt at the time of this writing. + +Extract `bin/protoc` from the release and copy it into /usr/bin/protoc. Give it execute permissions. + +Check the new version with `protoc --version`.
diff --git a/cq/appengine/__init__.py b/cq/appengine/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/cq/appengine/__init__.py
diff --git a/cq/appengine/config_test.py b/cq/appengine/config_test.py new file mode 100644 index 0000000..726de1a --- /dev/null +++ b/cq/appengine/config_test.py
@@ -0,0 +1,162 @@ +"""Tests for config.""" + +import os +import sys +import unittest + +# Allow imports to be rooted in continuous-tests/ folder +sys.path.insert( + 0, + os.path.realpath( + os.path.join(os.path.dirname(__file__), os.pardir, os.pardir))) + +# pylint: disable=wrong-import-position +from cq.appengine.genfiles import build_config_pb2 + +import google.protobuf.text_format + +_BUILD_RULES_RELPATH = 'configs/{env}/build_rules.protoascii' +_BUILD_DETAILS_RELPATH = 'configs/{env}/build_details.protoascii' + + +def GetBuildRules(build_config_env): + """Returns the BuildRules proto.""" + build_rules = build_config_pb2.BuildRules() + build_rules_path = os.path.join( + os.path.dirname(__file__), + _BUILD_RULES_RELPATH.format(env=build_config_env)) + with open(build_rules_path) as f: + google.protobuf.text_format.Merge(f.read(), build_rules) + return build_rules + + +def GetBuildDetails(build_config_env): + """Returns the BuildDetails proto.""" + build_details = build_config_pb2.BuildDetails() + build_details_path = os.path.join( + os.path.dirname(__file__), + _BUILD_DETAILS_RELPATH.format(env=build_config_env)) + with open(build_details_path) as f: + google.protobuf.text_format.Merge(f.read(), build_details) + return build_details + +# Use a wrapping class so the test runner does not mistakenly try to run +# tests on ConfigTest, which is not a fully-implemented test class +class BaseTestCases: + class ConfigTest(unittest.TestCase): + """A class to test a build config. + + Note: The |self.env| property is initialized externally to this class. This + class will be setup twice, once with the staging config and once with the + prod config. + """ + env = None + + @property + def build_rules_proto(self): + return GetBuildRules(self.env) + + @property + def build_details_proto(self): + return GetBuildDetails(self.env) + + def testParseBuildRules(self): + """Tests the build_rules config is a valid proto.""" + self.assertTrue(self.build_rules_proto) + + def testParseBuildDetails(self): + """Tests the build_details config is a valid proto.""" + self.assertTrue(self.build_details_proto) + + def testOnlySupportedGobHosts(self): + """Tests that only supported gob_hosts are used.""" + supported_hosts = { + 'caraway-internal', + 'chrome-internal', + 'eureka-internal', + 'eureka-partner', + 'eureka-staging-internal', + 'libassistant-internal', + 'nest-camera-internal', + 'nest-internal', + 'team', + } + for rule in self.build_rules_proto.build_rules: + self.assertIn(rule.gob_host, supported_hosts) + + def testEveryBuildRuleHasAMatchingBuildDetail(self): + """Test that every build in a build_rule has a matching build_detail.""" + + referenced_builds = set() + for rule in self.build_rules_proto.build_rules: + referenced_builds.update(rule.builds) + referenced_builds.update(rule.presubmit_builds) + for build_set in rule.build_sets: + referenced_builds.update( + self.build_rules_proto.build_sets[build_set].builds) + + build_detail_builds = set() + for build_name in self.build_details_proto.build_details: + build_detail_builds.add(build_name) + + # Note that it is acceptable for there to be extra build_details, since + # that is how a build is enabled for manually scheduling. + missing_build_details = referenced_builds - build_detail_builds + self.assertFalse(missing_build_details) + + def testScheduleValid(self): + for build, detail in self.build_details_proto.build_details.items(): + if detail.schedule.min_branch and detail.schedule.max_branch: + self.assertLess( + detail.schedule.min_branch, detail.schedule.max_branch, + 'Branch range ({} < {}) for {} is invalid'.format( + detail.schedule.min_branch, detail.schedule.max_branch, build + ) + ) + if detail.schedule.master_only and detail.schedule.release_only: + raise AssertionError( + 'Can only set master only or release only for {}'.format(build) + ) + + def testHasRequiredFields(self): + for name, detail in self.build_details_proto.build_details.items(): + self.assertTrue( + detail.HasField('config'), + f'{name} must have oneof field config set.') + which_config = detail.WhichOneof('config') + if which_config == 'device_tests': + self.assertGreater( + len(detail.device_tests.test_groups), + 0, + f'{name} must have at least one test_group') + self.assertTrue( + detail.device_tests.HasField('depends_on'), + f'{name} must have a depends_on set') + self.assertGreater( + len(detail.device_tests.depends_on), + 0, + f'{name} must have a non-empty depends_on') + elif which_config == 'cast_build': + self.assertTrue( + detail.cast_build.HasField('recipe'), + f'{name} must have a recipe set') + self.assertGreater( + len(detail.cast_build.recipe), + 0, + f'{name} must have a non-empty recipe') + elif which_config == 'jenkins_job': + self.assertTrue( + detail.jenkins_job.HasField('job_name'), + f'{name} must have a job_name set') + self.assertGreater( + len(detail.jenkins_job.job_name), + 0, + f'{name} must have a non-empty job_name') + + +class ProdConfigTest(BaseTestCases.ConfigTest): + env = "prod" + + +if __name__ == '__main__': + unittest.main()
diff --git a/cq/appengine/configs/prod/build_details.protoascii b/cq/appengine/configs/prod/build_details.protoascii new file mode 100644 index 0000000..107edbf --- /dev/null +++ b/cq/appengine/configs/prod/build_details.protoascii
@@ -0,0 +1,29 @@ +# +# ██████████ +# ████ ████ +# ██ ▒▒▒▒▒▒ ██ +# ██ ▒▒▒▒▒▒▒▒▒▒ ██ +# ██ ▒▒▒▒▒▒▒▒▒▒ ██ +# ██▒▒ ▒▒▒▒▒▒▒▒▒▒ ▒▒██ +# ██▒▒▒▒ ▒▒▒▒▒▒ ▒▒▒▒██ +# ██▒▒▒▒ ▒▒▒▒██ +# ██▒▒ ████████ ▒▒▒▒██ +# ██ ██████░░░░██████ ▒▒██ +# ██ ██░░░░██░░░░██░░░░██ ██ +# ████░░░░██░░░░██░░░░░░██ ██ +# ██░░░░░░░░░░░░░░░░░░██ ██ +# ██░░░░████████░░░░░░████ +# ██░░░░░░░░░░░░░░████ +# ████████████████████ +# ████▓▓██░░░░██▓▓██░░░░██ +# ██░░██▓▓██░░░░██▓▓▓▓██░░░░██ +# ██░░██▓▓██░░░░░░██▓▓▓▓██░░░░██ +# ██░░██▓▓██████████▓▓▓▓▓▓██░░░░██ +# ██░░██▓▓██ ██▓▓▓▓██░░░░██ +# ██████ ██ ██████████ +# ██ ██ ██ +# ██▓▓▓▓▓▓████▓▓▓▓██████ +# ██▓▓▓▓▓▓▓▓██▓▓▓▓▓▓▓▓▓▓██ +# ████████████████████████ +# +# Sorry, config is in another castle. go/cast-config-migration
diff --git a/cq/appengine/configs/prod/build_rules.protoascii b/cq/appengine/configs/prod/build_rules.protoascii new file mode 100644 index 0000000..107edbf --- /dev/null +++ b/cq/appengine/configs/prod/build_rules.protoascii
@@ -0,0 +1,29 @@ +# +# ██████████ +# ████ ████ +# ██ ▒▒▒▒▒▒ ██ +# ██ ▒▒▒▒▒▒▒▒▒▒ ██ +# ██ ▒▒▒▒▒▒▒▒▒▒ ██ +# ██▒▒ ▒▒▒▒▒▒▒▒▒▒ ▒▒██ +# ██▒▒▒▒ ▒▒▒▒▒▒ ▒▒▒▒██ +# ██▒▒▒▒ ▒▒▒▒██ +# ██▒▒ ████████ ▒▒▒▒██ +# ██ ██████░░░░██████ ▒▒██ +# ██ ██░░░░██░░░░██░░░░██ ██ +# ████░░░░██░░░░██░░░░░░██ ██ +# ██░░░░░░░░░░░░░░░░░░██ ██ +# ██░░░░████████░░░░░░████ +# ██░░░░░░░░░░░░░░████ +# ████████████████████ +# ████▓▓██░░░░██▓▓██░░░░██ +# ██░░██▓▓██░░░░██▓▓▓▓██░░░░██ +# ██░░██▓▓██░░░░░░██▓▓▓▓██░░░░██ +# ██░░██▓▓██████████▓▓▓▓▓▓██░░░░██ +# ██░░██▓▓██ ██▓▓▓▓██░░░░██ +# ██████ ██ ██████████ +# ██ ██ ██ +# ██▓▓▓▓▓▓████▓▓▓▓██████ +# ██▓▓▓▓▓▓▓▓██▓▓▓▓▓▓▓▓▓▓██ +# ████████████████████████ +# +# Sorry, config is in another castle. go/cast-config-migration
diff --git a/cq/appengine/genfiles/__init__.py b/cq/appengine/genfiles/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/cq/appengine/genfiles/__init__.py
diff --git a/cq/appengine/genfiles/build_config_pb2.py b/cq/appengine/genfiles/build_config_pb2.py new file mode 100644 index 0000000..d0776cc --- /dev/null +++ b/cq/appengine/genfiles/build_config_pb2.py
@@ -0,0 +1,736 @@ +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: build_config.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='build_config.proto', + package='build_config', + syntax='proto2', + serialized_pb=_b('\n\x12\x62uild_config.proto\x12\x0c\x62uild_config\"\xbd\x02\n\tBuildRule\x12\x10\n\x08gob_host\x18\x01 \x01(\t\x12\x0e\n\x06\x62ranch\x18\x03 \x01(\t\x12\x0f\n\x07project\x18\x04 \x01(\t\x12\x18\n\x10presubmit_builds\x18\x05 \x03(\t\x12\x0e\n\x06\x62uilds\x18\x06 \x03(\t\x12\x12\n\nbuild_sets\x18\x07 \x03(\t\x12J\n\x12property_overrides\x18\x08 \x03(\x0b\x32..build_config.BuildRule.PropertyOverridesEntry\x12\x16\n\x0e\x66ile_whitelist\x18\t \x03(\t\x1aU\n\x16PropertyOverridesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12*\n\x05value\x18\x02 \x01(\x0b\x32\x1b.build_config.PropertyValue:\x02\x38\x01J\x04\x08\x02\x10\x03\":\n\rPropertyValue\x12\x10\n\x06string\x18\x01 \x01(\tH\x00\x12\x0e\n\x04\x62ool\x18\x02 \x01(\x08H\x00\x42\x07\n\x05value\"\x1a\n\x08\x42uildSet\x12\x0e\n\x06\x62uilds\x18\x01 \x03(\t\"\xc1\x01\n\nBuildRules\x12,\n\x0b\x62uild_rules\x18\x01 \x03(\x0b\x32\x17.build_config.BuildRule\x12;\n\nbuild_sets\x18\x02 \x03(\x0b\x32\'.build_config.BuildRules.BuildSetsEntry\x1aH\n\x0e\x42uildSetsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12%\n\x05value\x18\x02 \x01(\x0b\x32\x16.build_config.BuildSet:\x02\x38\x01\"\x1e\n\nJenkinsJob\x12\x10\n\x08job_name\x18\x01 \x01(\t\"1\n\tCastBuild\x12\x0e\n\x06recipe\x18\x01 \x01(\t\x12\x14\n\x0c\x62uilder_name\x18\x02 \x01(\t\"\xd3\x04\n\x0b\x42uildDetail\x12\x16\n\x08required\x18\x01 \x01(\x08:\x04true\x12\x19\n\x11\x64isabled_branches\x18\x03 \x03(\t\x12L\n\x12property_overrides\x18\x05 \x03(\x0b\x32\x30.build_config.BuildDetail.PropertyOverridesEntry\x12?\n\x08schedule\x18\x07 \x01(\x0b\x32-.build_config.BuildDetail.ScheduleRestriction\x12\r\n\x05owner\x18\x0c \x01(\t\x12-\n\ncast_build\x18\x10 \x01(\x0b\x32\x17.build_config.CastBuildH\x00\x12/\n\x0bjenkins_job\x18\x11 \x01(\x0b\x32\x18.build_config.JenkinsJobH\x00\x1aU\n\x16PropertyOverridesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12*\n\x05value\x18\x02 \x01(\x0b\x32\x1b.build_config.PropertyValue:\x02\x38\x01\x1av\n\x13ScheduleRestriction\x12\x12\n\nmin_branch\x18\x01 \x01(\t\x12\x12\n\nmax_branch\x18\x02 \x01(\t\x12\x1b\n\x0crelease_only\x18\x03 \x01(\x08:\x05\x66\x61lse\x12\x1a\n\x0bmaster_only\x18\x04 \x01(\x08:\x05\x66\x61lseB\x08\n\x06\x63onfigJ\x04\x08\x02\x10\x03J\x04\x08\x04\x10\x05J\x04\x08\x06\x10\x07J\x04\x08\x08\x10\tJ\x04\x08\t\x10\nJ\x04\x08\n\x10\x0bJ\x04\x08\x0b\x10\x0cJ\x04\x08\r\x10\x0eJ\x04\x08\x0e\x10\x0fJ\x04\x08\x0f\x10\x10\"\xa3\x01\n\x0c\x42uildDetails\x12\x43\n\rbuild_details\x18\x01 \x03(\x0b\x32,.build_config.BuildDetails.BuildDetailsEntry\x1aN\n\x11\x42uildDetailsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12(\n\x05value\x18\x02 \x01(\x0b\x32\x19.build_config.BuildDetail:\x02\x38\x01') +) +_sym_db.RegisterFileDescriptor(DESCRIPTOR) + + + + +_BUILDRULE_PROPERTYOVERRIDESENTRY = _descriptor.Descriptor( + name='PropertyOverridesEntry', + full_name='build_config.BuildRule.PropertyOverridesEntry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='build_config.BuildRule.PropertyOverridesEntry.key', 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), + _descriptor.FieldDescriptor( + name='value', full_name='build_config.BuildRule.PropertyOverridesEntry.value', index=1, + number=2, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + options=_descriptor._ParseOptions(descriptor_pb2.MessageOptions(), _b('8\001')), + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=263, + serialized_end=348, +) + +_BUILDRULE = _descriptor.Descriptor( + name='BuildRule', + full_name='build_config.BuildRule', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='gob_host', full_name='build_config.BuildRule.gob_host', 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), + _descriptor.FieldDescriptor( + name='branch', full_name='build_config.BuildRule.branch', index=1, + 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), + _descriptor.FieldDescriptor( + name='project', full_name='build_config.BuildRule.project', index=2, + 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), + _descriptor.FieldDescriptor( + name='presubmit_builds', full_name='build_config.BuildRule.presubmit_builds', index=3, + number=5, 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), + _descriptor.FieldDescriptor( + name='builds', full_name='build_config.BuildRule.builds', index=4, + number=6, 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), + _descriptor.FieldDescriptor( + name='build_sets', full_name='build_config.BuildRule.build_sets', index=5, + number=7, 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), + _descriptor.FieldDescriptor( + name='property_overrides', full_name='build_config.BuildRule.property_overrides', index=6, + number=8, 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), + _descriptor.FieldDescriptor( + name='file_whitelist', full_name='build_config.BuildRule.file_whitelist', index=7, + number=9, 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), + ], + extensions=[ + ], + nested_types=[_BUILDRULE_PROPERTYOVERRIDESENTRY, ], + enum_types=[ + ], + options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=37, + serialized_end=354, +) + + +_PROPERTYVALUE = _descriptor.Descriptor( + name='PropertyValue', + full_name='build_config.PropertyValue', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='string', full_name='build_config.PropertyValue.string', 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), + _descriptor.FieldDescriptor( + name='bool', full_name='build_config.PropertyValue.bool', index=1, + number=2, 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), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + _descriptor.OneofDescriptor( + name='value', full_name='build_config.PropertyValue.value', + index=0, containing_type=None, fields=[]), + ], + serialized_start=356, + serialized_end=414, +) + + +_BUILDSET = _descriptor.Descriptor( + name='BuildSet', + full_name='build_config.BuildSet', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='builds', full_name='build_config.BuildSet.builds', index=0, + number=1, 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), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=416, + serialized_end=442, +) + + +_BUILDRULES_BUILDSETSENTRY = _descriptor.Descriptor( + name='BuildSetsEntry', + full_name='build_config.BuildRules.BuildSetsEntry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='build_config.BuildRules.BuildSetsEntry.key', 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), + _descriptor.FieldDescriptor( + name='value', full_name='build_config.BuildRules.BuildSetsEntry.value', index=1, + number=2, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + options=_descriptor._ParseOptions(descriptor_pb2.MessageOptions(), _b('8\001')), + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=566, + serialized_end=638, +) + +_BUILDRULES = _descriptor.Descriptor( + name='BuildRules', + full_name='build_config.BuildRules', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='build_rules', full_name='build_config.BuildRules.build_rules', index=0, + number=1, 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), + _descriptor.FieldDescriptor( + name='build_sets', full_name='build_config.BuildRules.build_sets', index=1, + number=2, 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), + ], + extensions=[ + ], + nested_types=[_BUILDRULES_BUILDSETSENTRY, ], + enum_types=[ + ], + options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=445, + serialized_end=638, +) + + +_JENKINSJOB = _descriptor.Descriptor( + name='JenkinsJob', + full_name='build_config.JenkinsJob', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='job_name', full_name='build_config.JenkinsJob.job_name', 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), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=640, + serialized_end=670, +) + + +_CASTBUILD = _descriptor.Descriptor( + name='CastBuild', + full_name='build_config.CastBuild', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='recipe', full_name='build_config.CastBuild.recipe', 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), + _descriptor.FieldDescriptor( + name='builder_name', full_name='build_config.CastBuild.builder_name', 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), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=672, + serialized_end=721, +) + + +_BUILDDETAIL_PROPERTYOVERRIDESENTRY = _descriptor.Descriptor( + name='PropertyOverridesEntry', + full_name='build_config.BuildDetail.PropertyOverridesEntry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='build_config.BuildDetail.PropertyOverridesEntry.key', 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), + _descriptor.FieldDescriptor( + name='value', full_name='build_config.BuildDetail.PropertyOverridesEntry.value', index=1, + number=2, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + options=_descriptor._ParseOptions(descriptor_pb2.MessageOptions(), _b('8\001')), + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=263, + serialized_end=348, +) + +_BUILDDETAIL_SCHEDULERESTRICTION = _descriptor.Descriptor( + name='ScheduleRestriction', + full_name='build_config.BuildDetail.ScheduleRestriction', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='min_branch', full_name='build_config.BuildDetail.ScheduleRestriction.min_branch', 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), + _descriptor.FieldDescriptor( + name='max_branch', full_name='build_config.BuildDetail.ScheduleRestriction.max_branch', 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), + _descriptor.FieldDescriptor( + name='release_only', full_name='build_config.BuildDetail.ScheduleRestriction.release_only', index=2, + number=3, type=8, cpp_type=7, label=1, + has_default_value=True, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='master_only', full_name='build_config.BuildDetail.ScheduleRestriction.master_only', index=3, + number=4, type=8, cpp_type=7, label=1, + has_default_value=True, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=1131, + serialized_end=1249, +) + +_BUILDDETAIL = _descriptor.Descriptor( + name='BuildDetail', + full_name='build_config.BuildDetail', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='required', full_name='build_config.BuildDetail.required', index=0, + number=1, type=8, cpp_type=7, label=1, + has_default_value=True, default_value=True, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='disabled_branches', full_name='build_config.BuildDetail.disabled_branches', index=1, + number=3, 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), + _descriptor.FieldDescriptor( + name='property_overrides', full_name='build_config.BuildDetail.property_overrides', index=2, + number=5, 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), + _descriptor.FieldDescriptor( + name='schedule', full_name='build_config.BuildDetail.schedule', index=3, + number=7, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='owner', full_name='build_config.BuildDetail.owner', index=4, + 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), + _descriptor.FieldDescriptor( + name='cast_build', full_name='build_config.BuildDetail.cast_build', index=5, + number=16, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='jenkins_job', full_name='build_config.BuildDetail.jenkins_job', index=6, + number=17, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + ], + extensions=[ + ], + nested_types=[_BUILDDETAIL_PROPERTYOVERRIDESENTRY, _BUILDDETAIL_SCHEDULERESTRICTION, ], + enum_types=[ + ], + options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + _descriptor.OneofDescriptor( + name='config', full_name='build_config.BuildDetail.config', + index=0, containing_type=None, fields=[]), + ], + serialized_start=724, + serialized_end=1319, +) + + +_BUILDDETAILS_BUILDDETAILSENTRY = _descriptor.Descriptor( + name='BuildDetailsEntry', + full_name='build_config.BuildDetails.BuildDetailsEntry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='build_config.BuildDetails.BuildDetailsEntry.key', 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), + _descriptor.FieldDescriptor( + name='value', full_name='build_config.BuildDetails.BuildDetailsEntry.value', index=1, + number=2, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + options=_descriptor._ParseOptions(descriptor_pb2.MessageOptions(), _b('8\001')), + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=1407, + serialized_end=1485, +) + +_BUILDDETAILS = _descriptor.Descriptor( + name='BuildDetails', + full_name='build_config.BuildDetails', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='build_details', full_name='build_config.BuildDetails.build_details', index=0, + number=1, 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), + ], + extensions=[ + ], + nested_types=[_BUILDDETAILS_BUILDDETAILSENTRY, ], + enum_types=[ + ], + options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=1322, + serialized_end=1485, +) + +_BUILDRULE_PROPERTYOVERRIDESENTRY.fields_by_name['value'].message_type = _PROPERTYVALUE +_BUILDRULE_PROPERTYOVERRIDESENTRY.containing_type = _BUILDRULE +_BUILDRULE.fields_by_name['property_overrides'].message_type = _BUILDRULE_PROPERTYOVERRIDESENTRY +_PROPERTYVALUE.oneofs_by_name['value'].fields.append( + _PROPERTYVALUE.fields_by_name['string']) +_PROPERTYVALUE.fields_by_name['string'].containing_oneof = _PROPERTYVALUE.oneofs_by_name['value'] +_PROPERTYVALUE.oneofs_by_name['value'].fields.append( + _PROPERTYVALUE.fields_by_name['bool']) +_PROPERTYVALUE.fields_by_name['bool'].containing_oneof = _PROPERTYVALUE.oneofs_by_name['value'] +_BUILDRULES_BUILDSETSENTRY.fields_by_name['value'].message_type = _BUILDSET +_BUILDRULES_BUILDSETSENTRY.containing_type = _BUILDRULES +_BUILDRULES.fields_by_name['build_rules'].message_type = _BUILDRULE +_BUILDRULES.fields_by_name['build_sets'].message_type = _BUILDRULES_BUILDSETSENTRY +_BUILDDETAIL_PROPERTYOVERRIDESENTRY.fields_by_name['value'].message_type = _PROPERTYVALUE +_BUILDDETAIL_PROPERTYOVERRIDESENTRY.containing_type = _BUILDDETAIL +_BUILDDETAIL_SCHEDULERESTRICTION.containing_type = _BUILDDETAIL +_BUILDDETAIL.fields_by_name['property_overrides'].message_type = _BUILDDETAIL_PROPERTYOVERRIDESENTRY +_BUILDDETAIL.fields_by_name['schedule'].message_type = _BUILDDETAIL_SCHEDULERESTRICTION +_BUILDDETAIL.fields_by_name['cast_build'].message_type = _CASTBUILD +_BUILDDETAIL.fields_by_name['jenkins_job'].message_type = _JENKINSJOB +_BUILDDETAIL.oneofs_by_name['config'].fields.append( + _BUILDDETAIL.fields_by_name['cast_build']) +_BUILDDETAIL.fields_by_name['cast_build'].containing_oneof = _BUILDDETAIL.oneofs_by_name['config'] +_BUILDDETAIL.oneofs_by_name['config'].fields.append( + _BUILDDETAIL.fields_by_name['jenkins_job']) +_BUILDDETAIL.fields_by_name['jenkins_job'].containing_oneof = _BUILDDETAIL.oneofs_by_name['config'] +_BUILDDETAILS_BUILDDETAILSENTRY.fields_by_name['value'].message_type = _BUILDDETAIL +_BUILDDETAILS_BUILDDETAILSENTRY.containing_type = _BUILDDETAILS +_BUILDDETAILS.fields_by_name['build_details'].message_type = _BUILDDETAILS_BUILDDETAILSENTRY +DESCRIPTOR.message_types_by_name['BuildRule'] = _BUILDRULE +DESCRIPTOR.message_types_by_name['PropertyValue'] = _PROPERTYVALUE +DESCRIPTOR.message_types_by_name['BuildSet'] = _BUILDSET +DESCRIPTOR.message_types_by_name['BuildRules'] = _BUILDRULES +DESCRIPTOR.message_types_by_name['JenkinsJob'] = _JENKINSJOB +DESCRIPTOR.message_types_by_name['CastBuild'] = _CASTBUILD +DESCRIPTOR.message_types_by_name['BuildDetail'] = _BUILDDETAIL +DESCRIPTOR.message_types_by_name['BuildDetails'] = _BUILDDETAILS + +BuildRule = _reflection.GeneratedProtocolMessageType('BuildRule', (_message.Message,), dict( + + PropertyOverridesEntry = _reflection.GeneratedProtocolMessageType('PropertyOverridesEntry', (_message.Message,), dict( + DESCRIPTOR = _BUILDRULE_PROPERTYOVERRIDESENTRY, + __module__ = 'build_config_pb2' + # @@protoc_insertion_point(class_scope:build_config.BuildRule.PropertyOverridesEntry) + )) + , + DESCRIPTOR = _BUILDRULE, + __module__ = 'build_config_pb2' + # @@protoc_insertion_point(class_scope:build_config.BuildRule) + )) +_sym_db.RegisterMessage(BuildRule) +_sym_db.RegisterMessage(BuildRule.PropertyOverridesEntry) + +PropertyValue = _reflection.GeneratedProtocolMessageType('PropertyValue', (_message.Message,), dict( + DESCRIPTOR = _PROPERTYVALUE, + __module__ = 'build_config_pb2' + # @@protoc_insertion_point(class_scope:build_config.PropertyValue) + )) +_sym_db.RegisterMessage(PropertyValue) + +BuildSet = _reflection.GeneratedProtocolMessageType('BuildSet', (_message.Message,), dict( + DESCRIPTOR = _BUILDSET, + __module__ = 'build_config_pb2' + # @@protoc_insertion_point(class_scope:build_config.BuildSet) + )) +_sym_db.RegisterMessage(BuildSet) + +BuildRules = _reflection.GeneratedProtocolMessageType('BuildRules', (_message.Message,), dict( + + BuildSetsEntry = _reflection.GeneratedProtocolMessageType('BuildSetsEntry', (_message.Message,), dict( + DESCRIPTOR = _BUILDRULES_BUILDSETSENTRY, + __module__ = 'build_config_pb2' + # @@protoc_insertion_point(class_scope:build_config.BuildRules.BuildSetsEntry) + )) + , + DESCRIPTOR = _BUILDRULES, + __module__ = 'build_config_pb2' + # @@protoc_insertion_point(class_scope:build_config.BuildRules) + )) +_sym_db.RegisterMessage(BuildRules) +_sym_db.RegisterMessage(BuildRules.BuildSetsEntry) + +JenkinsJob = _reflection.GeneratedProtocolMessageType('JenkinsJob', (_message.Message,), dict( + DESCRIPTOR = _JENKINSJOB, + __module__ = 'build_config_pb2' + # @@protoc_insertion_point(class_scope:build_config.JenkinsJob) + )) +_sym_db.RegisterMessage(JenkinsJob) + +CastBuild = _reflection.GeneratedProtocolMessageType('CastBuild', (_message.Message,), dict( + DESCRIPTOR = _CASTBUILD, + __module__ = 'build_config_pb2' + # @@protoc_insertion_point(class_scope:build_config.CastBuild) + )) +_sym_db.RegisterMessage(CastBuild) + +BuildDetail = _reflection.GeneratedProtocolMessageType('BuildDetail', (_message.Message,), dict( + + PropertyOverridesEntry = _reflection.GeneratedProtocolMessageType('PropertyOverridesEntry', (_message.Message,), dict( + DESCRIPTOR = _BUILDDETAIL_PROPERTYOVERRIDESENTRY, + __module__ = 'build_config_pb2' + # @@protoc_insertion_point(class_scope:build_config.BuildDetail.PropertyOverridesEntry) + )) + , + + ScheduleRestriction = _reflection.GeneratedProtocolMessageType('ScheduleRestriction', (_message.Message,), dict( + DESCRIPTOR = _BUILDDETAIL_SCHEDULERESTRICTION, + __module__ = 'build_config_pb2' + # @@protoc_insertion_point(class_scope:build_config.BuildDetail.ScheduleRestriction) + )) + , + DESCRIPTOR = _BUILDDETAIL, + __module__ = 'build_config_pb2' + # @@protoc_insertion_point(class_scope:build_config.BuildDetail) + )) +_sym_db.RegisterMessage(BuildDetail) +_sym_db.RegisterMessage(BuildDetail.PropertyOverridesEntry) +_sym_db.RegisterMessage(BuildDetail.ScheduleRestriction) + +BuildDetails = _reflection.GeneratedProtocolMessageType('BuildDetails', (_message.Message,), dict( + + BuildDetailsEntry = _reflection.GeneratedProtocolMessageType('BuildDetailsEntry', (_message.Message,), dict( + DESCRIPTOR = _BUILDDETAILS_BUILDDETAILSENTRY, + __module__ = 'build_config_pb2' + # @@protoc_insertion_point(class_scope:build_config.BuildDetails.BuildDetailsEntry) + )) + , + DESCRIPTOR = _BUILDDETAILS, + __module__ = 'build_config_pb2' + # @@protoc_insertion_point(class_scope:build_config.BuildDetails) + )) +_sym_db.RegisterMessage(BuildDetails) +_sym_db.RegisterMessage(BuildDetails.BuildDetailsEntry) + + +_BUILDRULE_PROPERTYOVERRIDESENTRY.has_options = True +_BUILDRULE_PROPERTYOVERRIDESENTRY._options = _descriptor._ParseOptions(descriptor_pb2.MessageOptions(), _b('8\001')) +_BUILDRULES_BUILDSETSENTRY.has_options = True +_BUILDRULES_BUILDSETSENTRY._options = _descriptor._ParseOptions(descriptor_pb2.MessageOptions(), _b('8\001')) +_BUILDDETAIL_PROPERTYOVERRIDESENTRY.has_options = True +_BUILDDETAIL_PROPERTYOVERRIDESENTRY._options = _descriptor._ParseOptions(descriptor_pb2.MessageOptions(), _b('8\001')) +_BUILDDETAILS_BUILDDETAILSENTRY.has_options = True +_BUILDDETAILS_BUILDDETAILSENTRY._options = _descriptor._ParseOptions(descriptor_pb2.MessageOptions(), _b('8\001')) +# @@protoc_insertion_point(module_scope)
diff --git a/cq/appengine/proto/build_config.proto b/cq/appengine/proto/build_config.proto new file mode 100644 index 0000000..b8829a0 --- /dev/null +++ b/cq/appengine/proto/build_config.proto
@@ -0,0 +1,115 @@ +syntax = "proto2"; + +package build_config; + +message BuildRule { + reserved 2; + + // The Gerrit/Git-on-Borg hostname (e.g. eureka-internal) + optional string gob_host = 1; + + // A regex to match against a branch. + optional string branch = 3; + + // A regex to match against a project name. + optional string project = 4; + + // The builds to be automatically scheduled when a CL is uploaded. + // These builds should be very fast (<5 mins) to run. + repeated string presubmit_builds = 5; + + // The builds to be run when a user requests CQ+1 or CQ+2. + // These builds can be slower to run (5-30mins). + repeated string builds = 6; + + // A name of a set of builds to be included. + repeated string build_sets = 7; + + // Map of property overrides for the project level. It should consist of + // property -> override value. For example gclient_root: src. + map<string, PropertyValue> property_overrides = 8; + + // List of regex file patterns to run this build against. + // If none specified will not check the files. + repeated string file_whitelist = 9; +} + +message PropertyValue { + oneof value { + string string = 1; + bool bool = 2; + } +} + +message BuildSet { + // List of builds in this set. + repeated string builds = 1; +} + +message BuildRules { + // List of BuildRules. + repeated BuildRule build_rules = 1; + + // Map build set name -> List of builds + map<string, BuildSet> build_sets = 2; +} + +message JenkinsJob { + // The name of the job which should be scheduled in the Jenkins backend. + optional string job_name = 1; +} + +message CastBuild { + // The name of the Cast CQ recipe to run for this build. + optional string recipe = 1; + // Override the name provided in the key and pass this builder_name into the + // recipe. + optional string builder_name = 2; +} + +message BuildDetail { + reserved 2, 4, 6, 8, 9, 10, 11, 13, 14, 15; + + // Whether this build is required to pass for a Verified+1. + optional bool required = 1 [default = true]; + + // Branches that this build is disabled on. + // Use the special value "*" to disable on all branches. + repeated string disabled_branches = 3; + + // Map of property overrides for the project level. It should consist of + // property -> override value. For example gclient_root: src. + map<string, PropertyValue> property_overrides = 5; + + message ScheduleRestriction { + // The minimum required branch number that this build is supported on. + optional string min_branch = 1; + // The first branch that this build is not supported on. + optional string max_branch = 2; + // If this build should only be scheduled on release branches. A release + // branch is defined as any branch matching the pattern \d\.\d+[_a-z]*. + // Note that this and master_only should never both be true. + optional bool release_only = 3 [default = false]; + // If this build should only be schedule on master branches. Note that + // this and release_only should never both be true. + optional bool master_only = 4 [default = false]; + } + // The restrictions used to schedule builds. These rules will be applied + // first, followed by explicit branch restrictions in disabled_branches. + optional ScheduleRestriction schedule = 7; + + // Required field - please populate this with the build OWNER + optional string owner = 12; + + oneof config { + // The configuration for the cast build to schedule for this build. + CastBuild cast_build = 16; + // The configuration for the jenkins job to schedule for this build. + JenkinsJob jenkins_job = 17; + } +} + +message BuildDetails { + // Map of build_name -> BuildDetail + map<string, BuildDetail> build_details = 1; +}
diff --git a/cq/landmines/README.md b/cq/landmines/README.md new file mode 100644 index 0000000..44adf33 --- /dev/null +++ b/cq/landmines/README.md
@@ -0,0 +1,44 @@ +Landmines let anyone force the CQ build slaves to clean their out directories. + +## Using Landmines +If you want to use a landmine to trigger the bots to clean themselves, +then go to continuous-tests/cq/landmines (the directory this file is in) and +bump the number of the landmine file. +For instance, if there is currently a 'landmine.6' file, create 'landmine.7'. +The CQ will only care about the landmine with the largest number, regardless +of how many landmine files there are. + +In the landmine file, add a quick note explaining why a landmine is necessary, +and add a bug number if there is one. This part is purely documentation, but +it is nice to have. + +Then, commit your change with the new/updated landmine file. + +The next time the CQ runs, the builder then checks if +~/landmines/landmine.<number>/<manifest_branch> exists. +If it already exists, then the builder continues normally. +If it does not exists, the builder runs: + `make clean` && `touch ~/landmines/landmine.<number>/<manifest_branch>` +This cleans out the $ROOT/out/ directory and all $ROOT/chromium/src/out_* +directories, and then records that the landmine has been processed. + +## Landmine File Format +A landmine file must be located inside continous-tests/cq/landmines +A landmine file must have a name of the format: landmine.<number> +Examples: + continuous-tests/cq/landmines/landmine.1 + continuous-tests/cq/landmines/landmine.23 + continuous-tests/cq/landmines/landmine.9999 + +## Landmine File Contents +The contents of a landmine file do not affect the behaviour of a landmine +in anyway. However, it is a convenient place to document why a landmine +was needed. A short description and a bug # are usually good to include. + +## Landmine History +Each slave keeps track of which landmines it has already seen in its +own ~/landmines directory. Each time a slave sees a new landmine, +it adds a ~/landmines/<landmine>/<manifest_branch> file to the folder, +to indicate it saw <landmine> and triggered a clean. Since the CQ slaves keep +separate checkouts for each manifest branch, the history needs to include +<manifest_branch>.
diff --git a/cq/landmines/landmine.10 b/cq/landmines/landmine.10 new file mode 100644 index 0000000..4a0e1e6 --- /dev/null +++ b/cq/landmines/landmine.10
@@ -0,0 +1,6 @@ +b/68346539 + +Trying to land Chromium roll that includes this CL: +https://chromium-review.googlesource.com/c/chromium/src/+/729047 + +Note, it needed a landmine upstream to land. So do we :)
diff --git a/cq/landmines/landmine.11 b/cq/landmines/landmine.11 new file mode 100644 index 0000000..5278f2f --- /dev/null +++ b/cq/landmines/landmine.11
@@ -0,0 +1,4 @@ +I moved some code around in this CL: +https://eureka-internal-review.git.corp.google.com/c/vendor/amlogic/+/127186 + +And need to clean up CQ from stale dependencies
diff --git a/cq/landmines/landmine.12 b/cq/landmines/landmine.12 new file mode 100644 index 0000000..eeb667c --- /dev/null +++ b/cq/landmines/landmine.12
@@ -0,0 +1,3 @@ +CQ failing, and locally a clean build fixes the failure. + +Attempting to fix in CQ by adding this landmine.
diff --git a/cq/landmines/landmine.13 b/cq/landmines/landmine.13 new file mode 100644 index 0000000..d8c1f65 --- /dev/null +++ b/cq/landmines/landmine.13
@@ -0,0 +1,4 @@ +Chromium's build_time_unittests check that the incremental build is +no more than 45 days old. We need to do a fresh build in order for +the latest merge to pass these tests: b/72118853 +
diff --git a/cq/landmines/landmine.14 b/cq/landmines/landmine.14 new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/cq/landmines/landmine.14
diff --git a/cq/landmines/landmine.15 b/cq/landmines/landmine.15 new file mode 100644 index 0000000..d8c1f65 --- /dev/null +++ b/cq/landmines/landmine.15
@@ -0,0 +1,4 @@ +Chromium's build_time_unittests check that the incremental build is +no more than 45 days old. We need to do a fresh build in order for +the latest merge to pass these tests: b/72118853 +
diff --git a/cq/landmines/landmine.16 b/cq/landmines/landmine.16 new file mode 100644 index 0000000..d63a57b --- /dev/null +++ b/cq/landmines/landmine.16
@@ -0,0 +1,4 @@ +Chromium's build_time_unittests check that the incremental build is +no more than 45 days old. We need to do a fresh build in order for +the latest merge to pass these tests: b/76204844 +
diff --git a/cq/landmines/landmine.17 b/cq/landmines/landmine.17 new file mode 100644 index 0000000..69095b6 --- /dev/null +++ b/cq/landmines/landmine.17
@@ -0,0 +1,9 @@ +The following library repos are updated for following reasons +- tracking new remote upstream +- cloned to external/gwifi as they are only used by gWifi SDK + +The incremental build cannot handle the move the repos and intermediate +build results for the deprecated library checkouts broken the build, +thus need a fresh build. +b/72319911 +go/gwifi-deps-castos
diff --git a/cq/landmines/landmine.18 b/cq/landmines/landmine.18 new file mode 100644 index 0000000..0343551 --- /dev/null +++ b/cq/landmines/landmine.18
@@ -0,0 +1,4 @@ +Chromium's build_time_unittests check that the incremental build is +no more than 45 days old. We need to do a fresh build in order for +the latest merge to pass these tests: b/72157246 +
diff --git a/cq/landmines/landmine.19 b/cq/landmines/landmine.19 new file mode 100644 index 0000000..b2042ce --- /dev/null +++ b/cq/landmines/landmine.19
@@ -0,0 +1,7 @@ +b/79208340 + +I moved the ChromecastConfigAndroid implementation to internal. +Therefore the path of jni file is updated, and CQ need to clean its out directory. + +https://eureka-internal-review.git.corp.google.com/c/chromecast/internal/+/175156 +https://eureka-internal-review.git.corp.google.com/c/chromium/src/+/176180
diff --git a/cq/landmines/landmine.2 b/cq/landmines/landmine.2 new file mode 100644 index 0000000..b2be5f0 --- /dev/null +++ b/cq/landmines/landmine.2
@@ -0,0 +1,2 @@ +Deploying a change to the JDK version requires clearing out old build +artifacts. Change is in cl/120723305.
diff --git a/cq/landmines/landmine.20 b/cq/landmines/landmine.20 new file mode 100644 index 0000000..da800a9 --- /dev/null +++ b/cq/landmines/landmine.20
@@ -0,0 +1 @@ +Need to rebuild waves after https://eureka-partner-review.googlesource.com/c/vendor/waves/+/99308
diff --git a/cq/landmines/landmine.21 b/cq/landmines/landmine.21 new file mode 100644 index 0000000..d01ca16 --- /dev/null +++ b/cq/landmines/landmine.21
@@ -0,0 +1,19 @@ +b/79208340 + +Move the ChromecastConfigAndroid implementation to internal. +Since the path of jni file is updated, CQ need to clean its out directory. + +this landmine is used for branch master, branch 1.34 and branch 1.35. + +for master: +https://eureka-internal-review.git.corp.google.com/c/chromecast/internal/+/175156 +https://chromium-review.git.corp.google.com/c/chromium/src/+/1114227 + + +for 1.34: +https://eureka-internal-review.git.corp.google.com/c/chromecast/internal/+/184646 +https://eureka-internal-review.git.corp.google.com/c/chromium/src/+/184642 + +for 1.35: +https://eureka-internal-review.git.corp.google.com/c/chromecast/internal/+/192915 +https://eureka-internal-review.git.corp.google.com/c/chromium/src/+/192913
diff --git a/cq/landmines/landmine.22 b/cq/landmines/landmine.22 new file mode 100644 index 0000000..3417cc4 --- /dev/null +++ b/cq/landmines/landmine.22
@@ -0,0 +1 @@ +Clean the cq for the master branch.
diff --git a/cq/landmines/landmine.23 b/cq/landmines/landmine.23 new file mode 100644 index 0000000..2b25c07 --- /dev/null +++ b/cq/landmines/landmine.23
@@ -0,0 +1,8 @@ +b/79208340 + +Move the ChromecastConfigAndroid implementation to internal. +Since the path of jni file is updated, CQ need to clean its out directory. +(this landmine is used for the branch 1.36.) + +https://eureka-internal-review.git.corp.google.com/c/chromecast/internal/+/199639 +https://eureka-internal-review.git.corp.google.com/c/chromium/src/+/199621
diff --git a/cq/landmines/landmine.24 b/cq/landmines/landmine.24 new file mode 100644 index 0000000..17ddec7 --- /dev/null +++ b/cq/landmines/landmine.24
@@ -0,0 +1,3 @@ +Clear out dependency cycle caused by old __build_config artifacts. + +b/119278504#comment19
diff --git a/cq/landmines/landmine.25 b/cq/landmines/landmine.25 new file mode 100644 index 0000000..a44a9f2 --- /dev/null +++ b/cq/landmines/landmine.25
@@ -0,0 +1,13 @@ +Need a fresh build to uprev gwifi dependency libs + +The following libraries have been deprecated from +external/gwifi +- external/gwifi/libbrillo +- external/gwifi/shill + +They have been moved to external/gwifi/platform2 +during the uprev due to the cros upstream change. + +b/121276961 + +
diff --git a/cq/landmines/landmine.26 b/cq/landmines/landmine.26 new file mode 100644 index 0000000..3210726 --- /dev/null +++ b/cq/landmines/landmine.26
@@ -0,0 +1,4 @@ +Need a fresh build to clean SELinux on Estelle + +b/122370575 +
diff --git a/cq/landmines/landmine.27 b/cq/landmines/landmine.27 new file mode 100644 index 0000000..ed4fbaf --- /dev/null +++ b/cq/landmines/landmine.27
@@ -0,0 +1,7 @@ +Need a fresh build to clean SELinux on Estelle + +Incremental Estelle build was incompartible with all other builds. + +Previous solution has been reverted in http://go/eureka-review/229658 + +b/122370575 \ No newline at end of file
diff --git a/cq/landmines/landmine.28 b/cq/landmines/landmine.28 new file mode 100644 index 0000000..285bb09 --- /dev/null +++ b/cq/landmines/landmine.28
@@ -0,0 +1,3 @@ +Drop a landmine to fix a cyclical dependency after a GN refactor + +crbug.com/934404
diff --git a/cq/landmines/landmine.29 b/cq/landmines/landmine.29 new file mode 100644 index 0000000..1ace07c --- /dev/null +++ b/cq/landmines/landmine.29
@@ -0,0 +1,4 @@ +Drop a landmine to fix build failures due to stale makefile path + +https://eureka-internal-review.git.corp.google.com/c/eureka/+/254787 +
diff --git a/cq/landmines/landmine.3 b/cq/landmines/landmine.3 new file mode 100644 index 0000000..0b3e502 --- /dev/null +++ b/cq/landmines/landmine.3
@@ -0,0 +1 @@ +Clean the slaves after a bad push has put the incremental builds into a bad state (b/29466529). \ No newline at end of file
diff --git a/cq/landmines/landmine.30 b/cq/landmines/landmine.30 new file mode 100644 index 0000000..56ebf35 --- /dev/null +++ b/cq/landmines/landmine.30
@@ -0,0 +1,9 @@ +Drop a landmine to fix build failures due to incremental builds + +Incremental builds are failing to update import_includes when +adding a new dependent library to LOCAL_STATIC_LIBRARIES. + +https://nest-internal-review.googlesource.com/c/platform/nlnetworktools/+/58364 + +https://b.corp.google.com/issues/132905702 (related bug) +
diff --git a/cq/landmines/landmine.31 b/cq/landmines/landmine.31 new file mode 100644 index 0000000..2c85576 --- /dev/null +++ b/cq/landmines/landmine.31
@@ -0,0 +1,5 @@ +Drop a landmine to fix build failures in arm_androidtv_debug builds + +Incremental builds in CQ are failing but with ~65% failure rate when CB builds are green. + +http://b/134248243 (related bug)
diff --git a/cq/landmines/landmine.32 b/cq/landmines/landmine.32 new file mode 100644 index 0000000..a88eb6d --- /dev/null +++ b/cq/landmines/landmine.32
@@ -0,0 +1,10 @@ +Drop a landmine to fix build failures due to incremental builds + +Incremental builds are failing to update import_includes when +adding a new dependent library to LOCAL_STATIC_LIBRARIES. + +https://nest-internal-review.googlesource.com/c/platform/nlnetworktools/+/64805 +(Note that this is mostly the same as landmine.30, but used for cherry-picking changes into 1.39n branch) + +https://b.corp.google.com/issues/132905702 (related bug) +
diff --git a/cq/landmines/landmine.33 b/cq/landmines/landmine.33 new file mode 100644 index 0000000..0dc9586 --- /dev/null +++ b/cq/landmines/landmine.33
@@ -0,0 +1,7 @@ +Drop a landmine to fix build failures due to incremental builds + +Incremental builds are failing to correctly configure Weave builds. + + +https://nest-internal-review.googlesource.com/c/platform/weave/+/66378 +
diff --git a/cq/landmines/landmine.34 b/cq/landmines/landmine.34 new file mode 100644 index 0000000..cec8862 --- /dev/null +++ b/cq/landmines/landmine.34
@@ -0,0 +1,5 @@ +Drop a landmine to fix build failures due to incremental builds + +Incremental builds are failing due to camera-common refactor. + +https://eureka-internal-review.git.corp.google.com/c/vendor/amlogic/+/290199
diff --git a/cq/landmines/landmine.35 b/cq/landmines/landmine.35 new file mode 100644 index 0000000..b9e5fdd --- /dev/null +++ b/cq/landmines/landmine.35
@@ -0,0 +1,11 @@ +Force a clean build for tensorflow uprev. + +The following libraries have updated Android.mk in this uprev: +- libtflite +https://eureka-internal-review.git.corp.google.com/c/platform/external/tensorflow/+/291899 +- libtextclassifier_hash +https://eureka-internal-review.git.corp.google.com/c/platform/external/libtextclassifier/+/291918 +- libflatbufferutil +https://eureka-internal-review.git.corp.google.com/c/platform/external/flatbuffers/+/291977 + +b/137051697
diff --git a/cq/landmines/landmine.36 b/cq/landmines/landmine.36 new file mode 100644 index 0000000..3ad4b32 --- /dev/null +++ b/cq/landmines/landmine.36
@@ -0,0 +1,4 @@ +Force a clean build for tensorflow uprev 2. + +Tensorflow uprev was partially reverted due to broken build (b/137600157), after +relanding we need another clean build.
diff --git a/cq/landmines/landmine.37 b/cq/landmines/landmine.37 new file mode 100644 index 0000000..5a6b6f4 --- /dev/null +++ b/cq/landmines/landmine.37
@@ -0,0 +1 @@ +Force a clean build to fix valens-eng. \ No newline at end of file
diff --git a/cq/landmines/landmine.38 b/cq/landmines/landmine.38 new file mode 100644 index 0000000..a82b6e5 --- /dev/null +++ b/cq/landmines/landmine.38
@@ -0,0 +1,6 @@ +Drop a landmine to fix build failures due to incremental builds + +Incremental builds are failing due to GQ/NQ system image oversized caused by +leftover ML modules. + +https://eureka-internal-review.git.corp.google.com/c/vendor/amlogic/+/315581
diff --git a/cq/landmines/landmine.39 b/cq/landmines/landmine.39 new file mode 100644 index 0000000..aaa7fd6 --- /dev/null +++ b/cq/landmines/landmine.39
@@ -0,0 +1,3 @@ +Clean build to eliminate large artifacts stored on CQ slaves. For details see +b/142762112. +
diff --git a/cq/landmines/landmine.4 b/cq/landmines/landmine.4 new file mode 100644 index 0000000..5b5fe3e --- /dev/null +++ b/cq/landmines/landmine.4
@@ -0,0 +1,2 @@ +Update of Marvell SDK to ver 68051 for steak requires clearing ./out +for incremental builds.
diff --git a/cq/landmines/landmine.40 b/cq/landmines/landmine.40 new file mode 100644 index 0000000..8b4122d --- /dev/null +++ b/cq/landmines/landmine.40
@@ -0,0 +1,2 @@ +Force rebuild for switching prince userspace builds from 32-bit to 64-bit. +See b/140242422 for more details.
diff --git a/cq/landmines/landmine.41 b/cq/landmines/landmine.41 new file mode 100644 index 0000000..dc7c2c5 --- /dev/null +++ b/cq/landmines/landmine.41
@@ -0,0 +1,2 @@ +Force rebuild to clean up build errors caused by v4l2_capture refactoring +b/144132956
diff --git a/cq/landmines/landmine.42 b/cq/landmines/landmine.42 new file mode 100644 index 0000000..4845c7c --- /dev/null +++ b/cq/landmines/landmine.42
@@ -0,0 +1,2 @@ +Added NDEBUG flag for eng builds for libchrome and its dependents. Changing +flag doesn't rebuild the module, hence this landmine.
diff --git a/cq/landmines/landmine.43 b/cq/landmines/landmine.43 new file mode 100644 index 0000000..549ff65 --- /dev/null +++ b/cq/landmines/landmine.43
@@ -0,0 +1 @@ +DCHECK_ALWAYS_ON is enabled on eng build. Changing compile flag doesn't rebuild the module, hence this landmine.
diff --git a/cq/landmines/landmine.44 b/cq/landmines/landmine.44 new file mode 100644 index 0000000..34531e7 --- /dev/null +++ b/cq/landmines/landmine.44
@@ -0,0 +1,2 @@ +Clean build required to update exported includes change caused +by update_metadata-protos being added in eureka-internal/338022
diff --git a/cq/landmines/landmine.45 b/cq/landmines/landmine.45 new file mode 100644 index 0000000..3a69249 --- /dev/null +++ b/cq/landmines/landmine.45
@@ -0,0 +1,2 @@ +Clean build required to update weave quantity type that was added for +b/145148808 in http://go/nest-review/109016
diff --git a/cq/landmines/landmine.46 b/cq/landmines/landmine.46 new file mode 100644 index 0000000..aeb64a5 --- /dev/null +++ b/cq/landmines/landmine.46
@@ -0,0 +1,2 @@ +Clean build to attempt to clean up flakes caused by phoenix-schema +b/150692335 \ No newline at end of file
diff --git a/cq/landmines/landmine.47 b/cq/landmines/landmine.47 new file mode 100644 index 0000000..2d88dda --- /dev/null +++ b/cq/landmines/landmine.47
@@ -0,0 +1,2 @@ +Clean build to attempt to resolve linker errors in ml_framework tryjobs. +b/149926211
diff --git a/cq/landmines/landmine.48 b/cq/landmines/landmine.48 new file mode 100644 index 0000000..d43727a --- /dev/null +++ b/cq/landmines/landmine.48
@@ -0,0 +1,2 @@ +Clean build to attempt to resolve linker errors in nldaemon. +b/155189910
diff --git a/cq/landmines/landmine.49 b/cq/landmines/landmine.49 new file mode 100644 index 0000000..59dcf21 --- /dev/null +++ b/cq/landmines/landmine.49
@@ -0,0 +1,4 @@ +Incremental build is failing due to this bug: b/157750636 + +The /root/lib/teetz symbolic link needs to be removed before +we can use it as a directory.
diff --git a/cq/landmines/landmine.5 b/cq/landmines/landmine.5 new file mode 100644 index 0000000..eb11aeb --- /dev/null +++ b/cq/landmines/landmine.5
@@ -0,0 +1,5 @@ +Disks are filling up out of control. Pass a landmine to reclaim some space +in a safe way. + +b/31319903 +b/31318818
diff --git a/cq/landmines/landmine.50 b/cq/landmines/landmine.50 new file mode 100644 index 0000000..8254f26 --- /dev/null +++ b/cq/landmines/landmine.50
@@ -0,0 +1,3 @@ +Incremental build is failing due to this bug: b/158347254 + +Cleanup unused source files by previous Android.mak change
diff --git a/cq/landmines/landmine.51 b/cq/landmines/landmine.51 new file mode 100644 index 0000000..b1d6579 --- /dev/null +++ b/cq/landmines/landmine.51
@@ -0,0 +1 @@ +Clean build after estelle-user size decreases. b/159068553 \ No newline at end of file
diff --git a/cq/landmines/landmine.52 b/cq/landmines/landmine.52 new file mode 100644 index 0000000..42f99d1 --- /dev/null +++ b/cq/landmines/landmine.52
@@ -0,0 +1 @@ +Clean build for mushroom ota oversize failure in CQ.
diff --git a/cq/landmines/landmine.53 b/cq/landmines/landmine.53 new file mode 100644 index 0000000..300150f --- /dev/null +++ b/cq/landmines/landmine.53
@@ -0,0 +1,2 @@ +Create landmine to fix incremental build failure caused by TDK restructure +Bug:158269536
diff --git a/cq/landmines/landmine.54 b/cq/landmines/landmine.54 new file mode 100644 index 0000000..1069de8 --- /dev/null +++ b/cq/landmines/landmine.54
@@ -0,0 +1,2 @@ +Create a landmine to avoid issue with oemcrypto_tz +Bug:161850133
diff --git a/cq/landmines/landmine.55 b/cq/landmines/landmine.55 new file mode 100644 index 0000000..0ee98b6 --- /dev/null +++ b/cq/landmines/landmine.55
@@ -0,0 +1,2 @@ +Create a landmine to avoid issue with waves header +Bug:162108477
diff --git a/cq/landmines/landmine.56 b/cq/landmines/landmine.56 new file mode 100644 index 0000000..80b2ae0 --- /dev/null +++ b/cq/landmines/landmine.56
@@ -0,0 +1 @@ +Landmine to clean incremental build issue on 1.50 and 1.52 \ No newline at end of file
diff --git a/cq/landmines/landmine.57 b/cq/landmines/landmine.57 new file mode 100644 index 0000000..aae5e8b --- /dev/null +++ b/cq/landmines/landmine.57
@@ -0,0 +1,2 @@ +Landmine to force clean build with openssl library switch +b/150403073
diff --git a/cq/landmines/landmine.58 b/cq/landmines/landmine.58 new file mode 100644 index 0000000..82e96d4 --- /dev/null +++ b/cq/landmines/landmine.58
@@ -0,0 +1,2 @@ +Landmine to force clean of grpc since we are using a different repo. +b/132440534
diff --git a/cq/landmines/landmine.59 b/cq/landmines/landmine.59 new file mode 100644 index 0000000..8fef18e --- /dev/null +++ b/cq/landmines/landmine.59
@@ -0,0 +1,8 @@ +Landmine to force clean of vento-eng and vento-user intermediate +build results. + +vento-eng and vento-user were both enabled for a period, as a +result, incompatible intermediate eng/user build results caused +intermittent CQ failure + +b/174605330
diff --git a/cq/landmines/landmine.6 b/cq/landmines/landmine.6 new file mode 100644 index 0000000..0c47dd6 --- /dev/null +++ b/cq/landmines/landmine.6
@@ -0,0 +1,12 @@ +The cast_test_lists template is not giving ninja all the information it +needs. A CL went through that added a directory layer (essentially renaming +a file), but doing `ninja cast_test_lists` was not picking up the change. This +resulted in running outdated binaries against a checkout, which caused tests +to fail because the runtime datafile they need had moved. + +The CL in question (+2 Depends-On): +https://eureka-internal-review.git.corp.google.com/c/63729/ + +This landmine will clear the old test binaries so the new ones will get +built correctly. The cast_test_list template will be investigated to see +if it can pass the right dependency info to ninja.
diff --git a/cq/landmines/landmine.60 b/cq/landmines/landmine.60 new file mode 100644 index 0000000..821e445 --- /dev/null +++ b/cq/landmines/landmine.60
@@ -0,0 +1,6 @@ +Landmine to force clean for all CQ targets that depend on ML framework. + +A proto change made in that repo causes a dependency cycle at build time if +using an old build environment with old versions of the proto libs. + +b/177479085
diff --git a/cq/landmines/landmine.61 b/cq/landmines/landmine.61 new file mode 100644 index 0000000..dec8e95 --- /dev/null +++ b/cq/landmines/landmine.61
@@ -0,0 +1,3 @@ +Landmine to clean out old bad phoenix-schema virtual environments + +b/180013158
diff --git a/cq/landmines/landmine.62 b/cq/landmines/landmine.62 new file mode 100644 index 0000000..318cd34 --- /dev/null +++ b/cq/landmines/landmine.62
@@ -0,0 +1,3 @@ +Force clean build to rebuild spencer image with new partition table + +b/174071314
diff --git a/cq/landmines/landmine.63 b/cq/landmines/landmine.63 new file mode 100644 index 0000000..6ca6f0a --- /dev/null +++ b/cq/landmines/landmine.63
@@ -0,0 +1,3 @@ +Force clean build to rebuild spencer image with new glibc toolchain + +b/186795973
diff --git a/cq/landmines/landmine.64 b/cq/landmines/landmine.64 new file mode 100644 index 0000000..2d846a1 --- /dev/null +++ b/cq/landmines/landmine.64
@@ -0,0 +1,3 @@ +Landmine to clean out old files for libchrome update. + +b/146480114
diff --git a/cq/landmines/landmine.65 b/cq/landmines/landmine.65 new file mode 100644 index 0000000..2e73e1b --- /dev/null +++ b/cq/landmines/landmine.65
@@ -0,0 +1,5 @@ +Landmine to clean out x86 host files built with DEBUG. + +This is causing intermittent failures on CQ. + +b/197920849
diff --git a/cq/landmines/landmine.66 b/cq/landmines/landmine.66 new file mode 100644 index 0000000..3f2fb28 --- /dev/null +++ b/cq/landmines/landmine.66
@@ -0,0 +1,3 @@ +Landmine to clean old ninja results. + +b/259689547 \ No newline at end of file
diff --git a/cq/landmines/landmine.67 b/cq/landmines/landmine.67 new file mode 100644 index 0000000..30a5938 --- /dev/null +++ b/cq/landmines/landmine.67
@@ -0,0 +1,3 @@ +Landmine to clean old toolchain artifacts + +b/267195139
diff --git a/cq/landmines/landmine.68 b/cq/landmines/landmine.68 new file mode 100644 index 0000000..bc330ee --- /dev/null +++ b/cq/landmines/landmine.68
@@ -0,0 +1,2 @@ +Landmine to clean old toolchain artifacts +
diff --git a/cq/landmines/landmine.69 b/cq/landmines/landmine.69 new file mode 100644 index 0000000..cbf28eb --- /dev/null +++ b/cq/landmines/landmine.69
@@ -0,0 +1,4 @@ +Landmine to clean old toolchain artifacts + +b/286241987 +
diff --git a/cq/landmines/landmine.7 b/cq/landmines/landmine.7 new file mode 100644 index 0000000..160fdab --- /dev/null +++ b/cq/landmines/landmine.7
@@ -0,0 +1,8 @@ +Some incremental builds got messed up during a transition from gcc -> clang. +Most builders correctly cleaned with the CleanSpek, but I think some probably +did a build in between running CQ and the CL landing which resulted in a weird +build state. + +Most likely related to these: +https://eureka-internal-review.git.corp.google.com/#/c/69398/2/Android.mk +https://eureka-internal-review.git.corp.google.com/#/c/69399/
diff --git a/cq/landmines/landmine.8 b/cq/landmines/landmine.8 new file mode 100644 index 0000000..1efbc39 --- /dev/null +++ b/cq/landmines/landmine.8
@@ -0,0 +1,3 @@ +CL below broke incremental builds: + +https://eureka-internal-review.git.corp.google.com/#/c/77288/
diff --git a/cq/landmines/landmine.9 b/cq/landmines/landmine.9 new file mode 100644 index 0000000..67004af --- /dev/null +++ b/cq/landmines/landmine.9
@@ -0,0 +1,7 @@ +b/66855290 + +Builders are failing to build libchrome with: +error: undefined reference to 'base::ThreadRestrictions::AssertIOAllowed()' + +Cleaning the builder appears to let it recover, so probably a CL went through +that messed up the intermediate build somehow.
diff --git a/cq/requirements_recipe.in b/cq/requirements_recipe.in new file mode 100644 index 0000000..568b800 --- /dev/null +++ b/cq/requirements_recipe.in
@@ -0,0 +1,70 @@ +# +# Please update cq/requirements_recipe_test.in in case of changes here +# +# Explicit packages +home-monitoring==0.13.dev0 +google-api-core[grpc]==1.13.0 +google-apitools==0.5.31 +google-cloud-error-reporting==0.30.1 +netifaces==0.10.9 +networkx==2.2 +mock==2.0.0 +ply==3.8 +pyopenssl==19.0.0 +pre-commit==1.17.0 +psutil==5.5.0 +pycrypto==2.6.1 +pygraphviz==1.5 +requests==2.21.0 +wand==0.4.4 + +# Implicit packages +asn1crypto==0.24.0 # via cryptography +aspy.yaml==1.3.0 # via pre-commit +cachetools==3.1.0 # via google-auth +certifi==2018.11.29 # via requests +cffi==1.14.0 # via cryptography +cfgv==2.0.1 # via pre-commit +chardet==3.0.4 # via requests +configparser==3.7.4 # via importlib-metadata +contextlib2==0.5.5 # via importlib-metadata +cryptography==2.5 # via pyopenssl +decorator==4.3.2 # via networkx +dill==0.2.9 # via google-gax +enum34==1.1.6 # via grpcio +fasteners==0.14.1 # via google-apitools +fluent-logger==0.9.6 # via home-monitoring +future==0.16.0 # via google-gax +google-auth==1.6.2 # via google-api-core +google-cloud-core==1.0.2 # via google-cloud-logging +google-cloud-logging==1.11.0 # via google-cloud-error-reporting, home-monitoring +google-gax==0.16.0 # via home-monitoring +googleapis-common-protos==1.5.6 # via google-api-core +grpcio==1.30.0 # via google-api-core +httplib2==0.12.0 # via google-apitools, oauth2client +identify==1.4.5 # via pre-commit +idna==2.8 # via requests +importlib-metadata==0.19 # via importlib-resources, pre-commit +importlib-resources==1.0.2 # via pre-commit +ipaddress==1.0.22 # via cryptography +monotonic==1.5 # via fasteners +msgpack==0.6.1 # via fluent-logger +nodeenv==1.3.3 # via pre-commit +oauth2client==4.1.3 # via google-apitools +pathlib2==2.3.4 # via importlib-metadata, importlib-resources +ply==3.8 # via google-gax +pbr==5.1.2 # via mock +protobuf==3.6.1 # via google-api-core, googleapis-common-protos +pyasn1-modules==0.2.4 # via google-auth, oauth2client +pyasn1==0.4.5 # via oauth2client, pyasn1-modules, rsa +pycparser==2.19 # via cffi +pytz==2018.9 # via google-api-core +pyyaml==5.1.2 # via pre-commit, aspy.yaml +rsa==4.0 # via google-auth, oauth2client +scandir==1.10.0 # via pathlib2 +six==1.12.0 # via fasteners, google-api-core, google-apitools, google-auth, grpcio, oauth2client, protobuf +toml==0.10.0 # via pre-commit +typing==3.7.4 # via importlib-resources +urllib3==1.24.1 # via requests +virtualenv==16.7.2 # via pre-commit +zipp==0.5.2 # via importlib-metadata
diff --git a/cq/requirements_recipe.txt b/cq/requirements_recipe.txt new file mode 100644 index 0000000..6c1960d --- /dev/null +++ b/cq/requirements_recipe.txt
@@ -0,0 +1,75 @@ +# +# This file is autogenerated by pip-compile +# To update, run: +# +# pip-compile --output-file=cq/requirements_recipe.txt cq/requirements_recipe.in +# + +asn1crypto==0.24.0 +aspy.yaml==1.3.0 +cachetools==3.1.0 +certifi==2018.11.29 +cffi==1.14.0 +cfgv==2.0.1 +chardet==3.0.4 +configparser==3.7.4 +contextlib2==0.5.5 +cryptography==2.5 +decorator==4.3.2 +dill==0.2.9 +enum34==1.1.6 +fasteners==0.14.1 +fluent-logger==0.9.6 +funcsigs==1.0.2 # via mock +future==0.16.0 +futures==3.3.0 # via google-api-core, grpcio, pre-commit +google-api-core[grpc]==1.13.0 +google-apitools==0.5.31 +google-auth==1.6.2 +google-cloud-core==1.0.2 +google-cloud-error-reporting==0.30.1 +google-cloud-logging==1.11.0 +google-gax==0.16.0 +googleapis-common-protos==1.5.6 +grpcio==1.30.0 +home-monitoring==0.13.dev0 +httplib2==0.12.0 +identify==1.4.5 +idna==2.8 +importlib-metadata==0.19 +importlib-resources==1.0.2 +ipaddress==1.0.22 +mock==2.0.0 +monotonic==1.5 +msgpack==0.6.1 +netifaces==0.10.9 +networkx==2.2 +nodeenv==1.3.3 +oauth2client==4.1.3 +pathlib2==2.3.4 +pbr==5.1.2 +ply==3.8 +pre-commit==1.17.0 +protobuf==3.6.1 +psutil==5.5.0 +pyasn1-modules==0.2.4 +pyasn1==0.4.5 +pycparser==2.19 +pycrypto==2.6.1 +pygraphviz==1.5 +pyopenssl==19.0.0 +pytz==2018.9 +pyyaml==5.1.2 +requests==2.21.0 +rsa==4.0 +scandir==1.10.0 +six==1.12.0 +toml==0.10.0 +typing==3.7.4 +urllib3==1.24.1 +virtualenv==16.7.2 +wand==0.4.4 +zipp==0.5.2 + +# The following packages are considered to be unsafe in a requirements file: +# setuptools
diff --git a/cq/requirements_recipe3.in b/cq/requirements_recipe3.in new file mode 100644 index 0000000..568b800 --- /dev/null +++ b/cq/requirements_recipe3.in
@@ -0,0 +1,70 @@ +# +# Please update cq/requirements_recipe_test.in in case of changes here +# +# Explicit packages +home-monitoring==0.13.dev0 +google-api-core[grpc]==1.13.0 +google-apitools==0.5.31 +google-cloud-error-reporting==0.30.1 +netifaces==0.10.9 +networkx==2.2 +mock==2.0.0 +ply==3.8 +pyopenssl==19.0.0 +pre-commit==1.17.0 +psutil==5.5.0 +pycrypto==2.6.1 +pygraphviz==1.5 +requests==2.21.0 +wand==0.4.4 + +# Implicit packages +asn1crypto==0.24.0 # via cryptography +aspy.yaml==1.3.0 # via pre-commit +cachetools==3.1.0 # via google-auth +certifi==2018.11.29 # via requests +cffi==1.14.0 # via cryptography +cfgv==2.0.1 # via pre-commit +chardet==3.0.4 # via requests +configparser==3.7.4 # via importlib-metadata +contextlib2==0.5.5 # via importlib-metadata +cryptography==2.5 # via pyopenssl +decorator==4.3.2 # via networkx +dill==0.2.9 # via google-gax +enum34==1.1.6 # via grpcio +fasteners==0.14.1 # via google-apitools +fluent-logger==0.9.6 # via home-monitoring +future==0.16.0 # via google-gax +google-auth==1.6.2 # via google-api-core +google-cloud-core==1.0.2 # via google-cloud-logging +google-cloud-logging==1.11.0 # via google-cloud-error-reporting, home-monitoring +google-gax==0.16.0 # via home-monitoring +googleapis-common-protos==1.5.6 # via google-api-core +grpcio==1.30.0 # via google-api-core +httplib2==0.12.0 # via google-apitools, oauth2client +identify==1.4.5 # via pre-commit +idna==2.8 # via requests +importlib-metadata==0.19 # via importlib-resources, pre-commit +importlib-resources==1.0.2 # via pre-commit +ipaddress==1.0.22 # via cryptography +monotonic==1.5 # via fasteners +msgpack==0.6.1 # via fluent-logger +nodeenv==1.3.3 # via pre-commit +oauth2client==4.1.3 # via google-apitools +pathlib2==2.3.4 # via importlib-metadata, importlib-resources +ply==3.8 # via google-gax +pbr==5.1.2 # via mock +protobuf==3.6.1 # via google-api-core, googleapis-common-protos +pyasn1-modules==0.2.4 # via google-auth, oauth2client +pyasn1==0.4.5 # via oauth2client, pyasn1-modules, rsa +pycparser==2.19 # via cffi +pytz==2018.9 # via google-api-core +pyyaml==5.1.2 # via pre-commit, aspy.yaml +rsa==4.0 # via google-auth, oauth2client +scandir==1.10.0 # via pathlib2 +six==1.12.0 # via fasteners, google-api-core, google-apitools, google-auth, grpcio, oauth2client, protobuf +toml==0.10.0 # via pre-commit +typing==3.7.4 # via importlib-resources +urllib3==1.24.1 # via requests +virtualenv==16.7.2 # via pre-commit +zipp==0.5.2 # via importlib-metadata
diff --git a/cq/requirements_recipe3.txt b/cq/requirements_recipe3.txt new file mode 100644 index 0000000..7338081 --- /dev/null +++ b/cq/requirements_recipe3.txt
@@ -0,0 +1,242 @@ +# +# This file is autogenerated by pip-compile +# To update, run: +# +# pip-compile cq/requirements_recipe3.in +# +asn1crypto==0.24.0 + # via + # -r cq/requirements_recipe3.in + # cryptography +aspy.yaml==1.3.0 + # via + # -r cq/requirements_recipe3.in + # pre-commit +cachetools==3.1.0 + # via + # -r cq/requirements_recipe3.in + # google-auth +certifi==2018.11.29 + # via + # -r cq/requirements_recipe3.in + # requests +cffi==1.14.0 + # via + # -r cq/requirements_recipe3.in + # cryptography +cfgv==2.0.1 + # via + # -r cq/requirements_recipe3.in + # pre-commit +chardet==3.0.4 + # via + # -r cq/requirements_recipe3.in + # requests +configparser==3.7.4 + # via -r cq/requirements_recipe3.in +contextlib2==0.5.5 + # via -r cq/requirements_recipe3.in +cryptography==2.5 + # via + # -r cq/requirements_recipe3.in + # pyopenssl +decorator==4.3.2 + # via + # -r cq/requirements_recipe3.in + # networkx +dill==0.2.9 + # via + # -r cq/requirements_recipe3.in + # google-gax +enum34==1.1.6 + # via -r cq/requirements_recipe3.in +fasteners==0.14.1 + # via + # -r cq/requirements_recipe3.in + # google-apitools +fluent-logger==0.9.6 + # via -r cq/requirements_recipe3.in +future==0.16.0 + # via + # -r cq/requirements_recipe3.in + # google-gax +google-api-core[grpc]==1.13.0 + # via + # -r cq/requirements_recipe3.in + # google-cloud-core + # google-cloud-logging +google-apitools==0.5.31 + # via -r cq/requirements_recipe3.in +google-auth==1.6.2 + # via + # -r cq/requirements_recipe3.in + # google-api-core + # google-gax +google-cloud-core==1.0.2 + # via + # -r cq/requirements_recipe3.in + # google-cloud-logging +google-cloud-error-reporting==0.30.1 + # via -r cq/requirements_recipe3.in +google-cloud-logging==1.11.0 + # via + # -r cq/requirements_recipe3.in + # google-cloud-error-reporting +google-gax==0.16.0 + # via -r cq/requirements_recipe3.in +googleapis-common-protos==1.5.6 + # via + # -r cq/requirements_recipe3.in + # google-api-core + # google-gax +grpcio==1.30.0 + # via + # -r cq/requirements_recipe3.in + # google-api-core + # google-gax +home-monitoring==0.13.dev0 + # via -r cq/requirements_recipe3.in +httplib2==0.12.0 + # via + # -r cq/requirements_recipe3.in + # google-apitools + # oauth2client +identify==1.4.5 + # via + # -r cq/requirements_recipe3.in + # pre-commit +idna==2.8 + # via + # -r cq/requirements_recipe3.in + # requests +importlib-metadata==0.19 + # via + # -r cq/requirements_recipe3.in + # pre-commit +importlib-resources==1.0.2 + # via -r cq/requirements_recipe3.in +ipaddress==1.0.22 + # via -r cq/requirements_recipe3.in +mock==2.0.0 + # via -r cq/requirements_recipe3.in +monotonic==1.5 + # via + # -r cq/requirements_recipe3.in + # fasteners +msgpack==0.6.1 + # via + # -r cq/requirements_recipe3.in + # fluent-logger +netifaces==0.10.9 + # via -r cq/requirements_recipe3.in +networkx==2.2 + # via -r cq/requirements_recipe3.in +nodeenv==1.3.3 + # via + # -r cq/requirements_recipe3.in + # pre-commit +oauth2client==4.1.3 + # via + # -r cq/requirements_recipe3.in + # google-apitools +pathlib2==2.3.4 + # via -r cq/requirements_recipe3.in +pbr==5.1.2 + # via + # -r cq/requirements_recipe3.in + # mock +ply==3.8 + # via + # -r cq/requirements_recipe3.in + # google-gax +pre-commit==1.17.0 + # via -r cq/requirements_recipe3.in +protobuf==3.6.1 + # via + # -r cq/requirements_recipe3.in + # google-api-core + # google-gax + # googleapis-common-protos +psutil==5.5.0 + # via -r cq/requirements_recipe3.in +pyasn1-modules==0.2.4 + # via + # -r cq/requirements_recipe3.in + # google-auth + # oauth2client +pyasn1==0.4.5 + # via + # -r cq/requirements_recipe3.in + # oauth2client + # pyasn1-modules + # rsa +pycparser==2.19 + # via + # -r cq/requirements_recipe3.in + # cffi +pycrypto==2.6.1 + # via -r cq/requirements_recipe3.in +pygraphviz==1.5 + # via -r cq/requirements_recipe3.in +pyopenssl==19.0.0 + # via -r cq/requirements_recipe3.in +pytz==2018.9 + # via + # -r cq/requirements_recipe3.in + # google-api-core +pyyaml==5.1.2 + # via + # -r cq/requirements_recipe3.in + # aspy.yaml + # pre-commit +requests==2.21.0 + # via + # -r cq/requirements_recipe3.in + # google-api-core + # google-gax +rsa==4.0 + # via + # -r cq/requirements_recipe3.in + # google-auth + # oauth2client +scandir==1.10.0 + # via -r cq/requirements_recipe3.in +six==1.12.0 + # via + # -r cq/requirements_recipe3.in + # cfgv + # cryptography + # fasteners + # google-api-core + # google-apitools + # google-auth + # grpcio + # mock + # oauth2client + # pathlib2 + # pre-commit + # protobuf + # pyopenssl +toml==0.10.0 + # via + # -r cq/requirements_recipe3.in + # pre-commit +typing==3.7.4 + # via -r cq/requirements_recipe3.in +urllib3==1.24.1 + # via + # -r cq/requirements_recipe3.in + # requests +virtualenv==16.7.2 + # via + # -r cq/requirements_recipe3.in + # pre-commit +wand==0.4.4 + # via -r cq/requirements_recipe3.in +zipp==0.5.2 + # via + # -r cq/requirements_recipe3.in + # importlib-metadata + +# The following packages are considered to be unsafe in a requirements file: +# setuptools
diff --git a/cq/scripts/__init__.py b/cq/scripts/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/cq/scripts/__init__.py
diff --git a/cq/scripts/helpers/__init__.py b/cq/scripts/helpers/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/cq/scripts/helpers/__init__.py
diff --git a/cq/scripts/helpers/accelerator_utils.py b/cq/scripts/helpers/accelerator_utils.py new file mode 100644 index 0000000..fea0a05 --- /dev/null +++ b/cq/scripts/helpers/accelerator_utils.py
@@ -0,0 +1,6 @@ +from slave.accelerator import no_accelerator +from slave.accelerator import rbe_accelerator + + +def get_build_accelerator(): + return rbe_accelerator.Accelerator()
diff --git a/cq/scripts/helpers/branch_utils.py b/cq/scripts/helpers/branch_utils.py new file mode 100644 index 0000000..c0841e9 --- /dev/null +++ b/cq/scripts/helpers/branch_utils.py
@@ -0,0 +1,80 @@ +"""Utilities related to the Cast branching scheme.""" + +from __future__ import absolute_import +import re + +RELEASE_BRANCH_PATTERN = r'(?P<major>\d+)\.(?P<minor>\d+)(?P<version>.+)?' +# See go/nest-tv-branch-strategy. +ANDROID_TV_RELEASE_BRANCH_PATTERN = (r'^android(\d+)-(\d+\.\d+)-(.+)' + r'-(factory|ota)(|\d+)$') + + +def parse_release_branch(branch_name): + """Converts string branch_name to tuple (int major, int minor, version).""" + match = re.match(RELEASE_BRANCH_PATTERN, branch_name) + if not match: + raise ValueError('Invalid branch name: {}'.format(branch_name)) + major = int(match.group('major')) + minor = int(match.group('minor')) + version = match.group('version') + try: + version = int(version) + except (TypeError, ValueError): + pass + return major, minor, version + + +def is_release_branch(branch): + """Returns True if |branch| matching release branch patterns.""" + return (branch and + (re.match(RELEASE_BRANCH_PATTERN, branch) or + re.match(ANDROID_TV_RELEASE_BRANCH_PATTERN, branch))) + + +def is_master_branch(branch): + """Returns True if |branch| is a master branch.""" + return branch == 'master' + + +def is_branch_equal_to_or_later_than(branch, threshold): + """Returns True if |branch| is at least as new as |threshold|. + + Returns False if |branch| is older than |threshold|. Returns True if + |branch| is newer than |threshold|, matches |threshold|, or is 'master'. + + Args: + branch: A Cast branch, of the form X.YY{a-d} or 'master'. + threshold: A Cast branch, of the form X.YY{a-d} or 'master'. + + Returns: + True if |branch| is at least as new as |threshold|. + + Raises: + ValueError: if either |branch| or |threshold| is poorly-formed. + """ + if is_master_branch(branch): + return True + # This means it is a named branch. Usually a bringup branch so we should run + # everything. + if not is_release_branch(branch): + return True + # Exclude Android TV release branch from version comparison. + if re.match(ANDROID_TV_RELEASE_BRANCH_PATTERN, branch): + return True + if threshold == 'master': + return False + if threshold is None: + return True + + t_major, t_minor, t_ver = parse_release_branch(threshold) + major, minor, ver = parse_release_branch(branch) + t_ver = t_ver if t_ver is not None else -1 + ver = ver if ver is not None else -1 + # If the version is a string for one of them we need to compare both as + # strings. + if any(isinstance(v, str) for v in (t_ver, ver)): + t_ver = str(t_ver) + ver = str(ver) + return (major > t_major or + (major == t_major and minor > t_minor) or + (major == t_major and minor == t_minor and ver >= t_ver))
diff --git a/cq/scripts/helpers/branch_utils_test.py b/cq/scripts/helpers/branch_utils_test.py new file mode 100644 index 0000000..e340919 --- /dev/null +++ b/cq/scripts/helpers/branch_utils_test.py
@@ -0,0 +1,127 @@ +"""Tests for branch_utils.""" + +from __future__ import absolute_import +import os +import sys +import unittest + +# Allow imports from cq/scripts folder +sys.path.insert( + 0, + os.path.realpath(os.path.join(os.path.dirname(__file__), os.pardir))) +from helpers import branch_utils + + +class BranchUtilsTest(unittest.TestCase): + + def testAnyBranchAlwaysLaterThanNone(self): + """Test that the master branch is always the latest branch.""" + self.assertTrue( + branch_utils.is_branch_equal_to_or_later_than('master', None)) + self.assertTrue( + branch_utils.is_branch_equal_to_or_later_than('0.00', None)) + self.assertTrue( + branch_utils.is_branch_equal_to_or_later_than('3.45', None)) + + def testMasterBranchAlwaysLatest(self): + """Test that the master branch is always the latest branch.""" + self.assertTrue( + branch_utils.is_branch_equal_to_or_later_than('master', 'master')) + self.assertTrue( + branch_utils.is_branch_equal_to_or_later_than('master', '2.34')) + self.assertTrue( + branch_utils.is_branch_equal_to_or_later_than('master', '0.00')) + self.assertFalse( + branch_utils.is_branch_equal_to_or_later_than('3.45', 'master')) + self.assertFalse( + branch_utils.is_branch_equal_to_or_later_than('0.00', 'master')) + + def testNamedBranchLatest(self): + self.assertTrue( + branch_utils.is_branch_equal_to_or_later_than('pi-tv-dev', 'master')) + self.assertTrue( + branch_utils.is_branch_equal_to_or_later_than('pi-tv-dev', '2.34')) + self.assertTrue( + branch_utils.is_branch_equal_to_or_later_than('pi-tv-dev', '0.00')) + + def testAndroidTvBranchLatest(self): + self.assertTrue(branch_utils.is_branch_equal_to_or_later_than( + 'android12-5.4-boreal', None)) + self.assertTrue(branch_utils.is_branch_equal_to_or_later_than( + 'android12-5.4-boreal', 'master')) + self.assertTrue(branch_utils.is_branch_equal_to_or_later_than( + 'android12-5.4-boreal', '2.34')) + # Android TV release branch. + self.assertTrue(branch_utils.is_branch_equal_to_or_later_than( + 'android12-5.4-boreal-factory', None)) + self.assertTrue(branch_utils.is_branch_equal_to_or_later_than( + 'android12-5.4-boreal-factory', 'master')) + self.assertTrue(branch_utils.is_branch_equal_to_or_later_than( + 'android12-5.4-boreal-factory', '2.34')) + + def testBasicBranchComparison(self): + """Test that branches compare properly to one another.""" + self.assertFalse( + branch_utils.is_branch_equal_to_or_later_than('1.21', '2.34')) + self.assertTrue( + branch_utils.is_branch_equal_to_or_later_than('2.34', '1.21')) + self.assertFalse( + branch_utils.is_branch_equal_to_or_later_than('2.1', '11.1')) + self.assertTrue( + branch_utils.is_branch_equal_to_or_later_than('11.1', '2.1')) + self.assertTrue( + branch_utils.is_branch_equal_to_or_later_than('1.21', '1.21')) + + def testBranchesWithSameMajorDifferentMinor(self): + """Test that branches with the same major revision compare properly.""" + self.assertFalse( + branch_utils.is_branch_equal_to_or_later_than('1.21', '1.22')) + self.assertTrue( + branch_utils.is_branch_equal_to_or_later_than('1.22', '1.21')) + self.assertTrue( + branch_utils.is_branch_equal_to_or_later_than('1.100', '1.23')) + self.assertFalse( + branch_utils.is_branch_equal_to_or_later_than('1.23', '1.100')) + + def testBranchesWithSameMajorAndMinorDifferentVersion(self): + """Test same major, minor, but with a different verison.""" + self.assertFalse( + branch_utils.is_branch_equal_to_or_later_than('1.21', '1.21a')) + self.assertTrue( + branch_utils.is_branch_equal_to_or_later_than('1.21a', '1.21')) + self.assertFalse( + branch_utils.is_branch_equal_to_or_later_than('1.21a', '1.21b')) + self.assertTrue( + branch_utils.is_branch_equal_to_or_later_than('1.21b', '1.21a')) + self.assertFalse( + branch_utils.is_branch_equal_to_or_later_than('1.21d', '1.22')) + self.assertTrue( + branch_utils.is_branch_equal_to_or_later_than('1.22', '1.21d')) + self.assertTrue( + branch_utils.is_branch_equal_to_or_later_than('1.21d', '1.21d')) + + def testReleaseBranches(self): + self.assertFalse(branch_utils.is_release_branch(None)) + self.assertFalse(branch_utils.is_release_branch('')) + self.assertFalse(branch_utils.is_release_branch('master')) + self.assertFalse(branch_utils.is_release_branch('estelle')) + self.assertFalse(branch_utils.is_release_branch('android12-5.4-boreal')) + self.assertTrue(branch_utils.is_release_branch('1.36')) + self.assertTrue(branch_utils.is_release_branch('1.36a')) + self.assertTrue(branch_utils.is_release_branch('1.36_sdk_estelle')) + self.assertTrue(branch_utils.is_release_branch( + 'android12-5.4-boreal-factory')) + self.assertTrue(branch_utils.is_release_branch( + 'android12-5.4-boreal-ota12')) + + def testMasterBranches(self): + self.assertFalse(branch_utils.is_master_branch(None)) + self.assertFalse(branch_utils.is_master_branch('')) + self.assertFalse(branch_utils.is_master_branch('estelle')) + self.assertFalse(branch_utils.is_master_branch('1.36')) + self.assertFalse(branch_utils.is_master_branch('1.36a')) + self.assertFalse(branch_utils.is_master_branch('1.36_sdk_estelle')) + self.assertTrue(branch_utils.is_master_branch('master')) + +if __name__ == '__main__': + unittest.main()
diff --git a/cq/scripts/helpers/cast_shell_utils.py b/cq/scripts/helpers/cast_shell_utils.py new file mode 100644 index 0000000..edb1377 --- /dev/null +++ b/cq/scripts/helpers/cast_shell_utils.py
@@ -0,0 +1,266 @@ +"""Utils for running a desktop cast_shell instance.""" + +from __future__ import absolute_import +import json +import logging +import os +import shutil +import socket +import sys +import time + +# The step property key that stores the cast_shell executable path. +CAST_SHELL_EXE_PATH = 'cast_shell_exe_path' + +_AVAILABILITY_RETRY_WAIT_TIME_SECS = 10 +_AVAILABILITY_WAIT_TIME_SECS = 80 +_CAST_V2_DEBUG_APP_ID = 'C566BECD' +_CONNECTION_NAMESPACE = 'urn:x-cast:com.google.cast.tp.connection' +_SETUP_API_ROOT = 'http://{device_ip}:8008/setup/{api}' +_OZONE_PLATFORM_CAST = 'cast' +_OZONE_PLATFORM_HEADLESS = 'headless' # Used for chirp_shell. + +# Default cast_shell parameters +_CAST_V2_PORT = 8009 +_MULTIZONE_PORT = 10001 +_REMOTE_DUBIGGING_PORT = 9222 +_MDNS_MULTICAST_PORT = 5353 +_GCM_SUB_PATH = 'gcm_cast_cq' + +_DUMP_LOGCAT_MSG = ('dump of cast_shell logs: \n' + '*** BEGIN CAST_SHELL ***\n' + '%s\n' + '*** END CAST_SHELL ***\n') + + +class CastShellError(Exception): + """An error while trying to use cast_shell.""" + + +class CastShellTimeoutError(Exception): + """A timeout error while trying to use cast_shell.""" + + +def start_cast_shell(executor, + test_project_path, + cast_shell_path, + tmp_dir, + enable_cma_media_pipeline=False, + enable_ccs_transport_v2=False, + use_headless_ozone_platform=False, + launch_utility_process=False): + """Starts a local x86 cast shell. + + Note: if multiple cast_shell instances are to be started, they must + all have unique ports for all the keyword ports specified below and unique + HOME and TMPDIR directories. + + Args: + executor: Executor to run the subprocess + test_project_path: Path to the 'test' project. This will be appened to the + sys.path if it is not already there. + cast_shell_path: Path the to cast_shell executable + tmp_dir: A temporary dir to use as HOME and TMPDIR. If there are multiple + cast_shell instances, this should be unique across all instances. + enable_cma_media_pipeline: If True, pass in --enable-cma-media-pipeline + enable_ccs_transport_v2: If True, pass in --enable-ccs-transport-v2 + use_headless_ozone_platform: If True, use "headless" as --ozone-platform + (required for assistant-enabled cast_shells); otherwise, uses "cast". + launch_utility_process: If True, launches the utility process (required to + start the assistant debug HTTP server at port 8007). + + Returns: + A tuple of (<started subprocess>, + <file descriptor of cast_shell output file>, + <absolute path of cast_shell output file>). + These can be passed to upload_cast_shell_logs() below to store the log + files in GCS. + + Raises: + CastShellError: if cast_shell does not start correctly. + CastShellTimeoutError: if cast_shell takes too long to become available. + """ + if test_project_path not in sys.path: + sys.path.append(test_project_path) + + if use_headless_ozone_platform: + ozone_platform = _OZONE_PLATFORM_HEADLESS + else: + ozone_platform = _OZONE_PLATFORM_CAST + + command = [ + cast_shell_path, + '--no-sandbox', + '--disable-gpu', + '--ignore-gpu-blacklist', + '--ozone-platform={}'.format(ozone_platform), + '--port-for-cast-v2={}'.format(_CAST_V2_PORT), + '--port-for-multizone={}'.format(_MULTIZONE_PORT), + '--remote-debugging-port={}'.format(_REMOTE_DUBIGGING_PORT), + '--port-for-mdns-multicast={}'.format(_MDNS_MULTICAST_PORT), + '--gcm-sub-path="{}"'.format(_GCM_SUB_PATH), + '--disable-reboot-on-config-update', + ] + + if launch_utility_process: + # max-output-volume-dba1m is required when --launch-utility-process + # is specified. + command.extend(['--launch-utility-process', '--max-output-volume-dba1m=88']) + + if enable_cma_media_pipeline: + command.append('--enable-cma-media-pipeline') + if enable_ccs_transport_v2: + command.append('--enable-ccs-transport-v2') + + # HOME and TMPDIR should be unique across any running cast_shell instances. + cast_shell_env = {'HOME': tmp_dir, 'TMPDIR': tmp_dir} + + try: + subprocess, log_file_descriptor, log_file_path = ( + executor.exec_non_blocking_subprocess(command, env=cast_shell_env)) + + if subprocess.returncode is not None: + raise CastShellError('cast_shell startup failed') + + if not _await_cast_shell_availability(): + raise CastShellTimeoutError( + 'cast_shell took too long to become available.') + + except: + logging.exception('Unable to start Cast Shell.') + _dump_cast_shell_logs(log_file_descriptor, log_file_path) + raise + + logging.info('cast_shell started successfully.') + return subprocess, log_file_descriptor, log_file_path + + +def _dump_cast_shell_logs(log_file_descriptor, log_file_path): + """Dump the cast_shell logcat to the logger.""" + os.fsync(log_file_descriptor) + os.close(log_file_descriptor) + with open(log_file_path, 'r') as log_file: + logging.info(_DUMP_LOGCAT_MSG, log_file.read()) + + +def upload_cast_shell_logs(log_file_descriptor, log_file_path, gcs_root_dir, + sub_dir, upload_file_name): + """Move the process log file into GCS folder so that it's uploaded. + + Args: + log_file_descriptor: File descriptor of log file to be copied. This should + be the descriptor returned by start_cast_shell() above. + log_file_path: Absolute path of the log file to be copied. This should be + the path returned by start_cast_shell() above. + gcs_root_dir: The GCS directory. + sub_dir: The sub directory within GCS to upload to. + upload_file_name: A string; log file will be renamed and uploaded with this + name. + """ + output_dir = os.path.join(gcs_root_dir, sub_dir) + if not os.path.exists(output_dir): + os.makedirs(output_dir) + os.fsync(log_file_descriptor) + shutil.copy(log_file_path, os.path.join(output_dir, upload_file_name)) + logging.info( + 'cast_shell log will be avilable on GCS in the gs://cast-cq bucket under ' + '%s for this CL. (See the end of stdio of the "shell" step for the ' + 'specific path. It should be similar to: ' + 'gs://cast-cq/eureka-interal/project/branch/issue/patchset', + os.path.join(sub_dir, upload_file_name)) + + +def _get_eureka_info(executor, ip_address='localhost', params=None): + """Returns the parsed eureka info. + + The //chromecast/internal/setup/eureka_info.h describes the various fields + that will be available. + + This assumes that a cast_shell instance is available at |ip_address| (such + as from running start_cast_shell above). + + Args: + executor: Executor to run the subprocess + ip_address: IP address (as a string) of the device to get the info from. + (Defaults to 'localhost') + params: A list of parameters (as strings) to get from euruka_info. This must + be specified and cannot be an empty list. e.g. params=['name', + 'wifi.ssid', 'setup.stats.num_obtain_ip'] will + return {'name': 'devicename', + 'wifi': {'ssid': 'wifi-ssid-value'}, + 'setup': {'stats': {'num_obtain_ip': 0}}} + + Returns: + A dict with the eureka_info information on success, or an empty dict on + failure. + """ + api_endpoint = _SETUP_API_ROOT.format( + device_ip=ip_address, + api='eureka_info?params={}'.format(','.join(params))) + logging.info('Making Request to API Endpoint: %s', api_endpoint) + returncode, json_result, _ = executor.exec_subprocess(['curl', api_endpoint], + quiet=True) + if returncode == 0: + return json.loads(json_result) + + return {} + + +def get_device_name(executor, ip_address='localhost'): + """Returns the name of the device at |ip_address|.""" + return _get_eureka_info(executor, ip_address, ['name']).get('name') + + +def _await_cast_shell_availability(max_wait_time=_AVAILABILITY_WAIT_TIME_SECS): + """Wait's until max_wait_time seconds for cast shell availability. + + Args: + max_wait_time: Integer of wait time in seconds. + + Returns: + True if cast shell is up and running. + """ + remaining_time = max_wait_time + while remaining_time >= 0: + time.sleep(_AVAILABILITY_RETRY_WAIT_TIME_SECS) + remaining_time -= _AVAILABILITY_RETRY_WAIT_TIME_SECS + try: + if _connect_cast_shell(): + return True + except (socket.error, AssertionError): + logging.exception('Cast shell is not ready, will retry for %d seconds', + remaining_time) + return False + + +def _connect_cast_shell(): + """Returns True if able to to connect and send a message to cast shell. + + Returns: + True if able to to connect and send a message to cast shell. + + Raises: + Socket.error: if not able to connect to cast shell. + AssertionError: if not able to send message to cast shell. + """ + + # Assumes that test/ is on the PYTHONPATH + transport = __import__( + 'cast.tools.transport', + fromlist=[ + 'application', 'application_connection', 'receiver', 'transport' + ]) + receiver = transport.receiver.Receiver('receiver-0', 'localhost') + app = transport.application.Application(receiver, _CAST_V2_DEBUG_APP_ID) + try: + with (transport.application_connection.ApplicationConnection( + app, 'sender-1')) as app_conn: + app_conn.ConnectToReceiver() + message = transport.transport.BuildMessage( + 'sender-1', 'receiver-0', _CONNECTION_NAMESPACE, b'', binary=True) + app_conn.Send(message) + app_conn.Status() + except transport.socket_helper.SocketError as e: + raise socket.error(socket.error(e), sys.exc_info()[2]) + + return True
diff --git a/cq/scripts/helpers/cipd_upload_utils.py b/cq/scripts/helpers/cipd_upload_utils.py new file mode 100644 index 0000000..d15dba5 --- /dev/null +++ b/cq/scripts/helpers/cipd_upload_utils.py
@@ -0,0 +1,60 @@ +"""Collection of utility functions for uploading CIPD packages. + +Note: cipd is included in depot_tools. These utils assume depot_tools has been +included in $PATH. +""" + +from __future__ import absolute_import +import logging + + +def UploadCIPDPackage(executor, + pkg_def, + pkg_vars=None, + refs=None, + tags=None, + verification_timeout=None, + service_account_json=None, + dry_run=False): + """Uploads a new CIPD package, defined by pkg-def. + + Args: + executor: Executes the subprocess. + pkg_def: Path to cipd pkg-def .yaml file. + pkg_vars: A dict of variables to pass to cipd with -pkg-var. + refs: A list of refs to be assigned to the uploaded cipd package. + tags: A dict of tags to be assigned to the uploaded cipd package. + verification_timeout: Time allotted for cipd verification step ('XXmXXs'). + service_account_json: Path to service account JSON auth token. + dry_run: Boolean, if True skip actual upload. + + Returns: + Tuple of (return code, full stdout output, full stderr output). + """ + pkg_vars = pkg_vars or {} + refs = refs or [] + tags = tags or {} + cmd = [ + 'cipd', 'create', + '-pkg-def', pkg_def] + for key in pkg_vars.keys(): + value = pkg_vars[key] + var = ':'.join([str(key), str(value)]) + cmd += ['-pkg-var', var] + for ref in refs: + cmd += ['-ref', ref] + for key in tags.keys(): + value = tags[key] + tag = ':'.join([str(key), str(value)]) + cmd += ['-tag', tag] + + if verification_timeout: + cmd += ['-verification-timeout', verification_timeout] + + if service_account_json: + cmd += ['-service-account-json', service_account_json] + + if dry_run: + logging.info('CIPD upload command: %s', cmd) + cmd = ['echo'] + cmd + return executor.exec_subprocess(cmd)
diff --git a/cq/scripts/helpers/cipd_upload_utils_test.py b/cq/scripts/helpers/cipd_upload_utils_test.py new file mode 100644 index 0000000..f9f92ff --- /dev/null +++ b/cq/scripts/helpers/cipd_upload_utils_test.py
@@ -0,0 +1,50 @@ +"""Test for cipd_upload_utils.""" +import unittest +import unittest.mock + +from cq.scripts.helpers import cipd_upload_utils + + +class CIPDUploadUtilsTest(unittest.TestCase): + + def setUp(self): + self._executor = unittest.mock.MagicMock() + + def testUploadCIPDPackage(self): + """Verifies simple UploadCIPDPackage call.""" + pkg_def = '/path/to/pkg.yaml' + + cipd_upload_utils.UploadCIPDPackage(self._executor, pkg_def, dry_run=False) + + self._executor.exec_subprocess.assert_called_once_with([ + 'cipd', 'create', '-pkg-def', pkg_def]) + + def testUploadCIPDPackageAllArgs(self): + """Verifies UploadCIPDPackage with all args specified.""" + pkg_def = '/path/to/pkg.yaml' + refs = ['test', 'latest'] + tags = {'tag1': 'this', 'tag2': 'that'} + verification_timeout = '5m0s' + service_account_json = '/path/to/token.json' + + cipd_upload_utils.UploadCIPDPackage( + self._executor, + pkg_def, + refs=refs, + tags=tags, + verification_timeout=verification_timeout, + service_account_json=service_account_json, + dry_run=False) + + self._executor.exec_subprocess.assert_called_once_with([ + 'cipd', 'create', + '-pkg-def', pkg_def, + '-ref', 'test', + '-ref', 'latest', + '-tag', 'tag1:this', '-tag', 'tag2:that', + '-verification-timeout', verification_timeout, + '-service-account-json', service_account_json,]) + + +if __name__ == '__main__': + unittest.main()
diff --git a/cq/scripts/helpers/clang_format/clang-format-diff.py b/cq/scripts/helpers/clang_format/clang-format-diff.py new file mode 100644 index 0000000..ef59d17 --- /dev/null +++ b/cq/scripts/helpers/clang_format/clang-format-diff.py
@@ -0,0 +1,123 @@ +#!/usr/bin/env python +# +#===- clang-format-diff.py - ClangFormat Diff Reformatter ----*- python -*--===# +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +#===------------------------------------------------------------------------===# + +r""" +ClangFormat Diff Reformatter +============================ + +This script reads input from a unified diff and reformats all the changed +lines. This is useful to reformat all the lines touched by a specific patch. +Example usage for git/svn users: + + git diff -U0 HEAD^ | clang-format-diff.py -p1 -i + svn diff --diff-cmd=diff -x-U0 | clang-format-diff.py -i + +""" + +from __future__ import absolute_import +from __future__ import print_function +import argparse +import difflib +import re +import string +import subprocess +import StringIO +import sys + + +def main(): + parser = argparse.ArgumentParser(description= + 'Reformat changed lines in diff. Without -i ' + 'option just output the diff that would be ' + 'introduced.') + parser.add_argument('-i', action='store_true', default=False, + help='apply edits to files instead of displaying a diff') + parser.add_argument('-p', metavar='NUM', default=0, + help='strip the smallest prefix containing P slashes') + parser.add_argument('-regex', metavar='PATTERN', default=None, + help='custom pattern selecting file paths to reformat ' + '(case sensitive, overrides -iregex)') + parser.add_argument('-iregex', metavar='PATTERN', default= + r'.*\.(cpp|cc|c\+\+|cxx|c|cl|h|hpp|m|mm|inc|js|ts|proto' + r'|protodevel|java)', + help='custom pattern selecting file paths to reformat ' + '(case insensitive, overridden by -regex)') + parser.add_argument('-sort-includes', action='store_true', default=False, + help='let clang-format sort include blocks') + parser.add_argument('-v', '--verbose', action='store_true', + help='be more verbose, ineffective without -i') + parser.add_argument('-style', + help='formatting style to apply (LLVM, Google, Chromium, ' + 'Mozilla, WebKit)') + parser.add_argument('-binary', default='clang-format', + help='location of binary to use for clang-format') + args = parser.parse_args() + + # Extract changed lines for each file. + filename = None + lines_by_file = {} + for line in sys.stdin: + match = re.search('^\+\+\+\ (.*?/){%s}(\S*)' % args.p, line) + if match: + filename = match.group(2) + if filename is None: + continue + + if args.regex is not None: + if not re.match('^%s$' % args.regex, filename): + continue + else: + if not re.match('^%s$' % args.iregex, filename, re.IGNORECASE): + continue + + match = re.search('^@@.*\+(\d+)(,(\d+))?', line) + if match: + start_line = int(match.group(1)) + line_count = 1 + if match.group(3): + line_count = int(match.group(3)) + if line_count == 0: + continue + end_line = start_line + line_count - 1; + lines_by_file.setdefault(filename, []).extend( + ['-lines', str(start_line) + ':' + str(end_line)]) + + # Reformat files containing changes in place. + for filename, lines in lines_by_file.items(): + if args.i and args.verbose: + print('Formatting', filename) + command = [args.binary, filename] + if args.i: + command.append('-i') + if args.sort_includes: + command.append('-sort-includes') + command.extend(lines) + if args.style: + command.extend(['-style', args.style]) + p = subprocess.Popen(command, stdout=subprocess.PIPE, + stderr=None, stdin=subprocess.PIPE) + stdout, _ = p.communicate() + if p.returncode != 0: + sys.exit(p.returncode); + + if not args.i: + with open(filename) as f: + code = f.readlines() + formatted_code = StringIO.StringIO(stdout).readlines() + diff = difflib.unified_diff(code, formatted_code, + filename, filename, + '(before formatting)', '(after formatting)') + diff_string = string.join(diff, '') + if len(diff_string) > 0: + sys.stdout.write(diff_string) + +if __name__ == '__main__': + main()
diff --git a/cq/scripts/helpers/commit_message_utils.py b/cq/scripts/helpers/commit_message_utils.py new file mode 100644 index 0000000..6c9e934 --- /dev/null +++ b/cq/scripts/helpers/commit_message_utils.py
@@ -0,0 +1,17 @@ +"""Encapsulates regex matchers to detect magic keywords in commit messages.""" + +from __future__ import absolute_import +import re + +REVERT = '^Revert' +REVERT_MSG = '^This reverts commit [0-9a-f]{5,40}' +CHERRY_PICK_MSG = r'\(cherry picked from commit [0-9a-f]{5,40}\)' + + +def is_revert_commit_message(commit_message): + return bool(re.search(REVERT, commit_message, re.MULTILINE) or + re.search(REVERT_MSG, commit_message, re.MULTILINE)) + + +def is_cherry_pick_commit_message(commit_message): + return bool(re.search(CHERRY_PICK_MSG, commit_message, re.MULTILINE))
diff --git a/cq/scripts/helpers/commit_message_utils_test.py b/cq/scripts/helpers/commit_message_utils_test.py new file mode 100644 index 0000000..8eefea6 --- /dev/null +++ b/cq/scripts/helpers/commit_message_utils_test.py
@@ -0,0 +1,42 @@ +"""Tests for commit_message_utils.""" +import unittest + +from cq.scripts.helpers import commit_message_utils + +EXAMPLE_REVERT_COMMIT_MESSAGE = """ +Revert "Split AssistantService's implementation off CastService's" + +Revert the commit because it breaks Cast on AT. + +This reverts commit 9c2d5e2bb6d51a8ad6cb9b0fa9c5e867cc525d7a. + +Test: Cast boots again on Jasper on O +Bug: 110371959 + +Change-Id: I3fa23e842985bb673b60ea959b9bff3a484056f3 +""" + +EXAMPLE_NON_REVERT_COMMIT_MESSAGE = """ +Split AssistantService's implementation off CastService's + +Still uses v2 and then Mojo to talk to libassistant, both of which will +now be able to be removed. + +Bug: 109845832 +Test: For the moment only that it compiles (assistant enabled and not). +Change-Id: I22552ed2737d75c62947c8394fb0fab2cf17a013 +""" + +class CommitMessageUtilsTest(unittest.TestCase): + + def testTheCommitMessageThatPromptedChangeInClangFormatStep(self): + self.assertTrue(commit_message_utils.is_revert_commit_message( + EXAMPLE_REVERT_COMMIT_MESSAGE)) + + def testTheCommitMessageForTheChangeThatItWasReverting(self): + self.assertFalse(commit_message_utils.is_revert_commit_message( + EXAMPLE_NON_REVERT_COMMIT_MESSAGE)) + + +if __name__ == '__main__': + unittest.main()
diff --git a/cq/scripts/helpers/coverage_utils.py b/cq/scripts/helpers/coverage_utils.py new file mode 100644 index 0000000..cc0aca7 --- /dev/null +++ b/cq/scripts/helpers/coverage_utils.py
@@ -0,0 +1,31 @@ +"""Contains utils for processing coverage files.""" +import pathlib + +_RBE_PREFIX = pathlib.Path('/b/f/w') + + +def rewrite_file_paths_in_lcov(input_path, output_path, workspace_path): + """Copy the input lcov file to the output, after fixing the paths in it.""" + with open(output_path, 'w') as out_file: + with open(input_path, 'r') as in_file: + for line in in_file: + if line.startswith('SF:'): + path = pathlib.Path(line.removeprefix('SF:').strip()) + path = _convert_to_workspace_relative_path(path, workspace_path) + out_file.write(f'SF:{path}\n') + else: + out_file.write(line) + + +def _convert_to_workspace_relative_path(path, workspace_path): + if not path.is_absolute(): + raise ValueError(f'Expected absolute paths in lcov file, got {path}') + absolute_workspace_path_or_symlink = _fix_rbe_prefix(path, workspace_path) + absolute_workspace_path = absolute_workspace_path_or_symlink.resolve() + return absolute_workspace_path.relative_to(workspace_path) + + +def _fix_rbe_prefix(path, workspace_path): + if path.is_relative_to(_RBE_PREFIX): + return workspace_path / path.relative_to(_RBE_PREFIX) + return path
diff --git a/cq/scripts/helpers/coverage_utils_test.py b/cq/scripts/helpers/coverage_utils_test.py new file mode 100644 index 0000000..88d615a --- /dev/null +++ b/cq/scripts/helpers/coverage_utils_test.py
@@ -0,0 +1,111 @@ +import contextlib +import pathlib +import tempfile +import unittest + +from cq.scripts.helpers import coverage_utils + + +class CoverageUtilsTest(unittest.TestCase): + + def setUp(self): + super().setUp() + with contextlib.ExitStack() as stack: + self._temp_dir_path = pathlib.Path( + stack.enter_context(tempfile.TemporaryDirectory())) + self.addCleanup(stack.pop_all().close) + self._workspace_path = self._temp_dir_path / 'workspace' + self._workspace_path.mkdir() + + def test_rewrite_file_paths_in_lcov_with_rbe_prefix(self): + real_file = self._workspace_path / 'foo' + real_file.touch() + input_file = self._temp_dir_path / 'input.lcov' + input_file.write_text('\n'.join(_lcov_record('/b/f/w/foo'))) + output_file = self._temp_dir_path / 'output.lcov' + + coverage_utils.rewrite_file_paths_in_lcov( + input_file, output_file, self._workspace_path) + + expected_contents = '\n'.join(_lcov_record('foo')) + self.assertEqual(output_file.read_text(), expected_contents) + + def test_rewrite_file_paths_in_lcov_with_symlink(self): + real_file = self._workspace_path / 'real' + real_file.touch() + symlink = self._workspace_path / 'symlink' + symlink.symlink_to(real_file) + input_file = self._temp_dir_path / 'input.lcov' + input_file.write_text('\n'.join(_lcov_record(symlink))) + output_file = self._temp_dir_path / 'output.lcov' + + coverage_utils.rewrite_file_paths_in_lcov( + input_file, output_file, self._workspace_path) + + expected_contents = '\n'.join(_lcov_record('real')) + self.assertEqual(output_file.read_text(), expected_contents) + + def test_rewrite_file_paths_in_lcov_with_rbe_symlink(self): + real_file = self._workspace_path / 'real' + real_file.touch() + symlink = self._workspace_path / 'symlink' + symlink.symlink_to(real_file) + input_file = self._temp_dir_path / 'input.lcov' + input_file.write_text('\n'.join(_lcov_record('/b/f/w/symlink'))) + output_file = self._temp_dir_path / 'output.lcov' + + coverage_utils.rewrite_file_paths_in_lcov( + input_file, output_file, self._workspace_path) + + expected_contents = '\n'.join(_lcov_record('real')) + self.assertEqual(output_file.read_text(), expected_contents) + + def test_rewrite_file_paths_in_lcov_with_absolute_path(self): + real_file = self._workspace_path / 'real' + real_file.touch() + input_file = self._temp_dir_path / 'input.lcov' + input_file.write_text('\n'.join(_lcov_record(real_file))) + output_file = self._temp_dir_path / 'output.lcov' + + coverage_utils.rewrite_file_paths_in_lcov( + input_file, output_file, self._workspace_path) + + expected_contents = '\n'.join(_lcov_record('real')) + self.assertEqual(output_file.read_text(), expected_contents) + + def test_rewrite_file_paths_in_lcov_with_absolute_missing_path(self): + real_file = self._workspace_path / 'real' + input_file = self._temp_dir_path / 'input.lcov' + input_file.write_text('\n'.join(_lcov_record(real_file))) + output_file = self._temp_dir_path / 'output.lcov' + + coverage_utils.rewrite_file_paths_in_lcov( + input_file, output_file, self._workspace_path) + + expected_contents = '\n'.join(_lcov_record('real')) + self.assertEqual(output_file.read_text(), expected_contents) + + def test_rewrite_file_paths_in_lcov_with_relative_path(self): + real_file = self._workspace_path / 'real' + real_file.touch() + input_file = self._temp_dir_path / 'input.lcov' + input_file.write_text('\n'.join(_lcov_record('real'))) + output_file = self._temp_dir_path / 'output.lcov' + + with self.assertRaises(ValueError): + coverage_utils.rewrite_file_paths_in_lcov( + input_file, output_file, self._workspace_path) + + +def _lcov_record(path): + return [ + f'SF:{path}', + 'LH:10', + 'LC:22', + 'end_of_record', + '', + ] + + +if __name__ == '__main__': + unittest.main()
diff --git a/cq/scripts/helpers/data_manager.py b/cq/scripts/helpers/data_manager.py new file mode 100644 index 0000000..721d048 --- /dev/null +++ b/cq/scripts/helpers/data_manager.py
@@ -0,0 +1,143 @@ +"""DataManager to share data between steps.""" + +from __future__ import absolute_import +import copy +import six + +from helpers import repo_utils + + +class DataManager(object): + """Manages passing data between build steps.""" + + def __init__(self, executor, properties): + self._data_store = {} + self._executor = executor + self._project_path_lookup = None + self._project_remote_lookup = None + self._project_revision_lookup = None + self._properties = properties + + def add_data(self, key, data, replace=False): + """Adds data to be retrieved later by other DataManager consumers. + + Args: + key: string value to associate the stored data with. Must not already + have a value stored with that key. + data: any value, not cloned. + replace: if True, any data stored in |key| will be replaced. + if False, a KeyError is raised if |key| already has a value. + (defaults to False) + + Raises: + KeyError: if the key already has an associated value and replace is False. + """ + assert isinstance(key, six.string_types) + if self._data_store.get(key) == data: + return + if key in self._data_store and not replace: + raise KeyError(key) + self._data_store[key] = data + + def clear_project_info(self): + """Clears the project info to be reset in the next run.""" + self._project_path_lookup = None + self._project_remote_lookup = None + self._project_revision_lookup = None + + def contains_project(self, project): + """Boolean if the given project is included in the repo client.""" + if not self._project_path_lookup: + self._project_path_lookup = repo_utils.get_project_path_lookup( + self._executor, self.manifest_url) + return project in self._project_path_lookup + + def ensure_project_info(self): + """Initializes all project lookup tables.""" + if self._project_path_lookup: + return + manifest_content = repo_utils.get_manifest(self._executor) + self._project_path_lookup = repo_utils.get_project_path_lookup( + self._executor, self.manifest_url, manifest=manifest_content) + self._project_remote_lookup = repo_utils.get_project_remote_lookup( + self._executor, self.manifest_url, manifest=manifest_content) + self._project_revision_lookup = repo_utils.get_project_revision_lookup( + self._executor, self.manifest_url, self.manifest_branch, + manifest=manifest_content) + + def get_data(self, key, default=None): + """Returns previously stored data associated with a known key. + + Args: + key: string key the data is associated with. + default: Default return value if the key is not found. + + Returns: + The value associated with the provided key. + """ + assert isinstance(key, six.string_types) + return self._data_store.get(key, default) + + def get_project_path(self, project): + """Returns the path to the project. + + Args: + project: The name of the project (usually patch_project) to lookup. + + Returns: + The relative path from the base checkout to the project. + """ + self.ensure_project_info() + return self._project_path_lookup.get(project) + + def get_project_path_lookup_table(self): + """Returns the project path lookup table.""" + self.ensure_project_info() + return self._project_path_lookup + + def get_project_remote(self, project): + """Returns the remote for the project. + + Args: + project: The name of the project (usually patch_project) to lookup. + + Returns: + The remote for the project. + """ + self.ensure_project_info() + return self._project_remote_lookup.get(project) + + def get_project_revision(self, project): + """Returns the revision for the project. + + Args: + project: The name of the project (usually patch_project) to lookup. + + Returns: + The revision for the project. + """ + self.ensure_project_info() + return self._project_revision_lookup.get(project) + + def get_property(self, name, default=None): + """Returns the requested property value, or default if not found.""" + if not self._properties: + return default + return self._properties.get(name, default) + + @property + def manifest_branch(self): + """Returns the manifest branch to use for this step.""" + return self.get_property('manifest_branch') + + @property + def manifest_url(self): + """Returns the manifest url to use for this step.""" + return self.get_property('manifest_url') + + +class DataManagerMock(DataManager): + """Mocks data passing between steps for tests.""" + + def get_all_data(self): + return copy.deepcopy(self._data_store)
diff --git a/cq/scripts/helpers/diff_utils.py b/cq/scripts/helpers/diff_utils.py new file mode 100644 index 0000000..fccd46c --- /dev/null +++ b/cq/scripts/helpers/diff_utils.py
@@ -0,0 +1,134 @@ +"""Compilation of utility functions for working with file diffs.""" + +from __future__ import absolute_import +import re + +import six + +def diff_to_comments(diff): + r"""Converts a unified diff to a map of comments to be added to a review. + + Comments are formatted according to: + https://gerrit-review.googlesource.com/Documentation/rest-api-changes.html#comment-input + + Example output: + { + 'path/to/foo': [{'line': '1', 'message': '+ bar'}, + {'line': '10', 'message': '+ baz\n- foo'}] + 'path/to/bar': [{'line': '8', 'message': '- biz'}] + } + + Args: + diff: output from difflib.unified_diff() + + Returns: + A dictionary of comments to be added to a review. + Keys are filenames and values are lists of dictionaries + with 'line' and 'message' entries. + """ + comments = {} + tofile = '' + line_range = () + message_lines = [] + + for line in diff: + line = line.strip() + if line.startswith('+++'): + if message_lines: + # We transitioned from one file's diffs to the next, + # so add last comment from the previous file + _add_comment(tofile, line_range, message_lines, comments) + message_lines = [] + tofile = _get_filename(line) + elif line.startswith('---'): + # fromfile name is not used + continue + elif line.startswith('@@') and line.endswith('@@'): + if message_lines: + _add_comment(tofile, line_range, message_lines, comments) + message_lines = [] + line_range = _get_linerange(line) + else: + message_lines.append(line) + + if message_lines: + _add_comment(tofile, line_range, message_lines, comments) + + return comments + + +def _get_filename(line): + """Returns the filename from a unified diff line. + + The line should be of the format: + --- filename\tdate\tdate + +++ filename\tdate\tdate + + Args: + line: A line from a unified diff output + + Returns: + the filename in the line, if it exists. '' otherwise. + """ + assert isinstance(line, six.string_types) + assert line.startswith('---') or line.startswith('+++') + + if len(line) > 4: + return line[4:].split('\t', 1)[0] + else: + return '' + + +def _get_linerange(line): + """Returns a tuple of (start_line, end_line) for this change. + + The line should be of the format: + @@ -#,# +#,# @@ + + Args: + line: A line from a unified diff output + + Returns: + The line number of the tofile that the change starts at. + """ + assert isinstance(line, six.string_types) + assert line.startswith('@@') + assert line.endswith('@@') + + matches = re.search(r'-(\d+)(,(\d+))? \+(\d+)(,(\d+))?', line) + start_line = matches.group(4) + diff_length = matches.group(6) or 1 + end_line = str(int(start_line) + int(diff_length) - 1) + return (start_line, end_line) + + +def _add_comment(filename, line_range, message_lines, comments): + """Add a comment to the list of comments. + + Args: + filename: the file the comment applies to + line_range: the (start_line, end_line) numbers that this comment applies to + message_lines: a list of lines to put in the comment + comments: the dictionary of comments to add this comment to + """ + assert message_lines + assert len(line_range) == 2 + + start_line, end_line = line_range + start_character = 0 + end_character = max(len(message_lines[-1]) - 1, 0) + # If the message line is a diff'd line, it will have an extra character + # at the start that the actual file line does not have. + if message_lines[-1].startswith(('-', '+')): + end_character -= 1 + # Prepend a space to each line so gerrit doesn't format the "-" as a list. + message_lines = [' ' + line for line in message_lines] + comment = {'range': {'start_line': str(start_line), + 'start_character': str(start_character), + 'end_line': str(end_line), + 'end_character': str(end_character)}, + 'message': '\n'.join(message_lines)} + if filename in comments: + comments[filename].append(comment) + else: + comments[filename] = [comment]
diff --git a/cq/scripts/helpers/diff_utils_test.py b/cq/scripts/helpers/diff_utils_test.py new file mode 100644 index 0000000..3e3d9eb --- /dev/null +++ b/cq/scripts/helpers/diff_utils_test.py
@@ -0,0 +1,203 @@ +"""Tests for diff_utils.""" + +from __future__ import absolute_import +import difflib +import os +import sys +import unittest + +# Allow imports from cq/scripts folder +sys.path.insert( + 0, + os.path.realpath( + os.path.join(os.path.dirname(__file__), os.pardir))) +from helpers import diff_utils + +FROM_FILE = 'FROM_FILE' +TO_FILE = 'TO_FILE' + + +class DiffUtilsTest(unittest.TestCase): + + # pylint: disable=invalid-name + def diff_strings(self, from_string, to_string, from_name, to_name): + return difflib.unified_diff(from_string.splitlines(True), + to_string.splitlines(True), + fromfile=from_name, + tofile=to_name, + n=0) + + def testEmptyDiff(self): + """Tests creating comments from an empty diff.""" + empty = '' + + diff = self.diff_strings(empty, empty, FROM_FILE, TO_FILE) + comments = diff_utils.diff_to_comments(diff) + + self.assertEquals(comments, {}) + + def testSingleLineSingleDiff(self): + """Tests creating a comment from a diff made form a single line.""" + from_lines = 'This line is foo.' + to_lines = 'This line is bar.' + + diff = self.diff_strings(from_lines, to_lines, FROM_FILE, TO_FILE) + comments = diff_utils.diff_to_comments(diff) + + self.assertEqual(len(comments), 1) + self.assertIn(TO_FILE, comments) + self.assertEqual(len(comments[TO_FILE]), 1) + + expected_range = {'start_line': '1', + 'start_character': '0', + 'end_line': '1', + 'end_character': '16'} + comment_range = comments[TO_FILE][0]['range'] + self.assertEqual(expected_range, comment_range) + + message = comments[TO_FILE][0]['message'] + self.assertIn('-' + from_lines, message) + self.assertIn('+' + to_lines, message) + self.assertEqual(len(message.splitlines()), 2) + + def testMultipleLineSingleDiff(self): + """Tests creating comments from a diff made of multiple lines.""" + from_lines = ('This line is the same.\n' + 'This line is foo.\n' + 'This line is foo also.\n' + 'This line is the same.') + to_lines = ('This line is the same.\n' + 'This line is bar.\n' + 'This line is bar also.\n' + 'This line is the same.') + + diff = self.diff_strings(from_lines, to_lines, FROM_FILE, TO_FILE) + comments = diff_utils.diff_to_comments(diff) + + self.assertEqual(len(comments), 1) + self.assertIn(TO_FILE, comments) + self.assertEqual(len(comments[TO_FILE]), 1) + + expected_range = {'start_line': '2', + 'start_character': '0', + 'end_line': '3', + 'end_character': '21'} + comment_range = comments[TO_FILE][0]['range'] + self.assertEqual(expected_range, comment_range) + + message = comments[TO_FILE][0]['message'] + self.assertEqual(message.count('-'), 2) + self.assertEqual(message.count('+'), 2) + self.assertEqual(len(message.splitlines()), 4) + + def testMultipleLineMultipleDiff(self): + """Tests creating multiple comments from a multi-part diff.""" + from_lines = ('This line is the same.\n' + 'This line is foo.\n' + 'This line is the same.\n' + 'This line is foo.\n' + 'This line is foo.') + to_lines = ('This line is the same.\n' + 'This line is bar.\n' + 'This line is the same.\n' + 'This line is bar.\n' + 'This line is bar.') + + diff = self.diff_strings(from_lines, to_lines, FROM_FILE, TO_FILE) + comments = diff_utils.diff_to_comments(diff) + + self.assertEqual(len(comments), 1) + self.assertIn(TO_FILE, comments) + self.assertEqual(len(comments[TO_FILE]), 2) + + # First diff + expected_range = {'start_line': '2', + 'start_character': '0', + 'end_line': '2', + 'end_character': '16'} + comment_range = comments[TO_FILE][0]['range'] + self.assertEqual(expected_range, comment_range) + + message = comments[TO_FILE][0]['message'] + self.assertEqual(message.count('-'), 1) + self.assertEqual(message.count('+'), 1) + self.assertEqual(len(message.splitlines()), 2) + + # Second diff + expected_range = {'start_line': '4', + 'start_character': '0', + 'end_line': '5', + 'end_character': '16'} + comment_range = comments[TO_FILE][1]['range'] + self.assertEqual(expected_range, comment_range) + + message = comments[TO_FILE][1]['message'] + self.assertEqual(message.count('-'), 2) + self.assertEqual(message.count('+'), 2) + self.assertEqual(len(message.splitlines()), 4) + + def testNoFileName(self): + """Tests creating a comment when tofile is not passed to unified_diff().""" + from_lines = 'This line is foo.' + to_lines = 'This line is bar.' + + diff = difflib.unified_diff(from_lines, to_lines) + comments = diff_utils.diff_to_comments(diff) + + self.assertEqual(len(comments), 1) + self.assertIn('', comments) + self.assertEqual(len(comments['']), 1) + + def testSpacesForGerritFormatting(self): + """Tests that each line of a file level comment starts with a space.""" + from_lines = ('This line is the same.\n' + 'This line is foo.\n' + 'This line is foo also.\n' + 'This line is the same.') + to_lines = ('This line is the same.\n' + 'This line is bar.\n' + 'This line is bar also.\n' + 'This line is the same.') + + diff = self.diff_strings(from_lines, to_lines, FROM_FILE, TO_FILE) + comments = diff_utils.diff_to_comments(diff) + + message = comments[TO_FILE][0]['message'] + for line in message.splitlines(): + self.assertTrue(line.startswith(' ')) + + def testDiffWithMultipleFiles(self): + """Tests that a multifile diff puts comments with the proper file.""" + diff = ['--- foo1.cc\n', + '+++ foo1.cc\n', + '@@ -123,1 +123,1 @@\n', + 'message1.0\n', + '--- foo2.cc\n', + '+++ foo2.cc\n', + '@@ -456,1 +456,1 @@\n', + 'message2.0\n', + '@@ -456,1 +456,1 @@\n', + 'message2.1\n', + '--- foo3.cc\n', + '+++ foo3.cc\n', + '@@ -789,1 +789,1 @@\n', + 'message3.0\n',] + comments = diff_utils.diff_to_comments(diff) + + self.assertEqual(len(comments), 3) + self.assertIn('foo1.cc', comments) + self.assertIn('foo2.cc', comments) + self.assertIn('foo3.cc', comments) + + self.assertEqual(len(comments['foo1.cc']), 1) + self.assertEqual(len(comments['foo2.cc']), 2) + self.assertEqual(len(comments['foo3.cc']), 1) + + self.assertIn('message1.0', comments['foo1.cc'][0]['message']) + self.assertIn('message2.0', comments['foo2.cc'][0]['message']) + self.assertIn('message2.1', comments['foo2.cc'][1]['message']) + self.assertIn('message3.0', comments['foo3.cc'][0]['message']) + + +if __name__ == '__main__': + unittest.main()
diff --git a/cq/scripts/helpers/env_constants.py b/cq/scripts/helpers/env_constants.py new file mode 100644 index 0000000..56cc72e --- /dev/null +++ b/cq/scripts/helpers/env_constants.py
@@ -0,0 +1,10 @@ +"""Environmental constants utilized by multiple CQ scripts.""" +import pathlib + + +def get_mosaic_role_path(): + return pathlib.Path('/usr', 'local', 'google', 'home', 'mosaic-role') + + +def get_continuous_tests_path(): + return pathlib.Path(get_mosaic_role_path(), 'continuous-tests')
diff --git a/cq/scripts/helpers/gclient_utils.py b/cq/scripts/helpers/gclient_utils.py new file mode 100644 index 0000000..cc99ef3 --- /dev/null +++ b/cq/scripts/helpers/gclient_utils.py
@@ -0,0 +1,60 @@ +"""Collection of utilities to work with gclient.""" + +from __future__ import absolute_import +import imp +import logging +import os +import pathlib + +from helpers import git_utils + +_DEPOT_TOOLS_SEARCH_PATHS = [ + # Newer containers don't include depot_tools so search for it in the + # manifest. This is the preferred version because it will be pinned on + # release branches and track upstream on master. + pathlib.Path('/workspace/checkout/chromium/tools/depot_tools'), + # Legacy containers have depot_tools installed at this path. + pathlib.Path('/workspace/depot_tools'), +] + + +def find_depot_tools(): + for path in _DEPOT_TOOLS_SEARCH_PATHS: + if path.exists(): + return path + + raise ValueError('Cannot find a suitable installation of depot_tools') + + +def disable_depot_tools_auto_update_cmd(): + depot_tools_path = find_depot_tools() + return [ + 'python3', + str(depot_tools_path / 'update_depot_tools_toggle.py'), + '--disable', + ] + + +def gclient_sync_cmd(executor, jobs=None, extra_args=None): + """Returns the command list to run gclient sync.""" + depot_tools_path = find_depot_tools() + logging.info( + 'Using depot_tools at %s (%s)', + depot_tools_path, + git_utils.get_head_sha(executor, str(depot_tools_path)), + ) + + # See go/authenticating-cipd-on-nest-infra for more context on this command. + luci_auth_wrapped_cmd = [ + str(depot_tools_path / 'luci-auth'), 'context', '-disable-git-auth', '-service-account-json', + ':gce', '--', + str(depot_tools_path / 'gclient'), 'sync', '--force', '--with_branch_heads', + '--delete_unversioned_trees', '--reset' + ] + + if jobs is not None: + luci_auth_wrapped_cmd.append('--jobs={}'.format(jobs)) + if extra_args is not None: + luci_auth_wrapped_cmd.extend(extra_args) + + return luci_auth_wrapped_cmd
diff --git a/cq/scripts/helpers/gcs_utils.py b/cq/scripts/helpers/gcs_utils.py new file mode 100644 index 0000000..1537d8a --- /dev/null +++ b/cq/scripts/helpers/gcs_utils.py
@@ -0,0 +1,30 @@ +"""Collection of utilities to work with Google Cloud Storage and gsutil.""" + +import os + + +def gsutil(): + """Returns the path to the gsutil binary.""" + # Search the normal install path for gsutil first. This should succeed + # most of the time. (A notable exception being GCE instances, which + # have gsutil on the PATH somewhere else.) + gsutil_path = os.path.expanduser('~/gsutil/gsutil') + if os.path.exists(gsutil_path): + return gsutil_path + + # Otherwise, assume that gsutil is on the PATH so that this will find it. + return 'gsutil' + + +def upload_directory_cmd(local_dir, gcs_dir): + """Command to upload the contents of the local directory to the GCS bucket. + + Note that this assumes a gsutil install located at ~/gsutil. + + Args: + local_dir: local directory to upload the contents of (e.g. path/to/foo) + gcs_dir: directory on GCS to upload to (e.g. gs://my-bucket/foo) + Returns: + The command (as a list) to execute to upload a directory to GCS. + """ + return [gsutil(), 'cp', '-r', local_dir, gcs_dir]
diff --git a/cq/scripts/helpers/generate_gn_helper.sh b/cq/scripts/helpers/generate_gn_helper.sh new file mode 100755 index 0000000..adfdfe4 --- /dev/null +++ b/cq/scripts/helpers/generate_gn_helper.sh
@@ -0,0 +1,43 @@ +#!/bin/bash +# +# Helper script to run generate_gn from the CQ (and python scripts in general) + +function usage { + echo "Usage: generate_gn_helper.sh <path-to-chromecast_build_env.sh> <gn-root-dir>" + echo "chromecast_build_env.sh can be found at chromium/src/chromecast/internal/build" + echo "gn-root-dir is usually chromium/src (but in general is where the .gn file is)" +} + +function main { + + if [[ "$#" -ne 2 ]]; then + usage + exit 1 + fi + + local chromecast_build_env_script="$1" + local gn_root_dir="$2" + + if [[ ! -e "${chromecast_build_env_script}" ]]; then + echo "${chromecast_build_env_script} does not exist." + usage + exit 1 + fi + + if [[ ! -e "${gn_root_dir}" ]]; then + echo "${gn_root_dir} does not exist." + usage + exit 1 + fi + + ( + # Source chromecast_build_env.sh to get generate_gn and setup_chrome_env_* + . "${chromecast_build_env_script}" + + cd "${gn_root_dir}" + setup_chrome_env_clang_chromecast `pwd -P` Eng + generate_gn --check + ) +} + +main "$@"
diff --git a/cq/scripts/helpers/git_utils.py b/cq/scripts/helpers/git_utils.py new file mode 100644 index 0000000..87c420b --- /dev/null +++ b/cq/scripts/helpers/git_utils.py
@@ -0,0 +1,211 @@ +"""Collection of utility functions to work with git.""" + +from __future__ import absolute_import +import collections +import os +import re +import six + +CHERRY_PICK_MSG = r'\(cherry picked from commit [0-9a-f]{5,40}\)' +SHA_PATTERN = r'[a-fA-F0-9]{40}' + +# `git diff` uses /dev/null as a placeholder name for new/deleted files. +FILENAME_PLACEHOLDER = '/dev/null' + + +def check_history_depth(executor, directory): + depth = executor.exec_subprocess( + ['git', 'rev-list', '--count', 'HEAD'], cwd=directory, check_output=True) + try: + return int(depth) + except ValueError: + return 0 + + +def changed_files(executor, + file_extensions=None, + directory=None, + file_exclusion_pattern=None, + depth=1): + """Returns a list of names of changed files in newest |depth| commits. + + Args: + executor: Executes the subprocess. + file_extensions: Filter output to only files with matching extensions. (e.g. + ['.cc', '.h'] for C++ files) + directory: Directory to execute the subprocess in. + file_exclusion_pattern: A regex pattern to filter files with. If the pattern + matches a file that file will not be included in the changed file list. + depth: The number of commits to find files from. + + Returns: + List of names of changed files. + """ + diff_output = executor.exec_subprocess([ + 'git', 'diff', 'HEAD~{}'.format(depth), '--name-only', '--diff-filter=AMR' + ], + cwd=directory, + check_output=True) + + if not diff_output: + return [] + + changed_filenames = diff_output.strip().split('\n') + + return filtered_files( + changed_filenames, + file_extensions=file_extensions, + file_exclusion_pattern=file_exclusion_pattern) + + +def get_changed_files_in_all_patches(executor, + patches, + path_lookup, + file_extensions=None, + file_exclusion_pattern=None): + """Returns every file that is changed as a result of applying |patches|. + + This method is useful when determining all files that have changed when a + series of patches have been applied via the Depends-On tag. This method + supports patches in multiple projects, as well as multiple patches in a + single project. + + Args: + executor: Executes the subprocess. + patches: A list of all of the patches applied to the checkout. For more + detail on the entries in this list, see scripts/slave/base_step.py. + path_lookup: A dictionary mapping project name to path. + file_extensions: Filter output to only files with matching extensions. (e.g. + ['.cc', '.h'] for C++ files) + file_exclusion_pattern: A regex pattern to filter files with. If the pattern + matches a file that file will not be included in the changed file list. + + Returns: + A list of file paths relative to the checkout root directory. + """ + + # |project_depth| is a dictionary mapping each project name to the number of + # patches that have been applied on top of that project's HEAD. Here's an + # example of what this might look like: + # { + # "chromecast/internal": 1, + # "chromium/src": 2, + # "some_other_project": 1 + # } + project_depths = collections.Counter( + patch['project'] for patch in patches if patch['project'] in path_lookup) + + # |path_lookup| dictionary uses real paths relative to the root checkout + # directory. However, some tools like gn expect paths to be symlinks, e.g. + # chromium/src/chromecast/internal/receiver/app/dummy.cc instead of + # cast/internal/receiver/app/dummy.cc. Create a dictionary here so that + # symlinks can be returned for some projects. + file_prefix_dict = { + "chromecast/internal": "chromium/src/chromecast/internal" + } + file_prefix_dict = path_lookup.get_dict() | file_prefix_dict + + # For each project, calculate the list of changed files, concatenate each file + # path with the project's path from checkout root, and append them to a list. + files = [] + for project in project_depths.keys(): + depth = project_depths[project] + if depth < check_history_depth(executor, path_lookup[project]): + files.extend([ + os.path.join(file_prefix_dict[project], f) + for f in changed_files( + executor, file_extensions, path_lookup[project], + file_exclusion_pattern, depth) + ]) + return files + + +def filtered_files(filenames, + file_extensions=None, + file_exclusion_pattern=None): + """Filters the list of files. + + Args: + filenames: A list of filenames to filter. + file_extensions: Filter output to only files with matching extensions. (e.g. + ['.cc', '.h'] for C++ files) + file_exclusion_pattern: A regex pattern to filter files with. If the pattern + matches a file that file will not be included in the changed file list. + + Returns: + List of files after applying the filters. + """ + if file_extensions: + filenames = [f for f in filenames if f.endswith(tuple(file_extensions))] + if file_exclusion_pattern: + filenames = [ + f for f in filenames if not re.search(file_exclusion_pattern, f) + ] + return filenames + + +def commit_message(executor, directory=None): + """Returns the most recent git commit message. + + Note that this does not include the Author: or Date: fields, + only the message body. + + Args: + executor: Executes the subprocess. + directory: Directory to execute the subprocess in (defaults to cwd) + + Returns: + The most recent git commit message. + """ + return executor.exec_subprocess(['git', 'log', '--format=%B', '-n', '1'], + cwd=directory, + check_output=True) + + +def is_cherry_pick(executor, directory=None): + """Returns if the most recent commit is a cherry pick. + + Args: + executor: Executes the subprocess. + directory: Directory to execute the subproccess in (defaults to cwd) + + Returns: + True iff the most recent commit is a cherry pick. + """ + return bool( + re.search(CHERRY_PICK_MSG, commit_message(executor, directory), + re.MULTILINE)) + + +def commit_author_email(executor, directory=None): + """Returns the author email of the most recent git commit. + + Args: + executor: Executes the subprocess. + directory: Directory to execute the subprocess in (defaults to cwd) + + Returns: + The email of the author of the most recent git commit. + """ + author = executor.exec_subprocess(['git', 'log', '--format=%ae', '-n', '1'], + cwd=directory, + check_output=True).strip() + # We have to first convert to a unicode str, then decode removing unicode + # chars. + return six.text_type(author.decode('utf-8')).encode('ascii', errors='ignore') + + +def is_sha(revision): + """Returns True if revision looks like a SHA.""" + return re.match(SHA_PATTERN, revision) + + +def get_head_sha(executor, directory): + """Returns the SHA of the HEAD revision for the given directory, + + or None if the directory specified is not a git repository + """ + + cmd_get_sha = ['git', 'rev-parse', 'HEAD'] + returncode, stdout, _ = executor.exec_subprocess(cmd_get_sha, cwd=directory) + return stdout.strip() if returncode == 0 else None
diff --git a/cq/scripts/helpers/git_utils_test.py b/cq/scripts/helpers/git_utils_test.py new file mode 100755 index 0000000..4e4a812 --- /dev/null +++ b/cq/scripts/helpers/git_utils_test.py
@@ -0,0 +1,152 @@ +"""Tests for git_utils.""" + +from __future__ import absolute_import +import os +import sys +import unittest + +# Allow imports from cq/scripts folder +sys.path.insert( + 0, + os.path.realpath(os.path.join(os.path.dirname(__file__), os.pardir))) +from helpers import git_utils +from helpers import repo_utils + + +# A mock executor that keeps simple git state. +class MockExecutor(object): + + def __init__(self): + self.current_branch = 'HEAD' + self.remote = '' + self.remote_branch = '' + self._handlers = [] + + def add_handler(self, handler): + self._handlers.append(handler) + + def exec_subprocess(self, command, cwd=None, check_output=False): + + for handler in self._handlers: + result = handler(command, cwd) + if result: + if check_output: + # check_output option only cares about stdout + return result[1] + return result + + if command[:2] == ['git', 'rev-parse']: + return (0, self.current_branch, '') + elif command[:2] == ['git', 'checkout']: + self.current_branch = command[command.index('-B') + 1] + self.remote, self.remote_branch = command[-1].split('/') + + return (0, '', '') + + +class GitUtilsTest(unittest.TestCase): + + def testNoFilterFiles(self): + """Tests with no filter.""" + filenames = [ + 'something.py', + 'something_else.cc' + ] + filtered_files = git_utils.filtered_files(filenames) + self.assertEquals(filenames, filtered_files) + + def testNoFilteredFiles(self): + """Tests filtering files by extension.""" + filenames = [ + 'something.py', + 'something_else.cc' + ] + filtered_files = git_utils.filtered_files(filenames, + file_extensions=['.py', '.cc']) + self.assertEquals(2, len(filtered_files)) + self.assertIn('something.py', filtered_files) + self.assertIn('something_else.cc', filtered_files) + + def testFilteredFiles(self): + """Tests filtering files by extension.""" + filenames = [ + 'something.py', + 'something_else.cc' + ] + filtered_files = git_utils.filtered_files(filenames, + file_extensions=['.py']) + self.assertEquals(1, len(filtered_files)) + self.assertIn('something.py', filtered_files) + + def testFilteredFilesExclusion(self): + """Tests filtering files by pattern.""" + filenames = [ + 'something.py', + 'something_foo_pb2.py', + 'something_else.cc' + ] + filtered_files = git_utils.filtered_files( + filenames, + file_extensions=['.py'], + file_exclusion_pattern=r'^.+_pb2.py$') + self.assertEquals(1, len(filtered_files)) + self.assertIn('something.py', filtered_files) + + def testGetAllFiles(self): + """Test getting all files affected by a group of patches.""" + patches = [ + {'project': 'chromium/src', 'patchset_number': 12345}, + {'project': 'chromium/src', 'patchset_number': 67890}, + {'project': 'chromecast/internal', 'patchset_number': 34567}, + {'project': 'test', 'patchset_number': 89012}, + {'project': 'project_with_no_path', 'patchset_number': 1}] + + path_lookup = repo_utils.ProjectLookupTable({ + 'chromium/src': 'chromium/src', + 'chromecast/internal': 'cast/internal', + 'test': 'test'}) + + def handle_git_revlist(cmd, cwd): + if cmd == ['git', 'rev-list', '--count', 'HEAD']: + return (0, '200', '') + return None + + def handle_git_diff(cmd, cwd): + if cmd[:2] != ['git', 'diff'] or '--name-only' not in cmd: + return None + if cwd == 'chromium/src': + self.assertTrue('HEAD~2' in cmd) + files = ['base/logging.h', 'media/base/config.cc', 'net/utils.h'] + elif cwd == 'cast/internal': + self.assertTrue('HEAD~1' in cmd) + files = ['receiver/client.h', 'base/logging.h'] + elif cwd == 'test': + self.assertTrue('HEAD~1' in cmd) + files = ['foo.h'] + else: + return (0, '', '') + return (0, '\n'.join(files), '') + + executor = MockExecutor() + executor.add_handler(handle_git_revlist) + executor.add_handler(handle_git_diff) + all_files = git_utils.get_changed_files_in_all_patches( + executor, patches, path_lookup) + self.assertEqual(set([ + 'chromium/src/base/logging.h', + 'chromium/src/media/base/config.cc', + 'chromium/src/net/utils.h', + 'chromium/src/chromecast/internal/receiver/client.h', + 'chromium/src/chromecast/internal/base/logging.h', + 'test/foo.h']), set(all_files)) + + def testIsRevisionASha(self): + """Tests cases for git_utils.is_sha.""" + self.assertTrue( + git_utils.is_sha('2fe8f3b110d8b117698265e18e432f32837247bb')) + self.assertFalse(git_utils.is_sha('master')) + self.assertFalse(git_utils.is_sha('unfork_m52')) + + +if __name__ == '__main__': + unittest.main()
diff --git a/cq/scripts/helpers/gn_utils.py b/cq/scripts/helpers/gn_utils.py new file mode 100644 index 0000000..e02fe56 --- /dev/null +++ b/cq/scripts/helpers/gn_utils.py
@@ -0,0 +1,216 @@ +"""Compilation of utility functions for working with GN.""" + +from __future__ import absolute_import +import collections +import os +import re + +from helpers import branch_utils +import six + +# TODO(mbjorge|maasen): generate these based on the base path of the repo +# Default location for GN files +GN_SHA1 = 'chromium/src/buildtools/linux64/gn.sha1' +GN_BINARY = 'chromium/src/buildtools/linux64/gn' + +# DEPRECATED: Do not reference this variable in new code. Prefer to use a +# path lookup for the chromium/src project instead. +GN_CHROMIUM_BASE_DIR = 'chromium/src' + +GENERATE_GN_HELPER_SCRIPT = 'scripts/helpers/generate_gn_helper.sh' + +GN_EXTENSIONS = ('.gn', '.gni') + +GN_DONE_MSG = r'Done. Wrote \d+ targets from \d+ files' +GN_HEADER_OK_MSG = r'Header dependency check OK' +GN_ERROR_MSG = ( + r'ERROR at //(?P<filename>[^:]+):(?P<line>\d+):\d+: (?P<error>.+?)\n') +GN_ERROR_DIVIDER_MSG = r'___________________' +GN_FORMAT_ERROR_MSG = r':(?P<linenum>\d+):(?P<column>\d+): ' + + +class GnUtilsError(Exception): + """Gn Utils specific exception.""" + + +def gn_check_error_to_comments(gn_check_output): + """Convert a gn check error message to comments for a gerrit review. + + Args: + gn_check_output: output from the `gn check` command + + Returns: + Comment to be added to a review message. + The comment is a dictionary with filenames as keys. + Each filename maps to an array of line-numbered comments for that file. + """ + assert isinstance(gn_check_output, six.string_types) + + comments = collections.defaultdict(list) + + # Check that GN check did not succeed + if re.search(GN_DONE_MSG, gn_check_output) or re.search( + GN_HEADER_OK_MSG, gn_check_output): + return comments + + error_msg = re.compile(GN_ERROR_MSG) + error_divider_msg = re.compile(GN_ERROR_DIVIDER_MSG) + + filename, linenum, message = '', '', [] + for line in gn_check_output.splitlines(True): + # Look for the start of a new error + match = error_msg.match(line) + if match: + filename = match.group('filename') + linenum = match.group('line') + message = ['ERROR: {}\n'.format(match.group('error'))] + continue + + # Look for the end of the current error + match = error_divider_msg.match(line) + if match: + comment = {'line': linenum, 'message': ''.join(message)} + comments[filename].append(comment) + filename, linenum, message = '', '', [] + continue + + # Add the contents of the error to the current comment + message.append(line) + + # The last error message does not have a trailing divider + if message: + comment = {'line': linenum, 'message': ''.join(message)} + comments[filename].append(comment) + + return comments + + +def gn_format_error_to_comments(filename, error_msg): + """Convert a gn format error message to comments for a gerrit review. + + Args: + filename: name of the file that caused the error + error_msg: Output message from gn format. Example: + "ERROR at /path/to/bad/file.gn:10:12: Invalid bar." + + Returns: + Comment to be added to a review message. + Example: + {'path/to/bad/file.gn': [{'line': 10, 'message': 'Invalid bar.'}]} + """ + assert error_msg.startswith('ERROR at ') + assert filename in error_msg + + lines = error_msg.splitlines(True) + match = re.search(GN_FORMAT_ERROR_MSG, lines[0]) + linenum = match.group('linenum') + message = error_msg[match.end():] + + return {filename: [{'line': linenum, 'message': message}]} + + +def filepath_to_gn_path(filename): + """convert chromium/src/a/b/BUILD.gn to //a/b:*.""" + if not filename.endswith('BUILD.gn'): + raise ValueError('Invalid path %s. Must be a BUILD.gn file.', filename) + if not filename.startswith(GN_CHROMIUM_BASE_DIR): + raise ValueError('Invalid path %s. Must start with %s', + filename, GN_CHROMIUM_BASE_DIR) + target_path = os.path.relpath(os.path.dirname(filename), GN_CHROMIUM_BASE_DIR) + if target_path == '.': + target_path = '' + return '//{}:*'.format(target_path) + + +def gn_label_to_target_name(gn_label): + """Convert '//foo/bar:baz' to 'baz'.""" + if not gn_label: + raise ValueError('Input label must not be empty.') + if gn_label[-1] in [':', '/']: + raise ValueError('A GN label must not end with {!r}: {}'.format( + gn_label[-1], gn_label)) + + if ':' in gn_label: + return gn_label.split(':')[-1] + if '/' in gn_label: + return gn_label.split('/')[-1] + + return gn_label + + +def get_gn_binary(executor): + """Returns the path to a gn binary. + + This attempts to download the latest version of GN. If the download fails, + then an older version will be used. If GN cannot be downloaded and no + older version can be found, this throws a GnUtilsError. + + Args: + executor: Executes the download of GN via executor.exec_subproces + + Returns: + A relative path to the GN binary. + + Raises: + GnUtilsError: if GN cannot be found or downloaded. + """ + ret, _, _ = _download_gn(GN_SHA1, executor) + + # If the download succeeded, trust that the binary is in the correct place + # and return. If the download fails, an old copy could still exist and be + # used. + if ret == 0 or _verify_gn_exists(): + return GN_BINARY + raise GnUtilsError('GN binary could not be found or downloaded.') + + +def _verify_gn_exists(): + """Returns boolean if gn exists.""" + return os.path.exists(GN_BINARY) + + +def _download_gn(sha1_path, executor): + """Downloads the latest GN from google storage. + + Args: + sha1_path: Path to gn.sha1 used to download GN. + Using gn_utils.GN_SHA1 will result in GN + being placed at gn_utils.GN_BINARY + executor: Executes the download via executor.exec_subprocess + + Returns: + (return_code, stdout, stderr) from the download process + + """ + assert isinstance(sha1_path, str) + assert hasattr(executor, 'exec_subprocess') + command = ['download_from_google_storage', + '--no_resume', + '--platform=linux*', + '--no_auth', + '--bucket', 'chromium-gn', + '-s', sha1_path] + return executor.exec_subprocess(command) + + +def is_gn_check_enabled(manifest_branch, product=None): + """Returns true if GN check can be used on |manifest_branch|. + + Since `gn check` will not run cleanly only older branches (<m51, <=1.21), + do not enable it. + + Args: + manifest_branch: The name of the manifest branch. + product: Optional product name (e.g. 'android', 'audio', 'chromecast') + Defaults to None. + Returns: + True if GN check can be used, False otherwise. + Raises: + ValueError: if the branch name is not recognized. + """ + # Development branch 'master' uses gn check. + if manifest_branch == 'master': + return True + + return branch_utils.is_branch_equal_to_or_later_than( + manifest_branch, '1.23' if product in ['android', 'atv'] else '1.22')
diff --git a/cq/scripts/helpers/gn_utils_test.py b/cq/scripts/helpers/gn_utils_test.py new file mode 100644 index 0000000..ec7a81b --- /dev/null +++ b/cq/scripts/helpers/gn_utils_test.py
@@ -0,0 +1,68 @@ +"""Tests for gn_utils. + +Before running these tests, run test_data/gn_utils/generate_test_data.sh with +a recent version of gn to make sure the test data is up to date. +""" + +from __future__ import absolute_import +import datetime +import os +import re +import sys +import unittest + +# Allow imports from cq/scripts folder +sys.path.insert( + 0, + os.path.realpath(os.path.join(os.path.dirname(__file__), os.pardir))) +from helpers import gn_utils + +class GnUtilsTest(unittest.TestCase): + def testValidGnLabelToTargetName(self): + """Tests that gn_label_to_target_name handles valid input properly.""" + self.assertEqual('baz', gn_utils.gn_label_to_target_name('//foo/bar:baz')) + self.assertEqual('baz', gn_utils.gn_label_to_target_name('//foo/bar/baz')) + self.assertEqual('foo', gn_utils.gn_label_to_target_name('//foo')) + self.assertEqual('qux', gn_utils.gn_label_to_target_name('qux')) + + def testBadGnLabelToTargetName(self): + """Tests that gn_label_to_target_name raises exceptions on bad input.""" + with self.assertRaises(ValueError): + gn_utils.gn_label_to_target_name('') + with self.assertRaises(ValueError): + gn_utils.gn_label_to_target_name(None) + with self.assertRaises(ValueError): + gn_utils.gn_label_to_target_name('//foo/') + with self.assertRaises(ValueError): + gn_utils.gn_label_to_target_name('//foo:') + + def testFilePathToGnLabel(self): + self.assertEqual( + '//:*', + gn_utils.filepath_to_gn_path('chromium/src/BUILD.gn')) + self.assertEqual( + '//foo:*', + gn_utils.filepath_to_gn_path('chromium/src/foo/BUILD.gn')) + self.assertEqual( + '//foo/bar/baz:*', + gn_utils.filepath_to_gn_path('chromium/src/foo/bar/baz/BUILD.gn')) + + def testFilePathToGnLabel_RaisesNotBuildGn(self): + with self.assertRaises(ValueError): + gn_utils.filepath_to_gn_path('chromium/src/x.cc') + with self.assertRaises(ValueError): + gn_utils.filepath_to_gn_path('chromium/src/foo.gni') + with self.assertRaises(ValueError): + gn_utils.filepath_to_gn_path('chromium/src/foo/bar') + + def testFilePathToGnLabel_RaisesNotChromiumSrc(self): + with self.assertRaises(ValueError): + gn_utils.filepath_to_gn_path('src/BUILD.gn') + with self.assertRaises(ValueError): + gn_utils.filepath_to_gn_path('BUILD.gn') + with self.assertRaises(ValueError): + gn_utils.filepath_to_gn_path('chromecast/internal/BUILD.gn') + + +if __name__ == '__main__': + unittest.main()
diff --git a/cq/scripts/helpers/luci_recipe_utils.py b/cq/scripts/helpers/luci_recipe_utils.py new file mode 100644 index 0000000..1cbd80c --- /dev/null +++ b/cq/scripts/helpers/luci_recipe_utils.py
@@ -0,0 +1,41 @@ +"""Utility functions for running the LUCI Recipe script.""" +from __future__ import absolute_import +import os + + +class LUCIRecipeRunner(object): + + def __init__(self, executor, script_path, package_path=None): + self._executor = executor + self._script_path = script_path + self._base_command = [self._script_path] + if package_path: + self._base_command.extend(['--package', package_path]) + + def run_tests(self, verbose=True): + """Run recipe expectation tests.""" + cmd = ['test', 'run'] + return self.run_command(cmd, verbose=verbose) + + def bundle(self, destination, verbose=True): + """Generate a recipe bundle at the specified destination.""" + cmd = ['bundle', '--destination', destination] + return self.run_command(cmd, verbose=verbose) + + def run_command(self, cmd, verbose=True): + """Execute a LUCI recipes command.""" + full_command = self._base_command[:] + + if verbose: + full_command.append('--verbose') + full_command.extend(cmd) + + try: + return self._executor.exec_subprocess(full_command) + finally: + self.cleanup() + + def cleanup(self): + """Delete generated dependencies left from recipe run.""" + deps_path = os.path.join(os.path.dirname(self._script_path), '.recipe_deps') + self._executor.exec_subprocess(['rm', '-rf', deps_path])
diff --git a/cq/scripts/helpers/machine_resource_utils.py b/cq/scripts/helpers/machine_resource_utils.py new file mode 100644 index 0000000..c65da5a --- /dev/null +++ b/cq/scripts/helpers/machine_resource_utils.py
@@ -0,0 +1,53 @@ +"""Utility functions for querying CPU, memory, disk, etc.""" + +from __future__ import absolute_import +import os + + +NET_DIRECTION_RX = 0 +NET_DIRECTION_TX = 1 + +_NET_STAT_ROOT = '/sys/class/net/' +_NET_STAT_BYTES = { + NET_DIRECTION_RX: 'rx_bytes', + NET_DIRECTION_TX: 'tx_bytes' +} + + +def get_free_disk_fraction(directory=None): + """Returns free disk space. From 0.0 (disk is full) to 1.0 (disk is empty).""" + if not directory: + directory = os.getcwd() + statvfs = os.statvfs(directory) + return float(statvfs.f_bavail) / float(statvfs.f_blocks) + + +def get_network_if(): + """Returns list of network interfaces on host.""" + try: + return [net_if for net_if in os.listdir(_NET_STAT_ROOT) if net_if != 'lo'] + except OSError: + return [] + + +def get_current_directional_traffic(if_list=None, direction=NET_DIRECTION_RX): + """Returns current network interfaces directional statistic in bytes.""" + if not if_list: + if_list = get_network_if() + bytes_count = 0 + for net_if in if_list: + stat_path = os.path.join( + _NET_STAT_ROOT, net_if, 'statistics', _NET_STAT_BYTES[direction]) + try: + with open(stat_path) as stat: + bytes_count += int(stat.read()) + except OSError: + pass + return bytes_count + + +def get_current_total_traffic(if_list=None): + """Returns current rx, tx and total network interfaces statistic in bytes.""" + rx_bytes = get_current_directional_traffic(if_list, NET_DIRECTION_RX) + tx_bytes = get_current_directional_traffic(if_list, NET_DIRECTION_TX) + return rx_bytes, tx_bytes, rx_bytes + tx_bytes
diff --git a/cq/scripts/helpers/machine_resource_utils_test.py b/cq/scripts/helpers/machine_resource_utils_test.py new file mode 100644 index 0000000..3f418da --- /dev/null +++ b/cq/scripts/helpers/machine_resource_utils_test.py
@@ -0,0 +1,43 @@ +"""Tests for machine_resource_utils.""" + +from __future__ import absolute_import +import os +import sys +import unittest + +# Allow imports from cq/scripts folder +sys.path.insert( + 0, + os.path.realpath(os.path.join(os.path.dirname(__file__), os.pardir))) +from helpers import machine_resource_utils + + +class MachineResourceUtilsTest(unittest.TestCase): + + def testGetFreeDiskFraction(self): + """Tests getting the free disk fraction.""" + self.assertLessEqual(0.0, machine_resource_utils.get_free_disk_fraction()) + self.assertLessEqual(machine_resource_utils.get_free_disk_fraction(), 1.0) + + def testGetNetworkIf(self): + """Tests getting network interface list.""" + if_list = machine_resource_utils.get_network_if() + self.assertTrue(if_list) + self.assertGreaterEqual(len(if_list), 1) + + def testGetNetworkStat(self): + if_list = machine_resource_utils.get_network_if() + self.assertGreater( + machine_resource_utils.get_current_directional_traffic( + if_list=if_list, + direction=machine_resource_utils.NET_DIRECTION_RX), + 0) + self.assertGreater( + machine_resource_utils.get_current_directional_traffic( + if_list=if_list, + direction=machine_resource_utils.NET_DIRECTION_TX), + 0) + + +if __name__ == '__main__': + unittest.main()
diff --git a/cq/scripts/helpers/make_utils.py b/cq/scripts/helpers/make_utils.py new file mode 100644 index 0000000..4f04059 --- /dev/null +++ b/cq/scripts/helpers/make_utils.py
@@ -0,0 +1,60 @@ +"""Compilation of utility functions for working with Android.mk and make.""" + +from __future__ import absolute_import +import collections +import os +import re + +# Example: path/to/file.c:123:4: error: this is an error +_MAKE_ERROR_PATTERN = (r'^(?P<filename>[^:]+):(?P<linenum>\d+):(?P<column>\d+):' + r' error: (?P<err_msg>.*)$') +_MAKE_TOO_MANY_ERRORS_MSG = 'Too many errors! See the logs for the rest.' + + +def make_error_to_comments(make_output, directory): + """Convert a make failure message to comments for a gerrit review. + + In general, a when make has an error it prints to stderr and it looks like: + + [...snip...] + external/iw/wowlan.c:27:3: error: expected ')' before 'return' + return 1; + ^ + external/iw/wowlan.c:182:1: error: expected expression before '}' token + } + ^ + cc1.elf: some warnings being treated as errors + make: *** [out/obj/EXECUTABLES/iw_intermediates/wowlan.o] Error 1 + [...snip...] + + And this extracts out the 'error' lines from the rest of the log. + + Args: + make_output: stderr output from a make build command. (Note: it's possible + this may contain output from other commands. In general though, make + errors occur early in the build process and stop the build.) + directory: The path to strip off of the beginning of filenames in the + make output. Example: + make errors are for "path/to/your/files.cc" + directory == "path/to" => comments are for "your/files.cc" + + Returns: + A dictionary of file comments to be added to a review. + Keys are filenames and values are lists of dictionaries with 'line' and + 'message' entries. + { 'path/to/file.cc': [{'line': 5, 'message': 'error!'}, ...]} + An empty dict is returned if no comments are found. + """ + comments = collections.defaultdict(list) + + for line in make_output.splitlines(): + match = re.match(_MAKE_ERROR_PATTERN, line) + if match: + filename = match.group('filename') + # Strip off directory name and slash + if directory and filename.startswith(directory): + filename = filename[len(directory) + len(os.path.sep):] + linenum = int(match.group('linenum')) + comments[filename].append({'line': linenum, 'message': line}) + + return comments
diff --git a/cq/scripts/helpers/make_utils_test.py b/cq/scripts/helpers/make_utils_test.py new file mode 100644 index 0000000..d0a0ed7 --- /dev/null +++ b/cq/scripts/helpers/make_utils_test.py
@@ -0,0 +1,79 @@ +"""Tests for make_utils.""" + +from __future__ import absolute_import +import os +import sys +import unittest + +# Allow imports from cq/scripts folder +sys.path.insert( + 0, os.path.realpath(os.path.join(os.path.dirname(__file__), os.pardir))) +from helpers import make_utils + + +class MakeUtilsTest(unittest.TestCase): + + def testSingleError(self): + """Test the comments generated for a signle error.""" + make_output = ('path/to/warn.c:000:0: warning: This is just a warning.\n' + 'path/to/file.c:123:4: error: This is an error\n' + ' extra information for the erorr.\n' + 'some more lines that come later.\n') + directory = 'path/to' + + expected_comments = { + 'file.c': [{ + 'line': 123, + 'message': 'path/to/file.c:123:4: error: This is an error' + }] + } + + self.assertDictEqual( + expected_comments, + make_utils.make_error_to_comments(make_output, directory)) + + def testMultipleErrors(self): + """Test the comments generated from multiple different errors.""" + make_output = ('path/to/warn.c:000:0: warning: This is just a warning.\n' + 'path/to/file1.c:123:4: error: This is error 1\n' + ' extra information for the erorr.\n' + 'path/to/file1.c:456:7: error: This is error 2\n' + 'path/to/other/file3.c:1:1: error: This is error 3\n' + 'some more lines that come later.\n') + directory = 'path/to' + + expected_comments = { + 'file1.c': [{ + 'line': 123, + 'message': 'path/to/file1.c:123:4: error: This is error 1' + }, { + 'line': 456, + 'message': 'path/to/file1.c:456:7: error: This is error 2' + }], + 'other/file3.c': [{ + 'line': 1, + 'message': 'path/to/other/file3.c:1:1: error: This is error 3' + }] + } + + self.assertDictEqual( + expected_comments, + make_utils.make_error_to_comments(make_output, directory)) + + def testNoErrors(self): + """Test that no comments are generated if there are no errors.""" + make_output = ('path/to/warn.c:000:0: warning: This is just a warning.\n' + 'path/to/file.c:123:4: warning: This is another warning.\n' + ' extra information for the warning.\n' + 'Some more lines with something that is not an error\n') + directory = 'path/to' + + expected_comments = {} + + self.assertDictEqual( + expected_comments, + make_utils.make_error_to_comments(make_output, directory)) + + +if __name__ == '__main__': + unittest.main()
diff --git a/cq/scripts/helpers/ninja_utils.py b/cq/scripts/helpers/ninja_utils.py new file mode 100644 index 0000000..d1c4d92 --- /dev/null +++ b/cq/scripts/helpers/ninja_utils.py
@@ -0,0 +1,97 @@ +"""Compilation of utility functions for working with ninja.""" + +from __future__ import absolute_import +import re + +# Example: [123/9876] +NINJA_PROGRESS_PREFIX = r'^\[\d+/\d+\]' +NINJA_FAILED_PREFIX = '^FAILED: ' +NINJA_BUILD_STOPPED = '^ninja: build stopped: ' +# Example: 1 error generated. +# Example: 15 errors generated. +NINJA_ERRORS_GENERATED = r'^\d+ error(s?) generated\.$' +NINJA_FILE_INCLUDED_FROM = '^In file included from ' +NINJA_CLANG = r'third_party/llvm-build/Release\+Asserts/bin/clang\+\+' +# Example: prebuilt/toolchain/mips32r1/bin/mipsel-buildroot-linux-uclibc-g++ +# Example: prebuilt/toolchain/armv7a/bin/armv7a-cros-linux-gnueabi-g++ +NINJA_GXX = r'prebuilt/toolchain/(\S+)(g\+\+)' + +NINJA_TOO_MANY_ERRORS_MSG = 'Too many errors! See the logs for the rest.' + + +def ninja_failure_to_comments(ninja_output, max_errors=None): + """Convert a ninja failure message to comments for a gerrit review. + + In general, a log is from ninja is expected to look somewhat like: + + [...snip...] + [123/9876] CXX obj/path/to/foo.o + [124/9876] CXX obj/path/to/bar.o + FAILED: obj/path/to/bar.o + path/to/compiler/clang++ -FLAG -FLAG ... ... ... + path/to/foo:503:27: error: error was here + More specific error stuff + ^~~~~ + 1 error generated. + [125/9876] STAMP obj/path/to/baz.o + [126/9876] ACTION path/to/script + ninja: build stopped: subcommand failed + [...snip...] + + And this extracts out the FAILED block from the rest of the log. + + Args: + ninja_output: output from a ninja build command. + (Note: this can also include output from other tools in + addition to the ninja output, in case ninja is a subcommand + of another tool, such as make.) + max_errors: The maximum number of errors to include. If not None, + then the returned list will contain at most N error messages. + If more than N errors were generated, then the list will also + contain an N+1'th message indicating errors were left out. + + Returns: + A list of multi-line strings. Each string represents the text of a + single "FAILED" message from ninja. + An empty list is returned if no comments are found. + """ + comments = set() + + comment, in_failed_block = '', False + for line in ninja_output.splitlines(True): + + # Found the start of a failure block + if re.search(NINJA_FAILED_PREFIX, line): + in_failed_block = True + continue + + # Haven't found the start of a failure block yet, + # so this line is part of a success. Skip it. + if not in_failed_block: + continue + + # Found the end of a failure block. + if (re.search(NINJA_BUILD_STOPPED, line) or + re.search(NINJA_ERRORS_GENERATED, line) or + re.search(NINJA_PROGRESS_PREFIX, line)): + comments.add(comment.strip('\n')) + comment, in_failed_block = '', False + continue + + # Ignore these lines, as they are long and do not add enough + # useful information compared to other lines + if (re.search(NINJA_FILE_INCLUDED_FROM, line) or + re.search(NINJA_CLANG, line) or + re.search(NINJA_GXX, line)): + continue + + # Found a line within a failure block. + comment += line + + comments = list(comments) # pylint: disable=redefined-variable-type + if max_errors and isinstance(max_errors, int): + max_errors = int(max_errors) + if len(comments) > max_errors: + comments = comments[0:max_errors] + [NINJA_TOO_MANY_ERRORS_MSG] + + return comments
diff --git a/cq/scripts/helpers/ninja_utils_test.py b/cq/scripts/helpers/ninja_utils_test.py new file mode 100644 index 0000000..517ddd8 --- /dev/null +++ b/cq/scripts/helpers/ninja_utils_test.py
@@ -0,0 +1,85 @@ +"""Tests for ninja_utils.""" + +from __future__ import absolute_import +import os +import sys +import unittest + +# Allow imports from cq/scripts folder +sys.path.insert(0, os.path.realpath(os.path.join( + os.path.dirname(__file__), os.pardir))) +from helpers import ninja_utils + + +class NinjaUtilsTest(unittest.TestCase): + + def testSingleError(self): + """Test the comments generated for a single error.""" + ninja_output = ( + '[1/230] CXX obj/test/test.o\n' + 'FAILED: obj test/test.o\n' + '../prebuilt/toolchain/mips32r1/bin/mipsel-buildroot-linux-uclibc-g++' + ' -MMD -MF obj/test/test1.o -DV8 -fno\n' + 'In file included from ../../path/to/file:58:0,\n' + 'This line is expected.\n' + 'This line is also expected.\n' + '[2/230] CXX obj/test/test.o\n') + + expected_comments = ['This line is expected.\nThis line is also expected.'] + self.assertEqual(expected_comments, + ninja_utils.ninja_failure_to_comments(ninja_output)) + + def testMultipleErrors(self): + """Test the comments generated from multiple different errors.""" + ninja_output = ( + '[1/230] CXX obj/test/test.o\n' + 'FAILED: obj test/test1.o\n' + '../prebuilt/toolchain/mips32r1/bin/mipsel-buildroot-linux-uclibc-g++' + ' -MMD -MF obj/test/test1.o -DV8 -fno\n' + 'In file included from ../../path/to/file:58:0,\n' + 'This line is expected.\n' + 'This line is also expected.\n' + '[2/230] CXX obj/test/test.o\n' + 'FAILED: obj test/test2.o\n' + '../prebuilt/toolchain/mips32r1/bin/mipsel-buildroot-linux-uclibc-g++' + ' -MMD -MF obj/test/test1.o -DV8 -fno\n' + 'In file included from ../../path/to/file:58:0,\n' + 'This line is expected again.\n' + 'This line is also expected again.\n' + '[3/230] CXX obj/test/test3.o\n') + expected_comments = [ + 'This line is expected.\nThis line is also expected.', + 'This line is expected again.\nThis line is also expected again.' + ] + self.assertEqual( + set(expected_comments), + set(ninja_utils.ninja_failure_to_comments(ninja_output))) + + def testNoErrors(self): + """Test that no comments are generated if there are no errors.""" + ninja_output = ( + '[1/230] CXX obj/test/test.o\n' + '[2/230] CXX obj/test/test.o\n' + 'Unknown warming that is not handled.\n' + 'file: error something failed\n') + expected_comments = [] + self.assertEqual(expected_comments, + ninja_utils.ninja_failure_to_comments(ninja_output)) + + def testMaxErrors(self): + """Test that max_errors limits the errors correctly.""" + ninja_output = ( + 'FAILED: obj test/test1.o\n' + 'This line might be in the comments.\n' + '[2/230] CXX obj/test/test.o\n' + 'FAILED: obj test/test2.o\n' + 'This line might be in the comments. (But not both lines!).\n' + '[3/230] CXX obj/test/test3.o\n') + # Note that the particular comments that are saved are random. + actual_comments = ninja_utils.ninja_failure_to_comments(ninja_output, + max_errors=1) + self.assertEqual(2, len(actual_comments)) + self.assertEqual(ninja_utils.NINJA_TOO_MANY_ERRORS_MSG, actual_comments[-1]) + +if __name__ == '__main__': + unittest.main()
diff --git a/cq/scripts/helpers/os_utils.py b/cq/scripts/helpers/os_utils.py new file mode 100644 index 0000000..8f1def5 --- /dev/null +++ b/cq/scripts/helpers/os_utils.py
@@ -0,0 +1,24 @@ +"""Utilities for dealing with the operating system.""" +from __future__ import absolute_import +import contextlib +import logging +import os + +@contextlib.contextmanager +def change_cwd(path): + old_path = os.path.abspath('.') + os.chdir(path) + logging.debug( + "Changed directory from %s to %s", old_path, os.path.abspath('.')) + yield + os.chdir(old_path) + logging.debug("Changed directory back to %s", old_path) + + +def find_files(root, filename): + matching_paths = [] + for base, _, files in os.walk(root): + if filename in files: + matching_paths.append(os.path.join(base, filename)) + return matching_paths +
diff --git a/cq/scripts/helpers/puppet_utils.py b/cq/scripts/helpers/puppet_utils.py new file mode 100644 index 0000000..837445d --- /dev/null +++ b/cq/scripts/helpers/puppet_utils.py
@@ -0,0 +1,165 @@ +"""Utilities for working with puppet tools.""" + +from __future__ import absolute_import +import collections +import re + +_ANSI_COLOR_ESCAPE_SEQUENCE = r'\x1b[^m]*m' + + +def parser_errors_to_comments(errors, directory): + """Convert errors reported by the puppet parser in Gerrit comments. + + An example of an error from the puppet parser validator looks like: + Error: Could not parse for environment prod: + Syntax error at ','; expected '}' at /path/to/puppet/file.pp:27 + + Args: + errors: List of stderr strings output from the pupper parser. + directory: The directory to strip off of any filenames so file comments + are rooted at the project directory that Gerrit expects. + + Returns: + Dict of Gerrit comments: + { 'filename': [{'line': '27', 'message': 'Error!'}, ...], ... } + """ + + comments = collections.defaultdict(list) + for error in errors: + error = re.sub(_ANSI_COLOR_ESCAPE_SEQUENCE, '', error) + error_parts = error.split() + error_location = error_parts[-1] # /path/to/puppet/file.pp:27 + abs_filename, line_number = error_location.split(':') + rel_filename_start = abs_filename.index(directory) + len(directory) + rel_filename = abs_filename[rel_filename_start:] + if rel_filename.startswith('/'): + rel_filename = rel_filename[1:] + + error_parts[-1] = '{}:{}'.format(rel_filename, line_number) + + comment = {'line': line_number, 'message': ' '.join(error_parts)} + comments[rel_filename].append(comment) + + return comments + + +def linter_errors_to_comments(errors, directory): + """Convert errors reported by puppet-lint in Gerrit comments. + + Example json error: + { + "message": "indentation of => is not properly aligned", + "line": 6, + "column": 12, + "token": "#<PuppetLint::Lexer::Token:0x00000001d885a0>", + "indent_depth": 13, + "newline": false, + "newline_indent": " ", + "kind": "warning", + "check": "arrow_alignment", + "fullpath": "/abs/path/to/puppet/manifests/common.pp", + "path": "manifests/common.pp", + "filename": "common.pp", + "KIND": "WARNING" + } + + + Args: + errors: List of error dicts returned from puppet-lint with --json + directory: The directory to strip off of any filenames so file comments + are rooted at the project directory that Gerrit expects. + + Returns: + Dict of Gerrit comments: + { 'filename': [{'line': '27', 'message': 'Error!'}, ...], ... } + """ + if not errors: + return {} + + # puppet-lint output can wrap errors in nested lists, e.g. + # [[error1, error2, ...]], so handle that gracefully. + if isinstance(errors[0], list): + errors = errors[0] + + comments = collections.defaultdict(list) + for error in errors: + comment = {'line': str(error['line']), 'message': error['message']} + rel_filename_start = error['path'].index(directory) + len(directory) + rel_filename = error['path'][rel_filename_start:] + if rel_filename.startswith('/'): + rel_filename = rel_filename[1:] + comments[rel_filename].append(comment) + return comments + + +def get_cron_entries(puppet_lines): + """Pull out cron entries from a puppet file. + + A cron entry is converted into a dict, where the keys are the attributes + and the values are the attribute values (as strings). + + In addition, the dict as a special '_line_number' attribute that records + the line number the cron entry started at. + + Example + # Puppet entry # As dict + 27: cron { 'my_cron': cron_entry = { + 28: ensure => present, 'ensure': 'present', + 29: hour => 2, ----> 'hour': '2', + 30: minute => 0, 'minute': '0', + 31: command => $some_script, 'command': '$some_script', + '_line_number': '27', + 32: } } + + Args: + puppet_lines: List of lines from a puppet_file (e.g. from readlines()). + + Returns: + List of dict objects representing the cron entries. + """ + cron_entries = [] + within_cron_entry = False + curly_brace_count = 0 + for line_number, line in enumerate(puppet_lines, start=1): + if 'cron {' in line: + within_cron_entry = True + curly_brace_count = 1 + cron_entry = {'_line_number': str(line_number)} + continue + + if not within_cron_entry: + continue + + curly_brace_count += line.count('{') - line.count('}') + if curly_brace_count == 0: + within_cron_entry = False + cron_entries.append(cron_entry) + cron_entry = {} + continue + + if '=>' in line: + attribute, value = line.split('=>', 1) + if value.rstrip().endswith(','): + value = value.rstrip()[:-1] + cron_entry[attribute.strip()] = value.lstrip() + + return cron_entries + + +def cron_errors_to_comments(errors): + """Converts |errors| into Gerrit-style comments. + + Args: + errors: List of (filename, cron_entry dict) + Returns: + Dict of Gerrit comments: + { 'filename': [{'line': '27', 'message': 'Error!'}, ...], ... } + """ + comments = collections.defaultdict(list) + for puppet_file, cron_entry in errors: + comment = {'line': cron_entry['_line_number'], + 'message': 'cron entry missing "minute" attribute.',} + comments[puppet_file].append(comment) + return comments + +
diff --git a/cq/scripts/helpers/puppet_utils_test.py b/cq/scripts/helpers/puppet_utils_test.py new file mode 100644 index 0000000..1e66809 --- /dev/null +++ b/cq/scripts/helpers/puppet_utils_test.py
@@ -0,0 +1,283 @@ +"""Tests for puppet_utils.""" + +from __future__ import absolute_import +import os +import sys +import unittest +# Allow imports from cq/scripts folder +sys.path.insert( + 0, os.path.realpath(os.path.join(os.path.dirname(__file__), os.pardir))) + +from helpers import puppet_utils + + +class PuppetParserUtilsTest(unittest.TestCase): + """Tests for the puppet parser utils.""" + + def testEmptyErrors(self): + """Tests converting 0 parser errors to comments.""" + errors = [] + directory = '' + expected_comments = {} + actual_comments = puppet_utils.parser_errors_to_comments(errors, directory) + self.assertEqual(actual_comments, expected_comments) + + def testSingleError(self): + """Tests converting a single parser error to a comment.""" + error = ("Error: Could not parse for environment production: " + "Syntax error at '='; expected '}' at " + "/abs/path/to/project/dir/manifests/common.pp:43") + errors = [error] + directory = '/abs/path/to/project/dir' + expected_comments = { + 'manifests/common.pp': [{ + 'line': '43', + 'message': + "Error: Could not parse for environment production: Syntax " + "error at '='; expected '}' at manifests/common.pp:43" + }] + } + actual_comments = puppet_utils.parser_errors_to_comments(errors, directory) + self.assertEqual(actual_comments, expected_comments) + + def testSingleError_WithAnsiColorSequence(self): + """Tests stripping ANSI color sequences when converint to comments.""" + error = ("\x1b[1;31mError: Could not parse for environment production: " + "Syntax error at '='; expected '}' at " + "/abs/path/to/project/dir/manifests/common.pp:43\x1b[1;39m") + errors = [error] + directory = '/abs/path/to/project/dir' + expected_comments = { + 'manifests/common.pp': [{ + 'line': '43', + 'message': + "Error: Could not parse for environment production: Syntax " + "error at '='; expected '}' at manifests/common.pp:43" + }] + } + actual_comments = puppet_utils.parser_errors_to_comments(errors, directory) + self.assertEqual(actual_comments, expected_comments) + + def testMultipleErrors(self): + """Tests converting multiple parser errors into separate comments.""" + error1 = ("Error: Could not parse for environment production: " + "Syntax error at '='; expected '}' at " + "/abs/path/to/project/dir/manifests/common.pp:43") + error2 = ("Error: Could not parse for environment production: " + "Syntax error at ','; expected ']' at " + "/abs/path/to/project/dir/manifests/other.pp:1") + errors = [error1, error2] + directory = '/abs/path/to/project/dir' + expected_comments = { + 'manifests/common.pp': [{ + 'line': '43', + 'message': + "Error: Could not parse for environment production: Syntax " + "error at '='; expected '}' at manifests/common.pp:43" + }], + 'manifests/other.pp': [{ + 'line': '1', + 'message': + "Error: Could not parse for environment production: Syntax " + "error at ','; expected ']' at manifests/other.pp:1" + }] + } + actual_comments = puppet_utils.parser_errors_to_comments(errors, directory) + self.assertEqual(actual_comments, expected_comments) + + +class PuppetLinterUtilsTest(unittest.TestCase): + """Tests for puppet-lint utils.""" + + def testEmpty(self): + """Tests converting 0 lint errors into comments.""" + errors = [] + directory = '' + expected_comments = {} + actual_comments = puppet_utils.linter_errors_to_comments(errors, directory) + self.assertEqual(actual_comments, expected_comments) + + def testSingleError(self): + """Tests converting a single linter error into a comment.""" + errors = [{ + 'kind': 'error', + 'check': 'syntax', + 'message': 'Bad indentation.', + 'line': 34, + 'column': 10, + 'fullpath': '/full/path/to/project/dir/manifests/common.pp', + 'path': 'project/dir/manifests/common.pp', + 'filename': 'common.pp', + 'KIND': 'ERROR' + }] + directory = 'project/dir' + expected_comments = { + 'manifests/common.pp': [{ + 'line': '34', + 'message': 'Bad indentation.' + }] + } + actual_comments = puppet_utils.linter_errors_to_comments(errors, directory) + self.assertEqual(actual_comments, expected_comments) + + def testMultipleErrors(self): + """Tests converting multiple linter errors into separate comments.""" + errors = [{ + 'kind': 'error', + 'check': 'syntax', + 'message': 'Bad indentation.', + 'line': 34, + 'column': 10, + 'fullpath': '/full/path/to/project/dir/manifests/common.pp', + 'path': 'project/dir/manifests/common.pp', + 'filename': 'common.pp', + 'KIND': 'ERROR' + }, { + 'message': 'unquoted resource title', + 'line': 6, + 'column': 11, + 'token': '#<PuppetLint::Lexer::Token:0x00000001088350>', + 'kind': 'warning', + 'check': 'unquoted_resource_title', + 'fullpath': '/path/to/project/dir/manifests/site.pp', + 'path': 'project/dir/manifests/site.pp', + 'filename': 'site.pp', + 'KIND': 'WARNING' + }] + directory = 'project/dir' + expected_comments = { + 'manifests/common.pp': [{ + 'line': '34', + 'message': 'Bad indentation.' + }], + 'manifests/site.pp': [{ + 'line': '6', + 'message': 'unquoted resource title' + }] + } + actual_comments = puppet_utils.linter_errors_to_comments(errors, directory) + self.assertEqual(actual_comments, expected_comments) + + + def testErrorInNestedList(self): + """Tests that if errors are wrapped in a list, things still work.""" + errors = [[{ + 'kind': 'error', + 'check': 'syntax', + 'message': 'Bad indentation.', + 'line': 34, + 'column': 10, + 'fullpath': '/full/path/to/project/dir/manifests/common.pp', + 'path': 'project/dir/manifests/common.pp', + 'filename': 'common.pp', + 'KIND': 'ERROR' + }]] + directory = 'project/dir' + expected_comments = { + 'manifests/common.pp': [{ + 'line': '34', + 'message': 'Bad indentation.' + }] + } + actual_comments = puppet_utils.linter_errors_to_comments(errors, directory) + self.assertEqual(actual_comments, expected_comments) + + +class PuppetCronUtilsTest(unittest.TestCase): + + def testGetCronEntries_EmptyFile(self): + puppet_lines = [] + expected_cron_entries = [] + actual_cron_entries = puppet_utils.get_cron_entries(puppet_lines) + self.assertEqual(expected_cron_entries, actual_cron_entries) + + def testGetCronEntries_SingleCron(self): + puppet_lines = ['cron { "$cron_name":', + ' ensure => present,', + ' command => $my_script,', + ' hour => 2,', + ' minute => 0,', + '}'] + expected_cron_entries = [ + {'_line_number': '1', + 'ensure': 'present', + 'command': '$my_script', + 'hour': '2', + 'minute': '0',} + ] + actual_cron_entries = puppet_utils.get_cron_entries(puppet_lines) + self.assertEqual(expected_cron_entries, actual_cron_entries) + + def testGetCronEntries_MultipleCrons(self): + puppet_lines = ['cron { "$cron_name":', + ' ensure => present,', + ' command => $my_script,', + ' hour => 2,', + ' minute => 0,', + '}', + '', + 'cron { \'other_cron\':', + ' ensure => absent,', + ' command => "/usr/bin/bad_thing arg1 arg2,', + ' hour => 2,', + '}'] + expected_cron_entries = [ + {'_line_number': '1', + 'ensure': 'present', + 'command': '$my_script', + 'hour': '2', + 'minute': '0',}, + {'_line_number': '8', + 'ensure': 'absent', + 'command': '"/usr/bin/bad_thing arg1 arg2', + 'hour': '2',}, + ] + actual_cron_entries = puppet_utils.get_cron_entries(puppet_lines) + self.assertEqual(expected_cron_entries, actual_cron_entries) + + + def testGetCronEntries_MultilineAttributeValue(self): + puppet_lines = ['cron { "$cron_name":', + ' ensure => present,', + ' command => "/usr/bin/script ', + ' --that-has-very-long-args=yep', + ' --and-is-split-over-several-lints"', + ' hour => 2,', + ' minute => 0,', + '}'] + # The extra lines in the command attribute are just ignored. + expected_cron_entries = [ + {'_line_number': '1', + 'ensure': 'present', + 'command': '"/usr/bin/script ', + 'hour': '2', + 'minute': '0',} + ] + actual_cron_entries = puppet_utils.get_cron_entries(puppet_lines) + self.assertEqual(expected_cron_entries, actual_cron_entries) + + def testGetCronEntries_CurlyBraceCounting(self): + puppet_lines = ['cron { "$cron_name":', + ' ensure => present, ', + ' command => "/usr/bin/script ', + ' hour => 2,', + ' minute => 0,', + ' attr => { nested stuff', + ' xyz ', + ' }', + '}'] + # The extra lines in the command attribute are just ignored. + expected_cron_entries = [ + {'_line_number': '1', + 'ensure': 'present', + 'command': '"/usr/bin/script ', + 'hour': '2', + 'minute': '0', + 'attr': '{ nested stuff',} + ] + actual_cron_entries = puppet_utils.get_cron_entries(puppet_lines) + self.assertEqual(expected_cron_entries, actual_cron_entries) + + +if __name__ == '__main__': + unittest.main()
diff --git a/cq/scripts/helpers/py_env_utils.py b/cq/scripts/helpers/py_env_utils.py new file mode 100644 index 0000000..966dde0 --- /dev/null +++ b/cq/scripts/helpers/py_env_utils.py
@@ -0,0 +1,221 @@ +"""Script to help with the creation of python virtual envs.""" +import glob +import logging +import os +from pathlib import Path +import sys +from typing import Iterable + +DEFAULT_LOCAL_PACKAGES = 'python_packages' +VENV_RECIPE_PY2 = '~/venv_recipe/bin' + + +def _get_pip(venv_root): + return os.path.join(venv_root, 'bin', 'pip') + + +def add_import_paths(venv_root: Path, paths: Iterable[Path]) -> None: + """Add an entry into the custom import locations for a venv. + + This will create a python path file in the provided virtual + environment such that python can import modules from + the provided path. + + Args: + venv_root: The root directory of a virtualenv to install into. + paths: The paths to add + """ + venv_lib = os.path.join(venv_root, 'lib', '*') + for version_lib in glob.glob(venv_lib): + pathfile = os.path.join(version_lib, 'site-packages', 'google.pth') + try: + with open(pathfile, 'r') as f: + content = f.read() + old_paths = [Path(p) for p in content.split('\n') if p] + new_paths = sorted(old_paths + paths) + except IOError: + new_paths = paths + with open(pathfile, 'w') as f: + f.write('\n'.join(str(p) for p in new_paths)) + logging.info('Wrote the following paths to %s: %s', pathfile, paths) + + +def create_virtual_env( + executor, directory, gcs_dir, local_packages=None, py3=False): + """Creates a python virtual env. + + Args: + executor: Executes the subprocess. + directory: Directory to execute the subprocess in. + gcs_dir: The directory that mirrors the gcs bucket + local_packages: Relative path to python packages under ~/gcs-mirror + py3: if True use python3 + + Returns: + The path to the new virtualenv directory root. + """ + python_sandbox_dir = os.path.join(directory, 'python-sandbox') + env = {} + if py3: + cmd = ['python3', '-m', 'venv', python_sandbox_dir] + else: + cmd = ['python2', '-m', 'virtualenv', + '--extra-search-dir={}'.format( + _get_find_links_path(gcs_dir, local_packages)), + '--no-download', + python_sandbox_dir] + env['PATH'] = os.pathsep.join([ + os.path.expanduser(VENV_RECIPE_PY2), os.getenv('PATH')]) + executor.exec_subprocess(cmd, env=env, check_output=True) + return python_sandbox_dir + + +def install_package(executor, venv_root, path, gcs_dir, local_packages=None): + """Install a local package from disk. + + Args: + executor: Executes the subprocess. + venv_root: The root directory of a virtualenv to install into. + path: The path to the package on local disk + gcs_dir: The path to the gcs mirror directory. + local_packages: Relative path to python packages under ~/gcs-mirror + """ + # Perform necessary default package upgrades. + _update_default_deps( + executor, + venv_root, + ['pip', 'wheel', 'setuptools'], + local_packages, + gcs_dir + ) + + venv_pip = _get_pip(venv_root) + + executor.exec_subprocess( + [venv_pip, 'install', '-e', path], + check_output=True) + + +def install_py_deps( + executor, venv_root, requirements, gcs_dir, local_packages=None): + """Install the python dependencies. + + Args: + executor: Executes the subprocess. + venv_root: The root directory of a virtualenv to install |requirements| in. + requirements: The path to the requirements.txt to install. + gcs_dir: The path to the gcs mirror directory. + local_packages: Relative path to python packages under ~/gcs-mirror + """ + if not os.path.isfile(requirements): + logging.warning('No requirements file found: %s', requirements) + return + + # Perform necessary default package upgrades. + _update_default_deps( + executor, + venv_root, + ['pip', 'wheel', 'setuptools'], + local_packages, + gcs_dir + ) + + venv_pip = _get_pip(venv_root) + + executor.exec_subprocess( + [venv_pip, 'install', '--no-index', + '--find-links=file://{}'.format( + _get_find_links_path(gcs_dir, local_packages)), + '-r', requirements], + check_output=True) + + +def _update_default_deps(executor, venv_root, deps, local_packages, gcs_dir): + """Update the pip packages required to install dependencies. + + Args: + executor: Executes the subprocess. + venv_root: The root directory of the virtualenv. + deps: List of pip packages to update. + local_packages: Relative path to python packages under ~/gcs-mirror. + gcs_dir: The path to the gcs mirror directory. + """ + venv_pip = _get_pip(venv_root) + for dep in deps: + executor.exec_subprocess( + [venv_pip, 'install', '--no-index', + '--find-links=file://{}'.format( + _get_find_links_path(gcs_dir, local_packages)), + '--upgrade', dep], + check_output=True) + + +def exec_within_virtual_env( + executor, venv_root, cmd, env=None): + """Executes |cmd| within a python virtualenv. + + Args: + executor: Executes the subprocess. + venv_root: The root directory of a virtualenv to run in. + cmd: The command list to pass to virtualenv python interpreter. This will + be prepended with virtualenv python, so it should not start with python. + (e.g. If you want to run `python my_python_script.py --flag1 --arg=3` + then pass cmd = ['my_python_script.py', '--flag1', '--arg=3'].) + env: A dictionary with additional environment variables. + + Returns: + returncode, stdout, stderr from the subprocess. + """ + venv_python = os.path.join(venv_root, 'bin', 'python') + full_cmd = [venv_python] + cmd + return executor.exec_subprocess(full_cmd, env=env) + + +def _get_find_links_path(gcs_dir: str, local_packages=None): + if not local_packages: + local_packages = DEFAULT_LOCAL_PACKAGES + return os.path.expanduser(os.path.join(gcs_dir, local_packages)) + + +class ActivateVenv(object): + """Context manage to activate python virtual environment. + + Will deactive on exit, and revert back to the previous venv. + This is designed to run from inside another venv. If not, it + will raise KeyError since sys.real_prefix only exists + when Python is run in a venv. Since our infras always run + from a venv, this is an acceptable assumption. + + Args: + venv_root: Path to the python virtual env root. + """ + def __init__(self, venv_root): + self._venv_root = venv_root + self._prev_os_path = None + self._prev_sys_path = None + self._prev_prefix = None + self._prev_real_prefix = None + self._save_current_env() + + def __enter__(self): + env_activation_file = os.path.join( + self._venv_root, 'bin', 'activate_this.py') + exec(compile(open(env_activation_file, "rb").read(), + env_activation_file, 'exec'), + dict(__file__=env_activation_file)) + + def __exit__(self, *args): + sys.path[:0] = self._prev_sys_path + sys.prefix = self._prev_prefix + os.environ['PATH'] = self._prev_os_path + if self._prev_real_prefix is not None: + sys.real_prefix = self._prev_real_prefix + + def _save_current_env(self): + self._prev_os_path = os.environ['PATH'] + self._prev_sys_path = list(sys.path) + self._prev_prefix = sys.prefix + # real_prefix attribute only exists if Python is run from a venv. + if hasattr(sys, 'real_prefix'): + self._prev_real_prefix = sys.real_prefix +
diff --git a/cq/scripts/helpers/py_test_runner.py b/cq/scripts/helpers/py_test_runner.py new file mode 100644 index 0000000..0ab97d8 --- /dev/null +++ b/cq/scripts/helpers/py_test_runner.py
@@ -0,0 +1,200 @@ +"""Run python unittests and dump a json report of the results to stdout. + +Usage: + python py_unittest_runner.py path/to/unittests_dir + +""" +import argparse +import json +import logging +import os +from pathlib import Path +import sys +from typing import Optional + +import gunittest.runner + +LOGGER = logging.getLogger(__name__) + +def run_tests(directory, test_file_filter_regex, timeout, + fail_fast: bool, + after_module: Optional[str]=None, + multiprocessing=True, module_path_regex='.'): + """Crawl |directory| and run all python tests. + + Args: + directory: Path to search for python tests to run. + test_file_filter_regex: File pattern for tests to be run. + timeout: Test timeout (in seconds). + multiprocessing: Use multiprocessing if True. + module_path_regex: Regex to determine which modules to include. + fail_fast: Fail on first encountered error. + + Returns: + The summarized test results. + """ + + results = gunittest.runner.RunTests( + directory, + module_path_regex=module_path_regex, + test_file_filter_regex=test_file_filter_regex, + timeout=timeout, + use_multiprocessing=multiprocessing, + after_module=after_module, + fail_fast=fail_fast, + ) + summary = gunittest.runner.Summarize(results) + return summary + + +def generate_review(summary): + """Generate a Gerrit review from the test results |summary|. + + Args: + summary: A dictionary with: errors, failures, results keys each + containing a list of db.model.TestResult objects, summarizing the + results of a test run. + + Returns: + {'message': review_message, 'passing': passing}, where |review_message| + is a string giving summary information of the test run and |passing| is a + bool indicating if the tests all passed (no failurs, no errors). + """ + errors = summary.get('errors', []) + failures = summary.get('failures', []) + all_results = summary.get('results', []) + elapsed_secs = summary.get('elapsed_secs', 0) + passing = len(errors) + len(failures) == 0 + passing_msg = 'Passing' if passing else 'Failing' + message = ('Unit Test Results: {}\n' + 'Run: {}, Errors: {}, Failures: {}\n' + 'Total Run Time: {}').format(passing_msg, + len(all_results), + len(errors), + len(failures), elapsed_secs) + failure_msgs = [ + '{}\n\n{}\n'.format(f.GetTestName(), f.GetStack()) for f in failures + ] + if failure_msgs: + message += '\n\nFailures:\n{}'.format('\n'.join(failure_msgs)) + + error_msgs = [ + '{}\n\n{}\n'.format(e.GetTestName(), e.GetStack()) for e in errors + ] + if error_msgs: + message += '\n\nErrors:\n{}'.format('\n'.join(error_msgs)) + + LOGGER.info(message) + + return {'message': message, 'passing': passing} + + +def parse_cmdline_args() -> argparse.Namespace: + """Returns the parsed command line arguments.""" + parser = argparse.ArgumentParser( + description='Run python tests in a given directory.') + parser.add_argument('--after-module', + help=("Run tests that are from modules alphabetically " + "after the provided term.")) + parser.add_argument( + '--fail-fast', + action='store_true', + help='Fail on the first test error.') + parser.add_argument( + '--test_dir', + help='the directory to search for tests to run.', + required=True) + parser.add_argument( + '--output', type=Path, help='The file to output the JSON results to.', required=True) + parser.add_argument( + '--test_file_filter_regex', + help='File pattern for tests to be run.', + default='.*test.py$') + parser.add_argument( + '--module_path_regex', + help='Regex to determine which modules to include.', + default='.') + parser.add_argument( + '--timeout', + help='Timeout (in seconds) for running tests.', + type=int, + required=True) + parser.add_argument( + '--single-process', + help='Avoid using multiple processes when running tests.', + action='store_true', + ) + parser.add_argument( + "--verbose", + action="store_true", + help="When present, show debug logs for the test runner.", + ) + args = parser.parse_args() + + if not os.path.isdir(args.test_dir): + parser.error( + 'test_dir "{}" does not exist.'.format(os.path.abspath(args.test_dir))) + + return args + + +class LoggingSetupError(Exception): + pass + + +def _setup_logging(verbose: bool) -> None: + """Set up logging. + + We want to both allow sending logs from this runner and to capture logs + from tests that we plan to run. + + Args: + verbose: show verbose logs + """ + root = logging.getLogger() + if root.handlers: + raise LoggingSetupError( + "Someone is modifying the logging setup at import time. This is a bad " + "practice. This test runner refuses to fight with badly-behaved tests " + "and will now exit.") + root.setLevel(logging.WARNING) + level = logging.DEBUG if verbose else logging.INFO + LOGGER.setLevel(level) + stream = logging.StreamHandler() + stream.setFormatter( + logging.Formatter( + "%(levelname)s %(process)d:%(thread)d %(name)s %(asctime)s: %(message)s")) + LOGGER.addHandler(stream) + LOGGER.info("Logging handler established") + test_runner = logging.getLogger("gunittest.runner") + test_runner.addHandler(stream) + test_runner.setLevel(level) + + +def main(): + args = parse_cmdline_args() + try: + _setup_logging(args.verbose) + except LoggingSetupError as ex: + print(ex) + sys.exit(1) + test_results = run_tests( + args.test_dir, + test_file_filter_regex=args.test_file_filter_regex, + timeout=args.timeout, + multiprocessing=not args.single_process, + module_path_regex=args.module_path_regex, + after_module=args.after_module, + fail_fast=args.fail_fast, + ) + review = generate_review(test_results) + + if args.output.parent: + args.output.parent.mkdir(exist_ok=True) + + with open(args.output, 'w') as output: + json.dump(review, output) + + +if __name__ == '__main__': + main()
diff --git a/cq/scripts/helpers/pylint.py b/cq/scripts/helpers/pylint.py new file mode 100755 index 0000000..85c0d82 --- /dev/null +++ b/cq/scripts/helpers/pylint.py
@@ -0,0 +1,81 @@ +"""Script that lints a list of changed files then outputs a list of comments.""" + +from __future__ import absolute_import +import collections +import logging +import os +import re +import subprocess + +# path/to/file.py:27: [E1234(error-name), Text] Error message is here +LINT_WARNING_PATTERN = (r'^(?P<filename>[^:]+):(?P<line_num>\d+): ' + r'\[(?P<error_code>\w+)\((?P<error_name>.*)\).*\] ' + r'(?P<error_msg>.*)$') + + +class PylintError(Exception): + """Error for the pylint module.""" + + +def RunPylint(changed_files, pylintrc_file=None, cwd=None, executor=None): + """Runs pylint on a list of changed files. + + Args: + changed_files: List of files to lint. + pylintrc_file: Path to a pylintrc file to use with pylint (or None to use + the default pylintrc from depot_tools). + cwd: If provided, cwd in which to run pylint. + executor: If provided, object with which to invoke pylint. + + Returns: + stdout of the pylint command. + + Raises: + PylintError: if pylint cannot be found. + """ + if not changed_files: + return '' + + pylint = os.path.expanduser('~/depot_tools/pylint') + if not os.path.exists(pylint): + logging.error('pylint not installed in expected location: %s', pylint) + raise PylintError('Could not find pylint.') + + command = [pylint, '--output-format=parseable', '--disable=I'] + if pylintrc_file: + command += ['--rcfile={}'.format(pylintrc_file)] + command += changed_files + if executor: + _, stdout, _ = executor.exec_subprocess(command, cwd=cwd) + return stdout + + return subprocess.check_output(command, cwd=cwd) + + +def ParseLint(lines, cwd=None): + """Reads lines from lint output and inserts them into comments. + + Args: + lines: List of lint output lines to parse. + cwd: Base path relative to which parsed paths should be resolved. + Returns: + comments dictionary. + """ + comments = collections.defaultdict(list) + for line in lines: + match = re.match(LINT_WARNING_PATTERN, line) + if match: + warning = { + 'line': + match.group('line_num'), + 'message': + '{} [{}]'.format( + match.group('error_msg'), match.group('error_name')) + } + if cwd: + filename = os.path.relpath(match.group('filename'), cwd) + else: + filename = match.group('filename') + comments[filename].append(warning) + + return comments
diff --git a/cq/scripts/helpers/pylint_test.py b/cq/scripts/helpers/pylint_test.py new file mode 100644 index 0000000..cf39d1b --- /dev/null +++ b/cq/scripts/helpers/pylint_test.py
@@ -0,0 +1,40 @@ +"""Tests for pylint.""" +import os +import sys +import unittest + +from cq.scripts.helpers import pylint + + +class PylintTest(unittest.TestCase): + + def testParseLintOutput(self): + """Tests parsing lint output.""" + py_file = 'path/to/file_one.py' + lines = [ + '************* Module path.to.file_one', + 'path/to/file_one.py:37: [E0001(error-1), RunPylint] First error.', + 'path/to/file_one.py:50: [E(error/type2), RunPylint] Second error.', + 'path/to/file_one.py:1: [W1201(warningXYZ), RunPylint] Warning.', + ] + result_comments = pylint.ParseLint(lines) + + comments = result_comments[py_file] + self.assertIsNotNone(comments) + self.assertEqual(3, len(comments)) + + comment = comments[0] + self.assertEqual('37', comment['line']) + self.assertEqual('First error. [error-1]', comment['message']) + + comment = comments[1] + self.assertEqual('50', comment['line']) + self.assertEqual('Second error. [error/type2]', comment['message']) + + comment = comments[2] + self.assertEqual('1', comment['line']) + self.assertEqual('Warning. [warningXYZ]', comment['message']) + + +if __name__ == '__main__': + unittest.main()
diff --git a/cq/scripts/helpers/rbe_utils.py b/cq/scripts/helpers/rbe_utils.py new file mode 100644 index 0000000..7557eb5 --- /dev/null +++ b/cq/scripts/helpers/rbe_utils.py
@@ -0,0 +1,104 @@ +""" Utility functions for working with re-client tooling. + +Functions for starting and stopping reproxy. +""" + +from __future__ import absolute_import +import os + +RBE_SERVICE='remotebuildexecution.googleapis.com:443' +DEFAULT_INSTANCE = 'projects/nest-rbe-prod/instances/us-central' +RBE_REPROXY_ADDR = 'unix:///tmp/reproxy.sock' + +NEW_RBE_REL_PATH = 'chromium/src/buildtools/reclient' +OLD_RBE_REL_PATH = 'chromium/src/buildtools/rbe' + + +def _rbe_path(): + """Path to RBE binaries relative to chromium/src + + The path was moved from rbe -> reclient, but some old branches still use + the old path, so test the new path and fall back to the old path if needed. + """ + if os.path.exists(NEW_RBE_REL_PATH): + return NEW_RBE_REL_PATH + return OLD_RBE_REL_PATH + +def _depscan_path(): + return os.path.join(_rbe_path(), 'dependency_scanner_go_plugin.so') + +def _rbe_start_command(): + """Command to start the remote execution proxy (reproxy).""" + return [os.path.join(_rbe_path(), 'bootstrap'), + '-re_proxy=' + os.path.join(_rbe_path(), 'reproxy')] + +def _rbe_stop_command(): + """Command to stop the remote execution proxy (reproxy, via bootstrap).""" + return [os.path.join(_rbe_path(), 'bootstrap'), + '--shutdown'] + +def is_installed(): + """Returns True if the rbe bootstrap client is available.""" + return os.path.exists(os.path.join(_rbe_path(), 'bootstrap')) + + +def start_reproxy(executor): + """Runs 'reproxy <args>' to start the reproxy and connect to the rbe backend. + + This is run in a non-blocking fashion as the reproxy should be running for + the duration of the receipe. + + Args: + executor: Executes the subprocess. + + Returns: + (returncode, stdout, stderr) + """ + return executor.exec_subprocess(_rbe_start_command(), + env=_get_rbe_env(executor)) + + +def stop_reproxy(executor): + """Runs 'bootstrap --shutdown' which stops the reproxy process. + + Args: + executor: Executes the subprocess. + + Returns: + (returncode, stdout, stderr) + """ + return executor.exec_subprocess(_rbe_stop_command(), + env=_get_rbe_env(executor)) + + +def _get_rbe_env(executor): + """Returns the dict of environment vars to pass to bootstrap/reproxy. + + Args: + tmp_dir: Temporary directory to place logs. + + Returns: + dict of environment variables. + """ + # Set flags to reproxy via env variables. + tmp_dir = executor.get_tmp_dir() + log_dir = executor.get_gcs_dir() + env_values = { + 'RBE_use_gce_credentials': 'true', + 'RBE_service': RBE_SERVICE, + 'RBE_instance': executor.get_property('rbe_instance', DEFAULT_INSTANCE), + 'RBE_server_address': RBE_REPROXY_ADDR, + 'RBE_clean_include_paths': 'true', + 'RBE_log_dir': log_dir, + # The files generated by the proxy are large and not very useful. + 'RBE_proxy_log_dir': tmp_dir, + 'RBE_output_dir': log_dir, + # Set the clang plugins to ignore during deps scanning. + 'RBE_clang_depscan_ignored_plugins': + 'find-bad-constructs,blink-gc-plugin', + } + # The dependency_scanner_go_plugin.so is removed in newer versions of RBE + # But older branches still need it. Include only if needed. + if os.path.exists(_depscan_path()): + env_values['RBE_cpp_dependency_scanner_plugin'] = _depscan_path() + return env_values
diff --git a/cq/scripts/helpers/repo_utils.py b/cq/scripts/helpers/repo_utils.py new file mode 100644 index 0000000..d10a2b0 --- /dev/null +++ b/cq/scripts/helpers/repo_utils.py
@@ -0,0 +1,497 @@ +"""Tools to interact with repo.""" + +from __future__ import absolute_import +from contextlib import contextmanager +import logging +import os +import shutil +import tempfile +from xml.dom import minidom +import xml.etree.ElementTree as et + +import six + +DEFAULT_REMOTE = 'eureka' + +EUREKA_MANIFEST_PROJECT_NAME = 'eureka/manifest' +LIBASSISTANT_MANIFEST_PROJECT_NAME = 'standalone/manifest' + +EUREKA_INTERNAL_HOST_URL = 'https://eureka-internal.googlesource.com/' +EUREKA_PARTNER_HOST_URL = 'https://eureka-partner.googlesource.com/' + +EUREKA_MANIFEST_URL = ( + EUREKA_INTERNAL_HOST_URL + EUREKA_MANIFEST_PROJECT_NAME) +CATABUILDER_E2E_TESTS_MANIFEST_URL = ( + 'https://eureka-staging-internal.googlesource.com/' + 'catabuilder_e2e_tests_manifest') +GOTHAM_MCU_MANIFEST_URL = ( + 'https://team.googlesource.com/gotham-cr/manifest') +LIBASSISTANT_MANIFEST_URL = ( + 'https://libassistant-internal.googlesource.com/' + + LIBASSISTANT_MANIFEST_PROJECT_NAME) +PARTNER_MANIFEST_URL = ( + EUREKA_PARTNER_HOST_URL + 'partner/manifest') +PARTNER_AMLOGIC_MANIFEST_URL = ( + EUREKA_PARTNER_HOST_URL + 'amlogic/manifest') +CAST_AUDIO_STANDARD_MANIFEST_URL = ( + EUREKA_PARTNER_HOST_URL + 'partner/manifest_cast_audio') +CAST_AUDIO_REFERENCE_MANIFEST_URL = ( + EUREKA_PARTNER_HOST_URL + 'partner/manifest_cast_audio_reference') +CAST_ASSISTANT_REFERENCE_MANIFEST_URL = ( + EUREKA_PARTNER_HOST_URL + 'partner/manifest_cast_assistant_reference') +CAST_TV_MANIFEST_URL = ( + EUREKA_PARTNER_HOST_URL + 'partner/manifest_cast_tv') +CAST_TV_MARVELL_MANIFEST_URL = ( + EUREKA_PARTNER_HOST_URL + 'partner/manifest_cast_tv_marvell') +CAST_TV_MEDIATEK_MANIFEST_URL = ( + EUREKA_PARTNER_HOST_URL + 'partner/manifest_cast_tv_mediatek') +CAST_TV_MSTAR_MANIFEST_URL = ( + EUREKA_PARTNER_HOST_URL + 'partner/manifest_cast_tv_mstar') +CAST_TV_NOVATEK_URL = ( + EUREKA_PARTNER_HOST_URL + 'partner/manifest_cast_tv_novatek') +CAST_TV_COMCAST_URL = ( + EUREKA_PARTNER_HOST_URL + 'partner/manifest_comcast') +ABBEY_MANIFEST_URL = ( + EUREKA_INTERNAL_HOST_URL + 'abbey/manifest') +PARTNER_QUALCOMM_MANIFEST_URL = ( + EUREKA_PARTNER_HOST_URL + 'qualcomm/manifest') +PARTNER_QUALCOMM_MANIFEST_OTA_URL = ( + EUREKA_PARTNER_HOST_URL + 'qualcomm/manifest_ota') + +REPO_MANIFEST_PROJECT_PATH = '.repo/manifests' +REPO_MANIFEST_PROJECT_REMOTE = 'origin' + +REPO_MANIFEST_URL_TO_PROJECT_NAME = { + EUREKA_MANIFEST_URL: EUREKA_MANIFEST_PROJECT_NAME, + LIBASSISTANT_MANIFEST_URL: LIBASSISTANT_MANIFEST_PROJECT_NAME, +} + +MANIFEST_OVERRIDE_XML = 'manifest_contour.xml' + +REPO_MANIFEST_URL_TO_REPO_ALIAS = { + ABBEY_MANIFEST_URL: 'abbey', + CAST_ASSISTANT_REFERENCE_MANIFEST_URL: 'cast_assistant_reference', + CAST_AUDIO_REFERENCE_MANIFEST_URL: 'cast_audio_reference', + CAST_AUDIO_STANDARD_MANIFEST_URL: 'cast_audio_new', + CAST_TV_COMCAST_URL: 'cast_tv_comcast', + CAST_TV_MANIFEST_URL: 'cast_tv', + CAST_TV_MARVELL_MANIFEST_URL: 'cast_tv_marvell', + CAST_TV_MEDIATEK_MANIFEST_URL: 'cast_tv_mediatek', + CAST_TV_MSTAR_MANIFEST_URL: 'cast_tv_mstar', + CAST_TV_NOVATEK_URL: 'cast_tv_novatek', + EUREKA_MANIFEST_URL: 'internal', + GOTHAM_MCU_MANIFEST_URL: 'gotham_mcu', + LIBASSISTANT_MANIFEST_URL: 'libassistant', + PARTNER_AMLOGIC_MANIFEST_URL: 'partner_amlogic', + PARTNER_MANIFEST_URL: 'partner', + PARTNER_QUALCOMM_MANIFEST_URL: 'partner_qualcomm', + PARTNER_QUALCOMM_MANIFEST_OTA_URL: 'partner_qualcomm_ota', + CATABUILDER_E2E_TESTS_MANIFEST_URL: 'e2e_tests', +} + + +class DuplicateLookupError(Exception): + """Error if the project was included more than once.""" + + +class ManifestParseError(Exception): + """Error if unable to parse output of 'repo manifest' command.""" + + +class ProjectLookupTable(object): + """A lookup table for project and project paths.""" + + def __init__(self, lookup_dict=None, duplicate_keys=None): + """Create a ProjectLookupTable. + + Args: + lookup_dict: Dictionary of key/value pairs. + duplicate_keys: A list of keys that were duplicates. + """ + if not lookup_dict: + lookup_dict = {} + if not duplicate_keys: + duplicate_keys = [] + self._lookup_dict = lookup_dict + self._duplicate_keys = duplicate_keys + + def __getitem__(self, key): + """Get the value for the given key. + + Args: + key: The key to get a value for. + + Returns: + The value for the given key. + + Raises: + KeyError: If the key is not included. + DuplicateLookupError: If the key was included multiple times. + """ + return self.get(key) + + def __setitem__(self, key, value): + """Sets the value for the given key.""" + if self._lookup_dict.get(key): + self._duplicate_keys.append(key) + self._lookup_dict[key] = value + + def __contains__(self, key): + """Returns true if key is in the underlying dict.""" + return key in self._lookup_dict + + def get(self, key): + """Get the value for the given key. + + Args: + key: The key to get a value for. + + Returns: + The value for the given key. + + Raises: + KeyError: If the key is not included. + DuplicateLookupError: If the key was included multiple times. + """ + if key in self._duplicate_keys: + raise DuplicateLookupError( + 'Duplicate of {} found in manifest.'.format(key)) + + if key in self._lookup_dict: + return self._lookup_dict[key] + + if key.endswith('/') and key[:-1] in self._lookup_dict: + return self._lookup_dict[key[:-1]] + + # For legacy reasons, some project names in the manifest include a '.git' + # suffix. Gerrit strips off this suffix, though, so if we haven't found the + # key yet, try searching with a .git suffix. + key_git = key + '.git' + if key_git in self._lookup_dict: + return self._lookup_dict[key_git] + + raise KeyError('{} was not found in the project path lookup {}.'.format( + key, self._lookup_dict)) + + def get_dict(self): + """Gets the dictionary representing the lookup table. + + Returns: + The underlying dict storage of this object. + """ + return self._lookup_dict + + +def get_project_path_lookup(executor, manifest_url, manifest=None, **kwargs): + """Returns a project path lookup table. + + Using manifest apgument as a manifest content by default, if None + `repo manifest` will be invoked. + + Note that if duplicate projects are included in the manifest only 1 will be + included in the lookup. This will be the latter of the duplicates listed via + the `repo manifest` command. + + Args: + executor: Executes the subprocess. + manifest_url: The url where the repo manifest project is hosted. + manifest: Content of manifest file already loaded by build. + **kwargs: Any additional kwargs to pass to the executor. + + Returns: + A ProjectLookupTable representing the relative path for the given project. + """ + if not manifest: + manifest = get_manifest(executor, **kwargs) + return parse_manifest_for_path(manifest, manifest_url) + + +@contextmanager +def normalize_manifest_if_exists(manifest_path): + """Normalizes the manifest for the duration of the context manager.""" + if manifest_path: + temp_manifest = tempfile.NamedTemporaryFile(delete='False').name + shutil.copy2(manifest_path, temp_manifest) + _normalize_manifest(manifest_path) + try: + yield + finally: + if manifest_path: + shutil.copy2(temp_manifest, manifest_path) + os.unlink(temp_manifest) + + +def _normalize_manifest(manifest_path): + """Convert manifest to a more user friendly version.""" + with open(manifest_path, 'r') as f: + manifest = ''.join([ + line.strip() for line in f.readlines()]) + root = et.fromstring(manifest) + for remote in root.findall('remote'): + if 'github.googlesource.com' in remote.get('fetch'): + remote.set('fetch', 'https://github.com') + remote.attrib.pop('review', None) + break + normalized_manifest = minidom.parseString( + et.tostring(root)).toprettyxml(encoding='UTF-8', indent=' ') + with open(manifest_path, 'wb') as f: + f.write(normalized_manifest) + + +def override_manifest_command(override_path=None): + """Returns command for overriding .repo/manifest.xml by override_path.""" + if override_path is None: + override_path = os.path.join(os.pardir, MANIFEST_OVERRIDE_XML) + + return ['ln', '-sf', override_path, 'manifest.xml'] + + +def override_manifest(executor, override_path=None): + """Overriding .repo/manifest.xml by override_path.""" + return executor.exec_subprocess( + override_manifest_command(override_path), cwd='.repo') + + +def get_project_remote_lookup(executor, manifest_url, manifest=None, **kwargs): + """Returns a project remote lookup table. + + Using manifest apgument as a manifest content by default, if None + `repo manifest` will be invoked. + + Note that if duplicate projects are included in the manifest only 1 will be + included in the lookup. This will be the latter of the duplicates listed via + the `repo manifest` command. + + Args: + executor: Executes the subprocess. + manifest_url: The url where the repo manifest project is hosted. + manifest: Content of manifest file already loaded by build. + **kwargs: Any additional kwargs to pass to the executor. + + Returns: + A ProjectLookupTable representing the remote for the given project. + """ + if not manifest: + manifest = get_manifest(executor, **kwargs) + return parse_manifest_for_remote(manifest, manifest_url) + + +def get_project_revision_lookup(executor, manifest_url, manifest_branch, + manifest=None, **kwargs): + """Returns a project revision lookup table. + + Using manifest apgument as a manifest content by default, if None + `repo manifest` will be invoked. + + Note that if duplicate projects are included in the manifest only 1 will be + included in the lookup. This will be the latter of the duplicates listed via + the `repo manifest` command. + + Args: + executor: Executes the subprocess. + manifest_url: The url where the repo manifest project is hosted. + manifest_branch: The repo manifest branch of the current checkout. + manifest: Content of manifest file already loaded by build. + **kwargs: Any additional kwargs to pass to the executor. + + Returns: + A ProjectLookupTable representing the revision for the given project. + """ + if not manifest: + manifest = get_manifest(executor, **kwargs) + return parse_manifest_for_revision(manifest, manifest_url, manifest_branch) + + +def get_manifest(executor, retries=5, **kwargs): + """Returns the manifest file in a string form. + + Args: + executor: Executes the subprocess. + retries: number of retries to load manifest. + **kwargs: Any additional kwargs to pass to the executor. + + Raises: + ManifestParseError: if all retries fail. + Returns: + A string representing the manifest file. + """ + failures = 0 + while retries > failures: + manifest = executor.exec_subprocess( + ['repo', 'manifest'], + check_output=True, + **kwargs) + try: + lines = ''.join([line.strip() for line in manifest.splitlines()]) + _ = et.fromstring(lines) + return lines + except et.ParseError as error: + failures += 1 + logging.warning(('Failed to parse manifest file. Attempt %d/%d. ' + 'Error was: %s\nManifest file content was:\n%s'), + failures, retries, error, manifest) + + raise ManifestParseError( + 'Failed to parse manifest after %s retries' % failures) + + +def is_manifest_project(project): + """Checks if the project is a Manifest project. + + Args: + project: The name of the Gerrit project in which the files live. + + Returns: + True if it is a Manifest, False if not. + """ + return project in list(REPO_MANIFEST_URL_TO_PROJECT_NAME.values()) + + +def parse_manifest_for_path(manifest, manifest_url): + """Parses a repo manifest file for project paths. + + Args: + manifest: A string representing a manifest file. + manifest_url: The url where the repo manifest project is hosted. + + Returns: + A ProjectLookupTable representing the manifest for the given project. + """ + assert isinstance(manifest, six.string_types) + result = ProjectLookupTable() + + # Add an entry to this map representing the repo manifest project. + manifest_project_name = get_manifest_url_mapping( + REPO_MANIFEST_URL_TO_PROJECT_NAME, manifest_url) + if manifest_project_name: + result[manifest_project_name] = REPO_MANIFEST_PROJECT_PATH + + if not manifest: + return result + manifest = ''.join([line.strip() for line in manifest.splitlines()]) + root = et.fromstring(manifest) + for project in root.findall('project'): + name = project.get('name') + path = project.get('path') + if not path: + path = name + result[name] = path + return result + + +def parse_manifest_for_remote(manifest, manifest_url): + """Parses a repo manifest file for project remotes. + + Args: + manifest: A string representing a manifest file. + manifest_url: The url where the repo manifest project is hosted. + + Returns: + A ProjectLookupTable representing the manifest for the given project. + """ + assert isinstance(manifest, six.string_types) + result = ProjectLookupTable() + + # Add an entry to this map representing the repo manifest project. + manifest_project_name = get_manifest_url_mapping( + REPO_MANIFEST_URL_TO_PROJECT_NAME, manifest_url) + if manifest_project_name: + result[manifest_project_name] = REPO_MANIFEST_PROJECT_REMOTE + + if not manifest: + return result + manifest = ''.join([line.strip() for line in manifest.splitlines()]) + root = et.fromstring(manifest) + default_remote = DEFAULT_REMOTE + n = root.find('default') + if n is not None and n.get('remote') is not None: + default_remote = n.get('remote') + for project in root.findall('project'): + name = project.get('name') + remote = project.get('remote') + if not remote: + remote = default_remote + result[name] = remote + return result + + +def parse_manifest_for_revision(manifest, manifest_url, manifest_branch): + """Parses a repo manifest file for project revisions. + + Args: + manifest: A string representing a manifest file. + manifest_url: The url where the repo manifest project is hosted. + manifest_branch: The repo manifest branch of the current checkout. + + Returns: + A ProjectLookupTable representing the manifest for the given project. + """ + assert isinstance(manifest, six.string_types) + result = ProjectLookupTable() + + manifest_project_name = get_manifest_url_mapping( + REPO_MANIFEST_URL_TO_PROJECT_NAME, manifest_url) + if manifest_project_name: + result[manifest_project_name] = manifest_branch + + if not manifest: + return result + manifest = ''.join([line.strip() for line in manifest.splitlines()]) + root = et.fromstring(manifest) + + # Get the default revision frome the manifest. + default_revision = '' + for default_tag in root.findall('default'): + default_revision = default_tag.get('revision', '') + + # Create the lookup. If an entry does not explicitly reference a revision, + # assign the default revision. + for project in root.findall('project'): + name = project.get('name') + revision = project.get('revision') + if not revision: + revision = default_revision + result[name] = revision + return result + + +def requires_repo_sync(project, filenames): + """Given a list of touched files, determines if a repo sync is needed. + + If a change is applied to a repo manifest file (for example, to update the + revision of a project), we may need to run 'repo sync' again before building, + to ensure the project is checked out at the SHA we are trying to test. Return + true if this is the case. + + Args: + project: The name of the Gerrit project in which the files live. + filenames: A list of files that were modified in project. + Returns: + True if we should run 'repo sync' again before building. + + """ + + # Projects that are not manifest projects can be ignored. + if not is_manifest_project(project): + return False + + # If any file has been touched, we need to repo sync. + return bool(filenames) + + +def get_manifest_url_mapping(mapping, manifest_url): + """Get value from manifest_url mapping regardless of GoB domain name.""" + return mapping.get(manifest_url.replace( + '.git.corp.google.com', '.googlesource.com')) + + +def use_eureka_manifest(manifest_url): + """Returns True if this manifest points to eureka/manifest.""" + project_name = get_manifest_url_mapping( + REPO_MANIFEST_URL_TO_PROJECT_NAME, manifest_url) + return project_name and project_name == EUREKA_MANIFEST_PROJECT_NAME + + +def manifest_alias(manifest_url): + """Returns manifest alias.""" + return get_manifest_url_mapping(REPO_MANIFEST_URL_TO_REPO_ALIAS, manifest_url)
diff --git a/cq/scripts/helpers/repo_utils_test.py b/cq/scripts/helpers/repo_utils_test.py new file mode 100644 index 0000000..1eec759 --- /dev/null +++ b/cq/scripts/helpers/repo_utils_test.py
@@ -0,0 +1,360 @@ +"""Tests for repo_utils.""" + +from __future__ import absolute_import +import os +import sys +import tempfile +import unittest + +# Allow imports from cq/scripts folder +sys.path.insert( + 0, + os.path.realpath(os.path.join(os.path.dirname(__file__), os.pardir))) +from helpers import repo_utils + +SAMPLE_MANIFEST_STRING = """ +<?xml version="1.0" encoding="UTF-8"?> +<manifest> + <remote fetch="https://chromium.googlesource.com/" name="chromium" review="https://chromium-review.googlesource.com/"/> + <remote fetch="https://eureka-internal.googlesource.com/" name="eureka" review="sso://eureka-internal"/> + + <default revision="master"/> + + <project name="chromium/src" remote="eureka" revision="unfork_m43"/> + <project name="chromiumos/chromite" path="chromite/chromite" remote="chromium"/> + <project name="chromiumos/third_party/autotest" path="autotest" remote="chromium"/> + <project name="continuous-tests" remote="eureka"/> + <project name="fragglerock" remote="eureka"/> + <project name="prebuilt/toolchain" path="toolchain" remote="eureka"/> + <project name="test" remote="eureka"/> + <project name="legacyname.git" path="path/to/legacy" remote="eureka"/> +</manifest> +""" + +SAMPLE_MANIFEST_STRING_WITH_DUPLICATE_NAMES = """ +<?xml version="1.0" encoding="UTF-8"?> +<manifest> + <remote fetch="https://chromium.googlesource.com/" name="chromium" review="https://chromium-review.googlesource.com/"/> + <remote fetch="https://eureka-internal.googlesource.com/" name="eureka" review="sso://eureka-internal"/> + + <default revision="master"/> + + <project name="chromium/src" remote="eureka" revision="unfork_m43"/> + <project name="chromiumos/chromite" path="chromite/chromite" remote="chromium"/> + <project name="chromiumos/third_party/autotest" path="autotest" remote="chromium"/> + <project name="continuous-tests" remote="eureka"/> + <project name="fragglerock" remote="eureka"/> + <project name="prebuilt/toolchain" path="toolchain" remote="eureka"/> + <project name="test" path="test1" remote="eureka"/> + <project name="test" path="test2" remote="eureka"/> +</manifest> +""" + +SAMPLE_MANIFEST_INCOMPLETE_STRING = """ +<?xml version="1.0" encoding="UTF-8"?> +<manifest> + <remote fetch="https://chromium.googlesource.com/" name="chromium" review="https://chromium-review.googlesource.com/"/> + <remote fetch="https://eureka-internal.googlesource.com/" name="eureka" review="sso://eureka-internal"/> + + <default revision="master"/> + + <project name="chromium/src" remote="eureka" revision="unfork_m43"/> + <project name="chromiumos/chromite" path="chromite/chromite" remote="chromium"/> + <project name="chromiumos/third_party/autotest" path="autotest" remote="chromium"/> + <project name="continuous-tests" remote="eureka"/> + <project name="fragglerock" remote="eureka"/> + <project name="prebuilt/toolchain" path="toolchain" remote="eureka"/> +""" + +SAMPLE_MANIFEST_WITH_DEFAULT_REMOTE = """ +<manifest> + <remote fetch="https://nest-internal.googlesource.com" name="cq-manifest" review="https://nest-internal-review.googlesource.com/"/> + <default remote="cq-manifest" revision="master"/> + <project name="nep/nest-harness-tests" path="nep/nest-harness-tests" /> +</manifest> +""" + +SAMPLE_MANIFEST_WITH_INTERNAL_GITHUB = """<manifest> + <remote fetch="https://eureka-internal.googlesource.com/" name="eureka" review="sso://eureka-internal"/> + <remote fetch="https://github.googlesource.com" name="github" review="https://github-review.googlesource.com/"/> + <remote fetch="https://chromium.googlesource.com/" name="chromium" review="https://chromium-review.googlesource.com/"/> + <default revision="master"/> + <project name="chromium/src" remote="eureka" revision="unfork_m43"/> + <project name="test-project1" remote="github"/> + <project name="chromiumos/chromite" path="chromite/chromite" remote="chromium"/> +</manifest> +""" + +SAMPLE_MANIFEST_WITH_EXTERNAL_GITHUB = """<?xml version="1.0" encoding="UTF-8"?> +<manifest> + <remote fetch="https://eureka-internal.googlesource.com/" name="eureka" review="sso://eureka-internal"/> + <remote fetch="https://github.com" name="github"/> + <remote fetch="https://chromium.googlesource.com/" name="chromium" review="https://chromium-review.googlesource.com/"/> + <default revision="master"/> + <project name="chromium/src" remote="eureka" revision="unfork_m43"/> + <project name="test-project1" remote="github"/> + <project name="chromiumos/chromite" path="chromite/chromite" remote="chromium"/> +</manifest> +""" + +TEST_MANIFEST_URL = 'https://foo.bar.googlesource.com/bat/baz' + + +class RepoUtilsTest(unittest.TestCase): + """Tests for the repo utils module.""" + + def testParseEmptyManifest(self): + """Tests parsing an empty manifest file.""" + manifest = '' + expected_lookup = { + 'eureka/manifest': '.repo/manifests', + } + project_lookup = repo_utils.parse_manifest_for_path( + manifest, repo_utils.EUREKA_MANIFEST_URL) + lookup = project_lookup._lookup_dict + self.assertEqual(expected_lookup, lookup) + + def testParseManifest(self): + """Tests parsing a manifest file for paths.""" + expected_lookup = { + 'chromium/src': 'chromium/src', + 'chromiumos/chromite': 'chromite/chromite', + 'chromiumos/third_party/autotest': 'autotest', + 'continuous-tests': 'continuous-tests', + 'eureka/manifest': '.repo/manifests', + 'fragglerock': 'fragglerock', + 'legacyname.git': 'path/to/legacy', + 'prebuilt/toolchain': 'toolchain', + 'test': 'test' + } + project_lookup = repo_utils.parse_manifest_for_path( + SAMPLE_MANIFEST_STRING, + repo_utils.EUREKA_MANIFEST_URL) + lookup = project_lookup._lookup_dict + self.assertEqual(expected_lookup, lookup) + + def testParseManifestForNonEurekaManifest(self): + """Tests parsing a non-eureka manifest for path.""" + expected_lookup = { + 'bat/baz': '.repo/manifests', + 'chromium/src': 'chromium/src', + 'chromiumos/chromite': 'chromite/chromite', + 'chromiumos/third_party/autotest': 'autotest', + 'continuous-tests': 'continuous-tests', + 'fragglerock': 'fragglerock', + 'legacyname.git': 'path/to/legacy', + 'prebuilt/toolchain': 'toolchain', + 'test': 'test' + } + original_map = repo_utils.REPO_MANIFEST_URL_TO_PROJECT_NAME + repo_utils.REPO_MANIFEST_URL_TO_PROJECT_NAME = {TEST_MANIFEST_URL: + 'bat/baz'} + project_lookup = repo_utils.parse_manifest_for_path( + SAMPLE_MANIFEST_STRING, TEST_MANIFEST_URL) + lookup = project_lookup._lookup_dict + self.assertEqual(expected_lookup, lookup) + repo_utils.REPO_MANIFEST_URL_TO_PROJECT_NAME = original_map + + def testParseManifestRemotes(self): + """Tests parsing a manifest file for remotes.""" + expected_lookup = { + 'chromium/src': 'eureka', + 'chromiumos/chromite': 'chromium', + 'chromiumos/third_party/autotest': 'chromium', + 'continuous-tests': 'eureka', + 'eureka/manifest': 'origin', + 'fragglerock': 'eureka', + 'legacyname.git': 'eureka', + 'prebuilt/toolchain': 'eureka', + 'test': 'eureka' + } + project_lookup = repo_utils.parse_manifest_for_remote( + SAMPLE_MANIFEST_STRING, + repo_utils.EUREKA_MANIFEST_URL) + lookup = project_lookup._lookup_dict + self.assertEqual(expected_lookup, lookup) + + def testParseManifestRemotesForNonEurekaManifest(self): + """Tests parsing a non-eureka manifest for remotes.""" + expected_lookup = { + 'bat/baz': 'origin', + 'chromium/src': 'eureka', + 'chromiumos/chromite': 'chromium', + 'chromiumos/third_party/autotest': 'chromium', + 'continuous-tests': 'eureka', + 'fragglerock': 'eureka', + 'legacyname.git': 'eureka', + 'prebuilt/toolchain': 'eureka', + 'test': 'eureka' + } + original_map = repo_utils.REPO_MANIFEST_URL_TO_PROJECT_NAME + repo_utils.REPO_MANIFEST_URL_TO_PROJECT_NAME = {TEST_MANIFEST_URL: + 'bat/baz'} + project_lookup = repo_utils.parse_manifest_for_remote( + SAMPLE_MANIFEST_STRING, TEST_MANIFEST_URL) + lookup = project_lookup._lookup_dict + self.assertEqual(expected_lookup, lookup) + repo_utils.REPO_MANIFEST_URL_TO_PROJECT_NAME = original_map + + def testParseManifestRemotesForNonEurekaDefaultRemote(self): + expected_lookup = { + 'nep/nest-harness-tests': 'cq-manifest' + } + project_lookup = repo_utils.parse_manifest_for_remote( + SAMPLE_MANIFEST_WITH_DEFAULT_REMOTE, TEST_MANIFEST_URL) + lookup = project_lookup._lookup_dict + self.assertEqual(expected_lookup, lookup) + + def testParseManifestRevisions(self): + """Tests parsing a manifest file for revisions.""" + expected_lookup = { + 'chromium/src': 'unfork_m43', + 'chromiumos/chromite': 'master', + 'chromiumos/third_party/autotest': 'master', + 'continuous-tests': 'master', + 'eureka/manifest': 'unfork_m51', + 'fragglerock': 'master', + 'legacyname.git': 'master', + 'prebuilt/toolchain': 'master', + 'test': 'master' + } + project_lookup = repo_utils.parse_manifest_for_revision( + SAMPLE_MANIFEST_STRING, + repo_utils.EUREKA_MANIFEST_URL, + 'unfork_m51') + lookup = project_lookup._lookup_dict + self.assertEqual(expected_lookup, lookup) + + def testParseManifestWithDups(self): + """Tests parsing a manifest file with duplicates.""" + expected_lookup = { + 'chromium/src': 'chromium/src', + 'chromiumos/chromite': 'chromite/chromite', + 'chromiumos/third_party/autotest': 'autotest', + 'continuous-tests': 'continuous-tests', + 'eureka/manifest': '.repo/manifests', + 'fragglerock': 'fragglerock', + 'prebuilt/toolchain': 'toolchain', + 'test': 'test2' + } + expected_duplicates = ['test'] + project_lookup = repo_utils.parse_manifest_for_path( + SAMPLE_MANIFEST_STRING_WITH_DUPLICATE_NAMES, + repo_utils.EUREKA_MANIFEST_URL) + lookup = project_lookup._lookup_dict + duplicates = project_lookup._duplicate_keys + self.assertEqual(expected_lookup, lookup) + self.assertEqual(expected_duplicates, duplicates) + + def testLookupDuplicateRepoRaisesError(self): + """Tests a lookup on a duplicate repo raises an error.""" + + class MockExecutor(object): + + # pylint: disable=invalid-name,no-method-argument + def exec_subprocess(*args, **kwargs): + del kwargs + return SAMPLE_MANIFEST_STRING_WITH_DUPLICATE_NAMES + + lookup = repo_utils.get_project_path_lookup( + MockExecutor(), repo_utils.EUREKA_MANIFEST_URL) + + self.assertEqual('continuous-tests', lookup.get('continuous-tests')) + with self.assertRaises(KeyError): + lookup.get('foobar') + with self.assertRaises(repo_utils.DuplicateLookupError): + lookup.get('test') + self.assertEqual('continuous-tests', lookup['continuous-tests']) + with self.assertRaises(KeyError): + lookup['foobar'] # pylint: disable=pointless-statement + with self.assertRaises(repo_utils.DuplicateLookupError): + lookup['test'] # pylint: disable=pointless-statement + + def testManifestParseError(self): + """Tests parsing an incorrect manifest file.""" + + class MockExecutor(object): + + # pylint: disable=invalid-name,no-method-argument + def exec_subprocess(*args, **kwargs): + del kwargs + return SAMPLE_MANIFEST_INCOMPLETE_STRING + + with self.assertRaises(repo_utils.ManifestParseError): + _ = repo_utils.get_manifest(MockExecutor()) + + def testEmptyChangeDoesNotRequireRepoSync(self): + """Tests that an empty commit does not require a sync.""" + project = 'eureka/manifest' + + files = [] + self.assertFalse(repo_utils.requires_repo_sync(project, files)) + + def testSyncNotRequiredForOtherProjects(self): + """Tests that a sync is not required for other projects.""" + project = 'third_party/foobar' + + files = ['default.xml'] + self.assertFalse(repo_utils.requires_repo_sync(project, files)) + + def testChangeToAnyManifestFileRequiresRepoSync(self): + """Tests that a change to any manifest requires a sync.""" + project = 'eureka/manifest' + + files = ['default.xml'] + self.assertTrue(repo_utils.requires_repo_sync(project, files)) + + files = ['foobar.xml'] + self.assertTrue(repo_utils.requires_repo_sync(project, files)) + + def testProjectLookupWithTrailingSlash(self): + """Tests searching by project with a trailing slash.""" + expected_lookup = { + 'chromium/src': 'chromium/src', + 'chromiumos/chromite': 'chromite/chromite', + 'chromiumos/third_party/autotest': 'autotest', + 'continuous-tests': 'continuous-tests', + 'eureka/manifest': '.repo/manifests', + 'fragglerock': 'fragglerock', + 'prebuilt/toolchain': 'toolchain', + 'test': 'test' + } + project_lookup = repo_utils.parse_manifest_for_path( + SAMPLE_MANIFEST_STRING, + repo_utils.EUREKA_MANIFEST_URL) + for key, expected_value in expected_lookup.items(): + self.assertEqual(expected_value, project_lookup.get(key)) + self.assertEqual(expected_value, project_lookup.get(key + '/')) + + def testProjectLookupWithGitSuffix(self): + """Tests finding a project name that has a .git suffix.""" + key_without_git_suffix = 'legacyname' + key_with_git_suffix = 'legacyname.git' + expected_path = 'path/to/legacy' + project_lookup = repo_utils.parse_manifest_for_path( + SAMPLE_MANIFEST_STRING, + repo_utils.EUREKA_MANIFEST_URL) + + actual_path = project_lookup.get(key_without_git_suffix) + self.assertEqual(expected_path, actual_path) + + actual_path = project_lookup.get(key_with_git_suffix) + self.assertEqual(expected_path, actual_path) + + def testNormalizeManifestSwapsOutInternalGithub(self): + """Tests github.com is temporarily used for the remote fetch.""" + with tempfile.NamedTemporaryFile(mode='w', delete=False) as f: + f.write(SAMPLE_MANIFEST_WITH_INTERNAL_GITHUB) + temp_manifest = f.name + with repo_utils.normalize_manifest_if_exists(temp_manifest): + with open(temp_manifest, 'r') as f: + manifest_content = f.read() + self.assertEqual(manifest_content, SAMPLE_MANIFEST_WITH_EXTERNAL_GITHUB) + with open(temp_manifest, 'r') as f: + manifest_content = f.read() + self.assertEqual(manifest_content, SAMPLE_MANIFEST_WITH_INTERNAL_GITHUB) + os.unlink(temp_manifest) + + +if __name__ == '__main__': + unittest.main()
diff --git a/cq/scripts/helpers/retry_utils.py b/cq/scripts/helpers/retry_utils.py new file mode 100644 index 0000000..7eb2747 --- /dev/null +++ b/cq/scripts/helpers/retry_utils.py
@@ -0,0 +1,29 @@ +import logging +import random + +def disable_retry_wait_for_test(): + """Disables retry waiting. Use only with tests.""" + disable_retry_wait_for_test.on = True +disable_retry_wait_for_test.on = False + +def retry_delay(attempt, min_delay=5, base=30): + """Get seconds to delay before attempting a retry. + + Uses exponential backoff to determine the delay time. Setting min_delay + to 5s since lsremote and bandwidth refills every 5s. + + Args: + attempt: current attempt number. + min_delay: left boundary of delay time to randomly choose from. + base: delay duration we are doubling on each attempt. + + Returns: + The number of seconds to wait before retrying. + """ + assert min_delay <= base + exponential_delay = base * 2**attempt + logging.info('Picking a random delay between ' + '%s and %s seconds', min_delay, exponential_delay) + if disable_retry_wait_for_test.on: + return 0 + return random.randint(min_delay, exponential_delay)
diff --git a/cq/scripts/helpers/sanitizer_utils.py b/cq/scripts/helpers/sanitizer_utils.py new file mode 100644 index 0000000..e1a5745 --- /dev/null +++ b/cq/scripts/helpers/sanitizer_utils.py
@@ -0,0 +1,199 @@ +"""Utils for working with the Clang sanitizers (asan, msan, tsan, ubsan).""" + +_SANITIZER_STRING = { + 'asan': 'AddressSanitizer', + 'lsan': 'LeakSanitizer', + 'msan': 'MemorySanitizer', + 'tsan': 'ThreadSanitizer', + 'ubsan': 'runtime error:' +} + +_MAX_ERRORS = 1 +_TOO_MANY_ERRORS_MSG = '<Too many errors to print. Check logs for more.>' +_MAX_LINES_PER_ERROR = 30 +_ERROR_SNIPPED_MSG = '<...snip (error too long; removed {} lines)...>\n' + + +def get_sanitizer_to_comments_for(sanitizer): + """Returns a function that converts |sanitizer| output to review comments.""" + if sanitizer == 'asan': + return lambda returncode, stdout, stderr: _asan_to_comments(stdout) + if sanitizer == 'msan': + return lambda returncode, stdout, stderr: _msan_to_comments(stdout) + if sanitizer == 'tsan': + return lambda returncode, stdout, stderr: _tsan_to_comments(stdout) + if sanitizer == 'ubsan': + return lambda returncode, stdout, stderr: _ubsan_to_comments(stdout) + raise ValueError('Unknown sanitizer: [{}]'.format(sanitizer)) + + +def get_validator_for(sanitizer): + """Returns a function that validates output for |sanitizer|. + + The returned validator takes: returncode, stdout, stderr and returns + True if the output should be considered a success of False if the output + indicates an error of some kind occured. + + Args: + sanitizer: 'asan', 'msan', 'tsan', or 'ubsan' + + Returns: + Validator function. + + Raises: + ValueError: for unknown |sanitizer|. + """ + if sanitizer == 'asan': + return _asan_lsan_validator + if sanitizer == 'msan': + return _msan_validator + if sanitizer == 'tsan': + return _tsan_validator + if sanitizer == 'ubsan': + return _ubsan_validator + raise ValueError('Unknown sanitizer: [{}]'.format(sanitizer)) + + +def _asan_lsan_validator(returncode, stdout, stderr): + del stderr # unused + asan_error_msg = 'ERROR: {}'.format(_SANITIZER_STRING['asan']) + lsan_error_msg = 'ERROR: {}'.format(_SANITIZER_STRING['lsan']) + asan_summary_msg = 'SUMMARY: {}'.format(_SANITIZER_STRING['asan']) + error_indicator = ((asan_error_msg in stdout or lsan_error_msg in stdout) and + (asan_summary_msg in stdout)) + return returncode == 0 or not error_indicator + + +def _msan_validator(returncode, stdout, stderr): + del stderr # unused + warning_msg = 'WARNING: {}'.format(_SANITIZER_STRING['msan']) + summary_msg = 'SUMMARY: {}'.format(_SANITIZER_STRING['msan']) + error_indicator = (warning_msg in stdout) and (summary_msg in stdout) + return returncode == 0 or not error_indicator + + +def _tsan_validator(returncode, stdout, stderr): + del stderr # unused + warning_msg = 'WARNING: {}'.format(_SANITIZER_STRING['tsan']) + summary_msg = 'SUMMARY: {}'.format(_SANITIZER_STRING['tsan']) + error_indicator = (warning_msg in stdout) and (summary_msg in stdout) + return returncode == 0 or not error_indicator + + +def _ubsan_validator(returncode, stdout, stderr): + del stderr # unused + return returncode == 0 or _SANITIZER_STRING['ubsan'] not in stdout + + +def _asan_to_comments(sanitizer_output, lsan=True): + """Convert the output from ASAN into comments for Gerrit. + + Args: + sanitizer_output: Output from running a binary with ASAN enabled. + lsan: Set True if asan/lsan were run together, to get comments from both. + (Default is True) + + Returns: + A review dict suitable for passing to base_step.add_review + """ + sanitizer_strings = [_SANITIZER_STRING['asan']] + if lsan: + sanitizer_strings.append(_SANITIZER_STRING['lsan']) + + return _sanitizer_to_comments(sanitizer_strings, sanitizer_output) + + +def _msan_to_comments(sanitizer_output): + return _sanitizer_to_comments([_SANITIZER_STRING['msan']], sanitizer_output) + + +def _tsan_to_comments(sanitizer_output): + return _sanitizer_to_comments([_SANITIZER_STRING['tsan']], sanitizer_output) + + +def _ubsan_to_comments(sanitizer_output): + """Convert output from UBSAN into comments for Gerrit. + + UBSAN output is much different than other sanitizers, so it needs to + be handled specially. + + Args: + sanitizer_output: Output from running a binary with ubsan enabled. + + Returns: + A review dict suitable for passing to base_step.add_review + """ + all_errors = [] + for line in sanitizer_output.splitlines(True): + if _SANITIZER_STRING['ubsan'] in line: + all_errors.append(line) + if len(all_errors) > _MAX_ERRORS: + break + + if len(all_errors) > _MAX_ERRORS: + all_errors = all_errors[:_MAX_ERRORS] + all_errors.append('<Too many errors to print. Check logs for more.>') + + if all_errors: + return {'review': {'message': '\n\n'.join(all_errors)}} + return {} + + +def _sanitizer_to_comments(sanitizer_strings, sanitizer_output): + """Converts output from ASAN/LSAN/MSAN/TSAN into comments for Gerrit. + + Aside from UBSAN, all the sanitizers generate output that is in roughly + the same format, so they can all get parsed/scraped the same way. + + Args: + sanitizer_strings: List of the identifying strings to search for in the logs + (e.g. AddressSanitizer, LeakSanitizer, MemorySanitizer, ThreadSanitizer) + sanitizer_output: Output from running a binary with a sanitizer enabled. + + Returns: + A review dict suitable for passing to base_step.add_review + """ + all_errors = [] + current_error = [] + for line in sanitizer_output.splitlines(True): + if _is_start_of_error(line, sanitizer_strings): + current_error = [line] + elif current_error and _is_end_of_error(line, sanitizer_strings): + current_error.append(line) + all_errors.append(''.join(_shorten_error_if_necessary(current_error))) + current_error = [] + if len(all_errors) > _MAX_ERRORS: + break + elif current_error: + current_error.append(line) + + if len(all_errors) > _MAX_ERRORS: + all_errors = all_errors[:_MAX_ERRORS] + all_errors.append(_TOO_MANY_ERRORS_MSG) + + if all_errors: + return {'review': {'message': '\n\n'.join(all_errors)}} + return {} + + +def _is_start_of_error(line, sanitizer_strings): + warning_patterns = ['WARNING: {}'.format(s) for s in sanitizer_strings] + error_patterns = ['ERROR: {}'.format(s) for s in sanitizer_strings] + begin_error_patterns = warning_patterns + error_patterns + return any(begin_error in line for begin_error in begin_error_patterns) + + +def _is_end_of_error(line, sanitizer_strings): + end_error_patterns = ['SUMMARY: {}'.format(s) for s in sanitizer_strings] + return any(end_error in line for end_error in end_error_patterns) + + +def _shorten_error_if_necessary(error): + if len(error) <= _MAX_LINES_PER_ERROR: + return error + + start_of_error = error[:int(_MAX_LINES_PER_ERROR / 2)] + end_of_error = error[int(-1 * _MAX_LINES_PER_ERROR / 2):] + num_snipped_lines = len(error) - _MAX_LINES_PER_ERROR + snipped_msg = [_ERROR_SNIPPED_MSG.format(num_snipped_lines)] + return start_of_error + snipped_msg + end_of_error
diff --git a/cq/scripts/helpers/sanitizer_utils_test.py b/cq/scripts/helpers/sanitizer_utils_test.py new file mode 100644 index 0000000..7813e8b --- /dev/null +++ b/cq/scripts/helpers/sanitizer_utils_test.py
@@ -0,0 +1,115 @@ +"""Tests for sanitizer_utils.""" + +from __future__ import absolute_import +import os +import sys +import unittest + +# Allow imports from cq/scripts folder +sys.path.insert( + 0, os.path.realpath(os.path.join(os.path.dirname(__file__), os.pardir))) +from helpers import sanitizer_utils +from helpers import sanitizer_utils_test_data as test_data + + +class SanitizerUtilsTest(unittest.TestCase): + + def testAsanToComments(self): + """Tests converting ASAN errors to Gerrit comments.""" + comment_generator = sanitizer_utils.get_sanitizer_to_comments_for('asan') + actual_review = comment_generator(0, test_data.ASAN_ERROR_MESSAGE, '') + expected_review = {'review': {'message': test_data.ASAN_COMMENT}} + self.assertDictEqual(expected_review, actual_review) + + def testAsanLsanToComments(self): + """Tests converting ASAN/LSAN combined errors to Gerrit comments.""" + comment_generator = sanitizer_utils.get_sanitizer_to_comments_for('asan') + actual_review = comment_generator(0, test_data.ASAN_LSAN_ERROR_MESSAGE, '') + expected_review = {'review': {'message': test_data.ASAN_LSAN_COMMENT}} + self.assertDictEqual(expected_review, actual_review) + + def testAsanValidator(self): + """Tests that ASAN errors are correctly detected from ASAN output.""" + validator = sanitizer_utils.get_validator_for('asan') + self.assertTrue(validator(0, '', '')) + self.assertTrue(validator(0, 'Some stdout stuff', 'Some stderr')) + self.assertFalse(validator(1, test_data.ASAN_ERROR_MESSAGE, '')) + + def testAsanLsanValidator(self): + """Tests that LSAN errors are correctly detected from ASAN/LSAN output.""" + validator = sanitizer_utils.get_validator_for('asan') + self.assertFalse(validator(1, test_data.ASAN_LSAN_ERROR_MESSAGE, '')) + + def testMsanToComments(self): + """Tests converting MSAN errors to Gerrit comments.""" + comment_generator = sanitizer_utils.get_sanitizer_to_comments_for('msan') + actual_review = comment_generator(0, test_data.MSAN_ERROR_MESSAGE, '') + expected_review = {'review': {'message': test_data.MSAN_COMMENT}} + self.assertDictEqual(expected_review, actual_review) + + def testMsanValidator(self): + """Tests that MSAN errors are correctly detected from MSAN output.""" + validator = sanitizer_utils.get_validator_for('msan') + self.assertTrue(validator(0, '', '')) + self.assertTrue(validator(0, 'Some stdout stuff', 'Some stderr')) + self.assertFalse(validator(1, test_data.MSAN_ERROR_MESSAGE, '')) + + def testTsanToComments(self): + """Tests converting TSAN errors to Gerrit comments.""" + comment_generator = sanitizer_utils.get_sanitizer_to_comments_for('tsan') + actual_review = comment_generator(0, test_data.TSAN_ERROR_MESSAGE, '') + expected_review = {'review': {'message': test_data.TSAN_COMMENT}} + self.maxDiff = None + self.assertDictEqual(expected_review, actual_review) + + def testTsanValidator(self): + """Tests that TSAN errors are correctly detected from TSAN output.""" + validator = sanitizer_utils.get_validator_for('tsan') + self.assertTrue(validator(0, '', '')) + self.assertTrue(validator(0, 'Some stdout stuff', 'Some stderr')) + self.assertFalse(validator(1, test_data.TSAN_ERROR_MESSAGE, '')) + + def testUbsanToComments(self): + """Tests converting UBSAN errors to Gerrit comments.""" + comment_generator = sanitizer_utils.get_sanitizer_to_comments_for('ubsan') + actual_review = comment_generator(0, test_data.UBSAN_ERROR_MESSAGE, '') + self.maxDiff = None + expected_review = { + 'review': { + 'message': + '\n\n'.join([ + test_data.UBSAN_COMMENT, + '<Too many errors to print. Check logs for more.>' + ]) + } + } + self.assertDictEqual(expected_review, actual_review) + + def testUbsanValidator(self): + """Tests that UBSAN errors are correctly detected from UBSAN output.""" + validator = sanitizer_utils.get_validator_for('ubsan') + self.assertTrue(validator(0, '', '')) + self.assertTrue(validator(0, 'Some stdout stuff', 'Some stderr')) + self.assertFalse(validator(1, test_data.UBSAN_ERROR_MESSAGE, '')) + + def testTruncateVeryLongErrorMessage(self): + """Tests that very long error messages get truncated.""" + very_long_comment_builder = ['WARNING: AddressSanitizer'] + very_long_comment_builder += ['line with error info'] * 1000 + very_long_comment_builder += ['SUMMARY: AddressSanitizer'] + very_long_comment = '\n'.join(very_long_comment_builder) + + comment_generator = sanitizer_utils.get_sanitizer_to_comments_for('asan') + actual_review = comment_generator(0, very_long_comment, '') + actual_review_message = actual_review['review']['message'] + + self.assertIn('<...snip (error too long; removed 972 lines)...>', + actual_review_message) + + expected_message_length = sanitizer_utils._MAX_LINES_PER_ERROR + 1 + actual_message_length = len(actual_review_message.splitlines()) + self.assertEqual(actual_message_length, expected_message_length) + + +if __name__ == '__main__': + unittest.main()
diff --git a/cq/scripts/helpers/sanitizer_utils_test_data.py b/cq/scripts/helpers/sanitizer_utils_test_data.py new file mode 100644 index 0000000..4971845 --- /dev/null +++ b/cq/scripts/helpers/sanitizer_utils_test_data.py
@@ -0,0 +1,230 @@ +"""Test data for sanitizer_utils_test. + +These are copy/pasted directly from the sanitizer logs from catabuilder. They +live in a separate file because they are large and would otherwise clutter +sanitizer_utils_test.py unnecessarily. +""" +# pylint: disable=line-too-long + +ASAN_ERROR_MESSAGE = ( + """GMOCK WARNING: +Uninteresting mock function call - returning directly. + Function call: UnregisterService(@0x618000000558 0x604000013f90, @0x7f9bbba11760 8-byte object <10-E2 01-00 40-60 00-00>) +NOTE: You can safely ignore the above warning unless this call should not happen. +GMOCK WARNING: +Uninteresting mock function call - returning directly. + Function call: RemoveExternalNamespaceHandler +================================================================= +==23973==ERROR: AddressSanitizer: alloc-dealloc-mismatch (operator new [] vs operator delete) on 0x619000009180 + #0 0x51a1fb in operator delete(void*) (out_clang_chromecast_gn_asan/Release/cast_multizone_unittests+0x51a1fb) + #1 0x5e2eca in operator() buildtools/third_party/libc++/trunk/include/memory:2529:13 + #2 0x5e2eca in reset buildtools/third_party/libc++/trunk/include/memory:2735 + #3 0x5e2eca in ~unique_ptr buildtools/third_party/libc++/trunk/include/memory:2703 + #4 0x5e2eca in ~SocketBuffer chromecast/internal/multizone/fake_multizone_device.cc:39 + #5 0x5e2eca in operator() buildtools/third_party/libc++/trunk/include/memory:2529 + +0x619000009180 is located 0 bytes inside of 1024-byte region [0x619000009180,0x619000009580) +allocated by thread T0 here: + #0 0x51973b in operator new[](unsigned long) (out_clang_chromecast_gn_asan/Release/cast_multizone_unittests+0x51973b) + #1 0x5a2173 in SocketBuffer chromecast/internal/multizone/fake_multizone_device.cc:34:15 + #2 0x5a2173 in chromecast::multizone::FakeMultizoneDevice::StreamSocketPair::StreamSocketPair() chromecast/internal/multizone/fake_multizone_device.cc:203 + #3 0x5a1cbd in chromecast::multizone::FakeMultizoneDevice::FakeMultizoneDevice + #4 0x64446f in chromecast::multizone::MultizoneManagerTest::AddFollower + + +SUMMARY: AddressSanitizer: alloc-dealloc-mismatch (out_clang_chromecast_gn_asan/Release/cast_multizone_unittests+0x51a1fb) in operator delete(void*) +==23973==HINT: if you don't care about these errors you may set ASAN_OPTIONS=alloc_dealloc_mismatch=0 +==23973==ABORTING +[73/206] MultizoneManagerTest.LaunchAndUnlaunchLeader (CRASHED) +[74/206] MultizoneMediaManagerTest.GetActiveState (2 ms)""") + +ASAN_COMMENT = ( + """==23973==ERROR: AddressSanitizer: alloc-dealloc-mismatch (operator new [] vs operator delete) on 0x619000009180 + #0 0x51a1fb in operator delete(void*) (out_clang_chromecast_gn_asan/Release/cast_multizone_unittests+0x51a1fb) + #1 0x5e2eca in operator() buildtools/third_party/libc++/trunk/include/memory:2529:13 + #2 0x5e2eca in reset buildtools/third_party/libc++/trunk/include/memory:2735 + #3 0x5e2eca in ~unique_ptr buildtools/third_party/libc++/trunk/include/memory:2703 + #4 0x5e2eca in ~SocketBuffer chromecast/internal/multizone/fake_multizone_device.cc:39 + #5 0x5e2eca in operator() buildtools/third_party/libc++/trunk/include/memory:2529 + +0x619000009180 is located 0 bytes inside of 1024-byte region [0x619000009180,0x619000009580) +allocated by thread T0 here: + #0 0x51973b in operator new[](unsigned long) (out_clang_chromecast_gn_asan/Release/cast_multizone_unittests+0x51973b) + #1 0x5a2173 in SocketBuffer chromecast/internal/multizone/fake_multizone_device.cc:34:15 + #2 0x5a2173 in chromecast::multizone::FakeMultizoneDevice::StreamSocketPair::StreamSocketPair() chromecast/internal/multizone/fake_multizone_device.cc:203 + #3 0x5a1cbd in chromecast::multizone::FakeMultizoneDevice::FakeMultizoneDevice + #4 0x64446f in chromecast::multizone::MultizoneManagerTest::AddFollower + + +SUMMARY: AddressSanitizer: alloc-dealloc-mismatch (out_clang_chromecast_gn_asan/Release/cast_multizone_unittests+0x51a1fb) in operator delete(void*) +""") + +ASAN_LSAN_ERROR_MESSAGE = ( + """[----------] Global test environment tear-down +[==========] 10 tests from 2 test cases ran. (24 ms total) +[ PASSED ] 10 tests. + +================================================================= +==23625==ERROR: LeakSanitizer: detected memory leaks + +Direct leak of 320 byte(s) in 2 object(s) allocated from: + #0 0x4f616b in operator new(unsigned long) (/usr/local/google/home/mosaic-role/slave/repo_clients/internal/chromium/src/out_clang_chromecast_gn_asan/Release/cast_crash_unittests+0x4f616b) + #1 0x54b2ab in chromecast::CastCrashdumpUploader::CastCrashdumpUploader(chromecast::CastCrashdumpData const&) chromecast/crash/cast_crashdump_uploader.cc:37:35 + #2 0x521291 in MockCastCrashdumpUploader chromecast/crash/linux/minidump_uploader_unittest.cc:54:9 + #3 0x521291 in StrictMock<chromecast::CastCrashdumpData> testing/gmock/include/gmock/gmock-generated-nice-strict.h:284 + + +SUMMARY: AddressSanitizer: 320 byte(s) leaked in 2 allocation(s). +[11/46] DumpInfoTest.TooFewFieldsIsNotValid (0 ms) +[ RUN ] DumpInfoTest.BadTimeStringIsNotValid +[23625:23625:1109/162235:610901543961:INFO:dump_info.cc(147)] Failed to convert dump time invalid +[ OK ] DumpInfoTest.BadTimeStringIsNotValid (1 ms) +[ RUN ] DumpInfoTest.AllRequiredFieldsIsValid +[ OK ] DumpInfoTest.AllRequiredFieldsIsValid (0 ms)""") + +ASAN_LSAN_COMMENT = ( + """==23625==ERROR: LeakSanitizer: detected memory leaks + +Direct leak of 320 byte(s) in 2 object(s) allocated from: + #0 0x4f616b in operator new(unsigned long) (/usr/local/google/home/mosaic-role/slave/repo_clients/internal/chromium/src/out_clang_chromecast_gn_asan/Release/cast_crash_unittests+0x4f616b) + #1 0x54b2ab in chromecast::CastCrashdumpUploader::CastCrashdumpUploader(chromecast::CastCrashdumpData const&) chromecast/crash/cast_crashdump_uploader.cc:37:35 + #2 0x521291 in MockCastCrashdumpUploader chromecast/crash/linux/minidump_uploader_unittest.cc:54:9 + #3 0x521291 in StrictMock<chromecast::CastCrashdumpData> testing/gmock/include/gmock/gmock-generated-nice-strict.h:284 + + +SUMMARY: AddressSanitizer: 320 byte(s) leaked in 2 allocation(s). +""") + +MSAN_ERROR_MESSAGE = ( + """[85/97] HotspotManagerTest.Start_Mutliple_Stop_Multiple_Mixed (7 ms) +[86/97] UmaHashUtilTest.HashBuildNumber64 (1 ms) +[87/97] UmaHashUtilTest.HashSdkVersion64 (0 ms) +[1109/162418:ERROR:kill_posix.cc(84)] Unable to terminate process group 9794: No such process +[ RUN ] UdpSocketWrapperTest.DeleteInCallback +Uninitialized bytes in __interceptor_sendto at offset 0 inside [0x7010000007c0, 1) +==9794==WARNING: MemorySanitizer: use-of-uninitialized-value + #0 0x928115 in net::UDPSocketPosix::InternalSendTo(net::IOBuffer*, int, net::IPEndPoint const*) net/udp/udp_socket_posix.cc:636:16 + #1 0x92742d in net::UDPSocketPosix::SendToOrWrite(net::IOBuffer*, int, net::IPEndPoint const*, base::Callback<void (int), (base::internal::CopyMode)1, (base::internal::RepeatMode)1> const&) net/udp/udp_socket_posix.cc:254:16 + #2 0x65a4d7 in chromecast::UdpSocketWrapper::SendTo(scoped_refptr<net::IOBuffer> const&, int, net::IPEndPoint const&) chromecast/internal/net/udp_socket_wrapper.cc:113:23 + + Uninitialized value was created by a heap allocation + #0 0x4a6662 in operator new[](unsigned long) (/usr/local/google/home/mosaic-role/slave/repo_clients/internal/chromium/src/out_clang_chromecast_gn_msan/Release/cast_net_internal_unittests+0x4a6662) + #1 0x8bcdc3 in net::IOBuffer::IOBuffer(int) net/base/io_buffer.cc:35:11 + #2 0x8bd468 in net::IOBufferWithSize::IOBufferWithSize(int) net/base/io_buffer.cc:53:7 + +SUMMARY: MemorySanitizer: use-of-uninitialized-value net/udp/udp_socket_posix.cc:636:16 in net::UDPSocketPosix::InternalSendTo(net::IOBuffer*, int, net::IPEndPoint const*) +Exiting +[88/97] UdpSocketWrapperTest.DeleteInCallback (CRASHED) +[89/97] UdpSocketWrapperTest.StartStopStart (3 ms)""") + +MSAN_COMMENT = ( + """==9794==WARNING: MemorySanitizer: use-of-uninitialized-value + #0 0x928115 in net::UDPSocketPosix::InternalSendTo(net::IOBuffer*, int, net::IPEndPoint const*) net/udp/udp_socket_posix.cc:636:16 + #1 0x92742d in net::UDPSocketPosix::SendToOrWrite(net::IOBuffer*, int, net::IPEndPoint const*, base::Callback<void (int), (base::internal::CopyMode)1, (base::internal::RepeatMode)1> const&) net/udp/udp_socket_posix.cc:254:16 + #2 0x65a4d7 in chromecast::UdpSocketWrapper::SendTo(scoped_refptr<net::IOBuffer> const&, int, net::IPEndPoint const&) chromecast/internal/net/udp_socket_wrapper.cc:113:23 + + Uninitialized value was created by a heap allocation + #0 0x4a6662 in operator new[](unsigned long) (/usr/local/google/home/mosaic-role/slave/repo_clients/internal/chromium/src/out_clang_chromecast_gn_msan/Release/cast_net_internal_unittests+0x4a6662) + #1 0x8bcdc3 in net::IOBuffer::IOBuffer(int) net/base/io_buffer.cc:35:11 + #2 0x8bd468 in net::IOBufferWithSize::IOBufferWithSize(int) net/base/io_buffer.cc:53:7 + +SUMMARY: MemorySanitizer: use-of-uninitialized-value net/udp/udp_socket_posix.cc:636:16 in net::UDPSocketPosix::InternalSendTo(net::IOBuffer*, int, net::IPEndPoint const*) +""") + +TSAN_ERROR_MESSAGE = ( + """ThreadSanitizer: reported 1 warnings +[814/4508] FileSystemOperationImplWriteTest.TestWriteInvalidFile (5 ms) +[ RUN ] FileSystemOperationImplWriteTest.TestWriteDir +[ OK ] FileSystemOperationImplWriteTest.TestWriteDir (5 ms) + +[----------] 2 tests from FileSystemOperationRunnerTest +[ RUN ] FileSystemOperationRunnerTest.NotFoundError +[19800:19800:1109/163405:702831287703:WARNING:sandbox_quota_observer.cc(114)] Could not get usage cache path for: filesystem:http://example.com/temporary/foo +[19800:19800:1109/163405:702831288401:WARNING:obfuscated_file_util.cc(1181)] Failed to get origin+type directory: filesystem:http://example.com/temporary/foo error:-4 +[19800:19800:1109/163405:702831288884:WARNING:sandbox_quota_observer.cc(114)] Could not get usage cache path for: filesystem:http://example.com/temporary/foo +[ OK ] FileSystemOperationRunnerTest.NotFoundError (10 ms) +[----------] 2 tests from FileSystemOperationRunnerTest (14 ms total) + +[----------] Global test environment tear-down +[==========] 10 tests from 2 test cases ran. (97 ms total) +[ PASSED ] 10 tests. +================== +WARNING: ThreadSanitizer: data race (pid=19800) + Read of size 4 at 0x0000097b6dc0 by thread T1: + #0 logging::ShouldCreateLogMessage(int) base/logging.cc:412:10 (content_unittests+0x000003aefaa7) + #1 operator-> base/memory/ref_counted.h:319:5 (content_unittests+0x000003afb7e3) + #2 base::MessageLoop::BindToCurrentThread() base/message_loop/message_loop.cc:343 (content_unittests+0x000003afb7e3) + #3 base::Thread::ThreadMain() base/threading/thread.cc:299:18 (content_unittests+0x000003b5d100) + #4 base::(anonymous namespace)::ThreadFunc(void*) base/threading/platform_thread_posix.cc:71:13 (content_unittests+0x000003b535d8) + + Previous write of size 4 at 0x0000097b6dc0 by main thread: + #0 logging::BaseInitLoggingImpl_built_with_NDEBUG(logging::LoggingSettings const&) base/logging.cc:373:25 (content_unittests+0x000003aef754) + #1 InitLogging base/logging.h:232:10 (content_unittests+0x000002fc08c3) + #2 base::TestSuite::Initialize() base/test/test_suite.cc:331 (content_unittests+0x000002fc08c3) + #3 content::ContentTestSuiteBase::Initialize() content/public/test/content_test_suite_base.cc:61:20 (content_unittests+0x000002fb2ccf) + + Location is global 'logging::(anonymous namespace)::g_logging_destination' of size 4 at 0x0000097b6dc0 (content_unittests+0x0000097b6dc0) + + Thread T1 'test_io_thread' (tid=19902, running) created by main thread at: + #0 pthread_create <null> (content_unittests+0x00000050c9b5) + #1 base::(anonymous namespace)::CreateThread(unsigned long, bool, base::PlatformThread::Delegate*, base::PlatformThreadHandle*, base::ThreadPriority) base/threading/platform_thread_posix.cc:110:13 (content_unittests+0x000003b53175) + #2 base::PlatformThread::CreateWithPriority(unsigned long, base::PlatformThread::Delegate*, base::PlatformThreadHandle*, base::ThreadPriority) base/threading/platform_thread_posix.cc:191:10 (content_unittests+0x000003b53025) + +SUMMARY: ThreadSanitizer: data race base/logging.cc:412:10 in logging::ShouldCreateLogMessage(int) +==================""") + +TSAN_COMMENT = ( + """WARNING: ThreadSanitizer: data race (pid=19800) + Read of size 4 at 0x0000097b6dc0 by thread T1: + #0 logging::ShouldCreateLogMessage(int) base/logging.cc:412:10 (content_unittests+0x000003aefaa7) + #1 operator-> base/memory/ref_counted.h:319:5 (content_unittests+0x000003afb7e3) + #2 base::MessageLoop::BindToCurrentThread() base/message_loop/message_loop.cc:343 (content_unittests+0x000003afb7e3) + #3 base::Thread::ThreadMain() base/threading/thread.cc:299:18 (content_unittests+0x000003b5d100) + #4 base::(anonymous namespace)::ThreadFunc(void*) base/threading/platform_thread_posix.cc:71:13 (content_unittests+0x000003b535d8) + + Previous write of size 4 at 0x0000097b6dc0 by main thread: + #0 logging::BaseInitLoggingImpl_built_with_NDEBUG(logging::LoggingSettings const&) base/logging.cc:373:25 (content_unittests+0x000003aef754) + #1 InitLogging base/logging.h:232:10 (content_unittests+0x000002fc08c3) + #2 base::TestSuite::Initialize() base/test/test_suite.cc:331 (content_unittests+0x000002fc08c3) + #3 content::ContentTestSuiteBase::Initialize() content/public/test/content_test_suite_base.cc:61:20 (content_unittests+0x000002fb2ccf) + + Location is global 'logging::(anonymous namespace)::g_logging_destination' of size 4 at 0x0000097b6dc0 (content_unittests+0x0000097b6dc0) + + Thread T1 'test_io_thread' (tid=19902, running) created by main thread at: + #0 pthread_create <null> (content_unittests+0x00000050c9b5) + #1 base::(anonymous namespace)::CreateThread(unsigned long, bool, base::PlatformThread::Delegate*, base::PlatformThreadHandle*, base::ThreadPriority) base/threading/platform_thread_posix.cc:110:13 (content_unittests+0x000003b53175) + #2 base::PlatformThread::CreateWithPriority(unsigned long, base::PlatformThread::Delegate*, base::PlatformThreadHandle*, base::ThreadPriority) base/threading/platform_thread_posix.cc:191:10 (content_unittests+0x000003b53025) + +SUMMARY: ThreadSanitizer: data race base/logging.cc:412:10 in logging::ShouldCreateLogMessage(int) +""") + +UBSAN_ERROR_MESSAGE = ( + """INFO:root:running command: chromium/src/out_clang_chromecast_gn_ubsan/Release/net_unittests --ozone-platform=headless --test-launcher-bot-mode --gtest_filter=-:* --gtest_output=xml:/tmp/reports/test_detail_net_unittests.xml +../../buildtools/third_party/libc++/trunk/include/list:208:16: runtime error: downcast of address 0x000006a388f8 with insufficient space for an object of type 'std::__1::__list_node<std::__1::pair<net::(anonymous namespace)::TransactionPhase, void (*)(net::MockHttpCache *)>, void *>' +0x000006a388f8: note: pointer points here + 3c 12 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + #0 0x47a615 (/usr/local/google/home/mosaic-role/slave/repo_clients/internal/chromium/src/out_clang_chromecast_gn_ubsan/Release/net_unittests+0x47a615) + #1 0x350073c (/usr/local/google/home/mosaic-role/slave/repo_clients/internal/chromium/src/out_clang_chromecast_gn_ubsan/Release/net_unittests+0x350073c) + #2 0x7f1bab1fded4 (/lib/x86_64-linux-gnu/libc.so.6+0x21ed4) + +../../buildtools/third_party/libc++/trunk/include/list:560:31: runtime error: downcast of address 0x000006a388f8 with insufficient space for an object of type 'std::__1::__list_node<std::__1::pair<net::(anonymous namespace)::TransactionPhase, void (*)(net::MockHttpCache *)>, void *>' +0x000006a388f8: note: pointer points here + 3c 12 00 00 60 ff b7 ae 3c 12 00 00 a0 fb b7 ae 3c 12 00 00 09 00 00 00 00 00 00 00 00 00 00 00 + #0 0xb9929d (/usr/local/google/home/mosaic-role/slave/repo_clients/internal/chromium/src/out_clang_chromecast_gn_ubsan/Release/net_unittests+0xb9929d) + #1 0xbb300c (/usr/local/google/home/mosaic-role/slave/repo_clients/internal/chromium/src/out_clang_chromecast_gn_ubsan/Release/net_unittests+0xbb300c) + #2 0x2d71d51 (/usr/local/google/home/mosaic-role/slave/repo_clients/internal/chromium/src/out_clang_chromecast_gn_ubsan/Release/net_unittests+0x2d71d51) + +IMPORTANT DEBUGGING NOTE: batches of tests are run inside their +own process. For debugging a test inside a debugger, use the +--gtest_filter=<your_test_name> flag along with +--single-process-tests. +Using sharding settings from environment. This is shard 0/1 +Using 32 parallel jobs. +0 tests run +Tests took 0 seconds. +INFO:root:completed running command: chromium/src/out_clang_chromecast_gn_ubsan/Release/net_unittests --ozone-platform=headless --test-launcher-bot-mode --gtest_filter=-:* --gtest_output=xml:/tmp/reports/test_detail_net_unittests.xml""") + + +UBSAN_COMMENT = ( + """../../buildtools/third_party/libc++/trunk/include/list:208:16: runtime error: downcast of address 0x000006a388f8 with insufficient space for an object of type 'std::__1::__list_node<std::__1::pair<net::(anonymous namespace)::TransactionPhase, void (*)(net::MockHttpCache *)>, void *>' +""")
diff --git a/cq/scripts/helpers/signal_utils.py b/cq/scripts/helpers/signal_utils.py new file mode 100644 index 0000000..aed36b6 --- /dev/null +++ b/cq/scripts/helpers/signal_utils.py
@@ -0,0 +1,26 @@ +"""Simple context managers for handling signals.""" + +from __future__ import absolute_import +import contextlib +import signal + + +class SigtermException(Exception): + """Exception for getting a SIGTERM.""" + + +def _sigterm_handler(signum, frame): + del signum, frame # Unused. + raise SigtermException() + + +@contextlib.contextmanager +def sigterm_handler(): + """A simple handler for SIGTERM.""" + + old_sigterm_handler = signal.signal(signal.SIGTERM, _sigterm_handler) + try: + yield + finally: + # Reset previous handlers + signal.signal(signal.SIGTERM, old_sigterm_handler)
diff --git a/cq/scripts/helpers/timeout.py b/cq/scripts/helpers/timeout.py new file mode 100644 index 0000000..8ebeee4 --- /dev/null +++ b/cq/scripts/helpers/timeout.py
@@ -0,0 +1,62 @@ +"""A simple timeout context manager. + +Note: this depends on SIGALRM and is thus UNIX specific; + this will not work on Windows. +""" + +from __future__ import absolute_import +import contextlib +import signal + + +class TimeoutException(Exception): + """Exception for timing out.""" + + +def _default_timeout_handler(signum, frame): + del signum, frame # Unused. + raise TimeoutException() + + +@contextlib.contextmanager +def timeout(handler=_default_timeout_handler, timeout_secs=0): + """A simple timeout contextmanager based on SIGALRM. + + Usage: + + try: + with timeout(handler=my_handler, timeout_secs=30): + do_stuff_that_might_take_too_long() + except timeout.TimeoutException: + clean_up_from_timeout() + finally: + other_clean_up() + + Note: Only one timeout instance can be used at a time, since the + signal handler is changed and all previously set SIGALARMs + are cleared. + + Args: + handler: A function called with two arguments: + |signum| (the signal number which should be signal.SIGALRM) + |frame| (the current stack frame, which can be None) + (Defaults to a function that just raises TimeoutException.) + timeout_secs: The amount of time before a timeout, in seconds. + + Yields: + Nothing. Yields is used as part of the contextmanager construct. + + Raises: + timeout.TimeoutException (if the default handler is used). + """ + old_handler = signal.signal(signal.SIGALRM, handler) + old_timeout = signal.alarm(timeout_secs) + try: + yield + except: + # Catch any exceptions (e.g. TimeoutException) that get raised so that + # the clean-up in the finally block can happen. Then re-raise the exception. + raise + finally: + signal.signal(signal.SIGALRM, old_handler) # reset the previous handler + signal.alarm(old_timeout) # reset the previous time remaining
diff --git a/cq/scripts/helpers/timeout_test.py b/cq/scripts/helpers/timeout_test.py new file mode 100644 index 0000000..f218463 --- /dev/null +++ b/cq/scripts/helpers/timeout_test.py
@@ -0,0 +1,102 @@ +"""Tests for timeout.""" + +from __future__ import absolute_import +import signal +import time +import unittest + +from . import timeout + +LONG_TIME_SECS = 10 + + +class TimeoutTest(unittest.TestCase): + + def testRunWithoutTimeout(self): + """Tests that handler is not called if there is no timeout.""" + def _Handler(signum, frame): + del signum, frame # Unused. + self.fail('Timeout should not occur.') + + with timeout.timeout(handler=_Handler, timeout_secs=LONG_TIME_SECS): + pass + + def testRunWithZeroTimeout(self): + """Tests that SIGALRM isn't raised with a 0 second timeout.""" + def _Handler(signum, frame): + del signum, frame # Unused. + self.fail('Timeout should not occur.') + + with timeout.timeout(handler=_Handler, timeout_secs=0): + pass + + def testDefaultHandler(self): + """Tests the default handler raises the correct exception.""" + with self.assertRaises(timeout.TimeoutException): + with timeout.timeout(timeout_secs=1): + time.sleep(LONG_TIME_SECS) + + def testRunWithTimeout(self): + """Tests timing out with a custom timeout handler.""" + + class TestException(Exception): + """A custom exception for this test.""" + + def _Handler(signum, frame): + del frame # Unused. + self.assertEqual(signum, signal.SIGALRM) + raise TestException() + + with self.assertRaises(TestException): + with timeout.timeout(handler=_Handler, timeout_secs=1): + time.sleep(LONG_TIME_SECS) + + def testPreviouslySetHandlerIsCalledWithoutTimeout(self): + """Tests that previous handler is called if there is no timeout.""" + + class TestException(Exception): + """A custom exception for this test.""" + + def _FirstHandler(signum, frame): + del frame # Unused. + self.assertEqual(signum, signal.SIGALRM) + raise TestException() + + def _SecondHandler(signum, frame): + del signum, frame # Unused. + self.fail('Timeout should not occur.') + + with self.assertRaises(TestException): + signal.signal(signal.SIGALRM, _FirstHandler) + signal.alarm(2) + with timeout.timeout(handler=_SecondHandler, timeout_secs=LONG_TIME_SECS): + pass + time.sleep(LONG_TIME_SECS) + + def testPreviouslySetHandlerIsCalledWithTimeout(self): + """Tests that previous handler is called if there is a timeout.""" + + class TestException(Exception): + """A custom exception for this test.""" + + def _FirstHandler(signum, frame): + del frame # Unused. + self.assertEqual(signum, signal.SIGALRM) + raise TestException() + + def _SecondHandler(signum, frame): + del frame # Unused. + self.assertEqual(signum, signal.SIGALRM) + raise TestException() + + with self.assertRaises(TestException): + signal.signal(signal.SIGALRM, _FirstHandler) + signal.alarm(2) + with self.assertRaises(TestException): + with timeout.timeout(handler=_SecondHandler, timeout_secs=1): + time.sleep(LONG_TIME_SECS) + time.sleep(LONG_TIME_SECS) + + +if __name__ == '__main__': + unittest.main()
diff --git a/cq/scripts/helpers/typo_fixer.py b/cq/scripts/helpers/typo_fixer.py new file mode 100644 index 0000000..c706885 --- /dev/null +++ b/cq/scripts/helpers/typo_fixer.py
@@ -0,0 +1,41 @@ +"""Tool for fixing for common typos.""" + +from __future__ import absolute_import +import collections +import logging +import os +import re + +from helpers import typos + + +def fix(line): + """Return a list of (typo, suggestion) for typos in |line|.""" + suggestions = [] + for typo in typos.TYPOS: + for match in re.finditer(typo.typo_pattern, line, re.IGNORECASE): + original = match.group(0) + suggestion = re.sub( + typo.typo_pattern, + typo.replacement_pattern, + original, + count=1, + flags=re.IGNORECASE) + + # The typo check was triggering too many false positives when words + # were mixed with CamelCase. Detect that case and ignore those suggestions + # to reduce the false positive case. + if re.search(r'[a-z][A-Z]', original): + continue + + if original.islower(): + suggestion = suggestion.lower() + elif original.isupper(): + suggestion = suggestion.upper() + elif original.istitle(): + suggestion = suggestion.title() + + if original != suggestion: + suggestions.append((original, suggestion)) + + return suggestions
diff --git a/cq/scripts/helpers/typo_fixer_test.py b/cq/scripts/helpers/typo_fixer_test.py new file mode 100644 index 0000000..0ae468a --- /dev/null +++ b/cq/scripts/helpers/typo_fixer_test.py
@@ -0,0 +1,111 @@ +"""Tests for typo_fixer.""" + +from __future__ import absolute_import +import os +import sys +import unittest + +from unittest import mock + +# Allow imports from cq/scripts folder +# pylint: disable=wrong-import-position +sys.path.insert(0, os.path.realpath(os.path.join( + os.path.dirname(__file__), os.pardir))) +from helpers import typo_fixer + + +class AssertItemsEqualMixin(): + def assertItemsEqual(self, first, second): + return self.assertEqual(sorted(first), sorted(second)) + +# Behaviour tests for the typo fixer. +class TypoFixerTest(unittest.TestCase, AssertItemsEqualMixin): + + def testDefaultDictionary_NoCorrections(self): + self.assertEqual([], typo_fixer.fix('This has no spelling mistakes.')) + + def testDefaultDictionary_SingleWord_SingleCorrection(self): + self.assertItemsEqual([('shoudl', 'should')], typo_fixer.fix('shoudl')) + self.assertItemsEqual([('taget', 'target')], typo_fixer.fix('taget')) + self.assertItemsEqual([('santizier', 'sanitizer')], + typo_fixer.fix('santizier')) + + def testDefaultDictionary_Sentence_SingleCorrection(self): + self.assertItemsEqual([('elasped', 'elapsed')], + typo_fixer.fix('Time has elasped')) + self.assertItemsEqual([('propogates', 'propagates')], + typo_fixer.fix('Foo propogates this.')) + self.assertItemsEqual([('Inhert', 'Inherit')], + typo_fixer.fix('Inhert from parent')) + + def testDefaultDictionary_Sentence_MultipleCorrections(self): + self.assertItemsEqual([('libary', 'library'), + ('guaratee', 'guarantee'), + ('postive', 'positive')], + typo_fixer.fix('The libary guaratees this is postive')) + + def testDefaultDictionary_PreserveCase(self): + self.assertItemsEqual([('LIBARY', 'LIBRARY')], typo_fixer.fix('LIBARY')) + self.assertItemsEqual([('Libary', 'Library')], typo_fixer.fix('Libary')) + self.assertItemsEqual([('libary', 'library')], typo_fixer.fix('libary')) + + +# A colleciton of positive / negative examples for individual typos. +class TyposTest(unittest.TestCase, AssertItemsEqualMixin): + + def testThenThan(self): + # Positive + self.assertItemsEqual([('less then', 'less than')], + typo_fixer.fix('less then three')) + self.assertItemsEqual([('greater then', 'greater than')], + typo_fixer.fix('greater then')) + # Negative + self.assertItemsEqual([], typo_fixer.fix('bigger than 3, smaller than 4')) + + def testDependency(self): + # Positive + self.assertItemsEqual([('depedency', 'dependency')], + typo_fixer.fix('depedency')) + self.assertItemsEqual([('depedencies', 'dependencies')], + typo_fixer.fix('depedencies')) + # Negative + self.assertItemsEqual([], typo_fixer.fix('dependency dependencies')) + + def testPerference(self): + # Positive + self.assertItemsEqual([('prefferrance', 'preference')], + typo_fixer.fix('That is my prefferrance')) + + # Negative + self.assertItemsEqual([], typo_fixer.fix('What are your preferences?')) + + def testTodo(self): + # Positive + self.assertItemsEqual([('TOOO(abc)', 'TODO(abc)')], + typo_fixer.fix('TOOO(abc): A thing')) + self.assertItemsEqual([('TOOD(xyz@)', 'TODO(xyz@)')], + typo_fixer.fix('TOOD(xyz@)')) + self.assertItemsEqual([('TDO(b/1234)', 'TODO(b/1234)')], + typo_fixer.fix('TDO(b/1234): That last thing')) + # Negative + self.assertItemsEqual([], typo_fixer.fix(' TODO: something\n' + ' TODO(abc@): something\n' + ' TODO(b/1234): something\n')) + + def testDefault(self): + #Negative + self.assertItemsEqual([], typo_fixer.fix('Make |kDefaultDelayMs| longer')) + + def testSuccess(self): + # Postive + self.assertItemsEqual([('Successs', 'Success')], + typo_fixer.fix('Successs on the mission today.')) + + # Negative + # Note: this particular example does not generate a fix even though + # it matches "SuccessS", because the match has mixed case. + self.assertItemsEqual([], typo_fixer.fix('kGenericSuccessStatus')) + + +if __name__ == '__main__': + unittest.main()
diff --git a/cq/scripts/helpers/typos.py b/cq/scripts/helpers/typos.py new file mode 100644 index 0000000..b852f39 --- /dev/null +++ b/cq/scripts/helpers/typos.py
@@ -0,0 +1,348 @@ +# This was copied from google3/devtools/linter/common_typos/typos.txt on +# 2017-11-03 and modified to be compatible with the python re module. + +# NOTE: Typos here will apply to documentation, code, comments, and commit +# messages. Please make sure that you do not add any typos here that exist in +# projects' external dependencies (e.g. as part of a different project's API). +# +# Regular expressions on the left are replaced with those on the right. +# +# If you update this with anything complex, please add a corresponding test or +# two for both positive and negative examples. +# +# Mostly taken and/or adapted from http://sites/lolcodesearch. +# +# Be careful with optional capture groups and references - optional groups +# must be transformed as "(abc)?" -> "(abc|)", otherwise it may throw an +# exception if the optional group isn't matched but is referenced in expansion. +# +# Only RE2 syntax regular expressions are supported. Backreferences and +# negative assertions make the expression non-regular, and take worst-case +# exponential time. +# +# The typo fixer will ignore any suggestsions in which the original and the +# suggested fix are the same, which can be useful since it is sometimes +# to make a simple regex that matches all the misspellings while not matching +# the correct spelling. + +# pylint: disable=line-too-long + +from __future__ import absolute_import +import collections +Typo = collections.namedtuple('Type', ['typo_pattern', 'replacement_pattern']) + +TYPOS = [ + Typo(r'(a|)syncho(r|ro|)(r|n)ous(ly|)', r'\1synchronous\4'), + Typo(r'(con|de)(stuct|truct|cruct)', r'\1struct'), + Typo(r'(c|sh|w)oudl', r'\1ould'), + Typo(r'(c|sh|w)oul(e|n|s|t)', r'\1ould'), + Typo(r'(depricate|depreciate|deperecate)(d|)', r'deprecate\2'), + Typo(r'(m|re|)maping', r'\1mapping'), + Typo(r'(not|mod)(if|fi)cation(s|)', r'\1ification\3'), + Typo(r'(not|mod)ifica(iton|toin)(s|)', r'\1ification\3'), + Typo(r'(pre|)sumbit', r'\1submit'), + Typo(r'(proto|)tpye(s|)', r'\1type\2'), + Typo(r'(un|)healhty', r'\1healthy'), + Typo(r'(re|)genrate(ed|)', r'\1generate\2'), + Typo(r'\b(flase|fales|fasle)\b', r'false'), + Typo(r'\b(more|less|greater|lesser|bigger|smaller)(\s+)then\b', + r'\1\2than'), + Typo(r'\b(ture|treu)\b', r'true'), + Typo(r'\b(uknown|unkown|unkwon|unkowon)\b', r'unknown'), + Typo(r'\b(un|)singed\b', r'\1signed'), + Typo(r'\balot\b', r'a\x20lot'), + Typo(r'\bandoid\b', r'android'), + Typo(r'\bbalue\b', r'value'), + Typo(r'\bcorn(\s|)job', r'cron\1job'), + Typo(r'\bfrist\b', r'first'), + Typo(r'\bgrammer\b', r'grammar'), + Typo(r'\bit\sself(\.|)([^-a-zA-Z\.]|$)', r'itself\1\2'), + Typo(r'\bommitted', r'omitted'), + Typo(r'\bsmapl(e[rsd]?|ing)\b', r'sampl\1'), + Typo(r'\btaget\b', r'target'), + Typo(r'\bthier\b', r'their'), + Typo(r'\btread(.|)safe\b', r'thread\1safe'), + Typo(r'acccount', r'account'), + Typo(r'accessibile', r'accessible'), + Typo(r'accomodat(e|ion)', r'accommodat\1'), + Typo(r'accross', r'across'), + Typo(r'acitiv(e|ity)', r'activ\1'), + Typo(r'activites', r'activities'), + Typo(r'acutally', r'actually'), + Typo(r'\badition', r'addition'), + Typo(r'adress', r'address'), + Typo(r'aggragat(e|ed|ing|ion)', r'aggregat\1'), + Typo(r'aggree', r'agree'), + Typo(r'agressive', r'aggressive'), + Typo(r'ajust', r'adjust'), + Typo(r'alredy', r'already'), + Typo(r'andriod', r'android'), + Typo(r'applicaiton(s|)', r'application\1'), + Typo(r'argu(e|)me?nt(s|)', r'argument\2'), + Typo(r'arround', r'around'), + Typo(r'asign', r'assign'), + Typo(r'assosciated', r'associated'), + Typo(r'asume', r'assume'), + Typo(r'atribute', r'attribute'), + Typo(r'authentification', r'authentication'), + Typo(r'availiability', r'availability'), + Typo(r'availiable|avaliable', r'available'), + Typo(r'bandwith', r'bandwidth'), + Typo(r'baord', r'board'), + Typo(r'bec(u|)ase\b', r'because'), + Typo(r'befor\b', r'before'), + Typo(r'begining', r'beginning'), + Typo(r'borgcorn', r'borgcron'), + Typo(r'bormgon', r'borgmon'), + Typo(r'breif', r'brief'), + Typo(r'bulid(er|s|ing|)', r'build\1'), + Typo(r'calender', r'calendar'), + Typo(r'capbilit(y|ies)', r'capabilit\1'), + Typo(r'cannonical', r'canonical'), + Typo(r'celcius', r'Celsius'), + Typo(r'chagne', r'change'), + Typo(r'chanel', r'channel'), + Typo(r'charachter(s|)', r'character\1'), + Typo(r'choosen\b', r'chosen'), + Typo(r'choses\b', r'chooses'), + Typo(r'chrome(cats|csat)', r'chromecast'), + Typo(r'cilent', r'client'), + Typo(r'classif(er|cation)', r'classifi\1'), + Typo(r'columio', r'columnio'), + Typo(r'com+it+(ed|ing)\b', r'committ\1'), + Typo(r'comming\b', r'coming'), + Typo(r'comparision', r'comparison'), + Typo(r'compatability', r'compatibility'), + Typo(r'complier', r'compiler'), + Typo(r'(pre|)comptuation(s|)', r'\1computation\2'), + Typo(r'consistant', r'consistent'), + Typo(r'contaning', r'containing'), + Typo(r'contant(s|)', r'constant\1'), + Typo(r'contians', r'contains'), + Typo(r'continous', r'continuous'), + Typo(r'convertable', r'convertible'), + Typo(r'convertion', r'conversion'), + Typo(r'correspondan(ce|t)', r'corresponden\1'), + Typo(r'cosnt', r'const'), + Typo(r'course(.|)grained', r'coarse\1grained'), + Typo(r'curent\b', r'current'), + Typo(r'currenty', r'currently'), + Typo(r'dashborad', r'dashboard'), + Typo(r'deatil(s|ed|)', r'detail\1'), + Typo(r'deafult(s|)', r'default\1'), + Typo(r'definately', r'definitely'), + Typo(r'defintion(s|)', r'definition\1'), + Typo(r'dep(d|)e(n|)de(n|)c(y|ies)', r'dependenc\4'), + Typo(r'descritp(ions?|ors?)', r'descript\1'), + Typo(r'destript(ions?|ors?)', r'descript\1'), + Typo(r'deterine(s|d|)', r'determine\1'), + Typo(r'diferent', r'different'), + Typo(r'dimention', r'dimension'), + Typo(r'direcory', r'directory'), + Typo(r'dispatcer', r'dispatcher'), + Typo(r'egde(s|)', r'edge\1'), + Typo(r'elasped', r'elapsed'), + Typo(r'embeded', r'embedded'), + Typo(r'emmitt(ed|ing|er)', r'emitt\1'), + Typo(r'encryted', r'encrypted'), + Typo(r'encyrption', r'encryption'), + Typo(r'enity', r'entity'), + Typo(r'entires', r'entries\1'), + Typo(r'enviroment', r'environment'), + Typo(r'errror(s|)', r'error\1'), + Typo(r'estiamt(or|ed|e)', r'estimat\1'), + Typo(r'excecute', r'execute'), + Typo(r'excede', r'exceed'), + Typo(r'excelent', r'excellent'), + Typo(r'excercise', r'exercise'), + Typo(r'exisiting', r'existing'), + Typo(r'existan(t|ce)\b', r'existen\1'), + Typo(r'exmaple', r'example'), + Typo(r'expe(rie|ir|iri)ment(s|)', r'experiment\2'), + Typo(r'explicitely', r'explicitly'), + Typo(r'extenstion', r'extension'), + Typo(r'extention', r'extension'), + Typo(r'f(in|ni)shed', r'finished'), + Typo(r'farenheit', r'Fahrenheit'), + Typo(r'feas(i|a)b(i|)(le|ility)', r'feasib\3'), + Typo(r'fitler', r'filter'), + Typo(r'format(tt|)(ing|ed)', r'formatt\2'), + Typo(r'foward', r'forward'), + Typo(r'frequecy', r'frequency'), + Typo(r'func(iton|toin)(s|al|ed|ing|)', r'function\2'), + Typo(r'funtion', r'function'), + Typo(r'goole|googel|goolge', r'google'), + Typo(r'guaratee(d|)', r'guarantee\1'), + Typo(r'gurantee(d|)', r'guarantee\1'), + Typo(r'hanlder(s|)', r'handler\1'), + Typo(r'heigth', r'height'), + Typo(r'heirarchy', r'hierarchy'), + Typo(r'identifer(s|)', r'identifier\1'), + Typo(r'idenfifier(s|)', r'identifier\1'), + Typo(r'ignroe(d|s|)', r'ignore\1'), + Typo(r'impresssion', r'impression'), + Typo(r'ind(e|i)cies', r'indices'), + Typo(r'indeces', r'indices'), + Typo(r'indentif(ication|ied|ies|ier|iers|y|ying)', r'identif\1'), + Typo(r'independant', r'independent'), + Typo(r'ingored', r'ignored'), + Typo(r'inhert', r'inherit'), + Typo(r'initialzing', r'initializing'), + Typo(r'initialzi(ed|er|ers|es|ation)', r'initializ\1'), + Typo(r'instanciat(ed|ion|ions|e)', r'instantiat\1'), + Typo(r'instantitation', r'instantiation'), + Typo(r'intead', r'instead'), + Typo(r'interable', r'iterable'), + Typo(r'interator', r'iterator'), + Typo(r'interchangabl(e|y)', r'interchangeabl\1'), + Typo(r'interger', r'integer'), + Typo(r'intermittant', r'intermittent'), + Typo(r'intial(ly|)', r'initial\1'), + Typo(r'intializ(e|ed|er|ers|ing|ation|)', r'initializ\1'), + Typo(r'(in|)vlaid(ate|ated|)', r'\1valid\2'), + Typo(r'invokation', r'invocation'), + Typo(r'irregardless', r'regardless'), + Typo(r'javasscript', r'javascript'), + Typo(r'(ack|)knowlege(ment|d|)(s|)', r'\1knowledge\2\3'), + Typo(r'aknowle(d|)ge(ment|d|)(s|)', r'acknowledge\2\3'), + Typo(r'lamda', r'lambda'), + Typo(r'langauge(s|)', r'language\1'), + Typo(r'lastest', r'latest'), + Typo(r'lealaps', r'laelaps'), + Typo(r'lenght(s|)', r'length\1'), + Typo(r'libasis+[tan]+', r'libassistant'), + Typo(r'libary', r'library'), + Typo(r'listner', r'listener'), + Typo(r'locaiton(s|)', r'location\1'), + Typo(r'looup', r'lookup'), + Typo(r'managment', r'management'), + Typo(r'maxumum', r'maximum'), + Typo(r'maintenace', r'maintenance'), + Typo(r'meatadata|meatdata', r'metadata'), + Typo(r'medatata', r'metadata'), + Typo(r'migation', r'migration'), + Typo(r'moniter(s|ed|ing|able|)', r'monitor\1'), + Typo(r'mutiple|mulitple', r'multiple'), + Typo(r'neccessary', r'necessary'), + Typo(r'necesar(y|ily)', r'necessar\1'), + Typo(r'newstand', r'newsstand'), + Typo(r'nulltpr', r'nullptr'), + Typo(r'oc+ur+(a|e)nce', r'occurrence'), + Typo(r'occur(ed|ing)', r'occurr\1'), + Typo(r'offical', r'official'), + Typo(r'or(gi|ig)nal', r'original'), + Typo(r'ove(r|)riden', r'overridden'), + Typo(r'overide', r'override'), + Typo(r'ove(r|)rite', r'overwrite'), + Typo(r'ove(r|)rites', r'overwrites'), + Typo(r'ove(r|)rit(t|)en', r'overwritten'), + Typo(r'pacakge', r'package'), + Typo(r'paramter(s|)', r'parameter\1'), + Typo(r'path[aei]logical', r'pathological'), + Typo(r'permanant', r'permanent'), + Typo(r'platfrom|paltform|platfom|patform|plaftorm', r'platform'), + Typo(r'peroid(ic|ical|ically|)', r'period\1'), + Typo(r'persistant', r'persistent'), + Typo(r'pipeling|pipline', r'pipeline'), + Typo(r'postion', r'position'), + Typo(r'postive', r'positive'), + Typo(r'preceed(ed|ing)', r'preced\1'), + Typo(r'precodition(s|)', r'precondition\1'), + Typo(r'pref+er+ed', r'preferred'), + Typo(r'pref+er+[ae]nce(s|)', r'preference\1'), + Typo(r'presedence', r'precedence'), + Typo(r'(p|)revew|reviw(ed|s|)', r'\1review\2'), + Typo(r'proably', r'probably'), + Typo(r'procede', r'proceed'), + Typo(r'proces(ing|ed|es)', r'process\1'), + Typo(r'produciton', r'production'), + Typo(r'programatic(ally|)', r'programmatic\1'), + Typo(r'prohibitted', r'prohibited'), + Typo(r'propogat(ion|ed|es|e)', r'propagat\1'), + Typo(r'protocal', r'protocol'), + Typo(r'proudction', r'production'), + Typo(r'psuedo', r'pseudo'), + Typo(r'pubicly', r'publicly'), + Typo(r'publically', r'publicly'), + Typo(r'\bputing\b', r'putting'), + Typo(r'qualificaiton(s|)', r'qualification\1'), + Typo(r'realease', r'release'), + Typo(r'recieve', r'receive'), + Typo(r'recomend(ation|ations|s|ing|)', r'recommend\1'), + Typo(r'recrod', r'record'), + Typo(r'relase', r'release'), + Typo(r'relevent', r'relevant'), + Typo(r'(ir|)relvant', r'\1relevant'), + Typo(r'reponse|respone', r'response'), + Typo(r'reponsibilit(y|ies)', r'responsibilit\1'), + Typo(r'reqeust(s|ed|ing|)', r'request\1'), + Typo(r'reserach', r'research'), + Typo(r'(re|)sopurce', r'\1source'), + Typo(r'responsabilit(y|ies)', r'responsibilit\1'), + Typo(r'resopnse', r'response'), + Typo(r'resovl(e[sd]?|ing)', r'resolv\1'), + Typo(r'retre?ive(d|s|)', r'retrieve\1'), + Typo(r'retrival', r'retrieval'), + Typo(r'runnning', r'running'), + Typo(r'saftey', r'safety'), + Typo(r'san[ietz]+r', r'sanitizer'), + Typo(r'seconary', r'secondary'), + Typo(r'seperate(d|s|)', r'separate\1'), + Typo(r'serach', r'search'), + Typo(r'shoppping', r'shopping'), + Typo(r'similiar', r'similar'), + Typo(r'singals', r'signals'), + Typo(r'snasphot', r'snapshot'), + Typo(r'specical', r'special'), + Typo(r'speficying', r'specifying'), + Typo(r'standart', r'standard'), + Typo(r'starteg(ies|y)', r'strateg\1'), + Typo(r'statment', r'statement'), + Typo(r'stich(ed|ing)', r'stitch\1'), + Typo(r'stirng', r'string'), + Typo(r'stroage', r'storage'), + Typo(r'su+c+e+s+(ful|es|)', r'success\1'), + Typo(r'su+p+e+r+o+t+', r'superroot'), + Typo(r'substract', r'subtract'), + Typo(r'successfuly', r'successfully'), + Typo(r'sufix', r'suffix'), + Typo(r'sugest', r'suggest'), + Typo(r'sycn', r'sync'), + Typo(r'syncronize', r'synchronize'), + Typo(r'threre(after|fore|)', r'there\1'), + Typo(r'threshould|thershold', r'threshold'), + Typo(r'throught', r'through'), + Typo(r'thumnail', r'thumbnail'), + Typo(r'transfer(ing|ed)', r'transferr\1'), + Typo(r'transation', r'transaction'), + Typo(r'tricoder', r'tricorder'), + Typo(r'uderlying', r'underlying'), + Typo(r'udpate', r'update'), + Typo(r'undefiend', r'undefined'), + Typo(r'unkown', r'unknown'), + Typo(r'virutal', r'virtual'), + Typo(r'weigth(s|ing|)', r'weight\1'), + Typo(r'wether', r'whether'), + Typo(r'wierd(ness|o|)', r'weird\1'), + Typo(r'worfklow', r'workflow'), + Typo(r'writen', r'written'), + Typo(r'writting', r'writing'), + Typo(r'zweiback', r'zwieback'), + Typo(r'\bGoogle,(\s+)Inc\.?\b', r'Google\1Inc.'), + Typo(r'\band\s+and\b', r'and'), + Typo(r'\bif\s+if\b', r'if'), + Typo(r'\bit\s+it\b', r'it'), + Typo(r'\bof\s+of\b', r'of'), + Typo(r'\bthe\s+its\b', r'its'), + Typo(r'\bthe\s+the\b', r'the'), + Typo(r'\bwith\s+with\b', r'with'), + Typo(r'\bObjective\sC\b', r'Objective-C'), + Typo(r'http(s|):\/\/\/', r'http\1://'), + Typo(r'https:\/\/([[:alnum:]]+)\/', r'http://\1/'), + Typo(r'ouptut|ouput|outout|OUPTUT|OUPUT', r'output'), + Typo(r'A-za-z', r'A-Za-z'), + Typo(r'a-zA-z', r'a-zA-Z'), + Typo( + r'^(|.*[^TtRrSsEe])(TOOO|TOD0|TODI|TODP|TOO|TOSO|TODDO|TOOD|TOCO|TOTO|ODO|TDOO|TODOD|TOFO|TDDO|TODD|TOD|TODOO|TDO|TODL)\W?\(\s*(([a-z]{1,14}@?)|(b.?\d+))\s*\)', + r'\1TODO(\3)'), +]
diff --git a/cq/scripts/resources/kythe_step/vnames.json b/cq/scripts/resources/kythe_step/vnames.json new file mode 100644 index 0000000..bf04ad4 --- /dev/null +++ b/cq/scripts/resources/kythe_step/vnames.json
@@ -0,0 +1,24 @@ +[ + { + "pattern": "out_fuchsia_arm64_user/Release/gen/(.*)", + "vname": { + "corpus": "eureka-internal.googlesource.com/codesearch", + "root": "out_fuchsia/release/gen", + "path": "@1@" + } + }, + { + "pattern": "chromecast/internal/(.*)", + "vname": { + "corpus": "eureka-internal.googlesource.com/codesearch", + "path": "cast/internal/@1@" + } + }, + { + "pattern": "(.*)", + "vname": { + "corpus": "eureka-internal.googlesource.com/codesearch", + "path": "@1@" + } + } +] \ No newline at end of file
diff --git a/cq/scripts/slave/__init__.py b/cq/scripts/slave/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/cq/scripts/slave/__init__.py
diff --git a/cq/scripts/slave/accelerator/__init__.py b/cq/scripts/slave/accelerator/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/cq/scripts/slave/accelerator/__init__.py
diff --git a/cq/scripts/slave/accelerator/no_accelerator.py b/cq/scripts/slave/accelerator/no_accelerator.py new file mode 100644 index 0000000..59c92a8 --- /dev/null +++ b/cq/scripts/slave/accelerator/no_accelerator.py
@@ -0,0 +1,31 @@ + +class NoAccelerator(object): + @property + def make_flags(self): + return [] + + @property + def build_chromecast_flags(self): + return [] + + @property + def gn_flags(self): + return [] + + @property + def environment_variables(self): + return {} + + def setup_steps(self, step_kwargs): + del step_kwargs + return [] + + def tear_down_steps(self, step_kwargs): + del step_kwargs + return [] + + def setup_mocks(self, step): + pass + + def tear_down_mocks(self, step): + pass \ No newline at end of file
diff --git a/cq/scripts/slave/accelerator/rbe_accelerator.py b/cq/scripts/slave/accelerator/rbe_accelerator.py new file mode 100644 index 0000000..ef2e883 --- /dev/null +++ b/cq/scripts/slave/accelerator/rbe_accelerator.py
@@ -0,0 +1,39 @@ +from slave.step import reproxy_start_step +from slave.step import reproxy_stop_step +from helpers import rbe_utils + + +class Accelerator(object): + @property + def make_flags(self): + if rbe_utils.is_installed(): + return ['USE_RBE=1', 'ENABLE_RBE_BOOTSTRAP=0', 'NUM_JOBS=300'] + return [] + + @property + def build_chromecast_flags(self): + if rbe_utils.is_installed(): + return ['--use_rbe'] + return [] + + @property + def gn_flags(self): + if rbe_utils.is_installed(): + return ['use_rbe=true', 'enable_rbe_bootstrap=false'] + return [] + + @property + def environment_variables(self): + return {} + + def setup_steps(self, step_kwargs): + return [reproxy_start_step.ReproxyStartStep(**step_kwargs)] + + def tear_down_steps(self, step_kwargs): + return [reproxy_stop_step.ReproxyStopStep(**step_kwargs)] + + def setup_mocks(self, step): + pass + + def tear_down_mocks(self, step): + pass
diff --git a/cq/scripts/slave/base_recipe.py b/cq/scripts/slave/base_recipe.py new file mode 100644 index 0000000..250a55a --- /dev/null +++ b/cq/scripts/slave/base_recipe.py
@@ -0,0 +1,164 @@ +"""Base class for build recipes.""" +import abc +import logging +import os +from pathlib import Path +import pprint +import six +from typing import Any, Dict, Optional + +from helpers import accelerator_utils +from slave.accelerator import no_accelerator +from slave.step import clean_sync_step +from slave.step import git_clean_step +from slave.step import license_manager_step +from slave.step import make_clean_step +from slave.step import platform_info_step + + +LOGGER = logging.getLogger(__name__) + +class BuildNameNotSupportedError(Exception): + """Raised when a recipe does not support the given build_name.""" + + +class BaseRecipe(six.with_metaclass(abc.ABCMeta, object)): + """Base class for recipes.""" + + def __init__(self, + executor: 'Executor', + eureka_root: str, + enable_build_accelerator: bool=False, + properties: Optional[Dict[str, Any]]=None, + **kwargs): + """Base constructor. + + Args: + **kwargs: The kwargs to pass to individual steps. + """ + LOGGER.info("Creating recipe %s", type(self)) + LOGGER.info("Properties: %s", pprint.pformat(properties)) + LOGGER.info("Eureka root: %s", eureka_root) + self._eureka_root = Path(eureka_root) + self._properties = properties or {} + self._build_accelerator = ( + accelerator_utils.get_build_accelerator() + if enable_build_accelerator else no_accelerator.NoAccelerator()) + self._executor = executor + self._remote_lookup = None + self._path_lookup = None + self._fix_floats() + self._skip_gclient = self._properties.get('skip_gclient', False) + self._git_clean = self._properties.get('git_clean', False) + self._make_clean = self.build_system == 'catabuilder' + self._make_distclean = self._properties.get('make_distclean', False) + self._manifest_branch = self._properties.get('manifest_branch') + self._patch_project = self._properties.get('patch_project') + self._env = self._properties.get('build_env', 'local') + self._manifest_url = self._properties.get('manifest_url') + self._check_android_license = ( + self._env != 'local' and kwargs.get('check_android_license', False)) + + self._step_kwargs = kwargs.copy() + self._step_kwargs['build_accelerator'] = self._build_accelerator + self._step_kwargs["executor"] = executor + self._step_kwargs["eureka_root"] = self._eureka_root + self._step_kwargs["enable_build_accelerator"] = enable_build_accelerator + self._step_kwargs["properties"] = properties + + @property + def build_system(self): + """Returns the name of current build system.""" + return self._properties.get('build_system', 'local') + + @property + def buildername(self): + """Returns the buildername of the current build.""" + return self._properties.get('buildername') + + def get_setup_steps(self): + """Returns a list of all steps that should be executed as part of setup. + + Returns: + List of slave.base_step.BaseStep commands to be executed. + """ + setup_steps = [] + setup_steps.append( + platform_info_step.PlatformInfoStep( + directory='', **self._step_kwargs)) + + if not self._skip_gclient: + setup_steps.append( + clean_sync_step.GclientSyncStep( + directory='', **self._step_kwargs)) + + if self._check_android_license: + setup_steps.append(license_manager_step.AndroidSdkLicenseCheckAccept( + directory='', **self._step_kwargs)) + + setup_steps.extend( + self. _get_build_accelerator().setup_steps(self._step_kwargs)) + + if self._make_clean: + setup_steps += self.get_clean_steps() + + if self._make_distclean: + setup_steps.append( + make_clean_step.MakeDistCleanStep(**self._step_kwargs)) + + if self._git_clean: + setup_steps.append( + git_clean_step.GitCleanStep(**self._step_kwargs)) + + return setup_steps + + def _get_build_accelerator(self): + return self._build_accelerator + + def get_teardown_steps(self): + """Returns a list of all steps that should be executed as part of teardown. + + Returns: + List of slave.base_step.BaseStep commands to be executed. + """ + return self._get_build_accelerator().tear_down_steps(self._step_kwargs) + + @property + def build_number(self): + """Construct BUILD_NUMBER string in unified way between all systems. + + This property is matching the same property in the BaseStep, should be + altered together. + + Returns: + CL number (from 'issue' porperty) for CQ, buildset number for CB or 0 + """ + return str(self._properties.get( + 'issue', self._properties.get('buildset', '0'))) + + @abc.abstractmethod + def get_steps(self): + """Builds a list of all steps that should be executed by this recipe. + + Returns: + List of slave.base_step.BaseStep commands to be executed. + """ + return [] + + def get_clean_steps(self): + """Builds a list of all clean steps that should be executed by this recipe. + + Returns: + List of slave.base_step.BaseStep commands to be executed. + """ + return [] + + def _fix_floats(self): + """Buildbucket is enforcing floats, but we want ints.""" + for key, value in self._properties.items(): + if isinstance(value, float): + self._properties[key] = int(value) + + def _getcwd(self): + """Helper function to make it easy to mock os.getcwd() for tests.""" + return os.getcwd()
diff --git a/cq/scripts/slave/base_step.py b/cq/scripts/slave/base_step.py new file mode 100644 index 0000000..937868a --- /dev/null +++ b/cq/scripts/slave/base_step.py
@@ -0,0 +1,572 @@ +"""Base class for build steps.""" +import logging +import multiprocessing +import os +import re +import subprocess + +import psutil + +from cq.scripts.helpers import git_utils +from cq.scripts.helpers import timeout + +# Preventing running any step longer than this amount of time. +STEP_MAX_TIME_SECONDS = 2 * 60 * 60 + +# If it takes a subprocess more than 2 mins to exit, let's assume it's hung +# and will probably never return properly. +_SUBPROCESS_TIMEOUT = 2 * 60 + + +class StepError(Exception): + """Exception raised when a step failure happens.""" + + +class GoBlsremoteQuotaError(StepError): + """Exception raise for the GoB lsremote quota exceeded error.""" + ERROR_MSG = 'Short term ls-remote rate limit exceeded' + + +class GoBbandwidthQuotaError(StepError): + """Exception raise for the GoB bandwidth quota exceeded error.""" + ERROR_MSG = 'Short term bandwidth rate limit exceeded' + + +class GoBManifestInvalidRevisionError(StepError): + """Exception raise for the GoB invalid manifest revision error.""" + ERROR_MSG = 'ManifestInvalidRevisionError' + + +class BaseStep: + """Base class for build steps. + + Implementers should override the methods below as appropriate. + + Attributes: + name: user-visible name of this step. + env: representation of build_env build property. + data_manager: handles managing data between steps. + executor: invokes and interacts with external processes. + annotator: receives annotations from steps to communicate to build master. + halt_on_failure: whether or not this step's failure should end recipe + execution. + allow_list_filter: If specified, a list of regex's to use to filter + files that get linted. Only file names that match + at least one filter in the allow_list will get linted. + An empty list will result in no files getting linted. + If a file matches a allow_list filter and a deny_list + filter, the file will be deny_listed. + (default allows all files) + deny_list_filter: If specified, a list of regex's to use to filter files + that get linted. Only file names that do not match + any filter in the deny_list will get linted. + If a file matches a allow_list filter and a deny_list + filter, the file will be deny_listed. + (default allows all files) + """ + + def __init__(self, + name: str, + executor=None, + annotator=None, + data_manager=None, + halt_on_failure=False, + properties=None, + directory=None, + timeout_secs=STEP_MAX_TIME_SECONDS, + result_on_timeout=False, + allow_list_filter=None, + deny_list_filter=None, + prerun_data=None, + build_accelerator=None, **kwargs): + assert name + assert executor + assert data_manager + assert build_accelerator + assert isinstance(halt_on_failure, bool) + if allow_list_filter: + assert isinstance(allow_list_filter, list) + if deny_list_filter: + assert isinstance(deny_list_filter, list) + + self._name = name + self._executor = executor + self._annotator = annotator + self._data_manager = data_manager + self._non_blocking_subprocesses = [] + self._halt_on_failure = halt_on_failure + self._properties = properties + self._directory = directory + self._project_directory = None + self._project_remote = None + if not isinstance(timeout_secs, int): + timeout_secs = 0 + self._timeout_secs = timeout_secs + self._result_on_timeout = result_on_timeout + self._run_results = { + 'name': self.name, + 'exit_code': 0, + 'files': {}, + 'logs': {}, + 'valid': False + } + if prerun_data is None: + prerun_data = {} + else: + assert isinstance(prerun_data, dict) + self._run_results['valid'] = True + self._run_results.update(prerun_data) + + if allow_list_filter is None: + allow_list_filter = ['.*'] + if deny_list_filter is None: + deny_list_filter = [] + self._allow_list_filter = [re.compile(regex) for regex in allow_list_filter] + self._deny_list_filter = [re.compile(regex) for regex in deny_list_filter] + self._last_subprocess_cmd = None + self._build_accelerator = build_accelerator + + _ = kwargs + + @property + def results(self): + """Returns the result of this step run.""" + return self._run_results + + @property + def name(self): + """Returns the name of this step.""" + return self._name + + @property + def build_system(self): + """Returns the name of current build system.""" + return self.get_property('build_system', 'local') + + @property + def env(self): + return self.get_property('build_env', 'local') + + @property + def remote(self): + """Returns the remote to use for this step.""" + if not self._project_remote: + self._project_remote = self.get_project_remote(self.patch_project) + return self._project_remote + + @property + def directory(self): + """Returns the directory to use for this step.""" + if self._directory is not None: + return self._directory + if not self._project_directory: + if self.patch_project: + self._project_directory = self.get_project_path(self.patch_project) + else: + self._project_directory = '' + return self._project_directory + + @property + def build_accelerator(self): + return self._build_accelerator + + def get_property(self, name, default=None): + """Returns the requested property value, or default if not found.""" + if not self._properties: + return default + return self._properties.get(name, default) + + @property + def depends_on_list(self): + """Returns the list of Depends-On information. + + Each item in the list is a dict of the form: + { + 'gob_host': <Gerrit on borg host name> + 'project': <Project name, should match a name in the repo manifest> + 'change_number': <CL #> + 'patchset_number': <PS #> + } + + Returns: + List of depends-on dicts. + """ + return self.get_property('depends_on', default=[]) + + @property + def build_number(self): + """Construct BUILD_NUMBER string in unified way between all systems. + + This property is matching the same property in the BaseRecipe, should be + altered together. + + Returns: + CL number (from 'issue' porperty) for CQ, buildset number for CB or 0 + """ + return str(self.get_property( + 'issue', default=self.get_property('buildset', default='0'))) + + @property + def patchset(self): + """Returns the patchset number for this step.""" + return self.get_property('patchset', default='0') + + @property + def patch_project(self): + """Returns the patch_project to use for this step.""" + return self.get_property('patch_project') + + @property + def manifest_branch(self): + """Returns the manifest branch to use for this step.""" + return self.get_property('manifest_branch') + + def allow_listed(self, filename): + return any(re.search(regex, filename) for regex in self._allow_list_filter) + + def deny_listed(self, filename): + return any(re.search(regex, filename) for regex in self._deny_list_filter) + + def changed_files(self, file_extensions=None): + changed_files = git_utils.changed_files( + self, directory=self.directory, file_extensions=file_extensions) + return [f for f in changed_files + if self.allow_listed(f) and not self.deny_listed(f)] + + def get_num_jobs(self, multiplier=2): + """Returns the number of jobs this step can use. + + Uses a heuristic to figure out the number of parallel jobs supported by + the build machine. Currently this is just 2x the number of CPU cors. + + Args: + multiplier: The multiplier to use. + + Returns: + The number of jobs to use. + """ + return multiprocessing.cpu_count() * multiplier + + def exec_subprocess(self, + command, + check_output=False, + cwd=None, + *args, + **kwargs): # pylint: disable=keyword-arg-before-vararg + """Execute a command. + + Args: + command: The command to execute. + check_output: Whether or not to raise a CalledProcessError on non-zero + return code. + cwd: The current working directory to use for the subprocess. + Defaults to os.getcwd() + *args: positional params. + **kwargs: Key/Value dictionary params. + Returns: + Either just stderr if check_output=True, or a tuple of + (returncode, stdout, stderr) + """ + self._last_subprocess_cmd = command + + returncode, stdout, stderr = \ + self._executor.subprocess(command, *args, cwd=cwd, **kwargs) + + if check_output: + if returncode != 0: + full_output = stdout + if stderr: + full_output += '\nstderr:\n' + stderr + raise subprocess.CalledProcessError(returncode, + cmd=command, + output=full_output) + + return stdout + return returncode, stdout, stderr + + def exec_subprocess_chain(self, subprocess_chain): + """Execute a chain of commands, piping output between processes.""" + msg = ['Chain of commands, piping output between processes:'] + commands = msg + [' '.join(command[0]) for command in subprocess_chain] + commands = [cmd.strip() + '\n' for cmd in commands] + self._last_subprocess_cmd = commands + return self._executor.subprocess_chain(subprocess_chain) + + def exec_non_blocking_subprocess(self, *args, **kwargs): + subprocess, log_file_descriptor, log_file_path = ( + self._executor.non_blocking_subprocess(*args, **kwargs)) + self._non_blocking_subprocesses.append((subprocess, log_file_descriptor)) + return subprocess, log_file_descriptor, log_file_path + + def start_subprocess(self, *args, **kwargs): + """Direct call to the subprocess.Popen. + + Args: + stdin: A file stream, subprocess.PIPE, or None to read stdin from. + stdout: A file stream or subprocess.PIPE to redirect stdout. + stderr: A file stream or subprocess.PIPE to redirect stderr. + *args: passed to subprocess.Popen + **kwargs: passed to subprocess.Popen; + optionally, quiet=True can be passed as a kwarg, + in which case stdout/stderr from the subprocess + will not be written to file. This kwarg will not + get passed to subprocess.Popen. + + Returns: + Tuple of (subprocess, boolean indicating if subprocess output needs to be + saved.) + """ + return self._executor.start_subprocess(*args, **kwargs) + + def get_running_subprocess_pids(self): + current_running_processes = [] + for subprocess, _ in self._non_blocking_subprocesses: + if subprocess.returncode is None: + current_running_processes.append(subprocess.pid) + return current_running_processes + + def kill_all_blocking_subprocesses(self): + """Killing all current blocking subprocesses.""" + msg = u'Last cmd run by the executor: {}'.format( + str(self._last_subprocess_cmd)) + + # Print all current running processes + self.exec_subprocess(['ps', '-efH']) + + for subprocess in self._executor.get_blocking_subprocesses(): + pid = subprocess.pid + if not psutil.pid_exists(pid): + logging.info('[Kill all blocking] Process %d started at %d and is no ' + 'longer running, skip', pid, subprocess.start) + continue + subprocess_info = psutil.Process(pid) + + logging.info('[Kill all blocking] Process %d, (%s) started at %d. ' + 'Communicating with process...', + pid, ' '.join(subprocess_info.cmdline()), subprocess.start) + stdout = None + stderr = None + try: + stdout, stderr = subprocess.communicate(timeout=_SUBPROCESS_TIMEOUT) + logging.info('[Kill all blocking] Process %d: exited with ' + 'returncode = %d.', pid, subprocess.returncode) + except timeout.TimeoutException as e: + # Due to a quirkiness of Python imports, we cannot catch + # subprocess42.TimeoutExpired directly, so we are catching its base + # class instead. However, we need to check for the attributes existence + # to make sure this is indeed subprocess42.TimeoutExpired. + if hasattr(e, 'output'): + stdout = e.output + if hasattr(e, 'stderr'): + stderr = e.stderr + logging.exception('Timeout (%d s) expired while waiting for the ' + 'process to finish. Killing process: %d', + _SUBPROCESS_TIMEOUT, pid) + subprocess.kill() + subprocess.wait() + finally: + if stdout: + logging.info('[Kill all blocking] Stdout size for process %d: %d.', + pid, len(stdout)) + if stderr: + logging.info('[Kill all blocking] Stderr size for process %d: %d.', + pid, len(stderr)) + + + def kill_all_non_blocking_subprocesses(self): + """Killing all current non-blocking subprocesses.""" + for subprocess, log_file_descriptor in self._non_blocking_subprocesses: + try: + subprocess.poll() + if subprocess.returncode is None: + logging.info('Killing process: %d', subprocess.pid) + subprocess.kill() + except: # pylint: disable=bare-except + logging.exception('Killing process failed.') + try: + logging.info('Closing file handler %d', log_file_descriptor) + os.close(log_file_descriptor) + except: # pylint: disable=bare-except + logging.exception('Closing file handler failed.') + + def exec_read_file(self, file_path): + return self._executor.read_file(file_path) + + def glob_files(self, glob_expr): + return self._executor.glob_files(glob_expr) + + def get_tmp_dir(self): + return self._executor.get_tmp_dir() + + def get_new_tmp_file(self): + return self._executor.get_new_tmp_file() + + def write_temp_file(self, contents: str): + """Write a text string to a temporary file.""" + return self._executor.write_temp_file(contents) + + def add_review(self, review): + """Adds |review| to the review comment. + + Args: + review: A dict with optional 'message' and 'comments' keys. + If 'message' is present, it will be added as a review comment. + If 'comments' is present, they will be added as file comments. + + 'message': A string to be added to the review message. + 'comments': A dict of comments in the form of + {<filename>: [{'line': <line #>, + 'message': <file comment>}, + {'line': <line #>, + 'message': <file comment>}, + ... + ], + <filename>: [...], + ... + } + Note that the 'line' field is optional, and if not + provided will result in a file-level comment instead + of a line-specific comment. + To add a comment to the commit message, use + '/COMMIT_MSG' as the filename. + """ + if 'message' in review: + assert isinstance(review['message'], str) + if self._annotator: + self._annotator.add_message(review['message']) + if 'comments' in review: + assert isinstance(review['comments'], dict) + if self._annotator: + self._annotator.add_comments(review['comments']) + + def get_cq_root(self): + """Returns the absolute path to the root of the CQ src.""" + return self._executor.get_cq_root() + + def get_gcs_dir(self): + """This directory will be uploaded to GCS when a recipe finishes.""" + return self._executor.get_gcs_dir() + + def set_build_property(self, name, value): + """Sets a build property for this step to return to the builder. + + Args: + name: property name (must be a string) + value: property value (must be JSON-serializable) + """ + assert isinstance(name, str) + assert value is not None + self._properties[name] = value + if self._annotator: + self._annotator.set_build_property(name, value) + + def halt_on_failure(self): + """Returns whether this step's failure should end the recipe.""" + return self._halt_on_failure + + def set_halt_on_failure(self): + """Forces step failure to end the recipe run.""" + self._halt_on_failure = True + + def get_name(self): + """Returns the name of this step, used for status display and flow control. + + Returns: + The name of this step. + """ + return self._name + + def get_timeout(self): + """Returns the length of time, in seconds, this step is allowed to run.""" + return self._timeout_secs + + def result_on_timeout(self): + """Returns the result value to use if this step times out.""" + return self._result_on_timeout + + def get_step_data(self, key, default=None): + """Retrieves step data from a previous step. + + Args: + key: Unique name the step data was indexed by. + default: Default return value if the key is not found. + + Returns: + Data associated with the given key. + """ + return self._data_manager.get_data(key, default=default) + + def add_step_data(self, key, value, replace=False): + """Provides step data for future steps. + + Args: + key: Unique name to index this step data. + value: Actual data to provide to future steps. + replace: whether |value| can replace previously stored data in |key|. + (defaults to False) + """ + self._data_manager.add_data(key, value, replace) + + def clear_project_info(self): + """Clears the project info to be reset in the next run.""" + return self._data_manager.clear_project_info() + + def contains_project(self, project): + """Boolean if the given project is included in the repo client.""" + return self._data_manager.contains_project(project) + + def ensure_project_info(self): + """Populate the project info.""" + return self._data_manager.ensure_project_info() + + def get_project_path(self, project): + """Returns the path to the project. + + Args: + project: The name of the project (usually patch_project) to lookup. + + Returns: + The relative path from the base checkout to the project. + """ + return self._data_manager.get_project_path(project) + + def get_project_path_lookup_table(self): + """Returns the project path lookup table.""" + return self._data_manager.get_project_path_lookup_table() + + def get_project_remote(self, project): + """Returns the remote for the project. + + Args: + project: The name of the project (usually patch_project) to lookup. + + Returns: + The remote for the project. + """ + return self._data_manager.get_project_remote(project) + + def get_project_revision(self, project): + """Returns the revision for the project. + + Args: + project: The name of the project (usually patch_project) to lookup. + + Returns: + The revision for the project. + """ + return self._data_manager.get_project_revision(project) + + def run(self) -> bool: + """Synchronously executes this step of the recipe. + + Returns: + Whether or not the step succeeded. + """ + raise NotImplementedError("Subclasses should have implemented this.") + + def add_mock_executions(self, generator): + """Adds mock executions to the generator.""" + + def _getcwd(self): + """Helper function to make it easy to mock os.getcwd() for tests.""" + return os.getcwd()
diff --git a/cq/scripts/slave/recipe/__init__.py b/cq/scripts/slave/recipe/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/cq/scripts/slave/recipe/__init__.py
diff --git a/cq/scripts/slave/recipe/cast_service_builder.py b/cq/scripts/slave/recipe/cast_service_builder.py new file mode 100644 index 0000000..528f4f6 --- /dev/null +++ b/cq/scripts/slave/recipe/cast_service_builder.py
@@ -0,0 +1,67 @@ +"""Recipe for building cast_service standalone executable.""" +import os + +from slave import base_recipe +from slave.step import gn_step +from slave.step import ninja_step +from slave.step import sanitizer_unittest_step + +BUILD_CONFIGS = { + 'cast_service_x64' : { + 'build_args_product': 'displayassistant_x64_eng', + 'build_args': 'enable_standalone_cast_service=true', + } +} + + + +def GetValidBuildNames(): + return list(BUILD_CONFIGS.keys()) + +def CreateRecipe(build_name: str, **kwargs): + config = BUILD_CONFIGS[build_name] + return CastServiceRecipe(build_name, config, **kwargs) + +class CastServiceRecipe(base_recipe.BaseRecipe): + """This recipe builds the cast_service standalone executable.""" + def __init__(self, build_name, config, **kwargs): + base_recipe.BaseRecipe.__init__( + self, enable_build_accelerator=True, **kwargs) + self._config = config + self._build_name = build_name + + def get_steps(self): + steps = [] + cwd = os.getcwd() + setup_steps = self.get_setup_steps() + chromium_root = setup_steps[0].get_project_path('chromium/src') + out_dir = os.path.join(chromium_root, + 'out_{}'.format(self._build_name), + 'release') + + gn_gen_step = gn_step.GnGenStep( + build_args_product=self._config['build_args_product'], + build_args=[self._config['build_args']], + out_dir=out_dir, + halt_on_failure=True, + cwd=cwd, + **self._step_kwargs + ) + steps.append(gn_gen_step) + gn_args_step = gn_step.GnArgsStep( + out_dir=out_dir, + cwd=cwd, + halt_on_failure=True, + **self._step_kwargs + ) + steps.append(gn_args_step) + + ninja_build_step = ninja_step.NinjaStep( + out_dir=out_dir, + target='cast_service', + cwd=cwd, + jobs=64, + halt_on_failure=True, + **self._step_kwargs) + steps.append(ninja_build_step) + return steps
diff --git a/cq/scripts/slave/recipe/cast_shell_guitar_e2e_test_runner.py b/cq/scripts/slave/recipe/cast_shell_guitar_e2e_test_runner.py new file mode 100644 index 0000000..fba8d41 --- /dev/null +++ b/cq/scripts/slave/recipe/cast_shell_guitar_e2e_test_runner.py
@@ -0,0 +1,77 @@ +# Lint as: python3 +"""Recipie for running oxygen guitar end to end tests for cast shells.""" + +import os +from slave import base_recipe +from slave.recipe import clang_builder +from slave.step import cast_shell_step +from slave.step import gcs_upload_step + +SHELL_TO_BUILD = 'audioassistant_grte_eng' +GCS_BUCKET = 'nest-virtualhome-release' +GCS_UPLOAD_PATH = ("google3/googledata/chrome/" + "dongle/test/cast_shell/" + "cast_shell_binary/chirp/") +CQ_BUILD_PREFIX = 'cq' + + +def GetValidBuildNames(): + return ['guitar_e2e_test_assistant'] + + +def CreateRecipe(build_name: str, **kwargs): + """Builds a recipe object.""" + if build_name != 'guitar_e2e_test_assistant': + raise base_recipe.BuildNameNotSupportedError(build_name) + return CastShellGuitarE2ERecipe(**kwargs) + + +class CastShellGuitarE2ERecipe(base_recipe.BaseRecipe): + """Recipe to run e2e tests on a repository.""" + + def __init__(self, + **kwargs): + super().__init__( + enable_build_accelerator=True, + **kwargs) + + def get_steps(self): + build_shell_config = clang_builder.BUILD_CONFIGS['audioassistant_grte_eng'] + + build_branding = build_shell_config.get('build_branding', None) + build_arch = build_shell_config.get('build_arch', None) + build_product = build_shell_config.get('build_product', None) + build_flavor = build_shell_config.get('build_flavor', None) + enable_assistant = build_shell_config.get('enable_assistant', False) + build_args_official = build_shell_config.get('build_args_official', None) + grte_compatible = build_shell_config.get('grte_compatible', False) + build_args_product = build_shell_config.get('build_args_product', None) + + steps = [] + + cast_shell_build_step = cast_shell_step.CastShellStep( + build_branding, build_arch, build_product, + build_flavor, enable_assistant, + build_args_official=build_args_official, + code_coverage=False, grte_compatible=grte_compatible, + build_args_product=build_args_product, halt_on_failure=True, + sanitizer=None, archive_to_tmp=False, skip_create_zip=True, + strip_binaries=True, **self._step_kwargs) + steps.append(cast_shell_build_step) + outdir = cast_shell_build_step.out_dir + outdir = os.path.basename(outdir) + print('Out Dir', outdir) + gcs_upload_file_step = gcs_upload_step.GcsUploadStep( + gcs_bucket=GCS_BUCKET, + gcs_path=GCS_UPLOAD_PATH + + CQ_BUILD_PREFIX + + self.build_number + "_" + + str(cast_shell_build_step.patchset) + "/", + src_path=os.path.join( + cast_shell_build_step.get_gcs_dir(), + outdir) + "/", + name='upload to nest-virtualhome-release', + **self._step_kwargs) + steps.append(gcs_upload_file_step) + + return steps
diff --git a/cq/scripts/slave/recipe/catabuilder_e2e_mock.py b/cq/scripts/slave/recipe/catabuilder_e2e_mock.py new file mode 100644 index 0000000..dc243d2 --- /dev/null +++ b/cq/scripts/slave/recipe/catabuilder_e2e_mock.py
@@ -0,0 +1,83 @@ +"""Recipe for Catabuilder E2E tests.""" +import enum +import json +import logging +import os +from typing import Dict, List, Union + +from slave import base_recipe +from slave import base_step + + +@enum.unique +class Status(enum.Enum): + PASS = 'PASSES' + FAIL = 'FAILS' + + +_RESULTS_FILE = 'results.json' + + +def GetValidBuildNames() -> List[str]: + return [ + 'catabuilder-e2e-mock-1', + 'catabuilder-e2e-mock-2', + 'catabuilder-e2e-mock-3', + ] + + +def CreateRecipe(build_name: str, **kwargs) -> 'CatabuilderE2EMockRecipe': + """Defines how this recipe gets built.""" + return CatabuilderE2EMockRecipe(build_name, **kwargs) + + +class CatabuilderE2EMockRecipe(base_recipe.BaseRecipe): + """Recipe to execute e2e fake build.""" + + def __init__(self, builder_name, **kwargs): + base_recipe.BaseRecipe.__init__(self, **kwargs) + self._builder_name = builder_name + + def get_steps(self) -> List['CatabuilderE2EMockStep']: + return [ + CatabuilderE2EMockStep( + builder_name=self._builder_name, **self._step_kwargs), + ] + + +class CatabuilderE2EMockStep(base_step.BaseStep): + """Step that does the verification of the expected CB behavior.""" + + def __init__(self, builder_name, **kwargs): + base_step.BaseStep.__init__(self, name='e2e_mock', **kwargs) + self._builder_name = builder_name + + def run(self) -> bool: + results = self._process_instructions() + self._save_results_to_gcs_dir(results) + outcome = self.get_property('outcome') + self.set_build_property('e2e_tests', 'yes') + if outcome == Status.PASS.value: + return True + if outcome == Status.FAIL.value: + return False + raise ValueError('Status must be set in the "outcome" property.') + + def _process_instructions(self) -> Dict[str, Union[str, int, bool]]: + instruction_project = self.get_property('project') + project_path = self.get_project_path(instruction_project) + instruction_filename = self.get_property('instructions_file') + instruction_path = os.path.join(project_path, instruction_filename) + logging.info('Opening instruction file: %s', instruction_path) + with open(instruction_path, 'r') as instruction_file: + instructions = json.load(instruction_file) + assert isinstance(instructions, dict) + logging.info('Instruction file content: %s', instructions) + return instructions + + def _save_results_to_gcs_dir(self, results) -> None: + gcs_dir = self._executor.get_gcs_dir() + results_path = os.path.join(gcs_dir, _RESULTS_FILE) + with open(results_path, 'w') as results_file: + logging.info('Writing results to: %s', results_path) + json.dump(results, results_file, indent=2, sort_keys=True)
diff --git a/cq/scripts/slave/recipe/catatester_binaries_runner.py b/cq/scripts/slave/recipe/catatester_binaries_runner.py new file mode 100644 index 0000000..4ef2a4e --- /dev/null +++ b/cq/scripts/slave/recipe/catatester_binaries_runner.py
@@ -0,0 +1,129 @@ +"""Recipe for generating and testing test binaries.""" +import os +from typing import Dict, Union + +from slave import base_recipe +from slave.step import catatester_binaries_step +from slave.step import cipd_upload_step +from slave.step import py_env_setup_step +from slave.step import py_test_step +from slave.test import test_generator +from tools import subprocess42 + +_CIPD_PACKAGE_ROOT = os.path.join('lab_system', 'cipd_packages') + + +# (b/149845115) Current lab environment can only support the below libc version +TARGETED_LIBC_VERSION = '2.28' + +BUILD_CONFIGS = { + 'catatester_binaries': { + 'py3': False, + 'requirements_file_name': 'requirements.txt', + }, + 'py3_catatester_binaries': { + 'py3': True, + 'requirements_file_name': 'requirements3.txt', + }, +} + +Config = Dict[str, Union[bool, str]] + + +def GetValidBuildNames(): + return list(BUILD_CONFIGS.keys()) + + +def CreateRecipe(build_name: str, eureka_root: str, **kwargs): + if build_name in BUILD_CONFIGS: + return CatatesterBinariesRecipe( + config=BUILD_CONFIGS[build_name], eureka_root=eureka_root, **kwargs) + raise base_recipe.BuildNameNotSupportedError(build_name) + + +class CatatesterBinariesRecipe(base_recipe.BaseRecipe): + """Recipe to generate and test Catatester binaries.""" + + def __init__(self, config: Config, eureka_root: str, **kwargs): + base_recipe.BaseRecipe.__init__(self, eureka_root=eureka_root, **kwargs) + self._py3 = config.get('py3', False) + self._requirements_file_name = config.get('requirements_file_name', + 'requirements.txt') + + # pylint: disable=method-hidden + def _supported_libc_found(self): + """Return True if supported version is found; otherwise, False.""" + short_timeout_secs = 5 + cmd = ['ldd', '--version'] + output, _, returncode, _ = subprocess42.call_with_timeout( + cmd, timeout=short_timeout_secs, text=True) + if returncode != 0: + return False + return TARGETED_LIBC_VERSION in output + + def get_steps(self): + requirements_project = 'test' + requirements_path = os.path.join('lab_system', self._requirements_file_name) + catatester_python_packages = 'team-catatester/python_packages' + + test_regex = '.*test_binaries.py$' + test_timeout = 60 * 15 # 15 minutes + additional_import_paths = [ + self._eureka_root / path for path in ( + 'builder/masters', + 'builder/masters/src', + 'chromium/src/third_party/catapult/telemetry', + 'chromium/src/chromecast/internal', + 'chromium/src/chromecast/tools', + 'continuous-tests', + 'continuous-tests/cq/scripts', + 'test', + 'testing/external/autotest', + 'testing/external/chromite', + 'testing/sprockets', + ) + ] + steps = [ + py_env_setup_step.PyEnvSetupStep( + additional_import_paths=additional_import_paths, + requirements_project=requirements_project, + requirements_path=requirements_path, + local_packages_dir=catatester_python_packages, + py3=self._py3, + **self._step_kwargs), + catatester_binaries_step.CatatesterBinariesBuildStep( + halt_on_failure=True, py3=self._py3, **self._step_kwargs), + py_test_step.PyTestStep( + test_file_filter_regex=test_regex, + timeout=test_timeout, + project='test', + halt_on_failure=True, + **self._step_kwargs), + ] + + if self._supported_libc_found(): + tool_step = self._GetCIPDUploadStep( + os.path.join(_CIPD_PACKAGE_ROOT, 'tool_binaries.yaml'), + 'Upload tool binaries') + test_step = self._GetCIPDUploadStep( + os.path.join(_CIPD_PACKAGE_ROOT, 'test_binaries.yaml'), + 'Upload test binaries', + verification_timeout='30m0s') + steps.extend([tool_step, test_step]) + + # Temporary single package upload. See b/118714546. + standalone_step = self._GetCIPDUploadStep( + os.path.join(_CIPD_PACKAGE_ROOT, 'standalone_binary.yaml'), + 'Upload standalone binary') + steps.append(standalone_step) + + return steps + + def _GetCIPDUploadStep(self, pkg_def, step_name, verification_timeout=None): + """Helper to generate a CIPDUploadStep.""" + return cipd_upload_step.CIPDUploadStep( + os.path.join('test', pkg_def), + verification_timeout=verification_timeout, + step_name=step_name, + **self._step_kwargs) +
diff --git a/cq/scripts/slave/recipe/ccstudio_builder.py b/cq/scripts/slave/recipe/ccstudio_builder.py new file mode 100644 index 0000000..d532e75 --- /dev/null +++ b/cq/scripts/slave/recipe/ccstudio_builder.py
@@ -0,0 +1,45 @@ +"""Recipe for running a CCStudio build on the given device.""" +import os + +from slave import base_recipe +from slave.step import ccstudio_step +from slave.step import py_env_setup_step + + + +def GetValidBuildNames(): + """Get all valid build names.""" + return ['abbey-eng', 'abbey-user'] + + +def CreateRecipe(build_name: str, **kwargs): + """Build a recipe object.""" + return CCStudioRecipe(build_name, **kwargs) + + +class CCStudioRecipe(base_recipe.BaseRecipe): + """Recipe to run CCStudio build.""" + + def __init__(self, build_name, **kwargs): + prop = kwargs.get('properties', {}) + prop['skip_gclient'] = True + if 'properties' not in kwargs: + kwargs['properties'] = prop + base_recipe.BaseRecipe.__init__(self, **kwargs) + self._build_name = build_name + + def get_steps(self): + requirements_project = 'abbey' + requirements_path = os.path.join('build', 'requirements.txt') + abbey_python_packages = 'team-abbey/python_packages' + return [ + py_env_setup_step.PyEnvSetupStep( + local_packages_dir=abbey_python_packages, + py3=True, + requirements_path=requirements_path, + requirements_project=requirements_project, + **self._step_kwargs), + ccstudio_step.CCStudioStep(self._build_name, + **self._step_kwargs), + ] +
diff --git a/cq/scripts/slave/recipe/cipd_package_upload.py b/cq/scripts/slave/recipe/cipd_package_upload.py new file mode 100644 index 0000000..b62fefc --- /dev/null +++ b/cq/scripts/slave/recipe/cipd_package_upload.py
@@ -0,0 +1,84 @@ +"""Recipe for uploading test source code to CIPD.""" + +from __future__ import absolute_import +import os + +from slave import base_recipe +from slave.step import cipd_upload_step + + +# _BUILD_CONFIG entries are keyed by build name. Config dicts must include +# 'pkg_project' and 'pkg_def'. If version is supplied and True, then a version +# tag will be added with the format 'version:<build-number>'. +_BUILD_CONFIG = { + 'catatester_devicemap_upload': { + 'pkg_project': 'continuous-tests', + 'pkg_def': 'catatester/devicemap/cipd.yaml', + 'refs': ['live', 'staging'], + }, + 'catatester_puppet_upload': { + 'pkg_project': 'continuous-tests', + 'pkg_def': 'catatester/puppet_cipd_pkg.yaml', + 'refs': ['staging'], + }, + 'continuous_tests_files_upload': { + 'pkg_project': 'continuous-tests', + 'pkg_def': 'essential_pkg.yaml', + 'refs': ['live', 'staging'], + }, +} + + +def GetValidBuildNames(): + return list(_BUILD_CONFIG.keys()) + + +def CreateRecipe(build_name: str, **kwargs): + """Creates a recipe based on build info stored in _BUILD_CONFIG. + + Args: + build_name: The name of the build. + + Raises: + ValueError if required info isn't included in config. + """ + build_cfg = _BUILD_CONFIG[build_name] + return CIPDPackageUploadRecipe( + build_cfg['pkg_project'], + build_cfg['pkg_def'], + refs=build_cfg.get('refs'), + include_version=build_cfg.get('version'), + **kwargs) + + +class CIPDPackageUploadRecipe(base_recipe.BaseRecipe): + """Uploads the designated test source files to CIPD.""" + + def __init__(self, pkg_project, pkg_def, refs=None, tags=None, + include_version=False, **kwargs): + """Constructor. + + Args: + pkg_project: The project containing the pkg_def file. + pkg_def: The relative path to the pkg_def file, from the project root. + refs: A list of refs to be assigned to the uploaded cipd package. + tags: A dict of tags to be assigned to the uploaded cipd package. + """ + base_recipe.BaseRecipe.__init__(self, **kwargs) + self._pkg_project = pkg_project + self._pkg_def = pkg_def + self._refs = refs + self._tags = tags or {} + + if include_version: + self._tags['version'] = self.build_number + + def get_steps(self): + return [ + cipd_upload_step.CIPDUploadStep( + os.path.join(self._pkg_project, self._pkg_def), + refs=self._refs, + tags=self._tags, + **self._step_kwargs)] + +
diff --git a/cq/scripts/slave/recipe/clang_builder.py b/cq/scripts/slave/recipe/clang_builder.py new file mode 100644 index 0000000..542367a --- /dev/null +++ b/cq/scripts/slave/recipe/clang_builder.py
@@ -0,0 +1,656 @@ +"""Recipe for running a clang-based cast_shell build on the given patch.""" +import pathlib + +from cgi import test +from slave import base_recipe +from slave import base_step +from slave.step import cast_shell_step +from slave.step import code_coverage_step +from slave.step import landmine_step +from slave.step import make_clean_step +from slave.step import unittest_step +from slave.test import test_generator + +BUILD_CONFIGS = { + # TODO(b/73231972) remove after migration to atv_arm_eng + 'arm_androidtv_debug': { + 'build_branding': 'chrome', + 'build_args_product': 'atv_arm_eng', + 'build_args_official': False, + 'build_product': 'atv', + 'build_flavor': 'Debug', + 'build_arch': 'arm', + 'run_gtests': False, + }, + 'asan_x64_eng': { + 'build_args_product': 'asan_x64_eng', + 'build_args_official': False, + # TODO(b/148885147) Remove params below + 'build_branding': 'chrome', + 'build_product': 'chromecast', + 'build_flavor': 'Eng', + 'build_arch': 'clang', + 'sanitizer': 'asan', + }, + # Replacement of content_shell_androidtv_arm64_debug_gn + 'atv_arm64_eng': { + 'build_args_product': 'atv_arm64_eng', + 'build_args_official': False, + 'run_gtests': False, + }, + 'atv_arm64_emulator_eng': { + 'build_args_product': 'atv_arm64_emulator_eng', + 'build_args_official': False, + 'run_gtests': False, + }, + # Replacement of content_shell_androidtv_arm64_internal_gn + 'atv_arm64_user': { + 'build_args_product': 'atv_arm64_user', + 'build_args_official': True, + 'run_gtests': False, + }, + # Replacement of content_shell_androidtv_arm_debug_gn, arm_androidtv_debug + 'atv_arm_eng': { + 'build_args_product': 'atv_arm_eng', + 'build_args_official': False, + 'run_gtests': False, + }, + # Replacement of content_shell_androidtv_arm_internal_gn + 'atv_arm_user': { + 'build_args_product': 'atv_arm_user', + 'build_args_official': True, + 'run_gtests': False, + }, + # Replacement of x86_androidtv_shell + 'atv_x86_emulator_eng': { + 'build_args_product': 'atv_x86_emulator_eng', + 'build_args_official': False, + 'run_gtests': False, + }, + # Replacement of content_shell_androidtv_x86_debug_gn + 'atv_x86_eng': { + 'build_args_product': 'atv_x86_eng', + 'build_args_official': False, + 'run_gtests': False, + }, + # Replacement of content_shell_androidtv_x86_internal_gn + 'atv_x86_user': { + 'build_args_product': 'atv_x86_user', + 'build_args_official': True, + 'run_gtests': False, + }, + 'atv_x64_emulator_eng': { + 'build_args_product': 'atv_x64_emulator_eng', + 'build_args_official': False, + 'run_gtests': False, + }, + 'atv_x64_eng': { + 'build_args_product': 'atv_x64_eng', + 'build_args_official': False, + 'run_gtests': False, + }, + 'atv_x64_user': { + 'build_args_product': 'atv_x64_user', + 'build_args_official': True, + 'run_gtests': False, + }, + # Replacement of content_shell_grte_audio + 'audio_grte_eng': { + 'build_args_product': 'audio_grte_eng', + 'build_args_official': False, + 'build_gtests': False, + }, + # Replacement of content_shell_clang_audio_internal_gn + 'audio_x64_eng': { + 'build_args_product': 'audio_x64_eng', + 'build_args_official': False, + 'timeout_secs_run_gtest': 1 * 60 * 60, # Limit each test step by 1h + # TODO(b/148885147) Remove params below + 'build_branding': 'chrome', + 'build_product': 'audio', + 'build_flavor': 'Debug', + 'build_arch': 'clang', + }, + # Replacement of content_shell_clang_audio_gn + 'audio_x64_user': { + 'build_args_product': 'audio_x64_user', + 'build_args_official': False, + 'timeout_secs_run_gtest': 1 * 60 * 60, # Limit each test step by 1h + # TODO(b/148885147) Remove params below + 'build_branding': 'chromium', + 'build_product': 'audio', + 'build_flavor': 'Debug', + 'build_arch': 'clang', + }, + # Replacement of content_shell_grte_chirp + 'audioassistant_grte_eng': { + 'build_args_product': 'audioassistant_grte_eng', + 'build_args_official': False, + 'build_gtests': False, + }, + # Replacement of content_shell_x86_chirp, x86_clang_audio_chirp + 'audioassistant_x64_eng': { + 'build_args_product': 'audioassistant_x64_eng', + 'build_args_official': False, + 'timeout_secs_run_gtest': 1 * 60 * 60, # Limit each test step by 1h + # TODO(b/145840052): Remove once the build is fast enough. + 'timeout_secs_build_gtests': 5 * 60 * 60, + # TODO(b/148885147) Remove params below + 'build_branding': 'chrome', + 'build_product': 'audio', + 'build_flavor': 'Debug', + 'build_arch': 'clang', + 'enable_assistant': True, + }, + # Replacement of content_shell_cube_arm_debug, arm_cube_debug + 'cube_arm_eng': { + 'build_args_product': 'cube_arm_eng', + 'build_args_official': False, + 'run_gtests': False, + }, + # Replacement of content_shell_cube_arm_internal, arm_cube_internal + 'cube_arm_user': { + 'build_args_product': 'cube_arm_user', + 'build_args_official': True, + 'run_gtests': False, + }, + # Replacement of content_shell_cube_x86_debug, x86_cube_debug + 'cube_x64_eng': { + 'build_args_product': 'cube_x64_eng', + 'build_args_official': False, + 'run_gtests': False, + }, + # Replacement of content_shell_cube_x86_internal, x86_cube_internal + 'cube_x64_user': { + 'build_args_product': 'cube_x64_user', + 'build_args_official': True, + 'run_gtests': False, + }, + # Replacement of grte_manhattan_camera + 'displayassistant_grte_camera_eng': { + 'build_args_product': 'displayassistant_grte_camera_eng', + 'build_args_official': False, + 'build_gtests': False, + }, + # Replacement of content_shell_grte_manhattan + 'displayassistant_grte_eng': { + 'build_args_product': 'displayassistant_grte_eng', + 'build_args_official': False, + 'build_gtests': False, + }, + # Replacement of grte_opal_camera + 'displayassistant_grte_opal_camera_eng': { + 'build_args_product': 'displayassistant_grte_opal_camera_eng', + 'build_args_official': False, + 'build_gtests': False, + }, + # Replacement of grte_opal + 'displayassistant_grte_opal_eng': { + 'build_args_product': 'displayassistant_grte_opal_eng', + 'build_args_official': False, + 'build_gtests': False, + }, + # Replacement of content_shell_x86_manhattan, x86_manhattan + 'displayassistant_x64_eng': { + 'build_args_product': 'displayassistant_x64_eng', + 'build_args_official': False, + 'timeout_secs_run_gtest': 1 * 60 * 60, # Limit each test step by 1h + # TODO(b/145840052): Remove once the build is fast enough. + 'timeout_secs_build_gtests': 5 * 60 * 60, + # TODO(b/148885147) Remove params below + 'build_branding': 'chrome', + 'build_product': 'display', + 'build_flavor': 'Debug', + 'build_arch': 'clang', + 'enable_assistant': True, + }, + 'gabbro_arm_eng': { + 'build_args_product': 'gabbro_arm_debug', + 'build_args_official': False, + 'run_gtests': False, + }, + 'gabbro_arm_user': { + 'build_args_product': 'gabbro_arm_internal', + 'build_args_official': True, + 'run_gtests': False, + }, + 'gabbro_x64_eng': { + 'build_args_product': 'gabbro_x86_debug', + 'build_args_official': False, + 'run_gtests': False, + }, + 'gabbro_x64_user': { + 'build_args_product': 'gabbro_x86_internal', + 'build_args_official': True, + 'run_gtests': False, + }, + 'grte_opal_selina': { + 'build_branding': 'chrome', + 'build_args_product': 'grte_opal_selina', + 'build_args_official': False, + 'build_product': 'display', + 'build_flavor': 'Eng', + 'build_arch': 'x86', + 'enable_assistant': True, + 'build_gtests': False, + }, + # Replacement of content_shell_desktop_msan, memory_sanitizer + 'msan_x64_eng': { + 'build_args_product': 'msan_x64_eng', + 'build_args_official': False, + 'timeout_secs_run_gtest': 1 * 60 * 60, # Limit each test step by 1h + # TODO(b/148885147) Remove params below + 'build_branding': 'chrome', + 'build_product': 'chromecast', + 'build_flavor': 'Eng', + 'build_arch': 'clang', + 'sanitizer': 'msan', + }, + # Replacement of content_shell_soba_arm_debug_gn, arm_soba_debug + 'soba_arm_eng': { + 'build_args_product': 'soba_arm_eng', + 'build_args_official': False, + 'run_gtests': False, + 'check_android_license': True, + }, + # Replacement of content_shell_soba_arm_noassist_debug_gn + 'soba_arm_noassist_eng': { + 'build_args_product': 'soba_arm_noassist_eng', + 'build_args_official': False, + 'run_gtests': False, + 'check_android_license': True, + }, + # Replacement of content_shell_soba_arm_noassist_internal_gn + 'soba_arm_noassist_user': { + 'build_args_product': 'soba_arm_noassist_user', + 'build_args_official': True, + 'run_gtests': False, + 'check_android_license': True, + }, + # Replacement of content_shell_soba_arm_internal_gn + 'soba_arm_user': { + 'build_args_product': 'soba_arm_user', + 'build_args_official': True, + 'run_gtests': False, + 'check_android_license': True, + }, + # Replacement of content_shell_soba_x86_debug_gn, x86_soba_debug + 'soba_x64_eng': { + 'build_args_product': 'soba_x64_eng', + 'build_args_official': False, + 'run_gtests': False, + 'check_android_license': True, + }, + # Replacement of thread_sanitizer + 'tsan_x64_eng': { + 'build_args_product': 'tsan_x64_eng', + 'build_args_official': False, + }, + # Replacement of content_shell_udon_arm_debug_gn, arm_udon_debug + 'udon_arm_eng': { + 'build_args_product': 'udon_arm_eng', + 'build_args_official': False, + 'run_gtests': False, + }, + # Replacement of content_shell_udon_arm_internal_gn + 'udon_arm_user': { + 'build_args_product': 'udon_arm_user', + 'build_args_official': True, + 'run_gtests': False, + }, + # Replacement of content_shell_udon_x86_debug_gn, x86_udon_debug + 'udon_x64_eng': { + 'build_args_product': 'udon_x64_eng', + 'build_args_official': False, + 'run_gtests': False, + }, + # Replacement of content_shell_udon_x86_internal_gn + 'udon_x64_user': { + 'build_args_product': 'udon_x64_user', + 'build_args_official': True, + 'run_gtests': False, + }, + # Replacement of x86_udon_assistant_debug + 'udonassistant_x64_eng': { + 'build_args_product': 'udonassistant_x64_eng', + 'build_args_official': False, + 'run_gtests': False, + }, + # Replacement of content_shell_grte_video + 'video_grte_eng': { + 'build_args_product': 'video_grte_eng', + 'build_args_official': False, + 'build_gtests': False, + }, + # CWR, x64, release + 'cwr_x64-user': { + 'build_args_product': 'video_cwr_x64_user', + 'build_args_official': False, + 'build_gtests': False, + 'build_target': 'chromecast/internal/build/packaging:cwr_package_cksum', + }, + # CWR, x64, debug + 'cwr_x64-eng': { + 'build_args_product': 'video_cwr_x64_eng', + 'build_args_official': False, + 'build_gtests': False, + 'build_target': 'chromecast/internal/build/packaging:cwr_package_cksum', + }, + # CWR for RaspberryPi, ARMv7a, release + 'cwr_rpix_armv7a-user': { + 'build_args_product': 'video_cwr_rpix_armv7a_user', + 'build_args_official': False, + 'build_gtests': False, + 'build_target': 'chromecast/internal/build/packaging:cwr_package_cksum', + 'enable_build_accelerator': False, + }, + # CWR for RaspberryPi, ARMv7a, debug + 'cwr_rpix_armv7a-eng': { + 'build_args_product': 'video_cwr_rpix_armv7a_eng', + 'build_args_official': False, + 'build_gtests': False, + 'build_target': 'chromecast/internal/build/packaging:cwr_package_cksum', + 'enable_build_accelerator': False, + }, + # CWR for WebOS, ARMv7a softfp, release + 'cwr_webos_arm-user': { + 'build_args_product': 'video_cwr_webos_arm_user', + 'build_args_official': False, + 'build_gtests': False, + 'build_target': 'chromecast/internal/build/packaging:cwr_package_cksum', + 'enable_build_accelerator': False, + }, + # CWR for WebOS, ARMv7a softfp, debug + 'cwr_webos_arm-eng': { + 'build_args_product': 'video_cwr_webos_arm_eng', + 'build_args_official': False, + 'build_gtests': False, + 'build_target': 'chromecast/internal/build/packaging:cwr_package_cksum', + 'enable_build_accelerator': False, + }, + # CWR for WebOS24, ARMv7a softfp, release + 'cwr_webos24_arm-user': { + 'build_args_product': 'video_cwr_webos24_arm_user', + 'build_args_official': False, + 'build_gtests': False, + 'build_target': 'chromecast/internal/build/packaging:cwr_package_cksum', + 'enable_build_accelerator': False, + }, + # CWR for WebOS24, ARMv7a softfp, debug + 'cwr_webos24_arm-eng': { + 'build_args_product': 'video_cwr_webos24_arm_eng', + 'build_args_official': False, + 'build_gtests': False, + 'build_target': 'chromecast/internal/build/packaging:cwr_package_cksum', + 'enable_build_accelerator': False, + }, + # CWR for CrOS, ARMv7a hard, release + 'cwr_cros_arm-user': { + 'build_args_product': 'video_cwr_cros_arm_user', + 'build_args_official': False, + 'build_gtests': False, + 'build_target': 'chromecast/internal/build/packaging:cwr_package_cksum', + 'enable_build_accelerator': False, + }, + # CWR for CrOS, ARMv7a hard, debug + 'cwr_cros_arm-eng': { + 'build_args_product': 'video_cwr_cros_arm_eng', + 'build_args_official': False, + 'build_gtests': False, + 'build_target': 'chromecast/internal/build/packaging:cwr_package_cksum', + 'enable_build_accelerator': False, + }, + # Replacement of x86_clang_internal_absolute_code_coverage + 'video_x64_absolute_code_coverage_eng': { + 'build_branding': 'chrome', + 'build_args_product': 'video_x64_eng', + 'build_args_official': False, + 'build_flavor': 'Debug', # Must be Debug for code coverage to work. + 'build_product': 'chromecast', + 'build_arch': 'clang', + 'code_coverage': True, + 'report_to_zoss': True, + 'absolute_coverage': True, + 'timeout_secs_build_gtests': 5 * 60 * 60, + }, + # Replacement of content_shell_clang_internal_gn, x86_clang_internal + 'video_x64_eng': { + 'build_args_product': 'video_x64_eng', + 'build_args_official': False, + 'timeout_secs_run_gtest': 1 * 60 * 60, # Limit each test step by 1h + # TODO(b/148885147) Remove params below + 'build_branding': 'chrome', + 'build_product': 'chromecast', + 'build_flavor': 'Debug', # Must be Debug for code coverage to work. + 'build_arch': 'clang', + 'code_coverage': False, # TODO(b/33835295): Temporarily disable since + # code coverage is often causing builds to take + # an extra hour to complete and not actually + # producing useful coverage results. + }, + # Replacement of content_shell_unfork_clang_gn + 'video_x64_user': { + 'build_args_product': 'video_x64_user', + 'build_args_official': False, + 'timeout_secs_run_gtest': 1 * 60 * 60, # Limit each test step by 1h + # TODO(b/148885147) Remove params below + 'build_branding': 'chromium', + 'build_product': 'chromecast', + 'build_flavor': 'Debug', # Must be Debug for code coverage to work. + 'build_arch': 'clang', + 'code_coverage': False, # TODO(b/33835295): Temporarily disable since + # code coverage is often causing builds to take + # an extra hour to complete and not actually + # producing useful coverage results. + }, + # TODO(b/73288720) remove after migration to atv_x64_emulator_eng + 'x86_androidtv_shell': { + 'build_branding': 'chrome', + 'build_args_product': 'atv_x64_emulator_eng', + 'build_args_official': False, + 'build_product': 'atv', + 'build_flavor': 'Debug', + 'build_arch': 'x86', + 'run_gtests': False, + }, + # This build is only for libassistant code coverage experiment. + # TODO(mengdi): make sure this build only build and run libassistant + # unittests with --whitelisted_tests. + 'x86_clang_audio_chirp_libassistant_code_coverage': { + 'build_branding': 'chrome', + 'build_args_product': 'audioassistant_x64_eng', + 'build_args_official': False, + 'build_product': 'audio', + 'build_flavor': 'Debug', + 'build_arch': 'clang', + 'enable_assistant': True, + 'absolute_coverage': True, + 'code_coverage': True, + + # TODO(b/145840052): Remove once the build is fast enough. + 'timeout_secs_build_gtests': 5 * 60 * 60, + }, + # TODO(b/73288720) remove after migration to + # video_x64_absolute_code_coverage_eng + 'x86_clang_internal_absolute_code_coverage': { + 'build_branding': 'chrome', + 'build_args_product': 'displayassistant_x64_eng', + 'build_args_official': False, + 'build_product': 'chromecast', + 'build_flavor': 'Debug', + 'build_arch': 'clang', + 'code_coverage': True, + 'absolute_coverage': True, + 'enable_assistant': True, + + # TODO(b/145840052): Remove once the build is fast enough. + 'timeout_secs_build_gtests': 5 * 60 * 60, + }, + # TODO(b/73231972) Not used in CQ, to be removed + 'x86_clang_internal_incremental_code_coverage': { + 'build_branding': 'chrome', + 'build_args_product': 'video_x64_eng', + 'build_args_official': False, + 'build_product': 'chromecast', + 'build_flavor': 'Debug', + 'build_arch': 'clang', + 'code_coverage': True, + + # TODO(b/145840052): Remove once the build is fast enough. + 'timeout_secs_build_gtests': 5 * 60 * 60, + }, +} + + +def GetValidBuildNames(): + return list(BUILD_CONFIGS.keys()) + + +def CreateRecipe(build_name: str, **kwargs): + """Builds a recipe object.""" + config = BUILD_CONFIGS[build_name] + # Extracts default_properties from build config and adds it to the overall + # properties in kwargs. + default_properties = config.get('default_properties', {}) + kwargs['properties'] = dict( + list(default_properties.items()) + + list(kwargs.get('properties', {}).items())) + return ClangRecipe(config, **kwargs) + + +class ClangRecipe(base_recipe.BaseRecipe): + """Recipe to run a clang-based cast-shell build.""" + + def __init__(self, config, **kwargs): + base_recipe.BaseRecipe.__init__( + self, + check_android_license=config.get('check_android_license', False), + enable_build_accelerator=config.get('enable_build_accelerator', True), + **kwargs) + self._config = config + self._properties = kwargs.get('properties', {}) + + def get_steps(self): + build_branding = self._config.get('build_branding', None) + build_args_product = self._config['build_args_product'] + build_product = self._config.get('build_product', None) + build_args_official = self._config.get('build_args_official', None) + build_arch = self._config.get('build_arch', None) + build_flavor = self._config.get('build_flavor', None) + build_gtests = self._config.get('build_gtests', True) + run_gtests = self._config.get('run_gtests', True) + code_coverage = self._config.get('code_coverage', False) + report_to_zoss = self._config.get('report_to_zoss', False) + absolute_coverage = self._config.get('absolute_coverage', False) + enable_assistant = self._config.get('enable_assistant', False) + grte_compatible = self._config.get('grte_compatible', False) + sanitizer = self._config.get('sanitizer', None) + build_target = self._config.get('build_target', None) + + steps = [] + + if self.build_system == 'catabuilder': + steps.append(make_clean_step.MakeCleanStep(**self._step_kwargs)) + else: + steps += [ + landmine_step.LandmineStep(**self._step_kwargs), + ] + + # Sanitizers work by running the unittests. No need to waste time + # building cast shell by itself. + # Always build on CB to have an option of manual debug + # out_dir generated by CastShellStep also used by RunCoverageCommandStep. + if sanitizer is None or self.build_system == 'catabuilder': + steps += [ + cast_shell_step.CastShellStep( + build_branding, + build_arch, + build_product, + build_flavor, + enable_assistant, + build_args_official=build_args_official, + code_coverage=code_coverage, + grte_compatible=grte_compatible, + build_args_product=build_args_product, + halt_on_failure=True, + sanitizer=sanitizer, + build_target=build_target, + **self._step_kwargs), + ] + + if build_gtests: + steps += [ + unittest_step.BuildAffectedUnitTestsStep( + build_branding, + build_arch, + build_product, + build_flavor, + enable_assistant, + build_args_official=build_args_official, + sanitizer=sanitizer, + code_coverage=code_coverage, + absolute_coverage=absolute_coverage, + build_args_product=build_args_product, + halt_on_failure=True, + timeout_secs=self._config.get('timeout_secs_build_gtests', + base_step.STEP_MAX_TIME_SECONDS), + **self._step_kwargs), + ] + + # TODO(maasen): Move issue & patchset to properties on the base_step + # and generate this URL there. + if build_gtests and run_gtests and not code_coverage: + if 'issue' in self._properties and 'patchset' in self._properties: + report_url = 'http://go/cast-cq/coverage/{0}/{1}'.format( + self._properties['issue'], self._properties['patchset']) + else: + report_url = '' + + steps += [ + unittest_step.RunAffectedUnitTestsStep( + build_branding, + build_arch, + build_product, + build_flavor, + report_url, + steps, + sanitizer=sanitizer, + build_args_product=build_args_product, + build_args_official=build_args_official, + enable_network_service=True, + timeout_secs=self._config.get('timeout_secs_run_gtest', + base_step.STEP_MAX_TIME_SECONDS), + **self._step_kwargs), + ] + + elif code_coverage: + + if report_to_zoss: + report_format = 'lcov' + ignore_filename_regex = '.*/gen/.*|.*/third_party/.*' + else: + report_format = None + ignore_filename_regex = None + + coverage_step = code_coverage_step.RunCoverageCommandStep( + build_branding, + build_arch, + build_product, + build_flavor, + sanitizer=sanitizer, + build_args_product=build_args_product, + build_args_official=build_args_official, + ignore_filename_regex=ignore_filename_regex, + report_format=report_format, + **self._step_kwargs, + ) + steps.append(coverage_step) + if report_to_zoss: + steps.append( + code_coverage_step.CollectLcovCoverageStep( + lcov_files=coverage_step.get_lcov_output_file_paths(), + **self._step_kwargs, + ) + ) + + return steps
diff --git a/cq/scripts/slave/recipe/clang_format.py b/cq/scripts/slave/recipe/clang_format.py new file mode 100644 index 0000000..3275dda --- /dev/null +++ b/cq/scripts/slave/recipe/clang_format.py
@@ -0,0 +1,60 @@ +"""Recipe for running clang-format-diff on the given build.""" + +from __future__ import absolute_import +from slave import base_recipe +from slave.step import clang_format_step + + +# Note that the keys are Gerrit project names. +PROJECT_CONFIGS = { + 'chromecast/internal': { + 'deny_list_filter': [r'vendor/media/google3/(.*)', 'android/prebuilt', + r'(.*)/third_party/(.*)'] + }, + 'chromium/src': { + 'deny_list_filter': [r'.*'], + }, + 'eureka/playready_cdm': { + 'deny_list_filter': [r'cast_playready_dummy.cc'], + }, + 'libassistant/internal/third_party': { + 'deny_list_filter': [r'.*'], + }, + 'vendor/amlogic': { + 'deny_list_filter': [r'(\w+)/prebuilt/(.*)'], + }, + 'vendor/google/neural_network_models': { + 'deny_list_filter': [ + r'NBGParser', + ], + }, + 'vendor/marvell': { + 'deny_list_filter': [r'(\w+)/prebuilt/(.*)'], + }, +} + + +def GetValidBuildNames(): + return ['clang_format'] + + +def CreateRecipe(build_name: str, **kwargs): + """Builds a recipe object.""" + del build_name # Unused. + return ClangFormatRecipe(**kwargs) + + +class ClangFormatRecipe(base_recipe.BaseRecipe): + """Recipe to clang-format a change.""" + + def get_steps(self): + allow_list_filter = PROJECT_CONFIGS.get( + self._properties['patch_project'], {}).get('allow_list_filter', None) + deny_list_filter = PROJECT_CONFIGS.get( + self._properties['patch_project'], {}).get('deny_list_filter', None) + + return [ + clang_format_step.ClangFormatStep(allow_list_filter=allow_list_filter, + deny_list_filter=deny_list_filter, + **self._step_kwargs), + ]
diff --git a/cq/scripts/slave/recipe/clang_tidy.py b/cq/scripts/slave/recipe/clang_tidy.py new file mode 100644 index 0000000..48b7e6a --- /dev/null +++ b/cq/scripts/slave/recipe/clang_tidy.py
@@ -0,0 +1,133 @@ +"""Recipe for running clang-tidy-diff on the given build.""" +import logging +from slave import base_recipe +from slave import base_step +from slave.step import clang_tidy_step +from slave.step import compdb_gen_step +from slave.step import cast_shell_step +from slave.step import unittest_step +from slave.recipe import clang_builder +from slave.recipe import ota_builder +from slave.step import ota_resign_step + +# Note that the keys are Gerrit project names. +# TODO(mingcl): Allow configuring build-specific filters to avoid reporting +# duplicate clang-tidy suggestions from different builds. +PROJECT_CONFIGS = { + 'chromecast/internal': { + 'deny_list_filter': [ + r'vendor/media/google3/(.*)', 'android/prebuilt', + r'(.*)/third_party/(.*)' + ] + }, +} + +BUILD_CONFIGS = { + 'audioassistant_x64_eng_rbe_clang_tidy': { + 'build_args_product': 'audioassistant_x64_eng', + 'build_args_official': False, + # TODO(b/145840052): Remove once the build is fast enough. + 'timeout_secs_build_gtests': 5 * 60 * 60, + # TODO(b/148885147) Remove params below + 'build_branding': 'chrome', + 'build_product': 'audio', + 'build_flavor': 'Debug', + 'build_arch': 'clang', + 'enable_assistant': True, + 'run_gtests': False, + }, + 'nq-eng_clang_tidy': { + 'build_flavor': 'release', + 'resign': ota_resign_step.NQ_RESIGN, + 'factory': ota_resign_step.NQ_FACTORY, + 'usbstick': ota_resign_step.NQ_USBSTICK, + 'partner_bucket': ['cast-partner-amlogic-internal'], + }, +} + +# The name of build directory used by actual build recipe. +# Since the build directory name could change when the build recipe/script get +# changed, the best we can do is to update this dictionary when needed. +# This should be fine since clang tidy check is non-blocking. +BUILD_DIRECTORIES = { + 'audioassistant_x64_eng_rbe_clang_tidy': 'out_clang_audio_gn/Debug/', + 'nq-eng_clang_tidy': 'out_chromecast_nq/release/', +} + +# Specifies the recipe which will be used to make sure all files required for +# compilation is available before running clang-tidy +BUILD_RECIPE_NAME = { + 'audioassistant_x64_eng_rbe_clang_tidy': 'clang_builder', + 'nq-eng_clang_tidy': 'ota_builder', +} + + +def GetValidBuildNames(): + return [ + 'audioassistant_x64_eng_rbe_clang_tidy', + 'nq-eng_clang_tidy', + ] + + +def CreateRecipe(build_name: str, **kwargs): + """Builds a recipe object.""" + # Extracts default_properties from build config and adds it to the overall + # properties in kwargs. + config = BUILD_CONFIGS[build_name] + return ClangTidyRecipe( + build_name, + build_config=config, + build_dir=BUILD_DIRECTORIES[build_name], + build_recipe_name=BUILD_RECIPE_NAME[build_name], + **kwargs) + + +def RemoveClangTidySuffix(text): + if text.endswith('_clang_tidy'): + return text[:-len('_clang_tidy')] + return text + + +class ClangTidyRecipe(base_recipe.BaseRecipe): + """Recipe to clang-tidy a change.""" + + def __init__(self, build_name, build_config, build_dir, build_recipe_name, + **kwargs): + base_recipe.BaseRecipe.__init__( + self, enable_build_accelerator=True, **kwargs) + self._properties = kwargs.get('properties', {}) + self._build_name = build_name + self._build_config = build_config + self._build_dir = build_dir + self._build_recipe_name = build_recipe_name + self._builder_kwargs = kwargs + + def get_steps(self): + allow_list_filter = PROJECT_CONFIGS.get(self._properties['patch_project'], + {}).get('allow_list_filter', None) + deny_list_filter = PROJECT_CONFIGS.get(self._properties['patch_project'], + {}).get('deny_list_filter', None) + + # Build cast shell and unittests to generate necessary header files + if self._build_recipe_name == 'clang_builder': + build_steps = clang_builder.ClangRecipe( + self._build_config, **self._builder_kwargs).get_steps() + elif self._build_recipe_name == 'ota_builder': + build_steps = ota_builder.OtaRecipe( + RemoveClangTidySuffix(self._build_name), self._build_config, + **self._builder_kwargs).get_steps() + else: + logging.error('Unknown build recipe name: ' + self._build_recipe_name + + '. Might need to update BUILD_RECIPE_NAME.') + build_steps = [] + + return build_steps + [ + # Generate compilation database from the build directory. + compdb_gen_step.CompdbGenStep( + build_dir=self._build_dir, **self._step_kwargs), + # Then clang tidy can use the compilation database to check the code. + clang_tidy_step.ClangTidyStep( + allow_list_filter=allow_list_filter, + deny_list_filter=deny_list_filter, + **self._step_kwargs), + ]
diff --git a/cq/scripts/slave/recipe/clusterfuzz_builder.py b/cq/scripts/slave/recipe/clusterfuzz_builder.py new file mode 100644 index 0000000..d97832e --- /dev/null +++ b/cq/scripts/slave/recipe/clusterfuzz_builder.py
@@ -0,0 +1,144 @@ +"""Recipe to build and upload fuzz testing targets to clusterfuzz GCS Bucket""" +import os + +from helpers import branch_utils +from helpers import gcs_utils +from slave import base_recipe +from slave.step import gcs_upload_step +from slave.step import gn_step +from slave.step import make_clean_step +from slave.step import ninja_step +from slave.step import shell_step + +BUILD_CONFIGS = { + 'tcp_socket_impl_fuzzer': { + 'archive_name': 'tcp_socket_impl_fuzzer', + 'build_args_product': 'video_x64_eng', + 'build_target': ('chromecast/internal/smart_home/actions/' + 'platform/cast:tcp_socket_impl_fuzzer'), + 'run_gtests': False, + 'build_args': [ + 'use_libfuzzer=true', + 'is_asan=true', + 'is_component_build=false', + ], + 'gcs_bucket': 'catabuilder-clusterfuzz-results', + 'gcs_path': 'tcp_socket_impl_fuzzer', + }, + 'udp_socket_impl_fuzzer': { + 'archive_name': 'udp_socket_impl_fuzzer', + 'build_args_product': 'video_x64_eng', + 'build_target': ('chromecast/internal/smart_home/actions/' + 'platform/cast:udp_socket_impl_fuzzer'), + 'run_gtests': False, + 'build_args': [ + 'use_libfuzzer=true', + 'is_asan=true', + 'is_component_build=false', + ], + 'gcs_bucket': 'catabuilder-clusterfuzz-results', + 'gcs_path': 'udp_socket_impl_fuzzer', + }, +} + + +def GetValidBuildNames(): + return list(BUILD_CONFIGS.keys()) + + +def CreateRecipe(build_name: str, **kwargs): + """Builds a recipe object.""" + config = BUILD_CONFIGS[build_name] + return FuzzRecipe(config, **kwargs) + + +class FuzzRecipe(base_recipe.BaseRecipe): + """Recipe to build and upload fuzz testing targets to clusterfuzz GCS""" + + def __init__(self, config, **kwargs): + base_recipe.BaseRecipe.__init__( + self, enable_build_accelerator=True, **kwargs) + self._build_config = config + + def get_num_jobs(self): # pylint:disable=method-hidden + """Count of jobs to use.""" + setup_steps = self.get_setup_steps() + return setup_steps[0].get_num_jobs() + + def get_steps(self): + cwd = os.getcwd() + gcs_bucket = self._build_config.get('gcs_bucket') + gcs_path = self._build_config.get('gcs_path') + jobs = self.get_num_jobs() + build_args = self._build_config.get('build_args') + build_args_product = self._build_config.get('build_args_product') + build_target = self._build_config.get('build_target') + post_submit_upload = self.build_system == 'catabuilder' + archive_name = self._build_config.get('archive_name') + fuzz_archive = '{}.zip'.format(self.build_number) + + # Going to build target to out directory + out_dir = os.path.join('out', archive_name, self.build_number) + steps = [] + if self.build_system == 'catabuilder': + steps.append(make_clean_step.MakeCleanStep(**self._step_kwargs)) + + # Generate gn gen step + gn_gen_step = gn_step.GnGenStep( + build_args_product=build_args_product, + build_args=build_args, + out_dir=out_dir, + halt_on_failure=True, + cwd=cwd, + **self._step_kwargs) + steps.append(gn_gen_step) + + # Generate gn args step + gn_args_step = gn_step.GnArgsStep( + out_dir=out_dir, cwd=cwd, halt_on_failure=True, **self._step_kwargs) + steps.append(gn_args_step) + + # Generate ninja build step + ninja_build_step = ninja_step.NinjaStep( + out_dir=out_dir, + target=build_target, + cwd=cwd, + jobs=jobs, + halt_on_failure=True, + **self._step_kwargs) + steps.append(ninja_build_step) + + # Zip build artifacts excluding obj file + zip_output_step = shell_step.ShellStep( + name='Zip build artifacts', + command=['zip', '-rq', fuzz_archive, + '.', '-x', "'*obj*'"], + directory=os.getcwd()+'/'+out_dir, + **self._step_kwargs) + + steps.append(zip_output_step) + + # Upload Fuzz Testing build output to gcs + # only if recipe is running from Catabuilder. + if post_submit_upload: + # Write and upload targets.list file + contents = '\n'.join( + BUILD_CONFIGS[config]['gcs_path'] for config in BUILD_CONFIGS) + targets_list_file = self._executor.write_temp_file(contents) + + gcs_step = gcs_upload_step.GcsUploadStep( + gcs_bucket, + 'targets.list', + name='Clusterfuzz GCS upload for targets.list', + src_path=targets_list_file, + **self._step_kwargs) + + gcs_step = gcs_upload_step.GcsUploadStep( + gcs_bucket, + gcs_path, + name='Clusterfuzz GCS upload for target: ' + archive_name, + src_path=os.getcwd()+'/'+out_dir+'/'+fuzz_archive, + **self._step_kwargs) + steps.append(gcs_step) + + return steps
diff --git a/cq/scripts/slave/recipe/code_coverage_e2e_mock.py b/cq/scripts/slave/recipe/code_coverage_e2e_mock.py new file mode 100644 index 0000000..c915487 --- /dev/null +++ b/cq/scripts/slave/recipe/code_coverage_e2e_mock.py
@@ -0,0 +1,78 @@ +import json +import os +import pathlib +import shutil + +from slave import base_recipe +from slave import base_step +from slave.step import code_coverage_step + + +def GetValidBuildNames(): + return ['incremental-coverage-e2e-mock-1', 'absolute-coverage-e2e-mock-1'] + +def CreateRecipe(build_name: str, **kwargs): + """Defines how this recipe gets built.""" + return CodeCoverageE2EMockRecipe(build_name, **kwargs) + + +class CodeCoverageE2EMockRecipe(base_recipe.BaseRecipe): + """Recipe to execute e2e fake build.""" + + def __init__(self, builder_name, data_manager, **kwargs): + base_recipe.BaseRecipe.__init__(self, data_manager=data_manager, **kwargs) + self._builder_name = builder_name + self._data_manager = data_manager + + def get_steps(self): + if 'code_health_project_path' in self._properties: + project_path = pathlib.Path(self._properties['code_health_project_path']) + else: + project_path = pathlib.Path(self._data_manager.get_project_path( + self._properties['patch_project'] + )) + config_file_path = project_path / 'recipe_config.json' + config = json.loads(config_file_path.read_text()) + return [ + code_coverage_step.CollectLcovCoverageStep( + lcov_files=config.get('input_lcov_files', []), + **self._step_kwargs, + ), + CodeCoverageE2EMockStep( + builder_name=self._builder_name, + output_files=config.get('output_files', []), + output_properties=config.get('output_properties', {}), + project_path=project_path, + **self._step_kwargs, + ), + ] + + +class CodeCoverageE2EMockStep(base_step.BaseStep): + + def __init__( + self, + builder_name, + output_files, + output_properties, + project_path, + **kwargs, + ): + base_step.BaseStep.__init__(self, name="code_coverage_e2e_mock", **kwargs) + self._builder_name = builder_name + self._properties = kwargs.get('properties', {}) + self._output_files = output_files + self._output_properties = output_properties + self._project_path = project_path + + def run(self): + for path in self._output_files: + path = pathlib.Path(path) + dest_dir = pathlib.Path(self.get_gcs_dir()) / path.parent + dest_dir.mkdir(exist_ok=True, parents=True) + shutil.copy(self._project_path / path, dest_dir) + + for key, value in self._output_properties.items(): + self.set_build_property(key, value) + + return True
diff --git a/cq/scripts/slave/recipe/combined_sdk.py b/cq/scripts/slave/recipe/combined_sdk.py new file mode 100644 index 0000000..0025791 --- /dev/null +++ b/cq/scripts/slave/recipe/combined_sdk.py
@@ -0,0 +1,268 @@ +"""Recipe for building Combined SDK, bootloader, kernel.""" +from helpers import branch_utils + +from slave import base_recipe +from slave.step import combined_sdk_clean +from slave.step import combined_sdk_compile +from slave.step import py_env_setup_step + + + +FAKE_WORK_DIR = 'out' +FAKE_PREBUILT_SUBDIR = ( + FAKE_WORK_DIR + '/vendor/{vendor}/{product}/prebuilt') + +OSS_SDK_DIR = '/tmp/oss' +OSS_SDK_RELEASE_SCRIPT = './sdk/build_scripts/release_oss.sh' + +BUILD_LOGS_DIR = 'sdk/build_scripts/build_log/log' + +MARVELL_PREBUILT_FILE = 'marvell-prebuilt.tgz' + +MARVELL = { + 'name': 'marvell', + 'build_script': 'sdk/build_scripts/build_all.sh', + 'fake_work_dir': FAKE_WORK_DIR, + 'fake_prebuilt_dir': FAKE_PREBUILT_SUBDIR, + 'prebuilt_file': MARVELL_PREBUILT_FILE, + 'include_product_param': False, + 'requirements_project': 'marvell/sdk/amp', + 'requirements_path': 'requirements3.txt', + 'oss_sdk_dir': OSS_SDK_DIR, + 'oss_sdk_release_script': OSS_SDK_RELEASE_SCRIPT, + 'build_logs_dir': BUILD_LOGS_DIR, + 'purge_dirs': [ + MARVELL_PREBUILT_FILE, + OSS_SDK_DIR, + FAKE_WORK_DIR, + ] +} + +AMLOGIC_PREBUILT_FILE = 'amlogic-prebuilt.tgz' + +AMLOGIC = { + 'name': 'amlogic', + 'build_script': 'sdk/build_scripts/build_all.sh', + 'fake_work_dir': FAKE_WORK_DIR, + 'fake_prebuilt_dir': FAKE_PREBUILT_SUBDIR, + 'prebuilt_file': AMLOGIC_PREBUILT_FILE, + 'include_product_param': True, + 'requirements_project': 'amlogic/sdk', + 'requirements_path': 'requirements3.txt', + 'oss_sdk_dir': OSS_SDK_DIR, + 'oss_sdk_release_script': OSS_SDK_RELEASE_SCRIPT, + 'build_logs_dir': BUILD_LOGS_DIR, + 'purge_dirs': [ + AMLOGIC_PREBUILT_FILE, + OSS_SDK_DIR, + FAKE_WORK_DIR, + ] +} + +QUALCOMM_PREBUILT_FILE = 'qualcomm-prebuilt.tgz' + +QUALCOMM = { + 'name': 'qualcomm', + 'build_script': 'sdk/build_scripts/build_all.sh', + 'fake_work_dir': FAKE_WORK_DIR, + 'fake_prebuilt_dir': FAKE_PREBUILT_SUBDIR, + 'prebuilt_file': QUALCOMM_PREBUILT_FILE, + 'include_product_param': True, + 'requirements_project': 'qualcomm_sirocco/sdk', + 'requirements_path': 'requirements3.txt', + 'oss_sdk_dir': OSS_SDK_DIR, + 'oss_sdk_release_script': OSS_SDK_RELEASE_SCRIPT, + 'build_logs_dir': BUILD_LOGS_DIR, + 'purge_dirs': [ + QUALCOMM_PREBUILT_FILE, + OSS_SDK_DIR, + FAKE_WORK_DIR, + 'qualcomm', + 'u-boot', + ] +} + +MEDIATEK_PREBUILT_FILE = 'mediatek-prebuilt.tgz' +MEDIATEK_WORK_DIR = 'out_sdk' +MEDIATEK = { + 'name': 'mediatek', + 'build_script': 'sdk/build_scripts/build_all.sh', + 'fake_work_dir': MEDIATEK_WORK_DIR, + 'fake_prebuilt_dir': FAKE_PREBUILT_SUBDIR, + 'prebuilt_file': MEDIATEK_PREBUILT_FILE, + 'include_product_param': True, + 'requirements_project': 'kirkwood/alps/device/google/kirkwood', + 'requirements_path': 'sdk/requirements.txt', + 'oss_sdk_dir': OSS_SDK_DIR, + 'oss_sdk_release_script': OSS_SDK_RELEASE_SCRIPT, + 'build_logs_dir': BUILD_LOGS_DIR, + 'purge_dirs': [ + MEDIATEK_PREBUILT_FILE, + OSS_SDK_DIR, + MEDIATEK_WORK_DIR, + 'out', + ] +} + +BUILD_CONFIGS = { + 'combined-sdk-kernel-bootloader': { + 'vendor_config': MARVELL, + 'product': 'salami', + }, + 'combined-sdk-kernel-bootloader-amlogic-biggie': { + 'vendor_config': AMLOGIC, + 'product': 'biggie', + }, + 'combined-sdk-kernel-bootloader-amlogic-boreal': { + 'vendor_config': AMLOGIC, + 'product': 'boreal', + }, + 'combined-sdk-kernel-bootloader-amlogic-elaine': { + 'vendor_config': AMLOGIC, + 'product': 'elaine', + }, + 'combined-sdk-kernel-bootloader-amlogic-estelle': { + 'vendor_config': AMLOGIC, + 'product': 'estelle', + }, + 'combined-sdk-kernel-bootloader-amlogic-gq': { + 'vendor_config': AMLOGIC, + 'product': 'gq', + }, + 'combined-sdk-kernel-bootloader-amlogic-korlan': { + 'vendor_config': AMLOGIC, + 'product': 'korlan', + }, + 'combined-sdk-kernel-bootloader-amlogic-lumia': { + 'vendor_config': AMLOGIC, + 'product': 'lumia', + }, + 'combined-sdk-kernel-bootloader-amlogic-newman': { + 'vendor_config': AMLOGIC, + 'product': 'newman', + }, + 'combined-sdk-kernel-bootloader-amlogic-nq': { + 'vendor_config': AMLOGIC, + 'product': 'nq', + }, + 'combined-sdk-kernel-bootloader-amlogic-sabrina': { + 'vendor_config': AMLOGIC, + 'product': 'sabrina', + }, + 'combined-sdk-kernel-bootloader-amlogic-spencer': { + 'vendor_config': AMLOGIC, + 'product': 'spencer', + }, + 'combined-sdk-kernel-bootloader-amlogic-a049': { + 'vendor_config': AMLOGIC, + 'product': 'a049', + }, + 'combined-sdk-kernel-bootloader-amlogic-venus': { + 'vendor_config': AMLOGIC, + 'product': 'venus', + }, + 'combined-sdk-kernel-bootloader-qualcomm-brezza': { + 'vendor_config': QUALCOMM, + 'product': 'brezza', + }, + 'combined-sdk-kernel-bootloader-qualcomm-sirocco': { + 'vendor_config': QUALCOMM, + 'product': 'sirocco', + }, + 'combined-sdk-kernel-bootloader-mediatek-kirkwood': { + 'vendor_config': MEDIATEK, + 'product': 'kirkwood', + }, + 'combined-sdk-kernel-bootloader-mediatek-kirkwood-user': { + 'vendor_config': MEDIATEK, + 'product': 'kirkwood-user', + }, + +} + + +def GetValidBuildNames(): + return list(BUILD_CONFIGS.keys()) + + +def CreateRecipe(build_name: str, **kwargs): + """Builds a recipe object.""" + return CombinedSdkRecipe(build_name, BUILD_CONFIGS[build_name], **kwargs) + + +class CombinedSdkRecipe(base_recipe.BaseRecipe): + """Recipe to run an ota build.""" + + def __init__(self, build_name, build_config, **kwargs): + base_recipe.BaseRecipe.__init__(self, **kwargs) + self._build_name = build_name + self._build_config = build_config + + def _oss_run_condition(self): + if self.build_system != 'catabuilder': + return False + if branch_utils.is_release_branch(self._manifest_branch): + return True + return False + + def get_setup_steps(self): + steps = [] + purge_dirs = self._build_config['vendor_config']['purge_dirs'] + steps.append(combined_sdk_clean.CleanPrebuiltsSDKStep( + purge_dirs, **self._step_kwargs)) + steps += super(CombinedSdkRecipe, self).get_setup_steps() + return steps + + def get_steps(self): + vendor_config = self._build_config['vendor_config'] + sdk_python_packages = 'team-sdk/python_packages' + steps = [ + combined_sdk_clean.DirtyCheckSDKStep( + halt_on_failure=False, **self._step_kwargs), + combined_sdk_clean.CleanCheckoutSDKStep(**self._step_kwargs), + combined_sdk_clean.DirtyCheckSDKStep( + halt_on_failure=True, **self._step_kwargs), + py_env_setup_step.PyEnvSetupStep( + local_packages_dir=sdk_python_packages, + py3=True, + requirements_path=vendor_config['requirements_path'], + requirements_project=vendor_config['requirements_project'], + **self._step_kwargs), + combined_sdk_compile.CompileSDKStep( + self._build_config, **self._step_kwargs), + combined_sdk_compile.CreateTarStep( + self._build_config, **self._step_kwargs), + ] + if self._oss_run_condition(): + steps.append(combined_sdk_compile.OssCreateTarStep( + self._build_config, **self._step_kwargs)) + steps += [ + combined_sdk_compile.CreateLogDirStep( + self._build_config, **self._step_kwargs), + combined_sdk_compile.ArchiveArtifactsStep( + self._build_config, **self._step_kwargs), + ] + return steps + + def get_steps_for_ota_builder(self): + vendor_config = self._build_config['vendor_config'] + sdk_python_packages = 'team-sdk/python_packages' + return [ + py_env_setup_step.PyEnvSetupStep( + local_packages_dir=sdk_python_packages, + py3=True, + requirements_path=vendor_config['requirements_path'], + requirements_project=vendor_config['requirements_project'], + **self._step_kwargs), + combined_sdk_compile.CompileSDKStep( + self._build_config, **self._step_kwargs), + combined_sdk_compile.CopySDKStep(self._build_config, + **self._step_kwargs), + combined_sdk_compile.CreateTarStep( + self._build_config, **self._step_kwargs), + combined_sdk_compile.CreateLogDirStep( + self._build_config, **self._step_kwargs), + combined_sdk_compile.ArchiveArtifactsStep( + self._build_config, **self._step_kwargs), + ] +
diff --git a/cq/scripts/slave/recipe/config_validator.py b/cq/scripts/slave/recipe/config_validator.py new file mode 100644 index 0000000..a09bdc1 --- /dev/null +++ b/cq/scripts/slave/recipe/config_validator.py
@@ -0,0 +1,39 @@ +"""Recipe for running config validation checks on the given build.""" +from slave import base_recipe +from slave.step import json_check_step +from slave.step import xml_check_step + + +PROJECT_CONFIGS = { + 'chromium/src': { + 'deny_list_filter': ['.*'], + } +} + + +def GetValidBuildNames(): + return ['config_validator'] + + +def CreateRecipe(build_name: str, **kwargs): + """Builds a recipe object.""" + del build_name # Unused. + return ConfigValidatorRecipe(**kwargs) + + +class ConfigValidatorRecipe(base_recipe.BaseRecipe): + """Recipe to run config validatoins on a repository.""" + + def __init__(self, **kwargs): + base_recipe.BaseRecipe.__init__(self, **kwargs) + self._config = PROJECT_CONFIGS.get( + self._properties.get('patch_project'), {}) + self._deny_list_filter = self._config.get('deny_list_filter') + + def get_steps(self): + return [ + json_check_step.JsonCheckStep(deny_list_filter=self._deny_list_filter, + **self._step_kwargs), + xml_check_step.XmlCheckStep(deny_list_filter=self._deny_list_filter, + **self._step_kwargs), + ]
diff --git a/cq/scripts/slave/recipe/container_autoroller_e2e_test.py b/cq/scripts/slave/recipe/container_autoroller_e2e_test.py new file mode 100644 index 0000000..641c946 --- /dev/null +++ b/cq/scripts/slave/recipe/container_autoroller_e2e_test.py
@@ -0,0 +1,42 @@ +import logging +import json +import time + +from helpers import git_utils +from slave import base_recipe +from slave import base_step + + + +def GetValidBuildNames(): + return ['container_autoroller_e2e_test'] + +def CreateRecipe(build_name: str, **kwargs): + """Defines how this recipe gets built.""" + return ContainterAutorollerE2ERecipe(build_name, **kwargs) + + +class ContainterAutorollerE2ERecipe(base_recipe.BaseRecipe): + """Recipe to execute e2e fake build.""" + + def __init__(self, builder_name, **kwargs): + base_recipe.BaseRecipe.__init__(self, **kwargs) + self._builder_name = builder_name + + def get_steps(self): + return [ + ContainterAutorollerE2EStep( + builder_name=self._builder_name, + **self._step_kwargs + ), + ] + + +class ContainterAutorollerE2EStep(base_step.BaseStep): + + def __init__(self, builder_name, **kwargs): + base_step.BaseStep.__init__(self, name="e2e_mock", **kwargs) + self._builder_name = builder_name + + def run(self): + return True
diff --git a/cq/scripts/slave/recipe/container_builder.py b/cq/scripts/slave/recipe/container_builder.py new file mode 100644 index 0000000..7657cf8 --- /dev/null +++ b/cq/scripts/slave/recipe/container_builder.py
@@ -0,0 +1,85 @@ +import os +import pathlib + +from slave import base_recipe +from slave.step import shell_step + + +def GetValidBuildNames(): + return [ + 'abbey_container', + 'container_building_container', + 'gotham_container', + 'monotainer', + 'recipe_bullseye', + ] + + +def CreateRecipe(build_name: str, **kwargs): + del build_name + return ContainerBuilderRecipe(**kwargs) + + +class ContainerBuilderRecipe(base_recipe.BaseRecipe): + """Recipe to build and optionally push a container image.""" + + def get_steps(self): + steps = [ContainerBuildStep( + directory=str(self._eureka_root), + halt_on_failure=True, + **self._step_kwargs)] + if 'container_push_url' in self._properties: + steps += [ContainerPushStep(halt_on_failure=True, **self._step_kwargs)] + return steps + + +class ContainerBuildStep(shell_step.ShellStep): + + def __init__(self, **kwargs): + super().__init__(name='container build', **kwargs) + self._git_config_path = pathlib.Path.home() / 'containers' / 'gitconfig' + self._pip_config_path = pathlib.Path.home() / 'containers' / 'pip.conf' + self._gcs_mirror_path = pathlib.Path.home() / 'gcs-mirror' + self._git_creds_path = pathlib.Path.home() / '.git-credential-cache' + + def get_commands(self): + build_id = self.get_property('basil_build_id') + creds_path = self._git_creds_path + return [ + self.ShellCommand([ + 'podman', + 'build', + '--format=oci', + '--arch=amd64', + f'--tag={build_id}', + '--no-cache', + '--isolation=chroot', + f'--label=build_id={build_id}', + '--volume=/etc/gitconfig:/etc/gitconfig:ro', + '--volume=/etc/pip.conf:/etc/pip.conf:ro', + '--volume=/workspace/gcs-mirror:/workspace/gcs-mirror:ro', + ('--volume=/workspace/git-credential-cache:' + '/workspace/git-credential-cache:ro'), + self.get_property('container_context_path'), + ]), + ] + + +class ContainerPushStep(shell_step.ShellStep): + + def __init__(self, **kwargs): + super().__init__(name='container push', **kwargs) + + def get_commands(self): + build_id = self.get_property('basil_build_id') + push_url = self.get_property('container_push_url') + image_tag = self.get_property('buildset') + builder_name = self.get_property('buildername') + return [ + self.ShellCommand([ + 'podman', + 'push', + f'localhost/{build_id}:latest', + f'{push_url}/{builder_name}:{image_tag}', + ], num_retries=3), + ]
diff --git a/cq/scripts/slave/recipe/cq_e2e_mock.py b/cq/scripts/slave/recipe/cq_e2e_mock.py new file mode 100644 index 0000000..b4162d4 --- /dev/null +++ b/cq/scripts/slave/recipe/cq_e2e_mock.py
@@ -0,0 +1,115 @@ +import logging +import json + +from helpers import git_utils +from slave import base_recipe +from slave import base_step + + +CONFIG_TAG = 'cq_e2e_config:' +PASS = 'PASSES' +FAIL = 'FAILS' +_DEFAULT_CONFIG = {} + + +def GetValidBuildNames(): + return [ + 'cq-e2e-mock-1', + 'cq-e2e-mock-2', + 'cq-e2e-mock-experimental', + 'cq-e2e-mock-legacy', + 'cq-e2e-mock-recipe', + ] + + +def CreateRecipe(build_name: str, **kwargs): + """Defines how this recipe gets built.""" + return CqE2EMockRecipe(build_name, **kwargs) + + +class CqE2EMockRecipe(base_recipe.BaseRecipe): + """Recipe to execute e2e fake build.""" + + def __init__(self, builder_name, **kwargs): + base_recipe.BaseRecipe.__init__(self, **kwargs) + self._builder_name = builder_name + + def get_steps(self): + return [ + CqE2EMockStep(builder_name=self._builder_name, **self._step_kwargs), + ] + + +class CqE2EMockStep(base_step.BaseStep): + + def __init__(self, builder_name, **kwargs): + base_step.BaseStep.__init__(self, name="e2e_mock", **kwargs) + self._builder_name = builder_name + + def run(self): + for directory in self._get_patch_dirs(): + build = self._get_build_config(directory) + if build: + break + else: + return True + + if build.get('print_patch_order', False): + self._print_patch_order() + + if build.get('review'): + self.add_review(build['review']) + + outcome = build.get('outcome', PASS) + if outcome == PASS: + return True + if outcome == FAIL: + return False + raise ValueError('status must be set in the build config.') + + def _get_build_config(self, directory): + logging.info('Checking for config from latest commit in %s', directory) + commit_message = git_utils.commit_message(self, directory) + lines = commit_message.split('\n') + build_config = None + for line in lines: + if line.startswith(CONFIG_TAG): + build_config = line + if build_config: + build_config = build_config[len(CONFIG_TAG):] + build_config = build_config.strip() + build_config = json.loads(build_config) + logging.info('Build config is %s', build_config) + return build_config.get(self._builder_name, _DEFAULT_CONFIG) + return _DEFAULT_CONFIG + + def _get_patch_dirs(self): + dirs = list() + for patch in [{'project': self.patch_project}] + self.depends_on_list: + try: + new_dir = self.get_project_path(patch['project']) + if new_dir not in dirs: + dirs.append(new_dir) + except KeyError: + logging.info( + 'Ignoring KeyError since %s is not in the manifest', + patch['project'] + ) + logging.info('patch dirs are: %s', dirs) + return dirs + + def _print_patch_order(self): + main_patch = { + 'change_number': self.get_property('issue', 0), + 'gob_host': self.get_property('gerrit'), + 'patchset_number': self.patchset, + 'project': self.patch_project, + } + patches = self.depends_on_list + patches.append(main_patch) + msg = 'Patch Order: ' + ', '.join([ + '{}/{}/{}'.format( + p['gob_host'], int(p['change_number']), int(p['patchset_number'])) + for p in patches + ]) + self.add_review({'message': msg})
diff --git a/cq/scripts/slave/recipe/device_unittest_runner.py b/cq/scripts/slave/recipe/device_unittest_runner.py new file mode 100644 index 0000000..8c17a49 --- /dev/null +++ b/cq/scripts/slave/recipe/device_unittest_runner.py
@@ -0,0 +1,170 @@ +"""Recipe for running unit test on a given deivce. + +The unit test running on a device involves: +1. Download the OTA zip file +2. Install the OTA +3. Copy test dependencies to the device +4. Run unit test cases +""" +import os +import shlex +import sys + +from slave import base_recipe +from slave.step import device_unit_test_step +from slave.step import fetch_ota_step + + +def GetValidBuildNames(): + return ['device_unittest'] + + +def CreateRecipe(build_name: str, **kwargs): + """Builds a recipe object.""" + del build_name # Unused. + property_dict = kwargs['properties'] + mandatory_field_list = ['product_name', + 'branch_name', + 'build_number', + 'build_flavor', + 'board_type', + 'device_id', + 'repo_alias'] + assert all(mandatory_field in property_dict + for mandatory_field in mandatory_field_list) + + return DeviceUnittestRecipe(**kwargs) + + +class DeviceUnittestRecipe(base_recipe.BaseRecipe): + """Recipe to run unit tests on a device.""" + + def __init__(self, **kwargs): + base_recipe.BaseRecipe.__init__(self, **kwargs) + self._property_dict = kwargs['properties'] + self._work_dir = kwargs['properties']['recipe_tmp_dir'] + + def get_tmp_dir(self): + return self._step_kwargs['executor'].get_tmp_dir() + + def get_python_path_dict(self): + """Returns PYTHONPATH used in the unit test.""" + python_path_list = sys.path[:] + for py_path in ('test', 'continuous-tests/build'): + python_path_list.append(os.path.join(self._work_dir, py_path)) + return {'PYTHONPATH': ':'.join(python_path_list)} + + def get_install_ota_command_list(self): + cmd = ('python %s/test/ota/ota_update.py ' + '--bypass_init_availability_check ' + '--ota_package=%s/ota.zip ' + '--mandate_external_storage ' + '--use_tunnel ' + '--expected_build=%s ' + '--expected_build_flavor=%s ' + '--device_id=%s ' + '--debug ;' % ( + self._work_dir, + self.get_tmp_dir(), + self._property_dict['build_number'], + self._property_dict['build_flavor'], + self._property_dict['device_id'])) + return shlex.split(cmd) + + def get_copy_dependencies_command_list(self): + slave_name = os.path.basename(self.get_tmp_dir()) + cmd = ('python %s/test/unit_test/prep_device.py ' + '--device_id=%s ' + '--repo_alias=%s ' + '--branch_name=%s ' + '--target_name=%s-%s ' + '--build_number=%s ' + '--slave_name=%s ' + '--test_binary_dir=%s/unit_test_binaries ' + '--debug' % ( + self._work_dir, + self._property_dict['device_id'], + self._property_dict['repo_alias'], + self._property_dict['branch_name'], + self._property_dict['product_name'], + self._property_dict['build_flavor'], + self._property_dict['build_number'], + slave_name, + self.get_tmp_dir())) + return shlex.split(cmd) + + def get_run_test_command_list(self): + slave_name = os.path.basename(self.get_tmp_dir()) + cmd = ('python3 %s/test/unit_test/run_unit_test_2.py ' + '--debug ' + '--use_tunnel ' + '--repo_alias=%s ' + '--device_id=%s ' + '--branch_name=%s ' + '--report_directory_on_workstation=%s ' + '--unittest_command_list_file=%s/%s/run_test_list.txt ' + '--test_binary_dir=%s/unit_test_binaries ' + '--cloud_logs_path=%s' % ( + self._work_dir, + self._property_dict['repo_alias'], + self._property_dict['device_id'], + self._property_dict['branch_name'], + self._property_dict['local_log_directory'], + self._work_dir, + slave_name, + self.get_tmp_dir(), + self._property_dict['cloud_logs_path'])) + return shlex.split(cmd) + + def get_setup_steps(self): + # Bypass all the repo operations + return [] + + def get_steps(self): + slave_name = os.path.basename(self.get_tmp_dir()) + + return [ + fetch_ota_step.FetchOtaStep( + branch=self._property_dict['branch_name'], + product=self._property_dict['product_name'], + board=self._property_dict['board_type'], + flavor=self._property_dict['build_flavor'], + work_dir=self.get_tmp_dir(), + **self._step_kwargs), + device_unit_test_step.UnitTestShellStep( + name='installing', + command=self.get_install_ota_command_list(), + directory=self._work_dir, + env=self.get_python_path_dict(), + halt_on_failure=True, + **self._step_kwargs), + device_unit_test_step.UnitTestShellStep( + name='Create unit test binary directory', + command=['mkdir', '%s/unit_test_binaries' % self.get_tmp_dir()], + directory=self._work_dir, + env=self.get_python_path_dict(), + halt_on_failure=True, + **self._step_kwargs), + device_unit_test_step.UnitTestShellStep( + name='Copy test dependencies to device', + command=self.get_copy_dependencies_command_list(), + directory=self._work_dir, + env=self.get_python_path_dict(), + halt_on_failure=True, + **self._step_kwargs), + device_unit_test_step.UnitTestShellStep( + name='Run unit test on device', + command=self.get_run_test_command_list(), + directory=self._work_dir, + env=self.get_python_path_dict(), + halt_on_failure=True, + **self._step_kwargs), + device_unit_test_step.UnitTestShellStep( + name='Clean up unit test directory', + command=['rm', '-rf', '%s/%s' % (self._work_dir, slave_name)], + directory=self._work_dir, + env=self.get_python_path_dict(), + halt_on_failure=True, + **self._step_kwargs) + ] +
diff --git a/cq/scripts/slave/recipe/dipper_builder.py b/cq/scripts/slave/recipe/dipper_builder.py new file mode 100644 index 0000000..e130eb8 --- /dev/null +++ b/cq/scripts/slave/recipe/dipper_builder.py
@@ -0,0 +1,35 @@ +"""Recipe for running a Dipper build on the given device.""" +import os + +from slave import base_recipe +from slave.step import dipper_step + + + +def GetValidBuildNames(): + """Gets all valid build names.""" + return ['dipper-eng', 'dipper-user'] + + +def CreateRecipe(build_name: str, **kwargs): + """Builds a recipe object.""" + return DipperRecipe(build_name, **kwargs) + + +class DipperRecipe(base_recipe.BaseRecipe): + """Recipe to run Dipper build.""" + + def __init__(self, build_name, **kwargs): + prop = kwargs.get('properties', {}) + prop['skip_gclient'] = True + if 'properties' not in kwargs: + kwargs['properties'] = prop + base_recipe.BaseRecipe.__init__(self, **kwargs) + self._build_name = build_name + + def get_steps(self): + return [ + dipper_step.DipperStep( + self._build_name, + **self._step_kwargs), + ]
diff --git a/cq/scripts/slave/recipe/docker_testing_image_runner.py b/cq/scripts/slave/recipe/docker_testing_image_runner.py new file mode 100644 index 0000000..71eb6e9 --- /dev/null +++ b/cq/scripts/slave/recipe/docker_testing_image_runner.py
@@ -0,0 +1,63 @@ +"""Recipe for building and depoying the docker image used by the testing team. +""" +import os + +from slave import base_recipe +from slave.step import docker_testing_image_step +from slave.step import docker_push_testing_step + +DOCKER_INFORMATION = { + 'docker_testing_image': { + 'bucket': 'gcr.io/google.com/home-ci-controller-staging/home-testing', + 'path_info': { + 'project': 'test', + 'dockerfile': 'docker_images'} # Path in project to Dockerfile + } +} + +def GetValidBuildNames(): + return ['docker_testing_image',] + +def CreateRecipe(build_name: str, **kwargs): + bucket = DOCKER_INFORMATION[build_name]['bucket'] + path_info = DOCKER_INFORMATION[build_name]['path_info'] + return DockerTestingImageRecipe( + bucket=bucket, + path_info=path_info, + **kwargs) + +class DockerTestingImageRecipe(base_recipe.BaseRecipe): + """Recipe to build and push the Docker image that will be used by the home + testing team. + + Args: + bucket: The URL of the docker bucket where the image will be pushed and + stored + path_info: Dictionary to have the project and internal path to the + Dockerfile. For example: + 'path_info': { + 'project': 'project_repo', + 'dockerfile': 'path/to/dockerfile/folder' + } + + Returns: + Steps for build and push docker images. + """ + + def __init__(self, bucket, path_info, **kwargs): + base_recipe.BaseRecipe.__init__(self, **kwargs) + self._path_info = path_info + self._docker_bucket = bucket + + def get_steps(self): + steps = [ + docker_testing_image_step.DockerImageBuildStep( + self._docker_bucket, + self._path_info, + **self._step_kwargs), + docker_push_testing_step.DockerPushTestingStep( + self._docker_bucket, + self._path_info, + **self._step_kwargs) + ] + return steps
diff --git a/cq/scripts/slave/recipe/eureka_kythe_builder.py b/cq/scripts/slave/recipe/eureka_kythe_builder.py new file mode 100644 index 0000000..e87ec3f --- /dev/null +++ b/cq/scripts/slave/recipe/eureka_kythe_builder.py
@@ -0,0 +1,142 @@ +"""Recipe to create and publish KZIPs for Kythe. + +See go/eureka-cs-indexing for more context. +""" +import copy +import os + +from slave import base_recipe +from slave.step import gcs_upload_step +from slave.step import gn_step +from slave.step import kythe_step +from slave.step import make_clean_step +from slave.step import ninja_step +from slave.test import test_generator + + +# WARNING: the build_args_product and build_args_flavor are used to construct +# the naming of the out folder. As per the vnames.json file, Kythe expects this +# exact naming in order to properly index and serve generated files. +BUILD_CONFIGS = { + 'fuchsia_eureka_kythe_prod': { + 'build_args_product': 'fuchsia_arm64_user', + 'build_args_flavor': 'Release', + 'build_args': ['is_official_build=true'], + 'build_target': 'cast_agent_exe', + 'gcs_folder': 'prod' + }, + 'fuchsia_eureka_kythe_staging': { + 'build_args_product': 'fuchsia_arm64_user', + 'build_args_flavor': 'Release', + 'build_args': ['is_official_build=true'], + 'build_target': 'cast_agent_exe', + 'gcs_folder': 'staging' + }, +} + +GCS_UPLOAD_BUCKET = 'eureka-kythe' + +# Expect that merged KZIPs are at least 1 GB +MIN_EXPECTED_KZIP_SIZE = 1 * 1024 * 1024 * 1024 + + +def GetValidBuildNames(): + return list(BUILD_CONFIGS.keys()) + + +def CreateRecipe(build_name: str, **kwargs): + config = BUILD_CONFIGS[build_name] + return EurekaKytheRecipe(config, **kwargs) + + +class EurekaKytheRecipe(base_recipe.BaseRecipe): + + def __init__(self, config, **kwargs): + base_recipe.BaseRecipe.__init__( + self, enable_build_accelerator=True, **kwargs) + self._build_config = config + + def get_clean_steps(self): + return [make_clean_step.MakeCleanStep(**self._step_kwargs)] + + # Needed so that we can properly mock expectations in test. + def get_num_jobs(self): # pylint:disable=method-hidden + """Count of jobs to use.""" + setup_steps = self.get_setup_steps() + return setup_steps[0].get_num_jobs(multiplier=10) + + def get_steps(self): + steps = [] + + cwd = os.getcwd() + continuous_tests_root = os.path.abspath( + self.get_setup_steps()[0].get_project_path('continuous-tests')) + chromium_root = self.get_setup_steps()[0].get_project_path('chromium/src') + build_args = copy.deepcopy(self._build_config.get('build_args')) + build_args_product = self._build_config.get('build_args_product') + build_args_flavor = self._build_config.get('build_args_flavor') + build_target = self._build_config.get('build_target') + gcs_folder = self._build_config.get('gcs_folder') + out_dir = os.path.join(chromium_root, 'out_{}'.format(build_args_product), + build_args_flavor) + + # STEP: Generate gn gen for build + gn_gen_step = gn_step.GnGenStep( + build_args_product=build_args_product, + build_args=build_args, + out_dir=out_dir, + halt_on_failure=True, + cwd=cwd, + **self._step_kwargs) + steps.append(gn_gen_step) + + # STEP: List gn args + gn_args_step = gn_step.GnArgsStep( + out_dir=out_dir, cwd=cwd, halt_on_failure=True, **self._step_kwargs) + steps.append(gn_args_step) + + # STEP: Generate ninja build + num_jobs = self.get_num_jobs() + ninja_build_step = ninja_step.NinjaStep( + out_dir=out_dir, + target=build_target, + cwd=cwd, + jobs=num_jobs, + halt_on_failure=True, + **self._step_kwargs) + steps.append(ninja_build_step) + + # STEP: Generate compilation database + gn_gen_step = gn_step.GnGenCompilationDBStep( + out_dir=out_dir, + cwd=cwd, + build_args_product=build_args_product, + target_name=build_target, + halt_on_failure=True, + **self._step_kwargs) + compdb_file = gn_gen_step.get_compdb_file_location() + steps.append(gn_gen_step) + + # STEP: Generate KZIPs + kzip_gen_step = kythe_step.GenerateKzipStep( + cwd=cwd, + tests_root=continuous_tests_root, + chromium_root=chromium_root, + out_dir=out_dir, + compdb_file=compdb_file, + min_expected_kzip_bytes=MIN_EXPECTED_KZIP_SIZE, + halt_on_failures=True, + **self._step_kwargs) + kzip_file = kzip_gen_step.get_kythe_output_file() + steps.append(kzip_gen_step) + + # STEP: Upload to GCS + upload_step = gcs_upload_step.GcsUploadStep( + gcs_bucket=GCS_UPLOAD_BUCKET, + gcs_path=gcs_folder, + src_path=kzip_file, + **self._step_kwargs) + steps.append(upload_step) + + return steps +
diff --git a/cq/scripts/slave/recipe/eurtest_e2e_test_runner.py b/cq/scripts/slave/recipe/eurtest_e2e_test_runner.py new file mode 100644 index 0000000..90ca487 --- /dev/null +++ b/cq/scripts/slave/recipe/eurtest_e2e_test_runner.py
@@ -0,0 +1,85 @@ +# Lint as: python3 +"""Recipe for running eurtest e2e tests against a particular build.""" +import os + +from slave import base_recipe +from slave.recipe import clang_builder +from slave.step import cast_shell_step +from slave.step import py_env_setup_step +from slave.step import py_test_step + + +DEFAULT_E2E_TEST_TIMEOUT_SECONDS = 3600 +SHELL_TO_BUILD = 'displayassistant_grte_opal_eng' +TEST_FILE_FILTER_REGEX = ( + r'test/eurtest/tests/assistant/presubmit_tests/.*_test_case.py$') + + +def GetValidBuildNames(): + return ['py_e2e_test_eurtest_assistant'] + + +def CreateRecipe(build_name: str, **kwargs): + """Builds a recipe object.""" + if build_name != 'py_e2e_test_eurtest_assistant': + raise base_recipe.BuildNameNotSupportedError(build_name) + return EurtestE2ERecipe(**kwargs) + + +class EurtestE2ERecipe(base_recipe.BaseRecipe): + """Recipe to run e2e tests on a repository.""" + + def __init__(self, + **kwargs): + super().__init__( + enable_build_accelerator=True, + **kwargs) + + + def get_steps(self): + build_shell_config = clang_builder.BUILD_CONFIGS['displayassistant_grte_opal_eng'] + + build_branding = build_shell_config.get('build_branding', None) + build_arch = build_shell_config.get('build_arch', None) + build_product = build_shell_config.get('build_product', None) + build_flavor = build_shell_config.get('build_flavor', None) + enable_assistant = build_shell_config.get('enable_assistant', False) + build_args_official = build_shell_config.get('build_args_official', None) + grte_compatible = build_shell_config.get('grte_compatible', False) + build_args_product = build_shell_config.get('build_args_product', None) + additional_import_paths = [ + self._eureka_root / path for path + in ( + 'builder/masters', + 'builder/masters/src', + 'chromium/src/third_party/catapult/telemetry', + 'chromium/src/chromecast/internal', + 'chromium/src/chromecast/tools', + 'continuous-tests', + 'continuous-tests/cq/scripts', + 'test', + 'testing/external/autotest', + 'testing/external/chromite', + 'testing/sprockets', + )] + return [ + cast_shell_step.CastShellStep( + build_branding, build_arch, build_product, + build_flavor, enable_assistant, + build_args_official=build_args_official, + code_coverage=False, grte_compatible=grte_compatible, + build_args_product=build_args_product, halt_on_failure=True, + sanitizer=None, archive_to_tmp=True, **self._step_kwargs), + py_env_setup_step.PyEnvSetupStep( + additional_import_paths=additional_import_paths, + local_packages_dir='team-catatester/python_packages', + py3=True, + requirements_path='lab_system/requirements3.txt', + requirements_project='test', + **self._step_kwargs), + py_test_step.PyTestStep( + project='test', + test_file_filter_regex=TEST_FILE_FILTER_REGEX, + timeout=DEFAULT_E2E_TEST_TIMEOUT_SECONDS, + **self._step_kwargs) + ]
diff --git a/cq/scripts/slave/recipe/fuchsia_builder.py b/cq/scripts/slave/recipe/fuchsia_builder.py new file mode 100644 index 0000000..8e70f32 --- /dev/null +++ b/cq/scripts/slave/recipe/fuchsia_builder.py
@@ -0,0 +1,294 @@ +"""Recipe to build and test fuchsia-cast.""" +import copy +import os +import re +import tempfile + +from helpers import branch_utils +from slave import base_recipe +from slave.step import cipd_upload_step +from slave.step import fuchsia_cipd_upload_step +from slave.step import fuchsia_emulator_step +from slave.step import fuchsia_unittest_step +from slave.step import gn_step +from slave.step import landmine_step +from slave.step import make_clean_step +from slave.step import ninja_step +from slave.step import shell_step +from slave.test import test_generator + + +BUILD_CONFIGS = { + 'arm64_fuchsia': { + 'architecture': 'arm64', + 'build_args_product': 'fuchsia_arm64_user', + 'build_args_flavor': 'Release', + 'build_product': 'display', + 'build_target': 'chromecast/internal/fuchsia:all', + 'test_target': 'chromecast/internal/fuchsia:chromecast_fuchsia_tests', + 'run_gtests': False, + 'run_catatester': True, + 'build_args': [] + }, + 'arm64_fuchsia_eng': { + 'architecture': 'arm64', + 'build_args_product': 'fuchsia_arm64_eng', + 'build_args_flavor': 'Eng', + 'build_product': 'display', + 'build_target': 'chromecast/internal/fuchsia:all', + 'test_target': 'chromecast/internal/fuchsia:chromecast_fuchsia_tests', + 'run_gtests': False, + 'build_args': [] + }, + 'arm64_fuchsia_eng_optimized': { + 'architecture': 'arm64', + 'build_args_product': 'fuchsia_arm64_eng_optimized', + 'build_args_flavor': 'EngOptimized', + 'build_product': 'display', + 'build_target': 'chromecast/internal/fuchsia:all', + 'test_target': 'chromecast/internal/fuchsia:chromecast_fuchsia_tests', + 'run_gtests': False, + 'build_args': [] + }, + 'x64_fuchsia': { + 'architecture': 'amd64', + 'build_args_product': 'fuchsia_x64_user', + 'build_args_flavor': 'Release', + 'build_product': 'display', + 'build_target': 'chromecast/internal/fuchsia:all', + 'test_target': 'chromecast/internal/fuchsia:chromecast_fuchsia_tests', + 'run_gtests': True, + 'build_args': ['dcheck_always_on=true'] + }, + 'x64_fuchsia_eng': { + 'architecture': 'amd64', + 'build_args_product': 'fuchsia_x64_eng', + 'build_args_flavor': 'Eng', + 'build_product': 'display', + 'build_target': 'chromecast/internal/fuchsia:all', + 'test_target': 'chromecast/internal/fuchsia:chromecast_fuchsia_tests', + 'run_gtests': True, + 'build_args': [] + }, + 'x64_fuchsia_eng_optimized': { + 'architecture': 'amd64', + 'build_args_product': 'fuchsia_x64_eng_optimized', + 'build_args_flavor': 'EngOptimized', + 'build_product': 'display', + 'build_target': 'chromecast/internal/fuchsia:all', + 'test_target': 'chromecast/internal/fuchsia:chromecast_fuchsia_tests', + 'run_gtests': True, + 'build_args': [] + }, +} + +SHORTLIVED_BRANCH_PATTERN = ( + r'(?P<major>\d+)\.(?P<minor>\d+)_shortlived_(?P<build>\d+)') + +CIPD_UPLOADS_FILE_NAME = 'cipd_uploads' + + +def GetValidBuildNames(): + return list(BUILD_CONFIGS.keys()) + + +def CreateRecipe(build_name: str, **kwargs): + """Builds a recipe object.""" + config = BUILD_CONFIGS[build_name] + return FuchsiaRecipe(config, **kwargs) + + +class FuchsiaRecipe(base_recipe.BaseRecipe): + """Recipe to lint a repository.""" + + def __init__(self, config, **kwargs): + base_recipe.BaseRecipe.__init__( + self, enable_build_accelerator=True, **kwargs) + self._build_config = config + self._fuchsia_workdir = None + self._properties = kwargs.get('properties', {}) + + def get_fuchsia_bucket(self, chromium_root): + """Get the current Fuchsia bucket to get artifacts from. + + Usually, this will pull artifacts from either the public or private Fuchsia + SDK buckets. For go/feureka-dd builds, it will pull from a temporary bucket. + + Args: + chromium_root: Path to chromium source directory. + + Returns: + GCP bucket. For example: 'fuchsia-sdk' or 'fuchsia'. + """ + bucket_path = os.path.join(chromium_root, 'build/fuchsia/sdk-bucket.txt') + bucket = 'fuchsia' + # Only go/feureka-dd writes to the bucket file + with open(bucket_path) as f: + # Trim any whitespace on each line + bucket = f.readline().rstrip() + return bucket or 'fuchsia' + + def get_num_jobs(self): # pylint:disable=method-hidden + """Count of jobs to use.""" + setup_steps = self.get_setup_steps() + return setup_steps[0].get_num_jobs(multiplier=10) + + def create_temp_directory(self): + return tempfile.TemporaryDirectory().name + + def get_steps(self): + # Use one of the setup steps to get chromium root + cwd = os.getcwd() + setup_steps = self.get_setup_steps() + chromium_root = setup_steps[0].get_project_path('chromium/src') + gcs_dir = setup_steps[0].get_gcs_dir() + jobs = self.get_num_jobs() + architecture = self._build_config.get('architecture') + build_args_product = self._build_config.get('build_args_product') + build_args_flavor = self._build_config.get('build_args_flavor') + build_args = copy.deepcopy(self._build_config.get('build_args')) + if self.build_system == 'catabuilder': + build_args.append('is_official_build=true') + build_target = self._build_config.get('build_target') + test_target = self._build_config.get('test_target') + run_gtests = self._build_config.get('run_gtests') + run_catatester = self._build_config.get('run_catatester', False) + post_submit_upload = self.build_system == 'catabuilder' + self._fuchsia_sdk_root = os.path.join(chromium_root, + 'third_party/fuchsia-sdk/') + self._fuchsia_workdir = self.create_temp_directory() + + # Extend buildargs with incremental build id + incremental_build_prop = ('cast_build_incremental="{}"'.format( + self.build_number)) + build_args.append(incremental_build_prop) + out_dir = os.path.join(chromium_root, 'out_{}'.format(build_args_product), + build_args_flavor) + steps = [] + if self.build_system == 'catabuilder': + steps.append(make_clean_step.MakeCleanStep(**self._step_kwargs)) + else: + steps += [ + landmine_step.LandmineStep(**self._step_kwargs), + ] + # Generate gn gen step + gn_gen_step = gn_step.GnGenStep( + build_args_product=build_args_product, + build_args=build_args, + out_dir=out_dir, + halt_on_failure=True, + cwd=cwd, + **self._step_kwargs) + steps.append(gn_gen_step) + # Generate gn args step + gn_args_step = gn_step.GnArgsStep( + out_dir=out_dir, cwd=cwd, halt_on_failure=True, **self._step_kwargs) + steps.append(gn_args_step) + # Generate ninja build step + ninja_build_step = ninja_step.NinjaStep( + out_dir=out_dir, + target=build_target, + cwd=cwd, + jobs=jobs, + halt_on_failure=True, + **self._step_kwargs) + steps.append(ninja_build_step) + # Generate ninja build tests step + max_timeout_secs = 4 * 60 * 60 + ninja_build_tests_step = ninja_step.NinjaStep( + out_dir=out_dir, + target=test_target, + halt_on_failure=True, + timeout_secs=max_timeout_secs, + cwd=cwd, + jobs=jobs, + **self._step_kwargs) + steps.append(ninja_build_tests_step) + if run_gtests: + bucket = self.get_fuchsia_bucket(chromium_root) + + # Start FEMU + femu_start_step = fuchsia_emulator_step.FuchsiaEmulatorStartStep( + bucket=bucket, + fuchsia_sdk_root=self._fuchsia_sdk_root, + fuchsia_workdir=self._fuchsia_workdir, + **self._step_kwargs) + steps.append(femu_start_step) + + step = fuchsia_unittest_step.FuchsiaUnitTestStep( + out_dir=out_dir, + fuchsia_workdir=self._fuchsia_workdir, + recipe_steps=steps, + cwd=cwd, + **self._step_kwargs) + steps.append(step) + + # Upload the artifacts to CIPD + refs = {self._manifest_branch} + + tags = { + 'version': self.build_number, + } + + far_pkg_vars = { + 'targetarch': architecture + } + + cipd_uploads_file = os.path.join(out_dir, 'gen', CIPD_UPLOADS_FILE_NAME) + cipd_yaml_dir = chromium_root + steps.append(fuchsia_cipd_upload_step.FuchsiaCIPDUploadStep( + steps, cipd_uploads_file, cipd_yaml_dir, + refs=refs, + tags=tags, + pkg_vars=far_pkg_vars, + **self._step_kwargs)) + + # Package gunit test dependencies and upload to gcs + # only if recipe is running from Catabuilder. + if post_submit_upload and run_catatester: + max_timeout_secs = 30 * 60 + ninja_test_deps_archive_step = ninja_step.NinjaStep( + out_dir=out_dir, + target='chromecast_test_deps_archive', + halt_on_failure=True, + timeout_secs=max_timeout_secs, + cwd=cwd, + jobs=jobs, + **self._step_kwargs) + steps.append(ninja_test_deps_archive_step) + + src_path = os.path.join(out_dir, 'test_deps.tar.gz') + dst_path = os.path.join(gcs_dir, 'artifacts', 'tests') + copy_deps_steps = [ + shell_step.ShellStep( + name='Create test deps destination folder', + command=[ + 'mkdir', + '-p', + dst_path, + ], + directory=os.getcwd(), + **self._step_kwargs), + shell_step.ShellStep( + name='Move test_deps.tar.gz to upload folder', + command=['mv', src_path, dst_path], + directory=os.getcwd(), + **self._step_kwargs) + ] + steps.extend(copy_deps_steps) + return steps + + def get_teardown_steps(self): + """Returns a list of all steps that should be executed as part of teardown. + + Teardown steps are always called, even if previous steps fail. + + Returns: + List of slave.base_step.BaseStep commands to be executed. + """ + return [ + fuchsia_emulator_step.FuchsiaEmulatorTeardownStep( + fuchsia_sdk_root=self._fuchsia_sdk_root, + fuchsia_workdir=self._fuchsia_workdir, + **self._step_kwargs) + ] + super().get_teardown_steps()
diff --git a/cq/scripts/slave/recipe/gn_check.py b/cq/scripts/slave/recipe/gn_check.py new file mode 100644 index 0000000..40eef22 --- /dev/null +++ b/cq/scripts/slave/recipe/gn_check.py
@@ -0,0 +1,22 @@ +"""Recipe for running a gn check on the given build.""" +from slave import base_recipe +from slave.step import gn_check_step + + +def GetValidBuildNames(): + return ['gn_check'] + + +def CreateRecipe(build_name: str, **kwargs): + """Builds a recipe object.""" + del build_name # Unused. + return GnCheckRecipe(**kwargs) + + +class GnCheckRecipe(base_recipe.BaseRecipe): + """Recipe to gn check a change.""" + + def get_steps(self): + return [ + gn_check_step.GnCheckStep(**self._step_kwargs) + ]
diff --git a/cq/scripts/slave/recipe/gotham_builder.py b/cq/scripts/slave/recipe/gotham_builder.py new file mode 100644 index 0000000..b3b3449 --- /dev/null +++ b/cq/scripts/slave/recipe/gotham_builder.py
@@ -0,0 +1,248 @@ +"""Recipe for building gotham.""" +import os + +from slave import base_recipe +from slave.step import gotham_build_step +from slave.step import make_clean_step +from slave.step import py_env_setup_step +from slave.test import test_generator + + +# When adding new boards they also need to be added to: +# - build_specs.json +# - build_details.protoascii (Staging & Prod) +# - build_rules.protoascii (Staging & Prod) +# - run 'cq/scripts/tools/recipes_test.py --train' to +# generate recipe_expectation/*.json + +BUILD_CONFIGS = { + # Legacy naming convention. + 'gotham_bootloader': { + 'build_name': 'bootloader', + 'board': 'gotham_bootloader', + }, + 'gotham_bootloader_16mb': { + 'build_name': 'bootloader', + 'board': 'gotham_bootloader_16mb', + }, + 'gotham_eng': { + 'build_name': 'eng', + 'board': '', + }, + 'gotham_eng-arkham2': { + 'build_name': 'eng', + 'board': 'arkham2', + }, + 'gotham_eng-gotham_evt': { + 'build_name': 'eng', + 'board': 'gotham_evt', + }, + 'gotham_eng-gotham_p2': { + 'build_name': 'eng', + 'board': 'gotham_p2', + }, + 'gotham_factory': { + 'build_name': 'factory', + 'board': '', + }, + 'gotham_factory-arkham2': { + 'build_name': 'factory', + 'board': 'arkham2', + }, + 'gotham_factory-gotham_evt': { + 'build_name': 'factory', + 'board': 'gotham_evt', + }, + 'gotham_factory-gotham_p2': { + 'build_name': 'factory', + 'board': 'gotham_p2', + }, + 'gotham_test': { + 'build_name': 'test', + 'board': '', + }, + 'gotham_test-arkham2': { + 'build_name': 'test', + 'board': 'arkham2', + }, + 'gotham_test-gotham_evt': { + 'build_name': 'test', + 'board': 'gotham_evt', + }, + 'gotham_test-gotham_p2': { + 'build_name': 'test', + 'board': 'gotham_p2', + }, + 'gotham_test-host': { + 'build_name': 'test', + 'board': 'host', + }, + + # Current naming convention. + 'gotham_mcu-bootloader-eng': { + 'build_name': 'bootloader-eng', + 'board': '', + }, + 'gotham_mcu-bootloader-user': { + 'build_name': 'bootloader-user', + 'board': '', + }, + 'gotham_mcu-eng': { + 'build_name': 'eng', + 'board': '', + }, + 'gotham_mcu-eng-gotham_dvt': { + 'build_name': 'eng', + 'board': 'gotham_dvt', + }, + 'gotham_mcu-eng-metrics-gotham_dvt': { + 'build_name': 'metrics', + 'board': '', + }, + 'gotham_mcu-eng-gotham_evt': { + 'build_name': 'eng', + 'board': 'gotham_evt', + }, + 'gotham_mcu-user': { + 'build_name': 'user', + 'board': '', + }, + 'gotham_mcu-user-gotham_dvt': { + 'build_name': 'user', + 'board': 'gotham_dvt', + }, + 'gotham_mcu-user-gotham_evt': { + 'build_name': 'user', + 'board': 'gotham_evt', + }, + 'gotham_mcu-fsi-eng': { + 'build_name': 'fsi-eng', + 'board': '', + }, + 'gotham_mcu-fsi-eng-gotham_dvt': { + 'build_name': 'fsi-eng', + 'board': 'gotham_dvt', + }, + 'gotham_mcu-fsi-eng-gothm_evt': { + 'build_name': 'fsi-eng', + 'board': 'gothm_evt', + }, + 'gotham_mcu-fsi-user': { + 'build_name': 'fsi-user', + 'board': '', + }, + 'gotham_mcu-fsi-user-gotham_dvt': { + 'build_name': 'fsi-user', + 'board': 'gotham_dvt', + }, + 'gotham_mcu-fsi-user-gotham_evt': { + 'build_name': 'fsi-user', + 'board': 'gotham_evt', + }, + 'gotham_mcu-factory': { + 'build_name': 'factory', + 'board': '', + }, + 'gotham_mcu-factory-arkham2': { + 'build_name': 'factory', + 'board': 'arkham2', + }, + 'gotham_mcu-factory-gotham_dvt': { + 'build_name': 'factory', + 'board': 'gotham_dvt', + }, + 'gotham_mcu-factory-gotham_evt': { + 'build_name': 'factory', + 'board': 'gotham_evt', + }, + 'gotham_mcu-rma-unlock': { + 'build_name': 'rma-unlock', + 'board': '', + }, + 'gotham_mcu-test': { + 'build_name': 'test', + 'board': '', + }, + 'gotham_mcu-test-gotham_dvt': { + 'build_name': 'test', + 'board': 'gotham_dvt', + }, + 'gotham_mcu-test-gotham_evt': { + 'build_name': 'test', + 'board': 'gotham_evt', + }, + 'gotham_mcu-test-host': { + 'build_name': 'test', + 'board': 'host', + }, + 'gotham_linux_x64': { + 'build_name': 'linux', + 'board': '', + }, + 'gotham_mcu-dynamic-analysis': { + 'build_name': 'dynamic-analysis', + 'board': '', + } +} + + +def GetValidBuildNames(): + return list(BUILD_CONFIGS.keys()) + + +def CreateRecipe(build_name: str, **kwargs): + return GothamRecipe(build_name, **kwargs) + + +class GothamRecipe(base_recipe.BaseRecipe): + """Recipe to build gotham using the build_gotham.""" + + def __init__(self, build_name, **kwargs): + prop = kwargs.get('properties', {}) + prop['skip_gclient'] = True + if 'properties' not in kwargs: + kwargs['properties'] = prop + self._executor = kwargs['executor'] + base_recipe.BaseRecipe.__init__(self, **kwargs) + + self._build_name = BUILD_CONFIGS[build_name]['build_name'] + self._board = BUILD_CONFIGS[build_name]['board'] + + def _get_clean_dir(self): + if 'bootloader' in self._build_name: + return 'gotham/source/bootloader' + if 'factory' in self._build_name: + return 'gotham/source/fct' + if 'rma-unlock' in self._build_name: + return 'gotham/source/rma_unlock' + return 'gotham/source/app' + + def get_steps(self): + clean_dir = self._get_clean_dir() + requirements_path = os.path.join('tools/build_tools/', 'requires.txt') + gotham_python_packages = 'team-gotham/python_packages' + + steps = [] + + # TODO(b/147378899, b/147672428) include landmine support + if self.build_system == 'catabuilder': + steps.append(make_clean_step.MakeCleanStep( + clean_dir=clean_dir, **self._step_kwargs)) + + steps.extend([ + py_env_setup_step.PyEnvSetupStep( + local_packages_dir=gotham_python_packages, + py3=True, + requirements_path=requirements_path, + requirements_project='gotham-cr/gotham', + **self._step_kwargs), + gotham_build_step.GothamBuildStep( + build_name=self._build_name, + board=self._board, + name='build', + cwd='gotham/tools/buildbot/', + **self._step_kwargs) + ]) + + return steps +
diff --git a/cq/scripts/slave/recipe/include_what_you_use.py b/cq/scripts/slave/recipe/include_what_you_use.py new file mode 100644 index 0000000..5205734 --- /dev/null +++ b/cq/scripts/slave/recipe/include_what_you_use.py
@@ -0,0 +1,98 @@ +"""Recipe for giving include-what-you-use (iwyu) suggestions on the given build.""" + +# TODO(mingcl): This recipe is WIP + +import logging +from slave import base_recipe +from slave import base_step +from slave.step import include_what_you_use_step +from slave.step import compdb_gen_step +from slave.step import cast_shell_step +from slave.step import unittest_step +from slave.recipe import clang_builder + +# Note that the keys are Gerrit project names. +# TODO(mingcl): Allow configuring build-specific filters to avoid reporting +# duplicate clang-tidy suggestions from different builds. +PROJECT_CONFIGS = { + 'chromecast/internal': { + 'deny_list_filter': [ + r'vendor/media/google3/(.*)', 'android/prebuilt', + r'(.*)/third_party/(.*)' + ] + }, +} + +BUILD_CONFIGS = { + 'audioassistant_x64_eng_iwyu': { + 'build_args_product': 'audioassistant_x64_eng', + 'build_args_official': False, + # TODO(b/145840052): Remove once the build is fast enough. + 'timeout_secs_build_gtests': 5 * 60 * 60, + # TODO(b/148885147) Remove params below + 'build_branding': 'chrome', + 'build_product': 'audio', + 'build_flavor': 'Debug', + 'build_arch': 'clang', + 'enable_assistant': True, + 'run_gtests': False, + }, +} + +# The name of build directory used by actual build recipe. +# Since the build directory name could change when the build recipe/script get +# changed, the best we can do is to update this dictionary when needed. +# This should be fine since clang tidy check is non-blocking. +BUILD_DIRECTORIES = { + 'audioassistant_x64_eng_iwyu': 'out_clang_audio_gn/Debug/', +} + +def GetValidBuildNames(): + return [ + 'audioassistant_x64_eng_iwyu', + ] + + +def CreateRecipe(build_name: str, **kwargs): + """Builds a recipe object.""" + # Extracts default_properties from build config and adds it to the overall + # properties in kwargs. + config = BUILD_CONFIGS[build_name] + return ClangTidyRecipe( + build_name, + build_config=config, + build_dir=BUILD_DIRECTORIES[build_name], + **kwargs) + +class ClangTidyRecipe(base_recipe.BaseRecipe): + """Recipe to clang-tidy a change.""" + + def __init__(self, build_name, build_config, build_dir, **kwargs): + base_recipe.BaseRecipe.__init__( + self, enable_build_accelerator=True, **kwargs) + self._properties = kwargs.get('properties', {}) + self._build_name = build_name + self._build_config = build_config + self._build_dir = build_dir + self._builder_kwargs = kwargs + + def get_steps(self): + allow_list_filter = PROJECT_CONFIGS.get(self._properties['patch_project'], + {}).get('allow_list_filter', None) + deny_list_filter = PROJECT_CONFIGS.get(self._properties['patch_project'], + {}).get('deny_list_filter', None) + + # Build cast shell and unittests to generate necessary header files + build_steps = clang_builder.ClangRecipe( + self._build_config, **self._builder_kwargs).get_steps() + + return build_steps + [ + # Generate compilation database from the build directory. + compdb_gen_step.CompdbGenStep( + build_dir=self._build_dir, **self._step_kwargs), + # Then iwyu can use the compilation database to analyze the code + include_what_you_use_step.IncludeWhatYouUseStep( + allow_list_filter=allow_list_filter, + deny_list_filter=deny_list_filter, + **self._step_kwargs), + ]
diff --git a/cq/scripts/slave/recipe/junit_builder.py b/cq/scripts/slave/recipe/junit_builder.py new file mode 100644 index 0000000..1380e1c --- /dev/null +++ b/cq/scripts/slave/recipe/junit_builder.py
@@ -0,0 +1,107 @@ +"""Recipe for building and running JUnit tests.""" +from slave import base_recipe +from slave.step import unittest_step, jacoco_coverage_processing_step + +BUILD_BRANDING = 'chrome' +BUILD_ARCH = 'x86' +BUILD_FLAVOR = 'Release' +BUILD_PRODUCT = 'android' + +# This is needed to override the "DEFAULT_MANIFEST_STRING" in test_generator.py +# by adding the chromium/tools/depot_tools project. +SAMPLE_MANIFEST_STRING = """ +<?xml version="1.0" encoding="UTF-8"?> +<manifest> + <remote fetch="https://chromium.googlesource.com/" name="chromium" review="https://chromium-review.googlesource.com/"/> + <remote fetch="https://eureka-internal.googlesource.com/" name="eureka" review="sso://eureka-internal"/> + <remote fetch="https://github.com/" name="github"/> + + <default revision="master"/> + + <project name="chromium/src" remote="eureka" revision="unfork_m43"/> + <project name="chromium/tools/depot_tools" remote="chromium"/> + <project name="chromiumos/chromite" path="chromite/chromite" remote="chromium"/> + <project name="chromiumos/third_party/autotest" path="autotest" remote="chromium"/> + <project name="continuous-tests" remote="eureka"/> + <project name="fake/unittest" remote="eureka"/> + <project name="fragglerock" remote="eureka"/> + <project name="prebuilt/toolchain" path="toolchain" remote="eureka"/> + <project name="google/sprockets" path="test/sprockets" remote="github"/> + <project name="test" remote="eureka"/> + <project name="chromecast/internal" path="chromium/src/chromecast/internal" remote="eureka"/> + <project name="chromecast/internal/voice_ui" path="chromium/src/chromecast/internal/chirp" remote="eureka"/> + <project name="vendor/amlogic" remote="eureka"/> + <project name="vendor/marvell" remote="eureka"/> +</manifest> +""" + +BUILD_CONFIGS = { + 'junit_androidtv': { + 'build_args_product': 'atv_x86_user', + 'build_args_official': False, + 'code_coverage': True, + }, + 'junit_soba': { + 'build_args_product': 'soba_arm_internal', + 'build_args_official': False, + 'code_coverage': True, + }, + 'junit_udon': { + 'build_args_product': 'udon_x64_user', + 'build_args_official': False, + 'code_coverage': True, + }, +} + + +def GetValidBuildNames(): + return BUILD_CONFIGS.keys() + + +def CreateRecipe(build_name: str, **kwargs): + """Builds a recipe object.""" + config = BUILD_CONFIGS[build_name] + return JunitRecipe(config, **kwargs) + +class JunitRecipe(base_recipe.BaseRecipe): + """Recipe to build and run JUnit tests.""" + + def __init__(self, config, **kwargs): + base_recipe.BaseRecipe.__init__( + self, enable_build_accelerator=True, **kwargs) + self._config = config + + def get_steps(self): + build_args_product = self._config['build_args_product'] + build_args_official = self._config['build_args_official'] + code_coverage = self._config['code_coverage'] + + steps = [] + steps += [ + unittest_step.BuildAffectedUnitTestsStep( + BUILD_BRANDING, BUILD_ARCH, BUILD_PRODUCT, + BUILD_FLAVOR, enable_assistant=False, sanitizer=None, + build_args_product=build_args_product, + build_args_official=build_args_official, + halt_on_failure=True, junit=True, + code_coverage=code_coverage, **self._step_kwargs), + unittest_step.RunAffectedUnitTestsStep( + BUILD_BRANDING, BUILD_ARCH, BUILD_PRODUCT, BUILD_FLAVOR, + report_url='', recipe_steps=steps, sanitizer=None, + build_args_product=build_args_product, + build_args_official=build_args_official, + enable_network_service=False, junit=True, **self._step_kwargs), + ] + + # If code coverage is enabled we must process coverage + # files and generate a report. + if code_coverage: + steps.append( + jacoco_coverage_processing_step.JacocoCoverageProcessingStep( + BUILD_BRANDING, BUILD_ARCH, BUILD_PRODUCT, BUILD_FLAVOR, + 'coverage', build_args_product=build_args_product, + build_args_official=build_args_official, **self._step_kwargs + ) + ) + + return steps
diff --git a/cq/scripts/slave/recipe/libassistant_sdk_validator.py b/cq/scripts/slave/recipe/libassistant_sdk_validator.py new file mode 100644 index 0000000..a5f5c9d --- /dev/null +++ b/cq/scripts/slave/recipe/libassistant_sdk_validator.py
@@ -0,0 +1,50 @@ +"""Recipe to validate libassistant sdk code on the given patch.""" +from slave import base_recipe +from slave.step import libassistant_sdk_step as sdk_step + +# pylint: disable=line-too-long +SAMPLE_MANIFEST_STRING = """ +<?xml version="1.0" encoding="UTF-8"?> +<manifest> + <remote fetch="https://libassistant-internal.googlesource.com/" name="libassistant" review="https://libassistant-internal-review.googlesource.com/"/> + + <default revision="master"/> + + <project name="standalone/src" path="src" remote="libassistant"/> + <project name="standalone/deps" path="src/deps" remote="libassistant"/> + <project name="libassistant/contrib" path="src/libassistant/contrib" remote="libassistant"/> + <project name="libassistant/shared" path="src/libassistant/shared" remote="libassistant"/> + <project name="libassistant/internal" path="src/libassistant/internal" remote="libassistant"/> + <project name="libassistant/internal/third_party" path="src/libassistant/internal/third_party" remote="libassistant"/> +</manifest> +""" +# pylint: enable=line-too-long + +DEFAULT_PROPERTIES = {'gclient_root': 'src'} + + +def GetValidBuildNames(): + return ['validate_libassistant_sdk'] + + +def CreateRecipe(build_name: str, **kwargs): + del build_name + return LibassistantSdkRecipe(**kwargs) + + +class LibassistantSdkRecipe(base_recipe.BaseRecipe): + """Recipe to validate libassistant sdk.""" + + def __init__(self, **kwargs): + base_recipe.BaseRecipe.__init__(self, **kwargs) + # we don't want to run this recipe in CB + assert self.build_system == 'cq' + + self._step_kwargs['properties'] = dict( + list(DEFAULT_PROPERTIES.items()) + + list(self._step_kwargs.get('properties', {}).items()) + ) + + def get_steps(self): + return [sdk_step.SdkValidationStep(**self._step_kwargs)] +
diff --git a/cq/scripts/slave/recipe/luci_recipe_runner.py b/cq/scripts/slave/recipe/luci_recipe_runner.py new file mode 100644 index 0000000..5dc52d6 --- /dev/null +++ b/cq/scripts/slave/recipe/luci_recipe_runner.py
@@ -0,0 +1,130 @@ +"""Recipe for running LUCI recipe tests.""" +import logging +import os + +from slave import base_recipe +from slave import base_step +from slave.step import cipd_upload_step +from slave.step import luci_recipe_step +from slave.step import shell_step + +from slave.test import test_generator + +PROJECT_CONFIGS = { + 'test': { + # Path to the desired recipes.py script. + 'script': 'swarming/recipes/recipes.py', + # Path to the recipes.cfg file for the recipe package. + 'package': 'infra/config/recipes.cfg', + # luci_recipe_bundle only. Desired out dir for generated bundle. + 'bundle': 'swarming/recipes/bundle', + # luci_recipe_bundle only. Path to the cipd def for the recipe package. + 'cipd_cfg': 'swarming/recipes/cipd.yaml', + 'cipd_refs': ['staging'], + 'test_retries': 0, + }, + # Gazoo recipes. + # nest-internal + 'gazoo/infra': { + 'script': 'recipes/recipes.py', + 'package': 'infra/config/recipes.cfg', + 'bundle': 'recipes/bundle', + 'cipd_cfg': 'recipes/cipd.yaml', + 'cipd_refs': ['gazoo-staging'], + # Adding retries for flaky coverage report (b/145263501). + 'test_retries': 4, + }, +} + +BUILD_CONFIGS = { + 'luci_recipe_test': { + 'project': None, # Project provided by CQ via `patch_project`. + 'upload_to_cipd': False, + }, + 'gazoo_recipes_upload': { + 'project': 'gazoo/infra', + 'upload_to_cipd': True, + }, +} + + +def GetValidBuildNames(): + return list(BUILD_CONFIGS.keys()) + + +def CreateRecipe(build_name: str, **kwargs): + return LUCIRecipeRecipe(build_name, **kwargs) + + +class DoNothingStep(base_step.BaseStep): + """Does nothing.""" + def __init__(self, msg, **kwargs): + """Creates a JsonCheckStep instance. + Args: + **kwargs: Any additional args to pass to BaseStep. + """ + base_step.BaseStep.__init__(self, name='nothing to do here.', **kwargs) + self._msg = msg + + def run(self): + """Print a message and return.""" + logging.info(self._msg) + return True + + +class LUCIRecipeRecipe(base_recipe.BaseRecipe): + """Recipe to run LUCI recipe functions.""" + + def __init__(self, build_name, **kwargs): + super(LUCIRecipeRecipe, self).__init__(**kwargs) + self._build_name = build_name + + def get_steps(self): + build_config = BUILD_CONFIGS[self._build_name] + if build_config.get('project'): + # Running on CB. Set patch_project via BUILD_CONFIGS. + self._properties['patch_project'] = build_config['project'] + if not PROJECT_CONFIGS.get(self._properties['patch_project']): + return [DoNothingStep('Project {} not in PROJECT_CONFIGS.', + **self._step_kwargs)] + project_config = PROJECT_CONFIGS[self._properties['patch_project']] + script_path = project_config['script'] + package_path = project_config['package'] + test_retries = project_config['test_retries'] + steps = [ + luci_recipe_step.LUCIRecipeTestStep( + script_path, + package_path, + test_retries, + name='Test recipes', + **self._step_kwargs), + ] + + if build_config.get('upload_to_cipd'): + bundle_path = project_config['bundle'] + cipd_path = project_config['cipd_cfg'] + cipd_refs = project_config['cipd_refs'] + cleanup_cmd = ['rm', '-rf', bundle_path] + steps.extend([ + shell_step.ShellStep( + name='Ensure bundle dir does not exist', + command=cleanup_cmd, + **self._step_kwargs), + luci_recipe_step.LUCIRecipeBundleStep( + script_path, + package_path, + bundle_path, + name='Bundle recipes', + **self._step_kwargs), + cipd_upload_step.CIPDUploadStep( + os.path.join(self._properties['patch_project'], cipd_path), + refs=cipd_refs, + **self._step_kwargs), + shell_step.ShellStep( + name='Cleanup bundle dir', + command=cleanup_cmd, + **self._step_kwargs) + ]) + + return steps +
diff --git a/cq/scripts/slave/recipe/lucicfg.py b/cq/scripts/slave/recipe/lucicfg.py new file mode 100644 index 0000000..cfa5b37 --- /dev/null +++ b/cq/scripts/slave/recipe/lucicfg.py
@@ -0,0 +1,23 @@ +"""Recipe for running lucicfg validation.""" +from slave import base_recipe +from slave.step import lucicfg_step + + +def GetValidBuildNames(): + return ['lucicfg_validate'] + + +def CreateRecipe(build_name: str, **kwargs): + del build_name + return LucicfgRecipe(**kwargs) + + +class LucicfgRecipe(base_recipe.BaseRecipe): + """Recipe to run lucicfg validation.""" + + def get_steps(self): + return [ + lucicfg_step.FindConfigsStep(**self._step_kwargs), + lucicfg_step.LucicfgValidateStep(**self._step_kwargs) + ] +
diff --git a/cq/scripts/slave/recipe/ml_framework_sanitizer.py b/cq/scripts/slave/recipe/ml_framework_sanitizer.py new file mode 100644 index 0000000..2b55547 --- /dev/null +++ b/cq/scripts/slave/recipe/ml_framework_sanitizer.py
@@ -0,0 +1,105 @@ +"""Recipe for running asan on ml_framwork x86 unittests.""" +import os + +from slave import base_recipe +from slave.step import gn_step +from slave.step import ninja_step +from slave.step import sanitizer_unittest_step + +BUILD_CONFIGS = { + 'ml_framework_x64_asan': { + 'sanitizer': 'asan', + 'build_args_product' : 'asan_x64_eng', + 'build_args' : 'enable_ml_framework=true is_debug=true ' + 'chromecast_branding="google"', + 'runtime_flags' : '', + }, + 'ml_framework_x64_tsan': { + 'sanitizer': 'tsan', + 'build_args_product' : 'tsan_x64_eng', + 'build_args' : 'enable_ml_framework=true ' + 'chromecast_branding="google"', + 'runtime_flags' : '', + }, + 'ml_framework_x64_msan': { + 'sanitizer': 'msan', + 'build_args_product' : 'msan_x64_eng', + 'build_args' : 'enable_ml_framework=true ' + 'chromecast_branding="google"', + 'runtime_flags' : '', + }, + 'ml_framework_x64_ubsan': { + 'sanitizer': 'ubsan', + 'build_args_product' : 'ubsan_x64', + 'build_args' : 'enable_ml_framework=true', + 'runtime_flags' : ' --single-process-tests', + }, +} + + +def GetValidBuildNames(): + return list(BUILD_CONFIGS.keys()) + + +def CreateRecipe(build_name: str, **kwargs): + config = BUILD_CONFIGS[build_name] + return MlFrameworkAsanRecipe(build_name, config, **kwargs) + + +class MlFrameworkAsanRecipe(base_recipe.BaseRecipe): + """This recipe runs the ml_framework unittests with ASAN/LSAN enabled.""" + def __init__(self, build_name, config, **kwargs): + base_recipe.BaseRecipe.__init__( + self, enable_build_accelerator=True, **kwargs) + self._config = config + self._build_name = build_name + + def get_steps(self): + steps = [] + cwd = os.getcwd() + setup_steps = self.get_setup_steps() + chromium_root = setup_steps[0].get_project_path('chromium/src') + out_dir = os.path.join( + chromium_root, + 'out_{}'.format(self._build_name), + 'release') + + gn_gen_step = gn_step.GnGenStep( + build_args_product=self._config['build_args_product'], + build_args=[self._config['build_args']], + out_dir=out_dir, + halt_on_failure=True, + cwd=cwd, + **self._step_kwargs + ) + steps.append(gn_gen_step) + gn_args_step = gn_step.GnArgsStep( + out_dir=out_dir, + cwd=cwd, + halt_on_failure=True, + **self._step_kwargs + ) + steps.append(gn_args_step) + + ninja_build_step = ninja_step.NinjaStep( + out_dir=out_dir, + target='ml_framework_unittests', + cwd=cwd, + jobs=64, + halt_on_failure=True, + **self._step_kwargs + ) + steps.append(ninja_build_step) + + kwargs = self._step_kwargs + kwargs['unittest_prefix_filter'] = 'ml_' + sanitizer_test_step = sanitizer_unittest_step.SanitizerUnitTestShellStep( + name='ml_framework_unittests', + command=['./ml_framework_unittests' + self._config['runtime_flags']], + directory=out_dir, + sanitizer=self._config['sanitizer'], + halt_on_failure=True, + **kwargs + ) + steps.append(sanitizer_test_step) + return steps
diff --git a/cq/scripts/slave/recipe/null.py b/cq/scripts/slave/recipe/null.py new file mode 100644 index 0000000..44fe16e --- /dev/null +++ b/cq/scripts/slave/recipe/null.py
@@ -0,0 +1,19 @@ +""" +Awesome recipe, that does nothing. +""" + +from slave import base_recipe + +def GetValidBuildNames(): + return ['null', 'vaapp-test'] + +def CreateRecipe(build_name: str, **kwargs): + return NullRecipe(**kwargs) + +class NullRecipe(base_recipe.BaseRecipe): + def __init__(self, **kwargs): + base_recipe.BaseRecipe.__init__( + self, enable_build_accelerator=False, **kwargs) + + def get_steps(self): + return [] \ No newline at end of file
diff --git a/cq/scripts/slave/recipe/ota_builder.py b/cq/scripts/slave/recipe/ota_builder.py new file mode 100644 index 0000000..3be023c --- /dev/null +++ b/cq/scripts/slave/recipe/ota_builder.py
@@ -0,0 +1,1189 @@ +"""Recipe for running a ota build on the given patch.""" +import os + +from helpers import branch_utils +from helpers import gcs_utils +from helpers import repo_utils + +from slave import base_recipe +from slave.step import gcs_upload_step +from slave.step import gn_check_step +from slave.step import host_tests_step +from slave.step import landmine_step +from slave.step import make_clean_step +from slave.step import ota_build_tests_step +from slave.step import ota_factory_tool_step +from slave.step import ota_fct_step +from slave.step import ota_oss_step +from slave.step import ota_resign_step +from slave.step import ota_step +from slave.step import ota_strip_binaries_step +from slave.step import partner_build_check_step +from slave.test import test_generator + +PHOENIX_SCHEMA_BUILDS = [ + 'elaine-eng', # 1.48_efct + 'elaine-user', # 1.48_efct + 'gq-eng', # 1.49qfsi + 'gq-user', # 1.49qfsi + 'newman-eng', # 1.38nf + 'newman-user', # 1.38nf + 'nq-eng', # 1.49qfsi + 'nq-user', # 1.49qfsi + 'valens-eng', # 1.41 + 'valens-user', # 1.41 + 'vento-eng', # 1.40fsi + 'vento-user', # 1.40fsi +] + +BUILD_CONFIGS = { + 'anchovy-eng': { + 'build_flavor': + 'release', + 'resign': + ota_resign_step.EUREKA_RESIGN, + 'partner_bucket': [ + 'cast-partner-marvell-internal', + 'cast-partner-synaptics-internal', + ], + }, + 'anchovy-user': { + 'build_flavor': + 'release', + 'resign': + ota_resign_step.EUREKA_RESIGN, + 'partner_bucket': [ + 'cast-partner-marvell-internal', + 'cast-partner-synaptics-internal', + ], + }, + 'assistantdefault-eng': { + 'build_flavor': 'release', + 'resign': ota_resign_step.ASSISTANTDEFAULT_RESIGN, + 'partner_bucket': ['cast-partner-gva'], + 'upload_libassisant_arch': 'arm', + }, + 'assistantdefault-user': { + 'build_flavor': 'release', + 'resign': ota_resign_step.ASSISTANTDEFAULT_RESIGN, + 'partner_bucket': ['cast-partner-gva'], + 'upload_libassisant_arch': 'arm', + }, + 'assistantdefault-1led-eng': { + 'build_flavor': 'release', + 'resign': ota_resign_step.ASSISTANTDEFAULT_RESIGN, + 'partner_bucket': ['cast-partner-gva'], + }, + 'assistantdefault-1led-user': { + 'build_flavor': 'release', + 'resign': ota_resign_step.ASSISTANTDEFAULT_RESIGN, + 'partner_bucket': ['cast-partner-gva'], + }, + 'assistantdefault-partner-user': { + 'build_flavor': 'release', + 'resign': ota_resign_step.ASSISTANTDEFAULT_RESIGN, + 'partner_bucket': ['cast-partner-gva'], + 'upload_libassisant_arch': 'arm', + }, + 'audiodefault-eng': { + 'build_flavor': 'release', + 'partner_bucket': ['cast-partner-gva'], + }, + 'audiodefault-partner-eng': { + 'build_flavor': 'release', + 'partner_bucket': ['cast-partner-gva'], + }, + 'audiodefault-user': { + 'build_flavor': 'release', + 'partner_bucket': ['cast-partner-gva'], + }, + 'audiodefault_dynamic-eng': { + 'build_flavor': 'release', + 'partner_bucket': ['cast-partner-gva'], + }, + 'audiodefault_dynamic-user': { + 'build_flavor': 'release', + 'partner_bucket': ['cast-partner-gva'], + }, + 'biggie-eng': { + 'build_flavor': 'release', + 'resign': ota_resign_step.BIGGIE_RESIGN, + 'factory': ota_resign_step.BIGGIE_FACTORY, + 'partner_bucket': ['cast-partner-amlogic-internal'], + 'upload_libassisant_arch': 'arm64', + }, + 'biggie-user': { + 'build_flavor': 'release', + 'resign': ota_resign_step.BIGGIE_RESIGN, + 'partner_bucket': ['cast-partner-amlogic-internal'], + 'upload_libassisant_arch': 'arm64', + 'branch_extra_params': { + '1.40rd': ['RETAIL_DEMO_BUILD=true'], + }, + }, + 'bowie-eng': { + 'build_flavor': + 'release', + 'board_name': + 'bowie-p0', + 'resign': + ota_resign_step.BOWIE_RESIGN, + 'factory': + ota_resign_step.BOWIE_FACTORY, + 'usbstick': + ota_resign_step.BOWIE_USBSTICK, + 'test_board_name': + 'bowie-p0', + 'partner_bucket': [ + 'cast-partner-marvell-internal', + 'cast-partner-synaptics-internal', + ], + }, + 'bowie-user': { + 'build_flavor': + 'release', + 'board_name': + 'bowie-p0', + 'resign': + ota_resign_step.BOWIE_RESIGN, + 'test_board_name': + 'bowie-p0', + 'partner_bucket': [ + 'cast-partner-marvell-internal', + 'cast-partner-synaptics-internal', + ], + }, + 'brezza-eng': { + 'build_flavor': 'release', + 'resign': ota_resign_step.BREZZA_RESIGN, + 'factory': ota_resign_step.BREZZA_FACTORY, + 'factory_tool': ota_resign_step.BREZZA_FACTORY_TOOL, + 'usbstick': ota_resign_step.BREZZA_USBSTICK, + 'partner_bucket': ['cast-partner-qualcomm-internal'], + 'skip_ota_tests': True, + }, + 'brezza-user': { + 'build_flavor': 'release', + 'resign': ota_resign_step.BREZZA_RESIGN, + 'partner_bucket': ['cast-partner-qualcomm-internal'], + 'skip_ota_tests': True, + }, + 'brezza-partner-eng': { + 'build_flavor': 'release', + 'resign': ota_resign_step.BREZZA_RESIGN, + 'partner_bucket': ['cast-partner-qualcomm-internal'], + 'branch_extra_params': { + 'master': ['PARTNER_BUILD=true'], + }, + 'skip_ota_tests': True, + }, + 'caprica-eng': { + 'build_flavor': 'release', + 'resign': ota_resign_step.CAPRICA_RESIGN, + 'factory': ota_resign_step.CAPRICA_FACTORY, + 'usbstick': ota_resign_step.CAPRICA_USBSTICK, + 'partner_bucket': ['cast-partner-synaptics-internal'], + }, + 'caprica-user': { + 'build_flavor': 'release', + 'resign': ota_resign_step.CAPRICA_RESIGN, + 'partner_bucket': ['cast-partner-synaptics-internal'], + }, + 'caprica-yeti-eng': { + 'build_flavor': 'release', + 'resign': ota_resign_step.CAPRICA_RESIGN, + 'factory': ota_resign_step.CAPRICA_FACTORY, + }, + 'caprica-yeti-user': { + 'build_flavor': 'release', + 'resign': ota_resign_step.CAPRICA_RESIGN, + }, + 'chorizo-eng': { + 'build_flavor': + 'release', + 'resign': + ota_resign_step.CHORIZO_RESIGN, + 'partner_bucket': [ + 'cast-partner-marvell-internal', + 'cast-partner-synaptics-internal', + ], + }, + 'chorizo-user': { + 'build_flavor': + 'release', + 'max_ota_size': + 104000000, + 'resign': + ota_resign_step.CHORIZO_RESIGN, + 'partner_bucket': [ + 'cast-partner-marvell-internal', + 'cast-partner-synaptics-internal', + ], + }, + 'chromeos_armv7a-eng': { + 'build_flavor': 'release', + 'board_name': 'sirocco-b1', + 'build_usonia_daemon': True, + 'build_thread_telemetry_service_cros': True, + 'target_name': 'sirocco-eng', + 'skip_ota_tests': True, + }, + 'chromeos_armv7a-user': { + 'build_flavor': 'release', + 'board_name': 'sirocco-b1', + 'build_usonia_daemon': True, + 'build_thread_telemetry_service_cros': True, + 'target_name': 'sirocco-user', + 'skip_ota_tests': True, + }, + 'core_runtime-eng': { + 'build_flavor': 'release', + 'partner_bucket': ['core-runtime-cb-upload'], + }, + 'core_runtime-user': { + 'build_flavor': 'release', + 'partner_bucket': ['core-runtime-cb-upload'], + }, + 'dragonfly-eng': { + 'build_flavor': 'release', + 'partner_bucket': ['cast-partner-sigmadesign-tv'], + }, + 'dragonfly-user': { + 'build_flavor': 'release', + 'partner_bucket': ['cast-partner-sigmadesign-tv'], + }, + 'elaine-eng': { + 'build_flavor': 'release', + 'resign': ota_resign_step.ELAINE_RESIGN, + 'factory': ota_resign_step.ELAINE_FACTORY, + 'usbstick': ota_resign_step.ELAINE_USBSTICK, + 'clean_steps': [], + 'partner_bucket': [ + 'cast-partner-amlogic-internal', 'cast-partner-broadcom-internal' + ], + 'eng_build': True, + }, + 'elaine-user': { + 'build_flavor': + 'release', + 'resign': + ota_resign_step.ELAINE_RESIGN, + 'clean_steps': [], + 'partner_bucket': [ + 'cast-partner-amlogic-internal', 'cast-partner-broadcom-internal' + ], + }, + 'elaine-fuchsia-eng': { + 'build_flavor': 'release', + 'board_name': 'elaine-b3', + 'resign': ota_resign_step.ELAINE_FUCHSIA_RESIGN, + 'clean_steps': [], + 'default_properties': { + 'fuchsia_sync': True, + }, + 'eng_build': True, + }, + 'elaine-fuchsia-user': { + 'build_flavor': 'release', + 'board_name': 'elaine-b3', + 'resign': ota_resign_step.ELAINE_FUCHSIA_RESIGN, + 'clean_steps': [], + 'default_properties': { + 'fuchsia_sync': True, + }, + }, + 'estelle-eng': { + 'build_flavor': + 'release', + 'resign': + ota_resign_step.ESTELLE_RESIGN, + 'factory': + ota_resign_step.ESTELLE_FACTORY, + 'usbstick': + ota_resign_step.ESTELLE_USBSTICK, + 'partner_bucket': [ + 'cast-partner-amlogic-internal', 'cast-partner-broadcom-internal' + ], + }, + 'estelle-health-eng': { + 'build_flavor': 'release', + 'resign': ota_resign_step.ESTELLE_RESIGN, + 'factory': ota_resign_step.ESTELLE_FACTORY, + }, + 'estelle-health-user': { + 'build_flavor': 'release', + 'resign': ota_resign_step.ESTELLE_RESIGN, + }, + 'estelle-ml_framework-eng': { + 'build_flavor': 'release', + 'resign': ota_resign_step.ESTELLE_RESIGN, + }, + 'estelle-opal-eng': { + 'build_flavor': 'release', + 'resign': ota_resign_step.ESTELLE_RESIGN, + 'factory': ota_resign_step.ESTELLE_FACTORY, + }, + 'estelle-opal-user': { + 'build_flavor': 'release', + 'resign': ota_resign_step.ESTELLE_RESIGN, + }, + 'estelle-fuchsia-eng': { + 'build_flavor': 'release', + 'resign': ota_resign_step.ESTELLE_FUCHSIA_RESIGN, + 'default_properties': { + 'fuchsia_sync': True, + }, + }, + 'estelle-fuchsia-user': { + 'build_flavor': 'release', + 'resign': ota_resign_step.ESTELLE_FUCHSIA_RESIGN, + 'default_properties': { + 'fuchsia_sync': True, + }, + }, + 'estelle-sdm-eng': { + 'build_flavor': 'release', + 'resign': ota_resign_step.ESTELLE_RESIGN, + 'factory': ota_resign_step.ESTELLE_FACTORY, + }, + 'estelle-sdm-user': { + 'build_flavor': 'release', + 'resign': ota_resign_step.ESTELLE_RESIGN, + }, + 'estelle-user': { + 'build_flavor': + 'release', + 'max_ota_size': + 170000000, + 'resign': + ota_resign_step.ESTELLE_RESIGN, + 'partner_bucket': [ + 'cast-partner-amlogic-internal', 'cast-partner-broadcom-internal' + ], + }, + 'korlan-eng': { + 'build_flavor': 'release', + 'board_name': 'korlan-b1', + 'max_ota_size': 43000000, + 'resign': ota_resign_step.KORLAN_RESIGN, + 'factory': ota_resign_step.KORLAN_FACTORY, + 'usbstick': ota_resign_step.KORLAN_USBSTICK, + 'factory_tool': ota_resign_step.KORLAN_FACTORY_TOOL, + 'partner_bucket': ['cast-partner-amlogic-internal'], + }, + 'korlan-user': { + 'build_flavor': 'release', + 'resign': ota_resign_step.KORLAN_RESIGN, + 'partner_bucket': ['cast-partner-amlogic-internal'], + }, + 'lumia-eng': { + 'build_flavor': 'release', + 'resign': ota_resign_step.LUMIA_RESIGN, + 'partner_bucket': ['cast-partner-amlogic-internal'], + }, + 'lumia-user': { + 'build_flavor': 'release', + 'resign': ota_resign_step.LUMIA_RESIGN, + 'partner_bucket': ['cast-partner-amlogic-internal'], + }, + 'gq-eng': { + 'build_flavor': 'release', + 'resign': ota_resign_step.GQ_RESIGN, + 'factory': ota_resign_step.GQ_FACTORY, + 'usbstick': ota_resign_step.GQ_USBSTICK, + 'partner_bucket': ['cast-partner-amlogic-internal'], + 'branch_extra_params': { + '1.49qfsi_retail': ['RETAIL_DEMO_BUILD=true'], + }, + 'check_camera_targets': True, + 'eng_build': True, + }, + 'gq-user': { + 'build_flavor': 'release', + 'resign': ota_resign_step.GQ_RESIGN, + 'partner_bucket': ['cast-partner-amlogic-internal'], + 'branch_extra_params': { + '1.49qfsi_retail': ['RETAIL_DEMO_BUILD=true'], + }, + 'check_camera_targets': True, + }, + 'mozart-eng': { + 'build_flavor': 'release', + 'partner_bucket': ['cast-partner-mediatek-audio'], + }, + 'mushroom-eng': { + 'build_flavor': 'release', + 'max_ota_size': 115000000, + 'resign': ota_resign_step.MUSHROOM_RESIGN, + 'factory': ota_resign_step.MUSHROOM_FACTORY, + 'usbstick': ota_resign_step.MUSHROOM_USBSTICK, + 'partner_bucket': ['cast-partner-synaptics-internal'], + }, + 'mushroom-sdm-eng': { + 'build_flavor': 'release', + 'resign': ota_resign_step.MUSHROOM_RESIGN, + 'factory': ota_resign_step.MUSHROOM_FACTORY, + }, + 'mushroom-sdm-user': { + 'build_flavor': 'release', + 'resign': ota_resign_step.MUSHROOM_RESIGN, + }, + 'mushroom-user': { + 'build_flavor': 'release', + 'max_ota_size': 115000000, + 'resign': ota_resign_step.MUSHROOM_RESIGN, + 'partner_bucket': ['cast-partner-synaptics-internal'], + 'branch_extra_params': { + '1.40rd': ['RETAIL_DEMO_BUILD=true'], + }, + }, + 'newman-eng': { + 'build_flavor': 'release', + 'board_name': 'newman-b3', + 'resign': ota_resign_step.NEWMAN_RESIGN_ENG, + 'factory': ota_resign_step.NEWMAN_FACTORY, + 'usbstick': ota_resign_step.NEWMAN_USBSTICK, + 'partner_bucket': [ + 'cast-partner-amlogic-internal', 'cast-partner-broadcom-internal' + ], + 'test_board_name': 'newman-b3', + }, + 'newman-eng_legacy': { + 'build_flavor': 'release', + 'board_name': 'newman-b3', + 'resign': ota_resign_step.NEWMAN_RESIGN_ENG, + 'factory': ota_resign_step.NEWMAN_FACTORY, + 'partner_bucket': [ + 'cast-partner-amlogic-internal', 'cast-partner-broadcom-internal' + ], + 'test_board_name': 'newman-b3', + }, + 'newman-fuchsia-eng': { + 'build_flavor': 'release', + 'board_name': 'newman-b3', + 'resign': ota_resign_step.NEWMAN_FUCHSIA_RESIGN, + 'default_properties': { + 'fuchsia_sync': True, + }, + 'test_board_name': 'newman-b3', + }, + 'newman-fuchsia-user': { + 'build_flavor': 'release', + 'board_name': 'newman-b3', + 'resign': ota_resign_step.NEWMAN_FUCHSIA_RESIGN, + 'default_properties': { + 'fuchsia_sync': True, + }, + 'test_board_name': 'newman-b3', + }, + 'newman-fuchsia_rev-eng': { + 'build_flavor': 'release', + 'board_name': 'newman-b3', + 'resign': ota_resign_step.NEWMAN_FUCHSIA_RESIGN, + 'default_properties': { + 'fuchsia_sync': True, + }, + 'test_board_name': 'newman-b3', + }, + 'newman-fuchsia_rev-user': { + 'build_flavor': 'release', + 'board_name': 'newman-b3', + 'resign': ota_resign_step.NEWMAN_FUCHSIA_RESIGN, + 'default_properties': { + 'fuchsia_sync': True, + }, + 'test_board_name': 'newman-b3', + }, + 'newman-user': { + 'build_flavor': 'release', + 'board_name': 'newman-b3', + 'resign': ota_resign_step.NEWMAN_RESIGN, + 'partner_bucket': [ + 'cast-partner-amlogic-internal', 'cast-partner-broadcom-internal' + ], + 'test_board_name': 'newman-b3', + }, + 'newman-modular_comms-user': { + 'build_flavor': 'release', + 'board_name': 'newman-b3', + 'resign': ota_resign_step.NEWMAN_RESIGN, + 'test_board_name': 'newman-b3', + }, + 'nq-eng': { + 'build_flavor': 'release', + 'resign': ota_resign_step.NQ_RESIGN, + 'factory': ota_resign_step.NQ_FACTORY, + 'usbstick': ota_resign_step.NQ_USBSTICK, + 'partner_bucket': ['cast-partner-amlogic-internal'], + 'check_camera_targets': True, + 'eng_build': True, + }, + 'nq-user': { + 'build_flavor': 'release', + 'resign': ota_resign_step.NQ_RESIGN, + 'partner_bucket': ['cast-partner-amlogic-internal'], + 'check_camera_targets': True, + }, + 'np8340-eng': { + 'build_flavor': 'release', + }, + 'np8340-user': { + 'build_flavor': 'release', + }, + 'pepperoni-eng': { + 'build_flavor': + 'release', + 'resign': + ota_resign_step.PEPPERONI_RESIGN, + 'partner_bucket': [ + 'cast-partner-marvell-internal', + 'cast-partner-synaptics-internal', + ], + }, + 'pepperoni-user': { + 'build_flavor': + 'release', + 'resign': + ota_resign_step.PEPPERONI_RESIGN, + 'partner_bucket': [ + 'cast-partner-marvell-internal', + 'cast-partner-synaptics-internal', + ], + }, + 'pineapple-eng': { + 'build_flavor': + 'release', + 'max_ota_size': + 115000000, + 'resign': + ota_resign_step.PINEAPPLE_RESIGN, + 'factory': + ota_resign_step.PINEAPPLE_FACTORY, + 'usbstick': + ota_resign_step.PINEAPPLE_USBSTICK, + 'partner_bucket': [ + 'cast-partner-marvell-internal', + 'cast-partner-synaptics-internal', + ], + }, + 'pineapple-user': { + 'build_flavor': 'release', + 'max_ota_size': 115000000, + 'resign': ota_resign_step.PINEAPPLE_RESIGN, + 'partner_bucket': [ + 'cast-partner-marvell-internal', + 'cast-partner-synaptics-internal', + ], + 'branch_extra_params': { + '1.40rd': ['RETAIL_DEMO_BUILD=true'], + }, + }, + 'pineapple-sdm-eng': { + 'build_flavor': 'release', + 'resign': ota_resign_step.PINEAPPLE_RESIGN, + 'factory': ota_resign_step.PINEAPPLE_FACTORY, + }, + 'pineapple-sdm-user': { + 'build_flavor': 'release', + 'resign': ota_resign_step.PINEAPPLE_RESIGN, + }, + 'prince-demo-eng': { + 'build_flavor': 'release', + 'board_name': 'prince-p2', + 'resign': ota_resign_step.PRINCE_RESIGN, + 'test_board_name': 'prince-p2', + }, + 'prince-demo-user': { + 'build_flavor': 'release', + 'board_name': 'prince-p2', + 'resign': ota_resign_step.PRINCE_RESIGN, + 'test_board_name': 'prince-p2', + }, + 'prince-iot_cast-eng': { + 'build_flavor': + 'release', + 'board_name': + 'prince-p2', + 'resign': + ota_resign_step.PRINCE_RESIGN, + 'factory': + ota_resign_step.PRINCE_FACTORY, + 'usbstick': + ota_resign_step.PRINCE_USBSTICK, + 'factory_tool': + ota_resign_step.PRINCE_FACTORY_TOOL, + 'test_board_name': + 'prince-p2', + 'partner_bucket': [ + 'cast-partner-marvell-internal', + 'cast-partner-synaptics-internal', + ], + }, + 'prince-eng': { + 'build_flavor': + 'release', + 'board_name': + 'prince-p2', + 'resign': + ota_resign_step.PRINCE_RESIGN, + 'factory': + ota_resign_step.PRINCE_FACTORY, + 'usbstick': + ota_resign_step.PRINCE_USBSTICK, + 'factory_tool': + ota_resign_step.PRINCE_FACTORY_TOOL, + 'test_board_name': + 'prince-p2', + 'partner_bucket': [ + 'cast-partner-marvell-internal', + 'cast-partner-synaptics-internal', + ], + }, + 'prince-user': { + 'build_flavor': + 'release', + 'board_name': + 'prince-p2', + 'resign': + ota_resign_step.PRINCE_RESIGN, + 'test_board_name': + 'prince-p2', + 'partner_bucket': [ + 'cast-partner-marvell-internal', + 'cast-partner-synaptics-internal', + ], + }, + 'salami-eng': { + 'build_flavor': + 'release', + 'resign': + ota_resign_step.SALAMI_RESIGN, + 'partner_bucket': [ + 'cast-partner-marvell-internal', + 'cast-partner-synaptics-internal', + ], + }, + 'salami-user': { + 'build_flavor': + 'release', + 'resign': + ota_resign_step.SALAMI_RESIGN, + 'partner_bucket': [ + 'cast-partner-marvell-internal', + 'cast-partner-synaptics-internal', + ], + }, + 'sirocco-eng': { + 'build_flavor': 'release', + 'resign': ota_resign_step.SIROCCO_RESIGN, + 'factory': ota_resign_step.SIROCCO_FACTORY, + 'usbstick': ota_resign_step.SIROCCO_USBSTICK, + 'factory_tool': ota_resign_step.SIROCCO_FACTORY_TOOL, + 'partner_bucket': ['cast-partner-qualcomm-internal'], + 'skip_ota_tests': True, + }, + 'sirocco-user': { + 'build_flavor': 'release', + 'resign': ota_resign_step.SIROCCO_RESIGN, + 'partner_bucket': ['cast-partner-qualcomm-internal'], + 'skip_ota_tests': True, + }, + 'sirocco-partner-eng': { + 'build_flavor': 'release', + 'resign': ota_resign_step.SIROCCO_RESIGN, + 'partner_bucket': ['cast-partner-qualcomm-internal'], + 'branch_extra_params': { + 'master': ['PARTNER_BUILD=true'], + }, + 'skip_ota_tests': True, + }, + 'spencer-eng': { + 'build_flavor': 'release', + 'resign': ota_resign_step.SPENCER_RESIGN, + 'factory': ota_resign_step.SPENCER_FACTORY, + 'usbstick': ota_resign_step.SPENCER_USBSTICK, + 'factory_tool': ota_resign_step.SPENCER_FACTORY_TOOL, + 'partner_bucket': ['cast-partner-amlogic-internal'], + 'check_camera_targets': True, + 'eng_build': True, + }, + 'spencer-user': { + 'build_flavor': 'release', + 'resign': ota_resign_step.SPENCER_RESIGN, + 'partner_bucket': ['cast-partner-amlogic-internal'], + 'check_camera_targets': True, + }, + 'a049-eng': { + 'build_flavor': 'release', + 'resign': ota_resign_step.A049_RESIGN, + 'factory': ota_resign_step.A049_FACTORY, + 'usbstick': ota_resign_step.A049_USBSTICK, + 'factory_tool': ota_resign_step.A049_FACTORY_TOOL, + 'partner_bucket': ['cast-partner-amlogic-internal'], + 'check_camera_targets': True, + 'eng_build': True, + }, + 'a049-user': { + 'build_flavor': 'release', + 'resign': ota_resign_step.A049_RESIGN, + 'partner_bucket': ['cast-partner-amlogic-internal'], + 'check_camera_targets': True, + }, + 'sprinkles-eng': { + 'build_flavor': 'release', + 'board_name': 'sprinkles-korlan', + 'max_ota_size': 43000000, + 'resign': ota_resign_step.SPRINKLES_RESIGN, + 'factory': ota_resign_step.SPRINKLES_FACTORY, + 'usbstick': ota_resign_step.SPRINKLES_USBSTICK, + 'factory_tool': ota_resign_step.SPRINKLES_FACTORY_TOOL, + 'partner_bucket': ['cast-partner-amlogic-internal'], + }, + 'sprinkles-user': { + 'build_flavor': 'release', + 'resign': ota_resign_step.SPRINKLES_RESIGN, + 'partner_bucket': ['cast-partner-amlogic-internal'], + }, + 'steak-eng': { + 'build_flavor': + 'release', + 'resign': + ota_resign_step.STEAK_RESIGN, + 'factory': + ota_resign_step.STEAK_FACTORY, + 'usbstick': + ota_resign_step.STEAK_USBSTICK, + 'partner_bucket': [ + 'cast-partner-marvell-internal', + 'cast-partner-synaptics-internal', + ], + }, + 'steak-user': { + 'build_flavor': + 'release', + 'max_ota_size': + 104000000, + 'resign': + ota_resign_step.STEAK_RESIGN, + 'partner_bucket': [ + 'cast-partner-marvell-internal', + 'cast-partner-synaptics-internal', + ], + }, + 'steak-yeti-eng': { + 'build_flavor': 'release', + 'resign': ota_resign_step.STEAK_RESIGN, + 'factory': ota_resign_step.STEAK_FACTORY, + }, + 'steak-yeti-user': { + 'build_flavor': 'release', + 'resign': ota_resign_step.STEAK_RESIGN, + }, + 'tvdefault-eng': { + 'build_flavor': 'release', + }, + 'tvdefault-user': { + 'build_flavor': 'release', + }, + 'valens-eng': { + 'build_flavor': + 'release', + 'board_name': + 'valens-b1', + 'max_ota_size': + 155000000, + 'resign': + ota_resign_step.VALENS_RESIGN, + 'factory': + ota_resign_step.VALENS_FACTORY, + 'unand': + ota_resign_step.VALENS_UNAND, + 'usbstick': + ota_resign_step.VALENS_USBSTICK, + 'test_board_name': + 'valens-b1', + 'partner_bucket': [ + 'cast-partner-marvell-internal', + 'cast-partner-synaptics-internal', + ], + }, + 'valens-modular_comms-eng': { + 'build_flavor': 'release', + 'board_name': 'valens-b1', + 'max_ota_size': 155000000, + 'resign': ota_resign_step.VALENS_RESIGN, + 'test_board_name': 'valens-b1', + }, + 'valens-user': { + 'build_flavor': + 'release', + 'board_name': + 'valens-b1', + 'max_ota_size': + 130000000, + 'resign': + ota_resign_step.VALENS_RESIGN, + 'test_board_name': + 'valens-b1', + 'partner_bucket': [ + 'cast-partner-marvell-internal', + 'cast-partner-synaptics-internal', + ], + }, + 'vento-eng': { + 'build_flavor': + 'release', + 'board_name': + 'vento-b3', + 'max_ota_size': + 158000000, + 'factory': + ota_resign_step.VENTO_FACTORY, + 'unand': + ota_resign_step.VENTO_UNAND, + 'resign': + ota_resign_step.VENTO_RESIGN, + 'test_board_name': + 'vento-b3', + 'partner_bucket': [ + 'cast-partner-qca-wireless', + 'cast-partner-synaptics-internal', + ], + }, + 'vento-user': { + 'build_flavor': + 'release', + 'board_name': + 'vento-b3', + 'max_ota_size': + 133000000, + 'resign': + ota_resign_step.VENTO_RESIGN, + 'test_board_name': + 'vento-b3', + 'partner_bucket': [ + 'cast-partner-qca-wireless', + 'cast-partner-synaptics-internal', + ], + }, + 'venus-eng': { + 'build_flavor': 'release', + 'resign': ota_resign_step.VENUS_RESIGN, + 'factory': ota_resign_step.VENUS_FACTORY, + 'factory_tool': ota_resign_step.VENUS_FACTORY_TOOL, + 'usbstick': ota_resign_step.VENUS_USBSTICK, + 'partner_bucket': ['cast-partner-amlogic-internal'], + 'check_camera_targets': True, + 'eng_build': True, + }, + 'venus-user': { + 'build_flavor': 'release', + 'resign': ota_resign_step.VENUS_RESIGN, + 'partner_bucket': ['cast-partner-amlogic-internal'], + 'check_camera_targets': True, + }, +} + +SKIP_OTA_TESTS_BRANCH = [ + '1.55sfsi', + '1.57q', +] + +for phoenix_schema_build in PHOENIX_SCHEMA_BUILDS: + BUILD_CONFIGS[phoenix_schema_build.replace('-', ota_step.GANETI_TAG)] = ( + BUILD_CONFIGS[phoenix_schema_build]) + +# TODO(b/117437843) Remove prod after migtation completion +PARTNER_ARCHIVE_BUCKET_STAGING_BUCKET = { + 'prod': 'cast-partner-staging', + 'staging': 'cast-partner-staging', + 'dev': 'cast-partner-dev', +} + +PARTNER_BUILDS = {'audiodefault-eng'} + +OSS_SUPPORT_MIN_BRANCH = '1.10' +OSS_SUPPORT_BUILDER_PREFIX_WHITELIST = 'combined-sdk-kernel-bootloader' + +FACTORY_SUPPORT_MIN_BRANCH = '1.21' +FACTORY_TOOL_SUPPORT_MIN_BRANCH = '1.37' + +CAMERA_TARGET_CHECK_MIN_BRANCH = '1.57' + +USONIA_DAEMON_CHECK_MIN_BRANCH = '1.61' +THREAD_TELEMETRY_SERVICE_CROS_CHECK_MIN_BRANCH = '1.61' + + +def GetValidBuildNames(): + return list(BUILD_CONFIGS.keys()) + + +def CreateRecipe(build_name: str, **kwargs): + """Builds a recipe object.""" + return OtaRecipe(build_name, BUILD_CONFIGS[build_name], **kwargs) + + +class OtaRecipe(base_recipe.BaseRecipe): + """Recipe to run an ota build.""" + + def __init__(self, build_name, build_config, **kwargs): + base_recipe.BaseRecipe.__init__( + self, enable_build_accelerator=True, **kwargs) + self._build_name = build_name + self._build_config = build_config + # Extracts default_properties from build config and adds it to the overall + # properties. + default_properties = build_config.get('default_properties', {}) + self._step_kwargs['properties'] = dict( + list(default_properties.items()) + + list(self._step_kwargs.get('properties', {}).items())) + self._skip_landmine = self.build_system == 'catabuilder' + self._skip_gncheck = self.build_system == 'catabuilder' + + def _oss_run_condition(self): + if self.build_system != 'catabuilder': + return False + if self._builds_usonia_daemon(): + return False + if self._build_name.startswith(OSS_SUPPORT_BUILDER_PREFIX_WHITELIST): + return True + if not self._build_name.endswith('-user'): + return False + + # Here we check whether the existing branch is > the + # OSS_SUPPORT_MIN_BRANCH which has support for OSS on the + # dev side. If there is non-dot-release branch or we are less + # than this supported branch, trivially return. + return (branch_utils.is_release_branch(self._manifest_branch) and + branch_utils.is_branch_equal_to_or_later_than( + self._manifest_branch, OSS_SUPPORT_MIN_BRANCH)) + + def _fct_run_condition(self): + if 'factory' not in self._build_config: + return False + return branch_utils.is_branch_equal_to_or_later_than( + self._manifest_branch, FACTORY_SUPPORT_MIN_BRANCH) + + def _usbstick_run_condition(self): + if 'usbstick' not in self._build_config: + return False + return branch_utils.is_branch_equal_to_or_later_than( + self._manifest_branch, FACTORY_SUPPORT_MIN_BRANCH) + + def _factory_tool_run_condition(self): + if 'factory_tool' not in self._build_config: + return False + return branch_utils.is_branch_equal_to_or_later_than( + self._manifest_branch, FACTORY_TOOL_SUPPORT_MIN_BRANCH) + + def _ota_extra_params(self): + return self._build_config.get( + 'build_extra_params', [] + ) + self._build_config.get('branch_extra_params', {}).get( + self._manifest_branch, [] + ) + + def get_clean_steps(self): + """Builds a list of all clean steps that should be executed by this recipe. + + Returns: + List of slave.base_step.BaseStep commands to be executed. + """ + return [make_clean_step.MakeCleanStep(**self._step_kwargs)] + + def _camera_target_check_condition(self): + return (BUILD_CONFIGS[self._build_name].get('check_camera_targets', False) + and branch_utils.is_branch_equal_to_or_later_than( + self._manifest_branch, CAMERA_TARGET_CHECK_MIN_BRANCH)) + + def _builds_usonia_daemon(self): + return (BUILD_CONFIGS[self._build_name].get('build_usonia_daemon', False) + and branch_utils.is_branch_equal_to_or_later_than( + self._manifest_branch, USONIA_DAEMON_CHECK_MIN_BRANCH)) + + def _builds_thread_telemetry_service_cros(self): + return (BUILD_CONFIGS[self._build_name].get( + 'build_thread_telemetry_service_cros', False) and + branch_utils.is_branch_equal_to_or_later_than( + self._manifest_branch, USONIA_DAEMON_CHECK_MIN_BRANCH)) + + def get_steps(self): + steps = [] + + if not self._skip_landmine: + steps.append(landmine_step.LandmineStep(**self._step_kwargs)) + if not self._skip_gncheck and not self._builds_usonia_daemon() \ + and not self._builds_thread_telemetry_service_cros(): + steps.append( + gn_check_step.GnCheckForOta(self._build_name, **self._step_kwargs)) + + board_name = self._build_config.get('board_name') + apply_dev_signing = self.build_system == 'catabuilder' + max_ota_size = self._build_config.get('max_ota_size') + target_name = self._build_config.get('target_name') + steps.append( + ota_step.OtaStep( + self._build_name, + board_name=board_name, + extra_params=self._ota_extra_params(), + halt_on_failure=True, + max_ota_size=max_ota_size, + target_name=target_name, + **self._step_kwargs)) + + if self._camera_target_check_condition(): + product_name = self._build_name.split('-')[0] + is_eng_build = BUILD_CONFIGS[self._build_name].get('eng_build', False) + steps.append( + ota_step.OtaCameraTargetsStep(product_name, is_eng_build, + **self._step_kwargs)) + + if self._builds_usonia_daemon(): + steps.append( + ota_step.OtaUsoniaDaemonStep(self._build_name, **self._step_kwargs)) + if self._builds_thread_telemetry_service_cros(): + steps.append( + ota_step.ThreadTelemetryServiceCrosStep( + build_name=self._build_name, **self._step_kwargs)) + + if self.build_system == 'catabuilder': + steps.append(ota_step.OtaPropStep(**self._step_kwargs)) + + if self._oss_run_condition(): + steps.append( + ota_oss_step.OtaOssStep( + self._build_name, halt_on_failure=True, **self._step_kwargs)) + + # factory_tools have their own makefiles for compiling + if self._factory_tool_run_condition(): + steps.append( + ota_factory_tool_step.CompileFactoryToolStep( + self._build_name, + self._build_config.get('factory_tool', {}), + halt_on_failure=True, + **self._step_kwargs)) + if self._fct_run_condition(): + steps.append( + ota_fct_step.OtaFctCompileStep( + self._build_name, + self._build_config.get('factory', {}), + halt_on_failure=True, + **self._step_kwargs)) + # Generation of image/board specific FCT images performed by the same + # resign script but from different intermediate source binaries + steps.extend( + ota_resign_step.get_resign_steps( + self._build_name, + resign_config=self._build_config.get('factory'), + build_branch=self._manifest_branch, + apply_dev_signing=apply_dev_signing, + halt_on_failure=True, + **self._step_kwargs)) + steps.extend( + ota_resign_step.get_resign_steps( + self._build_name, + resign_config=self._build_config.get('unand'), + build_branch=self._manifest_branch, + apply_dev_signing=apply_dev_signing, + halt_on_failure=True, + **self._step_kwargs)) + if self._usbstick_run_condition(): + steps.append( + ota_fct_step.OtaFctCompileStep( + self._build_name, + self._build_config.get('usbstick', {}), + name='build usbstick images', + halt_on_failure=True, + **self._step_kwargs)) + steps.extend( + ota_resign_step.get_resign_steps( + self._build_name, + resign_config=self._build_config.get('usbstick'), + build_branch=self._manifest_branch, + apply_dev_signing=apply_dev_signing, + halt_on_failure=True, + **self._step_kwargs)) + steps.extend( + ota_resign_step.get_resign_steps( + self._build_name, + resign_config=self._build_config.get('resign'), + build_branch=self._manifest_branch, + apply_dev_signing=apply_dev_signing, + halt_on_failure=True, + **self._step_kwargs)) + + if ((not self._build_config.get('skip_ota_tests')) and + (self._manifest_branch not in SKIP_OTA_TESTS_BRANCH)): + test_board_name = self._build_config.get('test_board_name') + steps.extend([ + ota_build_tests_step.OtaBuildTestsStep( + self._build_name, + board_name=test_board_name, + extra_params=self._ota_extra_params(), + halt_on_failure=True, + **self._step_kwargs), + host_tests_step.RunHostTestsStep(**self._step_kwargs), + ota_strip_binaries_step.OtaStripBinariesStep( + halt_on_failure=True, **self._step_kwargs), + ]) + + # if this is a partner build, we need to do additional checks + if self._build_name in PARTNER_BUILDS: + build_flavor = self._build_config.get('build_flavor', 'release') + steps.append( + partner_build_check_step.PartnerBuildCheckStep( + self._build_name, build_flavor, **self._step_kwargs)) + + # TODO(b/118514002) remove once copy to partners service will be available + if self.build_system == 'catabuilder': + steps.extend(self._partner_upload_steps()) + + return steps + + # TODO(b/118514002) remove once copy to partners service will be available + def _partner_upload_steps(self): + steps = [] + gcs_path = self._get_partner_gcs_path() + gclient_out_path = '/tmp/{}_{}_gclient_out.json'.format( + self._build_name, self.build_number) + + # TODO(b/117437843) Remove recipe_ check after migtation completion + for partner_bucket in self._build_config.get('partner_bucket', []): + build_env = self._properties.get('build_env', 'dev') + if build_env != 'prod' or self._build_name.startswith('recipe_'): + upload_bucket = PARTNER_ARCHIVE_BUCKET_STAGING_BUCKET[build_env] + upload_path = os.path.join(partner_bucket, gcs_path + '/') + else: + upload_bucket = partner_bucket + upload_path = gcs_path + '/' + + # Upload gclient_out.json file + if os.path.isfile(gclient_out_path): + steps.append( + gcs_upload_step.GcsUploadStep( + upload_bucket, + upload_path, + name='gclient_out.json upload to {}'.format(partner_bucket), + src_path=gclient_out_path, + result_property='gcs_output_{}'.format(partner_bucket), + **self._step_kwargs)) + + steps.append( + gcs_upload_step.GcsUploadStep( + upload_bucket, + upload_path, + name='upload to {}'.format(partner_bucket), + result_property='gcs_output_{}'.format(partner_bucket), + **self._step_kwargs)) + + return steps + + def _get_partner_gcs_path(self): + """Construct the gcs relative path within a bucket for specified build.""" + gcs_path = [ + self._properties['repo_alias'], + self._properties['manifest_branch'], + self._properties['buildername'], + self._properties['buildset'], + ] + return '/'.join(str(i) for i in gcs_path)
diff --git a/cq/scripts/slave/recipe/precommit.py b/cq/scripts/slave/recipe/precommit.py new file mode 100644 index 0000000..c75b619 --- /dev/null +++ b/cq/scripts/slave/recipe/precommit.py
@@ -0,0 +1,57 @@ +"""Recipe for running pre-commit tests. + +pre-commit is a framework written in python that allows each +repository to define its own set of checks that will be run +before code is committed. It uses a git hook and a config file +at the root of the repository. + +This recipe looks for the config file and runs pre-commit. +""" +import logging +import os + +from slave import base_recipe +from slave.step import precommit_step +from slave.step import py_env_setup_step + +CONFIG_FILE_DEFAULT = ".pre-commit-config.yaml" +CONFIG_FILE_BETA = ".pre-commit-config.beta.yaml" + +def GetValidBuildNames(): + return ["precommit", "precommit-beta"] + +def CreateRecipe(build_name: str, **kwargs): + """Defines how this recipe gets built.""" + if build_name.endswith("-beta"): + config_file = CONFIG_FILE_BETA + show_output = False + else: + config_file = CONFIG_FILE_DEFAULT + show_output = True + return PreCommitRecipe( + config_file=config_file, + show_output=show_output, + **kwargs) + +class PreCommitRecipe(base_recipe.BaseRecipe): + """Recipe to execute pre-commit hooks.""" + + def __init__(self, config_file, show_output, **kwargs): + base_recipe.BaseRecipe.__init__(self, **kwargs) + self._config_file = config_file + self._repo_root_directory = kwargs["eureka_root"] + self._show_output = show_output + + def get_steps(self): + return [ + py_env_setup_step.PyEnvSetupStep( + py3=True, + requirements_project="continuous-tests", + requirements_path="configs/pre-commit/requirements.txt", + **self._step_kwargs), + precommit_step.PreCommitStep( + config_file=self._config_file, + repo_root_directory=self._repo_root_directory, + show_output=self._show_output, + **self._step_kwargs), + ]
diff --git a/cq/scripts/slave/recipe/py_test_runner.py b/cq/scripts/slave/recipe/py_test_runner.py new file mode 100644 index 0000000..9803a33 --- /dev/null +++ b/cq/scripts/slave/recipe/py_test_runner.py
@@ -0,0 +1,155 @@ +"""Recipe for running python tests against the given build.""" +import logging +import os +from pathlib import Path +from typing import Dict, List, Union + +from slave import base_recipe +from slave.step import py_env_setup_step +from slave.step import py_test_step + + +LOGGER = logging.getLogger(__name__) +DEFAULT_UNIT_TEST_TIMEOUT_SECONDS = 300 +DEFAULT_INTEGRATION_TEST_TIMEOUT_SECONDS = 3600 +DEFAULT_E2E_TEST_TIMEOUT_SECONDS = 3600 +UNIT_TEST_REGEX_SUFFIX = r'.*_test\.py$' +INTEGRATION_TEST_REGEX_SUFFIX = r'.*_test_integration\.py$' +E2E_TEST_REGEX_SUFFIX = r'.*_test_case.py$' +PY3_EXCLUDED_PATH = [ + 'cq/buildbot-masters', + 'cq/scripts/master', +] + + +BUILD_CONFIGS = { + 'py_unittest_builder_masters': { + 'project': 'builder/masters', + 'py_requirements_path': 'requirements_buildbot.txt', + 'py_requirements_project': 'builder/masters', + 'py_packages_mirror_dir': 'python_packages', + 'test_file_filter_regex': UNIT_TEST_REGEX_SUFFIX, + 'test_timeout_seconds': DEFAULT_UNIT_TEST_TIMEOUT_SECONDS, + }, + 'py_unittest_builder_scripts': { + 'project': 'builder/scripts', + 'test_file_filter_regex': UNIT_TEST_REGEX_SUFFIX, + 'test_timeout_seconds': DEFAULT_UNIT_TEST_TIMEOUT_SECONDS, + }, + 'py3_unittest_continuous_tests': { + 'project': 'continuous-tests', + 'py_requirements_path': 'cq/requirements_recipe3.txt', + 'py_requirements_project': 'continuous-tests', + 'py_packages_mirror_dir': 'python_packages', + 'test_file_filter_regex': UNIT_TEST_REGEX_SUFFIX, + 'test_timeout_seconds': DEFAULT_UNIT_TEST_TIMEOUT_SECONDS * 2, + 'module_path_regex': '^((?!{}).)*$'.format('|'.join(PY3_EXCLUDED_PATH)), + 'py3': True, + }, + 'py_unittest_test': { + 'project': 'test', + 'test_file_filter_regex': UNIT_TEST_REGEX_SUFFIX, + 'test_timeout_seconds': DEFAULT_UNIT_TEST_TIMEOUT_SECONDS, + }, + 'py3_unittest_test': { + 'project': 'test', + 'test_file_filter_regex': UNIT_TEST_REGEX_SUFFIX, + 'test_timeout_seconds': DEFAULT_UNIT_TEST_TIMEOUT_SECONDS * 2, + 'py3': True, + 'py_requirements_path': os.path.join('lab_system', 'requirements3.txt'), + }, + 'py_unittest_chromecast_internal': { + 'project': 'chromecast/internal', + 'py_requirements_path': os.path.join('lab_system', 'requirements3.txt'), + 'py3': True, + # The gunittest runner filters use full, absolute file paths, + # and will search into the nested git projects within + # chromecast/internal. To avoid finding unwanted test modules, include + # a 'chromecast/internal' prefix and only search specific directories. + 'test_file_filter_regex': + (r'cast/internal/(build|tools|android/build)/' + + UNIT_TEST_REGEX_SUFFIX), + 'test_timeout_seconds': DEFAULT_UNIT_TEST_TIMEOUT_SECONDS, + }, + 'py_integration_test_chromecast_internal': { + 'project': 'chromecast/internal', + 'py_requirements_path': os.path.join('lab_system', 'requirements3.txt'), + 'py3': True, + # The gunittest runner filters use full, absolute file paths, + # and will search into the nested git projects within + # chromecast/internal. To avoid finding unwanted test modules, include + # a 'chromecast/internal' prefix and only search specific directories. + 'test_file_filter_regex': + (r'cast/internal/(build|tools|android/build)/' + + INTEGRATION_TEST_REGEX_SUFFIX), + 'test_timeout_seconds': DEFAULT_INTEGRATION_TEST_TIMEOUT_SECONDS, + }, +} +Config = Dict[str, Union[str, int]] + +def GetValidBuildNames(): + return list(BUILD_CONFIGS.keys()) + + +def CreateRecipe(build_name: str, **kwargs): + """Builds a recipe object.""" + if build_name in BUILD_CONFIGS: + return PyTestRecipe( + config=BUILD_CONFIGS[build_name], + **kwargs) + raise base_recipe.BuildNameNotSupportedError(build_name) + + +class PyTestRecipe(base_recipe.BaseRecipe): + """Recipe to run python tests on a repository.""" + + def __init__(self, + config: Config, + **kwargs): + super().__init__(**kwargs) + self._config = config + LOGGER.info("Eureka root when creatini PyTestRecipe: %s", self._eureka_root) + + def get_steps(self): + requirements_project = self._config.get('py_requirements_project', 'test') + requirements_path = self._config.get( + 'py_requirements_path', os.path.join('lab_system', 'requirements.txt')) + python_packages_dir = self._config.get( + 'py_packages_mirror_dir', 'team-catatester/python_packages') + test_file_filter_regex = self._config.get( + 'test_file_filter_regex', UNIT_TEST_REGEX_SUFFIX) + test_timeout_seconds = self._config.get( + 'test_timeout_seconds', DEFAULT_UNIT_TEST_TIMEOUT_SECONDS) + test_py3 = self._config.get('py3', False) + module_path_regex = self._config.get('module_path_regex', '.') + LOGGER.info("Eureka root when creating additional import paths: %s", self._eureka_root) + additional_import_paths = [ + self._eureka_root / path for path + in ( + 'builder/masters', + 'builder/masters/src', + 'chromium/src/third_party/catapult/telemetry', + 'chromium/src/chromecast/internal', + 'chromium/src/chromecast/tools', + 'continuous-tests', + 'continuous-tests/cq/scripts', + 'test', + 'testing/external/autotest', + 'testing/external/chromite', + 'testing/sprockets', + )] + return [ + py_env_setup_step.PyEnvSetupStep( + additional_import_paths=additional_import_paths, + local_packages_dir=python_packages_dir, + py3=test_py3, + requirements_path=requirements_path, + requirements_project=requirements_project, + **self._step_kwargs), + py_test_step.PyTestStep( + project=self._config.get('project'), + test_file_filter_regex=test_file_filter_regex, + timeout=test_timeout_seconds, + module_path_regex=module_path_regex, + **self._step_kwargs) + ]
diff --git a/cq/scripts/slave/recipe/pylint.py b/cq/scripts/slave/recipe/pylint.py new file mode 100644 index 0000000..9170b39 --- /dev/null +++ b/cq/scripts/slave/recipe/pylint.py
@@ -0,0 +1,47 @@ +"""Recipe for running a pylint on the given build.""" +from slave import base_recipe +from slave.step import pylint_step + +# Note that the keys are Gerrit project names. +PROJECT_CONFIGS = { + 'continuous-tests': { + 'pylintrc_file': 'pylintrc', + 'deny_list_filter': [ + 'cq/scripts/master/buildbucket/', + 'cq/scripts/helper/cpplint/', + 'cq/scripts/master/deferred_resource.py', + 'cq/appengine/genfiles', + ], + }, + 'builder/buildbot': { + 'deny_list_filter': ['.*'], + }, + 'test': { + 'pylintrc_file': '.pylintrc', + } +} + + +def GetValidBuildNames(): + return ['lint'] + + +def CreateRecipe(build_name: str, **kwargs): + """Builds a recipe object.""" + del build_name # Unused. + return PylintRecipe(**kwargs) + + +class PylintRecipe(base_recipe.BaseRecipe): + """Recipe to lint a repository.""" + + def get_steps(self): + deny_list_filter = PROJECT_CONFIGS.get(self._properties['patch_project'], + {}).get('deny_list_filter', None) + pylintrc_file = PROJECT_CONFIGS.get(self._properties['patch_project'], + {}).get('pylintrc_file', None) + + return [ + pylint_step.PylintStep(pylintrc_file=pylintrc_file, + deny_list_filter=deny_list_filter, **self._step_kwargs), + ]
diff --git a/cq/scripts/slave/recipe/sdk_ota_builder.py b/cq/scripts/slave/recipe/sdk_ota_builder.py new file mode 100644 index 0000000..35fba35 --- /dev/null +++ b/cq/scripts/slave/recipe/sdk_ota_builder.py
@@ -0,0 +1,56 @@ +"""Recipe for running a ota build on the given SDK patch.""" +from slave import base_recipe +from slave.recipe import combined_sdk +from slave.recipe import ota_builder +from slave.step import combined_sdk_compile + +SDK_CONFIG = { + 'korlan-eng-with-sdk': { + 'product': 'korlan', + 'sdk_path': 'vendor/amlogic/amlogic_sdk_korlan', + 'fake_out_path': 'out', + 'ota_config_key': 'korlan-eng', + 'sdk_config_key': 'combined-sdk-kernel-bootloader-amlogic-korlan', + }, + 'korlan-user-with-sdk': { + 'product': 'korlan', + 'sdk_path': 'vendor/amlogic/amlogic_sdk_korlan', + 'fake_out_path': 'out', + 'ota_config_key': 'korlan-user', + 'sdk_config_key': 'combined-sdk-kernel-bootloader-amlogic-korlan', + }, +} + + +def GetValidBuildNames(): + return list(SDK_CONFIG.keys()) + + +def CreateRecipe(build_name: str, **kwargs): + """Builds a recipe object.""" + return SdkOtaRecipe(build_name, **kwargs) + + +class SdkOtaRecipe(base_recipe.BaseRecipe): + """Recipe to run an ota build.""" + + def __init__(self, build_name, **kwargs): + base_recipe.BaseRecipe.__init__( + self, enable_build_accelerator=True, **kwargs) + self._build_name = build_name + self._build_config = SDK_CONFIG[self._build_name] + self._build_kwargs = kwargs + + def get_steps(self): + steps = [] + + sdk_config_key = self._build_config.get('sdk_config_key') + sdk_path = self._build_config.get('sdk_path') + combined_sdk_recipe = combined_sdk.CreateRecipe( + sdk_config_key, cwd=sdk_path, repo_regex=sdk_path, + **self._build_kwargs) + steps += combined_sdk_recipe.get_steps_for_ota_builder() + ota_config_key = self._build_config.get('ota_config_key') + steps += ota_builder.CreateRecipe(ota_config_key, + **self._build_kwargs).get_steps() + return steps
diff --git a/cq/scripts/slave/recipe/sprockets_conformance_test_runner.py b/cq/scripts/slave/recipe/sprockets_conformance_test_runner.py new file mode 100644 index 0000000..940c19f --- /dev/null +++ b/cq/scripts/slave/recipe/sprockets_conformance_test_runner.py
@@ -0,0 +1,49 @@ +"""Recipe for running a the Sprockets Conformance tests.""" +from slave import base_recipe +from slave.step import cast_shell_step +from slave.step import landmine_step +from slave.step import sprockets_step + +_BUILD_ARGS_PRODUCT = 'video_x64_eng' +_BUILD_ARGS_OFFICIAL = False +_BUILD_BRANDING = 'chrome' +_BUILD_ARCH = 'clang' +_BUILD_PRODUCT = 'chromecast' +# TODO(mbjorge|seantopping): Change to 'Release' when b/32749161 is resolved. +_BUILD_FLAVOR = 'Debug' +_ENABLED_CHIRP = False +# TODO(b/24062312): 'clang' --> 'x86' + + +def GetValidBuildNames(): + return [ + 'sprockets_conformance_tests', + ] + + +def CreateRecipe(build_name: str, **kwargs): + """Builds a recipe object.""" + del build_name # Unused. + return SprocketsConformanceTestsRecipe(**kwargs) + + +class SprocketsConformanceTestsRecipe(base_recipe.BaseRecipe): + """Recipe to run a Sprockets conformance tests against desktop cast shell.""" + + def __init__(self, **kwargs): + base_recipe.BaseRecipe.__init__( + self, enable_build_accelerator=True, **kwargs) + self._properties = kwargs.get('properties', {}) + + def get_steps(self): + return [ + landmine_step.LandmineStep(**self._step_kwargs), + cast_shell_step.CastShellStep(_BUILD_BRANDING, _BUILD_ARCH, + _BUILD_PRODUCT, + _BUILD_FLAVOR, _ENABLED_CHIRP, + build_args_product=_BUILD_ARGS_PRODUCT, + build_args_official=_BUILD_ARGS_OFFICIAL, + halt_on_failure=True, + **self._step_kwargs), + sprockets_step.SprocketsConformanceTestStep(**self._step_kwargs) + ]
diff --git a/cq/scripts/slave/recipe/x86_cast_camera_hal_builder.py b/cq/scripts/slave/recipe/x86_cast_camera_hal_builder.py new file mode 100644 index 0000000..d79d853 --- /dev/null +++ b/cq/scripts/slave/recipe/x86_cast_camera_hal_builder.py
@@ -0,0 +1,54 @@ +import os +import pathlib + +from slave import base_recipe +from slave.step import x86_cast_camera_hal_step +from slave.step import code_coverage_step + +BUILD_CONFIGS = { + 'cast_camera_hal_tests_x86_64': { + 'code_coverage': True, + }, + 'cast_camera_hal_tests_x86_64_coverage': { + 'code_coverage': True, + } +} + +def GetValidBuildNames(): + return list(BUILD_CONFIGS.keys()) + + +def CreateRecipe(build_name: str, **kwargs): + config = BUILD_CONFIGS[build_name] + return CastCameraHalRecipe(config, **kwargs) + + +class CastCameraHalRecipe(base_recipe.BaseRecipe): + """ Recipe for build/run cast camera hal test""" + + def __init__(self, config, **kwargs): + self._config = config + base_recipe.BaseRecipe.__init__(self, **kwargs) + + def get_steps(self): + steps = [ + x86_cast_camera_hal_step.BuildCastCameraHalTestStep( + **self._step_kwargs), + x86_cast_camera_hal_step.RunCastCameraHalTestStep( + **self._step_kwargs) + ] + + if self._config.get('code_coverage', False): + lcov_paths = [os.path.join(self._executor.get_gcs_dir(), + 'code_coverage_html', + 'coverage.lcov')] + steps += [ + x86_cast_camera_hal_step.InstallCoverageTools( + **self._step_kwargs), + x86_cast_camera_hal_step.CollectCameraHalTestCoverageStep( + **self._step_kwargs), + code_coverage_step.CollectLcovCoverageStep( + lcov_paths, **self._step_kwargs), + ] + + return steps
diff --git a/cq/scripts/slave/recipe/x86_integration_test_runner.py b/cq/scripts/slave/recipe/x86_integration_test_runner.py new file mode 100644 index 0000000..8a85a54 --- /dev/null +++ b/cq/scripts/slave/recipe/x86_integration_test_runner.py
@@ -0,0 +1,81 @@ +"""Recipe for running integration tests against locally started cast shell.""" +import os + +from slave import base_recipe +from slave.step import cast_shell_step +from slave.step import py_env_setup_step +from slave.step import x86_integration_test_step + +# TODO(b/24062312): 'clang' --> 'x86' +BUILD_ARCH = 'clang' +BUILD_ARGS_PRODUCT = 'video_x64_eng' +BUILD_ARGS_OFFICIAL = False +BUILD_BRANDING = 'chrome' +BUILD_FLAVOR = 'Debug' +BUILD_PRODUCT = 'chromecast' +ENABLE_CHIRP = False + +BUILD_CONFIGS = { + 'cast_compliance_tests': { + 'py3': True, + 'py_requirements_path': os.path.join('lab_system', 'requirements3.txt'), + }, + 'cast_compliance_tests_rbe': {} +} + + +def GetValidBuildNames(): + return BUILD_CONFIGS.keys() + + +def CreateRecipe(build_name: str, **kwargs): + """Builds a recipe object.""" + return CastComplianceTestRecipe(build_name, + BUILD_CONFIGS[build_name], + **kwargs) + + +class CastComplianceTestRecipe(base_recipe.BaseRecipe): + """Recipe to run cast compliance tests against x86 cast shell.""" + + def __init__(self, build_name, build_config, **kwargs): + base_recipe.BaseRecipe.__init__( + self, enable_build_accelerator=True, **kwargs) + self._build_name = build_name + self._py3 = build_config.get('py3', False) + self._requirements_path = build_config.get( + 'py_requirements_path', os.path.join('lab_system', 'requirements.txt')) + + def get_steps(self): + steps = [ + cast_shell_step.CastShellStep(BUILD_BRANDING, BUILD_ARCH, + BUILD_PRODUCT, BUILD_FLAVOR, ENABLE_CHIRP, + build_args_product=BUILD_ARGS_PRODUCT, + build_args_official=BUILD_ARGS_OFFICIAL, + halt_on_failure=True, + **self._step_kwargs), + py_env_setup_step.PyEnvSetupStep( + local_packages_dir='team-catatester/python_packages', + py3=self._py3, + requirements_path=self._requirements_path, + requirements_project='test', + **self._step_kwargs), + x86_integration_test_step.RunIntegrationTestStep( + test_case_class=['CastReceiverComplianceTestCase'], + # TODO(kiranthampi): re-enable when b/34853664 is resolved. + # 'CastReceiverCapabilityTestCase', + # 'CastReceiverMirroringProtocolTestCase', + # 'CastReceiverMultipleSendersTestCase', + # 'CastReceiverQueueTestCase', + # 'CastReceiverStressTestCase', + # TODO(mbjorge|kiranthampi): re-enable when b/27219805 is resolved. + # 'CastReceiverVolumeControlTestCase' + test_case_module='eurtest.tests.cast.receiver.compliance_test_case', + test_sequence_class='X86DisabledLoggingTestSequence', + test_sequence_module=('eurtest.framework.disabled_logging_' + 'test_sequence'), + test_config_file_path='tests.cast.receiver_x86', + headless=True, + **self._step_kwargs), + ] + return steps
diff --git a/cq/scripts/slave/recipe/x86_manhattan_test_integration_runner.py b/cq/scripts/slave/recipe/x86_manhattan_test_integration_runner.py new file mode 100644 index 0000000..44736d6 --- /dev/null +++ b/cq/scripts/slave/recipe/x86_manhattan_test_integration_runner.py
@@ -0,0 +1,45 @@ +"""Recipe for running integration tests against manhattan shell.""" +from slave import base_recipe +from slave.step import cast_shell_step +from slave.step import x86_manhattan_test_integration_step + +# TODO(b/24062312): 'clang' --> 'x86' +BUILD_ARCH = 'clang' +BUILD_ARGS_PRODUCT = 'displayassistant_x64_eng' +BUILD_ARGS_OFFICIAL = False +BUILD_BRANDING = 'chrome' +BUILD_FLAVOR = 'Debug' +BUILD_PRODUCT = 'display' +ENABLE_ASSISTANT = True + + +def GetValidBuildNames(): + return ['manhattan_shell_crash_loop_test'] + + +def CreateRecipe(build_name: str, **kwargs): + """Builds a recipe object.""" + del build_name # Unused. + return ManhattanShellCrashLoopTestRecipe(**kwargs) + + +class ManhattanShellCrashLoopTestRecipe(base_recipe.BaseRecipe): + """Recipe to run cast compliance tests against x86 cast shell.""" + + def __init__(self, **kwargs): + base_recipe.BaseRecipe.__init__( + self, enable_build_accelerator=True, **kwargs) + + def get_steps(self): + steps = [ + cast_shell_step.CastShellStep(BUILD_BRANDING, BUILD_ARCH, + BUILD_PRODUCT, BUILD_FLAVOR, + ENABLE_ASSISTANT, + build_args_product=BUILD_ARGS_PRODUCT, + build_args_official=BUILD_ARGS_OFFICIAL, + halt_on_failure=True, + **self._step_kwargs), + x86_manhattan_test_integration_step.RunManhattanShellCrashTestStep( + **self._step_kwargs), + ] + return steps
diff --git a/cq/scripts/slave/recipe/x86_nccm_test_runner.py b/cq/scripts/slave/recipe/x86_nccm_test_runner.py new file mode 100644 index 0000000..8531e4e --- /dev/null +++ b/cq/scripts/slave/recipe/x86_nccm_test_runner.py
@@ -0,0 +1,94 @@ +import os + +from slave import base_recipe +from slave.step import code_coverage_step +from slave.step import gn_step +from slave.step import gn_check_step +from slave.step import x86_camera_step + +BUILD_BRANDING = 'chrome' +BUILD_ARCH = 'x86' +BUILD_FLAVOR = 'Release' +BUILD_PRODUCT = 'chromecast' +BUILD_ARGS_OFFICIAL = False +BUILD_ARGS_PRODUCT = 'nccm_x86' + +COVERAGE_IGNORE_FILENAME_REGEX = '.*/gen/.*|.*/third_party/.*' +COVERAGE_REPORT_FORMAT = 'lcov' + + +def GetValidBuildNames(): + return [ + BUILD_ARGS_PRODUCT, + ] + + +def CreateRecipe(build_name: str, **kwargs): + del build_name + return NccmRecipe(**kwargs) + + +class NccmRecipe(base_recipe.BaseRecipe): + """ Recipe for build/run reconnect proxy test""" + + def __init__(self, **kwargs): + base_recipe.BaseRecipe.__init__( + self, enable_build_accelerator=True, **kwargs) + self._properties = kwargs.get('properties', {}) + self._code_coverage = self._properties.get('code_coverage', False) + + def get_steps(self): + cwd = os.getcwd() + + # Output directory for gn gen step must match expected output directory + # for RunCoverageCommandStep based on given BUILD_ARCH, BUILD_PRODUCT, etc. + out_dir_parts = ['out', BUILD_ARCH, BUILD_PRODUCT, 'gn'] + out_dir = os.path.join( + 'chromium/src', '_'.join(out_dir_parts), BUILD_FLAVOR) + + build_args = [] + if self._code_coverage: + build_args.append('use_clang_coverage=true') + build_args.append('is_component_build=false') + + steps = [ + gn_step.GnGenStep(build_args_product=BUILD_ARGS_PRODUCT, + build_args=build_args, + out_dir=out_dir, + cwd=cwd, + halt_on_failure=True, + **self._step_kwargs), + x86_camera_step.BuildNccmUnitTestStep(out_dir=out_dir, + **self._step_kwargs), + ] + + if self._code_coverage: + # Code coverage step executes the binary from the step before based + # on the list of executables stored in step data and collects + # coverage information. + coverage_step = code_coverage_step.RunCoverageCommandStep( + BUILD_BRANDING, + BUILD_ARCH, + BUILD_PRODUCT, + BUILD_FLAVOR, + sanitizer=None, + build_args_product=BUILD_ARGS_PRODUCT, + build_args_official=BUILD_ARGS_OFFICIAL, + ignore_filename_regex=COVERAGE_IGNORE_FILENAME_REGEX, + report_format=COVERAGE_REPORT_FORMAT, + **self._step_kwargs, + ) + steps.extend([ + coverage_step, + code_coverage_step.CollectLcovCoverageStep( + lcov_files=coverage_step.get_lcov_output_file_paths(), + **self._step_kwargs, + ), + ]) + else: + steps += [ + x86_camera_step.RunNccmUnitTestStep(out_dir=out_dir, + **self._step_kwargs) + ] + + return steps
diff --git a/cq/scripts/slave/recipe/x86_photon_test_runner.py b/cq/scripts/slave/recipe/x86_photon_test_runner.py new file mode 100644 index 0000000..1f29d60 --- /dev/null +++ b/cq/scripts/slave/recipe/x86_photon_test_runner.py
@@ -0,0 +1,63 @@ +import os + +from slave import base_recipe +from slave.step import code_coverage_step +from slave.step import gn_step +from slave.step import gn_check_step +from slave.step import x86_camera_step + +BUILD_BRANDING = 'chrome' +BUILD_ARCH = 'x86' +BUILD_FLAVOR = 'Release' +BUILD_PRODUCT = 'chromecast' +BUILD_ARGS_OFFICIAL = False +BUILD_ARGS_PRODUCT = 'photon_x86' + +COVERAGE_IGNORE_FILENAME_REGEX = '.*/gen/.*|.*/third_party/.*' +COVERAGE_REPORT_FORMAT = 'lcov' + + +def GetValidBuildNames(): + return [ + BUILD_ARGS_PRODUCT, + ] + + +def CreateRecipe(build_name: str, **kwargs): + del build_name + return PhotonRecipe(**kwargs) + + +class PhotonRecipe(base_recipe.BaseRecipe): + """ Recipe for build/run photon build""" + + def __init__(self, **kwargs): + base_recipe.BaseRecipe.__init__( + self, enable_build_accelerator=True, **kwargs) + self._properties = kwargs.get('properties', {}) + self._code_coverage = self._properties.get('code_coverage', False) + + def get_steps(self): + cwd = os.getcwd() + + # Output directory for gn gen step must match expected output directory + # for RunCoverageCommandStep based on given BUILD_ARCH, BUILD_PRODUCT, etc. + out_dir_parts = ['out', BUILD_ARCH, BUILD_PRODUCT, 'gn'] + out_dir = os.path.join( + 'chromium/src', '_'.join(out_dir_parts), BUILD_FLAVOR) + + build_args = [] + + steps = [ + gn_step.GnGenStep(build_args_product=BUILD_ARGS_PRODUCT, + build_args=build_args, + out_dir=out_dir, + cwd=cwd, + halt_on_failure=True, + **self._step_kwargs), + x86_camera_step.BuildPhotonStep(out_dir=out_dir, **self._step_kwargs), + x86_camera_step.RunPhotonUnitTestStep(out_dir=out_dir, + **self._step_kwargs), + ] + + return steps
diff --git a/cq/scripts/slave/recipe/x86_reconnect_proxy_builder.py b/cq/scripts/slave/recipe/x86_reconnect_proxy_builder.py new file mode 100644 index 0000000..bdf5136 --- /dev/null +++ b/cq/scripts/slave/recipe/x86_reconnect_proxy_builder.py
@@ -0,0 +1,34 @@ +import os + +from slave import base_recipe +from slave.step import x86_camera_step + + +def GetValidBuildNames(): + return ['newman_x86_64-eng', 'newman_x64-eng'] + + +def CreateRecipe(build_name: str, **kwargs): + del build_name + return ReconnectProxyRecipe(**kwargs) + + +class ReconnectProxyRecipe(base_recipe.BaseRecipe): + """ Recipe for build/run reconnect proxy test""" + + def __init__(self, **kwargs): + base_recipe.BaseRecipe.__init__(self, **kwargs) + # newman_x86_64 --> newman + product = self.buildername[:self.buildername.find('_')] + self._step_kwargs.update({ + 'product': product + }) + + def get_steps(self): + + return [ + x86_camera_step.BuildReconnectProxyTestStep( + **self._step_kwargs), + x86_camera_step.RunReconnectTestsStep( + **self._step_kwargs), + ]
diff --git a/cq/scripts/slave/recipe/x86_simulator_builder.py b/cq/scripts/slave/recipe/x86_simulator_builder.py new file mode 100644 index 0000000..f413fd8 --- /dev/null +++ b/cq/scripts/slave/recipe/x86_simulator_builder.py
@@ -0,0 +1,115 @@ +from slave import base_recipe +from slave.step import code_coverage_step +from slave.step import x86_camera_step + + +COVERAGE_IGNORE_FILENAME_REGEX = '.*/gen/.*|.*/third_party/.*' +COVERAGE_REPORT_FORMAT = 'lcov' + + +def GetValidBuildNames(): + return [ + 'gq_x64-eng', + 'gq_x86_64-eng', + 'gq_x64-eng-coverage', + 'nq_x64-eng', + 'nq_x86_64-eng', + 'nq_exp_x86_64-eng', + 'nq_x64-eng-coverage', + 'spencer_x64-eng', + 'spencer_x86_64-eng', + 'spencer_x64-eng-coverage', + 'venus_x64-eng', + 'venus_x86_64-eng', + 'venus_x64-eng-coverage', + ] + + +def CreateRecipe(build_name: str, **kwargs): + del build_name + return X86SimulatorRecipe(**kwargs) + + +class X86SimulatorRecipe(base_recipe.BaseRecipe): + """ Recipe for build x86 64 simulator""" + + def __init__(self, **kwargs): + base_recipe.BaseRecipe.__init__( + self, enable_build_accelerator=True, **kwargs) + self._code_coverage = self._properties.get('code_coverage', False) + + # nq_x64-eng --> nq + product = self.buildername[:self.buildername.find('_')] + if ('exp' in self.buildername): + product = product + '_exp' + + self._step_kwargs.update({ + 'code_coverage': self._code_coverage, + 'product': product + }) + + self.out_dir = f'out_chromecast_{product}_x86_64/release' + self.chromium_out_dir = f'chromium/src/{self.out_dir}' + + def get_steps(self): + steps = [ + x86_camera_step.MakeCleanSim( + **self._step_kwargs), + x86_camera_step.BuildSimulatorStep( + **self._step_kwargs), + x86_camera_step.BuildChromiumIotTestsStep( + out_dir=self.chromium_out_dir, **self._step_kwargs) + ] + + if self._code_coverage: + # RunCoverageCommandStep already takes a product as an arg. + step_kwargs = self._step_kwargs.copy() + product = step_kwargs.pop('product') + '_x86_64' + + # Set appropriate LD_LIBRARY_PATH and TARGET_PRODUCT when executing test. + # coverage.py executes tests with chromium/src as the working directory + # so LD_LIBRARY_PATH has to be relative to chromium/src. + test_env = { + 'LD_LIBRARY_PATH': ':'.join([ + '../../prebuilt/toolchain/x86_64/usr/lib64', + f'../../out/target/product/{product}/system/lib', + ]), + 'TARGET_PRODUCT': product, + } + + coverage_step = code_coverage_step.RunCoverageCommandStep( + None, + None, + None, + None, + sanitizer=None, + build_args_product=self.buildername, + build_args_official=False, + ignore_filename_regex=COVERAGE_IGNORE_FILENAME_REGEX, + report_format=COVERAGE_REPORT_FORMAT, + build_out_dir=self.out_dir, + test_env=test_env, + **step_kwargs, + ) + steps.extend([ + coverage_step, + code_coverage_step.CollectLcovCoverageStep( + lcov_files=coverage_step.get_lcov_output_file_paths(), + **step_kwargs, + ), + ]) + else: + steps += [ + x86_camera_step.RunChromiumIotTestsStep( + cwd=self.chromium_out_dir, + **self._step_kwargs) + ] + + steps += [ + x86_camera_step.CreateSimTarStep( + **self._step_kwargs), + x86_camera_step.BuildAndRunNldaemonUnitTestStep( + **self._step_kwargs), + ] + + return steps
diff --git a/cq/scripts/slave/recipe/x86_wifi_simulator_builder.py b/cq/scripts/slave/recipe/x86_wifi_simulator_builder.py new file mode 100644 index 0000000..8da56f3 --- /dev/null +++ b/cq/scripts/slave/recipe/x86_wifi_simulator_builder.py
@@ -0,0 +1,93 @@ +from slave import base_recipe +from slave.step import code_coverage_step +from slave.step import x86_wifi_step +from slave.step import code_coverage_step + +COVERAGE_IGNORE_FILENAME_REGEX = '.*/gen/.*|.*/third_party/.*' +COVERAGE_REPORT_FORMAT = 'lcov' + +def GetValidBuildNames(): + return [ + 'sirocco_x86_64-eng', + 'sirocco_x86_64-eng-coverage', + ] + + +def CreateRecipe(build_name: str, **kwargs): + del build_name + return X86WifiSimulatorRecipe(**kwargs) + + +class X86WifiSimulatorRecipe(base_recipe.BaseRecipe): + """ Recipe for build x86 64 simulator""" + + def __init__(self, **kwargs): + base_recipe.BaseRecipe.__init__( + self, enable_build_accelerator=True, **kwargs) + self._code_coverage = self._properties.get('code_coverage', False) + self._run_tests = (self._properties.get('run_tests', False) + or self._code_coverage) + self._step_kwargs.update({ + 'code_coverage': self._code_coverage, + 'run_tests': self._run_tests, + }) + + # sirocco_x86_64-eng --> sirocco_x86_64 + self._product = self.buildername[:self.buildername.find('-')] + self.out_dir = f'out_chromecast_{self._product}/release' + self.chromium_out_dir = f'chromium/src/{self.out_dir}' + + def get_steps(self): + + steps = [ + x86_wifi_step.MakeCleanSim( + **self._step_kwargs), + ] + + if self._run_tests: + # For unit test build, we don't need to build the whole simulator, + # just unit tests + test_env = { + 'LD_LIBRARY_PATH': ':'.join([ + self.out_dir, + f'../../out/target/product/{self._product}/system/lib', + ]), + 'TARGET_PRODUCT': self._product, + } + # Always run the unit tests, even in coverage case so we can report + # unit test failures in CQ. + # TODO(b/261494263): have RunCoverageCommandStep report failure so we + # only run tests once per build + steps.extend([ + x86_wifi_step.BuildUnitTestsStep(**self._step_kwargs), + x86_wifi_step.RunUnitTestsStep( + test_env=test_env, + build_out_dir=self.out_dir, + **self._step_kwargs), + ]) + if self._code_coverage: + coverage_step = code_coverage_step.RunCoverageCommandStep( + None, None, None, + None, sanitizer=None, + build_args_product=self.buildername, + build_args_official=False, + ignore_filename_regex=COVERAGE_IGNORE_FILENAME_REGEX, + report_format=COVERAGE_REPORT_FORMAT, + build_out_dir=self.out_dir, + test_env=test_env, + **self._step_kwargs, + ) + steps.extend([ + coverage_step, + code_coverage_step.CollectLcovCoverageStep( + lcov_files=coverage_step.get_lcov_output_file_paths(), + **self._step_kwargs, + ), + ]) + else: + steps.extend([ + x86_wifi_step.BuildSimulatorStep(**self._step_kwargs), + x86_wifi_step.CreateSimTarStep(**self._step_kwargs), + ]) + + return steps
diff --git a/cq/scripts/slave/step/__init__.py b/cq/scripts/slave/step/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/cq/scripts/slave/step/__init__.py
diff --git a/cq/scripts/slave/step/cast_shell_step.py b/cq/scripts/slave/step/cast_shell_step.py new file mode 100644 index 0000000..1e7511c --- /dev/null +++ b/cq/scripts/slave/step/cast_shell_step.py
@@ -0,0 +1,321 @@ +"""Build step class for building x86 cast_shell.""" +import logging +import os +import sys + +from helpers import branch_utils +from helpers import cast_shell_utils +from helpers import gn_utils +from helpers import ninja_utils +from slave import base_step +from slave.step import gn_check_step + +_UNIT_TEST_HELPER_MODULE = 'unit_test.unit_test_helper' + +BUILD_SCRIPT_PROJECT = 'chromecast/internal' +BUILD_SCRIPT_REL_PATH = 'build/build_chromecast.py' +CAST_SHELL_EXE = 'cast_shell' + + +def _InjectPythonPath(path): + if path not in sys.path: + sys.path.append(path) + + +class NonOtaBuildBaseStep(base_step.BaseStep): + """Base step for building and running a non-ota build. + + This is for any non-ota build that uses the build_chromecast.py build flow + instead of the OTA `make` build flow. + """ + + def __init__(self, name, branding, build_type, product, build_flavor, + sanitizer=None, build_args_product=None, + build_args_official=None, **kwargs): + """Creates a UnittestBaseStep instance. + + Args: + name: The name of the step. + branding: Build branding (chromium or chrome). + build_type: Type of system to build for ('x86', 'clang', or 'arm'). + product: product to build for (ie. 'chromecast', 'audio'). + build_flavor: Flavor of build ('Debug', 'Eng', 'Release'). + build_args_official: Whether to do an official build (disables debugging). + sanitizer: Clang saniziter to run with ('asan', 'msan', 'tsan', 'ubsan'). + build_args_product: The build/args/product/*.gn product to build for. + build_args_official: Whether the build is an official build. MUST be set + for any build that will ship to users. Disables debugging; do not + set for development builds. + **kwargs: Any additional args to pass to BaseStep. + """ + super().__init__(name=name, **kwargs) + + # TODO(b/73231972) remove branding, build_type, product, build_flavor + # after migration to new builds + assert branding in ['chromium', 'chrome', None] + assert build_type in ['x86', 'clang', 'arm', 'arm64', None] + assert product in [ + 'chromecast', 'audio', 'android', 'atv', 'display', None] + assert build_flavor in ['Debug', 'Eng', 'Release', None] + assert sanitizer in ['asan', 'msan', 'tsan', 'ubsan', None] + assert build_args_product + assert build_args_official is not None + + self._branding = branding + self._build_type = build_type + self._product = product + self._build_flavor = build_flavor + self._build_args_official = build_args_official + self._enable_gn_check = gn_utils.is_gn_check_enabled(self.manifest_branch, + product) + self._sanitizer = sanitizer + self._build_args_product = build_args_product + + self._build_target = kwargs.get('build_target') + + # Re-calculate the out directory. This mimics the calculation done in + # build_chromecast.py because we don't want to just import it and we can't + # refactor it because we have old branches we need to be able to build. + chrome_root = self.get_project_path('chromium/src') + self._outdir = os.path.join(chrome_root, 'out_' + build_args_product) + if self._build_flavor is None: + return + build_out_parts = ['out', build_type, product, 'gn'] + if sanitizer: + build_out_parts.append(sanitizer) + self._build_out_dir = os.path.join(chrome_root, '_'.join(build_out_parts)) + flavor_part = 'Release' if build_flavor == 'Eng' else build_flavor + self._outdir = os.path.join(self._build_out_dir, flavor_part) + + @property + def build_type_dir(self): + # TODO(b/73231972) remove build_type based logic once deprecated + if self._build_type is None: + if '_arm_' in self._build_args_product: + return 'arm' + elif '_arm64_' in self._build_args_product: + return 'arm64' + elif '_x86_' in self._build_args_product: + return 'x86' + return 'clang' + return self._build_type + + @property + def build_flavor_dir(self): + # TODO(b/73231972) remove build_flavor based logic once deprecated + # castshell builds had build_flavor == Debug despite non debug suffix + if self._build_flavor is None: + return 'Debug' if ('debug' in self._build_args_product or + 'castshell' in self._build_args_product + ) else 'Release' + return 'Release' if self._build_flavor == 'Eng' else self._build_flavor + + @property + def build_product_dir(self): + # TODO(b/73231972) remove product based logic once deprecated + if self._product is None: + return 'chromecast' + return self._product + + def _get_minimum_required_argv_for_outdir(self): + """Returns the arguments needed to get the outdir from build_chromecast.py. + + The chromecast/internal/build/build_chromecast.py script takes many command + line arguments, but only a select few are needed to be able to determine + the out directory that a build will happen in. + + This helper method assembles the minimum set of arguments required to + pass to build_chromecast.py to be generate the correct out directory. + + Returns: + A list of arguments + """ + # Set up the argv as if running the build_chromecast.py script. + argv = [ + 'build_chromecast.py', + '--archive_dir', self.get_gcs_dir(), + '--build_args_product', self._build_args_product, + '--build_number', self.build_number, + '--chrome_root', self.get_project_path('chromium/src')] + + # TODO(b/73231972) remove unused flags once migrated to new builds + if self._build_flavor: + argv += ['--build_flavor', self._build_flavor] + if self._build_type: + argv += ['--build_type', self._build_type] + if self._branding: + argv += ['--chromecast_branding', self._branding] + if self._product: + argv += ['--product_name', self._product] + + if self._sanitizer: + argv += ['--sanitizer', self._sanitizer] + + if self._build_target: + argv += ['--build_target', self._build_target] + + return argv + + def run(self): + raise NotImplementedError + + +class CastShellStep(NonOtaBuildBaseStep, gn_check_step.GnCheckStepBase): + """Build step class for building cast_shell.""" + + def __init__(self, branding, build_type, product, build_flavor, + enable_assistant, sanitizer=None, archive_to_tmp=False, + skip_create_zip=False, strip_binaries=False, **kwargs): + """Creates a CastShellStep instance. + + Args: + branding: Build branding ('chromium' or 'chrome'). + build_type: Type of system to build for ('x86', 'clang', or 'arm'). + product: product to build for (ie. 'chromecast', 'audio'). + build_flavor: Flavor of build ('Debug', 'Eng', 'Release'). + enable_assistant: enable Assistant functionality. Audio products only. + sanitizer: Clang saniziter to run with ('asan', 'msan', 'tsan', 'ubsan'). + **kwargs: Any additional args to pass to BaseStep. + """ + self._enable_code_coverage = kwargs.pop('code_coverage', False) + gn_check_step.GnCheckStepBase.__init__(self, **kwargs) + NonOtaBuildBaseStep.__init__(self, 'build cast_shell', branding, + build_type, product, build_flavor, + sanitizer=sanitizer, **kwargs) + self._enable_assistant = enable_assistant + self._archive_to_tmp = archive_to_tmp + self._skip_create_zip = skip_create_zip + self._strip_binaries = strip_binaries + self._unit_test_helper = None + + @property + def unit_test_helper(self): + """Use the unit_test_helper module to be consistent with Catabuilder.""" + if not self._unit_test_helper: + _InjectPythonPath(self.get_project_path('test')) + self._unit_test_helper = __import__( + _UNIT_TEST_HELPER_MODULE, fromlist=['']) + return self._unit_test_helper + + @property + def out_dir(self): + return self._outdir + + def BuildCastShell(self): + self.archive_dir = \ + self.get_tmp_dir() if self._archive_to_tmp else self.get_gcs_dir() + + base_path = self.get_project_path(BUILD_SCRIPT_PROJECT) + build_script = os.path.join(base_path, BUILD_SCRIPT_REL_PATH) + command = ['python3', build_script, + '--archive_dir', self.archive_dir, + '--build_args_product', self._build_args_product, + '--build_number', self.build_number, + '--chrome_root', self.get_project_path('chromium/src')] + command += self.build_accelerator.build_chromecast_flags + + # TODO(b/73231972) remove unused flags once migrated to new builds + if self._build_flavor: + command += ['--build_flavor', self._build_flavor] + if self._build_type: + command += ['--build_type', self._build_type] + if self._branding: + command += ['--chromecast_branding', self._branding] + if self._product: + command += ['--product_name', self._product] + if self._build_args_official: + command += ['--official'] + + if self._enable_assistant: + command += ['--enable_assistant'] + + if self._enable_gn_check: + command += ['--enable_gn_check'] + + if self._sanitizer: + command += ['--sanitizer', self._sanitizer] + + if self._build_target: + command += ['--build_target', self._build_target] + + if self._enable_code_coverage: + command += ['--enable_code_coverage'] + + if self._skip_create_zip: + command += ['--skip_create_zip'] + + returncode, stdout, _ = self.exec_subprocess(command) + + if returncode != 0: + comments = ninja_utils.ninja_failure_to_comments(stdout, max_errors=3) + for comment in comments: + self.add_review({'message': comment}) + + if self._enable_gn_check: + self.gn_check_to_review(stdout) + + return returncode + + + def StripBinaries(self): + """Strips binaries and *.so files built.""" + # out_dir: "chromium/src/out_audioassistant_grte_eng" + # build_out_dirname = "out_audioassistant_grte_eng" + # buildout_dir_path = "/tmp/Xvsgfvcfg/out_audioassistant_grte_eng" + # build_chromecast.py copies files from build_out_dir to buildout_dir_path + build_out_dirname = os.path.basename(self._outdir) + buildout_dir_path = os.path.join(self.archive_dir, build_out_dirname) + binaries_to_strip = [] + + if not os.path.exists(buildout_dir_path): + print( + 'Directory %s not found. Skipping strip binaries.' + % buildout_dir_path) + return + + # Filter out directories and non *.so files from build outputs + for path in os.listdir(buildout_dir_path): + if os.path.isfile(os.path.join(buildout_dir_path, path)) \ + and ('.so' in path): + binaries_to_strip.append(os.path.join(buildout_dir_path, path)) + + CAST_BINARIES_LIST = [ + 'cast_shell', + 'aurora', + 'ml_framework', + 'exo_main', + 'hello_world' + ] + + # Add cast binaries to binaries_to_strip + for path in os.listdir(buildout_dir_path): + if os.path.isfile(os.path.join(buildout_dir_path, path)) \ + and (path in CAST_BINARIES_LIST): + binaries_to_strip.append(os.path.join(buildout_dir_path, path)) + + # Strip binaries to same path's + for binary_path in binaries_to_strip: + print('Stripping %s' % binary_path) + try: + self.unit_test_helper.StripBinary(binary_path) + except Exception as e: + logging.error( + 'Error while stripping binary %s %s' % (binary_path, str(e))) + + def run(self): + """Builds cast_shell. + + Returns: + True iff there were no errors. + """ + returncode = self.BuildCastShell() + + if self._strip_binaries: + self.StripBinaries() + + cast_shell_exe_path = os.path.join(self._outdir, CAST_SHELL_EXE) + self.add_step_data(cast_shell_utils.CAST_SHELL_EXE_PATH, + cast_shell_exe_path) + print("Cast shell exe path: ", cast_shell_exe_path) + + return returncode == 0
diff --git a/cq/scripts/slave/step/catatester_binaries_step.py b/cq/scripts/slave/step/catatester_binaries_step.py new file mode 100644 index 0000000..849df1f --- /dev/null +++ b/cq/scripts/slave/step/catatester_binaries_step.py
@@ -0,0 +1,115 @@ +"""Build step class for building and testing test binaries.""" + +from __future__ import absolute_import +import logging +import os +import tempfile + +from helpers import cipd_upload_utils +from helpers import py_env_utils +from slave import base_step + + +class CatatesterBinariesException(Exception): + """Raised on step exceptions.""" + + +class CatatesterBinariesBuildStep(base_step.BaseStep): + """Step for building Catatester Binaries.""" + + def __init__(self, py3: bool, **kwargs): + """Creates a CatatesterBinariesBuildStep instance. + + Args: + **kwargs: Any additional args to pass to BaseStep. + """ + base_step.BaseStep.__init__(self, + name='build catatester binaries', + **kwargs) + self.py3 = py3 + + def _get_configs_path(self): # pylint: disable=method-hidden + """Path to the configs file.""" + continuous_tests = os.path.abspath( + self.get_project_path('continuous-tests')) + return os.path.join(continuous_tests, 'lab_system', 'master', 'config') + + def _get_python_path(self): + """Get the PYTHONPATH to execute tests with. + + This method was written based on test/setup_env.sh + """ + python_path = [] + + python_path.append(os.path.abspath(self.get_project_path('test'))) + + # continuous-tests/ has to be above all the other repositories + continuous_tests_repo = os.path.abspath( + self.get_project_path('continuous-tests')) + python_path.append(continuous_tests_repo) + + chromium_repo = os.path.abspath(self.get_project_path('chromium/src')) + chromium_telemetry_repo = os.path.join( + chromium_repo, 'third_party', 'catapult', 'telemetry') + python_path.append(chromium_telemetry_repo) + python_path.append(os.path.join( + chromium_telemetry_repo, 'third_party', 'websocket-client')) + python_path.append(os.path.join(chromium_repo, 'chromecast', 'tools')) + + python_path.append(os.path.join(continuous_tests_repo, 'cq')) + + python_path.append(os.path.abspath( + self.get_project_path('chromiumos/third_party/autotest'))) + python_path.append(os.path.abspath( + self.get_project_path('chromiumos/chromite'))) + + sprockets_repo = os.path.abspath(self.get_project_path('google/sprockets')) + python_path.append(sprockets_repo) + + return os.pathsep.join(python_path) + + def _get_env_path(self, venv_root): + """Prepends virtualenv bin directory to existing $PATH var.""" + venv_bin = os.path.join(venv_root, 'bin') + current_path_var = os.getenv('PATH') + return os.pathsep.join([venv_bin, current_path_var]) + + def _build_binaries(self, venv_root): + """Generates pyinstaller spec files and builds binaries. + + Returns True if build succeeds, else False. + """ + venv_root = self.get_step_data('virtual_env_root') + binary_generator = os.path.join( + self.get_project_path('test'), + 'swarming', 'pyinstaller_tools', 'binary_generator.py') + cmd = [binary_generator] + + env = {} + env['FRAGGLE_ROCK_CONFIG_FILES'] = self._get_configs_path() + env['PYTHONPATH'] = self._get_python_path() + env['PATH'] = self._get_env_path(venv_root) + + returncode, stdout, stderr = py_env_utils.exec_within_virtual_env( + self, venv_root, cmd, env=env) + + if returncode != 0: + logging.error('Failed to generate binaries: %s\n%s', stdout, stderr) + return False + + return True + + def run(self): + """Creates all catatester binaries. + + Sets a build property "review" with the output in case of failure. + + Returns: + True if there were no test errors, else False. + """ + venv_root = self.get_step_data('virtual_env_root') + success = self._build_binaries(venv_root) + if not success: + # TODO(adrexler): Provide more useful failure message + self.add_review({'message': 'Failed to generate all binaries.'}) + return success
diff --git a/cq/scripts/slave/step/ccstudio_step.py b/cq/scripts/slave/step/ccstudio_step.py new file mode 100644 index 0000000..223d96e --- /dev/null +++ b/cq/scripts/slave/step/ccstudio_step.py
@@ -0,0 +1,60 @@ +"""Build step class for CCStudio build.""" + +from __future__ import absolute_import +import os + +from slave import base_step + +class CCStudioStep(base_step.BaseStep): + """Build step class for CCStudio build.""" + + def __init__(self, build_name, name='ccstudio build', **kwargs): + """Create a CCStudioStep instance. + + Args: + build_name: Name of build (e.g. abbey-eng). + name: User-visible name of this step. + **kwargs: Any additional args to pass to BaseStep. + """ + base_step.BaseStep.__init__(self, name=name, **kwargs) + self._build_name = build_name + + def _build(self): + """Build |build_name| image by CCStudioStep. + + Returns: + True if image was built successfully; False if failed. + """ + venv_root = self.get_step_data('virtual_env_root', '/usr') + python_path = os.path.join(venv_root, 'bin') + ccs_dir = os.path.expanduser('~/ccstudio/ccs/eclipse') + src_dir = self.get_project_path('abbey') + dist_dir = self.get_gcs_dir() + command = [ + os.path.join(src_dir, 'build', 'build.sh'), + '--python_path={python_path}'.format(python_path=python_path), + '--ccs_dir={ccs_dir}'.format(ccs_dir=ccs_dir), + '--src_dir={src_dir}'.format(src_dir=src_dir), + '--dist_dir={dist_dir}'.format(dist_dir=dist_dir), + '--build_name={build_name}'.format(build_name=self._build_name), + ] + returncode, stdout, stderr = self.exec_subprocess(command) + if returncode != 0: + self._error_processor(stdout, stderr) + return False + return True + + def run(self): + """Build images. + + Returns: + True if there were no errors. + """ + return self._build() + + def _error_processor(self, stdout, stderr): + # TODO(b/141637066): Improve error handling + if stdout: + self.add_review({'message': stdout}) + if stderr: + self.add_review({'message': stderr})
diff --git a/cq/scripts/slave/step/cipd_upload_step.py b/cq/scripts/slave/step/cipd_upload_step.py new file mode 100644 index 0000000..ce4a1b8 --- /dev/null +++ b/cq/scripts/slave/step/cipd_upload_step.py
@@ -0,0 +1,91 @@ +"""Step class for uploading new CIPD packages.""" +from __future__ import absolute_import +import logging +import os + +from helpers import cipd_upload_utils +from slave import base_step + + +class CIPDUploadError(Exception): + """Raised when an error occurs with CIPDUploadStep.""" + + +class CIPDUploadStep(base_step.BaseStep): + """Uploads a new CIPD package.""" + + def __init__(self, pkg_def, pkg_vars=None, refs=None, tags=None, + verification_timeout=None, step_name='Upload CIPD Package', + **kwargs): + """Constructor. + + Args: + pkg_def: The path to the pkg_def file relative to the build root. + pkg_vars: A dict of variables to pass to cipd with -pkg-var. + refs: A list of refs to be assigned to the uploaded cipd package. + tags: A dict of tags to be assigned to the uploaded cipd package. + verification_timeout: Time allotted for cipd verification step ('XXmXXs'). + step_name: name of the Buildbot step. Used for uniquely identifying the + step and for display in the builder status. + **kwargs: Any additional args to pass to BaseStep. + """ + base_step.BaseStep.__init__(self, + name=step_name, + **kwargs) + self._cipd_upload = self.build_system == 'catabuilder' + if not self._cipd_upload: + self._name += ' DRY RUN' + self._pkg_def_path = pkg_def + self._pkg_vars = pkg_vars + self._refs = refs + self._tags = self._GetDefaultTags() + self._tags.update(tags or {}) + self._verification_timeout = verification_timeout + + def _GetDefaultTags(self): + """Returns a dict of default tags to be included on all CIPD uploads.""" + tags = {} + + tags['system'] = '_'.join([self.build_system, self.env]) + + if 'buildset' in self._properties: + tags['buildset'] = self.get_property('buildset') + + return tags + + # TODO(b/144364136) remove support JSON support after migration to GCE + def _GetServiceAccountJson(self): + """Returns path to service_account_json param for current environment.""" + path = os.environ.get('GOOGLE_APPLICATION_CREDENTIALS') + if not path and self._cipd_upload: + path = ':gce' + return path + + def run(self): + """Uploads the designated CIPD package. + + Returns: + True iff CIPD package is uploaded successfully. + """ + service_account_json = self._GetServiceAccountJson() + + returncode, _, stderr = cipd_upload_utils.UploadCIPDPackage( + self, + self._pkg_def_path, + pkg_vars=self._pkg_vars, + refs=self._refs, + tags=self._tags, + verification_timeout=self._verification_timeout, + service_account_json=service_account_json, + dry_run=not self._cipd_upload) + + if returncode == 0: + if self._cipd_upload: + logging.info('Package uploaded successfully: %s', self._pkg_def_path) + return True + + message = 'CIPD upload for {} exited with nonzero returncode {}. {}'.format( + self._pkg_def_path, returncode, stderr) + logging.error(message) + self.add_review({'message': message}) + return False
diff --git a/cq/scripts/slave/step/clang_format_step.py b/cq/scripts/slave/step/clang_format_step.py new file mode 100644 index 0000000..e7a4074 --- /dev/null +++ b/cq/scripts/slave/step/clang_format_step.py
@@ -0,0 +1,129 @@ +"""Build step class for formatting C++ files with clang-format-diff.""" + +from __future__ import absolute_import +import logging +import os + +from helpers import commit_message_utils +from helpers import diff_utils +from helpers import git_utils +from slave import base_step + +CLANG_FORMAT_DIFF_SCRIPT = 'scripts/helpers/clang_format/clang-format-diff.py' +GIT_DIFF_COMMAND = ['git', 'diff', '-U0', 'HEAD^'] +CLANG_FORMAT_ERROR_MSG = ('Fix format errors with `git cast format` ' + '(see go/git-cast for more info)') + + +class ClangFormatStep(base_step.BaseStep): + """Build step class for clang-formatting C++ files.""" + + def __init__(self, **kwargs): + """Creates a ClangFormatStep instance. + + Note that this step will only format files with the following extensions: + .cc, .cpp, .cxx, .c++, .c, .cl, .h, .hpp, .m, .mm, .inc, .js, .proto, + .protodevel, .java + + Note that this step uses clang-format-diff, so that only the changed + parts of a file are re-formatted. + + Args: + **kwargs: Any additional args to pass to BaseStep. + """ + base_step.BaseStep.__init__(self, name='clang-format', **kwargs) + + def _filter_comments(self, comments): + for filename in list(comments): + if self.allow_listed(filename) and not self.deny_listed(filename): + continue + del comments[filename] + return comments + + def _clang_format_binary(self): + """Returns the path to the clang-format binary. + + This first attempts to find the clang-format from buildtools, but will + fall back to the latest pre-installed clang format if it cannot find it. + + Returns: + Path to the clang-format binary. + """ + try: + chromium_src = self.get_project_path('chromium/src') + clang_format_binary = os.path.join(chromium_src, 'buildtools', 'linux64', + 'clang-format') + if os.path.exists(clang_format_binary): + return clang_format_binary + except KeyError: + pass + + return 'clang-format-3.6' + + def _clang_format_diff_script(self): + """Returns the path of the clang-format-diff.py script.""" + try: + chromium_src = self.get_project_path('chromium/src') + clang_format_diff_script = os.path.join(chromium_src, 'buildtools', + 'clang_format', 'script', + 'clang-format-diff.py') + if os.path.exists(clang_format_diff_script): + return clang_format_diff_script + except KeyError: + pass + + return os.path.join(self.get_cq_root(), CLANG_FORMAT_DIFF_SCRIPT) + + def run(self): + """Runs clang-format-diff on changed files for the current commit. + + Sets a build property "review" with the output. + + Returns: + True iff there were no formatting errors. + """ + # Do not format cherry-picks; errors are ignored for upstream consistency + if git_utils.is_cherry_pick(self, self.directory): + logging.info('clang_format check skipped because this is a cherry-pick.') + return True + + diff_command = (GIT_DIFF_COMMAND, {'cwd': self.directory}) + clang_format_diff = os.path.relpath(self._clang_format_diff_script(), + self.directory) + clang_format = os.path.relpath(self._clang_format_binary(), self.directory) + format_command = (['python3', + clang_format_diff, + '-binary', + clang_format, + '-p1', + '-style', + 'file',], {'cwd': self.directory}) + + returncode, stdout, _ = self.exec_subprocess_chain([diff_command, + format_command]) + + if returncode == 0 and not stdout: + logging.info('clang_format check received no output on stdout') + return True + + comments = diff_utils.diff_to_comments(stdout.splitlines()) + comments = self._filter_comments(comments) + + if not comments: + # All the comments were filtered out, so this was actually a success. + logging.info('clang_format had no comments after filtering.') + return True + + self.add_review({'message': CLANG_FORMAT_ERROR_MSG, 'comments': comments}) + # Do not block the build if this is a revert. + commit_message = git_utils.commit_message(self, self.directory) + if commit_message_utils.is_revert_commit_message(commit_message): + logging.info('looks like a revert, allowing it through.') + return True + logging.info('clang_format failure, adding %d comments.', len(comments)) + logging.info('If you believe that your project should be exempt from ' + 'formatting requirements you can follow the instructions at ' + 'go/cast-format-exemption in order to disable formatting checks ' + 'on your code. This is often useful for projects that pull code ' + 'from third-party sources.') + return False
diff --git a/cq/scripts/slave/step/clang_tidy_step.py b/cq/scripts/slave/step/clang_tidy_step.py new file mode 100644 index 0000000..6a90d1e --- /dev/null +++ b/cq/scripts/slave/step/clang_tidy_step.py
@@ -0,0 +1,239 @@ +"""Build step class for formatting C++ files with clang-tidy-diff.""" + +from __future__ import absolute_import +import logging +import os +from collections import defaultdict +import yaml + +from helpers import commit_message_utils +from helpers import diff_utils +from helpers import git_utils +from slave import base_step + +CLANG_FORMAT_DIFF_SCRIPT = 'clang-tidy-diff.py' +GIT_DIFF_COMMAND = ['git', 'diff', '-U0', 'HEAD^'] + +# TODO(mingcl): point the go link to g3doc and add instructions/explanations +# there +CLANG_TIDY_MSG = ( + 'ClangTidy have some suggestions. This will not block submission. See ' + 'go/eureka-clang-tidy') + + +# Given file name and character offset, return a tuple consisting line number +# and character position in the line +def char_offset_to_line_number(filename, char_offset): + try: + with open(filename) as f: + content = f.read(char_offset) + line_number = content.count('\n') + 1 + line_start_position = content.rfind('\n') + if line_start_position == -1: + char_position = char_offset + else: + char_position = char_offset - (line_start_position + 1) + return (line_number, char_position) + except (OSError, IOError) as _: + logging.info('Cannot open {} in repo. '.format(filename) + + 'It might be a generated file. ' + + 'Returning arbitrary line number and offset ' + + 'because Gerrit will ignore this comment anyway.') + return (1, 0) + + +# Given file, offset and length, convert it to CommentRange object that Gerrit +# API accepts +def to_comment_range_object(base_dir, file_path, offset, length): + (start_line, start_character) = char_offset_to_line_number( + os.path.join(base_dir, file_path), offset) + (end_line, end_character) = char_offset_to_line_number( + os.path.join(base_dir, file_path), offset + length) + return { + 'start_line': int(start_line), + 'start_character': int(start_character), + 'end_line': int(end_line), + 'end_character': int(end_character) + } + + +# Given git repo root and file_path from the repo, normalize and convert +# file_path to the relative path from repo_root. +# This is needed because pathes outputed by clang-tidy-diff script might +# contain redundant double dots +def path_relative_to_repo_root(repo_root, file_path): + return os.path.relpath( + os.path.normpath(os.path.join(repo_root, file_path)), repo_root) + + +def suggestion_to_gerrit_comments(suggestions_str, base_dir): + r""" Convert a YAML clang_tidy output to gerrit comment format + + Comments are formatted according to: + https://gerrit-review.googlesource.com/Documentation/rest-api-changes.html#comment-input + + Args: + suggestions_str: YAML string exported by clang tidy + base_dir: Absolution path of the directory which the clang tidy command is + run in + """ + if not suggestions_str: + return {} + + diagnostics = yaml.safe_load(suggestions_str).get('Diagnostics', []) + + if not diagnostics: + return {} + + comments = defaultdict(list) + + for diagnostic in diagnostics: + diagnostic_name = diagnostic['DiagnosticName'] + diagnostic_message = diagnostic['DiagnosticMessage'] + diagnostic_level = diagnostic['Level'] + # Don't report errors. They will be caught by other builders anyway. + if diagnostic_level == 'Error': + continue + comments[path_relative_to_repo_root( + base_dir, diagnostic_message['FilePath'])].append({ + 'message': + '[non-blocking] ClangTidy: [{}] {}: {}'.format( + diagnostic_name, diagnostic_level, + diagnostic_message['Message']), + 'range': + to_comment_range_object(base_dir, + diagnostic_message['FilePath'], + diagnostic_message['FileOffset'], 1) + }) + for replacement in diagnostic_message['Replacements']: + if replacement['Length'] > 0 and replacement['ReplacementText']: + replacement_suggestion_message = 'Replace this with `' + replacement[ + 'ReplacementText'] + '`.' + elif replacement['Length'] > 0: + replacement_suggestion_message = 'Remove this.' + elif replacement['ReplacementText']: + replacement_suggestion_message = 'Insert `' + replacement[ + 'ReplacementText'] + '` here.' + # Avoid zero length comment length to accurately indicate the location + # of insertion + replacement['Length'] = 1 + else: + # It makes no sense to suggest to replace empty string with empty + # string. Leave the suggestion message empty + replacement_suggestion_message = '' + comments[path_relative_to_repo_root( + base_dir, replacement['FilePath'])].append({ + 'message': + '[non-blocking] ClangTidy: [{}] {}\n{}'.format( + diagnostic_name, diagnostic_message['Message'], + replacement_suggestion_message), + 'range': + to_comment_range_object(base_dir, replacement['FilePath'], + replacement['Offset'], + replacement['Length']) + }) + # If Notes exists, also convert them to comments + for note in diagnostic.get('Notes', []): + comments[path_relative_to_repo_root(base_dir, note['FilePath'])].append({ + 'message': + '[non-blocking] ClangTidy: [{}] {}'.format( + diagnostic_name, note['Message']), + 'range': + to_comment_range_object(base_dir, note['FilePath'], + note['FileOffset'], 1) + }) + return comments + + +class ClangTidyStep(base_step.BaseStep): + """Build step class for clang-tidying C++ files.""" + + def __init__(self, **kwargs): + """Creates a ClangTidyStep instance. + + Note that this step uses clang-tidy-diff, so that only the changed + parts of a file are checked. + + Args: + **kwargs: Any additional args to pass to BaseStep. + """ + base_step.BaseStep.__init__(self, name='clang-tidy', **kwargs) + + def _filter_comments(self, comments): + for filename in list(comments): + if self.allow_listed(filename) and not self.deny_listed(filename): + continue + del comments[filename] + return comments + + def run(self): + """Runs clang-tidy-diff on changed files for the current commit. + + Sets a build property "review" with the output. + + Returns: + True iff there were no suggestions. + """ + # Do not run on cherry-picks; errors are ignored for upstream consistency + if git_utils.is_cherry_pick(self, self.directory): + logging.info('clang_tidy check skipped because this is a cherry-pick.') + return True + + # Do not run if the build looks like a revert. + commit_message = git_utils.commit_message(self, self.directory) + if commit_message_utils.is_revert_commit_message(commit_message): + logging.info('looks like a revert, allowing it through.') + return True + + # Ensure there is prebuilt clang-tidy binary available in + # chromium/src/third_party/llvm-build/Release+Asserts/bin/ + # It won't be there if this step has never been run before. + returncode, _, _ = self.exec_subprocess([ + 'python3', + os.path.join( + self.get_project_path('chromium/src'), + 'tools/clang/scripts/update.py'), '--package', 'clang-tidy' + ]) + if returncode != 0: + return False + + output_file = 'clang_tidy_fixes.yaml' + + diff_command = (GIT_DIFF_COMMAND, {'cwd': self.directory}) + clang_tidy_command = ([ + 'clang-tidy-diff.py', + '-clang-tidy-binary', + os.path.join(self._getcwd(), self.get_project_path('chromium/src'), + 'third_party/llvm-build/Release+Asserts/bin/clang-tidy'), + '-p1', + '-export-fixes', + output_file, + ], { + 'cwd': self.directory + }) + + returncode, stdout, _ = self.exec_subprocess_chain( + [diff_command, clang_tidy_command]) + if returncode != 0: + return False + + clang_tidy_fixes = '' + try: + with open(os.path.join(self.directory, output_file)) as file: + clang_tidy_fixes = file.read() + logging.info('yaml outputed by clang-tidy:\n%s', clang_tidy_fixes) + except (OSError, IOError) as _: + logging.info('clang tidy suggestion file not exist') + + gerrit_comments = suggestion_to_gerrit_comments(clang_tidy_fixes, + self.directory) + + gerrit_comments = self._filter_comments(gerrit_comments) + + if gerrit_comments == {}: + logging.info('clang_tidy has no comments') + return True + + self.add_review({'message': CLANG_TIDY_MSG, 'comments': gerrit_comments}) + + return False
diff --git a/cq/scripts/slave/step/clean_sync_step.py b/cq/scripts/slave/step/clean_sync_step.py new file mode 100644 index 0000000..ac7b513 --- /dev/null +++ b/cq/scripts/slave/step/clean_sync_step.py
@@ -0,0 +1,164 @@ +"""Build step class for setting up a clean build environment.""" + +import logging +import os +import re + +from helpers import gclient_utils +from slave import base_step +from slave.step import shell_step + +_GCLIENT_CWD = 'chromium' +_GCLIENT_ENV = { + # Set libassistant retries to wait for binaries to be compiled + # Expected wait time is about 900 sec. + 'LIBASSISTANT_FINDARCHIVE_RETRY_COUNT': + '15', + 'LIBASSISTANT_FINDARCHIVE_RETRY_INTERVAL': + '300', + # Export CHROME_HEADLESS so that the license agreement is + # automatically accepted in //build/android/play_services/update.py. + 'CHROME_HEADLESS': + '1', + + # Set this so `gclient sync` does not update the ninja files with GYP. + # This call is very expensive and is unecessary: On GN builds, GN is + # used to generate the ninja files, and on GYP builds, we do this as a + # later step. + 'GYP_CHROMIUM_NO_ACTION': + '1', + + # Set this so `gclient sync` will pick up the prebuilt, + # instrumented libraries that msan needs to run effectively. + # Specifically, gclient sync will run + # //third_party/intrumented_libraries/scripts/download_binaries.py$ + # to download the prebuilt library binaries. + 'GYP_DEFINES': ('use_prebuilt_instrumented_libraries=1 ' + 'msan=1 ' + 'msan_track_origins=2'), +} + +_FUCHSIA_SYNC_ENV_VAR = 'FUCHSIA_SYNC' + +_INSERT_SHA = '{INSERT_SHA}' +_INSERT_PROJECT = '{INSERT_PROJECT}' + +_GCLIENT_ERROR_RECOVERY = { + 'Cannot fast-forward merge, attempt to rebase?': [ + 'git', 'reset', '--hard', _INSERT_SHA + ], + 'Conflict while rebasing this branch.': ['git', 'am', '--abort'], + 'Already in a conflict, i.e. (no branch).': ['git', 'am', '--abort'], + 'Command \'git rev-list -n 1 HEAD\' returned non-zero exit status 128': [ + 'git', 'pull' + ], + 'subprocess.CalledProcessError': [ + 'git', 'submodule', 'deinit', '--all', '-f' + ], + 'fetch_post_sync_builddeps.SubmoduleSyncError': [ + 'rm', '-rf', _INSERT_PROJECT + ], +} + +UNIX_SUCCESS_CODE = 0 + + +class UnhandledGClientSyncError(base_step.StepError): + """Exception raised when an unrecognized gclient sync failure happens.""" + + +class GclientSyncStep(shell_step.ShellStep): + """Runs `gclient sync` after patches have been applied.""" + + def __init__(self, **kwargs): + """Creates a GclientSyncStep instance. + + Args: + **kwargs: Any additional args to pass to BaseStep. + """ + shell_step.ShellStep.__init__( + self, name='gclient sync', halt_on_failure=True, **kwargs) + self._gclient_root = kwargs.get('properties', + {}).get('gclient_root', _GCLIENT_CWD) + self._fuchsia_sync = kwargs.get('properties', {}).get('fuchsia_sync', False) + self._gclient_extra_args = kwargs.get('properties', + {}).get('gclient_extra_args') + + def _setup_for_repo_sync_retry(self, returncode, stdout, stderr): + """A function to run before retrying a failed gclient sync.""" + del returncode # Unused. + + for recoverable in _GCLIENT_ERROR_RECOVERY: + if recoverable in stderr: + reg_exp = r'^(?:\d+> )?_+ (?P<project_dir>[^\s]+) at (?P<sha>.*)$' + match = re.search(reg_exp, stderr, re.MULTILINE) + # See b/112112992 for context on the error. + if match: + project_dir = match.group('project_dir') + project_dir = os.path.join(self._gclient_root, project_dir) + sha = match.group('sha') + command = self._insert_template(_GCLIENT_ERROR_RECOVERY[recoverable], + _INSERT_SHA, sha) + self.exec_subprocess(command, cwd=project_dir) + break + + reg_exp = (r'Command \'git rev-list -n 1 HEAD\' ' + r'returned non-zero exit status 128 in (?P<project_dir>.*)') + match = re.search(reg_exp, stderr, re.MULTILINE) + if match: + project_dir = match.group('project_dir') + self.exec_subprocess( + _GCLIENT_ERROR_RECOVERY[recoverable], cwd=project_dir) + break + logging.info('Found error in stderr but fail to recover: %s', + recoverable) + elif recoverable in stdout: + reg_exp = (r'subprocess\.CalledProcessError: Command ' + r'\'\[\'git\', \'-C\', \'(?P<project_dir>.+)\', ' + r'\'submodule\', \'sync\'\]\' returned non-zero exit status') + match = re.search(reg_exp, stdout, re.MULTILINE) + if match: + project_dir = match.group('project_dir') + self.exec_subprocess( + _GCLIENT_ERROR_RECOVERY[recoverable], cwd=project_dir) + break + + # See b/135531243 for context on the error. + reg_exp = r'(?P<project_name>.+) submodules failed to sync' + match = re.search(reg_exp, stdout, re.MULTILINE) + if match: + project_dir = self.get_project_path(match.group('project_name')) + command = self._insert_template(_GCLIENT_ERROR_RECOVERY[recoverable], + _INSERT_PROJECT, project_dir) + self.exec_subprocess(command) + break + logging.info('Found error in stdout but fail to recover: %s', + recoverable) + + def _insert_template(self, command, template, value): + return [w if w != template else value for w in command] + + def get_commands(self): + # Ensures that additions to the gclient env here will remain deterministic. + env = dict(_GCLIENT_ENV) + if self._fuchsia_sync: + env[_FUCHSIA_SYNC_ENV_VAR] = '1' + return [ + # Bazel uses a shared location for extracting its installation. + # Sometimes those installations get corrupt. This forces Bazel to + # extract itself for every build. + self.ShellCommand(['rm', '-rf', + os.path.expanduser('~/.cache/bazel')]), + self.ShellCommand(gclient_utils.disable_depot_tools_auto_update_cmd()), + self.ShellCommand( # pylint: disable=unexpected-keyword-arg + gclient_utils.gclient_sync_cmd( + self._executor, + jobs=self.get_num_jobs(), + extra_args=self._gclient_extra_args, + ), + cwd=self._gclient_root, + env=env, + num_retries=3, + setup_for_retry=self._setup_for_repo_sync_retry, + halt_on_failure=True), + ]
diff --git a/cq/scripts/slave/step/code_coverage_step.py b/cq/scripts/slave/step/code_coverage_step.py new file mode 100644 index 0000000..12f16e4 --- /dev/null +++ b/cq/scripts/slave/step/code_coverage_step.py
@@ -0,0 +1,222 @@ +"""Build step class for generating code coverage reports.""" +import fileinput +import logging +import os +import pathlib +import shutil +import time +from slave import base_step +from slave.step import cast_shell_step +from cq.scripts.helpers import coverage_utils + +COVERAGE_SCRIPT_PATH = 'tools/code_coverage/coverage.py' +COVERAGE_REPORT_PATH = 'code_coverage_html' +COVERAGE_LCOV_PATH = f'{COVERAGE_REPORT_PATH}/linux/coverage.lcov' +STEP_DATA_TEST_LIST = 'step_data_test_list' + +# This is a list of test suites to filter out of the coverage +# run. Tests are added to this list of they crash, or otherwise disrupt the +# generation of code coverage data. +TESTS_TO_FILTER_OUT = [ + 'bindings_browsertests', # b/178190494 + 'cast_shell_browsertests', # b/178190494 + 'cast_shell_internal_browsertests', # b/178190494 +] + +# TODO(b/232528731): Can potentially try to find where this is defined +# dynamically to avoid hardcoding it. If possible, +# use a configuration variable instead. +PREFIX_FILTER = '/b/f/w' + + +class RunCoverageCommandStep(cast_shell_step.NonOtaBuildBaseStep): + """Build step class generating code coverage data.""" + + def __init__(self, branding, build_type, product, build_flavor, + sanitizer=None, build_args_product=None, junit=False, + ignore_filename_regex=None, report_format=None, + build_out_dir=None, test_env=None, **kwargs): + """Creates a RunCoverageCommandStep instance. + + Args: + branding: Build branding (chromium or chrome). + build_type: Type of system to build for ('x86', 'clang', or 'arm'). + product: product to build for (ie. 'chromecast', 'audio'). + build_flavor: Flavor of build ('Debug', 'Eng', 'Release'). + sanitizer: Clang sanitizer to run with ('asan', 'msan', 'tsan', 'ubsan'). + build_args_product: The name of one of the + chromecast/internal/build/args/product files to use for the GN args. + junit: If true, run junit tests, otherwise run gtests (Default False). + ignore_filename_regex: Skip source code files with file paths that match + the given regular expression. + report_format: Output format of the "llvm-cov show/export" command + ('html', 'text', 'lcov'). + build_out_dir: Build output directory. + test_env: Dictionary of env variables to set while executing tests. + **kwargs: Any additional args to pass to BaseStep. + """ + cast_shell_step.NonOtaBuildBaseStep.__init__( + self, 'generate coverage data', branding, build_type, + product, build_flavor, sanitizer=sanitizer, timeout_secs=0, + build_args_product=build_args_product, **kwargs) + + self._junit = junit + self._ignore_filename_regex = ignore_filename_regex + self._format = report_format + self._build_out_dir = build_out_dir + self._test_env = test_env + + def _get_build_out_dir(self, use_flavor=False): + if self._build_out_dir: + return self._build_out_dir + + out_dir = ['out', self.build_type_dir, self.build_product_dir, 'gn'] + if self._sanitizer: + out_dir.append(self._sanitizer) + + if use_flavor: + return os.path.join('_'.join(out_dir), self.build_flavor_dir) + + return '_'.join(out_dir) + + def _generate_coverage_args(self, test_list): + """Generates unit test related arguments for the coverage script. + + The coverage script takes in a list of unit test binaries as + an argument, and a corresponding test command for that binary. + This function reads from a list of test commands and constructs + a list of binaries and the command for that binary to be parsed + by coverage. + + Args: + test_list: A list where each element represents a test command. + + Returns: + A list of binaries and a list of commands arguments. + """ + test_binary_list = [] + test_command_list = [] + + for test_binary_command in test_list: + test_command = test_binary_command.strip().split(' ') + test_name = test_command[0] + if test_name in TESTS_TO_FILTER_OUT: + # Skip filtered tests + continue + test_binary_list.append(test_name) + test_command_list.append('--command') + test_command_list.append( + self._construct_formatted_test_command(test_command)) + + return test_binary_list, test_command_list + + def _construct_formatted_test_command(self, test_command): + """Formats a test command to be parsed by the coverage script. + + Args: + test_command: A list representation of a test command. + + Returns: + String argument representation of test command for the coverage script. + """ + test_path = os.path.join(self._get_build_out_dir(use_flavor=True), + test_command[0]) + return '{} {}'.format(test_path, ' '.join(test_command[1:])) + + def _get_test_list(self): + return self.get_step_data(STEP_DATA_TEST_LIST) + + def get_lcov_output_file_paths(self): + return [pathlib.Path(self.get_gcs_dir()) / COVERAGE_LCOV_PATH] + + def run(self): + """Runs the chromium coverage script and generates a report. + + Returns: + True iff there were no errors. + """ + # JUnit tests are not supported. + if self._junit: + return True + else: + test_list = self._get_test_list() + + test_binary_list, test_command_list = self._generate_coverage_args( + test_list) + + coverage_script_path = os.path.join(self.get_project_path('chromium/src'), + COVERAGE_SCRIPT_PATH) + vpython3_path = os.path.join( + self.get_project_path('chromium/tools/depot_tools'), 'vpython3') + report_path = os.path.join(self.get_gcs_dir(), COVERAGE_REPORT_PATH) + + command = [vpython3_path, coverage_script_path] + command += test_binary_list + command += [ + '-o', report_path, '-b', self._get_build_out_dir(use_flavor=True), '-v'] + if self._format: + command += ['--format', self._format] + if self._ignore_filename_regex: + command += ['--ignore-filename-regex', self._ignore_filename_regex] + command += test_command_list + + # This is necessary because generating the HTML for code coverage can + # take 3+ hours, in which there is no stdout printed at all. Since a + # build is killed if there is no stdout for 2 hours, this block outputs + # every 1 minute to keep the build alive. + # TODO(kevinmk): Work out a way to have the coverage command output + # something meaningful during the HTML generation step. + subprocess, log_fd, log_file_path = self.exec_non_blocking_subprocess( + command, env=self._test_env) + + logging.info('Writing to FD: %d and path %s', log_fd, log_file_path) + + while subprocess.poll() is None: + logging.info('[%s] Waiting for completion...', + time.strftime('%Y-%m-%d %H:%M:%S %Z')) + try: + out_files = os.listdir(report_path) + logging.info('Generated Files: %s', str(out_files)) + except FileNotFoundError: + pass # Ignore the error if the folder hasn't been created yet. + time.sleep(60) + + try: + shutil.copyfile(log_file_path, os.path.join(self.get_gcs_dir(), + 'coverage.py.log')) + with open(log_file_path, 'r') as f: + print(f.read()) + except IOError: + logging.warning('Log file does not exist.') + + return True + + +class CollectLcovCoverageStep(base_step.BaseStep): + """Collects and alters the LCOV files for uploading as artifacts.""" + + def __init__(self, lcov_files, eureka_root, **kwargs): + super().__init__('Collect LCOV Coverage', eureka_root=eureka_root, **kwargs) + self._lcov_files = [pathlib.Path(f) for f in lcov_files] + self._workspace_root = pathlib.Path(eureka_root) + + def run(self): + gcs_dir = pathlib.Path(self.get_gcs_dir()) + artifact_directory = gcs_dir / 'coverage' + artifact_directory.mkdir(exist_ok=True) + lcov_output_property = [] + for lcov_file in self._lcov_files: + output_filename = _transform_file_path(lcov_file) + output_path = artifact_directory / output_filename + logging.info('Copying %s to %s', lcov_file, output_path) + coverage_utils.rewrite_file_paths_in_lcov( + lcov_file, output_path, self._workspace_root) + lcov_output_property.append(str(output_path.relative_to(gcs_dir))) + if lcov_output_property: + self.set_build_property('coverage_lcov_files', lcov_output_property) + return True + + +def _transform_file_path(file_path): + """Constructs a unique filename from path.""" + return '_'.join(file_path.resolve().relative_to('/').parts)
diff --git a/cq/scripts/slave/step/combined_sdk_clean.py b/cq/scripts/slave/step/combined_sdk_clean.py new file mode 100644 index 0000000..3c21d8b --- /dev/null +++ b/cq/scripts/slave/step/combined_sdk_clean.py
@@ -0,0 +1,85 @@ +"""Build step class for setting up a clean SDK build environment.""" + +from __future__ import absolute_import +from slave.step import shell_step + + +_REPO_CMD = ['repo', '--time'] + + +def _dirty_validator(returncode, stdout, stderr): + return returncode == 0 and 'dirty' not in stdout and 'dirty' not in stderr + + +class CleanPrebuiltsSDKStep(shell_step.ShellStep): + """Build step class for setting up a clean SDK build environment.""" + + def __init__(self, purge_dirs, **kwargs): + """Creates a CleanSDKStep instance.""" + shell_step.ShellStep.__init__( + self, + name='SDK: clean build output & prebuilts', + halt_on_failure=True, + num_retries=0, + **kwargs) + self._purge_dirs = purge_dirs + + def get_commands(self): + commands = [] + if self._purge_dirs: + commands += [self.ShellCommand(['rm', '-rf'] + self._purge_dirs)] + return commands + + +class DirtyCheckSDKStep(shell_step.ShellStep): + """Build step class for setting up a clean SDK build environment.""" + + def __init__(self, halt_on_failure=True, **kwargs): + """Creates a CleanSDKStep instance.""" + name = 'SDK: git rev dirty ' + name += 'check' if halt_on_failure else 'info' + shell_step.ShellStep.__init__( + self, + name=name, + halt_on_failure=halt_on_failure, + num_retries=0, + **kwargs) + self._repo_regex = ['-r', kwargs['repo_regex'] + ] if 'repo_regex' in kwargs else [] + + def get_commands(self): + return [ + self.ShellCommand( + _REPO_CMD + [ + 'forall', *self._repo_regex, '-p', '--verbose', '--command', + 'git rev-parse --verify --short HEAD' + ], + validator=_dirty_validator), + ] + + +class CleanCheckoutSDKStep(shell_step.ShellStep): + """Build step class for setting up a clean SDK build environment.""" + + def __init__(self, **kwargs): + """Creates a CleanSDKStep instance.""" + shell_step.ShellStep.__init__( + self, + name='SDK: reset & clean', + halt_on_failure=True, + num_retries=0, + **kwargs) + self._repo_regex = ['-r', kwargs['repo_regex'] + ] if 'repo_regex' in kwargs else [] + + def get_commands(self): + return [ + self.ShellCommand(_REPO_CMD + [ + 'forall', *self._repo_regex, '-p', '--verbose', '--command', + 'git reset --hard' + ]), + self.ShellCommand(_REPO_CMD + [ + 'forall', *self._repo_regex, '-p', '--verbose', '--command', + 'git clean -fdx' + ]), + ]
diff --git a/cq/scripts/slave/step/combined_sdk_compile.py b/cq/scripts/slave/step/combined_sdk_compile.py new file mode 100644 index 0000000..3d431d3 --- /dev/null +++ b/cq/scripts/slave/step/combined_sdk_compile.py
@@ -0,0 +1,141 @@ +"""Build step class for compiling SDK.""" + +from __future__ import absolute_import +import os + +from slave.step import shell_step + + +class BaseSDKStep(shell_step.ShellStep): + """Base step class for SDK build.""" + + def __init__(self, name, build_config, **kwargs): + """Creates a BaseSDKStep instance.""" + shell_step.ShellStep.__init__( + self, + name=name, + halt_on_failure=True, + num_retries=0, + **kwargs) + self._vendor_config = build_config['vendor_config'] + + +class OssCreateTarStep(BaseSDKStep): + """Tarball open source files step class for SDK build.""" + + def __init__(self, build_config, **kwargs): + """Creates a OssCreateTarStep instance.""" + BaseSDKStep.__init__(self, name='SDK: tarball open source files', + build_config=build_config, **kwargs) + + def get_commands(self): + oss_sdk_dir = self._vendor_config['oss_sdk_dir'] + oss_sdk_release_script = self._vendor_config['oss_sdk_release_script'] + return [ + self.ShellCommand(['mkdir', '-p', oss_sdk_dir]), + self.ShellCommand([oss_sdk_release_script, oss_sdk_dir]), + ] + + +class CreateTarStep(BaseSDKStep): + """Tarball prebuilt file step class for SDK build.""" + + def __init__(self, build_config, **kwargs): + """Creates a CreateTarStep instance.""" + BaseSDKStep.__init__(self, name='SDK: tar-ing build output', + build_config=build_config, **kwargs) + + def get_commands(self): + prebuilt_file = self._vendor_config['prebuilt_file'] + fake_work_dir = self._vendor_config['fake_work_dir'] + return [self.ShellCommand(['tar', 'czf', + prebuilt_file, + '-C', fake_work_dir, '.'])] + + +class CreateLogDirStep(BaseSDKStep): + """Tarball prebuilt file step class for SDK build.""" + + def __init__(self, build_config, **kwargs): + """Creates a CreateLogDirStep instance.""" + BaseSDKStep.__init__(self, name='SDK: ensure sdk log dir structure exists', + build_config=build_config, **kwargs) + + def get_commands(self): + build_logs_dir = self._vendor_config['build_logs_dir'] + return [self.ShellCommand(['mkdir', '-p', build_logs_dir])] + + +class ArchiveArtifactsStep(BaseSDKStep): + """Copy SDK build artifacts to upload.""" + + def __init__(self, build_config, **kwargs): + """Creates a ArchiveArtifactsStep instance.""" + BaseSDKStep.__init__(self, name='SDK: archive artifacts', + build_config=build_config, **kwargs) + + def get_commands(self): + commands = [] + upload_dir = self.get_gcs_dir() + + prebuilt_file = self._vendor_config['prebuilt_file'] + commands += [self.ShellCommand(['cp', prebuilt_file, upload_dir])] + + build_logs_dir = self._vendor_config['build_logs_dir'] + if os.path.isdir(build_logs_dir) and os.listdir(build_logs_dir): + commands += [self.ShellCommand(['cp', '-r', build_logs_dir, upload_dir])] + + oss_sdk_dir = self._vendor_config['oss_sdk_dir'] + if os.path.isdir(oss_sdk_dir) and os.listdir(oss_sdk_dir): + commands += [self.ShellCommand(['cp', '-r', oss_sdk_dir, upload_dir])] + + return commands + + +class CompileSDKStep(BaseSDKStep): + """Build step class for compiling SDK build.""" + + def __init__(self, build_config, **kwargs): + """Creates a CompileSDKStep instance.""" + name = 'SDK: compile {} SDK'.format(build_config['vendor_config']['name']) + BaseSDKStep.__init__(self, name=name, + build_config=build_config, **kwargs) + self._product = build_config['product'] + + def get_commands(self): + commands = [] + + fake_prebuilt_dir = self._vendor_config['fake_prebuilt_dir'].format( + vendor=self._vendor_config['name'], product=self._product) + commands += [self.ShellCommand(['mkdir', '-p', fake_prebuilt_dir])] + + build_script = self._vendor_config['build_script'] + fake_work_dir = self._vendor_config['fake_work_dir'] + build_command = [build_script, fake_work_dir] + if self._vendor_config['include_product_param']: + build_command.append(self._product) + build_command.append(self.build_number) + build_command.append( + '--venv_root={}'.format(self.get_step_data('virtual_env_root'))) + commands += [self.ShellCommand(build_command)] + return commands + + +class CopySDKStep(BaseSDKStep): + """Build step class for copying the built SDK output""" + + def __init__(self, build_config, **kwargs): + """Creats a CopySDKStep instance.""" + name = 'SDK: copy {} SDK to eureka'.format(build_config.get('product')) + self._eureka_root = kwargs['eureka_root'] + self._build_config = build_config + BaseSDKStep.__init__( + self, name=name, build_config=build_config, **kwargs) + + def get_commands(self): + fake_work_dir = self._vendor_config['fake_work_dir'] + return [ + self.ShellCommand( + ['cp', '-dprv', os.path.join(fake_work_dir, '.'), + str(self._eureka_root)]) + ]
diff --git a/cq/scripts/slave/step/compdb_gen_step.py b/cq/scripts/slave/step/compdb_gen_step.py new file mode 100644 index 0000000..4751646 --- /dev/null +++ b/cq/scripts/slave/step/compdb_gen_step.py
@@ -0,0 +1,92 @@ +""" + Build step class for generating compilation database from build directory, + it is useful for analysis tools that require actual compilation command, + e.g. clang-tidy and iwyu +""" + +from __future__ import absolute_import +import logging +import os + +from helpers import commit_message_utils +from helpers import diff_utils +from helpers import git_utils +from slave import base_step + +BUILD_SCRIPT_PROJECT = 'chromecast/internal' +BUILD_SCRIPT_REL_PATH = 'build/build_chromecast.py' + + +class CompdbGenStep(base_step.BaseStep): + """Build step class for generating compilation database""" + + def __init__(self, build_dir, **kwargs): + """Creates a CompdbGenStep instance. + + Args: + build_dir: The relative path that contains the build. (relative to + chromium/src project path) + **kwargs: Any additional args to pass to BaseStep. + """ + base_step.BaseStep.__init__(self, name='compdb_gen', **kwargs) + self._build_dir = build_dir + + def run(self): + """ Use gn to generate compilation database + + Returns: + True iff success. + """ + + # Make sure build directory exists before using it to generate + # compilation database. (because the next call to exec_subprocess_chain + # can fail silently if the first command files) + returncode, _, _ = self.exec_subprocess( + ['ls', self._build_dir], cwd=self.get_project_path('chromium/src')) + + if returncode != 0: + logging.info( + 'Build directory does not exist. May need to update the build_dir ' + 'argument passed into this step.') + return False + + compdb_gen_command = ([ + 'ninja', '-C', self._build_dir, '-t', 'compdb', 'cxx', 'cc' + ], { + 'cwd': self.get_project_path('chromium/src') + }) + + write_to_file = (['cp', '/dev/stdin', 'compile_commands.json'], { + 'cwd': self.get_project_path('chromium/src') + }) + + _, _, _ = self.exec_subprocess_chain([compdb_gen_command, write_to_file]) + + # Remove rbe specific parameters from compilation database, which + # present before the path of clang++ compiler. This is not required but + # can reduce unnecessary warnings output by clang_tidy/iwyu + # pylint: disable=line-too-long + patch_rbe_command = [ + 'sed', '-i', + 's|"command":.*\.\./\.\./third_party/llvm-build/Release+Asserts/bin/clang++' + ' |"command": ' + '"../../third_party/llvm-build/Release+Asserts/bin/clang++ |g', + 'compile_commands.json' + ] + + _, _, _ = self.exec_subprocess( + patch_rbe_command, cwd=self.get_project_path('chromium/src')) + + # Do the same for clang + # pylint: disable=line-too-long + patch_rbe_command = [ + 'sed', '-i', + 's|"command":.*\.\./\.\./third_party/llvm-build/Release+Asserts/bin/clang' + ' |"command": "../../third_party/llvm-build/Release+Asserts/bin/clang ' + '|g', 'compile_commands.json' + ] + + _, _, _ = self.exec_subprocess( + patch_rbe_command, cwd=self.get_project_path('chromium/src')) + + return True
diff --git a/cq/scripts/slave/step/device_unit_test_step.py b/cq/scripts/slave/step/device_unit_test_step.py new file mode 100644 index 0000000..b4c4fb7 --- /dev/null +++ b/cq/scripts/slave/step/device_unit_test_step.py
@@ -0,0 +1,24 @@ +"""Override ShellStep to set cwd and env.""" + +from __future__ import absolute_import +from slave.step import shell_step + + +class UnitTestShellStep(shell_step.ShellStep): + """Unit test steps which include cwd and env.""" + + def __init__(self, env=None, **kwargs): + """Constructor.""" + shell_step.ShellStep.__init__(self, **kwargs) + self._env = env + + def get_commands(self): + """Returns which commands to be run. Can be overridden by a subclass. + + Returns: + List of ShellCommand objects to execute. + """ + assert isinstance(self._command, list) + return [self.ShellCommand(self._command, + cwd=self.directory, + env=self._env)]
diff --git a/cq/scripts/slave/step/dipper_step.py b/cq/scripts/slave/step/dipper_step.py new file mode 100644 index 0000000..5bf0089 --- /dev/null +++ b/cq/scripts/slave/step/dipper_step.py
@@ -0,0 +1,99 @@ +"""Build step class for Dipper build.""" + +from __future__ import absolute_import +import os + +from slave import base_step + +class DipperStep(base_step.BaseStep): + """Build step class for Dipper build.""" + + def __init__(self, build_name, name='Dipper build', **kwargs): + """Create a Dipper instance. + + Args: + build_name: Name of build (e.g. dipper-eng). + name: User-visible name of this step. + **kwargs: Any additional args to pass to BaseStep. + """ + base_step.BaseStep.__init__(self, name=name, **kwargs) + self._build_name = build_name + + def _get_pip_local_path(self): + """Gets the local python package folder. + + Returns: + The local dipper-required python package folder as string. + """ + gcs_path = self._properties.get( + 'gcs_mirror_path', '/workspace/gcs-mirror') + return os.path.expanduser(os.path.join(gcs_path, + 'team-dipper/python_packages')) + + def _build(self, variant, src_dir): + """Build |build_name| artifacts by Dipper toolchain. + + Args: + variant: "user" or "eng" variant + src_dir: the root path of source codes + + Returns: + True if artifacts were built successfully; False if failed. + """ + os.environ['PIP_FIND_LINKS'] = self._get_pip_local_path() + + build_command = [ + os.path.join('build', 'build.sh'), + '--{variant}'.format(variant=variant), + ] + returncode, stdout, stderr = self.exec_subprocess( + build_command, cwd=src_dir) + if returncode != 0: + self._error_processor(stdout, stderr) + return False + + return True + + def _copy(self, variant, src_dir): + """Copy |build_name| artifacts to GCS. + + Args: + variant: "user" or "eng" variant + src_dir: the root path of source codes + + Returns: + True if artifacts were copied successfully; False if failed. + """ + + artifacts_path = 'out/target/product/dipper' + artifacts_file = os.path.join( + artifacts_path, 'd6_artifacts-{variant}.zip'.format(variant=variant)) + dist_dir = self.get_gcs_dir() + copy_command = [ + 'cp', + artifacts_file, + dist_dir + ] + returncode, stdout, stderr = self.exec_subprocess(copy_command, cwd=src_dir) + if returncode != 0: + self._error_processor(stdout, stderr) + return False + + return True + + def run(self): + """Build artifacts and copy to distribution(GCS). + + Returns: + True if there were no errors. + """ + variant = "user" if self._build_name.endswith("user") else "eng" + src_dir = self.get_project_path('telink/d6') + + return self._build(variant, src_dir) and self._copy(variant, src_dir) + + def _error_processor(self, stdout, stderr): + if stdout: + self.add_review({'message': stdout}) + if stderr: + self.add_review({'message': stderr})
diff --git a/cq/scripts/slave/step/docker_push_testing_step.py b/cq/scripts/slave/step/docker_push_testing_step.py new file mode 100644 index 0000000..b6de619 --- /dev/null +++ b/cq/scripts/slave/step/docker_push_testing_step.py
@@ -0,0 +1,66 @@ +"""Step class for uploading new Docker images for testing team.""" + +from __future__ import absolute_import +import logging +import os + +from slave import base_step + +class DockerPushTestingException(Exception): + """Raised when an error occurs with DockerPushTestingStep.""" + + +class DockerPushTestingStep(base_step.BaseStep): + """Uploads the latest Docker image.""" + + def __init__(self, bucket, path_info, **kwargs): + """ Creates a DockerPushTestingStep instance. + + Args: + bucket: The URL of the docker bucket where the image will be pushed and + stored + path_info: Dictionary to have the project and internal path to the + Dockerfile. For example: + 'path_info': { + 'project': 'project_repo', + 'dockerfile': 'path/to/dockerfile/folder' + } + **kwargs: Any additional args to pass to BaseStep. + """ + base_step.BaseStep.__init__(self, + name='push home-testing Docker image', + **kwargs) + self._docker_bucket = bucket + self._dockerfile_path = os.path.join( + self.get_project_path(path_info['project']), + path_info['dockerfile']) + + def _push_image(self): + """Pushes the image to GCR. + + Returns: + True if push succeeds, False otherwise + """ + cmd = [ + 'cd', + self._dockerfile_path, + ';', + 'docker', + 'push', + self._docker_bucket] + return_code, _, stderr = self.exec_subprocess(cmd) + if return_code != 0: + logging.error('Failed to push image: %s', stderr) + return False + return True + + def run(self): + """Push the build Docker image. + + Returns: + True if successfull, else False. + """ + success = self._push_image() + if not success: + self.add_review({'message': 'Failed to push the image'}) + return success
diff --git a/cq/scripts/slave/step/docker_testing_image_step.py b/cq/scripts/slave/step/docker_testing_image_step.py new file mode 100644 index 0000000..5072aed --- /dev/null +++ b/cq/scripts/slave/step/docker_testing_image_step.py
@@ -0,0 +1,78 @@ +"""Build step class for building home testing docker image.""" + +from __future__ import absolute_import +import logging +import os + +from slave import base_step + + +class DockerImageError(Exception): + """Raised on step exceptions.""" + + +class DockerImageBuildStep(base_step.BaseStep): + """Steps for building docker testing image.""" + + def __init__(self, bucket, path_info, **kwargs): + """Creates a DockerTestingImageBuildStep instance. + + Args: + bucket: The URL of the docker bucket where the image will be pushed and + stored + path_info: Dictionary to have the project and internal path to the + Dockerfile. For example: + 'path_info': { + 'project': 'project_repo', + 'dockerfile': 'path/to/dockerfile/folder' + } + **kwargs: Any additional args to pass to BaseStep. + """ + base_step.BaseStep.__init__(self, + name='docker_testing_image', + **kwargs) + self._docker_bucket = bucket + self._dockerfile_path = os.path.join( + self.get_project_path(path_info['project']), + path_info['dockerfile']) + + def _build_image(self): + """Builds and tags the image. + + Returns: + If successfully built returns True, else False. + """ + build_tag = ':{}'.format(self.build_number) + + cmd = [ + 'cd', + self._dockerfile_path, + ';', + 'docker', + 'build', + '-t', + self._docker_bucket, + '-t', + self._docker_bucket + build_tag, + '.'] + + return_code, _, stderr = self.exec_subprocess(cmd) + + if return_code != 0: + logging.error( + 'Failed to build or tag Docker image:\n%s', stderr) + return False + return True + + def run(self): + """Creates the Docker image and makes the push to GCR. + + Sets a build property "review" with the output in case of failure. + + Returns: + True if there were no test errors, False otherwise. + """ + success = self._build_image() + if not success: + self.add_review({'message': 'Failed to build Docker image.'}) + return success
diff --git a/cq/scripts/slave/step/fetch_ota_step.py b/cq/scripts/slave/step/fetch_ota_step.py new file mode 100644 index 0000000..f1de0af --- /dev/null +++ b/cq/scripts/slave/step/fetch_ota_step.py
@@ -0,0 +1,100 @@ +"""Fetch OTA step.""" + +from __future__ import absolute_import +import importlib +import logging +import os +import sys + +# As per b/128461961 requests is an indirect requirement to import fetcher +import requests +from slave import base_step + + +class FetchOtaException(Exception): # pylint: disable=g-bad-exception-name + """Raised when a fetch_ota_step exception happens.""" + + +class FetchOtaStep(base_step.BaseStep): + """Step to fetch the required OTA for a device.""" + + def __init__( + self, branch, product, board, + flavor, work_dir, **kwargs): + """Creates a FetchOtaStep instance. + + Args: + branch: Which branch should be used. + product: Name of DUT. + board: Type of board of product. + flavor: Type of build. + work_dir: Location of files to work on. + **kwargs: Any additionar args to pass to BaseStep + """ + base_step.BaseStep.__init__(self, name='fetch_ota', **kwargs) + self._branch = branch + self._board_type = board + self._flavor = flavor + self._product = product + self._work_dir = work_dir + + def _get_fetcher_module(self): + """Returns the fetcher class from eurtest. + + Returns: + Fetcher module from eurtest. + """ + test_path = os.path.abspath(os.path.join( + os.pardir, self.get_project_path('test'))) + if test_path not in sys.path: + sys.path.insert( + 0, test_path) + return importlib.import_module('eurtest.tools.build.fetcher') + + def GetFetcher(self): + """Configures the fetcher for the OTA required. + + Returns: + A Fetcher instance for the OTA required for this test run. + """ + fetcher = self._get_fetcher_module() + ota_fetcher = fetcher.GetFetcher( + branch=self._branch, + product=self._product, + flavor=self._flavor, + board_type=self._board_type + ) + return ota_fetcher + + def _fetch(self): + """Fetches the OTA using the recipe information passed down. + + Returns: + If successfully fetched returns True, else False. + """ + success = True + fetcher_lib = self._get_fetcher_module() + ota_fetcher = self.GetFetcher() + try: + ota_fetcher.Fetch(self.get_property('build_number'), self._work_dir) + except fetcher_lib.FetcherError: + success = False + logging.error( + 'Failed to found ota for build %s for %s', + self.get_property('build_number'), + self._product) + return success + + def run(self): + """Fetches and saves in a temporary directory the OTA. + + Returns: + True if successfully fetched the OTA, False otherwise. + """ + success = self._fetch() + if not success: + review_message = 'Failed to fetch OTA for build %s and device %s' % ( + self.get_property('build_number'), + self._product) + self.add_review({'message': review_message}) + return success
diff --git a/cq/scripts/slave/step/fuchsia_cipd_upload_step.py b/cq/scripts/slave/step/fuchsia_cipd_upload_step.py new file mode 100644 index 0000000..fab461f --- /dev/null +++ b/cq/scripts/slave/step/fuchsia_cipd_upload_step.py
@@ -0,0 +1,55 @@ +"""Step class for uploading fuchsia-specific CIPD artifacts.""" + +from __future__ import absolute_import +import os + +from slave import base_step +from slave.step import cipd_upload_step + +class FuchsiaCIPDUploadStep(base_step.BaseStep): + """Generates all required CIPDUploadSteps for a fuchsia build.""" + + def __init__(self, recipe_steps, file_name, yaml_dir, refs=None, tags=None, + pkg_vars=None, **kwargs): + super().__init__(name='fuchsia_cipd_upload', **kwargs) + self.recipe_steps = recipe_steps + self.file_name = file_name + self.yaml_dir = yaml_dir + + # Assert that required CIPD kwargs have been passed in. These + # will be forworded to CIPDUploadStep. + assert refs is not None + assert tags is not None + assert pkg_vars is not None + self.cipd_kwargs = ( + kwargs | { 'refs': refs, 'tags': tags, 'pkg_vars': pkg_vars } + ) + + def run(self): + # Assume that there is only one instance of this step in + # |self._recipe_steps|. + current_step_index = next( + (i for i, step in enumerate(self.recipe_steps) + if isinstance(step, FuchsiaCIPDUploadStep)), -1) + if current_step_index == -1: + raise RuntimeError( + 'Could not find FuchsiaCIPDUploadStep class in recipe') + + contents = [] + with open(self.file_name) as f: + contents = f.readlines() + + # The file locations stored in CIPD_UPLOADS_FILE_NAME are relative + # to chromium root and prefixed with "//". We strip the "//" prefix + # so that the remaining relative path can be easily joined. + for artifact in [line.strip().lstrip('/') for line in contents]: + artifact_yaml = os.path.basename(artifact) + cipd_far_def = os.path.join(self.yaml_dir, artifact) + step = cipd_upload_step.CIPDUploadStep( + cipd_far_def, + step_name='Upload .far CIPD Package: ' + artifact_yaml + '.', + verification_timeout='10m0s', + **self.cipd_kwargs) + # Add the step after the current step, FuchsiaCIPDUploadStep. + self.recipe_steps.insert(current_step_index + 1, step) + return True
diff --git a/cq/scripts/slave/step/fuchsia_emulator_step.py b/cq/scripts/slave/step/fuchsia_emulator_step.py new file mode 100644 index 0000000..6a22d6b --- /dev/null +++ b/cq/scripts/slave/step/fuchsia_emulator_step.py
@@ -0,0 +1,237 @@ +"""Step class for managing a Fuchsia emulator instance using ffx emu.""" + +import logging +import os +import shutil +import socket + +from unittest import mock + +from slave import base_step + + +_STEP_DATA_FEMU_CAST = 'step_data_femu_cast' +_STEP_DATA_FEMU_HTTP = 'step_data_femu_http' +_STEP_DATA_FEMU_HTTPS = 'step_data_femu_https' +_STEP_DATA_FEMU_SSH = 'step_data_femu_ssh' +_STEP_DATA_FEMU_LOG = 'step_data_femu_log' +_STEP_DATA_PACKAGE_SERVER_LOG = 'step_data_package_server_log' + +_FFX_LOG = 'ffx.log' +_FFX_DAEMON_LOG = 'ffx.daemon.log' + +_SSH_CONFIG_TEMPLATE = ''' +# Generated by Eureka CQ FuchsiaEmulatorStep using ffx emu. +# Ports are changed to an available TCP port assigned to QEMU. +Host * + Port {port} + StrictHostKeyChecking no + IdentityFile {auth_path} + ControlPersist 1m + ControlMaster auto + ControlPath /tmp/ssh-%r@%h:%p + ServerAliveInterval 1 + ServerAliveCountMax 3 + ConnectTimeout 5 +''' + +class FuchsiaEmulatorError(RuntimeError): + """Errors relating to FEMU.""" + +class BaseFuchsiaEmulatorStep(base_step.BaseStep): + """BaseFuchsiaEmulatorStep with common utilities.""" + def __init__(self, + fuchsia_sdk_root, + fuchsia_workdir, + product='terminal.qemu-x64', + name='Unknown FEMU step', + **kwargs): + """Creates a BaseFuchsiaEmulatorStep instance. + + Args: + fuchsia_sdk_root: Path to the Fuchsia SDK. + fuchsia_workdir: Path to directory with Fuchsia artifacts. + product: Product image to run the emulator on. + name: Name of the step to pass to BaseStep. + kwargs: Remaining args to pass to BaseStep. + """ + base_step.BaseStep.__init__(self, name=name, **kwargs) + self._fuchsia_sdk_root = fuchsia_sdk_root + prod, board = product.split('.', 1) + self._product_bundle = os.path.join(fuchsia_sdk_root, 'images', prod, board) + # GN SDK scripts + self._ffx = os.path.join(self._fuchsia_sdk_root, 'sdk/tools/x64/ffx') + + # Common Paths + self._fuchsia_workdir_path = fuchsia_workdir + + def _dump_file_to_log(self, file_path): + """Dump file to log. + + Args: + file_path: Location of the file to add to the logger output. + """ + logging.info('%s log:', file_path) + with open(file_path) as file_fd: + logging.info(file_fd.read()) + + +class FuchsiaEmulatorStartStep(BaseFuchsiaEmulatorStep): + """Step for starting local Fuchsia assets on FEMU.""" + + def __init__(self, **kwargs): + """Creates a FuchsiaEmulatorCreateStep instance. + + Args: + kwargs: Passed to FuchsiaEmulatorBaseStep. + """ + BaseFuchsiaEmulatorStep.__init__(self, name="Start FEMU", **kwargs) + self.femu_log = None + self.package_server_log = None + self._ports_in_use = [] + + def _get_available_tcp_port(self, max_attempts=100): + """Find a unique and open port. + + Verify port is available by opening a listening socket on it. + + Verify uniqueness by storing a list of ports returned, and ensuring no + duplicates in this list. + """ + # Search for a port that is open and verify it isn't + # already being used for another FEMU port. + attempts = 0 + while attempts < max_attempts: + attempts += 1 + # Look for an open port + sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + sock.bind(("", 0)) + port = sock.getsockname()[1] + sock.close() + # Verify port is not being used for another port + if port not in self._ports_in_use: + break + if attempts >= max_attempts: + raise FuchsiaEmulatorError('Failed to find open tcp port') + self._ports_in_use.append(port) + return port + + def write_file(self, file, content): + with open(file, 'w') as f: + f.write(content) + + def create_ssh_config(self): + """Create SSH config for the test runner to connect to FEMU. + + Assumes that FEMU has already been started. + """ + home_dir = os.path.expanduser('~') + ssh_dir = os.path.join(home_dir, '.ssh') + returncode, _, _ = self.exec_subprocess(['mkdir', '-p', ssh_dir]) + if returncode != 0: + self._dump_file_to_log(self.femu_log) + self._dump_file_to_log(self.package_server_log) + raise FuchsiaEmulatorError('Failed to create ssh out dir') + ssh_config_path = os.path.join(home_dir, '.fuchsia', 'sshconfig') + ssh_config_content = _SSH_CONFIG_TEMPLATE.format( + port=self._ssh_port, + auth_path=os.path.join(ssh_dir, 'fuchsia_ed25519')) + self.write_file(ssh_config_path, ssh_config_content) + logging.info('ssh_config for chromium test at %s', ssh_config_path) + + def start_femu(self): + """Start Fuchsia Emulator process.""" + self._ssh_port = self._get_available_tcp_port() + + _, self.femu_log = self.get_new_tmp_file() + logging.info('femu log at %s', self.femu_log) + self.add_step_data(_STEP_DATA_FEMU_LOG, self.femu_log) + + _, self.package_server_log = self.get_new_tmp_file() + logging.info('package server log at %s', self.package_server_log) + self.add_step_data(_STEP_DATA_PACKAGE_SERVER_LOG, self.package_server_log) + + # HACK(b/290049007) + # For currently unknown reasons, there is an ffx daemon socket already + # present, but occassionally unresponsive. The emu start command will + # fail if it attempts to use this bad daemon. As a stop-gap measure + # to get Eureka CQ/CB back to green, we will force restart the daemon. + ffx_daemon_stop = [ + self._ffx, + '-c', 'log.level=debug', + '-c', 'log.dir={}'.format(self._fuchsia_workdir_path), + 'daemon', + 'stop', + '-t', '5000', + ] + self.exec_subprocess(ffx_daemon_stop, check_output=True) + + # Start FEMU + femu_command = [ + self._ffx, + '--timeout', '100', + '-c', 'log.level=debug', + '-c', 'log.dir={}'.format(self._fuchsia_workdir_path), + 'emu', + 'start', + '--startup-timeout', '100', + self._product_bundle, + '--log', self.femu_log, + '--port-map', f'ssh:{self._ssh_port}', + '--headless', # Run without gui on infra + ] + self.exec_subprocess(femu_command, check_output=True) + + def run(self): + """Starts a local FEMU instance.""" + self.start_femu() + # Copy SSH config needed for chromium test runners. + self.create_ssh_config() + # Output logs to give additional debugging information. + self._dump_file_to_log(self.femu_log) + # Store femu ports in step data for test steps. + self.add_step_data(_STEP_DATA_FEMU_SSH, self._ssh_port) + return True + + +class FuchsiaEmulatorTeardownStep(BaseFuchsiaEmulatorStep): + """Step for cleaning up after the FuchsiaEmulatorStartStep.""" + + def __init__(self, **kwargs): + """Creates a FuchsiaEmulatorTeardownStep instance.""" + BaseFuchsiaEmulatorStep.__init__(self, name="Teardown FEMU", **kwargs) + + def _copy_logs_to_gcs(self): + """Copies FuchsiaEmulator related logs to the GCS directory""" + log_source_files_to_destinations = { + self.get_step_data(_STEP_DATA_FEMU_LOG): 'femu_system_log.txt', + self.get_step_data( + _STEP_DATA_PACKAGE_SERVER_LOG + ): 'package_server_log.txt', + os.path.join(self._fuchsia_workdir_path, _FFX_LOG): 'ffx.log', + os.path.join( + self._fuchsia_workdir_path, _FFX_DAEMON_LOG + ): 'ffx.daemon.log', + } + + for src, dst in log_source_files_to_destinations.items(): + if not os.path.isfile(src): + logging.warning('The expected log file "%s" does not exist!', src) + continue + + gcs_upload_dst = os.path.join(self.get_gcs_dir(), dst) + shutil.copyfile(src, gcs_upload_dst) + + def run(self): + """Cleanup after FuchsiaEmulatorTeardownStep.""" + # Kill FEMU + self._copy_logs_to_gcs() + femu_command = [self._ffx, + 'emu', + 'stop', + '--all', + ] + # Don't check the return code. If emulator crashed, ffx emu will + # throw an error but it doesn't mean the kill action failed. + self.exec_subprocess(femu_command) + return True
diff --git a/cq/scripts/slave/step/fuchsia_hermetic_test_step.py b/cq/scripts/slave/step/fuchsia_hermetic_test_step.py new file mode 100644 index 0000000..bbc3dcd --- /dev/null +++ b/cq/scripts/slave/step/fuchsia_hermetic_test_step.py
@@ -0,0 +1,25 @@ +"""Build step class for executing Fuchsia hermetic tests.""" + +from __future__ import absolute_import +import os + +from slave import base_step +from slave.step import shell_step + +class FuchsiaHermeticTestStep(base_step.BaseStep): + """Build step class to run runner scripts as unit tests.""" + + def __init__(self, name='fuchsia_hermetic_tests', arch='x64', **kwargs): + base_step.BaseStep.__init__(self, name=name, **kwargs) + self._arch = arch + + def run(self): + command = ['python3', os.path.join(self.get_project_path('standalone/src'), + 'build/fuchsia/catabuilder_test_hook.py')] + + command += ['--test_group_name', self.name] + command += ['--arch', self._arch] + + returncode, _, _ = self.exec_subprocess(command) + + return returncode == 0
diff --git a/cq/scripts/slave/step/fuchsia_unittest_step.py b/cq/scripts/slave/step/fuchsia_unittest_step.py new file mode 100644 index 0000000..ba538ad --- /dev/null +++ b/cq/scripts/slave/step/fuchsia_unittest_step.py
@@ -0,0 +1,117 @@ +"""Build step class for executing unit tests.""" + +from __future__ import absolute_import +import logging +import os + +from helpers import git_utils +from slave import base_step +from slave.step import shell_step + +class Error(RuntimeError): + """Error for this module.""" + + +class FuchsiaUnitTestStep(base_step.BaseStep): + """Build step class to run runner scripts as unit tests.""" + + def __init__(self, out_dir, fuchsia_workdir, recipe_steps, + name='fuchsia_unit_test', **kwargs): + base_step.BaseStep.__init__(self, name=name, **kwargs) + self._changed_files = None + self._fuchsia_workdir = fuchsia_workdir + self._out_dir = out_dir + self._step_kwargs = kwargs + self._recipe_steps = recipe_steps + + def _current_step_index(self): + """Returns first index of this class in _recipe_steps.""" + for step in self._recipe_steps: + # Assume there is only one instanceof this class. + if isinstance(step, FuchsiaUnitTestStep): + return self._recipe_steps.index(step) + return -1 + + def _gunit_retry_if(self, returncode, stdout, stderr): + """Returns whether or not the chromium unit test should be retried. + + See more: + //chromium/src/build/fuchsia/runner_exceptions.py + """ + # Test runner exits between [60, 80] for infra related flakes. + if 60 < returncode < 80: + return True + # Not all exceptions are caught by the test runner, and some require + # extra checks + reasons = [ + # Package server failed to transfer blobs in time for test + "Error while resolving", + # Long running tests may experience the ssh connection dropping + "Timeout when executing", + ] + for retry_reason in reasons: + if retry_reason in stdout: + return True + return False + + + def add_unittest_step(self, suite_name, runner_cmd, fail_fast=False): + # 15 mins max timeout per test suite. Some tests like net_unittest + # take more than 5 mins to run. + max_timeout_secs = 15 * 60 + # This step name makes it easy to filter Fuchsia test flakiness in the + # CQ build reliability dashboard + step_name = "Fuchsia Unittest %s" % suite_name + step = shell_step.ShellStep( + command=runner_cmd, + num_retries=2, + retry_if=self._gunit_retry_if, + directory=os.getcwd(), + halt_on_failure=fail_fast, + name=step_name, + timeout_secs=max_timeout_secs, + **self._step_kwargs) + # This step should be added after the current fuchsia unittest step. + # However, it is created during the recipe run, which is non-trivial. + current_step_index = self._current_step_index() + if current_step_index == -1: + raise Error('Could not find FuchsiaUnitTestStep class to append to') + self._recipe_steps.insert(current_step_index + 1, step) + + def read_file(self, file_path): # pylint: disable=method-hidden + """Reads a file. + + Args: + file_path: A string with the path to the file open. + + Returns: + A list of strings with the file content. + """ + content_list = [] + with open(file_path) as f: + content_list = f.readlines() + return [line.strip() for line in content_list] + + def run(self): + test_list_path = os.path.join(os.getcwd(), self._out_dir, 'tests', + 'fuchsia_run_test_list.txt') + runner_folder = os.path.join(os.getcwd(), self._out_dir, 'bin') + test_list = self.read_file(test_list_path) + for suite_cmd in test_list: + suite_cmd_parts = suite_cmd.split() + suite_name = suite_cmd_parts[0] + + runner_script = 'run_{}'.format(suite_name) + fuchsia_out_dir = os.path.join(self._fuchsia_workdir, 'packages') + logs_dir = os.path.join(self.get_gcs_dir(), suite_name) + os.makedirs(logs_dir, exist_ok=True) + + runner_cmd = [ + os.path.join(runner_folder, runner_script), + '--logs-dir', logs_dir, + '--device', 'device', + '--fuchsia-out-dir', fuchsia_out_dir + ] + suite_cmd_parts[1:] # Append gtest filters to the command + + self.add_unittest_step(suite_name, runner_cmd, fail_fast=False) + return True
diff --git a/cq/scripts/slave/step/gcs_upload_step.py b/cq/scripts/slave/step/gcs_upload_step.py new file mode 100644 index 0000000..5cc2177 --- /dev/null +++ b/cq/scripts/slave/step/gcs_upload_step.py
@@ -0,0 +1,85 @@ +"""Build step class for uploading artifacts to GCS bucket.""" +from __future__ import absolute_import +import logging +import os + +from helpers import gcs_utils +from helpers import repo_utils +from slave import base_step + + +class GcsUploadStep(base_step.BaseStep): + """Build step class for uploading artifacts to GCS bucket.""" + + def __init__(self, gcs_bucket, gcs_path, src_path=None, skip_empty=False, + name='gcs_upload', result_property='gcs_output', **kwargs): + """Creates a GcsUploadStep instance. + + Step will upload from src_path to bigstore + The bigstore destination will be gs://<gcs_bucket>/<gcs_path> + If src_path pointing to dir, content of dir (e.g. file.txt) will be + uploaded to GCS as gs://<gcs_bucket>/<gcs_path>/file.txt + If src_path pointing to file (e.g. file.jpg) and gcs_path have trailing + slash, file will be uploaded gs://<gcs_bucket>/<gcs_path>/file.jpg + If src_path pointing to file (e.g. file.txt) and gcs_path does not have + trailing slash, than last component of gcs_path will become new name of + the uploaded object, file will be uploaded to gs://<gcs_bucket>/<gcs_path> + + Args: + gcs_bucket: destination bucket name. + gcs_path: relative path in bucket to upload src_path. + src_path: local path to file or dir upload, default to get_gcs_dir(). + skip_empty: if true step will not proceed and return success when + src_path does not exists or epmty dir. + name: step name. + result_property: name of property to save upload location and result. + **kwargs: Any additional args to pass to BaseStep. + """ + self._src_path = src_path + self._skip_empty = skip_empty + self._gcs_bucket = gcs_bucket + self._gcs_path = gcs_path + self._result_property = result_property + base_step.BaseStep.__init__(self, name=name, **kwargs) + + def run(self): + """Uploading to bigstore. + + Returns: + True if upload completed successfully. + """ + + if not self._src_path: + self._src_path = self.get_gcs_dir() + if self._skip_empty: + if not os.path.exists(self._src_path): + logging.info('Path %s does not exist, skipping', self._src_path) + return True + if os.path.isdir(self._src_path) and not os.listdir(self._src_path): + logging.info('Directory %s is empty, skipping', self._src_path) + return True + + if os.path.isdir(self._src_path): + path_to_upload = os.path.join(self._src_path, '.') + gcs_path = self._gcs_path + else: + path_to_upload = self._src_path + gcs_path = os.path.join(self._gcs_path, os.path.basename(self._src_path)) + + gcs_uri = 'gs://{gcs_bucket}/{gcs_path}'.format( + gcs_bucket=self._gcs_bucket, gcs_path=gcs_path) + command = gcs_utils.upload_directory_cmd( + path_to_upload, gcs_uri) + with repo_utils.normalize_manifest_if_exists( + self.get_property('manifest_override_path')): + returncode, _, _ = self.exec_subprocess(command) + gcs_output = { + 'uri': gcs_uri, + 'path': self._gcs_path, + 'bucket': self._gcs_bucket, + 'result': returncode, + } + self.set_build_property(self._result_property, gcs_output) + if returncode != 0: + return False + return True
diff --git a/cq/scripts/slave/step/git_clean_step.py b/cq/scripts/slave/step/git_clean_step.py new file mode 100644 index 0000000..702c786 --- /dev/null +++ b/cq/scripts/slave/step/git_clean_step.py
@@ -0,0 +1,46 @@ +"""Git clean step.""" + +from __future__ import absolute_import +import logging + +from helpers import branch_utils +from slave import base_step + + +class GitCleanStep(base_step.BaseStep): + """git clean step class.""" + + def __init__(self, **kwargs): + """Creates a GitCleanStep instance. + + Args: + **kwargs: Any additional args to pass to BaseStep. + """ + base_step.BaseStep.__init__(self, name='git_clean', **kwargs) + self._clean_project = self.get_property('git_clean_project') + self._min_branch = self.get_property('git_clean_min_branch') + + def run(self): + # Do all the cleaning. + command = ['git', 'clean', '-x', '-f', '-d'] + + if not branch_utils.is_branch_equal_to_or_later_than( + self.manifest_branch, self._min_branch): + logging.info('Branch is older than %s, nothing to do.', self._min_branch) + return True + + logging.info("Clean project is '%s'", self._clean_project) + if not self._clean_project: + return True + projects = [p.strip() for p in self._clean_project.split(',')] + + for project in projects: + if project: + clean_dir = self.get_project_path(project) + else: + clean_dir = None + logging.info("Cleaning project '%s' at '%s'", project, clean_dir) + returncode, _, _ = self.exec_subprocess(command, cwd=clean_dir) + if returncode != 0: + return False + return True \ No newline at end of file
diff --git a/cq/scripts/slave/step/gn_check_step.py b/cq/scripts/slave/step/gn_check_step.py new file mode 100644 index 0000000..bb8fd9e --- /dev/null +++ b/cq/scripts/slave/step/gn_check_step.py
@@ -0,0 +1,205 @@ +"""Build step class for running `gn check`.""" +import logging +import os + +from helpers import git_utils +from helpers import gn_utils +from helpers import py_env_utils +from slave import base_step + +_GN_ROOT_DIR_PROJECT = 'chromium/src' +_GN_CHECK_OUT_DIR = 'out_gn_check' +_MESH_TAG = '-mesh-eng' + +# Bare bones GN configs that allow for basic smoke tests to run during +# presubmit. All the full builds also do GN checks as part of the build, +# so the full GN configs will also be tested. +_DESKTOP_VIDEO_GN_ARGS = ['is_chromecast=true', + 'chromecast_branding="internal"'] +_DESKTOP_AUDIO_GN_ARGS = ['is_chromecast=true', + 'chromecast_branding="internal"', + 'is_cast_audio_only=true'] +_GN_CONFIGS = [_DESKTOP_VIDEO_GN_ARGS, + _DESKTOP_AUDIO_GN_ARGS,] + + +class GnCheckStepBase(base_step.BaseStep): + """Base step for running GnCheck. + + The key part here being shared is the method for parsing gn check output + and making it into a comment. + """ + + def __init__(self, name:str='gn check', **kwargs): + super().__init__(name=name, **kwargs) + + def run(self): + raise NotImplementedError + + def gn_check_to_review(self, stdout): + """Converts gn_check |stdout| into comments and adds them to the review.""" + comments = gn_utils.gn_check_error_to_comments(stdout) + + # GN makes comments relative to the root GN directory, + # but we want the file comments to be relative to |self.directory| + directory_prefix = self.directory + gn_root_dir = self.get_project_path(_GN_ROOT_DIR_PROJECT) + if directory_prefix.startswith(gn_root_dir): + directory_prefix = directory_prefix[len(gn_root_dir + os.path.sep):] + + # GN can generate comments for files not directly included in the CL, so + # split these comments out to the review message + files_in_cl = git_utils.changed_files(self, directory=self.directory) + file_comments, review_comments = {}, {} + for filename, comment_list in comments.items(): + full_filename = filename + if directory_prefix and filename.startswith(directory_prefix): + filename = filename[len(directory_prefix + os.path.sep):] + + if filename in files_in_cl: + file_comments[filename] = comment_list + else: + review_comments[full_filename] = comment_list + + # To limit comment filesize, only add the first comment. In theory, seeing + # one GN check issue will inspire people to run gn check locally to clean + # up the other issues. + logging.info('All GN check comments: %s', comments) + break + + # Generate the review message + review_message = [ + 'Run `gn check out_chromecast_$PRODUCT/release` or ', + '`lunch $PRODUCT && make build.ninja ENABLE_GN_CHECK=1`', + ] + for filename, comments in review_comments.items(): + review_message.append(filename) + for comment in comments: + review_message.append('LINE: ' + comment['line']) + review_message.append(comment['message']) + review_message.append('----------') + review_message.append('') + + self.add_review({ + 'message': '\n'.join(review_message), + 'comments': file_comments + }) + + +class GnCheckStep(GnCheckStepBase): + """Build step class for running gn check via generate_gn helper.""" + + def __init__(self, name: str='gn check', **kwargs): + """Creates a GnCheckStep instance. + + Args: + **kwargs: Any additional args to pass to BaseStep. + """ + super().__init__(name=name, **kwargs) + + def run(self): + """Runs gn gen --check and reports any errors. + + Sets a build property "review" with the output if there are errors. + + Returns: + True iff gn check reported no errors. + """ + out_dir = os.path.join(self.get_tmp_dir(), _GN_CHECK_OUT_DIR) + root_dir = self.get_project_path(_GN_ROOT_DIR_PROJECT) + all_checks_passed = True + for gn_config in _GN_CONFIGS: + command = [gn_utils.GN_BINARY, + 'gen', out_dir, + '--root={}'.format(root_dir), + '--args={}'.format(' '.join(gn_config)), + '--check'] + returncode, stdout, _ = self.exec_subprocess(command, quiet=True) + + if returncode != 0: + all_checks_passed = False + self.gn_check_to_review(stdout) + + return all_checks_passed + + +class GnCheckForOta(GnCheckStepBase): + """Step for running gn check on OTA builds.""" + + def __init__(self, build_name, **kwargs): + """Creats a GnCheckForOta instance. + + Args: + build_name: Name of build (e.g. pepperoni-eng, tvdefault-eng) + **kwargs: Any additional args to pass to BaseStep. + """ + GnCheckStepBase.__init__(self, **kwargs) + self._enable_gn_check = gn_utils.is_gn_check_enabled(self.manifest_branch) + self._product = build_name.split('-')[0] + self._is_mesh_build = build_name.endswith(_MESH_TAG) + self._build_name = build_name.replace(_MESH_TAG, '-eng') + + def rerun_if_necessary(self, returncode, stdout, stderr, command, env): + """Do some cleanup and rerun |command| if it failed previously. + + In the majority of runs, this function will just be a no-op. + + Occasionally, running `make` will produce a corrupted + AllocationTestHarness.P file. This bad file will stay around until it is + cleaned out, causing builds to fail unnecessarily. This checks for this case + and fixes it. (b/31939016) + + Args: + returncode: Returncode from previous run of |command| + stdout: Stdout from previous run of |command| + stderr: Stderr from previous run of |command| + command: Command to potentially re-run (as a list of strings) + env: Extra environment variables to use + + Returns: + (returncode, stdout, stderr) from |command| + """ + if returncode != 0 and 'AllocationTestHarness.P' in stderr: + logging.warning('Bad AllocationTestHarness.P file was detected' + ' (b/31939016). Cleaning and then re-trying the previous' + ' command.') + clean_cmd = ['make', 'clean'] + self.exec_subprocess(clean_cmd) + + returncode, stdout, stderr = self.exec_subprocess(command, env=env) + + return returncode, stdout, stderr + + def run(self): + """"Builds the build.ninja target, passing --check to `gn gen`. + + Returns: + True iff there were no gn check errors. + """ + # `make PRODUCT-$product-build.ninja` is essentally equivalent to + # `lunch $product-eng && make build.ninja`. The build.ninja target + # then invokes `gn gen --check`. + command = [ + 'make', '-j{}'.format(self.get_num_jobs()), + 'PRODUCT-' + self._product + '-build.ninja', + 'ENABLE_GN_CHECK=1', + 'DISABLE_AUTO_INSTALLCLEAN=true', + ] + + if self._is_mesh_build: + command += ['USE_GWIFI=1'] + + command += self.build_accelerator.make_flags + env = self.build_accelerator.environment_variables + + returncode, stdout, stderr = self.exec_subprocess(command, env=env) + + returncode, stdout, _ = self.rerun_if_necessary(returncode, stdout, stderr, + command, env) + + if returncode == 0: + logging.info('gn check reported no issues.') + return True + + self.gn_check_to_review(stdout) + return False
diff --git a/cq/scripts/slave/step/gn_step.py b/cq/scripts/slave/step/gn_step.py new file mode 100644 index 0000000..c6d6068 --- /dev/null +++ b/cq/scripts/slave/step/gn_step.py
@@ -0,0 +1,106 @@ +"""Build steps to run GN commands on eureka internal.""" + +from __future__ import absolute_import +import os + +from helpers import gn_utils +from slave.step import shell_step + + +class GnGenStep(shell_step.ShellStep): + """Build step class to call gn gen as a recipe step.""" + + def __init__(self, build_args_product, build_args, out_dir, cwd, *args, + **kwargs): + self._build_args_product = build_args_product + self._build_args = build_args + self._out_dir = out_dir + super().__init__(name='gn_gen', cwd=cwd, *args, **kwargs) + + def get_commands(self): + """Returns which commands to be run. + + Can be overridden by a subclass. + + Returns: + List of ShellCommand objects to execute. + """ + gn_import = ( + 'import("//chromecast/internal/build/args/product/{}.gn")').format( + self._build_args_product) + build_args = self._build_args + self.build_accelerator.gn_flags + args_str = '{} {}'.format(gn_import, ' '.join(build_args)) + cmd_list = [ + gn_utils.GN_BINARY, 'gen', self._out_dir, '--root=chromium/src', + '--check', '--args={}'.format(args_str) + ] + return [self.ShellCommand(cmd_list, validator=self._validator)] + + +class GnArgsStep(shell_step.ShellStep): + """Build step class to call gn args as a recipe step.""" + + def __init__(self, out_dir, cwd, *args, **kwargs): + cmd_list = [ + gn_utils.GN_BINARY, + 'args', + out_dir, + '--root=chromium/src', + '--list', + '--short', + '--overrides-only', + ] + super().__init__(command=cmd_list, name='gn_list', cwd=cwd, *args, **kwargs) + + +class GnGenCompilationDBStep(shell_step.ShellStep): + """Build step class to call gn gen as a recipe step.""" + + def __init__(self, out_dir, cwd, build_args_product, target_name, *args, + **kwargs): + self._build_args_product = build_args_product + self._target_name = target_name + self._out_dir = out_dir + self._build_args = [ + 'use_rbe=false', 'use_goma=false', 'clang_use_chrome_plugins=false' + ] + super().__init__(name='gn_gen_compdb', cwd=cwd, *args, **kwargs) + + def get_compdb_file_location(self): + return os.path.join(self._out_dir, 'compile_commands.json') + + def get_commands(self): + """Returns which commands to be run. + + Can be overridden by a subclass. + + Returns: + List of ShellCommand objects to execute. + """ + commands = [] + + # Re-generate the GN arguments for the product in order to disable build + # accelerators and clang_use_chrome_plugins. Otherwise, the Kythe analyzer + # will err as it does not have context of these compiler directives. + gn_import = ( + 'import("//chromecast/internal/build/args/product/{}.gn")').format( + self._build_args_product) + args_str = '{} {}'.format(gn_import, ' '.join(self._build_args)) + args_with_acceleration_disabled = '--args={}'.format(args_str) + + # Generate the compdb (compile_commands.json) file. + compile_commands_flag = '--export-compile-commands={}'.format( + self._target_name) + + gen_compdb_command = [ + gn_utils.GN_BINARY, + 'gen', + self._out_dir, + '--root=chromium/src', + args_with_acceleration_disabled, + compile_commands_flag, + ] + commands.append( + self.ShellCommand(gen_compdb_command, validator=self._validator)) + + return commands
diff --git a/cq/scripts/slave/step/gotham_build_step.py b/cq/scripts/slave/step/gotham_build_step.py new file mode 100644 index 0000000..dc6fcae --- /dev/null +++ b/cq/scripts/slave/step/gotham_build_step.py
@@ -0,0 +1,37 @@ +"""Build step class for building Gotham.""" + +from __future__ import absolute_import +from slave import base_step +from slave.step import shell_step + + +class GothamBuildStep(shell_step.ShellStep): + """Step for building Catatester Binaries.""" + + def __init__(self, build_name, board, **kwargs): + """Creates a GothamBuildStep instance. + + Args: + build_name: The type of build. + board: Name of the board. + **kwargs: Any additional args to pass to ShellStep. + """ + self._build_name = build_name + self._board = board + shell_step.ShellStep.__init__(self, command=['./build_gotham.sh'], **kwargs) + + def run(self): + """Runs ShellStep to build gotham after appending venv path. + + Returns: + result of ShellStep + """ + + self._command.append('--skip_setup_venv') + self._command.append('--out_dir={}'.format(self.get_gcs_dir())) + self._command.append( + '--venv_install_dir={}'.format(self.get_step_data('virtual_env_root'))) + self._command.append(self.build_number) + self._command.append(self._build_name) + self._command.append(self._board) + return shell_step.ShellStep.run(self)
diff --git a/cq/scripts/slave/step/host_tests_step.py b/cq/scripts/slave/step/host_tests_step.py new file mode 100644 index 0000000..5c45bcd --- /dev/null +++ b/cq/scripts/slave/step/host_tests_step.py
@@ -0,0 +1,34 @@ +"""Run the Android.mk host tests.""" + +from __future__ import absolute_import +import os + +from slave.step import shell_step + + +_TEST_PROJECT = 'test' +_RUN_HOST_TEST_SCRIPT = 'unit_test/run_host_tests.py' + + +class RunHostTestsStep(shell_step.ShellStep): + """Step to run the Android.mk host tests.""" + + def __init__(self, env=None, **kwargs): + del env # Unsused + shell_step.ShellStep.__init__(self, name='run host tests', **kwargs) + + def get_commands(self): + """Return commands to run the host tests. + + After building the `make test-build-target`, these tests + can be found in out/host/*/bin/* and include tests + such as usbtest and led_unittests. + + Returns: + List of ShellCommand objects to execute to run the host tests. + """ + test_project_dir = self.get_project_path(_TEST_PROJECT) + run_test_script = os.path.join(test_project_dir, _RUN_HOST_TEST_SCRIPT) + return [self.ShellCommand(['python3', run_test_script], + cwd=os.getcwd(), + env={'PYTHONPATH': test_project_dir})]
diff --git a/cq/scripts/slave/step/include_what_you_use_step.py b/cq/scripts/slave/step/include_what_you_use_step.py new file mode 100644 index 0000000..84aed50 --- /dev/null +++ b/cq/scripts/slave/step/include_what_you_use_step.py
@@ -0,0 +1,82 @@ +"""Build step class for analyzing C/C++ include directives""" + +# TODO(mingcl): This step is WIP + +from collections import defaultdict +import logging +import os +import yaml + +from helpers import commit_message_utils +from helpers import diff_utils +from helpers import git_utils +from slave import base_step + +GET_GIT_MODIFIED_FILE_NAMES = ['git', 'diff', '--name-only', 'HEAD^'] + + +class IncludeWhatYouUseStep(base_step.BaseStep): + """Build step class for running iwyu on C/C++ files.""" + + def __init__(self, **kwargs): + """Creates a IncludeWhatYouUseStep instance. + + Note that this step uses clang-tidy-diff, so that only the changed + parts of a file are checked. + + Args: + **kwargs: Any additional args to pass to BaseStep. + """ + base_step.BaseStep.__init__(self, name='clang-tidy', **kwargs) + + def _filter_files(self, filenames): + """Filter out the files that we are going to pass to iwyu tool """ + return [ + filename for filename in filenames if filename.endswith('.cc') and + self.allow_listed(filename) and not self.deny_listed(filename) + ] + + def run(self): + """Runs iwyu on changed files for the current commit. + + Returns: + True iff there were no suggestions. + """ + # Do not run on cherry-picks; errors are ignored for upstream consistency + if git_utils.is_cherry_pick(self, self.directory): + logging.info('iwyu check skipped because this is a cherry-pick.') + return True + + # Do not run if the build looks like a revert. + commit_message = git_utils.commit_message(self, self.directory) + if commit_message_utils.is_revert_commit_message(commit_message): + logging.info('looks like a revert, allowing it through.') + return True + + _, stdout, _ = self.exec_subprocess( + GET_GIT_MODIFIED_FILE_NAMES, cwd=self.directory) + cc_file_names = self._filter_files(stdout.splitlines()) + + if not cc_file_names: + logging.info('No files to check.') + return True + + # TODO(mingcl): Figure out if there is edge cases that checking .cc files + # alone is not enough + logging.info('Going to check the following files: %s', + ' '.join(cc_file_names)) + + # TODO(mingcl): Don't hard code the path of compilation database as ../../ + returncode, stdout, _ = self.exec_subprocess( + ['iwyu_tool', '-p', '../../'] + cc_file_names, cwd=self.directory) + + if returncode != 0: + logging.info('Some errors happened when running iwyu_tool') + return False + + # TODO(mingcl): Analysis iwyu output here + + self.add_review({'message': stdout}) + + # TODO(mingcl): Return false when there are iwyu violations + return True
diff --git a/cq/scripts/slave/step/jacoco_coverage_processing_step.py b/cq/scripts/slave/step/jacoco_coverage_processing_step.py new file mode 100644 index 0000000..ac4b719 --- /dev/null +++ b/cq/scripts/slave/step/jacoco_coverage_processing_step.py
@@ -0,0 +1,276 @@ +"""Build step class for processing jacoco exec files.""" +import collections +import json +import logging +import os +import pathlib +import zipfile +import xml.etree.ElementTree as ET + +from slave.step import cast_shell_step + +COVERAGE_SCRIPT_PATH = 'build/android/generate_jacoco_report.py' +SOURCES_JSON_SUFFIX = '__jacoco_sources.json' +MAPPINGS_FILE = 'jcov_file_mappings.json' + +class JacocoCoverageProcessingStep(cast_shell_step.NonOtaBuildBaseStep): + """Build step class to process jacoco code coverage data.""" + + def __init__( + self, + branding, + build_type, + product, + build_flavor, + coverage_dir, + report_out_dir='report', + report_format='xml', + sanitizer=None, + build_args_product=None, + build_args_official=None, + **kwargs, + ): + """Creates a JacocoCoverageProcessingStep instance. + + Args: + branding: Build branding (chromium or chrome). + build_type: Type of system to build for ('x86', 'clang', or 'arm'). + product: product to build for (ie. 'chromecast', 'audio'). + build_flavor: Flavor of build ('Debug', 'Eng', 'Release'). + coverage_dir: Directory under the build directory that contains the + jacoco exec files. + report_out_dir: Directory under the gcs directory, to output coverage + report. + sanitizer: Clang sanitizer to run with + ('asan', 'msan', 'tsan', 'ubsan'). + build_args_product: The name of one of the + chromecast/internal/build/args/product files to use for the GN args. + report_format: Output format of the jacoco coverage report + ('html', 'xml', 'csv'). + build_args_official: Whether the build is an official build. MUST be set + for any build that will ship to users. Disables debugging; do not + set for development builds. + **kwargs: Any additional args to pass to BaseStep. + """ + super().__init__( + 'process jacoco code coverage data.', + branding, + build_type, + product, + build_flavor, + sanitizer, + build_args_product, + build_args_official, + **kwargs, + ) + self._coverage_dir = coverage_dir + self._report_out_dir = report_out_dir + self._report_format = report_format + + assert report_format in ['xml', 'html', 'csv'] + + def get_output_report_path(self): + if self._report_format == 'xml': + logging.info('gcs dir:%s', self.get_gcs_dir()) + path = ( + pathlib.Path(self.get_gcs_dir()) + / self._report_out_dir + / 'processed_report.xml' + ) + return path + + def _remap_coverage_report_paths(self, input_xml_report, output_xml_report): + """Creates a new xml file which has the file path as in the fs. + + Args: + input_xml_report: path to xml report. + output_xml_report: path to write the procesed xml report. + """ + jacoco_xml = ET.parse(input_xml_report) + mapped_files = set() + + for root, _, files in os.walk(self._outdir, followlinks=True): + for file in files: + if file.endswith(SOURCES_JSON_SUFFIX): + file_path = os.path.join(root, file) + mapped_files = mapped_files.union( + self._get_mappings_from_sources_json(file_path, jacoco_xml) + ) + + self._update_coverage_report_xml( + mapped_files, + jacoco_xml, + output_xml_report, + ) + + def _update_coverage_report_xml( + self, + source_to_workspace_path_mapping, + report_contents, + output_report_path, + ): + root = report_contents.getroot() + + new_packages = collections.defaultdict(lambda: ET.Element('package')) + + new_root = ET.Element('report') + new_tree = ET.ElementTree(new_root) + + for file_mapping in source_to_workspace_path_mapping: + pkg_name, file_name, real_path = file_mapping + real_package_path = str(pathlib.Path(real_path).parent) + file_element = root.find( + f'.//package[@name="{pkg_name}"]//sourcefile[@name="{file_name}"]' + ) + if file_element is None: + continue + + new_packages[real_package_path].set('name', real_package_path) + new_packages[real_package_path].append(file_element) + + for new_package in new_packages.values(): + new_root.append(new_package) + + new_tree.write(output_report_path, encoding='utf-8') + + def _get_mappings_from_sources_json(self, sources_json_file, jacoco_xml): + """Maps the files to their real paths. + + Args: + sources_json_file: path to sources json file. + jacoco_xml: object for parsing xml report. + """ + with open(sources_json_file) as file: + parsed_json = json.load(file) + + mapped_files = set() + src_dirs_sorted = sorted(parsed_json['source_dirs'], key=len) + + for jar_file in parsed_json['input_path']: + with zipfile.ZipFile(jar_file, 'r') as zf: + for java_class_file in zf.infolist(): + package, sourcefile = self._get_filepath_from_classpath( + java_class_file.filename, jacoco_xml) + + if package and sourcefile: + real_path = self._get_path_to_file_from_src_dirs( + src_dirs_sorted, package, sourcefile) + + if real_path: + mapped_files.add((package, sourcefile, real_path)) + + return mapped_files + + def _get_filepath_from_classpath(self, class_file, jacoco_xml): + """Given the class file name and the jacoco_xml object, this function + returns the package name and the filename of the class. + + Args: + class_file: filepath to a class relative to the JAR's root. + jacoco_xml: the parsed Jacoco XML report. + """ + class_name = class_file.split('.')[0] + package = self._get_package_from_class_file(class_file) + root = jacoco_xml.getroot() + + class_element = root.find(f'.//class[@name="{class_name}"]') + + # For some reason, the bool value of some of the element objects are + # `False`. + if class_element is not None: + filename = class_element.attrib['sourcefilename'] + + return package, filename + + return None, None + + def _get_package_from_class_file(self, class_file): + """Given the class file name, this function returns the package name. + + Args: + class_file: name of class file. + """ + return class_file.rsplit('/', 1)[0] + + def _get_path_to_file_from_src_dirs(self, src_dirs, pkg_name, sourcefile): + """Returns the path to the file, given the `source_dirs` list from the + sources json file, the name of the package, and the sourcefile name. + + Args: + src_dirs: `source_dirs` list from sources json file. src_dirs should be + sorted by length of package to avoid issues with overlapping + package names. + pkg_name: name of package. + sourcefile: name of source file. + """ + for src_dir in src_dirs: + if src_dir.endswith(pkg_name): + path = os.path.join('chromium/src', src_dir, sourcefile) + + # Resolve symlinks. + path = os.path.join(self._getcwd(), path) + path = os.path.realpath(path) + path = os.path.relpath(path, self._getcwd()) + + return path + + return None + + def run(self): + """Runs the generate jacoco report script and generates a coverage report + from the jacoco `exec` files. + + Returns: + True iff scripts ran successfuly with no errors. + """ + coverage_script_path = os.path.join( + self.get_project_path('chromium/src'), COVERAGE_SCRIPT_PATH) + + vpython3_path = os.path.join( + self.get_project_path('chromium/tools/depot_tools'), + 'vpython3', + ) + + command = [vpython3_path, coverage_script_path] + command += ['--format', self._report_format] + + report_path = os.path.join(self.get_gcs_dir(), self._report_out_dir) + + # Make sure directory exists. + os.makedirs(report_path, exist_ok=True) + + if self._report_format == 'html': + command += ['--output-dir', report_path] + else: + report_file = os.path.join(report_path, f'report.{self._report_format}') + + command += ['--output-file', report_file] + + coverage_dir_path = os.path.join(self._outdir, self._coverage_dir) + + if (not os.path.exists(coverage_dir_path) or + not os.path.isdir(coverage_dir_path) or + not os.listdir(coverage_dir_path)): + logging.info( + 'No files found under coverage directory: %s... Not processing ' + 'coverage files', + coverage_dir_path, + ) + return True + + command += ['--sources-json-dir', self._outdir] + command += ['--coverage-dir', coverage_dir_path] + command += ['--device-or-host', 'host'] + + returncode, _, _ = self.exec_subprocess(command) + + # Create the mappings file only for xml reports, as this is the only + # format that is accepted by the coverage processor at the moment. + if self._report_format == 'xml': + output_path = self.get_output_report_path() + self._remap_coverage_report_paths(report_file, output_path) + self.set_build_property( + 'coverage_jacoco_files', + [str(output_path.relative_to(self.get_gcs_dir()))]) + + return returncode == 0
diff --git a/cq/scripts/slave/step/json_check_step.py b/cq/scripts/slave/step/json_check_step.py new file mode 100644 index 0000000..ff6b1e0 --- /dev/null +++ b/cq/scripts/slave/step/json_check_step.py
@@ -0,0 +1,55 @@ +"""Build step class for validating JSON files.""" + +from __future__ import absolute_import +import collections +import json +import os +import re + +from helpers import git_utils +from slave import base_step + +_JSON_PARSE_ERROR_MSG = 'This JSON file failed to parse. {}' +_JSON_ERROR_POSITION_PATTERN = r'line (?P<linenum>\d+) column \d+' + + +class JsonCheckStep(base_step.BaseStep): + """Build step class for validating JSON files.""" + + def __init__(self, **kwargs): + """Creates a JsonCheckStep instance. + + Args: + **kwargs: Any additional args to pass to BaseStep. + """ + base_step.BaseStep.__init__(self, name='json check', **kwargs) + + def _value_error_to_comment(self, err): + comment = {'message': _JSON_PARSE_ERROR_MSG.format(str(err))} + match = re.search(_JSON_ERROR_POSITION_PATTERN, str(err)) + if match: + comment['line'] = match.group('linenum') + return comment + + def run(self): + """Attempts to parse all .json files in the current commit. + + Sets a build property "review" with the output if there are any errors. + + Returns: + True iff there were no parsing errors. + """ + comments = collections.defaultdict(list) + for json_filename in self.changed_files(file_extensions=['.json']): + with open(os.path.join(self.directory, json_filename)) as json_file: + try: + json.load(json_file) + except ValueError as err: + comments[json_filename].append(self._value_error_to_comment(err)) + + if comments: + self.add_review({'comments': comments}) + return False + + # No Errors + return True
diff --git a/cq/scripts/slave/step/kythe_step.py b/cq/scripts/slave/step/kythe_step.py new file mode 100644 index 0000000..d37d48f --- /dev/null +++ b/cq/scripts/slave/step/kythe_step.py
@@ -0,0 +1,76 @@ +"""Build steps to run Kythe commands on eureka internal.""" + +import os + +from helpers import git_utils +from slave.step import shell_step + +KYTHE_RUN_EXTRACTOR_BINARY = \ + "chromecast/internal/third_party/kythe/tools/runextractor" +KYTHE_CXX_EXTRACTOR_BINARY = \ + "chromecast/internal/third_party/kythe/extractors/cxx_extractor" +KYTHE_KZIP_BINARY = "chromecast/internal/third_party/kythe/tools/kzip" +EUREKA_INTERNAL_CORUPUS = "eureka-internal.googlesource.com/codesearch" +VNAMES_JSON_FILE_LOCATION = \ + "cq/scripts/resources/kythe_step/vnames.json" + + +class GenerateKzipStep(shell_step.ShellStep): + + def __init__(self, cwd, tests_root, chromium_root, out_dir, compdb_file, + min_expected_kzip_bytes, *args, **kwargs): + super().__init__(name="kythe_gen", cwd=cwd, *args, **kwargs) + + self._tests_root = tests_root + self._chromium_root = chromium_root + self._compdb_file = compdb_file + self._min_kzip_size = min_expected_kzip_bytes + + self._runextractor_binary = os.path.join(self._chromium_root, + KYTHE_RUN_EXTRACTOR_BINARY) + self._cxx_extractor_binary = os.path.join(self._chromium_root, + KYTHE_CXX_EXTRACTOR_BINARY) + self._kzip_binary = os.path.join(self._chromium_root, KYTHE_KZIP_BINARY) + self._kythe_output_directory = os.path.join(out_dir, "kythe-output") + head_sha = git_utils.get_head_sha(self, directory=self._chromium_root) + if head_sha is None: + raise ValueError("Head SHA could not be determined for {}".format( + self._chromium_root)) + self._merged_kzip_file = os.path.join(out_dir, head_sha + ".kzip") + self._initialize_env() + + def get_kythe_output_file(self): + return self._merged_kzip_file + + def _initialize_env(self): + os.environ["KYTHE_ROOT_DIRECTORY"] = os.path.abspath(self._chromium_root) + os.environ["KYTHE_CORPUS"] = EUREKA_INTERNAL_CORUPUS + os.environ["KYTHE_OUTPUT_DIRECTORY"] = self._kythe_output_directory + os.environ["KYTHE_VNAMES"] = os.path.join(self._tests_root, + VNAMES_JSON_FILE_LOCATION) + + def get_commands(self): + cmd_prep_output = ["mkdir", "-p", self._kythe_output_directory] + cmd_gen_kzips = [ + self._runextractor_binary, "compdb", "-extractor", + self._cxx_extractor_binary, "-path", self._compdb_file + ] + cmd_merge_kzips = [ + self._kzip_binary, "merge", "--output", self._merged_kzip_file, + "--recursive", self._kythe_output_directory + ] + cmd_validate_kzip = ["du", "-b", self._merged_kzip_file] + return [ + self.ShellCommand(cmd_prep_output, validator=self._validator), + self.ShellCommand(cmd_gen_kzips, validator=self._validator), + self.ShellCommand(cmd_merge_kzips, validator=self._validator), + self.ShellCommand( + cmd_validate_kzip, validator=self._validate_merged_kzip) + ] + + def _validate_merged_kzip(self, returncode, stdout, stderr): + if returncode != 0: + return False + + byte_size = stdout.split()[0] + return byte_size.isdigit() and int(byte_size) > self._min_kzip_size
diff --git a/cq/scripts/slave/step/landmine_step.py b/cq/scripts/slave/step/landmine_step.py new file mode 100644 index 0000000..3022f4d --- /dev/null +++ b/cq/scripts/slave/step/landmine_step.py
@@ -0,0 +1,87 @@ +"""Landmine step for clobbering output directories when needed. + +This step checks for a landmine file in continuous-tests/cq/landmines, and +clobbers all the output directories if it finds a new landmine. + +For more information on using landmines, checkout out the documentation at +continous-tests/cq/landmines/README.md +""" + +from __future__ import absolute_import +import logging +import os +import re + +from helpers import git_utils +from slave.step import shell_step + +LANDMINE_PATTERN = r'landmine\.(?P<landmine_number>\d+)' + + +class LandmineStep(shell_step.ShellStep): + """Landmine step for clobbering output directories when needed.""" + + def __init__(self, eureka_root, **kwargs): + """Creates a LandmineStep instance.""" + shell_step.ShellStep.__init__(self, + name='landmine', + halt_on_failure=True, + **kwargs) + self._landmine_path = eureka_root / '.landmines' + + def get_landmine_dir(self): + """Return the directory where new landmine files get checked in.""" + continuous_tests = self.get_project_path('continuous-tests') + return os.path.join(continuous_tests, 'cq', 'landmines') + + def get_landmine(self): + """Returns the name of landmine file with the highest number (or None).""" + landmine = None + max_landmine_number = float('-inf') + + landmine_dir = self.get_landmine_dir() + if not os.path.isdir(landmine_dir): + return landmine + + for filename in os.listdir(landmine_dir): + match = re.search(LANDMINE_PATTERN, filename) + if match: + logging.info('Found landmine file: %s', filename) + landmine_number = int(match.group('landmine_number')) + if landmine_number > max_landmine_number: + landmine, max_landmine_number = filename, landmine_number + logging.info('Highest landmine: %s', landmine) + return landmine + + def should_clobber(self, landmine): + """Returns True if |landmine| is new, indicating a clobber should happen.""" + return not (self._landmine_path / landmine).exists() + + def should_mark_landmine_used(self, landmine): + """A landmine should only be marked used once it is committed. + + If a landmine is in the patches running through CQ, then do not mark + the landmine as used, so that if a builder runs another CL between running + the landmine CL and the landmine actually landing, the landmine can run + again. + """ + all_patches = [{'project': self.patch_project}] + self.depends_on_list + changed_files = git_utils.get_changed_files_in_all_patches( + self, all_patches, self.get_project_path_lookup_table()) + return all(landmine not in f for f in changed_files) + + def get_commands(self): + commands = [] + landmine = self.get_landmine() + if landmine and self.should_clobber(landmine): + commands.append(self.ShellCommand(['make', 'clean'], cwd=os.getcwd())) + commands.append(self.ShellCommand( + ['mkdir', '-p', str(self._landmine_path)], + cwd=os.getcwd())) + + if self.should_mark_landmine_used(landmine): + commands.append(self.ShellCommand( + ['touch', str(self._landmine_path / landmine)], + cwd=os.getcwd())) + + return commands
diff --git a/cq/scripts/slave/step/libassistant_sdk_step.py b/cq/scripts/slave/step/libassistant_sdk_step.py new file mode 100644 index 0000000..7c5c2c9 --- /dev/null +++ b/cq/scripts/slave/step/libassistant_sdk_step.py
@@ -0,0 +1,26 @@ +"""Step class for libassistant sdk validation.""" + +from __future__ import absolute_import +import os + +from slave import base_step + + +class SdkValidationStep(base_step.BaseStep): + """Validate libassistant sdk.""" + + def __init__(self, **kwargs): + super(SdkValidationStep, self).__init__(name='verify_sdk', **kwargs) + + def run(self): + """Run the script to validate sdk code. + + Returns: + True iff there were no errors. + """ + verify_script = os.path.join( + self.get_project_path('standalone/src'), + 'build/libassistant/verify_sdk.py') + + returncode, _, _ = self.exec_subprocess([verify_script]) + return returncode == 0
diff --git a/cq/scripts/slave/step/license_manager_step.py b/cq/scripts/slave/step/license_manager_step.py new file mode 100644 index 0000000..6a55acd --- /dev/null +++ b/cq/scripts/slave/step/license_manager_step.py
@@ -0,0 +1,85 @@ +"""Build step class for setting up a build licenses.""" + +from __future__ import absolute_import +import logging +import os +import shlex + +from slave import base_step +from slave.step import shell_step + + +_ANDROID_SDK_PATH = [ + 'chromium/src/third_party/android_sdk/public', + 'chromium/src/third_party/android_tools/sdk', +] +_ANDROID_SDK_MANAGER_BIN = 'tools/bin/sdkmanager' + +_ANDROID_SDK_MANAGER = 'bash -c "yes {param} | {sdk_manager_bin} --licenses"' +_ONLY_CHECK_LICENSE = 'n' +_AUTO_ACCEPT_LICENSE = 'y' + +_ANDROID_SDK_LICENSE_OK = 'All SDK package licenses accepted' +_ANDROID_SDK_LICENSE_FAIL = 'SDK package license not accepted' +_ANDROID_SDK_LICENSES_FAIL = 'SDK package licenses not accepted' + + +def _get_sdk_manager_command(param): + return shlex.split(_ANDROID_SDK_MANAGER.format( + param=param, sdk_manager_bin=_ANDROID_SDK_MANAGER_BIN)) + + +class LicenseError(base_step.StepError): + """Exception raised when an unrecognized license status received.""" + pass + + +class AndroidSdkLicenseCheckAccept(shell_step.ShellStep): + """Build step for checking and accepting Android SDK license.""" + + def __init__(self, **kwargs): + shell_step.ShellStep.__init__( + self, + name='Android SDK License Installation', + halt_on_failure=True, + **kwargs) + self.command = None + + def _android_sdk_status_validator(self, returncode, stdout, stderr): + del returncode, stderr # Unused. + if _ANDROID_SDK_LICENSE_OK in stdout: + logging.info('Android SDK licenses accepted') + return True + if (_ANDROID_SDK_LICENSE_FAIL in stdout + or _ANDROID_SDK_LICENSES_FAIL in stdout): + logging.info('Some Android SDK licenses not accepted') + return False + raise LicenseError('Fail to check status of Android SDK package') + + def _prepare_license_accept(self, returncode, stdout, stderr, cwd=''): + """A function to run before retrying a failed repo sync.""" + del returncode, stdout, stderr # Unused. + logging.info('Auto-accepting Android SDK licenses') + self.exec_subprocess( + _get_sdk_manager_command(_AUTO_ACCEPT_LICENSE), + cwd=cwd) + + def _valid_sdk_path(self): + return [sdk_path for sdk_path in + _ANDROID_SDK_PATH if os.path.isfile(os.path.join( + sdk_path, _ANDROID_SDK_MANAGER_BIN))] + + def get_commands(self): + return [ + self.ShellCommand( + _get_sdk_manager_command(_ONLY_CHECK_LICENSE), + cwd=sdk_path, + num_retries=1, + validator=self._android_sdk_status_validator, + setup_for_retry=( + lambda returncode, stdout, stderr, cwd=sdk_path: + self._prepare_license_accept( + returncode, stdout, stderr, cwd=cwd)), + halt_on_failure=True) + for sdk_path in self._valid_sdk_path() + ]
diff --git a/cq/scripts/slave/step/luci_recipe_step.py b/cq/scripts/slave/step/luci_recipe_step.py new file mode 100644 index 0000000..6e33bcf --- /dev/null +++ b/cq/scripts/slave/step/luci_recipe_step.py
@@ -0,0 +1,68 @@ +"""Executes LUCI recipe tests.""" +from __future__ import absolute_import +import os + +from helpers import luci_recipe_utils +from slave import base_step + +_STEP_TIMEOUT_SECS = 5 * 60 # 5 minutes. + + +class LUCIRecipeBaseStep(base_step.BaseStep): + """Step for executing LUCI recipe commands for a single recipe package.""" + + def __init__(self, + script_path, + package_path, + timeout_secs=_STEP_TIMEOUT_SECS, + **kwargs): + super(LUCIRecipeBaseStep, self).__init__( + timeout_secs=timeout_secs, **kwargs) + script_abspath = os.path.join(self.directory, script_path) + package_abspath = os.path.join(self.directory, package_path) + + self._recipe_runner = luci_recipe_utils.LUCIRecipeRunner( + self, script_abspath, package_path=package_abspath) + + +class LUCIRecipeTestStep(LUCIRecipeBaseStep): + """Step for executing LUCI recipe expectation tests.""" + + def __init__(self, + script_path, + package_path, + test_retries, + **kwargs): + super().__init__( + script_path, package_path, **kwargs) + self._test_retries = test_retries + + def run(self): + retries = 0 + while retries <= self._test_retries: + returncode, _, _ = self._recipe_runner.run_tests() + if returncode == 0: + return True + retries += 1 + + # Max retries reached. + self.add_review({'message': 'Recipe tests failed! See step logs.'}) + return False + + +class LUCIRecipeBundleStep(LUCIRecipeBaseStep): + """Step for bundling a LUCI recipe.""" + + def __init__(self, script_path, package_path, destination, **kwargs): + super(LUCIRecipeBundleStep, self).__init__( + script_path, package_path, **kwargs) + self._destination_abspath = os.path.join(self.directory, destination) + + def run(self): + returncode, _, _ = self._recipe_runner.bundle(self._destination_abspath) + + if returncode != 0: + self.add_review({ + 'message': 'Failed to generate recipe bundle! See step logs.'}) + return False + return True
diff --git a/cq/scripts/slave/step/lucicfg_step.py b/cq/scripts/slave/step/lucicfg_step.py new file mode 100644 index 0000000..6244be6 --- /dev/null +++ b/cq/scripts/slave/step/lucicfg_step.py
@@ -0,0 +1,66 @@ +"""Steps for executing lucicfg commands.""" + +from __future__ import absolute_import +import logging +import os + +from slave import base_step +from helpers import os_utils + +_CONFIG_PATHS_KEY = 'lucicfg_paths' + + +class FindConfigsStep(base_step.BaseStep): + """Step for finding all `main.star` luci configs.""" + + def __init__(self, **kwargs): + super(FindConfigsStep, self).__init__(name='Find luci configs', **kwargs) + + def _get_config_paths(self): + return os_utils.find_files(self.directory, 'main.star') + + def run(self): + config_paths = self._get_config_paths() + logging.info(config_paths) + self.add_step_data(_CONFIG_PATHS_KEY, config_paths) + return True + + +class LucicfgValidateStep(base_step.BaseStep): + """Step for running `lucicfg validate` on `main.star` files.""" + + def __init__(self, **kwargs): + super(LucicfgValidateStep, self).__init__(name='Validate configs', **kwargs) + + def _validate_config(self, config_path): + """Runs `lucicfg validate` against a single config.""" + cmd = ['lucicfg', 'validate', config_path] + + # Validate with GCE service account, if specified. + if self.get_property('gce_service_account'): + cmd.extend(['-service-account-json', + self.get_property('gce_service_account')]) + + retcode, _, stderr = self.exec_subprocess(cmd) + + if retcode == 0: + logging.info('%s is valid!', config_path) + return True + + self.add_review({'message': stderr}) + logging.error('%s is NOT valid!', config_path) + return False + + def run(self): + """Runs the lucicfg validate step. + + Attempts to validate every luci config found in the directory. + Expects depot_tools to be on $PATH. + """ + config_paths = self.get_step_data(_CONFIG_PATHS_KEY) + results = [] + for config_path in config_paths: + result = self._validate_config(config_path) + results.append(result) + + return all(results)
diff --git a/cq/scripts/slave/step/make_clean_step.py b/cq/scripts/slave/step/make_clean_step.py new file mode 100644 index 0000000..b71d813 --- /dev/null +++ b/cq/scripts/slave/step/make_clean_step.py
@@ -0,0 +1,62 @@ +"""Make clean step.""" + +from __future__ import absolute_import +import logging + +from helpers import branch_utils +from slave import base_step + + +class MakeCleanStep(base_step.BaseStep): + """Make clean step class.""" + + def __init__(self, clean_dir=None, **kwargs): + """Creates a MakeCleanStep instance. + + Args: + clean_dir: Dir where to run make clean + **kwargs: Any additional args to pass to BaseStep. + """ + self._clean_dir = clean_dir + base_step.BaseStep.__init__(self, name='clean', **kwargs) + + def run(self): + # Do all the cleaning. + command = ['make', 'clean'] + returncode, _, _ = self.exec_subprocess(command, cwd=self._clean_dir) + + return returncode == 0 + + +class MakeDistCleanStep(base_step.BaseStep): + """Make clean step class.""" + + def __init__(self, **kwargs): + """Creates a MakeCleanStep instance. + + Args: + **kwargs: Any additional args to pass to BaseStep. + """ + base_step.BaseStep.__init__(self, name='distclean', **kwargs) + self._clean_project = self.get_property('make_distclean_project') + self._min_branch = self.get_property('make_distclean_min_branch') + + def run(self): + # Do all the cleaning. + command = ['make', 'distclean'] + + if not branch_utils.is_branch_equal_to_or_later_than( + self.manifest_branch, self._min_branch): + logging.info('Branch is older than %s, nothing to do.', self._min_branch) + return True + + if self._clean_project: + clean_dir = self.get_project_path(self._clean_project) + else: + clean_dir = None + returncode, _, _ = self.exec_subprocess( + command, + cwd=clean_dir, + env={"VERBOSE": "1"}) + + return returncode == 0
diff --git a/cq/scripts/slave/step/ninja_step.py b/cq/scripts/slave/step/ninja_step.py new file mode 100644 index 0000000..650c9b9 --- /dev/null +++ b/cq/scripts/slave/step/ninja_step.py
@@ -0,0 +1,25 @@ +"""Build step class for executing ninja commands.""" + +from __future__ import absolute_import +import os + +from slave.step import shell_step + + +class NinjaStep(shell_step.ShellStep): + """Build step class to call ninja commands as recipe steps.""" + + def __init__(self, out_dir, target, cwd, jobs, *args, **kwargs): + cmd_list = [ + 'ninja', + '-C', + out_dir, + '-k', + '500', + '-j', + str(jobs), + target + ] + name = 'ninja {}'.format(target) + super(NinjaStep, self).__init__( + command=cmd_list, name=name, cwd=cwd, *args, **kwargs)
diff --git a/cq/scripts/slave/step/ota_build_tests_step.py b/cq/scripts/slave/step/ota_build_tests_step.py new file mode 100644 index 0000000..2895c1b --- /dev/null +++ b/cq/scripts/slave/step/ota_build_tests_step.py
@@ -0,0 +1,50 @@ +"""Build step class for building OTA tests..""" + +from __future__ import absolute_import +from slave import base_step +from slave.step import ota_step + + +class OtaBuildTestsStep(ota_step.OtaStep): + """Build step class for building OTA tests.""" + + def __init__(self, build_name, board_name=None, **kwargs): + """Creates a OtaBuildTestsStep instance. + + Args: + build_name: Name of build (e.g. anchovy-eng, tvdefault-eng) + board_name: optional BOARD_NAME param for make if any. + **kwargs: Any additional args to pass to BaseStep. + """ + ota_step.OtaStep.__init__(self, build_name=build_name, + name='build ota tests', + board_name=board_name, **kwargs) + + def run(self): + """Builds ota tests. + + Returns: + True iff there were no errors. + """ + # Because the out/host directory is shared, the host tests can fail if + # the intermediate artifacts are not cleared and rebuilt correctly. Force + # all of out/hosts to get rebuilt everytime by clearing out/host entirely. + command = ['rm', '-rf', 'out/host'] + self.exec_subprocess(command) + + command = ['make', + '-j{}'.format(self.get_num_jobs( + multiplier=ota_step.BUILD_ACCELERATION_JOB_MULTIPLIER)), + 'PRODUCT-' + self._build_name, + 'tests-build-target', + 'DISABLE_AUTO_INSTALLCLEAN=true'] + command += self.build_accelerator.make_flags + command += self._make_extra_flags() + + returncode, stdout, stderr = self.exec_subprocess( + command, env=self.make_command_env()) + + if returncode != 0: + self._error_processor(stdout, stderr) + + return returncode == 0
diff --git a/cq/scripts/slave/step/ota_factory_tool_step.py b/cq/scripts/slave/step/ota_factory_tool_step.py new file mode 100644 index 0000000..3f116ca --- /dev/null +++ b/cq/scripts/slave/step/ota_factory_tool_step.py
@@ -0,0 +1,98 @@ +"""Compile Factory Tools""" + +from __future__ import absolute_import +import os +import shutil + +from slave import base_step +from slave.step import ota_step + + +class CompileFactoryToolStep(ota_step.OtaStep): + """Resign step class for building Factory Tools""" + + def __init__(self, build_name, factory_config, + name='build factory tools', **kwargs): + """Creates a CompileFactoryToolStep instance. + + Args: + build_name: Name of build (e.g. prince-eng, nq-eng) + command: make factory tools command + factory_config: factory tool build configs,types + name: user-visible name of this step. + **kwargs: Any additional args to pass to BaseStep. + """ + self.factory_config = factory_config + ota_step.OtaStep.__init__(self, build_name=build_name, name=name, **kwargs) + + def _make_factory_tools(self): + """Builds Factory tools for Products. + + Returns: + True if the tool was built successfully, False otherwise. + """ + factory_tool_types = self.factory_config.get('factory_tool_types') + if not factory_tool_types: + return True + + command = ['make'] + command += [str(t) for t in factory_tool_types] + command += ['BUILD_NUMBER={}'.format(self.build_number)] + command += self.make_target_param(True) + + returncode, stdout, stderr = self.exec_subprocess(command) + if returncode != 0: + self._error_processor(stdout, stderr) + return False + + if not self._create_factory_dir(): + return False + + return self._copy_factory_tool_to_factory(factory_tool_types) + + def _copy_factory_tool_to_factory(self, factory_tool_types): + """Copy factory tools to tool_type folder""" + product = self._build_name.split('-')[0] + for factory_tool_type in factory_tool_types: + # Use BUILD_NUMBER as factory tools version + target_files_zip = self.factory_config['source_tool_path'].format( + product=product, tool_type=factory_tool_type, + version=self.build_number, ext='zip') + target_files_no_ext, zip_ext = os.path.splitext( + os.path.basename(target_files_zip)) + dest_file_path = os.path.join(self._ota_archive_output_dir(), 'factory', + '{}{}'.format(target_files_no_ext,zip_ext)) + returncode, _, _ = self.exec_subprocess( + ['cp', target_files_zip, dest_file_path]) + if returncode != 0: + return False + # Copy factory-runin2_package-<product>-<version>.sh for runin2_package + if factory_tool_type == 'runin2_package': + runin_sh = self.factory_config['source_tool_path'].format( + product=product, tool_type=factory_tool_type, + version=self.build_number,ext='sh') + runin_sh_dest_path = os.path.join(self._ota_archive_output_dir(), + 'factory', '{}{}'.format(target_files_no_ext, '.sh')) + returncode, _, _ = self.exec_subprocess( + ['cp', runin_sh, runin_sh_dest_path]) + if returncode != 0: + return False + # Copy runin profiles and rename with self.BUILD_NUMBER + runin_profile_path = self.factory_config['runin_profile_path'].format( + product=product) + returncode, _, _ = self.exec_subprocess(['cp', '-r', runin_profile_path, + os.path.join(self._ota_archive_output_dir(), + 'factory')]) + if returncode != 0: + return False + + return True + + def _create_factory_dir(self): + command = ['mkdir', '-p', + os.path.join(self._ota_archive_output_dir(), 'factory')] + returncode, _, _ = self.exec_subprocess(command) + return returncode == 0 + + def run(self): + return self._make_factory_tools()
diff --git a/cq/scripts/slave/step/ota_fct_step.py b/cq/scripts/slave/step/ota_fct_step.py new file mode 100644 index 0000000..808d57a --- /dev/null +++ b/cq/scripts/slave/step/ota_fct_step.py
@@ -0,0 +1,82 @@ +"""FCT steps for building OTA's.""" + +from __future__ import absolute_import +import os +import shutil + +from slave import base_step +from slave.step import ota_step + + +class OtaFctCompileStep(ota_step.OtaStep): + """FCT Compile step class for building OTA's.""" + + def __init__(self, build_name, factory_config, + name='build factory images', **kwargs): + """Creates a OtaFctCompileStep instance. + + Args: + build_name: Name of build (e.g. anchovy-eng, tvdefault-eng) + factory_config: hostboot or usbstick config. Each element of the + 'factory_image_types' will be suffixed with 'image' to form the final + make target. For example, the list ['bft', 'sft'] will result in this + make command: 'make bftimage sftimage' + name: user-visible name of this step. + **kwargs: Any additional args to pass to BaseStep. + """ + self.factory_config = factory_config + ota_step.OtaStep.__init__(self, build_name=build_name, name=name, **kwargs) + + def _make_fct(self): + """Builds |build_name| FCT packages for the |issue| and |patchset|. + + Returns: + True if the OTA package was built successfully, False otherwise. + """ + factory_image_types = self.factory_config.get('factory_image_types') + if not factory_image_types: + return True + + command = ['make'] + command += ['{}image'.format(t) for t in factory_image_types] + command += ['BUILD_NUMBER={}'.format(self.build_number)] + command += self.make_target_param(True) + + returncode, stdout, stderr = self.exec_subprocess(command) + if returncode != 0: + self._error_processor(stdout, stderr) + return False + + if not self._create_factory_dir(): + return False + + return self._copy_factory_target_files_to_out_artifacts(factory_image_types) + + def _copy_factory_target_files_to_out_artifacts(self, factory_image_types): + """These are used for resigning factory images e.g. prod reflashimage.""" + product = self._build_name.split('-')[0] + for image_type in factory_image_types: + target_files_zip = self.factory_config['source_binary_path'].format( + product=product, image_type=image_type) + target_files_no_ext, zip_ext = os.path.splitext( + os.path.basename(target_files_zip)) + dest_file_path = os.path.join(self._ota_archive_output_dir(), 'factory', + '{}-{}-{}-{}{}'.format(product, image_type, + target_files_no_ext, + self.build_number, + zip_ext)) + returncode, _, _ = self.exec_subprocess( + ['cp', target_files_zip, dest_file_path]) + if returncode != 0: + return False + + return True + + def _create_factory_dir(self): + command = ['mkdir', '-p', + os.path.join(self._ota_archive_output_dir(), 'factory')] + returncode, _, _ = self.exec_subprocess(command) + return returncode == 0 + + def run(self): + return self._make_fct()
diff --git a/cq/scripts/slave/step/ota_oss_step.py b/cq/scripts/slave/step/ota_oss_step.py new file mode 100644 index 0000000..f61e799 --- /dev/null +++ b/cq/scripts/slave/step/ota_oss_step.py
@@ -0,0 +1,89 @@ +"""OSS step class for building OTA's.""" + +from __future__ import absolute_import +import os +from slave.step import ota_step +import xml.etree.ElementTree as et + +from helpers import repo_utils + +MANIFEST_OSS_XML = 'manifest_oss.xml' + + +class OtaOssStep(ota_step.OtaStep): + """OSS creation step class for building OTA's.""" + + def __init__(self, + build_name, + name='populate oss manifest and tarball open source files', + **kwargs): + """Creates a OtaOssStep instance. + + Args: + build_name: Name of build (e.g. anchovy-eng, tvdefault-eng) + name: user-visible name of this step. + **kwargs: Any additional args to pass to BaseStep. + """ + ota_step.OtaStep.__init__(self, build_name=build_name, name=name, **kwargs) + + def _make_oss(self): + """Builds |build_name| OTA package for the |issue| and |patchset|. + + Returns: + True if the OTA package was built successfully, False otherwise. + """ + command = ['make', + 'release_oss', + 'OSS_ROOT=./{}'.format(self._dist_dir()),] + command += self.make_target_param(True) + + returncode, stdout, stderr = self.exec_subprocess(command) + if returncode != 0: + self._error_processor(stdout, stderr) + + return returncode == 0 + + def _compile_oss_manifest_and_save(self): + """Generates a manifest of oss projects for |product|.""" + product = self._build_name.split('-')[0] + oss_projects_file = os.path.join('vendor/eureka/tools/open_source/', + product + '_oss_project.txt') + repo_manifest_content = repo_utils.get_manifest(self._executor) + + if repo_manifest_content and os.path.isfile(oss_projects_file): + root = et.fromstring(repo_manifest_content) + with open(oss_projects_file, 'r') as f: + oss_project_list = f.read().splitlines() + for project in root.findall('project'): + if project.attrib['name'] not in oss_project_list: + root.remove(project) + oss_manifest_content = et.tostring(root, encoding='unicode') + with open(MANIFEST_OSS_XML, 'w') as f: + f.write(oss_manifest_content) + output_dir = self.get_gcs_dir() + self.exec_subprocess(['cp', MANIFEST_OSS_XML, output_dir]) + + def _clear_oss_artifacts(self): + """Removes all OTA artifacts leftover by previous builds.""" + ota_files = self.glob_files('out/dist/*/chromecast_oss.tgz') + if ota_files: + self.exec_subprocess(['rm', '-f'] + ota_files) + + def _archive_artifacts(self): + """Copies the artifacts for archival.""" + output_dir = self.get_gcs_dir() + + if self.build_system == 'catabuilder': + dist_files = self.glob_files( + '{}/chromecast_oss.tgz'.format(self._dist_dir())) + for f in dist_files: + self.exec_subprocess(['cp', '-r', f, output_dir]) + + def run(self): + self._clear_oss_artifacts() + self._compile_oss_manifest_and_save() + if not self._make_oss(): + return False + self._archive_artifacts() + + return True
diff --git a/cq/scripts/slave/step/ota_resign_step.py b/cq/scripts/slave/step/ota_resign_step.py new file mode 100644 index 0000000..16e0983 --- /dev/null +++ b/cq/scripts/slave/step/ota_resign_step.py
@@ -0,0 +1,1199 @@ +"""Resign step class for building OTA's.""" + +from __future__ import absolute_import +from helpers import branch_utils +from slave import base_step +from slave.step import ota_step + +SOURCE_BINARY_PATH = ('out/target/product/{product}/obj/PACKAGING/' + 'target_files_intermediates/' + '{product}-target_files-{buildset}.zip') + +SOURCE_FACTORY_PATH = ('out/target/product/{product}/factory/' + '{image_type}/hostboot-target-files.zip') + +SOURCE_USBSTICK_PATH = ('out/target/product/{product}/factory/' + '{image_type}/usbstick-target-files.zip') + +DESTINATION_USBSTICK_IMAGE_PATH = ('{output_dir}/factory/{product}-' + '{image_type}-{variant}-{buildset}.img') + +SOURCE_FACTORY_TOOL_PATH = ('out/target/product/{product}/' + 'factory-{tool_type}-{product}-{version}.{ext}') + +RUNIN2_PROFILE_PATH = ('out/target/product/{product}/' + 'factory/profile/') + +FCT_ZIP_PATH = ('out/target/product/{product}/factory/' + '{product}-fct-{buildset}.zip') + +AMLOGIC_RESIGN_COMMAND = [ + './vendor/amlogic/build/tools/releasetools/ota_from_target_files', + '-v', +] + +BREZZA_RESIGN_COMMAND = [ + './vendor/qualcomm/brezza/build/tools/releasetools/ota_from_target_files', + '-v', +] + +ELAINE_RESIGN_COMMAND = [ + './vendor/amlogic/elaine/build/tools/releasetools/ota_from_target_files', + '-v', +] + + +ESTELLE_RESIGN_COMMAND = [ + './vendor/amlogic/estelle/build/tools/releasetools/ota_from_target_files', + '-v', +] + +KORLAN_RESIGN_COMMAND = [ + './vendor/amlogic/korlan/build/tools/releasetools/ota_from_target_files', + '-v', +] + +LUMIA_RESIGN_COMMAND = [ + './vendor/amlogic/lumia/build/tools/releasetools/ota_from_target_files', + '-v', +] + +GQ_RESIGN_COMMAND = [ + './vendor/amlogic/gq/build/tools/releasetools/ota_from_target_files', + '-v', +] + +NEWMAN_RESIGN_COMMAND = [ + './vendor/amlogic/newman/build/tools/releasetools/ota_from_target_files', + '-v', +] + +NQ_RESIGN_COMMAND = [ + './vendor/amlogic/nq/build/tools/releasetools/ota_from_target_files', + '-v', +] + +SIROCCO_RESIGN_COMMAND = [ + './vendor/qualcomm/sirocco/build/tools/releasetools/ota_from_target_files', + '-v', +] + +SPENCER_RESIGN_COMMAND = [ + './vendor/amlogic/spencer/build/tools/releasetools/ota_from_target_files', + '-v', +] + +A049_RESIGN_COMMAND = [ + './vendor/amlogic/a049/build/tools/releasetools/ota_from_target_files', + '-v', +] + +SPRINKLES_RESIGN_COMMAND = [ + './vendor/amlogic/korlan/build/tools/releasetools/ota_from_target_files', + '-v', +] + +TQ_RESIGN_COMMAND = [ + './vendor/amlogic/tq/build/tools/releasetools/ota_from_target_files', + '-v', +] + +MARVELL_RESIGN_COMMAND = [ + './vendor/marvell/build/tools/releasetools/ota_from_target_files', + '-v', +] + +VALENS_UNAND_COMMAND = [ + './vendor/marvell/valens/build/tools/mk-fct-unand.sh' +] + +VENTO_UNAND_COMMAND = [ + './vendor/marvell/vento/build/tools/mk-fct-unand.sh' +] + +VENUS_RESIGN_COMMAND = [ + './vendor/amlogic/venus/build/tools/releasetools/ota_from_target_files', + '-v', +] + +ASSISTANTDEFAULT_RESIGN = { + 'command': ['cp'], + 'source_binary_path': '{dist_dir}/{product}-ota-{buildset}.zip', + 'include_params': False, + 'variants': [{'board': 'assistantdefault-b1'}], +} + +BIGGIE_RESIGN = { + 'command': AMLOGIC_RESIGN_COMMAND, + 'variants': [ + {'board': 'biggie-b1'}, + {'board': 'biggie-b1', 'omaha_channel': 'beta-channel'}, + {'board': 'biggie-b3'}, + {'board': 'biggie-b3', 'omaha_channel': 'beta-channel'}, + ], +} + +BIGGIE_FACTORY = { + 'command': AMLOGIC_RESIGN_COMMAND, + 'factory_image_types': ['fct'], + 'source_binary_path': SOURCE_FACTORY_PATH, + 'variants': [ + {'board': 'biggie-b1', 'usb_host_package': None}, + {'board': 'biggie-b3', 'usb_host_package': None}, + {'board': 'biggie-b4', 'usb_host_package': None}, + ], +} + +BOWIE_RESIGN = { + 'command': MARVELL_RESIGN_COMMAND, + 'variants': [ + {'board': 'bowie-p0'}, + {'board': 'bowie-p0', 'omaha_channel': 'beta-channel'}, + ], +} + +BOWIE_FACTORY = { + 'command': MARVELL_RESIGN_COMMAND, + 'factory_image_types': ['fct'], + 'source_binary_path': SOURCE_FACTORY_PATH, + 'variants': [ + {'board': 'bowie-p0', 'usb_host_package': None}, + ], +} + +BOWIE_USBSTICK = { + 'command': MARVELL_RESIGN_COMMAND, + 'factory_image_types': ['reflash', 'fctsecure', 'partdump'], + 'source_binary_path': SOURCE_USBSTICK_PATH, + 'destination_path_template': DESTINATION_USBSTICK_IMAGE_PATH, + 'variants': [ + {'board': 'bowie-p0', 'usb_stick_image': None}, + ], +} + +BREZZA_RESIGN = { + 'command': BREZZA_RESIGN_COMMAND, + 'variants': [ + {'board': 'brezza-p0'}, + {'board': 'brezza-p0', 'omaha_channel': 'beta-channel'}, + {'board': 'brezza-p1'}, + {'board': 'brezza-p1', 'omaha_channel': 'beta-channel'}, + {'board': 'brezza-p2'}, + {'board': 'brezza-p2', 'omaha_channel': 'beta-channel'}, + {'board': 'brezza-b1'}, + {'board': 'brezza-b1', 'omaha_channel': 'beta-channel'}, + ], +} + +BREZZA_FACTORY = { + 'command': BREZZA_RESIGN_COMMAND, + 'factory_image_types': ['fct'], + 'source_binary_path': SOURCE_FACTORY_PATH, + 'variants': [ + {'board': 'brezza-p1', 'usb_host_package': None}, + {'board': 'brezza-p2', 'usb_host_package': None}, + ], +} + +BREZZA_FACTORY_TOOL = { + 'command':['make'], + 'factory_tool_types': ['runin2_package', 'provision_package'], + 'source_tool_path': SOURCE_FACTORY_TOOL_PATH, + 'runin_profile_path': RUNIN2_PROFILE_PATH +} + +BREZZA_USBSTICK = { + 'command': BREZZA_RESIGN_COMMAND, + 'factory_image_types': ['reflash'], + 'source_binary_path': SOURCE_USBSTICK_PATH, + 'destination_path_template': DESTINATION_USBSTICK_IMAGE_PATH, + 'variants': [ + {'board': 'brezza-p2', 'usb_stick_image': None}, + ], +} + +CAPRICA_RESIGN = { + 'command': MARVELL_RESIGN_COMMAND, + 'min_branches': { + 'caprica-b1': '1.31', + 'caprica-b2': '1.31', + 'caprica-b3': '1.31', + }, + 'variants': [ + {'board': 'caprica-b1', 'tz': 'on'}, + {'board': 'caprica-b1', 'tz': 'on', 'omaha_channel': 'beta-channel'}, + {'board': 'caprica-b2', 'tz': 'on'}, + {'board': 'caprica-b2', 'tz': 'on', 'omaha_channel': 'beta-channel'}, + {'board': 'caprica-b3', 'tz': 'on'}, + {'board': 'caprica-b3', 'tz': 'on', 'omaha_channel': 'beta-channel'}, + {'board': 'caprica-b3', 'tz': 'on', 'omaha_channel': 'stable-channel'}, + ], +} + +CAPRICA_FACTORY = { + 'command': MARVELL_RESIGN_COMMAND, + 'factory_image_types': ['fct'], + 'source_binary_path': SOURCE_FACTORY_PATH, + 'variants': [ + # BG2 usbboot prebuilts do not have TZ support. + {'board': 'caprica-b1', 'usb_host_package': None, 'tz': 'off'}, + {'board': 'caprica-b2', 'usb_host_package': None, 'tz': 'off'}, + {'board': 'caprica-b3', 'usb_host_package': None, 'tz': 'off'}, + {'board': 'caprica-b4', 'usb_host_package': None, 'tz': 'off'}, + ], +} + +CAPRICA_USBSTICK = { + 'command': MARVELL_RESIGN_COMMAND, + 'factory_image_types': ['reflash', 'fctsecure', 'partdump'], + 'source_binary_path': SOURCE_USBSTICK_PATH, + 'destination_path_template': DESTINATION_USBSTICK_IMAGE_PATH, + 'variants': [ + {'board': 'caprica-b1', 'usb_stick_image': None}, + {'board': 'caprica-b3', 'usb_stick_image': None}, + ], +} + +CHORIZO_RESIGN = { + 'command': MARVELL_RESIGN_COMMAND, + 'min_branches': { + 'earth-b1': '1.12', + 'earth-b2': '1.13', + 'earth-b3': '1.15', + }, + 'variants': [ + {'board': 'earth-b1', 'tz': 'on'}, + {'board': 'earth-b2', 'tz': 'on'}, + {'board': 'earth-b2', 'tz': 'on', 'omaha_channel': 'beta-channel'}, + {'board': 'earth-b2', 'tz': 'on', 'omaha_channel': 'stable-channel'}, + {'board': 'earth-b3', 'tz': 'on'}, + {'board': 'earth-b3', 'tz': 'on', 'omaha_channel': 'beta-channel'}, + {'board': 'earth-b3', 'tz': 'on', 'omaha_channel': 'stable-channel'}, + ], +} + +ELAINE_FUCHSIA_RESIGN = { + 'command': ELAINE_RESIGN_COMMAND, + 'variants': [ + {'board': 'elaine-b3'}, + {'board': 'elaine-b3', 'omaha_channel': 'beta-channel'}, + ], +} + +ELAINE_RESIGN = { + 'command': ELAINE_RESIGN_COMMAND, + 'variants': [ + {'board': 'elaine-p2', 'always_resign': True}, + {'board': 'elaine-p2', 'omaha_channel': 'beta-channel'}, + {'board': 'elaine-b1'}, + {'board': 'elaine-b1', 'omaha_channel': 'beta-channel'}, + {'board': 'elaine-b3'}, + {'board': 'elaine-b3', 'omaha_channel': 'beta-channel'}, + {'board': 'elaine-b3', 'omaha_channel': 'stable-channel'}, + ], +} + +ELAINE_FACTORY = { + 'command': ELAINE_RESIGN_COMMAND, + 'factory_image_types': ['fct'], + 'source_binary_path': SOURCE_FACTORY_PATH, + 'variants': [ + {'board': 'elaine-p2', 'usb_host_package': None}, + {'board': 'elaine-b1', 'usb_host_package': None}, + {'board': 'elaine-b3', 'usb_host_package': None}, + {'board': 'elaine-b4', 'usb_host_package': None}, + ], +} + +ELAINE_USBSTICK = { + 'command': ELAINE_RESIGN_COMMAND, + 'factory_image_types': ['reflash', 'fctsecure', 'partdump'], + 'source_binary_path': SOURCE_USBSTICK_PATH, + 'destination_path_template': DESTINATION_USBSTICK_IMAGE_PATH, + 'variants': [ + {'board': 'elaine-b1', 'usb_stick_image': None}, + {'board': 'elaine-b3', 'usb_stick_image': None}, + ], +} + +ESTELLE_FUCHSIA_RESIGN = { + 'command': ESTELLE_RESIGN_COMMAND, + 'variants': [ + {'board': 'estelle-b3'}, + {'board': 'estelle-b3', 'omaha_channel': 'beta-channel'}, + ], +} + +ESTELLE_RESIGN = { + 'command': ESTELLE_RESIGN_COMMAND, + 'variants': [ + {'board': 'estelle-p2'}, + {'board': 'estelle-p2', 'omaha_channel': 'beta-channel'}, + {'board': 'estelle-b1'}, + {'board': 'estelle-b1', 'omaha_channel': 'beta-channel'}, + {'board': 'estelle-b3'}, + {'board': 'estelle-b3', 'omaha_channel': 'beta-channel'}, + ], +} + +ESTELLE_FACTORY = { + 'command': ESTELLE_RESIGN_COMMAND, + 'factory_image_types': ['fct'], + 'source_binary_path': SOURCE_FACTORY_PATH, + 'variants': [ + {'board': 'estelle-b1', 'usb_host_package': None}, + {'board': 'estelle-b3', 'usb_host_package': None}, + {'board': 'estelle-b4', 'usb_host_package': None}, + ], +} + +ESTELLE_USBSTICK = { + 'command': ESTELLE_RESIGN_COMMAND, + 'factory_image_types': ['reflash', 'partdump'], + 'source_binary_path': SOURCE_USBSTICK_PATH, + 'destination_path_template': DESTINATION_USBSTICK_IMAGE_PATH, + 'variants': [ + {'board': 'estelle-b3', 'usb_stick_image': None}, + ], +} + +EUREKA_RESIGN = { + 'command': MARVELL_RESIGN_COMMAND, + 'variants': [ + {'board': 'eureka-b1', 'tz': 'on'}, + ], +} + +KORLAN_RESIGN = { + 'command': KORLAN_RESIGN_COMMAND, + 'variants': [ + {'board': 'korlan-p2'}, + {'board': 'korlan-p2', 'omaha_channel': 'beta-channel'}, + {'board': 'korlan-b1'}, + {'board': 'korlan-b1', 'omaha_channel': 'beta-channel'}, + {'board': 'korlan-b3'}, + {'board': 'korlan-b3', 'omaha_channel': 'beta-channel'}, + ], +} + +KORLAN_FACTORY = { + 'command': KORLAN_RESIGN_COMMAND, + 'factory_image_types': ['fct'], + 'source_binary_path': SOURCE_FACTORY_PATH, + 'variants': [ + {'board': 'korlan-p2', 'usb_host_package': None}, + {'board': 'korlan-b1', 'usb_host_package': None}, + {'board': 'korlan-b3', 'usb_host_package': None}, + ], +} + +KORLAN_FACTORY_TOOL = { + 'command':['make'], + 'factory_tool_types': ['runin2_package', 'provision_package'], + 'source_tool_path': SOURCE_FACTORY_TOOL_PATH, + 'runin_profile_path': RUNIN2_PROFILE_PATH +} + +KORLAN_USBSTICK = { + 'command': KORLAN_RESIGN_COMMAND, + 'factory_image_types': ['reflash', 'fctsecure'], + 'source_binary_path': SOURCE_USBSTICK_PATH, + 'destination_path_template': DESTINATION_USBSTICK_IMAGE_PATH, + 'variants': [ + {'board': 'korlan-p2', 'usb_stick_image': None}, + {'board': 'korlan-b1', 'usb_stick_image': None}, + {'board': 'korlan-b3', 'usb_stick_image': None}, + ], +} + +LUMIA_RESIGN = { + 'command': LUMIA_RESIGN_COMMAND, + 'variants': [ + {'board': 'lumia-p0'}, + {'board': 'lumia-p0', 'omaha_channel': 'beta-channel'}, + ], +} + +GQ_RESIGN = { + 'command': GQ_RESIGN_COMMAND, + 'variants': [ + {'board': 'gq-b1', + 'disabled_branches': ['1.48_shortlived_198292']}, + {'board': 'gq-b1', 'omaha_channel': 'beta-channel', + 'disabled_branches': ['1.48_shortlived_198292']}, + {'board': 'gq-b3', + 'disabled_branches': ['1.48_shortlived_198292']}, + {'board': 'gq-b3', 'omaha_channel': 'beta-channel', + 'disabled_branches': ['1.48_shortlived_198292']}, + ], +} + +GQ_FACTORY = { + 'command': GQ_RESIGN_COMMAND, + 'factory_image_types': ['fct'], + 'source_binary_path': SOURCE_FACTORY_PATH, + 'variants': [ + {'board': 'gq-b1', 'usb_host_package': None, + 'disabled_branches': ['1.48_shortlived_198292']}, + {'board': 'gq-b3', 'usb_host_package': None, + 'disabled_branches': ['1.48_shortlived_198292']}, + {'board': 'gq-b4', 'usb_host_package': None, + 'disabled_branches': ['1.48_shortlived_198292']}, + ], +} + +GQ_USBSTICK = { + 'command': GQ_RESIGN_COMMAND, + 'factory_image_types': ['reflash', 'partdump', 'fctsecure'], + 'source_binary_path': SOURCE_USBSTICK_PATH, + 'destination_path_template': DESTINATION_USBSTICK_IMAGE_PATH, + 'variants': [ + {'board': 'gq-b1', 'usb_stick_image': None}, + {'board': 'gq-b3', 'usb_stick_image': None}, + ], +} + +MUSHROOM_RESIGN = { + 'command': MARVELL_RESIGN_COMMAND, + 'min_branches': { + 'joplin-b1': '1.23', + 'joplin-b3': '1.26', + }, + 'variants': [ + {'board': 'joplin-b1', 'tz': 'on'}, + {'board': 'joplin-b1', 'tz': 'on', 'omaha_channel': 'beta-channel'}, + {'board': 'joplin-b1', 'tz': 'on', 'omaha_channel': 'stable-channel'}, + {'board': 'joplin-b3', 'tz': 'on'}, + {'board': 'joplin-b3', 'tz': 'on', 'omaha_channel': 'beta-channel'}, + {'board': 'joplin-b3', 'tz': 'on', 'omaha_channel': 'stable-channel'}, + ], +} + +MUSHROOM_FACTORY = { + 'command': MARVELL_RESIGN_COMMAND, + 'factory_image_types': ['fct'], + 'source_binary_path': SOURCE_FACTORY_PATH, + 'variants': [ + # BG2 usbboot prebuilts do not have TZ support. + {'board': 'joplin-b1', 'usb_host_package': None, 'tz': 'off'}, + {'board': 'joplin-b3', 'usb_host_package': None, 'tz': 'off'}, + {'board': 'joplin-b4', 'usb_host_package': None, 'tz': 'off'}, + ], +} + +MUSHROOM_USBSTICK = { + 'command': MARVELL_RESIGN_COMMAND, + 'factory_image_types': ['reflash'], + 'source_binary_path': SOURCE_USBSTICK_PATH, + 'destination_path_template': DESTINATION_USBSTICK_IMAGE_PATH, + 'variants': [ + {'board': 'joplin-b3', 'usb_stick_image': None} + ], +} + +NEWMAN_FUCHSIA_RESIGN = { + 'command': NEWMAN_RESIGN_COMMAND, + 'variants': [ + {'board': 'newman-b3'}, + {'board': 'newman-b3', 'omaha_channel': 'beta-channel'}, + ], +} + +NEWMAN_RESIGN = { + 'command': NEWMAN_RESIGN_COMMAND, + 'variants': [ + {'board': 'newman-b1'}, + {'board': 'newman-b1', 'omaha_channel': 'beta-channel'}, + {'board': 'newman-b3'}, + {'board': 'newman-b3', 'omaha_channel': 'beta-channel'}, + ], +} + +NEWMAN_RESIGN_ENG = { + 'command': NEWMAN_RESIGN_COMMAND, + 'variants': [ + {'board': 'newman-b1'}, + {'board': 'newman-b3'}, + ], +} + +NEWMAN_FACTORY = { + 'command': NEWMAN_RESIGN_COMMAND, + 'factory_image_types': ['fct'], + 'source_binary_path': SOURCE_FACTORY_PATH, + 'variants': [ + {'board': 'newman-b1', 'usb_host_package': None}, + {'board': 'newman-b3', 'usb_host_package': None}, + {'board': 'newman-b4', 'usb_host_package': None}, + ], +} + +NEWMAN_USBSTICK = { + 'command': NEWMAN_RESIGN_COMMAND, + 'factory_image_types': ['reflash', 'fctsecure', 'partdump'], + 'source_binary_path': SOURCE_USBSTICK_PATH, + 'destination_path_template': DESTINATION_USBSTICK_IMAGE_PATH, + 'variants': [ + {'board': 'newman-b1', 'usb_stick_image': None}, + {'board': 'newman-b3', 'usb_stick_image': None}, + ], +} + +NQ_RESIGN = { + 'command': NQ_RESIGN_COMMAND, + 'variants': [ + {'board': 'nq-b1', + 'disabled_branches': ['1.48_shortlived_198292']}, + {'board': 'nq-b1', 'omaha_channel': 'beta-channel', + 'disabled_branches': ['1.48_shortlived_198292']}, + {'board': 'nq-b3', + 'disabled_branches': ['1.48_shortlived_198292']}, + {'board': 'nq-b3', 'omaha_channel': 'beta-channel', + 'disabled_branches': ['1.48_shortlived_198292']}, + ], +} + +NQ_FACTORY = { + 'command': NQ_RESIGN_COMMAND, + 'factory_image_types': ['fct'], + 'source_binary_path': SOURCE_FACTORY_PATH, + 'variants': [ + {'board': 'nq-b1', 'usb_host_package': None, + 'disabled_branches': ['1.48_shortlived_198292']}, + {'board': 'nq-b3', 'usb_host_package': None, + 'disabled_branches': ['1.48_shortlived_198292']}, + {'board': 'nq-b4', 'usb_host_package': None, + 'disabled_branches': ['1.48_shortlived_198292']}, + ], +} + +NQ_USBSTICK = { + 'command': NQ_RESIGN_COMMAND, + 'factory_image_types': ['reflash', 'partdump', 'fctsecure'], + 'source_binary_path': SOURCE_USBSTICK_PATH, + 'destination_path_template': DESTINATION_USBSTICK_IMAGE_PATH, + 'variants': [ + {'board': 'nq-b1', 'usb_stick_image': None}, + {'board': 'nq-b3', 'usb_stick_image': None}, + ], +} + +PEPPERONI_RESIGN = { + 'command': MARVELL_RESIGN_COMMAND, + 'min_branches': { + 'hendrix-b1': '1.14', + 'hendrix-b3': '1.15', + }, + 'variants': [ + {'board': 'hendrix-b1', 'tz': 'on'}, + {'board': 'hendrix-b1', 'tz': 'on', 'omaha_channel': 'beta-channel'}, + {'board': 'hendrix-b1', 'tz': 'on', 'omaha_channel': 'stable-channel'}, + {'board': 'hendrix-b3', 'tz': 'on'}, + {'board': 'hendrix-b3', 'tz': 'on', 'omaha_channel': 'beta-channel'}, + {'board': 'hendrix-b3', 'tz': 'on', 'omaha_channel': 'stable-channel'}, + ], +} + +PINEAPPLE_RESIGN = { + 'command': MARVELL_RESIGN_COMMAND, + 'min_branches': { + 'chirp-b1': '1.20', + 'chirp-b3': '1.21', + }, + 'variants': [ + {'board': 'chirp-b1', 'tz': 'on'}, + {'board': 'chirp-b1', 'tz': 'on', 'omaha_channel': 'beta-channel'}, + {'board': 'chirp-b1', 'tz': 'on', 'omaha_channel': 'stable-channel'}, + {'board': 'chirp-b3', 'tz': 'on'}, + {'board': 'chirp-b3', 'tz': 'on', 'omaha_channel': 'beta-channel'}, + {'board': 'chirp-b3', 'tz': 'on', 'omaha_channel': 'stable-channel'}, + ], +} + +PINEAPPLE_FACTORY = { + 'command': MARVELL_RESIGN_COMMAND, + 'factory_image_types': ['fct'], + 'source_binary_path': SOURCE_FACTORY_PATH, + 'variants': [ + # BG2 usbboot prebuilts do not have TZ support. + {'board': 'chirp-b1', 'usb_host_package': None, 'tz': 'off'}, + {'board': 'chirp-b3', 'usb_host_package': None, 'tz': 'off'}, + {'board': 'chirp-b4', 'usb_host_package': None, 'tz': 'off'}, + ], +} + +PINEAPPLE_USBSTICK = { + 'command': MARVELL_RESIGN_COMMAND, + 'factory_image_types': ['reflash'], + 'source_binary_path': SOURCE_USBSTICK_PATH, + 'destination_path_template': DESTINATION_USBSTICK_IMAGE_PATH, + 'variants': [ + {'board': 'chirp-b3', 'usb_stick_image': None} + ], +} + +PRINCE_RESIGN = { + 'command': MARVELL_RESIGN_COMMAND, + 'variants': [ + {'board': 'prince-p2', 'tz': 'on'}, + {'board': 'prince-p2', 'tz': 'on', 'omaha_channel': 'beta-channel'}, + {'board': 'prince-b1', 'tz': 'on', 'always_resign': True}, + {'board': 'prince-b1', 'tz': 'on', 'omaha_channel': 'beta-channel'}, + {'board': 'prince-b3', 'tz': 'on'}, + {'board': 'prince-b3', 'tz': 'on', 'omaha_channel': 'beta-channel'} + ], +} + +PRINCE_FACTORY = { + 'command': MARVELL_RESIGN_COMMAND, + 'factory_image_types': ['fct'], + 'source_binary_path': SOURCE_FACTORY_PATH, + 'variants': [ + {'board': 'prince-p2', 'usb_host_package': None}, + {'board': 'prince-b1', 'usb_host_package': None}, + {'board': 'prince-b3', 'usb_host_package': None}, + {'board': 'prince-b4', 'usb_host_package': None} + ], +} + +PRINCE_USBSTICK = { + 'command': MARVELL_RESIGN_COMMAND, + 'factory_image_types': ['reflash', 'fctsecure', 'partdump'], + 'source_binary_path': SOURCE_USBSTICK_PATH, + 'destination_path_template': DESTINATION_USBSTICK_IMAGE_PATH, + 'variants': [ + {'board': 'prince-p2', 'usb_stick_image': None}, + {'board': 'prince-b1', 'usb_stick_image': None}, + {'board': 'prince-b3', 'usb_stick_image': None} + ], +} + +# Make factory tools eg. provision package +PRINCE_FACTORY_TOOL = { + 'command':['make'], + 'factory_tool_types': ['provision_package'], + 'source_tool_path': SOURCE_FACTORY_TOOL_PATH +} + +# Use separate factory_tool config as spencer may build runin packages in CB +SPENCER_FACTORY_TOOL = { + 'command':['make'], + 'factory_tool_types': ['provision_package', 'runin2_package'], + 'source_tool_path': SOURCE_FACTORY_TOOL_PATH, + 'runin_profile_path': RUNIN2_PROFILE_PATH +} + +VENUS_FACTORY_TOOL = { + 'command':['make'], + 'factory_tool_types': ['provision_package', 'runin2_package'], + 'source_tool_path': SOURCE_FACTORY_TOOL_PATH, + 'runin_profile_path': RUNIN2_PROFILE_PATH +} + +A049_FACTORY_TOOL = { + 'command':['make'], + 'factory_tool_types': ['provision_package', 'runin2_package'], + 'source_tool_path': SOURCE_FACTORY_TOOL_PATH, + 'runin_profile_path': RUNIN2_PROFILE_PATH +} + +SALAMI_RESIGN = { + 'command': MARVELL_RESIGN_COMMAND, + 'variants': [ + {'board': 'lexx-b3', 'tz': 'on'}, + ], +} + +SIROCCO_RESIGN = { + 'command': SIROCCO_RESIGN_COMMAND, + 'variants': [ + {'board': 'sirocco-p1'}, + {'board': 'sirocco-p1', 'omaha_channel': 'beta-channel'}, + {'board': 'sirocco-b1'}, + {'board': 'sirocco-b1', 'omaha_channel': 'beta-channel'}, + {'board': 'sirocco-b3'}, + {'board': 'sirocco-b3', 'omaha_channel': 'beta-channel'}, + {'board': 'sirocco-b3', 'omaha_channel': 'stable-channel'}, + ], +} + +SIROCCO_FACTORY = { + 'command': SIROCCO_RESIGN_COMMAND, + 'factory_image_types': ['fct'], + 'source_binary_path': SOURCE_FACTORY_PATH, + 'variants': [ + {'board': 'sirocco-p1', 'usb_host_package': None}, + {'board': 'sirocco-b1', 'usb_host_package': None}, + {'board': 'sirocco-b3', 'usb_host_package': None}, + ], +} + +SIROCCO_FACTORY_TOOL = { + 'command':['make'], + 'factory_tool_types': ['runin2_package', 'provision_package'], + 'source_tool_path': SOURCE_FACTORY_TOOL_PATH, + 'runin_profile_path': RUNIN2_PROFILE_PATH +} + +SIROCCO_USBSTICK = { + 'command': SIROCCO_RESIGN_COMMAND, + 'factory_image_types': ['reflash', 'partdump', 'fctsecure'], + 'source_binary_path': SOURCE_USBSTICK_PATH, + 'destination_path_template': DESTINATION_USBSTICK_IMAGE_PATH, + 'variants': [ + {'board': 'sirocco-b1', 'usb_stick_image': None}, + {'board': 'sirocco-b3', 'usb_stick_image': None}, + ], +} + +SPENCER_RESIGN = { + 'command': SPENCER_RESIGN_COMMAND, + 'variants': [ + {'board': 'spencer-p1'}, + {'board': 'spencer-p1u'}, + {'board': 'spencer-p2'}, + {'board': 'spencer-p2', 'omaha_channel': 'beta-channel'}, + {'board': 'spencer-b1'}, + {'board': 'spencer-b1', 'omaha_channel': 'beta-channel'}, + {'board': 'spencer-b3'}, + {'board': 'spencer-b3', 'omaha_channel': 'beta-channel'}, + ], +} + +SPENCER_FACTORY = { + 'command': SPENCER_RESIGN_COMMAND, + 'factory_image_types': ['fct'], + 'source_binary_path': SOURCE_FACTORY_PATH, + 'variants': [ + {'board': 'spencer-p1', 'usb_host_package': None}, + {'board': 'spencer-p1u', 'usb_host_package': None}, + {'board': 'spencer-p2', 'usb_host_package': None}, + {'board': 'spencer-b1', 'usb_host_package': None}, + {'board': 'spencer-b3', 'usb_host_package': None}, + ], +} + +SPENCER_USBSTICK = { + 'command': SPENCER_RESIGN_COMMAND, + 'factory_image_types': ['reflash', 'partdump', 'fctsecure'], + 'source_binary_path': SOURCE_USBSTICK_PATH, + 'destination_path_template': DESTINATION_USBSTICK_IMAGE_PATH, + 'variants': [ + {'board': 'spencer-p2', 'usb_stick_image': None}, + {'board': 'spencer-b1', 'usb_stick_image': None}, + {'board': 'spencer-b3', 'usb_stick_image': None}, + ], +} + +SPRINKLES_RESIGN = { + 'command': SPRINKLES_RESIGN_COMMAND, + 'variants': [ + {'board': 'sprinkles-korlan'}, + {'board': 'sprinkles-korlan', 'omaha_channel': 'beta-channel'}, + ], +} + +SPRINKLES_FACTORY = { + 'command': SPRINKLES_RESIGN_COMMAND, + 'factory_image_types': ['fct'], + 'source_binary_path': SOURCE_FACTORY_PATH, + 'variants': [ + {'board': 'sprinkles-korlan', 'usb_host_package': None}, + ], +} + +SPRINKLES_FACTORY_TOOL = { + 'command':['make'], + 'factory_tool_types': ['runin2_package', 'provision_package'], + 'source_tool_path': SOURCE_FACTORY_TOOL_PATH, + 'runin_profile_path': RUNIN2_PROFILE_PATH +} + +SPRINKLES_USBSTICK = { + 'command': SPRINKLES_RESIGN_COMMAND, + 'factory_image_types': ['reflash'], + 'source_binary_path': SOURCE_USBSTICK_PATH, + 'destination_path_template': DESTINATION_USBSTICK_IMAGE_PATH, + 'variants': [ + {'board': 'sprinkles-korlan', 'usb_stick_image': None}, + ], +} + +STEAK_RESIGN = { + 'command': MARVELL_RESIGN_COMMAND, + 'min_branches': { + 'luther-b1': '1.20', + 'luther-b2': '1.21', + }, + 'variants': [ + {'board': 'luther-b2', 'tz': 'on'}, + {'board': 'luther-b2', 'tz': 'on', 'omaha_channel': 'beta-channel'}, + {'board': 'luther-b2', 'tz': 'on', 'omaha_channel': 'stable-channel'}, + ], +} + +STEAK_FACTORY = { + 'command': MARVELL_RESIGN_COMMAND, + 'factory_image_types': ['fct'], + 'source_binary_path': SOURCE_FACTORY_PATH, + 'variants': [ + # bg4cdp USB boot host tool supports TZ + {'board': 'luther-b2', 'usb_host_package': None}, + {'board': 'luther-b4', 'usb_host_package': None}, + ], +} + +STEAK_USBSTICK = { + 'command': MARVELL_RESIGN_COMMAND, + 'factory_image_types': ['reflash', 'fctsecure', 'partdump'], + 'source_binary_path': SOURCE_USBSTICK_PATH, + 'destination_path_template': DESTINATION_USBSTICK_IMAGE_PATH, + 'variants': [ + {'board': 'luther-b2', 'usb_stick_image': None} + ], +} + +TQ_RESIGN = { + 'command': TQ_RESIGN_COMMAND, + 'variants': [ + {'board': 'tq-p1'}, + {'board': 'tq-p2'}, + {'board': 'tq-p2', 'omaha_channel': 'beta-channel'}, + ], +} + +TQ_FACTORY = { + 'command': TQ_RESIGN_COMMAND, + 'factory_image_types': ['fct'], + 'source_binary_path': SOURCE_FACTORY_PATH, + 'variants': [ + {'board': 'tq-p1', 'usb_host_package': None}, + {'board': 'tq-p2', 'usb_host_package': None}, + ], +} + +VALENS_RESIGN = { + 'command': MARVELL_RESIGN_COMMAND, + 'variants': [ + {'board': 'valens-p2', 'tz': 'on'}, + {'board': 'valens-p2', 'tz': 'on', 'omaha_channel': 'beta-channel'}, + {'board': 'valens-b1', 'tz': 'on'}, + {'board': 'valens-b1', 'tz': 'on', 'omaha_channel': 'beta-channel'}, + {'board': 'valens-b3', 'tz': 'on'}, + {'board': 'valens-b3', 'tz': 'on', 'omaha_channel': 'beta-channel'}, + ], +} + +VALENS_FACTORY = { + 'command': MARVELL_RESIGN_COMMAND, + 'factory_image_types': ['fct'], + 'source_binary_path': SOURCE_FACTORY_PATH, + 'variants': [ + {'board': 'valens-p2', 'usb_host_package': None}, + {'board': 'valens-b1', 'usb_host_package': None}, + {'board': 'valens-b3', 'usb_host_package': None}, + {'board': 'valens-b4', 'usb_host_package': None}, + ], +} + +# uNAND step require fct zip created first +VALENS_UNAND = { + 'command': VALENS_UNAND_COMMAND, + 'factory_image_types': ['unand'], + 'source_binary_path': FCT_ZIP_PATH, + 'variants': [ + {'board': 'valens-p2'}, + {'board': 'valens-b1'}, + {'board': 'valens-b3'}, + {'board': 'valens-b4'}, + ], +} + +VALENS_USBSTICK = { + 'command': MARVELL_RESIGN_COMMAND, + 'factory_image_types': ['reflash', 'fctsecure', 'partdump'], + 'source_binary_path': SOURCE_USBSTICK_PATH, + 'destination_path_template': DESTINATION_USBSTICK_IMAGE_PATH, + 'variants': [ + {'board': 'valens-b3', 'usb_stick_image': None} + ], +} + +VENTO_RESIGN = { + 'command': MARVELL_RESIGN_COMMAND, + 'variants': [ + {'board': 'vento-p0', 'tz': 'on'}, + {'board': 'vento-p0', 'tz': 'on', 'omaha_channel': 'beta-channel'}, + {'board': 'vento-b1', 'tz': 'on'}, + {'board': 'vento-b1', 'tz': 'on', 'omaha_channel': 'beta-channel'}, + {'board': 'vento-b3', 'tz': 'on'}, + {'board': 'vento-b3', 'tz': 'on', 'omaha_channel': 'beta-channel'}, + ], +} + +VENTO_FACTORY = { + 'command': MARVELL_RESIGN_COMMAND, + 'factory_image_types': ['fct'], + 'source_binary_path': SOURCE_FACTORY_PATH, + 'variants': [ + {'board': 'vento-p0', 'usb_host_package': None}, + {'board': 'vento-b1', 'usb_host_package': None}, + {'board': 'vento-b3', 'usb_host_package': None}, + {'board': 'vento-b4', 'usb_host_package': None}, + ], +} + +# uNAND step require fct zip created first +VENTO_UNAND = { + 'command': VENTO_UNAND_COMMAND, + 'factory_image_types': ['unand'], + 'source_binary_path': FCT_ZIP_PATH, + 'variants': [ + {'board': 'vento-p0'}, + {'board': 'vento-b1'}, + {'board': 'vento-b3'}, + {'board': 'vento-b4'}, + ], +} + +VENUS_RESIGN = { + 'command': VENUS_RESIGN_COMMAND, + 'variants': [ + {'board': 'venus-p1'}, + {'board': 'venus-p1', 'omaha_channel': 'beta-channel'}, + {'board': 'venus-p2'}, + {'board': 'venus-p2', 'omaha_channel': 'beta-channel'}, + {'board': 'venus-b1', + 'disabled_branches': ['1.57_shortlived_265478_vfctp2']}, + {'board': 'venus-b1', 'omaha_channel': 'beta-channel', + 'disabled_branches': ['1.57_shortlived_265478_vfctp2']}, + {'board': 'venus-b3', + 'disabled_branches': ['1.57_shortlived_265478_vfctp2']}, + {'board': 'venus-b3', 'omaha_channel': 'beta-channel', + 'disabled_branches': ['1.57_shortlived_265478_vfctp2']}, + ], +} + +VENUS_FACTORY = { + 'command': VENUS_RESIGN_COMMAND, + 'factory_image_types': ['fct'], + 'source_binary_path': SOURCE_FACTORY_PATH, + 'variants': [ + {'board': 'venus-p1', 'usb_host_package': None}, + {'board': 'venus-p2', 'usb_host_package': None}, + {'board': 'venus-b1', 'usb_host_package': None, + 'disabled_branches': ['1.57_shortlived_265478_vfctp2']}, + {'board': 'venus-b3', 'usb_host_package': None, + 'disabled_branches': ['1.57_shortlived_265478_vfctp2']}, + ], +} + +VENUS_USBSTICK = { + 'command': VENUS_RESIGN_COMMAND, + 'factory_image_types': ['reflash', 'partdump', 'fctsecure'], + 'source_binary_path': SOURCE_USBSTICK_PATH, + 'destination_path_template': DESTINATION_USBSTICK_IMAGE_PATH, + 'variants': [ + {'board': 'venus-p2', 'usb_stick_image': None}, + {'board': 'venus-b1', 'usb_stick_image': None, + 'disabled_branches': ['1.57_shortlived_265478_vfctp2']}, + {'board': 'venus-b3', 'usb_stick_image': None, + 'disabled_branches': ['1.57_shortlived_265478_vfctp2']}, + ], +} + +A049_RESIGN = { + 'command': A049_RESIGN_COMMAND, + 'variants': [ + {'board': 'a049-p0'}, + ], +} + +A049_FACTORY = { + 'command': A049_RESIGN_COMMAND, + 'factory_image_types': ['fct'], + 'source_binary_path': SOURCE_FACTORY_PATH, + 'variants': [ + {'board': 'a049-p0', 'usb_host_package': None}, + ], +} + +A049_USBSTICK = { + 'command': A049_RESIGN_COMMAND, + 'factory_image_types': ['reflash', 'partdump', 'fctsecure'], + 'source_binary_path': SOURCE_USBSTICK_PATH, + 'destination_path_template': DESTINATION_USBSTICK_IMAGE_PATH, + 'variants': [ + {'board': 'a049-p0', 'usb_stick_image': None}, + ], +} + +def get_resign_steps(build_name, resign_config, build_branch, + apply_dev_signing, **step_kwargs): + """Returns list of resign steps if any. + + Args: + build_name: Name of build (e.g. anchovy-eng, tvdefault-eng). + resign_config: dictionary with resign params. + build_branch: manifest branch for current buildset. + apply_dev_signing: Ingnore per-board dev_signing param if True. + **step_kwargs: kwargs for step constructor. + Returns: + List of OtaResignStep objects if any + """ + if not resign_config or 'command' not in resign_config: + return [] + + steps = [] + + min_branches = resign_config.get('min_branches', {}) + for variant in resign_config.get('variants', []): + if build_branch in variant.get('disabled_branches', []): + continue + params = variant.copy() + if 'disabled_branches' in params: + params.pop('disabled_branches') + product = params.get('board', '') + resign_variant = apply_dev_signing or params.get('always_resign', False) + if 'always_resign' in params: + params.pop('always_resign') + if not resign_variant: + continue + if branch_utils.is_branch_equal_to_or_later_than( + build_branch, min_branches.get(product, None)): + for factory_image_type in resign_config.get( + 'factory_image_types', [None]): + if factory_image_type == 'unand': + steps.append(OtaUnandStep( + build_name, command=resign_config['command'], + params=params, + source_binary_path=resign_config.get( + 'source_binary_path', FCT_ZIP_PATH), + **step_kwargs + )) + else: + steps.append(OtaResignStep( + build_name, command=resign_config['command'], + params=params, factory_image_type=factory_image_type, + source_binary_path=resign_config.get( + 'source_binary_path', SOURCE_BINARY_PATH), + destination_path_template=resign_config.get( + 'destination_path_template', None), + include_params=resign_config.get('include_params', True), + **step_kwargs + )) + + return steps + + +class OtaResignStep(ota_step.OtaStep): + """Resign step class for building OTA's.""" + + def __init__(self, build_name, + command, params, source_binary_path, include_params, + destination_path_template=None, name=None, + factory_image_type=None, **kwargs): + """Creates a OtaResignStep instance. + + Args: + build_name: Name of build (e.g. anchovy-eng, tvdefault-eng) + command: resign command, list + params: resign params, dictionary + source_binary_path: path to source binary, string + include_params: if True, params will be converted command flags/values + destination_path_template: string. If None, a default template is used. + name: user-visible name of this step. + factory_image_type: Type of factory image, None otherwise + **kwargs: Any additional args to pass to BaseStep. + """ + if not name: + name = 'resign ' + if factory_image_type: + name += factory_image_type + ' ' + name += params['board'] + + tz = '' + if params.get('tz') == 'off': + tz = '-no-tz' + name += ' no trustzone' + elif params.get('tz') == 'on': + name += ' trustzone' + + if 'omaha_channel' in params: + channel = '-' + params['omaha_channel'] + name += ' ' + params['omaha_channel'] + else: + channel = '' + + ota_step.OtaStep.__init__(self, build_name=build_name, name=name, **kwargs) + product = self._build_name.split('-')[0] + + if destination_path_template is None: + if factory_image_type: + destination_path_template = ('{output_dir}/factory/{product}-' + '{image_type}-{variant}-{buildset}.zip') + else: + destination_path_template = ('{output_dir}/{product}-ota-{variant}' + '{tz}{channel}-{buildset}.zip') + self._resign_command = command[:] + if include_params: + for flag in params.keys(): + param = params[flag] + if param: + self._resign_command += ['--' + flag, param] + else: + self._resign_command += ['--' + flag] + + self._resign_command.append(source_binary_path.format( + dist_dir=self._dist_dir(), + product=product, + image_type=factory_image_type, + buildset=self.build_number)) + + self._resign_command.append(destination_path_template.format( + output_dir=self._ota_archive_output_dir(), product=product, + buildset=self.build_number, + image_type=factory_image_type, + variant=params['board'], channel=channel, tz=tz)) + + def run(self): + returncode, stdout, stderr = self.exec_subprocess(self._resign_command) + if returncode != 0: + self._error_processor(stdout, stderr) + + return returncode == 0 + + +class OtaUnandStep(OtaResignStep): + """Resign step class for building OTA's.""" + + # pylint: disable=super-init-not-called + def __init__(self, build_name, + command, params, source_binary_path, + name=None, **kwargs): + """Creates a OtaResignStep instance. + + Args: + build_name: Name of build (e.g. anchovy-eng, tvdefault-eng) + command: resign command, list + params: resign params, dictionary + source_binary_path: path to source binary, string + name: user-visible name of this step. + **kwargs: Any additional args to pass to BaseStep. + """ + if not name: + name = 'resign uNAND ' + name += params['board'] + + # pylint: disable=non-parent-init-called + ota_step.OtaStep.__init__(self, build_name=build_name, name=name, **kwargs) + + product = self._build_name.split('-')[0] + self._resign_command = command[:] + self._resign_command.append(params['board']) + self._resign_command.append(source_binary_path.format( + dist_dir=self._dist_dir(), + product=product, + buildset=self.build_number)) + self._resign_command.append('{output_dir}/factory'.format( + output_dir=self._ota_archive_output_dir()))
diff --git a/cq/scripts/slave/step/ota_step.py b/cq/scripts/slave/step/ota_step.py new file mode 100644 index 0000000..d50b68d --- /dev/null +++ b/cq/scripts/slave/step/ota_step.py
@@ -0,0 +1,607 @@ +"""Build step class for building OTA's.""" + +from __future__ import absolute_import +import logging +import os +import re +import sys + +from helpers import make_utils +from helpers import ninja_utils +from helpers import py_env_utils +from slave import base_step + +# Taken from recommended value in autoninja +BUILD_ACCELERATION_JOB_MULTIPLIER = 40 + +# Allow sufficient time for builds without build acceleration to finish. +_OTA_STEP_MAX_TIME_SECONDS = 6 * 60 * 60 + +_MESH_TAG = '-mesh-' +_YETI_TAG = '-yeti-' +_SDM_TAG = '-sdm-' +_GALLIUM_TAG = '-gallium-' +_OPAL_TAG = '-opal-' +_CONCIERGE_TAG = '-concierge-' +_HEALTH_TAG = '-health-' +_FUCHSIA_TAG = '-fuchsia-' +_FUCHSIA_REV_TAG = '-fuchsia_rev-' +_ML_FRAMEWORK_TAG = '-ml_framework-' +_DEMO_TAG = '-demo-' +_OTA_FILES_RE = r'.*-ota-.*\..*' +_PARTNER_TAG = '-partner-' +_LEGACY_TAG = '_legacy' +_1LED_TAG = '-1led-' +_MODULAR_COMMS_TAG = '-modular_comms-' +_IOT_CAST_TAG = '-iot_cast-' + +GANETI_TAG = '-ganeti-' + +_OTA_ZIP_TEMPLATE = '{}-ota-{}.zip' + + +class OtaStep(base_step.BaseStep): + """Build step class for building OTA's.""" + + def __init__(self, build_name, name='build ota', board_name=None, + extra_params=None, max_ota_size=None, target_name=None, + timeout_secs=_OTA_STEP_MAX_TIME_SECONDS, + **kwargs): + """Creates a OtaStep instance. + + Args: + build_name: Name of build (e.g. anchovy-eng, tvdefault-eng) + name: user-visible name of this step. + board_name: optional BOARD_NAME param for make if any. + extra_params: optional list of params to add + max_ota_size: Max size of OTA to enfoce if any enforcement required. + timeout_secs: Max execution time for OTA steps. + **kwargs: Any additional args to pass to BaseStep. + """ + base_step.BaseStep.__init__(self, name=name, timeout_secs=timeout_secs, + **kwargs) + self._build_name = build_name + self._board_name = board_name + self._extra_params = extra_params + self._max_ota_size = max_ota_size + self._target_name = target_name + + self._enable_verbose_logging = self._properties.get( + 'enable_verbose_logging', False) + + self._is_mesh_build = _MESH_TAG in self._build_name + self._build_name = self._build_name.replace(_MESH_TAG, '-') + + self._is_yeti_build = _YETI_TAG in self._build_name + self._build_name = self._build_name.replace(_YETI_TAG, '-') + + self._is_sdm_build = _SDM_TAG in self._build_name + self._build_name = self._build_name.replace(_SDM_TAG, '-') + + self._is_gallium_build = _GALLIUM_TAG in self._build_name + self._build_name = self._build_name.replace(_GALLIUM_TAG, '-') + + self._is_opal_build = _OPAL_TAG in self._build_name + self._build_name = self._build_name.replace(_OPAL_TAG, '-') + + self._is_concierge_build = _CONCIERGE_TAG in self._build_name + self._build_name = self._build_name.replace(_CONCIERGE_TAG, '-') + + self._is_health_build = _HEALTH_TAG in self._build_name + self._build_name = self._build_name.replace(_HEALTH_TAG, '-') + + self._is_fuchsia_build = _FUCHSIA_TAG in self._build_name + self._build_name = self._build_name.replace(_FUCHSIA_TAG, '-') + + self._is_fuchsia_rev_build = _FUCHSIA_REV_TAG in self._build_name + self._build_name = self._build_name.replace(_FUCHSIA_REV_TAG, '-') + + self._is_ml_framework_build = _ML_FRAMEWORK_TAG in self._build_name + self._build_name = self._build_name.replace(_ML_FRAMEWORK_TAG, '-') + + self._is_demo_build = _DEMO_TAG in self._build_name + self._build_name = self._build_name.replace(_DEMO_TAG, '-') + + self._is_ganeti_build = GANETI_TAG in self._build_name + self._build_name = self._build_name.replace(GANETI_TAG, '-') + + self._is_1led_build = _1LED_TAG in self._build_name + self._build_name = self._build_name.replace(_1LED_TAG, '-') + + self._is_modular_comms_build = _MODULAR_COMMS_TAG in self._build_name + self._build_name = self._build_name.replace(_MODULAR_COMMS_TAG, '-') + + self._is_iot_cast_build = _IOT_CAST_TAG in self._build_name + self._build_name = self._build_name.replace(_IOT_CAST_TAG, '-') + + # Partner repo is specified in properties, but the tag needs to be + # removed from the build name. + self._build_name = self._build_name.replace(_PARTNER_TAG, '-') + + self._build_name = self._build_name.replace(_LEGACY_TAG, '') + + def _dist_dir(self): + dist_dir = os.path.join('out/dist', self.build_number) + if self.patchset != '0': + dist_dir = os.path.join(dist_dir, str(self.patchset)) + return dist_dir + + def make_target_param(self, target_params=False): + """Creates PRODUCT or TARGET params for make. + + build/build test steps are using PRODUCT-<build name> notation, + TARGET_PRODUCT and TARGET_BUILD_VARIANT params required for OSS and FCT. + + Args: + target_params: use TARGET style params regardless current build_system. + Returns: + array of params to be appended to make command. + """ + target_name = self._target_name + if not target_name: + target_name = self._build_name + if target_params: + product, variant = target_name.split('-') + return ['TARGET_PRODUCT={}'.format(product), + 'TARGET_BUILD_VARIANT={}'.format(variant)] + return ['PRODUCT-' + target_name] + + def make_command_env(self): + """Generates env dictionary for make command.""" + return self.build_accelerator.environment_variables + + def _make_extra_flags(self): + """Generates make extra params based on build type.""" + + flags = [] + variant = self._build_name.split('-')[-1] + if variant != 'eng': + flags += ['OFFICIAL_BUILD=1'] + if self._enable_verbose_logging: + flags.append('showcommands') + if self._is_mesh_build: + flags += ['USE_GWIFI=1'] + if self._is_yeti_build: + flags += ['ENABLE_YETI=1', 'ENABLE_CLASSIC_YETI=0'] + if self._is_sdm_build: + flags += ['ENABLE_HOSPITALITY=1', 'ENABLE_MANAGED_MODE=1'] + if self._is_gallium_build: + flags += ['ENABLE_GALLIUM=1'] + if self._is_opal_build: + flags += ['ENABLE_OPAL=true'] + if self._is_concierge_build: + flags += ['ENABLE_SOUND_PRESENCE=1'] + if self._is_health_build: + flags += ['ENABLE_HEALTH_SOUND=1', 'ENABLE_MANAGED_MODE=1'] + if self._is_fuchsia_build: + flags += ['FUCHSIA_OTA=true'] + if self._is_fuchsia_rev_build: + flags += ['FUCHSIA_REVERSE=true'] + if self._is_ml_framework_build: + flags += ['ENABLE_ML_FRAMEWORK=true'] + if self._is_demo_build: + flags += ['DEMO_OTA=true'] + if self._board_name: + flags += ['BOARD_NAME={}'.format(self._board_name)] + if self._is_1led_build: + flags += ['NUM_LEDS=1'] + if self._is_modular_comms_build: + flags += ['ENABLE_MODULAR_COMMS=true'] + if self._is_iot_cast_build: + flags += ['ENABLE_IOT_CAST=1'] + if self._extra_params: + flags += self._extra_params + return flags + + def _build_ota(self, custom_shell): + """Builds |build_name| OTA package for the |issue| and |patchset|. + + Args: + custom_shell: List containing custom shell, to be used with make. + Returns: + True if the OTA package was built successfully, False otherwise. + """ + # Clean the systemimage first to avoid bleedover on incremental builds + # from previous builds of the same product. + command = ['make', + 'BUILD_NUMBER={}'.format(self.build_number), + 'USER=auto', + 'clean-systemimage', + 'DIST_DIR={}'.format(self._dist_dir())] + command += self.build_accelerator.make_flags + + quiet = False + if custom_shell: + quiet = True + + # For this step, don't use PRODUCT-* because it adds a "dist" goal. Just + # perform the clean-systemimage. + command += self.make_target_param(target_params=True) + command += self._make_extra_flags() + returncode, stdout, stderr = self.exec_subprocess( + command, env=self.make_command_env(), quiet=quiet) + + # We permit this step to fail because the clean-systemimage step + # is custom to Cast OS and does not exist on older release branches. + # Since CQ build logic always runs on master, regardless of the age + # of the code being built, we must maintain backwards compatibility. + if returncode != 0: + logging.warning( + 'Failed to run clean-systemimage. This is normal on release branches ' + 'from 1.50 and earlier. If this happens on a newer branch it is an ' + 'error and will cause non-deterministic ota package sizes.\n' + 'Return code %d, stderr:\n%s', + returncode, stderr) + + + command = ['make', + '--output-sync=target', + '-j{}'.format(self.get_num_jobs( + multiplier=BUILD_ACCELERATION_JOB_MULTIPLIER)), + 'BUILD_NUMBER={}'.format(self.build_number), + 'USER=auto', + 'dist', + 'DIST_DIR={}'.format(self._dist_dir()), + 'DISABLE_AUTO_INSTALLCLEAN=true',] + command += self.build_accelerator.make_flags + command += self.make_target_param() + command += self._make_extra_flags() + + if custom_shell: + command += custom_shell + + returncode, stdout, stderr = self.exec_subprocess( + command, env=self.make_command_env(), quiet=quiet) + + if custom_shell: + self._merge_build_logs() + + if returncode != 0: + if custom_shell: + self._dump_error_logs(stdout, stderr) + self._error_processor(stdout, stderr) + else: + if custom_shell: + self._print_build_success() + + if custom_shell: + sys.stdout.write('Complete logs can be found in build_ota.log ' + 'within invocation artifacts, sorted by module. Logs that are ' + 'generated outside of a module are logged under the "general" module.\n') + sys.stdout.flush() + + return returncode == 0 + + def _error_processor(self, stdout, stderr): + messages = ninja_utils.ninja_failure_to_comments(stdout, max_errors=3) + for message in messages: + self.add_review({'message': message}) + + comments = make_utils.make_error_to_comments(stderr, self.directory) + if comments: + self.add_review({'comments': comments}) + + def _print_build_success(self): + sys.stdout.write('Build successful.\n') + sys.stdout.flush() + + def _clear_dist(self, quiet): + """Clears everything in the dist directory leftover from previous builds. + Args: + quiet: Suppress subprocess output. + """ + dist_dirs = self.glob_files('out/dist/*') + if dist_dirs: + self.exec_subprocess(['rm', '-rf'] + dist_dirs, quiet=quiet) + + def _clear_ota_artifacts(self, quiet): + """Removes all OTA artifacts leftover by previous builds. + Args: + quiet: Suppress subprocess output. + """ + archive_pattern = re.compile(_OTA_FILES_RE) + + dist_files = self.glob_files('{}/*'.format(self._dist_dir())) + ota_files = [f for f in dist_files if archive_pattern.match(f)] + if ota_files: + self.exec_subprocess(['rm', '-f'] + ota_files, quiet=quiet) + + def _clear_symbols_artifacts(self, quiet): + """Removes all symbols artifacts leftover by previous builds. + Args: + quiet: Suppress subprocess output. + """ + symbols_files = self.glob_files('out/target/product/*/*-symbols-*.zip') + if symbols_files: + self.exec_subprocess(['rm', '-f'] + symbols_files, quiet=quiet) + + def _ota_archive_output_dir(self): + """Return system specific archive dir.""" + output_dir = self.get_gcs_dir() + if self.build_system != 'catabuilder': + output_dir = os.path.join(output_dir, 'artifacts') + if not os.path.exists(output_dir): + os.makedirs(output_dir) + + return output_dir + + def _archive_artifacts(self, quiet): + """Copies the artifacts for archival. + Args: + quiet: Suppress subprocess output. + """ + output_dir = self._ota_archive_output_dir() + if self.build_system == 'catabuilder': + # Archive everything in the continuous build system. + archive_pattern = re.compile(r'.*') + else: + archive_pattern = re.compile(_OTA_FILES_RE) + + dist_files = self.glob_files('{}/*'.format(self._dist_dir())) + archive_files = [f for f in dist_files if archive_pattern.match(f)] + for f in archive_files: + self.exec_subprocess(['cp', '-r', f, output_dir], quiet=quiet) + + # Save the OTA file list for later use. + ota_files = [f for f in archive_files if re.match(_OTA_FILES_RE, f)] + if ota_files: + filenames = [os.path.basename(x) for x in ota_files] + self.set_build_property('ota_files', filenames) + + def _dump_error_logs(self, stdout, stderr): + """Dumps error logs to stderr.""" + product = self._build_name.split('-')[0] + error_log_files = sorted(self.glob_files( + 'out/target/product/' + product + '/build_logs/*.err.txt'), + key=os.path.basename) + + if error_log_files: + sys.stdout.write('The following modules failed to build:\n') + sys.stdout.flush() + for error_file in error_log_files: + with open(error_file, 'r') as err_file: + contents = err_file.read() + sys.stdout.write(os.path.basename(error_file).split('.')[0] + ':\n') + sys.stdout.flush() + sys.stderr.write(contents) + sys.stderr.flush() + else: + # No errors found, dump error logs to test.log. + sys.stderr.write(stderr) + sys.stderr.flush() + + def _merge_build_logs(self): + """Copies build logs for archival.""" + product = self._build_name.split('-')[0] + build_log_files = sorted(self.glob_files( + 'out/target/product/' + product + '/build_logs/*.out.txt'), + key=os.path.basename) + output_dir = self.get_gcs_dir() + if not os.path.exists(output_dir): + os.makedirs(output_dir) + build_logs_file = os.path.join(output_dir, 'build_ota.log') + with open(build_logs_file, 'w') as out_file: + for log_file in build_log_files: + with open(log_file, 'r') as in_file: + contents = in_file.read() + if contents: + out_file.write('**********************************' + '************************************\n'); + out_file.write(os.path.basename(log_file).split('.')[0] + ':\n') + out_file.write('**********************************' + '************************************\n'); + out_file.write(contents + '\n') + out_file.flush() + + def _check_ota_size(self): + """Checks the size of the OTA. + + Returns: + Boolean if the OTA is under the max size. + """ + # TODO(gfhuang): A/B ota size check need rework. + # This as-is checks both .zip and .bin. + archive_pattern = re.compile(_OTA_FILES_RE) + + dist_files = self.glob_files('{}/*'.format(self._dist_dir())) + ota_files = [f for f in dist_files if archive_pattern.match(f)] + self._log_ota_size(ota_files) + if not self._max_ota_size: + return True + + for ota_file in ota_files: + ota_size = os.path.getsize(ota_file) + if ota_size > self._max_ota_size: + message = 'OTA size of {} exceed max of {} for file {}'.format( + ota_size, self._max_ota_size, ota_file) + sys.stdout.write(message + '\n') + sys.stdout.flush() + self.add_review({'message': message}) + return False + return True + + def _log_ota_size(self, ota_files): + target_ota_filename = _OTA_ZIP_TEMPLATE.format( + self.get_property('buildername', default='').split('-')[0], + self.get_property('buildset')) + ota_file = next((f for f in ota_files + if os.path.basename(f) == target_ota_filename), None) + + if not ota_file: + return + + self.set_build_property('ota_size', os.path.getsize(ota_file)) + if self._max_ota_size: + self.set_build_property('max_ota_size', self._max_ota_size) + + def _make_custom_shell(self): + """Returns a list containing a path to the custom shell""" + shell_path = os.path.abspath(os.path.join( + os.getcwd(), + 'build/android-mk-module-split-shell')) + if os.path.isfile(shell_path): + return ['ANDROID_BUILD_SHELL={}'.format(shell_path)] + return [] + + def run(self): + """Builds ota package. + + Returns: + True iff there were no errors. + """ + custom_shell = self._make_custom_shell() + self._clear_dist(bool(custom_shell)) + self._clear_ota_artifacts(bool(custom_shell)) + self._clear_symbols_artifacts(bool(custom_shell)) + if not self._build_ota(custom_shell): + return False + self._archive_artifacts(bool(custom_shell)) + if not self._check_ota_size(): + return False + return True + + +class OtaPropStep(base_step.BaseStep): + """Ota Property file step class for generating repo.prop.""" + + def __init__(self, **kwargs): + """Creates a OtaPropStep instance. + + Args: + **kwargs: Any additional args to pass to BaseStep. + """ + base_step.BaseStep.__init__(self, name='save repo.prop', **kwargs) + + def run(self): + prop_cmd = [ + 'repo', 'forall', '-c', + 'git show -s --format="$REPO_PROJECT %H"' + ] + proj_sha_pair_re = re.compile(r'^.+? [0-9a-f]{40}$', flags=re.IGNORECASE) + + repo_prop = self.exec_subprocess(prop_cmd, check_output=True, quiet=True) + valid_lines = [l for l in repo_prop.split('\n') + if proj_sha_pair_re.match(l.strip())] + prop_file = os.path.join(self.get_gcs_dir(), 'repo.prop') + with open(prop_file, 'w') as f: + f.write('\n'.join(valid_lines)) + return True + +class OtaCameraTargetsStep(base_step.BaseStep): + """Ota Property file step class for generating repo.prop.""" + + def __init__(self, product_name, is_eng_build, name='camera targets check', + **kwargs): + """Creates a OtaCameraTargets instance. + + Args: + product_name: product name without variant, e.g. spencer, venus + is_eng_build: if this build is eng build + name: user-visible name of this step. + **kwargs: Any additional args to pass to BaseStep. + """ + base_step.BaseStep.__init__(self, name='camera targets check', **kwargs) + self._is_eng_build = is_eng_build + self._product_name = product_name + + def run(self): + eng_targets = [ + '/system/bin/camera_tool', + '/system/bin/ffprobe', + '/system/bin/ffmpeg', + '/system/bin/cast_camera_hal_test' + ] + general_targets = [ '/obj/lib/libcast_camera_hal.so' ] + if self._is_eng_build: + for t in eng_targets: + abs_path = 'out/target/product/' + self._product_name + t + if not os.path.exists(abs_path): + logging.error('Missing binary %s' % abs_path) + return False + for b in general_targets: + abs_path = 'out/target/product/' + self._product_name + b + if not os.path.exists(abs_path): + logging.error('Missing binary %s' % abs_path) + return False + return True + + +class OtaUsoniaDaemonStep(OtaStep): + """Ota Property file step class for generating repo.prop.""" + + def __init__(self, build_name, **kwargs): + """Creates a OtaPropStep instance. + + Args: + **kwargs: Any additional args to pass to BaseStep. + """ + OtaStep.__init__(self, build_name=build_name, + name='build usonia_daemon', **kwargs) + + def run(self): + """Builds |usonia_daemon| for the |issue| and |patchset|. + Returns: + True if the usonia_daemon package is successfully built. + """ + + chromium_src = 'chromium/src' + usonia_tarball = os.path.join(chromium_src, + 'usonia-{}.tar.gz'.format(self.build_number)) + command = ['chromecast/internal/usonia/package_wifi.py', '-o', + '-f', '.', self.build_number] + returncode, stdout, stderr = self.exec_subprocess( + command, env=self.make_command_env(), cwd=chromium_src) + if returncode != 0: + self.exec_subprocess(['rm', '-rf', usonia_tarball]) + self._error_processor(stdout, stderr) + return False + + archive_dir = self._ota_archive_output_dir() + returncode, stdout, stderr = self.exec_subprocess( + ['cp', '-r', usonia_tarball, archive_dir]) + + self.exec_subprocess(['rm', '-rf', usonia_tarball]) + if returncode != 0: + self._error_processor(stdout, stderr) + return False + + return True + + +class ThreadTelemetryServiceCrosStep(OtaStep): + """Build step class for building Thread Telemetry Service for use in Chrome + OS.""" + + def __init__(self, **kwargs): + OtaStep.__init__(self, name='build thread_telemetry_service_cros', **kwargs) + + def run(self): + chromium_src = 'chromium/src' + tarball = os.path.join(chromium_src, + 'thread_telemetry_service-{}.tar.gz'.format( + self.build_number)) + command = [ + 'chromecast/internal/device/thread/' + 'build_thread_telemetry_service_cros.py', + '-o', + '-f', + '.', + self.build_number, + ] + returncode, stdout, stderr = self.exec_subprocess( + command, env=self.make_command_env(), cwd=chromium_src) + if returncode != 0: + self.exec_subprocess(['rm', '-f', tarball]) + self._error_processor(stdout, stderr) + return False + + archive_dir = self._ota_archive_output_dir() + returncode, stdout, stderr = self.exec_subprocess( + ['cp', '-r', tarball, archive_dir]) + + self.exec_subprocess(['rm', '-f', tarball]) + if returncode != 0: + self._error_processor(stdout, stderr) + return False + + return True
diff --git a/cq/scripts/slave/step/ota_strip_binaries_step.py b/cq/scripts/slave/step/ota_strip_binaries_step.py new file mode 100644 index 0000000..7170159 --- /dev/null +++ b/cq/scripts/slave/step/ota_strip_binaries_step.py
@@ -0,0 +1,186 @@ +"""Build step class for stripping OTA test binaries.""" + +# pylint triggers false positives in _setup/_teardown_mocks +# pylint: disable=method-hidden + +from __future__ import absolute_import +import logging +import os +import sys + +from slave import base_step + +_UNIT_TEST_ARCHIVE_MODULE = 'unit_test.unit_test_archive_lib' +_UNIT_TEST_HELPER_MODULE = 'unit_test.unit_test_helper' + +# If a file is larger than this, the strip tool will fail to recognize the file. +_MAX_32BIT_FILESIZE = 2**32 +_MAX_32BIT_FILESIZE_STR = '4GB' +_STRIPPED_EXT = '.stripped' + + +def _InjectPythonPath(path): + if path not in sys.path: + sys.path.append(path) + + +class OtaStripBinariesStep(base_step.BaseStep): + """Build step class for stripping OTA test binaries.""" + + def __init__(self, **kwargs): + """Creates a OtaStripBinariesStep instance. + + Args: + **kwargs: Any additional args to pass to BaseStep. + """ + base_step.BaseStep.__init__(self, name='strip binaries', **kwargs) + # Use the unit_test_helper modules to be consistent with Catabuilder. + self._unit_test_helper = None + self._unit_test_archive_lib = None + self._const = None + # Save list of files that need to be cleaned up at the end. + # Can't cleanup stripped binaries until after done archiving them. + self._stripped_binaries = [] + + @property + def const(self): + if not self._const: + self._const = self.unit_test_helper.GetUnitTestConst(None) + return self._const + + @property + def gcs_archive_dir(self): + output_dir = os.path.join(self.get_gcs_dir(), 'artifacts', 'tests') + if not os.path.exists(output_dir): + os.makedirs(output_dir) + return output_dir + + @property + def unit_test_helper(self): + """Use the unit_test_helper module to be consistent with Catabuilder.""" + if not self._unit_test_helper: + _InjectPythonPath(self.get_project_path('test')) + self._unit_test_helper = __import__( + _UNIT_TEST_HELPER_MODULE, fromlist=['']) + return self._unit_test_helper + + @property + def unit_test_archive_lib(self): + """Use unit_test_archive_lib module to be consistent with Catabuilder.""" + if not self._unit_test_archive_lib: + _InjectPythonPath(self.get_project_path('test')) + self._unit_test_archive_lib = __import__( + _UNIT_TEST_ARCHIVE_MODULE, fromlist=['']) + return self._unit_test_archive_lib + + def _get_out_dir(self): + chromium_src_dir = self.get_project_path('chromium/src') + return self.unit_test_helper.GetOutDir(chromium_src_dir) + + def _get_binaries_to_strip(self, out_dir): + return [ + binary for binary in + self.unit_test_helper.GetListOfBinariesToBeStripped(out_dir) + if binary.strip() + ] + + def _clear_test_binaries(self, test_binary_paths): + for binary in test_binary_paths: + stripped_binary = binary + _STRIPPED_EXT + if os.path.exists(stripped_binary): + try: + os.remove(stripped_binary) + except OSError: + continue + + def _get_test_files_to_archive(self, out_dir, stripped_binary_paths): + """Gets the set of test binaries & dependency files to archive.""" + stripped_binary_names = set( + [os.path.basename(path) for path in stripped_binary_paths]) + # Get a flattened deduped list of all binaries & dependencies to tar. + tar_files = set() + deps_dict = self.unit_test_archive_lib.GetAllTestDependenciesDict( + self.const, out_dir) + for test_deps in deps_dict.values(): + for dependency in test_deps: + # Use the stripped version of test binaries where available. + if os.path.basename( + dependency) in stripped_binary_names and os.path.exists( + os.path.join(self.const.chrome_srcroot, + dependency + _STRIPPED_EXT)): + tar_files.add(dependency + _STRIPPED_EXT) + else: + tar_files.add(dependency) + return tar_files + + def _strip_binary(self, file_path, output_binary): + return self.unit_test_helper.StripBinary( + file_path, output_file=output_binary) + + def _strip_error_to_comment(self, binary, stderr): + """Convert errors from the strip tool into comments for gerrit.""" + if not stderr: + return '' + + comment = stderr.replace(os.path.abspath(os.getcwd()), '') + binary_size = os.path.getsize(binary) + if binary_size > _MAX_32BIT_FILESIZE: + logging.warning('%s=%s bytes > %s', binary, binary_size, + _MAX_32BIT_FILESIZE_STR) + comment += ('{binary} ({size:,}bytes) is larger than {max_size}.' + ' Too large to strip. (b/33284348)'.format( + binary=os.path.basename(binary), + size=binary_size, + max_size=_MAX_32BIT_FILESIZE_STR)) + return comment + + def _strip_binaries(self, test_binaries): + """Strip the test binaries built for the most recent ota.""" + failure_messages = [] + for binary in test_binaries: + # Try to strip the binary. + output_binary = binary + _STRIPPED_EXT + try: + self._strip_binary(binary, output_binary) + except IOError as e: + # If stripping failed, report the error. + failure_messages.append(self._strip_error_to_comment(binary, str(e))) + return failure_messages + + def _archive_binaries(self, files_to_archive): + self.unit_test_archive_lib.ZipWithRelativeFileList( + self.const.chrome_srcroot, + os.path.join(self.gcs_archive_dir, 'test_deps.tar.gz'), + files_to_archive, + # Remove .stripped from all filenames within the tar. + transform=r's|{}$||'.format(_STRIPPED_EXT)) + + def run(self): + """Run the strip tool over the unittest binaries and archive them to GCS.""" + try: + out_dir = self._get_out_dir() + except ValueError as error: + # |out_dir| may not exist if a previous build step failed. However, we + # still want this step to be marked as failing in case the out_dir does + # actually exist somewhere and this step isn't finding it correctly. + self.add_review({'message': error.message}) + return False + + test_binary_paths = self._get_binaries_to_strip(out_dir) + # Clear in case recipe aborted in a previous run before able to cleanup + self._clear_test_binaries(test_binary_paths) + + failure_messages = self._strip_binaries(test_binary_paths) + if failure_messages: + self.add_review({'message': '\n'.join(failure_messages)}) + return False + + # Archive stripped test binaries into a tar file in gcs_archive_dir + # so that they'll be uploaded to GCS. Catatester will use the tar file + # for running these tests on-device in the lab. + files_to_archive = self._get_test_files_to_archive(out_dir, + test_binary_paths) + self._archive_binaries(files_to_archive) + + self._clear_test_binaries(test_binary_paths) + return True
diff --git a/cq/scripts/slave/step/partner_build_check_step.py b/cq/scripts/slave/step/partner_build_check_step.py new file mode 100644 index 0000000..432e808 --- /dev/null +++ b/cq/scripts/slave/step/partner_build_check_step.py
@@ -0,0 +1,67 @@ +"""Build step class for running partner build checks on source tree.""" + +from __future__ import absolute_import +import logging +import os + +from slave import base_step + +_PARTNER_BUILD_ERROR_MSG = ('Your change causes cast_shell to depend on ' + 'libcutil. This is not acceptable for partner ' + 'builds. Please rework your CL!') + +_READELF_FAILURE_MSG = ('readelf returned failure. Please make sure cast_shell' + 'is built and readelf is installed!') + + +class PartnerBuildCheckStep(base_step.BaseStep): + """Build step class for checking GN desc.""" + + def __init__(self, build_name, build_flavor, **kwargs): + """Creates a PartnerBuildCheckStep instance. + + This step requires ota build to be completed since it checks on cast_shell + executable. + + Args: + build_name: Name of build (e.g. pepperoni-eng, tvdefault-eng). + build_flavor: Flavor of build ('debug' or 'release'). + **kwargs: Any additional args to pass to BaseStep. + """ + base_step.BaseStep.__init__(self, name='partner build check', **kwargs) + + self._product = build_name.split('-')[0] + self._build_flavor = build_flavor + + def run(self): + """Runs gn desc on all changed GN files for the current commit. + + Sets a build property "review" with the output. + + Returns: + True iff there were no issues in partner build. + """ + cast_shell_path = os.path.join('chromium', 'src', + 'out_chromecast_' + self._product, + self._build_flavor, + 'cast_shell') + if not os.path.isfile(cast_shell_path): + logging.info('cast_shell is not built, cannot check partner build') + self.add_review({'message': 'Ota build did not complete'}) + return False + + command = ['readelf', + '-d', + cast_shell_path] + + returncode, stdout, _ = self.exec_subprocess(command) + + if returncode != 0: + self.add_review({'message': _READELF_FAILURE_MSG}) + return False + + if 'libcutil' in stdout: + self.add_review({'message': _PARTNER_BUILD_ERROR_MSG}) + return False + + return True
diff --git a/cq/scripts/slave/step/platform_info_step.py b/cq/scripts/slave/step/platform_info_step.py new file mode 100644 index 0000000..7e2bc1a --- /dev/null +++ b/cq/scripts/slave/step/platform_info_step.py
@@ -0,0 +1,28 @@ +"""Platform Statistics Gathering step.""" + +from __future__ import absolute_import +import logging + +from helpers import branch_utils +from slave import base_step + + +class PlatformInfoStep(base_step.BaseStep): + """A quick step class for gathering useful os/platform information.""" + + def __init__(self, **kwargs): + """Creates a PlatformInfoStep instance. + + Args: + **kwargs: Any additional args to pass to BaseStep. + """ + base_step.BaseStep.__init__(self, name='Platform Information', **kwargs) + + def run(self): + kernel_version_cmd = ['/bin/uname', '-v'] + cpu_info_cmd = ['/usr/bin/lscpu'] + + self.exec_subprocess(kernel_version_cmd, check_output=True) + self.exec_subprocess(cpu_info_cmd, check_output=True) + + return True
diff --git a/cq/scripts/slave/step/precommit_step.py b/cq/scripts/slave/step/precommit_step.py new file mode 100644 index 0000000..819643e --- /dev/null +++ b/cq/scripts/slave/step/precommit_step.py
@@ -0,0 +1,163 @@ +"""A step to run pre-commit hooks. + +See documentation on the precommit recipe - this module +contains the single step in that recipe.""" +from __future__ import absolute_import +import logging +import os +import pprint +import tempfile + +from helpers import git_utils +from helpers import os_utils +from slave import base_step + + +class PreCommitStep(base_step.BaseStep): + """Step for running pre-commit hook checks.""" + + def __init__(self, config_file, repo_root_directory, show_output, **kwargs): + """ + Args: + config_file: The pre-commit config file to use. + repo_root_directory: The root directory to the repo checkout. + show_output: True to make the output a comment on the CL. + **kwargs: Additional args passed to BaseStep. + """ + base_step.BaseStep.__init__(self, name="precommit", **kwargs) + self._config_file = config_file + self._repo_root_directory = repo_root_directory + self._show_output = show_output + + def run(self): + """Run the step. + + Returns: + True if either: + 1. There is a pre-commit config and there were no pre-commit failures. + 2. There was no pre-commit config. + """ + try: + directory = self.directory + except KeyError: + logging.info("Unable to get self.directory. Skipping pre-commit.") + return True + + pre_commit_config = os.path.join(directory, self._config_file) + if not os.path.exists(pre_commit_config): + logging.info("No pre-commit config at %s (%s), skipping", + pre_commit_config, os.path.abspath(pre_commit_config)) + return True + + results = [ + self._run_commit_message_hooks(), + self._run_pre_commit_hooks(), + self._run_push_hooks(), + ] + returncode = max(returncode for returncode, _, _ in results) + stdout = "\n".join(stdout for _, stdout, _ in results) + stderr = "\n".join(stderr for _, _, stderr in results) + if self._show_output: + try: + self.add_review({ + "comments": {}, + "message": "stdout: {}\n\nstderr: {}".format(stdout, stderr), + }) + except UnicodeDecodeError: + self.add_review({ + "comments": {}, + "message": ("Failed to decode precommit output as unicode, " + "please check the builder log directly."), + }) + else: + self.add_review({ + "comments": {}, + "message": ("This builder is non-blocking and its output can be " + "ignored."), + }) + if returncode: + return False + return True + + def _get_env(self): + env = os.environ.copy() + env["EUREKAROOT"] = self._repo_root_directory + logging.info("Using PATH: %s", + pprint.pformat(env.get("PATH", "").split(":"))) + try: + chromium_src = self.get_project_path("chromium/src") + buildtools_path = os.path.join( + self._repo_root_directory, + chromium_src, + "buildtools") + logging.info("Setting CHROMIUM_BUILDTOOLS_PATH to %s", buildtools_path) + env["CHROMIUM_BUILDTOOLS_PATH"] = buildtools_path + except KeyError: + logging.info("Unable to set CHROMIUM_BUILDTOOLS_PATH, " + "no chromium/src found.") + return env + + def _precommit_binary(self) -> str: + """Get the path to pre-commit in our recipe's virtualenv.""" + return os.path.join(self.get_step_data("virtual_env_root"), + "bin", "pre-commit") + + def _run_commit_message_hooks(self): + """Run all the hooks for commit message checks. + + Returns: + A tuple of returncode, stdout, stderr from pre-commit + """ + env = self._get_env() + with os_utils.change_cwd(self.directory): + commit_message = git_utils.commit_message(self) + commit_message_path = self.write_temp_file(commit_message) + logging.debug("Using commit message tempfile %s", commit_message_path) + cmd = [ + self._precommit_binary(), + "run", + "--config", self._config_file, + "--hook-stage", "commit-msg", + "--commit-msg-filename", commit_message_path, + ] + return self.exec_subprocess(cmd, env=env) + + def _run_pre_commit_hooks(self): + """Run all the hooks of the 'pre-commit' type. + + This is an unfortunate naming problem - 'pre-commit' the framework + shares a name with the 'pre-commit' git hook type, which are hooks + to run before committing. This function runs just those hooks, as + opposted to pre-push, commit-message, or other hook types. + + Returns: + A tuple of returncode, stdout, stderr from pre-commit + """ + env = self._get_env() + with os_utils.change_cwd(self.directory): + cmd = [ + self._precommit_binary(), + "run", + "--config", self._config_file, + "--source", "HEAD^", + "--origin", "HEAD" + ] + return self.exec_subprocess(cmd, env=env) + + def _run_push_hooks(self): + """Run all the hooks of the 'push' stage. + + Returns: + A tuple of returncode, stdout, stderr from pre-commit + """ + env = self._get_env() + with os_utils.change_cwd(self.directory): + cmd = [ + self._precommit_binary(), + "run", + "--hook-stage", "push", + "--config", self._config_file, + "--source", "HEAD^", + "--origin", "HEAD" + ] + return self.exec_subprocess(cmd, env=env)
diff --git a/cq/scripts/slave/step/py_env_setup_step.py b/cq/scripts/slave/step/py_env_setup_step.py new file mode 100644 index 0000000..01229bd --- /dev/null +++ b/cq/scripts/slave/step/py_env_setup_step.py
@@ -0,0 +1,80 @@ +"""Build step class for setting up a Python environment.""" +from pathlib import Path +import os +from typing import Iterable, Optional + +from helpers import py_env_utils +from slave import base_step + + +class PyEnvSetupStep(base_step.BaseStep): + """Step for setting up python envs.""" + + def __init__(self, + additional_import_paths: Optional[Iterable[Path]]=None, + local_package_project: str=None, + local_packages_dir: str=None, + py3: bool=False, + requirements_project: str=None, + requirements_path: str=None, + **kwargs): + """Creates a PyEnvSetupStep instance. + + Args: + additional_import_paths: Paths to add to sys.path for the environment + local_package_project: manifest project to look a python packages on disk + local_packages_dir: Relative path to python packages under ~/gcs-mirror + py3: if True use python3 + requirements_project: manifest project to look for requirements_path + requirements_path: path to requirements file under requirements_project + gcs_mirror_path: The directory that mirrors the gcs bucket + **kwargs: Any additional args to pass to BaseStep. + """ + super().__init__(name='py_env_setup', **kwargs) + self._gcs_dir = self._properties.get( + 'gcs_mirror_path', '/workspace/gcs-mirror') + self._additional_import_paths = additional_import_paths + self._local_package_project = local_package_project + self._local_packages_dir = local_packages_dir + self._py3 = py3 + self._requirements_path = requirements_path + self._requirements_project = requirements_project + + def run(self) -> bool: + """Sets up a Python environment. + + Adds 'virtual_env_root' to the step data. + + Returns: + True iff the environment was set up correctly. + """ + py_requirements_dir = self.get_project_path(self._requirements_project) \ + if self._requirements_project else None + local_package_path = self.get_project_path(self._local_package_project) \ + if self._local_package_project else None + venv_root = py_env_utils.create_virtual_env( + self, + self.get_tmp_dir(), + gcs_dir=self._gcs_dir, + local_packages=self._local_packages_dir, + py3=self._py3) + py_env_utils.add_import_paths(venv_root, [Path.home() / 'depot_tools']) + self.add_step_data('virtual_env_root', venv_root) + if py_requirements_dir: + requirements = os.path.join(py_requirements_dir, + self._requirements_path) + py_env_utils.install_py_deps( + self, venv_root, requirements, self._gcs_dir, self._local_packages_dir + ) + if local_package_path: + py_env_utils.install_package( + self, + venv_root, + local_package_path, + self._gcs_dir, + local_packages=self._local_packages_dir + ) + + if self._additional_import_paths: + py_env_utils.add_import_paths(venv_root, self._additional_import_paths) + return True
diff --git a/cq/scripts/slave/step/py_test_step.py b/cq/scripts/slave/step/py_test_step.py new file mode 100644 index 0000000..0b82c99 --- /dev/null +++ b/cq/scripts/slave/step/py_test_step.py
@@ -0,0 +1,95 @@ +"""Build step class for running Python tests.""" +import json +import logging +import os + +from helpers import py_env_utils +from slave import base_step + +_UNITTEST_RESULT_MARKER = '__CQ_UNITTEST_RESULTS_SUMMARY__:' + + +class PyTestStep(base_step.BaseStep): + """Step for running python tests.""" + + def __init__(self, + project, + test_file_filter_regex, + timeout, + module_path_regex='.', + **kwargs): + """Creates a PyTestStep instance. + + Args: + project: Manifest project to look for tests inside of it. + test_file_filter_regex: File pattern for tests to be run. + timeout: Timeout for test run (in seconds). + module_path_regex: Regex to determine which modules to include. + **kwargs: Any additional args to pass to BaseStep. + """ + base_step.BaseStep.__init__(self, name='py_test', **kwargs) + self._project = project + self.test_file_filter_regex = test_file_filter_regex + self.module_path_regex = module_path_regex + self.timeout = timeout + + def _execute_tests(self, venv_root): # pylint: disable=method-hidden + """Execute the tests. + + Args: + venv_root: Path to the python virtual env root to activate. + + Returns: + Tuple: (review, passing) Where passing is a boolean if the tests + passed and review is the generated review message. + """ + test_runner = os.path.abspath( + os.path.join(self.get_cq_root(), + 'scripts/helpers/py_test_runner.py')) + directory = os.path.join( + self._getcwd(), self.get_project_path(self._project)) + test_results = os.path.join(self.get_tmp_dir(), 'test_review.json') + cmd = [test_runner, + '--test_dir', directory, + '--output', test_results, + '--test_file_filter_regex', self.test_file_filter_regex, + '--module_path_regex', self.module_path_regex, + '--timeout', str(self.timeout)] + env = { + 'SHELL_EXE_BINARY_PATH': self.get_step_data('cast_shell_exe_path', ''), + } + returncode, stdout, stderr = py_env_utils.exec_within_virtual_env( + self, venv_root, cmd, env=env) + + if returncode != 0: + logging.error('Failed to run tests: %s\n%s', stdout, stderr) + return {'message': 'Tests did not run properly', 'passing': False} + + return self._parse_test_results(test_results) + + def _parse_test_results(self, test_results_file): + with open(test_results_file) as f: + return json.load(f) + + def run(self): + """Runs python tests on the repository. + + Sets a build property "review" with the output. + + Returns: + True iff there were no test errors. + """ + venv_root = self.get_step_data('virtual_env_root') + try: + review = self._execute_tests(venv_root) + passing = review['passing'] + if passing: + logging.info(review.get('message')) + else: + self.add_review(review) + except Exception as e: # pylint: disable=broad-except + logging.exception('Failure while executing tests.') + self.add_review({'message': 'Failed due to exception [{}].'.format(e)}) + return False + + return passing
diff --git a/cq/scripts/slave/step/pylint_step.py b/cq/scripts/slave/step/pylint_step.py new file mode 100644 index 0000000..26217c1 --- /dev/null +++ b/cq/scripts/slave/step/pylint_step.py
@@ -0,0 +1,63 @@ +"""Build step class for linting Python files with pylint.""" + +from __future__ import absolute_import +import logging +import os + +from helpers import git_utils +from helpers import pylint +from slave import base_step + +PYLINTRC_NAMES = ['pylintrc', '.pylintrc'] + +class PylintStep(base_step.BaseStep): + """Build step class for linting Python files.""" + + def __init__(self, pylintrc_file=None, **kwargs): + """Creates a PylintStep instance. + + Args: + **kwargs: Any additional args to pass to BaseStep. + """ + base_step.BaseStep.__init__(self, name='pylint', **kwargs) + self._pylintrc_file = pylintrc_file + + def run(self): + """Runs pylint on all changed files for the current commit. + + Sets a build property "review" with the output. + + Returns: + True iff there were no lint errors. + """ + changed_files = git_utils.changed_files( + self, directory=self.directory, file_extensions=['.py'], + file_exclusion_pattern=r'^.+_pb2.py$') + + changed_files = [f + for f in changed_files + if self.allow_listed(f) and not self.deny_listed(f)] + + if not self._pylintrc_file: + for name in PYLINTRC_NAMES: + path = os.path.join(self.directory, name) + if os.path.isfile(path): + self._pylintrc_file = path + break + try: + lint_output = pylint.RunPylint( + changed_files, pylintrc_file=self._pylintrc_file, cwd=self.directory, + executor=self) + comments = pylint.ParseLint(lint_output.splitlines()) + + if not comments: + logging.info('Autogenerated lint comments: looks clean') + return True + except pylint.PylintError as e: + message = str(e) + self.add_review({'message': message}) + return False + + self.add_review({'message': 'Autogenerated lint comments', + 'comments': comments}) + return False
diff --git a/cq/scripts/slave/step/reproxy_start_step.py b/cq/scripts/slave/step/reproxy_start_step.py new file mode 100644 index 0000000..7cbb4a0 --- /dev/null +++ b/cq/scripts/slave/step/reproxy_start_step.py
@@ -0,0 +1,43 @@ +"""Build step class for starting reproxy.""" + +from __future__ import absolute_import +import logging + +from helpers import rbe_utils +from slave import base_step + + +class ReproxyStartStep(base_step.BaseStep): + """Build step class for starting the remote execution reproxy.""" + + def __init__(self, **kwargs): + """Creates a ReproxyStartStep instance. + + Args: + **kwargs: Any additional args to pass to BaseStep. + """ + super().__init__(name='reproxy start', **kwargs) + + def run(self): + """Starts the reproxy process. + + Starts reproxy via the bootstrap control binary. + + Returns: + True if reproxy has started successfully. + """ + + if not rbe_utils.is_installed(): + if self.build_system == 'catabuilder': + return True + logging.warning( + 'RBE was requested (via use_rbe=True) but it is not installed on ' + 'this branch. go/cherry-pick-rbe to fix this build error.') + return False + + retcode, _, _ = rbe_utils.start_reproxy(self) + if retcode != 0: + logging.error('reproxy failed to start') + return False + + return True
diff --git a/cq/scripts/slave/step/reproxy_stop_step.py b/cq/scripts/slave/step/reproxy_stop_step.py new file mode 100644 index 0000000..7740d32 --- /dev/null +++ b/cq/scripts/slave/step/reproxy_stop_step.py
@@ -0,0 +1,38 @@ +"""Build step class for stopping reproxy.""" + +from __future__ import absolute_import +import logging + +from helpers import rbe_utils +from slave import base_step + + +class ReproxyStopStep(base_step.BaseStep): + """Build step class for stoping the remote execution reproxy.""" + + def __init__(self, **kwargs): + """Creates a ReproxyStopStep instance. + + Args: + **kwargs: Any additional args to pass to BaseStep. + """ + super().__init__(name='reproxy stop', **kwargs) + + def run(self): + """Stops the reproxy process. + + Stops reproxy via the bootstrap control binary. This also generates + the rbe_metrics.txt file. + + Returns: + True always. Don't fail the build if reproxy fails to stop. + """ + + if not rbe_utils.is_installed(): + return True + + retcode, _, _ = rbe_utils.stop_reproxy(self) + if retcode != 0: + logging.error('reproxy failed to stop') + + return True
diff --git a/cq/scripts/slave/step/sanitizer_unittest_step.py b/cq/scripts/slave/step/sanitizer_unittest_step.py new file mode 100644 index 0000000..c047a6a --- /dev/null +++ b/cq/scripts/slave/step/sanitizer_unittest_step.py
@@ -0,0 +1,80 @@ +"""Run a unittest with a sanitizer. + +The key feature of this step is that this step will only be marked as failed +if the sanitizer detects an issue. If a test fails for another reason, then +this step is not considered to have failed. + +Available sanitizers are: asan, msan, tsan, and ubsan. +""" + +from __future__ import absolute_import +import os + +from helpers import sanitizer_utils +from slave.step import shell_step + + +class SanitizerUnitTestShellStep(shell_step.ShellStep): + """Unit test step running with a sanitizer .""" + + def __init__(self, sanitizer=None, **kwargs): + """Constructor.""" + assert sanitizer in ['asan', 'msan', 'tsan', 'ubsan'] + properties_handler = sanitizer_utils.get_sanitizer_to_comments_for( + sanitizer) + shell_step.ShellStep.__init__( + self, properties_handler=properties_handler, **kwargs) + self._sanitizer = sanitizer + self._unittest_prefix_filter = 'cast_' + if 'unittest_prefix_filter' in kwargs: + self._unittest_prefix_filter = kwargs['unittest_prefix_filter'] + + + symbolizer = os.path.relpath( + os.path.join( + self.get_project_path('chromium/src'), + 'third_party/llvm-build/Release+Asserts/bin/llvm-symbolizer'), + self.directory) + suppression_dir = os.path.relpath( + os.path.join( + self.get_project_path('chromecast/internal'), 'build/sanitizers'), + self.directory) + asan_options = ('detect_leaks=1 ' + 'detect_odr_violation=0 ' + 'symbolize=1 ' + 'external_symbolizer_path={}'.format(symbolizer)) + lsan_options = ('suppressions={}/lsan_suppressions'.format(suppression_dir)) + tsan_options = ('external_symbolizer_path={} ' + 'suppressions={}/tsan_suppressions').format(symbolizer, + suppression_dir) + ubsan_options = ('external_symbolizer_path={}'.format(symbolizer)) + + self._sanitizer_env = { + 'ASAN_OPTIONS': asan_options, + 'LSAN_OPTIONS': lsan_options, + 'MSAN_SYMBOLIZER_PATH': symbolizer, + 'TSAN_OPTIONS': tsan_options, + 'UBSAN_OPTIONS': ubsan_options, + } + + @property + def validator(self): + # Non-cast unittests (i.e. upstream Chromium tests) are not MSAN clean, so + # do not block on them until upstream MSAN bots are stabilized. + # (crbug/658452) + if not self._name.startswith(self._unittest_prefix_filter): + return lambda *args: True + return sanitizer_utils.get_validator_for(self._sanitizer) + + def get_commands(self): + """Returns which commands to be run. Can be overridden by a subclass. + + Returns: + List of ShellCommand objects to execute. + """ + assert isinstance(self._command, list) + return [self.ShellCommand( + self._command, + validator=self.validator, + cwd=self.directory, + env=self._sanitizer_env)]
diff --git a/cq/scripts/slave/step/shell_step.py b/cq/scripts/slave/step/shell_step.py new file mode 100644 index 0000000..a1f47c8 --- /dev/null +++ b/cq/scripts/slave/step/shell_step.py
@@ -0,0 +1,230 @@ +"""Build step class for executing a simple shell command.""" + +from __future__ import absolute_import +import logging +import time + +import six +from helpers import retry_utils +from helpers import signal_utils +from slave import base_step + +class ShellStep(base_step.BaseStep): + """Build step class for executing a shell command.""" + + class ShellCommand(object): + """A simple object wrapping a shell command to execute.""" + + def __init__(self, command, validator=None, cwd=None, env=None, + num_retries=0, setup_for_retry=None, halt_on_failure=False, + retry_if=None): + """Constructor for a ShellCommand object. + + Args: + command: The command to be run, as a list of strings (required). + validator: A function that takes 3 arguments: returncode, stdout, stderr + from the run command and returns a boolean value indicating if the + command succeeded (True) or failed (False). + (Default checks if returncode == 0) + cwd: The directory from which this command is to be run. This will + override the current directory of the step. + env: A dictionary mapping environment variables to their values. + num_retries: The number of times to retry this step if it fails. + (Defaults to 0) + retry_if: A function that takes 3 arguments: returncode, stdout, stderr + from the run command and returns whether to retry the command (True) + or to skip retrying (False). + setup_for_retry: A function to run before attempting to retry this + command. Can be used to do work that may help the command + succeed upon retry. Only used if num_retries > 0. + halt_on_failure: Boolean if we should stop running subsequent steps on + failure. (Defaults to False) + """ + assert isinstance(command, list) + assert not cwd or isinstance(cwd, six.string_types) + assert not env or isinstance(env, dict) + + self.command = command + self._validator = validator + self.cwd = cwd + self.env = env or {} + self._num_retries = num_retries + self._retry_if = retry_if + self._setup_for_retry = setup_for_retry + self._halt_on_failure = halt_on_failure + + @property + def num_retries(self): + """Number of retries to run.""" + return self._num_retries + + @property + def halt_on_failure(self): + """Boolean if we should halt on a failure.""" + return self._halt_on_failure + + def exec_retry_setup(self, returncode, stdout, stderr): + """Run this before attempting to retry this command. + + If command has failed from a recoverable issue, then this can be used + to recover so that the next retry attempt of |self.command| will succeed. + + Args: + returncode: returncode of |self.command| that failed and is about to + be retried. + stdout: stdout of |self.command| that failed and is about to be retried. + stderr: stderr of |self.command| that failed and is about to be retried. + """ + if self._setup_for_retry: + self._setup_for_retry(returncode, stdout, stderr) + + def validate(self, returncode, stdout, stderr): + if self._validator: + return self._validator(returncode, stdout, stderr) + return returncode == 0 + + def retry_if(self, returncode, stdout, stderr): + """If command fails validator, check if it should be retried.""" + if self._retry_if: + return self._retry_if(returncode, stdout, stderr) + return returncode != 0 + + def __init__(self, name=None, command=None, validator=None, + properties_handler=None, force_success=False, num_retries=0, + retry_if=None, cwd=None, env=None, **kwargs): + """Creates a ShellStep instance. + + Args: + name: name of this step + command: shell command to run, as a list (argv). + validator: A function that takes 3 arguments: returncode, stdout, stderr + from the run command and returns a boolean value indicating if the + command succeeded (True) or failed (False). + (Default checks if returncode == 0) + properties_handler: if provided, method for providing properties from the + command output. + force_success: Force this step to return success, even if the shell + command returns non-zero. (Defaults to False) + num_retries: The number of times to retry this step if it fails. + (Defaults to 0) + retry_if: A function that takes 3 arguments: returncode, stdout, stderr + from the run command and returns whether to retry the command (True) + or to skip retrying (False). + cwd: The directory from which the ShellCommands will be run if cwd is + not set on the ShellCommand. This will override the current directory + for the step also. + env: A dictionary mapping environment variables to their values to be + used if no env is set on the ShelLCommands. + **kwargs: Any additional args to pass to BaseStep. + """ + base_step.BaseStep.__init__(self, name=name, **kwargs) + + self._command = command + self._validator = validator + self._properties_handler = properties_handler + self._force_success = force_success + self._num_retries = num_retries + self._retry_if = retry_if + self._cwd = cwd + self._env = env + + def _execute_cmd(self, cmd): + """Executes a ShellCommand. + + Args: + cmd: A ShellCommand instance. + + Returns: + A tuple of: + Boolean if the command was successful, returncode, stdout, stderr + """ + directory = cmd.cwd or self._cwd or self.directory or None + environment = cmd.env or self._env or {} + retry = True + attempt = 0 + success = True + while retry: + returncode, stdout, stderr = self.exec_subprocess( + cmd.command, cwd=directory, env=environment) + success = cmd.validate(returncode, stdout, stderr) + retry = attempt < cmd.num_retries and not success + if retry and cmd.retry_if(returncode, stdout, stderr): + delay = retry_utils.retry_delay(attempt) + attempt += 1 + logging.info( + 'Retrying command in %s seconds. Attempt %s of %s.', + delay, attempt, cmd.num_retries) + time.sleep(delay) + cmd.exec_retry_setup(returncode, stdout, stderr) + return success, returncode, stdout, stderr + + def run(self): + """Executes this step by running all commands found in get_commands(). + + Returns: + True iff the return code of every command was 0. + """ + retry, success = True, True + returncode, stdout, stderr = 0, '', '' + attempt = 0 + + while retry: + try: + success = True # Reset success for each retry + for shell_command in self.get_commands(): + cmd_success, returncode, stdout, stderr = self._execute_cmd( + shell_command + ) + + success = self._force_success or cmd_success + if shell_command.halt_on_failure and not success: + break + except signal_utils.SigtermException: + # We want to skip retries in case of a Sigterm because this means we + # got a signal from outside to stop current execution. + raise + except Exception: # pylint: disable=broad-except + # Absorb all exceptions until there are no retries left. + if attempt < self._num_retries: + logging.exception(('Step exception during [%s] ignored because there ' + 'are still retries(%d) remainining.'), + self.get_name(), + self._num_retries - attempt) + success = False + else: + logging.exception('Step exception during [%s] with no retries left.', + self.get_name(),) + return False + + finally: + retry = attempt < self._num_retries and not success + + if retry: + delay = retry_utils.retry_delay(attempt) + attempt += 1 + logging.info( + 'Retrying [%s] in %s seconds. Attempt %s of %s.', + self.get_name(), delay, attempt, self._num_retries) + time.sleep(delay) + + # Only set properties from the final run, otherwise properties from + # failed runs and successful runs could be mixed together. + if self._properties_handler: + new_properties = self._properties_handler(returncode, stdout, stderr) + for property_name in new_properties: + if property_name == 'review': + self.add_review(new_properties[property_name]) + else: + self.set_build_property(property_name, new_properties[property_name]) + + return success + + def get_commands(self): + """Returns which commands to be run. Can be overridden by a subclass. + + Returns: + List of ShellCommand objects to execute. + """ + assert isinstance(self._command, list) + return [self.ShellCommand(self._command, validator=self._validator, + retry_if=self._retry_if)]
diff --git a/cq/scripts/slave/step/sprockets_step.py b/cq/scripts/slave/step/sprockets_step.py new file mode 100644 index 0000000..3a1d878 --- /dev/null +++ b/cq/scripts/slave/step/sprockets_step.py
@@ -0,0 +1,88 @@ +"""Step for running Sprockets protocol conformance tests. + +See go/sprockets-eng and go/stl-manual for more information. +""" + +from __future__ import absolute_import +import collections +import json +import logging +import os + +from helpers import cast_shell_utils +from slave import base_step + +_SprocketsTestConfig = collections.namedtuple('_SprocketsTestConfig', + 'project, config') +_SPROCKETS_PROJECT = 'google/sprockets' +_SPROCKETS_TEST_DRIVER = 'test_driver.py' +_SPROCKETS_TEST_CONFIGS = [ + _SprocketsTestConfig(project='test', config='sprockets_tests/tests.json') +] + +_CAST_SHELL_FAILURE_MSG = 'Failed to start up and communicate with cast_shell.' +_SPROCKETS_TEST_FAILURE_MSG = ( + 'Sprockets test failed. See the build log for details.') + + +class SprocketsConformanceTestStep(base_step.BaseStep): + """Step to run Sprockets tests.""" + + def __init__(self, **kwargs): + """Constructor.""" + base_step.BaseStep.__init__( + self, name='sprockets conformance tests', directory='', **kwargs) + + def read_config(self, config_file_path): + if not os.path.exists(config_file_path): + logging.info('%s does not exist. Skipping.', config_file_path) + return [] + with open(config_file_path) as config_json: + return json.load(config_json) + + def run(self): + """Returns which commands to be run. Can be overridden by a subclass. + + Returns: + List of ShellCommand objects to execute. + """ + try: + _, log_descriptor, log_path = cast_shell_utils.start_cast_shell( + self, + self.get_project_path('test'), + self.get_step_data(cast_shell_utils.CAST_SHELL_EXE_PATH), + self.get_tmp_dir(), + use_headless_ozone_platform=True, + enable_ccs_transport_v2=True) + except (cast_shell_utils.CastShellError, + cast_shell_utils.CastShellTimeoutError): + logging.exception('Failed to start cast_shell') + self.add_review({'message': _CAST_SHELL_FAILURE_MSG}) + return False + + sprockets_path = self.get_project_path(_SPROCKETS_PROJECT) + sprockets_test_runner = os.path.join(sprockets_path, _SPROCKETS_TEST_DRIVER) + + success = True + for config in _SPROCKETS_TEST_CONFIGS: + config_path_root = self.get_project_path(config.project) + config_file_path = os.path.join(config_path_root, config.config) + for test in self.read_config(config_file_path): + test_path_root = self.get_project_path(test['project']) + test_manifest = os.path.join(test_path_root, test['manifest']) + test_command = ['python3', sprockets_test_runner, test_manifest] + test_command.extend(test['args']) + returncode, _, _ = self.exec_subprocess(test_command) + success = (returncode == 0) and success + + if log_descriptor and log_path: + cast_shell_utils.upload_cast_shell_logs(log_descriptor, log_path, + self.get_gcs_dir(), + 'sprockets_conformance_tests', + 'cast_shell.logcat') + if not success: + self.add_review({ + 'message': _SPROCKETS_TEST_FAILURE_MSG + }) + + return success
diff --git a/cq/scripts/slave/step/unittest_step.py b/cq/scripts/slave/step/unittest_step.py new file mode 100644 index 0000000..d7bc89c --- /dev/null +++ b/cq/scripts/slave/step/unittest_step.py
@@ -0,0 +1,627 @@ +"""Build step classes for building and running unit tests.""" +import logging +import os +import re + +import six + +from helpers import branch_utils +from helpers import git_utils +from helpers import gn_utils +from helpers import ninja_utils +from slave import base_step +from slave.step import cast_shell_step +from slave.step import sanitizer_unittest_step +from slave.step import shell_step + +_BUILD_CHROMECAST_SCRIPT = 'build/build_chromecast.py' + +RUN_TEST_LIST_PATH = 'tests/run_test_list.txt' +RUN_JUNIT_TEST_LIST_PATH = 'junit/run_junit_test_list.txt' + +STEP_DATA_TEST_LIST = 'step_data_test_list' +STEP_DATA_JUNIT_TEST_LIST = 'step_data_junit_test_list' + +ANDROID_TEST_RUNNER_PROJECT = 'test' +ANDROID_TEST_RUNNER_PATH = 'unit_test/atv_unit_test_runner.py' +TRANSFORM_XML_TO_JSON_PATH = 'unit_test/transform_xml_results_to_json.py' + +UNIT_TEST_REPORT_PATH = 'unit_test_results' + +# This is the maximum number of modified files a single change can have +# before we assume that we need to run all unit tests. This value exists +# because it takes time to calculate which tests need to be run for a set +# of files and for very large changes, like chromium merges, it's just better +# to assume we need to run all tests. +MAX_TARGETS_FOR_ALL_TESTS = 1000 + +# There are some files that GN does not know about that could affect the +# unit tests. If any of these files are touched, then build and run all the +# unit tests in order to be safe. +# A map of <project-name> -> <list of file regexes to match>. +FORCE_RUN_ALL_TESTS_WHITELIST = { + 'chromecast/internal': [r'build/.*', r'vendor/google3/prebuilts.json'], + 'vendor/amlogic': [r'google3_prebuilts.json'], + 'vendor/marvell': [r'google3_prebuilts.json'], +} + + +class GnExecutionError(RuntimeError): + """Exception raised when a gn command returns a non-zero return code.""" + + +class BuildAffectedUnitTestsStep(cast_shell_step.NonOtaBuildBaseStep): + """Build step class for building unit tests.""" + + def __init__(self, + branding, + build_type, + product, + build_flavor, + enable_assistant, + sanitizer=None, + code_coverage=False, + absolute_coverage=False, + build_args_product=None, + build_args_official=None, + junit=False, + **kwargs): + """Instantiate the class. + + Args: + branding: Build branding (chromium or chrome). + build_type: Type of system to build for ('x86', 'clang', or 'arm'). + product: product to build for (ie. 'chromecast', 'audio'). + build_flavor: Flavor of build ('Debug', 'Eng', 'Release'). + enable_assistant: enable Assistant functionality. Audio products only. + sanitizer: Clang saniziter to run with ('asan', 'msan', 'tsan', 'ubsan'). + code_coverage: True if code coverage is enabled for this build. + absolute_coverage: True if you want to run coverage for all unit tests. + build_args_product: The name of one of the + chromecast/internal/build/args/product files to use for the GN args. + build_args_official: Whether the build is an official build. MUST be set + for any build that will ship to users. Disables debugging; do not set + for development builds. + junit: If True, build junit tests. Otherwise, build gtests (Default False) + **kwargs: Any additional args to pass to BaseStep. + """ + if junit: + step_name = 'build affected junit tests' + else: + step_name = 'build affected gtest unit tests' + cast_shell_step.NonOtaBuildBaseStep.__init__( + self, + step_name, + branding, + build_type, + product, + build_flavor, + sanitizer=sanitizer, + build_args_product=build_args_product, + build_args_official=build_args_official, + **kwargs) + self._enable_assistant = enable_assistant + self._code_coverage = code_coverage + self._absolute_coverage = absolute_coverage + self._junit = junit + self._run_only_affected_tests = ( + self.get_property('build_system') != 'catabuilder' and + branch_utils.is_branch_equal_to_or_later_than(self.manifest_branch, + '1.27')) + self._changed_files = None + + def BuildUnitTests(self): + archive_dir = self.get_gcs_dir() + + build_script = os.path.join( + self.get_project_path('chromecast/internal'), _BUILD_CHROMECAST_SCRIPT) + command = [ + 'python3', build_script, '--archive_dir', archive_dir, + '--build_args_product', self._build_args_product, '--build_number', + self.build_number, '--chrome_root', + self.get_project_path('chromium/src') + ] + command += self.build_accelerator.build_chromecast_flags + + # TODO(b/73231972) remove unused flags once migrated to new builds + if self._build_flavor: + command += ['--build_flavor', self._build_flavor] + if self._build_type: + command += ['--build_type', self._build_type] + if self._branding: + command += ['--chromecast_branding', self._branding] + if self._product: + command += ['--product_name', self._product] + if self._build_args_official: + command += ['--official'] + + command += ['--tests_only'] + + if self.get_property('build_system') == 'catabuilder': + command += ['--enable_gn_check'] + + if self._enable_assistant: + command += ['--enable_assistant'] + + if self._sanitizer: + command += ['--sanitizer', self._sanitizer] + + if self._junit: + command += ['--use_junit'] + + if self._code_coverage: + command += ['--enable_code_coverage'] + + if not self._must_run_all_tests(): + # Run `gn gen` to make sure the out folder exists before `gn refs` is run. + returncode, _, _ = self.exec_subprocess(command + ['--gn_gen_only']) + if returncode != 0: + return returncode + + # Determine which tests are affected and only build those tests. + affected_tests = self._get_affected_tests() + if affected_tests: + logging.info('Building %s tests affected by this change.', + len(affected_tests)) + affected_tests_arg = ','.join(sorted(affected_tests)) + command += ['--whitelisted_tests', affected_tests_arg] + else: + logging.info( + 'Affected test calculation returned no results, will build all ' + 'tests instead.') + + returncode, stdout, _ = self.exec_subprocess(command) + + if returncode != 0: + comments = ninja_utils.ninja_failure_to_comments(stdout, max_errors=3) + for comment in comments: + self.add_review({'message': comment}) + else: + returncode = self.ArchiveUnitTests() + + return returncode + + def _get_unit_test_out_dir(self): + """Generate build-specific out dir name. + + Out dir created by _BUILD_CHROMECAST_SCRIPT in format below: + out_<build_type>_<product>_<gn>[_<sanitizer>] + e.g. out_arm_android_gn for content_shell_udon_arm_debug_gn build. + + Returns: + Path to UnittestStep out dir + """ + out_dir = ['out', self.build_type_dir, self.build_product_dir, 'gn'] + if self._sanitizer: + out_dir.append(self._sanitizer) + return '_'.join(out_dir) + + def ArchiveUnitTests(self, dest_name='test_deps.zip'): # pylint: disable=method-hidden + """Saving build_tests_android.zip to gcs_dir. + + Args: + dest_name: desired archive name after upload. + + Returns: + 0 if succeed, returncode > 0 if failed + """ + # Skip archive step if no build_tests_android.zip expected + # build_tests_android.zip been generated by GetTestDepsTargets in + # chromecast/internal/build/build_chromecast.py + is_android_or_atv = any(product in self._build_args_product + for product in ['cube', 'soba', 'udon', 'atv']) + if not is_android_or_atv or self._junit: + return 0 + out_dir = self._get_unit_test_out_dir() + + archive_path = 'chromium/src/{}/{}/tests/build_tests_android.zip'.format( + out_dir, self.build_flavor_dir) + + # Archive only if build_tests_android.zip was generated + if not os.path.isfile(archive_path): + return 0 + + archive_dir = os.path.join(self.get_gcs_dir(), 'artifacts/tests') + command = ['mkdir', '-p', archive_dir] + returncode, _, _ = self.exec_subprocess(command) + if not returncode: + command = ['cp', archive_path, os.path.join(archive_dir, dest_name)] + returncode, _, _ = self.exec_subprocess(command) + + return returncode + + def _get_changed_files(self): + if self._changed_files is None: + all_patches = [{'project': self.patch_project}] + self.depends_on_list + self._changed_files = git_utils.get_changed_files_in_all_patches( + self, all_patches, self.get_project_path_lookup_table()) + return self._changed_files + + def _must_run_all_tests(self): + """Returns if all the unittests must be ran based on the changed files.""" + + if self._absolute_coverage: + return True + + if not self._run_only_affected_tests: + return True + + for project, patterns in FORCE_RUN_ALL_TESTS_WHITELIST.items(): + for pattern in patterns: + full_pattern = os.path.join(self.get_project_path(project), pattern) + if any(re.search(full_pattern, f) for f in self._get_changed_files()): + return True + + # .gni files can get imported anywhere and cause deps, configs, etc. + # to change. It would be too burdensome to try to find the affected + # targets in this case, so we need to build/run all the tests. + if any(f.endswith('.gni') for f in self._get_changed_files()): + return True + + return False + + def _get_affected_tests(self): + """Return a list of the testing binaries affected by the changed files. + + Uses gn to determine which test binaries are affected. + + Returns: + A set of testing binaries affected by the changed files. + + Raises: + GnUtilsError: If the gn binary cannot be found. + GnExecutionError: If the gn command fails. + """ + + if not self._get_changed_files(): + return set() + + # Non-gn files can be passed to gn refs normally. If a CL modifies a + # BUILD.gn file, then instead pass a GN label that matches against + # all targets in that BUILD.gn file, otherwise GN will effectively + # ignore the file. (e.g. //foo/bar/BUILD.gn -> //foo/bar:*). + gn_refs_targets = [] + for f in self._get_changed_files(): + # Only care about the BUILD.gn files in chromium/src. Some projects + # outside chromium/src also contain BUILD.gn files, + # e.g. <eurekaroot>/external/gwifi/libchrome-cros, which should + # NOT be considered to affect unit tests + if f.endswith('BUILD.gn') and f.startswith('chromium/src'): + gn_refs_targets.append(gn_utils.filepath_to_gn_path(f)) + else: + gn_refs_targets.append(f) + + gn_binary = gn_utils.get_gn_binary(self) + + is_android_or_atv = any(product in self._build_args_product + for product in ['cube', 'soba', 'udon', 'atv']) + if is_android_or_atv: + return self._get_android_affected_tests(gn_binary) + + return self._get_linux_affected_tests(gn_binary, gn_refs_targets) + + def _get_linux_affected_tests(self, gn_binary, targets): + # If there's just way too many targets then just use all unit tests + # otherwise we could be waiting a very long time calculating that we + # do, in fact, need to run all the unit tests + if len(targets) > MAX_TARGETS_FOR_ALL_TESTS: + command = [ + gn_binary, 'refs', + '--root={}'.format(self.get_project_path('chromium/src')), + self._outdir, '--testonly=true', '--as=output', '--type=executable', + '--all', '-q', '*' + ] + else: + # The non-android test templates generate normal test executables, so + # look for those. + targets_str = '\n'.join(targets + ['']) + tmp_file_path = self.write_temp_file(targets_str) + + command = [ + gn_binary, 'refs', + '--root={}'.format(self.get_project_path('chromium/src')), + self._outdir, '--testonly=true', '--as=output', '--type=executable', + '--all', '-q', '@' + tmp_file_path + ] + + returncode, stdout, _ = self.exec_subprocess(command) + + if returncode != 0: + raise GnExecutionError( + 'Could not determine the tests affected by this change.') + + return set(test.strip() for test in stdout.splitlines() if test.strip()) + + def _get_android_affected_tests(self, gn_binary): + + # Determining affected tests for Android builds has been non-deterministic. + # (b/145934413, b/132997084, etc.) allowing breaking changes through + # presubmit. Until that is fixed, always run all test suites. + command = [ + gn_binary, 'refs', + '--root={}'.format(self.get_project_path('chromium/src')), self._outdir, + '--testonly=true', '--as=label', + '--type={}'.format('group' if self._junit else 'action'), '--all', '-q', + '*' + ] + + returncode, stdout, _ = self.exec_subprocess(command) + + if returncode != 0: + raise GnExecutionError( + 'Could not determine the tests affected by this change.') + + # Convert each label returned in |stdout| to a GN target name. Some of the + # labels are legitimate test targets, but many are intermediate targets + # which are internal details of GN templates. Do some basic filtering to + # cut the list down. The rest will be filtered by the cast_test_list. + return set( + gn_utils.gn_label_to_target_name(label.strip()) + for label in stdout.splitlines() + if label.strip() and '__' not in label) + + def run(self): + """Builds unittests. + + Returns: + True iff there were no errors. + """ + returncode = self.BuildUnitTests() + + if returncode != 0: + return False + + run_test_list = ( + RUN_JUNIT_TEST_LIST_PATH if self._junit else RUN_TEST_LIST_PATH) + step_data_key = ( + STEP_DATA_JUNIT_TEST_LIST if self._junit else STEP_DATA_TEST_LIST) + + # Load the tests to be run. + test_list = self.exec_read_file(os.path.join(self._outdir, + run_test_list)).splitlines() + + # Load the tests affected by this set of patches. + try: + affected_tests = self._get_affected_tests() + except gn_utils.GnUtilsError as e: + self.add_review({'message': str(e)}) + return False + except RuntimeError as e: + self.add_review({'message': str(e)}) + return False + + if not self._must_run_all_tests() and affected_tests: + # Filter the test list for tests that are affected by the changed files + # and save this in step data. + test_list = [ + test_cmd for test_cmd in test_list + if test_cmd.split()[0] in affected_tests + ] + self.add_step_data(step_data_key, test_list) + + return True + + +class RunAffectedUnitTestsStep(cast_shell_step.NonOtaBuildBaseStep): + """Build step class for running x86 unit tests, if any.""" + + def __init__(self, + branding, + build_type, + product, + build_flavor, + report_url, + recipe_steps, + sanitizer=None, + build_args_product=None, + build_args_official=None, + junit=False, + enable_network_service=False, + **kwargs): + """Instantiate the class. + + Args: + branding: Build branding (chromium or chrome). + build_type: Type of system to build for ('x86', 'clang', or 'arm'). + product: product to build for (ie. 'chromecast', 'audio'). + build_flavor: Flavor of build ('Debug', 'Eng', 'Release'). + report_url: The URL the code coverage report can be accessed at. + recipe_steps: Reference to the list of steps for this recipe. + sanitizer: Clang saniziter to run with ('asan', 'msan', 'tsan', 'ubsan'). + build_args_product: The name of one of the + chromecast/internal/build/args/product files to use for the GN args. + junit: If true, run junit tests, otherwise run gtests (Default False). + enable_network_service: If true, include --enable-features=NetworkService + **kwargs: Any additional args to pass to BaseStep. + """ + if junit: + step_name = 'run affected junit tests' + else: + step_name = 'run affected gtest unit tests' + cast_shell_step.NonOtaBuildBaseStep.__init__( + self, + step_name, + branding, + build_type, + product, + build_flavor, + sanitizer=sanitizer, + build_args_product=build_args_product, + build_args_official=build_args_official, + **kwargs) + + assert isinstance(report_url, six.string_types) + assert isinstance(recipe_steps, list) + assert build_args_product + + self._report_url = report_url + self._recipe_steps = recipe_steps + self._junit = junit + self._enable_network_service = enable_network_service + self._step_kwargs = kwargs + + # Index to insert new steps at. This is to make sure that different steps that + # are included after the RunAffectedUnitTestsStep actually run after it, + # rather than the new steps being appended after them. + self._insert_index = None + + def get_report_dir(self): + """Returns a unit test result directory.""" + report_dir = os.path.join(self.get_gcs_dir(), UNIT_TEST_REPORT_PATH) + if not os.path.isdir(report_dir): + os.mkdir(report_dir) + return report_dir + + def get_gtest_xml_log_uri(self, test_name): + """Returns a unit test xml log uri for the given gtest.""" + return '{}/test_detail_{}.xml'.format(self.get_report_dir(), test_name) + + def get_gtest_step(self, test_name, test_command): + """Returns a step that runs the unit test executable.""" + if self._sanitizer: + return sanitizer_unittest_step.SanitizerUnitTestShellStep( + name=test_name, + command=test_command, + directory=self._outdir, + sanitizer=self._sanitizer, + **self._step_kwargs) + + return shell_step.ShellStep( + name=test_name, + command=test_command, + directory=self._outdir, + **self._step_kwargs) + + def get_junit_step(self, test_name): + """Returns a step that runs a junit test.""" + return self.get_android_runner_step(test_name, 'junit') + + def get_android_runner_step(self, test_name, test_type): + """Returns a step that runs an android test.""" + test_runner = self._get_test_runner() + pythonpath = self._get_python_path() + # Single device, should be single test. + wrapper_command = [ + 'python3', + test_runner, + '--debug', # Dumps test output to stdout. + '--type', + test_type, + '--test_result_dir', + self.get_gcs_dir(), + '--unit_test_binary_dir', + self._outdir, + '--unittest_name', + test_name + ] + return shell_step.ShellStep( + name=test_name, + command=wrapper_command, + directory='', + env={'PYTHONPATH': pythonpath}, + **self._step_kwargs) + + def get_json_step(self, test_name): + """Returns a step that generates test_result.json from existing xml.""" + report_dir = self.get_report_dir() + test_project_dir = self.get_project_path(ANDROID_TEST_RUNNER_PROJECT) + xml_to_json = os.path.join(test_project_dir, TRANSFORM_XML_TO_JSON_PATH) + wrapper_command = [ + 'python3', xml_to_json, '--xml_dir_path', report_dir, '--branch_name', + self.manifest_branch, '--build_number', self.build_number, + '--test_name', test_name + ] + # TODO(b/73231972) remove unused flags once migrated to new builds + if self._build_flavor and self._product: + wrapper_command += [ + '--build_flavor', + self._build_flavor, + '--product_name', + self._product, + ] + else: + wrapper_command += [ + '--build_args_product', + self._build_args_product, + ] + return shell_step.ShellStep( + name='summary json for {}'.format(test_name), + command=wrapper_command, + directory='', + env={'PYTHONPATH': test_project_dir}, + **self._step_kwargs) + + def _add_step_to_recipe_steps(self, step): + if self._insert_index is None: + self._insert_index = self._recipe_steps.index(self) + 1 + + self._recipe_steps.insert(self._insert_index, step) + self._insert_index += 1 + + def add_gtest_tests(self): + test_list = self.get_step_data(STEP_DATA_TEST_LIST) + + for test_exec_text in test_list: + test_command = test_exec_text.split(' ') + test_name = test_command[0] + test_command[0] = './' + test_name + if (self._enable_network_service and + branch_utils.is_branch_equal_to_or_later_than(self.manifest_branch, + '1.41')): + test_command.append( + '--enable-features=NetworkService,NetworkServiceInProcess') + # TODO(b/130182642): Re-enable these tests once Chromium supports + # network service in unit tests. + disabled_tests = (':CastDevToolsManagerDelegateTest.*' + ':CastMediaBlockerTest.*' + ':CastSessionIdMapTest.*') + for i, part in enumerate(test_command): + if part.startswith('--gtest_filter=-'): + test_command[i] = part + disabled_tests + break + if i == len(test_command) - 1: + test_command.append('--gtest_filter=-' + disabled_tests) + + test_command.append('--gtest_output=xml:{}'.format( + self.get_gtest_xml_log_uri(test_name))) + self._add_step_to_recipe_steps( + self.get_gtest_step(test_name, test_command)) + + self._add_step_to_recipe_steps(self.get_json_step('unit_test')) + + def add_junit_tests(self): + test_list = self.get_step_data(STEP_DATA_JUNIT_TEST_LIST) + for test_exec_text in test_list: + test_name = test_exec_text.split(' ')[0] + self._add_step_to_recipe_steps(self.get_junit_step(test_name)) + + def _get_test_runner(self): + test_project_dir = self.get_project_path(ANDROID_TEST_RUNNER_PROJECT) + return os.path.join(test_project_dir, ANDROID_TEST_RUNNER_PATH) + + def _get_python_path(self): + test_project_dir = self.get_project_path(ANDROID_TEST_RUNNER_PROJECT) + return ':'.join( + [test_project_dir, + self.get_project_path('continuous-tests')]) + + def run(self): + """Adds a separate step for each Chromium test case to be executed. + + Returns: + True, it shouldn't be possible for this step to fail. + """ + + original_step_count = len(self._recipe_steps) + if self._junit: + self.add_junit_tests() + else: + self.add_gtest_tests() + new_steps_count = len(self._recipe_steps) - original_step_count + if new_steps_count: + logging.info('Running %s tests affecting this change.', new_steps_count) + else: + logging.info('No affected tests were detected for this change. None ' + 'will be run.') + + return True
diff --git a/cq/scripts/slave/step/x86_camera_step.py b/cq/scripts/slave/step/x86_camera_step.py new file mode 100644 index 0000000..c065d1b --- /dev/null +++ b/cq/scripts/slave/step/x86_camera_step.py
@@ -0,0 +1,463 @@ +from __future__ import absolute_import +import os +import re +import collections + +from slave import base_step +from slave.step import code_coverage_step + +BUILD_VARIANT = 'eng' + +TARGET_PRODUCT = { + 'gq': 'gq_x86_64', + 'newman': 'newman_x86_64', + 'nq': 'nq_x86_64', + 'nq_exp': 'nq_exp_x86_64', + 'spencer': 'spencer_x86_64', + 'venus': 'venus_x86_64', +} + +BUILD_ITEM = { + 'gq': ['curl', 'nldaemon', 'nldaemon-cli', 'chromium-iot'], + 'newman': 'reconnect-tests', + 'nq': ['curl', 'nldaemon', 'nldaemon-cli', 'chromium-iot'], + 'nq_exp': ['curl', 'nldaemon', 'nldaemon-cli', 'chromium-iot', + 'libcast_camera_hal', 'libamvenc_api_c328', 'libdma_api_c328', + 'libcutils'], + 'spencer': ['curl', 'nldaemon', 'nldaemon-cli', 'chromium-iot'], + 'venus': ['curl', 'nldaemon', 'nldaemon-cli', 'chromium-iot'], + 'iot-tests': 'chromium-iot-tests' +} + +_MAKE_ERROR_PATTERN = ( + r'^(?P<filename>[^:]+):(?P<linenum>\d+):(?P<column>\d+): ' + 'error: (?P<err_msg>.*)$', + r'^(?P<filename>[^\-]+)-(?P<linenum>\d+): error: (?P<err_msg>.*)$', +) + +IOT_TESTS_LIST = 'tests/iot/run_test_list.txt' + +OUT_DIR = 'out/target/product/newman_x86_64/system/bin' +NCCM_OUT_DIR = 'chromium/src/out/Release/' +NCCM_BUILD_ITEM = os.path.join("chromecast/internal/iot_services", + "nestcam_context_manager:nccm_unittests") + +PHOTON_OUT_DIR = 'chromium/src/out/Release/' +PHOTON_BUILD_ITEMS = [ os.path.join("chromecast/internal/iot_services", + "photon_hal:photon_hal_group"), + os.path.join("chromecast/internal/iot_services", + "photon_hal:photon_hal_tests") ] + +SIM_SYSTEM = [ + "out/target/product/{}/system/bin/", + "out/target/product/{}/system/etc/", + "out/target/product/{}/system/lib/", + "out/target/product/{}/symbols/system/chrome/bin/", + "out/target/product/{}/symbols/system/chrome/lib/", +] +SIM_LIB = [ + "chromium/src/build/linux/debian_sid_amd64-sysroot/usr/lib/x86_64-linux-gnu/", + os.path.join("chromium/src/build/linux/debian_sid_amd64-sysroot/lib", + "x86_64-linux-gnu/libcom_err.so.2.1"), + os.path.join("chromium/src/build/linux/debian_sid_amd64-sysroot/lib", + "x86_64-linux-gnu/libkeyutils.so.1.9"), + os.path.join("chromium/src/third_party/android_ndk/toolchains/llvm/prebuilt", + "linux-x86_64/lib64/libc++.so.1"), +] +SIM_CONFIG = "virtual-home/cirque-park/build_eureka/{}/" +MOJO_EVENTS = "virtual-home/cirque-park/build_eureka/mojo_events/" +SAMPLE_VIDEO = "vendor/nest/reconnect/data/test/proxy_video.h264" +SAMPLE_AUDIO = "vendor/nest/reconnect/data/test/proxy_audio_mono.opus" +SAMPLE_JPEG = "vendor/nest/reconnect/data/test/{}_sample.jpeg" + +CODE_COVERAGE_GN_ARGS = 'use_clang_coverage=true is_component_build=false' + +def make_error_to_comments(stderr, directory): + """ + parse stderr with regex error pattern and return comments dict + Args: + stderr (str): logs from stderr + Return: + (dict) comments: { + "filename": + { "linenum": <int>, + "message": <str> error message, + } + } + """ + comments = collections.defaultdict(list) + + for line in stderr.splitlines(): + match = [m for m in [ + re.match(err_pat, line) for err_pat in _MAKE_ERROR_PATTERN + ] if m is not None] + if match: + match = match[0] + filename = match.group('filename') + if directory and filename.startswith(directory): + filename = filename[len(directory) + len(os.path.sep):] + linenum = int(match.group('linenum')) + comments[filename].append({'line': linenum, 'message': line}) + return comments + + +class MakeCleanSim(base_step.BaseStep): + + def __init__(self, **kwargs): + self.product = kwargs['product'] + base_step.BaseStep.__init__(self, + name='make clean x86_64 {}'.format( + self.product.upper()), + halt_on_failure=True, + **kwargs) + + def run(self): + + command = [ + 'make', + 'TARGET_PRODUCT={}'.format(TARGET_PRODUCT[self.product]), + 'TARGET_BUILD_VARIANT={}'.format(BUILD_VARIANT), + 'clean' + ] + returncode, _, stderr = self.exec_subprocess(command) + if returncode != 0: + comment = make_error_to_comments(stderr, '') + self.add_review({ + 'comments': comment + }) + return False + + return True + + +class BuildSimulatorStep(base_step.BaseStep): + + def __init__(self, code_coverage=False, **kwargs): + self.product = kwargs['product'] + self._code_coverage = code_coverage + base_step.BaseStep.__init__(self, + name='build x86_64 {}'.format( + self.product.upper()), + halt_on_failure=True, + **kwargs) + + def run(self): + command = [ + 'make', + '-j{}'.format(self.get_num_jobs()), + 'TARGET_PRODUCT={}'.format(TARGET_PRODUCT[self.product]), + 'TARGET_BUILD_VARIANT={}'.format(BUILD_VARIANT) + ] + + if self._code_coverage: + command.append( + 'COMMAND_LINE_GN_ARGS=\'{}\''.format(CODE_COVERAGE_GN_ARGS)) + + command += self.build_accelerator.make_flags + command += BUILD_ITEM[self.product] + returncode, _, stderr = self.exec_subprocess(command) + if returncode != 0: + comment = make_error_to_comments(stderr, '') + self.add_review({ + 'comments': comment + }) + return False + return True + + +class CreateSimTarStep(base_step.BaseStep): + + def __init__(self, **kwargs): + self.product = kwargs['product'] + base_step.BaseStep.__init__(self, + name='tar-ing sim artifacts', + halt_on_failure=True, + **kwargs) + + def run(self): + tar_filename = '{}.tar.gz'.format(TARGET_PRODUCT[self.product]) + command = [ + 'tar', + 'czf', + os.path.join(self.get_gcs_dir(), tar_filename), + SIM_CONFIG.format("{}_x86".format(self.product)), + MOJO_EVENTS, + SAMPLE_VIDEO, + SAMPLE_AUDIO, + SAMPLE_JPEG.format(self.product) + ] + command += [path.format(TARGET_PRODUCT[self.product]) for path in SIM_SYSTEM] + command += SIM_LIB + returncode, _, stderr = self.exec_subprocess(command) + if returncode != 0: + comment = make_error_to_comments(stderr, '') + self.add_review({ + 'comments': comment + }) + else: + self.set_build_property('ota_files', [tar_filename]) + + return True + + +class BuildChromiumIotTestsStep(base_step.BaseStep): + + def __init__(self, code_coverage=False, **kwargs): + self.product = kwargs['product'] + self.out_dir = kwargs['out_dir'] + self._code_coverage = code_coverage + base_step.BaseStep.__init__(self, + name='build chromium-iot-tests', + halt_on_failure=True, + **kwargs) + + def run(self): + + command = [ + 'make', + '-j{}'.format(self.get_num_jobs()), + 'TARGET_PRODUCT={}'.format(TARGET_PRODUCT[self.product]), + 'TARGET_BUILD_VARIANT={}'.format(BUILD_VARIANT), + '{}'.format(BUILD_ITEM['iot-tests']) + ] + + if self._code_coverage: + command.append( + 'COMMAND_LINE_GN_ARGS=\'{}\''.format(CODE_COVERAGE_GN_ARGS)) + + command += self.build_accelerator.make_flags + + returncode, _, stderr = self.exec_subprocess(command) + if returncode != 0: + comment = make_error_to_comments(stderr, '') + self.add_review({ + 'comments': comment + }) + return False + + test_list = self.exec_read_file( + os.path.join(self.out_dir, IOT_TESTS_LIST)).splitlines() + self.add_step_data(code_coverage_step.STEP_DATA_TEST_LIST, test_list) + return True + + +class RunChromiumIotTestsStep(base_step.BaseStep): + + def __init__(self, **kwargs): + self.cwd = kwargs['cwd'] + self.product = kwargs['product'] + base_step.BaseStep.__init__(self, + name='run chromium-iot-tests', + halt_on_failure=True, + **kwargs) + def get_commands(self): + commands = [] + with open(os.path.join(self.cwd, IOT_TESTS_LIST), 'r') as f: + for line in f: + commands.append(["./{}".format(line.rstrip())]) + return commands + + def run(self): + commands = self.get_commands() + env = { + 'LD_LIBRARY_PATH': ":".join( + ['../../../../prebuilt/toolchain/x86_64/usr/lib64', + os.path.join('../../../../out/target/product', + '{}/system/lib'.format(TARGET_PRODUCT[self.product])) + ]) + } + for command in commands: + returncode, _, _ = self.exec_subprocess(command, cwd=self.cwd, env=env) + # return early if any unittest fails + if returncode != 0: + return False + return True + + +class BuildReconnectProxyTestStep(base_step.BaseStep): + + def __init__(self, **kwargs): + self.product = kwargs['product'] + base_step.BaseStep.__init__(self, + name='build reconnect-tests', + halt_on_failure=True, + **kwargs) + + def run(self): + + command = [ + 'make', + '-j{}'.format(self.get_num_jobs()), + 'TARGET_PRODUCT={}'.format(TARGET_PRODUCT[self.product]), + 'TARGET_BUILD_VARIANT={}'.format(BUILD_VARIANT), + '{}'.format(BUILD_ITEM[self.product]) + ] + returncode, _, stderr = self.exec_subprocess(command) + if returncode != 0: + comment = make_error_to_comments(stderr, '') + self.add_review({ + 'comments': comment + }) + return False + return True + + +class RunReconnectTestsStep(base_step.BaseStep): + + def __init__(self, **kwargs): + base_step.BaseStep.__init__(self, + name='run reconnect-tests', + halt_on_failure=True, + **kwargs) + + def run(self): + + command = [ + './{}'.format(os.path.join(OUT_DIR, 'reconnect-tests')) + ] + returncode, _, _ = self.exec_subprocess(command) + return returncode == 0 + + +class BuildNccmUnitTestStep(base_step.BaseStep): + + def __init__(self, **kwargs): + self.out_dir = kwargs.get('out_dir', NCCM_OUT_DIR) + base_step.BaseStep.__init__(self, + name='build nccm_unittests', + halt_on_failure=True, + **kwargs) + + def run(self): + + command = [ + 'autoninja', + '-C', + self.out_dir, + NCCM_BUILD_ITEM + ] + returncode, _, stderr = self.exec_subprocess(command) + if returncode != 0: + comment = make_error_to_comments(stderr, '') + self.add_review({ + 'comments': comment + }) + return False + + self.add_step_data( + code_coverage_step.STEP_DATA_TEST_LIST, ['nccm_unittests']) + return True + + +class RunNccmUnitTestStep(base_step.BaseStep): + + def __init__(self, **kwargs): + self.out_dir = kwargs['out_dir'] + base_step.BaseStep.__init__(self, + name='run nccm_unittests', + halt_on_failure=True, + **kwargs) + + def run(self): + + command = [ + ('./{}').format(os.path.join(self.out_dir, 'nccm_unittests'))] + returncode, _, _ = self.exec_subprocess(command) + return returncode == 0 + + +class BuildAndRunNldaemonUnitTestStep(base_step.BaseStep): + + def __init__(self, **kwargs): + self.product = kwargs['product'] + super().__init__( + name='run nldaemon_unittests', + halt_on_failure=True, + **kwargs, + ) + + def run(self): + if self.product != 'gq': + # gq_x86_64 is experimental as of 2020-Dec-17 + # Not blocking others if the tests fails. + return True + + # We need to do a clean build so the coverage data can be generated correctly. + command = [ + 'make', + 'TARGET_PRODUCT={}'.format(TARGET_PRODUCT[self.product]), + 'TARGET_BUILD_VARIANT={}'.format(BUILD_VARIANT), + 'clean' + ] + returncode, _, stderr = self.exec_subprocess(command) + if returncode != 0: + comment = make_error_to_comments(stderr, '') + self.add_review({ + 'comments': comment + }) + return False + + env = { + 'LD_LIBRARY_PATH': ":".join( + [os.path.join('chromium/src/third_party/android_ndk', + 'toolchains/llvm/prebuilt/linux-x86_64/lib64'), + os.path.join('out/target/product', + '{}/system/lib'.format(TARGET_PRODUCT[self.product])) + ]) + } + command = [ + 'make', + '-j{}'.format(self.get_num_jobs()), + 'ENABLE_CODE_COVERAGE=1', + 'TARGET_PRODUCT={}'.format(TARGET_PRODUCT[self.product]), + 'TARGET_BUILD_VARIANT={}'.format(BUILD_VARIANT), + 'nldaemon_unittests_run' + ] + returncode, _, stderr = self.exec_subprocess(command, env=env) + if returncode != 0: + comment = make_error_to_comments(stderr, '') + self.add_review({ + 'comments': comment + }) + return False + return True + +class BuildPhotonStep(base_step.BaseStep): + + def __init__(self, **kwargs): + self.out_dir = kwargs.get('out_dir', PHOTON_OUT_DIR) + base_step.BaseStep.__init__(self, + name='build photon', + halt_on_failure=True, + **kwargs) + + def run(self): + command = [ + 'autoninja', + '-C', + self.out_dir + ] + command += PHOTON_BUILD_ITEMS + returncode, _, stderr = self.exec_subprocess(command) + if returncode != 0: + comment = make_error_to_comments(stderr, '') + self.add_review({ + 'comments': comment + }) + return False + return True + +class RunPhotonUnitTestStep(base_step.BaseStep): + + def __init__(self, **kwargs): + self.out_dir = kwargs['out_dir'] + base_step.BaseStep.__init__(self, + name='run photon_hal_tests', + halt_on_failure=True, + **kwargs) + + def run(self): + command = [ + ('./{}').format(os.path.join(self.out_dir, 'photon_hal_tests'))] + returncode, _, _ = self.exec_subprocess(command) + return returncode == 0
diff --git a/cq/scripts/slave/step/x86_cast_camera_hal_step.py b/cq/scripts/slave/step/x86_cast_camera_hal_step.py new file mode 100644 index 0000000..9309854 --- /dev/null +++ b/cq/scripts/slave/step/x86_cast_camera_hal_step.py
@@ -0,0 +1,166 @@ +from __future__ import absolute_import +import collections +import logging +import os +import re +import shutil + +from slave import base_step + +BUILD_VARIANT = 'eng' + +TARGET_PRODUCT = { + 'nq': 'nq_exp_x86_64', +} + +TEST_TARGET = 'cast_camera_hal_host_test' + +MAKE_ERROR_PATTERN = ( + r'^(?P<filename>[^:]+):(?P<linenum>\d+):(?P<column>\d+): ' + 'error: (?P<err_msg>.*)$', + r'^(?P<filename>[^\-]+)-(?P<linenum>\d+): error: (?P<err_msg>.*)$', +) + +OUT_DIR = 'out/host/linux-x86/bin' + +def make_error_to_comments(stderr, directory): + """ + parse stderr with regex error pattern and return comments dict + Args: + stderr (str): logs from stderr + Return: + (dict) comments: { + "filename": + { "linenum": <int>, + "message": <str> error message, + } + } + """ + comments = collections.defaultdict(list) + + for line in stderr.splitlines(): + match = [m for m in [ + re.match(err_pat, line) for err_pat in MAKE_ERROR_PATTERN + ] if m is not None] + if match: + match = match[0] + filename = match.group('filename') + if directory and filename.startswith(directory): + filename = filename[len(directory) + len(os.path.sep):] + linenum = int(match.group('linenum')) + comments[filename].append({'line': linenum, 'message': line}) + return comments + +class BuildCastCameraHalTestStep(base_step.BaseStep): + + def __init__(self, **kwargs): + base_step.BaseStep.__init__(self, + name='build {}'.format(TEST_TARGET), + halt_on_failure=True, + **kwargs) + + def run(self): + + # TODO(b/240648405): remove TARGET_PRODUCT flag + command = [ + 'make', + '-j{}'.format(self.get_num_jobs()), + 'TARGET_PRODUCT={}'.format(TARGET_PRODUCT['nq']), + 'TARGET_BUILD_VARIANT={}'.format(BUILD_VARIANT), + '{}'.format(TEST_TARGET) + ] + returncode, _, stderr = self.exec_subprocess(command) + if returncode != 0: + comment = make_error_to_comments(stderr, '') + self.add_review({ + 'comments': comment + }) + return False + + return True + +class RunCastCameraHalTestStep(base_step.BaseStep): + + def __init__(self, **kwargs): + base_step.BaseStep.__init__(self, + name='run {}'.format(TEST_TARGET), + halt_on_failure=True, + **kwargs) + + def run(self): + + command = [ + './{}'.format(os.path.join(OUT_DIR, TEST_TARGET)) + ] + returncode, _, _ = self.exec_subprocess(command) + return returncode == 0 + +class InstallCoverageTools(base_step.BaseStep): + + def __init__(self, **kwargs): + base_step.BaseStep.__init__(self, + name="install coverage tools", + halt_on_failure=True, + **kwargs) + def run(self): + # python3 chromium/src/tools/clang/scripts/update.py --package \ + # coverage_tools + vpython3_path = os.path.join( + self.get_project_path('chromium/tools/depot_tools'), 'vpython3') + update_py_path = os.path.join( + self.get_project_path('chromium/src'), 'tools/clang/scripts/update.py') + command = [vpython3_path, update_py_path, '--package', 'coverage_tools'] + returncode, _, _ = self.exec_subprocess(command) + return returncode == 0 + +class CollectCameraHalTestCoverageStep(base_step.BaseStep): + + def __init__(self, **kwargs): + base_step.BaseStep.__init__(self, + name="generate coverage data", + halt_on_failure=True, + **kwargs) + + def run(self): + # generate coverage report + eureka_dir = os.getcwd() + output_dir = os.path.join(eureka_dir, 'code_coverage_html','linux') + make_output_dir_command = ['mkdir', '-p', output_dir] + returncode, _, _ = self.exec_subprocess(make_output_dir_command) + if returncode != 0: + self.add_review({ + 'comments': 'Failed to create output directory: {}'.format(output_dir) + }) + return False + + cast_camera_hal_dir = os.path.join(eureka_dir, + 'hardware', + 'cast-camera-hal') + cast_camera_hal_test_dir = os.path.join(cast_camera_hal_dir, + 'test') + coverage_collecting_script = os.path.join(cast_camera_hal_test_dir, + 'analyze-test-coverage.sh') + manifest_file = os.path.join(cast_camera_hal_test_dir, + 'camera-hal-host-coverage-manifest.txt') + + collect_coverage_data_command = [ + '{}'.format(coverage_collecting_script), + '-u{}'.format(cast_camera_hal_dir), + '-b{}'.format(eureka_dir), + '-g{}'.format(manifest_file), + '-o{}'.format(output_dir) + ] + + returncode, _, _ = self.exec_subprocess( + collect_coverage_data_command, + env={"ANDROID_BUILD_TOP": eureka_dir}) + + try: + copied_report_dir = os.path.join(self.get_gcs_dir(), 'code_coverage_html') + shutil.copytree(output_dir, copied_report_dir) + out_files = os.listdir(copied_report_dir) + logging.info('Generated files: %s', str(out_files)) + except IOError: + logging.warning('Failed to copy coverage output to GCS') + + return returncode == 0
diff --git a/cq/scripts/slave/step/x86_integration_test_step.py b/cq/scripts/slave/step/x86_integration_test_step.py new file mode 100644 index 0000000..8e804e7 --- /dev/null +++ b/cq/scripts/slave/step/x86_integration_test_step.py
@@ -0,0 +1,221 @@ +"""Step class to run tests against a local x86 cast shell.""" + +from __future__ import absolute_import +import datetime +import glob +import json +import logging +import os +import time +import traceback + +from helpers import cast_shell_utils +from helpers import py_env_utils +from slave import base_step + +_FRAGGLE_ROCK_CONFIG_FILES_ENV_VAR = 'FRAGGLE_ROCK_CONFIG_FILES' +_LOG_DIR = 'integration_test_logs' + + +# pylint: disable=method-hidden + + +class RunIntegrationTestStep(base_step.BaseStep): + """Step for running integration test against a local x86 cast shell.""" + + def __init__(self, test_case_class, test_case_module, test_sequence_class, + test_sequence_module, test_config_file_path, + device_class='LocalX86CastShellDevice', + device_module='eurtest.device.local_x86_cast_shell_device', + assistant_enabled=False, + headless=False, + debug_output=True, + **kwargs): + """Creates a RunIntegrationTestStep instance. + + Args: + test_case_class: A list of TestCase implementations to run. Each TestCase + class is expected to be defined in the test_case_module. + test_case_module: Module containing TestCase implementation to run. + test_sequence_class: TestSequence implementation to run. + test_sequence_module: Module containing TestSequence implementation to + run. + test_config_file_path: Dot-notation path to the test's config file + relative to config_file_root_dir. + device_class: A string with the name of Python class that represents the + device. + device_module: Dot-notation path to the module containing |device_class|. + assistant_enabled: Whether the x86 cast_shell against which tests will + be run is assistant-enabled (in which case, some special flags are + specified with the cast_shell is started). + headless: Whether the x86 cast_shell uses headless ozone platform. + debug_output: Log debug output from the test. + **kwargs: Any additional args to pass to BaseStep. + """ + base_step.BaseStep.__init__(self, name='Run integration tests', **kwargs) + self._test_case_class = test_case_class + self._test_case_module = test_case_module + self._test_sequence_class = test_sequence_class + self._test_sequence_module = test_sequence_module + self._test_config_file_path = test_config_file_path + self._device_class = device_class + self._device_module = device_module + self._device_ip = '127.0.0.1' + self._config_file_root_dir = os.path.join( + self.get_project_path('continuous-tests'), 'lab_system', 'master', + 'config') + self._assistant_enabled = assistant_enabled + self._headless = headless + self._debug_output = debug_output + + def _remove_existing_results_json(self): + """Remove any results JSON files from previous runs.""" + previous_results = glob.glob(os.path.join(os.getcwd(), '*results.json')) + for result_found in previous_results: + os.remove(result_found) + + def _execute_tests(self, venv_root): + """Execute the integration tests using eurtest.framework.test_runner. + + Args: + venv_root: Path to virtual environment root directory. + + Returns: + A Tuple of (a dict representing a review object, + a boolean indicating if tests passed) + """ + self._remove_existing_results_json() + + short_wait_secs = 5 + env = { + _FRAGGLE_ROCK_CONFIG_FILES_ENV_VAR: self._config_file_root_dir, + 'PYTHONPATH': self._get_python_path() + } + runner = os.path.abspath( + os.path.join(self.get_project_path('test'), + 'eurtest', 'framework', 'test_runner.py')) + run_info = {} + run_info['start_timestamp'] = datetime.datetime.now().isoformat() + run_info['branch_name'] = self.manifest_branch + run_info['platform'] = 'clang_x86' + cmd = [ + runner, + '--test_case_class', ','.join(self._test_case_class), + '--test_case_module', self._test_case_module, + '--test_sequence_class', self._test_sequence_class, + '--test_sequence_module', self._test_sequence_module, + '--target_device_ethernet_ip', self._device_ip, + '--target_device_wifi_ip', self._device_ip, + '--device_class', self._device_class, + '--device_module', self._device_module, + '--run_information_json', json.dumps(run_info), + '--test_config_file_path', self._test_config_file_path, + '--nouse_tunnel' + ] + if self._debug_output: + cmd.append('--debug') + returncode, stdout, stderr = py_env_utils.exec_within_virtual_env( + self, venv_root, cmd, env=env) + if returncode != 0: + logging.error('Failed to run tests: %s\n%s', stdout, stderr) + + review = ({'message': 'no result found'}, False) + # A JSON file will be saved to results_path directory within a few seconds + time.sleep(short_wait_secs) + results = glob.glob(os.path.join(os.getcwd(), '*results.json')) + if results: + # Assumption: there should be only one results JSON file + review = self.generate_review(results[0]) + return review + + def generate_review(self, results): + """Generate a review object from integration test results. + + Args: + results: File path to result JSON file. + + Returns: + A Tuple of (a dict representing a review object, + a boolean indicating if tests passed) + """ + passing = True + result_messages = [] + results_data = [] + summary = 'Suites: {}, Run: {}, Errors: {}, Failures: {}' + with open(results) as results_json: + json_output = json.load(results_json) + if isinstance(json_output, list): + results_data.extend(json_output) + else: + results_data.append(json_output) + for result in results_data: + suite_count = 0 + test_count = 0 + failure_count = 0 + error_count = 0 + for suite in result['test_suites']: + suite_count += 1 + test_count += suite['test_count'] + failure_count += suite['failure_count'] + error_count += suite['error_count'] + if failure_count + error_count > 0: + message = ('Test: {}, {}, Time Taken(sec): {:.2f}').format( + result['test_name'], + summary.format(suite_count, test_count, error_count, failure_count), + result['elapsed_secs']) + result_messages.append(message) + passing = False + if passing: + status = 'Looks Good. All tests passed.' + else: + status = 'Cast compliance tests failed. See the build logs for details.' + review = { + 'message': ('{} \n{}'.format(status, '\n'.join(result_messages))) + } + return review, passing + + def _get_python_path(self): + """Returns the PYTHONPATH to execute tests with.""" + projects = ['test', 'continuous-tests'] + python_paths = [ + os.path.abspath(self.get_project_path(project)) for project in projects] + return os.pathsep.join(python_paths) + + def run(self): + """Starts a local x86 cast shell and run integration tests against it. + + Returns: + True iff all tests pass. + """ + log_fd = None + log_file_path = None + try: + # Launch cast_shell + _, log_fd, log_file_path = cast_shell_utils.start_cast_shell( + self, + self.get_project_path('test'), + self.get_step_data(cast_shell_utils.CAST_SHELL_EXE_PATH), + self.get_tmp_dir(), + enable_cma_media_pipeline=True, + use_headless_ozone_platform=( + self._headless or self._assistant_enabled), + launch_utility_process=self._assistant_enabled) + venv_root = self.get_step_data('virtual_env_root') + review_message, is_passing = self._execute_tests(venv_root) + except: # pylint: disable=bare-except + review_message = { + 'message': ('Cast compliance test setup failed.\n{}'.format( + traceback.format_exc())) + } + is_passing = False + + if log_fd and log_file_path: + cast_shell_utils.upload_cast_shell_logs(log_fd, + log_file_path, + self.get_gcs_dir(), _LOG_DIR, + 'cast_shell_console.txt') + if not is_passing: + self.add_review(review_message) + else: + logging.info(review_message.get('message')) + return is_passing
diff --git a/cq/scripts/slave/step/x86_manhattan_test_integration_step.py b/cq/scripts/slave/step/x86_manhattan_test_integration_step.py new file mode 100644 index 0000000..f7d81f5 --- /dev/null +++ b/cq/scripts/slave/step/x86_manhattan_test_integration_step.py
@@ -0,0 +1,104 @@ +"""Step class to run crash tests against a local x86 Manhattan shell.""" + +from __future__ import absolute_import +import logging +import time + +from helpers import cast_shell_utils +from slave import base_step + +_LOG_DIR = 'crash_test_logs' + + +class RunManhattanShellCrashTestStep(base_step.BaseStep): + """Step for running crash test against a local x86 cast shell.""" + + def __init__(self, **kwargs): + """Creates a RunManhattanShellCrashTestStep instance. + + Args: + **kwargs: Any additional args to pass to BaseStep. + """ + base_step.BaseStep.__init__(self, + name='Run crash loop integration test', + **kwargs) + self.wait_time = 30 + self.timeout = 300 + + def _starting_cast_shell(self): + """Starts a local x86 cast shell and get its process Id. + + Returns: + A tuple of cast shell status, process id, log file descriptor and log file + path. + """ + status = True + + try: + subprocess, log_file_descriptor, log_file_path = ( + cast_shell_utils.start_cast_shell( + self, + self.get_project_path('test'), + self.get_step_data(cast_shell_utils.CAST_SHELL_EXE_PATH), + self.get_tmp_dir(), + enable_cma_media_pipeline=False, + use_headless_ozone_platform=True, + launch_utility_process=True)) + except (cast_shell_utils.CastShellError, + cast_shell_utils.CastShellTimeoutError): + logging.exception('Failed to start cast_shell') + status = False + + return status, subprocess.pid, log_file_descriptor, log_file_path + + def _is_cast_shell_still_running(self, cast_shell_running_pid): + """Verify cast_shell is still running. + + Args: + cast_shell_running_pid: Started cast_shell process id. + Returns: + boolean indicating if cast_shell is still running. + """ + current_running_processes = self.get_running_subprocess_pids() + if cast_shell_running_pid not in current_running_processes: + return False + device_name = cast_shell_utils.get_device_name(self) + logging.info('Retrieved Device Name: %s', device_name) + if not device_name: + return False + return True + + def _timeout_wait(self, start_time): + """Returns True if waiting for a timeout, returns False others.""" + elapsed = time.time() - start_time + if elapsed < self.timeout: + logging.info( + '%s seconds have elapsed, %s second remaining, waiting %s seconds', + elapsed, self.timeout - elapsed, self.wait_time) + time.sleep(self.wait_time) + return True + return False + + def run(self): + """Run test against x86 cast shell every 30 sec. to confirm its running. + + Returns: + True if all tests pass. + """ + start_time = time.time() + + is_passing, cast_shell_pid, log_file_descriptor, log_file_path = ( + self._starting_cast_shell()) + + while self._timeout_wait(start_time): + if not self._is_cast_shell_still_running(cast_shell_pid): + is_passing = False + logging.info('Manhattan cast_shell failed after it started') + break + + if log_file_descriptor and log_file_path: + cast_shell_utils.upload_cast_shell_logs(log_file_descriptor, + log_file_path, + self.get_gcs_dir(), _LOG_DIR, + 'cast_shell_console.txt') + return is_passing
diff --git a/cq/scripts/slave/step/x86_wifi_step.py b/cq/scripts/slave/step/x86_wifi_step.py new file mode 100644 index 0000000..ead9c01 --- /dev/null +++ b/cq/scripts/slave/step/x86_wifi_step.py
@@ -0,0 +1,235 @@ +from __future__ import absolute_import +import os +import pathlib +import re +import collections + +from slave import base_step +from slave.step import code_coverage_step + +BUILD_VARIANT = 'eng' +TARGET_PRODUCT = 'sirocco_x86_64' +BUILD_ITEM = 'sirocco_virtual_device_deps' +UNIT_TESTS = [ + 'ap-wireless_unittest', + 'ap-infra_unittests', + 'ap-daemons_unittest', +] + +_MAKE_ERROR_PATTERN = ( + r'^(?P<filename>[^:]+):(?P<linenum>\d+):(?P<column>\d+): ' + 'error: (?P<err_msg>.*)$', + r'^(?P<filename>[^\-]+)-(?P<linenum>\d+): error: (?P<err_msg>.*)$', +) + +_GTEST_ERROR_TEST_NAME_PATTERN = re.compile(r'^\[. FAILED. \] (\S+\.\S+)$', + re.MULTILINE) + +def make_error_to_comments(stderr, directory): + """ + parse stderr with regex error pattern and return comments dict + Args: + stderr (str): logs from stderr + Return: + (dict) comments: { + "filename": + { "linenum": <int>, + "message": <str> error message, + } + } + """ + comments = collections.defaultdict(list) + + for line in stderr.splitlines(): + match = [m for m in [ + re.match(err_pat, line) for err_pat in _MAKE_ERROR_PATTERN + ] if m is not None] + if match: + match = match[0] + filename = match.group('filename') + if directory and filename.startswith(directory): + filename = filename[len(directory) + len(os.path.sep):] + linenum = int(match.group('linenum')) + comments[filename].append({'line': linenum, 'message': line}) + return comments + + +class MakeCleanSim(base_step.BaseStep): + + def __init__(self, **kwargs): + base_step.BaseStep.__init__(self, + name='make clean sirocco_x86_64', + halt_on_failure=True, + **kwargs) + + def run(self): + + command = [ + 'make', + 'TARGET_PRODUCT={}'.format(TARGET_PRODUCT), + 'TARGET_BUILD_VARIANT={}'.format(BUILD_VARIANT), + 'clean' + ] + returncode, _, stderr = self.exec_subprocess(command) + if returncode != 0: + comment = make_error_to_comments(stderr, '') + self.add_review({ + 'comments': comment + }) + return False + + return True + + +class BuildSimulatorStep(base_step.BaseStep): + + def __init__(self, code_coverage=False, **kwargs): + self._code_coverage = code_coverage + base_step.BaseStep.__init__(self, + name='build x86_64 sirocco_x86_64', + halt_on_failure=True, + **kwargs) + + def run(self): + command = [ + 'make', + '-j{}'.format(self.get_num_jobs()), + 'TARGET_PRODUCT={}'.format(TARGET_PRODUCT), + 'TARGET_BUILD_VARIANT={}'.format(BUILD_VARIANT) + ] + + command += self.build_accelerator.make_flags + command += [BUILD_ITEM] + returncode, _, stderr = self.exec_subprocess(command) + if returncode != 0: + comment = make_error_to_comments(stderr, '') + self.add_review({ + 'comments': comment + }) + return False + + return True + +class BuildUnitTestsStep(base_step.BaseStep): + + def __init__(self, code_coverage=False, **kwargs): + self._code_coverage = code_coverage + super().__init__(name='build unittests sirocco_x86_64', + halt_on_failure=True, + **kwargs) + + def run(self): + command = [ + 'make', + '-j{}'.format(self.get_num_jobs()), + 'TARGET_PRODUCT={}'.format(TARGET_PRODUCT), + 'TARGET_BUILD_VARIANT={}'.format(BUILD_VARIANT), + ] + + if self._code_coverage: + command.append('COMMAND_LINE_GN_ARGS=\'' + 'use_clang_coverage=true is_component_build=false\'' + ) + + if self.build_accelerator.make_flags: + command.extend(self.build_accelerator.make_flags) + command.append('sirocco_virtual_unittests') + returncode, _, stderr = self.exec_subprocess(command) + if returncode: + comment = make_error_to_comments(stderr, '') + self.add_review({ + 'comments': comment + }) + return False + test_list = UNIT_TESTS.copy() + self.add_step_data(code_coverage_step.STEP_DATA_TEST_LIST, test_list) + return True + +class RunUnitTestsStep(base_step.BaseStep): + + def __init__(self, test_env=None, build_out_dir=None, **kwargs): + self._test_env = test_env + self._build_out_dir = build_out_dir + super().__init__(name='run unittests sirocco_x86_64', + halt_on_failure=True, + **kwargs) + + def run(self): + # Use to run all tests, then if any failed we fail this step + errors = [] + for test in UNIT_TESTS: + returncode, stdout, _ = self.exec_subprocess( + [f'{self._build_out_dir}/{test}'], + cwd='chromium/src', + env=self._test_env + ) + if returncode: + gtest_failures = re.findall(_GTEST_ERROR_TEST_NAME_PATTERN, stdout) + if gtest_failures: + errors.extend( + [f'{test_case} from {test}' for test_case in gtest_failures] + ) + else: + errors.append(f'Test execution error for {test}') + if errors: + error_msg = '\n'.join(errors) + self.add_review({ + 'message': f'{len(errors)} failure(s) from unit tests:\n{error_msg}', + }) + return False + return True + +class CreateSimTarStep(base_step.BaseStep): + + def __init__(self, **kwargs): + self._eurekaroot = kwargs['eureka_root'] + base_step.BaseStep.__init__(self, + name='tar-ing sim artifacts', + halt_on_failure=True, + **kwargs) + + + def run(self): + dockerignore = os.path.join(self._eurekaroot, + 'vendor/x86_64_simulator/sirocco_x86_64/products', + 'Dockerfile.dockerignore') + + include_files = [] + exclude_files = [] + try: + with open(dockerignore) as f: + # Skip * on first line that excludes everything + for line in f.readlines()[1:]: + line = line.replace('\\', '') # Strip escaped + characters + if line.startswith('!'): + paths = self._eurekaroot.glob(line[1:].rstrip()) + include_files.extend( + [str(path.relative_to(self._eurekaroot)) for path in paths]) + else: + path = line.rstrip() + exclude_files.append(path) + except OSError: + # Ignore missing file here for tests + # tar would fail because the archive is empty + pass + + tar_filename = '{}.tar.gz'.format(TARGET_PRODUCT) + command = ['tar'] + command += ['-C', str(self._eurekaroot)] + command += [f'--exclude={file}' for file in exclude_files] + command += [ + '-czf', + os.path.join(self.get_gcs_dir(), tar_filename), + ] + command += include_files + + returncode, _, stderr = self.exec_subprocess(command) + if returncode != 0: + comment = f'tar-ing failed: {stderr}' + self.add_review({ + 'message': comment + }) + return False + + self.set_build_property('ota_files', [tar_filename]) + return True
diff --git a/cq/scripts/slave/step/xml_check_step.py b/cq/scripts/slave/step/xml_check_step.py new file mode 100644 index 0000000..78d33bd --- /dev/null +++ b/cq/scripts/slave/step/xml_check_step.py
@@ -0,0 +1,55 @@ +"""Build step class for validating XML files.""" + +from __future__ import absolute_import +import collections +import os +import re +import xml.etree + +from helpers import git_utils +from slave import base_step + +_XML_PARSE_ERROR_MSG = 'This XML file failed to parse: {}' +_XML_ERROR_POSITION_PATTERN = r'line (?P<linenum>\d+), column \d+' + + +class XmlCheckStep(base_step.BaseStep): + """Build step class for validating XML files.""" + + def __init__(self, **kwargs): + """Creates a XmlCheckStep instance. + + Args: + **kwargs: Any additional args to pass to BaseStep. + """ + base_step.BaseStep.__init__(self, name='xml check', **kwargs) + + def _parse_error_to_comment(self, err): + comment = {'message': _XML_PARSE_ERROR_MSG.format(str(err))} + match = re.search(_XML_ERROR_POSITION_PATTERN, str(err)) + if match: + comment['line'] = match.group('linenum') + return comment + + def run(self): + """Attempts to parse all .xml files in the current commit. + + Sets a build property "review" with the output if there are any errors. + + Returns: + True iff there were no parsing errors. + """ + comments = collections.defaultdict(list) + for xml_filename in self.changed_files(file_extensions=['.xml']): + with open(os.path.join(self.directory, xml_filename)) as xml_file: + try: + xml.etree.ElementTree.parse(xml_file) + except xml.etree.ElementTree.ParseError as err: + comments[xml_filename].append(self._parse_error_to_comment(err)) + + if comments: + self.add_review({'comments': comments}) + return False + + # No Errors + return True
diff --git a/cq/scripts/slave/test/__init__.py b/cq/scripts/slave/test/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/cq/scripts/slave/test/__init__.py
diff --git a/cq/scripts/slave/test/test_generator.py b/cq/scripts/slave/test/test_generator.py new file mode 100644 index 0000000..4187dfa --- /dev/null +++ b/cq/scripts/slave/test/test_generator.py
@@ -0,0 +1,250 @@ +"""Tools for generating custom recipe tests.""" + +from __future__ import absolute_import +import copy +import re +import sys + +import six + +DEFAULT_TEST_PROPERTIES = { + 'revision_ref': 'refs/changes/45/12345/1', + 'patch_branch': 'master', + 'patch_project': 'fake/unittest', + 'gerrit': 'eureka-internal', + 'issue': 12345, + 'patchset': 3, + 'manifest_url': 'https://eureka-internal.googlesource.com/eureka/manifest', + 'shallow_checkout': False, +} + +# Mock manifest used by default in recipes_test. +# Defined here to be used by custom test_generators as well. +DEFAULT_MANIFEST_STRING = """ +<?xml version="1.0" encoding="UTF-8"?> +<manifest> + <remote fetch="https://chromium.googlesource.com/" name="chromium" review="https://chromium-review.googlesource.com/"/> + <remote fetch="https://eureka-internal.googlesource.com/" name="eureka" review="sso://eureka-internal"/> + <remote fetch="https://github.com/" name="github"/> + + <default revision="master"/> + + <project name="chromium/src" remote="eureka" revision="unfork_m43"/> + <project name="chromium/tools/depot_tools" remote="chromium"/> + <project name="chromiumos/chromite" path="chromite/chromite" remote="chromium"/> + <project name="chromiumos/third_party/autotest" path="autotest" remote="chromium"/> + <project name="continuous-tests" remote="eureka"/> + <project name="fake/unittest" remote="eureka"/> + <project name="fragglerock" remote="eureka"/> + <project name="prebuilt/toolchain" path="toolchain" remote="eureka"/> + <project name="google/sprockets" path="test/sprockets" remote="github"/> + <project name="test" remote="eureka"/> + <project name="chromecast/internal" path="chromium/src/chromecast/internal" remote="eureka"/> + <project name="chromecast/internal/voice_ui" path="chromium/src/chromecast/internal/chirp" remote="eureka"/> + <project name="vendor/amlogic" remote="eureka"/> + <project name="vendor/marvell" remote="eureka"/> +</manifest> +""" + + +def repo_version_matcher(): + return match('repo', 'version') + + +def gclient_sync_matcher(): + return match( + 'luci-auth', 'context -disable-git-auth -service-account-json :gce -- ' + + 'gclient sync --force --with_branch_heads ' + + '--delete_unversioned_trees --reset --jobs=[0-9]+') + + +def match(tool, optional_arg_regex=''): + return '{} {}'.format(any_path_to(tool), optional_arg_regex) + + +def any_path_to(tool): + return '(\/?[A-z]\/?)*\/?' + tool + + +class TestGenerator(object): + """The state needed to run a single recipe test. + + An instance of this class should represent a unique test for a build recipe, + allowing the recipe to provide fake data for one or more steps in order to + trigger a certain result. + """ + + def __init__(self, test_name, buildername, branch='master', properties=None): + """Instantiates a TestGenerator instance. + + Args: + test_name: name for this test case. Unique within a recipe. + buildername: the name of the build used for the test. Must be valid within + the recipe this instance is used with. + branch: The manifest branch used to generate the manifest. Defaults to a + reasonable value. + properties: If set, these properties will be added to the dict returned by + get_properties, overriding the DEFAULT_TEST_PROPERTIES when duplicate + keys exist. + """ + assert buildername + assert test_name + self._test_name = test_name + self._buildername = buildername + self._repo_branch = branch + self._custom_properties = properties + + self._mock_files = {} + self._mock_executions = [] + + def add_mock_execution(self, + execution_regex, + retcode=0, + stdout=None, + stderr=None, + reusable=True): + """Adds a mock execution result. + + Args: + execution_regex: regex used to match an executed command. + retcode: return code to mock if the regex matches. + stdout: stdout to mock if the regex matches. + stderr: stderr to mock if the regex matches. + """ + assert isinstance(execution_regex, six.string_types) + assert isinstance(retcode, int) + self._mock_executions.append({ + 'regex': execution_regex, + 'retcode': retcode, + 'used': False, + 'stdout': stdout, + 'stderr': stderr, + 'reusable': reusable, + }) + + def exec_command(self, command): + """Mocks a command execution and returns exit values as appropriate. + + Args: + command: the command to run, as a single string. + + Returns: + The tuple (return code, stdout, stderr). If values are explicitly mocked, + those values will be inserted; otherwise, the default is (0, '', ''). + """ + assert isinstance(command, six.string_types) + for execution in self._mock_executions: + if execution['used'] and not execution['reusable']: + continue + if re.search(execution['regex'], command): + execution['used'] = True + stdout = execution['stdout'] or '' + stderr = execution['stderr'] or '' + return (execution['retcode'], stdout, stderr) + return (0, '', '') + + def exec_non_blocking_command(self, command): + """Mocks a non blocking command execution and returns a mock subprocess. + + Args: + command: the command to run, as a single string. + + Returns: + A mock subprocess instance. + """ + assert isinstance(command, six.string_types) + + log_file_descriptor = 9999 + log_file_path = '/tmpFolder/tmpPath' + + class MockSubprocess(object): + returncode = None + pid = 123 + + def terminate(self, *args, **kwargs): # pylint: disable=unused-argument,invalid-name + return 0 + + def poll(self, *args, **kwargs): # pylint: disable=unused-argument,invalid-name + return 0 + + def kill(self): # pylint: disable-unused-argument,invalid-name + return 0 + + return MockSubprocess(), log_file_descriptor, log_file_path + + def add_mock_file(self, filename, file_contents): + """Adds a mock file result by filename. + + A mock result will override file contents read using + BaseStep.exec_read_file. + + Args: + filename: the path, relative or absolute, of the file to mock. + file_contents: the contents of the file to return when read. + + Raises: + KeyError: if the filename was already mocked in this TestGenerator. + """ + assert isinstance(filename, six.string_types) + assert isinstance(file_contents, six.string_types) + if filename in self._mock_files: + raise KeyError(filename) + self._mock_files[filename] = {'contents': file_contents, 'used': False} + + def all_mocks_used(self): + """Returns whether or not all mocks were exercised for this test.""" + for filename in self._mock_files: + mock = self._mock_files[filename] + if not mock['used']: + return False + + for mock in self._mock_executions: + if not mock['used']: + return False + + return True + + def get_unused_mocks_message(self): + """Returns the list of mocks that were unused for this test.""" + results = [] + for filename in self._mock_files: + mock = self._mock_files[filename] + if not mock['used']: + results.append(str(mock)) + + for mock in self._mock_executions: + if not mock['used']: + results.append(str(mock)) + + if results: + return 'Unused mocks:\n{}'.format('\n'.join(results)) + return None + + def read_file(self, filename): + """Mocks reading file contents within a test context. + + Args: + filename: the path, relative or absolute, of the file to read. + + Returns: + The mocked file contents, or an empty string if not explicitly mocked. + """ + if filename in self._mock_files: + self._mock_files[filename]['used'] = True + return self._mock_files[filename]['contents'] + return '' + + def get_test_name(self): + """Returns the test name represented by this instance.""" + return self._test_name + + def get_properties(self): + """Returns a set of build properties used for running this test.""" + properties = copy.deepcopy(DEFAULT_TEST_PROPERTIES) + properties['manifest_branch'] = self._repo_branch + properties['buildername'] = self._buildername + + if self._custom_properties: + properties.update(self._custom_properties) + + return properties
diff --git a/cq/scripts/tools/__init__.py b/cq/scripts/tools/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/cq/scripts/tools/__init__.py
diff --git a/cq/scripts/tools/fix-expectations b/cq/scripts/tools/fix-expectations new file mode 100755 index 0000000..6b6c1df --- /dev/null +++ b/cq/scripts/tools/fix-expectations
@@ -0,0 +1,93 @@ +#!/usr/bin/env python3 +import argparse +import logging +import os +import re +import typing + + +def main(): + parser = argparse.ArgumentParser() + parser.add_argument("logfile", help="The log file from CQ to ingest") + parser.add_argument( + "-v", "--verbose", + action="store_true", + help="Add debug logging.") + args = parser.parse_args() + + logging.basicConfig(level=logging.DEBUG if args.verbose else logging.INFO) + with open(args.logfile, "r") as f: + _fix_expectation_files(f.read()) + + +def _remove_ansi(line: str) -> str: + ansi_escape = re.compile(r'(?:\x1B[@-_]|[\x80-\x9F])[0-?]*[ -/]*[@-~]') + return ansi_escape.sub('', line) + +def _fix_expectation_files(content: typing.Text) -> None: + filename = None + lines = [] + filename_to_content = {} + for i, line in enumerate(content.split("\n")): + # Handle cases where we don't get a clean finishing line + # because of color codes. + line = _remove_ansi(line) + if line == "}\n": + lines.append(line) + content = "\n".join(lines) + if filename in filename_to_content: + if filename_to_content[filename] != content: + _write_expectation(filename + ".1", + filename_to_content[filename]) + _write_expectation(filename + ".2", content) + raise Exception("Whoa, got two conflicting contents.") + else: + filename_to_content[filename] = content + filename = None + lines = [] + continue + + if filename: + if not line: + lines.append("") + logging.debug( + "Finished reading corrected version of %s " + "at %d lines at line %d", + filename, len(lines), i) + content = "\n".join(lines) + + if filename in filename_to_content: + if filename_to_content[filename] != content: + _write_expectation(filename + ".1", + filename_to_content[filename]) + _write_expectation(filename + ".2", content) + raise Exception("Whoa, got two conflicting contents.") + else: + filename_to_content[filename] = content + filename = None + lines = [] + else: + lines.append(line) + else: + match = re.match( + "^Correct expectation file (?P<filename>.*):", line) + if match: + filename = match.group("filename") + logging.debug("Found corrected version of '%s'", filename) + for filename, file_content in filename_to_content.items(): + _write_expectation(filename, file_content) + +def _write_expectation(filename: typing.Text, content: str) -> None: + fullpath = os.path.abspath(os.path.join( + os.path.dirname(__file__), + "..", + "slave", + "recipe_expectations", + filename, + )) + logging.info("Writing %s with %d lines", fullpath, len(content.split("\n"))) + with open(fullpath, "w") as f: + f.write(content) + +if __name__ == "__main__": + main()
diff --git a/cq/scripts/tools/run_recipe.py b/cq/scripts/tools/run_recipe.py new file mode 100755 index 0000000..7f2cbe3 --- /dev/null +++ b/cq/scripts/tools/run_recipe.py
@@ -0,0 +1,910 @@ +#!/workspace/recipe_python_virtual_env/bin/python +"""This script allows execution of a recipe without buildbot. + +Example: + +./run_recipe.py lint --properties-file - <<EOF +{ + 'property1': 'value1', + 'property2': 'value2', +} +EOF +""" +import argparse +import contextlib +import dataclasses +import datetime +import glob +import io +import json +import logging +import os +import pathlib +import pdb +import resource +import shutil +import subprocess +import sys +import tempfile +import time +import traceback +from typing import Dict, Union +import urllib.parse + +# Allow imports from cq/scripts folder. +sys.path.insert( + 0, os.path.realpath(os.path.join(os.path.dirname(__file__), os.pardir))) +# Allow imports from the root of continuous-tests +sys.path.insert( + 0, + os.path.realpath( + os.path.join( + os.path.dirname(os.path.dirname(os.path.dirname(__file__))), + os.pardir))) +# pylint: disable=wrong-import-position + +from helpers import data_manager +from helpers import repo_utils +from helpers import signal_utils +from helpers import timeout +from tools import subprocess42 + +SUCCESS = 0 +FAILURE = 1 + +USAGE = """ +%(prog)s <recipe_name> --properties-file <filename> [options] + +The properties file should contain a Python dictionary. If the filename +"-" is used, then the dictionary is read from stdin, for example: + +%(prog)s recipe_name --properties-file - <<EOF +{ + 'property1: 'value1', + 'property2: 'value2', +} +EOF + +The --eureka-root specifies which working eureka repository to run the tests in. +If unspecified, it will run in the current directory. +""" + +# buildbot is reducing soft limit to 1024 and recipe inherits it from buildslave +_RLIMIT_NOFILE_SOFT = 8192 +_RUNNING_STEP_NAME = None +_REVIEW_MESSAGE_CHAR_LIMIT = 10000 +_TRUNCATED_MESSAGE = '...[truncated]' + +Properties = Dict['str', Union[str, int]] + + +class RecipeRunnerError(Exception): + """Generic exception for recipe errors.""" + + +def get_tmp_dir(): + """Returns the correct tmp dir.""" + tmp_dir = os.environ.get('CQ_TEMP_DIR') + if not tmp_dir: + tmp_dir = ('/usr/local/google/tmp' + if os.path.isdir('/usr/local/google') else tempfile.gettempdir()) + return tmp_dir + + +def load_recipe_module(recipe): + """Returns a reference to the module for a given recipe. + + Args: + recipe: name of the recipe (filename in scripts/slave/recipes). + + Returns: + Handle to the module for the given recipe file. + """ + sys_path_copy = sys.path[:] + sys.path.insert( + 0, os.path.realpath(os.path.join(os.path.dirname(__file__), os.pardir))) + module = __import__('slave.recipe.' + recipe) + recipe_module = getattr(getattr(module, 'recipe'), recipe) + sys.path = sys_path_copy + return recipe_module + + +def load_recipe(recipe, build_name: str, **kwargs): + """Loads a recipe from a name and properties structure. + + Args: + recipe: name of the recipe (filename in scripts/slave/recipes). + build_name: name of the build to execute via this recipe. + **kwargs: additional named args to pass to the recipe + + Returns: + A BaseRecipe instance corresponding to the given inputs. + + Raises: + KeyError: if build_name not found in valid build names for the recipe. + """ + recipe_module = load_recipe_module(recipe) + if build_name not in recipe_module.GetValidBuildNames(): + raise KeyError('Build name "%s" not valid for recipe "%s"' % + (build_name, recipe)) + return recipe_module.CreateRecipe(build_name, **kwargs) + + +def run_recipe(recipe, + properties: Properties, + eureka_root: str, + use_debugger: bool = False): + """Runs a recipe, mimicking BuildBot as needed. + + Args: + recipe: name of the recipe (filename in scripts/slave/recipes). + properties: dictionary of properties for the given build. + eureka_root: the root directory to run the commands in. + use_debugger: Boolean param to pass to run_steps(). + + Returns: + one of SUCCESS or FAILURE. + """ + annotator = Annotator() + gcs_dir = properties.get('artifacts_dir') + executor = SubprocessExecutor(gcs_dir) + assert 'buildername' in properties + build_name = properties['buildername'] + eureka_root_abs = os.path.abspath(eureka_root) + + manifest_output_path = ( + pathlib.Path(executor.get_gcs_dir()) / repo_utils.MANIFEST_OVERRIDE_XML) + manifest_output_path.write_text( + repo_utils.get_manifest(executor, cwd=eureka_root_abs, quiet=True)) + properties['manifest_override_path'] = str(manifest_output_path) + annotator.set_build_property( + 'manifest_override_path', str(manifest_output_path)) + + dm = data_manager.DataManager(executor, properties) + dm.add_data('recipe_start_time', datetime.datetime.now()) + recipe = load_recipe( + recipe, + build_name, + properties=properties, + annotator=annotator, + executor=executor, + data_manager=dm, + eureka_root=eureka_root_abs) + + logging.info('Running setup steps.') + result = run_steps(recipe.get_setup_steps(), eureka_root_abs, annotator) + + if result == SUCCESS: + logging.info('Running main recipe steps.') + result = run_steps( + recipe.get_steps(), + eureka_root_abs, + annotator, + use_debugger=use_debugger) + + logging.info('Running teardown steps.') + run_steps(recipe.get_teardown_steps(), eureka_root_abs, annotator) + + write_result_file( + annotator.message, + annotator.file_comments, + annotator.output_properties, + ) + + return result + + +def run_steps(steps, root_dir, annotator, use_debugger=False): + """Runs a list of steps. + + Args: + steps: A list of steps to run. + root_dir: The root directory to reset to prior to each step. + annotator: An instance of an Annotator to use to run each step. + use_debugger: If True will re-raise exception + + Returns: + one of SUCCESS or FAILURE. + """ + global _RUNNING_STEP_NAME + + result = SUCCESS + for step in steps: + # reset cwd to root before each step, allowing steps to change cwd + os.chdir(root_dir) + logging.info('Running step: %s', step.get_name()) + exception = None + step_result = FAILURE + try: + _RUNNING_STEP_NAME = step.get_name() + step_result = annotator.run_step(step) + except Exception: # pylint: disable=broad-except + logging.exception('Encountered an unexpected error while running %s', + step.get_name()) + exception = traceback.format_exc() + finally: + _RUNNING_STEP_NAME = None + if exception: + if use_debugger: + raise # pylint: disable=misplaced-bare-raise + + return FAILURE # pylint: disable=lost-exception + + result = max(result, step_result) + + if result != SUCCESS and step.halt_on_failure(): + logging.info('Halting on failure from step %s', step.get_name()) + break + + return result + + +class ExecutorInvalidKeywordArgsError(Exception): + """SubprocessExecutor expects a single command list.""" + + +class ExecutorInvalidArgsError(Exception): + """SubprocessExecutor expects a single command list.""" + + +class SubprocessExecutor(object): + """Executes subprocess commands.""" + + def __init__(self, gcs_dir): + """Constructor for SubprocessExecutor. Creates temporary directories.""" + tempdir = get_tmp_dir() + self._tempdir = tempfile.mkdtemp(dir=tempdir) + self._gcs_dir = gcs_dir + self._cq_root = os.path.abspath( + os.path.join(os.path.dirname(__file__), os.pardir, os.pardir)) + self._blocking_subprocesses = [] + + def get_cq_root(self): + """Returns the absolute path to the root of the CQ src.""" + return self._cq_root + + def get_tmp_dir(self): + """Returns a tempdir available to the executor.""" + return self._tempdir + + def get_gcs_dir(self): + """This directory will be uploaded to GCS when a recipe finishes.""" + return self._gcs_dir + + def get_new_tmp_file(self): + """Creates a new temporary file. + + Returns: + A tuple of newly created temporary file descriptor and absolute path. + """ + return tempfile.mkstemp(dir=self.get_tmp_dir(), text=True) + + def write_temp_file(self, contents: str): + """Writes a temporary file. + + Args: + contents: Text string to write + + Returns: + The name of the file. + """ + tmp_file, tmp_file_path = self.get_new_tmp_file() + os.write(tmp_file, contents.encode('utf-8')) + os.close(tmp_file) + return tmp_file_path + + def get_blocking_subprocesses(self): + """Returns all the blocking subproccesses this executor has started.""" + return self._blocking_subprocesses + + def read_file(self, file_path): + """Reads a file by path and returns the contents. + + No sanity checking or validation is performed by this method. + + Args: + file_path: path to a file, either relative from cwd or absolute. + + Returns: + The contents of the file loaded from file_path. + """ + with open(file_path) as f: + return f.read() + + def glob_files(self, glob_expr): + """Performs a file glob and returns the list of files. + + Args: + glob_expr: the file glob expression to search for. + + Returns: + A list, the output of glob.glob(glob_expr). + """ + assert isinstance(glob_expr, str) + return glob.glob(glob_expr) + + def exec_subprocess(self, + command, + check_output=False, + cwd=None, + *args, + **kwargs): # pylint: disable=keyword-arg-before-vararg + """Execute a subprocess. + + Args: + command: The command to execute. + check_output: Whether or not to raise a CalledProcessError on non-zero + return code. + cwd: The current working directory to use for the subprocess. + *args: passed to self._executor.subprocess + **kwargs: passed to self._executor.subprocess This should be used + sparingly at the recipe level because none of the information about the + subprocess is captured in any logs. + + Returns: + Just stdout, if check_output=True, otherwise a tuple of + (returncode, stdout, stderr). + """ + returncode, stdout, stderr = self.subprocess( + command, *args, cwd=cwd, **kwargs) + if check_output: + if returncode != 0: + raise subprocess.CalledProcessError( + returncode, cmd=command, output=stdout + '\nstderr:\n' + stderr) + return stdout + return (returncode, stdout, stderr) + + def subprocess(self, *args, **kwargs): + """Executes a subprocess using subprocess.Popen. + + Args: + *args: passed to subprocess.Popen + **kwargs: passed to subprocess.Popen; optionally, quiet=True can be passed + as a kwarg, in which case stdout/stderr from the subprocess will not be + written to sys. This kwarg will not get passed to subprocess.Popen. + + Returns: + Tuple of (return code, full stdout output, full stderr output) + + Raises: + ExecutorInvalidArgsError: if |args| is not a single command list. + """ + if len(args) != 1 or not isinstance(args[0], list): + raise ExecutorInvalidArgsError( + 'Expected a tuple with a single list element, found args={}'.format( + args)) + + stdin = None + stdout = subprocess.PIPE + stderr = subprocess.PIPE + if 'stdin' in kwargs: + stdin = kwargs['stdin'] + del kwargs['stdin'] + if 'stdout' in kwargs: + stdout = kwargs['stdout'] + del kwargs['stdout'] + if 'stderr' in kwargs: + stderr = kwargs['stderr'] + del kwargs['stderr'] + + sp, quiet = (self.start_subprocess(stdin, stdout, stderr, *args, **kwargs)) + self._blocking_subprocesses.append(sp) + stdout, stderr = self.wait_for_subprocess_completion(sp, quiet) + logging.info('[%s] Completed command "%s" with return code %d', + time.strftime('%Y-%m-%d %H:%M:%S %Z'), + ' '.join(map(str, args[0])), sp.returncode) + return (sp.returncode, stdout, stderr) + + def subprocess_chain(self, subprocess_chain): + """Executs a chain of subprocesses, piping output between processes. + + Args: + subprocess_chain: A list of subprocesses, where each item is a tuple of + (command, **kwargs) to pass to subprocess.Popen. If command is empty, it + must be []. If **kwargs is empty, it must be {}. + e.g. [(['ls', '-al'], {'cwd':'path/to/foo'}), ([], {})] + + Returns: + Tuple of (return code, full stdout output, full stderr output) + """ + assert isinstance(subprocess_chain, list) + + logging.info('Starting command pipeline.') + prev_process = None + for command, kwargs in subprocess_chain: + assert isinstance(command, list) + assert isinstance(kwargs, dict) + if prev_process: + sp, quiet = self.start_subprocess(prev_process.stdout, subprocess.PIPE, + subprocess.PIPE, command, **kwargs) + prev_process.stdout.close() # Allow prev_process to receive a SIGPIPE + prev_process = sp + else: + # First process starts without piping in any stdin + prev_process, quiet = ( + self.start_subprocess(None, subprocess.PIPE, subprocess.PIPE, + command, **kwargs)) + self._blocking_subprocesses.append(prev_process) + + stdout, stderr = self.wait_for_subprocess_completion(prev_process, quiet) + logging.info('Command pipeline finished with returncode %d', + prev_process.returncode) + return (prev_process.returncode, stdout, stderr) + + def non_blocking_subprocess(self, *args, **kwargs): + """Starts a non blocking subprocess using subprocess.Popen. + + The new subprocess is detached from parent process and created under a new + process group. + + Args: + *args: passed to subprocess.Popen + **kwargs: passed to subprocess.Popen. + + Returns: + A tuple of newly created subprocess, log file descriptor and log file + path. + """ + kwargs['detached'] = True + file_descriptor, file_path = self.get_new_tmp_file() + sp, _ = self.start_subprocess(None, file_descriptor, file_descriptor, *args, + **kwargs) + logging.info('Started command %s, pid = %d', args, sp.pid) + return sp, file_descriptor, file_path + + def start_subprocess(self, stdin, stdout, stderr, *args, **kwargs): + """Executes a subprocess using subprocess.Popen. + + Args: + stdin: A file stream, subprocess.PIPE, or None to read stdin from. + stdout: A file stream or subprocess.PIPE to redirect stdout. + stderr: A file stream or subprocess.PIPE to redirect stderr. + *args: passed to subprocess.Popen + **kwargs: passed to subprocess.Popen; optionally, quiet=True can be passed + as a kwarg, in which case stdout/stderr from the subprocess will not be + written to file. This kwarg will not get passed to subprocess.Popen. + text: If stdout and stderr should be treated as text, encoded in + the default encoding for the platform. + + Returns: + Tuple of (subprocess, boolean indicating if subprocess output needs to be + saved.) + + Raises: + ExecutorInvalidArgsError: if |args| is not a single command list. + ExecutorInvalidKeywordArgsError: if stdin, stdout, stderr in |kwargs|. + """ + for kwarg in ['stdin', 'stdout', 'stderr']: + if kwarg in kwargs: + raise ExecutorInvalidKeywordArgsError( + '{} cannot be a kwarg: kwargs={}'.format(kwarg, kwargs)) + if len(args) != 1 or not isinstance(args[0], list): + raise ExecutorInvalidArgsError( + 'Expected a tuple with a single list element, found args={}'.format( + args)) + + if 'cwd' in kwargs: + if kwargs['cwd'] is None: + cwd_message = 'with cwd=None, using {}'.format(os.path.abspath('.')) + else: + cwd_message = 'with specified cwd of "{}"'.format(kwargs['cwd']) + else: + cwd_message = 'with default cwd of "{}"'.format(os.path.abspath('.')) + + text = kwargs.get('text', True) + quiet = not text + if 'quiet' in kwargs: + quiet = kwargs['quiet'] + del kwargs['quiet'] + + logging.info('[%s] Running command: "%s" %s, with env: %s', + time.strftime('%Y-%m-%d %H:%M:%S %Z'), + ' '.join(map(str, args[0])), cwd_message, + kwargs.get('env', {})) + + if not text and not quiet: + raise ValueError('quiet and text cannot both be False') + # Add any extra args from 'env' to a copy of os.environ + extra_env = kwargs.pop('env', {}) + env = os.environ.copy() + if extra_env: + env.update(extra_env) + if 'TMPDIR' not in env: + env['TMPDIR'] = self.get_tmp_dir() + sp = subprocess42.Popen( + stdin=stdin, + stdout=stdout, + stderr=stderr, + env=env, + text=text, + *args, + **kwargs) + return (sp, quiet) + + def wait_for_subprocess_completion(self, sp, quiet): + """Waits till subprocess is completed. + + Args: + sp: A file stream or subprocess.PIPE to redirect stdout. + quiet: If True stdout/stderr from the subprocess will not be written to + file/console. + + Returns: + Tuple of strings (stdout, stderr) + """ + stdout_array = [] + stderr_array = [] + + for pipe, data in sp.yield_any(): + if pipe == 'stdout': + if not quiet: + sys.stdout.write(data) + sys.stdout.flush() + stdout_array.append(data) + else: + if not quiet: + sys.stderr.write(data) + sys.stderr.flush() + stderr_array.append(data) + + return ''.join(stdout_array), ''.join(stderr_array) + + +def print_command(command): + return sys.__stdout__.write(json.dumps(command) + '\n') + + +class JsonIOWrapper(io.TextIOBase): + + def __init__(self, channel): + super().__init__() + self._channel = channel + self._line = '' + + def flush(self) -> None: + if self._line: + self._write_line() + + def write(self, s: str) -> int: + self._line += s + if self._line.endswith('\n') or len(self._line) > 1000: + return self._write_line() + return 0 + + def _write_line(self) -> int: + log_command = { + 'channel': self._channel, + 'text': self._line, + } + self._line = '' + if _RUNNING_STEP_NAME: + log_command['step_name'] = _RUNNING_STEP_NAME + return print_command({ + 'log': log_command, + }) + + +@dataclasses.dataclass(frozen=True) +class FileCommentRange: + start_line: int + start_character: int + end_line: int + end_character: int + + +@dataclasses.dataclass(frozen=True) +class FileComment: + file_path: str + location: Union[int, FileCommentRange, None] + message: str + + +class Annotator(object): + """Prints annotation commands to be interpreted by the buildbot master.""" + + def __init__(self): + self._output_properties = {} + self._messages = [] + self._file_comments = [] + + @property + def output_properties(self): + return self._output_properties + + @property + def message(self): + return truncate('\n\n'.join(self._messages), 10000) + + @property + def file_comments(self): + return self._file_comments[:100] + + def run_step(self, step): + """Runs a build step, printing annotations as necessary. + + Arguments: + step: BaseStep instance to be executed. + + Returns: + SUCCESS if the step runs to completion, FAILURE otherwise. + """ + print_command({ + 'start_step': { + 'step_name': step.get_name(), + }, + }) + + return_value = SUCCESS + result = False + + try: + timeout_sec = step.get_timeout() + with signal_utils.sigterm_handler(): + with timeout.timeout(timeout_secs=timeout_sec): + result = step.run() + assert isinstance(result, bool) + except timeout.TimeoutException: + result = step.result_on_timeout() + logging.error( + 'Error: Step timed out. The current step timeout ' + 'threshold is %s seconds', timeout_sec) + step.kill_all_blocking_subprocesses() + except signal_utils.SigtermException: + logging.error('Error: Received SIGTERM. If this was run by Buildbot, ' + 'that means a step timed out because no logs was ' + 'produced for a specified period of time. We should stop ' + 'and try to clean up everything before Buildbot sends ' + 'a SIGKILL.') + step.set_halt_on_failure() + step.kill_all_blocking_subprocesses() + except Exception: # pylint: disable=broad-except + logging.exception('Step %s finished with an exception.', step.get_name()) + raise + finally: + if not result: + return_value = FAILURE + step.kill_all_non_blocking_subprocesses() + + print_command({ + 'finish_step': { + 'step_name': step.get_name(), + 'outcome': 'FAILED' if return_value == FAILURE else 'PASSED' + }, + }) + + return return_value + + def set_build_property(self, name, value): + """Communicates a new build property to the buildbot master. + + Args: + name: property name (must be a string) + value: property value (must be JSON-serializable) + """ + self._output_properties[name] = value + + def add_message(self, message): + self._messages.append(message) + + def add_comments(self, comments): + for filename, file_comments in comments.items(): + if len(filename) > 200: + logging.warning('Skipping file comment because path is too long') + else: + assert isinstance(file_comments, list) + for comment in file_comments: + if 'line' in comment: + location = comment['line'] + assert isinstance(location, int) and location > 0 + elif 'range' in comment: + range_data = comment['range'] + fields = [ + ('start_line', 1), + ('start_character', 0), + ('end_line', 1), + ('end_character', 0)] + for field, minimum_value in fields: + assert field in range_data + assert isinstance(range_data[field], int) + assert range_data[field] >= minimum_value + location = FileCommentRange( + start_line=range_data['start_line'], + start_character=range_data['start_character'], + end_line=range_data['end_line'], + end_character=range_data['end_character'], + ) + else: + location = None + self._file_comments.append(FileComment( + file_path=filename, + location=location, + message=truncate(comment['message'], 1000), + )) + + +def truncate(s, max_length) -> str: + if len(s) > max_length: + return s[:(max_length - len(_TRUNCATED_MESSAGE))] + _TRUNCATED_MESSAGE + return s + + +def postmortem(type_, value, tb): + """A sys.excepthook for handling exceptions with pdb.""" + traceback.print_exception(type_, value, tb) + pdb.pm() + + +def load_recipe_properties(parsed_args) -> Properties: + """Loads recipe properties from file or from params JSON.""" + if parsed_args.properties_file: + filename = parsed_args.properties_file + properties_file = sys.stdin if filename == '-' else open(filename) + properties = json.loads(properties_file.read()) + assert isinstance(properties, dict) + elif parsed_args.properties: + properties = json.loads(parsed_args.properties) + assert isinstance(properties, dict) + else: + raise RecipeRunnerError('properties are required') + + return properties + + +def amend_recipe_properties(properties): + """Set defaults and convert special values in recipe properties.""" + properties = update_recipe_properties_from_environment(properties) + + manifest_url = properties.get('manifest_url') + if manifest_url: + properties['repo_alias'] = repo_utils.manifest_alias(manifest_url) + return properties + + +def get_branch_root(properties) -> str: + """Returns workspace_checkout_path from the properties if it exists.""" + + branch_root = properties.get('workspace_checkout_path') + if not branch_root: + raise ValueError('workspace_checkout_path is a required recipe parameter.') + if not os.path.exists(branch_root): + logging.info('Creating directory %s', branch_root) + os.makedirs(branch_root) + return branch_root + + +def write_result_file(message, file_comments, output_properties): + result_file = pathlib.Path('/workspace/output/result.json') + result_file.write_text(json.dumps({ + 'message': message, + 'file_comments': [convert_file_comment(c) for c in file_comments], + 'output_properties': output_properties, + })) + + +def convert_file_comment(file_comment): + comment = { + 'file_path': file_comment.file_path, + 'message': file_comment.message, + } + if isinstance(file_comment.location, int): + comment['line'] = file_comment.location + elif isinstance(file_comment.location, FileCommentRange): + comment['range'] = dataclasses.asdict(file_comment.location) + return comment + + +def get_build_system(austin_build_system): + return 'cq' if austin_build_system == 'presubmit' else 'catabuilder' + + +def get_gob_host_id(host_url: str) -> str: + """Returns the ID of the GoB host. Derived from host_url.""" + hostname = get_hostname(host_url) + if hostname: + parts = hostname.split('.') + if len(parts) == 3 and hostname.endswith('.googlesource.com'): + return parts[0] + if len(parts) == 5 and hostname.endswith('.git.corp.google.com'): + return parts[0] + raise ValueError('Unable to extract GoB host ID from host URL.') + + +def get_hostname(host_url: str) -> str: + return urllib.parse.urlparse(host_url).hostname + + +def get_depends_on(patchset_data): + return { + 'change_number': int(patchset_data['change_number']), + 'gob_host': get_gob_host_id(patchset_data['host_url']), + 'patchset_number': int(patchset_data['patch_number']), + 'project': patchset_data['project'], + 'branch': patchset_data['target_branch'], + } + + +def get_patchset_properties(): + patchset_data = json.loads(os.environ['AUSTIN_PATCHSETS']) + if not patchset_data: + return {} + main_patch = patchset_data[-1] + return { + 'depends_on': [get_depends_on(p) for p in patchset_data[:-1]], + 'gerrit': get_gob_host_id(main_patch['host_url']), + 'issue': int(main_patch['change_number']), + 'patch_project': main_patch['project'], + 'patchset': int(main_patch['patch_number']), + } + + +def update_recipe_properties_from_environment(recipe_properties): + return { + **recipe_properties, + 'artifacts_dir': os.environ['AUSTIN_OUTPUT_ARTIFACT_PATH'], + 'basil_build_id': os.environ['AUSTIN_BUILD_ID'], + 'build_env': os.environ['AUSTIN_BUILD_ENVIRONMENT'], + 'build_system': get_build_system(os.environ['AUSTIN_BUILD_SYSTEM']), + 'buildset': os.environ['AUSTIN_BUILDSET_ID'], + 'container_push_url': os.environ['AUSTIN_CONTAINER_PUSH_URL'], + 'manifest_branch': os.environ['AUSTIN_MANIFEST_BRANCH'], + 'manifest_url': os.environ['AUSTIN_MANIFEST_GIT_REPO_URL'], + 'workspace_checkout_path': os.environ['AUSTIN_CHECKOUT_PATH'], + 'rbe_instance': os.environ['AUSTIN_RBE_INSTANCE'], + **get_patchset_properties(), + } + + +def main(args): + """Gets the recipe name and properties and runs an annotated run.""" + print_command({ + 'enable_steps': {}, + }) + with contextlib.redirect_stdout(JsonIOWrapper('STDOUT')): + with contextlib.redirect_stderr(JsonIOWrapper('STDERR')): + logging.getLogger().setLevel(level=logging.INFO) + try: + return main_logged(args) + except BaseException: + logging.exception('An unexpected error occurred') + return 1 + + +def main_logged(args): + # Increase NOFILE soft limit to allow bigger builds, see b/140431372 + _, hard_limit = resource.getrlimit(resource.RLIMIT_NOFILE) + resource.setrlimit(resource.RLIMIT_NOFILE, + (min(hard_limit, _RLIMIT_NOFILE_SOFT), hard_limit)) + + parser = argparse.ArgumentParser(usage=USAGE) + parser.add_argument('recipe') + parser.add_argument( + '--pdb', + action='store_true', + help='Drop into a pdb session on unhandled exception') + parser.add_argument('--properties-file') + parser.add_argument('--properties') + parsed_args = parser.parse_args(args) + + if parsed_args.pdb: + sys.excepthook = postmortem + + properties = load_recipe_properties(parsed_args) + logging.info( + 'Properties: %s', json.dumps(properties, indent=2, sort_keys=True)) + properties = amend_recipe_properties(properties) + logging.info( + 'Amended properties: %s', + json.dumps(properties, indent=2, sort_keys=True), + ) + + branch_root = get_branch_root(properties) + + return run_recipe( + recipe=parsed_args.recipe, + properties=properties, + eureka_root=branch_root, + use_debugger=parsed_args.pdb) + + +if __name__ == '__main__': + sys.exit(main(sys.argv[1:]))
diff --git a/cq/scripts/tools/subprocess42.py b/cq/scripts/tools/subprocess42.py new file mode 100644 index 0000000..dfb279a --- /dev/null +++ b/cq/scripts/tools/subprocess42.py
@@ -0,0 +1,678 @@ +# Copyright 2013 The LUCI Authors. All rights reserved. +# Use of this source code is governed under the Apache License, Version 2.0 +# that can be found in the LICENSE file. + +"""subprocess42 is the answer to life the universe and everything. + +It has the particularity of having a Popen implementation that can yield output +as it is produced while implementing a timeout and NOT requiring the use of +worker threads. + +Example: + Wait for a child process with a timeout, send SIGTERM, wait a grace period + then send SIGKILL: + + def wait_terminate_then_kill(proc, timeout, grace): + try: + return proc.wait(timeout) + except subprocess42.TimeoutExpired: + proc.terminate() + try: + return proc.wait(grace) + except subprocess42.TimeoutExpired: + proc.kill() + return proc.wait() + + +TODO(maruel): Add VOID support like subprocess2. +""" +import collections +import contextlib +import errno +import locale +import os +import signal +import sys +import threading +import time + +import subprocess + +from cq.scripts.helpers import timeout as time_out + + +# Default maxsize argument. +MAX_SIZE = 16384 + + +# Set to True when inhibit_crash_dump() has been called. +_OS_ERROR_REPORTING_INHIBITED = False + + +# subprocess.mswindows is an internal-only API. It was moved in Python3. +mswindows = getattr( + subprocess, "mswindows", getattr(subprocess, "_mswindows", False)) +if mswindows: + # pylint: disable=wrong-import-position + import ctypes # pylint: disable=wrong-import-order + import msvcrt # pylint: disable=wrong-import-order + from ctypes import wintypes # pylint: disable=wrong-import-order + from ctypes import windll # pylint: disable=wrong-import-order + + + # Which to be received depends on how this process was called and outside the + # control of this script. See Popen docstring for more details. + STOP_SIGNALS = (signal.SIGBREAK, signal.SIGTERM) + + + def ReadFile(handle, desired_bytes): + """Calls kernel32.ReadFile().""" + c_read = wintypes.DWORD() + buff = wintypes.create_string_buffer(desired_bytes+1) + windll.kernel32.ReadFile( + handle, buff, desired_bytes, wintypes.byref(c_read), None) + # NULL terminate it. + buff[c_read.value] = '\x00' + return wintypes.GetLastError(), buff.value + + def PeekNamedPipe(handle): + """Calls kernel32.PeekNamedPipe(). Simplified version.""" + c_avail = wintypes.DWORD() + c_message = wintypes.DWORD() + success = windll.kernel32.PeekNamedPipe( + handle, None, 0, None, wintypes.byref(c_avail), + wintypes.byref(c_message)) + if not success: + raise OSError(wintypes.GetLastError()) + return c_avail.value + + def recv_multi_impl(conns, maxsize, timeout): + """Reads from the first available pipe. + + It will immediately return on a closed connection, independent of timeout. + + Arguments: + - maxsize: Maximum number of bytes to return. Defaults to MAX_SIZE. + - timeout: If None, it is blocking. If 0 or above, will return None if no + data is available within |timeout| seconds. + + Returns: + tuple(int(index), str(data), bool(closed)). + """ + assert conns + assert timeout is None or isinstance(timeout, (int, float)), timeout + maxsize = max(maxsize or MAX_SIZE, 1) + + # TODO(maruel): Use WaitForMultipleObjects(). Python creates anonymous pipes + # for proc.stdout and proc.stderr but they are implemented as named pipes on + # Windows. Since named pipes are not waitable object, they can't be passed + # as-is to WFMO(). So this means N times CreateEvent(), N times ReadFile() + # and finally WFMO(). This requires caching the events handles in the Popen + # object and remembering the pending ReadFile() calls. This will require + # some re-architecture to store the relevant event handle and OVERLAPPEDIO + # object in Popen or the file object. + start = time.time() + handles = [ + (i, msvcrt.get_osfhandle(c.fileno())) for i, c in enumerate(conns) + ] + while True: + for index, handle in handles: + try: + avail = min(PeekNamedPipe(handle), maxsize) + if avail: + return index, ReadFile(handle, avail)[1], False + except OSError: + # The pipe closed. + return index, None, True + + if timeout is not None and (time.time() - start) >= timeout: + return None, None, False + # Polling rocks. + time.sleep(0.001) + +else: + import fcntl # pylint: disable=wrong-import-order,wrong-import-position + import select # pylint: disable=wrong-import-order,wrong-import-position + + + # Signals that mean this process should exit quickly. + STOP_SIGNALS = (signal.SIGINT, signal.SIGTERM) + + + def recv_multi_impl(conns, maxsize, timeout): + """Reads from the first available pipe. + + It will immediately return on a closed connection, independent of timeout. + + Arguments: + - maxsize: Maximum number of bytes to return. Defaults to MAX_SIZE. + - timeout: If None, it is blocking. If 0 or above, will return None if no + data is available within |timeout| seconds. + + Returns: + tuple(int(index), str(data), bool(closed)). + """ + assert conns + assert timeout is None or isinstance(timeout, (int, float)), timeout + maxsize = max(maxsize or MAX_SIZE, 1) + + # select(timeout=0) will block, it has to be a value > 0. + if timeout == 0: + timeout = 0.001 + try: + r, _, _ = select.select(conns, [], [], timeout) + except select.error: + r = None + if not r: + return None, None, False + + conn = r[0] + # Temporarily make it non-blocking. + # TODO(maruel): This is not very efficient when the caller is doing this in + # a loop. Add a mechanism to have the caller handle this. + flags = fcntl.fcntl(conn, fcntl.F_GETFL) + if not conn.closed: + # pylint: disable=E1101 + fcntl.fcntl(conn, fcntl.F_SETFL, flags | os.O_NONBLOCK) + try: + try: + data = conn.read(maxsize) + except IOError as e: + # On posix, this means the read would block. + if e.errno == errno.EAGAIN: + return conns.index(conn), None, False + raise e + + if not data: + # On posix, this means the channel closed. + return conns.index(conn), None, True + + return conns.index(conn), data, False + finally: + if not conn.closed: + fcntl.fcntl(conn, fcntl.F_SETFL, flags) + + +class TimeoutExpired(time_out.TimeoutException): + """Compatible with python3 subprocess.""" + def __init__(self, cmd, timeout, output=None, stderr=None): + self.cmd = cmd + self.timeout = timeout + self.output = output + # Non-standard: + self.stderr = stderr + super(TimeoutExpired, self).__init__(str(self)) + + def __str__(self): + return "Command '%s' timed out after %s seconds" % (self.cmd, self.timeout) + + +class Popen(subprocess.Popen): + """Adds timeout support on stdout and stderr. + + Inspired by + http://code.activestate.com/recipes/440554-module-to-allow-asynchronous-subprocess-use-on-win/ + + Unlike subprocess, yield_any(), recv_*(), communicate() will close stdout and + stderr once the child process closes them, after all the data is read. + + Mutated behavior: + - args: transparently encode('utf-8') any unicode items. + - cwd: transparently encode('utf-8') if unicode. + - env: transparently encode('utf-8') any unicode keys or values. + + Additional arguments: + - detached: If True, the process is created in a new process group. On + Windows, use CREATE_NEW_PROCESS_GROUP. On posix, use os.setpgid(0, 0). + + Additional members: + - start: timestamp when this process started. + - end: timestamp when this process exited, as seen by this process. + - detached: If True, the child process was started as a detached process. + - gid: process group id, if any. + - duration: time in seconds the process lasted. + + Additional methods: + - yield_any(): yields output until the process terminates. + - recv_any(): reads from stdout and/or stderr with optional timeout. + - recv_out() & recv_err(): specialized version of recv_any(). + """ + # subprocess.Popen.__init__() is not threadsafe; there is a race between + # creating the exec-error pipe for the child and setting it to CLOEXEC during + # which another thread can fork and cause the pipe to be inherited by its + # descendents, which will cause the current Popen to hang until all those + # descendents exit. Protect this with a lock so that only one fork/exec can + # happen at a time. + popen_lock = threading.Lock() + + def __init__(self, args, text=False, **kwargs): + assert 'creationflags' not in kwargs + assert 'preexec_fn' not in kwargs, 'Use detached=True instead' + + # Windows version of subprocess.Popen() really doens't like unicode. In + # practice we should use the current ANSI code page, but settle for utf-8 + # across all OSes for consistency. + to_str = lambda i: i if isinstance(i, str) else i.encode('utf-8') + args = [to_str(i) for i in args] + if kwargs.get('cwd') is not None: + kwargs['cwd'] = to_str(kwargs['cwd']) + if kwargs.get('env'): + kwargs['env'] = { + to_str(k): to_str(v) for k, v in kwargs['env'].items() + } + + self.start = time.time() + self.end = None + self.gid = None + self.detached = kwargs.pop('detached', False) + if self.detached: + if mswindows: + kwargs['creationflags'] = subprocess.CREATE_NEW_PROCESS_GROUP + else: + kwargs['preexec_fn'] = lambda: os.setpgid(0, 0) + with self.popen_lock: + super(Popen, self).__init__(args, **kwargs) + self.args = args + self.text = text + if self.detached and not mswindows: + try: + self.gid = os.getpgid(self.pid) + except OSError: + # sometimes the process can run+finish before we collect its pgid. fun. + pass + + def duration(self): + """Duration of the child process. + + It is greater or equal to the actual time the child process ran. It can be + significantly higher than the real value if neither .wait() nor .poll() was + used. + """ + return (self.end or time.time()) - self.start + + # pylint: disable=arguments-differ,redefined-builtin + def communicate(self, input=None, timeout=None): + """Implements python3's timeout support. + + Unlike wait(), timeout=0 is considered the same as None. + + Raises: + - TimeoutExpired when more than timeout seconds were spent waiting for the + process. + """ + if not timeout: + return super(Popen, self).communicate(input=input) + + assert isinstance(timeout, (int, float)), timeout + + if self.stdin or self.stdout or self.stderr: + if self.stdout: + stdout = u'' if self.text else b'' + else: + stdout = None + if self.stderr: + stderr = u'' if self.text else b'' + else: + stderr = None + + t = None + if input is not None: + assert self.stdin, ( + 'Can\'t use communicate(input) if not using ' + 'Popen(stdin=subprocess42.PIPE') + # TODO(maruel): Switch back to non-threading. + def write(): + try: + self.stdin.write(input) + except IOError: + pass + t = threading.Thread(name='Popen.communicate', target=write) + t.daemon = True + t.start() + + try: + if self.stdout or self.stderr: + start = time.time() + end = start + timeout + def remaining(): + return max(end - time.time(), 0) + for pipe, data in self.yield_any(timeout=remaining): + if pipe is None: + raise TimeoutExpired(self.args, timeout, stdout, stderr) + assert pipe in ('stdout', 'stderr'), pipe + if pipe == 'stdout': + stdout += data + else: + stderr += data + else: + # Only stdin is piped. + self.wait(timeout=timeout) + finally: + if t: + try: + self.stdin.close() + except IOError: + pass + t.join() + else: + # No pipe. The user wanted to use wait(). + self.wait(timeout=timeout) + return None, None + + # Indirectly initialize self.end. + self.wait() + return stdout, stderr + + def poll(self): + ret = super(Popen, self).poll() + if ret is not None and not self.end: + self.end = time.time() + return ret + + def yield_any_line(self, **kwargs): + """Yields lines until the process terminates. + + Like yield_any, but yields lines. + """ + return split(self.yield_any(**kwargs)) + + def yield_any(self, maxsize=None, timeout=None): + """Yields output until the process terminates. + + Unlike wait(), does not raise TimeoutExpired. + + Yields: + (pipename, data) where pipename is either 'stdout', 'stderr' or None in + case of timeout or when the child process closed one of the pipe(s) and + all pending data on the pipe was read. + + Arguments: + - maxsize: See recv_any(). Can be a callable function. + - timeout: If None, the call is blocking. If set, yields None, None if no + data is available within |timeout| seconds. It resets itself after + each yield. Can be a callable function. + """ + assert self.stdout or self.stderr + if timeout is not None: + # timeout=0 effectively means that the pipe is continuously polled. + if isinstance(timeout, (int, float)): + assert timeout >= 0, timeout + old_timeout = timeout + timeout = lambda: old_timeout + else: + assert callable(timeout), timeout + + if maxsize is not None and not callable(maxsize): + assert isinstance(maxsize, (int, float)), maxsize + + last_yield = time.time() + while self.poll() is None: + to = timeout() if timeout else None + if to is not None: + to = max(to - (time.time() - last_yield), 0) + t, data = self.recv_any( + maxsize=maxsize() if callable(maxsize) else maxsize, timeout=to) + if data or to == 0: + yield t, data + last_yield = time.time() + + # Read all remaining output in the pipes. + # There is 3 cases: + # - pipes get closed automatically by the calling process before it exits + # - pipes are closed automated by the OS + # - pipes are kept open due to grand-children processes outliving the + # children process. + while True: + ms = maxsize + if callable(maxsize): + ms = maxsize() + # timeout=0 is mainly to handle the case where a grand-children process + # outlives the process started. + t, data = self.recv_any(maxsize=ms, timeout=0) + if not data: + break + yield t, data + + def recv_any(self, maxsize=None, timeout=None): + """Reads from the first pipe available from stdout and stderr. + + Unlike wait(), does not throw TimeoutExpired. + + Arguments: + - maxsize: Maximum number of bytes to return. Defaults to MAX_SIZE. + - timeout: If None, it is blocking. If 0 or above, will return None if no + data is available within |timeout| seconds. + + Returns: + tuple(pipename or None, str(data)). pipename is one of 'stdout' or + 'stderr'. + """ + # recv_multi_impl will early exit on a closed connection. Loop accordingly + # to simplify call sites. + while True: + pipes = [ + x for x in ((self.stderr, 'stderr'), (self.stdout, 'stdout')) if x[0] + ] + # If both stdout and stderr have the exact file handle, they are + # effectively the same pipe. Deduplicate it since otherwise it confuses + # recv_multi_impl(). + if len(pipes) == 2 and self.stderr.fileno() == self.stdout.fileno(): + pipes.pop(0) + + if not pipes: + return None, None + start = time.time() + conns, names = list(zip(*pipes)) + index, data, closed = recv_multi_impl(conns, maxsize, timeout) + if index is None: + return index, data + if closed: + self._close(names[index]) + if not data: + # Loop again. The other pipe may still be open. + if timeout: + timeout -= (time.time() - start) + continue + + if self.text and data: + data = data.decode( + encoding=locale.getpreferredencoding(), errors='replace') + if self.universal_newlines: + data = self._translate_newlines(data) + return names[index], data + + def recv_out(self, maxsize=None, timeout=None): + """Reads from stdout synchronously with timeout.""" + return self._recv('stdout', maxsize, timeout) + + def recv_err(self, maxsize=None, timeout=None): + """Reads from stderr synchronously with timeout.""" + return self._recv('stderr', maxsize, timeout) + + def terminate(self): + """Tries to do something saner on Windows that the stdlib. + + Windows: + self.detached/CREATE_NEW_PROCESS_GROUP determines what can be used: + - If set, only SIGBREAK can be sent and it is sent to a single process. + - If not set, in theory only SIGINT can be used and *all processes* in + the processgroup receive it. In practice, we just kill the process. + See http://msdn.microsoft.com/library/windows/desktop/ms683155.aspx + The default on Windows is to call TerminateProcess() always, which is not + useful. + + On Posix, always send SIGTERM. + """ + try: + if mswindows and self.detached: + return self.send_signal(signal.CTRL_BREAK_EVENT) + super(Popen, self).terminate() + except OSError: + # The function will throw if the process terminated in-between. Swallow + # this. + pass + + def kill(self): + """Kills the process and its children if possible. + + Swallows exceptions and return True on success. + """ + if self.gid: + try: + os.killpg(self.gid, signal.SIGKILL) + except OSError: + return False + else: + try: + super(Popen, self).kill() + except OSError: + return False + return True + + def _close(self, which): + """Closes either stdout or stderr.""" + getattr(self, which).close() + setattr(self, which, None) + + def _recv(self, which, maxsize, timeout): + """Reads from one of stdout or stderr synchronously with timeout.""" + conn = getattr(self, which) + if conn is None: + return None + _, data, closed = recv_multi_impl([conn], maxsize, timeout) + if closed: + self._close(which) + + if self.text and data: + data = data.decode( + encoding=locale.getpreferredencoding(), errors='replace') + if self.universal_newlines: + data = self._translate_newlines(data) + return data + + +@contextlib.contextmanager +def set_signal_handler(signals, handler): + """Temporarilly override signals handler. + + Useful when waiting for a child process to handle signals like SIGTERM, so the + signal can be propagated to the child process. + """ + previous = {s: signal.signal(s, handler) for s in signals} + try: + yield + finally: + for sig, h in previous.items(): + signal.signal(sig, h) + + +def call(*args, **kwargs): + """Adds support for timeout.""" + timeout = kwargs.pop('timeout', None) + return Popen(*args, **kwargs).wait(timeout) + + +def check_call(*args, **kwargs): + """Adds support for timeout.""" + retcode = call(*args, **kwargs) + if retcode: + raise subprocess.CalledProcessError(retcode, kwargs.get('args') or args[0]) + return 0 + + +def check_output(*args, **kwargs): + """Adds support for timeout.""" + timeout = kwargs.pop('timeout', None) + if 'stdout' in kwargs: + raise ValueError('stdout argument not allowed, it will be overridden.') + process = Popen(stdout=subprocess.PIPE, *args, **kwargs) + output, _ = process.communicate(timeout=timeout) + retcode = process.poll() + if retcode: + raise subprocess.CalledProcessError(retcode, kwargs.get('args') or args[0], output) + return output + + +def call_with_timeout(args, timeout, **kwargs): + """Runs an executable; kill it in case of timeout.""" + proc = Popen(args, stdin=subprocess.PIPE, stdout=subprocess.PIPE, + stderr=subprocess.PIPE, **kwargs) + try: + out, err = proc.communicate(timeout=timeout) + except TimeoutExpired as e: + out = e.output + err = e.stderr + proc.kill() + proc.wait() + return out, err, proc.returncode, proc.duration() + + +def inhibit_os_error_reporting(): + """Inhibits error reporting UI and core files. + + This function should be called as early as possible in the process lifetime. + """ + global _OS_ERROR_REPORTING_INHIBITED + if not _OS_ERROR_REPORTING_INHIBITED: + _OS_ERROR_REPORTING_INHIBITED = True + if sys.platform == 'win32': + # Windows has a bad habit of opening a dialog when a console program + # crashes, rather than just letting it crash. Therefore, when a program + # crashes on Windows, we don't find out until the build step times out. + # This code prevents the dialog from appearing, so that we find out + # immediately and don't waste time waiting for a user to close the dialog. + # https://msdn.microsoft.com/en-us/library/windows/desktop/ms680621.aspx + SEM_FAILCRITICALERRORS = 1 + SEM_NOGPFAULTERRORBOX = 2 + SEM_NOALIGNMENTFAULTEXCEPT = 0x8000 + ctypes.windll.kernel32.SetErrorMode( + SEM_FAILCRITICALERRORS|SEM_NOGPFAULTERRORBOX| + SEM_NOALIGNMENTFAULTEXCEPT) + # TODO(maruel): Other OSes. + # - OSX, need to figure out a way to make the following process tree local: + # defaults write com.apple.CrashReporter UseUNC 1 + # defaults write com.apple.CrashReporter DialogType none + # - Ubuntu, disable apport if needed. + + +def split(data, sep='\n'): + """Splits pipe data by |sep|. Does some buffering. + + For example, [('stdout', 'a\nb'), ('stdout', '\n'), ('stderr', 'c\n')] -> + [('stdout', 'a'), ('stdout', 'b'), ('stderr', 'c')]. + + Args: + data: iterable of tuples (pipe_name, bytes). + + Returns: + An iterator of tuples (pipe_name, bytes) where bytes is the input data + but split by sep into separate tuples. + """ + # A dict {pipe_name -> list of pending chunks without separators} + pending_chunks = collections.defaultdict(list) + for pipe_name, chunk in data: + if chunk is None: + # Happens if a pipe is closed. + continue + + pending = pending_chunks[pipe_name] + start = 0 # offset in chunk to start |sep| search from + while start < len(chunk): + j = chunk.find(sep, start) + if j == -1: + pending_chunks[pipe_name].append(chunk[start:]) + break + + to_emit = chunk[start:j] + start = j + 1 + if pending: + # prepend and forget + to_emit = ''.join(pending) + to_emit + pending = [] + pending_chunks[pipe_name] = pending + yield pipe_name, to_emit + + # Emit remaining chunks that don't end with separators as is. + for pipe_name, chunks in sorted(pending_chunks.items()): + if chunks: + yield pipe_name, ''.join(chunks)
diff --git a/doc/epydoc.cfg b/doc/epydoc.cfg new file mode 100644 index 0000000..df3a6c5 --- /dev/null +++ b/doc/epydoc.cfg
@@ -0,0 +1,16 @@ +[epydoc] + +output: html +target: /var/www/eureka/git_doc/ + +graph: all +# TODO(gogan): figure out how to generate a pstat output for the full lib: +#pstat: /tmp/git.testing.pstat +#dotpath: /usr/bin/dot + +frames: no +url: https://eureka-internal.googlesource.com/test/ + +simple-term: yes + +name: Eureka Testing Library
diff --git a/doc/epydoc.css b/doc/epydoc.css new file mode 100644 index 0000000..3ed1be2 --- /dev/null +++ b/doc/epydoc.css
@@ -0,0 +1,692 @@ +/* Epydoc CSS Stylesheet +* +* This is a massivley hacked stylesheet for epydoc, the very nice Python API +* Documentation generator. The general look and feel is based on sphinx. +* +* Feel free to tweak this some more to make the theme even more pleasing +* if you have the time to spare for such things. The typography in particular +* could do with sorting out. Unless you like writing masocistic CSS however, +* I'd recommend looking to refactor the markup generated by epydoc. +* +*/ + +/* Yahoo! Reset Styles +Copyright (c) 2008, Yahoo! Inc. All rights reserved. +Code licensed under the BSD License: +http://developer.yahoo.net/yui/license.txt +version: 2.5.1 +*/ +html { + color: #000; + background: #FFF; +} +body,div,dl,dt,dd,ul,ol,li,h1,h2,h3,h4,h5,h6,pre,code,form,fieldset,legend,input,textarea,p,blockquote,th,td { + margin: 0; + padding: 0; +} +table { + border-collapse: collapse; + border-spacing: 0; +} +fieldset,img { + border: 0; +} +address,caption,cite,code,dfn,em,strong,th,var { + font-style: normal; + font-weight: normal; +} +li { + list-style: none; +} +caption,th { + text-align: left; +} +h1,h2,h3,h4,h5,h6 { + font-size: 100%; + font-weight: normal; +} +q:before,q:after { + content: ''; +} +abbr,acronym { + border: 0; + font-variant: normal; +} +sup { + vertical-align: text-top; +} +sub { + vertical-align: text-bottom; +} +input,textarea,select { + font-family: inherit; + font-size: inherit; + font-weight: inherit; +} +input,textarea,select {*font-size:100%; +} +legend { + color: #000; +} +body { + font: 13px/1.231 arial,helvetica,clean,sans-serif;*font-size:small;*font:x-small; +} +table { + font-size: inherit; + font: 100%; +} +pre,code,kbd,samp,tt { + font-family: monospace;*font-size:108%; + line-height: 100%; +} + + + +/* Default Colors & Styles +* - Set the default foreground & background color with 'body'; and +* link colors with 'a:link' and 'a:visited'. +* - Use bold for decision list terms. +* - The heading styles defined here are used for headings *within* +* docstring descriptions. All headings used by epydoc itself use +* either class='epydoc' or class='toc' (CSS styles for both +* defined below). +*/ +body { + background: #ffffff; + color: #000000; +} +p { + margin-top: 0.5em; + margin-bottom: 0.5em; +} +a { + color: #355f7c; + text-decoration: none; +} + +a:hover { + text-decoration: underline; +} + +dt { + font-weight: bold; +} +h1, h2 { + color: #20435C; + background: #F2F2F2; + border-bottom: 1px solid #CCC; + padding: 10px; +} +center { + display: none; +} +code { + font-size: 100%; +} +/* N.B.: class, not pseudoclass */ +a.link { + font-family: monospace; +} + +/* Page Header & Footer +* - The standard page header consists of a navigation bar (with +* pointers to standard pages such as 'home' and 'trees'); a +* breadcrumbs list, which can be used to navigate to containing +* classes or modules; options links, to show/hide private +* variables and to show/hide frames; and a page title (using +* <h1>). The page title may be followed by a link to the +* corresponding source code (using 'span.codelink'). +* - The footer consists of a navigation bar, a timestamp, and a +* pointer to epydoc's homepage. +*/ +h1.epydoc { + margin: -14px 0 0; + font-size: +140%; + color: #20435C; +} +h2.epydoc { + font-size: +130%; +} +h3.epydoc { + font-size: +115%; + margin-top: 0.2em; + margin-left: 25px; +} +td h3.epydoc { + font-size: +115%; + font-weight: bold; + margin-bottom: 0; +} +table.navbar { + background: #133F52; + color: #355f7c; + border: 0; +} +table.navbar table { + color: #355f7c; +} +th.navbar-select { + background: #1C4E63; + color: #FFF; +} +table.navbar table th { + padding-left: 15px; +} +table.navbar a { + text-decoration: none; + color: #FFF; + padding: 0 10px; + display: block; +} +table td.footer { + padding: 10px; + color: #666; + font-size: 90%; +} +/* Table Headers +* - Each summary table and details section begins with a 'header' +* row. This row contains a section title (marked by +* 'span.table-header') as well as a show/hide private link +* (marked by 'span.options', defined above). +* - Summary tables that contain user-defined groups mark those +* groups using 'group header' rows. +*/ +td.table-header { + background: #F2F2F2; + color: #20435C; + border: 1px solid #CCC; + padding: 5px 10px; +} +td.table-header table a:visited { + color: #204080; +} +span.table-header { + font-size: 120%; +} +th.group-header { + background: #c0e0f8; + color: #000000; + text-align: left; + font-size: 115%; + border: 1px solid #608090; +} + +/* Summary Tables (functions, variables, etc) +* - Each object is described by a single row of the table with +* two cells. The left cell gives the object's type, and is +* marked with 'code.summary-type'. The right cell gives the +* object's name and a summary description. +* - CSS styles for the table's header and group headers are +* defined above, under 'Table Headers' +*/ +table.summary { + border-collapse: collapse; + background: #FFF; + color: #000000; + border: 1px solid #CCC; + margin: 0 0 20px; +} +td.summary { + border: 1px solid #CCC; + padding: 5px 10px; +} +code.summary-type { + font-size: 85%; +} + +/* Details Tables (functions, variables, etc) +* - Each object is described in its own div. +* - A single-row summary table w/ table-header is used as +* a header for each details section (CSS style for table-header +* is defined above, under 'Table Headers'). +*/ +table.details { + border-collapse: collapse; + background: #FFF; + color: #000000; + border: 0; + margin: .2em 0 0 0; +} +table.details table { + color: #000000; +} + +/* Fields */ +dl.fields { + margin-left: 2em; + margin-top: 1em; + margin-bottom: 1em; +} +dl.fields dd ul { + margin-left: 0em; + padding-left: 0em; +} +dl.fields dd ul li ul { + margin-left: 2em; + padding-left: 0em; +} +div.fields { + margin-left: 2em; +} +div.fields p { + margin-bottom: 0.5em; +} + +/* Index tables (identifier index, term index, etc) +* - link-index is used for indices containing lists of links +* (namely, the identifier index & term index). +* - index-where is used in link indices for the text indicating +* the container/source for each link. +* - metadata-index is used for indices containing metadata +* extracted from fields (namely, the bug index & todo index). +*/ +table.link-index { + border-collapse: collapse; + background: #F2F2F2; + color: #000000; + border: 1px solid #CCC; +} +td.link-index { + border-width: 0px; + padding: 3px; +} +span.index-where { + font-size: 70%; +} +table.metadata-index { + border-collapse: collapse; + background: #e8f0f8; + color: #000000; + border: 1px solid #608090; + margin: .2em 0 0 0; +} +td.metadata-index { + border-width: 1px; + border-style: solid; +} +table.link-index h2.epydoc { + border-width: 1px 0; +} + +/* Function signatures +* - sig* is used for the signature in the details section. +* - .summary-sig* is used for the signature in the summary +* table, and when listing property accessor functions. +* */ +.sig-name { + color: #006080; +} +.sig-arg { + color: #008060; +} +.sig-default { + color: #602000; +} +.summary-sig { + font-family: monospace; +} +.summary-sig-name { + color: #006080; + font-weight: bold; +} +table.summary a.summary-sig-name:link { + color: #006080; + font-weight: bold; +} +table.summary a.summary-sig-name:visited { + color: #006080; + font-weight: bold; +} +.summary-sig-arg { + color: #006040; +} +.summary-sig-default { + color: #501800; +} + +/* Subclass list +*/ +ul.subclass-list { + display: inline; +} +ul.subclass-list li { + display: inline; +} + +/* To render variables, classes etc. like functions */ +table.summary .summary-name { + color: #006080; + font-weight: bold; + font-family: monospace; +} +table.summary +a.summary-name:link { + color: #006080; + font-weight: bold; + font-family: monospace; +} +table.summary +a.summary-name:visited { + color: #006080; + font-weight: bold; + font-family: monospace; +} + +/* Variable values +* - In the 'variable details' sections, each varaible's value is +* listed in a 'pre.variable' box. The width of this box is +* restricted to 80 chars; if the value's repr is longer than +* this it will be wrapped, using a backslash marked with +* class 'variable-linewrap'. If the value's repr is longer +* than 3 lines, the rest will be ellided; and an ellipsis +* marker ('...' marked with 'variable-ellipsis') will be used. +* - If the value is a string, its quote marks will be marked +* with 'variable-quote'. +* - If the variable is a regexp, it is syntax-highlighted using +* the re* CSS classes. +*/ +pre.variable { + padding: .5em; + margin: 0; + background: #F2F2F2; + color: #000000; + border: 1px solid #CCC; +} +.variable-linewrap { + color: #604000; + font-weight: bold; +} +.variable-ellipsis { + color: #604000; + font-weight: bold; +} +.variable-quote { + color: #604000; + font-weight: bold; +} +.variable-group { + color: #008000; + font-weight: bold; +} +.variable-op { + color: #604000; + font-weight: bold; +} +.variable-string { + color: #006030; +} +.variable-unknown { + color: #a00000; + font-weight: bold; +} +.re { + color: #000000; +} +.re-char { + color: #006030; +} +.re-op { + color: #600000; +} +.re-group { + color: #003060; +} +.re-ref { + color: #404040; +} + +/* Base tree +* - Used by class pages to display the base class hierarchy. +*/ +pre.base-tree { + font-size: 80%; + margin: 0; +} + + +/* Syntax Highlighting for Source Code +* - doctest examples are displayed in a 'pre.py-doctest' block. +* If the example is in a details table entry, then it will use +* the colors specified by the 'table pre.py-doctest' line. +* - Source code listings are displayed in a 'pre.py-src' block. +* Each line is marked with 'span.py-line' (used to draw a line +* down the left margin, separating the code from the line +* numbers). Line numbers are displayed with 'span.py-lineno'. +* The expand/collapse block toggle button is displayed with +* 'a.py-toggle' (Note: the CSS style for 'a.py-toggle' should not +* modify the font size of the text.) +* - If a source code page is opened with an anchor, then the +* corresponding code block will be highlighted. The code +* block's header is highlighted with 'py-highlight-hdr'; and +* the code block's body is highlighted with 'py-highlight'. +* - The remaining py-* classes are used to perform syntax +* highlighting (py-string for string literals, py-name for names, +* etc.) +*/ +pre.py-doctest { + padding: .5em; + margin: 1em; + background: #F2F2F2; + color: #000000; + border: 1px solid #CCC; +} +table pre.py-doctest { + background: #F2F2F2; + color: #000000; +} +pre.py-src { + border: 1px solid #CCC; + background: #FFF; + color: #000000; + margin: 20px 0; +} +.py-line { + border-left: 1px solid #CCC; + margin-left: .2em; + padding-left: .4em; +} +.py-lineno { + font-style: italic; + font-size: 90%; + padding-left: .5em; +} +a.py-toggle { + text-decoration: none; +} +div.py-highlight-hdr { + border-top: 1px solid #CCC; + border-bottom: 1px solid #CCC; + background: #F2F2F2; +} +div.py-highlight { + border-bottom: 1px solid #CCC; + background: #F2F2F2; +} +.py-prompt { + color: #005050; + font-weight: bold; +} +.py-more { + color: #005050; + font-weight: bold; +} +.py-string { + color: #006030; +} +.py-comment { + color: #003060; +} +.py-keyword { + color: #600000; +} +.py-output { + color: #404040; +} +.py-name { + color: #000050; +} +.py-name:link { + color: #000050 !important; +} +.py-name:visited { + color: #000050 !important; +} +.py-number { + color: #005000; +} +.py-defname { + color: #000060; + font-weight: bold; +} +.py-def-name { + color: #000060; + font-weight: bold; +} +.py-base-class { + color: #000060; +} +.py-param { + color: #000060; +} +.py-docstring { + color: #006030; +} +.py-decorator { + color: #804020; +} + +/* Graphs & Diagrams +* - These CSS styles are used for graphs & diagrams generated using +* Graphviz dot. 'img.graph-without-title' is used for bare +* diagrams (to remove the border created by making the image +* clickable). +*/ +img.graph-without-title { + border: none; +} +img.graph-with-title { + border: 1px solid #000000; +} +span.graph-title { + font-weight: bold; +} + +/* General-purpose classes +* - 'p.indent-wrapped-lines' defines a paragraph whose first line +* is not indented, but whose subsequent lines are. +* - The 'nomargin-top' class is used to remove the top margin (e.g. +* from lists). The 'nomargin' class is used to remove both the +* top and bottom margin (but not the left or right margin -- +* for lists, that would cause the bullets to disappear.) +*/ +p.indent-wrapped-lines { + padding: 0 0 0 7em; + text-indent: -7em; + margin: 0; +} +.nomargin-top { + margin: 20px; +} +.nomargin { + margin-top: 0; + margin-bottom: 0; +} + +/* HTML Log */ +div.log-block { + padding: 0; + margin: .5em 0 .5em 0; + background: #e8f0f8; + color: #000000; + border: 1px solid #000000; +} +div.log-error { + padding: .1em .3em .1em .3em; + margin: 4px; + background: #ffb0b0; + color: #000000; + border: 1px solid #000000; +} +div.log-warning { + padding: .1em .3em .1em .3em; + margin: 4px; + background: #ffffb0; + color: #000000; + border: 1px solid #000000; +} +div.log-info { + padding: .1em .3em .1em .3em; + margin: 4px; + background: #b0ffb0; + color: #000000; + border: 1px solid #000000; +} +h2.log-hdr { + background: #70b0ff; + color: #000000; + margin: 0; + padding: 0em 0.5em 0em 0.5em; + border-bottom: 1px solid #000000; + font-size: 110%; +} +p.log { + font-weight: bold; + margin: .5em 0 .5em 0; +} +tr.opt-changed { + color: #000000; + font-weight: bold; +} +tr.opt-default { + color: #606060; +} +pre.log { + margin: 0; + padding: 0; + padding-left: 1em; +} + +/* Hacks +* This section is reseerved for the really horrible bits. In reality the +* markup generated by epydoc wants a good kickings but a CSS patch is +* better than nothing. Some of this does remove useful links or output +* because finding somewhere to put them on the page wasn't easy. If your +* favourite link has disappeared this is probably the reason. +*/ + +ul ul { + margin-left: 1em; +} +ul ul ul { + margin-left: 2em; +} +ul ul ul ul { + margin-left: 3em; +} +a[target=mainFrame], a[target=moduleFrame] { + margin: 0 10px; +} +h2.toc { + margin-bottom: 10px; +} +h1.toc { + display: none; +} +.options { + display: none; +} +hr, br { + display: none; +} +a[href="toc-everything.html"] { + display: none; +} +.breadcrumbs { + visibility: hidden; +} +.details p { + margin-left: 25px; +} +body > p { + margin: 20px; +}
diff --git a/essential_pkg.yaml b/essential_pkg.yaml new file mode 100644 index 0000000..aa3be8f --- /dev/null +++ b/essential_pkg.yaml
@@ -0,0 +1,11 @@ +package: home_internal/continuous-tests +description: continuous tests config files required for swarming host. +root: . +data: + - dir: lab_system/master/config/device_type + - dir: lab_system/master/config/site + - dir: lab_system/master/config/tests + - dir: catatester/configs/prod + - dir: catatester/genfiles + - file: __init__.py + - file: catatester/__init__.py
diff --git a/lab_system/master/config/android/device_name.json b/lab_system/master/config/android/device_name.json new file mode 100644 index 0000000..8d15d50 --- /dev/null +++ b/lab_system/master/config/android/device_name.json
@@ -0,0 +1,43 @@ +{ + "D6503": "SonyZ2", + "D6616": "SonyZ3", + "E5803": "SonyZ5C", + "E6653": "SonyZ5", + "E6853": "SonyZ5P", + "Yaris5TM0": "Alcatel7040N", + "angler": "Nexus6P", + "bullhead": "Nexus5X", + "d2spr": "S3", + "degaswifiue": "GalaxyTab4", + "dragon": "PixelC", + "e2nam": "OptimusF60", + "e7lte": "GPad7", + "falcon_umts": "MotoG", + "flo": "Nexus7", + "flounder": "Nexus9", + "heroqlteatt": "S7", + "heroqlteusc": "S7", + "hero2qlteatt": "S7Edge", + "g2": "G2", + "g3": "G3", + "hammerhead": "Nexus5", + "herolte": "S7", + "hero2lte": "S7Edge", + "hlteatt": "Note3", + "htc_m8": "M8", + "ja3g": "S4", + "jflteatt": "S4", + "klteatt": "S5", + "lt02ltespr": "GalaxyTab3", + "m7": "M7", + "noblelteatt": "Note5", + "noblelteskt": "Note5", + "shamu": "Nexus6", + "trlteatt": "Note4", + "w5": "OptimusL70", + "w7": "OptimusL90", + "zenlte": "S6EdgePlus", + "zenlteatt": "S6EdgePlus", + "zerolteatt": "S6Edge", + "zeroflteatt": "S6" +}
diff --git a/lab_system/master/config/branch/1_22.cfg b/lab_system/master/config/branch/1_22.cfg new file mode 100644 index 0000000..2de4150 --- /dev/null +++ b/lab_system/master/config/branch/1_22.cfg
@@ -0,0 +1,14 @@ +# Config file for 1.22 branch. +# +# Do not modify property names +# Run make reconfig if you change a value +# while buildbot is running +# +# PROPERTIES + +# Branch name to use in run +BRANCH_NAME=1.22 + +SCHEDULER=45 * * * * + +USE_GN=1
diff --git a/lab_system/master/config/branch/1_26a.cfg b/lab_system/master/config/branch/1_26a.cfg new file mode 100644 index 0000000..e5d6d5b --- /dev/null +++ b/lab_system/master/config/branch/1_26a.cfg
@@ -0,0 +1,15 @@ +# Config file for release branch +# +# Do not modify property names +# Run make reconfig if you change a value +# while buildbot is running +# +# PROPERTIES + +# Branch name to use for the run. Change it to the latest release branch. +BRANCH_NAME=1.26a + +# How often the tests will run +#SCHEDULER=31 0,8,16 * * * + +USE_GN=1
diff --git a/lab_system/master/config/branch/1_27_factory.cfg b/lab_system/master/config/branch/1_27_factory.cfg new file mode 100644 index 0000000..d0040e1 --- /dev/null +++ b/lab_system/master/config/branch/1_27_factory.cfg
@@ -0,0 +1,15 @@ +# Config file for branch for 1.27 Factory build +# +# Do not modify property names +# Run make reconfig if you change a value +# while buildbot is running +# +# PROPERTIES + +# Branch name to use for the run. Change it to the next release branch. +BRANCH_NAME=1.27f + +# How often the tests will run +SCHEDULER=15 */2 * * * + +USE_GN=1
diff --git a/lab_system/master/config/branch/1_28_factory.cfg b/lab_system/master/config/branch/1_28_factory.cfg new file mode 100644 index 0000000..246ff89 --- /dev/null +++ b/lab_system/master/config/branch/1_28_factory.cfg
@@ -0,0 +1,15 @@ +# Config file for branch for 1.28 Factory build +# +# Do not modify property names +# Run make reconfig if you change a value +# while buildbot is running +# +# PROPERTIES + +# Branch name to use for the run. Change it to the next release branch. +BRANCH_NAME=1.28f + +# How often the tests will run +SCHEDULER=15 */2 * * * + +USE_GN=1
diff --git a/lab_system/master/config/branch/1_28a.cfg b/lab_system/master/config/branch/1_28a.cfg new file mode 100644 index 0000000..bcb410b --- /dev/null +++ b/lab_system/master/config/branch/1_28a.cfg
@@ -0,0 +1,15 @@ +# Config file for branch for 1.28a build +# +# Do not modify property names +# Run make reconfig if you change a value +# while buildbot is running +# +# PROPERTIES + +# Branch name to use for the run. Change it to the next release branch. +BRANCH_NAME=1.28a + +# How often the tests will run +SCHEDULER=15 */2 * * * + +USE_GN=1
diff --git a/lab_system/master/config/branch/androidthings_next_release.cfg b/lab_system/master/config/branch/androidthings_next_release.cfg new file mode 100644 index 0000000..0631bee --- /dev/null +++ b/lab_system/master/config/branch/androidthings_next_release.cfg
@@ -0,0 +1,12 @@ +# Config file for AndroidThings next release branch +# +# Do not modify property names +# Run make reconfig if you change a value +# while buildbot is running +# +# PROPERTIES + +# Branch name to use for the run. Change it to the latest release branch. +BRANCH_NAME=1.26at + +USE_GN=1
diff --git a/lab_system/master/config/branch/androidthings_release.cfg b/lab_system/master/config/branch/androidthings_release.cfg new file mode 100644 index 0000000..bfc1ca4 --- /dev/null +++ b/lab_system/master/config/branch/androidthings_release.cfg
@@ -0,0 +1,12 @@ +# Config file for AndroidThings release branch +# +# Do not modify property names +# Run make reconfig if you change a value +# while buildbot is running +# +# PROPERTIES + +# Branch name to use for the run. Change it to the latest release branch. +BRANCH_NAME=1.25at + +USE_GN=1
diff --git a/lab_system/master/config/branch/cast_assistant_reference_master.cfg b/lab_system/master/config/branch/cast_assistant_reference_master.cfg new file mode 100644 index 0000000..7992dfe --- /dev/null +++ b/lab_system/master/config/branch/cast_assistant_reference_master.cfg
@@ -0,0 +1,10 @@ +# Config file for cast assistant reference branch +# +# Do not modify property names +# Run make reconfig if you change a value +# while buildbot is running +# +# PROPERTIES + +# Branch name to use in run +BRANCH_NAME=master
diff --git a/lab_system/master/config/branch/cast_assistant_reference_release.cfg b/lab_system/master/config/branch/cast_assistant_reference_release.cfg new file mode 100644 index 0000000..88fb62b --- /dev/null +++ b/lab_system/master/config/branch/cast_assistant_reference_release.cfg
@@ -0,0 +1,10 @@ +# Config file for cast assistant reference branch +# +# Do not modify property names +# Run make reconfig if you change a value +# while buildbot is running +# +# PROPERTIES + +# Branch name to use in run +BRANCH_NAME=1.26
diff --git a/lab_system/master/config/branch/cast_audio_mediatek_master.cfg b/lab_system/master/config/branch/cast_audio_mediatek_master.cfg new file mode 100644 index 0000000..d09aaf2 --- /dev/null +++ b/lab_system/master/config/branch/cast_audio_mediatek_master.cfg
@@ -0,0 +1,10 @@ +# Config file for cast audio branch +# +# Do not modify property names +# Run make reconfig if you change a value +# while buildbot is running +# +# PROPERTIES + +# Branch name to use in run +BRANCH_NAME=master
diff --git a/lab_system/master/config/branch/cast_audio_mediatek_next_release.cfg b/lab_system/master/config/branch/cast_audio_mediatek_next_release.cfg new file mode 100644 index 0000000..521826c --- /dev/null +++ b/lab_system/master/config/branch/cast_audio_mediatek_next_release.cfg
@@ -0,0 +1,10 @@ +# Config file for cast audio branch +# +# Do not modify property names +# Run make reconfig if you change a value +# while buildbot is running +# +# PROPERTIES + +# Branch name to use in run +BRANCH_NAME=1.27
diff --git a/lab_system/master/config/branch/cast_audio_mediatek_release.cfg b/lab_system/master/config/branch/cast_audio_mediatek_release.cfg new file mode 100644 index 0000000..521826c --- /dev/null +++ b/lab_system/master/config/branch/cast_audio_mediatek_release.cfg
@@ -0,0 +1,10 @@ +# Config file for cast audio branch +# +# Do not modify property names +# Run make reconfig if you change a value +# while buildbot is running +# +# PROPERTIES + +# Branch name to use in run +BRANCH_NAME=1.27
diff --git a/lab_system/master/config/branch/cast_audio_reference_master.cfg b/lab_system/master/config/branch/cast_audio_reference_master.cfg new file mode 100644 index 0000000..6983d58 --- /dev/null +++ b/lab_system/master/config/branch/cast_audio_reference_master.cfg
@@ -0,0 +1,10 @@ +# Config file for cast audio reference branch +# +# Do not modify property names +# Run make reconfig if you change a value +# while buildbot is running +# +# PROPERTIES + +# Branch name to use in run +BRANCH_NAME=master
diff --git a/lab_system/master/config/branch/cast_audio_reference_release.cfg b/lab_system/master/config/branch/cast_audio_reference_release.cfg new file mode 100644 index 0000000..7ac81e9 --- /dev/null +++ b/lab_system/master/config/branch/cast_audio_reference_release.cfg
@@ -0,0 +1,10 @@ +# Config file for cast audio reference branch +# +# Do not modify property names +# Run make reconfig if you change a value +# while buildbot is running +# +# PROPERTIES + +# Branch name to use in run +BRANCH_NAME=1.26
diff --git a/lab_system/master/config/branch/cast_tv_dragonfly_master.cfg b/lab_system/master/config/branch/cast_tv_dragonfly_master.cfg new file mode 100644 index 0000000..1e55e22 --- /dev/null +++ b/lab_system/master/config/branch/cast_tv_dragonfly_master.cfg
@@ -0,0 +1,10 @@ +# Config file for cast tv dragonfly branch +# +# Do not modify property names +# Run make reconfig if you change a value +# while buildbot is running +# +# PROPERTIES + +# Branch name to use in run +BRANCH_NAME=master
diff --git a/lab_system/master/config/branch/cast_tv_dragonfly_next_release.cfg b/lab_system/master/config/branch/cast_tv_dragonfly_next_release.cfg new file mode 100644 index 0000000..44a09fd --- /dev/null +++ b/lab_system/master/config/branch/cast_tv_dragonfly_next_release.cfg
@@ -0,0 +1,10 @@ +# Config file for cast tv dragonfly branch +# +# Do not modify property names +# Run make reconfig if you change a value +# while buildbot is running +# +# PROPERTIES + +# Branch name to use in run +BRANCH_NAME=1.27
diff --git a/lab_system/master/config/branch/cast_tv_dragonfly_release.cfg b/lab_system/master/config/branch/cast_tv_dragonfly_release.cfg new file mode 100644 index 0000000..dfef1bb --- /dev/null +++ b/lab_system/master/config/branch/cast_tv_dragonfly_release.cfg
@@ -0,0 +1,10 @@ +# Config file for cast tv dragonfly branch +# +# Do not modify property names +# Run make reconfig if you change a value +# while buildbot is running +# +# PROPERTIES + +# Branch name to use in run +BRANCH_NAME=1.26
diff --git a/lab_system/master/config/branch/cast_tv_firefly_master.cfg b/lab_system/master/config/branch/cast_tv_firefly_master.cfg new file mode 100644 index 0000000..ba0646c --- /dev/null +++ b/lab_system/master/config/branch/cast_tv_firefly_master.cfg
@@ -0,0 +1,10 @@ +# Config file for cast tv firefly branch +# +# Do not modify property names +# Run make reconfig if you change a value +# while buildbot is running +# +# PROPERTIES + +# Branch name to use in run +BRANCH_NAME=master
diff --git a/lab_system/master/config/branch/cast_tv_marvell_master.cfg b/lab_system/master/config/branch/cast_tv_marvell_master.cfg new file mode 100644 index 0000000..94cac1b --- /dev/null +++ b/lab_system/master/config/branch/cast_tv_marvell_master.cfg
@@ -0,0 +1,10 @@ +# Config file for cast tv marvell branch +# +# Do not modify property names +# Run make reconfig if you change a value +# while buildbot is running +# +# PROPERTIES + +# Branch name to use in run +BRANCH_NAME=master
diff --git a/lab_system/master/config/branch/cast_tv_marvell_next_release.cfg b/lab_system/master/config/branch/cast_tv_marvell_next_release.cfg new file mode 100644 index 0000000..6222f37 --- /dev/null +++ b/lab_system/master/config/branch/cast_tv_marvell_next_release.cfg
@@ -0,0 +1,10 @@ +# Config file for cast tv marvell branch +# +# Do not modify property names +# Run make reconfig if you change a value +# while buildbot is running +# +# PROPERTIES + +# Branch name to use in run +BRANCH_NAME=1.27
diff --git a/lab_system/master/config/branch/cast_tv_marvell_release.cfg b/lab_system/master/config/branch/cast_tv_marvell_release.cfg new file mode 100644 index 0000000..6fdc7e3 --- /dev/null +++ b/lab_system/master/config/branch/cast_tv_marvell_release.cfg
@@ -0,0 +1,10 @@ +# Config file for cast tv marvell branch +# +# Do not modify property names +# Run make reconfig if you change a value +# while buildbot is running +# +# PROPERTIES + +# Branch name to use in run +BRANCH_NAME=1.26
diff --git a/lab_system/master/config/branch/cast_tv_mediatek_master.cfg b/lab_system/master/config/branch/cast_tv_mediatek_master.cfg new file mode 100644 index 0000000..ba1b613 --- /dev/null +++ b/lab_system/master/config/branch/cast_tv_mediatek_master.cfg
@@ -0,0 +1,10 @@ +# Config file for cast tv Mars_US branch +# +# Do not modify property names +# Run make reconfig if you change a value +# while buildbot is running +# +# PROPERTIES + +# Branch name to use in run +BRANCH_NAME=master
diff --git a/lab_system/master/config/branch/cast_tv_mediatek_next_release.cfg b/lab_system/master/config/branch/cast_tv_mediatek_next_release.cfg new file mode 100644 index 0000000..c153155 --- /dev/null +++ b/lab_system/master/config/branch/cast_tv_mediatek_next_release.cfg
@@ -0,0 +1,10 @@ +# Config file for cast tv Mars_US branch +# +# Do not modify property names +# Run make reconfig if you change a value +# while buildbot is running +# +# PROPERTIES + +# Branch name to use in run +BRANCH_NAME=1.27
diff --git a/lab_system/master/config/branch/cast_tv_mediatek_release.cfg b/lab_system/master/config/branch/cast_tv_mediatek_release.cfg new file mode 100644 index 0000000..c4cd4d1 --- /dev/null +++ b/lab_system/master/config/branch/cast_tv_mediatek_release.cfg
@@ -0,0 +1,10 @@ +# Config file for cast tv Mars_US branch +# +# Do not modify property names +# Run make reconfig if you change a value +# while buildbot is running +# +# PROPERTIES + +# Branch name to use in run +BRANCH_NAME=1.26
diff --git a/lab_system/master/config/branch/cast_tv_mstar_master.cfg b/lab_system/master/config/branch/cast_tv_mstar_master.cfg new file mode 100644 index 0000000..dcd749e --- /dev/null +++ b/lab_system/master/config/branch/cast_tv_mstar_master.cfg
@@ -0,0 +1,10 @@ +# Config file for cast tv bubbletea branch +# +# Do not modify property names +# Run make reconfig if you change a value +# while buildbot is running +# +# PROPERTIES + +# Branch name to use in run +BRANCH_NAME=master
diff --git a/lab_system/master/config/branch/cast_tv_mstar_next_release.cfg b/lab_system/master/config/branch/cast_tv_mstar_next_release.cfg new file mode 100644 index 0000000..aaa5c6a --- /dev/null +++ b/lab_system/master/config/branch/cast_tv_mstar_next_release.cfg
@@ -0,0 +1,10 @@ +# Config file for cast tv bubbletea branch +# +# Do not modify property names +# Run make reconfig if you change a value +# while buildbot is running +# +# PROPERTIES + +# Branch name to use in run +BRANCH_NAME=1.27
diff --git a/lab_system/master/config/branch/cast_tv_mstar_release.cfg b/lab_system/master/config/branch/cast_tv_mstar_release.cfg new file mode 100644 index 0000000..e982a38 --- /dev/null +++ b/lab_system/master/config/branch/cast_tv_mstar_release.cfg
@@ -0,0 +1,10 @@ +# Config file for cast tv bubbletea branch +# +# Do not modify property names +# Run make reconfig if you change a value +# while buildbot is running +# +# PROPERTIES + +# Branch name to use in run +BRANCH_NAME=1.26
diff --git a/lab_system/master/config/branch/cast_tv_novatek_master.cfg b/lab_system/master/config/branch/cast_tv_novatek_master.cfg new file mode 100644 index 0000000..3d97fa7 --- /dev/null +++ b/lab_system/master/config/branch/cast_tv_novatek_master.cfg
@@ -0,0 +1,10 @@ +# Config file for cast tv master branch +# +# Do not modify property names +# Run make reconfig if you change a value +# while buildbot is running +# +# PROPERTIES + +# Branch name to use in run +BRANCH_NAME=master
diff --git a/lab_system/master/config/branch/cast_tv_novatek_next_release.cfg b/lab_system/master/config/branch/cast_tv_novatek_next_release.cfg new file mode 100644 index 0000000..a1e81b5 --- /dev/null +++ b/lab_system/master/config/branch/cast_tv_novatek_next_release.cfg
@@ -0,0 +1,10 @@ +# Config file for cast tv next release branch +# +# Do not modify property names +# Run make reconfig if you change a value +# while buildbot is running +# +# PROPERTIES + +# Branch name to use in run +BRANCH_NAME=1.27
diff --git a/lab_system/master/config/branch/cast_tv_novatek_release.cfg b/lab_system/master/config/branch/cast_tv_novatek_release.cfg new file mode 100644 index 0000000..0776912 --- /dev/null +++ b/lab_system/master/config/branch/cast_tv_novatek_release.cfg
@@ -0,0 +1,10 @@ +# Config file for cast tv release branch +# +# Do not modify property names +# Run make reconfig if you change a value +# while buildbot is running +# +# PROPERTIES + +# Branch name to use in run +BRANCH_NAME=1.26
diff --git a/lab_system/master/config/branch/dogfood.cfg b/lab_system/master/config/branch/dogfood.cfg new file mode 100644 index 0000000..a3cab64 --- /dev/null +++ b/lab_system/master/config/branch/dogfood.cfg
@@ -0,0 +1,18 @@ +# Config file for dogfood branches +# +# Do not modify property names +# Run make reconfig if you change a value +# while buildbot is running +# +# PROPERTIES + +# Branch name to use in the run. Change it to the latest release branch. +BRANCH_NAME=dogfood-release + +# Mirroring test chrome build +CHROME_BUILD=33.0.1750.112 +# Mirroring test extension version +EXTENSION_VERSION=2.2014.10215.10042 + +# How often tests on the branch will run +SCHEDULER=10 12 * * 0
diff --git a/lab_system/master/config/branch/klp-modular-dev.cfg b/lab_system/master/config/branch/klp-modular-dev.cfg new file mode 100644 index 0000000..37a4f1e --- /dev/null +++ b/lab_system/master/config/branch/klp-modular-dev.cfg
@@ -0,0 +1,10 @@ +# Config file for molly branch +# +# Do not modify property names +# Run make reconfig if you change a value +# while buildbot is running +# +# PROPERTIES + +# Branch name to use in run +BRANCH_NAME=master
diff --git a/lab_system/master/config/branch/master.cfg b/lab_system/master/config/branch/master.cfg new file mode 100644 index 0000000..834434d --- /dev/null +++ b/lab_system/master/config/branch/master.cfg
@@ -0,0 +1,14 @@ +# Config file for master branch +# +# Do not modify property names +# Run make reconfig if you change a value +# while buildbot is running +# +# PROPERTIES + +# Branch name to use in run +BRANCH_NAME=master + +SCHEDULER=31 * * * * + +USE_GN=1
diff --git a/lab_system/master/config/branch/mirroring_earth_on_demand.cfg b/lab_system/master/config/branch/mirroring_earth_on_demand.cfg new file mode 100644 index 0000000..d72c544 --- /dev/null +++ b/lab_system/master/config/branch/mirroring_earth_on_demand.cfg
@@ -0,0 +1,14 @@ +# Config file for Whitelist on_demand branch +# +# Do not modify property names +# Run make reconfig if you change a value +# while buildbot is running +# +# PROPERTIES + +# Branch name and build number match the current production release. +BRANCH_NAME=1.30 +BUILD=113131 + +# on demand branch will only run when forced. +SCHEDULER=None
diff --git a/lab_system/master/config/branch/mirroring_eureka_on_demand.cfg b/lab_system/master/config/branch/mirroring_eureka_on_demand.cfg new file mode 100644 index 0000000..d72c544 --- /dev/null +++ b/lab_system/master/config/branch/mirroring_eureka_on_demand.cfg
@@ -0,0 +1,14 @@ +# Config file for Whitelist on_demand branch +# +# Do not modify property names +# Run make reconfig if you change a value +# while buildbot is running +# +# PROPERTIES + +# Branch name and build number match the current production release. +BRANCH_NAME=1.30 +BUILD=113131 + +# on demand branch will only run when forced. +SCHEDULER=None
diff --git a/lab_system/master/config/branch/mirroring_lexx_on_demand.cfg b/lab_system/master/config/branch/mirroring_lexx_on_demand.cfg new file mode 100644 index 0000000..d72c544 --- /dev/null +++ b/lab_system/master/config/branch/mirroring_lexx_on_demand.cfg
@@ -0,0 +1,14 @@ +# Config file for Whitelist on_demand branch +# +# Do not modify property names +# Run make reconfig if you change a value +# while buildbot is running +# +# PROPERTIES + +# Branch name and build number match the current production release. +BRANCH_NAME=1.30 +BUILD=113131 + +# on demand branch will only run when forced. +SCHEDULER=None
diff --git a/lab_system/master/config/branch/mirroring_luther_on_demand.cfg b/lab_system/master/config/branch/mirroring_luther_on_demand.cfg new file mode 100644 index 0000000..d72c544 --- /dev/null +++ b/lab_system/master/config/branch/mirroring_luther_on_demand.cfg
@@ -0,0 +1,14 @@ +# Config file for Whitelist on_demand branch +# +# Do not modify property names +# Run make reconfig if you change a value +# while buildbot is running +# +# PROPERTIES + +# Branch name and build number match the current production release. +BRANCH_NAME=1.30 +BUILD=113131 + +# on demand branch will only run when forced. +SCHEDULER=None
diff --git a/lab_system/master/config/branch/next_release.cfg b/lab_system/master/config/branch/next_release.cfg new file mode 100644 index 0000000..b7f1978 --- /dev/null +++ b/lab_system/master/config/branch/next_release.cfg
@@ -0,0 +1,15 @@ +# Config file for branch for the next release +# +# Do not modify property names +# Run make reconfig if you change a value +# while buildbot is running +# +# PROPERTIES + +# Branch name to use for the run. Change it to the next release branch. +BRANCH_NAME=1.32 + +# How often the tests will run +SCHEDULER=15 */2 * * * + +USE_GN=1
diff --git a/lab_system/master/config/branch/on_demand.cfg b/lab_system/master/config/branch/on_demand.cfg new file mode 100644 index 0000000..660ab59 --- /dev/null +++ b/lab_system/master/config/branch/on_demand.cfg
@@ -0,0 +1,13 @@ +# Config file for on_demand branch +# +# Do not modify property names +# Run make reconfig if you change a value +# while buildbot is running +# +# PROPERTIES + +# Branch name to use in the run. +BRANCH_NAME=1.26 + +# on demand branch will only run when forced. +SCHEDULER=None
diff --git a/lab_system/master/config/branch/release.cfg b/lab_system/master/config/branch/release.cfg new file mode 100644 index 0000000..b15a507 --- /dev/null +++ b/lab_system/master/config/branch/release.cfg
@@ -0,0 +1,15 @@ +# Config file for release branch +# +# Do not modify property names +# Run make reconfig if you change a value +# while buildbot is running +# +# PROPERTIES + +# Branch name to use for the run. Change it to the latest release branch. +BRANCH_NAME=1.31 + +# How often the tests will run +#SCHEDULER=31 0,8,16 * * * + +USE_GN=1
diff --git a/lab_system/master/config/buildbot/multi_master_config.json b/lab_system/master/config/buildbot/multi_master_config.json new file mode 100644 index 0000000..3c94baa --- /dev/null +++ b/lab_system/master/config/buildbot/multi_master_config.json
@@ -0,0 +1,197 @@ +{ + "home-platform-infra-14.cbf.corp.google.com": { + "database_ip": "173.194.227.201", + "database_name": "home_platform_infra_14", + "multi_master": false, + "slaves": { + "home-platform-infra-14.cbf.corp.google.com": [ + "apps_launch_monitor", + "app_prelaunch", + "bluetooth_a2dp", + "build_upgrade", + "cloudcast", + "cpu_load", + "js_features" + ] + } + }, + "home-platform-infra-16.cbf.corp.google.com": { + "database_ip": "173.194.227.201", + "database_name": "home_platform_infra_16", + "multi_master": false, + "slaves": { + "home-platform-infra-16.cbf.corp.google.com": [ + "assistant_remote_casting" + ] + } + }, + "home-lab-ci-master-1.mtv.corp.google.com": { + "database_ip": "173.194.227.201", + "multi_master": false, + "slaves": { + "home-lab-ci-slave-3.mtv.corp.google.com": [ + "monitoring", + "uma_logging_wifi", + "webgl_conformance", + "factory" + ], + "home-lab-ci-slave-1.mtv.corp.google.com": [ + "e2e_latency", + "eraser_for_hotword", + "hotword_detection_latency", + "hotword_samples_regression", + "hotwording", + "imax" + ], + "home-lab-ci-slave-2.mtv.corp.google.com": [ + "multizone", + "octane", + "preview_test", + "tdls_test", + "uma_logging" + ], + "home-lab-ci-master-1.mtv.corp.google.com": [ + "testingrepounittests" + ] + } + }, + "cast-lab-infra-1.mtv.corp.google.com": { + "database_ip": "173.194.106.223", + "multi_master": false, + "slaves": { + "cast-lab-infra-1.mtv.corp.google.com": [ + "cast_tv_unit_test", + "audiodefault_unit_test" + ] + } + }, + "cast-lab-infra-20.mtv.corp.google.com": { + "database_ip": "173.194.106.223", + "database_name": "cast_lab_infra_20", + "multi_master": false, + "slaves": { + "cast-lab-infra-20.mtv.corp.google.com": [ + "cast_tv_unit_test", + "audiodefault_unit_test" + ] + } + }, + "cast-lab-infra-10.mtv.corp.google.com": { + "database_ip": "173.194.106.223", + "database_name": "unit_test", + "is_scheduler": true, + "multi_master": true + }, + "cast-lab-infra-2.mtv.corp.google.com": { + "database_ip": "173.194.227.201", + "multi_master": false, + "slaves": { + "cast-lab-infra-2.mtv.corp.google.com": [ + "android_mirroring", + "android_mirroring_uma" + ] + } + }, + "cast-lab-infra-12.mtv.corp.google.com": { + "database_ip": "173.194.227.201", + "database_name": "cast_lab_infra_12", + "multi_master": false, + "slaves": { + "cast-lab-infra-12.mtv.corp.google.com": [ + "android_mirroring", + "android_mirroring_uma" + ] + } + }, + "cast-lab-infra-3.mtv.corp.google.com": { + "database_ip": "173.194.106.223", + "database_name": "cast_lab_infra_3_mtv_corp_google_com", + "multi_master": false, + "slaves": { + "cast-lab-infra-3.mtv.corp.google.com": [ + "ota_installable" + ] + } + }, + "cast-lab-infra-13.mtv.corp.google.com": { + "database_ip": "173.194.106.223", + "database_name": "cast_lab_infra_13", + "multi_master": false, + "slaves": { + "cast-lab-infra-13.mtv.corp.google.com": [ + "ota_installable" + ] + } + }, + "cast-lab-infra-7.mtv.corp.google.com": { + "database_ip": "173.194.106.223", + "database_name": "unit_test", + "is_scheduler": false, + "multi_master": true, + "slaves": { + "cast-lab-infra-7.mtv.corp.google.com": [ + "ota_installable" + ] + } + }, + "cast-lab-infra-17.mtv.corp.google.com": { + "database_ip": "173.194.106.223", + "database_name": "unit_test_prod", + "is_scheduler": false, + "multi_master": true, + "slaves": { + "cast-lab-infra-17.mtv.corp.google.com": [ + "ota_installable" + ] + } + }, + "cast-lab-infra-9.mtv.corp.google.com": { + "database_ip": "173.194.106.223", + "database_name": "unit_test", + "is_scheduler": true, + "multi_master": true + }, + "cast-lab-infra-19.mtv.corp.google.com": { + "database_ip": "173.194.106.223", + "database_name": "unit_test_prod", + "is_scheduler": true, + "multi_master": true + }, + "home-platform-infra-18.cbf.corp.google.com": { + "database_ip": "173.194.106.223", + "database_name": "home_platform_infra_18", + "multi_master": false, + "slaves": { + "home-platform-infra-18.cbf.corp.google.com": [ + "atv_unit_test", + "cast_atv", + "androidthings_unit_test", + "cast_androidthings" + ] + } + }, + "home-platform-infra-19.cbf.corp.google.com": { + "database_ip": "173.194.106.223", + "database_name": "home_platform_infra_19", + "multi_master": false, + "slaves": { + "home-platform-infra-19.cbf.corp.google.com": [ + "cast_tv_unit_test", + "audiodefault_unit_test" + ] + } + }, + "home-platform-infra-20.cbf.corp.google.com": { + "database_ip": "173.194.106.223", + "database_name": "home_platform_infra_20", + "multi_master": false, + "slaves": { + "home-platform-infra-20.cbf.corp.google.com": [ + "atv_unit_test", + "cast_atv", + "androidthings_unit_test", + "cast_androidthings" + ] + } + } +}
diff --git a/lab_system/master/config/device_monitoring/excluded_device_list.txt b/lab_system/master/config/device_monitoring/excluded_device_list.txt new file mode 100644 index 0000000..be0cc4c --- /dev/null +++ b/lab_system/master/config/device_monitoring/excluded_device_list.txt
@@ -0,0 +1,34 @@ +100.107.130.239 +100.107.130.240 +100.107.130.241 +100.107.130.242 +100.107.131.10 +100.107.131.16 +100.107.131.19 +100.107.131.20 +100.107.131.214 +100.107.131.3 +100.107.131.4 +100.107.131.45 +100.107.131.70 +100.107.131.74 +100.107.131.75 +100.107.131.79 +100.107.131.8 +172.17.21.159 +172.17.21.167 +172.17.21.188 +172.17.21.197 +172.17.21.226 +172.17.21.234 +172.17.21.55 +172.17.21.71 +172.17.23.117 +172.17.23.172 +172.17.23.189 +172.17.23.210 +172.17.23.249 +172.17.23.28 +172.17.23.72 +172.17.23.80 +172.27.28.207
diff --git a/lab_system/master/config/device_monitoring/query_all_devices.sql b/lab_system/master/config/device_monitoring/query_all_devices.sql new file mode 100644 index 0000000..5218523 --- /dev/null +++ b/lab_system/master/config/device_monitoring/query_all_devices.sql
@@ -0,0 +1,2 @@ +--Query device with unit test device type +select ip, type_name from ((select mac, ip, type_name, network_interface.device_id as id from network_interface join (select type_name, device.device_id from device where status != 3) as temp on network_interface.device_id=temp.device_id where ip != '' and type_name in %s) as foo join (select interface_mac, device_group_id from interface_group) as temp2 on mac=interface_mac) where ip not in %s;
diff --git a/lab_system/master/config/device_monitoring/query_unit_test_devices.sql b/lab_system/master/config/device_monitoring/query_unit_test_devices.sql new file mode 100644 index 0000000..4622e0e --- /dev/null +++ b/lab_system/master/config/device_monitoring/query_unit_test_devices.sql
@@ -0,0 +1,2 @@ +--Query device with unit test device type +select ip, type_name from ((select mac, ip, type_name, network_interface.device_id as id from network_interface join (select type_name, device.device_id from device where status != 3) as temp on network_interface.device_id=temp.device_id where ip != '' and type_name in %s) as foo join (select interface_mac, device_group_id from interface_group) as temp2 on mac=interface_mac and device_group_id=(select device_group_id from device_group where group_name='unit_test' limit 1)) where ip not in %s;
diff --git a/lab_system/master/config/device_monitoring/unit_test_type_list.txt b/lab_system/master/config/device_monitoring/unit_test_type_list.txt new file mode 100644 index 0000000..1429059 --- /dev/null +++ b/lab_system/master/config/device_monitoring/unit_test_type_list.txt
@@ -0,0 +1,19 @@ +audiodefault +bubbletea +chirp +chorizo +dragonfly +earth +eureka +guabao +hendrix +lexx +luther +luther_b2 +mars_us +mozart +n00007 +pepperoni +redwood +suncake +taroball
diff --git a/lab_system/master/config/device_type/assistantdefault.cfg b/lab_system/master/config/device_type/assistantdefault.cfg new file mode 100644 index 0000000..bfb87e0 --- /dev/null +++ b/lab_system/master/config/device_type/assistantdefault.cfg
@@ -0,0 +1,36 @@ +# Config file for the assistant reference device +# +# Do not modify the property names +# +# Run make reconfig if you change a value +# and buildbot is running +# +# PROPERTIES + +# name to be used for assistant reference device test +DEVICE_TYPE=assistantdefault + +# ota zip file format is: PRODUCT_NAME-OTA_NAME-BUILD.zip +PRODUCT_NAME=assistantdefault + +# Device module which contains class to control this device. +DEVICE_MODULE=eurtest.device.assistant_device + +# Device class to use to control this device. +DEVICE_CLASS=Assistant + +# Path to build installer +BUILD_INSTALLER_PATH=/usr/local/google/repositories/HEAD/test/ota/ota_update.py + +# Cloud Storage bucket root e.g. gs://gtv-eureka/internal +BUILD_BUCKET_ROOT=gtv-eureka/internal +UNIT_TEST_BUCKET_ROOT=chromecast-unit-test/internal + +# build project name e.g. eureka is "chromecast" +BUILD_PROJECT_NAME=chromecast + +# Unique repository name for this product +REPO_ALIAS=internal + +# The board type to get the latest build +BOARD_TYPE=none
diff --git a/lab_system/master/config/device_type/astro_migration.cfg b/lab_system/master/config/device_type/astro_migration.cfg new file mode 100644 index 0000000..2f0f9cf --- /dev/null +++ b/lab_system/master/config/device_type/astro_migration.cfg
@@ -0,0 +1,40 @@ +# Config file for astro_migration device type +# Copied from estelle.cfg +# +# Do not modify the property names +# +# Run make reconfig if you change a value +# and buildbot is running +# +# PROPERTIES + +# name to be used for tests +DEVICE_TYPE=astro_migration + +# ota zip file format is: PRODUCT_NAME-OTA_NAME-BUILD.zip +PRODUCT_NAME=estelle + +# Device module which contains class to control this device. +DEVICE_MODULE=udm.device.astro_migration + +# Device class to use to control this device. +DEVICE_CLASS=AstroMigration + +# Path to build installer +BUILD_INSTALLER_PATH=/usr/local/google/repositories/HEAD/test/ota/ota_update.py + +# Platform version +PLATFORM_VERSION=2.0 + +# Cloud Storage bucket root e.g. gs://gtv-eureka/internal +BUILD_BUCKET_ROOT=gtv-eureka/internal +UNIT_TEST_BUCKET_ROOT=chromecast-unit-test/internal + +# build project name e.g. eureka is "chromecast" +BUILD_PROJECT_NAME=chromecast + +# Unique repository name for this product +REPO_ALIAS=internal + +# The board type to get the latest build +BOARD_TYPE=estelle-b3
diff --git a/lab_system/master/config/device_type/audiodefault.cfg b/lab_system/master/config/device_type/audiodefault.cfg new file mode 100644 index 0000000..757f871 --- /dev/null +++ b/lab_system/master/config/device_type/audiodefault.cfg
@@ -0,0 +1,36 @@ +# Config file for cast audio reference device +# +# Do not modify the property names +# +# Run make reconfig if you change a value +# and buildbot is running +# +# PROPERTIES + +# name to be used for audio reference device test, usually audiodefault +DEVICE_TYPE=audiodefault + +# ota zip file format is: PRODUCT_NAME-OTA_NAME-BUILD.zip +PRODUCT_NAME=audiodefault + +# Device module which contains class to control this device. +DEVICE_MODULE=eurtest.device.device + +# Device class to use to control this device. +DEVICE_CLASS=Device + +# Path to build installer +BUILD_INSTALLER_PATH=/usr/local/google/repositories/HEAD/test/ota/ota_update.py + +# Cloud Storage bucket root e.g. gs://gtv-eureka/internal +BUILD_BUCKET_ROOT=gtv-eureka/cast_audio_reference +UNIT_TEST_BUCKET_ROOT=chromecast-unit-test/cast_audio_reference + +# build project name e.g. eureka is "chromecast" +BUILD_PROJECT_NAME=tv + +# Unique repository name for this product +REPO_ALIAS=cast_audio_reference + +# The board type to get the latest build +BOARD_TYPE=none
diff --git a/lab_system/master/config/device_type/biggie.cfg b/lab_system/master/config/device_type/biggie.cfg new file mode 100644 index 0000000..23a1d78 --- /dev/null +++ b/lab_system/master/config/device_type/biggie.cfg
@@ -0,0 +1,39 @@ +# Config file for Biggie device type +# +# Do not modify the property names +# +# Run make reconfig if you change a value +# and buildbot is running +# +# PROPERTIES + +# name to be used for tests +DEVICE_TYPE=biggie + +# ota zip file format is: PRODUCT_NAME-OTA_NAME-BUILD.zip +PRODUCT_NAME=biggie + +# Device module which contains class to control this device. +DEVICE_MODULE=eurtest.device.assistant_device + +# Device class to use to control this device. +DEVICE_CLASS=Assistant + +# Path to build installer +BUILD_INSTALLER_PATH=/usr/local/google/repositories/HEAD/test/ota/ota_update.py + +# Platform version +PLATFORM_VERSION=2.0 + +# Cloud Storage bucket root e.g. gs://gtv-eureka/internal +BUILD_BUCKET_ROOT=gtv-eureka/internal +UNIT_TEST_BUCKET_ROOT=chromecast-unit-test/internal + +# build project name e.g. eureka is "chromecast" +BUILD_PROJECT_NAME=chromecast + +# Unique repository name for this product +REPO_ALIAS=internal + +# The board type to get the latest build +BOARD_TYPE=biggie-b1
diff --git a/lab_system/master/config/device_type/biggie_b3.cfg b/lab_system/master/config/device_type/biggie_b3.cfg new file mode 100644 index 0000000..2741148 --- /dev/null +++ b/lab_system/master/config/device_type/biggie_b3.cfg
@@ -0,0 +1,39 @@ +# Config file for Biggie device type +# +# Do not modify the property names +# +# Run make reconfig if you change a value +# and buildbot is running +# +# PROPERTIES + +# name to be used for tests +DEVICE_TYPE=biggie_b3 + +# ota zip file format is: PRODUCT_NAME-OTA_NAME-BUILD.zip +PRODUCT_NAME=biggie + +# Device module which contains class to control this device. +DEVICE_MODULE=eurtest.device.assistant_device + +# Device class to use to control this device. +DEVICE_CLASS=Assistant + +# Path to build installer +BUILD_INSTALLER_PATH=/usr/local/google/repositories/HEAD/test/ota/ota_update.py + +# Platform version +PLATFORM_VERSION=2.0 + +# Cloud Storage bucket root e.g. gs://gtv-eureka/internal +BUILD_BUCKET_ROOT=gtv-eureka/internal +UNIT_TEST_BUCKET_ROOT=chromecast-unit-test/internal + +# build project name e.g. eureka is "chromecast" +BUILD_PROJECT_NAME=chromecast + +# Unique repository name for this product +REPO_ALIAS=internal + +# The board type to get the latest build +BOARD_TYPE=biggie-b3
diff --git a/lab_system/master/config/device_type/caprica.cfg b/lab_system/master/config/device_type/caprica.cfg new file mode 100644 index 0000000..3704413 --- /dev/null +++ b/lab_system/master/config/device_type/caprica.cfg
@@ -0,0 +1,23 @@ +# Config file for caprica device type +# +# Do not modify the property names +# +# Run make reconfig if you change a value +# and buildbot is running +# +# PROPERTIES + +# name to be used for eureka tests, usually eureka +DEVICE_TYPE=caprica + +# ota zip file format is: PRODUCT_NAME-OTA_NAME-BUILD.zip +PRODUCT_NAME=caprica + +# Device module which contains class to control this device. +DEVICE_MODULE=eurtest.device.device + +# Device class to use to control this device. +DEVICE_CLASS=Device + +# The board type to get the latest build +BOARD_TYPE=caprica-b3
diff --git a/lab_system/master/config/device_type/chirp.cfg b/lab_system/master/config/device_type/chirp.cfg new file mode 100644 index 0000000..ad42ae2 --- /dev/null +++ b/lab_system/master/config/device_type/chirp.cfg
@@ -0,0 +1,36 @@ +# Config file for chirp device type +# +# Do not modify the property names +# +# Run make reconfig if you change a value +# and buildbot is running +# +# PROPERTIES + +# name to be used for eureka tests, usually eureka +DEVICE_TYPE=chirp + +# ota zip file format is: PRODUCT_NAME-OTA_NAME-BUILD.zip +PRODUCT_NAME=pineapple + +# Device module which contains class to control this device. +DEVICE_MODULE=eurtest.device.assistant_device + +# Device class to use to control this device. +DEVICE_CLASS=Assistant + +# Path to build installer +BUILD_INSTALLER_PATH=/usr/local/google/repositories/HEAD/test/ota/ota_update.py + +# Cloud Storage bucket root e.g. gs://gtv-eureka/internal +BUILD_BUCKET_ROOT=gtv-eureka/internal +UNIT_TEST_BUCKET_ROOT=chromecast-unit-test/internal + +# build project name e.g. eureka is "chromecast" +BUILD_PROJECT_NAME=chromecast + +# Unique repository name for this product +REPO_ALIAS=internal + +# The board type to get the latest build +BOARD_TYPE=chirp-b1
diff --git a/lab_system/master/config/device_type/chirp_b3.cfg b/lab_system/master/config/device_type/chirp_b3.cfg new file mode 100644 index 0000000..79ec12c --- /dev/null +++ b/lab_system/master/config/device_type/chirp_b3.cfg
@@ -0,0 +1,36 @@ +# Config file for chirp device type +# +# Do not modify the property names +# +# Run make reconfig if you change a value +# and buildbot is running +# +# PROPERTIES + +# name to be used for eureka tests, usually eureka +DEVICE_TYPE=chirp_b3 + +# ota zip file format is: PRODUCT_NAME-OTA_NAME-BUILD.zip +PRODUCT_NAME=pineapple + +# Device module which contains class to control this device. +DEVICE_MODULE=eurtest.device.assistant_device + +# Device class to use to control this device. +DEVICE_CLASS=Assistant + +# Path to build installer +BUILD_INSTALLER_PATH=/usr/local/google/repositories/HEAD/test/ota/ota_update.py + +# Cloud Storage bucket root e.g. gs://gtv-eureka/internal +BUILD_BUCKET_ROOT=gtv-eureka/internal +UNIT_TEST_BUCKET_ROOT=chromecast-unit-test/internal + +# build project name e.g. eureka is "chromecast" +BUILD_PROJECT_NAME=chromecast + +# Unique repository name for this product +REPO_ALIAS=internal + +# The board type to get the latest build +BOARD_TYPE=chirp-b3
diff --git a/lab_system/master/config/device_type/earth.cfg b/lab_system/master/config/device_type/earth.cfg new file mode 100644 index 0000000..332d187 --- /dev/null +++ b/lab_system/master/config/device_type/earth.cfg
@@ -0,0 +1,36 @@ +# Config file for earth device type +# +# Do not modify the property names +# +# Run make reconfig if you change a value +# and buildbot is running +# +# PROPERTIES + +# name to be used for eureka tests, usually eureka +DEVICE_TYPE=earth + +# ota zip file format is: PRODUCT_NAME-OTA_NAME-BUILD.zip +PRODUCT_NAME=chorizo + +# Device module which contains class to control this device. +DEVICE_MODULE=eurtest.device.device + +# Device class to use to control this device. +DEVICE_CLASS=Device + +# Path to build installer +BUILD_INSTALLER_PATH=/usr/local/google/repositories/HEAD/test/ota/ota_update.py + +# Cloud Storage bucket root e.g. gs://gtv-eureka/internal +BUILD_BUCKET_ROOT=gtv-eureka/internal +UNIT_TEST_BUCKET_ROOT=chromecast-unit-test/internal + +# build project name e.g. eureka is "chromecast" +BUILD_PROJECT_NAME=chromecast + +# Unique repository name for this product +REPO_ALIAS=internal + +# The board type to get the latest build +BOARD_TYPE=earth-b3
diff --git a/lab_system/master/config/device_type/elaine.cfg b/lab_system/master/config/device_type/elaine.cfg new file mode 100644 index 0000000..d027d1d --- /dev/null +++ b/lab_system/master/config/device_type/elaine.cfg
@@ -0,0 +1,39 @@ +# Config file for elaine device type +# +# Do not modify the property names +# +# Run make reconfig if you change a value +# and buildbot is running +# +# PROPERTIES + +# name to be used for tests +DEVICE_TYPE=elaine + +# ota zip file format is: PRODUCT_NAME-OTA_NAME-BUILD.zip +PRODUCT_NAME=elaine + +# Device module which contains class to control this device. +DEVICE_MODULE=eurtest.device.assistant_device + +# Device class to use to control this device. +DEVICE_CLASS=Assistant + +# Path to build installer +BUILD_INSTALLER_PATH=/usr/local/google/repositories/HEAD/test/ota/ota_update.py + +# Platform version +PLATFORM_VERSION=2.0 + +# Cloud Storage bucket root e.g. gs://gtv-eureka/internal +BUILD_BUCKET_ROOT=gtv-eureka/internal +UNIT_TEST_BUCKET_ROOT=chromecast-unit-test/internal + +# build project name e.g. eureka is "chromecast" +BUILD_PROJECT_NAME=chromecast + +# Unique repository name for this product +REPO_ALIAS=internal + +# The board type to get the latest build +BOARD_TYPE=elaine-b1
diff --git a/lab_system/master/config/device_type/estelle.cfg b/lab_system/master/config/device_type/estelle.cfg new file mode 100644 index 0000000..e453dd1 --- /dev/null +++ b/lab_system/master/config/device_type/estelle.cfg
@@ -0,0 +1,39 @@ +# Config file for estelle device type +# +# Do not modify the property names +# +# Run make reconfig if you change a value +# and buildbot is running +# +# PROPERTIES + +# name to be used for tests +DEVICE_TYPE=estelle + +# ota zip file format is: PRODUCT_NAME-OTA_NAME-BUILD.zip +PRODUCT_NAME=estelle + +# Device module which contains class to control this device. +DEVICE_MODULE=eurtest.device.assistant_device + +# Device class to use to control this device. +DEVICE_CLASS=Assistant + +# Path to build installer +BUILD_INSTALLER_PATH=/usr/local/google/repositories/HEAD/test/ota/ota_update.py + +# Platform version +PLATFORM_VERSION=2.0 + +# Cloud Storage bucket root e.g. gs://gtv-eureka/internal +BUILD_BUCKET_ROOT=gtv-eureka/internal +UNIT_TEST_BUCKET_ROOT=chromecast-unit-test/internal + +# build project name e.g. eureka is "chromecast" +BUILD_PROJECT_NAME=chromecast + +# Unique repository name for this product +REPO_ALIAS=internal + +# The board type to get the latest build +BOARD_TYPE=estelle-p0
diff --git a/lab_system/master/config/device_type/eureka.cfg b/lab_system/master/config/device_type/eureka.cfg new file mode 100644 index 0000000..ec0a10f --- /dev/null +++ b/lab_system/master/config/device_type/eureka.cfg
@@ -0,0 +1,36 @@ +# Config file for eureka device type +# +# Do not modify the property names +# +# Run make reconfig if you change a value +# and buildbot is running +# +# PROPERTIES + +# name to be used for eureka tests, usually eureka +DEVICE_TYPE=eureka + +# ota zip file format is: PRODUCT_NAME-OTA_NAME-BUILD.zip +PRODUCT_NAME=anchovy + +# Device module which contains class to control this device. +DEVICE_MODULE=eurtest.device.device + +# Device class to use to control this device. +DEVICE_CLASS=Device + +# Path to build installer +BUILD_INSTALLER_PATH=/usr/local/google/repositories/HEAD/test/ota/ota_update.py + +# Cloud Storage bucket root e.g. gs://gtv-eureka/internal +BUILD_BUCKET_ROOT=gtv-eureka/internal +UNIT_TEST_BUCKET_ROOT=chromecast-unit-test/internal + +# build project name e.g. eureka is "chromecast" +BUILD_PROJECT_NAME=chromecast + +# Unique repository name for this product +REPO_ALIAS=internal + +# Board type +BOARD_TYPE=eureka-b1
diff --git a/lab_system/master/config/device_type/hendrix.cfg b/lab_system/master/config/device_type/hendrix.cfg new file mode 100644 index 0000000..cc71a7a --- /dev/null +++ b/lab_system/master/config/device_type/hendrix.cfg
@@ -0,0 +1,36 @@ +# Config file for earth device type +# +# Do not modify the property names +# +# Run make reconfig if you change a value +# and buildbot is running +# +# PROPERTIES + +# name to be used for eureka tests, usually eureka +DEVICE_TYPE=hendrix + +# ota zip file format is: PRODUCT_NAME-OTA_NAME-BUILD.zip +PRODUCT_NAME=pepperoni + +# Device module which contains class to control this device. +DEVICE_MODULE=eurtest.device.chromecast_audio + +# Device class to use to control this device. +DEVICE_CLASS=ChromecastAudio + +# Path to build installer +BUILD_INSTALLER_PATH=/usr/local/google/repositories/HEAD/test/ota/ota_update.py + +# Cloud Storage bucket root e.g. gs://gtv-eureka/internal +BUILD_BUCKET_ROOT=gtv-eureka/internal +UNIT_TEST_BUCKET_ROOT=chromecast-unit-test/internal + +# build project name e.g. eureka is "chromecast" +BUILD_PROJECT_NAME=chromecast + +# Unique repository name for this product +REPO_ALIAS=internal + +# The board type to get the latest build +BOARD_TYPE=hendrix-b3
diff --git a/lab_system/master/config/device_type/joplin.cfg b/lab_system/master/config/device_type/joplin.cfg new file mode 100644 index 0000000..b75ad34 --- /dev/null +++ b/lab_system/master/config/device_type/joplin.cfg
@@ -0,0 +1,39 @@ +# Config file for joplin device type +# +# Do not modify the property names +# +# Run make reconfig if you change a value +# and buildbot is running +# +# PROPERTIES + +# name to be used for tests +DEVICE_TYPE=joplin + +# ota zip file format is: PRODUCT_NAME-OTA_NAME-BUILD.zip +PRODUCT_NAME=mushroom + +# Device module which contains class to control this device. +DEVICE_MODULE=eurtest.device.assistant_device + +# Device class to use to control this device. +DEVICE_CLASS=Assistant + +# Path to build installer +BUILD_INSTALLER_PATH=/usr/local/google/repositories/HEAD/test/ota/ota_update.py + +# Platform version +PLATFORM_VERSION=2.0 + +# Cloud Storage bucket root e.g. gs://gtv-eureka/internal +BUILD_BUCKET_ROOT=gtv-eureka/internal +UNIT_TEST_BUCKET_ROOT=chromecast-unit-test/internal + +# build project name e.g. eureka is "chromecast" +BUILD_PROJECT_NAME=chromecast + +# Unique repository name for this product +REPO_ALIAS=internal + +# The board type to get the latest build +BOARD_TYPE=joplin-b1
diff --git a/lab_system/master/config/device_type/lexx.cfg b/lab_system/master/config/device_type/lexx.cfg new file mode 100644 index 0000000..0ebc5a1 --- /dev/null +++ b/lab_system/master/config/device_type/lexx.cfg
@@ -0,0 +1,39 @@ +# Config file for lexx device type +# +# Do not modify the property names +# +# Run make reconfig if you change a value +# and buildbot is running +# +# PROPERTIES + +# name to be used for tests +DEVICE_TYPE=lexx + +# ota zip file format is: PRODUCT_NAME-OTA_NAME-BUILD.zip +PRODUCT_NAME=salami + +# Device module which contains class to control this device. +DEVICE_MODULE=eurtest.device.device + +# Device class to use to control this device. +DEVICE_CLASS=Device + +# Path to build installer +BUILD_INSTALLER_PATH=/usr/local/google/repositories/HEAD/test/ota/ota_update.py + +# Platform version +PLATFORM_VERSION=2.0 + +# Cloud Storage bucket root e.g. gs://gtv-eureka/internal +BUILD_BUCKET_ROOT=gtv-eureka/internal +UNIT_TEST_BUCKET_ROOT=chromecast-unit-test/internal + +# build project name e.g. eureka is "chromecast" +BUILD_PROJECT_NAME=chromecast + +# Unique repository name for this product +REPO_ALIAS=internal + +# The board type to get the latest build +BOARD_TYPE=lexx-b3
diff --git a/lab_system/master/config/device_type/luther.cfg b/lab_system/master/config/device_type/luther.cfg new file mode 100644 index 0000000..fe0c076 --- /dev/null +++ b/lab_system/master/config/device_type/luther.cfg
@@ -0,0 +1,39 @@ +# Config file for luther device type +# +# Do not modify the property names +# +# Run make reconfig if you change a value +# and buildbot is running +# +# PROPERTIES + +# name to be used for tests +DEVICE_TYPE=luther_b2 + +# ota zip file format is: PRODUCT_NAME-OTA_NAME-BUILD.zip +PRODUCT_NAME=steak + +# Device module which contains class to control this device. +DEVICE_MODULE=eurtest.device.device + +# Device class to use to control this device. +DEVICE_CLASS=Device + +# Path to build installer. +BUILD_INSTALLER_PATH=/usr/local/google/repositories/HEAD/test/ota/ota_update.py + +# Platform version +PLATFORM_VERSION=4.0 + +# Cloud Storage bucket root e.g. gs://gtv-eureka/internal +BUILD_BUCKET_ROOT=gtv-eureka/internal +UNIT_TEST_BUCKET_ROOT=chromecast-unit-test/internal + +# build project name e.g. eureka is "chromecast" +BUILD_PROJECT_NAME=chromecast + +# Unique repository name for this product +REPO_ALIAS=internal + +# The board type to get the latest build +BOARD_TYPE=luther-b2
diff --git a/lab_system/master/config/device_type/luther_b2.cfg b/lab_system/master/config/device_type/luther_b2.cfg new file mode 100644 index 0000000..fe0c076 --- /dev/null +++ b/lab_system/master/config/device_type/luther_b2.cfg
@@ -0,0 +1,39 @@ +# Config file for luther device type +# +# Do not modify the property names +# +# Run make reconfig if you change a value +# and buildbot is running +# +# PROPERTIES + +# name to be used for tests +DEVICE_TYPE=luther_b2 + +# ota zip file format is: PRODUCT_NAME-OTA_NAME-BUILD.zip +PRODUCT_NAME=steak + +# Device module which contains class to control this device. +DEVICE_MODULE=eurtest.device.device + +# Device class to use to control this device. +DEVICE_CLASS=Device + +# Path to build installer. +BUILD_INSTALLER_PATH=/usr/local/google/repositories/HEAD/test/ota/ota_update.py + +# Platform version +PLATFORM_VERSION=4.0 + +# Cloud Storage bucket root e.g. gs://gtv-eureka/internal +BUILD_BUCKET_ROOT=gtv-eureka/internal +UNIT_TEST_BUCKET_ROOT=chromecast-unit-test/internal + +# build project name e.g. eureka is "chromecast" +BUILD_PROJECT_NAME=chromecast + +# Unique repository name for this product +REPO_ALIAS=internal + +# The board type to get the latest build +BOARD_TYPE=luther-b2
diff --git a/lab_system/master/config/device_type/newman.cfg b/lab_system/master/config/device_type/newman.cfg new file mode 100644 index 0000000..8b77ea0 --- /dev/null +++ b/lab_system/master/config/device_type/newman.cfg
@@ -0,0 +1,25 @@ +# Config file for newman device type +# +# Do not modify the property names +# +# Run make reconfig if you change a value +# and buildbot is running +# +# PROPERTIES + +# name to be used for tests +DEVICE_TYPE=newman + +# ota zip file format is: PRODUCT_NAME-OTA_NAME-BUILD.zip +PRODUCT_NAME=newman + +# Device module which contains class to control this device. +DEVICE_MODULE=eurtest.device.assistant_device + +# Device class to use to control this device. +DEVICE_CLASS=Assistant + +# Approved wifi channels by nation for prince, +# that differ from standard channels available in that country. +CA=36,40,44,48,52,56,60,64,100,104,108,112,116,120,124,128,132,136,140,144,149,153,157,161,165 +KR=36,40,44,48,52,56,60,64,100,104,108,112,116,120,124,128,132,136,140,144,149,153,157,161,165
diff --git a/lab_system/master/config/device_type/prince.cfg b/lab_system/master/config/device_type/prince.cfg new file mode 100644 index 0000000..a4bb088 --- /dev/null +++ b/lab_system/master/config/device_type/prince.cfg
@@ -0,0 +1,27 @@ +# Config file for Prince device type +# +# Do not modify the property names +# +# PROPERTIES + +# name to be used for tests +DEVICE_TYPE=prince + +# ota zip file format is: PRODUCT_NAME-OTA_NAME-BUILD.zip +PRODUCT_NAME=prince + +# Device module which contains class to control this device. +DEVICE_MODULE=eurtest.device.assistant_device + +# Device class to use to control this device. +DEVICE_CLASS=Assistant + +# Approved wifi channels by nation for prince, +# that differ from standard channels available in that country +FR=36,40,44,48,52,56,60,64,100,104,108,112,116,120,124,128,132,136,140,149,153,157,161,165 +JP=36,40,44,48,52,56,60,64,100,104,108,112,116,120,124,128,132,136,140,144 +IT=36,40,44,48,52,56,60,64,100,104,108,112,116,120,124,128,132,136,140,149,153,157,161,165 +GB=36,40,44,48,52,56,60,64,100,104,108,112,116,120,124,128,132,136,140,149,153,157,161,165 +IE=36,40,44,48,52,56,60,64,100,104,108,112,116,120,124,128,132,136,140,149,153,157,161,165 +PL=36,40,44,48,52,56,60,64,100,104,108,112,116,120,124,128,132,136,140,149,153,157,161,165 +KR=36,40,44,48,52,56,60,64,100,104,108,112,116,120,124,128,132,136,140,144,149,153,157,161,165
diff --git a/lab_system/master/config/device_type/sabrina.cfg b/lab_system/master/config/device_type/sabrina.cfg new file mode 100644 index 0000000..3dae473 --- /dev/null +++ b/lab_system/master/config/device_type/sabrina.cfg
@@ -0,0 +1,20 @@ +# Config file for sabrina device type +# +# Do not modify the property names +# +# Run make reconfig if you change a value +# and buildbot is running +# +# PROPERTIES + +# name to be used as device type +DEVICE_TYPE=sabrina + +# product name +PRODUCT_NAME=sabrina + +# Device module which contains class to control this device. +DEVICE_MODULE=eurtest.device.android + +# Device class to use to control this device. +DEVICE_CLASS=Android
diff --git a/lab_system/master/config/device_type/spencer.cfg b/lab_system/master/config/device_type/spencer.cfg new file mode 100644 index 0000000..847c44c --- /dev/null +++ b/lab_system/master/config/device_type/spencer.cfg
@@ -0,0 +1,20 @@ +# Config file for Spencer device type +# +# Do not modify the property names +# +# Run make reconfig if you change a value +# and buildbot is running +# +# PROPERTIES + +# name to be used as device type +DEVICE_TYPE=spencer + +# product name +PRODUCT_NAME=spencer + +# Device module which contains class to control this device. +DEVICE_MODULE=udm.device.nest_iot_device + +# Device class to use to control this device. +DEVICE_CLASS=SpencerDevice
diff --git a/lab_system/master/config/device_type/valens.cfg b/lab_system/master/config/device_type/valens.cfg new file mode 100644 index 0000000..2b1ffb8 --- /dev/null +++ b/lab_system/master/config/device_type/valens.cfg
@@ -0,0 +1,39 @@ +# Config file for valens device type +# +# Do not modify the property names +# +# Run make reconfig if you change a value +# and buildbot is running +# +# PROPERTIES + +# name to be used for tests +DEVICE_TYPE=valens + +# ota zip file format is: PRODUCT_NAME-OTA_NAME-BUILD.zip +PRODUCT_NAME=valens + +# Device module which contains class to control this device. +DEVICE_MODULE=eurtest.device.assistant_device + +# Device class to use to control this device. +DEVICE_CLASS=Assistant + +# Path to build installer +BUILD_INSTALLER_PATH=/usr/local/google/repositories/HEAD/test/ota/ota_update.py + +# Platform version +PLATFORM_VERSION=2.0 + +# Cloud Storage bucket root e.g. gs://gtv-eureka/internal +BUILD_BUCKET_ROOT=gtv-eureka/internal +UNIT_TEST_BUCKET_ROOT=chromecast-unit-test/internal + +# build project name e.g. eureka is "chromecast" +BUILD_PROJECT_NAME=chromecast + +# Unique repository name for this product +REPO_ALIAS=internal + +# The board type to get the latest build +BOARD_TYPE=valens-p2
diff --git a/lab_system/master/config/device_type/vento.cfg b/lab_system/master/config/device_type/vento.cfg new file mode 100644 index 0000000..01c4a8d --- /dev/null +++ b/lab_system/master/config/device_type/vento.cfg
@@ -0,0 +1,39 @@ +# Config file for vento device type +# +# Do not modify the property names +# +# Run make reconfig if you change a value +# and buildbot is running +# +# PROPERTIES + +# name to be used for tests +DEVICE_TYPE=vento + +# ota zip file format is: PRODUCT_NAME-OTA_NAME-BUILD.zip +PRODUCT_NAME=vento + +# Device module which contains class to control this device. +DEVICE_MODULE=eurtest.device.assistant_device + +# Device class to use to control this device. +DEVICE_CLASS=Assistant + +# Path to build installer +BUILD_INSTALLER_PATH=/usr/local/google/repositories/HEAD/test/ota/ota_update.py + +# Platform version +PLATFORM_VERSION=1.0 + +# Cloud Storage bucket root e.g. gs://gtv-eureka/internal +BUILD_BUCKET_ROOT=gtv-eureka/internal +UNIT_TEST_BUCKET_ROOT=chromecast-unit-test/internal + +# build project name e.g. eureka is "chromecast" +BUILD_PROJECT_NAME=chromecast + +# Unique repository name for this product +REPO_ALIAS=internal + +# The board type to get the latest build +BOARD_TYPE=vento-p0
diff --git a/lab_system/master/config/groups/acer_core_i5_chrome_mirroring_win_eureka_master.cfg b/lab_system/master/config/groups/acer_core_i5_chrome_mirroring_win_eureka_master.cfg new file mode 100644 index 0000000..83e4930 --- /dev/null +++ b/lab_system/master/config/groups/acer_core_i5_chrome_mirroring_win_eureka_master.cfg
@@ -0,0 +1,17 @@ +# Config file for acer_staging slave + +# PROPERTIES +SPECIFIC_DEVICE_IP=192.168.0.106 +SELF_IP=172.17.23.194 +HOME_DIR=C:/Users/gtvchrome +USER_NAME=gtvchrome +CHROME_DRIVER=chromedriver.exe +CHROME_ZIP=chrome-win32.zip +CHROME_PATH=chrome-win32 +PLATFORM=win + +# Mirroring test chrome build +CHROME_CHANNEL=stable + +# Mirroring test extension flavor +EXTENSION_FLAVOR=canary
diff --git a/lab_system/master/config/groups/android_mirroring_cast_tv_1.cfg b/lab_system/master/config/groups/android_mirroring_cast_tv_1.cfg new file mode 100644 index 0000000..8f3c2f9 --- /dev/null +++ b/lab_system/master/config/groups/android_mirroring_cast_tv_1.cfg
@@ -0,0 +1,10 @@ +# Config file for recording laptop + +# PROPERTIES +SELF_IP=100.107.130.19 +HOME_DIR=/Users/gtvchrome +USER_NAME=gtvchrome +REPO_ROOT=repository/eureka +SPECIFIC_DEVICE_IP=192.168.1.54 +RECORDER_DEVICE_TYPE='video_recorder' +
diff --git a/lab_system/master/config/groups/android_mirroring_recording_1.cfg b/lab_system/master/config/groups/android_mirroring_recording_1.cfg new file mode 100644 index 0000000..6fa6394 --- /dev/null +++ b/lab_system/master/config/groups/android_mirroring_recording_1.cfg
@@ -0,0 +1,19 @@ +# Config file for recording laptop + +# PROPERTIES +SELF_IP=100.107.131.0 +HOME_DIR=/Users/gtvchrome +USER_NAME=gtvchrome +REPO_ROOT=repository/eureka +SPECIFIC_DEVICE_IP=192.168.1.6 +RECORDER_DEVICE_TYPE='video_recorder' + +# GmsCore file name +GMSCORE_APK=GmsCore.apk + +# GMSCore branch and target defining builds to fetch: +GMSCORE_BRANCH=ub-gcore-saga-release +GMSCORE_TARGET=GmsCore + +# GMSCORE Build Id +BID=2250156
diff --git a/lab_system/master/config/groups/android_mirroring_recording_2.cfg b/lab_system/master/config/groups/android_mirroring_recording_2.cfg new file mode 100644 index 0000000..c6649e9 --- /dev/null +++ b/lab_system/master/config/groups/android_mirroring_recording_2.cfg
@@ -0,0 +1,19 @@ +# Config file for recording laptop + +# PROPERTIES +SELF_IP=100.115.4.74 +HOME_DIR=/Users/gtvchrome +USER_NAME=gtvchrome +REPO_ROOT=repository/eureka +SPECIFIC_DEVICE_IP=192.168.0.103 +RECORDER_DEVICE_TYPE='video_recorder' + +# GmsCore file name +GMSCORE_APK=GmsCore.apk + +# GMSCore branch and target defining builds to fetch: +GMSCORE_BRANCH=ub-gcore-saga-release +GMSCORE_TARGET=GmsCore + +# GMSCORE Build Id +BID=2250156
diff --git a/lab_system/master/config/groups/android_mirroring_recording_3.cfg b/lab_system/master/config/groups/android_mirroring_recording_3.cfg new file mode 100644 index 0000000..d297082 --- /dev/null +++ b/lab_system/master/config/groups/android_mirroring_recording_3.cfg
@@ -0,0 +1,19 @@ +# Config file for recording laptop + +# PROPERTIES +SELF_IP=100.115.4.73 +HOME_DIR=/Users/gtvchrome +USER_NAME=gtvchrome +REPO_ROOT=repository/eureka +SPECIFIC_DEVICE_IP=192.168.0.3 +RECORDER_DEVICE_TYPE='video_recorder' + +# GmsCore file name +GMSCORE_APK=GmsCore.apk + +# GMSCore branch and target defining builds to fetch: +GMSCORE_BRANCH=ub-gcore-saga-release +GMSCORE_TARGET=GmsCore + +# GMSCORE Build Id +BID=2250156
diff --git a/lab_system/master/config/groups/android_mirroring_recording_4.cfg b/lab_system/master/config/groups/android_mirroring_recording_4.cfg new file mode 100644 index 0000000..574aba8 --- /dev/null +++ b/lab_system/master/config/groups/android_mirroring_recording_4.cfg
@@ -0,0 +1,9 @@ +# Config file for laptop connecting to OEM devices + +# PROPERTIES +SELF_IP=100.107.131.181 +HOME_DIR=/Users/gtvchrome +USER_NAME=gtvchrome +REPO_ROOT=repository/eureka +SPECIFIC_DEVICE_IP=192.168.0.4 +RECORDER_DEVICE_TYPE='video_recorder'
diff --git a/lab_system/master/config/groups/android_mirroring_uma.cfg b/lab_system/master/config/groups/android_mirroring_uma.cfg new file mode 100644 index 0000000..46d753b --- /dev/null +++ b/lab_system/master/config/groups/android_mirroring_uma.cfg
@@ -0,0 +1,11 @@ +# Config file for recording laptop + +# PROPERTIES +SELF_IP=100.115.4.111 +HOME_DIR=/Users/gtvchrome +USER_NAME=gtvchrome +REPO_ROOT=repository/eureka +SPECIFIC_DEVICE_IP=192.168.0.4 +REMOTE_LOG_DIR=/Users/gtvchrome/results/uma +# TODO(kevinfei): remove IPA_DIR once iOS test has its dedicated setup +IPA_DIR=/Users/gtvchrome/ipa
diff --git a/lab_system/master/config/groups/audio_mirroring_nexus_1.cfg b/lab_system/master/config/groups/audio_mirroring_nexus_1.cfg new file mode 100644 index 0000000..5b84a2c --- /dev/null +++ b/lab_system/master/config/groups/audio_mirroring_nexus_1.cfg
@@ -0,0 +1,38 @@ +# Config file for laptop connecting to OEM devices + +# PROPERTIES +SELF_IP=100.107.130.143 +HOME_DIR=/home/gtvchrome +AUDIO_RECORDER_IP=100.107.131.179 +AUDIO_RECORDER_HOME_DIR=/Users/gtvchrome +USER_NAME=gtvchrome +REPO_ROOT=repository/eureka +SPECIFIC_DEVICE_IP=192.168.0.103 +RECORDER_DEVICE_TYPE='audio_recorder' + +# GmsCore file name +GMSCORE_APK=GmsCore.apk + +# GMSCore branch and target defining builds to fetch: +GMSCORE_BRANCH=ub-gcore-saga-release +GMSCORE_TARGET=GmsCore + +# GMSCORE Build Id +BID=2250156 + +# Sender device +ANDROID_DEVICE_NAME=nexus5 +# Audio Reference +REMOTE_AUDIO_REF_DIR=/media/media/www/audio_mirroring +# Audio score file name +AUDIO_SCORE_FILE_NAME=audio_score.txt +# Audio alignment analysis file name +AUDIO_ALIGNMENT_FILE_NAME=audio_missing_delay.json +# Recorded audio file name +RECORDED_AUDIO_FILE_NAME=audio_all_chn.wav +# Original reference audio file name +ORIGINAL_AUDIO_FILE_NAME=sunshine-reference_delay_000.wav +# Find highest audio score binary +FIND_MAX_AUDIO_SCORE=test/report/audio_mirroring/find_max_audio_score.py +# Upload test result binary +UPLOAD_TEST_RESULT=test/report/audio_mirroring/upload_test_result.py
diff --git a/lab_system/master/config/groups/audio_mirroring_nexus_2.cfg b/lab_system/master/config/groups/audio_mirroring_nexus_2.cfg new file mode 100644 index 0000000..5ca6a7e --- /dev/null +++ b/lab_system/master/config/groups/audio_mirroring_nexus_2.cfg
@@ -0,0 +1,38 @@ +# Config file for laptop connecting to OEM devices + +# PROPERTIES +SELF_IP=172.17.21.224 +HOME_DIR=/home/gtvchrome +AUDIO_RECORDER_IP=172.17.21.219 +AUDIO_RECORDER_HOME_DIR=/Users/gtvchrome +USER_NAME=gtvchrome +REPO_ROOT=repository/eureka +SPECIFIC_DEVICE_IP=10.0.1.4 +RECORDER_DEVICE_TYPE='audio_recorder' + +# GmsCore file name +GMSCORE_APK=GmsCore.apk + +# GMSCore branch and target defining builds to fetch: +GMSCORE_BRANCH=ub-gcore-saga-release +GMSCORE_TARGET=GmsCore + +# GMSCORE Build Id +BID=2250156 + +# Sender device +ANDROID_DEVICE_NAME=nexus5 +# Audio Reference +REMOTE_AUDIO_REF_DIR=/media/media/www/audio_mirroring +# Audio score file name +AUDIO_SCORE_FILE_NAME=audio_score.txt +# Audio alignment analysis file name +AUDIO_ALIGNMENT_FILE_NAME=audio_missing_delay.json +# Recorded audio file name +RECORDED_AUDIO_FILE_NAME=audio_all_chn.wav +# Original reference audio file name +ORIGINAL_AUDIO_FILE_NAME=sunshine-reference_delay_000.wav +# Find highest audio score binary +FIND_MAX_AUDIO_SCORE=test/report/audio_mirroring/find_max_audio_score.py +# Upload test result binary +UPLOAD_TEST_RESULT=test/report/audio_mirroring/upload_test_result.py
diff --git a/lab_system/master/config/groups/bot.cfg b/lab_system/master/config/groups/bot.cfg new file mode 100644 index 0000000..81622af --- /dev/null +++ b/lab_system/master/config/groups/bot.cfg
@@ -0,0 +1,9 @@ +# Swarming configuration +ISOLATE_SERVER=cast-isolate.appspot.com +SWARMING_SERVER=cast-swarming.appspot.com +# Swarming Bot Configuration +BOT_OS=Ubuntu +BOT_POOL=unit_test +BOT_HARD_TIMEOUT=10800 +BOT_IO_TIMEOUT=10800 +REMOTE_HOME_DIR=/home/gtvchrome/repositories
diff --git a/lab_system/master/config/groups/cast_androidthings.cfg b/lab_system/master/config/groups/cast_androidthings.cfg new file mode 100644 index 0000000..92aa585 --- /dev/null +++ b/lab_system/master/config/groups/cast_androidthings.cfg
@@ -0,0 +1,10 @@ +# Android Things test properties + +USER_NAME=gtvchrome +REMOTE_REPO_ROOT=/home/gtvchrome/repositories +REMOTE_TEST_ROOT=/home/gtvchrome/repositories/HEAD +CHROMIUM_SRC=chromium/src +ANDROID_TEST_RUNNER_PATH=build/android/test_runner.py +REMOTE_OTA_ZIP_PATH=/home/gtvchrome/repositories/test_deps_claimed.zip +REMOTE_TEMP_DIR=/home/gtvchrome/atv_tmp +REMOTE_RESULT_DIR=/home/gtvchrome/results
diff --git a/lab_system/master/config/groups/cast_mdns.cfg b/lab_system/master/config/groups/cast_mdns.cfg new file mode 100644 index 0000000..05cc376 --- /dev/null +++ b/lab_system/master/config/groups/cast_mdns.cfg
@@ -0,0 +1,7 @@ +# Config file for cast_mdns test + +# PROPERTIES +SELF_IP=172.17.23.200 +HOME_DIR=/home/gtvchrome +USER_NAME=gtvchrome +REPO_ROOT=repository/eureka
diff --git a/lab_system/master/config/groups/chrome_sdk_end_to_end_v2.cfg b/lab_system/master/config/groups/chrome_sdk_end_to_end_v2.cfg new file mode 100644 index 0000000..eec9439 --- /dev/null +++ b/lab_system/master/config/groups/chrome_sdk_end_to_end_v2.cfg
@@ -0,0 +1,25 @@ +# Config file for chrome_sdk_end_to_end_v2 group + +# PROPERTIES +REMOTE_TEST_FILES_FOLDER=/var/www/gtv/bin + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.cast.chrome.end_to_end_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=CastChromeEndToEndTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.framework.javascript_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=JavascriptTestSequence + +# Location of test binary +TEST_BINARY_FILE=gs://test_logs/test_binaries/test_bin.zip + +# Account information used to download internal cast extension +ACCOUNT_FILE=/usr/local/google/staging/fraggle_rock/chrome_sdk/account.txt + +# Public keys for different cast extensions +EXTENSION_PUBLIC_KEYS_FILE=/usr/local/google/staging/fraggle_rock/chrome_sdk/public_keys.json
diff --git a/lab_system/master/config/groups/fugu_unit_test.cfg b/lab_system/master/config/groups/fugu_unit_test.cfg new file mode 100644 index 0000000..07009ae --- /dev/null +++ b/lab_system/master/config/groups/fugu_unit_test.cfg
@@ -0,0 +1,10 @@ +# Android TV unit test properties + +USER_NAME=gtvchrome +REMOTE_REPO_ROOT=/home/gtvchrome/repositories +REMOTE_TEST_ROOT=/home/gtvchrome/repositories/HEAD +CHROMIUM_SRC=chromium/src +ANDROID_TEST_RUNNER_PATH=build/android/test_runner.py +REMOTE_OTA_ZIP_PATH=/home/gtvchrome/repositories/test_deps_claimed.zip +REMOTE_TEMP_DIR=/home/gtvchrome/atv_tmp +REMOTE_RESULT_DIR=/home/gtvchrome/results
diff --git a/lab_system/master/config/groups/hp_core_i5_chrome_mirroring_win_eureka_master.cfg b/lab_system/master/config/groups/hp_core_i5_chrome_mirroring_win_eureka_master.cfg new file mode 100644 index 0000000..73f0454 --- /dev/null +++ b/lab_system/master/config/groups/hp_core_i5_chrome_mirroring_win_eureka_master.cfg
@@ -0,0 +1,17 @@ +# Config file for acer_staging slave + +# PROPERTIES +SPECIFIC_DEVICE_IP=192.168.0.244 +SELF_IP=172.17.23.78 +HOME_DIR=C:/Users/gtvchrome +USER_NAME=gtvchrome +CHROME_DRIVER=chromedriver.exe +CHROME_ZIP=chrome-win32.zip +CHROME_PATH=chrome-win32 +PLATFORM=win + +# Mirroring test chrome build +CHROME_CHANNEL=beta + +# Mirroring test extension flavor +EXTENSION_FLAVOR=canary
diff --git a/lab_system/master/config/groups/macbookair_haswell_chrome_mirroring_mac_eureka_master.cfg b/lab_system/master/config/groups/macbookair_haswell_chrome_mirroring_mac_eureka_master.cfg new file mode 100644 index 0000000..6d5fa0f --- /dev/null +++ b/lab_system/master/config/groups/macbookair_haswell_chrome_mirroring_mac_eureka_master.cfg
@@ -0,0 +1,17 @@ +# Config file for macbookair_staging slave + +# PROPERTIES +SPECIFIC_DEVICE_IP=192.168.0.102 +SELF_IP=172.17.23.86 +HOME_DIR=/Users/gtvchrome +USER_NAME=gtvchrome +CHROME_DRIVER=chromedriver +CHROME_ZIP=chrome-mac.zip +CHROME_PATH=chrome-mac +PLATFORM=mac + +# Mirroring test chrome build +CHROME_CHANNEL=beta + +# Mirroring test extension flavor +EXTENSION_FLAVOR=canary
diff --git a/lab_system/master/config/groups/macbookpro13_core_i5_chrome_mirroring_mac_eureka_master.cfg b/lab_system/master/config/groups/macbookpro13_core_i5_chrome_mirroring_mac_eureka_master.cfg new file mode 100644 index 0000000..74d6fbe --- /dev/null +++ b/lab_system/master/config/groups/macbookpro13_core_i5_chrome_mirroring_mac_eureka_master.cfg
@@ -0,0 +1,21 @@ +# Config file for +# macbookpro13_core_i5_chrome_mirroring_mac_eureka_master slave + +# PROPERTIES +SPECIFIC_DEVICE_IP=192.168.0.103 +SELF_IP=172.17.23.84 +HOME_DIR=/Users/gtvchrome +USER_NAME=gtvchrome +CHROME_DRIVER=chromedriver +CHROME_ZIP=chrome-mac.zip +CHROME_PATH=chrome-mac +PLATFORM=mac +TEST_CONFIG=continuous-tests/lab_system/master/config/tests/chrome_mirroring_benchmark/chrome_mirroring_benchmark_test_conf.json +RESULTS_DIR=results +TEST_NAME=chrome_mirroring_mac + +# Mirroring test chrome build +CHROME_CHANNEL=beta + +# Mirroring test extension flavor +EXTENSION_FLAVOR=canary
diff --git a/lab_system/master/config/groups/macbookpro13_core_i5_retina_chrome_mirroring_mac_eureka_master.cfg b/lab_system/master/config/groups/macbookpro13_core_i5_retina_chrome_mirroring_mac_eureka_master.cfg new file mode 100644 index 0000000..b0561d0 --- /dev/null +++ b/lab_system/master/config/groups/macbookpro13_core_i5_retina_chrome_mirroring_mac_eureka_master.cfg
@@ -0,0 +1,18 @@ +# Config file for +# macbookpro13_core_i5_retina_chrome_mirroring_mac_eureka_master slave + +# PROPERTIES +SPECIFIC_DEVICE_IP=192.168.0.101 +SELF_IP=172.17.23.56 +HOME_DIR=/Users/gtvchrome +USER_NAME=gtvchrome +CHROME_DRIVER=chromedriver +CHROME_ZIP=chrome-mac.zip +CHROME_PATH=chrome-mac +PLATFORM=mac + +# Mirroring test chrome build +CHROME_CHANNEL=beta + +# Mirroring test extension flavor +EXTENSION_FLAVOR=canary
diff --git a/lab_system/master/config/groups/nexus_player_recording.cfg b/lab_system/master/config/groups/nexus_player_recording.cfg new file mode 100644 index 0000000..7e1feaf --- /dev/null +++ b/lab_system/master/config/groups/nexus_player_recording.cfg
@@ -0,0 +1,9 @@ +# Config file for Nexus Player recording laptop + +# PROPERTIES +SELF_IP=100.107.131.180 +HOME_DIR=/Users/gtvchrome +USER_NAME=gtvchrome +REPO_ROOT=repository/eureka +SPECIFIC_DEVICE_IP=E34884C7 +RECORDER_DEVICE_TYPE='video_recorder'
diff --git a/lab_system/master/config/groups/remote_display_ios_1.cfg b/lab_system/master/config/groups/remote_display_ios_1.cfg new file mode 100644 index 0000000..7da5b6d --- /dev/null +++ b/lab_system/master/config/groups/remote_display_ios_1.cfg
@@ -0,0 +1,9 @@ +# Config file for recording laptop + +# PROPERTIES +SELF_IP=100.107.130.67 +HOME_DIR=/Users/gtvchrome +USER_NAME=gtvchrome +REPO_ROOT=repository/eureka +SPECIFIC_DEVICE_IP=192.168.0.4 +IPA_DIR=/Users/gtvchrome/ipa
diff --git a/lab_system/master/config/groups/remote_display_ios_latency_1.cfg b/lab_system/master/config/groups/remote_display_ios_latency_1.cfg new file mode 100644 index 0000000..0c4a4ba --- /dev/null +++ b/lab_system/master/config/groups/remote_display_ios_latency_1.cfg
@@ -0,0 +1,9 @@ +# Config file for recording laptop + +# PROPERTIES +SELF_IP=172.17.21.219 +HOME_DIR=/Users/gtvchrome +USER_NAME=gtvchrome +REPO_ROOT=repository/eureka +SPECIFIC_DEVICE_IP=10.0.1.7 +IPA_DIR=/Users/gtvchrome/ipa
diff --git a/lab_system/master/config/groups/remote_display_recording_1.cfg b/lab_system/master/config/groups/remote_display_recording_1.cfg new file mode 100644 index 0000000..e21a5ae --- /dev/null +++ b/lab_system/master/config/groups/remote_display_recording_1.cfg
@@ -0,0 +1,19 @@ +# Config file for recording laptop + +# PROPERTIES +SELF_IP=100.107.131.0 +HOME_DIR=/Users/gtvchrome +USER_NAME=gtvchrome +REPO_ROOT=repository/eureka +SPECIFIC_DEVICE_IP=192.168.1.6 +RECORDER_DEVICE_TYPE='video_recorder' + +# GmsCore file name +GMSCORE_APK=GmsCore.apk + +# GMSCore branch and target defining builds to fetch: +GMSCORE_BRANCH=ub-gcore-saga-release +GMSCORE_TARGET=GmsCore + +# Build Id +BID=2250156
diff --git a/lab_system/master/config/groups/remote_display_recording_2.cfg b/lab_system/master/config/groups/remote_display_recording_2.cfg new file mode 100644 index 0000000..34bfa07 --- /dev/null +++ b/lab_system/master/config/groups/remote_display_recording_2.cfg
@@ -0,0 +1,19 @@ +# Config file for recording laptop + +# PROPERTIES +SELF_IP=100.107.130.131 +HOME_DIR=/Users/gtvchrome +USER_NAME=gtvchrome +REPO_ROOT=repository/eureka +SPECIFIC_DEVICE_IP=192.168.0.103 +RECORDER_DEVICE_TYPE='video_recorder' + +# GmsCore file name +GMSCORE_APK=GmsCore.apk + +# GMSCore branch and target defining builds to fetch: +GMSCORE_BRANCH=ub-gcore-saga-release +GMSCORE_TARGET=GmsCore + +# Build Id +BID=2250156
diff --git a/lab_system/master/config/groups/remote_display_recording_3.cfg b/lab_system/master/config/groups/remote_display_recording_3.cfg new file mode 100644 index 0000000..2cae7b2 --- /dev/null +++ b/lab_system/master/config/groups/remote_display_recording_3.cfg
@@ -0,0 +1,19 @@ +# Config file for recording laptop + +# PROPERTIES +SELF_IP=100.107.130.36 +HOME_DIR=/Users/gtvchrome +USER_NAME=gtvchrome +REPO_ROOT=repository/eureka +SPECIFIC_DEVICE_IP=192.168.0.3 +RECORDER_DEVICE_TYPE='video_recorder' + +# GmsCore file name +GMSCORE_APK=GmsCore.apk + +# GMSCore branch and target defining builds to fetch: +GMSCORE_BRANCH=ub-gcore-saga-release +GMSCORE_TARGET=GmsCore + +# Build Id +BID=2250156
diff --git a/lab_system/master/config/groups/remote_display_recording_4.cfg b/lab_system/master/config/groups/remote_display_recording_4.cfg new file mode 100644 index 0000000..e7ef280 --- /dev/null +++ b/lab_system/master/config/groups/remote_display_recording_4.cfg
@@ -0,0 +1,9 @@ +# Config file for recording laptop + +# PROPERTIES +SELF_IP=100.107.131.181 +HOME_DIR=/Users/gtvchrome +USER_NAME=gtvchrome +REPO_ROOT=repository/eureka +SPECIFIC_DEVICE_IP=192.168.0.4 +RECORDER_DEVICE_TYPE='video_recorder'
diff --git a/lab_system/master/config/ios/ios_device_type.json b/lab_system/master/config/ios/ios_device_type.json new file mode 100644 index 0000000..924675b --- /dev/null +++ b/lab_system/master/config/ios/ios_device_type.json
@@ -0,0 +1,26 @@ +{ + "iPad4,4": { + "IpaName": "GLES3.ipa", + "ProductName": "iPadMini2WiFi", + "UnityAppName": "com.google.cast.test.unityplugin", + "UnityAppType": "GLES3" + }, + "iPhone5,2": { + "IpaName": "GLES2.ipa", + "ProductName": "iPhone5", + "UnityAppName": "com.google.cast.test.unityplugin", + "UnityAppType": "GLES2" + }, + "iPad5,3": { + "IpaName": "METAL.ipa", + "ProductName": "iPhone6s", + "UnityAppName": "com.google.cast.test.unityplugin", + "UnityAppType": "METAL" + }, + "iPhone8,1": { + "IpaName": "METAL.ipa", + "ProductName": "iPhone6s", + "UnityAppName": "com.google.cast.test.unityplugin", + "UnityAppType": "METAL" + } +}
diff --git a/lab_system/master/config/isolate/unit_test.isolate.template b/lab_system/master/config/isolate/unit_test.isolate.template new file mode 100644 index 0000000..d2d6e01 --- /dev/null +++ b/lab_system/master/config/isolate/unit_test.isolate.template
@@ -0,0 +1,19 @@ +{ + 'variables': { + 'files': [ + {% for path in mandatory_paths %}'{{ relative_path }}/{{ path }}/', + {% endfor %}], + }, + 'conditions': [ + ['OS=="{{ os_platform }}"', { + 'variables': { + 'command': [ + '{{ relative_path }}/continuous-tests/cq/scripts/tools/run_recipe.py', + '{{ valid_test_name }}', + '--eureka-root={{ remote_home_dir }}', + '--properties={% raw %}{{% endraw %}{% for key, value in props.iteritems() %}"{{ key }}": "{{ value }}", {% endfor %}"recipe_tmp_dir": "{{ recipe_tmp_dir }}"{% raw %}}{% endraw %}' + ], + }, + }], + ], +}
diff --git a/lab_system/master/config/kir/branch/master.cfg b/lab_system/master/config/kir/branch/master.cfg new file mode 100644 index 0000000..0cd1393 --- /dev/null +++ b/lab_system/master/config/kir/branch/master.cfg
@@ -0,0 +1,10 @@ +# Config file for master branch +# +# Do not modify property names +# Run make reconfig if you change a value +# while buildbot is running +# +# PROPERTIES + +# Branch name to use in the run +BRANCH_NAME=unfork_m37
diff --git a/lab_system/master/config/kir/branch/release.cfg b/lab_system/master/config/kir/branch/release.cfg new file mode 100644 index 0000000..a31ad9c --- /dev/null +++ b/lab_system/master/config/kir/branch/release.cfg
@@ -0,0 +1,10 @@ +# Config file for release branches +# +# Do not modify property names +# Run make reconfig if you change a value +# while buildbot is running +# +# PROPERTIES + +# Branch name to use in the run. Change it to the latest release branch. +BRANCH_NAME=1.9
diff --git a/lab_system/master/config/kir/dashboard/dashboard.cfg b/lab_system/master/config/kir/dashboard/dashboard.cfg new file mode 100755 index 0000000..52721da --- /dev/null +++ b/lab_system/master/config/kir/dashboard/dashboard.cfg
@@ -0,0 +1,1112 @@ +{ + "Chrome SDK v2 Flinging Test - Mac_Canary_Canary_Release ": { + "configuration": { + "hAxis": { + "slantedText": true + } + }, + "device_type": "eureka", + "sql_data": { + "column_types": [ + "string", + "number", + "number", + "number" + ], + "columns_to_plot": [ + 0, + 1, + 2, + 3 + ], + "headers": { + "Time": 0, + "Tests Run": 1, + "Failures": 2, + "Errors": 3 + }, + "query": "SELECT datetime(test_run.start_timestamp, 'localtime'), test_suite.test_count, test_suite.failure_count, test_suite.error_count FROM test_run, test_suite WHERE test_run.run_id = test_suite.run_id AND test_run.builder_name = 'chrome_sdk_end_to_end_v2_mac_canary_canary_release' AND (test_suite.suite_name LIKE '%%flinging_test_bin.html%%' OR test_suite.suite_name = 'TestFlinging') AND test_run.test_name = 'CastChromeEndToEndTestCase' AND datetime(test_run.start_timestamp) >= datetime('now', '-30 days') ORDER BY test_run.start_timestamp;" + }, + "table_description": [ + ["Time", "string"], + ["Tests Run", "number"], + ["Failures", "number"], + ["Errors", "number"] + ], + "test_category": "sdk_Mac_Canary_Canary_Release", + "title": "Chrome SDK v2 Flinging Test - Mac_Canary_Canary_Release" + }, + "Chrome SDK v2 Flinging Test - Win_Canary_Canary_Release ": { + "configuration": { + "hAxis": { + "slantedText": true + } + }, + "device_type": "eureka", + "sql_data": { + "column_types": [ + "string", + "number", + "number", + "number" + ], + "columns_to_plot": [ + 0, + 1, + 2, + 3 + ], + "headers": { + "Time": 0, + "Tests Run": 1, + "Failures": 2, + "Errors": 3 + }, + "query": "SELECT datetime(test_run.start_timestamp, 'localtime'), test_suite.test_count, test_suite.failure_count, test_suite.error_count FROM test_run, test_suite WHERE test_run.run_id = test_suite.run_id AND test_run.builder_name = 'chrome_sdk_end_to_end_v2_win_canary_canary_release' AND (test_suite.suite_name LIKE '%%flinging_test_bin.html%%' OR test_suite.suite_name = 'TestFlinging') AND test_run.test_name = 'CastChromeEndToEndTestCase' AND datetime(test_run.start_timestamp) >= datetime('now', '-30 days') ORDER BY test_run.start_timestamp;" + }, + "table_description": [ + ["Time", "string"], + ["Tests Run", "number"], + ["Failures", "number"], + ["Errors", "number"] + ], + "test_category": "sdk_Win_Canary_Canary_Release", + "title": "Chrome SDK v2 Flinging Test - Win_Canary_Canary_Release" + }, + "Chrome SDK v2 Flinging Test - Mac_Beta_Staging_Dogfood ": { + "configuration": { + "hAxis": { + "slantedText": true + } + }, + "device_type": "eureka", + "sql_data": { + "column_types": [ + "string", + "number", + "number", + "number" + ], + "columns_to_plot": [ + 0, + 1, + 2, + 3 + ], + "headers": { + "Time": 0, + "Tests Run": 1, + "Failures": 2, + "Errors": 3 + }, + "query": "SELECT datetime(test_run.start_timestamp, 'localtime'), test_suite.test_count, test_suite.failure_count, test_suite.error_count FROM test_run, test_suite WHERE test_run.run_id = test_suite.run_id AND test_run.builder_name = 'chrome_sdk_end_to_end_v2_mac_beta_staging_dogfood' AND (test_suite.suite_name LIKE '%%flinging_test_bin.html%%' OR test_suite.suite_name = 'TestFlinging') AND test_run.test_name = 'CastChromeEndToEndTestCase' AND datetime(test_run.start_timestamp) >= datetime('now', '-30 days') ORDER BY test_run.start_timestamp;" + }, + "table_description": [ + ["Time", "string"], + ["Tests Run", "number"], + ["Failures", "number"], + ["Errors", "number"] + ], + "test_category": "sdk_Mac_Beta_Staging_Dogfood", + "title": "Chrome SDK v2 Flinging Test - Mac" + }, + "Chrome SDK v2 Flinging Test - Win_Beta_Staging_Dogfood ": { + "configuration": { + "hAxis": { + "slantedText": true + } + }, + "device_type": "eureka", + "sql_data": { + "column_types": [ + "string", + "number", + "number", + "number" + ], + "columns_to_plot": [ + 0, + 1, + 2, + 3 + ], + "headers": { + "Time": 0, + "Tests Run": 1, + "Failures": 2, + "Errors": 3 + }, + "query": "SELECT datetime(test_run.start_timestamp, 'localtime'), test_suite.test_count, test_suite.failure_count, test_suite.error_count FROM test_run, test_suite WHERE test_run.run_id = test_suite.run_id AND test_run.builder_name = 'chrome_sdk_end_to_end_v2_win_beta_staging_dogfood' AND (test_suite.suite_name LIKE '%%flinging_test_bin.html%%' OR test_suite.suite_name = 'TestFlinging') AND test_run.test_name = 'CastChromeEndToEndTestCase' AND datetime(test_run.start_timestamp) >= datetime('now', '-30 days') ORDER BY test_run.start_timestamp;" + }, + "table_description": [ + ["Time", "string"], + ["Tests Run", "number"], + ["Failures", "number"], + ["Errors", "number"] + ], + "test_category": "sdk_Win_Beta_Staging_Dogfood", + "title": "Chrome SDK v2 Flinging Test - Win_Beta_Staging_Dogfood" + }, + "Chrome SDK v2 Flinging Test - Mac_Canary_Dev_Release ": { + "configuration": { + "hAxis": { + "slantedText": true + } + }, + "device_type": "eureka", + "sql_data": { + "column_types": [ + "string", + "number", + "number", + "number" + ], + "columns_to_plot": [ + 0, + 1, + 2, + 3 + ], + "headers": { + "Time": 0, + "Tests Run": 1, + "Failures": 2, + "Errors": 3 + }, + "query": "SELECT datetime(test_run.start_timestamp, 'localtime'), test_suite.test_count, test_suite.failure_count, test_suite.error_count FROM test_run, test_suite WHERE test_run.run_id = test_suite.run_id AND test_run.builder_name = 'chrome_sdk_end_to_end_v2_mac_canary_dev_release' AND (test_suite.suite_name LIKE '%%flinging_test_bin.html%%' OR test_suite.suite_name = 'TestFlinging') AND test_run.test_name = 'CastChromeEndToEndTestCase' AND datetime(test_run.start_timestamp) >= datetime('now', '-30 days') ORDER BY test_run.start_timestamp;" + }, + "table_description": [ + ["Time", "string"], + ["Tests Run", "number"], + ["Failures", "number"], + ["Errors", "number"] + ], + "test_category": "sdk_Mac_Canary_Dev_Release", + "title": "Chrome SDK v2 Flinging Test - Mac_Canary_Dev_Release" + }, + "Chrome SDK v2 Flinging Test - Win_Canary_Dev_Release ": { + "configuration": { + "hAxis": { + "slantedText": true + } + }, + "device_type": "eureka", + "sql_data": { + "column_types": [ + "string", + "number", + "number", + "number" + ], + "columns_to_plot": [ + 0, + 1, + 2, + 3 + ], + "headers": { + "Time": 0, + "Tests Run": 1, + "Failures": 2, + "Errors": 3 + }, + "query": "SELECT datetime(test_run.start_timestamp, 'localtime'), test_suite.test_count, test_suite.failure_count, test_suite.error_count FROM test_run, test_suite WHERE test_run.run_id = test_suite.run_id AND test_run.builder_name = 'chrome_sdk_end_to_end_v2_win_canary_dev_release' AND (test_suite.suite_name LIKE '%%flinging_test_bin.html%%' OR test_suite.suite_name = 'TestFlinging') AND test_run.test_name = 'CastChromeEndToEndTestCase' AND datetime(test_run.start_timestamp) >= datetime('now', '-30 days') ORDER BY test_run.start_timestamp;" + }, + "table_description": [ + ["Time", "string"], + ["Tests Run", "number"], + ["Failures", "number"], + ["Errors", "number"] + ], + "test_category": "sdk_Win_Canary_Dev_Release", + "title": "Chrome SDK v2 Flinging Test - Win_Canary_Dev_Release" + }, + "Chrome SDK v2 Joining Test - Mac_Canary_Canary_Release ": { + "configuration": { + "hAxis": { + "slantedText": true + } + }, + "device_type": "eureka", + "sql_data": { + "column_types": [ + "string", + "number", + "number", + "number" + ], + "columns_to_plot": [ + 0, + 1, + 2, + 3 + ], + "headers": { + "Time": 0, + "Tests Run": 1, + "Failures": 2, + "Errors": 3 + }, + "query": "SELECT datetime(test_run.start_timestamp, 'localtime'), test_suite.test_count, test_suite.failure_count, test_suite.error_count FROM test_run, test_suite WHERE test_run.run_id = test_suite.run_id AND test_run.builder_name = 'chrome_sdk_end_to_end_v2_mac_canary_canary_release' AND (test_suite.suite_name LIKE '%%/join_test_bin.html%%' OR test_suite.suite_name = 'TestJoin') AND test_run.test_name = 'CastChromeEndToEndTestCase' AND datetime(test_run.start_timestamp) >= datetime('now', '-30 days') ORDER BY test_run.start_timestamp;" + }, + "table_description": [ + ["Time", "string"], + ["Tests Run", "number"], + ["Failures", "number"], + ["Errors", "number"] + ], + "test_category": "sdk_Mac_Canary_Canary_Release", + "title": "Chrome SDK v2 Join Test - Mac_Canary_Canary_Release" + }, + "Chrome SDK v2 Joining Test - Win_Canary_Canary_Release ": { + "configuration": { + "hAxis": { + "slantedText": true + } + }, + "device_type": "eureka", + "sql_data": { + "column_types": [ + "string", + "number", + "number", + "number" + ], + "columns_to_plot": [ + 0, + 1, + 2, + 3 + ], + "headers": { + "Time": 0, + "Tests Run": 1, + "Failures": 2, + "Errors": 3 + }, + "query": "SELECT datetime(test_run.start_timestamp, 'localtime'), test_suite.test_count, test_suite.failure_count, test_suite.error_count FROM test_run, test_suite WHERE test_run.run_id = test_suite.run_id AND test_run.builder_name = 'chrome_sdk_end_to_end_v2_win_canary_canary_release' AND (test_suite.suite_name LIKE '%%/join_test_bin.html%%' OR test_suite.suite_name = 'TestJoin') AND test_run.test_name = 'CastChromeEndToEndTestCase' AND datetime(test_run.start_timestamp) >= datetime('now', '-30 days') ORDER BY test_run.start_timestamp;" + }, + "table_description": [ + ["Time", "string"], + ["Tests Run", "number"], + ["Failures", "number"], + ["Errors", "number"] + ], + "test_category": "sdk_Win_Canary_Canary_Release", + "title": "Chrome SDK v2 Join Test - Win_Canary_Canary_Release" + }, + "Chrome SDK v2 Joining Test - Mac_Beta_Staging_Dogfood ": { + "configuration": { + "hAxis": { + "slantedText": true + } + }, + "device_type": "eureka", + "sql_data": { + "column_types": [ + "string", + "number", + "number", + "number" + ], + "columns_to_plot": [ + 0, + 1, + 2, + 3 + ], + "headers": { + "Time": 0, + "Tests Run": 1, + "Failures": 2, + "Errors": 3 + }, + "query": "SELECT datetime(test_run.start_timestamp, 'localtime'), test_suite.test_count, test_suite.failure_count, test_suite.error_count FROM test_run, test_suite WHERE test_run.run_id = test_suite.run_id AND test_run.builder_name = 'chrome_sdk_end_to_end_v2_mac_beta_staging_dogfood' AND (test_suite.suite_name LIKE '%%/join_test_bin.html%%' OR test_suite.suite_name = 'TestJoin') AND test_run.test_name = 'CastChromeEndToEndTestCase' AND datetime(test_run.start_timestamp) >= datetime('now', '-30 days') ORDER BY test_run.start_timestamp;" + }, + "table_description": [ + ["Time", "string"], + ["Tests Run", "number"], + ["Failures", "number"], + ["Errors", "number"] + ], + "test_category": "sdk_Mac_Beta_Staging_Dogfood", + "title": "Chrome SDK v2 Joining Test - Mac_Beta_Staging_Dogfood" + }, + "Chrome SDK v2 Joining Test - Win_Beta_Staging_Dogfood ": { + "configuration": { + "hAxis": { + "slantedText": true + } + }, + "device_type": "eureka", + "sql_data": { + "column_types": [ + "string", + "number", + "number", + "number" + ], + "columns_to_plot": [ + 0, + 1, + 2, + 3 + ], + "headers": { + "Time": 0, + "Tests Run": 1, + "Failures": 2, + "Errors": 3 + }, + "query": "SELECT datetime(test_run.start_timestamp, 'localtime'), test_suite.test_count, test_suite.failure_count, test_suite.error_count FROM test_run, test_suite WHERE test_run.run_id = test_suite.run_id AND test_run.builder_name = 'chrome_sdk_end_to_end_v2_win_beta_staging_dogfood' AND (test_suite.suite_name LIKE '%%/join_test_bin.html%%' OR test_suite.suite_name = 'TestJoin') AND test_run.test_name = 'CastChromeEndToEndTestCase' AND datetime(test_run.start_timestamp) >= datetime('now', '-30 days') ORDER BY test_run.start_timestamp;" + }, + "table_description": [ + ["Time", "string"], + ["Tests Run", "number"], + ["Failures", "number"], + ["Errors", "number"] + ], + "test_category": "sdk_Win_Beta_Staging_Dogfood", + "title": "Chrome SDK v2 Join Test - Win_Beta_Staging_Dogfood" + }, + "Chrome SDK v2 Joining Test - Mac_Canary_Dev_Release ": { + "configuration": { + "hAxis": { + "slantedText": true + } + }, + "device_type": "eureka", + "sql_data": { + "column_types": [ + "string", + "number", + "number", + "number" + ], + "columns_to_plot": [ + 0, + 1, + 2, + 3 + ], + "headers": { + "Time": 0, + "Tests Run": 1, + "Failures": 2, + "Errors": 3 + }, + "query": "SELECT datetime(test_run.start_timestamp, 'localtime'), test_suite.test_count, test_suite.failure_count, test_suite.error_count FROM test_run, test_suite WHERE test_run.run_id = test_suite.run_id AND test_run.builder_name = 'chrome_sdk_end_to_end_v2_mac_canary_dev_release' AND (test_suite.suite_name LIKE '%%/join_test_bin.html%%' OR test_suite.suite_name = 'TestJoin') AND test_run.test_name = 'CastChromeEndToEndTestCase' AND datetime(test_run.start_timestamp) >= datetime('now', '-30 days') ORDER BY test_run.start_timestamp;" + }, + "table_description": [ + ["Time", "string"], + ["Tests Run", "number"], + ["Failures", "number"], + ["Errors", "number"] + ], + "test_category": "sdk_Mac_Canary_Dev_Release", + "title": "Chrome SDK v2 Join Test - Mac_Canary_Dev_Release" + }, + "Chrome SDK v2 Joining Test - Win_Canary_Dev_Release ": { + "configuration": { + "hAxis": { + "slantedText": true + } + }, + "device_type": "eureka", + "sql_data": { + "column_types": [ + "string", + "number", + "number", + "number" + ], + "columns_to_plot": [ + 0, + 1, + 2, + 3 + ], + "headers": { + "Time": 0, + "Tests Run": 1, + "Failures": 2, + "Errors": 3 + }, + "query": "SELECT datetime(test_run.start_timestamp, 'localtime'), test_suite.test_count, test_suite.failure_count, test_suite.error_count FROM test_run, test_suite WHERE test_run.run_id = test_suite.run_id AND test_run.builder_name = 'chrome_sdk_end_to_end_v2_win_canary_dev_release' AND (test_suite.suite_name LIKE '%%/join_test_bin.html%%' OR test_suite.suite_name = 'TestJoin') AND test_run.test_name = 'CastChromeEndToEndTestCase' AND datetime(test_run.start_timestamp) >= datetime('now', '-30 days') ORDER BY test_run.start_timestamp;" + }, + "table_description": [ + ["Time", "string"], + ["Tests Run", "number"], + ["Failures", "number"], + ["Errors", "number"] + ], + "test_category": "sdk_Win_Canary_Dev_Release", + "title": "Chrome SDK v2 Join Test - Win_Canary_Dev_Release" + }, + "Chrome SDK v2 MDNS Test - Mac_Canary_Canary_Release ": { + "configuration": { + "hAxis": { + "slantedText": true + } + }, + "device_type": "eureka", + "sql_data": { + "column_types": [ + "string", + "number", + "number", + "number" + ], + "columns_to_plot": [ + 0, + 1, + 2, + 3 + ], + "headers": { + "Time": 0, + "Tests Run": 1, + "Failures": 2, + "Errors": 3 + }, + "query": "SELECT datetime(test_run.start_timestamp, 'localtime'), test_suite.test_count, test_suite.failure_count, test_suite.error_count FROM test_run, test_suite WHERE test_run.run_id = test_suite.run_id AND test_run.builder_name = 'chrome_sdk_end_to_end_v2_mac_canary_canary_release' AND (test_suite.suite_name LIKE '%%mdns_test_bin.html%%' OR test_suite.suite_name = 'TestmDNS') AND test_run.test_name = 'CastChromeEndToEndTestCase' AND datetime(test_run.start_timestamp) >= datetime('now', '-30 days') ORDER BY test_run.start_timestamp;" + }, + "table_description": [ + ["Time", "string"], + ["Tests Run", "number"], + ["Failures", "number"], + ["Errors", "number"] + ], + "test_category": "sdk_Mac_Canary_Canary_Release", + "title": "Chrome SDK v2 MDNS Test - Mac_Canary_Canary_Release" + }, + "Chrome SDK v2 MDNS Test - Win_Canary_Canary_Release ": { + "configuration": { + "hAxis": { + "slantedText": true + } + }, + "device_type": "eureka", + "sql_data": { + "column_types": [ + "string", + "number", + "number", + "number" + ], + "columns_to_plot": [ + 0, + 1, + 2, + 3 + ], + "headers": { + "Time": 0, + "Tests Run": 1, + "Failures": 2, + "Errors": 3 + }, + "query": "SELECT datetime(test_run.start_timestamp, 'localtime'), test_suite.test_count, test_suite.failure_count, test_suite.error_count FROM test_run, test_suite WHERE test_run.run_id = test_suite.run_id AND test_run.builder_name = 'chrome_sdk_end_to_end_v2_win_canary_canary_release' AND (test_suite.suite_name LIKE '%%mdns_test_bin.html%%' OR test_suite.suite_name = 'TestmDNS') AND test_run.test_name = 'CastChromeEndToEndTestCase' AND datetime(test_run.start_timestamp) >= datetime('now', '-30 days') ORDER BY test_run.start_timestamp;" + }, + "table_description": [ + ["Time", "string"], + ["Tests Run", "number"], + ["Failures", "number"], + ["Errors", "number"] + ], + "test_category": "sdk_Win_Canary_Canary_Release", + "title": "Chrome SDK v2 MDNS Test - Win_Canary_Canary_Release" + }, + "Chrome SDK v2 MDNS Test - Mac_Beta_Staging_Dogfood ": { + "configuration": { + "hAxis": { + "slantedText": true + } + }, + "device_type": "eureka", + "sql_data": { + "column_types": [ + "string", + "number", + "number", + "number" + ], + "columns_to_plot": [ + 0, + 1, + 2, + 3 + ], + "headers": { + "Time": 0, + "Tests Run": 1, + "Failures": 2, + "Errors": 3 + }, + "query": "SELECT datetime(test_run.start_timestamp, 'localtime'), test_suite.test_count, test_suite.failure_count, test_suite.error_count FROM test_run, test_suite WHERE test_run.run_id = test_suite.run_id AND test_run.builder_name = 'chrome_sdk_end_to_end_v2_mac_beta_staging_dogfood' AND (test_suite.suite_name LIKE '%%mdns_test_bin.html%%' OR test_suite.suite_name = 'TestmDNS') AND test_run.test_name = 'CastChromeEndToEndTestCase' AND datetime(test_run.start_timestamp) >= datetime('now', '-30 days') ORDER BY test_run.start_timestamp;" + }, + "table_description": [ + ["Time", "string"], + ["Tests Run", "number"], + ["Failures", "number"], + ["Errors", "number"] + ], + "test_category": "sdk_Mac_Beta_Staging_Dogfood", + "title": "Chrome SDK v2 MDNS Test - Mac_Beta_Staging_Dogfood" + }, + "Chrome SDK v2 MDNS Test - Win_Beta_Staging_Dogfood ": { + "configuration": { + "hAxis": { + "slantedText": true + } + }, + "device_type": "eureka", + "sql_data": { + "column_types": [ + "string", + "number", + "number", + "number" + ], + "columns_to_plot": [ + 0, + 1, + 2, + 3 + ], + "headers": { + "Time": 0, + "Tests Run": 1, + "Failures": 2, + "Errors": 3 + }, + "query": "SELECT datetime(test_run.start_timestamp, 'localtime'), test_suite.test_count, test_suite.failure_count, test_suite.error_count FROM test_run, test_suite WHERE test_run.run_id = test_suite.run_id AND test_run.builder_name = 'chrome_sdk_end_to_end_v2_win_beta_staging_dogfood' AND (test_suite.suite_name LIKE '%%mdns_test_bin.html%%' OR test_suite.suite_name = 'TestmDNS') AND test_run.test_name = 'CastChromeEndToEndTestCase' AND datetime(test_run.start_timestamp) >= datetime('now', '-30 days') ORDER BY test_run.start_timestamp;" + }, + "table_description": [ + ["Time", "string"], + ["Tests Run", "number"], + ["Failures", "number"], + ["Errors", "number"] + ], + "test_category": "sdk_Win_Beta_Staging_Dogfood", + "title": "Chrome SDK v2 MDNS Test - Win_Beta_Staging_Dogfood" + }, + "Chrome SDK v2 MDNS Test - Mac_Canary_Dev_Release ": { + "configuration": { + "hAxis": { + "slantedText": true + } + }, + "device_type": "eureka", + "sql_data": { + "column_types": [ + "string", + "number", + "number", + "number" + ], + "columns_to_plot": [ + 0, + 1, + 2, + 3 + ], + "headers": { + "Time": 0, + "Tests Run": 1, + "Failures": 2, + "Errors": 3 + }, + "query": "SELECT datetime(test_run.start_timestamp, 'localtime'), test_suite.test_count, test_suite.failure_count, test_suite.error_count FROM test_run, test_suite WHERE test_run.run_id = test_suite.run_id AND test_run.builder_name = 'chrome_sdk_end_to_end_v2_mac_canary_dev_release' AND (test_suite.suite_name LIKE '%%mdns_test_bin.html%%' OR test_suite.suite_name = 'TestmDNS') AND test_run.test_name = 'CastChromeEndToEndTestCase' AND datetime(test_run.start_timestamp) >= datetime('now', '-30 days') ORDER BY test_run.start_timestamp;" + }, + "table_description": [ + ["Time", "string"], + ["Tests Run", "number"], + ["Failures", "number"], + ["Errors", "number"] + ], + "test_category": "sdk_Mac_Canary_Dev_Release", + "title": "Chrome SDK v2 MDNS Test - Mac_Canary_Dev_Release" + }, + "Chrome SDK v2 MDNS Test - Win_Canary_Dev_Release ": { + "configuration": { + "hAxis": { + "slantedText": true + } + }, + "device_type": "eureka", + "sql_data": { + "column_types": [ + "string", + "number", + "number", + "number" + ], + "columns_to_plot": [ + 0, + 1, + 2, + 3 + ], + "headers": { + "Time": 0, + "Tests Run": 1, + "Failures": 2, + "Errors": 3 + }, + "query": "SELECT datetime(test_run.start_timestamp, 'localtime'), test_suite.test_count, test_suite.failure_count, test_suite.error_count FROM test_run, test_suite WHERE test_run.run_id = test_suite.run_id AND test_run.builder_name = 'chrome_sdk_end_to_end_v2_win_canary_dev_release' AND (test_suite.suite_name LIKE '%%mdns_test_bin.html%%' OR test_suite.suite_name = 'TestmDNS') AND test_run.test_name = 'CastChromeEndToEndTestCase' AND datetime(test_run.start_timestamp) >= datetime('now', '-30 days') ORDER BY test_run.start_timestamp;" + }, + "table_description": [ + ["Time", "string"], + ["Tests Run", "number"], + ["Failures", "number"], + ["Errors", "number"] + ], + "test_category": "sdk_Win_Canary_Dev_Release", + "title": "Chrome SDK v2 MDNS Test - Win_Canary_Dev_Release" + }, + "Chrome SDK v2 Media Joining Test - Mac_Canary_Canary_Release ": { + "configuration": { + "hAxis": { + "slantedText": true + } + }, + "device_type": "eureka", + "sql_data": { + "column_types": [ + "string", + "number", + "number", + "number" + ], + "columns_to_plot": [ + 0, + 1, + 2, + 3 + ], + "headers": { + "Time": 0, + "Tests Run": 1, + "Failures": 2, + "Errors": 3 + }, + "query": "SELECT datetime(test_run.start_timestamp, 'localtime'), test_suite.test_count, test_suite.failure_count, test_suite.error_count FROM test_run, test_suite WHERE test_run.run_id = test_suite.run_id AND test_run.builder_name = 'chrome_sdk_end_to_end_v2_mac_canary_canary_release' AND (test_suite.suite_name LIKE '%%media_join_test_bin.html%%' OR test_suite.suite_name = 'TestMediaJoin') AND test_run.test_name = 'CastChromeEndToEndTestCase' AND datetime(test_run.start_timestamp) >= datetime('now', '-30 days') ORDER BY test_run.start_timestamp;" + }, + "table_description": [ + ["Time", "string"], + ["Tests Run", "number"], + ["Failures", "number"], + ["Errors", "number"] + ], + "test_category": "sdk_Mac_Canary_Canary_Release", + "title": "Chrome SDK v2 Media Joining Test - Mac_Canary_Canary_Release" + }, + "Chrome SDK v2 Media Joining Test - Win_Canary_Canary_Latest ": { + "configuration": { + "hAxis": { + "slantedText": true + } + }, + "device_type": "eureka", + "sql_data": { + "column_types": [ + "string", + "number", + "number", + "number" + ], + "columns_to_plot": [ + 0, + 1, + 2, + 3 + ], + "headers": { + "Time": 0, + "Tests Run": 1, + "Failures": 2, + "Errors": 3 + }, + "query": "SELECT datetime(test_run.start_timestamp, 'localtime'), test_suite.test_count, test_suite.failure_count, test_suite.error_count FROM test_run, test_suite WHERE test_run.run_id = test_suite.run_id AND test_run.builder_name = 'chrome_sdk_end_to_end_v2_win_canary_canary_release' AND (test_suite.suite_name LIKE '%%media_join_test_bin.html%%' OR test_suite.suite_name = 'TestMediaJoin') AND test_run.test_name = 'CastChromeEndToEndTestCase' AND datetime(test_run.start_timestamp) >= datetime('now', '-30 days') ORDER BY test_run.start_timestamp;" + }, + "table_description": [ + ["Time", "string"], + ["Tests Run", "number"], + ["Failures", "number"], + ["Errors", "number"] + ], + "test_category": "sdk_Win_Canary_Canary_Release", + "title": "Chrome SDK v2 Media Joining Test - Win_Canary_Canary_Release" + }, + "Chrome SDK v2 Media Joining Test - Mac_Beta_Staging_Dogfood ": { + "configuration": { + "hAxis": { + "slantedText": true + } + }, + "device_type": "eureka", + "sql_data": { + "column_types": [ + "string", + "number", + "number", + "number" + ], + "columns_to_plot": [ + 0, + 1, + 2, + 3 + ], + "headers": { + "Time": 0, + "Tests Run": 1, + "Failures": 2, + "Errors": 3 + }, + "query": "SELECT datetime(test_run.start_timestamp, 'localtime'), test_suite.test_count, test_suite.failure_count, test_suite.error_count FROM test_run, test_suite WHERE test_run.run_id = test_suite.run_id AND test_run.builder_name = 'chrome_sdk_end_to_end_v2_mac_beta_staging_dogfood' AND (test_suite.suite_name LIKE '%%media_join_test_bin.html%%' OR test_suite.suite_name = 'TestMediaJoin') AND test_run.test_name = 'CastChromeEndToEndTestCase' AND datetime(test_run.start_timestamp) >= datetime('now', '-30 days') ORDER BY test_run.start_timestamp;" + }, + "table_description": [ + ["Time", "string"], + ["Tests Run", "number"], + ["Failures", "number"], + ["Errors", "number"] + ], + "test_category": "sdk_Mac_Beta_Staging_Dogfood", + "title": "Chrome SDK v2 Media Joining Test - Mac_Beta_Staging_Dogfood" + }, + "Chrome SDK v2 Media Joining Test - Win_Beta_Staging_Dogfood ": { + "configuration": { + "hAxis": { + "slantedText": true + } + }, + "device_type": "eureka", + "sql_data": { + "column_types": [ + "string", + "number", + "number", + "number" + ], + "columns_to_plot": [ + 0, + 1, + 2, + 3 + ], + "headers": { + "Time": 0, + "Tests Run": 1, + "Failures": 2, + "Errors": 3 + }, + "query": "SELECT datetime(test_run.start_timestamp, 'localtime'), test_suite.test_count, test_suite.failure_count, test_suite.error_count FROM test_run, test_suite WHERE test_run.run_id = test_suite.run_id AND test_run.builder_name = 'chrome_sdk_end_to_end_v2_win_beta_staging_dogfood' AND (test_suite.suite_name LIKE '%%media_join_test_bin.html%%' OR test_suite.suite_name = 'TestMediaJoin') AND test_run.test_name = 'CastChromeEndToEndTestCase' AND datetime(test_run.start_timestamp) >= datetime('now', '-30 days') ORDER BY test_run.start_timestamp;" + }, + "table_description": [ + ["Time", "string"], + ["Tests Run", "number"], + ["Failures", "number"], + ["Errors", "number"] + ], + "test_category": "sdk_Win_Beta_Staging_Dogfood", + "title": "Chrome SDK v2 Media Joining Test - Win_Beta_Staging_Dogfood" + }, + "Chrome SDK v2 Media Joining Test - Mac_Canary_Dev_Release ": { + "configuration": { + "hAxis": { + "slantedText": true + } + }, + "device_type": "eureka", + "sql_data": { + "column_types": [ + "string", + "number", + "number", + "number" + ], + "columns_to_plot": [ + 0, + 1, + 2, + 3 + ], + "headers": { + "Time": 0, + "Tests Run": 1, + "Failures": 2, + "Errors": 3 + }, + "query": "SELECT datetime(test_run.start_timestamp, 'localtime'), test_suite.test_count, test_suite.failure_count, test_suite.error_count FROM test_run, test_suite WHERE test_run.run_id = test_suite.run_id AND test_run.builder_name = 'chrome_sdk_end_to_end_v2_mac_canary_dev_release' AND (test_suite.suite_name LIKE '%%media_join_test_bin.html%%' OR test_suite.suite_name = 'TestMediaJoin') AND test_run.test_name = 'CastChromeEndToEndTestCase' AND datetime(test_run.start_timestamp) >= datetime('now', '-30 days') ORDER BY test_run.start_timestamp;" + }, + "table_description": [ + ["Time", "string"], + ["Tests Run", "number"], + ["Failures", "number"], + ["Errors", "number"] + ], + "test_category": "sdk_Mac_Canary_Dev_Release", + "title": "Chrome SDK v2 Media Joining Test - Mac_Canary_Dev_Release" + }, + "Chrome SDK v2 Media Joining Test - Win_Canary_Dev_Release ": { + "configuration": { + "hAxis": { + "slantedText": true + } + }, + "device_type": "eureka", + "sql_data": { + "column_types": [ + "string", + "number", + "number", + "number" + ], + "columns_to_plot": [ + 0, + 1, + 2, + 3 + ], + "headers": { + "Time": 0, + "Tests Run": 1, + "Failures": 2, + "Errors": 3 + }, + "query": "SELECT datetime(test_run.start_timestamp, 'localtime'), test_suite.test_count, test_suite.failure_count, test_suite.error_count FROM test_run, test_suite WHERE test_run.run_id = test_suite.run_id AND test_run.builder_name = 'chrome_sdk_end_to_end_v2_win_canary_dev_release' AND (test_suite.suite_name LIKE '%%media_join_test_bin.html%%' OR test_suite.suite_name = 'TestMediaJoin') AND test_run.test_name = 'CastChromeEndToEndTestCase' AND datetime(test_run.start_timestamp) >= datetime('now', '-30 days') ORDER BY test_run.start_timestamp;" + }, + "table_description": [ + ["Time", "string"], + ["Tests Run", "number"], + ["Failures", "number"], + ["Errors", "number"] + ], + "test_category": "sdk_Win_Canary_Dev_Release", + "title": "Chrome SDK v2 Media Joining Test - Win_Canary_Dev_Release" + }, + "Chrome SDK v2 Auto Joining Test - Mac_Canary_Canary_Release ": { + "configuration": { + "hAxis": { + "slantedText": true + } + }, + "device_type": "eureka", + "sql_data": { + "column_types": [ + "string", + "number", + "number", + "number" + ], + "columns_to_plot": [ + 0, + 1, + 2, + 3 + ], + "headers": { + "Time": 0, + "Tests Run": 1, + "Failures": 2, + "Errors": 3 + }, + "query": "SELECT datetime(test_run.start_timestamp, 'localtime'), test_suite.test_count, test_suite.failure_count, test_suite.error_count FROM test_run, test_suite WHERE test_run.run_id = test_suite.run_id AND test_run.builder_name = 'chrome_sdk_end_to_end_v2_mac_canary_canary_release' AND (test_suite.suite_name LIKE '%%/auto_join_test_bin.html%%' OR test_suite.suite_name = 'TestAutoJoin') AND test_run.test_name = 'CastChromeEndToEndTestCase' AND datetime(test_run.start_timestamp) >= datetime('now', '-30 days') ORDER BY test_run.start_timestamp;" + }, + "table_description": [ + ["Time", "string"], + ["Tests Run", "number"], + ["Failures", "number"], + ["Errors", "number"] + ], + "test_category": "sdk_Mac_Canary_Canary_Release", + "title": "Chrome SDK v2 Auto Join Test - Mac_Canary_Canary_Release" + }, + "Chrome SDK v2 Auto Joining Test - Win_Canary_Canary_Release ": { + "configuration": { + "hAxis": { + "slantedText": true + } + }, + "device_type": "eureka", + "sql_data": { + "column_types": [ + "string", + "number", + "number", + "number" + ], + "columns_to_plot": [ + 0, + 1, + 2, + 3 + ], + "headers": { + "Time": 0, + "Tests Run": 1, + "Failures": 2, + "Errors": 3 + }, + "query": "SELECT datetime(test_run.start_timestamp, 'localtime'), test_suite.test_count, test_suite.failure_count, test_suite.error_count FROM test_run, test_suite WHERE test_run.run_id = test_suite.run_id AND test_run.builder_name = 'chrome_sdk_end_to_end_v2_win_canary_canary_release' AND (test_suite.suite_name LIKE '%%/auto_join_test_bin.html%%' OR test_suite.suite_name = 'TestAutoJoin') AND test_run.test_name = 'CastChromeEndToEndTestCase' AND datetime(test_run.start_timestamp) >= datetime('now', '-30 days') ORDER BY test_run.start_timestamp;" + }, + "table_description": [ + ["Time", "string"], + ["Tests Run", "number"], + ["Failures", "number"], + ["Errors", "number"] + ], + "test_category": "sdk_Win_Canary_Canary_Release", + "title": "Chrome SDK v2 Auto Join Test - Win_Canary_Canary_Release" + }, + "Chrome SDK v2 Auto Joining Test - Mac_Beta_Staging_Dogfood ": { + "configuration": { + "hAxis": { + "slantedText": true + } + }, + "device_type": "eureka", + "sql_data": { + "column_types": [ + "string", + "number", + "number", + "number" + ], + "columns_to_plot": [ + 0, + 1, + 2, + 3 + ], + "headers": { + "Time": 0, + "Tests Run": 1, + "Failures": 2, + "Errors": 3 + }, + "query": "SELECT datetime(test_run.start_timestamp, 'localtime'), test_suite.test_count, test_suite.failure_count, test_suite.error_count FROM test_run, test_suite WHERE test_run.run_id = test_suite.run_id AND test_run.builder_name = 'chrome_sdk_end_to_end_v2_mac_beta_staging_dogfood' AND (test_suite.suite_name LIKE '%%/auto_join_test_bin.html%%' OR test_suite.suite_name = 'TestAutoJoin') AND test_run.test_name = 'CastChromeEndToEndTestCase' AND datetime(test_run.start_timestamp) >= datetime('now', '-30 days') ORDER BY test_run.start_timestamp;" + }, + "table_description": [ + ["Time", "string"], + ["Tests Run", "number"], + ["Failures", "number"], + ["Errors", "number"] + ], + "test_category": "sdk_Mac_Beta_Staging_Dogfood", + "title": "Chrome SDK v2 Auto Joining Test - Mac_Beta_Staging_Dogfood" + }, + "Chrome SDK v2 Auto Joining Test - Win_Beta_Staging_Dogfood ": { + "configuration": { + "hAxis": { + "slantedText": true + } + }, + "device_type": "eureka", + "sql_data": { + "column_types": [ + "string", + "number", + "number", + "number" + ], + "columns_to_plot": [ + 0, + 1, + 2, + 3 + ], + "headers": { + "Time": 0, + "Tests Run": 1, + "Failures": 2, + "Errors": 3 + }, + "query": "SELECT datetime(test_run.start_timestamp, 'localtime'), test_suite.test_count, test_suite.failure_count, test_suite.error_count FROM test_run, test_suite WHERE test_run.run_id = test_suite.run_id AND test_run.builder_name = 'chrome_sdk_end_to_end_v2_win_beta_staging_dogfood' AND (test_suite.suite_name LIKE '%%/auto_join_test_bin.html%%' OR test_suite.suite_name = 'TestAutoJoin') AND test_run.test_name = 'CastChromeEndToEndTestCase' AND datetime(test_run.start_timestamp) >= datetime('now', '-30 days') ORDER BY test_run.start_timestamp;" + }, + "table_description": [ + ["Time", "string"], + ["Tests Run", "number"], + ["Failures", "number"], + ["Errors", "number"] + ], + "test_category": "sdk_Win_Beta_Staging_Dogfood", + "title": "Chrome SDK v2 Auto Joining Test - Win_Beta_Staging_Dogfood" + }, + "Chrome SDK v2 Auto Joining Test - Mac_Canary_Dev_Release ": { + "configuration": { + "hAxis": { + "slantedText": true + } + }, + "device_type": "eureka", + "sql_data": { + "column_types": [ + "string", + "number", + "number", + "number" + ], + "columns_to_plot": [ + 0, + 1, + 2, + 3 + ], + "headers": { + "Time": 0, + "Tests Run": 1, + "Failures": 2, + "Errors": 3 + }, + "query": "SELECT datetime(test_run.start_timestamp, 'localtime'), test_suite.test_count, test_suite.failure_count, test_suite.error_count FROM test_run, test_suite WHERE test_run.run_id = test_suite.run_id AND test_run.builder_name = 'chrome_sdk_end_to_end_v2_mac_canary_dev_release' AND (test_suite.suite_name LIKE '%%/auto_join_test_bin.html%%' OR test_suite.suite_name = 'TestAutoJoin') AND test_run.test_name = 'CastChromeEndToEndTestCase' AND datetime(test_run.start_timestamp) >= datetime('now', '-30 days') ORDER BY test_run.start_timestamp;" + }, + "table_description": [ + ["Time", "string"], + ["Tests Run", "number"], + ["Failures", "number"], + ["Errors", "number"] + ], + "test_category": "sdk_Mac_Canary_Dev_Release", + "title": "Chrome SDK v2 Auto Join Test - Mac_Canary_Dev_Release" + }, + "Chrome SDK v2 Auto Joining Test - Win_Canary_Dev_Release ": { + "configuration": { + "hAxis": { + "slantedText": true + } + }, + "device_type": "eureka", + "sql_data": { + "column_types": [ + "string", + "number", + "number", + "number" + ], + "columns_to_plot": [ + 0, + 1, + 2, + 3 + ], + "headers": { + "Time": 0, + "Tests Run": 1, + "Failures": 2, + "Errors": 3 + }, + "query": "SELECT datetime(test_run.start_timestamp, 'localtime'), test_suite.test_count, test_suite.failure_count, test_suite.error_count FROM test_run, test_suite WHERE test_run.run_id = test_suite.run_id AND test_run.builder_name = 'chrome_sdk_end_to_end_v2_win_canary_dev_release' AND (test_suite.suite_name LIKE '%%/auto_join_test_bin.html%%' OR test_suite.suite_name = 'TestAutoJoin') AND test_run.test_name = 'CastChromeEndToEndTestCase' AND datetime(test_run.start_timestamp) >= datetime('now', '-30 days') ORDER BY test_run.start_timestamp;" + }, + "table_description": [ + ["Time", "string"], + ["Tests Run", "number"], + ["Failures", "number"], + ["Errors", "number"] + ], + "test_category": "sdk_Win_Canary_Dev_Release", + "title": "Chrome SDK v2 Auto Join Test - Win_Canary_Dev_Release" + } +}
diff --git a/lab_system/master/config/kir/device_type/dummy.cfg b/lab_system/master/config/kir/device_type/dummy.cfg new file mode 100755 index 0000000..90c2b48 --- /dev/null +++ b/lab_system/master/config/kir/device_type/dummy.cfg
@@ -0,0 +1,29 @@ +# Config file for dummy device type. +# +# To activate a change in a configuration value, run: +# +# buildbot reconfig +# +# That will force the running buildbot instance to reconfigure +# and use the new configuration values. +# +# It is generally safe to change configuration values, +# but changing configuration names is not recommended as it will result +# in errors. +# +# Every device_type to test requires a device_type config file. +# +# PROPERTIES + + +# Product name of dummy device. +# PRODUCT_NAME value is passed to the GET_LATEST_BUILD_SCRIPT via the +# --product flag. + +PRODUCT_NAME=dummy + +# Name to be used for <type_template> tests. +# The value must correspond with the device types defined in the database +# by the device allocator (galloc). + +DEVICE_TYPE=dummy \ No newline at end of file
diff --git a/lab_system/master/config/kir/device_type/eureka.cfg b/lab_system/master/config/kir/device_type/eureka.cfg new file mode 100644 index 0000000..60c066d --- /dev/null +++ b/lab_system/master/config/kir/device_type/eureka.cfg
@@ -0,0 +1,14 @@ +# Config file for eureka device type +# +# Do not modify the property names +# +# Run make reconfig if you change a value +# and buildbot is running +# +# PROPERTIES + +# name to be used for eureka tests, usually eureka +DEVICE_TYPE=eureka + +# ota zip file format is: PRODUCT_NAME-OTA_NAME-BUILD.zip +PRODUCT_NAME=anchovy
diff --git a/lab_system/master/config/kir/groups/acer_i5_2450m_intelhd3000_win7.cfg b/lab_system/master/config/kir/groups/acer_i5_2450m_intelhd3000_win7.cfg new file mode 100644 index 0000000..ee5a88d --- /dev/null +++ b/lab_system/master/config/kir/groups/acer_i5_2450m_intelhd3000_win7.cfg
@@ -0,0 +1,25 @@ +# Config file for acer_i5_2450m_intelhd3000_win7 slave + +# PROPERTIES + +SPECIFIC_DEVICE_IP=172.31.25.7 +SELF_IP=172.31.25.2 + +HOME_DIR=C:/Users/gtvchrome +USER_NAME=gtvchrome +CHROME_DRIVER=chromedriver.exe +CHROME_ZIP=chrome-win32.zip +CHROME_PATH=chrome-win32 +PLATFORM=win + +CHROME_FOLDER=/usr/local/google/home/repositories/fraggle_rock/config/tests/chrome_mirroring/latest_chrome/acer_i5_2450m_intelhd3000_win7 +CHROME_VERSION=canary +EXTENSION_FOLDER=/usr/local/google/home/repositories/fraggle_rock/config/tests/chrome_mirroring/extension/acer_i5_2450m_intelhd3000_win7 +EXTENSION_BUILD=canary + +MASTER_HOME_DIR=/usr/local/google/home/repositories +CHROME_PERF_DASHBOARD=https://chromeperf.appspot.com/add_point + +# TODO (cliffordcheng): To be added +#DEVICE_TYPE=win +#DEVICE_GROUP=acer_i5_2450m_intelhd3000_win7
diff --git a/lab_system/master/config/kir/groups/acer_i5_3337u_intelhd4000_win8.cfg b/lab_system/master/config/kir/groups/acer_i5_3337u_intelhd4000_win8.cfg new file mode 100755 index 0000000..3c20b96 --- /dev/null +++ b/lab_system/master/config/kir/groups/acer_i5_3337u_intelhd4000_win8.cfg
@@ -0,0 +1,32 @@ +# Config file for acer_i5_3337u_intelhd4000_win8 slave + +# PROPERTIES + +SPECIFIC_DEVICE_IP=172.31.25.7 +SELF_IP=172.31.25.20 + +HOME_DIR=C:/Users/gtvchrome +USER_NAME=gtvchrome +CHROME_DRIVER=chromedriver.exe +CHROME_ZIP=chrome-win32.zip +CHROME_PATH=chrome-win32 +PLATFORM=win + +CHROME_FOLDER=/usr/local/google/home/repositories/fraggle_rock/config/tests/chrome_mirroring/latest_chrome/acer_i5_3337u_intelhd4000_win8 +CHROME_VERSION=canary +EXTENSION_FOLDER=/usr/local/google/home/repositories/fraggle_rock/config/tests/chrome_mirroring/extension/acer_i5_3337u_intelhd4000_win8 +EXTENSION_BUILD=staging + +MASTER_HOME_DIR=/usr/local/google/home/repositories +CHROME_PERF_DASHBOARD=https://chromeperf.appspot.com/add_point + +SENDER_DEVICE_TYPE=mac +SENDER_DEVICE_GROUP=video_recorder_set_0 +SENDER_DEVICE_NUMBER=1 + +PROCESSOR_MACHINE_IP=172.31.25.28 +PROCESSOR_DEVICE_TYPE=linux +PROCESSOR_DEVICE_GROUP=video_processing_machine_0 +PROCESSOR_DEVICE_NUMBER=1 +PROCESSOR_RESULTS_DIR=/home/gtvchrome/results +PROCESSOR_TEST_DIR=/home/gtvchrome/repository/eureka/test
diff --git a/lab_system/master/config/kir/groups/asus_i3_2328m_intelhd3000_win8.cfg b/lab_system/master/config/kir/groups/asus_i3_2328m_intelhd3000_win8.cfg new file mode 100644 index 0000000..386ba09 --- /dev/null +++ b/lab_system/master/config/kir/groups/asus_i3_2328m_intelhd3000_win8.cfg
@@ -0,0 +1,31 @@ +# Config file for asus_i3_2328m_intelhd3000_win8 slave + +# PROPERTIES + +SELF_IP=172.31.25.2 + +HOME_DIR=C:/Users/gtvchrome +USER_NAME=gtvchrome +CHROME_DRIVER=chromedriver.exe +CHROME_ZIP=chrome-win32.zip +CHROME_PATH=chrome-win +PLATFORM=win + +CHROME_FOLDER=/usr/local/google/home/repositories/fraggle_rock/config/tests/chrome_mirroring/latest_chrome/asus_i3_2328m_intelhd3000_win8 +CHROME_VERSION=canary +EXTENSION_FOLDER=/usr/local/google/home/repositories/fraggle_rock/config/tests/chrome_mirroring/extension/asus_i3_2328m_intelhd3000_win8 +EXTENSION_BUILD=staging + +MASTER_HOME_DIR=/usr/local/google/home/repositories +CHROME_PERF_DASHBOARD=https://chromeperf.appspot.com/add_point + +SENDER_DEVICE_TYPE=mac +SENDER_DEVICE_GROUP=video_recorder_set_0 +SENDER_DEVICE_NUMBER=1 + +PROCESSOR_MACHINE_IP=172.31.25.28 +PROCESSOR_DEVICE_TYPE=linux +PROCESSOR_DEVICE_GROUP=video_processing_machine_0 +PROCESSOR_DEVICE_NUMBER=1 +PROCESSOR_RESULTS_DIR=/home/gtvchrome/results +PROCESSOR_TEST_DIR=/home/gtvchrome/repository/eureka/test
diff --git a/lab_system/master/config/kir/groups/bling_cast.cfg b/lab_system/master/config/kir/groups/bling_cast.cfg new file mode 100644 index 0000000..90fd6d1 --- /dev/null +++ b/lab_system/master/config/kir/groups/bling_cast.cfg
@@ -0,0 +1,31 @@ +# Configuration values for the bling Web SDK e2e test. + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.cast.bling.end_to_end_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=CastBlingEndToEndTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.cast.bling.end_to_end_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=CastBlingEndToEndTestSequence + +# The mac device's username +MAC_USERNAME=gtvchrome + +# The type of the macbook to be used +MAC_DEVICE_TYPE=mac + +# The group of the macbook to be used +MAC_DEVICE_GROUP=bling_cast + +# The mac device's home dir +MAC_HOME_DIR=/Users/gtvchrome + +# The type of the iOS to be used, using 32 bit iOS device +IOS_DEVICE_TYPE=iphone + +# The group of the iOS device to be used +IOS_DEVICE_GROUP=bling_cast
diff --git a/lab_system/master/config/kir/groups/chrome_sdk_end_to_end_v2.cfg b/lab_system/master/config/kir/groups/chrome_sdk_end_to_end_v2.cfg new file mode 100755 index 0000000..faf776b --- /dev/null +++ b/lab_system/master/config/kir/groups/chrome_sdk_end_to_end_v2.cfg
@@ -0,0 +1,31 @@ +# Config file for chrome_sdk_end_to_end_v2 group + +# PROPERTIES +REMOTE_TEST_FILES_FOLDER=/var/www/http + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.cast.chrome.end_to_end_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=CastChromeEndToEndTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.framework.javascript_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=JavascriptTestSequence + +# Location of test binary +TEST_BINARY_FILE=gs://test_logs/test_binaries/test_bin.zip + +# Location of changelist file +EXTENSION_CHANGELIST_FILE=gs://test_logs/test_binaries/changelist.txt + +# Location of dev extension +DEV_EXTENSION_FILE=gs://test_logs/test_binaries/extension_dev.zip + +# Account information used to download internal cast extension +ACCOUNT_FILE=/usr/local/google/home/repository/credentials/account.txt + +# Public keys for different cast extensions +EXTENSION_PUBLIC_KEYS_FILE=/usr/local/google/home/repository/credentials/public_keys.json
diff --git a/lab_system/master/config/kir/groups/hp_core2duo_p8600_gma4500_win7.cfg b/lab_system/master/config/kir/groups/hp_core2duo_p8600_gma4500_win7.cfg new file mode 100644 index 0000000..fc48317 --- /dev/null +++ b/lab_system/master/config/kir/groups/hp_core2duo_p8600_gma4500_win7.cfg
@@ -0,0 +1,33 @@ +# Config file for hp_core2duo_p8600_gma4500_win7 slave + +# PROPERTIES + +SPECIFIC_DEVICE_IP=172.31.25.1 +SELF_IP=172.31.25.17 + +HOME_DIR=C:/Users/gtvchrome +USER_NAME=gtvchrome +CHROME_DRIVER=chromedriver.exe +CHROME_ZIP=chrome-win32.zip +CHROME_PATH=chrome-win32 +PLATFORM=win + +CHROME_FOLDER=/usr/local/google/home/repositories/fraggle_rock/config/tests/chrome_mirroring/latest_chrome/hp_core2duo_p8600_gma4500_win7 +CHROME_VERSION=canary +EXTENSION_FOLDER=/usr/local/google/home/repositories/fraggle_rock/config/tests/chrome_mirroring/extension/hp_core2duo_p8600_gma4500_win7 +EXTENSION_BUILD=staging + +MASTER_HOME_DIR=/usr/local/google/home/repositories +CHROME_PERF_DASHBOARD=https://chromeperf.appspot.com/add_point + +SENDER_DEVICE_TYPE=mac +SENDER_DEVICE_GROUP=video_recorder_set_1 +SENDER_DEVICE_NUMBER=1 + +PROCESSOR_MACHINE_IP=172.31.25.28 +PROCESSOR_DEVICE_TYPE=linux +PROCESSOR_DEVICE_GROUP=video_processing_machine_1 +PROCESSOR_DEVICE_NUMBER=1 +PROCESSOR_RESULTS_DIR=/home/gtvchrome/results +PROCESSOR_TEST_DIR=/home/gtvchrome/repository/eureka/test +
diff --git a/lab_system/master/config/kir/groups/hp_core_i5_3210m_intelhd4000_win8_mtv.cfg b/lab_system/master/config/kir/groups/hp_core_i5_3210m_intelhd4000_win8_mtv.cfg new file mode 100644 index 0000000..834ac55 --- /dev/null +++ b/lab_system/master/config/kir/groups/hp_core_i5_3210m_intelhd4000_win8_mtv.cfg
@@ -0,0 +1,30 @@ +# Config file for hp_core_i5 in MTV lab. + +# PROPERTIES +SELF_IP=172.17.23.78 +HOME_DIR=C:/Users/gtvchrome +USER_NAME=gtvchrome +CHROME_DRIVER=chromedriver.exe +PLATFORM=win + +# Mirroring test chrome build +CHROME_VERSION=beta + +# Mirroring test extension flavor +EXTENSION_BUILD=beta + +# Recorder machine +SENDER_DEVICE_TYPE=mac +SENDER_DEVICE_GROUP=video_recorder_mtv +SENDER_DEVICE_NUMBER=1 + + +PROCESSOR_MACHINE_IP=172.31.25.28 +PROCESSOR_DEVICE_TYPE=linux +PROCESSOR_DEVICE_GROUP=video_processing_machine_0 +PROCESSOR_DEVICE_NUMBER=1 +PROCESSOR_RESULTS_DIR=/home/gtvchrome/results +PROCESSOR_TEST_DIR=/home/gtvchrome/repository/eureka/test + + +
diff --git a/lab_system/master/config/kir/groups/macbookair_i5_2557m_intelhd3000.cfg b/lab_system/master/config/kir/groups/macbookair_i5_2557m_intelhd3000.cfg new file mode 100644 index 0000000..4751c2d --- /dev/null +++ b/lab_system/master/config/kir/groups/macbookair_i5_2557m_intelhd3000.cfg
@@ -0,0 +1,27 @@ +# Config file for macbookair_i5_2557m_intelhd3000 slave + +# PROPERTIES + +SPECIFIC_DEVICE_IP=172.31.25.3 +SELF_IP=172.31.25.29 + +HOME_DIR=/Users/gtvchrome +USER_NAME=gtvchrome +CHROME_DRIVER=chromedriver +CHROME_ZIP=chrome-mac.zip +CHROME_PATH=chrome-mac +PLATFORM=mac + +CHROME_FOLDER=/usr/local/google/home/repositories/fraggle_rock/config/tests/chrome_mirroring/latest_chrome/macbookair_i5_2557m_intelhd3000 +CHROME_VERSION=canary +EXTENSION_FOLDER=/usr/local/google/home/repositories/fraggle_rock/config/tests/chrome_mirroring/extension/macbookair_i5_2557m_intelhd3000 +EXTENSION_BUILD=canary + +MASTER_HOME_DIR=/usr/local/google/home/repositories +CHROME_PERF_DASHBOARD=https://chromeperf.appspot.com/add_point + +SENDER_DEVICE_TYPE=mac +SENDER_DEVICE_GROUP=video_recorder_set_0 +SENDER_DEVICE_NUMBER=1 + +PROCESSOR_MACHINE_IP=172.31.25.11
diff --git a/lab_system/master/config/kir/groups/macbookair_i5_4250u_intelhd5000.cfg b/lab_system/master/config/kir/groups/macbookair_i5_4250u_intelhd5000.cfg new file mode 100755 index 0000000..d6da498 --- /dev/null +++ b/lab_system/master/config/kir/groups/macbookair_i5_4250u_intelhd5000.cfg
@@ -0,0 +1,33 @@ +# Config file for macbookair_i5_4250u_intelhd5000 slave + +# PROPERTIES + +SPECIFIC_DEVICE_IP=172.31.25.19 +SELF_IP=172.31.25.27 + +HOME_DIR=/Users/gtvchrome +USER_NAME=gtvchrome +CHROME_DRIVER=chromedriver +CHROME_ZIP=chrome-mac.zip +CHROME_PATH=chrome-mac +PLATFORM=mac + +CHROME_FOLDER=/usr/local/google/home/repositories/fraggle_rock/config/tests/chrome_mirroring/latest_chrome/macbookair_i5_4250u_intelhd5000 +CHROME_VERSION=canary +EXTENSION_FOLDER=/usr/local/google/home/repositories/fraggle_rock/config/tests/chrome_mirroring/extension/macbookair_i5_4250u_intelhd5000 +EXTENSION_BUILD=staging + +MASTER_HOME_DIR=/usr/local/google/home/repositories +CHROME_PERF_DASHBOARD=https://chromeperf.appspot.com/add_point + +SENDER_DEVICE_TYPE=mac +SENDER_DEVICE_GROUP=video_recorder_set_1 +SENDER_DEVICE_NUMBER=1 + +PROCESSOR_MACHINE_IP=172.31.25.28 +PROCESSOR_DEVICE_TYPE=linux +PROCESSOR_DEVICE_GROUP=video_processing_machine_1 +PROCESSOR_DEVICE_NUMBER=1 +PROCESSOR_RESULTS_DIR=/home/gtvchrome/results +PROCESSOR_TEST_DIR=/home/gtvchrome/repository/eureka/test +
diff --git a/lab_system/master/config/kir/groups/macbookair_i5_4250u_intelhd5000_mtv.cfg b/lab_system/master/config/kir/groups/macbookair_i5_4250u_intelhd5000_mtv.cfg new file mode 100644 index 0000000..d7321cc --- /dev/null +++ b/lab_system/master/config/kir/groups/macbookair_i5_4250u_intelhd5000_mtv.cfg
@@ -0,0 +1,27 @@ +onfig file for macbook air in MTV lab. + +# PROPERTIES +SELF_IP=172.17.23.86 +HOME_DIR=/Users/gtvchrome +USER_NAME=gtvchrome +CHROME_DRIVER=chromedriver +PLATFORM=mac + +# Mirroring test chrome build +CHROME_VERSION=beta + +# Mirroring test extension flavor +EXTENSION_BUILD=beta + +# Recorder machine +SENDER_DEVICE_TYPE=mac +SENDER_DEVICE_GROUP=video_recorder_mtv +SENDER_DEVICE_NUMBER=1 + + +PROCESSOR_MACHINE_IP=172.31.25.28 +PROCESSOR_DEVICE_TYPE=linux +PROCESSOR_DEVICE_GROUP=video_processing_machine_0 +PROCESSOR_DEVICE_NUMBER=1 +PROCESSOR_RESULTS_DIR=/home/gtvchrome/results +PROCESSOR_TEST_DIR=/home/gtvchrome/repository/eureka/test
diff --git a/lab_system/master/config/kir/groups/macbookpro_i7_2675qm_radeon6750m.cfg b/lab_system/master/config/kir/groups/macbookpro_i7_2675qm_radeon6750m.cfg new file mode 100755 index 0000000..ad0aeea --- /dev/null +++ b/lab_system/master/config/kir/groups/macbookpro_i7_2675qm_radeon6750m.cfg
@@ -0,0 +1,33 @@ +# Config file for macbookpro_i7_2675qm_radeon6750m slave + +# PROPERTIES + +SPECIFIC_DEVICE_IP=172.31.25.8 +SELF_IP=172.31.25.22 + +HOME_DIR=/Users/gtvchrome +USER_NAME=gtvchrome +CHROME_DRIVER=chromedriver +CHROME_ZIP=chrome-mac.zip +CHROME_PATH=chrome-mac +PLATFORM=mac + +CHROME_FOLDER=/usr/local/google/home/repositories/fraggle_rock/config/tests/chrome_mirroring/latest_chrome/macbookpro_i7_2675qm_radeon6750m +CHROME_VERSION=canary +EXTENSION_FOLDER=/usr/local/google/home/repositories/fraggle_rock/config/tests/chrome_mirroring/extension/macbookpro_i7_2675qm_radeon6750m +EXTENSION_BUILD=staging + +MASTER_HOME_DIR=/usr/local/google/home/repositories +CHROME_PERF_DASHBOARD=https://chromeperf.appspot.com/add_point + +SENDER_DEVICE_TYPE=mac +SENDER_DEVICE_GROUP=video_recorder_set_1 +SENDER_DEVICE_NUMBER=1 + +PROCESSOR_MACHINE_IP=172.31.25.28 +PROCESSOR_DEVICE_TYPE=linux +PROCESSOR_DEVICE_GROUP=video_processing_machine_1 +PROCESSOR_DEVICE_NUMBER=1 +PROCESSOR_RESULTS_DIR=/home/gtvchrome/results +PROCESSOR_TEST_DIR=/home/gtvchrome/repository/eureka/test +
diff --git a/lab_system/master/config/kir/groups/samsung_i7_3630qm_radeon7730m_win8.cfg b/lab_system/master/config/kir/groups/samsung_i7_3630qm_radeon7730m_win8.cfg new file mode 100644 index 0000000..29dca4b --- /dev/null +++ b/lab_system/master/config/kir/groups/samsung_i7_3630qm_radeon7730m_win8.cfg
@@ -0,0 +1,30 @@ +# Config file for samsung_i7_3630qm_radeon7730m_win8 slave + +# PROPERTIES + +SPECIFIC_DEVICE_IP=172.31.25.10 +SELF_IP=172.31.25.15 + +HOME_DIR=C:/Users/gtvchrome +USER_NAME=gtvchrome +CHROME_DRIVER=chromedriver.exe +CHROME_ZIP=chrome-win32.zip +CHROME_PATH=chrome-win32 +PLATFORM=win + +CHROME_VERSION=canary +EXTENSION_BUILD=staging + +MASTER_HOME_DIR=/usr/local/google/home/repositories +CHROME_PERF_DASHBOARD=https://chromeperf.appspot.com/add_point + +SENDER_DEVICE_TYPE=mac +SENDER_DEVICE_GROUP=video_recorder_set_0 +SENDER_DEVICE_NUMBER=1 + +PROCESSOR_MACHINE_IP=172.31.25.28 +PROCESSOR_DEVICE_TYPE=linux +PROCESSOR_DEVICE_GROUP=video_processing_machine_0 +PROCESSOR_DEVICE_NUMBER=1 +PROCESSOR_RESULTS_DIR=/home/gtvchrome/results +PROCESSOR_TEST_DIR=/home/gtvchrome/repository/eureka/test
diff --git a/lab_system/master/config/kir/groups/trial_machine_win.cfg b/lab_system/master/config/kir/groups/trial_machine_win.cfg new file mode 100755 index 0000000..69b3077 --- /dev/null +++ b/lab_system/master/config/kir/groups/trial_machine_win.cfg
@@ -0,0 +1,32 @@ +# Config file for trial_machine_win slave + +# PROPERTIES + +SPECIFIC_DEVICE_IP=172.31.25.7 +SELF_IP=172.31.25.20 + +HOME_DIR=C:/Users/gtvchrome +USER_NAME=gtvchrome +CHROME_DRIVER=chromedriver.exe +CHROME_ZIP=chrome-win32.zip +CHROME_PATH=chrome-win32 +PLATFORM=win + +CHROME_FOLDER=/usr/local/google/home/repositories/fraggle_rock/config/tests/chrome_mirroring/latest_chrome/trial_machine_win +CHROME_VERSION=canary +EXTENSION_FOLDER=/usr/local/google/home/repositories/fraggle_rock/config/tests/chrome_mirroring/extension/trial_machine_win +EXTENSION_BUILD=staging + +MASTER_HOME_DIR=/usr/local/google/home/repositories +CHROME_PERF_DASHBOARD=https://chromeperf.appspot.com/add_point + +SENDER_DEVICE_TYPE=mac +SENDER_DEVICE_GROUP=video_recorder_set_0 +SENDER_DEVICE_NUMBER=1 + +PROCESSOR_MACHINE_IP=172.31.25.28 +PROCESSOR_DEVICE_TYPE=linux +PROCESSOR_DEVICE_GROUP=video_processing_machine_0 +PROCESSOR_DEVICE_NUMBER=1 +PROCESSOR_RESULTS_DIR=/home/gtvchrome/results +PROCESSOR_TEST_DIR=/home/gtvchrome/repository/eureka/test
diff --git a/lab_system/master/config/kir/site/site.cfg b/lab_system/master/config/kir/site/site.cfg new file mode 100755 index 0000000..dce4e9f --- /dev/null +++ b/lab_system/master/config/kir/site/site.cfg
@@ -0,0 +1,299 @@ +# Config file for site wide values. +# +# These values are expected to change on a site by site basis. If the system +# is set up in a new location, these values would need to be changed to work +# at that location. +# +# To activate a change in a configuration value, run: +# +# buildbot reconfig +# +# That will force the running buildbot instance to reconfigure +# and use the new configuration values. +# +# It is generally safe to change configuration values, but changing or +# deleting configuration names is not recommended as it will result +# in errors. +# +# PROPERTIES + +# EUREKA_TEST_DIRECTORY is the same as INTERNAL_REPOSITYORY_PATH +EUREKA_TEST_DIRECTORY=/usr/local/google/home/repository/eureka + +# Enables functionality that is only available within Google if set to 1. +# If running externally, set this to 0 to ensure that all Google specific +# functionality is not run. + +G_INTERNAL=0 + +# CTS reporting root directory. It should be a place accessible from web to +# view results. + +CTS_REPORTING_DIRECTORY=/path/to/cts/reporting/dir + +# Path to logs storage dir when tests run. + +LOCAL_LOGS_DIRECTORY=/usr/local/google/home/logs/logs + +# Bug search tool. + +BUG_SEARCH_COMMAND=/path/to/tool --param= + +# The script defined in GET_LATEST_BUILD_SCRIPT property identifies the path and +# build number of the latest Google TV build to use for testing. +# +# Before each test is launched, the script is executed. The script is expected +# to output the path to the latest build when --output_format is set to "path". +# It is expected to output the number of the latest build +# when --output_format is set to "number". +# +# If --build_number is provided, the script is expected to output the path to +# the build zip file for that build number. +# +# It is up to the user to implement the script. It can be a simple bash script +# or a more involved binary. The only requirement is that the script adheres to +# the command line signature detailed below. +# +# An implementation of the script is free to use or ignore the values of the +# command line flags passed to the script. However, it must accept the flags. +# If an implementation of the script does not accept these flags, +# all tests will fail at the GET_BUILD step. +# +# For convenience, a template python script exists in +# lab_system/get_latest_build.py +# That template can be copied and extended for a new site installation. +# +# The GET_LATEST_BUILD_SCRIPT is passed the following parameters. Again, +# implementations can use or ignore these values internally, but they must allow +# them. +# +# --build_number +# +# This is the number of a build. When provided, the script is expected to output +# the path to the given build number. +# +# --output_mode +# +# This defines how the output is formatted. There are two values used: "path" +# and "number". +# +# In "path" mode, the full path to the latest build zip file is output by +# the script. +# In "number" mode, the latest build number is output by the script. +# +# --branch +# +# This is the branch of the build. This corresponds to the BRANCH_NAME +# value in the config/branch/<branch>.cfg file. +# +# --product +# +# This is the code name of the Google TV product. +# Different implementations of Google TV (eg. buddy box vs. a TV) +# have identifying code names. +# This parameter specifies which implementation is to be tested. +# +# This parameter will be set to the PRODUCT_NAME specified in +# config/device_type/<device_type>.cfg +# +# --build_output_type +# +# This is the type of the output produced by the build process. +# The "ota" build is the build zip file that is installed on a Google TV device. +# The "symbols" build is generated by the build process to enable symbolization +# of stack traces from the native code level. +# The "tests" build zip contains the binaries for unit tests +# and native system tests. +# +# The "ota" build is most commonly used; tests will not run if the +# GET_LATEST_BUILD_SCRIPT does not work with the "ota" flag. "symbols" is +# optional; if a symbolized build zip is not available, the only impact is +# that the parsed logs from tests will not have symbolized stack traces. +# +# "tests" is required if Google TV unit tests are being run. +# +# --flavor +# +# The values passed to --flavor are "eng" or "tests". +# "eng" specifies the eng build is to be used. +# +# This is a Google TV build that is built with "eng" permissions. +# "tests" is for Google TV builds that are output when building the "tests" +# build flavor. For more information on build flavors, see the Google TV build +# documentation. +# +# "tests" is required if Google TV unit tests are being run. +# +# The GET_LATEST_BUILD_SCRIPT script must be executable by the user +# running the buildbot installation. +# +# A very basic test to ensure that the script adheres to the command line +# signature is to run it with the flags, eg. +# +# /path/to/script --branch=foo --product=bar --build_output_type=ota --flavor=eng +# --output_mode=path + +GET_LATEST_BUILD_SCRIPT=/usr/local/google/home/repository/eureka/continuous-tests/build/get_latest_build.py + +# Root location where tests logs are stored +RESULTS=gs://test_logs + +# Base URL to Google Storage console +GS_CONSOLE_BASE_URL=https://cloud.google.com/console#/storage/ + +# Waterfall server port. + +URL_PORT=8010 + +# CSV root dir. + +CSV_ROOT=/var/www/logs + +# Port used for communication between master and slaves: + +MASTER_SLAVE_PORT_NUMBER=8014 + +# Parsed root dir. It should be accessible from web. + +PARSED_ROOT=/path/to/parsed/root/dir + +# Dashboard server port. + +SERVER_PORT=8020 + +# Path to file for storing event histories. + +HISTORY_PROVIDER_FILE_PATH=/path/to/event_history.sqlite + +# Database type. +# The currently supported backend databases are defined in db/database_types.py. +# The default database type is Sqlite. To use a Sqlite database: +# Set DB_TYPE=sqlite and set DB_PATH=/path, where path is the location where +# the Sqlite database will be stored. +# +# To use a PostgreSQL database: +# Set DB_TYPE=postgresql and set DB_PATH=/path, where path is the location where +# the PostgreSQL database configuration file exists. An example PostgreSQL +# configuration file is at db/db.config. +# +# NOTE: If using postgresql, the third party psycopg2 library must be installed +# in your python environment. If not, ImportErrors will occur when using any of +# the tools that interface with the database. + +DB_TYPE=sqlite + +# Master hostname. + +MASTER_HOSTNAME=cloudview-test.cbf.corp.google.com + +# Password for communication between buildbot master and slaves. This password +# should not be set to an actual user password. It purely governs the +# communication between the master and slaves. + +MASTER_SLAVE_PASSWORD=buildbotmasterslavepassword + +# Dashboard server entry point, could be either an IP or a hostname. +# Defines the host name that the web server will listen on. For example, +# the results dashboard will be available at SERVER_HOSTNAME:8080/dashboard. + +SERVER_HOSTNAME=0.0.0.0 + +# Cts package location. +# Format is <CTS_ROOT>/<CTS_DIRECTORY>/<CTS_PACKAGE_LOCATION> +# <CTS_DIRECTORY> is in config/device_type/<device_type>.cfg. +# It usually will be repository/testcases. + +CTS_PACKAGE_LOCATION=repository/testcases + +# Location of any useful system monitoring files. System monitoring files can +# be stored here and will be accessible via the http server /monitor/ route. + +MONITOR_FILE_PATH=/path/to/dir + +# Emails will be sent to any email address listed here. Additional notifier +# names must have incrementing numbers: +# EMAIL_NOTIFIER_1, EMAIL_NOTIFIER_2, EMAIL_NOTIFIER_N + +EMAIL_NOTIFIER_1=leilei@google.com + +# Web SDK test notification mail notifiers: +WEB_SDK_EMAIL_NOTIFIERS=cloudview-build+sdk-automation@google.com + +# Name for the continuous tests system. The value will appear in the waterfall +# page. + +NAME=Chromecast continuous tests system + +# Web accessible location to upload logcats. + +WEB_LOG_DIR=/path/to/upload/root/dir + +# cts media path + +CTS_MEDIA_PATH=/path/to/android-cts-media + +# Path to the base output directory in which all test data is written: + +BASE_OUTPUT_DIRECTORY=/tmp + +# Parsed http endpoint. + +PARSED_LINK=http://path.to.parsed/dir + +# Email sender. + +EMAIL_SENDER=cloudview_test@google.com + +# HTTP endpoint for reaching WEB_LOG_DIR. URLs will be constructed as: +# WEB_HREF/WEB_LOG_DIR/.. + +WEB_HREF=http://path + +# Directory where cts is installed. Format is <CTS_ROOT>/<CTS_DIRECTORY> +# <CTS_DIRECTORY> is in config/device_type/<device_type>.cfg. + +CTS_ROOT=/path/to/cts/installation + +# Location of script to find apps that will be installed on the new build. + +UNBUNDLED_APK_IDENTIFIER=/path/to/script.sh + +# Are you going to run in production? [yes for prod/no for staging] +PROD=0 + +# System specific command to make a directory. + +MKDIR_COMMAND=mkdir -p + +# To copy files from repository, usually will be cp, but it can be different +# if using a specific system. + +CP_COMMAND=cp + +# For a PostgreSQL database backend (ie. DB_TYPE=postgresql), provide the path +# to the PostgreSQL database configuration file (see notes for DB_TYPE above). +# +# For a Sqlite database backend (ie. DB_TYPE=sqlite), provide the path to the +# Sqlite database file: + +DB_PATH=/usr/local/google/home/repository/fraggle_rock/database/sqlite.db + +# Chrome cast server and directory +HTTP_SERVER_IP=172.17.32.130 + +# User name of HTTPS server. +HTTP_SERVER_USERNAME=gtvchrome + +# Base URL of log server +LOGS_SERVER=https://console.developers.google.com/project/apps~cast-in-chrome/storage/test_logs + +# Location where build status JSON is expected: +BUILD_STATUS_DIRECTORY_PATH=/tmp/build/status/ + +BUILD_INSTALLER_PATH=/usr/local/google/home/repository/eureka/test/ota/ota_update.py + +# URL endpoint for the chromeperf dashboard for adding data. Your host must be +# whitelisted to use the default value. A dev endpoint is available at: +# https://chrome-perf.googleplex.com/add_point +# This endpoint will accept data and return a 200 if it is correctly formatted. +CHROME_PERF_UPLOAD_URL=https://chromeperf.appspot.com/add_point
diff --git a/lab_system/master/config/kir/steps/default.cfg b/lab_system/master/config/kir/steps/default.cfg new file mode 100644 index 0000000..4e87f49 --- /dev/null +++ b/lab_system/master/config/kir/steps/default.cfg
@@ -0,0 +1,94 @@ +[ + { + "step_description": "Sets up testrun specific properties", + "step_identifier": "properties", + "step_factories": [ + { + "module_path": "lab_system.master.steps.factory.setup.properties", + "class_name": "PropertiesSetterStepFactory" + } + ] + }, + { + "step_description": "Allocates devices for the testrun", + "step_identifier": "device_allocation", + "step_factories": [ + { + "module_path": "lab_system.master.steps.factory.device.allocator", + "class_name": "DeviceAllocatorStepFactory" + } + ] + }, + { + "step_description": "Fetches and installs builds on devices", + "step_identifier": "build_handling", + "step_factories": [ + { + "module_path": "lab_system.master.steps.factory.build.fetcher", + "class_name": "BuildFetcherStepFactory" + }, + { + "module_path": "lab_system.master.steps.factory.build.installer_eurlab", + "class_name": "BuildInstallerStepFactory" + } + ] + }, + { + "step_description": "Sets up slave and devices for the testrun. Currently a placeholder with no-ops.", + "step_identifier": "testrun_setup", + "step_factories": [ + { + "module_path": "lab_system.master.steps.factory.output.logs_eurlab", + "class_name": "StartLoggingStepFactory" + } + ] + }, + { + "step_description": "Executes the tests using the eurtest runner.", + "step_identifier": "test_running", + "step_factories": [ + { + "module_path": "lab_system.master.steps.factory.run.test_runner", + "class_name": "TestRunnerStepFactory" + } + ] + }, + { + "step_description": "Replaces logs_copy with a no-op", + "step_identifier": "logs_copy", + "step_factories": [ + { + "module_path": "lab_system.master.steps.factory.common.noop", + "class_name": "NoopStepFactory" + } + ] + }, + { + "step_description": "Processes the output of the test", + "step_identifier": "output_processing", + "step_factories": [ + { + "module_path": "lab_system.master.steps.factory.output.logs_eurlab", + "class_name": "StopLoggingStepFactory" + }, + { + "module_path": "lab_system.master.steps.factory.output.logs", + "class_name": "CopyLogsToRepositoryStepFactory" + } + ] + }, + { + "step_description": "Cleans up slave and devices after the testrun", + "step_identifier": "testrun_cleanup", + "step_factories": [ + { + "module_path": "lab_system.master.steps.factory.device.deallocator", + "class_name": "DeviceDeallocatorStepFactory" + }, + { + "module_path": "lab_system.master.steps.factory.cleanup.workdir", + "class_name": "CleanupWorkdirStepFactory" + } + ] + } +]
diff --git a/lab_system/master/config/kir/tests/bling/test_defs.json b/lab_system/master/config/kir/tests/bling/test_defs.json new file mode 100644 index 0000000..1b4f0dc --- /dev/null +++ b/lab_system/master/config/kir/tests/bling/test_defs.json
@@ -0,0 +1,33 @@ +[ + { + "group_name": "bling_cast", + "slave_name": "bling_cast_end_to_end", + "test_name": "bling_cast_end_to_end", + "identifier": "bling_cast_end_to_end", + "scheduler": "none", + "device_type": "eureka", + "device_group": "bling_cast", + "branch": "release", + "step_factories": [ + { + "step_description": "Sets up slave and devices for the testrun.", + "step_identifier": "testrun_setup", + "step_factories": [ + { + "module_path": "lab_system.master.steps.factory.common.noop", + "class_name": "NoopStepFactory" + } + ] + }, + { + "step_description": "Processes the output of the test", + "step_identifier": "output_processing", + "step_factories": [ + { + "module_path": "lab_system.master.steps.factory.output.logs", + "class_name": "CopyLogsToRepositoryStepFactory" + } + ] + }] + } +]
diff --git a/lab_system/master/config/kir/tests/chrome_mirroring/acer_core_i5_2450m_intelhd3000_win7.cfg b/lab_system/master/config/kir/tests/chrome_mirroring/acer_core_i5_2450m_intelhd3000_win7.cfg new file mode 100644 index 0000000..a0fe8b8 --- /dev/null +++ b/lab_system/master/config/kir/tests/chrome_mirroring/acer_core_i5_2450m_intelhd3000_win7.cfg
@@ -0,0 +1,19 @@ +# Config file for acer_core_i5 in MTV lab. + +# PROPERTIES +SELF_IP=172.17.23.194 +HOME_DIR=C:/Users/gtvchrome +USER_NAME=gtvchrome +CHROME_DRIVER=chromedriver.exe +PLATFORM=win + +# Mirroring test chrome build +CHROME_VERSION=beta + +# Mirroring test extension flavor +EXTENSION_BUILD=beta + +# Recorder machine +SENDER_DEVICE_TYPE=mac +SENDER_DEVICE_GROUP=video_recorder +SENDER_DEVICE_NUMBER=1
diff --git a/lab_system/master/config/kir/tests/chrome_mirroring/config_files_on_slaves.json b/lab_system/master/config/kir/tests/chrome_mirroring/config_files_on_slaves.json new file mode 100755 index 0000000..7db27dc --- /dev/null +++ b/lab_system/master/config/kir/tests/chrome_mirroring/config_files_on_slaves.json
@@ -0,0 +1,61 @@ +{ + "macbookair_i5_4250u_intelhd5000": { + "cfg_files": [ + "soccer_30fps_encoded_v2", + "gangnam_encoded_v2", + "gangnam_encoded_v2_bad_wifi" + ] + }, + "macbookpro_i7_2675qm_radeon6750m": { + "cfg_files": [ + "soccer_30fps_encoded_v2", + "gangnam_encoded_v2", + "gangnam_encoded_v2_bad_wifi" + ] + }, + "acer_i5_3337u_intelhd4000_win8": { + "cfg_files": [ + "soccer_30fps_encoded_v2", + "gangnam_encoded_v2", + "gangnam_encoded_v2_bad_wifi" + ] + }, + "samsung_i7_3630qm_radeon7730m_win8": { + "cfg_files": [ + "soccer_30fps_encoded_v2", + "gangnam_encoded_v2", + "gangnam_encoded_v2_bad_wifi" + ] + }, + "asus_i3_2328m_intelhd3000_win8": { + "cfg_files": [ + "soccer_30fps_encoded_v2", + "gangnam_encoded_v2", + "gangnam_encoded_v2_bad_wifi" + ] + }, + "macbookair_i5_4250u_intelhd5000_mtv": { + "cfg_files": [ + "soccer_30fps_encoded_v2", + "gangnam_encoded_v2" + ] + }, + "hp_core_i5_3210m_intelhd4000_win8_mtv": { + "cfg_files": [ + "soccer_30fps_encoded_v2", + "gangnam_encoded_v2" + ] + }, + "hp_core2duo_p8600_gma4500_win7": { + "cfg_files": [ + "soccer_30fps_encoded_v2", + "gangnam_encoded_v2", + "gangnam_encoded_v2_bad_wifi" + ] + }, + "trial_machine_win": { + "cfg_files": [ + "gangnam_encoded_v2" + ] + } +}
diff --git a/lab_system/master/config/kir/tests/chrome_mirroring/hp_core_i5_3210m_intelhd4000_win8_mtv.cfg b/lab_system/master/config/kir/tests/chrome_mirroring/hp_core_i5_3210m_intelhd4000_win8_mtv.cfg new file mode 100644 index 0000000..d6bd2ec --- /dev/null +++ b/lab_system/master/config/kir/tests/chrome_mirroring/hp_core_i5_3210m_intelhd4000_win8_mtv.cfg
@@ -0,0 +1,19 @@ +# Config file for hp_core_i5_3210m_intelhd4000_win8_mtv in MTV lab. + +# PROPERTIES +SELF_IP=172.17.23.78 +HOME_DIR=C:/Users/gtvchrome +USER_NAME=gtvchrome +CHROME_DRIVER=chromedriver.exe +PLATFORM=win + +# Mirroring test chrome build +CHROME_VERSION=beta + +# Mirroring test extension flavor +EXTENSION_BUILD=beta + +# Recorder machine +SENDER_DEVICE_TYPE=mac +SENDER_DEVICE_GROUP=video_recorder +SENDER_DEVICE_NUMBER=1
diff --git a/lab_system/master/config/kir/tests/chrome_mirroring/macbookair_i5_4250u_intelhd5000_mtv.cfg b/lab_system/master/config/kir/tests/chrome_mirroring/macbookair_i5_4250u_intelhd5000_mtv.cfg new file mode 100644 index 0000000..1b81e61 --- /dev/null +++ b/lab_system/master/config/kir/tests/chrome_mirroring/macbookair_i5_4250u_intelhd5000_mtv.cfg
@@ -0,0 +1,27 @@ +# Config file for macbookair_i5_4250u_intelhd5000_mtv in MTV lab. + +# PROPERTIES +SELF_IP=172.17.23.86 +HOME_DIR=/Users/gtvchrome +USER_NAME=gtvchrome +CHROME_DRIVER=chromedriver +PLATFORM=mac + +# Mirroring test chrome build +CHROME_VERSION=beta + +# Mirroring test extension flavor +EXTENSION_BUILD=beta + +# Recorder machine +SENDER_DEVICE_TYPE=mac +SENDER_DEVICE_GROUP=video_recorder_mtv +SENDER_DEVICE_NUMBER=1 + + +PROCESSOR_MACHINE_IP=172.31.25.28 +PROCESSOR_DEVICE_TYPE=linux +PROCESSOR_DEVICE_GROUP=video_processing_machine_0 +PROCESSOR_DEVICE_NUMBER=1 +PROCESSOR_RESULTS_DIR=/home/gtvchrome/results +PROCESSOR_TEST_DIR=/home/gtvchrome/repository/eureka/test
diff --git a/lab_system/master/config/kir/tests/chrome_mirroring/macbookpro_i5_3210m_intelhd4000.cfg b/lab_system/master/config/kir/tests/chrome_mirroring/macbookpro_i5_3210m_intelhd4000.cfg new file mode 100644 index 0000000..c8437a7 --- /dev/null +++ b/lab_system/master/config/kir/tests/chrome_mirroring/macbookpro_i5_3210m_intelhd4000.cfg
@@ -0,0 +1,19 @@ +# Config file for macbook pro in MTV lab. + +# PROPERTIES +SELF_IP=172.17.23.56 +HOME_DIR=/Users/gtvchrome +USER_NAME=gtvchrome +CHROME_DRIVER=chromedriver +PLATFORM=mac + +# Mirroring test chrome build +CHROME_VERSION=stable + +# Mirroring test extension flavor +EXTENSION_BUILD=beta + +# Recorder machine +SENDER_DEVICE_TYPE=mac +SENDER_DEVICE_GROUP=video_recorder +SENDER_DEVICE_NUMBER=1
diff --git a/lab_system/master/config/kir/tests/chrome_mirroring/slaves/acer_i5_3337u_intelhd4000_win8/config/bad_wifi.config b/lab_system/master/config/kir/tests/chrome_mirroring/slaves/acer_i5_3337u_intelhd4000_win8/config/bad_wifi.config new file mode 100644 index 0000000..a7bd44e --- /dev/null +++ b/lab_system/master/config/kir/tests/chrome_mirroring/slaves/acer_i5_3337u_intelhd4000_win8/config/bad_wifi.config
@@ -0,0 +1,4 @@ +{ + "udp_proxy_server": "http://172.31.25.18:8888", + "network_profile": "bad" +}
diff --git a/lab_system/master/config/kir/tests/chrome_mirroring/slaves/acer_i5_3337u_intelhd4000_win8/config/bunny_480p_desktop_mirror.config b/lab_system/master/config/kir/tests/chrome_mirroring/slaves/acer_i5_3337u_intelhd4000_win8/config/bunny_480p_desktop_mirror.config new file mode 100644 index 0000000..e16eb0e --- /dev/null +++ b/lab_system/master/config/kir/tests/chrome_mirroring/slaves/acer_i5_3337u_intelhd4000_win8/config/bunny_480p_desktop_mirror.config
@@ -0,0 +1,29 @@ +{ + "add_debug_dongle_ip": "172.31.25.7", + "chrome_binary_location": "C:\\Users\\gtvchrome\\repository\\chrome\\src\\out\\Debug\\chrome.exe", + "cpu_consumption": "true", + "cpu_interval": "1", + "resolution_1280_720": "1280x720", + "device_ip": "172.31.25.7", + "enable_webrtc_getstats": "true", + "extension_path": "C:\\Users\\gtvchrome\\repository\\extension\\extension.crx", + "extra_flags": " --no-proxy-server --start-maximized --whitelisted-extension-id=hfaagokkkhdbgiakmmlclaapfelnkoah --disable-web-security --enable-experimental-extension-apis --enable-usermedia-screen-capturing --enable-logging --v=1 --vmodule=*source*/talk/*=3", + "full_screen": "on", + "get_log": "true", + "gpu": "on", + "log_file_name": "C:\\Users\\gtvchrome\\results\\sender.json", + "logging": "mirroring", + "machine_name": "acer_i5_3337u_intelhd4000_win8", + "mirror_duration": "560", + "network_profile": "", + "set_fullscreen_zoom": "on", + "startup_latency": "false", + "test_type": "video", + "tracing_duration": "560", + "video_fps": "24fps", + "video_name": "bunny_video_24fps_480p_desktop_mirroring", + "video_resolution": "480p", + "comments": "Buffered mode, NACK on", + "video_site": "http://172.31.25.18/test_site/index.html?video=bunny_480p", + "desktop_capture": "true" +}
diff --git a/lab_system/master/config/kir/tests/chrome_mirroring/slaves/acer_i5_3337u_intelhd4000_win8/config/gangnam_encoded.config b/lab_system/master/config/kir/tests/chrome_mirroring/slaves/acer_i5_3337u_intelhd4000_win8/config/gangnam_encoded.config new file mode 100644 index 0000000..0de4c5e --- /dev/null +++ b/lab_system/master/config/kir/tests/chrome_mirroring/slaves/acer_i5_3337u_intelhd4000_win8/config/gangnam_encoded.config
@@ -0,0 +1,33 @@ +{ + "_deps": ["processor.config"], + "chrome_binary_location": "C:\\Users\\gtvchrome\\repository\\chrome\\src\\out\\Debug\\chrome.exe", + "extension_path": "C:\\Users\\gtvchrome\\repository\\extension\\extension.crx", + "extra_flags": "--no-proxy-server --start-maximized --whitelisted-extension-id=fmfcbgogabcbclcofgocippekhfcmgfj --disable-web-security --enable-experimental-extension-apis --enable-logging --v=1 --vmodule=*libjingle/source_internal/talk/*=4,*=0", + "high_tab_projection_quality": "ql-high", + "gpu": "on", + "full_screen": "on", + "set_fullscreen_zoom": "off", + "get_log": "true", + "log_file_name": "C:\\Users\\gtvchrome\\results\\sender.json", + "logging": "mirroring", + "enable_webrtc_getstats": "true", + "mirror_duration": "400", + "tracing_duration": "400", + "machine_name": "acer_i5_3337u_intelhd4000_win8", + "video_fps": "24", + "video_name": "gangnam_encoded", + "video_resolution": "720p", + "comments": "mirroring v1, video content 720p 24fps, ethernet", + "video_site": "http://172.31.25.18/test_site/index.html?video=gangnam_720p_av_test", + "recorded_video_directory": "/Users/gtvchrome/Movies/Game\\ Capture\\ HD\\ Library/mirroring/", + "capture_software": "/Applications/Game\\ Capture\\ HD.app/Contents/MacOS/Game\\ Capture\\ HD", + "test_type": "video", + "startup_latency": "false", + "network_profile": "", + "cpu_consumption": "true", + "cpu_interval": "1", + "use_sdk": "false", + "quality_test": "all", + "cast_mirroring_version": "1.0", + "cast_streaming_off": "useCastStreaming-off" +}
diff --git a/lab_system/master/config/kir/tests/chrome_mirroring/slaves/acer_i5_3337u_intelhd4000_win8/config/gangnam_encoded_v2.config b/lab_system/master/config/kir/tests/chrome_mirroring/slaves/acer_i5_3337u_intelhd4000_win8/config/gangnam_encoded_v2.config new file mode 100644 index 0000000..18afbc7 --- /dev/null +++ b/lab_system/master/config/kir/tests/chrome_mirroring/slaves/acer_i5_3337u_intelhd4000_win8/config/gangnam_encoded_v2.config
@@ -0,0 +1,34 @@ +{ + "_deps": ["processor.config"], + "chrome_binary_location": "C:\\Users\\gtvchrome\\repository\\chrome\\src\\out\\Debug\\chrome.exe", + "extension_path": "C:\\Users\\gtvchrome\\repository\\extension", + "extra_flags": "--no-proxy-server --start-maximized --whitelisted-extension-id=enhhojjnijigcajfphajepfemndkmdlo --disable-web-security --enable-experimental-extension-apis --v=0 --enable-logging --vmodule=*media/cast/*=3,*chrome/renderer/media/*=3,*=0", + "high_tab_projection_quality": "ql-high", + "gpu": "on", + "full_screen": "on", + "set_fullscreen_zoom": "off", + "get_log": "true", + "log_file_name": "C:\\Users\\gtvchrome\\results\\sender.json", + "logging": "mirroring", + "enable_webrtc_getstats": "true", + "mirror_duration": "400", + "tracing_duration": "400", + "machine_name": "acer_i5_3337u_intelhd4000_win8", + "video_fps": "24", + "video_name": "gangnam_encoded", + "video_resolution": "720p", + "comments": "mirroring v2, video content 720p 24fps, ethernet", + "video_site": "http://172.31.25.18/test_site/index.html?video=gangnam_720p_av_test", + "recorded_video_directory": "/Users/gtvchrome/Movies/Game\\ Capture\\ HD\\ Library/mirroring/", + "capture_software": "/Applications/Game\\ Capture\\ HD.app/Contents/MacOS/Game\\ Capture\\ HD", + "test_type": "video", + "startup_latency": "false", + "network_profile": "", + "cpu_consumption": "true", + "cpu_interval": "1", + "use_sdk": "false", + "quality_test": "all", + "cast_mirroring_version": "2.0", + "cast_streaming_on": "useCastStreaming-on" +} +
diff --git a/lab_system/master/config/kir/tests/chrome_mirroring/slaves/acer_i5_3337u_intelhd4000_win8/config/gangnam_encoded_v2_bad_wifi.config b/lab_system/master/config/kir/tests/chrome_mirroring/slaves/acer_i5_3337u_intelhd4000_win8/config/gangnam_encoded_v2_bad_wifi.config new file mode 100644 index 0000000..84e4c42 --- /dev/null +++ b/lab_system/master/config/kir/tests/chrome_mirroring/slaves/acer_i5_3337u_intelhd4000_win8/config/gangnam_encoded_v2_bad_wifi.config
@@ -0,0 +1,33 @@ +{ + "_deps": ["processor.config", "bad_wifi.config"], + "chrome_binary_location": "C:\\Users\\gtvchrome\\repository\\chrome\\src\\out\\Debug\\chrome.exe", + "extension_path": "C:\\Users\\gtvchrome\\repository\\extension\\extension.crx", + "extra_flags": "--no-proxy-server --start-maximized --whitelisted-extension-id=fmfcbgogabcbclcofgocippekhfcmgfj --disable-web-security --enable-experimental-extension-apis --v=0 --enable-logging --vmodule=*media/cast/*=3,*chrome/renderer/media/*=3,*=0", + "high_tab_projection_quality": "ql-high", + "gpu": "on", + "full_screen": "on", + "set_fullscreen_zoom": "off", + "get_log": "true", + "log_file_name": "C:\\Users\\gtvchrome\\results\\sender.json", + "logging": "mirroring", + "enable_webrtc_getstats": "true", + "mirror_duration": "400", + "tracing_duration": "400", + "machine_name": "acer_i5_3337u_intelhd4000_win8", + "video_fps": "24", + "video_name": "gangnam_encoded", + "video_resolution": "720p", + "comments": "mirroring v2, video content 720p 24fps, bad wifi", + "video_site": "http://172.31.25.18/test_site/index.html?video=gangnam_720p_av_test", + "recorded_video_directory": "/Users/gtvchrome/Movies/Game\\ Capture\\ HD\\ Library/mirroring/", + "capture_software": "/Applications/Game\\ Capture\\ HD.app/Contents/MacOS/Game\\ Capture\\ HD", + "test_type": "video", + "startup_latency": "false", + "cpu_consumption": "true", + "cpu_interval": "1", + "use_sdk": "false", + "quality_test": "all", + "cast_mirroring_version": "2.0", + "cast_streaming_on": "useCastStreaming-on" +} +
diff --git a/lab_system/master/config/kir/tests/chrome_mirroring/slaves/acer_i5_3337u_intelhd4000_win8/config/processor.config b/lab_system/master/config/kir/tests/chrome_mirroring/slaves/acer_i5_3337u_intelhd4000_win8/config/processor.config new file mode 100644 index 0000000..0e8eaf1 --- /dev/null +++ b/lab_system/master/config/kir/tests/chrome_mirroring/slaves/acer_i5_3337u_intelhd4000_win8/config/processor.config
@@ -0,0 +1,24 @@ +{ + "root_dir": "/home/gtvchrome", + "results_dir": "results", + "mirror_mp4_file": "Segment_0001.mp4", + "mirror_yuv_file": "mirror.yuv", + "mirror_wav_file": "mirror.wav", + "mirror_stats_file": "mirror_stats.txt", + "mirror_audio_results_file": "audio_results.txt", + "mirror_psnr_ssim_file": "psnr_ssim.txt", + "audio_tools_dir": "audio_quality_tools", + "image_tools_dir": "image_quality_tools", + "reference_dir": "image_quality_tools/sample_videos", + "test_utils_dir": "repository/eureka/test/utilities", + "zxing_dir": "image_quality_tools/zxing/cpp/build", + "barcode_tools_dir": "repository/eureka/test/barcode_tools", + "frame_width": "1280", + "frame_height": "720", + "barcode_height": "32", + "image_extract_interval": "1", + "ffmpeg": "ffmpeg", + "sox": "sox", + "audio_compare_tool": "polqa/PolqaOem64" +} +
diff --git a/lab_system/master/config/kir/tests/chrome_mirroring/slaves/acer_i5_3337u_intelhd4000_win8/config/soccer_30fps_encoded_60fps_capture_v2.config b/lab_system/master/config/kir/tests/chrome_mirroring/slaves/acer_i5_3337u_intelhd4000_win8/config/soccer_30fps_encoded_60fps_capture_v2.config new file mode 100644 index 0000000..205d914 --- /dev/null +++ b/lab_system/master/config/kir/tests/chrome_mirroring/slaves/acer_i5_3337u_intelhd4000_win8/config/soccer_30fps_encoded_60fps_capture_v2.config
@@ -0,0 +1,35 @@ +{ + "_deps": ["processor.config"], + "chrome_binary_location": "C:\\Users\\gtvchrome\\repository\\chrome\\src\\out\\Debug\\chrome.exe", + "extension_path": "C:\\Users\\gtvchrome\\repository\\extension", + "extra_flags": "--no-proxy-server --start-maximized --whitelisted-extension-id=enhhojjnijigcajfphajepfemndkmdlo --disable-web-security --enable-experimental-extension-apis --v=0 --enable-logging --vmodule=*media/cast/*=3,*chrome/renderer/media/*=3,*=0", + "high_tab_projection_quality": "ql-high", + "gpu": "on", + "full_screen": "on", + "set_fullscreen_zoom": "off", + "get_log": "true", + "log_file_name": "C:\\Users\\gtvchrome\\results\\sender.json", + "logging": "mirroring", + "enable_webrtc_getstats": "true", + "mirror_duration": "400", + "tracing_duration": "400", + "machine_name": "acer_i5_3337u_intelhd4000_win8", + "video_fps": "30", + "video_name": "soccer_30fps_encoded", + "video_resolution": "720p", + "comments": "mirroring v2, video content 720p 30fps, capture at 60fps, ethernet", + "video_site": "http://172.31.25.18/test_site/index.html?video=soccer_30fps_encoded", + "recorded_video_directory": "/Users/gtvchrome/Movies/Game\\ Capture\\ HD\\ Library/mirroring/", + "capture_software": "/Applications/Game\\ Capture\\ HD.app/Contents/MacOS/Game\\ Capture\\ HD", + "test_type": "video", + "startup_latency": "false", + "network_profile": "", + "cpu_consumption": "true", + "cpu_interval": "1", + "use_sdk": "false", + "quality_test": "audio", + "cast_mirroring_version": "2.0", + "cast_streaming_on": "useCastStreaming-on", + "max_frame_rate": "60" +} +
diff --git a/lab_system/master/config/kir/tests/chrome_mirroring/slaves/acer_i5_3337u_intelhd4000_win8/config/soccer_30fps_encoded_v2.config b/lab_system/master/config/kir/tests/chrome_mirroring/slaves/acer_i5_3337u_intelhd4000_win8/config/soccer_30fps_encoded_v2.config new file mode 100644 index 0000000..3b87592 --- /dev/null +++ b/lab_system/master/config/kir/tests/chrome_mirroring/slaves/acer_i5_3337u_intelhd4000_win8/config/soccer_30fps_encoded_v2.config
@@ -0,0 +1,34 @@ +{ + "_deps": ["processor.config"], + "chrome_binary_location": "C:\\Users\\gtvchrome\\repository\\chrome\\src\\out\\Debug\\chrome.exe", + "extension_path": "C:\\Users\\gtvchrome\\repository\\extension", + "extra_flags": "--no-proxy-server --start-maximized --whitelisted-extension-id=enhhojjnijigcajfphajepfemndkmdlo --disable-web-security --enable-experimental-extension-apis --v=0 --enable-logging --vmodule=*media/cast/*=3,*chrome/renderer/media/*=3,*=0", + "high_tab_projection_quality": "ql-high", + "gpu": "on", + "full_screen": "on", + "set_fullscreen_zoom": "off", + "get_log": "true", + "log_file_name": "C:\\Users\\gtvchrome\\results\\sender.json", + "logging": "mirroring", + "enable_webrtc_getstats": "true", + "mirror_duration": "400", + "tracing_duration": "400", + "machine_name": "acer_i5_3337u_intelhd4000_win8", + "video_fps": "30", + "video_name": "soccer_30fps_encoded", + "video_resolution": "720p", + "comments": "mirroring v2, video content 720p 30fps, ethernet", + "video_site": "http://172.31.25.18/test_site/index.html?video=soccer_30fps_encoded", + "recorded_video_directory": "/Users/gtvchrome/Movies/Game\\ Capture\\ HD\\ Library/mirroring/", + "capture_software": "/Applications/Game\\ Capture\\ HD.app/Contents/MacOS/Game\\ Capture\\ HD", + "test_type": "video", + "startup_latency": "false", + "network_profile": "", + "cpu_consumption": "true", + "cpu_interval": "1", + "use_sdk": "false", + "quality_test": "audio", + "cast_mirroring_version": "2.0", + "cast_streaming_on": "useCastStreaming-on" +} +
diff --git a/lab_system/master/config/kir/tests/chrome_mirroring/slaves/acer_i5_3337u_intelhd4000_win8/config/titanfall_60fps_encoded_v2.config b/lab_system/master/config/kir/tests/chrome_mirroring/slaves/acer_i5_3337u_intelhd4000_win8/config/titanfall_60fps_encoded_v2.config new file mode 100644 index 0000000..04fbf26 --- /dev/null +++ b/lab_system/master/config/kir/tests/chrome_mirroring/slaves/acer_i5_3337u_intelhd4000_win8/config/titanfall_60fps_encoded_v2.config
@@ -0,0 +1,35 @@ +{ + "_deps": ["processor.config"], + "chrome_binary_location": "C:\\Users\\gtvchrome\\repository\\chrome\\src\\out\\Debug\\chrome.exe", + "extension_path": "C:\\Users\\gtvchrome\\repository\\extension", + "extra_flags": "--no-proxy-server --start-maximized --whitelisted-extension-id=enhhojjnijigcajfphajepfemndkmdlo --disable-web-security --enable-experimental-extension-apis --v=0 --enable-logging --vmodule=*media/cast/*=3,*chrome/renderer/media/*=3,*=0", + "high_tab_projection_quality": "ql-high", + "gpu": "on", + "full_screen": "on", + "set_fullscreen_zoom": "off", + "get_log": "true", + "log_file_name": "C:\\Users\\gtvchrome\\results\\sender.json", + "logging": "mirroring", + "enable_webrtc_getstats": "true", + "mirror_duration": "400", + "tracing_duration": "400", + "machine_name": "acer_i5_3337u_intelhd4000_win8", + "video_fps": "60", + "video_name": "titanfall_60fps_encoded", + "video_resolution": "720p", + "comments": "mirroring v2, video content 720p 60fps, ethernet", + "video_site": "http://172.31.25.18/test_site/index.html?video=titanfall_60fps_encoded", + "recorded_video_directory": "/Users/gtvchrome/Movies/Game\\ Capture\\ HD\\ Library/mirroring/", + "capture_software": "/Applications/Game\\ Capture\\ HD.app/Contents/MacOS/Game\\ Capture\\ HD", + "test_type": "video", + "startup_latency": "false", + "network_profile": "", + "cpu_consumption": "true", + "cpu_interval": "1", + "use_sdk": "false", + "quality_test": "all", + "cast_mirroring_version": "2.0", + "cast_streaming_on": "useCastStreaming-on", + "max_frame_rate": "60" +} +
diff --git a/lab_system/master/config/kir/tests/chrome_mirroring/slaves/asus_i3_2328m_intelhd3000_win8/config/bad_wifi.config b/lab_system/master/config/kir/tests/chrome_mirroring/slaves/asus_i3_2328m_intelhd3000_win8/config/bad_wifi.config new file mode 100644 index 0000000..a7bd44e --- /dev/null +++ b/lab_system/master/config/kir/tests/chrome_mirroring/slaves/asus_i3_2328m_intelhd3000_win8/config/bad_wifi.config
@@ -0,0 +1,4 @@ +{ + "udp_proxy_server": "http://172.31.25.18:8888", + "network_profile": "bad" +}
diff --git a/lab_system/master/config/kir/tests/chrome_mirroring/slaves/asus_i3_2328m_intelhd3000_win8/config/bunny_480p_desktop_mirror.config b/lab_system/master/config/kir/tests/chrome_mirroring/slaves/asus_i3_2328m_intelhd3000_win8/config/bunny_480p_desktop_mirror.config new file mode 100644 index 0000000..39fb7f5 --- /dev/null +++ b/lab_system/master/config/kir/tests/chrome_mirroring/slaves/asus_i3_2328m_intelhd3000_win8/config/bunny_480p_desktop_mirror.config
@@ -0,0 +1,29 @@ +{ + "add_debug_dongle_ip": "172.31.25.24", + "chrome_binary_location": "C:\\Users\\gtvchrome\\repository\\chrome\\src\\out\\Debug\\chrome.exe", + "cpu_consumption": "true", + "cpu_interval": "1", + "resolution_1280_720": "1280x720", + "device_ip": "172.31.25.24", + "enable_webrtc_getstats": "true", + "extension_path": "C:\\Users\\gtvchrome\\repository\\extension\\extension.crx", + "extra_flags": " --no-proxy-server --start-maximized --whitelisted-extension-id=hfaagokkkhdbgiakmmlclaapfelnkoah --disable-web-security --enable-experimental-extension-apis --enable-usermedia-screen-capturing --enable-logging --v=1 --vmodule=*source*/talk/*=3", + "full_screen": "on", + "get_log": "true", + "gpu": "on", + "log_file_name": "C:\\Users\\gtvchrome\\results\\sender.json", + "logging": "mirroring", + "machine_name": "asus_i3_2328m_intelhd3000_win8", + "mirror_duration": "560", + "network_profile": "", + "set_fullscreen_zoom": "on", + "startup_latency": "false", + "test_type": "video", + "tracing_duration": "560", + "video_fps": "24fps", + "video_name": "bunny_video_24fps_480p_default_desktop_mirroring", + "video_resolution": "480p", + "comments": "Buffered mode, NACK on", + "video_site": "http://172.31.25.18/test_site/index.html?video=bunny_480p", + "desktop_capture": "true" +}
diff --git a/lab_system/master/config/kir/tests/chrome_mirroring/slaves/asus_i3_2328m_intelhd3000_win8/config/gangnam_encoded.config b/lab_system/master/config/kir/tests/chrome_mirroring/slaves/asus_i3_2328m_intelhd3000_win8/config/gangnam_encoded.config new file mode 100644 index 0000000..fc2592c --- /dev/null +++ b/lab_system/master/config/kir/tests/chrome_mirroring/slaves/asus_i3_2328m_intelhd3000_win8/config/gangnam_encoded.config
@@ -0,0 +1,33 @@ +{ + "_deps": ["processor.config"], + "chrome_binary_location": "C:\\Users\\gtvchrome\\repository\\chrome\\src\\out\\Debug\\chrome.exe", + "extension_path": "C:\\Users\\gtvchrome\\repository\\extension\\extension.crx", + "extra_flags": "--no-proxy-server --start-maximized --whitelisted-extension-id=fmfcbgogabcbclcofgocippekhfcmgfj --disable-web-security --enable-experimental-extension-apis --enable-logging --v=1 --vmodule=*libjingle/source_internal/talk/*=4,*=0", + "high_tab_projection_quality": "ql-high", + "gpu": "on", + "full_screen": "on", + "set_fullscreen_zoom": "off", + "get_log": "true", + "log_file_name": "C:\\Users\\gtvchrome\\results\\sender.json", + "logging": "mirroring", + "enable_webrtc_getstats": "true", + "mirror_duration": "400", + "tracing_duration": "400", + "machine_name": "asus_i3_2328m_intelhd3000_win8", + "video_fps": "24", + "video_name": "gangnam_encoded", + "video_resolution": "720p", + "comments": "mirroring v1, video content 720p 24fps, ethernet", + "video_site": "http://172.31.25.18/test_site/index.html?video=gangnam_720p_av_test", + "recorded_video_directory": "/Users/gtvchrome/Movies/Game\\ Capture\\ HD\\ Library/mirroring/", + "capture_software": "/Applications/Game\\ Capture\\ HD.app/Contents/MacOS/Game\\ Capture\\ HD", + "test_type": "video", + "startup_latency": "false", + "network_profile": "", + "cpu_consumption": "true", + "cpu_interval": "1", + "use_sdk": "false", + "quality_test": "all", + "cast_mirroring_version": "1.0", + "cast_streaming_off": "useCastStreaming-off" +}
diff --git a/lab_system/master/config/kir/tests/chrome_mirroring/slaves/asus_i3_2328m_intelhd3000_win8/config/gangnam_encoded_v2.config b/lab_system/master/config/kir/tests/chrome_mirroring/slaves/asus_i3_2328m_intelhd3000_win8/config/gangnam_encoded_v2.config new file mode 100644 index 0000000..1cbe267 --- /dev/null +++ b/lab_system/master/config/kir/tests/chrome_mirroring/slaves/asus_i3_2328m_intelhd3000_win8/config/gangnam_encoded_v2.config
@@ -0,0 +1,34 @@ +{ + "_deps": ["processor.config"], + "chrome_binary_location": "C:\\Users\\gtvchrome\\repository\\chrome\\src\\out\\Debug\\chrome.exe", + "extension_path": "C:\\Users\\gtvchrome\\repository\\extension\\extension.crx", + "extra_flags": "--no-proxy-server --start-maximized --whitelisted-extension-id=fmfcbgogabcbclcofgocippekhfcmgfj --disable-web-security --enable-experimental-extension-apis --v=0 --enable-logging --vmodule=*media/cast/*=3,*chrome/renderer/media/*=3,*=0", + "high_tab_projection_quality": "ql-high", + "gpu": "on", + "full_screen": "on", + "set_fullscreen_zoom": "off", + "get_log": "true", + "log_file_name": "C:\\Users\\gtvchrome\\results\\sender.json", + "logging": "mirroring", + "enable_webrtc_getstats": "true", + "mirror_duration": "400", + "tracing_duration": "400", + "machine_name": "asus_i3_2328m_intelhd3000_win8", + "video_fps": "24", + "video_name": "gangnam_encoded", + "video_resolution": "720p", + "comments": "mirroring v2, video content 720p 24fps, ethernet", + "video_site": "http://172.31.25.18/test_site/index.html?video=gangnam_720p_av_test", + "recorded_video_directory": "/Users/gtvchrome/Movies/Game\\ Capture\\ HD\\ Library/mirroring/", + "capture_software": "/Applications/Game\\ Capture\\ HD.app/Contents/MacOS/Game\\ Capture\\ HD", + "test_type": "video", + "startup_latency": "false", + "network_profile": "", + "cpu_consumption": "true", + "cpu_interval": "1", + "use_sdk": "false", + "quality_test": "all", + "cast_mirroring_version": "2.0", + "cast_streaming_on": "useCastStreaming-on" +} +
diff --git a/lab_system/master/config/kir/tests/chrome_mirroring/slaves/asus_i3_2328m_intelhd3000_win8/config/gangnam_encoded_v2_bad_wifi.config b/lab_system/master/config/kir/tests/chrome_mirroring/slaves/asus_i3_2328m_intelhd3000_win8/config/gangnam_encoded_v2_bad_wifi.config new file mode 100644 index 0000000..a299e94 --- /dev/null +++ b/lab_system/master/config/kir/tests/chrome_mirroring/slaves/asus_i3_2328m_intelhd3000_win8/config/gangnam_encoded_v2_bad_wifi.config
@@ -0,0 +1,33 @@ +{ + "_deps": ["processor.config", "bad_wifi.config"], + "chrome_binary_location": "C:\\Users\\gtvchrome\\repository\\chrome\\src\\out\\Debug\\chrome.exe", + "extension_path": "C:\\Users\\gtvchrome\\repository\\extension\\extension.crx", + "extra_flags": "--no-proxy-server --start-maximized --whitelisted-extension-id=fmfcbgogabcbclcofgocippekhfcmgfj --disable-web-security --enable-experimental-extension-apis --v=0 --enable-logging --vmodule=*media/cast/*=3,*chrome/renderer/media/*=3,*=0", + "high_tab_projection_quality": "ql-high", + "gpu": "on", + "full_screen": "on", + "set_fullscreen_zoom": "off", + "get_log": "true", + "log_file_name": "C:\\Users\\gtvchrome\\results\\sender.json", + "logging": "mirroring", + "enable_webrtc_getstats": "true", + "mirror_duration": "400", + "tracing_duration": "400", + "machine_name": "asus_i3_2328m_intelhd3000_win8", + "video_fps": "24", + "video_name": "gangnam_encoded", + "video_resolution": "720p", + "comments": "mirroring v2, video content 720p 24fps, bad wifi", + "video_site": "http://172.31.25.18/test_site/index.html?video=gangnam_720p_av_test", + "recorded_video_directory": "/Users/gtvchrome/Movies/Game\\ Capture\\ HD\\ Library/mirroring/", + "capture_software": "/Applications/Game\\ Capture\\ HD.app/Contents/MacOS/Game\\ Capture\\ HD", + "test_type": "video", + "startup_latency": "false", + "cpu_consumption": "true", + "cpu_interval": "1", + "use_sdk": "false", + "quality_test": "all", + "cast_mirroring_version": "2.0", + "cast_streaming_on": "useCastStreaming-on" +} +
diff --git a/lab_system/master/config/kir/tests/chrome_mirroring/slaves/asus_i3_2328m_intelhd3000_win8/config/gangnam_encoded_v2_wifi.config b/lab_system/master/config/kir/tests/chrome_mirroring/slaves/asus_i3_2328m_intelhd3000_win8/config/gangnam_encoded_v2_wifi.config new file mode 100644 index 0000000..b6c9009 --- /dev/null +++ b/lab_system/master/config/kir/tests/chrome_mirroring/slaves/asus_i3_2328m_intelhd3000_win8/config/gangnam_encoded_v2_wifi.config
@@ -0,0 +1,34 @@ +{ + "_deps": ["processor.config", "bad_wifi.config"], + "chrome_binary_location": "C:\\Users\\gtvchrome\\repository\\chrome\\src\\out\\Debug\\chrome.exe", + "extension_path": "C:\\Users\\gtvchrome\\repository\\extension\\extension.crx", + "extra_flags": "--no-proxy-server --start-maximized --whitelisted-extension-id=fmfcbgogabcbclcofgocippekhfcmgfj --disable-web-security --enable-experimental-extension-apis --v=0 --enable-logging --vmodule=*media/cast/*=3,*chrome/renderer/media/*=3,*=0", + "high_tab_projection_quality": "ql-high", + "gpu": "on", + "full_screen": "on", + "set_fullscreen_zoom": "off", + "get_log": "true", + "log_file_name": "C:\\Users\\gtvchrome\\results\\sender.json", + "logging": "mirroring", + "enable_webrtc_getstats": "true", + "mirror_duration": "400", + "tracing_duration": "400", + "machine_name": "asus_i3_2328m_intelhd3000_win8", + "video_fps": "24", + "video_name": "gangnam_encoded", + "video_resolution": "720p", + "comments": "mirroring v2, video content 720p 24fps, good wifi", + "video_site": "http://172.31.25.18/test_site/index.html?video=gangnam_720p_av_test", + "recorded_video_directory": "/Users/gtvchrome/Movies/Game\\ Capture\\ HD\\ Library/mirroring/", + "capture_software": "/Applications/Game\\ Capture\\ HD.app/Contents/MacOS/Game\\ Capture\\ HD", + "test_type": "video", + "startup_latency": "false", + "network_profile": "", + "cpu_consumption": "true", + "cpu_interval": "1", + "use_sdk": "false", + "quality_test": "all", + "cast_mirroring_version": "2.0", + "cast_streaming_on": "useCastStreaming-on" +} +
diff --git a/lab_system/master/config/kir/tests/chrome_mirroring/slaves/asus_i3_2328m_intelhd3000_win8/config/processor.config b/lab_system/master/config/kir/tests/chrome_mirroring/slaves/asus_i3_2328m_intelhd3000_win8/config/processor.config new file mode 100644 index 0000000..0e8eaf1 --- /dev/null +++ b/lab_system/master/config/kir/tests/chrome_mirroring/slaves/asus_i3_2328m_intelhd3000_win8/config/processor.config
@@ -0,0 +1,24 @@ +{ + "root_dir": "/home/gtvchrome", + "results_dir": "results", + "mirror_mp4_file": "Segment_0001.mp4", + "mirror_yuv_file": "mirror.yuv", + "mirror_wav_file": "mirror.wav", + "mirror_stats_file": "mirror_stats.txt", + "mirror_audio_results_file": "audio_results.txt", + "mirror_psnr_ssim_file": "psnr_ssim.txt", + "audio_tools_dir": "audio_quality_tools", + "image_tools_dir": "image_quality_tools", + "reference_dir": "image_quality_tools/sample_videos", + "test_utils_dir": "repository/eureka/test/utilities", + "zxing_dir": "image_quality_tools/zxing/cpp/build", + "barcode_tools_dir": "repository/eureka/test/barcode_tools", + "frame_width": "1280", + "frame_height": "720", + "barcode_height": "32", + "image_extract_interval": "1", + "ffmpeg": "ffmpeg", + "sox": "sox", + "audio_compare_tool": "polqa/PolqaOem64" +} +
diff --git a/lab_system/master/config/kir/tests/chrome_mirroring/slaves/asus_i3_2328m_intelhd3000_win8/config/soccer_30fps_encoded_60fps_capture_v2.config b/lab_system/master/config/kir/tests/chrome_mirroring/slaves/asus_i3_2328m_intelhd3000_win8/config/soccer_30fps_encoded_60fps_capture_v2.config new file mode 100644 index 0000000..6931d93 --- /dev/null +++ b/lab_system/master/config/kir/tests/chrome_mirroring/slaves/asus_i3_2328m_intelhd3000_win8/config/soccer_30fps_encoded_60fps_capture_v2.config
@@ -0,0 +1,35 @@ +{ + "_deps": ["processor.config"], + "chrome_binary_location": "C:\\Users\\gtvchrome\\repository\\chrome\\src\\out\\Debug\\chrome.exe", + "extension_path": "C:\\Users\\gtvchrome\\repository\\extension\\extension.crx", + "extra_flags": "--no-proxy-server --start-maximized --whitelisted-extension-id=fmfcbgogabcbclcofgocippekhfcmgfj --disable-web-security --enable-experimental-extension-apis --v=0 --enable-logging --vmodule=*media/cast/*=3,*chrome/renderer/media/*=3,*=0", + "high_tab_projection_quality": "ql-high", + "gpu": "on", + "full_screen": "on", + "set_fullscreen_zoom": "off", + "get_log": "true", + "log_file_name": "C:\\Users\\gtvchrome\\results\\sender.json", + "logging": "mirroring", + "enable_webrtc_getstats": "true", + "mirror_duration": "400", + "tracing_duration": "400", + "machine_name": "asus_i3_2328m_intelhd3000_win8", + "video_fps": "30", + "video_name": "soccer_30fps_encoded_60fps_capture", + "video_resolution": "720p", + "comments": "mirroring v2, video content 720p 30fps, capture at 60fps, ethernet", + "video_site": "http://172.31.25.18/test_site/index.html?video=soccer_30fps_encoded", + "recorded_video_directory": "/Users/gtvchrome/Movies/Game\\ Capture\\ HD\\ Library/mirroring/", + "capture_software": "/Applications/Game\\ Capture\\ HD.app/Contents/MacOS/Game\\ Capture\\ HD", + "test_type": "video", + "startup_latency": "false", + "network_profile": "", + "cpu_consumption": "true", + "cpu_interval": "1", + "use_sdk": "false", + "quality_test": "audio", + "cast_mirroring_version": "2.0", + "cast_streaming_on": "useCastStreaming-on", + "max_frame_rate": "60" +} +
diff --git a/lab_system/master/config/kir/tests/chrome_mirroring/slaves/asus_i3_2328m_intelhd3000_win8/config/soccer_30fps_encoded_v2.config b/lab_system/master/config/kir/tests/chrome_mirroring/slaves/asus_i3_2328m_intelhd3000_win8/config/soccer_30fps_encoded_v2.config new file mode 100644 index 0000000..ae09d7b --- /dev/null +++ b/lab_system/master/config/kir/tests/chrome_mirroring/slaves/asus_i3_2328m_intelhd3000_win8/config/soccer_30fps_encoded_v2.config
@@ -0,0 +1,34 @@ +{ + "_deps": ["processor.config"], + "chrome_binary_location": "C:\\Users\\gtvchrome\\repository\\chrome\\src\\out\\Debug\\chrome.exe", + "extension_path": "C:\\Users\\gtvchrome\\repository\\extension\\extension.crx", + "extra_flags": "--no-proxy-server --start-maximized --whitelisted-extension-id=fmfcbgogabcbclcofgocippekhfcmgfj --disable-web-security --enable-experimental-extension-apis --v=0 --enable-logging --vmodule=*media/cast/*=3,*chrome/renderer/media/*=3,*=0", + "high_tab_projection_quality": "ql-high", + "gpu": "on", + "full_screen": "on", + "set_fullscreen_zoom": "off", + "get_log": "true", + "log_file_name": "C:\\Users\\gtvchrome\\results\\sender.json", + "logging": "mirroring", + "enable_webrtc_getstats": "true", + "mirror_duration": "400", + "tracing_duration": "400", + "machine_name": "asus_i3_2328m_intelhd3000_win8", + "video_fps": "30", + "video_name": "soccer_30fps_encoded", + "video_resolution": "720p", + "comments": "mirroring v2, video content 720p 30fps, ethernet", + "video_site": "http://172.31.25.18/test_site/index.html?video=soccer_30fps_encoded", + "recorded_video_directory": "/Users/gtvchrome/Movies/Game\\ Capture\\ HD\\ Library/mirroring/", + "capture_software": "/Applications/Game\\ Capture\\ HD.app/Contents/MacOS/Game\\ Capture\\ HD", + "test_type": "video", + "startup_latency": "false", + "network_profile": "", + "cpu_consumption": "true", + "cpu_interval": "1", + "use_sdk": "false", + "quality_test": "audio", + "cast_mirroring_version": "2.0", + "cast_streaming_on": "useCastStreaming-on" +} +
diff --git a/lab_system/master/config/kir/tests/chrome_mirroring/slaves/asus_i3_2328m_intelhd3000_win8/config/titanfall_60fps_encoded_v2.config b/lab_system/master/config/kir/tests/chrome_mirroring/slaves/asus_i3_2328m_intelhd3000_win8/config/titanfall_60fps_encoded_v2.config new file mode 100644 index 0000000..31fb4b8 --- /dev/null +++ b/lab_system/master/config/kir/tests/chrome_mirroring/slaves/asus_i3_2328m_intelhd3000_win8/config/titanfall_60fps_encoded_v2.config
@@ -0,0 +1,35 @@ +{ + "_deps": ["processor.config"], + "chrome_binary_location": "C:\\Users\\gtvchrome\\repository\\chrome\\src\\out\\Debug\\chrome.exe", + "extension_path": "C:\\Users\\gtvchrome\\repository\\extension\\extension.crx", + "extra_flags": "--no-proxy-server --start-maximized --whitelisted-extension-id=fmfcbgogabcbclcofgocippekhfcmgfj --disable-web-security --enable-experimental-extension-apis --v=0 --enable-logging --vmodule=*media/cast/*=3,*chrome/renderer/media/*=3,*=0", + "high_tab_projection_quality": "ql-high", + "gpu": "on", + "full_screen": "on", + "set_fullscreen_zoom": "off", + "get_log": "true", + "log_file_name": "C:\\Users\\gtvchrome\\results\\sender.json", + "logging": "mirroring", + "enable_webrtc_getstats": "true", + "mirror_duration": "400", + "tracing_duration": "400", + "machine_name": "asus_i3_2328m_intelhd3000_win8", + "video_fps": "60", + "video_name": "titanfall_60fps_encoded", + "video_resolution": "720p", + "comments": "mirroring v2, video content 720p 60fps, ethernet", + "video_site": "http://172.31.25.18/test_site/index.html?video=titanfall_60fps_encoded", + "recorded_video_directory": "/Users/gtvchrome/Movies/Game\\ Capture\\ HD\\ Library/mirroring/", + "capture_software": "/Applications/Game\\ Capture\\ HD.app/Contents/MacOS/Game\\ Capture\\ HD", + "test_type": "video", + "startup_latency": "false", + "network_profile": "", + "cpu_consumption": "true", + "cpu_interval": "1", + "use_sdk": "false", + "quality_test": "audio", + "cast_mirroring_version": "2.0", + "cast_streaming_on": "useCastStreaming-on", + "max_frame_rate": "60" +} +
diff --git a/lab_system/master/config/kir/tests/chrome_mirroring/slaves/hp_core2duo_p8600_gma4500_win7/config/bad_wifi.config b/lab_system/master/config/kir/tests/chrome_mirroring/slaves/hp_core2duo_p8600_gma4500_win7/config/bad_wifi.config new file mode 100644 index 0000000..a7bd44e --- /dev/null +++ b/lab_system/master/config/kir/tests/chrome_mirroring/slaves/hp_core2duo_p8600_gma4500_win7/config/bad_wifi.config
@@ -0,0 +1,4 @@ +{ + "udp_proxy_server": "http://172.31.25.18:8888", + "network_profile": "bad" +}
diff --git a/lab_system/master/config/kir/tests/chrome_mirroring/slaves/hp_core2duo_p8600_gma4500_win7/config/bunny_480p_desktop_mirror.config b/lab_system/master/config/kir/tests/chrome_mirroring/slaves/hp_core2duo_p8600_gma4500_win7/config/bunny_480p_desktop_mirror.config new file mode 100644 index 0000000..8d2e883 --- /dev/null +++ b/lab_system/master/config/kir/tests/chrome_mirroring/slaves/hp_core2duo_p8600_gma4500_win7/config/bunny_480p_desktop_mirror.config
@@ -0,0 +1,29 @@ +{ + "add_debug_dongle_ip": "172.31.25.1", + "chrome_binary_location": "C:\\Users\\gtvchrome\\repository\\chrome\\src\\out\\Debug\\chrome.exe", + "cpu_consumption": "true", + "cpu_interval": "1", + "resolution_1280_720": "1280x720", + "device_ip": "172.31.25.1", + "enable_webrtc_getstats": "true", + "extension_path": "C:\\Users\\gtvchrome\\extension_dev\\extension.crx", + "extra_flags": "--no-proxy-server --start-maximized --whitelisted-extension-id=hfaagokkkhdbgiakmmlclaapfelnkoah --disable-web-security --enable-experimental-extension-apis --enable-usermedia-screen-capturing --enable-logging --v=1 --vmodule=*source*/talk/*=3", + "full_screen": "on", + "get_log": "true", + "gpu": "on", + "log_file_name": "C:\\Users\\gtvchrome\\results\\sender.json", + "logging": "mirroring", + "machine_name": "hp_core2duo_p8600_gma4500_win7", + "mirror_duration": "560", + "network_profile": "", + "set_fullscreen_zoom": "on", + "startup_latency": "false", + "test_type": "video", + "tracing_duration": "560", + "video_fps": "24fps", + "video_name": "bunny_video_24fps_480p_default_desktop_mirroring", + "video_resolution": "480p", + "comments": "Buffered mode, NACK on", + "video_site": "http://172.31.25.18/test_site/index.html?video=bunny_480p", + "desktop_capture": "true" +}
diff --git a/lab_system/master/config/kir/tests/chrome_mirroring/slaves/hp_core2duo_p8600_gma4500_win7/config/gangnam_encoded.config b/lab_system/master/config/kir/tests/chrome_mirroring/slaves/hp_core2duo_p8600_gma4500_win7/config/gangnam_encoded.config new file mode 100644 index 0000000..5e0beed --- /dev/null +++ b/lab_system/master/config/kir/tests/chrome_mirroring/slaves/hp_core2duo_p8600_gma4500_win7/config/gangnam_encoded.config
@@ -0,0 +1,33 @@ +{ + "_deps": ["processor.config"], + "chrome_binary_location": "C:\\Users\\gtvchrome\\repository\\chrome\\src\\out\\Debug\\chrome.exe", + "extension_path": "C:\\Users\\gtvchrome\\repository\\extension\\extension.crx", + "extra_flags": "--no-proxy-server --start-maximized --whitelisted-extension-id=fmfcbgogabcbclcofgocippekhfcmgfj --disable-web-security --enable-experimental-extension-apis --enable-logging --v=1 --vmodule=*libjingle/source_internal/talk/*=4,*=0", + "low_tab_projection_quality": "ql-low", + "gpu": "on", + "full_screen": "on", + "set_fullscreen_zoom": "off", + "get_log": "true", + "log_file_name": "C:\\Users\\gtvchrome\\results\\sender.json", + "logging": "mirroring", + "enable_webrtc_getstats": "true", + "mirror_duration": "400", + "tracing_duration": "400", + "machine_name": "hp_core2duo_p8600_gma4500_win7", + "video_fps": "24", + "video_name": "gangnam_encoded", + "video_resolution": "720p", + "comments": "mirroring v1, video content 720p 24fps, ethernet", + "video_site": "http://172.31.25.18/test_site/index.html?video=gangnam_720p_av_test", + "recorded_video_directory": "/Users/gtvchrome/Movies/Game\\ Capture\\ HD\\ Library/mirroring/", + "capture_software": "/Applications/Game\\ Capture\\ HD.app/Contents/MacOS/Game\\ Capture\\ HD", + "test_type": "video", + "startup_latency": "false", + "network_profile": "", + "cpu_consumption": "true", + "cpu_interval": "1", + "use_sdk": "false", + "quality_test": "all", + "cast_mirroring_version": "1.0", + "cast_streaming_off": "useCastStreaming-off" +}
diff --git a/lab_system/master/config/kir/tests/chrome_mirroring/slaves/hp_core2duo_p8600_gma4500_win7/config/gangnam_encoded_v2.config b/lab_system/master/config/kir/tests/chrome_mirroring/slaves/hp_core2duo_p8600_gma4500_win7/config/gangnam_encoded_v2.config new file mode 100644 index 0000000..f4c4059 --- /dev/null +++ b/lab_system/master/config/kir/tests/chrome_mirroring/slaves/hp_core2duo_p8600_gma4500_win7/config/gangnam_encoded_v2.config
@@ -0,0 +1,34 @@ +{ + "_deps": ["processor.config"], + "chrome_binary_location": "C:\\Users\\gtvchrome\\repository\\chrome\\src\\out\\Debug\\chrome.exe", + "extension_path": "C:\\Users\\gtvchrome\\repository\\extension\\extension.crx", + "extra_flags": "--no-proxy-server --start-maximized --whitelisted-extension-id=fmfcbgogabcbclcofgocippekhfcmgfj --disable-web-security --enable-experimental-extension-apis --v=0 --enable-logging --vmodule=*media/cast/*=3,*chrome/renderer/media/*=3,*=0", + "low_tab_projection_quality": "ql-low", + "gpu": "on", + "full_screen": "on", + "set_fullscreen_zoom": "off", + "get_log": "true", + "log_file_name": "C:\\Users\\gtvchrome\\results\\sender.json", + "logging": "mirroring", + "enable_webrtc_getstats": "true", + "mirror_duration": "400", + "tracing_duration": "400", + "machine_name": "hp_core2duo_p8600_gma4500_win7", + "video_fps": "24", + "video_name": "gangnam_encoded", + "video_resolution": "720p", + "comments": "mirroring v2, video content 720p 24fps, ethernet", + "video_site": "http://172.31.25.18/test_site/index.html?video=gangnam_720p_av_test", + "recorded_video_directory": "/Users/gtvchrome/Movies/Game\\ Capture\\ HD\\ Library/mirroring/", + "capture_software": "/Applications/Game\\ Capture\\ HD.app/Contents/MacOS/Game\\ Capture\\ HD", + "test_type": "video", + "startup_latency": "false", + "network_profile": "", + "cpu_consumption": "true", + "cpu_interval": "1", + "use_sdk": "false", + "quality_test": "all", + "cast_mirroring_version": "2.0", + "cast_streaming_on": "useCastStreaming-on" +} +
diff --git a/lab_system/master/config/kir/tests/chrome_mirroring/slaves/hp_core2duo_p8600_gma4500_win7/config/gangnam_encoded_v2_bad_wifi.config b/lab_system/master/config/kir/tests/chrome_mirroring/slaves/hp_core2duo_p8600_gma4500_win7/config/gangnam_encoded_v2_bad_wifi.config new file mode 100644 index 0000000..ec89110 --- /dev/null +++ b/lab_system/master/config/kir/tests/chrome_mirroring/slaves/hp_core2duo_p8600_gma4500_win7/config/gangnam_encoded_v2_bad_wifi.config
@@ -0,0 +1,33 @@ +{ + "_deps": ["processor.config", "bad_wifi.config"], + "chrome_binary_location": "C:\\Users\\gtvchrome\\repository\\chrome\\src\\out\\Debug\\chrome.exe", + "extension_path": "C:\\Users\\gtvchrome\\repository\\extension\\extension.crx", + "extra_flags": "--no-proxy-server --start-maximized --whitelisted-extension-id=fmfcbgogabcbclcofgocippekhfcmgfj --disable-web-security --enable-experimental-extension-apis --v=0 --enable-logging --vmodule=*media/cast/*=3,*chrome/renderer/media/*=3,*=0", + "low_tab_projection_quality": "ql-low", + "gpu": "on", + "full_screen": "on", + "set_fullscreen_zoom": "off", + "get_log": "true", + "log_file_name": "C:\\Users\\gtvchrome\\results\\sender.json", + "logging": "mirroring", + "enable_webrtc_getstats": "true", + "mirror_duration": "400", + "tracing_duration": "400", + "machine_name": "hp_core2duo_p8600_gma4500_win7", + "video_fps": "24", + "video_name": "gangnam_encoded", + "video_resolution": "720p", + "comments": "mirroring v2, video content 720p 24fps, bad wifi", + "video_site": "http://172.31.25.18/test_site/index.html?video=gangnam_720p_av_test", + "recorded_video_directory": "/Users/gtvchrome/Movies/Game\\ Capture\\ HD\\ Library/mirroring/", + "capture_software": "/Applications/Game\\ Capture\\ HD.app/Contents/MacOS/Game\\ Capture\\ HD", + "test_type": "video", + "startup_latency": "false", + "cpu_consumption": "true", + "cpu_interval": "1", + "use_sdk": "false", + "quality_test": "all", + "cast_mirroring_version": "2.0", + "cast_streaming_on": "useCastStreaming-on" +} +
diff --git a/lab_system/master/config/kir/tests/chrome_mirroring/slaves/hp_core2duo_p8600_gma4500_win7/config/processor.config b/lab_system/master/config/kir/tests/chrome_mirroring/slaves/hp_core2duo_p8600_gma4500_win7/config/processor.config new file mode 100644 index 0000000..0e8eaf1 --- /dev/null +++ b/lab_system/master/config/kir/tests/chrome_mirroring/slaves/hp_core2duo_p8600_gma4500_win7/config/processor.config
@@ -0,0 +1,24 @@ +{ + "root_dir": "/home/gtvchrome", + "results_dir": "results", + "mirror_mp4_file": "Segment_0001.mp4", + "mirror_yuv_file": "mirror.yuv", + "mirror_wav_file": "mirror.wav", + "mirror_stats_file": "mirror_stats.txt", + "mirror_audio_results_file": "audio_results.txt", + "mirror_psnr_ssim_file": "psnr_ssim.txt", + "audio_tools_dir": "audio_quality_tools", + "image_tools_dir": "image_quality_tools", + "reference_dir": "image_quality_tools/sample_videos", + "test_utils_dir": "repository/eureka/test/utilities", + "zxing_dir": "image_quality_tools/zxing/cpp/build", + "barcode_tools_dir": "repository/eureka/test/barcode_tools", + "frame_width": "1280", + "frame_height": "720", + "barcode_height": "32", + "image_extract_interval": "1", + "ffmpeg": "ffmpeg", + "sox": "sox", + "audio_compare_tool": "polqa/PolqaOem64" +} +
diff --git a/lab_system/master/config/kir/tests/chrome_mirroring/slaves/hp_core2duo_p8600_gma4500_win7/config/soccer_30fps_encoded_60fps_capture_v2.config b/lab_system/master/config/kir/tests/chrome_mirroring/slaves/hp_core2duo_p8600_gma4500_win7/config/soccer_30fps_encoded_60fps_capture_v2.config new file mode 100644 index 0000000..37c4768 --- /dev/null +++ b/lab_system/master/config/kir/tests/chrome_mirroring/slaves/hp_core2duo_p8600_gma4500_win7/config/soccer_30fps_encoded_60fps_capture_v2.config
@@ -0,0 +1,35 @@ +{ + "_deps": ["processor.config"], + "chrome_binary_location": "C:\\Users\\gtvchrome\\repository\\chrome\\src\\out\\Debug\\chrome.exe", + "extension_path": "C:\\Users\\gtvchrome\\repository\\extension\\extension.crx", + "extra_flags": "--no-proxy-server --start-maximized --whitelisted-extension-id=fmfcbgogabcbclcofgocippekhfcmgfj --disable-web-security --enable-experimental-extension-apis --v=0 --enable-logging --vmodule=*media/cast/*=3,*chrome/renderer/media/*=3,*=0", + "low_tab_projection_quality": "ql-low", + "gpu": "on", + "full_screen": "on", + "set_fullscreen_zoom": "off", + "get_log": "true", + "log_file_name": "C:\\Users\\gtvchrome\\results\\sender.json", + "logging": "mirroring", + "enable_webrtc_getstats": "true", + "mirror_duration": "400", + "tracing_duration": "400", + "machine_name": "hp_core2duo_p8600_gma4500_win7", + "video_fps": "30", + "video_name": "soccer_30fps_encoded", + "video_resolution": "720p", + "comments": "mirroring v2, video content 720p 30fps, capture at 60fps, ethernet", + "video_site": "http://172.31.25.18/test_site/index.html?video=soccer_30fps_encoded", + "recorded_video_directory": "/Users/gtvchrome/Movies/Game\\ Capture\\ HD\\ Library/mirroring/", + "capture_software": "/Applications/Game\\ Capture\\ HD.app/Contents/MacOS/Game\\ Capture\\ HD", + "test_type": "video", + "startup_latency": "false", + "network_profile": "", + "cpu_consumption": "true", + "cpu_interval": "1", + "use_sdk": "false", + "quality_test": "audio", + "cast_mirroring_version": "2.0", + "cast_streaming_on": "useCastStreaming-on", + "max_frame_rate": "60" +} +
diff --git a/lab_system/master/config/kir/tests/chrome_mirroring/slaves/hp_core2duo_p8600_gma4500_win7/config/soccer_30fps_encoded_v2.config b/lab_system/master/config/kir/tests/chrome_mirroring/slaves/hp_core2duo_p8600_gma4500_win7/config/soccer_30fps_encoded_v2.config new file mode 100644 index 0000000..bb689df --- /dev/null +++ b/lab_system/master/config/kir/tests/chrome_mirroring/slaves/hp_core2duo_p8600_gma4500_win7/config/soccer_30fps_encoded_v2.config
@@ -0,0 +1,34 @@ +{ + "_deps": ["processor.config"], + "chrome_binary_location": "C:\\Users\\gtvchrome\\repository\\chrome\\src\\out\\Debug\\chrome.exe", + "extension_path": "C:\\Users\\gtvchrome\\repository\\extension\\extension.crx", + "extra_flags": "--no-proxy-server --start-maximized --whitelisted-extension-id=fmfcbgogabcbclcofgocippekhfcmgfj --disable-web-security --enable-experimental-extension-apis --v=0 --enable-logging --vmodule=*media/cast/*=3,*chrome/renderer/media/*=3,*=0", + "low_tab_projection_quality": "ql-low", + "gpu": "on", + "full_screen": "on", + "set_fullscreen_zoom": "off", + "get_log": "true", + "log_file_name": "C:\\Users\\gtvchrome\\results\\sender.json", + "logging": "mirroring", + "enable_webrtc_getstats": "true", + "mirror_duration": "400", + "tracing_duration": "400", + "machine_name": "hp_core2duo_p8600_gma4500_win7", + "video_fps": "30", + "video_name": "soccer_30fps_encoded", + "video_resolution": "720p", + "comments": "mirroring v2, video content 720p 30fps, ethernet", + "video_site": "http://172.31.25.18/test_site/index.html?video=soccer_30fps_encoded", + "recorded_video_directory": "/Users/gtvchrome/Movies/Game\\ Capture\\ HD\\ Library/mirroring/", + "capture_software": "/Applications/Game\\ Capture\\ HD.app/Contents/MacOS/Game\\ Capture\\ HD", + "test_type": "video", + "startup_latency": "false", + "network_profile": "", + "cpu_consumption": "true", + "cpu_interval": "1", + "use_sdk": "false", + "quality_test": "audio", + "cast_mirroring_version": "2.0", + "cast_streaming_on": "useCastStreaming-on" +} +
diff --git a/lab_system/master/config/kir/tests/chrome_mirroring/slaves/hp_core2duo_p8600_gma4500_win7/config/titanfall_60fps_encoded_v2.config b/lab_system/master/config/kir/tests/chrome_mirroring/slaves/hp_core2duo_p8600_gma4500_win7/config/titanfall_60fps_encoded_v2.config new file mode 100644 index 0000000..2b22d26 --- /dev/null +++ b/lab_system/master/config/kir/tests/chrome_mirroring/slaves/hp_core2duo_p8600_gma4500_win7/config/titanfall_60fps_encoded_v2.config
@@ -0,0 +1,35 @@ +{ + "_deps": ["processor.config"], + "chrome_binary_location": "C:\\Users\\gtvchrome\\repository\\chrome\\src\\out\\Debug\\chrome.exe", + "extension_path": "C:\\Users\\gtvchrome\\repository\\extension\\extension.crx", + "extra_flags": "--no-proxy-server --start-maximized --whitelisted-extension-id=fmfcbgogabcbclcofgocippekhfcmgfj --disable-web-security --enable-experimental-extension-apis --v=0 --enable-logging --vmodule=*media/cast/*=3,*chrome/renderer/media/*=3,*=0", + "low_tab_projection_quality": "ql-low", + "gpu": "on", + "full_screen": "on", + "set_fullscreen_zoom": "off", + "get_log": "true", + "log_file_name": "C:\\Users\\gtvchrome\\results\\sender.json", + "logging": "mirroring", + "enable_webrtc_getstats": "true", + "mirror_duration": "400", + "tracing_duration": "400", + "machine_name": "hp_core2duo_p8600_gma4500_win7", + "video_fps": "60", + "video_name": "titanfall_60fps_encoded", + "video_resolution": "720p", + "comments": "mirroring v2, video content 720p 60fps, ethernet", + "video_site": "http://172.31.25.18/test_site/index.html?video=titanfall_60fps_encoded", + "recorded_video_directory": "/Users/gtvchrome/Movies/Game\\ Capture\\ HD\\ Library/mirroring/", + "capture_software": "/Applications/Game\\ Capture\\ HD.app/Contents/MacOS/Game\\ Capture\\ HD", + "test_type": "video", + "startup_latency": "false", + "network_profile": "", + "cpu_consumption": "true", + "cpu_interval": "1", + "use_sdk": "false", + "quality_test": "audio", + "cast_mirroring_version": "2.0", + "cast_streaming_on": "useCastStreaming-on", + "max_frame_rate": "60" +} +
diff --git a/lab_system/master/config/kir/tests/chrome_mirroring/slaves/hp_core_i5_3210m_intelhd4000_win8_mtv/config/gangnam_encoded_v2.config b/lab_system/master/config/kir/tests/chrome_mirroring/slaves/hp_core_i5_3210m_intelhd4000_win8_mtv/config/gangnam_encoded_v2.config new file mode 100644 index 0000000..dcce4ea --- /dev/null +++ b/lab_system/master/config/kir/tests/chrome_mirroring/slaves/hp_core_i5_3210m_intelhd4000_win8_mtv/config/gangnam_encoded_v2.config
@@ -0,0 +1,31 @@ +{ + "_deps": ["processor.config"], + "chrome_binary_location": "C:\\Users\\gtvchrome\\repository\\chrome\\src\\out\\Debug\\chrome.exe", + "extension_path": "C:\\Users\\gtvchrome\\repository\\extension\\extension.crx", + "extra_flags": "--no-proxy-server --start-maximized --whitelisted-extension-id=dliochdbjfkdbacpmhlcpmleaejidimm --disable-web-security --enable-experimental-extension-apis --v=0 --enable-logging --vmodule=*media/cast/*=3,*chrome/renderer/media/*=3,*=0", + "full_screen": "on", + "gpu": "on", + "get_log": "true", + "log_file_name": "C:\\Users\\gtvchrome\\results\\sender.json", + "logging": "mirroring", + "enable_webrtc_getstats": "true", + "mirror_duration": "400", + "tracing_duration": "400", + "machine_name": "hp_core_i5_3210m_intelhd4000_win8_mtv", + "video_fps": "24", + "video_name": "gangnam_encoded", + "video_resolution": "720p", + "comments": "mirroring v2, video content 720p 24fps, ethernet", + "video_site": "http://172.17.23.200/perf_test/test_site/index.html?video=gangnam_720p_av_test", + "recorded_video_directory": "/Users/gtvchrome/Movies/Game\\ Capture\\ HD\\ Library/mirroring/", + "capture_software": "/Applications/Game\\ Capture\\ HD.app/Contents/MacOS/Game\\ Capture\\ HD", + "test_type": "video", + "startup_latency": "false", + "network_profile": "", + "cpu_consumption": "true", + "cpu_interval": "1", + "use_sdk": "false", + "quality_test": "all", + "cast_mirroring_version": "2.0", + "cast_streaming_on": "useCastStreaming-on" +}
diff --git a/lab_system/master/config/kir/tests/chrome_mirroring/slaves/hp_core_i5_3210m_intelhd4000_win8_mtv/config/processor.config b/lab_system/master/config/kir/tests/chrome_mirroring/slaves/hp_core_i5_3210m_intelhd4000_win8_mtv/config/processor.config new file mode 100644 index 0000000..0e8eaf1 --- /dev/null +++ b/lab_system/master/config/kir/tests/chrome_mirroring/slaves/hp_core_i5_3210m_intelhd4000_win8_mtv/config/processor.config
@@ -0,0 +1,24 @@ +{ + "root_dir": "/home/gtvchrome", + "results_dir": "results", + "mirror_mp4_file": "Segment_0001.mp4", + "mirror_yuv_file": "mirror.yuv", + "mirror_wav_file": "mirror.wav", + "mirror_stats_file": "mirror_stats.txt", + "mirror_audio_results_file": "audio_results.txt", + "mirror_psnr_ssim_file": "psnr_ssim.txt", + "audio_tools_dir": "audio_quality_tools", + "image_tools_dir": "image_quality_tools", + "reference_dir": "image_quality_tools/sample_videos", + "test_utils_dir": "repository/eureka/test/utilities", + "zxing_dir": "image_quality_tools/zxing/cpp/build", + "barcode_tools_dir": "repository/eureka/test/barcode_tools", + "frame_width": "1280", + "frame_height": "720", + "barcode_height": "32", + "image_extract_interval": "1", + "ffmpeg": "ffmpeg", + "sox": "sox", + "audio_compare_tool": "polqa/PolqaOem64" +} +
diff --git a/lab_system/master/config/kir/tests/chrome_mirroring/slaves/hp_core_i5_3210m_intelhd4000_win8_mtv/config/soccer_30fps_encoded_60fps_capture_v2.config b/lab_system/master/config/kir/tests/chrome_mirroring/slaves/hp_core_i5_3210m_intelhd4000_win8_mtv/config/soccer_30fps_encoded_60fps_capture_v2.config new file mode 100644 index 0000000..247ae6f --- /dev/null +++ b/lab_system/master/config/kir/tests/chrome_mirroring/slaves/hp_core_i5_3210m_intelhd4000_win8_mtv/config/soccer_30fps_encoded_60fps_capture_v2.config
@@ -0,0 +1,32 @@ +{ + "_deps": ["processor.config"], + "chrome_binary_location": "C:\\Users\\gtvchrome\\repository\\chrome\\src\\out\\Debug\\chrome.exe", + "extension_path": "C:\\Users\\gtvchrome\\repository\\extension\\extension.crx", + "extra_flags": "--no-proxy-server --start-maximized --whitelisted-extension-id=dliochdbjfkdbacpmhlcpmleaejidimm --disable-web-security --enable-experimental-extension-apis --v=0 --enable-logging --vmodule=*media/cast/*=3,*chrome/renderer/media/*=3,*=0", + "gpu": "on", + "full_screen": "on", + "get_log": "true", + "log_file_name": "C:\\Users\\gtvchrome\\results\\sender.json", + "logging": "mirroring", + "enable_webrtc_getstats": "true", + "mirror_duration": "400", + "tracing_duration": "400", + "machine_name": "hp_core_i5_3210m_intelhd4000_win8_mtv", + "video_fps": "30", + "video_name": "soccer_30fps_encoded", + "video_resolution": "720p", + "comments": "mirroring v2, video content 720p 30fps, capture at 60fps, ethernet", + "video_site": "http://172.17.23.200/perf_test/test_site/index.html?video=soccer_30fps_encoded", + "recorded_video_directory": "/Users/gtvchrome/Movies/Game\\ Capture\\ HD\\ Library/mirroring/", + "capture_software": "/Applications/Game\\ Capture\\ HD.app/Contents/MacOS/Game\\ Capture\\ HD", + "test_type": "video", + "startup_latency": "false", + "network_profile": "", + "cpu_consumption": "true", + "cpu_interval": "1", + "use_sdk": "false", + "quality_test": "audio", + "cast_mirroring_version": "2.0", + "cast_streaming_on": "useCastStreaming-on", + "max_frame_rate": "60" +}
diff --git a/lab_system/master/config/kir/tests/chrome_mirroring/slaves/hp_core_i5_3210m_intelhd4000_win8_mtv/config/soccer_30fps_encoded_v2.config b/lab_system/master/config/kir/tests/chrome_mirroring/slaves/hp_core_i5_3210m_intelhd4000_win8_mtv/config/soccer_30fps_encoded_v2.config new file mode 100644 index 0000000..3d3e28d --- /dev/null +++ b/lab_system/master/config/kir/tests/chrome_mirroring/slaves/hp_core_i5_3210m_intelhd4000_win8_mtv/config/soccer_30fps_encoded_v2.config
@@ -0,0 +1,31 @@ +{ + "_deps": ["processor.config"], + "chrome_binary_location": "C:\\Users\\gtvchrome\\repository\\chrome\\src\\out\\Debug\\chrome.exe", + "extension_path": "C:\\Users\\gtvchrome\\repository\\extension\\extension.crx", + "extra_flags": "--no-proxy-server --start-maximized --whitelisted-extension-id=dliochdbjfkdbacpmhlcpmleaejidimm --disable-web-security --enable-experimental-extension-apis --v=0 --enable-logging --vmodule=*media/cast/*=3,*chrome/renderer/media/*=3,*=0", + "gpu": "on", + "full_screen": "on", + "get_log": "true", + "log_file_name": "C:\\Users\\gtvchrome\\results\\sender.json", + "logging": "mirroring", + "enable_webrtc_getstats": "true", + "mirror_duration": "400", + "tracing_duration": "400", + "machine_name": "hp_core_i5_3210m_intelhd4000_win8_mtv", + "video_fps": "30", + "video_name": "soccer_30fps_encoded", + "video_resolution": "720p", + "comments": "mirroring v2, video content 720p 30fps, ethernet", + "video_site": "http://172.17.23.200/perf_test/test_site/index.html?video=soccer_30fps_encoded", + "recorded_video_directory": "/Users/gtvchrome/Movies/Game\\ Capture\\ HD\\ Library/mirroring/", + "capture_software": "/Applications/Game\\ Capture\\ HD.app/Contents/MacOS/Game\\ Capture\\ HD", + "test_type": "video", + "startup_latency": "false", + "network_profile": "", + "cpu_consumption": "true", + "cpu_interval": "1", + "use_sdk": "false", + "quality_test": "audio", + "cast_mirroring_version": "2.0", + "cast_streaming_on": "useCastStreaming-on" +}
diff --git a/lab_system/master/config/kir/tests/chrome_mirroring/slaves/hp_core_i5_3210m_intelhd4000_win8_mtv/config/titanfall_60fps_encoded_v2.config b/lab_system/master/config/kir/tests/chrome_mirroring/slaves/hp_core_i5_3210m_intelhd4000_win8_mtv/config/titanfall_60fps_encoded_v2.config new file mode 100644 index 0000000..273a15b --- /dev/null +++ b/lab_system/master/config/kir/tests/chrome_mirroring/slaves/hp_core_i5_3210m_intelhd4000_win8_mtv/config/titanfall_60fps_encoded_v2.config
@@ -0,0 +1,32 @@ +{ + "_deps": ["processor.config"], + "chrome_binary_location": "C:\\Users\\gtvchrome\\repository\\chrome\\src\\out\\Debug\\chrome.exe", + "extension_path": "C:\\Users\\gtvchrome\\repository\\extension\\extension.crx", + "extra_flags": "--no-proxy-server --start-maximized --whitelisted-extension-id=dliochdbjfkdbacpmhlcpmleaejidimm --disable-web-security --enable-experimental-extension-apis --v=0 --enable-logging --vmodule=*media/cast/*=3,*chrome/renderer/media/*=3,*=0", + "gpu": "on", + "full_screen": "on", + "get_log": "true", + "log_file_name": "C:\\Users\\gtvchrome\\results\\sender.json", + "logging": "mirroring", + "enable_webrtc_getstats": "true", + "mirror_duration": "400", + "tracing_duration": "400", + "machine_name": "hp_core_i5_3210m_intelhd4000_win8_mtv", + "video_fps": "60", + "video_name": "titanfall_60fps_encoded", + "video_resolution": "720p", + "comments": "mirroring v2, video content 720p 60fps, ethernet", + "video_site": "http://172.31.25.18/test_site/index.html?video=titanfall_60fps_encoded", + "recorded_video_directory": "/Users/gtvchrome/Movies/Game\\ Capture\\ HD\\ Library/mirroring/", + "capture_software": "/Applications/Game\\ Capture\\ HD.app/Contents/MacOS/Game\\ Capture\\ HD", + "test_type": "video", + "startup_latency": "false", + "network_profile": "", + "cpu_consumption": "true", + "cpu_interval": "1", + "use_sdk": "false", + "quality_test": "audio", + "cast_mirroring_version": "2.0", + "cast_streaming_on": "useCastStreaming-on", + "max_frame_rate": "60" +}
diff --git a/lab_system/master/config/kir/tests/chrome_mirroring/slaves/macbookair_i5_4250u_intelhd5000/config/bad_wifi.config b/lab_system/master/config/kir/tests/chrome_mirroring/slaves/macbookair_i5_4250u_intelhd5000/config/bad_wifi.config new file mode 100644 index 0000000..5d576b1 --- /dev/null +++ b/lab_system/master/config/kir/tests/chrome_mirroring/slaves/macbookair_i5_4250u_intelhd5000/config/bad_wifi.config
@@ -0,0 +1,4 @@ +{ + "udp_proxy_server": "http://172.31.25.18:8888", + "network_profile": "bad" +} \ No newline at end of file
diff --git a/lab_system/master/config/kir/tests/chrome_mirroring/slaves/macbookair_i5_4250u_intelhd5000/config/bunny_480p_desktop_mirror.config b/lab_system/master/config/kir/tests/chrome_mirroring/slaves/macbookair_i5_4250u_intelhd5000/config/bunny_480p_desktop_mirror.config new file mode 100644 index 0000000..ca5df9f --- /dev/null +++ b/lab_system/master/config/kir/tests/chrome_mirroring/slaves/macbookair_i5_4250u_intelhd5000/config/bunny_480p_desktop_mirror.config
@@ -0,0 +1,31 @@ +{ + "add_debug_dongle_ip": "172.31.25.19", + "chrome_binary_location": "/Users/gtvchrome/repository/chrome/src/out/Debug/Google Chrome.app/Contents/MacOS/Google Chrome", + "cpu_consumption": "true", + "cpu_interval": "1", + "resolution_1280_720": "1280x720", + "device_ip": "172.31.25.19", + "enable_webrtc_getstats": "true", + "extension_path": "/Users/gtvchrome/repository/extension/extension.crx", + "extra_flags": "--no-proxy-server --start-maximized --whitelisted-extension-id=hfaagokkkhdbgiakmmlclaapfelnkoah --disable-web-security --enable-experimental-extension-apis --enable-usermedia-screen-capturing --enable-logging --v=1 --vmodule=*libjingle/source_internal/talk/*=4,*=0", + "full_screen": "on", + "get_log": "true", + "gpu": "on", + "log_file_name": "/Users/gtvchrome/results/sender.json", + "logging": "mirroring", + "machine_name": "macbookair_i5_4250u_intelhd5000", + "mirror_duration": "560", + "network_profile": "", + "set_fullscreen_zoom": "on", + "ssh_private_key": "/Users/gtvchrome/.ssh/id_rsa", + "startup_latency": "false", + "test_type": "video", + "tracing_duration": "560", + "video_fps": "24fps", + "video_name": "bunny_video_24fps_480p_default_desktop_mirroring", + "video_resolution": "480p", + "comments": "Buffered mode, NACK on", + "video_site": "http://172.31.25.18/test_site/index.html?video=bunny_480p", + "use_sdk": "true", + "desktop_capture": "true" +}
diff --git a/lab_system/master/config/kir/tests/chrome_mirroring/slaves/macbookair_i5_4250u_intelhd5000/config/gangnam_encoded.config b/lab_system/master/config/kir/tests/chrome_mirroring/slaves/macbookair_i5_4250u_intelhd5000/config/gangnam_encoded.config new file mode 100644 index 0000000..4b80ade --- /dev/null +++ b/lab_system/master/config/kir/tests/chrome_mirroring/slaves/macbookair_i5_4250u_intelhd5000/config/gangnam_encoded.config
@@ -0,0 +1,33 @@ +{ + "_deps": ["processor.config"], + "chrome_binary_location": "/Users/gtvchrome/repository/chrome/src/out/Debug/Google Chrome.app/Contents/MacOS/Google Chrome", + "extension_path": "/Users/gtvchrome/repository/extension/extension.crx", + "extra_flags": "--no-proxy-server --start-maximized --whitelisted-extension-id=fmfcbgogabcbclcofgocippekhfcmgfj --disable-web-security --enable-experimental-extension-apis --enable-logging --v=1 --vmodule=*libjingle/source_internal/talk/*=4,*=0", + "high_tab_projection_quality": "ql-high", + "gpu": "on", + "full_screen": "on", + "set_fullscreen_zoom": "off", + "get_log": "true", + "log_file_name": "/Users/gtvchrome/results/sender.json", + "logging": "mirroring", + "enable_webrtc_getstats": "true", + "mirror_duration": "400", + "tracing_duration": "400", + "machine_name": "macbookair_i5_4250u_intelhd5000", + "video_fps": "24", + "video_name": "gangnam_encoded", + "video_resolution": "720p", + "comments": "mirroring v1, video content 720p 24fps, ethernet", + "video_site": "http://172.31.25.18/test_site/index.html?video=gangnam_720p_av_test", + "recorded_video_directory": "/Users/gtvchrome/Movies/Game\\ Capture\\ HD\\ Library/mirroring/", + "capture_software": "/Applications/Game\\ Capture\\ HD.app/Contents/MacOS/Game\\ Capture\\ HD", + "test_type": "video", + "startup_latency": "false", + "network_profile": "", + "cpu_consumption": "true", + "cpu_interval": "1", + "use_sdk": "false", + "quality_test": "all", + "cast_mirroring_version": "1.0", + "cast_streaming_off": "useCastStreaming-off" +}
diff --git a/lab_system/master/config/kir/tests/chrome_mirroring/slaves/macbookair_i5_4250u_intelhd5000/config/gangnam_encoded_v2.config b/lab_system/master/config/kir/tests/chrome_mirroring/slaves/macbookair_i5_4250u_intelhd5000/config/gangnam_encoded_v2.config new file mode 100644 index 0000000..20d7466 --- /dev/null +++ b/lab_system/master/config/kir/tests/chrome_mirroring/slaves/macbookair_i5_4250u_intelhd5000/config/gangnam_encoded_v2.config
@@ -0,0 +1,34 @@ +{ + "_deps": ["processor.config"], + "chrome_binary_location": "/Users/gtvchrome/repository/chrome/src/out/Debug/Google Chrome.app/Contents/MacOS/Google Chrome", + "extension_path": "/Users/gtvchrome/repository/extension/extension.crx", + "extra_flags": "--no-proxy-server --start-maximized --whitelisted-extension-id=fmfcbgogabcbclcofgocippekhfcmgfj --disable-web-security --enable-experimental-extension-apis --v=0 --enable-logging=stderr --vmodule=*media/cast/*=3,*chrome/renderer/media/*=3,*=0 --log-level=1", + "high_tab_projection_quality": "ql-high", + "gpu": "on", + "full_screen": "on", + "set_fullscreen_zoom": "off", + "get_log": "true", + "log_file_name": "/Users/gtvchrome/results/sender.json", + "logging": "mirroring", + "enable_webrtc_getstats": "true", + "mirror_duration": "400", + "tracing_duration": "400", + "machine_name": "macbookair_i5_4250u_intelhd5000", + "video_fps": "24", + "video_name": "gangnam_encoded", + "video_resolution": "720p", + "comments": "mirroring v2, video content 720p 24fps, ethernet", + "video_site": "http://172.31.25.18/test_site/index.html?video=gangnam_720p_av_test", + "recorded_video_directory": "/Users/gtvchrome/Movies/Game\\ Capture\\ HD\\ Library/mirroring/", + "capture_software": "/Applications/Game\\ Capture\\ HD.app/Contents/MacOS/Game\\ Capture\\ HD", + "test_type": "video", + "startup_latency": "false", + "network_profile": "", + "cpu_consumption": "true", + "cpu_interval": "1", + "use_sdk": "false", + "quality_test": "all", + "cast_mirroring_version": "2.0", + "cast_streaming_on": "useCastStreaming-on" +} +
diff --git a/lab_system/master/config/kir/tests/chrome_mirroring/slaves/macbookair_i5_4250u_intelhd5000/config/gangnam_encoded_v2_bad_wifi.config b/lab_system/master/config/kir/tests/chrome_mirroring/slaves/macbookair_i5_4250u_intelhd5000/config/gangnam_encoded_v2_bad_wifi.config new file mode 100644 index 0000000..78a62b1 --- /dev/null +++ b/lab_system/master/config/kir/tests/chrome_mirroring/slaves/macbookair_i5_4250u_intelhd5000/config/gangnam_encoded_v2_bad_wifi.config
@@ -0,0 +1,33 @@ +{ + "_deps": ["processor.config", "bad_wifi.config"], + "chrome_binary_location": "/Users/gtvchrome/repository/chrome/src/out/Debug/Google Chrome.app/Contents/MacOS/Google Chrome", + "extension_path": "/Users/gtvchrome/repository/extension/extension.crx", + "extra_flags": "--no-proxy-server --start-maximized --whitelisted-extension-id=fmfcbgogabcbclcofgocippekhfcmgfj --disable-web-security --enable-experimental-extension-apis --v=0 --enable-logging=stderr --vmodule=*media/cast/*=3,*chrome/renderer/media/*=3,*=0 --log-level=1", + "high_tab_projection_quality": "ql-high", + "gpu": "on", + "full_screen": "on", + "set_fullscreen_zoom": "off", + "get_log": "true", + "log_file_name": "/Users/gtvchrome/results/sender.json", + "logging": "mirroring", + "enable_webrtc_getstats": "true", + "mirror_duration": "400", + "tracing_duration": "400", + "machine_name": "macbookair_i5_4250u_intelhd5000", + "video_fps": "24", + "video_name": "gangnam_encoded", + "video_resolution": "720p", + "comments": "mirroring v2, video content 720p 24fps, bad wifi", + "video_site": "http://172.31.25.18/test_site/index.html?video=gangnam_720p_av_test", + "recorded_video_directory": "/Users/gtvchrome/Movies/Game\\ Capture\\ HD\\ Library/mirroring/", + "capture_software": "/Applications/Game\\ Capture\\ HD.app/Contents/MacOS/Game\\ Capture\\ HD", + "test_type": "video", + "startup_latency": "false", + "cpu_consumption": "true", + "cpu_interval": "1", + "use_sdk": "false", + "quality_test": "all", + "cast_mirroring_version": "2.0", + "cast_streaming_on": "useCastStreaming-on" +} +
diff --git a/lab_system/master/config/kir/tests/chrome_mirroring/slaves/macbookair_i5_4250u_intelhd5000/config/processor.config b/lab_system/master/config/kir/tests/chrome_mirroring/slaves/macbookair_i5_4250u_intelhd5000/config/processor.config new file mode 100644 index 0000000..0e8eaf1 --- /dev/null +++ b/lab_system/master/config/kir/tests/chrome_mirroring/slaves/macbookair_i5_4250u_intelhd5000/config/processor.config
@@ -0,0 +1,24 @@ +{ + "root_dir": "/home/gtvchrome", + "results_dir": "results", + "mirror_mp4_file": "Segment_0001.mp4", + "mirror_yuv_file": "mirror.yuv", + "mirror_wav_file": "mirror.wav", + "mirror_stats_file": "mirror_stats.txt", + "mirror_audio_results_file": "audio_results.txt", + "mirror_psnr_ssim_file": "psnr_ssim.txt", + "audio_tools_dir": "audio_quality_tools", + "image_tools_dir": "image_quality_tools", + "reference_dir": "image_quality_tools/sample_videos", + "test_utils_dir": "repository/eureka/test/utilities", + "zxing_dir": "image_quality_tools/zxing/cpp/build", + "barcode_tools_dir": "repository/eureka/test/barcode_tools", + "frame_width": "1280", + "frame_height": "720", + "barcode_height": "32", + "image_extract_interval": "1", + "ffmpeg": "ffmpeg", + "sox": "sox", + "audio_compare_tool": "polqa/PolqaOem64" +} +
diff --git a/lab_system/master/config/kir/tests/chrome_mirroring/slaves/macbookair_i5_4250u_intelhd5000/config/soccer_30fps_encoded_60fps_capture_v2.config b/lab_system/master/config/kir/tests/chrome_mirroring/slaves/macbookair_i5_4250u_intelhd5000/config/soccer_30fps_encoded_60fps_capture_v2.config new file mode 100644 index 0000000..fbf6a62 --- /dev/null +++ b/lab_system/master/config/kir/tests/chrome_mirroring/slaves/macbookair_i5_4250u_intelhd5000/config/soccer_30fps_encoded_60fps_capture_v2.config
@@ -0,0 +1,35 @@ +{ + "_deps": ["processor.config"], + "chrome_binary_location": "/Users/gtvchrome/repository/chrome/src/out/Debug/Google Chrome.app/Contents/MacOS/Google Chrome", + "extension_path": "/Users/gtvchrome/repository/extension/extension.crx", + "extra_flags": "--no-proxy-server --start-maximized --whitelisted-extension-id=fmfcbgogabcbclcofgocippekhfcmgfj --disable-web-security --enable-experimental-extension-apis --v=0 --enable-logging=stderr --vmodule=*media/cast/*=3,*chrome/renderer/media/*=3,*=0 --log-level=1", + "high_tab_projection_quality": "ql-high", + "gpu": "on", + "full_screen": "on", + "set_fullscreen_zoom": "off", + "get_log": "true", + "log_file_name": "/Users/gtvchrome/results/sender.json", + "logging": "mirroring", + "enable_webrtc_getstats": "true", + "mirror_duration": "400", + "tracing_duration": "400", + "machine_name": "macbookair_i5_4250u_intelhd5000", + "video_fps": "30", + "video_name": "soccer_30fps_encoded", + "video_resolution": "720p", + "comments": "mirroring v2, video content 720p 30fps, capture at 60fps, ethernet", + "video_site": "http://172.31.25.18/test_site/index.html?video=soccer_30fps_encoded", + "recorded_video_directory": "/Users/gtvchrome/Movies/Game\\ Capture\\ HD\\ Library/mirroring/", + "capture_software": "/Applications/Game\\ Capture\\ HD.app/Contents/MacOS/Game\\ Capture\\ HD", + "test_type": "video", + "startup_latency": "false", + "network_profile": "", + "cpu_consumption": "true", + "cpu_interval": "1", + "use_sdk": "false", + "quality_test": "all", + "cast_mirroring_version": "2.0", + "cast_streaming_on": "useCastStreaming-on", + "max_frame_rate": "60" +} +
diff --git a/lab_system/master/config/kir/tests/chrome_mirroring/slaves/macbookair_i5_4250u_intelhd5000/config/soccer_30fps_encoded_v2.config b/lab_system/master/config/kir/tests/chrome_mirroring/slaves/macbookair_i5_4250u_intelhd5000/config/soccer_30fps_encoded_v2.config new file mode 100644 index 0000000..775dfc1 --- /dev/null +++ b/lab_system/master/config/kir/tests/chrome_mirroring/slaves/macbookair_i5_4250u_intelhd5000/config/soccer_30fps_encoded_v2.config
@@ -0,0 +1,34 @@ +{ + "_deps": ["processor.config"], + "chrome_binary_location": "/Users/gtvchrome/repository/chrome/src/out/Debug/Google Chrome.app/Contents/MacOS/Google Chrome", + "extension_path": "/Users/gtvchrome/repository/extension/extension.crx", + "extra_flags": "--no-proxy-server --start-maximized --whitelisted-extension-id=fmfcbgogabcbclcofgocippekhfcmgfj --disable-web-security --enable-experimental-extension-apis --v=0 --enable-logging=stderr --vmodule=*media/cast/*=3,*chrome/renderer/media/*=3,*=0 --log-level=1", + "high_tab_projection_quality": "ql-high", + "gpu": "on", + "full_screen": "on", + "set_fullscreen_zoom": "off", + "get_log": "true", + "log_file_name": "/Users/gtvchrome/results/sender.json", + "logging": "mirroring", + "enable_webrtc_getstats": "true", + "mirror_duration": "400", + "tracing_duration": "400", + "machine_name": "macbookair_i5_4250u_intelhd5000", + "video_fps": "30", + "video_name": "soccer_30fps_encoded", + "video_resolution": "720p", + "comments": "mirroring v2, video content 720p 30fps, ethernet", + "video_site": "http://172.31.25.18/test_site/index.html?video=soccer_30fps_encoded", + "recorded_video_directory": "/Users/gtvchrome/Movies/Game\\ Capture\\ HD\\ Library/mirroring/", + "capture_software": "/Applications/Game\\ Capture\\ HD.app/Contents/MacOS/Game\\ Capture\\ HD", + "test_type": "video", + "startup_latency": "false", + "network_profile": "", + "cpu_consumption": "true", + "cpu_interval": "1", + "use_sdk": "false", + "quality_test": "all", + "cast_mirroring_version": "2.0", + "cast_streaming_on": "useCastStreaming-on" +} +
diff --git a/lab_system/master/config/kir/tests/chrome_mirroring/slaves/macbookair_i5_4250u_intelhd5000/config/titanfall_60fps_encoded_v2.config b/lab_system/master/config/kir/tests/chrome_mirroring/slaves/macbookair_i5_4250u_intelhd5000/config/titanfall_60fps_encoded_v2.config new file mode 100644 index 0000000..06fe844 --- /dev/null +++ b/lab_system/master/config/kir/tests/chrome_mirroring/slaves/macbookair_i5_4250u_intelhd5000/config/titanfall_60fps_encoded_v2.config
@@ -0,0 +1,35 @@ +{ + "_deps": ["processor.config"], + "chrome_binary_location": "/Users/gtvchrome/repository/chrome/src/out/Debug/Google Chrome.app/Contents/MacOS/Google Chrome", + "extension_path": "/Users/gtvchrome/repository/extension/extension.crx", + "extra_flags": "--no-proxy-server --start-maximized --whitelisted-extension-id=fmfcbgogabcbclcofgocippekhfcmgfj --disable-web-security --enable-experimental-extension-apis --v=0 --enable-logging=stderr --vmodule=*media/cast/*=3,*chrome/renderer/media/*=3,*=0 --log-level=1", + "high_tab_projection_quality": "ql-high", + "gpu": "on", + "full_screen": "on", + "set_fullscreen_zoom": "off", + "get_log": "true", + "log_file_name": "/Users/gtvchrome/results/sender.json", + "logging": "mirroring", + "enable_webrtc_getstats": "true", + "mirror_duration": "400", + "tracing_duration": "400", + "machine_name": "macbookair_i5_4250u_intelhd5000", + "video_fps": "60", + "video_name": "titanfall_60fps_encoded", + "video_resolution": "720p", + "comments": "mirroring v2, video content 720p 60fps, ethernet", + "video_site": "http://172.31.25.18/test_site/index.html?video=titanfall_60fps_encoded", + "recorded_video_directory": "/Users/gtvchrome/Movies/Game\\ Capture\\ HD\\ Library/mirroring/", + "capture_software": "/Applications/Game\\ Capture\\ HD.app/Contents/MacOS/Game\\ Capture\\ HD", + "test_type": "video", + "startup_latency": "false", + "network_profile": "", + "cpu_consumption": "true", + "cpu_interval": "1", + "use_sdk": "false", + "quality_test": "all", + "cast_mirroring_version": "2.0", + "cast_streaming_on": "useCastStreaming-on", + "max_frame_rate": "60" +} +
diff --git a/lab_system/master/config/kir/tests/chrome_mirroring/slaves/macbookair_i5_4250u_intelhd5000_mtv/config/gangnam_encoded_v2.config b/lab_system/master/config/kir/tests/chrome_mirroring/slaves/macbookair_i5_4250u_intelhd5000_mtv/config/gangnam_encoded_v2.config new file mode 100644 index 0000000..28394de --- /dev/null +++ b/lab_system/master/config/kir/tests/chrome_mirroring/slaves/macbookair_i5_4250u_intelhd5000_mtv/config/gangnam_encoded_v2.config
@@ -0,0 +1,31 @@ +{ + "_deps": ["processor.config"], + "chrome_binary_location": "/Users/gtvchrome/repository/chrome/src/out/Debug/Google Chrome.app/Contents/MacOS/Google Chrome", + "extension_path": "/Users/gtvchrome/repository/extension/extension.crx", + "extra_flags": "--no-proxy-server --start-maximized --whitelisted-extension-id=dliochdbjfkdbacpmhlcpmleaejidimm --disable-web-security --enable-experimental-extension-apis --v=0 --enable-logging=stderr --vmodule=*media/cast/*=3,*chrome/renderer/media/*=3,*=0 --log-level=1", + "gpu": "on", + "full_screen": "on", + "get_log": "true", + "log_file_name": "/Users/gtvchrome/results/sender.json", + "logging": "mirroring", + "enable_webrtc_getstats": "true", + "mirror_duration": "400", + "tracing_duration": "400", + "machine_name": "macbookair_i5_4250u_intelhd5000_mtv", + "video_fps": "24", + "video_name": "gangnam_encoded", + "video_resolution": "720p", + "comments": "mirroring v2, video content 720p 24fps, ethernet", + "video_site": "http://172.17.23.200/perf_test/test_site/index.html?video=gangnam_720p_av_test", + "recorded_video_directory": "/Users/gtvchrome/Movies/Game\\ Capture\\ HD\\ Library/mirroring/", + "capture_software": "/Applications/Game\\ Capture\\ HD.app/Contents/MacOS/Game\\ Capture\\ HD", + "test_type": "video", + "startup_latency": "false", + "network_profile": "", + "cpu_consumption": "true", + "cpu_interval": "1", + "use_sdk": "false", + "quality_test": "all", + "cast_mirroring_version": "2.0", + "cast_streaming_on": "useCastStreaming-on" +}
diff --git a/lab_system/master/config/kir/tests/chrome_mirroring/slaves/macbookair_i5_4250u_intelhd5000_mtv/config/processor.config b/lab_system/master/config/kir/tests/chrome_mirroring/slaves/macbookair_i5_4250u_intelhd5000_mtv/config/processor.config new file mode 100644 index 0000000..0e8eaf1 --- /dev/null +++ b/lab_system/master/config/kir/tests/chrome_mirroring/slaves/macbookair_i5_4250u_intelhd5000_mtv/config/processor.config
@@ -0,0 +1,24 @@ +{ + "root_dir": "/home/gtvchrome", + "results_dir": "results", + "mirror_mp4_file": "Segment_0001.mp4", + "mirror_yuv_file": "mirror.yuv", + "mirror_wav_file": "mirror.wav", + "mirror_stats_file": "mirror_stats.txt", + "mirror_audio_results_file": "audio_results.txt", + "mirror_psnr_ssim_file": "psnr_ssim.txt", + "audio_tools_dir": "audio_quality_tools", + "image_tools_dir": "image_quality_tools", + "reference_dir": "image_quality_tools/sample_videos", + "test_utils_dir": "repository/eureka/test/utilities", + "zxing_dir": "image_quality_tools/zxing/cpp/build", + "barcode_tools_dir": "repository/eureka/test/barcode_tools", + "frame_width": "1280", + "frame_height": "720", + "barcode_height": "32", + "image_extract_interval": "1", + "ffmpeg": "ffmpeg", + "sox": "sox", + "audio_compare_tool": "polqa/PolqaOem64" +} +
diff --git a/lab_system/master/config/kir/tests/chrome_mirroring/slaves/macbookair_i5_4250u_intelhd5000_mtv/config/soccer_30fps_encoded_60fps_capture_v2.config b/lab_system/master/config/kir/tests/chrome_mirroring/slaves/macbookair_i5_4250u_intelhd5000_mtv/config/soccer_30fps_encoded_60fps_capture_v2.config new file mode 100644 index 0000000..6cde31b --- /dev/null +++ b/lab_system/master/config/kir/tests/chrome_mirroring/slaves/macbookair_i5_4250u_intelhd5000_mtv/config/soccer_30fps_encoded_60fps_capture_v2.config
@@ -0,0 +1,32 @@ +{ + "_deps": ["processor.config"], + "chrome_binary_location": "/Users/gtvchrome/repository/chrome/src/out/Debug/Google Chrome.app/Contents/MacOS/Google Chrome", + "extension_path": "/Users/gtvchrome/repository/extension/extension.crx", + "extra_flags": "--no-proxy-server --start-maximized --whitelisted-extension-id=dliochdbjfkdbacpmhlcpmleaejidimm --disable-web-security --enable-experimental-extension-apis --v=0 --enable-logging=stderr --vmodule=*media/cast/*=3,*chrome/renderer/media/*=3,*=0 --log-level=1", + "gpu": "on", + "full_screen": "on", + "get_log": "true", + "log_file_name": "/Users/gtvchrome/results/sender.json", + "logging": "mirroring", + "enable_webrtc_getstats": "true", + "mirror_duration": "400", + "tracing_duration": "400", + "machine_name": "macbookair_i5_4250u_intelhd5000_mtv", + "video_fps": "30", + "video_name": "soccer_30fps_encoded", + "video_resolution": "720p", + "comments": "mirroring v2, video content 720p 30fps, capture at 60fps, ethernet", + "video_site": "http://172.17.23.200/perf_test/test_site/index.html?video=soccer_30fps_encoded", + "recorded_video_directory": "/Users/gtvchrome/Movies/Game\\ Capture\\ HD\\ Library/mirroring/", + "capture_software": "/Applications/Game\\ Capture\\ HD.app/Contents/MacOS/Game\\ Capture\\ HD", + "test_type": "video", + "startup_latency": "false", + "network_profile": "", + "cpu_consumption": "true", + "cpu_interval": "1", + "use_sdk": "false", + "quality_test": "audio", + "cast_mirroring_version": "2.0", + "cast_streaming_on": "useCastStreaming-on", + "max_frame_rate": "60" +}
diff --git a/lab_system/master/config/kir/tests/chrome_mirroring/slaves/macbookair_i5_4250u_intelhd5000_mtv/config/soccer_30fps_encoded_v2.config b/lab_system/master/config/kir/tests/chrome_mirroring/slaves/macbookair_i5_4250u_intelhd5000_mtv/config/soccer_30fps_encoded_v2.config new file mode 100644 index 0000000..b082265 --- /dev/null +++ b/lab_system/master/config/kir/tests/chrome_mirroring/slaves/macbookair_i5_4250u_intelhd5000_mtv/config/soccer_30fps_encoded_v2.config
@@ -0,0 +1,31 @@ +{ + "_deps": ["processor.config"], + "chrome_binary_location": "/Users/gtvchrome/repository/chrome/src/out/Debug/Google Chrome.app/Contents/MacOS/Google Chrome", + "extension_path": "/Users/gtvchrome/repository/extension/extension.crx", + "extra_flags": "--no-proxy-server --start-maximized --whitelisted-extension-id=dliochdbjfkdbacpmhlcpmleaejidimm --disable-web-security --enable-experimental-extension-apis --v=0 --enable-logging=stderr --vmodule=*media/cast/*=3,*chrome/renderer/media/*=3,*=0 --log-level=1", + "gpu": "on", + "full_screen": "on", + "get_log": "true", + "log_file_name": "/Users/gtvchrome/results/sender.json", + "logging": "mirroring", + "enable_webrtc_getstats": "true", + "mirror_duration": "400", + "tracing_duration": "400", + "machine_name": "macbookair_i5_4250u_intelhd5000_mtv", + "video_fps": "30", + "video_name": "soccer_30fps_encoded", + "video_resolution": "720p", + "comments": "mirroring v2, video content 720p 30fps, ethernet", + "video_site": "http://172.17.23.200/perf_test/test_site/index.html?video=soccer_30fps_encoded", + "recorded_video_directory": "/Users/gtvchrome/Movies/Game\\ Capture\\ HD\\ Library/mirroring/", + "capture_software": "/Applications/Game\\ Capture\\ HD.app/Contents/MacOS/Game\\ Capture\\ HD", + "test_type": "video", + "startup_latency": "false", + "network_profile": "", + "cpu_consumption": "true", + "cpu_interval": "1", + "use_sdk": "false", + "quality_test": "audio", + "cast_mirroring_version": "2.0", + "cast_streaming_on": "useCastStreaming-on" +}
diff --git a/lab_system/master/config/kir/tests/chrome_mirroring/slaves/macbookair_i5_4250u_intelhd5000_mtv/config/titanfall_60fps_encoded_v2.config b/lab_system/master/config/kir/tests/chrome_mirroring/slaves/macbookair_i5_4250u_intelhd5000_mtv/config/titanfall_60fps_encoded_v2.config new file mode 100644 index 0000000..821fa4b --- /dev/null +++ b/lab_system/master/config/kir/tests/chrome_mirroring/slaves/macbookair_i5_4250u_intelhd5000_mtv/config/titanfall_60fps_encoded_v2.config
@@ -0,0 +1,32 @@ +{ + "_deps": ["processor.config"], + "chrome_binary_location": "/Users/gtvchrome/repository/chrome/src/out/Debug/Google Chrome.app/Contents/MacOS/Google Chrome", + "extension_path": "/Users/gtvchrome/repository/extension/extension.crx", + "extra_flags": "--no-proxy-server --start-maximized --whitelisted-extension-id=dliochdbjfkdbacpmhlcpmleaejidimm --disable-web-security --enable-experimental-extension-apis --v=0 --enable-logging=stderr --vmodule=*media/cast/*=3,*chrome/renderer/media/*=3,*=0 --log-level=1", + "gpu": "on", + "full_screen": "on", + "get_log": "true", + "log_file_name": "/Users/gtvchrome/results/sender.json", + "logging": "mirroring", + "enable_webrtc_getstats": "true", + "mirror_duration": "400", + "tracing_duration": "400", + "machine_name": "macbookair_i5_4250u_intelhd5000_mtv", + "video_fps": "60", + "video_name": "titanfall_60fps_encoded", + "video_resolution": "720p", + "comments": "mirroring v2, video content 720p 60fps, ethernet", + "video_site": "http://172.31.25.18/test_site/index.html?video=titanfall_60fps_encoded", + "recorded_video_directory": "/Users/gtvchrome/Movies/Game\\ Capture\\ HD\\ Library/mirroring/", + "capture_software": "/Applications/Game\\ Capture\\ HD.app/Contents/MacOS/Game\\ Capture\\ HD", + "test_type": "video", + "startup_latency": "false", + "network_profile": "", + "cpu_consumption": "true", + "cpu_interval": "1", + "use_sdk": "false", + "quality_test": "audio", + "cast_mirroring_version": "2.0", + "cast_streaming_on": "useCastStreaming-on", + "max_frame_rate": "60" +}
diff --git a/lab_system/master/config/kir/tests/chrome_mirroring/slaves/macbookpro_i7_2675qm_radeon6750m/config/bad_wifi.config b/lab_system/master/config/kir/tests/chrome_mirroring/slaves/macbookpro_i7_2675qm_radeon6750m/config/bad_wifi.config new file mode 100644 index 0000000..5d576b1 --- /dev/null +++ b/lab_system/master/config/kir/tests/chrome_mirroring/slaves/macbookpro_i7_2675qm_radeon6750m/config/bad_wifi.config
@@ -0,0 +1,4 @@ +{ + "udp_proxy_server": "http://172.31.25.18:8888", + "network_profile": "bad" +} \ No newline at end of file
diff --git a/lab_system/master/config/kir/tests/chrome_mirroring/slaves/macbookpro_i7_2675qm_radeon6750m/config/bunny_480p_desktop_mirror.config b/lab_system/master/config/kir/tests/chrome_mirroring/slaves/macbookpro_i7_2675qm_radeon6750m/config/bunny_480p_desktop_mirror.config new file mode 100644 index 0000000..204a2a4 --- /dev/null +++ b/lab_system/master/config/kir/tests/chrome_mirroring/slaves/macbookpro_i7_2675qm_radeon6750m/config/bunny_480p_desktop_mirror.config
@@ -0,0 +1,30 @@ +{ + "add_debug_dongle_ip": "172.31.25.8", + "chrome_binary_location": "/Users/gtvchrome/repository/chrome/src/out/Debug/Google Chrome.app/Contents/MacOS/Google Chrome", + "cpu_consumption": "true", + "cpu_interval": "1", + "resolution_1280_720": "1280x720", + "device_ip": "172.31.25.8", + "enable_webrtc_getstats": "true", + "extension_path": "/Users/gtvchrome/repository/extension/extension.crx", + "extra_flags": "--no-proxy-server --start-maximized --whitelisted-extension-id=hfaagokkkhdbgiakmmlclaapfelnkoah --disable-web-security --enable-experimental-extension-apis --enable-usermedia-screen-capturing --enable-logging --v=1 --vmodule=*libjingle/source_internal/talk/*=4,*=0", + "full_screen": "on", + "get_log": "true", + "gpu": "on", + "log_file_name": "/Users/gtvchrome/results/sender.json", + "logging": "mirroring", + "machine_name": "macbookpro_i7_2675qm_radeon6750m", + "mirror_duration": "560", + "network_profile": "", + "set_fullscreen_zoom": "on", + "ssh_private_key": "/Users/gtvchrome/.ssh/id_rsa", + "startup_latency": "false", + "test_type": "video", + "tracing_duration": "560", + "video_fps": "24fps", + "video_name": "bunny_video_24fps_480p_default_desktop_mirroring", + "video_resolution": "480p", + "comments": "Buffered mode, NACK on", + "video_site": "http://172.31.25.18/test_site/index.html?video=bunny_480p", + "desktop_capture": "true" +}
diff --git a/lab_system/master/config/kir/tests/chrome_mirroring/slaves/macbookpro_i7_2675qm_radeon6750m/config/gangnam_encoded.config b/lab_system/master/config/kir/tests/chrome_mirroring/slaves/macbookpro_i7_2675qm_radeon6750m/config/gangnam_encoded.config new file mode 100644 index 0000000..eeedcb5 --- /dev/null +++ b/lab_system/master/config/kir/tests/chrome_mirroring/slaves/macbookpro_i7_2675qm_radeon6750m/config/gangnam_encoded.config
@@ -0,0 +1,33 @@ +{ + "_deps": ["processor.config"], + "chrome_binary_location": "/Users/gtvchrome/repository/chrome/src/out/Debug/Google Chrome.app/Contents/MacOS/Google Chrome", + "extension_path": "/Users/gtvchrome/repository/extension/extension.crx", + "extra_flags": "--no-proxy-server --start-maximized --whitelisted-extension-id=fmfcbgogabcbclcofgocippekhfcmgfj --disable-web-security --enable-experimental-extension-apis --enable-logging --v=1 --vmodule=*libjingle/source_internal/talk/*=4,*=0", + "high_tab_projection_quality": "ql-high", + "gpu": "on", + "full_screen": "on", + "set_fullscreen_zoom": "off", + "get_log": "true", + "log_file_name": "/Users/gtvchrome/results/sender.json", + "logging": "mirroring", + "enable_webrtc_getstats": "true", + "mirror_duration": "400", + "tracing_duration": "400", + "machine_name": "macbookpro_i7_2675qm_radeon6750m", + "video_fps": "24", + "video_name": "gangnam_encoded", + "video_resolution": "720p", + "comments": "mirroring v1, video content 720p 24fps, ethernet", + "video_site": "http://172.31.25.18/test_site/index.html?video=gangnam_720p_av_test", + "recorded_video_directory": "/Users/gtvchrome/Movies/Game\\ Capture\\ HD\\ Library/mirroring/", + "capture_software": "/Applications/Game\\ Capture\\ HD.app/Contents/MacOS/Game\\ Capture\\ HD", + "test_type": "video", + "startup_latency": "false", + "network_profile": "", + "cpu_consumption": "true", + "cpu_interval": "1", + "use_sdk": "false", + "quality_test": "all", + "cast_mirroring_version": "1.0", + "cast_streaming_off": "useCastStreaming-off" +}
diff --git a/lab_system/master/config/kir/tests/chrome_mirroring/slaves/macbookpro_i7_2675qm_radeon6750m/config/gangnam_encoded_v2.config b/lab_system/master/config/kir/tests/chrome_mirroring/slaves/macbookpro_i7_2675qm_radeon6750m/config/gangnam_encoded_v2.config new file mode 100644 index 0000000..99e880b --- /dev/null +++ b/lab_system/master/config/kir/tests/chrome_mirroring/slaves/macbookpro_i7_2675qm_radeon6750m/config/gangnam_encoded_v2.config
@@ -0,0 +1,34 @@ +{ + "_deps": ["processor.config"], + "chrome_binary_location": "/Users/gtvchrome/repository/chrome/src/out/Debug/Google Chrome.app/Contents/MacOS/Google Chrome", + "extension_path": "/Users/gtvchrome/repository/extension/extension.crx", + "extra_flags": "--no-proxy-server --start-maximized --whitelisted-extension-id=fmfcbgogabcbclcofgocippekhfcmgfj --disable-web-security --enable-experimental-extension-apis --v=0 --enable-logging=stderr --vmodule=*media/cast/*=3,*chrome/renderer/media/*=3,*=0 --log-level=1", + "high_tab_projection_quality": "ql-high", + "gpu": "on", + "full_screen": "on", + "set_fullscreen_zoom": "off", + "get_log": "true", + "log_file_name": "/Users/gtvchrome/results/sender.json", + "logging": "mirroring", + "enable_webrtc_getstats": "true", + "mirror_duration": "400", + "tracing_duration": "400", + "machine_name": "macbookpro_i7_2675qm_radeon6750m", + "video_fps": "24", + "video_name": "gangnam_encoded", + "video_resolution": "720p", + "comments": "mirroring v2, video content 720p 24fps, ethernet", + "video_site": "http://172.31.25.18/test_site/index.html?video=gangnam_720p_av_test", + "recorded_video_directory": "/Users/gtvchrome/Movies/Game\\ Capture\\ HD\\ Library/mirroring/", + "capture_software": "/Applications/Game\\ Capture\\ HD.app/Contents/MacOS/Game\\ Capture\\ HD", + "test_type": "video", + "startup_latency": "false", + "network_profile": "", + "cpu_consumption": "true", + "cpu_interval": "1", + "use_sdk": "false", + "quality_test": "all", + "cast_mirroring_version": "2.0", + "cast_streaming_on": "useCastStreaming-on" +} +
diff --git a/lab_system/master/config/kir/tests/chrome_mirroring/slaves/macbookpro_i7_2675qm_radeon6750m/config/gangnam_encoded_v2_bad_wifi.config b/lab_system/master/config/kir/tests/chrome_mirroring/slaves/macbookpro_i7_2675qm_radeon6750m/config/gangnam_encoded_v2_bad_wifi.config new file mode 100644 index 0000000..949a234 --- /dev/null +++ b/lab_system/master/config/kir/tests/chrome_mirroring/slaves/macbookpro_i7_2675qm_radeon6750m/config/gangnam_encoded_v2_bad_wifi.config
@@ -0,0 +1,33 @@ +{ + "_deps": ["processor.config", "bad_wifi.config"], + "chrome_binary_location": "/Users/gtvchrome/repository/chrome/src/out/Debug/Google Chrome.app/Contents/MacOS/Google Chrome", + "extension_path": "/Users/gtvchrome/repository/extension/extension.crx", + "extra_flags": "--no-proxy-server --start-maximized --whitelisted-extension-id=fmfcbgogabcbclcofgocippekhfcmgfj --disable-web-security --enable-experimental-extension-apis --v=0 --enable-logging=stderr --vmodule=*media/cast/*=3,*chrome/renderer/media/*=3,*=0 --log-level=1", + "high_tab_projection_quality": "ql-high", + "gpu": "on", + "full_screen": "on", + "set_fullscreen_zoom": "off", + "get_log": "true", + "log_file_name": "/Users/gtvchrome/results/sender.json", + "logging": "mirroring", + "enable_webrtc_getstats": "true", + "mirror_duration": "400", + "tracing_duration": "400", + "machine_name": "macbookpro_i7_2675qm_radeon6750m", + "video_fps": "24", + "video_name": "gangnam_encoded", + "video_resolution": "720p", + "comments": "mirroring v2, video content 720p 24fps, bad wifi", + "video_site": "http://172.31.25.18/test_site/index.html?video=gangnam_720p_av_test", + "recorded_video_directory": "/Users/gtvchrome/Movies/Game\\ Capture\\ HD\\ Library/mirroring/", + "capture_software": "/Applications/Game\\ Capture\\ HD.app/Contents/MacOS/Game\\ Capture\\ HD", + "test_type": "video", + "startup_latency": "false", + "cpu_consumption": "true", + "cpu_interval": "1", + "use_sdk": "false", + "quality_test": "all", + "cast_mirroring_version": "2.0", + "cast_streaming_on": "useCastStreaming-on" +} +
diff --git a/lab_system/master/config/kir/tests/chrome_mirroring/slaves/macbookpro_i7_2675qm_radeon6750m/config/processor.config b/lab_system/master/config/kir/tests/chrome_mirroring/slaves/macbookpro_i7_2675qm_radeon6750m/config/processor.config new file mode 100644 index 0000000..0e8eaf1 --- /dev/null +++ b/lab_system/master/config/kir/tests/chrome_mirroring/slaves/macbookpro_i7_2675qm_radeon6750m/config/processor.config
@@ -0,0 +1,24 @@ +{ + "root_dir": "/home/gtvchrome", + "results_dir": "results", + "mirror_mp4_file": "Segment_0001.mp4", + "mirror_yuv_file": "mirror.yuv", + "mirror_wav_file": "mirror.wav", + "mirror_stats_file": "mirror_stats.txt", + "mirror_audio_results_file": "audio_results.txt", + "mirror_psnr_ssim_file": "psnr_ssim.txt", + "audio_tools_dir": "audio_quality_tools", + "image_tools_dir": "image_quality_tools", + "reference_dir": "image_quality_tools/sample_videos", + "test_utils_dir": "repository/eureka/test/utilities", + "zxing_dir": "image_quality_tools/zxing/cpp/build", + "barcode_tools_dir": "repository/eureka/test/barcode_tools", + "frame_width": "1280", + "frame_height": "720", + "barcode_height": "32", + "image_extract_interval": "1", + "ffmpeg": "ffmpeg", + "sox": "sox", + "audio_compare_tool": "polqa/PolqaOem64" +} +
diff --git a/lab_system/master/config/kir/tests/chrome_mirroring/slaves/macbookpro_i7_2675qm_radeon6750m/config/soccer_30fps_encoded_60fps_capture_v2.config b/lab_system/master/config/kir/tests/chrome_mirroring/slaves/macbookpro_i7_2675qm_radeon6750m/config/soccer_30fps_encoded_60fps_capture_v2.config new file mode 100644 index 0000000..70dc55a --- /dev/null +++ b/lab_system/master/config/kir/tests/chrome_mirroring/slaves/macbookpro_i7_2675qm_radeon6750m/config/soccer_30fps_encoded_60fps_capture_v2.config
@@ -0,0 +1,35 @@ +{ + "_deps": ["processor.config"], + "chrome_binary_location": "/Users/gtvchrome/repository/chrome/src/out/Debug/Google Chrome.app/Contents/MacOS/Google Chrome", + "extension_path": "/Users/gtvchrome/repository/extension/extension.crx", + "extra_flags": "--no-proxy-server --start-maximized --whitelisted-extension-id=fmfcbgogabcbclcofgocippekhfcmgfj --disable-web-security --enable-experimental-extension-apis --v=0 --enable-logging=stderr --vmodule=*media/cast/*=3,*chrome/renderer/media/*=3,*=0 --log-level=1", + "high_tab_projection_quality": "ql-high", + "gpu": "on", + "full_screen": "on", + "set_fullscreen_zoom": "off", + "get_log": "true", + "log_file_name": "/Users/gtvchrome/results/sender.json", + "logging": "mirroring", + "enable_webrtc_getstats": "true", + "mirror_duration": "400", + "tracing_duration": "400", + "machine_name": "macbookpro_i7_2675qm_radeon6750m", + "video_fps": "30", + "video_name": "soccer_30fps_encoded", + "video_resolution": "720p", + "comments": "mirroring v2, video content 720p 30fps, capture at 60fps, ethernet", + "video_site": "http://172.31.25.18/test_site/index.html?video=soccer_30fps_encoded", + "recorded_video_directory": "/Users/gtvchrome/Movies/Game\\ Capture\\ HD\\ Library/mirroring/", + "capture_software": "/Applications/Game\\ Capture\\ HD.app/Contents/MacOS/Game\\ Capture\\ HD", + "test_type": "video", + "startup_latency": "false", + "network_profile": "", + "cpu_consumption": "true", + "cpu_interval": "1", + "use_sdk": "false", + "quality_test": "all", + "cast_mirroring_version": "2.0", + "cast_streaming_on": "useCastStreaming-on", + "max_frame_rate": "60" +} +
diff --git a/lab_system/master/config/kir/tests/chrome_mirroring/slaves/macbookpro_i7_2675qm_radeon6750m/config/soccer_30fps_encoded_v2.config b/lab_system/master/config/kir/tests/chrome_mirroring/slaves/macbookpro_i7_2675qm_radeon6750m/config/soccer_30fps_encoded_v2.config new file mode 100644 index 0000000..11d9535 --- /dev/null +++ b/lab_system/master/config/kir/tests/chrome_mirroring/slaves/macbookpro_i7_2675qm_radeon6750m/config/soccer_30fps_encoded_v2.config
@@ -0,0 +1,34 @@ +{ + "_deps": ["processor.config"], + "chrome_binary_location": "/Users/gtvchrome/repository/chrome/src/out/Debug/Google Chrome.app/Contents/MacOS/Google Chrome", + "extension_path": "/Users/gtvchrome/repository/extension/extension.crx", + "extra_flags": "--no-proxy-server --start-maximized --whitelisted-extension-id=fmfcbgogabcbclcofgocippekhfcmgfj --disable-web-security --enable-experimental-extension-apis --v=0 --enable-logging=stderr --vmodule=*media/cast/*=3,*chrome/renderer/media/*=3,*=0 --log-level=1", + "high_tab_projection_quality": "ql-high", + "gpu": "on", + "full_screen": "on", + "set_fullscreen_zoom": "off", + "get_log": "true", + "log_file_name": "/Users/gtvchrome/results/sender.json", + "logging": "mirroring", + "enable_webrtc_getstats": "true", + "mirror_duration": "400", + "tracing_duration": "400", + "machine_name": "macbookpro_i7_2675qm_radeon6750m", + "video_fps": "30", + "video_name": "soccer_30fps_encoded", + "video_resolution": "720p", + "comments": "mirroring v2, video content 720p 30fps, ethernet", + "video_site": "http://172.31.25.18/test_site/index.html?video=soccer_30fps_encoded", + "recorded_video_directory": "/Users/gtvchrome/Movies/Game\\ Capture\\ HD\\ Library/mirroring/", + "capture_software": "/Applications/Game\\ Capture\\ HD.app/Contents/MacOS/Game\\ Capture\\ HD", + "test_type": "video", + "startup_latency": "false", + "network_profile": "", + "cpu_consumption": "true", + "cpu_interval": "1", + "use_sdk": "false", + "quality_test": "all", + "cast_mirroring_version": "2.0", + "cast_streaming_on": "useCastStreaming-on" +} +
diff --git a/lab_system/master/config/kir/tests/chrome_mirroring/slaves/macbookpro_i7_2675qm_radeon6750m/config/titanfall_60fps_encoded_v2.config b/lab_system/master/config/kir/tests/chrome_mirroring/slaves/macbookpro_i7_2675qm_radeon6750m/config/titanfall_60fps_encoded_v2.config new file mode 100644 index 0000000..3f9e04e --- /dev/null +++ b/lab_system/master/config/kir/tests/chrome_mirroring/slaves/macbookpro_i7_2675qm_radeon6750m/config/titanfall_60fps_encoded_v2.config
@@ -0,0 +1,35 @@ +{ + "_deps": ["processor.config"], + "chrome_binary_location": "/Users/gtvchrome/repository/chrome/src/out/Debug/Google Chrome.app/Contents/MacOS/Google Chrome", + "extension_path": "/Users/gtvchrome/repository/extension/extension.crx", + "extra_flags": "--no-proxy-server --start-maximized --whitelisted-extension-id=fmfcbgogabcbclcofgocippekhfcmgfj --disable-web-security --enable-experimental-extension-apis --v=0 --enable-logging=stderr --vmodule=*media/cast/*=3,*chrome/renderer/media/*=3,*=0 --log-level=1", + "high_tab_projection_quality": "ql-high", + "gpu": "on", + "full_screen": "on", + "set_fullscreen_zoom": "off", + "get_log": "true", + "log_file_name": "/Users/gtvchrome/results/sender.json", + "logging": "mirroring", + "enable_webrtc_getstats": "true", + "mirror_duration": "400", + "tracing_duration": "400", + "machine_name": "macbookpro_i7_2675qm_radeon6750m", + "video_fps": "60", + "video_name": "titanfall_60fps_encoded", + "video_resolution": "720p", + "comments": "mirroring v2, video content 720p 60fps, ethernet", + "video_site": "http://172.31.25.18/test_site/index.html?video=titanfall_60fps_encoded", + "recorded_video_directory": "/Users/gtvchrome/Movies/Game\\ Capture\\ HD\\ Library/mirroring/", + "capture_software": "/Applications/Game\\ Capture\\ HD.app/Contents/MacOS/Game\\ Capture\\ HD", + "test_type": "video", + "startup_latency": "false", + "network_profile": "", + "cpu_consumption": "true", + "cpu_interval": "1", + "use_sdk": "false", + "quality_test": "all", + "cast_mirroring_version": "2.0", + "cast_streaming_on": "useCastStreaming-on", + "max_frame_rate": "60" +} +
diff --git a/lab_system/master/config/kir/tests/chrome_mirroring/slaves/samsung_i7_3630qm_radeon7730m_win8/config/bad_wifi.config b/lab_system/master/config/kir/tests/chrome_mirroring/slaves/samsung_i7_3630qm_radeon7730m_win8/config/bad_wifi.config new file mode 100644 index 0000000..a7bd44e --- /dev/null +++ b/lab_system/master/config/kir/tests/chrome_mirroring/slaves/samsung_i7_3630qm_radeon7730m_win8/config/bad_wifi.config
@@ -0,0 +1,4 @@ +{ + "udp_proxy_server": "http://172.31.25.18:8888", + "network_profile": "bad" +}
diff --git a/lab_system/master/config/kir/tests/chrome_mirroring/slaves/samsung_i7_3630qm_radeon7730m_win8/config/bunny_480p_desktop_mirror.config b/lab_system/master/config/kir/tests/chrome_mirroring/slaves/samsung_i7_3630qm_radeon7730m_win8/config/bunny_480p_desktop_mirror.config new file mode 100644 index 0000000..f65cfe0 --- /dev/null +++ b/lab_system/master/config/kir/tests/chrome_mirroring/slaves/samsung_i7_3630qm_radeon7730m_win8/config/bunny_480p_desktop_mirror.config
@@ -0,0 +1,29 @@ +{ + "add_debug_dongle_ip": "172.31.25.10", + "chrome_binary_location": "C:\\Users\\gtvchrome\\repository\\chrome\\src\\out\\Debug\\chrome.exe", + "cpu_consumption": "true", + "cpu_interval": "1", + "resolution_1280_720": "1280x720", + "device_ip": "172.31.25.10", + "enable_webrtc_getstats": "true", + "extension_path": "C:\\Users\\gtvchrome\\repository\\extension\\extension.crx", + "extra_flags": "--no-proxy-server --start-maximized --whitelisted-extension-id=hfaagokkkhdbgiakmmlclaapfelnkoah --disable-web-security --enable-experimental-extension-apis --enable-usermedia-screen-capturing --enable-logging --v=1 --vmodule=*source*/talk/*=3", + "full_screen": "on", + "get_log": "true", + "gpu": "on", + "log_file_name": "C:\\Users\\gtvchrome\\results\\sender.json", + "logging": "mirroring", + "machine_name": "samsung_i7_3630qm_radeon7730m_win8", + "mirror_duration": "560", + "network_profile": "", + "set_fullscreen_zoom": "on", + "startup_latency": "false", + "test_type": "video", + "tracing_duration": "560", + "video_fps": "24fps", + "video_name": "bunny_video_24fps_480p_default_desktop_mirroring", + "video_resolution": "480p", + "comments": "Buffered mode, NACK on", + "video_site": "http://172.31.25.18/test_site/index.html?video=bunny_480p", + "desktop_capture": "true" +}
diff --git a/lab_system/master/config/kir/tests/chrome_mirroring/slaves/samsung_i7_3630qm_radeon7730m_win8/config/gangnam_encoded.config b/lab_system/master/config/kir/tests/chrome_mirroring/slaves/samsung_i7_3630qm_radeon7730m_win8/config/gangnam_encoded.config new file mode 100644 index 0000000..67dd618 --- /dev/null +++ b/lab_system/master/config/kir/tests/chrome_mirroring/slaves/samsung_i7_3630qm_radeon7730m_win8/config/gangnam_encoded.config
@@ -0,0 +1,33 @@ +{ + "_deps": ["processor.config"], + "chrome_binary_location": "C:\\Users\\gtvchrome\\repository\\chrome\\src\\out\\Debug\\chrome.exe", + "extension_path": "C:\\Users\\gtvchrome\\repository\\extension\\extension.crx", + "extra_flags": "--no-proxy-server --start-maximized --whitelisted-extension-id=fmfcbgogabcbclcofgocippekhfcmgfj --disable-web-security --enable-experimental-extension-apis --enable-logging --v=1 --vmodule=*libjingle/source_internal/talk/*=4,*=0", + "high_tab_projection_quality": "ql-high", + "gpu": "on", + "full_screen": "on", + "set_fullscreen_zoom": "off", + "get_log": "true", + "log_file_name": "C:\\Users\\gtvchrome\\results\\sender.json", + "logging": "mirroring", + "enable_webrtc_getstats": "true", + "mirror_duration": "400", + "tracing_duration": "400", + "machine_name": "samsung_i7_3630qm_radeon7730m_win8", + "video_fps": "24", + "video_name": "gangnam_encoded", + "video_resolution": "720p", + "comments": "mirroring v1, video content 720p 24fps, ethernet", + "video_site": "http://172.31.25.18/test_site/index.html?video=gangnam_720p_av_test", + "recorded_video_directory": "/Users/gtvchrome/Movies/Game\\ Capture\\ HD\\ Library/mirroring/", + "capture_software": "/Applications/Game\\ Capture\\ HD.app/Contents/MacOS/Game\\ Capture\\ HD", + "test_type": "video", + "startup_latency": "false", + "network_profile": "", + "cpu_consumption": "true", + "cpu_interval": "1", + "use_sdk": "false", + "quality_test": "all", + "cast_mirroring_version": "1.0", + "cast_streaming_off": "useCastStreaming-off" +}
diff --git a/lab_system/master/config/kir/tests/chrome_mirroring/slaves/samsung_i7_3630qm_radeon7730m_win8/config/gangnam_encoded_v2.config b/lab_system/master/config/kir/tests/chrome_mirroring/slaves/samsung_i7_3630qm_radeon7730m_win8/config/gangnam_encoded_v2.config new file mode 100644 index 0000000..ca64170 --- /dev/null +++ b/lab_system/master/config/kir/tests/chrome_mirroring/slaves/samsung_i7_3630qm_radeon7730m_win8/config/gangnam_encoded_v2.config
@@ -0,0 +1,34 @@ +{ + "_deps": ["processor.config", "../../common/common_win.cfg"], + "chrome_binary_location": "C:\\Users\\gtvchrome\\repository\\chrome\\src\\out\\Debug\\chrome.exe", + "extension_path": "C:\\Users\\gtvchrome\\repository\\extension", + "extra_flags": "--no-proxy-server --start-maximized --whitelisted-extension-id=enhhojjnijigcajfphajepfemndkmdlo --disable-web-security --enable-experimental-extension-apis --v=0 --enable-logging --vmodule=*media/cast/*=3,*chrome/renderer/media/*=3,*=0", + "high_tab_projection_quality": "ql-high", + "gpu": "on", + "full_screen": "on", + "set_fullscreen_zoom": "off", + "get_log": "true", + "log_file_name": "C:\\Users\\gtvchrome\\results\\sender.json", + "logging": "mirroring", + "enable_webrtc_getstats": "true", + "mirror_duration": "400", + "tracing_duration": "400", + "machine_name": "samsung_i7_3630qm_radeon7730m_win8", + "video_fps": "24", + "video_name": "gangnam_encoded", + "video_resolution": "720p", + "comments": "mirroring v2, video content 720p 24fps, ethernet", + "video_site": "http://172.31.25.18/test_site/index.html?video=gangnam_720p_av_test", + "recorded_video_directory": "/Users/gtvchrome/Movies/Game\\ Capture\\ HD\\ Library/mirroring/", + "capture_software": "/Applications/Game\\ Capture\\ HD.app/Contents/MacOS/Game\\ Capture\\ HD", + "test_type": "video", + "startup_latency": "false", + "network_profile": "", + "cpu_consumption": "true", + "cpu_interval": "1", + "use_sdk": "false", + "quality_test": "all", + "cast_mirroring_version": "2.0", + "cast_streaming_on": "useCastStreaming-on" +} +
diff --git a/lab_system/master/config/kir/tests/chrome_mirroring/slaves/samsung_i7_3630qm_radeon7730m_win8/config/gangnam_encoded_v2_bad_wifi.config b/lab_system/master/config/kir/tests/chrome_mirroring/slaves/samsung_i7_3630qm_radeon7730m_win8/config/gangnam_encoded_v2_bad_wifi.config new file mode 100644 index 0000000..10a3d00 --- /dev/null +++ b/lab_system/master/config/kir/tests/chrome_mirroring/slaves/samsung_i7_3630qm_radeon7730m_win8/config/gangnam_encoded_v2_bad_wifi.config
@@ -0,0 +1,33 @@ +{ + "_deps": ["processor.config", "bad_wifi.config"], + "chrome_binary_location": "C:\\Users\\gtvchrome\\repository\\chrome\\src\\out\\Debug\\chrome.exe", + "extension_path": "C:\\Users\\gtvchrome\\repository\\extension", + "extra_flags": "--no-proxy-server --start-maximized --whitelisted-extension-id=enhhojjnijigcajfphajepfemndkmdlo --disable-web-security --enable-experimental-extension-apis --v=1 --enable-logging --vmodule=*media/cast/*=3,*chrome/renderer/media/*=3,*=0", + "high_tab_projection_quality": "ql-high", + "gpu": "on", + "full_screen": "on", + "set_fullscreen_zoom": "off", + "get_log": "true", + "log_file_name": "C:\\Users\\gtvchrome\\results\\sender.json", + "logging": "mirroring", + "enable_webrtc_getstats": "true", + "mirror_duration": "400", + "tracing_duration": "400", + "machine_name": "samsung_i7_3630qm_radeon7730m_win8", + "video_fps": "24", + "video_name": "gangnam_encoded", + "video_resolution": "720p", + "comments": "mirroring v2, video content 720p 24fps, bad wifi", + "video_site": "http://172.31.25.18/test_site/index.html?video=gangnam_720p_av_test", + "recorded_video_directory": "/Users/gtvchrome/Movies/Game\\ Capture\\ HD\\ Library/mirroring/", + "capture_software": "/Applications/Game\\ Capture\\ HD.app/Contents/MacOS/Game\\ Capture\\ HD", + "test_type": "video", + "startup_latency": "false", + "cpu_consumption": "true", + "cpu_interval": "1", + "use_sdk": "false", + "quality_test": "all", + "cast_mirroring_version": "2.0", + "cast_streaming_on": "useCastStreaming-on" +} +
diff --git a/lab_system/master/config/kir/tests/chrome_mirroring/slaves/samsung_i7_3630qm_radeon7730m_win8/config/processor.config b/lab_system/master/config/kir/tests/chrome_mirroring/slaves/samsung_i7_3630qm_radeon7730m_win8/config/processor.config new file mode 100644 index 0000000..0e8eaf1 --- /dev/null +++ b/lab_system/master/config/kir/tests/chrome_mirroring/slaves/samsung_i7_3630qm_radeon7730m_win8/config/processor.config
@@ -0,0 +1,24 @@ +{ + "root_dir": "/home/gtvchrome", + "results_dir": "results", + "mirror_mp4_file": "Segment_0001.mp4", + "mirror_yuv_file": "mirror.yuv", + "mirror_wav_file": "mirror.wav", + "mirror_stats_file": "mirror_stats.txt", + "mirror_audio_results_file": "audio_results.txt", + "mirror_psnr_ssim_file": "psnr_ssim.txt", + "audio_tools_dir": "audio_quality_tools", + "image_tools_dir": "image_quality_tools", + "reference_dir": "image_quality_tools/sample_videos", + "test_utils_dir": "repository/eureka/test/utilities", + "zxing_dir": "image_quality_tools/zxing/cpp/build", + "barcode_tools_dir": "repository/eureka/test/barcode_tools", + "frame_width": "1280", + "frame_height": "720", + "barcode_height": "32", + "image_extract_interval": "1", + "ffmpeg": "ffmpeg", + "sox": "sox", + "audio_compare_tool": "polqa/PolqaOem64" +} +
diff --git a/lab_system/master/config/kir/tests/chrome_mirroring/slaves/samsung_i7_3630qm_radeon7730m_win8/config/soccer_30fps_encoded_60fps_capture_v2.config b/lab_system/master/config/kir/tests/chrome_mirroring/slaves/samsung_i7_3630qm_radeon7730m_win8/config/soccer_30fps_encoded_60fps_capture_v2.config new file mode 100644 index 0000000..d27f487 --- /dev/null +++ b/lab_system/master/config/kir/tests/chrome_mirroring/slaves/samsung_i7_3630qm_radeon7730m_win8/config/soccer_30fps_encoded_60fps_capture_v2.config
@@ -0,0 +1,35 @@ +{ + "_deps": ["processor.config"], + "chrome_binary_location": "C:\\Users\\gtvchrome\\repository\\chrome\\src\\out\\Debug\\chrome.exe", + "extension_path": "C:\\Users\\gtvchrome\\repository\\extension", + "extra_flags": "--no-proxy-server --start-maximized --whitelisted-extension-id=enhhojjnijigcajfphajepfemndkmdlo --disable-web-security --enable-experimental-extension-apis --v=0 --enable-logging --vmodule=*media/cast/*=3,*chrome/renderer/media/*=3,*=0", + "high_tab_projection_quality": "ql-high", + "gpu": "on", + "full_screen": "on", + "set_fullscreen_zoom": "off", + "get_log": "true", + "log_file_name": "C:\\Users\\gtvchrome\\results\\sender.json", + "logging": "mirroring", + "enable_webrtc_getstats": "true", + "mirror_duration": "400", + "tracing_duration": "400", + "machine_name": "samsung_i7_3630qm_radeon7730m_win8", + "video_fps": "30", + "video_name": "soccer_30fps_encoded", + "video_resolution": "720p", + "comments": "mirroring v2, video content 720p 30fps, capture at 60fps, ethernet", + "video_site": "http://172.31.25.18/test_site/index.html?video=soccer_30fps_encoded", + "recorded_video_directory": "/Users/gtvchrome/Movies/Game\\ Capture\\ HD\\ Library/mirroring/", + "capture_software": "/Applications/Game\\ Capture\\ HD.app/Contents/MacOS/Game\\ Capture\\ HD", + "test_type": "video", + "startup_latency": "false", + "network_profile": "", + "cpu_consumption": "true", + "cpu_interval": "1", + "use_sdk": "false", + "quality_test": "audio", + "cast_mirroring_version": "2.0", + "cast_streaming_on": "useCastStreaming-on", + "max_frame_rate": "60" +} +
diff --git a/lab_system/master/config/kir/tests/chrome_mirroring/slaves/samsung_i7_3630qm_radeon7730m_win8/config/soccer_30fps_encoded_v2.config b/lab_system/master/config/kir/tests/chrome_mirroring/slaves/samsung_i7_3630qm_radeon7730m_win8/config/soccer_30fps_encoded_v2.config new file mode 100644 index 0000000..d3f86a9 --- /dev/null +++ b/lab_system/master/config/kir/tests/chrome_mirroring/slaves/samsung_i7_3630qm_radeon7730m_win8/config/soccer_30fps_encoded_v2.config
@@ -0,0 +1,34 @@ +{ + "_deps": ["processor.config"], + "chrome_binary_location": "C:\\Users\\gtvchrome\\repository\\chrome\\src\\out\\Debug\\chrome.exe", + "extension_path": "C:\\Users\\gtvchrome\\repository\\extension", + "extra_flags": "--no-proxy-server --start-maximized --whitelisted-extension-id=enhhojjnijigcajfphajepfemndkmdlo --disable-web-security --enable-experimental-extension-apis --v=0 --enable-logging --vmodule=*media/cast/*=3,*chrome/renderer/media/*=3,*=0", + "high_tab_projection_quality": "ql-high", + "gpu": "on", + "full_screen": "on", + "set_fullscreen_zoom": "off", + "get_log": "true", + "log_file_name": "C:\\Users\\gtvchrome\\results\\sender.json", + "logging": "mirroring", + "enable_webrtc_getstats": "true", + "mirror_duration": "400", + "tracing_duration": "400", + "machine_name": "samsung_i7_3630qm_radeon7730m_win8", + "video_fps": "30", + "video_name": "soccer_30fps_encoded", + "video_resolution": "720p", + "comments": "mirroring v2, video content 720p 30fps, ethernet", + "video_site": "http://172.31.25.18/test_site/index.html?video=soccer_30fps_encoded", + "recorded_video_directory": "/Users/gtvchrome/Movies/Game\\ Capture\\ HD\\ Library/mirroring/", + "capture_software": "/Applications/Game\\ Capture\\ HD.app/Contents/MacOS/Game\\ Capture\\ HD", + "test_type": "video", + "startup_latency": "false", + "network_profile": "", + "cpu_consumption": "true", + "cpu_interval": "1", + "use_sdk": "false", + "quality_test": "audio", + "cast_mirroring_version": "2.0", + "cast_streaming_on": "useCastStreaming-on" +} +
diff --git a/lab_system/master/config/kir/tests/chrome_mirroring/slaves/samsung_i7_3630qm_radeon7730m_win8/config/titanfall_60fps_encoded_v2.config b/lab_system/master/config/kir/tests/chrome_mirroring/slaves/samsung_i7_3630qm_radeon7730m_win8/config/titanfall_60fps_encoded_v2.config new file mode 100644 index 0000000..bea1894 --- /dev/null +++ b/lab_system/master/config/kir/tests/chrome_mirroring/slaves/samsung_i7_3630qm_radeon7730m_win8/config/titanfall_60fps_encoded_v2.config
@@ -0,0 +1,35 @@ +{ + "_deps": ["processor.config"], + "chrome_binary_location": "C:\\Users\\gtvchrome\\repository\\chrome\\src\\out\\Debug\\chrome.exe", + "extension_path": "C:\\Users\\gtvchrome\\repository\\extension", + "extra_flags": "--no-proxy-server --start-maximized --whitelisted-extension-id=enhhojjnijigcajfphajepfemndkmdlo --disable-web-security --enable-experimental-extension-apis --v=0 --enable-logging --vmodule=*media/cast/*=3,*chrome/renderer/media/*=3,*=0", + "high_tab_projection_quality": "ql-high", + "gpu": "on", + "full_screen": "on", + "set_fullscreen_zoom": "off", + "get_log": "true", + "log_file_name": "C:\\Users\\gtvchrome\\results\\sender.json", + "logging": "mirroring", + "enable_webrtc_getstats": "true", + "mirror_duration": "400", + "tracing_duration": "400", + "machine_name": "samsung_i7_3630qm_radeon7730m_win8", + "video_fps": "60", + "video_name": "titanfall_60fps_encoded", + "video_resolution": "720p", + "comments": "mirroring v2, video content 720p 60fps, ethernet", + "video_site": "http://172.31.25.18/test_site/index.html?video=titanfall_60fps_encoded", + "recorded_video_directory": "/Users/gtvchrome/Movies/Game\\ Capture\\ HD\\ Library/mirroring/", + "capture_software": "/Applications/Game\\ Capture\\ HD.app/Contents/MacOS/Game\\ Capture\\ HD", + "test_type": "video", + "startup_latency": "false", + "network_profile": "", + "cpu_consumption": "true", + "cpu_interval": "1", + "use_sdk": "false", + "quality_test": "audio", + "cast_mirroring_version": "2.0", + "cast_streaming_on": "useCastStreaming-on", + "max_frame_rate": "60" +} +
diff --git a/lab_system/master/config/kir/tests/chrome_mirroring/slaves/trial_machine_win/config/bad_wifi.config b/lab_system/master/config/kir/tests/chrome_mirroring/slaves/trial_machine_win/config/bad_wifi.config new file mode 100755 index 0000000..95541c2 --- /dev/null +++ b/lab_system/master/config/kir/tests/chrome_mirroring/slaves/trial_machine_win/config/bad_wifi.config
@@ -0,0 +1,4 @@ +{ + "udp_proxy_ip": "172.31.25.18", + "network_profile": "bad" +}
diff --git a/lab_system/master/config/kir/tests/chrome_mirroring/slaves/trial_machine_win/config/gangnam_encoded.config b/lab_system/master/config/kir/tests/chrome_mirroring/slaves/trial_machine_win/config/gangnam_encoded.config new file mode 100755 index 0000000..3a99cbb --- /dev/null +++ b/lab_system/master/config/kir/tests/chrome_mirroring/slaves/trial_machine_win/config/gangnam_encoded.config
@@ -0,0 +1,33 @@ +{ + "_deps": ["processor.config"], + "chrome_binary_location": "C:\\Users\\gtvchrome\\repository\\chrome\\src\\out\\Debug\\chrome.exe", + "extension_path": "C:\\Users\\gtvchrome\\repository\\extension\\extension.crx", + "extra_flags": "--no-proxy-server --start-maximized --whitelisted-extension-id=hfaagokkkhdbgiakmmlclaapfelnkoah --disable-web-security --enable-experimental-extension-apis --enable-logging --v=1 --vmodule=*libjingle/source_internal/talk/*=4,*=0", + "high_tab_projection_quality": "ql-high", + "gpu": "on", + "full_screen": "on", + "set_fullscreen_zoom": "off", + "get_log": "true", + "log_file_name": "C:\\Users\\gtvchrome\\results\\sender.json", + "logging": "mirroring", + "enable_webrtc_getstats": "true", + "mirror_duration": "400", + "tracing_duration": "400", + "machine_name": "acer_i5_3337u_intelhd4000_win8", + "video_fps": "24", + "video_name": "gangnam_encoded", + "video_resolution": "720p", + "comments": "mirroring v1, video content 720p 24fps, ethernet", + "video_site": "http://172.31.25.18/test_site/index.html?video=gangnam_720p_av_test", + "recorded_video_directory": "/Users/gtvchrome/Movies/Game\\ Capture\\ HD\\ Library/mirroring/", + "capture_software": "/Applications/Game\\ Capture\\ HD.app/Contents/MacOS/Game\\ Capture\\ HD", + "test_type": "video", + "startup_latency": "false", + "network_profile": "", + "cpu_consumption": "true", + "cpu_interval": "1", + "use_sdk": "false", + "quality_test": "all", + "cast_mirroring_version": "1.0", + "cast_streaming_off": "useCastStreaming-off" +}
diff --git a/lab_system/master/config/kir/tests/chrome_mirroring/slaves/trial_machine_win/config/gangnam_encoded_v2.config b/lab_system/master/config/kir/tests/chrome_mirroring/slaves/trial_machine_win/config/gangnam_encoded_v2.config new file mode 100755 index 0000000..97ee1a9 --- /dev/null +++ b/lab_system/master/config/kir/tests/chrome_mirroring/slaves/trial_machine_win/config/gangnam_encoded_v2.config
@@ -0,0 +1,34 @@ +{ + "_deps": ["processor.config"], + "chrome_binary_location": "C:\\Users\\gtvchrome\\repository\\chrome\\src\\out\\Debug\\chrome.exe", + "extension_path": "C:\\Users\\gtvchrome\\repository\\extension\\extension.crx", + "extra_flags": "--no-proxy-server --start-maximized --whitelisted-extension-id=fmfcbgogabcbclcofgocippekhfcmgfj --disable-web-security --enable-experimental-extension-apis --v=0 --enable-logging --vmodule=*media/cast/*=3,*chrome/renderer/media/*=3,*=0", + "high_tab_projection_quality": "ql-high", + "gpu": "on", + "full_screen": "on", + "set_fullscreen_zoom": "off", + "get_log": "true", + "log_file_name": "C:\\Users\\gtvchrome\\results\\sender.json", + "logging": "mirroring", + "enable_webrtc_getstats": "true", + "mirror_duration": "400", + "tracing_duration": "400", + "machine_name": "acer_i5_3337u_intelhd4000_win8", + "video_fps": "24", + "video_name": "gangnam_encoded", + "video_resolution": "720p", + "comments": "mirroring v2, video content 720p 24fps, ethernet", + "video_site": "http://172.31.25.18/test_site/index.html?video=gangnam_720p_av_test", + "recorded_video_directory": "/Users/gtvchrome/Movies/Game\\ Capture\\ HD\\ Library/mirroring/", + "capture_software": "/Applications/Game\\ Capture\\ HD.app/Contents/MacOS/Game\\ Capture\\ HD", + "test_type": "video", + "startup_latency": "false", + "network_profile": "", + "cpu_consumption": "true", + "cpu_interval": "1", + "use_sdk": "false", + "quality_test": "all", + "cast_mirroring_version": "2.0", + "cast_streaming_on": "useCastStreaming-on" +} +
diff --git a/lab_system/master/config/kir/tests/chrome_mirroring/slaves/trial_machine_win/config/gangnam_encoded_v2_bad_wifi.config b/lab_system/master/config/kir/tests/chrome_mirroring/slaves/trial_machine_win/config/gangnam_encoded_v2_bad_wifi.config new file mode 100755 index 0000000..50ebb3d --- /dev/null +++ b/lab_system/master/config/kir/tests/chrome_mirroring/slaves/trial_machine_win/config/gangnam_encoded_v2_bad_wifi.config
@@ -0,0 +1,33 @@ +{ + "_deps": ["processor.config", "bad_wifi.config"], + "chrome_binary_location": "C:\\Users\\gtvchrome\\repository\\chrome\\src\\out\\Debug\\chrome.exe", + "extension_path": "C:\\Users\\gtvchrome\\repository\\extension\\extension.crx", + "extra_flags": "--no-proxy-server --start-maximized --whitelisted-extension-id=hfaagokkkhdbgiakmmlclaapfelnkoah --disable-web-security --enable-experimental-extension-apis --v=0 --enable-logging --vmodule=*media/cast/*=3,*chrome/renderer/media/*=3,*=0", + "high_tab_projection_quality": "ql-high", + "gpu": "on", + "full_screen": "on", + "set_fullscreen_zoom": "off", + "get_log": "true", + "log_file_name": "C:\\Users\\gtvchrome\\results\\sender.json", + "logging": "mirroring", + "enable_webrtc_getstats": "true", + "mirror_duration": "400", + "tracing_duration": "400", + "machine_name": "acer_i5_3337u_intelhd4000_win8", + "video_fps": "24", + "video_name": "gangnam_encoded", + "video_resolution": "720p", + "comments": "mirroring v2, video content 720p 24fps, bad wifi", + "video_site": "http://172.31.25.18/test_site/index.html?video=gangnam_720p_av_test", + "recorded_video_directory": "/Users/gtvchrome/Movies/Game\\ Capture\\ HD\\ Library/mirroring/", + "capture_software": "/Applications/Game\\ Capture\\ HD.app/Contents/MacOS/Game\\ Capture\\ HD", + "test_type": "video", + "startup_latency": "false", + "cpu_consumption": "true", + "cpu_interval": "1", + "use_sdk": "false", + "quality_test": "all", + "cast_mirroring_version": "2.0", + "cast_streaming_on": "useCastStreaming-on" +} +
diff --git a/lab_system/master/config/kir/tests/chrome_mirroring/slaves/trial_machine_win/config/processor.config b/lab_system/master/config/kir/tests/chrome_mirroring/slaves/trial_machine_win/config/processor.config new file mode 100755 index 0000000..0e8eaf1 --- /dev/null +++ b/lab_system/master/config/kir/tests/chrome_mirroring/slaves/trial_machine_win/config/processor.config
@@ -0,0 +1,24 @@ +{ + "root_dir": "/home/gtvchrome", + "results_dir": "results", + "mirror_mp4_file": "Segment_0001.mp4", + "mirror_yuv_file": "mirror.yuv", + "mirror_wav_file": "mirror.wav", + "mirror_stats_file": "mirror_stats.txt", + "mirror_audio_results_file": "audio_results.txt", + "mirror_psnr_ssim_file": "psnr_ssim.txt", + "audio_tools_dir": "audio_quality_tools", + "image_tools_dir": "image_quality_tools", + "reference_dir": "image_quality_tools/sample_videos", + "test_utils_dir": "repository/eureka/test/utilities", + "zxing_dir": "image_quality_tools/zxing/cpp/build", + "barcode_tools_dir": "repository/eureka/test/barcode_tools", + "frame_width": "1280", + "frame_height": "720", + "barcode_height": "32", + "image_extract_interval": "1", + "ffmpeg": "ffmpeg", + "sox": "sox", + "audio_compare_tool": "polqa/PolqaOem64" +} +
diff --git a/lab_system/master/config/kir/tests/chrome_mirroring/slaves/trial_machine_win/config/soccer_30fps_encoded_v2.config b/lab_system/master/config/kir/tests/chrome_mirroring/slaves/trial_machine_win/config/soccer_30fps_encoded_v2.config new file mode 100755 index 0000000..312e49c --- /dev/null +++ b/lab_system/master/config/kir/tests/chrome_mirroring/slaves/trial_machine_win/config/soccer_30fps_encoded_v2.config
@@ -0,0 +1,34 @@ +{ + "_deps": ["processor.config"], + "chrome_binary_location": "C:\\Users\\gtvchrome\\repository\\chrome\\src\\out\\Debug\\chrome.exe", + "extension_path": "C:\\Users\\gtvchrome\\repository\\extension\\extension.crx", + "extra_flags": "--no-proxy-server --start-maximized --whitelisted-extension-id=hfaagokkkhdbgiakmmlclaapfelnkoah --disable-web-security --enable-experimental-extension-apis --v=0 --enable-logging --vmodule=*media/cast/*=3,*chrome/renderer/media/*=3,*=0", + "high_tab_projection_quality": "ql-high", + "gpu": "on", + "full_screen": "on", + "set_fullscreen_zoom": "off", + "get_log": "true", + "log_file_name": "C:\\Users\\gtvchrome\\results\\sender.json", + "logging": "mirroring", + "enable_webrtc_getstats": "true", + "mirror_duration": "400", + "tracing_duration": "400", + "machine_name": "acer_i5_3337u_intelhd4000_win8", + "video_fps": "30", + "video_name": "soccer_30fps_encoded", + "video_resolution": "720p", + "comments": "mirroring v2, video content 720p 30fps, ethernet", + "video_site": "http://172.31.25.18/test_site/index.html?video=soccer_30fps_encoded", + "recorded_video_directory": "/Users/gtvchrome/Movies/Game\\ Capture\\ HD\\ Library/mirroring/", + "capture_software": "/Applications/Game\\ Capture\\ HD.app/Contents/MacOS/Game\\ Capture\\ HD", + "test_type": "video", + "startup_latency": "false", + "network_profile": "", + "cpu_consumption": "true", + "cpu_interval": "1", + "use_sdk": "true", + "quality_test": "audio", + "cast_mirroring_version": "2.0", + "cast_streaming_on": "useCastStreaming-on" +} +
diff --git a/lab_system/master/config/kir/tests/chrome_mirroring/test_defs.json b/lab_system/master/config/kir/tests/chrome_mirroring/test_defs.json new file mode 100755 index 0000000..8e781a6 --- /dev/null +++ b/lab_system/master/config/kir/tests/chrome_mirroring/test_defs.json
@@ -0,0 +1,1226 @@ +[ + { + "group_name": "macbookair_i5_4250u_intelhd5000", + "slave_name": "macbookair_i5_4250u_intelhd5000", + "test_name": "chrome_mirroring", + "branch": "release", + "device_type": "eureka", + "device_group": "video_recorder_set_1", + "identifier": "macbookair_i5_4250u_intelhd5000", + "scheduler": "none", + "step_factories": [ + { + "step_description": "Sets up testrun specific properties", + "step_identifier": "properties", + "step_factories": [ + { + "module_path": "lab_system.master.steps.factory.run.chrome_mirroring_runner", + "class_name": "MakeTempFiles" + }, + { + "module_path": "lab_system.master.steps.factory.run.chrome_mirroring_runner", + "class_name": "DownloadGoodCombinationsJson" + }, + { + "module_path": "lab_system.master.steps.factory.run.chrome_mirroring_runner", + "class_name": "OverwritePropertiesStepFactory" + } + ] + }, + { + "step_description": "Update Eureka build number, remove LOCAL_LOGS, update Chrome binaries and remove existing log files", + "step_identifier": "testrun_setup", + "step_factories": [ + { + "module_path": "lab_system.master.steps.factory.run.cloudview_runners.cloudview_chrome_mirroring_runner", + "class_name": "SetEurekaRecorderIpStepFactory" + }, + { + "module_path": "lab_system.master.steps.factory.sender.allocator", + "class_name": "SenderAllocatorStepFactory" + }, + { + "module_path": "lab_system.master.steps.factory.run.cloudview_runners.cloudview_chrome_mirroring_runner", + "class_name": "SetRecorderMachineIpStepFactory" + }, + { + "module_path": "lab_system.master.steps.factory.run.cloudview_runners.cloudview_chrome_mirroring_runner", + "class_name": "RemoveExistingLogFiles" + }, + { + "module_path": "lab_system.master.steps.factory.build.copy_test_repo", + "class_name": "CopyRepositoriesStepFactory" + }, + { + "module_path": "lab_system.master.steps.factory.chrome.download", + "class_name": "DownloadChromeStepFactory" + }, + { + "module_path": "lab_system.master.steps.factory.chrome.copy", + "class_name": "CopyChromeStepFactory" + }, + { + "module_path": "lab_system.master.steps.factory.extension.download_cws_extension", + "class_name": "DownloadWebStoreExtensionStepFactory" + }, + { + "module_path": "lab_system.master.steps.factory.extension.copy", + "class_name": "CopyExtensionStepFactory" + }, + { + "module_path": "lab_system.master.steps.factory.run.cloudview_runners.cloudview_chrome_mirroring_runner", + "class_name": "CopyConfigFilesStepFactory" + } + ] + }, + { + "step_description": "Runs chrome mirroring test", + "step_identifier": "test_running", + "step_factories": [ + { + "module_path": "lab_system.master.steps.factory.run.cloudview_runners.cloudview_chrome_mirroring_runner", + "class_name": "ChromeMirroringStepFactory" + }, + { + "module_path": "lab_system.master.steps.factory.device.deallocator", + "class_name": "DeviceDeallocatorStepFactory" + }, + { + "module_path": "lab_system.master.steps.factory.sender.deallocator", + "class_name": "SenderDeallocatorStepFactory" + } + ] + }, + { + "step_description": "Getting test result and them to Chrome Performance Dashboard", + "step_identifier": "output_processing", + "step_factories": [ + { + "module_path": "lab_system.master.steps.factory.run.cloudview_runners.cloudview_chrome_mirroring_runner", + "class_name": "CopyTestLogsStepFactory" + }, + { + "module_path": "lab_system.master.steps.factory.output.logs", + "class_name": "CopyLogsToRepositoryStepFactory" + }, + { + "module_path": "lab_system.master.steps.factory.run.chrome_mirroring_runner", + "class_name": "CopyResultToProcessorStepFactory" + }, + { + "module_path": "lab_system.master.steps.factory.run.chrome_mirroring_runner", + "class_name": "ProcessVideoStepFactory" + }, + { + "module_path": "lab_system.master.steps.factory.run.chrome_mirroring_runner", + "class_name": "CopyResultFromProcessorStepFactory" + }, + { + "module_path": "lab_system.master.steps.factory.output.logs", + "class_name": "CopyLogsToRepositoryStepFactory" + } + ] + }, + { + "step_description": "Cleanup", + "step_identifier": "testrun_cleanup", + "step_factories": [ + { + "module_path": "lab_system.master.steps.factory.cleanup.workdir", + "class_name": "CleanupWorkdirStepFactory" + }, + { + "module_path": "lab_system.master.steps.factory.run.chrome_mirroring_runner", + "class_name": "RemoveLogsOnMasterStepFactory" + } + ] + } + ] + }, + { + "group_name": "macbookpro_i7_2675qm_radeon6750m", + "slave_name": "macbookpro_i7_2675qm_radeon6750m", + "test_name": "chrome_mirroring", + "branch": "release", + "device_type": "eureka", + "device_group": "video_recorder_set_1", + "identifier": "macbookpro_i7_2675qm_radeon6750m", + "scheduler": "none", + "step_factories": [ + { + "step_description": "Sets up testrun specific properties", + "step_identifier": "properties", + "step_factories": [ + { + "module_path": "lab_system.master.steps.factory.run.chrome_mirroring_runner", + "class_name": "MakeTempFiles" + }, + { + "module_path": "lab_system.master.steps.factory.run.chrome_mirroring_runner", + "class_name": "DownloadGoodCombinationsJson" + }, + { + "module_path": "lab_system.master.steps.factory.run.chrome_mirroring_runner", + "class_name": "OverwritePropertiesStepFactory" + } + ] + }, + { + "step_description": "Update Eureka build number, remove LOCAL_LOGS, update Chrome binaries and remove existing log files", + "step_identifier": "testrun_setup", + "step_factories": [ + { + "module_path": "lab_system.master.steps.factory.run.cloudview_runners.cloudview_chrome_mirroring_runner", + "class_name": "SetEurekaRecorderIpStepFactory" + }, + { + "module_path": "lab_system.master.steps.factory.sender.allocator", + "class_name": "SenderAllocatorStepFactory" + }, + { + "module_path": "lab_system.master.steps.factory.run.cloudview_runners.cloudview_chrome_mirroring_runner", + "class_name": "SetRecorderMachineIpStepFactory" + }, + { + "module_path": "lab_system.master.steps.factory.run.cloudview_runners.cloudview_chrome_mirroring_runner", + "class_name": "RemoveExistingLogFiles" + }, + { + "module_path": "lab_system.master.steps.factory.build.copy_test_repo", + "class_name": "CopyRepositoriesStepFactory" + }, + { + "module_path": "lab_system.master.steps.factory.chrome.download", + "class_name": "DownloadChromeStepFactory" + }, + { + "module_path": "lab_system.master.steps.factory.chrome.copy", + "class_name": "CopyChromeStepFactory" + }, + { + "module_path": "lab_system.master.steps.factory.extension.download_cws_extension", + "class_name": "DownloadWebStoreExtensionStepFactory" + }, + { + "module_path": "lab_system.master.steps.factory.extension.copy", + "class_name": "CopyExtensionStepFactory" + }, + { + "module_path": "lab_system.master.steps.factory.run.cloudview_runners.cloudview_chrome_mirroring_runner", + "class_name": "CopyConfigFilesStepFactory" + } + ] + }, + { + "step_description": "Runs chrome mirroring test", + "step_identifier": "test_running", + "step_factories": [ + { + "module_path": "lab_system.master.steps.factory.run.cloudview_runners.cloudview_chrome_mirroring_runner", + "class_name": "ChromeMirroringStepFactory" + }, + { + "module_path": "lab_system.master.steps.factory.device.deallocator", + "class_name": "DeviceDeallocatorStepFactory" + }, + { + "module_path": "lab_system.master.steps.factory.sender.deallocator", + "class_name": "SenderDeallocatorStepFactory" + } + ] + }, + { + "step_description": "Getting test result and them to Chrome Performance Dashboard", + "step_identifier": "output_processing", + "step_factories": [ + { + "module_path": "lab_system.master.steps.factory.run.cloudview_runners.cloudview_chrome_mirroring_runner", + "class_name": "CopyTestLogsStepFactory" + }, + { + "module_path": "lab_system.master.steps.factory.output.logs", + "class_name": "CopyLogsToRepositoryStepFactory" + }, + { + "module_path": "lab_system.master.steps.factory.run.chrome_mirroring_runner", + "class_name": "CopyResultToProcessorStepFactory" + }, + { + "module_path": "lab_system.master.steps.factory.run.chrome_mirroring_runner", + "class_name": "ProcessVideoStepFactory" + }, + { + "module_path": "lab_system.master.steps.factory.run.chrome_mirroring_runner", + "class_name": "CopyResultFromProcessorStepFactory" + }, + { + "module_path": "lab_system.master.steps.factory.output.logs", + "class_name": "CopyLogsToRepositoryStepFactory" + } + ] + }, + { + "step_description": "Cleanup", + "step_identifier": "testrun_cleanup", + "step_factories": [ + { + "module_path": "lab_system.master.steps.factory.cleanup.workdir", + "class_name": "CleanupWorkdirStepFactory" + }, + { + "module_path": "lab_system.master.steps.factory.run.chrome_mirroring_runner", + "class_name": "RemoveLogsOnMasterStepFactory" + } + ] + } + ] + }, + { + "group_name": "acer_i5_3337u_intelhd4000_win8", + "slave_name": "acer_i5_3337u_intelhd4000_win8", + "test_name": "chrome_mirroring", + "branch": "release", + "device_type": "eureka", + "device_group": "video_recorder_set_0", + "identifier": "acer_i5_3337u_intelhd4000_win8", + "scheduler": "none", + "step_factories": [ + { + "step_description": "Sets up testrun specific properties", + "step_identifier": "properties", + "step_factories": [ + { + "module_path": "lab_system.master.steps.factory.run.chrome_mirroring_runner", + "class_name": "MakeTempFiles" + }, + { + "module_path": "lab_system.master.steps.factory.run.chrome_mirroring_runner", + "class_name": "DownloadGoodCombinationsJson" + }, + { + "module_path": "lab_system.master.steps.factory.run.chrome_mirroring_runner", + "class_name": "OverwritePropertiesStepFactory" + } + ] + }, + { + "step_description": "Update Eureka build number, remove LOCAL_LOGS, update Chrome binaries and remove existing log files", + "step_identifier": "testrun_setup", + "step_factories": [ + { + "module_path": "lab_system.master.steps.factory.run.cloudview_runners.cloudview_chrome_mirroring_runner", + "class_name": "SetEurekaRecorderIpStepFactory" + }, + { + "module_path": "lab_system.master.steps.factory.sender.allocator", + "class_name": "SenderAllocatorStepFactory" + }, + { + "module_path": "lab_system.master.steps.factory.run.cloudview_runners.cloudview_chrome_mirroring_runner", + "class_name": "SetRecorderMachineIpStepFactory" + }, + { + "module_path": "lab_system.master.steps.factory.run.cloudview_runners.cloudview_chrome_mirroring_runner", + "class_name": "RemoveExistingLogFiles" + }, + { + "module_path": "lab_system.master.steps.factory.build.copy_test_repo", + "class_name": "CopyRepositoriesStepFactory" + }, + { + "module_path": "lab_system.master.steps.factory.chrome.download", + "class_name": "DownloadChromeStepFactory" + }, + { + "module_path": "lab_system.master.steps.factory.chrome.copy", + "class_name": "CopyChromeStepFactory" + }, + { + "module_path": "lab_system.master.steps.factory.extension.download_cws_extension", + "class_name": "DownloadWebStoreExtensionStepFactory" + }, + { + "module_path": "lab_system.master.steps.factory.extension.copy", + "class_name": "CopyExtensionStepFactory" + }, + { + "module_path": "lab_system.master.steps.factory.run.cloudview_runners.cloudview_chrome_mirroring_runner", + "class_name": "CopyConfigFilesStepFactory" + } + ] + }, + { + "step_description": "Runs chrome mirroring test", + "step_identifier": "test_running", + "step_factories": [ + { + "module_path": "lab_system.master.steps.factory.run.cloudview_runners.cloudview_chrome_mirroring_runner", + "class_name": "ChromeMirroringStepFactory" + }, + { + "module_path": "lab_system.master.steps.factory.device.deallocator", + "class_name": "DeviceDeallocatorStepFactory" + }, + { + "module_path": "lab_system.master.steps.factory.sender.deallocator", + "class_name": "SenderDeallocatorStepFactory" + } + ] + }, + { + "step_description": "Getting test result and them to Chrome Performance Dashboard", + "step_identifier": "output_processing", + "step_factories": [ + { + "module_path": "lab_system.master.steps.factory.run.cloudview_runners.cloudview_chrome_mirroring_runner", + "class_name": "CopyTestLogsStepFactory" + }, + { + "module_path": "lab_system.master.steps.factory.output.logs", + "class_name": "CopyLogsToRepositoryStepFactory" + }, + { + "module_path": "lab_system.master.steps.factory.run.chrome_mirroring_runner", + "class_name": "CopyResultToProcessorStepFactory" + }, + { + "module_path": "lab_system.master.steps.factory.run.chrome_mirroring_runner", + "class_name": "ProcessVideoStepFactory" + }, + { + "module_path": "lab_system.master.steps.factory.run.chrome_mirroring_runner", + "class_name": "CopyResultFromProcessorStepFactory" + }, + { + "module_path": "lab_system.master.steps.factory.output.logs", + "class_name": "CopyLogsToRepositoryStepFactory" + } + ] + }, + { + "step_description": "Cleanup", + "step_identifier": "testrun_cleanup", + "step_factories": [ + { + "module_path": "lab_system.master.steps.factory.cleanup.workdir", + "class_name": "CleanupWorkdirStepFactory" + }, + { + "module_path": "lab_system.master.steps.factory.run.chrome_mirroring_runner", + "class_name": "RemoveLogsOnMasterStepFactory" + } + ] + } + ] + }, + { + "group_name": "samsung_i7_3630qm_radeon7730m_win8", + "slave_name": "samsung_i7_3630qm_radeon7730m_win8", + "test_name": "chrome_mirroring", + "branch": "release", + "device_type": "eureka", + "device_group": "video_recorder_set_0", + "identifier": "samsung_i7_3630qm_radeon7730m_win8", + "scheduler": "none", + "step_factories": [ + { + "step_description": "Sets up testrun specific properties", + "step_identifier": "properties", + "step_factories": [ + { + "module_path": "lab_system.master.steps.factory.run.chrome_mirroring_runner", + "class_name": "MakeTempFiles" + }, + { + "module_path": "lab_system.master.steps.factory.run.chrome_mirroring_runner", + "class_name": "DownloadGoodCombinationsJson" + }, + { + "module_path": "lab_system.master.steps.factory.run.chrome_mirroring_runner", + "class_name": "OverwritePropertiesStepFactory" + } + ] + }, + { + "step_description": "Update Eureka build number, remove LOCAL_LOGS, update Chrome binaries and remove existing log files", + "step_identifier": "testrun_setup", + "step_factories": [ + { + "module_path": "lab_system.master.steps.factory.run.cloudview_runners.cloudview_chrome_mirroring_runner", + "class_name": "SetEurekaRecorderIpStepFactory" + }, + { + "module_path": "lab_system.master.steps.factory.sender.allocator", + "class_name": "SenderAllocatorStepFactory" + }, + { + "module_path": "lab_system.master.steps.factory.run.cloudview_runners.cloudview_chrome_mirroring_runner", + "class_name": "SetRecorderMachineIpStepFactory" + }, + { + "module_path": "lab_system.master.steps.factory.run.cloudview_runners.cloudview_chrome_mirroring_runner", + "class_name": "RemoveExistingLogFiles" + }, + { + "module_path": "lab_system.master.steps.factory.build.copy_test_repo", + "class_name": "CopyRepositoriesStepFactory" + }, + { + "module_path": "lab_system.master.steps.factory.chrome.download", + "class_name": "DownloadChromeStepFactory" + }, + { + "module_path": "lab_system.master.steps.factory.chrome.copy", + "class_name": "CopyChromeStepFactory" + }, + { + "module_path": "lab_system.master.steps.factory.extension.download_cws_extension", + "class_name": "DownloadWebStoreExtensionStepFactory" + }, + { + "module_path": "lab_system.master.steps.factory.extension.copy", + "class_name": "CopyExtensionStepFactory" + }, + { + "module_path": "lab_system.master.steps.factory.run.cloudview_runners.cloudview_chrome_mirroring_runner", + "class_name": "CopyConfigFilesStepFactory" + } + ] + }, + { + "step_description": "Runs chrome mirroring test", + "step_identifier": "test_running", + "step_factories": [ + { + "module_path": "lab_system.master.steps.factory.run.cloudview_runners.cloudview_chrome_mirroring_runner", + "class_name": "ChromeMirroringStepFactory" + }, + { + "module_path": "lab_system.master.steps.factory.device.deallocator", + "class_name": "DeviceDeallocatorStepFactory" + }, + { + "module_path": "lab_system.master.steps.factory.sender.deallocator", + "class_name": "SenderDeallocatorStepFactory" + } + ] + }, + { + "step_description": "Getting test result and them to Chrome Performance Dashboard", + "step_identifier": "output_processing", + "step_factories": [ + { + "module_path": "lab_system.master.steps.factory.run.cloudview_runners.cloudview_chrome_mirroring_runner", + "class_name": "CopyTestLogsStepFactory" + }, + { + "module_path": "lab_system.master.steps.factory.output.logs", + "class_name": "CopyLogsToRepositoryStepFactory" + }, + { + "module_path": "lab_system.master.steps.factory.run.chrome_mirroring_runner", + "class_name": "CopyResultToProcessorStepFactory" + }, + { + "module_path": "lab_system.master.steps.factory.run.chrome_mirroring_runner", + "class_name": "ProcessVideoStepFactory" + }, + { + "module_path": "lab_system.master.steps.factory.run.chrome_mirroring_runner", + "class_name": "CopyResultFromProcessorStepFactory" + }, + { + "module_path": "lab_system.master.steps.factory.output.logs", + "class_name": "CopyLogsToRepositoryStepFactory" + } + ] + }, + { + "step_description": "Cleanup", + "step_identifier": "testrun_cleanup", + "step_factories": [ + { + "module_path": "lab_system.master.steps.factory.cleanup.workdir", + "class_name": "CleanupWorkdirStepFactory" + }, + { + "module_path": "lab_system.master.steps.factory.run.chrome_mirroring_runner", + "class_name": "RemoveLogsOnMasterStepFactory" + } + ] + } + ] + }, + { + "group_name": "asus_i3_2328m_intelhd3000_win8", + "slave_name": "asus_i3_2328m_intelhd3000_win8", + "test_name": "chrome_mirroring", + "branch": "release", + "device_type": "eureka", + "device_group": "video_recorder_set_0", + "identifier": "asus_i3_2328m_intelhd3000_win8", + "scheduler": "none", + "step_factories": [ + { + "step_description": "Sets up testrun specific properties", + "step_identifier": "properties", + "step_factories": [ + { + "module_path": "lab_system.master.steps.factory.run.chrome_mirroring_runner", + "class_name": "MakeTempFiles" + }, + { + "module_path": "lab_system.master.steps.factory.run.chrome_mirroring_runner", + "class_name": "DownloadGoodCombinationsJson" + }, + { + "module_path": "lab_system.master.steps.factory.run.chrome_mirroring_runner", + "class_name": "OverwritePropertiesStepFactory" + } + ] + }, + { + "step_description": "Update Eureka build number, remove LOCAL_LOGS, update Chrome binaries and remove existing log files", + "step_identifier": "testrun_setup", + "step_factories": [ + { + "module_path": "lab_system.master.steps.factory.run.cloudview_runners.cloudview_chrome_mirroring_runner", + "class_name": "SetEurekaRecorderIpStepFactory" + }, + { + "module_path": "lab_system.master.steps.factory.sender.allocator", + "class_name": "SenderAllocatorStepFactory" + }, + { + "module_path": "lab_system.master.steps.factory.run.cloudview_runners.cloudview_chrome_mirroring_runner", + "class_name": "SetRecorderMachineIpStepFactory" + }, + { + "module_path": "lab_system.master.steps.factory.run.cloudview_runners.cloudview_chrome_mirroring_runner", + "class_name": "RemoveExistingLogFiles" + }, + { + "module_path": "lab_system.master.steps.factory.build.copy_test_repo", + "class_name": "CopyRepositoriesStepFactory" + }, + { + "module_path": "lab_system.master.steps.factory.chrome.download", + "class_name": "DownloadChromeStepFactory" + }, + { + "module_path": "lab_system.master.steps.factory.chrome.copy", + "class_name": "CopyChromeStepFactory" + }, + { + "module_path": "lab_system.master.steps.factory.extension.download_cws_extension", + "class_name": "DownloadWebStoreExtensionStepFactory" + }, + { + "module_path": "lab_system.master.steps.factory.extension.copy", + "class_name": "CopyExtensionStepFactory" + }, + { + "module_path": "lab_system.master.steps.factory.run.cloudview_runners.cloudview_chrome_mirroring_runner", + "class_name": "CopyConfigFilesStepFactory" + } + ] + }, + { + "step_description": "Runs chrome mirroring test", + "step_identifier": "test_running", + "step_factories": [ + { + "module_path": "lab_system.master.steps.factory.run.cloudview_runners.cloudview_chrome_mirroring_runner", + "class_name": "ChromeMirroringStepFactory" + }, + { + "module_path": "lab_system.master.steps.factory.device.deallocator", + "class_name": "DeviceDeallocatorStepFactory" + }, + { + "module_path": "lab_system.master.steps.factory.sender.deallocator", + "class_name": "SenderDeallocatorStepFactory" + } + ] + }, + { + "step_description": "Getting test result and them to Chrome Performance Dashboard", + "step_identifier": "output_processing", + "step_factories": [ + { + "module_path": "lab_system.master.steps.factory.run.cloudview_runners.cloudview_chrome_mirroring_runner", + "class_name": "CopyTestLogsStepFactory" + }, + { + "module_path": "lab_system.master.steps.factory.output.logs", + "class_name": "CopyLogsToRepositoryStepFactory" + }, + { + "module_path": "lab_system.master.steps.factory.run.chrome_mirroring_runner", + "class_name": "CopyResultToProcessorStepFactory" + }, + { + "module_path": "lab_system.master.steps.factory.run.chrome_mirroring_runner", + "class_name": "ProcessVideoStepFactory" + }, + { + "module_path": "lab_system.master.steps.factory.run.chrome_mirroring_runner", + "class_name": "CopyResultFromProcessorStepFactory" + }, + { + "module_path": "lab_system.master.steps.factory.output.logs", + "class_name": "CopyLogsToRepositoryStepFactory" + } + ] + }, + { + "step_description": "Cleanup", + "step_identifier": "testrun_cleanup", + "step_factories": [ + { + "module_path": "lab_system.master.steps.factory.cleanup.workdir", + "class_name": "CleanupWorkdirStepFactory" + } + ] + } + ] + }, + { + "group_name": "hp_core2duo_p8600_gma4500_win7", + "slave_name": "hp_core2duo_p8600_gma4500_win7", + "test_name": "chrome_mirroring", + "branch": "release", + "device_type": "eureka", + "device_group": "video_recorder_set_1", + "identifier": "hp_core2duo_p8600_gma4500_win7", + "scheduler": "none", + "step_factories": [ + { + "step_description": "Sets up testrun specific properties", + "step_identifier": "properties", + "step_factories": [ + { + "module_path": "lab_system.master.steps.factory.run.chrome_mirroring_runner", + "class_name": "MakeTempFiles" + }, + { + "module_path": "lab_system.master.steps.factory.run.chrome_mirroring_runner", + "class_name": "DownloadGoodCombinationsJson" + }, + { + "module_path": "lab_system.master.steps.factory.run.chrome_mirroring_runner", + "class_name": "OverwritePropertiesStepFactory" + } + ] + }, + { + "step_description": "Update Eureka build number, remove LOCAL_LOGS, update Chrome binaries and remove existing log files", + "step_identifier": "testrun_setup", + "step_factories": [ + { + "module_path": "lab_system.master.steps.factory.run.cloudview_runners.cloudview_chrome_mirroring_runner", + "class_name": "SetEurekaRecorderIpStepFactory" + }, + { + "module_path": "lab_system.master.steps.factory.sender.allocator", + "class_name": "SenderAllocatorStepFactory" + }, + { + "module_path": "lab_system.master.steps.factory.run.cloudview_runners.cloudview_chrome_mirroring_runner", + "class_name": "SetRecorderMachineIpStepFactory" + }, + { + "module_path": "lab_system.master.steps.factory.run.cloudview_runners.cloudview_chrome_mirroring_runner", + "class_name": "RemoveExistingLogFiles" + }, + { + "module_path": "lab_system.master.steps.factory.build.copy_test_repo", + "class_name": "CopyRepositoriesStepFactory" + }, + { + "module_path": "lab_system.master.steps.factory.chrome.download", + "class_name": "DownloadChromeStepFactory" + }, + { + "module_path": "lab_system.master.steps.factory.chrome.copy", + "class_name": "CopyChromeStepFactory" + }, + { + "module_path": "lab_system.master.steps.factory.extension.download_cws_extension", + "class_name": "DownloadWebStoreExtensionStepFactory" + }, + { + "module_path": "lab_system.master.steps.factory.extension.copy", + "class_name": "CopyExtensionStepFactory" + }, + { + "module_path": "lab_system.master.steps.factory.run.cloudview_runners.cloudview_chrome_mirroring_runner", + "class_name": "CopyConfigFilesStepFactory" + } + ] + }, + { + "step_description": "Runs chrome mirroring test", + "step_identifier": "test_running", + "step_factories": [ + { + "module_path": "lab_system.master.steps.factory.run.cloudview_runners.cloudview_chrome_mirroring_runner", + "class_name": "ChromeMirroringStepFactory" + }, + { + "module_path": "lab_system.master.steps.factory.device.deallocator", + "class_name": "DeviceDeallocatorStepFactory" + }, + { + "module_path": "lab_system.master.steps.factory.sender.deallocator", + "class_name": "SenderDeallocatorStepFactory" + } + ] + }, + { + "step_description": "Getting test result and them to Chrome Performance Dashboard", + "step_identifier": "output_processing", + "step_factories": [ + { + "module_path": "lab_system.master.steps.factory.run.cloudview_runners.cloudview_chrome_mirroring_runner", + "class_name": "CopyTestLogsStepFactory" + }, + { + "module_path": "lab_system.master.steps.factory.output.logs", + "class_name": "CopyLogsToRepositoryStepFactory" + }, + { + "module_path": "lab_system.master.steps.factory.run.chrome_mirroring_runner", + "class_name": "CopyResultToProcessorStepFactory" + }, + { + "module_path": "lab_system.master.steps.factory.run.chrome_mirroring_runner", + "class_name": "ProcessVideoStepFactory" + }, + { + "module_path": "lab_system.master.steps.factory.run.chrome_mirroring_runner", + "class_name": "CopyResultFromProcessorStepFactory" + }, + { + "module_path": "lab_system.master.steps.factory.output.logs", + "class_name": "CopyLogsToRepositoryStepFactory" + } + ] + }, + { + "step_description": "Cleanup", + "step_identifier": "testrun_cleanup", + "step_factories": [ + { + "module_path": "lab_system.master.steps.factory.cleanup.workdir", + "class_name": "CleanupWorkdirStepFactory" + }, + { + "module_path": "lab_system.master.steps.factory.run.chrome_mirroring_runner", + "class_name": "RemoveLogsOnMasterStepFactory" + } + ] + } + ] + }, + { + "group_name": "macbookair_i5_4250u_intelhd5000_mtv", + "slave_name": "macbookair_i5_4250u_intelhd5000_mtv", + "test_name": "chrome_mirroring", + "branch": "master", + "device_type": "eureka", + "device_group": "video_recorder_mtv", + "identifier": "macbookair_i5_4250u_intelhd5000_mtv", + "scheduler": "none", + "step_factories": [ + { + "step_description": "Update Eureka build number, remove LOCAL_LOGS, update Chrome binaries and remove existing log files", + "step_identifier": "testrun_setup", + "step_factories": [ + { + "module_path": "lab_system.master.steps.factory.run.cloudview_runners.cloudview_chrome_mirroring_runner", + "class_name": "SetEurekaRecorderIpStepFactory" + }, + { + "module_path": "lab_system.master.steps.factory.sender.allocator", + "class_name": "SenderAllocatorStepFactory" + }, + { + "module_path": "lab_system.master.steps.factory.run.cloudview_runners.cloudview_chrome_mirroring_runner", + "class_name": "SetRecorderMachineIpStepFactory" + }, + { + "module_path": "lab_system.master.steps.factory.run.cloudview_runners.cloudview_chrome_mirroring_runner", + "class_name": "RemoveExistingLogFiles" + }, + { + "module_path": "lab_system.master.steps.factory.build.copy_test_repo", + "class_name": "CopyRepositoriesStepFactory" + }, + { + "module_path": "lab_system.master.steps.factory.chrome.download", + "class_name": "DownloadChromeStepFactory" + }, + { + "module_path": "lab_system.master.steps.factory.chrome.copy", + "class_name": "CopyChromeStepFactory" + }, + { + "module_path": "lab_system.master.steps.factory.extension.download_cws_extension", + "class_name": "DownloadWebStoreExtensionStepFactory" + }, + { + "module_path": "lab_system.master.steps.factory.extension.copy", + "class_name": "CopyExtensionStepFactory" + }, + { + "module_path": "lab_system.master.steps.factory.run.cloudview_runners.cloudview_chrome_mirroring_runner", + "class_name": "CopyConfigFilesStepFactory" + }, + { + "module_path": "lab_system.master.steps.factory.run.chrome_mirroring_runner", + "class_name": "SetLogs" + } + ] + }, + { + "step_description": "Runs chrome mirroring test", + "step_identifier": "test_running", + "step_factories": [ + { + "module_path": "lab_system.master.steps.factory.run.cloudview_runners.cloudview_chrome_mirroring_runner", + "class_name": "ChromeMirroringStepFactory" + }, + { + "module_path": "lab_system.master.steps.factory.device.deallocator", + "class_name": "DeviceDeallocatorStepFactory" + }, + { + "module_path": "lab_system.master.steps.factory.sender.deallocator", + "class_name": "SenderDeallocatorStepFactory" + } + ] + }, + { + "step_description": "Getting test result and them to Chrome Performance Dashboard", + "step_identifier": "output_processing", + "step_factories": [ + { + "module_path": "lab_system.master.steps.factory.run.cloudview_runners.cloudview_chrome_mirroring_runner", + "class_name": "CopyTestLogsStepFactory" + }, + { + "module_path": "lab_system.master.steps.factory.output.logs", + "class_name": "CopyLogsToRepositoryStepFactory" + }, + { + "module_path": "lab_system.master.steps.factory.run.chrome_mirroring_runner", + "class_name": "CopyResultToProcessorStepFactory" + }, + { + "module_path": "lab_system.master.steps.factory.run.chrome_mirroring_runner", + "class_name": "ProcessVideoStepFactory" + }, + { + "module_path": "lab_system.master.steps.factory.run.chrome_mirroring_runner", + "class_name": "CopyResultFromProcessorStepFactory" + }, + { + "module_path": "lab_system.master.steps.factory.output.logs", + "class_name": "CopyLogsToRepositoryStepFactory" + } + ] + }, + { + "step_description": "Cleanup", + "step_identifier": "testrun_cleanup", + "step_factories": [ + { + "module_path": "lab_system.master.steps.factory.cleanup.workdir", + "class_name": "CleanupWorkdirStepFactory" + }, + { + "module_path": "lab_system.master.steps.factory.run.chrome_mirroring_runner", + "class_name": "RemoveLogsOnMasterStepFactory" + } + ] + } + ] + }, + { + "group_name": "hp_core_i5_3210m_intelhd4000_win8_mtv", + "slave_name": "hp_core_i5_3210m_intelhd4000_win8_mtv", + "test_name": "chrome_mirroring", + "branch": "master", + "device_type": "eureka", + "device_group": "video_recorder_mtv", + "identifier": "hp_core_i5_3210m_intelhd4000_win8_mtv", + "scheduler": "none", + "step_factories": [ + { + "step_description": "Update Eureka build number, remove LOCAL_LOGS, update Chrome binaries and remove existing log files", + "step_identifier": "testrun_setup", + "step_factories": [ + { + "module_path": "lab_system.master.steps.factory.run.cloudview_runners.cloudview_chrome_mirroring_runner", + "class_name": "SetEurekaRecorderIpStepFactory" + }, + { + "module_path": "lab_system.master.steps.factory.sender.allocator", + "class_name": "SenderAllocatorStepFactory" + }, + { + "module_path": "lab_system.master.steps.factory.run.cloudview_runners.cloudview_chrome_mirroring_runner", + "class_name": "SetRecorderMachineIpStepFactory" + }, + { + "module_path": "lab_system.master.steps.factory.run.cloudview_runners.cloudview_chrome_mirroring_runner", + "class_name": "RemoveExistingLogFiles" + }, + { + "module_path": "lab_system.master.steps.factory.build.copy_test_repo", + "class_name": "CopyRepositoriesStepFactory" + }, + { + "module_path": "lab_system.master.steps.factory.chrome.download", + "class_name": "DownloadChromeStepFactory" + }, + { + "module_path": "lab_system.master.steps.factory.chrome.copy", + "class_name": "CopyChromeStepFactory" + }, + { + "module_path": "lab_system.master.steps.factory.extension.download_cws_extension", + "class_name": "DownloadWebStoreExtensionStepFactory" + }, + { + "module_path": "lab_system.master.steps.factory.extension.copy", + "class_name": "CopyExtensionStepFactory" + }, + { + "module_path": "lab_system.master.steps.factory.run.cloudview_runners.cloudview_chrome_mirroring_runner", + "class_name": "CopyConfigFilesStepFactory" + }, + { + "module_path": "lab_system.master.steps.factory.run.chrome_mirroring_runner", + "class_name": "SetLogs" + } + ] + }, + { + "step_description": "Runs chrome mirroring test", + "step_identifier": "test_running", + "step_factories": [ + { + "module_path": "lab_system.master.steps.factory.run.cloudview_runners.cloudview_chrome_mirroring_runner", + "class_name": "ChromeMirroringStepFactory" + }, + { + "module_path": "lab_system.master.steps.factory.device.deallocator", + "class_name": "DeviceDeallocatorStepFactory" + }, + { + "module_path": "lab_system.master.steps.factory.sender.deallocator", + "class_name": "SenderDeallocatorStepFactory" + } + ] + }, + { + "step_description": "Getting test result and them to Chrome Performance Dashboard", + "step_identifier": "output_processing", + "step_factories": [ + { + "module_path": "lab_system.master.steps.factory.run.cloudview_runners.cloudview_chrome_mirroring_runner", + "class_name": "CopyTestLogsStepFactory" + }, + { + "module_path": "lab_system.master.steps.factory.output.logs", + "class_name": "CopyLogsToRepositoryStepFactory" + }, + { + "module_path": "lab_system.master.steps.factory.run.chrome_mirroring_runner", + "class_name": "CopyResultToProcessorStepFactory" + }, + { + "module_path": "lab_system.master.steps.factory.run.chrome_mirroring_runner", + "class_name": "ProcessVideoStepFactory" + }, + { + "module_path": "lab_system.master.steps.factory.run.chrome_mirroring_runner", + "class_name": "CopyResultFromProcessorStepFactory" + }, + { + "module_path": "lab_system.master.steps.factory.output.logs", + "class_name": "CopyLogsToRepositoryStepFactory" + } + ] + }, + { + "step_description": "Cleanup", + "step_identifier": "testrun_cleanup", + "step_factories": [ + { + "module_path": "lab_system.master.steps.factory.cleanup.workdir", + "class_name": "CleanupWorkdirStepFactory" + }, + { + "module_path": "lab_system.master.steps.factory.run.chrome_mirroring_runner", + "class_name": "RemoveLogsOnMasterStepFactory" + } + ] + } + ] + }, + { + "group_name": "trial_machine_win", + "slave_name": "trial_machine_win", + "test_name": "chrome_mirroring", + "branch": "release", + "device_type": "eureka", + "device_group": "video_recorder_set_0", + "identifier": "trial_machine_win", + "scheduler": "none", + "step_factories": [ + { + "step_description": "Sets up testrun specific properties", + "step_identifier": "properties", + "step_factories": [ + { + "module_path": "lab_system.master.steps.factory.run.chrome_mirroring_runner", + "class_name": "MakeTempFiles" + }, + { + "module_path": "lab_system.master.steps.factory.run.chrome_mirroring_runner", + "class_name": "DownloadCustomCombinationsJson" + }, + { + "module_path": "lab_system.master.steps.factory.run.chrome_mirroring_runner", + "class_name": "OverwritePropertiesStepFactory" + } + ] + }, + { + "step_description": "Fetches and installs builds on devices", + "step_identifier": "build_handling", + "step_factories": [ + { + "module_path": "lab_system.master.steps.factory.run.chrome_mirroring_runner", + "class_name": "FetchEurekaOTAPackage" + }, + { + "module_path": "lab_system.master.steps.factory.run.chrome_mirroring_runner", + "class_name": "BuildInstallerStepFactory" + } + ] + }, + { + "step_description": "Update Eureka build number, remove LOCAL_LOGS, update Chrome binaries and remove existing log files", + "step_identifier": "testrun_setup", + "step_factories": [ + { + "module_path": "lab_system.master.steps.factory.run.cloudview_runners.cloudview_chrome_mirroring_runner", + "class_name": "SetEurekaRecorderIpStepFactory" + }, + { + "module_path": "lab_system.master.steps.factory.sender.allocator", + "class_name": "SenderAllocatorStepFactory" + }, + { + "module_path": "lab_system.master.steps.factory.run.cloudview_runners.cloudview_chrome_mirroring_runner", + "class_name": "SetRecorderMachineIpStepFactory" + }, + { + "module_path": "lab_system.master.steps.factory.run.cloudview_runners.cloudview_chrome_mirroring_runner", + "class_name": "RemoveExistingLogFiles" + }, + { + "module_path": "lab_system.master.steps.factory.build.copy_test_repo", + "class_name": "CopyRepositoriesStepFactory" + }, + { + "module_path": "lab_system.master.steps.factory.chrome.download", + "class_name": "DownloadChromeStepFactory" + }, + { + "module_path": "lab_system.master.steps.factory.chrome.copy", + "class_name": "CopyChromeStepFactory" + }, + { + "module_path": "lab_system.master.steps.factory.extension.download_cws_extension", + "class_name": "DownloadWebStoreExtensionStepFactory" + }, + { + "module_path": "lab_system.master.steps.factory.extension.copy", + "class_name": "CopyExtensionStepFactory" + }, + { + "module_path": "lab_system.master.steps.factory.run.cloudview_runners.cloudview_chrome_mirroring_runner", + "class_name": "CopyConfigFilesStepFactory" + } + ] + }, + { + "step_description": "Runs chrome mirroring test", + "step_identifier": "test_running", + "step_factories": [ + { + "module_path": "lab_system.master.steps.factory.run.cloudview_runners.cloudview_chrome_mirroring_runner", + "class_name": "ChromeMirroringStepFactory" + }, + { + "module_path": "lab_system.master.steps.factory.device.deallocator", + "class_name": "DeviceDeallocatorStepFactory" + }, + { + "module_path": "lab_system.master.steps.factory.sender.deallocator", + "class_name": "SenderDeallocatorStepFactory" + } + ] + }, + { + "step_description": "Getting test result and them to Chrome Performance Dashboard", + "step_identifier": "output_processing", + "step_factories": [ + { + "module_path": "lab_system.master.steps.factory.run.cloudview_runners.cloudview_chrome_mirroring_runner", + "class_name": "CopyTestLogsStepFactory" + }, + { + "module_path": "lab_system.master.steps.factory.output.logs", + "class_name": "CopyLogsToRepositoryStepFactory" + }, + { + "module_path": "lab_system.master.steps.factory.run.chrome_mirroring_runner", + "class_name": "CopyResultToProcessorStepFactory" + }, + { + "module_path": "lab_system.master.steps.factory.run.chrome_mirroring_runner", + "class_name": "ProcessVideoStepFactory" + }, + { + "module_path": "lab_system.master.steps.factory.run.chrome_mirroring_runner", + "class_name": "CopyResultFromProcessorStepFactory" + }, + { + "module_path": "lab_system.master.steps.factory.output.logs", + "class_name": "CopyLogsToRepositoryStepFactory" + } + ] + }, + { + "step_description": "Cleanup", + "step_identifier": "testrun_cleanup", + "step_factories": [ + { + "module_path": "lab_system.master.steps.factory.cleanup.workdir", + "class_name": "CleanupWorkdirStepFactory" + }, + { + "module_path": "lab_system.master.steps.factory.run.chrome_mirroring_runner", + "class_name": "RemoveLogsOnMasterStepFactory" + } + ] + } + ] + } +]
diff --git a/lab_system/master/config/kir/tests/server/server.cfg b/lab_system/master/config/kir/tests/server/server.cfg new file mode 100755 index 0000000..286153c --- /dev/null +++ b/lab_system/master/config/kir/tests/server/server.cfg
@@ -0,0 +1,11 @@ +# Config file for server tests +# +# Do not modify property names +# Run make reconfig if you change a value +# and buildbot is running +# +# PROPERTIES + +# Comma separated list defining valid IP addresses from which test results can +# be posted: +# RESULT_POST_IP_WHITELIST=
diff --git a/lab_system/master/config/kir/tests/server/test_defs.json b/lab_system/master/config/kir/tests/server/test_defs.json new file mode 100755 index 0000000..915bd0d --- /dev/null +++ b/lab_system/master/config/kir/tests/server/test_defs.json
@@ -0,0 +1,83 @@ +[ + { + "group_name": "server", + "slave_name": "server", + "test_name": "server", + "branch": "master", + "device_type": "dummy", + "identifier": "server", + "scheduler": "none", + "step_factories": [ + { + "step_description": "Overrides property setting - not necessary for unit tests", + "step_identifier": "properties", + "step_factories": [ + { + "module_path": "lab_system.master.steps.factory.common.noop", + "class_name": "NoopStepFactory" + } + ] + }, + { + "step_description": "Replaces device allocation with a no-op", + "step_identifier": "device_allocation", + "step_factories": [ + { + "module_path": "lab_system.master.steps.factory.common.noop", + "class_name": "NoopStepFactory" + } + ] + }, + { + "step_description": "Replaces build handling with a no-op", + "step_identifier": "build_handling", + "step_factories": [ + { + "module_path": "lab_system.master.steps.factory.common.noop", + "class_name": "NoopStepFactory" + } + ] + }, + { + "step_description": "Replaces testrun setup with a no-op", + "step_identifier": "testrun_setup", + "step_factories": [ + { + "module_path": "lab_system.master.steps.factory.common.noop", + "class_name": "NoopStepFactory" + } + ] + }, + { + "step_description": "Runs the unit tests", + "step_identifier": "test_running", + "step_factories": [ + { + "module_path": "lab_system.master.steps.factory.run.server", + "class_name": "WebServerStepFactory" + } + ] + }, + { + "step_description": "Replaces output processing with a no-op", + "step_identifier": "output_processing", + "step_factories": [ + { + "module_path": "lab_system.master.steps.factory.common.noop", + "class_name": "NoopStepFactory" + } + ] + }, + { + "step_description": "Replaces cleanup with a no-op", + "step_identifier": "testrun_cleanup", + "step_factories": [ + { + "module_path": "lab_system.master.steps.factory.common.noop", + "class_name": "NoopStepFactory" + } + ] + } + ] + } +]
diff --git a/lab_system/master/config/kir/tests/testingrepounittests/test_defs.json b/lab_system/master/config/kir/tests/testingrepounittests/test_defs.json new file mode 100755 index 0000000..80f54f6 --- /dev/null +++ b/lab_system/master/config/kir/tests/testingrepounittests/test_defs.json
@@ -0,0 +1,82 @@ +[ + { + "group_name": "testingrepounittests", + "slave_name": "testingrepounittests", + "test_name": "testingrepounittests", + "branch": "master", + "device_type": "dummy", + "identifier": "testingrepounittests", + "step_factories": [ + { + "step_description": "Overrides property setting - not necessary for server", + "step_identifier": "properties", + "step_factories": [ + { + "module_path": "lab_system.master.steps.factory.common.noop", + "class_name": "NoopStepFactory" + } + ] + }, + { + "step_description": "Replaces device allocation with a no-op", + "step_identifier": "device_allocation", + "step_factories": [ + { + "module_path": "lab_system.master.steps.factory.common.noop", + "class_name": "NoopStepFactory" + } + ] + }, + { + "step_description": "Replaces build handling with a no-op", + "step_identifier": "build_handling", + "step_factories": [ + { + "module_path": "lab_system.master.steps.factory.common.noop", + "class_name": "NoopStepFactory" + } + ] + }, + { + "step_description": "Replaces testrun setup with a no-op", + "step_identifier": "testrun_setup", + "step_factories": [ + { + "module_path": "lab_system.master.steps.factory.common.noop", + "class_name": "NoopStepFactory" + } + ] + }, + { + "step_description": "Runs the unit tests", + "step_identifier": "test_running", + "step_factories": [ + { + "module_path": "lab_system.master.steps.factory.run.unit", + "class_name": "UnitTestRunnerStepFactory" + } + ] + }, + { + "step_description": "Replaces output processing with a no-op", + "step_identifier": "output_processing", + "step_factories": [ + { + "module_path": "lab_system.master.steps.factory.common.noop", + "class_name": "NoopStepFactory" + } + ] + }, + { + "step_description": "Replaces cleanup with a no-op", + "step_identifier": "testrun_cleanup", + "step_factories": [ + { + "module_path": "lab_system.master.steps.factory.common.noop", + "class_name": "NoopStepFactory" + } + ] + } + ] + } +]
diff --git a/lab_system/master/config/kir/tests/testingrepounittests/testingrepounittests.cfg b/lab_system/master/config/kir/tests/testingrepounittests/testingrepounittests.cfg new file mode 100755 index 0000000..5be2d36 --- /dev/null +++ b/lab_system/master/config/kir/tests/testingrepounittests/testingrepounittests.cfg
@@ -0,0 +1,5 @@ +# Config file for repository unit tests +# +# Do not modify property names +# +# PROPERTIES
diff --git a/lab_system/master/config/plans/av_smokes b/lab_system/master/config/plans/av_smokes new file mode 100644 index 0000000..d1aad6f --- /dev/null +++ b/lab_system/master/config/plans/av_smokes
@@ -0,0 +1,2 @@ +video_formats SupportedVideoFormatsTestCase +audio_formats SupportedAudioFormatsTestCase
diff --git a/lab_system/master/config/plans/chirp_smoke b/lab_system/master/config/plans/chirp_smoke new file mode 100644 index 0000000..912bc56 --- /dev/null +++ b/lab_system/master/config/plans/chirp_smoke
@@ -0,0 +1,2 @@ +dictionary_latency_dogfood how_do_i_spell_vigorously +assistant_playback_latency_google_play_music play_some_music_for_dancing_on_google_play_music
diff --git a/lab_system/master/config/plans/drm b/lab_system/master/config/plans/drm new file mode 100644 index 0000000..448cd4d --- /dev/null +++ b/lab_system/master/config/plans/drm
@@ -0,0 +1,4 @@ +drm DrmPlayreadySmoothTestCase +drm DrmPlayreadyTestCase +drm DrmUnprefixedTestCase +drm DrmTestCase
diff --git a/lab_system/master/config/plans/performance b/lab_system/master/config/plans/performance new file mode 100644 index 0000000..88cd2c8 --- /dev/null +++ b/lab_system/master/config/plans/performance
@@ -0,0 +1,2 @@ +canvas_benchmarks +octane
diff --git a/lab_system/master/config/plans/smokes b/lab_system/master/config/plans/smokes new file mode 100644 index 0000000..13ac6f6 --- /dev/null +++ b/lab_system/master/config/plans/smokes
@@ -0,0 +1,7 @@ +audio_formats SupportedAudioFormatsTestCase +drm DrmPlayreadySmoothTestCase +drm DrmPlayreadyTestCase +drm DrmUnprefixedTestCase +drm DrmTestCase +receiver CastReceiverComplianceTestCase +video_formats SupportedVideoFormatsTestCase
diff --git a/lab_system/master/config/plans/uma_logging_background b/lab_system/master/config/plans/uma_logging_background new file mode 100644 index 0000000..ea03f64 --- /dev/null +++ b/lab_system/master/config/plans/uma_logging_background
@@ -0,0 +1,3 @@ +uma_logging UmaLoggingTestCase.testBackgroundSwappedIn +uma_logging UmaLoggingTestCase.testBackgroundReplaced +uma_logging UmaLoggingTestCase.testBackgroundCancelled
diff --git a/lab_system/master/config/site/site.cfg b/lab_system/master/config/site/site.cfg new file mode 100644 index 0000000..49b9fd8 --- /dev/null +++ b/lab_system/master/config/site/site.cfg
@@ -0,0 +1,198 @@ +# Config file for site wide values. +# +# These values are expected to change on a site by site basis. If the system +# is set up in a new location, these values would need to be changed to work +# at that location. +# +# Do not modify property names +# Run buildbot reconfig if you change a value and buildbot is running +# +# PROPERTIES + +# Path for internal unit tests. +INTERNAL_REPOSITORY_PATH=/usr/local/google/repositories/HEAD/continuous-tests + +# TODO(billiani): EUREKA_TEST_DIRECTORY should be HEAD/test. +EUREKA_TEST_DIRECTORY=/usr/local/google/repositories/HEAD + +#Gdb toolchain path +GDB_PATH=/usr/local/google/repositories/HEAD/toolchain/arm-unknown-linux-gnueabi-4.5.3-glibc/bin/arm-unknown-linux-gnueabi-gdb + +# Usage: GET_LATEST_BUILD_SCRIPT [options] +# +# Options: +# --branch=BRANCH branch to get latest build number +# --product=PRODUCT product to get latest build number +# --build_output_type=TYPE ota, symbols or tests +# --flavor eng or tests +# --build_number=BUILD number of build we want the path +# --output_mode path or number +# +# Uses to get path from a build number and to get a build number: +# get_latest_build.py --branch=%s --product=%s --build_number=%s +# --build_output_type=%s --flavor=%s --output_mode='path' +# get_latest_build.py --branch=%s --product=%s +# --build_output_type=%s --flavor=%s --output_mode='number' +# where script that prints path or latest build number is +GET_LATEST_BUILD_SCRIPT=/usr/local/google/repositories/HEAD/continuous-tests/build/get_latest_build.py + +# Root location where tests logs are stored +RESULTS=gs://fragglerock + +# GCS bucket to store test result JSON files +RESULT_JSON_BUCKET=gs://fr_json_logs + +# Run identifiers path +IDS_REPOSITORY=gs://fragglerock/run_identifiers + +# Base URL to Google Storage console +#GS_CONSOLE_BASE_URL=https://cloud.google.com/console#/storage/ +# Changing URL because of link redirect bug. +GS_CONSOLE_BASE_URL=https://console.developers.google.com/storage/ + +# Path to the base output directory in which all test data is written: +BASE_OUTPUT_DIRECTORY=/usr/local/google/staging/fraggle_rock/output + +# Run environment to use for this instance. This is used to differentiate +# multiple instances of the system. The value is used in several places, for +# example when building output directory paths. Suggested values for this are +# parameter are: prod, staging. +# TODO(billiani): Remove staging from PARSED, LOGS and CSV when using RUN_ENV +RUN_ENVIRONMENT=staging + +# where logs are stored when tests run +LOCAL_LOGS_DIRECTORY=/usr/local/google/staging/fraggle_rock/logs + +# Parsed http endpoint +PARSED_LINK=http://hivemind.mtv.corp.google.com/eureka/parsed + +# CSV root dir +CSV_ROOT=/var/www/eureka/csv + +# Waterfall server port +URL_PORT=8010 + +# Dashboard server port +SERVER_PORT=8080 + +# Server entry point +SERVER_HOSTNAME=0.0.0.0 + +# Continuous tests name +NAME=Home Continuous Tests System + +# master hostname +MASTER_HOSTNAME=home-lab-ci-master-1.mtv + +# Buildbot state db ip +STATE_DB=173.194.227.201 + +# Enables functionality that is only available within Google. If running +# externally, set this to 0 to ensure that all Google specific functionality is +# not run: +G_INTERNAL=1 + +# Database type. +# The currently supported backend databases are defined in db/database_types.py. +# The default database type is Sqlite. To use a Sqlite database: +# Set DB_TYPE=sqlite and set DB_PATH=/path, where path is the location where +# the Sqlite database will be stored. +# +# To use a PostgreSQL database: +# Set DB_TYPE=postgresql and set DB_PATH=/path, where path is the location where +# the PostgreSQL database configuration file exists. An example PostgreSQL +# configuration file is at db/db.config. +# +# NOTE: If using postgresql, the third party psycopg2 library must be installed +# in your python environment. If not, ImportErrors will occur when using any of +# the tools that interface with the database. +DB_TYPE=postgresql + +# For a PostgreSQL database backend (ie. DB_TYPE=postgresql), provide the path +# to the PostgreSQL database configuration file (see notes for DB_TYPE above). +# +# For a Sqlite database backend (ie. DB_TYPE=sqlite), provide the path to the +# Sqlite database file: +DB_PATH=/usr/local/google/repositories/HEAD/continuous-tests/db/db.config + +# Password for communication between buildbot master and slaves. This password +# should not be set to an actual user password. It purely governs the +# communication between the master and slaves. +MASTER_SLAVE_PASSWORD=buildbotmasterslavepassword + +# URL root for device-visible media server. This machine is accessible to all +# devices in the lab, and contains media, HTML and JavaScript files that are used +# in tests. +CNS_MEDIA_SERVER_URL=https://home-media-server.sandbox.google.com +GCS_MEDIA_SERVER_URL=https://home-media-server-staging.sandbox.google.com + +# The root path of the GCS media server bucket +GCS_ROOT_PATH=gs://home-media-server/dynamic + +# Path to Munin monitoring output: +MONITOR_FILE_PATH=/var/www/mtv/hivemind.mtv/ + +# FR6 test definition file root path. The buildbot master looks for +# subdirectories in this directory containing test_defs.json files. +# These files contain the definitions of the tests to run. +# This is an optional parameter; if it is not specified, the default test +# definitions directory (tests/) is used. +# FR6+ only. If using master.cfg prior to FR6, this parameter has no effect. +TESTS_DEFS_ROOT_PATH=tests/ + +# Mirroring test log file storage +REPORT_SERVER_PREFIX=https://cloud.google.com/console#/storage/fragglerock + +# Mirroring test status (HTML) storage +MIRRORING_REPORT_SERVER=gtvchrome@172.17.21.60 + +# Mirroring test results directory +MIRRORING_REPORT_DIRECTORY=/var/www/gtv/mirroring_report + +# Chrome Cast Extension folder, the extension files under this folder +# will be copied to remote machine, and the extension will be used in test. +EXTENSION_FOLDER=/usr/local/google/home/repositories/data/extension + +# Test html and js files folder, it should contain all the test html and js +# files for Chrome SDK end to end test. All the files under this folder will +# be copied to HTTPS server during SDK end to end test. +TEST_FILES_FOLDER=/usr/local/google/home/repositories/data/tests + +# Path to local directory to store chrome_sdk binary +CHROME_SDK_TEST_DATA_FOLDER=/usr/local/google/staging/fraggle_rock/chrome_sdk + +# The type of access point manager used for allocation/deallocation of +# access points. It can have one of two values "chaos" for Chrome Chaos +# lab infrastructure or "testing" for a testing purposes access point allocator. +ACCESS_POINT_MANAGER_TYPE=chaos + +# Location where build status JSON is expected: +BUILD_STATUS_DIRECTORY_PATH=/tmp/build/status/ + +# Port used for communication between master and slaves: +MASTER_SLAVE_PORT_NUMBER=8014 + +# Google Cloud project id +CLOUD_STORAGE_PROJECT_ID=634486810642 + +# Log pushers used to copy logs to their final destinations. +# Currently supported types are CLOUD_STORAGE and LOCAL_LINUX +LOG_PUSHERS=[{"type":"LOCAL_LINUX", "path": "/usr/local/google/staging/fraggle_rock/logs"}] + +# URL endpoint for the chromeperf dashboard for adding data. Your host must be +# whitelisted to use the default value. A dev endpoint is available at: +# https://chrome-perf.googleplex.com/add_point +# This endpoint will accept data and return a 200 if it is correctly formatted. +CHROME_PERF_UPLOAD_URL=https://chromeperf.appspot.com/add_point + +# Link template to allow for referencing code from our results viewer into GoB. +EUREKA_REPO_LINK=https://eureka-internal.git.corp.google.com/{}/+/master/{}#{} + +# Test repo url +TEST_REPO_LINK=https://eureka-internal.git.corp.google.com/test/+/ + +# Signed GmsCore APK Directory +SIGNED_GMSCORE_DIR=/google/data/ro/teams/cast-test/gmscore/latest_signed + +# Android build artifact fetcher +ANDROID_FETCH_ARTIFACT_BINARY=/google/data/ro/projects/android/fetch_artifact
diff --git a/lab_system/master/config/step_factories_recipes/android_mirroring.json b/lab_system/master/config/step_factories_recipes/android_mirroring.json new file mode 100644 index 0000000..fe57400 --- /dev/null +++ b/lab_system/master/config/step_factories_recipes/android_mirroring.json
@@ -0,0 +1,106 @@ +[ + { + "step_description": "Sets up testrun specific properties", + "step_factories": [ + { + "class_name": "RecordingPropertiesSetterStepFactory", + "module_path": "lab_system.master.steps.factory.run.android_mirroring_runner" + } + ], + "step_identifier": "properties" + }, + { + "step_description": "Allocates devices for the testrun", + "step_factories": [ + { + "class_name": "DeviceAllocatorStepFactory", + "module_path": "lab_system.master.steps.factory.run.android_mirroring_runner" + } + ], + "step_identifier": "device_allocation" + }, + { + "step_description": "Copying Build to test slave and installing on device", + "step_factories": [ + { + "class_name": "RsyncRepositoriesStepFactory", + "module_path": "lab_system.master.steps.factory.build.copy_test_repo" + }, + { + "class_name": "DefaultOtaFetcherStepFactory", + "module_path": "lab_system.master.steps.factory.build.fetcher" + }, + { + "class_name": "CopyBuildToSlaveStepFactory", + "module_path": "lab_system.master.steps.factory.run.android_mirroring_runner" + }, + { + "class_name": "TurnOnSpecificDevice", + "module_path": "lab_system.master.steps.factory.run.android_mirroring_runner" + }, + { + "class_name": "InstallBuildStepFactory", + "module_path": "lab_system.master.steps.factory.run.android_mirroring_runner" + } + ], + "step_identifier": "build_handling" + }, + { + "step_description": "Sets up logging", + "step_factories": [ + { + "class_name": "NoopStepFactory", + "module_path": "lab_system.master.steps.factory.common.noop" + } + ], + "step_identifier": "testrun_setup" + }, + { + "step_description": "Runs Android Mirroring Test", + "step_factories": [ + { + "class_name": "AndroidMirroringStepFactory", + "module_path": "lab_system.master.steps.factory.run.android_mirroring_runner" + } + ], + "step_identifier": "test_running" + }, + { + "step_description": "Copies local log files to Google Storage", + "step_factories": [ + { + "class_name": "NoopStepFactory", + "module_path": "lab_system.master.steps.factory.common.noop" + } + ], + "step_identifier": "logs_copy" + }, + { + "step_description": "Processes the output of the test", + "step_factories": [ + { + "class_name": "GetLogcatStepFactory", + "module_path": "lab_system.master.steps.factory.run.android_mirroring_runner" + }, + { + "class_name": "CopyLogsToRepositoryStepFactory", + "module_path": "lab_system.master.steps.factory.run.android_mirroring_runner" + } + ], + "step_identifier": "output_processing" + }, + { + "step_description": "Cleans up slave and devices after the testrun", + "step_identifier": "testrun_cleanup", + "step_factories": [ + { + "module_path": "lab_system.master.steps.factory.device.cloud_deallocator", + "class_name": "DeviceDeallocatorStepFactory" + }, + { + "module_path": "lab_system.master.steps.factory.cleanup.workdir", + "class_name": "CleanupWorkdirStepFactory" + } + ] + } +]
diff --git a/lab_system/master/config/step_factories_recipes/android_mirroring_cast_tv.json b/lab_system/master/config/step_factories_recipes/android_mirroring_cast_tv.json new file mode 100644 index 0000000..f8f2405 --- /dev/null +++ b/lab_system/master/config/step_factories_recipes/android_mirroring_cast_tv.json
@@ -0,0 +1,102 @@ +[ + { + "step_description": "Sets up testrun specific properties", + "step_factories": [ + { + "class_name": "RecordingPropertiesSetterStepFactory", + "module_path": "lab_system.master.steps.factory.run.android_mirroring_runner" + } + ], + "step_identifier": "properties" + }, + { + "step_description": "Allocates devices for the testrun", + "step_factories": [ + { + "class_name": "DeviceAllocatorStepFactory", + "module_path": "lab_system.master.steps.factory.run.android_mirroring_runner" + } + ], + "step_identifier": "device_allocation" + }, + { + "step_description": "Copying Build to test slave and installing on device", + "step_factories": [ + { + "class_name": "RsyncRepositoriesStepFactory", + "module_path": "lab_system.master.steps.factory.build.copy_test_repo" + }, + { + "class_name": "DefaultOtaFetcherStepFactory", + "module_path": "lab_system.master.steps.factory.build.fetcher" + }, + { + "class_name": "CopyBuildToSlaveStepFactory", + "module_path": "lab_system.master.steps.factory.run.android_mirroring_runner" + }, + { + "class_name": "InstallBuildStepFactory", + "module_path": "lab_system.master.steps.factory.run.android_mirroring_runner" + } + ], + "step_identifier": "build_handling" + }, + { + "step_description": "Sets up logging", + "step_factories": [ + { + "class_name": "NoopStepFactory", + "module_path": "lab_system.master.steps.factory.common.noop" + } + ], + "step_identifier": "testrun_setup" + }, + { + "step_description": "Runs Android Mirroring Test", + "step_factories": [ + { + "class_name": "AndroidMirroringStepFactory", + "module_path": "lab_system.master.steps.factory.run.android_mirroring_runner" + } + ], + "step_identifier": "test_running" + }, + { + "step_description": "Copies local log files to Google Storage", + "step_factories": [ + { + "class_name": "NoopStepFactory", + "module_path": "lab_system.master.steps.factory.common.noop" + } + ], + "step_identifier": "logs_copy" + }, + { + "step_description": "Processes the output of the test", + "step_factories": [ + { + "class_name": "GetLogcatStepFactory", + "module_path": "lab_system.master.steps.factory.run.android_mirroring_runner" + }, + { + "class_name": "CopyLogsToRepositoryStepFactory", + "module_path": "lab_system.master.steps.factory.run.android_mirroring_runner" + } + ], + "step_identifier": "output_processing" + }, + { + "step_description": "Cleans up slave and devices after the testrun", + "step_identifier": "testrun_cleanup", + "step_factories": [ + { + "module_path": "lab_system.master.steps.factory.device.deallocator", + "class_name": "DeviceDeallocatorStepFactory" + }, + { + "module_path": "lab_system.master.steps.factory.cleanup.workdir", + "class_name": "CleanupWorkdirStepFactory" + } + ] + } +]
diff --git a/lab_system/master/config/step_factories_recipes/android_mirroring_nexus_player.json b/lab_system/master/config/step_factories_recipes/android_mirroring_nexus_player.json new file mode 100644 index 0000000..1b65ab4 --- /dev/null +++ b/lab_system/master/config/step_factories_recipes/android_mirroring_nexus_player.json
@@ -0,0 +1,102 @@ +[ + { + "step_description": "Sets up testrun specific properties", + "step_factories": [ + { + "class_name": "RecordingPropertiesSetterStepFactory", + "module_path": "lab_system.master.steps.factory.run.android_mirroring_runner" + } + ], + "step_identifier": "properties" + }, + { + "step_description": "Allocates devices for the testrun", + "step_factories": [ + { + "class_name": "DeviceAllocatorStepFactory", + "module_path": "lab_system.master.steps.factory.run.android_mirroring_runner" + } + ], + "step_identifier": "device_allocation" + }, + { + "step_description": "Copying Build to test slave and installing on device", + "step_factories": [ + { + "class_name": "RsyncRepositoriesStepFactory", + "module_path": "lab_system.master.steps.factory.build.copy_test_repo" + }, + { + "class_name": "DefaultOtaFetcherStepFactory", + "module_path": "lab_system.master.steps.factory.build.fetcher" + }, + { + "class_name": "CopyBuildToSlaveStepFactory", + "module_path": "lab_system.master.steps.factory.run.android_mirroring_runner" + }, + { + "class_name": "InstallBuildStepFactory", + "module_path": "lab_system.master.steps.factory.run.android_mirroring_nexus_player_runner" + } + ], + "step_identifier": "build_handling" + }, + { + "step_description": "Sets up logging", + "step_factories": [ + { + "class_name": "NoopStepFactory", + "module_path": "lab_system.master.steps.factory.common.noop" + } + ], + "step_identifier": "testrun_setup" + }, + { + "step_description": "Runs Android Mirroring Test", + "step_factories": [ + { + "class_name": "AndroidMirroringStepFactory", + "module_path": "lab_system.master.steps.factory.run.android_mirroring_nexus_player_runner" + }, + { + "module_path": "lab_system.master.steps.factory.device.deallocator", + "class_name": "DeviceDeallocatorStepFactory" + } + ], + "step_identifier": "test_running" + }, + { + "step_description": "Copies local log files to Google Storage", + "step_factories": [ + { + "class_name": "NoopStepFactory", + "module_path": "lab_system.master.steps.factory.common.noop" + } + ], + "step_identifier": "logs_copy" + }, + { + "step_description": "Processes the output of the test", + "step_factories": [ + { + "class_name": "GetLogcatStepFactory", + "module_path": "lab_system.master.steps.factory.run.android_mirroring_runner" + }, + { + "class_name": "CopyLogsToRepositoryStepFactory", + "module_path": "lab_system.master.steps.factory.run.android_mirroring_runner" + } + ], + "step_identifier": "output_processing" + }, + { + "step_description": "Cleans up slave and devices after the testrun", + "step_identifier": "testrun_cleanup", + "step_factories": [ + { + "module_path": "lab_system.master.steps.factory.cleanup.workdir", + "class_name": "CleanupWorkdirStepFactory" + } + ] + } +]
diff --git a/lab_system/master/config/step_factories_recipes/android_mirroring_uma.json b/lab_system/master/config/step_factories_recipes/android_mirroring_uma.json new file mode 100644 index 0000000..cf88d84 --- /dev/null +++ b/lab_system/master/config/step_factories_recipes/android_mirroring_uma.json
@@ -0,0 +1,106 @@ +[ + { + "step_description": "Sets up testrun specific properties", + "step_factories": [ + { + "class_name": "RecordingPropertiesSetterStepFactory", + "module_path": "lab_system.master.steps.factory.run.android_mirroring_runner" + } + ], + "step_identifier": "properties" + }, + { + "step_description": "Allocates devices for the testrun", + "step_factories": [ + { + "class_name": "ReducedLeaseDeviceAllocatorStepFactory", + "module_path": "lab_system.master.steps.factory.device.cloud_allocator" + } + ], + "step_identifier": "device_allocation" + }, + { + "step_description": "Copying Build to test slave and installing on device", + "step_factories": [ + { + "class_name": "RsyncRepositoriesStepFactory", + "module_path": "lab_system.master.steps.factory.build.copy_test_repo" + }, + { + "class_name": "DefaultOtaFetcherStepFactory", + "module_path": "lab_system.master.steps.factory.build.fetcher" + }, + { + "class_name": "CopyBuildToSlaveStepFactory", + "module_path": "lab_system.master.steps.factory.run.android_mirroring_runner" + }, + { + "class_name": "InstallBuildStepFactory", + "module_path": "lab_system.master.steps.factory.run.android_mirroring_runner" + } + ], + "step_identifier": "build_handling" + }, + { + "step_description": "Sets up logging", + "step_factories": [ + { + "class_name": "NoopStepFactory", + "module_path": "lab_system.master.steps.factory.common.noop" + } + ], + "step_identifier": "testrun_setup" + }, + { + "step_description": "Runs Android Mirroring Test", + "step_factories": [ + { + "class_name": "AndroidMirroringUmaStepFactory", + "module_path": "lab_system.master.steps.factory.run.android_mirroring_runner" + } + ], + "step_identifier": "test_running" + }, + { + "step_description": "Copies local log files to Google Storage", + "step_factories": [ + { + "class_name": "NoopStepFactory", + "module_path": "lab_system.master.steps.factory.common.noop" + } + ], + "step_identifier": "logs_copy" + }, + { + "step_description": "Processes the output of the test", + "step_factories": [ + { + "class_name": "GetUmaTestLogsStepFactory", + "module_path": "lab_system.master.steps.factory.run.android_mirroring_runner" + }, + { + "class_name": "UploadScreenCastTestResultStepFactory", + "module_path": "lab_system.master.steps.factory.run.android_mirroring_runner" + }, + { + "class_name": "CopyLogsToRepositoryStepFactory", + "module_path": "lab_system.master.steps.factory.output.logs" + } + ], + "step_identifier": "output_processing" + }, + { + "step_description": "Cleans up slave and devices after the testrun", + "step_identifier": "testrun_cleanup", + "step_factories": [ + { + "module_path": "lab_system.master.steps.factory.device.cloud_deallocator", + "class_name": "DeviceDeallocatorStepFactory" + }, + { + "module_path": "lab_system.master.steps.factory.cleanup.workdir", + "class_name": "CleanupWorkdirStepFactory" + } + ] + } +]
diff --git a/lab_system/master/config/step_factories_recipes/androidthings_cast_test_recipe.json b/lab_system/master/config/step_factories_recipes/androidthings_cast_test_recipe.json new file mode 100644 index 0000000..893827b --- /dev/null +++ b/lab_system/master/config/step_factories_recipes/androidthings_cast_test_recipe.json
@@ -0,0 +1,142 @@ +[ + { + "step_description": "Sets up testrun specific properties", + "step_factories": [ + { + "class_name": "AtvPropertiesSetterStepFactory", + "module_path": "lab_system.master.steps.factory.run.atv_cast_test_runner" + }, + { + "class_name": "AddUnitTestMarkerStepFactory", + "module_path": "lab_system.master.steps.factory.run.unit_test_runner" + } + ], + "step_identifier": "properties" + }, + { + "step_description": "Allocates devices for the testrun", + "step_factories": [ + { + "class_name": "DeviceAllocatorStepFactory", + "module_path": "lab_system.master.steps.factory.device.cloud_allocator" + }, + { + "class_name": "GetFirstDeviceIpAddrStepFactory", + "module_path": "lab_system.master.steps.factory.device.allocator" + }, + { + "class_name": "RsyncRepositoriesStepFactory", + "module_path": "lab_system.master.steps.factory.build.copy_atv_test_repo" + }, + { + "class_name": "SetAtvIpAddrStepFactory", + "module_path": "lab_system.master.steps.factory.run.atv_cast_test_runner" + } + ], + "step_identifier": "device_allocation" + }, + { + "step_description": "Fetches and installs builds on devices", + "step_factories": [ + { + "class_name": "DownloadAndroidThingsArtifactStepFactory", + "module_path": "lab_system.master.steps.factory.run.androidthings_unit_test_runner" + }, + { + "class_name": "CopyAndroidThingsArtifactToDeviceStepFactory", + "module_path": "lab_system.master.steps.factory.run.androidthings_unit_test_runner" + }, + { + "class_name": "FlashAndroidThingsBuildToDeviceStepFactory", + "module_path": "lab_system.master.steps.factory.run.androidthings_unit_test_runner" + }, + { + "class_name": "AtvCastShellApkFetcherStepFactory", + "module_path": "lab_system.master.steps.factory.run.atv_cast_test_runner" + }, + { + "class_name": "CopyBuildToSlaveStepFactory", + "module_path": "lab_system.master.steps.factory.run.atv_cast_test_runner" + }, + { + "class_name": "InstallBuildStepFactory", + "module_path": "lab_system.master.steps.factory.run.atv_cast_test_runner" + }, + { + "class_name": "InstallCertAndStartCastReceiverStepFactory", + "module_path": "lab_system.master.steps.factory.run.androidthings_cast_test_runner" + } + ], + "step_identifier": "build_handling" + }, + { + "step_description": "Prepare Android TV", + "step_factories": [ + { + "class_name": "StartAtvPersistentLoggingStepFactory", + "module_path": "lab_system.master.steps.factory.run.atv_cast_test_runner" + } + ], + "step_identifier": "testrun_setup" + }, + { + "step_description": "Runs cast test.", + "step_factories": [ + { + "class_name": "AtvTestRunStepFactory", + "module_path": "lab_system.master.steps.factory.run.atv_cast_test_runner" + }, + { + "class_name": "GetAtvPersistentLogStepFactory", + "module_path": "lab_system.master.steps.factory.run.atv_cast_test_runner" + }, + { + "class_name": "GetLogcatStepFactory", + "module_path": "lab_system.master.steps.factory.run.atv_cast_test_runner" + }, + { + "class_name": "UploadResultToSpongeStepFactory", + "module_path": "lab_system.master.steps.factory.run.atv_cast_test_runner" + } + ], + "step_identifier": "test_running" + }, + { + "step_description": "Copy Logs", + "step_factories": [ + { + "class_name": "CopyLogsFromTimeStampedDirToRepositoryStepFactory", + "module_path": "lab_system.master.steps.factory.output.cloud_logs" + } + ], + "step_identifier": "logs_copy" + }, + { + "step_description": "Updates the good_to_test hint.", + "step_factories": [ + { + "class_name": "NoopStepFactory", + "module_path": "lab_system.master.steps.factory.common.noop" + } + ], + "step_identifier": "output_processing" + }, + { + "step_description": "Cleans up slave and devices after the testrun", + "step_factories": [ + { + "class_name": "DeviceDeallocatorStepFactory", + "module_path": "lab_system.master.steps.factory.device.cloud_deallocator" + }, + { + "class_name": "RemoveUnitTestMarkerStepFactory", + "module_path": "lab_system.master.steps.factory.run.unit_test_runner" + }, + { + "class_name": "CleanupWorkdirStepFactory", + "module_path": "lab_system.master.steps.factory.cleanup.workdir" + } + ], + "step_identifier": "testrun_cleanup" + } +]
diff --git a/lab_system/master/config/step_factories_recipes/androidthings_unit_test_recipe.json b/lab_system/master/config/step_factories_recipes/androidthings_unit_test_recipe.json new file mode 100644 index 0000000..78a7d35 --- /dev/null +++ b/lab_system/master/config/step_factories_recipes/androidthings_unit_test_recipe.json
@@ -0,0 +1,122 @@ +[ + { + "step_description": "Sets up testrun specific properties", + "step_factories": [ + { + "class_name": "UnitTestTmpSetterStepFactory", + "module_path": "lab_system.master.steps.factory.run.atv_unit_test_runner" + }, + { + "class_name": "UnitTestPropertiesSetterStepFactory", + "module_path": "lab_system.master.steps.factory.run.atv_unit_test_runner" + } + ], + "step_identifier": "properties" + }, + { + "step_description": "Allocates devices for the testrun", + "step_factories": [ + { + "class_name": "DeviceAllocatorStepFactory", + "module_path": "lab_system.master.steps.factory.device.cloud_allocator" + }, + { + "class_name": "GetFirstDeviceIpAddrStepFactory", + "module_path": "lab_system.master.steps.factory.device.allocator" + }, + { + "class_name": "RsyncRepositoriesStepFactory", + "module_path": "lab_system.master.steps.factory.build.copy_atv_test_repo" + }, + { + "class_name": "SetAtvIpAddrStepFactory", + "module_path": "lab_system.master.steps.factory.run.atv_cast_test_runner" + } + ], + "step_identifier": "device_allocation" + }, + { + "step_description": "Fetches and installs builds on devices", + "step_factories": [ + { + "class_name": "BuildFetcherStepFactory", + "module_path": "lab_system.master.steps.factory.run.atv_unit_test_runner" + }, + { + "class_name": "CopyBuildToSlaveStepFactory", + "module_path": "lab_system.master.steps.factory.build.copy_atv_test_repo" + }, + { + "class_name": "DownloadAndroidThingsArtifactStepFactory", + "module_path": "lab_system.master.steps.factory.run.androidthings_unit_test_runner" + }, + { + "class_name": "CopyAndroidThingsArtifactToDeviceStepFactory", + "module_path": "lab_system.master.steps.factory.run.androidthings_unit_test_runner" + }, + { + "class_name": "FlashAndroidThingsBuildToDeviceStepFactory", + "module_path": "lab_system.master.steps.factory.run.androidthings_unit_test_runner" + } + ], + "step_identifier": "build_handling" + }, + { + "step_description": "Unzip test apk files", + "step_factories": [ + { + "class_name": "PrepDeviceStepFactory", + "module_path": "lab_system.master.steps.factory.run.atv_unit_test_runner" + } + ], + "step_identifier": "testrun_setup" + }, + { + "step_description": "Runs unit test.", + "step_factories": [ + { + "class_name": "UnitTestRunStepFactory", + "module_path": "lab_system.master.steps.factory.run.atv_unit_test_runner" + }, + { + "class_name": "UploadResultToSpongeStepFactory", + "module_path": "lab_system.master.steps.factory.run.atv_unit_test_runner" + } + ], + "step_identifier": "test_running" + }, + { + "step_description": "Copy Logs", + "step_factories": [ + { + "class_name": "CopyLogsFromRootToRepositoryStepFactory", + "module_path": "lab_system.master.steps.factory.output.cloud_logs" + } + ], + "step_identifier": "logs_copy" + }, + { + "step_description": "Updates the good_to_test hint.", + "step_factories": [ + { + "class_name": "CreateHintStepFactory", + "module_path": "lab_system.master.steps.factory.run.atv_unit_test_runner" + } + ], + "step_identifier": "output_processing" + }, + { + "step_description": "Cleans up slave and devices after the testrun", + "step_factories": [ + { + "class_name": "DeviceDeallocatorStepFactory", + "module_path": "lab_system.master.steps.factory.device.cloud_deallocator" + }, + { + "class_name": "CleanupWorkdirStepFactory", + "module_path": "lab_system.master.steps.factory.cleanup.workdir" + } + ], + "step_identifier": "testrun_cleanup" + } +]
diff --git a/lab_system/master/config/step_factories_recipes/assistant_unit_test_recipe.json b/lab_system/master/config/step_factories_recipes/assistant_unit_test_recipe.json new file mode 100644 index 0000000..9aa9b47 --- /dev/null +++ b/lab_system/master/config/step_factories_recipes/assistant_unit_test_recipe.json
@@ -0,0 +1,110 @@ +[ + { + "step_description": "Sets up testrun specific properties", + "step_factories": [ + { + "class_name": "PropertiesSetterStepFactoryWithDummyBuild", + "module_path": "lab_system.master.steps.factory.setup.properties" + }, + { + "class_name": "AddUnitTestMarkerStepFactory", + "module_path": "lab_system.master.steps.factory.run.unit_test_runner" + } + ], + "step_identifier": "properties" + }, + { + "step_description": "Allocates devices for the testrun", + "step_factories": [ + { + "class_name": "ReducedLeaseDeviceAllocatorStepFactory", + "module_path": "lab_system.master.steps.factory.device.cloud_allocator" + }, + { + "class_name": "GetFirstDeviceIpAddrStepFactory", + "module_path": "lab_system.master.steps.factory.device.allocator" + } + ], + "step_identifier": "device_allocation" + }, + { + "step_description": "Fetches and installs builds on devices", + "step_factories": [ + { + "class_name": "DefaultOtaFetcherStepFactory", + "module_path": "lab_system.master.steps.factory.build.fetcher" + }, + { + "class_name": "BuildInstallerWithoutFormatRollbackStartedMarkerStepFactory", + "module_path": "lab_system.master.steps.factory.run.unit_test_runner" + } + ], + "step_identifier": "build_handling" + }, + { + "step_description": "Installs test binaries to unit test device", + "step_factories": [ + { + "class_name": "PrepDeviceRollbackStartedMarkerStepFactory", + "module_path": "lab_system.master.steps.factory.run.unit_test_runner" + } + ], + "step_identifier": "testrun_setup" + }, + { + "step_description": "Runs unit test.", + "step_factories": [ + { + "class_name": "UnitTestRunStepFactory", + "module_path": "lab_system.master.steps.factory.run.unit_test_runner" + }, + { + "class_name": "UploadResultToSpongeRollbackStartedMarkerStepFactory", + "module_path": "lab_system.master.steps.factory.run.unit_test_runner" + } + ], + "step_identifier": "test_running" + }, + { + "step_description": "Copy log files", + "step_factories": [ + { + "class_name": "CopyLogStepFactory", + "module_path": "lab_system.master.steps.factory.run.unit_test_runner" + }, + { + "class_name": "CopyLogsFromRootToRepositoryStepFactory", + "module_path": "lab_system.master.steps.factory.output.cloud_logs" + } + ], + "step_identifier": "logs_copy" + }, + { + "step_description": "A placeholder with no-ops to allow custom logs parsing.", + "step_factories": [ + { + "class_name": "NoopStepFactory", + "module_path": "lab_system.master.steps.factory.common.noop" + } + ], + "step_identifier": "output_processing" + }, + { + "step_description": "Cleans up slave and devices after the testrun", + "step_factories": [ + { + "class_name": "DeviceDeallocatorStepFactory", + "module_path": "lab_system.master.steps.factory.device.cloud_deallocator" + }, + { + "class_name": "RemoveUnitTestMarkerStepFactory", + "module_path": "lab_system.master.steps.factory.run.unit_test_runner" + }, + { + "class_name": "CleanupWorkdirStepFactory", + "module_path": "lab_system.master.steps.factory.cleanup.workdir" + } + ], + "step_identifier": "testrun_cleanup" + } +]
diff --git a/lab_system/master/config/step_factories_recipes/atv_cast_test_recipe.json b/lab_system/master/config/step_factories_recipes/atv_cast_test_recipe.json new file mode 100644 index 0000000..4dab8fc --- /dev/null +++ b/lab_system/master/config/step_factories_recipes/atv_cast_test_recipe.json
@@ -0,0 +1,126 @@ +[ + { + "step_description": "Sets up testrun specific properties", + "step_factories": [ + { + "class_name": "AtvPropertiesSetterStepFactory", + "module_path": "lab_system.master.steps.factory.run.atv_cast_test_runner" + }, + { + "class_name": "AddUnitTestMarkerStepFactory", + "module_path": "lab_system.master.steps.factory.run.unit_test_runner" + } + ], + "step_identifier": "properties" + }, + { + "step_description": "Allocates devices for the testrun", + "step_factories": [ + { + "class_name": "DeviceAllocatorStepFactory", + "module_path": "lab_system.master.steps.factory.device.cloud_allocator" + }, + { + "class_name": "GetFirstDeviceIpAddrStepFactory", + "module_path": "lab_system.master.steps.factory.device.allocator" + }, + { + "class_name": "RsyncRepositoriesStepFactory", + "module_path": "lab_system.master.steps.factory.build.copy_atv_test_repo" + }, + { + "class_name": "SetAtvIpAddrStepFactory", + "module_path": "lab_system.master.steps.factory.run.atv_cast_test_runner" + } + ], + "step_identifier": "device_allocation" + }, + { + "step_description": "Fetches and installs builds on devices", + "step_factories": [ + { + "class_name": "AtvCastShellApkFetcherStepFactory", + "module_path": "lab_system.master.steps.factory.run.atv_cast_test_runner" + }, + { + "class_name": "CopyBuildToSlaveStepFactory", + "module_path": "lab_system.master.steps.factory.run.atv_cast_test_runner" + }, + { + "class_name": "InstallBuildStepFactory", + "module_path": "lab_system.master.steps.factory.run.atv_cast_test_runner" + } + ], + "step_identifier": "build_handling" + }, + { + "step_description": "Prepare Android TV", + "step_factories": [ + { + "class_name": "StartAtvPersistentLoggingStepFactory", + "module_path": "lab_system.master.steps.factory.run.atv_cast_test_runner" + } + ], + "step_identifier": "testrun_setup" + }, + { + "step_description": "Runs cast test.", + "step_factories": [ + { + "class_name": "AtvTestRunStepFactory", + "module_path": "lab_system.master.steps.factory.run.atv_cast_test_runner" + }, + { + "class_name": "GetAtvPersistentLogStepFactory", + "module_path": "lab_system.master.steps.factory.run.atv_cast_test_runner" + }, + { + "class_name": "GetLogcatStepFactory", + "module_path": "lab_system.master.steps.factory.run.atv_cast_test_runner" + }, + { + "class_name": "UploadResultToSpongeStepFactory", + "module_path": "lab_system.master.steps.factory.run.atv_cast_test_runner" + } + ], + "step_identifier": "test_running" + }, + { + "step_description": "Copy Logs", + "step_factories": [ + { + "class_name": "CopyLogsFromTimeStampedDirToRepositoryStepFactory", + "module_path": "lab_system.master.steps.factory.output.cloud_logs" + } + ], + "step_identifier": "logs_copy" + }, + { + "step_description": "Updates the good_to_test hint.", + "step_factories": [ + { + "class_name": "NoopStepFactory", + "module_path": "lab_system.master.steps.factory.common.noop" + } + ], + "step_identifier": "output_processing" + }, + { + "step_description": "Cleans up slave and devices after the testrun", + "step_factories": [ + { + "class_name": "DeviceDeallocatorStepFactory", + "module_path": "lab_system.master.steps.factory.device.cloud_deallocator" + }, + { + "class_name": "RemoveUnitTestMarkerStepFactory", + "module_path": "lab_system.master.steps.factory.run.unit_test_runner" + }, + { + "class_name": "CleanupWorkdirStepFactory", + "module_path": "lab_system.master.steps.factory.cleanup.workdir" + } + ], + "step_identifier": "testrun_cleanup" + } +]
diff --git a/lab_system/master/config/step_factories_recipes/atv_unit_test_recipe.json b/lab_system/master/config/step_factories_recipes/atv_unit_test_recipe.json new file mode 100644 index 0000000..dd3d21d --- /dev/null +++ b/lab_system/master/config/step_factories_recipes/atv_unit_test_recipe.json
@@ -0,0 +1,106 @@ +[ + { + "step_description": "Sets up testrun specific properties", + "step_factories": [ + { + "class_name": "UnitTestTmpSetterStepFactory", + "module_path": "lab_system.master.steps.factory.run.atv_unit_test_runner" + }, + { + "class_name": "UnitTestPropertiesSetterStepFactory", + "module_path": "lab_system.master.steps.factory.run.atv_unit_test_runner" + } + ], + "step_identifier": "properties" + }, + { + "step_description": "Allocates devices for the testrun", + "step_factories": [ + { + "class_name": "DeviceAllocatorStepFactory", + "module_path": "lab_system.master.steps.factory.device.cloud_allocator" + }, + { + "class_name": "GetFirstDeviceIpAddrStepFactory", + "module_path": "lab_system.master.steps.factory.device.allocator" + }, + { + "class_name": "RsyncRepositoriesStepFactory", + "module_path": "lab_system.master.steps.factory.build.copy_atv_test_repo" + } + ], + "step_identifier": "device_allocation" + }, + { + "step_description": "Fetches and installs builds on devices", + "step_factories": [ + { + "class_name": "BuildFetcherStepFactory", + "module_path": "lab_system.master.steps.factory.run.atv_unit_test_runner" + }, + { + "class_name": "CopyBuildToSlaveStepFactory", + "module_path": "lab_system.master.steps.factory.build.copy_atv_test_repo" + } + ], + "step_identifier": "build_handling" + }, + { + "step_description": "Unzip test apk files", + "step_factories": [ + { + "class_name": "PrepDeviceStepFactory", + "module_path": "lab_system.master.steps.factory.run.atv_unit_test_runner" + } + ], + "step_identifier": "testrun_setup" + }, + { + "step_description": "Runs unit test.", + "step_factories": [ + { + "class_name": "UnitTestRunStepFactory", + "module_path": "lab_system.master.steps.factory.run.atv_unit_test_runner" + }, + { + "class_name": "UploadResultToSpongeStepFactory", + "module_path": "lab_system.master.steps.factory.run.atv_unit_test_runner" + } + ], + "step_identifier": "test_running" + }, + { + "step_description": "Copy Logs", + "step_factories": [ + { + "class_name": "CopyLogsFromRootToRepositoryStepFactory", + "module_path": "lab_system.master.steps.factory.output.cloud_logs" + } + ], + "step_identifier": "logs_copy" + }, + { + "step_description": "Updates the good_to_test hint.", + "step_factories": [ + { + "class_name": "CreateHintStepFactory", + "module_path": "lab_system.master.steps.factory.run.atv_unit_test_runner" + } + ], + "step_identifier": "output_processing" + }, + { + "step_description": "Cleans up slave and devices after the testrun", + "step_factories": [ + { + "class_name": "DeviceDeallocatorStepFactory", + "module_path": "lab_system.master.steps.factory.device.cloud_deallocator" + }, + { + "class_name": "CleanupWorkdirStepFactory", + "module_path": "lab_system.master.steps.factory.cleanup.workdir" + } + ], + "step_identifier": "testrun_cleanup" + } +]
diff --git a/lab_system/master/config/step_factories_recipes/audio_mirroring.json b/lab_system/master/config/step_factories_recipes/audio_mirroring.json new file mode 100644 index 0000000..7f3f79a --- /dev/null +++ b/lab_system/master/config/step_factories_recipes/audio_mirroring.json
@@ -0,0 +1,96 @@ +[ + { + "step_description": "Sets up testrun specific properties", + "step_factories": [ + { + "class_name": "RecordingPropertiesSetterStepFactory", + "module_path": "lab_system.master.steps.factory.run.android_mirroring_runner" + } + ], + "step_identifier": "properties" + }, + { + "step_description": "Allocates devices for the testrun", + "step_factories": [ + { + "class_name": "DeviceAllocatorStepFactory", + "module_path": "lab_system.master.steps.factory.run.android_mirroring_runner" + } + ], + "step_identifier": "device_allocation" + }, + { + "step_description": "Copying Build to test slave and installing on device", + "step_factories": [ + { + "class_name": "RsyncRepositoriesStepFactory", + "module_path": "lab_system.master.steps.factory.build.copy_test_repo" + }, + { + "class_name": "RsyncAudioReferenceStepFactory", + "module_path": "lab_system.master.steps.factory.run.audio_mirroring_runner" + }, + { + "class_name": "RsyncRepositoriesStepFactory", + "module_path": "lab_system.master.steps.factory.run.audio_mirroring_runner" + }, + { + "class_name": "DefaultOtaFetcherStepFactory", + "module_path": "lab_system.master.steps.factory.build.fetcher" + }, + { + "class_name": "CopyBuildToSlaveStepFactory", + "module_path": "lab_system.master.steps.factory.run.android_mirroring_runner" + }, + { + "class_name": "InstallBuildStepFactory", + "module_path": "lab_system.master.steps.factory.run.android_mirroring_runner" + } + ], + "step_identifier": "build_handling" + }, + { + "step_description": "Sets up logging", + "step_factories": [ + { + "class_name": "NoopStepFactory", + "module_path": "lab_system.master.steps.factory.common.noop" + } + ], + "step_identifier": "testrun_setup" + }, + { + "step_description": "Runs Audio Mirroring Test", + "step_factories": [ + { + "class_name": "AudioMirroringStepFactory", + "module_path": "lab_system.master.steps.factory.run.android_mirroring_runner" + } + ], + "step_identifier": "test_running" + }, + { + "step_description": "Copies local log files to Google Storage", + "step_factories": [ + { + "class_name": "NoopStepFactory", + "module_path": "lab_system.master.steps.factory.common.noop" + } + ], + "step_identifier": "logs_copy" + }, + { + "step_description": "Processes the output of the test", + "step_factories": [ + { + "class_name": "GetLogcatStepFactory", + "module_path": "lab_system.master.steps.factory.run.audio_mirroring_runner" + }, + { + "class_name": "CopyLogsToRepositoryStepFactory", + "module_path": "lab_system.master.steps.factory.run.audio_mirroring_runner" + } + ], + "step_identifier": "output_processing" + } +]
diff --git a/lab_system/master/config/step_factories_recipes/audiodefault_unit_test_recipe.json b/lab_system/master/config/step_factories_recipes/audiodefault_unit_test_recipe.json new file mode 100644 index 0000000..7fe8127 --- /dev/null +++ b/lab_system/master/config/step_factories_recipes/audiodefault_unit_test_recipe.json
@@ -0,0 +1,110 @@ +[ + { + "step_description": "Sets up testrun specific properties", + "step_factories": [ + { + "class_name": "UnitTestTmpSetterStepFactory", + "module_path": "lab_system.master.steps.factory.run.unit_test_runner" + }, + { + "class_name": "ReducedLeaseDeviceAllocatorStepFactory", + "module_path": "lab_system.master.steps.factory.device.cloud_allocator" + }, + { + "class_name": "GetFirstDeviceIpAddrStepFactory", + "module_path": "lab_system.master.steps.factory.device.allocator" + }, + { + "class_name": "UnitTestPropertiesSetterStepFactory", + "module_path": "lab_system.master.steps.factory.run.unit_test_runner" + } + ], + "step_identifier": "properties" + }, + { + "step_description": "Allocates devices for the testrun", + "step_factories": [ + { + "class_name": "NoopStepFactory", + "module_path": "lab_system.master.steps.factory.common.noop" + } + ], + "step_identifier": "device_allocation" + }, + { + "step_description": "Fetches and installs builds on devices", + "step_factories": [ + { + "class_name": "BuildFetcherStepFactory", + "module_path": "lab_system.master.steps.factory.run.unit_test_runner" + }, + { + "class_name": "BuildInstallerWithoutFormatStepFactory", + "module_path": "lab_system.master.steps.factory.run.unit_test_runner" + } + ], + "step_identifier": "build_handling" + }, + { + "step_description": "Installs test binaries to unit test device", + "step_factories": [ + { + "class_name": "PrepDeviceStepFactory", + "module_path": "lab_system.master.steps.factory.run.unit_test_runner" + } + ], + "step_identifier": "testrun_setup" + }, + { + "step_description": "Runs unit test.", + "step_factories": [ + { + "class_name": "UnitTestRunStepFactory", + "module_path": "lab_system.master.steps.factory.run.unit_test_runner" + }, + { + "class_name": "UploadResultToSpongeStepFactory", + "module_path": "lab_system.master.steps.factory.run.unit_test_runner" + } + ], + "step_identifier": "test_running" + }, + { + "step_description": "Create good build hint", + "step_factories": [ + { + "class_name": "CreateHintStepFactory", + "module_path": "lab_system.master.steps.factory.run.unit_test_runner" + }, + { + "class_name": "CopyLogsFromRootToRepositoryStepFactory", + "module_path": "lab_system.master.steps.factory.output.cloud_logs" + } + ], + "step_identifier": "logs_copy" + }, + { + "step_description": "A placeholder with no-ops to allow custom logs parsing.", + "step_factories": [ + { + "class_name": "NoopStepFactory", + "module_path": "lab_system.master.steps.factory.common.noop" + } + ], + "step_identifier": "output_processing" + }, + { + "step_description": "Cleans up slave and devices after the testrun", + "step_factories": [ + { + "class_name": "DeviceDeallocatorStepFactory", + "module_path": "lab_system.master.steps.factory.device.cloud_deallocator" + }, + { + "class_name": "CleanupWorkdirStepFactory", + "module_path": "lab_system.master.steps.factory.cleanup.workdir" + } + ], + "step_identifier": "testrun_cleanup" + } +]
diff --git a/lab_system/master/config/step_factories_recipes/bringup_ethernet_port.json b/lab_system/master/config/step_factories_recipes/bringup_ethernet_port.json new file mode 100644 index 0000000..0896500 --- /dev/null +++ b/lab_system/master/config/step_factories_recipes/bringup_ethernet_port.json
@@ -0,0 +1,98 @@ +[ + { + "step_description": "Sets up testrun specific properties", + "step_identifier": "properties", + "step_factories": [ + { + "module_path": "lab_system.master.steps.factory.setup.properties", + "class_name": "PropertiesSetterStepFactory" + } + ] + }, + { + "step_description": "Allocates devices for the testrun", + "step_identifier": "device_allocation", + "step_factories": [ + { + "module_path": "lab_system.master.steps.factory.device.cloud_allocator", + "class_name": "TwoHourLeaseShortTimeoutAllocatorStepFactory" + }, + { + "module_path": "lab_system.master.steps.factory.device.bringup_ethernet_port", + "class_name": "BringupEthernetPortStepFactory" + } + ] + }, + { + "step_description": "Fetches and installs builds on devices", + "step_identifier": "build_handling", + "step_factories": [ + { + "module_path": "lab_system.master.steps.factory.build.fetcher", + "class_name": "DefaultOtaFetcherStepFactory" + }, + { + "module_path": "lab_system.master.steps.factory.build.installer_eurlab", + "class_name": "BuildInstallerStepFactory" + } + ] + }, + { + "step_description": "A placeholder with no-ops to allow pre setup of tests.", + "step_identifier": "testrun_setup", + "step_factories": [ + { + "class_name": "NoopStepFactory", + "module_path": "lab_system.master.steps.factory.common.noop" + } + ] + }, + { + "step_description": "Executes the tests using the eurtest runner.", + "step_identifier": "test_running", + "step_factories": [ + { + "module_path": "lab_system.master.steps.factory.run.test_runner", + "class_name": "TestRunnerStepFactory" + } + ] + }, + { + "step_description": "Copies local log files to Google Storage", + "step_identifier": "logs_copy", + "step_factories": [ + { + "module_path": "lab_system.master.steps.factory.output.cloud_logs", + "class_name": "CopyLogsToRepositoryStepFactory" + } + ] + }, + { + "step_description": "A placeholder with no-ops to allow custom logs parsing.", + "step_identifier": "output_processing", + "step_factories": [ + { + "class_name": "NoopStepFactory", + "module_path": "lab_system.master.steps.factory.common.noop" + } + ] + }, + { + "step_description": "Cleans up slave and devices after the testrun", + "step_identifier": "testrun_cleanup", + "step_factories": [ + { + "module_path": "lab_system.master.steps.factory.device.bringup_ethernet_port", + "class_name": "SwapDutWithSwitchIpStepFactory" + }, + { + "module_path": "lab_system.master.steps.factory.device.cloud_deallocator", + "class_name": "DeviceDeallocatorStepFactory" + }, + { + "module_path": "lab_system.master.steps.factory.cleanup.workdir", + "class_name": "CleanupWorkdirStepFactory" + } + ] + } +]
diff --git a/lab_system/master/config/step_factories_recipes/chrome_sdk_dev_e2e.json b/lab_system/master/config/step_factories_recipes/chrome_sdk_dev_e2e.json new file mode 100644 index 0000000..ffd790b --- /dev/null +++ b/lab_system/master/config/step_factories_recipes/chrome_sdk_dev_e2e.json
@@ -0,0 +1,115 @@ +[ + { + "step_description": "Allocate laptop and chromecast devices for the test run", + "step_identifier": "device_allocation", + "step_factories": [ + { + "module_path": "lab_system.master.steps.factory.device.cloud_allocator", + "class_name": "DeviceAllocatorStepFactory" + }, + { + "module_path": "lab_system.master.steps.factory.sender.allocator", + "class_name": "SenderAllocatorStepFactory" + } + ] + }, + { + "step_description": "Set up test environment", + "step_identifier": "testrun_setup", + "step_factories": [ + { + "module_path": "lab_system.master.steps.factory.run.chrome_sdk_runner", + "class_name": "SetDeviceIpStepFactory" + }, + { + "module_path": "lab_system.master.steps.factory.build.copy_test_repo", + "class_name": "CopyRepositoriesStepFactory" + }, + { + "module_path": "lab_system.master.steps.factory.chrome.download", + "class_name": "DownloadChromeStepFactory" + }, + { + "module_path": "lab_system.master.steps.factory.chrome.copy", + "class_name": "CopyChromeStepFactory" + }, + { + "module_path": "lab_system.master.steps.factory.run.chrome_sdk_runner", + "class_name": "SetExtensionVersionStepFactory" + }, + { + "module_path": "lab_system.master.steps.factory.run.chrome_sdk_runner", + "class_name": "UnzipDevExtensionToTMPStepFactory" + }, + { + "module_path": "lab_system.master.steps.factory.extension.copy", + "class_name": "CopyExtensionStepFactory" + }, + { + "module_path": "lab_system.master.steps.factory.run.chrome_sdk_runner", + "class_name": "CopyTestFilesStepFactory" + }, + { + "module_path": "lab_system.master.steps.factory.output.logs_eurlab", + "class_name": "StartLoggingStepFactory" + } + ] + }, + { + "step_description": "Executes the tests", + "step_identifier": "test_running", + "step_factories": [ + { + "module_path": "lab_system.master.steps.factory.run.chrome_sdk_runner", + "class_name": "TestRunnerStepFactory" + } + ] + }, + { + "step_description": "Replaces logs_copy with a no-op", + "step_identifier": "logs_copy", + "step_factories": [ + { + "module_path": "lab_system.master.steps.factory.common.noop", + "class_name": "NoopStepFactory" + } + ] + }, + { + "step_description": "Processes the output of the test", + "step_identifier": "output_processing", + "step_factories": [ + { + "module_path": "lab_system.master.steps.factory.output.logs_eurlab", + "class_name": "StopLoggingStepFactory" + }, + { + "module_path": "lab_system.master.steps.factory.output.logs", + "class_name": "CopyLogsToRepositoryStepFactory" + }, + { + "module_path": "lab_system.master.steps.factory.output.logs", + "class_name": "UpdateLogMetadataStepFactory" + } + ] + }, + { + "step_description": "Cleanup", + "step_identifier": "testrun_cleanup", + "step_factories": [ + { + "module_path": "lab_system.master.steps.factory.device.cloud_deallocator", + "class_name": "DeviceDeallocatorStepFactory" + }, + { + "module_path": "lab_system.master.steps.factory.sender.deallocator", + "class_name": "SenderDeallocatorStepFactory" + }, + { + "module_path": "lab_system.master.steps.factory.cleanup.workdir", + "class_name": "CleanupWorkdirStepFactory" + } + ] + } +] +
diff --git a/lab_system/master/config/step_factories_recipes/chrome_sdk_other_e2e.json b/lab_system/master/config/step_factories_recipes/chrome_sdk_other_e2e.json new file mode 100644 index 0000000..e7de4ad --- /dev/null +++ b/lab_system/master/config/step_factories_recipes/chrome_sdk_other_e2e.json
@@ -0,0 +1,111 @@ +[ + { + "step_description": "Allocate laptop and chromecast devices for the test run", + "step_identifier": "device_allocation", + "step_factories": [ + { + "module_path": "lab_system.master.steps.factory.device.cloud_allocator", + "class_name": "DeviceAllocatorStepFactory" + }, + { + "module_path": "lab_system.master.steps.factory.sender.allocator", + "class_name": "SenderAllocatorStepFactory" + } + ] + }, + { + "step_description": "Set up test environment", + "step_identifier": "testrun_setup", + "step_factories": [ + { + "module_path": "lab_system.master.steps.factory.run.chrome_sdk_runner", + "class_name": "SetDeviceIpStepFactory" + }, + { + "module_path": "lab_system.master.steps.factory.build.copy_test_repo", + "class_name": "CopyRepositoriesStepFactory" + }, + { + "module_path": "lab_system.master.steps.factory.chrome.download", + "class_name": "DownloadChromeStepFactory" + }, + { + "module_path": "lab_system.master.steps.factory.chrome.copy", + "class_name": "CopyChromeStepFactory" + }, + { + "module_path": "lab_system.master.steps.factory.extension.download_cws_extension", + "class_name": "DownloadWebStoreExtensionStepFactory" + }, + { + "module_path": "lab_system.master.steps.factory.extension.copy", + "class_name": "CopyExtensionStepFactory" + }, + { + "module_path": "lab_system.master.steps.factory.run.chrome_sdk_runner", + "class_name": "CopyTestFilesStepFactory" + }, + { + "module_path": "lab_system.master.steps.factory.output.logs_eurlab", + "class_name": "StartLoggingStepFactory" + } + ] + }, + { + "step_description": "Executes the tests", + "step_identifier": "test_running", + "step_factories": [ + { + "module_path": "lab_system.master.steps.factory.run.chrome_sdk_runner", + "class_name": "TestRunnerStepFactory" + } + ] + }, + { + "step_description": "Replaces logs_copy with a no-op", + "step_identifier": "logs_copy", + "step_factories": [ + { + "module_path": "lab_system.master.steps.factory.common.noop", + "class_name": "NoopStepFactory" + } + ] + }, + { + "step_description": "Processes the output of the test", + "step_identifier": "output_processing", + "step_factories": [ + { + "module_path": "lab_system.master.steps.factory.output.logs_eurlab", + "class_name": "StopLoggingStepFactory" + }, + { + "module_path": "lab_system.master.steps.factory.output.logs", + "class_name": "CopyLogsToRepositoryStepFactory" + }, + { + "module_path": "lab_system.master.steps.factory.output.logs", + "class_name": "UpdateLogMetadataStepFactory" + } + ] + }, + { + "step_description": "Cleanup", + "step_identifier": "testrun_cleanup", + "step_factories": [ + { + "module_path": "lab_system.master.steps.factory.device.cloud_deallocator", + "class_name": "DeviceDeallocatorStepFactory" + }, + { + "module_path": "lab_system.master.steps.factory.sender.deallocator", + "class_name": "SenderDeallocatorStepFactory" + }, + { + "module_path": "lab_system.master.steps.factory.cleanup.workdir", + "class_name": "CleanupWorkdirStepFactory" + } + ] + } +] +
diff --git a/lab_system/master/config/step_factories_recipes/chrome_sdk_test_mrp_e2e.json b/lab_system/master/config/step_factories_recipes/chrome_sdk_test_mrp_e2e.json new file mode 100644 index 0000000..3c77f7d --- /dev/null +++ b/lab_system/master/config/step_factories_recipes/chrome_sdk_test_mrp_e2e.json
@@ -0,0 +1,103 @@ +[ + { + "step_description": "Allocate laptop and chromecast devices for the test run", + "step_identifier": "device_allocation", + "step_factories": [ + { + "module_path": "lab_system.master.steps.factory.device.cloud_allocator", + "class_name": "DeviceAllocatorStepFactory" + }, + { + "module_path": "lab_system.master.steps.factory.sender.allocator", + "class_name": "SenderAllocatorStepFactory" + } + ] + }, + { + "step_description": "Set up test environment", + "step_identifier": "testrun_setup", + "step_factories": [ + { + "module_path": "lab_system.master.steps.factory.run.chrome_sdk_runner", + "class_name": "SetDeviceIpStepFactory" + }, + { + "module_path": "lab_system.master.steps.factory.build.copy_test_repo", + "class_name": "CopyRepositoriesStepFactory" + }, + { + "module_path": "lab_system.master.steps.factory.chrome.download", + "class_name": "DownloadChromeStepFactory" + }, + { + "module_path": "lab_system.master.steps.factory.chrome.copy", + "class_name": "CopyChromeStepFactory" + }, + { + "module_path": "lab_system.master.steps.factory.run.chrome_sdk_runner", + "class_name": "CopyTestFilesStepFactory" + }, + { + "module_path": "lab_system.master.steps.factory.output.logs_eurlab", + "class_name": "StartLoggingStepFactory" + } + ] + }, + { + "step_description": "Executes the tests", + "step_identifier": "test_running", + "step_factories": [ + { + "module_path": "lab_system.master.steps.factory.run.chrome_sdk_runner", + "class_name": "TestRunnerStepFactory" + } + ] + }, + { + "step_description": "Replaces logs_copy with a no-op", + "step_identifier": "logs_copy", + "step_factories": [ + { + "module_path": "lab_system.master.steps.factory.common.noop", + "class_name": "NoopStepFactory" + } + ] + }, + { + "step_description": "Processes the output of the test", + "step_identifier": "output_processing", + "step_factories": [ + { + "module_path": "lab_system.master.steps.factory.output.logs_eurlab", + "class_name": "StopLoggingStepFactory" + }, + { + "module_path": "lab_system.master.steps.factory.output.logs", + "class_name": "CopyLogsToRepositoryStepFactory" + }, + { + "module_path": "lab_system.master.steps.factory.output.logs", + "class_name": "UpdateLogMetadataStepFactory" + } + ] + }, + { + "step_description": "Cleanup", + "step_identifier": "testrun_cleanup", + "step_factories": [ + { + "module_path": "lab_system.master.steps.factory.device.cloud_deallocator", + "class_name": "DeviceDeallocatorStepFactory" + }, + { + "module_path": "lab_system.master.steps.factory.sender.deallocator", + "class_name": "SenderDeallocatorStepFactory" + }, + { + "module_path": "lab_system.master.steps.factory.cleanup.workdir", + "class_name": "CleanupWorkdirStepFactory" + } + ] + } +] +
diff --git a/lab_system/master/config/step_factories_recipes/claim_hint_unit_test_recipe.json b/lab_system/master/config/step_factories_recipes/claim_hint_unit_test_recipe.json new file mode 100644 index 0000000..889089e --- /dev/null +++ b/lab_system/master/config/step_factories_recipes/claim_hint_unit_test_recipe.json
@@ -0,0 +1,115 @@ + +[ + { + "step_description": "Sets up testrun specific properties", + "step_factories": [ + { + "class_name": "UnitTestTmpSetterStepFactory", + "module_path": "lab_system.master.steps.factory.run.unit_test_runner" + }, + { + "class_name": "ReducedLeaseDeviceAllocatorStepFactory", + "module_path": "lab_system.master.steps.factory.device.cloud_allocator" + }, + { + "class_name": "GetFirstDeviceIpAddrStepFactory", + "module_path": "lab_system.master.steps.factory.device.allocator" + }, + { + "class_name": "UnitTestPropertiesSetterStepFactory", + "module_path": "lab_system.master.steps.factory.run.unit_test_runner" + } + ], + "step_identifier": "properties" + }, + { + "step_description": "Allocates devices for the testrun", + "step_factories": [ + { + "class_name": "NoopStepFactory", + "module_path": "lab_system.master.steps.factory.common.noop" + } + ], + "step_identifier": "device_allocation" + }, + { + "step_description": "Fetches and installs builds on devices", + "step_factories": [ + { + "class_name": "BuildFetcherStepFactory", + "module_path": "lab_system.master.steps.factory.run.unit_test_runner" + }, + { + "class_name": "BuildInstallerStepFactory", + "module_path": "lab_system.master.steps.factory.run.unit_test_runner" + } + ], + "step_identifier": "build_handling" + }, + { + "step_description": "Installs test binaries to unit test device", + "step_factories": [ + { + "class_name": "PrepDeviceStepFactory", + "module_path": "lab_system.master.steps.factory.run.unit_test_runner" + } + ], + "step_identifier": "testrun_setup" + }, + { + "step_description": "Runs unit test.", + "step_factories": [ + { + "class_name": "UnitTestRunStepFactory", + "module_path": "lab_system.master.steps.factory.run.unit_test_runner" + }, + { + "class_name": "UploadResultToSpongeStepFactory", + "module_path": "lab_system.master.steps.factory.run.unit_test_runner" + } + ], + "step_identifier": "test_running" + }, + { + "step_description": "Create good build hint", + "step_factories": [ + { + "class_name": "CreateHintStepFactory", + "module_path": "lab_system.master.steps.factory.run.unit_test_runner" + }, + { + "class_name": "CopyLogStepFactory", + "module_path": "lab_system.master.steps.factory.run.unit_test_runner" + }, + { + "class_name": "CopyLogsFromRootToRepositoryStepFactory", + "module_path": "lab_system.master.steps.factory.output.cloud_logs" + } + ], + "step_identifier": "logs_copy" + }, + { + "step_description": "A placeholder with no-ops to allow custom logs parsing.", + "step_factories": [ + { + "class_name": "NoopStepFactory", + "module_path": "lab_system.master.steps.factory.common.noop" + } + ], + "step_identifier": "output_processing" + }, + { + "step_description": "Cleans up slave and devices after the testrun", + "step_factories": [ + { + "class_name": "DeviceDeallocatorStepFactory", + "module_path": "lab_system.master.steps.factory.device.cloud_deallocator" + }, + { + "class_name": "CleanupWorkdirStepFactory", + "module_path": "lab_system.master.steps.factory.cleanup.workdir" + } + ], + "step_identifier": "testrun_cleanup" + } +]
diff --git a/lab_system/master/config/step_factories_recipes/default_with_new_device_allocation.json b/lab_system/master/config/step_factories_recipes/default_with_new_device_allocation.json new file mode 100644 index 0000000..ab72455 --- /dev/null +++ b/lab_system/master/config/step_factories_recipes/default_with_new_device_allocation.json
@@ -0,0 +1,90 @@ +[ + { + "step_description": "Sets up testrun specific properties", + "step_identifier": "properties", + "step_factories": [ + { + "module_path": "lab_system.master.steps.factory.setup.properties", + "class_name": "PropertiesSetterStepFactory" + } + ] + }, + { + "step_description": "Allocates devices for the testrun", + "step_identifier": "device_allocation", + "step_factories": [ + { + "module_path": "lab_system.master.steps.factory.device.cloud_allocator", + "class_name": "DeviceAllocatorStepFactory" + } + ] + }, + { + "step_description": "Fetches and installs builds on devices", + "step_identifier": "build_handling", + "step_factories": [ + { + "module_path": "lab_system.master.steps.factory.build.fetcher", + "class_name": "DefaultOtaFetcherStepFactory" + }, + { + "module_path": "lab_system.master.steps.factory.build.installer_eurlab", + "class_name": "BuildInstallerStepFactory" + } + ] + }, + { + "step_description": "A placeholder with no-ops to allow pre setup of tests.", + "step_identifier": "testrun_setup", + "step_factories": [ + { + "class_name": "NoopStepFactory", + "module_path": "lab_system.master.steps.factory.common.noop" + } + ] + }, + { + "step_description": "Executes the tests using the eurtest runner.", + "step_identifier": "test_running", + "step_factories": [ + { + "module_path": "lab_system.master.steps.factory.run.test_runner", + "class_name": "TestRunnerStepFactory" + } + ] + }, + { + "step_description": "Copies local log files to Google Storage", + "step_identifier": "logs_copy", + "step_factories": [ + { + "module_path": "lab_system.master.steps.factory.output.cloud_logs", + "class_name": "CopyLogsFromRootToRepositoryStepFactory" + } + ] + }, + { + "step_description": "A placeholder with no-ops to allow custom logs parsing.", + "step_identifier": "output_processing", + "step_factories": [ + { + "class_name": "NoopStepFactory", + "module_path": "lab_system.master.steps.factory.common.noop" + } + ] + }, + { + "step_description": "Cleans up slave and devices after the testrun", + "step_identifier": "testrun_cleanup", + "step_factories": [ + { + "module_path": "lab_system.master.steps.factory.device.cloud_deallocator", + "class_name": "DeviceDeallocatorStepFactory" + }, + { + "module_path": "lab_system.master.steps.factory.cleanup.workdir", + "class_name": "CleanupWorkdirStepFactory" + } + ] + } +]
diff --git a/lab_system/master/config/step_factories_recipes/fct_test_recipe.json b/lab_system/master/config/step_factories_recipes/fct_test_recipe.json new file mode 100644 index 0000000..16e1711 --- /dev/null +++ b/lab_system/master/config/step_factories_recipes/fct_test_recipe.json
@@ -0,0 +1,90 @@ +[ + { + "step_description": "Sets up testrun specific properties", + "step_factories": [ + { + "class_name": "PropertiesSetterStepFactory", + "module_path": "lab_system.master.steps.factory.setup.properties" + }, + { + "class_name": "AddUnitTestMarkerStepFactory", + "module_path": "lab_system.master.steps.factory.run.unit_test_runner" + } + ], + "step_identifier": "properties" + }, + { + "step_description": "Allocates devices for the testrun", + "step_factories": [ + { + "class_name": "DeviceAllocatorStepFactory", + "module_path": "lab_system.master.steps.factory.device.cloud_allocator" + }, + { + "class_name": "PrepFctWorkDirectoryStepFactory", + "module_path": "lab_system.master.steps.factory.run.fct_test_runner" + } + ], + "step_identifier": "device_allocation" + }, + { + "step_description": "Fetches and installs builds on devices", + "step_factories": [ + { + "class_name": "FctBuildFetcherStepFactory", + "module_path": "lab_system.master.steps.factory.run.fct_test_runner" + }, + { + "class_name": "CopyFctBuildToSlaveStepFactory", + "module_path": "lab_system.master.steps.factory.run.fct_test_runner" + }, + { + "class_name": "InstallFctBuildToDeviceStepFactory", + "module_path": "lab_system.master.steps.factory.run.fct_test_runner" + } + ], + "step_identifier": "build_handling" + }, + { + "step_description": "Run factory tests using the test runner.", + "step_factories": [ + { + "class_name": "TestRunnerStepFactory", + "module_path": "lab_system.master.steps.factory.run.test_runner" + } + ], + "step_identifier": "test_running" + }, + { + "step_description": "Copies local log files to Google Storage", + "step_factories": [ + { + "class_name": "CopyLogsToRepositoryStepFactory", + "module_path": "lab_system.master.steps.factory.output.cloud_logs" + } + ], + "step_identifier": "logs_copy" + }, + { + "step_description": "Cleans up slave and devices after the testrun", + "step_factories": [ + { + "class_name": "CleanFctWorkDirectoryStepFactory", + "module_path": "lab_system.master.steps.factory.run.fct_test_runner" + }, + { + "class_name": "DeviceDeallocatorStepFactory", + "module_path": "lab_system.master.steps.factory.device.cloud_deallocator" + }, + { + "class_name": "RemoveUnitTestMarkerStepFactory", + "module_path": "lab_system.master.steps.factory.run.unit_test_runner" + }, + { + "class_name": "CleanupWorkdirStepFactory", + "module_path": "lab_system.master.steps.factory.cleanup.workdir" + } + ], + "step_identifier": "testrun_cleanup" + } +]
diff --git a/lab_system/master/config/step_factories_recipes/gating_tests_recipe.json b/lab_system/master/config/step_factories_recipes/gating_tests_recipe.json new file mode 100644 index 0000000..f854763 --- /dev/null +++ b/lab_system/master/config/step_factories_recipes/gating_tests_recipe.json
@@ -0,0 +1,98 @@ +[ + { + "step_description": "Sets up testrun specific properties", + "step_factories": [ + { + "class_name": "PropertiesSetterStepFactoryWithDummyBuild", + "module_path": "lab_system.master.steps.factory.setup.properties" + }, + { + "class_name": "AddUnitTestMarkerStepFactory", + "module_path": "lab_system.master.steps.factory.run.unit_test_runner" + } + ], + "step_identifier": "properties" + }, + { + "step_description": "Allocates devices for the testrun", + "step_factories": [ + { + "class_name": "DeviceAllocatorStepFactory", + "module_path": "lab_system.master.steps.factory.device.cloud_allocator" + } + ], + "step_identifier": "device_allocation" + }, + { + "step_description": "Fetches and installs builds on devices", + "step_factories": [ + { + "class_name": "DefaultOtaFetcherStepFactory", + "module_path": "lab_system.master.steps.factory.build.fetcher" + }, + { + "class_name": "BuildInstallerStepFactory", + "module_path": "lab_system.master.steps.factory.build.installer_eurlab" + } + ], + "step_identifier": "build_handling" + }, + { + "step_description": "A placeholder with no-ops to allow pre setup of tests.", + "step_factories": [ + { + "class_name": "NoopStepFactory", + "module_path": "lab_system.master.steps.factory.common.noop" + } + ], + "step_identifier": "testrun_setup" + }, + { + "step_description": "Executes the tests using the eurtest runner.", + "step_factories": [ + { + "class_name": "TestRunnerStepFactory", + "module_path": "lab_system.master.steps.factory.run.test_runner" + } + ], + "step_identifier": "test_running" + }, + { + "step_description": "Copies local log files to Google Storage", + "step_factories": [ + { + "class_name": "CopyLogsToRepositoryStepFactory", + "module_path": "lab_system.master.steps.factory.output.cloud_logs" + } + ], + "step_identifier": "logs_copy" + }, + { + "step_description": "A placeholder with no-ops to allow custom logs parsing.", + "step_factories": [ + { + "class_name": "NoopStepFactory", + "module_path": "lab_system.master.steps.factory.common.noop" + } + ], + "step_identifier": "output_processing" + }, + { + "step_description": "Cleans up slave and devices after the testrun", + "step_factories": [ + { + "class_name": "DeviceDeallocatorStepFactory", + "module_path": "lab_system.master.steps.factory.device.cloud_deallocator" + }, + { + "class_name": "RemoveUnitTestMarkerStepFactory", + "module_path": "lab_system.master.steps.factory.run.unit_test_runner" + }, + { + "class_name": "CleanupWorkdirStepFactory", + "module_path": "lab_system.master.steps.factory.cleanup.workdir" + } + ], + "step_identifier": "testrun_cleanup" + } +]
diff --git a/lab_system/master/config/step_factories_recipes/multi_device_unit_test_recipe.json b/lab_system/master/config/step_factories_recipes/multi_device_unit_test_recipe.json new file mode 100644 index 0000000..38846eb --- /dev/null +++ b/lab_system/master/config/step_factories_recipes/multi_device_unit_test_recipe.json
@@ -0,0 +1,114 @@ +[ + { + "step_description": "Sets up testrun specific properties", + "step_factories": [ + { + "class_name": "UnitTestTmpSetterStepFactory", + "module_path": "lab_system.master.steps.factory.run.unit_test_runner" + }, + { + "class_name": "ReducedLeaseDeviceAllocatorStepFactory", + "module_path": "lab_system.master.steps.factory.device.cloud_allocator" + }, + { + "class_name": "GetCommaSeparatedDeviceIpAddrStepFactory", + "module_path": "lab_system.master.steps.factory.device.allocator" + }, + { + "class_name": "UnitTestPropertiesSetterStepFactory", + "module_path": "lab_system.master.steps.factory.run.unit_test_runner" + } + ], + "step_identifier": "properties" + }, + { + "step_description": "Allocates devices for the testrun", + "step_factories": [ + { + "class_name": "NoopStepFactory", + "module_path": "lab_system.master.steps.factory.common.noop" + } + ], + "step_identifier": "device_allocation" + }, + { + "step_description": "Fetches and installs builds on devices", + "step_factories": [ + { + "class_name": "BuildFetcherStepFactory", + "module_path": "lab_system.master.steps.factory.run.unit_test_runner" + }, + { + "class_name": "BuildInstallerStepFactory", + "module_path": "lab_system.master.steps.factory.run.unit_test_runner" + } + ], + "step_identifier": "build_handling" + }, + { + "step_description": "Installs test binaries to unit test device", + "step_factories": [ + { + "class_name": "PrepDeviceStepFactory", + "module_path": "lab_system.master.steps.factory.run.unit_test_runner" + } + ], + "step_identifier": "testrun_setup" + }, + { + "step_description": "Runs unit test.", + "step_factories": [ + { + "class_name": "UnitTestRunStepFactory", + "module_path": "lab_system.master.steps.factory.run.unit_test_runner" + }, + { + "class_name": "UploadResultToSpongeStepFactory", + "module_path": "lab_system.master.steps.factory.run.unit_test_runner" + } + ], + "step_identifier": "test_running" + }, + { + "step_description": "Create good build hint", + "step_factories": [ + { + "class_name": "CreateHintStepFactory", + "module_path": "lab_system.master.steps.factory.run.unit_test_runner" + }, + { + "class_name": "CopyLogStepFactory", + "module_path": "lab_system.master.steps.factory.run.unit_test_runner" + }, + { + "class_name": "CopyLogsToRepositoryStepFactory", + "module_path": "lab_system.master.steps.factory.output.logs" + } + ], + "step_identifier": "logs_copy" + }, + { + "step_description": "A placeholder with no-ops to allow custom logs parsing.", + "step_factories": [ + { + "class_name": "NoopStepFactory", + "module_path": "lab_system.master.steps.factory.common.noop" + } + ], + "step_identifier": "output_processing" + }, + { + "step_description": "Cleans up slave and devices after the testrun", + "step_factories": [ + { + "class_name": "DeviceDeallocatorStepFactory", + "module_path": "lab_system.master.steps.factory.device.cloud_deallocator" + }, + { + "class_name": "CleanupWorkdirStepFactory", + "module_path": "lab_system.master.steps.factory.cleanup.workdir" + } + ], + "step_identifier": "testrun_cleanup" + } +]
diff --git a/lab_system/master/config/step_factories_recipes/ota_installable_test_recipe.json b/lab_system/master/config/step_factories_recipes/ota_installable_test_recipe.json new file mode 100644 index 0000000..4562f09 --- /dev/null +++ b/lab_system/master/config/step_factories_recipes/ota_installable_test_recipe.json
@@ -0,0 +1,108 @@ +[ + { + "step_description": "Sets up testrun specific properties", + "step_factories": [ + { + "class_name": "UnitTestTmpSetterStepFactory", + "module_path": "lab_system.master.steps.factory.run.unit_test_runner" + }, + { + "class_name": "UnitTestPropertiesSetterStepFactory", + "module_path": "lab_system.master.steps.factory.run.unit_test_runner" + } + ], + "step_identifier": "properties" + }, + { + "step_description": "Allocates devices for the testrun", + "step_factories": [ + { + "class_name": "CheckBuildUsability", + "module_path": "lab_system.master.steps.factory.run.ota_installable_runner" + }, + { + "class_name": "BestEffortReducedLeaseDeviceAllocatorStepFactory", + "module_path": "lab_system.master.steps.factory.device.cloud_allocator" + }, + { + "class_name": "GetFirstDeviceIpAddrStepFactory", + "module_path": "lab_system.master.steps.factory.device.allocator" + } + ], + "step_identifier": "device_allocation" + }, + { + "step_description": "Fetches and installs builds on devices", + "step_factories": [ + { + "class_name": "BuildFetcherStepFactory", + "module_path": "lab_system.master.steps.factory.run.unit_test_runner" + }, + { + "class_name": "HealthCheckStepFactory", + "module_path": "lab_system.master.steps.factory.device.health_check" + }, + { + "class_name": "BuildInstallerStepFactory", + "module_path": "lab_system.master.steps.factory.run.ota_installable_runner" + } + ], + "step_identifier": "build_handling" + }, + { + "step_description": "Runs ota installable test.", + "step_factories": [ + { + "class_name": "TestRunnerStepFactory", + "module_path": "lab_system.master.steps.factory.run.ota_installable_runner" + }, + { + "class_name": "UploadResultToSpongeStepFactory", + "module_path": "lab_system.master.steps.factory.run.ota_installable_runner" + } + ], + "step_identifier": "test_running" + }, + { + "step_description": "Create good build hint", + "step_factories": [ + { + "class_name": "CopyLogsToRepositoryStepFactory", + "module_path": "lab_system.master.steps.factory.run.ota_installable_runner" + }, + { + "class_name": "CreateHintStepFactory", + "module_path": "lab_system.master.steps.factory.run.unit_test_runner" + } + ], + "step_identifier": "logs_copy" + }, + { + "step_description": "A placeholder with no-ops to allow custom logs parsing.", + "step_factories": [ + { + "class_name": "NoopStepFactory", + "module_path": "lab_system.master.steps.factory.common.noop" + } + ], + "step_identifier": "output_processing" + }, + { + "step_description": "Cleans up slave and devices after the testrun", + "step_factories": [ + { + "class_name": "DisableMdnsStepFactory", + "module_path": "lab_system.master.steps.factory.device.cloud_deallocator" + }, + { + "class_name": "DeviceDeallocatorStepFactory", + "module_path": "lab_system.master.steps.factory.device.cloud_deallocator" + }, + { + "class_name": "CleanupWorkdirStepFactory", + "module_path": "lab_system.master.steps.factory.cleanup.workdir" + } + ], + "step_identifier": "testrun_cleanup" + } +]
diff --git a/lab_system/master/config/step_factories_recipes/remote_display.json b/lab_system/master/config/step_factories_recipes/remote_display.json new file mode 100644 index 0000000..7d71030 --- /dev/null +++ b/lab_system/master/config/step_factories_recipes/remote_display.json
@@ -0,0 +1,106 @@ +[ + { + "step_description": "Sets up testrun specific properties", + "step_factories": [ + { + "class_name": "RecordingPropertiesSetterStepFactory", + "module_path": "lab_system.master.steps.factory.run.android_mirroring_runner" + } + ], + "step_identifier": "properties" + }, + { + "step_description": "Allocates devices for the testrun", + "step_factories": [ + { + "class_name": "DeviceAllocatorStepFactory", + "module_path": "lab_system.master.steps.factory.run.android_mirroring_runner" + } + ], + "step_identifier": "device_allocation" + }, + { + "step_description": "Copying Build to test slave and installing on device", + "step_factories": [ + { + "class_name": "RsyncRepositoriesStepFactory", + "module_path": "lab_system.master.steps.factory.build.copy_test_repo" + }, + { + "class_name": "DefaultOtaFetcherStepFactory", + "module_path": "lab_system.master.steps.factory.build.fetcher" + }, + { + "class_name": "CopyBuildToSlaveStepFactory", + "module_path": "lab_system.master.steps.factory.run.android_mirroring_runner" + }, + { + "class_name": "TurnOnSpecificDevice", + "module_path": "lab_system.master.steps.factory.run.android_mirroring_runner" + }, + { + "class_name": "InstallBuildStepFactory", + "module_path": "lab_system.master.steps.factory.run.android_mirroring_runner" + } + ], + "step_identifier": "build_handling" + }, + { + "step_description": "Sets up logging", + "step_factories": [ + { + "class_name": "NoopStepFactory", + "module_path": "lab_system.master.steps.factory.common.noop" + } + ], + "step_identifier": "testrun_setup" + }, + { + "step_description": "Runs Remote Display Test", + "step_factories": [ + { + "class_name": "RemoteDisplayStepFactory", + "module_path": "lab_system.master.steps.factory.run.android_mirroring_runner" + } + ], + "step_identifier": "test_running" + }, + { + "step_description": "Copies local log files to Google Storage", + "step_factories": [ + { + "class_name": "NoopStepFactory", + "module_path": "lab_system.master.steps.factory.common.noop" + } + ], + "step_identifier": "logs_copy" + }, + { + "step_description": "Processes the output of the test", + "step_factories": [ + { + "class_name": "GetLogcatStepFactory", + "module_path": "lab_system.master.steps.factory.run.android_mirroring_runner" + }, + { + "class_name": "CopyLogsToRepositoryStepFactory", + "module_path": "lab_system.master.steps.factory.run.android_mirroring_runner" + } + ], + "step_identifier": "output_processing" + }, + { + "step_description": "Cleans up slave and devices after the testrun", + "step_factories": [ + { + "class_name": "DeviceDeallocatorStepFactory", + "module_path": "lab_system.master.steps.factory.device.deallocator" + }, + { + "class_name": "CleanupWorkdirStepFactory", + "module_path": "lab_system.master.steps.factory.cleanup.workdir" + } + ], + "step_identifier": "testrun_cleanup" + } +]
diff --git a/lab_system/master/config/step_factories_recipes/remote_display_ios.json b/lab_system/master/config/step_factories_recipes/remote_display_ios.json new file mode 100644 index 0000000..e3aff32 --- /dev/null +++ b/lab_system/master/config/step_factories_recipes/remote_display_ios.json
@@ -0,0 +1,102 @@ +[ + { + "step_description": "Sets up testrun specific properties", + "step_factories": [ + { + "class_name": "RecordingPropertiesSetterStepFactory", + "module_path": "lab_system.master.steps.factory.run.android_mirroring_runner" + } + ], + "step_identifier": "properties" + }, + { + "step_description": "Allocates devices for the testrun", + "step_factories": [ + { + "class_name": "ReducedLeaseDeviceAllocatorStepFactory", + "module_path": "lab_system.master.steps.factory.device.cloud_allocator" + } + ], + "step_identifier": "device_allocation" + }, + { + "step_description": "Copying Build to test slave and installing on device", + "step_factories": [ + { + "class_name": "RsyncRepositoriesStepFactory", + "module_path": "lab_system.master.steps.factory.build.copy_test_repo" + }, + { + "class_name": "DefaultOtaFetcherStepFactory", + "module_path": "lab_system.master.steps.factory.build.fetcher" + }, + { + "class_name": "CopyBuildToSlaveStepFactory", + "module_path": "lab_system.master.steps.factory.run.android_mirroring_runner" + }, + { + "class_name": "InstallBuildStepFactory", + "module_path": "lab_system.master.steps.factory.run.android_mirroring_runner" + } + ], + "step_identifier": "build_handling" + }, + { + "step_description": "Sets up logging", + "step_factories": [ + { + "class_name": "NoopStepFactory", + "module_path": "lab_system.master.steps.factory.common.noop" + } + ], + "step_identifier": "testrun_setup" + }, + { + "step_description": "Runs Remote Display Test", + "step_factories": [ + { + "class_name": "IosRemoteDisplayStepFactory", + "module_path": "lab_system.master.steps.factory.run.ios_remote_display_runner" + } + ], + "step_identifier": "test_running" + }, + { + "step_description": "Copies local log files to Google Storage", + "step_factories": [ + { + "class_name": "NoopStepFactory", + "module_path": "lab_system.master.steps.factory.common.noop" + } + ], + "step_identifier": "logs_copy" + }, + { + "step_description": "Processes the output of the test", + "step_factories": [ + { + "class_name": "GetLogcatStepFactory", + "module_path": "lab_system.master.steps.factory.run.android_mirroring_runner" + }, + { + "class_name": "CopyLogsToRepositoryStepFactory", + "module_path": "lab_system.master.steps.factory.run.android_mirroring_runner" + } + ], + "step_identifier": "output_processing" + }, + { + "step_description": "Cleans up slave and devices after the testrun", + "step_factories": [ + { + "class_name": "DeviceDeallocatorStepFactory", + "module_path": "lab_system.master.steps.factory.device.cloud_deallocator" + }, + { + "class_name": "CleanupWorkdirStepFactory", + "module_path": "lab_system.master.steps.factory.cleanup.workdir" + } + ], + "step_identifier": "testrun_cleanup" + } +]
diff --git a/lab_system/master/config/step_factories_recipes/remote_display_ios_latency.json b/lab_system/master/config/step_factories_recipes/remote_display_ios_latency.json new file mode 100644 index 0000000..493b01d --- /dev/null +++ b/lab_system/master/config/step_factories_recipes/remote_display_ios_latency.json
@@ -0,0 +1,106 @@ +[ + { + "step_description": "Sets up testrun specific properties", + "step_factories": [ + { + "class_name": "RecordingPropertiesSetterStepFactory", + "module_path": "lab_system.master.steps.factory.run.android_mirroring_runner" + } + ], + "step_identifier": "properties" + }, + { + "step_description": "Allocates devices for the testrun", + "step_factories": [ + { + "class_name": "ReducedLeaseDeviceAllocatorStepFactory", + "module_path": "lab_system.master.steps.factory.device.cloud_allocator" + } + ], + "step_identifier": "device_allocation" + }, + { + "step_description": "Copying Build to test slave and installing on device", + "step_factories": [ + { + "class_name": "RsyncRepositoriesStepFactory", + "module_path": "lab_system.master.steps.factory.build.copy_test_repo" + }, + { + "class_name": "DefaultOtaFetcherStepFactory", + "module_path": "lab_system.master.steps.factory.build.fetcher" + }, + { + "class_name": "CopyBuildToSlaveStepFactory", + "module_path": "lab_system.master.steps.factory.run.android_mirroring_runner" + }, + { + "class_name": "InstallBuildStepFactory", + "module_path": "lab_system.master.steps.factory.run.android_mirroring_runner" + } + ], + "step_identifier": "build_handling" + }, + { + "step_description": "Sets up logging", + "step_factories": [ + { + "class_name": "NoopStepFactory", + "module_path": "lab_system.master.steps.factory.common.noop" + } + ], + "step_identifier": "testrun_setup" + }, + { + "step_description": "Runs Remote Display Test", + "step_factories": [ + { + "class_name": "IosLatencyStepFactory", + "module_path": "lab_system.master.steps.factory.run.ios_remote_display_runner" + } + ], + "step_identifier": "test_running" + }, + { + "step_description": "Copies local log files to Google Storage", + "step_factories": [ + { + "class_name": "NoopStepFactory", + "module_path": "lab_system.master.steps.factory.common.noop" + } + ], + "step_identifier": "logs_copy" + }, + { + "step_description": "Processes the output of the test", + "step_factories": [ + { + "class_name": "GetLogcatStepFactory", + "module_path": "lab_system.master.steps.factory.run.android_mirroring_runner" + }, + { + "class_name": "ProcessLatencyPhotoStepFactory", + "module_path": "lab_system.master.steps.factory.run.ios_remote_display_runner" + }, + { + "class_name": "CopyLogsToRepositoryStepFactory", + "module_path": "lab_system.master.steps.factory.run.android_mirroring_runner" + } + ], + "step_identifier": "output_processing" + }, + { + "step_description": "Cleans up slave and devices after the testrun", + "step_factories": [ + { + "class_name": "DeviceDeallocatorStepFactory", + "module_path": "lab_system.master.steps.factory.device.cloud_deallocator" + }, + { + "class_name": "CleanupWorkdirStepFactory", + "module_path": "lab_system.master.steps.factory.cleanup.workdir" + } + ], + "step_identifier": "testrun_cleanup" + } +]
diff --git a/lab_system/master/config/step_factories_recipes/remote_display_nexus_player.json b/lab_system/master/config/step_factories_recipes/remote_display_nexus_player.json new file mode 100644 index 0000000..bd495d1 --- /dev/null +++ b/lab_system/master/config/step_factories_recipes/remote_display_nexus_player.json
@@ -0,0 +1,102 @@ +[ + { + "step_description": "Sets up testrun specific properties", + "step_factories": [ + { + "class_name": "RecordingPropertiesSetterStepFactory", + "module_path": "lab_system.master.steps.factory.run.android_mirroring_runner" + } + ], + "step_identifier": "properties" + }, + { + "step_description": "Allocates devices for the testrun", + "step_factories": [ + { + "class_name": "DeviceAllocatorStepFactory", + "module_path": "lab_system.master.steps.factory.run.android_mirroring_runner" + } + ], + "step_identifier": "device_allocation" + }, + { + "step_description": "Copying Build to test slave and installing on device", + "step_factories": [ + { + "class_name": "RsyncRepositoriesStepFactory", + "module_path": "lab_system.master.steps.factory.build.copy_test_repo" + }, + { + "class_name": "DefaultOtaFetcherStepFactory", + "module_path": "lab_system.master.steps.factory.build.fetcher" + }, + { + "class_name": "CopyBuildToSlaveStepFactory", + "module_path": "lab_system.master.steps.factory.run.android_mirroring_runner" + }, + { + "class_name": "InstallBuildStepFactory", + "module_path": "lab_system.master.steps.factory.run.android_mirroring_nexus_player_runner" + } + ], + "step_identifier": "build_handling" + }, + { + "step_description": "Sets up logging", + "step_factories": [ + { + "class_name": "NoopStepFactory", + "module_path": "lab_system.master.steps.factory.common.noop" + } + ], + "step_identifier": "testrun_setup" + }, + { + "step_description": "Runs Remote Display Test", + "step_factories": [ + { + "class_name": "RemoteDisplayStepFactory", + "module_path": "lab_system.master.steps.factory.run.android_mirroring_nexus_player_runner" + }, + { + "module_path": "lab_system.master.steps.factory.device.deallocator", + "class_name": "DeviceDeallocatorStepFactory" + } + ], + "step_identifier": "test_running" + }, + { + "step_description": "Copies local log files to Google Storage", + "step_factories": [ + { + "class_name": "NoopStepFactory", + "module_path": "lab_system.master.steps.factory.common.noop" + } + ], + "step_identifier": "logs_copy" + }, + { + "step_description": "Processes the output of the test", + "step_factories": [ + { + "class_name": "GetLogcatStepFactory", + "module_path": "lab_system.master.steps.factory.run.android_mirroring_runner" + }, + { + "class_name": "CopyLogsToRepositoryStepFactory", + "module_path": "lab_system.master.steps.factory.run.android_mirroring_runner" + } + ], + "step_identifier": "output_processing" + }, + { + "step_description": "Cleans up slave and devices after the testrun", + "step_identifier": "testrun_cleanup", + "step_factories": [ + { + "module_path": "lab_system.master.steps.factory.cleanup.workdir", + "class_name": "CleanupWorkdirStepFactory" + } + ] + } +]
diff --git a/lab_system/master/config/step_factories_recipes/swarming_unit_test_recipe.json b/lab_system/master/config/step_factories_recipes/swarming_unit_test_recipe.json new file mode 100644 index 0000000..7d2b4eb --- /dev/null +++ b/lab_system/master/config/step_factories_recipes/swarming_unit_test_recipe.json
@@ -0,0 +1,126 @@ +[ + { + "step_description": "Sets up testrun specific properties", + "step_factories": [ + { + "class_name": "UnitTestTmpSetterStepFactory", + "module_path": "lab_system.master.steps.factory.run.unit_test_runner" + }, + { + "class_name": "ReducedLeaseDeviceAllocatorStepFactory", + "module_path": "lab_system.master.steps.factory.device.cloud_allocator" + }, + { + "class_name": "GetCommaSeparatedDeviceIpAddrStepFactory", + "module_path": "lab_system.master.steps.factory.device.allocator" + }, + { + "class_name": "UnitTestPropertiesSetterStepFactory", + "module_path": "lab_system.master.steps.factory.run.unit_test_runner" + } + ], + "step_identifier": "properties" + }, + { + "step_description": "Allocates devices for the testrun", + "step_factories": [ + { + "class_name": "NoopStepFactory", + "module_path": "lab_system.master.steps.factory.common.noop" + } + ], + "step_identifier": "device_allocation" + }, + { + "step_description": "Fetches and installs builds on devices", + "step_factories": [ + { + "class_name": "NoopStepFactory", + "module_path": "lab_system.master.steps.factory.common.noop" + } + ], + "step_identifier": "build_handling" + }, + { + "step_description": "Installs test binaries to unit test device", + "step_factories": [ + { + "class_name": "NoopStepFactory", + "module_path": "lab_system.master.steps.factory.common.noop" + } + ], + "step_identifier": "testrun_setup" + }, + { + "step_description": "Runs unit test.", + "step_factories": [ + { + "class_name": "CreateIsolateStepFactory", + "module_path": "lab_system.master.steps.factory.run.unit_test_runner" + }, + { + "class_name": "ArchiveIsolateStepFactory", + "module_path": "lab_system.master.steps.factory.run.unit_test_runner" + }, + { + "class_name": "GetHashStepFactory", + "module_path": "lab_system.master.steps.factory.run.unit_test_runner" + }, + { + "class_name": "TriggerTestStepFactory", + "module_path": "lab_system.master.steps.factory.run.unit_test_runner" + }, + { + "class_name": "CollectTestResultStepFactory", + "module_path": "lab_system.master.steps.factory.run.unit_test_runner" + }, + { + "class_name": "RecipeUploadResultToSpongeStepFactory", + "module_path": "lab_system.master.steps.factory.run.unit_test_runner" + } + ], + "step_identifier": "test_running" + }, + { + "step_description": "Create good build hint", + "step_factories": [ + { + "class_name": "CreateHintStepFactory", + "module_path": "lab_system.master.steps.factory.run.unit_test_runner" + }, + { + "class_name": "RemoveUnitTestBinariesStepFactory", + "module_path": "lab_system.master.steps.factory.run.unit_test_runner" + }, + { + "class_name": "CopyLogsToRepositoryStepFactory", + "module_path": "lab_system.master.steps.factory.output.cloud_logs" + } + ], + "step_identifier": "logs_copy" + }, + { + "step_description": "A placeholder with no-ops to allow custom logs parsing.", + "step_factories": [ + { + "class_name": "NoopStepFactory", + "module_path": "lab_system.master.steps.factory.common.noop" + } + ], + "step_identifier": "output_processing" + }, + { + "step_description": "Cleans up slave and devices after the testrun", + "step_factories": [ + { + "class_name": "DeviceDeallocatorStepFactory", + "module_path": "lab_system.master.steps.factory.device.cloud_deallocator" + }, + { + "class_name": "CleanupWorkdirStepFactory", + "module_path": "lab_system.master.steps.factory.cleanup.workdir" + } + ], + "step_identifier": "testrun_cleanup" + } +]
diff --git a/lab_system/master/config/step_factories_recipes/tdls_test.json b/lab_system/master/config/step_factories_recipes/tdls_test.json new file mode 100644 index 0000000..f3aca50 --- /dev/null +++ b/lab_system/master/config/step_factories_recipes/tdls_test.json
@@ -0,0 +1,22 @@ +[ + { + "step_description": "Allocates devices for the testrun", + "step_factories": [ + { + "class_name": "StrictDeviceAllocatorStepFactory", + "module_path": "lab_system.master.steps.factory.device.cloud_allocator" + } + ], + "step_identifier": "device_allocation" + }, + { + "step_description": "Running TDLS test.", + "step_factories": [ + { + "class_name": "TdlsTestRunnerStepFactory", + "module_path": "lab_system.master.steps.factory.run.tdls_runner" + } + ], + "step_identifier": "test_running" + } +]
diff --git a/lab_system/master/config/step_factories_recipes/unit_test_lower_case_product_name_recipe.json b/lab_system/master/config/step_factories_recipes/unit_test_lower_case_product_name_recipe.json new file mode 100644 index 0000000..1bf4ebf --- /dev/null +++ b/lab_system/master/config/step_factories_recipes/unit_test_lower_case_product_name_recipe.json
@@ -0,0 +1,114 @@ +[ + { + "step_description": "Sets up testrun specific properties", + "step_factories": [ + { + "class_name": "UnitTestTmpSetterStepFactory", + "module_path": "lab_system.master.steps.factory.run.unit_test_runner" + }, + { + "class_name": "LowerCaseDeviceAllocatorStepFactory", + "module_path": "lab_system.master.steps.factory.run.unit_test_runner" + }, + { + "class_name": "GetFirstDeviceIpAddrStepFactory", + "module_path": "lab_system.master.steps.factory.device.allocator" + }, + { + "class_name": "UnitTestPropertiesSetterStepFactory", + "module_path": "lab_system.master.steps.factory.run.unit_test_runner" + } + ], + "step_identifier": "properties" + }, + { + "step_description": "Allocates devices for the testrun", + "step_factories": [ + { + "class_name": "NoopStepFactory", + "module_path": "lab_system.master.steps.factory.common.noop" + } + ], + "step_identifier": "device_allocation" + }, + { + "step_description": "Fetches and installs builds on devices", + "step_factories": [ + { + "class_name": "BuildFetcherStepFactory", + "module_path": "lab_system.master.steps.factory.run.unit_test_runner" + }, + { + "class_name": "BuildInstallerStepFactory", + "module_path": "lab_system.master.steps.factory.run.unit_test_runner" + } + ], + "step_identifier": "build_handling" + }, + { + "step_description": "Installs test binaries to unit test device", + "step_factories": [ + { + "class_name": "PrepDeviceStepFactory", + "module_path": "lab_system.master.steps.factory.run.unit_test_runner" + } + ], + "step_identifier": "testrun_setup" + }, + { + "step_description": "Runs unit test.", + "step_factories": [ + { + "class_name": "UnitTestRunStepFactory", + "module_path": "lab_system.master.steps.factory.run.unit_test_runner" + }, + { + "class_name": "UploadResultToSpongeStepFactory", + "module_path": "lab_system.master.steps.factory.run.unit_test_runner" + } + ], + "step_identifier": "test_running" + }, + { + "step_description": "Create good build hint", + "step_factories": [ + { + "class_name": "CreateHintStepFactory", + "module_path": "lab_system.master.steps.factory.run.unit_test_runner" + }, + { + "class_name": "CopyLogStepFactory", + "module_path": "lab_system.master.steps.factory.run.unit_test_runner" + }, + { + "class_name": "CopyLogsFromRootToRepositoryStepFactory", + "module_path": "lab_system.master.steps.factory.output.cloud_logs" + } + ], + "step_identifier": "logs_copy" + }, + { + "step_description": "A placeholder with no-ops to allow custom logs parsing.", + "step_factories": [ + { + "class_name": "NoopStepFactory", + "module_path": "lab_system.master.steps.factory.common.noop" + } + ], + "step_identifier": "output_processing" + }, + { + "step_description": "Cleans up slave and devices after the testrun", + "step_factories": [ + { + "class_name": "DeviceDeallocatorStepFactory", + "module_path": "lab_system.master.steps.factory.device.cloud_deallocator" + }, + { + "class_name": "CleanupWorkdirStepFactory", + "module_path": "lab_system.master.steps.factory.cleanup.workdir" + } + ], + "step_identifier": "testrun_cleanup" + } +]
diff --git a/lab_system/master/config/step_factories_recipes/unit_test_no_usb_check_recipe.json b/lab_system/master/config/step_factories_recipes/unit_test_no_usb_check_recipe.json new file mode 100644 index 0000000..8eabf8d --- /dev/null +++ b/lab_system/master/config/step_factories_recipes/unit_test_no_usb_check_recipe.json
@@ -0,0 +1,114 @@ +[ + { + "step_description": "Sets up testrun specific properties", + "step_factories": [ + { + "class_name": "UnitTestTmpSetterStepFactory", + "module_path": "lab_system.master.steps.factory.run.unit_test_runner" + }, + { + "class_name": "ReducedLeaseDeviceAllocatorStepFactory", + "module_path": "lab_system.master.steps.factory.device.cloud_allocator" + }, + { + "class_name": "GetFirstDeviceIpAddrStepFactory", + "module_path": "lab_system.master.steps.factory.device.allocator" + }, + { + "class_name": "UnitTestPropertiesSetterStepFactory", + "module_path": "lab_system.master.steps.factory.run.unit_test_runner" + } + ], + "step_identifier": "properties" + }, + { + "step_description": "Allocates devices for the testrun", + "step_factories": [ + { + "class_name": "NoopStepFactory", + "module_path": "lab_system.master.steps.factory.common.noop" + } + ], + "step_identifier": "device_allocation" + }, + { + "step_description": "Fetches and installs builds on devices", + "step_factories": [ + { + "class_name": "BuildFetcherStepFactory", + "module_path": "lab_system.master.steps.factory.run.unit_test_runner" + }, + { + "class_name": "BuildInstallerNoUsbCheckStepFactory", + "module_path": "lab_system.master.steps.factory.run.unit_test_runner" + } + ], + "step_identifier": "build_handling" + }, + { + "step_description": "Installs test binaries to unit test device", + "step_factories": [ + { + "class_name": "PrepDeviceStepFactory", + "module_path": "lab_system.master.steps.factory.run.unit_test_runner" + } + ], + "step_identifier": "testrun_setup" + }, + { + "step_description": "Runs unit test.", + "step_factories": [ + { + "class_name": "UnitTestRunStepFactory", + "module_path": "lab_system.master.steps.factory.run.unit_test_runner" + }, + { + "class_name": "UploadResultToSpongeStepFactory", + "module_path": "lab_system.master.steps.factory.run.unit_test_runner" + } + ], + "step_identifier": "test_running" + }, + { + "step_description": "Create good build hint", + "step_factories": [ + { + "class_name": "CreateHintStepFactory", + "module_path": "lab_system.master.steps.factory.run.unit_test_runner" + }, + { + "class_name": "CopyLogStepFactory", + "module_path": "lab_system.master.steps.factory.run.unit_test_runner" + }, + { + "class_name": "CopyLogsFromRootToRepositoryStepFactory", + "module_path": "lab_system.master.steps.factory.output.cloud_logs" + } + ], + "step_identifier": "logs_copy" + }, + { + "step_description": "A placeholder with no-ops to allow custom logs parsing.", + "step_factories": [ + { + "class_name": "NoopStepFactory", + "module_path": "lab_system.master.steps.factory.common.noop" + } + ], + "step_identifier": "output_processing" + }, + { + "step_description": "Cleans up slave and devices after the testrun", + "step_factories": [ + { + "class_name": "DeviceDeallocatorStepFactory", + "module_path": "lab_system.master.steps.factory.device.cloud_deallocator" + }, + { + "class_name": "CleanupWorkdirStepFactory", + "module_path": "lab_system.master.steps.factory.cleanup.workdir" + } + ], + "step_identifier": "testrun_cleanup" + } +]
diff --git a/lab_system/master/config/step_factories_recipes/unit_test_recipe.json b/lab_system/master/config/step_factories_recipes/unit_test_recipe.json new file mode 100644 index 0000000..a827a8d --- /dev/null +++ b/lab_system/master/config/step_factories_recipes/unit_test_recipe.json
@@ -0,0 +1,114 @@ +[ + { + "step_description": "Sets up testrun specific properties", + "step_factories": [ + { + "class_name": "PropertiesSetterStepFactoryWithDummyBuild", + "module_path": "lab_system.master.steps.factory.setup.properties" + }, + { + "class_name": "AddUnitTestMarkerStepFactory", + "module_path": "lab_system.master.steps.factory.run.unit_test_runner" + } + ], + "step_identifier": "properties" + }, + { + "step_description": "Allocates devices for the testrun", + "step_factories": [ + { + "class_name": "ReducedLeaseDeviceAllocatorStepFactory", + "module_path": "lab_system.master.steps.factory.device.cloud_allocator" + }, + { + "class_name": "GetFirstDeviceIpAddrStepFactory", + "module_path": "lab_system.master.steps.factory.device.allocator" + } + ], + "step_identifier": "device_allocation" + }, + { + "step_description": "Fetches and installs builds on devices", + "step_factories": [ + { + "class_name": "DefaultOtaFetcherStepFactory", + "module_path": "lab_system.master.steps.factory.build.fetcher" + }, + { + "class_name": "BuildInstallerRollbackStartedMarkerStepFactory", + "module_path": "lab_system.master.steps.factory.run.unit_test_runner" + } + ], + "step_identifier": "build_handling" + }, + { + "step_description": "Installs test binaries to unit test device", + "step_factories": [ + { + "class_name": "PrepDeviceRollbackStartedMarkerStepFactory", + "module_path": "lab_system.master.steps.factory.run.unit_test_runner" + } + ], + "step_identifier": "testrun_setup" + }, + { + "step_description": "Runs unit test.", + "step_factories": [ + { + "class_name": "UnitTestRunStepFactory", + "module_path": "lab_system.master.steps.factory.run.unit_test_runner" + }, + { + "class_name": "UploadResultToSpongeRollbackStartedMarkerStepFactory", + "module_path": "lab_system.master.steps.factory.run.unit_test_runner" + } + ], + "step_identifier": "test_running" + }, + { + "step_description": "Copy log files", + "step_factories": [ + { + "class_name": "CopyLogStepFactory", + "module_path": "lab_system.master.steps.factory.run.unit_test_runner" + }, + { + "class_name": "CopyLogsFromRootToRepositoryStepFactory", + "module_path": "lab_system.master.steps.factory.output.cloud_logs" + } + ], + "step_identifier": "logs_copy" + }, + { + "step_description": "A placeholder with no-ops to allow custom logs parsing.", + "step_factories": [ + { + "class_name": "NoopStepFactory", + "module_path": "lab_system.master.steps.factory.common.noop" + } + ], + "step_identifier": "output_processing" + }, + { + "step_description": "Cleans up slave and devices after the testrun", + "step_factories": [ + { + "class_name": "DisableMdnsStepFactory", + "module_path": "lab_system.master.steps.factory.device.cloud_deallocator" + }, + { + "class_name": "DeviceDeallocatorStepFactory", + "module_path": "lab_system.master.steps.factory.device.cloud_deallocator" + }, + { + "class_name": "RemoveUnitTestMarkerStepFactory", + "module_path": "lab_system.master.steps.factory.run.unit_test_runner" + }, + { + "class_name": "CleanupWorkdirStepFactory", + "module_path": "lab_system.master.steps.factory.cleanup.workdir" + } + ], + "step_identifier": "testrun_cleanup" + } +]
diff --git a/lab_system/master/config/steps/default.cfg b/lab_system/master/config/steps/default.cfg new file mode 100644 index 0000000..5248503 --- /dev/null +++ b/lab_system/master/config/steps/default.cfg
@@ -0,0 +1,102 @@ +[ + { + "step_description": "Sets up testrun specific properties", + "step_identifier": "properties", + "step_factories": [ + { + "module_path": "lab_system.master.steps.factory.setup.properties", + "class_name": "PropertiesSetterStepFactory" + } + ] + }, + { + "step_description": "Allocates devices for the testrun", + "step_identifier": "device_allocation", + "step_factories": [ + { + "module_path": "lab_system.master.steps.factory.device.cloud_allocator", + "class_name": "DeviceAllocatorStepFactory" + } + ] + }, + { + "step_description": "Fetches and installs builds on devices", + "step_identifier": "build_handling", + "step_factories": [ + { + "module_path": "lab_system.master.steps.factory.device.device_clean", + "class_name": "DeviceCleanStepFactory" + }, + { + "module_path": "lab_system.master.steps.factory.build.fetcher", + "class_name": "DefaultOtaFetcherStepFactory" + }, + { + "module_path": "lab_system.master.steps.factory.device.health_check", + "class_name": "HealthCheckStepFactory" + }, + { + "module_path": "lab_system.master.steps.factory.build.installer_eurlab", + "class_name": "BuildInstallerStepFactory" + } + ] + }, + { + "step_description": "A placeholder with no-ops to allow pre setup of tests.", + "step_identifier": "testrun_setup", + "step_factories": [ + { + "class_name": "NoopStepFactory", + "module_path": "lab_system.master.steps.factory.common.noop" + } + ] + }, + { + "step_description": "Executes the tests using the eurtest runner.", + "step_identifier": "test_running", + "step_factories": [ + { + "module_path": "lab_system.master.steps.factory.run.test_runner", + "class_name": "TestRunnerStepFactory" + } + ] + }, + { + "step_description": "Copies local log files to Google Storage", + "step_identifier": "logs_copy", + "step_factories": [ + { + "module_path": "lab_system.master.steps.factory.output.cloud_logs", + "class_name": "CopyLogsToRepositoryStepFactory" + } + ] + }, + { + "step_description": "A placeholder with no-ops to allow custom logs parsing.", + "step_identifier": "output_processing", + "step_factories": [ + { + "class_name": "NoopStepFactory", + "module_path": "lab_system.master.steps.factory.common.noop" + } + ] + }, + { + "step_description": "Cleans up slave and devices after the testrun", + "step_identifier": "testrun_cleanup", + "step_factories": [ + { + "module_path": "lab_system.master.steps.factory.device.cloud_deallocator", + "class_name": "DisableMdnsStepFactory" + }, + { + "module_path": "lab_system.master.steps.factory.device.cloud_deallocator", + "class_name": "DeviceDeallocatorStepFactory" + }, + { + "module_path": "lab_system.master.steps.factory.cleanup.workdir", + "class_name": "CleanupWorkdirStepFactory" + } + ] + } +]
diff --git a/lab_system/master/config/swarming/README.md b/lab_system/master/config/swarming/README.md new file mode 100644 index 0000000..e28366d --- /dev/null +++ b/lab_system/master/config/swarming/README.md
@@ -0,0 +1,8 @@ +The bot_config file is used for the swarming bot config. + +This version saves the changes made specifically for the Cast team. + +To deploy, remove this file to bot_config.py and upload to the +[Bot Config](https://cast-swarming.appspot.com/restricted/upload/bot_config). + +Note: this file is not compliant with the gpylint code style.
diff --git a/lab_system/master/config/swarming/bot_config.py_ b/lab_system/master/config/swarming/bot_config.py_ new file mode 100644 index 0000000..4041c05 --- /dev/null +++ b/lab_system/master/config/swarming/bot_config.py_
@@ -0,0 +1,248 @@ +# coding: utf-8 +# Copyright 2013 The LUCI Authors. All rights reserved. +# Use of this source code is governed under the Apache License, Version 2.0 +# that can be found in the LICENSE file. + +"""This file is meant to be overriden by the server's specific copy. + +You can upload a new version via /restricted/upload/bot_config. + +There's 3 types of functions in this file: + - get_*() to return properties to describe this bot. + - on_*() as hooks based on events happening on the bot. + - setup_*() to setup global state on the host. + +This file shouldn't import from other scripts in this directory except +os_utilities which is guaranteed to be usable as an API. It's fine to import +from stdlib. + +Set the environment variable SWARMING_LOAD_TEST=1 to disable the use of +server-provided bot_config.py. This permits safe load testing. + +This file contains unicode to confirm UTF-8 encoded file is well supported. +Here's a pile of poo: 💩 +""" + +import os +import time + +from api import os_utilities +from api import platforms + +# Unused argument 'bot' - pylint: disable=W0613 + + +def get_dimensions(bot): + # pylint: disable=line-too-long + """Returns dict with the bot's dimensions. + + The dimensions are what are used to select the bot that can run each task. + + The bot id will be automatically selected based on the hostname with + os_utilities.get_dimensions(). If you want something more special, specify it + in your bot_config.py and override the item 'id'. + + The dimensions returned here will be joined with server defined dimensions + (extracted from bots.cfg config file based on the bot id). Server defined + dimensions override the ones provided by the bot. See bot.Bot.dimensions for + more information. + + See https://github.com/luci/luci-py/tree/master/appengine/swarming/doc/Magic-Values.md. + + Arguments: + - bot: bot.Bot instance or None. See ../api/bot.py. + """ + dimensions = os_utilities.get_dimensions() + + # The bot base directory is formatted like <HOME>/bots/<Pool>/<Id> + id = dimensions['id'][0] + index = os.path.basename(bot.base_dir) + pool_name = os.path.basename(os.path.dirname(bot.base_dir)) + + dimensions['pool'] = [pool_name] + dimensions['id'] = ['%s_%s' % (id, index)] + + return dimensions + + +def get_state(bot): + # pylint: disable=line-too-long + """Returns dict with a state of the bot reported to the server with each poll. + + It is only for dynamic state that changes while bot is running for information + for the sysadmins. + + The server can not use this state for immediate scheduling purposes (use + 'dimensions' for that), but it can use it for maintenance and bookkeeping + tasks. + + See https://github.com/luci/luci-py/tree/master/appengine/swarming/doc/Magic-Values.md. + + Arguments: + - bot: bot.Bot instance or None. See ../api/bot.py. + """ + return os_utilities.get_state() + + +def get_authentication_headers(bot): + """Returns authentication headers and their expiration time. + + The returned headers will be passed with each HTTP request to the Swarming + server (and only Swarming server). The bot will use the returned headers until + they are close to expiration (usually 6 min, see AUTH_HEADERS_EXPIRATION_SEC + in remote_client.py), and then it'll attempt to refresh them by calling + get_authentication_headers again. + + Can be used to implement per-bot authentication. If no headers are returned, + the server will use only IP whitelist for bot authentication. + + On GCE will use OAuth token of the default GCE service account. It should have + "User info" API scope enabled (this can be set when starting an instance). The + server should be configured (via bots.cfg) to trust this account (see + 'require_service_account' in bots.proto). + + May be called by different threads, but never concurrently. + + Arguments: + - bot: bot.Bot instance. See ../api/bot.py. + + Returns: + Tuple (dict with headers or None, unix timestamp of when they expire). + """ + if platforms.is_gce(): + tok = platforms.gce.oauth2_access_token() + return {'Authorization': 'Bearer %s' % tok}, time.time() + 5*60 + return (None, None) + + +### Hooks + + +def on_bot_shutdown(bot): + """Hook function called when the bot shuts down, usually rebooting. + + It's a good time to do other kinds of cleanup. + + Arguments: + - bot: bot.Bot instance. See ../api/bot.py. + """ + pass + + +def on_bot_startup(bot): + """Hook function called when the bot starts, before handshake with the server. + + Here the bot may initialize and examine its environment, pick initial state + and dimensions to send to the server during the handshake. + + Arguments: + - bot: bot.Bot instance. See ../api/bot.py. + """ + pass + + +def on_handshake(bot): + """Hook function called when the bot starts, after handshake with the server. + + Here the bot already knows server enforced dimensions (defined in server side + bots.cfg file). + + This is called right before starting to poll for tasks. It's a good time to + do some final initialization or cleanup that may depend on server provided + configuration. + + Arguments: + - bot: bot.Bot instance. See ../api/bot.py. + """ + pass + + +def on_before_task(bot, bot_file=None): + """Hook function called before running a task. + + It shouldn't do much, since it can't cancel the task so it shouldn't do + anything too fancy. + + Arguments: + - bot: bot.Bot instance. See ../api/bot.py. + - bot_file: Path to file to write information about the state of the bot. + This file can be used to pass certain info about the bot + to tasks, such as which connected android devices to run on. See + https://github.com/luci/luci-py/tree/master/appengine/swarming/doc/Magic-Values.md#run_isolated + TODO(bpastene): Remove default value None. + """ + pass + + +def on_after_task(bot, failure, internal_failure, dimensions, summary): + """Hook function called after running a task. + + It is an excellent place to do post-task cleanup of temporary files. + + The default implementation restarts after a task failure or an internal + failure. + + Arguments: + - bot: bot.Bot instance. See ../api/bot.py. + - failure: bool, True if the task failed. + - internal_failure: bool, True if an internal failure happened. + - dimensions: dict, Dimensions requested as part of the task. + - summary: dict, Summary of the task execution. + """ + # Example code: + #if failure: + # bot.restart('Task failure') + #elif internal_failure: + # bot.restart('Internal failure') + + +def on_bot_idle(bot, since_last_action): + """Hook function called once when the bot has been idle; when it has no + command to execute. + + This is an excellent place to put device in 'cool down' mode or any + "pre-warming" kind of stuff that could take several seconds to do, that would + not be appropriate to do in on_after_task(). It could be worth waiting for + `since_last_action` to be several seconds before doing a more lengthy + operation. + + This function is called repeatedly until an action is taken (a task, updating, + etc). + + This is a good place to do "auto reboot" for hardware based bots that are + rebooted periodically. + + Arguments: + - bot: bot.Bot instance. See ../api/bot.py. + - since_last_action: time in second since last action; e.g. amount of time the + bot has been idle. + """ + pass + + +### Setup + + +def setup_bot(bot): + """Does one time initialization for this bot. + + Returns True if it's fine to start the bot right away. Otherwise, the calling + script should exit. + + This is an excellent place to drop a README file in the bot directory, to give + more information about the purpose of this bot. + + Example: making this script starts automatically on user login via + os_utilities.set_auto_startup_win() or os_utilities.set_auto_startup_osx(). + """ + with open(os.path.join(bot.base_dir, 'README'), 'wb') as f: + f.write( +"""This directory contains a Swarming bot. + +Swarming source code is hosted at https://github.com/luci/luci-py. + +The bot was generated from the server %s. To get the bot's attributes, run: + + python swarming_bot.zip attributes +""" % bot.server) + return True
diff --git a/lab_system/master/config/tests/als_test/als_test.cfg b/lab_system/master/config/tests/als_test/als_test.cfg new file mode 100644 index 0000000..1b049a4 --- /dev/null +++ b/lab_system/master/config/tests/als_test/als_test.cfg
@@ -0,0 +1,25 @@ +# Config file for als test +# +# Do not modify property names +# Run make reconfig if you change a value +# and buildbot is running +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.als.als_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=AlsTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.als.als_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=AlsTestSequence + +# Sign in requirement +SIGNED_IN=True + +# Disable selina sensor in these devices +DEVICES_WITH_SELINA_SENSOR=elaine
diff --git a/lab_system/master/config/tests/als_test/elaine_input_rgbc_output_ct_and_brightness.yaml b/lab_system/master/config/tests/als_test/elaine_input_rgbc_output_ct_and_brightness.yaml new file mode 100644 index 0000000..37a1ec6 --- /dev/null +++ b/lab_system/master/config/tests/als_test/elaine_input_rgbc_output_ct_and_brightness.yaml
@@ -0,0 +1,292 @@ +# RGBC inputs for ambient light sensor, with their expected output color temperature and expected_brightness. + +# INPUTS: +# The RGBC values refer to the amount of light reported by a photodiode sensor. +# RGB refers to filtered red, green and blue light respectively. +# C refers to raw, unfiltered 'clear' light, and is roughly the sum of the three separate RGB values. + +# OUTPUTS: +# The expected computed values of color temperature and expected_brightness, given the input RGBC values +# Color temperature is measured in kelvin and ranges from a 'cool blue' white color, to a 'warm red' white color. +# Brightness is a percentage value where 100% is the greatest expected_brightness the light sensing system can perceive, while 0% is absolute darkness. + +- + red: 7555 + green: 7686 + blue: 6067 + clear: 21368 + expected_color_temp: 6650 + expected_brightness: 1 +- + red: 6980 + green: 7105 + blue: 5618 + clear: 19760 + expected_color_temp: 6650 + expected_brightness: 1 +- + red: 3002 + green: 3060 + blue: 2407 + clear: 8503 + expected_color_temp: 6650 + expected_brightness: 0.532 +- + red: 792 + green: 813 + blue: 636 + clear: 2249 + expected_color_temp: 6650 + expected_brightness: 0.141 +- + red: 235 + green: 240 + blue: 188 + clear: 666 + expected_color_temp: 6650 + expected_brightness: 0.033 +- + red: 124 + green: 128 + blue: 100 + clear: 353 + expected_color_temp: 6650 + expected_brightness: 0.018 +- + red: 67 + green: 69 + blue: 54 + clear: 190 + expected_color_temp: 6650 + expected_brightness: 0.010 +- + red: 0 + green: 0 + blue: 0 + clear: 0 + expected_color_temp: 2856 + expected_brightness: 0.001 +- + red: 22 + green: 23 + blue: 18 + clear: 63 + expected_color_temp: 6650 + expected_brightness: 0.004 +- + red: 7956 + green: 7833 + blue: 5998 + clear: 21775 + expected_color_temp: 6650 + expected_brightness: 1 +- + red: 7087 + green: 6590 + blue: 4790 + clear: 18341 + expected_color_temp: 6650 + expected_brightness: 1 +- + red: 3003 + green: 2791 + blue: 2015 + clear: 7762 + expected_color_temp: 6650 + expected_brightness: 0.488 +- + red: 810 + green: 755 + blue: 541 + clear: 2092 + expected_color_temp: 6650 + expected_brightness: 0.131 +- + red: 232 + green: 215 + blue: 154 + clear: 597 + expected_color_temp: 6650 + expected_brightness: 0.037 +- + red: 115 + green: 107 + blue: 77 + clear: 297 + expected_color_temp: 6650 + expected_brightness: 0.019 +- + red: 62 + green: 58 + blue: 41 + clear: 160 + expected_color_temp: 6650 + expected_brightness: 0.010 +- + red: 23 + green: 22 + blue: 15 + clear: 60 + expected_color_temp: 6345 + expected_brightness: 0.005 +- + red: 8772 + green: 7147 + blue: 4611 + clear: 20087 + expected_color_temp: 5241 + expected_brightness: 1.0 +- + red: 7056 + green: 5742 + blue: 3705 + clear: 16150 + expected_color_temp: 5237 + expected_brightness: 1 +- + red: 2922 + green: 2382 + blue: 1521 + clear: 6684 + expected_color_temp: 5179 + expected_brightness: 0.480 +- + red: 767 + green: 625 + blue: 393 + clear: 1745 + expected_color_temp: 5089 + expected_brightness: 0.127 +- + red: 222 + green: 180 + blue: 113 + clear: 503 + expected_color_temp: 5060 + expected_brightness: 0.037 +- + red: 113 + green: 92 + blue: 57 + clear: 257 + expected_color_temp: 5006 + expected_brightness: 0.019 +- + red: 55 + green: 45 + blue: 28 + clear: 125 + expected_color_temp: 5047 + expected_brightness: 0.009 +- + red: 23 + green: 18 + blue: 11 + clear: 52 + expected_color_temp: 4788 + expected_brightness: 0.005 +- + red: 7830 + green: 5235 + blue: 2787 + clear: 15228 + expected_color_temp: 3817 + expected_brightness: 1.0 +- + red: 6086 + green: 4035 + blue: 2160 + clear: 11771 + expected_color_temp: 3801 + expected_brightness: 1.0 +- + red: 2641 + green: 1741 + blue: 927 + clear: 5086 + expected_color_temp: 3773 + expected_brightness: 0.538 +- + red: 691 + green: 453 + blue: 241 + clear: 1326 + expected_color_temp: 3753 + expected_brightness: 0.141 +- + red: 188 + green: 124 + blue: 66 + clear: 361 + expected_color_temp: 3774 + expected_brightness: 0.038 +- + red: 103 + green: 68 + blue: 36 + clear: 198 + expected_color_temp: 3767 + expected_brightness: 0.021 +- + red: 50 + green: 33 + blue: 18 + clear: 96 + expected_color_temp: 3822 + expected_brightness: 0.010 +- + red: 24 + green: 16 + blue: 8 + clear: 47 + expected_color_temp: 3662 + expected_brightness: 0.006 +- + red: 5093 + green: 2304 + blue: 1234 + clear: 7848 + expected_color_temp: 2856 + expected_brightness: 0.933 +- + red: 4095 + green: 1751 + blue: 940 + clear: 6117 + expected_color_temp: 2856 + expected_brightness: 0.719 +- + red: 1832 + green: 774 + blue: 415 + clear: 2721 + expected_color_temp: 2856 + expected_brightness: 0.319 +- + red: 501 + green: 209 + blue: 111 + clear: 739 + expected_color_temp: 2856 + expected_brightness: 0.087 +- + red: 132 + green: 55 + blue: 29 + clear: 194 + expected_color_temp: 2856 + expected_brightness: 0.017 +- + red: 72 + green: 30 + blue: 16 + clear: 106 + expected_color_temp: 2856 + expected_brightness: 0.010 +- + red: 36 + green: 15 + blue: 8 + clear: 52 + expected_color_temp: 2856 + expected_brightness: 0.005
diff --git a/lab_system/master/config/tests/als_test/estelle_input_rgbc_output_ct_and_brightness.yaml b/lab_system/master/config/tests/als_test/estelle_input_rgbc_output_ct_and_brightness.yaml new file mode 100644 index 0000000..cb7503c --- /dev/null +++ b/lab_system/master/config/tests/als_test/estelle_input_rgbc_output_ct_and_brightness.yaml
@@ -0,0 +1,292 @@ +# RGBC inputs for ambient light sensor, with their expected output color temperature and expected_brightness. + +# INPUTS: +# The RGBC values refer to the amount of light reported by a photodiode sensor. +# RGB refers to filtered red, green and blue light respectively. +# C refers to raw, unfiltered 'clear' light, and is roughly the sum of the three separate RGB values. + +# OUTPUTS: +# The expected computed values of color temperature and expected_brightness, given the input RGBC values +# Color temperature is measured in kelvin and ranges from a 'cool blue' white color, to a 'warm red' white color. +# Brightness is a percentage value where 100% is the greatest expected_brightness the light sensing system can perceive, while 0% is absolute darkness. + +- + red: 7555 + green: 7686 + blue: 6067 + clear: 21368 + expected_color_temp: 6650 + expected_brightness: 0.918 +- + red: 6980 + green: 7105 + blue: 5618 + clear: 19760 + expected_color_temp: 6650 + expected_brightness: 0.849 +- + red: 3002 + green: 3060 + blue: 2407 + clear: 8503 + expected_color_temp: 6650 + expected_brightness: 0.365 +- + red: 792 + green: 813 + blue: 636 + clear: 2249 + expected_color_temp: 6650 + expected_brightness: 0.118 +- + red: 235 + green: 240 + blue: 188 + clear: 666 + expected_color_temp: 6650 + expected_brightness: 0.039 +- + red: 124 + green: 128 + blue: 100 + clear: 353 + expected_color_temp: 6650 + expected_brightness: 0.021 +- + red: 67 + green: 69 + blue: 54 + clear: 190 + expected_color_temp: 6650 + expected_brightness: 0.012 +- + red: 0 + green: 0 + blue: 0 + clear: 0 + expected_color_temp: 2856 + expected_brightness: 0.001 +- + red: 22 + green: 23 + blue: 18 + clear: 63 + expected_color_temp: 6650 + expected_brightness: 0.005 +- + red: 7956 + green: 7833 + blue: 5998 + clear: 21775 + expected_color_temp: 6650 + expected_brightness: 0.941 +- + red: 7087 + green: 6590 + blue: 4790 + clear: 18341 + expected_color_temp: 6650 + expected_brightness: 0.886 +- + red: 3003 + green: 2791 + blue: 2015 + clear: 7762 + expected_color_temp: 6617 + expected_brightness: 0.381 +- + red: 810 + green: 755 + blue: 541 + clear: 2092 + expected_color_temp: 6515 + expected_brightness: 0.120 +- + red: 232 + green: 215 + blue: 154 + clear: 597 + expected_color_temp: 6477 + expected_brightness: 0.037 +- + red: 115 + green: 107 + blue: 77 + clear: 297 + expected_color_temp: 6572 + expected_brightness: 0.019 +- + red: 62 + green: 58 + blue: 41 + clear: 160 + expected_color_temp: 6333 + expected_brightness: 0.011 +- + red: 23 + green: 22 + blue: 15 + clear: 60 + expected_color_temp: 5975 + expected_brightness: 0.005 +- + red: 8772 + green: 7147 + blue: 4611 + clear: 20087 + expected_color_temp: 4676 + expected_brightness: 1.0 +- + red: 7056 + green: 5742 + blue: 3705 + clear: 16150 + expected_color_temp: 4671 + expected_brightness: 0.947 +- + red: 2922 + green: 2382 + blue: 1521 + clear: 6684 + expected_color_temp: 4604 + expected_brightness: 0.395 +- + red: 767 + green: 625 + blue: 393 + clear: 1745 + expected_color_temp: 4497 + expected_brightness: 0.128 +- + red: 222 + green: 180 + blue: 113 + clear: 503 + expected_color_temp: 4463 + expected_brightness: 0.042 +- + red: 113 + green: 92 + blue: 57 + clear: 257 + expected_color_temp: 4399 + expected_brightness: 0.023 +- + red: 55 + green: 45 + blue: 28 + clear: 125 + expected_color_temp: 4448 + expected_brightness: 0.012 +- + red: 23 + green: 18 + blue: 11 + clear: 52 + expected_color_temp: 4143 + expected_brightness: 0.006 +- + red: 7830 + green: 5235 + blue: 2787 + clear: 15228 + expected_color_temp: 3001 + expected_brightness: 0.991 +- + red: 6086 + green: 4035 + blue: 2160 + clear: 11771 + expected_color_temp: 2982 + expected_brightness: 0.763 +- + red: 2641 + green: 1741 + blue: 927 + clear: 5086 + expected_color_temp: 2948 + expected_brightness: 0.355 +- + red: 691 + green: 453 + blue: 241 + clear: 1326 + expected_color_temp: 2926 + expected_brightness: 0.144 +- + red: 188 + green: 124 + blue: 66 + clear: 361 + expected_color_temp: 2950 + expected_brightness: 0.042 +- + red: 103 + green: 68 + blue: 36 + clear: 198 + expected_color_temp: 2942 + expected_brightness: 0.024 +- + red: 50 + green: 33 + blue: 18 + clear: 96 + expected_color_temp: 3006 + expected_brightness: 0.012 +- + red: 24 + green: 16 + blue: 8 + clear: 47 + expected_color_temp: 2868 + expected_brightness: 0.006 +- + red: 5093 + green: 2304 + blue: 1234 + clear: 7848 + expected_color_temp: 2856 + expected_brightness: 0.474 +- + red: 4095 + green: 1751 + blue: 940 + clear: 6117 + expected_color_temp: 2856 + expected_brightness: 0.392 +- + red: 1832 + green: 774 + blue: 415 + clear: 2721 + expected_color_temp: 2856 + expected_brightness: 0.225 +- + red: 501 + green: 209 + blue: 111 + clear: 739 + expected_color_temp: 2856 + expected_brightness: 0.078 +- + red: 132 + green: 55 + blue: 29 + clear: 194 + expected_color_temp: 2856 + expected_brightness: 0.022 +- + red: 72 + green: 30 + blue: 16 + clear: 106 + expected_color_temp: 2856 + expected_brightness: 0.013 +- + red: 36 + green: 15 + blue: 8 + clear: 52 + expected_color_temp: 2856 + expected_brightness: 0.007
diff --git a/lab_system/master/config/tests/als_test/newman_input_rgbc_output_ct_and_brightness.yaml b/lab_system/master/config/tests/als_test/newman_input_rgbc_output_ct_and_brightness.yaml new file mode 100644 index 0000000..a8cca14 --- /dev/null +++ b/lab_system/master/config/tests/als_test/newman_input_rgbc_output_ct_and_brightness.yaml
@@ -0,0 +1,280 @@ +- + red: 7555 + green: 7686 + blue: 6067 + clear: 21368 + expected_color_temp: 6650 + expected_brightness: 1.0 +- + red: 6980 + green: 7105 + blue: 5618 + clear: 19760 + expected_color_temp: 6650 + expected_brightness: 1.0 +- + red: 3002 + green: 3060 + blue: 2407 + clear: 8503 + expected_color_temp: 6650 + expected_brightness: 0.598 +- + red: 792 + green: 813 + blue: 636 + clear: 2249 + expected_color_temp: 6650 + expected_brightness: 0.158 +- + red: 235 + green: 240 + blue: 188 + clear: 666 + expected_color_temp: 6650 + expected_brightness: 0.048 +- + red: 124 + green: 128 + blue: 100 + clear: 353 + expected_color_temp: 6650 + expected_brightness: 0.026 +- + red: 67 + green: 69 + blue: 54 + clear: 190 + expected_color_temp: 6650 + expected_brightness: 0.015 +- + red: 0 + green: 0 + blue: 0 + clear: 0 + expected_color_temp: 2856 + expected_brightness: 0.001 +- + red: 22 + green: 23 + blue: 18 + clear: 63 + expected_color_temp: 6650 + expected_brightness: 0.006 +- + red: 7956 + green: 7833 + blue: 5998 + clear: 21775 + expected_color_temp: 6650 + expected_brightness: 1.0 +- + red: 7087 + green: 6590 + blue: 4790 + clear: 18341 + expected_color_temp: 6650 + expected_brightness: 1.0 +- + red: 3003 + green: 2791 + blue: 2015 + clear: 7762 + expected_color_temp: 6650 + expected_brightness: 0.555 +- + red: 810 + green: 755 + blue: 541 + clear: 2092 + expected_color_temp: 6650 + expected_brightness: 0.150 +- + red: 232 + green: 215 + blue: 154 + clear: 597 + expected_color_temp: 6650 + expected_brightness: 0.044 +- + red: 115 + green: 107 + blue: 77 + clear: 297 + expected_color_temp: 6650 + expected_brightness: 0.022 +- + red: 62 + green: 58 + blue: 41 + clear: 160 + expected_color_temp: 6649 + expected_brightness: 0.013 +- + red: 23 + green: 22 + blue: 15 + clear: 60 + expected_color_temp: 6344 + expected_brightness: 0.006 +- + red: 8772 + green: 7147 + blue: 4611 + clear: 20087 + expected_color_temp: 5240 + expected_brightness: 1.0 +- + red: 7056 + green: 5742 + blue: 3705 + clear: 16150 + expected_color_temp: 5236 + expected_brightness: 1.0 +- + red: 2922 + green: 2382 + blue: 1521 + clear: 6684 + expected_color_temp: 5179 + expected_brightness: 0.550 +- + red: 767 + green: 625 + blue: 393 + clear: 1745 + expected_color_temp: 5088 + expected_brightness: 0.145 +- + red: 222 + green: 180 + blue: 113 + clear: 503 + expected_color_temp: 5060 + expected_brightness: 0.043 +- + red: 113 + green: 92 + blue: 57 + clear: 257 + expected_color_temp: 5005 + expected_brightness: 0.023 +- + red: 55 + green: 45 + blue: 28 + clear: 125 + expected_color_temp: 5046 + expected_brightness: 0.012 +- + red: 23 + green: 18 + blue: 11 + clear: 52 + expected_color_temp: 4788 + expected_brightness: 0.006 +- + red: 7830 + green: 5235 + blue: 2787 + clear: 15228 + expected_color_temp: 3817 + expected_brightness: 1.0 +- + red: 6086 + green: 4035 + blue: 2160 + clear: 11771 + expected_color_temp: 3800 + expected_brightness: 1.0 +- + red: 2641 + green: 1741 + blue: 927 + clear: 5086 + expected_color_temp: 3772 + expected_brightness: 0.518 +- + red: 691 + green: 453 + blue: 241 + clear: 1326 + expected_color_temp: 3753 + expected_brightness: 0.138 +- + red: 188 + green: 124 + blue: 66 + clear: 361 + expected_color_temp: 3773 + expected_brightness: 0.039 +- + red: 103 + green: 68 + blue: 36 + clear: 198 + expected_color_temp: 3767 + expected_brightness: 0.022 +- + red: 50 + green: 33 + blue: 18 + clear: 96 + expected_color_temp: 3821 + expected_brightness: 0.011 +- + red: 24 + green: 16 + blue: 8 + clear: 47 + expected_color_temp: 3662.22 + expected_brightness: 0.006 +- + red: 5093 + green: 2304 + blue: 1234 + clear: 7848 + expected_color_temp: 2856 + expected_brightness: 0.836 +- + red: 4095 + green: 1751 + blue: 940 + clear: 6117 + expected_color_temp: 2856 + expected_brightness: 0.645 +- + red: 1832 + green: 774 + blue: 415 + clear: 2721 + expected_color_temp: 2856 + expected_brightness: 0.285 +- + red: 501 + green: 209 + blue: 111 + clear: 739 + expected_color_temp: 2856 + expected_brightness: 0.079 +- + red: 132 + green: 55 + blue: 29 + clear: 194 + expected_color_temp: 2856 + expected_brightness: 0.021 +- + red: 72 + green: 30 + blue: 16 + clear: 106 + expected_color_temp: 2856 + expected_brightness: 0.012 +- + red: 36 + green: 15 + blue: 8 + clear: 52 + expected_color_temp: 2856 + expected_brightness: 0.007
diff --git a/lab_system/master/config/tests/android_mirroring_uma/android_mirroring_uma.cfg b/lab_system/master/config/tests/android_mirroring_uma/android_mirroring_uma.cfg new file mode 100644 index 0000000..67eb59c --- /dev/null +++ b/lab_system/master/config/tests/android_mirroring_uma/android_mirroring_uma.cfg
@@ -0,0 +1,20 @@ +# Config file for the uma logging wifi tests: +# Those test cases will rely on devices with only wifi connection. +# +# Do not modify property names +# Run make reconfig if you change a value +# and buildbot is running +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.uma_logging.uma_logging_screen_cast_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=UmaLoggingScreenCastTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.uma_logging.uma_logging_screen_cast_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=UmaLoggingTestSequence
diff --git a/lab_system/master/config/tests/android_mirroring_uma/test_defs.json b/lab_system/master/config/tests/android_mirroring_uma/test_defs.json new file mode 100644 index 0000000..7a17df8 --- /dev/null +++ b/lab_system/master/config/tests/android_mirroring_uma/test_defs.json
@@ -0,0 +1,13 @@ +[ + { + "group_name": "android_mirroring_uma", + "slave_name": "android_mirroring_uma", + "test_name": "android_mirroring_uma", + "branch": ["master", "release"], + "device_type": "earth", + "device_group": "android_mirroring_uma", + "identifier": "android_mirroring_uma", + "scheduler": "0 */6 * * *", + "step_factories_recipe": "step_factories_recipes/android_mirroring_uma.json" + } +]
diff --git a/lab_system/master/config/tests/androidthings_unit_test/test_defs.json b/lab_system/master/config/tests/androidthings_unit_test/test_defs.json new file mode 100644 index 0000000..6917223 --- /dev/null +++ b/lab_system/master/config/tests/androidthings_unit_test/test_defs.json
@@ -0,0 +1,16 @@ +[ + { + "branch": ["master", "androidthings_release", "androidthings_next_release"], + "build_flavor": "Release", + "device_group": "unit_test", + "device_type": "imx7d_pico", + "group_name": "cast_androidthings", + "identifier": "androidthings", + "scheduler": "*/10 * * * *", + "slave_name": "androidthings", + "slave_number": [ + 1 + ], + "step_factories_recipe": "step_factories_recipes/androidthings_unit_test_recipe.json" + } +]
diff --git a/lab_system/master/config/tests/app_prelaunch/app_prelaunch.cfg b/lab_system/master/config/tests/app_prelaunch/app_prelaunch.cfg new file mode 100644 index 0000000..daee20c --- /dev/null +++ b/lab_system/master/config/tests/app_prelaunch/app_prelaunch.cfg
@@ -0,0 +1,21 @@ +# Config file for app prelaunch tests on multiple apps. + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.app_prelaunch.app_prelaunch_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=AppPreLaunchTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.app_prelaunch.app_prelaunch_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=AppPreLaunchIterableTestSequence + +# Name of the file (in the test's configuration directory) containing +# the apps to test with app prelaunch. The file has the format +# {'apps': [{'name':<app_name>,'id':<app_id>}...]}. +APPS_FILE_NAME=apps.json + +# App launch state that indicates the app has launched. +APP_STARTED_STATE_NAME=first_paint
diff --git a/lab_system/master/config/tests/app_prelaunch/app_prelaunch_c4a.cfg b/lab_system/master/config/tests/app_prelaunch/app_prelaunch_c4a.cfg new file mode 100644 index 0000000..757ff3b --- /dev/null +++ b/lab_system/master/config/tests/app_prelaunch/app_prelaunch_c4a.cfg
@@ -0,0 +1,21 @@ +# Config file for app prefetch for C4A devices. + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.app_prelaunch.app_prelaunch_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=AppPreLaunchTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.app_prelaunch.app_prelaunch_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=AppPreLaunchIterableTestSequence + +# Name of the file (in the test's configuration directory) containing +# the apps to test with app prelaunch. The file has the format +# {'apps': [{'name':<app_name>,'id':<app_id>}...]}. +APPS_FILE_NAME=apps_c4a.json + +# App launch state that indicates the app has launched. +APP_STARTED_STATE_NAME=first_audio
diff --git a/lab_system/master/config/tests/app_prelaunch/app_prelaunch_mpl.cfg b/lab_system/master/config/tests/app_prelaunch/app_prelaunch_mpl.cfg new file mode 100644 index 0000000..271ced7 --- /dev/null +++ b/lab_system/master/config/tests/app_prelaunch/app_prelaunch_mpl.cfg
@@ -0,0 +1,21 @@ +# Config file for app prelaunch tests on multiple apps. + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.app_prelaunch.app_prelaunch_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=AppPreLaunchTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.app_prelaunch.app_prelaunch_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=AppPreLaunchIterableTestSequence + +# Name of the file (in the test's configuration directory) containing +# the apps to test with app prelaunch. The file has the format +# {'apps': [{'name':<app_name>,'id':<app_id>}...]}. +APPS_FILE_NAME=apps_mpl.json + +# App launch state that indicates the app has launched. +APP_STARTED_STATE_NAME=first_paint
diff --git a/lab_system/master/config/tests/app_prelaunch/apps.json b/lab_system/master/config/tests/app_prelaunch/apps.json new file mode 100644 index 0000000..f08fc88 --- /dev/null +++ b/lab_system/master/config/tests/app_prelaunch/apps.json
@@ -0,0 +1,34 @@ +{"apps": [ + {"id": "233637DE", "name": "YouTube"}, + {"id": "CA5E8412", "name": "Netflix"}, + {"id": "16EA8A8F", "name": "Hulu"}, + {"id": "01CE20A3", "name": "HBO GO"}, + {"id": "B723160F", "name": "HBO Now"}, + {"id": "358E83DC", "name": "Twitch"}, + {"id": "2872939A", "name": "Google Play Music"}, + {"id": "B0E6A39F", "name": "Viaplay"}, + {"id": "5E81F6DB", "name": "BBC iPlayer"}, + {"id": "C193E492", "name": "WatchESPN"}, + {"id": "C3A34AD9", "name": "dTV"}, + {"id": "F05C50C9", "name": "Google Play Music"}, + {"id": "4A7E3D8E", "name": "MLBTV PROD/Akamai, release app"}, + {"id": "E92AD4B3", "name": "WATCH ABC"}, + {"id": "AA666EDD", "name": "Crunchyroll"}, + {"id": "C1132BA1", "name": "Showtime Anytime"}, + {"id": "0BBDC217", "name": "CBS All Access"}, + {"id": "091CBEE6", "name": "FOX Now"}, + {"id": "12F05308", "name": "TuneIn Free"}, + {"id": "8DD9AEA2", "name": "TuneIn Pro"}, + {"id": "36061251", "name": "Pandora"}, + {"id": "EBCB3521", "name": "Rhapsody/Napster"}, + {"id": "73290360", "name": "Google Play Music CQ"}, + {"id": "3F70D486", "name": "SVT Play"}, + {"id": "E874CC4F", "name": "NowTV"}, + {"id": "D4ECB123", "name": "BT Sport"}, + {"id": "8F76BAF4", "name": "My Canal"}, + {"id": "8DE85673", "name": "FranceTV"}, + {"id": "20E5CA27", "name": "Canal Play"}, + {"id": "CF54A666", "name": "Maxdome"}, + {"id": "CD28C71B", "name": "Red Bull TV US"} + ] +}
diff --git a/lab_system/master/config/tests/app_prelaunch/apps_c4a.json b/lab_system/master/config/tests/app_prelaunch/apps_c4a.json new file mode 100644 index 0000000..12a216d --- /dev/null +++ b/lab_system/master/config/tests/app_prelaunch/apps_c4a.json
@@ -0,0 +1,9 @@ +{"apps": [ + {"id": "12F05308", "name": "TuneIn Free"}, + {"id": "2872939A", "name": "Play Music"}, + {"id": "73290360", "name": "Play Music CQ"}, + {"id": "36061251", "name": "Pandora"}, + {"id": "8DD9AEA2", "name": "TuneIn Pro"}, + {"id": "EBCB3521", "name": "Rhapsody/Napster"} + ] +}
diff --git a/lab_system/master/config/tests/app_prelaunch/apps_mpl.json b/lab_system/master/config/tests/app_prelaunch/apps_mpl.json new file mode 100644 index 0000000..02af99c --- /dev/null +++ b/lab_system/master/config/tests/app_prelaunch/apps_mpl.json
@@ -0,0 +1,4 @@ +{"apps": [ + {"id": "CC1AD845", "name": "Default Receiver"} +] +}
diff --git a/lab_system/master/config/tests/app_prelaunch/cast_background_tab.cfg b/lab_system/master/config/tests/app_prelaunch/cast_background_tab.cfg new file mode 100644 index 0000000..c2636c8 --- /dev/null +++ b/lab_system/master/config/tests/app_prelaunch/cast_background_tab.cfg
@@ -0,0 +1,16 @@ +# Config file for app prelaunch tests on a single app. + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.app_prelaunch.app_prelaunch_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=CastBackgroundTabTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.app_prelaunch.app_prelaunch_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=AppPreLaunchTestSequence + +# App launch state that indicates the app has launched. +APP_STARTED_STATE_NAME=first_paint
diff --git a/lab_system/master/config/tests/app_prelaunch/test_defs.json b/lab_system/master/config/tests/app_prelaunch/test_defs.json new file mode 100644 index 0000000..957aa0a --- /dev/null +++ b/lab_system/master/config/tests/app_prelaunch/test_defs.json
@@ -0,0 +1,62 @@ +[ + { + "group_name": "app_prelaunch", + "slave_name": "app_prelaunch", + "test_name": "app_prelaunch", + "identifier": "app_prelaunch", + "device_type": "eureka", + "device_group": "eureka_background_tab_enabled", + "hidden": "true", + "scheduler": "1 */8 * * *", + "branch": ["master", "release", "on_demand"], + "build_flavor": "user" + }, + { + "group_name": "app_prelaunch", + "slave_name": "app_prelaunch_v2", + "test_name": "app_prelaunch", + "identifier": "app_prelaunch_v2", + "device_type": "lexx", + "device_group": "lexx_background_tab_enabled", + "hidden": "true", + "scheduler": "1 */2 * * *", + "branch": ["master", "release", "on_demand"], + "build_flavor": "user" + }, + { + "group_name": "app_prelaunch", + "slave_name": "app_prelaunch_v3", + "test_name": "app_prelaunch", + "identifier": "app_prelaunch_v3", + "device_type": "earth", + "device_group": "earth_background_tab_enabled", + "hidden": "true", + "scheduler": "1 */4 * * *", + "branch": ["master", "release", "on_demand"], + "build_flavor": "user" + }, + { + "group_name": "app_prelaunch", + "slave_name": "app_prelaunch_audio", + "test_name": "app_prelaunch_c4a", + "identifier": "app_prelaunch_c4a", + "device_type": "hendrix", + "device_group": "hendrix_background_tab_enabled", + "hidden": "true", + "scheduler": "1 */2 * * *", + "branch": ["master", "release"], + "build_flavor": "user" + }, + { + "group_name": "app_prelaunch", + "slave_name": "app_prelaunch", + "test_name": "app_prelaunch", + "identifier": "app_prelaunch_mpl", + "device_type": "eureka", + "device_group": "eureka_background_tab_enabled", + "scheduler": "1 */8 * * *", + "branch": ["master", "release", "next_release"], + "build_flavor": "user" + } + +]
diff --git a/lab_system/master/config/tests/apps_launch_monitor/apps.json b/lab_system/master/config/tests/apps_launch_monitor/apps.json new file mode 100755 index 0000000..fac11ee --- /dev/null +++ b/lab_system/master/config/tests/apps_launch_monitor/apps.json
@@ -0,0 +1,5 @@ +{"apps": [ + {"name": "Netflix", "id": "CA5E8412"}, + {"name": "YouTube", "id": "233637DE"} + ] +}
diff --git a/lab_system/master/config/tests/apps_launch_monitor/apps_c4a.json b/lab_system/master/config/tests/apps_launch_monitor/apps_c4a.json new file mode 100644 index 0000000..448ae1d --- /dev/null +++ b/lab_system/master/config/tests/apps_launch_monitor/apps_c4a.json
@@ -0,0 +1,13 @@ +{"apps": [ + {"id": "12F05308", "name": "TuneIn Free"}, + {"id": "2872939A", "name": "Google Play Music"}, + {"id": "28BE5D9A", "name": "Deezer"}, + {"id": "2DB7CC49", "name": "YouTube Music"}, + {"id": "36061251", "name": "Pandora"}, + {"id": "8DD9AEA2", "name": "TuneIn Pro"}, + {"id": "73290360", "name": "Google Play Music CQ"}, + {"id": "C54DBC0F", "name": "iHeartRadio"}, + {"id": "DF630089", "name": "Spotify"}, + {"id": "EBCB3521", "name": "Rhapsody/Napster"} + ] +}
diff --git a/lab_system/master/config/tests/apps_launch_monitor/apps_launch_monitor.cfg b/lab_system/master/config/tests/apps_launch_monitor/apps_launch_monitor.cfg new file mode 100644 index 0000000..511736c --- /dev/null +++ b/lab_system/master/config/tests/apps_launch_monitor/apps_launch_monitor.cfg
@@ -0,0 +1,30 @@ +# Config file for the canvas render performance tests. # # PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.apps_launch_monitor.apps_launch_monitor_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=AppLaunchMonitorTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.framework.test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=TestSequence + +# Relative path from root of test/ repository to the cast/ repository: +RELATIVE_PATH_TO_CAST=../cast + +# Relative path from root of test/ repository to the telemetry repository: +RELATIVE_PATH_TO_TELEMETRY=../chromium/src/tools/telemetry + +# Relative path (from the config/tests dir) to the file containing +# the apps to test with the apps launch monitor. The file has the format +# {'apps': [{'name':<app_name>,'id':<app_id>}...]}. +APPS_FILE_RELATIVE_PATH=apps_launch_monitor/apps.json + +# Set to 'true' to disable the collection of resource loading. +RESOURCES_COLLECTION_DISABLED=false +# Continue running on the latest build +# after all have been tested. +BUILD_SELECTION_POLICY=backtrack_then_latest
diff --git a/lab_system/master/config/tests/apps_launch_monitor/apps_launch_monitor_audio.cfg b/lab_system/master/config/tests/apps_launch_monitor/apps_launch_monitor_audio.cfg new file mode 100644 index 0000000..e130997 --- /dev/null +++ b/lab_system/master/config/tests/apps_launch_monitor/apps_launch_monitor_audio.cfg
@@ -0,0 +1,34 @@ +# Config file for collecting app launch data in audio-only devices. + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.apps_launch_monitor.apps_launch_monitor_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=AppLaunchMonitorTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.apps_launch_monitor.apps_launch_monitor_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=AppsLaunchMonitorTestSequence + +# Relative path from root of test/ repository to the cast/ repository: +RELATIVE_PATH_TO_CAST=../cast + +# Relative path from root of test/ repository to the telemetry repository: +RELATIVE_PATH_TO_TELEMETRY=../chromium/src/tools/telemetry + +# Relative path (from the config/tests dir) to the file containing +# the apps to test with the apps launch monitor. The file has the format +# {'apps': [{'name':<app_name>,'id':<app_id>}...]}. +APPS_FILE_RELATIVE_PATH=apps_launch_monitor/apps_c4a.json + +# Disable the collection of resource loading for Hendrix. +RESOURCES_COLLECTION_DISABLED=true +# Continue running on the latest build +# after all have been tested. +BUILD_SELECTION_POLICY=backtrack_then_latest + +# This config is used to determine if cast operations should be allowed even if +# device is not signed-in using a gaia account. +ENABLE_CAST_WITHOUT_SIGN_IN=True
diff --git a/lab_system/master/config/tests/apps_launch_monitor/test_defs.json b/lab_system/master/config/tests/apps_launch_monitor/test_defs.json new file mode 100644 index 0000000..846a727 --- /dev/null +++ b/lab_system/master/config/tests/apps_launch_monitor/test_defs.json
@@ -0,0 +1,79 @@ +[ + { + "group_name": "apps_launch_monitor", + "slave_name": "apps_launch_monitor", + "test_name": "apps_launch_monitor", + "identifier": "apps_launch_monitor", + "device_type": "eureka", + "device_group": "eureka_debug", + "scheduler": "1 0,8,16 * * *", + "branch": ["master", "release", "next_release"], + "build_flavor": "user" + }, + { + "group_name": "apps_launch_monitor", + "slave_name": "apps_launch_monitor_v2", + "test_name": "apps_launch_monitor", + "identifier": "apps_launch_monitor_v2", + "device_type": "lexx", + "device_group": "lexx_eth", + "scheduler": "1 0,4,8,12,16,20 * * *", + "branch": ["master", "release", "next_release", "on_demand"], + "build_flavor": "user" + }, + { + "group_name": "apps_launch_monitor", + "slave_name": "apps_launch_monitor_v3", + "test_name": "apps_launch_monitor", + "identifier": "apps_launch_monitor_v3", + "device_type": "earth", + "device_group": "earth_eth", + "scheduler": "1 0,4,8,12,16,20 * * *", + "branch": ["master", "release", "next_release", "on_demand"], + "build_flavor": "user" + }, + { + "group_name": "apps_launch_monitor", + "slave_name": "apps_launch_monitor_audio", + "test_name": "apps_launch_monitor_audio", + "identifier": "apps_launch_monitor_hendrix", + "device_type": "hendrix", + "device_group": "hendrix_eth", + "scheduler": "1 0,4,8,12,16,20 * * *", + "branch": ["master", "release", "next_release", "on_demand"], + "build_flavor": "user" + }, + { + "group_name": "apps_launch_monitor", + "slave_name": "apps_launch_monitor_audio", + "test_name": "apps_launch_monitor_audio", + "identifier": "apps_launch_monitor_chirp", + "device_type": "chirp", + "device_group": "chirp", + "scheduler": "1 0,2,4,8,12,15,18,20 * * *", + "branch": ["master", "release", "next_release"], + "build_flavor": "user" + }, + { + "group_name": "apps_launch_monitor", + "slave_name": "apps_launch_monitor_luther", + "test_name": "apps_launch_monitor", + "identifier": "apps_launch_monitor_luther", + "device_type": "luther_b2", + "device_group": "luther_eth", + "scheduler": "1 0,2,4,8,12,15,18,20 * * *", + "branch": ["master", "release", "next_release"], + "build_flavor": "user" + }, + { + "group_name": "apps_launch_monitor", + "slave_name": "apps_launch_monitor_audio", + "test_name": "apps_launch_monitor_audio", + "identifier": "apps_launch_monitor_joplin", + "device_type": "joplin", + "device_group": "joplin", + "scheduler": "1 0,4,8,12,16,20 * * *", + "branch": ["master", "release", "next_release"], + "build_flavor": "user" + } +]
diff --git a/lab_system/master/config/tests/assistant_alarm_timer_marketing_queries_test/marketing_golden_queries_with_alarms_media_test.cfg b/lab_system/master/config/tests/assistant_alarm_timer_marketing_queries_test/marketing_golden_queries_with_alarms_media_test.cfg new file mode 100644 index 0000000..7f7492c --- /dev/null +++ b/lab_system/master/config/tests/assistant_alarm_timer_marketing_queries_test/marketing_golden_queries_with_alarms_media_test.cfg
@@ -0,0 +1,46 @@ +# Config file for assistant marketing queries tests +# +# Do not modify property names +# Run make reconfig if you change a value +# and buildbot is running +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.assistant.assistant_query_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=AssistantQueryTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.assistant.query_driven_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=QueryDrivenTestSequence + +# Relative GCS path (from the cast-test-data bucket) to the directory containing +# the test audio config files. +GCS_AUDIO_DIR_PATH=assistant/pineapple-p2-rerecordings/synthetic_speech/chirp_marketing_golden/media_news_timers + +# This identifier will appear as a prefix on the name of test result. +# Valid only for tests that uses QueryDrivenTestSequence, otherwise ignored. +TEST_RESULT_PREFIX=marketing_golden_queries_media_news_timers_tests + + +# Number of times a test has to be repeated. This should be an integer. +# Test will be run these many times and for all successful outcomes the latency +# numbers will be persisted. +TEST_ITERATION_COUNT=1 + +# Assistant backend server to use. Valid values are : +# "NIGHTLY_DEV_SERVER", "TEAMFOOD_SERVER", "DOGFOOD_SERVER" and "PROD_SERVER" +# These values are defined in +# continuous-tests/internal/eurtest/device/assistant_device.py +ASSISTANT_BACKEND=DOGFOOD_SERVER + +# Never backtrack so service-related failures have a +# chronological correspondence to build numbers. +BUILD_SELECTION_POLICY=always_use_latest + +# Profilers to Run +PERF_PROFILERS=cgroup_profiler,spm_profiler
diff --git a/lab_system/master/config/tests/assistant_art_test/assistant_art_samples_test.cfg b/lab_system/master/config/tests/assistant_art_test/assistant_art_samples_test.cfg new file mode 100644 index 0000000..f87a830 --- /dev/null +++ b/lab_system/master/config/tests/assistant_art_test/assistant_art_samples_test.cfg
@@ -0,0 +1,50 @@ + # Config file for follow-up query tests +# +# Do not modify property names +# Run make reconfig if you change a value +# and buildbot is running +# +# PROPERTIES + +# Indicates whether or not we should sign the device in +SIGNED_IN=True + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.assistant.art_tests.assistant_art_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=AssistantArtTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.assistant.art_tests.assistant_art_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=AssistantArtTestSequence + +# Relative GCS path (from the cast-test-data bucket) to the directory containing +# the test audio config files. +GCS_AUDIO_FILES_PATH=assistant/art_samples/art_samples_1 +DOWNLOAD_DIRECTORY=/tmp/pi/art_samples/art_samples_1 +# assistant/art_samples/samples_1 + +# Assistant backend server to use. Valid values are : +# "NIGHTLY_DEV_SERVER", "TEAMFOOD_SERVER", "DOGFOOD_SERVER" and "PROD_SERVER" +# These values are defined in +# continuous-tests/internal/eurtest/device/assistant_device.py +ASSISTANT_BACKEND=DOGFOOD_SERVER + +BUILD_SELECTION_POLICY=backtrack_then_latest + +# Maximum number of builds to be used in build selection process. +MAX_BUILD_SELECTION_RANGE=3 + +# Test Volumes +TEST_VOLUME=90 + +# Options are 'Jabberjay', 'ConductedAudio', and 'Chatterbox' +STIMULUS_TYPE=Chatterbox + +#CGROUP_PARAMETER=-c -detailed-memory-report + +# Profilers to Run +PERF_PROFILERS=cgroup_profiler,data_profiler,spm_profiler
diff --git a/lab_system/master/config/tests/assistant_base_test/assistant_idle_device_test.cfg b/lab_system/master/config/tests/assistant_base_test/assistant_idle_device_test.cfg new file mode 100644 index 0000000..6eb2058 --- /dev/null +++ b/lab_system/master/config/tests/assistant_base_test/assistant_idle_device_test.cfg
@@ -0,0 +1,36 @@ +# Config file for follow-up query tests +# +# Do not modify property names +# Run make reconfig if you change a value +# and buildbot is running +# +# PROPERTIES + +# Indicates whether or not we should sign the device in +SIGNED_IN=False + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.assistant.base_tests.assistant_idle_device_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=AssistantIdleDeviceTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.assistant.assistant_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=AssistantTestSequence + +# Assistant backend server to use. Valid values are : +# "NIGHTLY_DEV_SERVER", "TEAMFOOD_SERVER", "DOGFOOD_SERVER" and "PROD_SERVER" +# These values are defined in +# continuous-tests/internal/eurtest/device/assistant_device.py +ASSISTANT_BACKEND=DOGFOOD_SERVER + +BUILD_SELECTION_POLICY=backtrack_then_latest + +# Maximum number of builds to be used in build selection process. +MAX_BUILD_SELECTION_RANGE=3 + +# Profilers to Run +PERF_PROFILERS=cgroup_profiler,spm_profiler
diff --git a/lab_system/master/config/tests/assistant_base_test/assistant_idle_signed_in_device_test.cfg b/lab_system/master/config/tests/assistant_base_test/assistant_idle_signed_in_device_test.cfg new file mode 100644 index 0000000..0764eef --- /dev/null +++ b/lab_system/master/config/tests/assistant_base_test/assistant_idle_signed_in_device_test.cfg
@@ -0,0 +1,36 @@ +# Config file for follow-up query tests +# +# Do not modify property names +# Run make reconfig if you change a value +# and buildbot is running +# +# PROPERTIES + +# Indicates whether or not we should sign the device in +SIGNED_IN=True + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.assistant.base_tests.assistant_idle_device_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=AssistantIdleDeviceTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.assistant.assistant_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=AssistantTestSequence + +# Assistant backend server to use. Valid values are : +# "NIGHTLY_DEV_SERVER", "TEAMFOOD_SERVER", "DOGFOOD_SERVER" and "PROD_SERVER" +# These values are defined in +# continuous-tests/internal/eurtest/device/assistant_device.py +ASSISTANT_BACKEND=DOGFOOD_SERVER + +BUILD_SELECTION_POLICY=backtrack_then_latest + +# Maximum number of builds to be used in build selection process. +MAX_BUILD_SELECTION_RANGE=3 + +# Profilers to Run +PERF_PROFILERS=cgroup_profiler,spm_profiler
diff --git a/lab_system/master/config/tests/assistant_duo_voice_calls_basic_test/assistant_duo_voice_calls_basic_test.cfg b/lab_system/master/config/tests/assistant_duo_voice_calls_basic_test/assistant_duo_voice_calls_basic_test.cfg new file mode 100644 index 0000000..0a1b36c --- /dev/null +++ b/lab_system/master/config/tests/assistant_duo_voice_calls_basic_test/assistant_duo_voice_calls_basic_test.cfg
@@ -0,0 +1,29 @@ +# Config file for assistant phone calls tests + +# Do not modify property names +# Run make reconfig if you change a value +# and buildbot is running + +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.assistant.assistant_duo_voice_calls_basic_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=AssistantDuoVoiceCallsBasicTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.assistant.assistant_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=AssistantTestSequence + +# Relative GCS path (from the cast-test-data bucket) to the directory containing +# the test audio config files. +GCS_AUDIO_DIR_PATH=assistant/pineapple-p2-rerecordings/synthetic_speech/duo_audio_calls + +# Assistant backend server to use. Valid values are : +# "NIGHTLY_DEV_SERVER", "TEAMFOOD_SERVER", "DOGFOOD_SERVER" and "PROD_SERVER" +# These values are defined in +# continuous-tests/internal/eurtest/device/assistant_device.py +ASSISTANT_BACKEND=DOGFOOD_SERVER
diff --git a/lab_system/master/config/tests/assistant_duo_voice_calls_test/assistant_duo_voice_calls_test.cfg b/lab_system/master/config/tests/assistant_duo_voice_calls_test/assistant_duo_voice_calls_test.cfg new file mode 100644 index 0000000..e45e405 --- /dev/null +++ b/lab_system/master/config/tests/assistant_duo_voice_calls_test/assistant_duo_voice_calls_test.cfg
@@ -0,0 +1,29 @@ +# Config file for assistant phone calls tests + +# Do not modify property names +# Run make reconfig if you change a value +# and buildbot is running + +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.assistant.assistant_duo_voice_calls_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=AssistantDuoVoiceCallsTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.assistant.assistant_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=AssistantTestSequence + +# Relative GCS path (from the cast-test-data bucket) to the directory containing +# the test audio config files. +GCS_AUDIO_DIR_PATH=assistant/pineapple-p2-rerecordings/synthetic_speech/duo_audio_calls + +# Assistant backend server to use. Valid values are : +# "NIGHTLY_DEV_SERVER", "TEAMFOOD_SERVER", "DOGFOOD_SERVER" and "PROD_SERVER" +# These values are defined in +# continuous-tests/internal/eurtest/device/assistant_device.py +ASSISTANT_BACKEND=DOGFOOD_SERVER
diff --git a/lab_system/master/config/tests/assistant_follow_up_query_test/assistant_follow_up_query_test.cfg b/lab_system/master/config/tests/assistant_follow_up_query_test/assistant_follow_up_query_test.cfg new file mode 100644 index 0000000..ff45f13 --- /dev/null +++ b/lab_system/master/config/tests/assistant_follow_up_query_test/assistant_follow_up_query_test.cfg
@@ -0,0 +1,37 @@ +# Config file for follow-up query tests +# +# Do not modify property names +# Run make reconfig if you change a value +# and buildbot is running +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.assistant.assistant_follow_up_query_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=AssistantFollowUpQueryTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.assistant.assistant_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=AssistantTestSequence + +# Relative GCS path (from the cast-test-data bucket) to the directory containing +# the test audio config files. +GCS_AUDIO_DIR_PATH=assistant/pineapple-p2-rerecordings/synthetic_speech/chirp_marketing_golden/follow_up/answers + +# Assistant backend server to use. Valid values are : +# "NIGHTLY_DEV_SERVER", "TEAMFOOD_SERVER", "DOGFOOD_SERVER" and "PROD_SERVER" +# These values are defined in +# continuous-tests/internal/eurtest/device/assistant_device.py +ASSISTANT_BACKEND=DOGFOOD_SERVER + +BUILD_SELECTION_POLICY=backtrack_then_latest + +# Maximum number of builds to be used in build selection process. +MAX_BUILD_SELECTION_RANGE=3 + +# Profilers to Run +PERF_PROFILERS=cgroup_profiler,spm_profiler
diff --git a/lab_system/master/config/tests/assistant_ganache_test/assistant_ganache_timer_dialogue_test_dogfood.cfg b/lab_system/master/config/tests/assistant_ganache_test/assistant_ganache_timer_dialogue_test_dogfood.cfg new file mode 100644 index 0000000..7c1ad1e --- /dev/null +++ b/lab_system/master/config/tests/assistant_ganache_test/assistant_ganache_timer_dialogue_test_dogfood.cfg
@@ -0,0 +1,34 @@ +# Config file for follow-up query tests + +# Do not modify property names +# Run make reconfig if you change a value +# and buildbot is running + +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.assistant.assistant_ganache_timer_dialogue_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=AssistantGanacheTimerDialogueTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.assistant.assistant_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=AssistantTestSequence + +# Relative GCS path (from the cast-test-data bucket) to the directory containing +# the test audio config files. +GCS_AUDIO_DIR_PATH=assistant/pineapple-p2-rerecordings/synthetic_speech/dialogue/ganache + +# Assistant backend server to use. Valid values are : +# "NIGHTLY_DEV_SERVER", "TEAMFOOD_SERVER", "DOGFOOD_SERVER" and "PROD_SERVER" +# These values are defined in +# continuous-tests/internal/eurtest/device/assistant_device.py +ASSISTANT_BACKEND=DOGFOOD_SERVER + +BUILD_SELECTION_POLICY=backtrack_then_latest + +# Maximum number of builds to be used in build selection process. +MAX_BUILD_SELECTION_RANGE=3
diff --git a/lab_system/master/config/tests/assistant_marketing_queries_test/marketing_golden_queries_test.cfg b/lab_system/master/config/tests/assistant_marketing_queries_test/marketing_golden_queries_test.cfg new file mode 100644 index 0000000..cb7fc3a --- /dev/null +++ b/lab_system/master/config/tests/assistant_marketing_queries_test/marketing_golden_queries_test.cfg
@@ -0,0 +1,39 @@ +# Config file for assistant marketing queries tests +# +# Do not modify property names +# Run make reconfig if you change a value +# and buildbot is running +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.assistant.assistant_latency_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=QueryDrivenLatencyTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.assistant.query_driven_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=QueryDrivenTestSequence + +# Relative GCS path (from the cast-test-data bucket) to the directory containing +# the test audio config files. +GCS_AUDIO_DIR_PATH=assistant/pineapple-p2-rerecordings/synthetic_speech/chirp_marketing_golden/answers + +# This identifier will appear as a prefix on the name of test result. +# Valid only for tests that uses QueryDrivenTestSequence, otherwise ignored. +TEST_RESULT_PREFIX=marketing_golden_queries_tests + +# Assistant backend server to use. Valid values are : +# "NIGHTLY_DEV_SERVER", "TEAMFOOD_SERVER", "DOGFOOD_SERVER" and "PROD_SERVER" +# These values are defined in +# continuous-tests/internal/eurtest/device/assistant_device.py +ASSISTANT_BACKEND=DOGFOOD_SERVER + +# Never backtrack so service-related failures have a +# chronological correspondence to build numbers. +BUILD_SELECTION_POLICY=always_use_latest + +
diff --git a/lab_system/master/config/tests/assistant_media_control_test/assistant_playback_commands.cfg b/lab_system/master/config/tests/assistant_media_control_test/assistant_playback_commands.cfg new file mode 100644 index 0000000..088befc --- /dev/null +++ b/lab_system/master/config/tests/assistant_media_control_test/assistant_playback_commands.cfg
@@ -0,0 +1,20 @@ +# Config file for media playback test cases. + +TEST_CASE_MODULE=eurtest.tests.assistant.media_playback_test_case +TEST_CASE_CLASS=AssistantMediaCommandsTestCase +TEST_SEQUENCE_MODULE=eurtest.tests.assistant.query_driven_test_sequence +TEST_SEQUENCE_CLASS=QueryDrivenTestSequence +# Relative GCS path (from the cast-test-data bucket) to the directory containing +# the test audio config files. +GCS_AUDIO_DIR_PATH=assistant/pineapple-p2-rerecordings/synthetic_speech/manual_speedup/playback_commands +# This identifier will appear as a prefix on the name of test result. +# Valid only for tests that uses QueryDrivenTestSequence, otherwise ignored. +TEST_RESULT_PREFIX=media_commands +ASSISTANT_BACKEND=TEAMFOOD_SERVER +BUILD_SELECTION_POLICY=backtrack_then_latest +# Maximum number of builds to be used in build selection process. +MAX_BUILD_SELECTION_RANGE=3 + +# Profilers to Run +PERF_PROFILERS=cgroup_profiler,spm_profiler +
diff --git a/lab_system/master/config/tests/assistant_media_integration_test/assistant_playback_gpm_default.cfg b/lab_system/master/config/tests/assistant_media_integration_test/assistant_playback_gpm_default.cfg new file mode 100644 index 0000000..e33d0c8 --- /dev/null +++ b/lab_system/master/config/tests/assistant_media_integration_test/assistant_playback_gpm_default.cfg
@@ -0,0 +1,17 @@ +# Config file for media playback test cases. + +TEST_CASE_MODULE=eurtest.tests.assistant.media_playback_test_case +TEST_CASE_CLASS=AssistantMediaPlaybackTestCase +TEST_SEQUENCE_MODULE=eurtest.tests.assistant.query_driven_test_sequence +TEST_SEQUENCE_CLASS=QueryDrivenTestSequence +# Relative GCS path (from the cast-test-data bucket) to the directory containing +# the test audio config files. +GCS_AUDIO_DIR_PATH=assistant/pineapple-p2-rerecordings/synthetic_speech/manual_speedup/gpm_2872939A_default/ +# This identifier will appear as a prefix on the name of test result. +# Valid only for tests that uses QueryDrivenTestSequence, otherwise ignored. +TEST_RESULT_PREFIX=playback_gpm_default +ASSISTANT_BACKEND=TEAMFOOD_SERVER +BUILD_SELECTION_POLICY=backtrack_then_latest +# Maximum number of builds to be used in build selection process. +MAX_BUILD_SELECTION_RANGE=3 +
diff --git a/lab_system/master/config/tests/assistant_media_integration_test/assistant_playback_pandora_default.cfg b/lab_system/master/config/tests/assistant_media_integration_test/assistant_playback_pandora_default.cfg new file mode 100644 index 0000000..d79dee9 --- /dev/null +++ b/lab_system/master/config/tests/assistant_media_integration_test/assistant_playback_pandora_default.cfg
@@ -0,0 +1,17 @@ +# Config file for media playback test cases. + +TEST_CASE_MODULE=eurtest.tests.assistant.media_playback_test_case +TEST_CASE_CLASS=AssistantMediaPlaybackTestCase +TEST_SEQUENCE_MODULE=eurtest.tests.assistant.query_driven_test_sequence +TEST_SEQUENCE_CLASS=QueryDrivenTestSequence +# Relative GCS path (from the cast-test-data bucket) to the directory containing +# the test audio config files. +GCS_AUDIO_DIR_PATH=assistant/pineapple-p2-rerecordings/synthetic_speech/manual_speedup/pandora_36061251_default/ +# This identifier will appear as a prefix on the name of test result. +# Valid only for tests that uses QueryDrivenTestSequence, otherwise ignored. +TEST_RESULT_PREFIX=playback_pandora_default +ASSISTANT_BACKEND=TEAMFOOD_SERVER +BUILD_SELECTION_POLICY=backtrack_then_latest +# Maximum number of builds to be used in build selection process. +MAX_BUILD_SELECTION_RANGE=3 +
diff --git a/lab_system/master/config/tests/assistant_media_integration_test/assistant_playback_spotify_default.cfg b/lab_system/master/config/tests/assistant_media_integration_test/assistant_playback_spotify_default.cfg new file mode 100644 index 0000000..58d9886 --- /dev/null +++ b/lab_system/master/config/tests/assistant_media_integration_test/assistant_playback_spotify_default.cfg
@@ -0,0 +1,20 @@ +# Config file for media playback test cases. + +TEST_CASE_MODULE=eurtest.tests.assistant.media_playback_test_case +TEST_CASE_CLASS=AssistantMediaPlaybackTestCase +TEST_SEQUENCE_MODULE=eurtest.tests.assistant.query_driven_test_sequence +TEST_SEQUENCE_CLASS=QueryDrivenTestSequence +# Relative GCS path (from the cast-test-data bucket) to the directory containing +# the test audio config files. +GCS_AUDIO_DIR_PATH=assistant/pineapple-p2-rerecordings/synthetic_speech/manual_speedup/spotify_CC32E753_default/ +# This identifier will appear as a prefix on the name of test result. +# Valid only for tests that uses QueryDrivenTestSequence, otherwise ignored. +TEST_RESULT_PREFIX=playback_spotify_default +ASSISTANT_BACKEND=TEAMFOOD_SERVER +BUILD_SELECTION_POLICY=backtrack_then_latest +# Maximum number of builds to be used in build selection process. +MAX_BUILD_SELECTION_RANGE=3 + +# Profilers to Run +PERF_PROFILERS=cgroup_profiler,spm_profiler +
diff --git a/lab_system/master/config/tests/assistant_media_integration_test/assistant_playback_tune_in.cfg b/lab_system/master/config/tests/assistant_media_integration_test/assistant_playback_tune_in.cfg new file mode 100644 index 0000000..aac68aa --- /dev/null +++ b/lab_system/master/config/tests/assistant_media_integration_test/assistant_playback_tune_in.cfg
@@ -0,0 +1,17 @@ +# Config file for media playback test cases. + +TEST_CASE_MODULE=eurtest.tests.assistant.media_playback_test_case +TEST_CASE_CLASS=AssistantMediaPlaybackTestCase +TEST_SEQUENCE_MODULE=eurtest.tests.assistant.query_driven_test_sequence +TEST_SEQUENCE_CLASS=QueryDrivenTestSequence +# Relative GCS path (from the cast-test-data bucket) to the directory containing +# the test audio config files. +GCS_AUDIO_DIR_PATH=assistant/pineapple-p2-rerecordings/synthetic_speech/manual_speedup/tunein_12F05308/ +# This identifier will appear as a prefix on the name of test result. +# Valid only for tests that uses QueryDrivenTestSequence, otherwise ignored. +TEST_RESULT_PREFIX=playback_tunein +ASSISTANT_BACKEND=TEAMFOOD_SERVER +BUILD_SELECTION_POLICY=backtrack_then_latest +# Maximum number of builds to be used in build selection process. +MAX_BUILD_SELECTION_RANGE=3 +
diff --git a/lab_system/master/config/tests/assistant_media_integration_test/assistant_playback_ytm_default.cfg b/lab_system/master/config/tests/assistant_media_integration_test/assistant_playback_ytm_default.cfg new file mode 100644 index 0000000..0c1a6c1 --- /dev/null +++ b/lab_system/master/config/tests/assistant_media_integration_test/assistant_playback_ytm_default.cfg
@@ -0,0 +1,20 @@ +# Config file for media playback test cases. + +TEST_CASE_MODULE=eurtest.tests.assistant.media_playback_test_case +TEST_CASE_CLASS=AssistantMediaPlaybackTestCase +TEST_SEQUENCE_MODULE=eurtest.tests.assistant.query_driven_test_sequence +TEST_SEQUENCE_CLASS=QueryDrivenTestSequence +# Relative GCS path (from the cast-test-data bucket) to the directory containing +# the test audio config files. +GCS_AUDIO_DIR_PATH=assistant/pineapple-p2-rerecordings/synthetic_speech/manual_speedup/ytm_2DB7CC49_default/ +# This identifier will appear as a prefix on the name of test result. +# Valid only for tests that uses QueryDrivenTestSequence, otherwise ignored. +TEST_RESULT_PREFIX=playback_ytm_default +ASSISTANT_BACKEND=TEAMFOOD_SERVER +BUILD_SELECTION_POLICY=backtrack_then_latest +# Maximum number of builds to be used in build selection process. +MAX_BUILD_SELECTION_RANGE=3 + +# Profilers to Run +PERF_PROFILERS=cgroup_profiler,spm_profiler +
diff --git a/lab_system/master/config/tests/assistant_media_latency/assistant_playback_latency_google_play_music.cfg b/lab_system/master/config/tests/assistant_media_latency/assistant_playback_latency_google_play_music.cfg new file mode 100644 index 0000000..59bf93b --- /dev/null +++ b/lab_system/master/config/tests/assistant_media_latency/assistant_playback_latency_google_play_music.cfg
@@ -0,0 +1,17 @@ +# Config file for media playback latency test cases. + +TEST_CASE_MODULE=eurtest.tests.assistant.media_playback_test_case +TEST_CASE_CLASS=AssistantPlaybackLatencyPreloadingTestCase +TEST_SEQUENCE_MODULE=eurtest.tests.assistant.query_driven_test_sequence +TEST_SEQUENCE_CLASS=QueryDrivenTestSequence +# Relative GCS path (from the cast-test-data bucket) to the directory containing +# the test audio config files. +GCS_AUDIO_DIR_PATH=assistant/pineapple-p2-rerecordings/synthetic_speech/local_media_playback/google_play_music/ +# This identifier will appear as a prefix on the name of test result. +# Valid only for tests that uses QueryDrivenTestSequence, otherwise ignored. +TEST_RESULT_PREFIX=playback_latency_google_play_music +ASSISTANT_BACKEND=DOGFOOD_SERVER +# Never bactrack so service-related failures have a +# chronological correspondence to build numbers. +BUILD_SELECTION_POLICY=always_use_latest +
diff --git a/lab_system/master/config/tests/assistant_media_latency/assistant_playback_latency_pandora.cfg b/lab_system/master/config/tests/assistant_media_latency/assistant_playback_latency_pandora.cfg new file mode 100644 index 0000000..0f8696b --- /dev/null +++ b/lab_system/master/config/tests/assistant_media_latency/assistant_playback_latency_pandora.cfg
@@ -0,0 +1,17 @@ +# Config file for media playback latency test cases. + +TEST_CASE_MODULE=eurtest.tests.assistant.media_playback_test_case +TEST_CASE_CLASS=AssistantPlaybackLatencyPreloadingTestCase +TEST_SEQUENCE_MODULE=eurtest.tests.assistant.query_driven_test_sequence +TEST_SEQUENCE_CLASS=QueryDrivenTestSequence +# Relative GCS path (from the cast-test-data bucket) to the directory containing +# the test audio config files. +GCS_AUDIO_DIR_PATH=assistant/pineapple-p2-rerecordings/synthetic_speech/local_media_playback/pandora/ +# This identifier will appear as a prefix on the name of test result. +# Valid only for tests that uses QueryDrivenTestSequence, otherwise ignored. +TEST_RESULT_PREFIX=playback_latency_pandora +ASSISTANT_BACKEND=DOGFOOD_SERVER +# Never bactrack so service-related failures have a +# chronological correspondence to build numbers. +BUILD_SELECTION_POLICY=always_use_latest +
diff --git a/lab_system/master/config/tests/assistant_media_latency/assistant_playback_latency_spotify.cfg b/lab_system/master/config/tests/assistant_media_latency/assistant_playback_latency_spotify.cfg new file mode 100644 index 0000000..c8b16d8 --- /dev/null +++ b/lab_system/master/config/tests/assistant_media_latency/assistant_playback_latency_spotify.cfg
@@ -0,0 +1,17 @@ +# Config file for media playback latency test cases. + +TEST_CASE_MODULE=eurtest.tests.assistant.media_playback_test_case +TEST_CASE_CLASS=AssistantPlaybackLatencyPreloadingTestCase +TEST_SEQUENCE_MODULE=eurtest.tests.assistant.query_driven_test_sequence +TEST_SEQUENCE_CLASS=QueryDrivenTestSequence +# Relative GCS path (from the cast-test-data bucket) to the directory containing +# the test audio config files. +GCS_AUDIO_DIR_PATH=assistant/pineapple-p2-rerecordings/synthetic_speech/local_media_playback/spotify/ +# This identifier will appear as a prefix on the name of test result. +# Valid only for tests that uses QueryDrivenTestSequence, otherwise ignored. +TEST_RESULT_PREFIX=playback_latency_spotify +ASSISTANT_BACKEND=DOGFOOD_SERVER +# Never bactrack so service-related failures have a +# chronological correspondence to build numbers. +BUILD_SELECTION_POLICY=always_use_latest +
diff --git a/lab_system/master/config/tests/assistant_media_latency/assistant_playback_latency_tune_in.cfg b/lab_system/master/config/tests/assistant_media_latency/assistant_playback_latency_tune_in.cfg new file mode 100644 index 0000000..eafe2ef --- /dev/null +++ b/lab_system/master/config/tests/assistant_media_latency/assistant_playback_latency_tune_in.cfg
@@ -0,0 +1,17 @@ +# Config file for media playback latency test cases. + +TEST_CASE_MODULE=eurtest.tests.assistant.media_playback_test_case +TEST_CASE_CLASS=AssistantPlaybackLatencyPreloadingTestCase +TEST_SEQUENCE_MODULE=eurtest.tests.assistant.query_driven_test_sequence +TEST_SEQUENCE_CLASS=QueryDrivenTestSequence +# Relative GCS path (from the cast-test-data bucket) to the directory containing +# the test audio config files. +GCS_AUDIO_DIR_PATH=assistant/pineapple-p2-rerecordings/synthetic_speech/local_media_playback/tune_in/ +# This identifier will appear as a prefix on the name of test result. +# Valid only for tests that uses QueryDrivenTestSequence, otherwise ignored. +TEST_RESULT_PREFIX=playback_latency_tune_in +ASSISTANT_BACKEND=DOGFOOD_SERVER +# Never bactrack so service-related failures have a +# chronological correspondence to build numbers. +BUILD_SELECTION_POLICY=always_use_latest +
diff --git a/lab_system/master/config/tests/assistant_media_latency/assistant_playback_latency_youtube_music.cfg b/lab_system/master/config/tests/assistant_media_latency/assistant_playback_latency_youtube_music.cfg new file mode 100644 index 0000000..5b933b3 --- /dev/null +++ b/lab_system/master/config/tests/assistant_media_latency/assistant_playback_latency_youtube_music.cfg
@@ -0,0 +1,17 @@ +# Config file for media playback latency test cases. + +TEST_CASE_MODULE=eurtest.tests.assistant.media_playback_test_case +TEST_CASE_CLASS=AssistantPlaybackLatencyPreloadingTestCase +TEST_SEQUENCE_MODULE=eurtest.tests.assistant.query_driven_test_sequence +TEST_SEQUENCE_CLASS=QueryDrivenTestSequence +# Relative GCS path (from the cast-test-data bucket) to the directory containing +# the test audio config files. +GCS_AUDIO_DIR_PATH=assistant/pineapple-p2-rerecordings/synthetic_speech/local_media_playback/youtube_music/ +# This identifier will appear as a prefix on the name of test result. +# Valid only for tests that uses QueryDrivenTestSequence, otherwise ignored. +TEST_RESULT_PREFIX=playback_latency_youtube_music +ASSISTANT_BACKEND=DOGFOOD_SERVER +# Never bactrack so service-related failures have a +# chronological correspondence to build numbers. +BUILD_SELECTION_POLICY=always_use_latest +
diff --git a/lab_system/master/config/tests/assistant_media_latency/assistant_playback_latency_youtube_music_fuchsia.cfg b/lab_system/master/config/tests/assistant_media_latency/assistant_playback_latency_youtube_music_fuchsia.cfg new file mode 100644 index 0000000..bc9f252 --- /dev/null +++ b/lab_system/master/config/tests/assistant_media_latency/assistant_playback_latency_youtube_music_fuchsia.cfg
@@ -0,0 +1,17 @@ +# Config file for media playback latency test cases. + +TEST_CASE_MODULE=eurtest.tests.assistant.media_playback_test_case +TEST_CASE_CLASS=AssistantPlaybackLatencyPreloadingTestCase +TEST_SEQUENCE_MODULE=eurtest.tests.assistant.fuchsia_query_driven_test_sequence +TEST_SEQUENCE_CLASS=FuchsiaQueryDrivenTestSequence +# Relative GCS path (from the cast-test-data bucket) to the directory containing +# the test audio config files. +GCS_AUDIO_DIR_PATH=assistant/pineapple-p2-rerecordings/synthetic_speech/local_media_playback/youtube_music/ +# This identifier will appear as a prefix on the name of test result. +# Valid only for tests that uses QueryDrivenTestSequence, otherwise ignored. +TEST_RESULT_PREFIX=playback_latency_youtube_music +ASSISTANT_BACKEND=DOGFOOD_SERVER +# Never bactrack so service-related failures have a +# chronological correspondence to build numbers. +BUILD_SELECTION_POLICY=always_use_latest +
diff --git a/lab_system/master/config/tests/assistant_multi_device_duo_calls_perf_test/assistant_multi_device_duo_calls_perf_test.cfg b/lab_system/master/config/tests/assistant_multi_device_duo_calls_perf_test/assistant_multi_device_duo_calls_perf_test.cfg new file mode 100644 index 0000000..e098d22 --- /dev/null +++ b/lab_system/master/config/tests/assistant_multi_device_duo_calls_perf_test/assistant_multi_device_duo_calls_perf_test.cfg
@@ -0,0 +1,25 @@ +# Config file for assistant phone calls tests + +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.assistant.assistant_multi_device_duo_calls_perf_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=AssistantMultiDeviceDuoCallsPerfTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.assistant.assistant_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=AssistantMultiDeviceTestSequence + +# Relative GCS path (from the cast-test-data bucket) to the directory containing +# the test audio config files. +GCS_AUDIO_DIR_PATH=assistant/pineapple-p2-rerecordings/synthetic_speech/duo_audio_calls + +# Assistant backend server to use. Valid values are : +# "NIGHTLY_DEV_SERVER", "TEAMFOOD_SERVER", "DOGFOOD_SERVER" and "PROD_SERVER" +# These values are defined in +# continuous-tests/internal/eurtest/device/assistant_device.py +ASSISTANT_BACKEND=DOGFOOD_SERVER
diff --git a/lab_system/master/config/tests/assistant_multi_device_duo_calls_test/assistant_multi_device_duo_calls_test.cfg b/lab_system/master/config/tests/assistant_multi_device_duo_calls_test/assistant_multi_device_duo_calls_test.cfg new file mode 100644 index 0000000..feca111 --- /dev/null +++ b/lab_system/master/config/tests/assistant_multi_device_duo_calls_test/assistant_multi_device_duo_calls_test.cfg
@@ -0,0 +1,31 @@ +# Config file for assistant phone calls tests + +# Do not modify property names +# Run make reconfig if you change a value +# and buildbot is running + +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.assistant.assistant_multi_device_duo_calls_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=AssistantMultiDeviceDuoCallsTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.assistant.assistant_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=AssistantMultiDeviceTestSequence + +# Relative GCS path (from the cast-test-data bucket) to the directory containing +# the test audio config files. +GCS_AUDIO_DIR_PATH=assistant/pineapple-p2-rerecordings/synthetic_speech/duo_audio_calls + +# Assistant backend server to use. Valid values are : +# "NIGHTLY_DEV_SERVER", "TEAMFOOD_SERVER", "DOGFOOD_SERVER" and "PROD_SERVER" +# These values are defined in +# continuous-tests/internal/eurtest/device/assistant_device.py +ASSISTANT_BACKEND=DOGFOOD_SERVER + +
diff --git a/lab_system/master/config/tests/assistant_oda_base_test/assistant_oda_base_test.cfg b/lab_system/master/config/tests/assistant_oda_base_test/assistant_oda_base_test.cfg new file mode 100644 index 0000000..d385290 --- /dev/null +++ b/lab_system/master/config/tests/assistant_oda_base_test/assistant_oda_base_test.cfg
@@ -0,0 +1,24 @@ +# Config file for Word Error Rate (WER) tests. +# +# Do not modify property names +# PROPERTIES + +# Assistant backend server to use. Valid values are : +# "NIGHTLY_DEV_SERVER", "TEAMFOOD_SERVER", "DOGFOOD_SERVER" and "PROD_SERVER" +# These values are defined in +# continuous-tests/internal/eurtest/device/assistant_device.py +ASSISTANT_BACKEND=DOGFOOD_SERVER + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.assistant.oda.assistant_oda_base_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=AssistantOdaBaseTestCase + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=AssistantOdaBaseTestSequence + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.assistant.oda.assistant_oda_base_test_sequence + +
diff --git a/lab_system/master/config/tests/assistant_oda_upl/assistant_oda_i18n.cfg b/lab_system/master/config/tests/assistant_oda_upl/assistant_oda_i18n.cfg new file mode 100644 index 0000000..c94d8da --- /dev/null +++ b/lab_system/master/config/tests/assistant_oda_upl/assistant_oda_i18n.cfg
@@ -0,0 +1,24 @@ +# Config file for Word Error Rate (WER) tests. +# +# Do not modify property names +# PROPERTIES + +# Relative GCS path (from the cast-test-data bucket) to the directory containing +# the test audio config files. +GCS_AUDIO_DIR_PATH=assistant/oda_upl/i18n/samples + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.assistant.oda.assistant_oda_smoke_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=AssistantOdaSmokeTestCase + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=AssistantOdaWerTestSequence + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.assistant.oda.assistant_oda_wer_test_sequence + +# Enable Personal Results for Device Assistant Settings during device linking +# This is applicable only for Display Devices +ALLOW_PERSONAL_RESULTS=True \ No newline at end of file
diff --git a/lab_system/master/config/tests/assistant_oda_upl/assistant_oda_media_initiation.cfg b/lab_system/master/config/tests/assistant_oda_upl/assistant_oda_media_initiation.cfg new file mode 100644 index 0000000..8e9375e --- /dev/null +++ b/lab_system/master/config/tests/assistant_oda_upl/assistant_oda_media_initiation.cfg
@@ -0,0 +1,25 @@ +# Config file for ODA Media Initiation tests. +# +# Do not modify property names +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.assistant.oda.assistant_oda_media_initiation_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=AssistantOdaMediaInitiationTestCase + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=AssistantOdaBaseTestSequence + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.assistant.oda.assistant_oda_base_test_sequence + +# Use Tunnel where applicable +USE_TUNNEL=False + +# Enable Personal Results for Device Assistant Settings during device linking +# This is applicable only for Display Devices +ALLOW_PERSONAL_RESULTS=True + +
diff --git a/lab_system/master/config/tests/assistant_oda_upl/assistant_oda_upl.cfg b/lab_system/master/config/tests/assistant_oda_upl/assistant_oda_upl.cfg new file mode 100644 index 0000000..53ffe4d --- /dev/null +++ b/lab_system/master/config/tests/assistant_oda_upl/assistant_oda_upl.cfg
@@ -0,0 +1,44 @@ +# Config file for marble upl +# +# Do not modify property names +# Run make reconfig if you change a value +# and buildbot is running +# +# PROPERTIES + +# GCS location where the alert tone and flow order json are stored +ALERT_TONE_FILENAME=alert_tone.wav +BEHAVIORS_JSON_FILENAME=behaviors.json +FLOWS_JSON_FILENAME=flows.json +GCS_PATH=assistant/oda_upl + +# GCS location where samples are stored +SAMPLES_GCS_PATH=assistant/oda_upl/samples + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.assistant.oda.assistant_oda_upl_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=AssistantOdaUplTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.assistant.oda.assistant_oda_upl_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=AssistantOdaUplTestSequence + +# Use Tunnel where applicable +USE_TUNNEL=False + +# Profilers to Run +PERF_PROFILERS=cgroup_profiler,spm_profiler + +# CGroup Profiler Options to Run +CGROUP_PARAMETER=-c -dmr + +# Timeout in seconds to wait before first test (5 minutes/300 seconds) +TIMEOUT_SECONDS_BEFORE_FIRST_TEST=300 + +# Enable Personal Results for Device Assistant Settings during device linking +# This is applicable only for Display Devices +ALLOW_PERSONAL_RESULTS=True \ No newline at end of file
diff --git a/lab_system/master/config/tests/assistant_oda_upl/assistant_oda_upl_no_profilers.cfg b/lab_system/master/config/tests/assistant_oda_upl/assistant_oda_upl_no_profilers.cfg new file mode 100644 index 0000000..a5acef3 --- /dev/null +++ b/lab_system/master/config/tests/assistant_oda_upl/assistant_oda_upl_no_profilers.cfg
@@ -0,0 +1,42 @@ +# Config file for marble upl +# +# Do not modify property names +# Run make reconfig if you change a value +# and buildbot is running +# +# PROPERTIES + +# GCS location where the alert tone and flow order json are stored +ALERT_TONE_FILENAME=alert_tone.wav +BEHAVIORS_JSON_FILENAME=behaviors.json +FLOWS_JSON_FILENAME=flows.json +GCS_PATH=assistant/oda_upl + +# GCS location where samples are stored +SAMPLES_GCS_PATH=assistant/oda_upl/samples + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.assistant.oda.assistant_oda_upl_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=AssistantOdaUplTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.assistant.oda.assistant_oda_upl_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=AssistantOdaUplTestSequence + +# Use Tunnel where applicable +USE_TUNNEL=False + +# Timeout in seconds to wait before first test (5 minutes/300 seconds) +TIMEOUT_SECONDS_BEFORE_FIRST_TEST=300 + +# Enable Personal Results for Device Assistant Settings during device linking +# This is applicable only for Display Devices +ALLOW_PERSONAL_RESULTS=True + +# SAVE ASR TRACES during tests. Default True to save files in test artifacts. +# If False, files will not be saved in test artifacts. +SAVE_ASR_TRACES=False \ No newline at end of file
diff --git a/lab_system/master/config/tests/assistant_oda_upl/assistant_oda_upl_no_profilers_fuchsia.cfg b/lab_system/master/config/tests/assistant_oda_upl/assistant_oda_upl_no_profilers_fuchsia.cfg new file mode 100644 index 0000000..92f9f4f --- /dev/null +++ b/lab_system/master/config/tests/assistant_oda_upl/assistant_oda_upl_no_profilers_fuchsia.cfg
@@ -0,0 +1,34 @@ +# Config file for marble upl +# +# Do not modify property names +# Run make reconfig if you change a value +# and buildbot is running +# +# PROPERTIES + +# GCS location where the alert tone and flow order json are stored +ALERT_TONE_FILENAME=alert_tone.wav +BEHAVIORS_JSON_FILENAME=behaviors.json +FLOWS_JSON_FILENAME=flows.json +GCS_PATH=assistant/oda_upl + +# GCS location where samples are stored +SAMPLES_GCS_PATH=assistant/oda_upl/samples + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.assistant.oda.assistant_oda_upl_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=AssistantOdaUplTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.assistant.oda.fuchsia_assistant_oda_upl_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=FuchsiaAssistantOdaUplTestSequence + +# Use Tunnel where applicable +USE_TUNNEL=False + +# Timeout in seconds to wait before first test (5 minutes/300 seconds) +TIMEOUT_SECONDS_BEFORE_FIRST_TEST=300 \ No newline at end of file
diff --git a/lab_system/master/config/tests/assistant_oda_upl/assistant_oda_upl_test.cfg b/lab_system/master/config/tests/assistant_oda_upl/assistant_oda_upl_test.cfg new file mode 100644 index 0000000..a50d4fc --- /dev/null +++ b/lab_system/master/config/tests/assistant_oda_upl/assistant_oda_upl_test.cfg
@@ -0,0 +1,38 @@ +# Config file for marble upl +# +# Do not modify property names +# Run make reconfig if you change a value +# and buildbot is running +# +# PROPERTIES + +# GCS location where the alert tone and flow order json are stored +ALERT_TONE_FILENAME=alert_tone.wav +BEHAVIORS_JSON_FILENAME=behaviors_test.json +FLOWS_JSON_FILENAME=flows_test.json +GCS_PATH=assistant/oda_upl + +# GCS location where samples are stored +SAMPLES_GCS_PATH=assistant/oda_upl/samples + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.assistant.oda.assistant_oda_upl_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=AssistantOdaUplTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.assistant.oda.assistant_oda_upl_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=AssistantOdaUplTestSequence + +# Use Tunnel whether to use a ssh tunnel or not +USE_TUNNEL=False + +# Timeout in seconds to wait before first test (5 minutes/300 seconds) +TIMEOUT_SECONDS_BEFORE_FIRST_TEST=300 + +# Enable Personal Results for Device Assistant Settings during device linking +# This is applicable only for Display Devices +ALLOW_PERSONAL_RESULTS=True \ No newline at end of file
diff --git a/lab_system/master/config/tests/assistant_oda_upl/assistant_oda_upl_warmwords.cfg b/lab_system/master/config/tests/assistant_oda_upl/assistant_oda_upl_warmwords.cfg new file mode 100644 index 0000000..784575d --- /dev/null +++ b/lab_system/master/config/tests/assistant_oda_upl/assistant_oda_upl_warmwords.cfg
@@ -0,0 +1,47 @@ +# Config file for marble upl +# +# Do not modify property names +# Run make reconfig if you change a value +# and buildbot is running +# +# PROPERTIES + +# GCS location where the alert tone and flow order json are stored +ALERT_TONE_FILENAME=alert_tone.wav +BEHAVIORS_JSON_FILENAME=behaviors_warmwords.json +FLOWS_JSON_FILENAME=flows_warmwords.json +GCS_PATH=assistant/oda_upl + +# GCS location where samples are stored +SAMPLES_GCS_PATH=assistant/oda_upl/samples_warmwords + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.assistant.oda.assistant_oda_upl_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=AssistantOdaUplTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.assistant.oda.assistant_oda_upl_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=AssistantOdaUplTestSequence + +# Use Tunnel where applicable +USE_TUNNEL=False + +# FLAG TO ENABLE or DISABLE WARM WORDS ON DEVICE +ENABLE_WARMWORDS=True + +# Profilers to Run +PERF_PROFILERS=cgroup_profiler,spm_profiler + +# CGroup Profiler Options to Run +CGROUP_PARAMETER=-c -dmr + +# Timeout in seconds to wait before first test (15 minutes/900 seconds) +TIMEOUT_SECONDS_BEFORE_FIRST_TEST=900 + +# Enable Personal Results for Device Assistant Settings during device linking +# This is applicable only for Display Devices +ALLOW_PERSONAL_RESULTS=True \ No newline at end of file
diff --git a/lab_system/master/config/tests/assistant_oda_upl/assistant_oda_upl_warmwords_long_run.cfg b/lab_system/master/config/tests/assistant_oda_upl/assistant_oda_upl_warmwords_long_run.cfg new file mode 100644 index 0000000..6bcd0fa --- /dev/null +++ b/lab_system/master/config/tests/assistant_oda_upl/assistant_oda_upl_warmwords_long_run.cfg
@@ -0,0 +1,44 @@ +# Config file for marble upl +# +# Do not modify property names +# Run make reconfig if you change a value +# and buildbot is running +# +# PROPERTIES + +# GCS location where the alert tone and flow order json are stored +ALERT_TONE_FILENAME=alert_tone.wav +BEHAVIORS_JSON_FILENAME=behaviors_warmwords.json +FLOWS_JSON_FILENAME=flows_warmwords.json +GCS_PATH=assistant/oda_upl + +# GCS location where samples are stored +SAMPLES_GCS_PATH=assistant/oda_upl/samples_warmwords + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.assistant.oda.assistant_oda_upl_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=AssistantOdaUplTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.assistant.oda.assistant_oda_upl_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=AssistantOdaUplTestSequence + +# Use Tunnel where applicable +USE_TUNNEL=False + +# FLAG TO ENABLE or DISABLE WARM WORDS ON DEVICE +ENABLE_WARMWORDS=True + +# Profilers to Run +PERF_PROFILERS=cgroup_profiler,spm_profiler + +# Timeout in seconds to wait between each test (15 minutes/900 seconds) +TIMEOUT_SECONDS_BETWEEN_TEST=900 + +# Enable Personal Results for Device Assistant Settings during device linking +# This is applicable only for Display Devices +ALLOW_PERSONAL_RESULTS=True \ No newline at end of file
diff --git a/lab_system/master/config/tests/assistant_oda_upl/assistant_oda_upl_warmwords_no_profilers_fuchsia.cfg b/lab_system/master/config/tests/assistant_oda_upl/assistant_oda_upl_warmwords_no_profilers_fuchsia.cfg new file mode 100644 index 0000000..acd3790 --- /dev/null +++ b/lab_system/master/config/tests/assistant_oda_upl/assistant_oda_upl_warmwords_no_profilers_fuchsia.cfg
@@ -0,0 +1,37 @@ +# Config file for marble upl +# +# Do not modify property names +# Run make reconfig if you change a value +# and buildbot is running +# +# PROPERTIES + +# GCS location where the alert tone and flow order json are stored +ALERT_TONE_FILENAME=alert_tone.wav +BEHAVIORS_JSON_FILENAME=behaviors_warmwords.json +FLOWS_JSON_FILENAME=flows_warmwords.json +GCS_PATH=assistant/oda_upl + +# GCS location where samples are stored +SAMPLES_GCS_PATH=assistant/oda_upl/samples_warmwords + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.assistant.oda.assistant_oda_upl_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=AssistantOdaUplTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.assistant.oda.fuchsia_assistant_oda_upl_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=FuchsiaAssistantOdaUplTestSequence + +# Use Tunnel where applicable +USE_TUNNEL=False + +# FLAG TO ENABLE or DISABLE WARM WORDS ON DEVICE +ENABLE_WARMWORDS=True + +# Timeout in seconds to wait before first test (5 minutes/300 seconds) +TIMEOUT_SECONDS_BEFORE_FIRST_TEST=300 \ No newline at end of file
diff --git a/lab_system/master/config/tests/assistant_phone_calls_events_test/assistant_phone_call_events_test.cfg b/lab_system/master/config/tests/assistant_phone_calls_events_test/assistant_phone_call_events_test.cfg new file mode 100644 index 0000000..f322ee4 --- /dev/null +++ b/lab_system/master/config/tests/assistant_phone_calls_events_test/assistant_phone_call_events_test.cfg
@@ -0,0 +1,36 @@ +# Config file for assistant phone calls tests + +# Do not modify property names +# Run make reconfig if you change a value +# and buildbot is running + +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.assistant.assistant_phone_calls_event_validation_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=AssistantPhoneCallsEventValidationTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.assistant.assistant_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=AssistantTestSequence + +# Relative GCS path (from the cast-test-data bucket) to the directory containing +# the test audio config files. +GCS_AUDIO_DIR_PATH=assistant/pineapple-p2-rerecordings/synthetic_speech/chirp_calls + +# Assistant backend server to use. Valid values are : +# "NIGHTLY_DEV_SERVER", "TEAMFOOD_SERVER", "DOGFOOD_SERVER" and "PROD_SERVER" +# These values are defined in +# continuous-tests/internal/eurtest/device/assistant_device.py +ASSISTANT_BACKEND=DOGFOOD_SERVER + +BUILD_SELECTION_POLICY=backtrack_then_latest + +# Maximum number of builds to be used in build selection process. +MAX_BUILD_SELECTION_RANGE=3 + +
diff --git a/lab_system/master/config/tests/assistant_phone_calls_quality_test/assistant_phone_calls_quality_test.cfg b/lab_system/master/config/tests/assistant_phone_calls_quality_test/assistant_phone_calls_quality_test.cfg new file mode 100644 index 0000000..3ac40de --- /dev/null +++ b/lab_system/master/config/tests/assistant_phone_calls_quality_test/assistant_phone_calls_quality_test.cfg
@@ -0,0 +1,36 @@ +# Config file for assistant phone calls tests + +# Do not modify property names +# Run make reconfig if you change a value +# and buildbot is running + +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.assistant.assistant_phone_calls_quality_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=AssistantPhoneCallsQualityTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.assistant.assistant_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=AssistantTestSequence + +# Relative GCS path (from the cast-test-data bucket) to the directory containing +# the test audio config files. +GCS_AUDIO_DIR_PATH=assistant/pineapple-p2-rerecordings/synthetic_speech/chirp_calls + +# Assistant backend server to use. Valid values are : +# "NIGHTLY_DEV_SERVER", "TEAMFOOD_SERVER", "DOGFOOD_SERVER" and "PROD_SERVER" +# These values are defined in +# continuous-tests/internal/eurtest/device/assistant_device.py +ASSISTANT_BACKEND=DOGFOOD_SERVER + +BUILD_SELECTION_POLICY=backtrack_then_latest + +# Maximum number of builds to be used in build selection process. +MAX_BUILD_SELECTION_RANGE=3 + +
diff --git a/lab_system/master/config/tests/assistant_phone_calls_test/assistant_phone_calls_test.cfg b/lab_system/master/config/tests/assistant_phone_calls_test/assistant_phone_calls_test.cfg new file mode 100644 index 0000000..181bc85 --- /dev/null +++ b/lab_system/master/config/tests/assistant_phone_calls_test/assistant_phone_calls_test.cfg
@@ -0,0 +1,36 @@ +# Config file for assistant phone calls tests + +# Do not modify property names +# Run make reconfig if you change a value +# and buildbot is running + +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.assistant.assistant_phone_calls_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=AssistantPhoneCallsTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.assistant.assistant_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=AssistantTestSequence + +# Relative GCS path (from the cast-test-data bucket) to the directory containing +# the test audio config files. +GCS_AUDIO_DIR_PATH=assistant/pineapple-p2-rerecordings/synthetic_speech/chirp_calls + +# Assistant backend server to use. Valid values are : +# "NIGHTLY_DEV_SERVER", "TEAMFOOD_SERVER", "DOGFOOD_SERVER" and "PROD_SERVER" +# These values are defined in +# continuous-tests/internal/eurtest/device/assistant_device.py +ASSISTANT_BACKEND=DOGFOOD_SERVER + +BUILD_SELECTION_POLICY=backtrack_then_latest + +# Maximum number of builds to be used in build selection process. +MAX_BUILD_SELECTION_RANGE=3 + +
diff --git a/lab_system/master/config/tests/assistant_presubmit/assistant_presubmit.cfg b/lab_system/master/config/tests/assistant_presubmit/assistant_presubmit.cfg new file mode 100644 index 0000000..5734b09 --- /dev/null +++ b/lab_system/master/config/tests/assistant_presubmit/assistant_presubmit.cfg
@@ -0,0 +1,31 @@ +# Config file for presubmit tests on virtual devices. +# +# Do not modify property names +# Run make reconfig if you change a value +# and buildbot is running +# +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.assistant.presubmit_hotword_count.presubmit_hotword_count_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=AssistantHotwordCountTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.assistant.presubmit_hotword_count.presubmit_hotword_count_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=PresubmitTestSequence + +# PROPERTIES + +# Test suite name of test being run +SUITE_NAME=AssistantHotwordPresubmitTest + +# Timeout for complete test run. +# Currently, it takes 3.5 hrs including failures. +SUITE_TIMEOUT_SECS=1200 + +# Use Tunnel where applicable + +TCP_TUNNEL_TIMEOUT_SECS=1800 +
diff --git a/lab_system/master/config/tests/assistant_pti_test/assistant_pti_interruption_test.cfg b/lab_system/master/config/tests/assistant_pti_test/assistant_pti_interruption_test.cfg new file mode 100644 index 0000000..13a2734 --- /dev/null +++ b/lab_system/master/config/tests/assistant_pti_test/assistant_pti_interruption_test.cfg
@@ -0,0 +1,30 @@ +# Config file for PTI Interruption Test +# +# Do not modify property names +# PROPERTIES + +# Assistant backend server to use. Valid values are : +# "NIGHTLY_DEV_SERVER", "TEAMFOOD_SERVER", "DOGFOOD_SERVER" and "PROD_SERVER" +# These values are defined in +# continuous-tests/internal/eurtest/device/assistant_device.py +ASSISTANT_BACKEND=DOGFOOD_SERVER + +# Relative GCS path (from the cast-test-data bucket) to the directory containing +# the test audio config files. +GCS_AUDIO_DIR_PATH=assistant/PTI/dialogues_to_stop + +# Bucket contains the waves from interruptions +INTERRUPTION_GCS_BUCKET=assistant/PTI/interruptions + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=AssistantPtiInterruptionTestCase + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.assistant.pti.assistant_pti_interruption_test_case + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=AssistantPtiInterruptionTestSequence + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.assistant.pti.assistant_pti_interruption_test_sequence +
diff --git a/lab_system/master/config/tests/assistant_pti_test/assistant_pti_overhear_test.cfg b/lab_system/master/config/tests/assistant_pti_test/assistant_pti_overhear_test.cfg new file mode 100644 index 0000000..fadd767 --- /dev/null +++ b/lab_system/master/config/tests/assistant_pti_test/assistant_pti_overhear_test.cfg
@@ -0,0 +1,33 @@ +# Config file for PTI overhear test results +# +# Do not modify property names +# PROPERTIES + +# Assistant backend server to use. Valid values are : +# "NIGHTLY_DEV_SERVER", "TEAMFOOD_SERVER", "DOGFOOD_SERVER" and "PROD_SERVER" +# These values are defined in +# continuous-tests/internal/eurtest/device/assistant_device.py +ASSISTANT_BACKEND=DOGFOOD_SERVER + +BUILD_SELECTION_POLICY=backtrack_then_latest + +# Relative GCS path (from the cast-test-data bucket) to the directory containing +# the test audio config files. +GCS_AUDIO_DIR_PATH=assistant/PTI/overhear + +# Maximum number of builds to be used in build selection process. +MAX_BUILD_SELECTION_RANGE=3 + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=AssistantPtiOverhearTestCase + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.assistant.pti.assistant_pti_overhear_test_case + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=AssistantPtiOverhearTestSequence + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.assistant.pti.assistant_pti_overhear_test_sequence + +
diff --git a/lab_system/master/config/tests/assistant_pti_test/assistant_pti_user_volume_test.cfg b/lab_system/master/config/tests/assistant_pti_test/assistant_pti_user_volume_test.cfg new file mode 100644 index 0000000..e35c2bf --- /dev/null +++ b/lab_system/master/config/tests/assistant_pti_test/assistant_pti_user_volume_test.cfg
@@ -0,0 +1,51 @@ +# Config file for running USER Volume Test +# +# Do not modify property names +# Run make reconfig if you change a value +# and buildbot is running +# +# PROPERTIES + +DIALOGUE_FILE=pti_rpi_interruption_dialogues.tar.gz + +# Relative GCS path (from the cast-test-data bucket) to the directory containing +# the test audio config files. +GCS_AUDIO_DIR_PATH=assistant/PTI/pti_rpi_samples/pti_rpi_interruption_dialogues + +GCS_BUCKET=cast-test-data +GCS_RPI_SAMPLES_PATH=assistant/PTI/pti_rpi_samples + +# Location of wav files on RPI +RPI_AUDIO_SAMPLES_DIR=/home/pi/pti_rpi_samples + +RPI_DOWNLOAD_DIR_PATH=/home/pi/pti_rpi_samples + +# Type of Hotword samples being tested. +SAMPLE_TYPE=PtiInterruptionSample + +# Test suite name of test being run +SUITE_NAME=PtiRPIVolumeTests + +# Timeout for complete test run. +# Currently, it takes 3.5 hrs including failures. +SUITE_TIMEOUT_SECS=14400 + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=AssistantPtiSpeakerVolumeTestCase + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.assistant.pti.assistant_pti_speaker_volume_test_case + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=AssistantPtiSpeakerVolumeTestSequence + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.assistant.pti.assistant_pti_speaker_volume_test_sequence + +# Use Tunnel where applicable + +TCP_TUNNEL_TIMEOUT_SECS=1800 + +WAIT_TIME=10 + +WAV_FILES_DIR_PATH=/home/pi/pti_rpi_interruption_dialogues
diff --git a/lab_system/master/config/tests/assistant_query_latency/answers_latency_dogfood.cfg b/lab_system/master/config/tests/assistant_query_latency/answers_latency_dogfood.cfg new file mode 100644 index 0000000..80e68f6 --- /dev/null +++ b/lab_system/master/config/tests/assistant_query_latency/answers_latency_dogfood.cfg
@@ -0,0 +1,15 @@ +TEST_CASE_MODULE=eurtest.tests.assistant.assistant_latency_test_case +TEST_CASE_CLASS=QueryDrivenLatencyTestCase +TEST_SEQUENCE_MODULE=eurtest.tests.assistant.query_driven_test_sequence +TEST_SEQUENCE_CLASS=QueryDrivenTestSequence +# Relative GCS path (from the cast-test-data bucket) to the directory containing +# the test audio config files. +GCS_AUDIO_DIR_PATH=assistant/pineapple-p2-rerecordings/synthetic_speech/chirp_answers_golden/answers +# This identifier will appear as a prefix on the name of test result. +# Valid only for tests that uses QueryDrivenTestSequence, otherwise ignored. +TEST_RESULT_PREFIX=answers_latency_tests +ASSISTANT_BACKEND=DOGFOOD_SERVER +# Never bactrack so service-related failures have a +# chronological correspondence to build numbers. +BUILD_SELECTION_POLICY=always_use_latest +
diff --git a/lab_system/master/config/tests/assistant_query_latency/answers_latency_dogfood_fuchsia.cfg b/lab_system/master/config/tests/assistant_query_latency/answers_latency_dogfood_fuchsia.cfg new file mode 100644 index 0000000..8cde8ed --- /dev/null +++ b/lab_system/master/config/tests/assistant_query_latency/answers_latency_dogfood_fuchsia.cfg
@@ -0,0 +1,15 @@ +TEST_CASE_MODULE=eurtest.tests.assistant.assistant_latency_test_case +TEST_CASE_CLASS=QueryDrivenLatencyTestCase +TEST_SEQUENCE_MODULE=eurtest.tests.assistant.fuchsia_query_driven_test_sequence +TEST_SEQUENCE_CLASS=FuchsiaQueryDrivenTestSequence +# Relative GCS path (from the cast-test-data bucket) to the directory containing +# the test audio config files. +GCS_AUDIO_DIR_PATH=assistant/pineapple-p2-rerecordings/synthetic_speech/chirp_answers_golden/answers +# This identifier will appear as a prefix on the name of test result. +# Valid only for tests that uses QueryDrivenTestSequence, otherwise ignored. +TEST_RESULT_PREFIX=answers_latency_tests +ASSISTANT_BACKEND=DOGFOOD_SERVER +# Never bactrack so service-related failures have a +# chronological correspondence to build numbers. +BUILD_SELECTION_POLICY=always_use_latest +
diff --git a/lab_system/master/config/tests/assistant_query_latency/answers_latency_prod.cfg b/lab_system/master/config/tests/assistant_query_latency/answers_latency_prod.cfg new file mode 100644 index 0000000..5ed9b8b --- /dev/null +++ b/lab_system/master/config/tests/assistant_query_latency/answers_latency_prod.cfg
@@ -0,0 +1,20 @@ +TEST_CASE_MODULE=eurtest.tests.assistant.assistant_latency_test_case +TEST_CASE_CLASS=QueryDrivenLatencyTestCase +TEST_SEQUENCE_MODULE=eurtest.tests.assistant.query_driven_test_sequence +TEST_SEQUENCE_CLASS=QueryDrivenTestSequence + +# Relative GCS path (from the cast-test-data bucket) to the directory containing +# the test audio config files. +GCS_AUDIO_DIR_PATH=assistant/pineapple-p2-rerecordings/synthetic_speech/chirp_answers_golden/answers + +# This identifier will appear as a prefix on the name of test result. +# Valid only for tests that uses QueryDrivenTestSequence, otherwise ignored. +TEST_RESULT_PREFIX=answers_latency_tests + +ASSISTANT_BACKEND=PROD_SERVER + +# Never bactrack so service-related failures have a +# chronological correspondence to build numbers. +BUILD_SELECTION_POLICY=always_use_latest + +
diff --git a/lab_system/master/config/tests/assistant_query_latency/calculator_latency_dogfood.cfg b/lab_system/master/config/tests/assistant_query_latency/calculator_latency_dogfood.cfg new file mode 100644 index 0000000..1e08e15 --- /dev/null +++ b/lab_system/master/config/tests/assistant_query_latency/calculator_latency_dogfood.cfg
@@ -0,0 +1,38 @@ +# Config file for assistant latency tests +# +# Do not modify property names +# Run make reconfig if you change a value +# and buildbot is running +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.assistant.assistant_latency_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=QueryDrivenLatencyTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.assistant.query_driven_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=QueryDrivenTestSequence + +# Relative GCS path (from the cast-test-data bucket) to the directory containing +# the test audio config files. +GCS_AUDIO_DIR_PATH=assistant/pineapple-p2-rerecordings/synthetic_speech/chirp_answers_golden/calculator + +# This identifier will appear as a prefix on the name of test result. +# Valid only for tests that uses QueryDrivenTestSequence, otherwise ignored. +TEST_RESULT_PREFIX=calculator_latency_tests + +# Assistant backend server to use. Valid values are : +# "NIGHTLY_DEV_SERVER", "TEAMFOOD_SERVER", "DOGFOOD_SERVER" and "PROD_SERVER" +# These values are defined in +# continuous-tests/internal/eurtest/device/assistant_device.py +ASSISTANT_BACKEND=DOGFOOD_SERVER +# Never bactrack so service-related failures have a +# chronological correspondence to build numbers. +BUILD_SELECTION_POLICY=always_use_latest + +
diff --git a/lab_system/master/config/tests/assistant_query_latency/canonical_queries_latency_dogfood.cfg b/lab_system/master/config/tests/assistant_query_latency/canonical_queries_latency_dogfood.cfg new file mode 100644 index 0000000..ef0ca7c --- /dev/null +++ b/lab_system/master/config/tests/assistant_query_latency/canonical_queries_latency_dogfood.cfg
@@ -0,0 +1,45 @@ +# Config file for assistant canonical queries latency tests +# +# Do not modify property names +# Run make reconfig if you change a value +# and buildbot is running +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.assistant.assistant_latency_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=QueryDrivenLatencyTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.assistant.query_driven_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=QueryDrivenTestSequence + +# Number of times a test has to be repeated. This should be an integer. +# Test will be run these many times and for all successful outcomes the latency +# numbers will be persisted. +TEST_ITERATION_COUNT=1 + +# Assistant backend server to use. Valid values are : +# "NIGHTLY_DEV_SERVER", "TEAMFOOD_SERVER", "DOGFOOD_SERVER" and "PROD_SERVER" +# These values are defined in +# continuous-tests/internal/eurtest/device/assistant_device.py +ASSISTANT_BACKEND=DOGFOOD_SERVER + +# Relative path (from the config/tests dir) to the file containing +# the list of audio test config files + +# Relative GCS path (from the cast-test-data bucket) to the directory containing +# the test audio config files. +GCS_AUDIO_DIR_PATH=assistant/pineapple-p2-rerecordings/synthetic_speech/chirp_answers_golden/canonical_queries + +# This identifier will appear as a prefix on the name of test result. +# Valid only for tests that uses QueryDrivenTestSequence, otherwise ignored. +TEST_RESULT_PREFIX=canonical_queries_latency_tests + +BUILD_SELECTION_POLICY=always_use_latest + +
diff --git a/lab_system/master/config/tests/assistant_query_latency/currency_latency_dogfood.cfg b/lab_system/master/config/tests/assistant_query_latency/currency_latency_dogfood.cfg new file mode 100644 index 0000000..63fe33e --- /dev/null +++ b/lab_system/master/config/tests/assistant_query_latency/currency_latency_dogfood.cfg
@@ -0,0 +1,39 @@ +# Config file for assistant latency tests +# +# Do not modify property names +# Run make reconfig if you change a value +# and buildbot is running +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.assistant.assistant_latency_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=QueryDrivenLatencyTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.assistant.query_driven_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=QueryDrivenTestSequence + +# Assistant backend server to use. Valid values are : +# "NIGHTLY_DEV_SERVER", "TEAMFOOD_SERVER", "DOGFOOD_SERVER" and "PROD_SERVER" +# These values are defined in +# continuous-tests/internal/eurtest/device/assistant_device.py +ASSISTANT_BACKEND=DOGFOOD_SERVER + +# Relative GCS path (from the cast-test-data bucket) to the directory containing +# the test audio config files. +GCS_AUDIO_DIR_PATH=assistant/pineapple-p2-rerecordings/synthetic_speech/chirp_answers_golden/currency + +# This identifier will appear as a prefix on the name of test result. +# Valid only for tests that uses QueryDrivenTestSequence, otherwise ignored. +TEST_RESULT_PREFIX=currency_latency_tests + +# Never bactrack so service-related failures have a +# chronological correspondence to build numbers. +BUILD_SELECTION_POLICY=always_use_latest + +
diff --git a/lab_system/master/config/tests/assistant_query_latency/dictionary_latency_dogfood.cfg b/lab_system/master/config/tests/assistant_query_latency/dictionary_latency_dogfood.cfg new file mode 100644 index 0000000..8beb2fc --- /dev/null +++ b/lab_system/master/config/tests/assistant_query_latency/dictionary_latency_dogfood.cfg
@@ -0,0 +1,37 @@ +# Config file for assistant latency tests +# +# Do not modify property names +# Run make reconfig if you change a value +# and buildbot is running +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.assistant.assistant_latency_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=QueryDrivenLatencyTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.assistant.query_driven_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=QueryDrivenTestSequence + +# Assistant backend server to use. Valid values are : +# "NIGHTLY_DEV_SERVER", "TEAMFOOD_SERVER", "DOGFOOD_SERVER" and "PROD_SERVER" +# These values are defined in +# continuous-tests/internal/eurtest/device/assistant_device.py +ASSISTANT_BACKEND=DOGFOOD_SERVER + +# Relative GCS path (from the cast-test-data bucket) to the directory containing +# the test audio config files. +GCS_AUDIO_DIR_PATH=assistant/pineapple-p2-rerecordings/synthetic_speech/chirp_answers_golden/dictionary + +# This identifier will appear as a prefix on the name of test result. +# Valid only for tests that uses QueryDrivenTestSequence, otherwise ignored. +TEST_RESULT_PREFIX=dictionary_latency_tests + +# Never bactrack so service-related failures have a +# chronological correspondence to build numbers. +BUILD_SELECTION_POLICY=always_use_latest
diff --git a/lab_system/master/config/tests/assistant_query_latency/finance_latency_dogfood.cfg b/lab_system/master/config/tests/assistant_query_latency/finance_latency_dogfood.cfg new file mode 100644 index 0000000..d90aa67 --- /dev/null +++ b/lab_system/master/config/tests/assistant_query_latency/finance_latency_dogfood.cfg
@@ -0,0 +1,17 @@ +TEST_CASE_MODULE=eurtest.tests.assistant.assistant_latency_test_case +TEST_CASE_CLASS=QueryDrivenLatencyTestCase +TEST_SEQUENCE_MODULE=eurtest.tests.assistant.query_driven_test_sequence +TEST_SEQUENCE_CLASS=QueryDrivenTestSequence +# Relative GCS path (from the cast-test-data bucket) to the directory containing +# the test audio config files. +GCS_AUDIO_DIR_PATH=assistant/pineapple-p2-rerecordings/synthetic_speech/chirp_answers_golden/finance + +# This identifier will appear as a prefix on the name of test result. +# Valid only for tests that uses QueryDrivenTestSequence, otherwise ignored. +TEST_RESULT_PREFIX=finance_latency_tests + +ASSISTANT_BACKEND=DOGFOOD_SERVER +# Never bactrack so service-related failures have a +# chronological correspondence to build numbers. +BUILD_SELECTION_POLICY=always_use_latest +
diff --git a/lab_system/master/config/tests/assistant_query_latency/local_results_latency_dogfood.cfg b/lab_system/master/config/tests/assistant_query_latency/local_results_latency_dogfood.cfg new file mode 100644 index 0000000..aa3a963 --- /dev/null +++ b/lab_system/master/config/tests/assistant_query_latency/local_results_latency_dogfood.cfg
@@ -0,0 +1,17 @@ +TEST_CASE_MODULE=eurtest.tests.assistant.assistant_latency_test_case +TEST_CASE_CLASS=QueryDrivenLatencyTestCase +TEST_SEQUENCE_MODULE=eurtest.tests.assistant.query_driven_test_sequence +TEST_SEQUENCE_CLASS=QueryDrivenTestSequence +# Relative GCS path (from the cast-test-data bucket) to the directory containing +# the test audio config files. +GCS_AUDIO_DIR_PATH=assistant/pineapple-p2-rerecordings/synthetic_speech/chirp_answers_golden/local_results + +# This identifier will appear as a prefix on the name of test result. +# Valid only for tests that uses QueryDrivenTestSequence, otherwise ignored. +TEST_RESULT_PREFIX=local_results_latency_tests + +ASSISTANT_BACKEND=DOGFOOD_SERVER +# Never bactrack so service-related failures have a +# chronological correspondence to build numbers. +BUILD_SELECTION_POLICY=always_use_latest +
diff --git a/lab_system/master/config/tests/assistant_query_latency/movie_listings_latency_dogfood.cfg b/lab_system/master/config/tests/assistant_query_latency/movie_listings_latency_dogfood.cfg new file mode 100644 index 0000000..27298a5 --- /dev/null +++ b/lab_system/master/config/tests/assistant_query_latency/movie_listings_latency_dogfood.cfg
@@ -0,0 +1,39 @@ +# Config file for assistant latency tests +# +# Do not modify property names +# Run make reconfig if you change a value +# and buildbot is running +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.assistant.assistant_latency_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=QueryDrivenLatencyTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.assistant.query_driven_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=QueryDrivenTestSequence + +# Assistant backend server to use. Valid values are : +# "NIGHTLY_DEV_SERVER", "TEAMFOOD_SERVER", "DOGFOOD_SERVER" and "PROD_SERVER" +# These values are defined in +# continuous-tests/internal/eurtest/device/assistant_device.py +ASSISTANT_BACKEND=DOGFOOD_SERVER + +# Relative GCS path (from the cast-test-data bucket) to the directory containing +# the test audio config files. +GCS_AUDIO_DIR_PATH=assistant/pineapple-p2-rerecordings/synthetic_speech/chirp_answers_golden/movie_listings + +# This identifier will appear as a prefix on the name of test result. +# Valid only for tests that uses QueryDrivenTestSequence, otherwise ignored. +TEST_RESULT_PREFIX=movie_listings_latency_tests + +# Never bactrack so service-related failures have a +# chronological correspondence to build numbers. +BUILD_SELECTION_POLICY=always_use_latest + +
diff --git a/lab_system/master/config/tests/assistant_query_latency/nutrition_latency_dogfood.cfg b/lab_system/master/config/tests/assistant_query_latency/nutrition_latency_dogfood.cfg new file mode 100644 index 0000000..eb7e809 --- /dev/null +++ b/lab_system/master/config/tests/assistant_query_latency/nutrition_latency_dogfood.cfg
@@ -0,0 +1,15 @@ +TEST_CASE_MODULE=eurtest.tests.assistant.assistant_latency_test_case +TEST_CASE_CLASS=QueryDrivenLatencyTestCase +TEST_SEQUENCE_MODULE=eurtest.tests.assistant.query_driven_test_sequence +TEST_SEQUENCE_CLASS=QueryDrivenTestSequence +# Relative GCS path (from the cast-test-data bucket) to the directory containing +# the test audio config files. +GCS_AUDIO_DIR_PATH=assistant/pineapple-p2-rerecordings/synthetic_speech/chirp_answers_golden/nutrition +# This identifier will appear as a prefix on the name of test result. +# Valid only for tests that uses QueryDrivenTestSequence, otherwise ignored. +TEST_RESULT_PREFIX=nutrition_latency_tests +ASSISTANT_BACKEND=DOGFOOD_SERVER +# Never bactrack so service-related failures have a +# chronological correspondence to build numbers. +BUILD_SELECTION_POLICY=always_use_latest +
diff --git a/lab_system/master/config/tests/assistant_query_latency/persona_latency_dogfood.cfg b/lab_system/master/config/tests/assistant_query_latency/persona_latency_dogfood.cfg new file mode 100644 index 0000000..1c7c08b --- /dev/null +++ b/lab_system/master/config/tests/assistant_query_latency/persona_latency_dogfood.cfg
@@ -0,0 +1,38 @@ +# Config file for assistant latency tests +# +# Do not modify property names +# Run make reconfig if you change a value +# and buildbot is running +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.assistant.assistant_latency_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=QueryDrivenLatencyTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.assistant.query_driven_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=QueryDrivenTestSequence + +# Relative GCS path (from the cast-test-data bucket) to the directory containing +# the test audio config files. +GCS_AUDIO_DIR_PATH=assistant/pineapple-p2-rerecordings/synthetic_speech/chirp_answers_golden/persona + +# This identifier will appear as a prefix on the name of test result. +# Valid only for tests that uses QueryDrivenTestSequence, otherwise ignored. +TEST_RESULT_PREFIX=persona_latency_tests + +# Assistant backend server to use. Valid values are : +# "NIGHTLY_DEV_SERVER", "TEAMFOOD_SERVER", "DOGFOOD_SERVER" and "PROD_SERVER" +# These values are defined in +# continuous-tests/internal/eurtest/device/assistant_device.py +ASSISTANT_BACKEND=DOGFOOD_SERVER +# Never bactrack so service-related failures have a +# chronological correspondence to build numbers. +BUILD_SELECTION_POLICY=always_use_latest + +
diff --git a/lab_system/master/config/tests/assistant_query_latency/recipes_latency_dogfood.cfg b/lab_system/master/config/tests/assistant_query_latency/recipes_latency_dogfood.cfg new file mode 100644 index 0000000..16b4f61 --- /dev/null +++ b/lab_system/master/config/tests/assistant_query_latency/recipes_latency_dogfood.cfg
@@ -0,0 +1,39 @@ +# Config file for assistant latency tests +# +# Do not modify property names +# Run make reconfig if you change a value +# and buildbot is running +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.assistant.assistant_latency_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=QueryDrivenLatencyTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.assistant.query_driven_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=QueryDrivenTestSequence + +# Relative GCS path (from the cast-test-data bucket) to the directory containing +# the test audio config files. +GCS_AUDIO_DIR_PATH=assistant/pineapple-p2-rerecordings/synthetic_speech/chirp_answers_golden/recipes + +# This identifier will appear as a prefix on the name of test result. +# Valid only for tests that uses QueryDrivenTestSequence, otherwise ignored. +TEST_RESULT_PREFIX=recipes + + +# Assistant backend server to use. Valid values are : +# "NIGHTLY_DEV_SERVER", "TEAMFOOD_SERVER", "DOGFOOD_SERVER" and "PROD_SERVER" +# These values are defined in +# continuous-tests/internal/eurtest/device/assistant_device.py +ASSISTANT_BACKEND=DOGFOOD_SERVER +# Never bactrack so service-related failures have a +# chronological correspondence to build numbers. +BUILD_SELECTION_POLICY=always_use_latest + +
diff --git a/lab_system/master/config/tests/assistant_query_latency/sports_latency_dogfood.cfg b/lab_system/master/config/tests/assistant_query_latency/sports_latency_dogfood.cfg new file mode 100644 index 0000000..ff7948e --- /dev/null +++ b/lab_system/master/config/tests/assistant_query_latency/sports_latency_dogfood.cfg
@@ -0,0 +1,15 @@ +TEST_CASE_MODULE=eurtest.tests.assistant.assistant_latency_test_case +TEST_CASE_CLASS=QueryDrivenLatencyTestCase +TEST_SEQUENCE_MODULE=eurtest.tests.assistant.query_driven_test_sequence +TEST_SEQUENCE_CLASS=QueryDrivenTestSequence +# Relative GCS path (from the cast-test-data bucket) to the directory containing +# the test audio config files. +GCS_AUDIO_DIR_PATH=assistant/pineapple-p2-rerecordings/synthetic_speech/chirp_answers_golden/sports +# This identifier will appear as a prefix on the name of test result. +# Valid only for tests that uses QueryDrivenTestSequence, otherwise ignored. +TEST_RESULT_PREFIX=sports_latency_tests +ASSISTANT_BACKEND=DOGFOOD_SERVER +# Never bactrack so service-related failures have a +# chronological correspondence to build numbers. +BUILD_SELECTION_POLICY=always_use_latest +
diff --git a/lab_system/master/config/tests/assistant_query_latency/traffic_latency_dogfood.cfg b/lab_system/master/config/tests/assistant_query_latency/traffic_latency_dogfood.cfg new file mode 100644 index 0000000..f89ed6a --- /dev/null +++ b/lab_system/master/config/tests/assistant_query_latency/traffic_latency_dogfood.cfg
@@ -0,0 +1,16 @@ +TEST_CASE_MODULE=eurtest.tests.assistant.assistant_latency_test_case +TEST_CASE_CLASS=QueryDrivenLatencyTestCase +TEST_SEQUENCE_MODULE=eurtest.tests.assistant.query_driven_test_sequence +TEST_SEQUENCE_CLASS=QueryDrivenTestSequence +# Relative GCS path (from the cast-test-data bucket) to the directory containing +# the test audio config files. +GCS_AUDIO_DIR_PATH=assistant/pineapple-p2-rerecordings/synthetic_speech/chirp_answers_golden/traffic +# This identifier will appear as a prefix on the name of test result. +# Valid only for tests that uses QueryDrivenTestSequence, otherwise ignored. +TEST_RESULT_PREFIX=traffic_latency_tests +ASSISTANT_BACKEND=DOGFOOD_SERVER +# Never bactrack so service-related failures have a +# chronological correspondence to build numbers. +BUILD_SELECTION_POLICY=always_use_latest + +
diff --git a/lab_system/master/config/tests/assistant_query_latency/translations_latency_dogfood.cfg b/lab_system/master/config/tests/assistant_query_latency/translations_latency_dogfood.cfg new file mode 100644 index 0000000..12097b6 --- /dev/null +++ b/lab_system/master/config/tests/assistant_query_latency/translations_latency_dogfood.cfg
@@ -0,0 +1,39 @@ +# Config file for assistant latency tests +# +# Do not modify property names +# Run make reconfig if you change a value +# and buildbot is running +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.assistant.assistant_latency_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=QueryDrivenLatencyTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.assistant.query_driven_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=QueryDrivenTestSequence + +# Assistant backend server to use. Valid values are : +# "NIGHTLY_DEV_SERVER", "TEAMFOOD_SERVER", "DOGFOOD_SERVER" and "PROD_SERVER" +# These values are defined in +# continuous-tests/internal/eurtest/device/assistant_device.py +ASSISTANT_BACKEND=DOGFOOD_SERVER + +# Relative GCS path (from the cast-test-data bucket) to the directory containing +# the test audio config files. +GCS_AUDIO_DIR_PATH=assistant/pineapple-p2-rerecordings/synthetic_speech/chirp_answers_golden/translations + +# This identifier will appear as a prefix on the name of test result. +# Valid only for tests that uses QueryDrivenTestSequence, otherwise ignored. +TEST_RESULT_PREFIX=translations_latency_tests + +# Never bactrack so service-related failures have a +# chronological correspondence to build numbers. +BUILD_SELECTION_POLICY=always_use_latest + +
diff --git a/lab_system/master/config/tests/assistant_query_latency/unit_conversions_latency_dogfood.cfg b/lab_system/master/config/tests/assistant_query_latency/unit_conversions_latency_dogfood.cfg new file mode 100644 index 0000000..b3c129b --- /dev/null +++ b/lab_system/master/config/tests/assistant_query_latency/unit_conversions_latency_dogfood.cfg
@@ -0,0 +1,39 @@ +# Config file for assistant latency tests +# +# Do not modify property names +# Run make reconfig if you change a value +# and buildbot is running +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.assistant.assistant_latency_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=QueryDrivenLatencyTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.assistant.query_driven_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=QueryDrivenTestSequence + +# Assistant backend server to use. Valid values are : +# "NIGHTLY_DEV_SERVER", "TEAMFOOD_SERVER", "DOGFOOD_SERVER" and "PROD_SERVER" +# These values are defined in +# continuous-tests/internal/eurtest/device/assistant_device.py +ASSISTANT_BACKEND=DOGFOOD_SERVER + +# Relative GCS path (from the cast-test-data bucket) to the directory containing +# the test audio config files. +GCS_AUDIO_DIR_PATH=assistant/pineapple-p2-rerecordings/synthetic_speech/chirp_answers_golden/unit_conversion + +# This identifier will appear as a prefix on the name of test result. +# Valid only for tests that uses QueryDrivenTestSequence, otherwise ignored. +TEST_RESULT_PREFIX=unit_conversions_latency_tests + +# Never bactrack so service-related failures have a +# chronological correspondence to build numbers. +BUILD_SELECTION_POLICY=always_use_latest + +
diff --git a/lab_system/master/config/tests/assistant_query_latency/weather_latency_dogfood.cfg b/lab_system/master/config/tests/assistant_query_latency/weather_latency_dogfood.cfg new file mode 100644 index 0000000..27b357b --- /dev/null +++ b/lab_system/master/config/tests/assistant_query_latency/weather_latency_dogfood.cfg
@@ -0,0 +1,15 @@ +TEST_CASE_MODULE=eurtest.tests.assistant.assistant_latency_test_case +TEST_CASE_CLASS=QueryDrivenLatencyTestCase +TEST_SEQUENCE_MODULE=eurtest.tests.assistant.query_driven_test_sequence +TEST_SEQUENCE_CLASS=QueryDrivenTestSequence +# Relative GCS path (from the cast-test-data bucket) to the directory containing +# the test audio config files. +GCS_AUDIO_DIR_PATH=assistant/pineapple-p2-rerecordings/synthetic_speech/chirp_answers_golden/weather +# This identifier will appear as a prefix on the name of test result. +# Valid only for tests that uses QueryDrivenTestSequence, otherwise ignored. +TEST_RESULT_PREFIX=weather_latency_tests +ASSISTANT_BACKEND=DOGFOOD_SERVER +# Never bactrack so service-related failures have a +# chronological correspondence to build numbers. +BUILD_SELECTION_POLICY=always_use_latest +
diff --git a/lab_system/master/config/tests/assistant_remote_casting/assistant_remote_casting_latency.cfg b/lab_system/master/config/tests/assistant_remote_casting/assistant_remote_casting_latency.cfg new file mode 100644 index 0000000..58cbac0 --- /dev/null +++ b/lab_system/master/config/tests/assistant_remote_casting/assistant_remote_casting_latency.cfg
@@ -0,0 +1,17 @@ +# Config file for media playback latency test cases. + +TEST_CASE_MODULE=eurtest.tests.assistant.remote_casting_test_case +TEST_CASE_CLASS=AssistantRemoteCastingLatencyTestCase +TEST_SEQUENCE_MODULE=eurtest.tests.assistant.remote_casting_test_case +TEST_SEQUENCE_CLASS=RemoteCastingTestSequence +# Relative GCS path (from the cast-test-data bucket) to the directory containing +# the test audio config files. +GCS_AUDIO_DIR_PATH=assistant/pineapple-p2-rerecordings/synthetic_speech/remote_casting/audio/ +# This identifier will appear as a prefix on the name of test result. +# Valid only for tests that uses QueryDrivenTestSequence, otherwise ignored. +TEST_RESULT_PREFIX=remote_casting_joplin +ASSISTANT_BACKEND=DOGFOOD_SERVER +# Never bactrack so service-related failures have a +# chronological correspondence to build numbers. +BUILD_SELECTION_POLICY=always_use_latest +
diff --git a/lab_system/master/config/tests/assistant_remote_casting/remote_casting_config.json b/lab_system/master/config/tests/assistant_remote_casting/remote_casting_config.json new file mode 100644 index 0000000..6cb2d56 --- /dev/null +++ b/lab_system/master/config/tests/assistant_remote_casting/remote_casting_config.json
@@ -0,0 +1,13 @@ +{ + "remote_audio": { + "devices": { + "source": { + "ip": "100.107.118.94" + }, + "target": { + "friendly_name": "kitchen", + "ip": "100.107.118.100" + } + } + } +}
diff --git a/lab_system/master/config/tests/assistant_remote_casting/test_defs.json b/lab_system/master/config/tests/assistant_remote_casting/test_defs.json new file mode 100644 index 0000000..cf50c75 --- /dev/null +++ b/lab_system/master/config/tests/assistant_remote_casting/test_defs.json
@@ -0,0 +1,25 @@ + [ + { + "group_name": "assistant_playback", + "slave_name": "assistant_playback", + "test_name": "assistant_remote_casting_latency", + "identifier": "assistant_remote_casting_latency", + "device_type": "joplin", + "device_group": "assistant_remote_casting_joplin", + "build_flavor": "user", + "branch": ["next_release", "release"], + "num_devices": "2", + "step_factories": [ + { + "step_description": "Allocates devices for the testrun", + "step_identifier": "device_allocation", + "step_factories": [ + { + "module_path": "lab_system.master.steps.factory.device.cloud_allocator", + "class_name": "StrictDeviceAllocatorStepFactory" + } + ] + } + ] + } +]
diff --git a/lab_system/master/config/tests/assistant_stop_command_test/stop_command_test.cfg b/lab_system/master/config/tests/assistant_stop_command_test/stop_command_test.cfg new file mode 100644 index 0000000..7abbe5a --- /dev/null +++ b/lab_system/master/config/tests/assistant_stop_command_test/stop_command_test.cfg
@@ -0,0 +1,41 @@ +# Config file for assistant latency tests +# +# Do not modify property names +# Run make reconfig if you change a value +# and buildbot is running +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.assistant.assistant_stop_command_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=AssistantStopCommandTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.assistant.query_driven_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=QueryDrivenTestSequence + +# Relative GCS path (from the cast-test-data bucket) to the directory containing +# the test audio config files. +GCS_AUDIO_DIR_PATH=assistant/pineapple-p2-rerecordings/synthetic_speech/actions_accepting_stop_command + +# This identifier will appear as a prefix on the name of test result. +# Valid only for tests that uses QueryDrivenTestSequence, otherwise ignored. +TEST_RESULT_PREFIX=stop_command_tests + + +# Assistant backend server to use. Valid values are : +# "NIGHTLY_DEV_SERVER", "TEAMFOOD_SERVER", "DOGFOOD_SERVER" and "PROD_SERVER" +# These values are defined in +# continuous-tests/internal/eurtest/device/assistant_device.py +ASSISTANT_BACKEND=DOGFOOD_SERVER + +BUILD_SELECTION_POLICY=backtrack_then_latest + +# Maximum number of builds to be used in build selection process. +MAX_BUILD_SELECTION_RANGE=3 + +
diff --git a/lab_system/master/config/tests/assistant_timer_test/assistant_timer_dialogue_test.cfg b/lab_system/master/config/tests/assistant_timer_test/assistant_timer_dialogue_test.cfg new file mode 100644 index 0000000..7edf50b --- /dev/null +++ b/lab_system/master/config/tests/assistant_timer_test/assistant_timer_dialogue_test.cfg
@@ -0,0 +1,37 @@ +# Config file for follow-up query tests +# +# Do not modify property names +# Run make reconfig if you change a value +# and buildbot is running +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.assistant.assistant_timer_dialogue_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=AssistantTimerDialogueTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.assistant.assistant_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=AssistantTestSequence + +# Relative GCS path (from the cast-test-data bucket) to the directory containing +# the test audio config files. +GCS_AUDIO_DIR_PATH=assistant/pineapple-p2-rerecordings/synthetic_speech/dialogue/timer + +# Assistant backend server to use. Valid values are : +# "NIGHTLY_DEV_SERVER", "TEAMFOOD_SERVER", "DOGFOOD_SERVER" and "PROD_SERVER" +# These values are defined in +# continuous-tests/internal/eurtest/device/assistant_device.py +ASSISTANT_BACKEND=DOGFOOD_SERVER + +BUILD_SELECTION_POLICY=backtrack_then_latest + +# Maximum number of builds to be used in build selection process. +MAX_BUILD_SELECTION_RANGE=3 + +# Use Tunnel where applicable +
diff --git a/lab_system/master/config/tests/assistant_wer_test/assistant_art_wer_originals_test.cfg b/lab_system/master/config/tests/assistant_wer_test/assistant_art_wer_originals_test.cfg new file mode 100644 index 0000000..9983d05 --- /dev/null +++ b/lab_system/master/config/tests/assistant_wer_test/assistant_art_wer_originals_test.cfg
@@ -0,0 +1,28 @@ +# Config file for Word Error Rate (WER) tests. +# +# Do not modify property names +# PROPERTIES + +# Assistant backend server to use. Valid values are : +# "NIGHTLY_DEV_SERVER", "TEAMFOOD_SERVER", "DOGFOOD_SERVER" and "PROD_SERVER" +# These values are defined in +# continuous-tests/internal/eurtest/device/assistant_device.py +ASSISTANT_BACKEND=DOGFOOD_SERVER + +# Relative GCS path (from the cast-test-data bucket) to the directory containing +# the test audio config files. +GCS_AUDIO_DIR_PATH=assistant/wer_samples_art_normalized/ + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.assistant.assistant_wer_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=AssistantWerTestCase + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=AssistantWerTestSequence + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.assistant.assistant_wer_test_sequence + +
diff --git a/lab_system/master/config/tests/assistant_wer_test/assistant_art_wer_originals_test_fuchsia.cfg b/lab_system/master/config/tests/assistant_wer_test/assistant_art_wer_originals_test_fuchsia.cfg new file mode 100644 index 0000000..0590910 --- /dev/null +++ b/lab_system/master/config/tests/assistant_wer_test/assistant_art_wer_originals_test_fuchsia.cfg
@@ -0,0 +1,28 @@ +# Config file for Word Error Rate (WER) tests. +# +# Do not modify property names +# PROPERTIES + +# Assistant backend server to use. Valid values are : +# "NIGHTLY_DEV_SERVER", "TEAMFOOD_SERVER", "DOGFOOD_SERVER" and "PROD_SERVER" +# These values are defined in +# continuous-tests/internal/eurtest/device/assistant_device.py +ASSISTANT_BACKEND=DOGFOOD_SERVER + +# Relative GCS path (from the cast-test-data bucket) to the directory containing +# the test audio config files. +GCS_AUDIO_DIR_PATH=assistant/wer_samples_art_normalized/ + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.assistant.assistant_wer_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=AssistantWerTestCase + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=FuchsiaAssistantWerTestSequence + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.assistant.fuchsia_assistant_wer_test_sequence + +
diff --git a/lab_system/master/config/tests/assistant_wer_test/assistant_wer_test.cfg b/lab_system/master/config/tests/assistant_wer_test/assistant_wer_test.cfg new file mode 100644 index 0000000..85019b7 --- /dev/null +++ b/lab_system/master/config/tests/assistant_wer_test/assistant_wer_test.cfg
@@ -0,0 +1,28 @@ +# Config file for Word Error Rate (WER) tests. +# +# Do not modify property names +# PROPERTIES + +# Assistant backend server to use. Valid values are : +# "NIGHTLY_DEV_SERVER", "TEAMFOOD_SERVER", "DOGFOOD_SERVER" and "PROD_SERVER" +# These values are defined in +# continuous-tests/internal/eurtest/device/assistant_device.py +ASSISTANT_BACKEND=DOGFOOD_SERVER + +# Relative GCS path (from the cast-test-data bucket) to the directory containing +# the test audio config files. +GCS_AUDIO_DIR_PATH=assistant/wer_samples + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.assistant.assistant_wer_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=AssistantWerTestCase + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=AssistantWerTestSequence + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.assistant.assistant_wer_test_sequence + +
diff --git a/lab_system/master/config/tests/assistant_wer_test/assistant_wer_test_fuchsia.cfg b/lab_system/master/config/tests/assistant_wer_test/assistant_wer_test_fuchsia.cfg new file mode 100644 index 0000000..eab5ccd --- /dev/null +++ b/lab_system/master/config/tests/assistant_wer_test/assistant_wer_test_fuchsia.cfg
@@ -0,0 +1,28 @@ +# Config file for Word Error Rate (WER) tests. +# +# Do not modify property names +# PROPERTIES + +# Assistant backend server to use. Valid values are : +# "NIGHTLY_DEV_SERVER", "TEAMFOOD_SERVER", "DOGFOOD_SERVER" and "PROD_SERVER" +# These values are defined in +# continuous-tests/internal/eurtest/device/assistant_device.py +ASSISTANT_BACKEND=DOGFOOD_SERVER + +# Relative GCS path (from the cast-test-data bucket) to the directory containing +# the test audio config files. +GCS_AUDIO_DIR_PATH=assistant/wer_samples + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.assistant.assistant_wer_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=AssistantWerTestCase + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=FuchsiaAssistantWerTestSequence + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.assistant.fuchsia_assistant_wer_test_sequence + +
diff --git a/lab_system/master/config/tests/atv_unit_test/test_defs.json b/lab_system/master/config/tests/atv_unit_test/test_defs.json new file mode 100644 index 0000000..1334dc5 --- /dev/null +++ b/lab_system/master/config/tests/atv_unit_test/test_defs.json
@@ -0,0 +1,30 @@ +[ + { + "branch": ["master", "release", "next_release"], + "build_flavor": "Release", + "device_group": "unit_test", + "device_type": "fugu", + "group_name": "fugu_unit_test", + "identifier": "fugu", + "scheduler": "*/10 * * * *", + "slave_name": "fugu", + "slave_number": [ + 1 + ], + "step_factories_recipe": "step_factories_recipes/atv_unit_test_recipe.json" + }, + { + "branch": ["master", "release", "next_release"], + "build_flavor": "Release", + "device_group": "unit_test", + "device_type": "darcy", + "group_name": "fugu_unit_test", + "identifier": "shield_tv", + "scheduler": "*/10 * * * *", + "slave_name": "shield_tv", + "slave_number": [ + 1 + ], + "step_factories_recipe": "step_factories_recipes/atv_unit_test_recipe.json" + } +]
diff --git a/lab_system/master/config/tests/audio_formats/audio_formats.cfg b/lab_system/master/config/tests/audio_formats/audio_formats.cfg new file mode 100644 index 0000000..503d7e2 --- /dev/null +++ b/lab_system/master/config/tests/audio_formats/audio_formats.cfg
@@ -0,0 +1,15 @@ +# Config file for JavaScript audio format tests. +# +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.audio_formats.audio_formats_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=SupportedAudioFormatsTestCase,SupportedAudioFormatsHiResTestCase,AudioBitRatesTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.framework.javascript_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=JavascriptTestSequence + +
diff --git a/lab_system/master/config/tests/audio_formats/audio_formats_mclean.cfg b/lab_system/master/config/tests/audio_formats/audio_formats_mclean.cfg new file mode 100644 index 0000000..763d4a5 --- /dev/null +++ b/lab_system/master/config/tests/audio_formats/audio_formats_mclean.cfg
@@ -0,0 +1,15 @@ +# Config file for JavaScript audio format tests. Different group. +# +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.audio_formats.audio_formats_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=SupportedAudioFormatsTestCase,SupportedAudioFormatsHiResTestCase,AudioBitRatesTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.framework.javascript_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=JavascriptTestSequence + +
diff --git a/lab_system/master/config/tests/audio_passthrough/audio_passthrough.cfg b/lab_system/master/config/tests/audio_passthrough/audio_passthrough.cfg new file mode 100644 index 0000000..a610265 --- /dev/null +++ b/lab_system/master/config/tests/audio_passthrough/audio_passthrough.cfg
@@ -0,0 +1,15 @@ +# Config file for JavaScript audio passthrough tests. +# +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.audio_passthrough.audio_passthrough_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=AudioPassthroughFormatsTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.framework.javascript_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=JavascriptTestSequence + +
diff --git a/lab_system/master/config/tests/audiodefault_unit_test/test_defs.json b/lab_system/master/config/tests/audiodefault_unit_test/test_defs.json new file mode 100644 index 0000000..f163f53 --- /dev/null +++ b/lab_system/master/config/tests/audiodefault_unit_test/test_defs.json
@@ -0,0 +1,42 @@ +[ + { + "branch": ["cast_audio_reference_master", "cast_audio_reference_release"], + "build_flavor": "eng", + "device_group": "unit_test", + "device_type": "audiodefault", + "identifier": "audiodefault_eng", + "scheduler": "*/10 * * * *", + "slave_name": "audiodefault_eng", + "slave_number": [ + 1 + ], + "step_factories_recipe": "step_factories_recipes/audiodefault_unit_test_recipe.json" + }, + { + "branch": ["cast_assistant_reference_master", "cast_assistant_reference_release"], + "build_flavor": "eng", + "device_group": "unit_test", + "device_type": "assistantdefault", + "hidden": "true", + "identifier": "assistant_reference_eng", + "scheduler": "*/10 * * * *", + "slave_name": "assistant_reference_eng", + "slave_number": [ + 1 + ], + "step_factories_recipe": "step_factories_recipes/audiodefault_unit_test_recipe.json" + }, + { + "branch": ["cast_audio_mediatek_master", "cast_audio_mediatek_release", "cast_audio_mediatek_next_release"], + "build_flavor": "eng", + "device_group": "unit_test", + "device_type": "mozart", + "identifier": "mozart_eng", + "scheduler": "*/10 * * * *", + "slave_name": "mozart_eng", + "slave_number": [ + 1 + ], + "step_factories_recipe": "step_factories_recipes/claim_hint_unit_test_recipe.json" + } +]
diff --git a/lab_system/master/config/tests/av_sync/atv_av_sync_720p_30fps.cfg b/lab_system/master/config/tests/av_sync/atv_av_sync_720p_30fps.cfg new file mode 100644 index 0000000..85eef7c --- /dev/null +++ b/lab_system/master/config/tests/av_sync/atv_av_sync_720p_30fps.cfg
@@ -0,0 +1,35 @@ +# Config file for presence test using conducted audio on android devices +# +# Do not modify property names +# Run make reconfig if you change a value +# and buildbot is running +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.avsync.av_sync_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=AVSyncTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.avsync.av_quality_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=AndroidAvQualityTestSequence + +# Specify the av channel based on video and testbed +AUDIO_CHANNEL=0 +VIDEO_CHANNEL=7 + +# Test parameters depending on the video provided above +NOISE_MEASUREMENT_DURATION_SEC=30 +PLAY_DURATION_NO_ACTION_SEC=300 +SEEK_FORWARD_SEC=10 +SYNC_MEASUREMENT_AFTER_ACTION_SEC=32 +ITERATION_PAUSE=10 +ITERATION_SEEK=10 +DURATION_BEFORE_RESUME_SEC=32 + +TEST_CASE_PREFIX=AVSync +VIDEO_SPECIFIERS=720P30_H264_2M
diff --git a/lab_system/master/config/tests/av_sync/atv_av_sync_720p_60fps.cfg b/lab_system/master/config/tests/av_sync/atv_av_sync_720p_60fps.cfg new file mode 100644 index 0000000..7db2d7e --- /dev/null +++ b/lab_system/master/config/tests/av_sync/atv_av_sync_720p_60fps.cfg
@@ -0,0 +1,35 @@ +# Config file for presence test using conducted audio on android devices +# +# Do not modify property names +# Run make reconfig if you change a value +# and buildbot is running +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.avsync.av_sync_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=AVSyncTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.avsync.av_quality_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=AndroidAvQualityTestSequence + +# Specify the av channel based on video and testbed +AUDIO_CHANNEL=0 +VIDEO_CHANNEL=7 + +# Test parameters depending on the video provided above +NOISE_MEASUREMENT_DURATION_SEC=30 +PLAY_DURATION_NO_ACTION_SEC=300 +SEEK_FORWARD_SEC=10 +SYNC_MEASUREMENT_AFTER_ACTION_SEC=32 +ITERATION_PAUSE=10 +ITERATION_SEEK=10 +DURATION_BEFORE_RESUME_SEC=32 + +TEST_CASE_PREFIX=AVSync +VIDEO_SPECIFIERS=720P60_H264_2M,720P60_VP9_2M,720P60_VP8_2M,720P60_H265_2M,720P60_H265_2M_HDR10
diff --git a/lab_system/master/config/tests/av_sync/atv_freezing_720p_60fps.cfg b/lab_system/master/config/tests/av_sync/atv_freezing_720p_60fps.cfg new file mode 100644 index 0000000..5a0105e --- /dev/null +++ b/lab_system/master/config/tests/av_sync/atv_freezing_720p_60fps.cfg
@@ -0,0 +1,25 @@ +# Config file for video freezing test on Android TV devices +# The test evaluate frame drop and duplication with different video codec, +# resolutions and bit rates. +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.avsync.video_freezing_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=VideoFreezingTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.avsync.av_quality_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=AndroidAvQualityTestSequence + +# Test parameters +PLAYBACK_DURATION_SEC=900 +RECORD_DELAY_SEC=20 +WAIT_FOR_BUFFER_SEC=30 + +TEST_CASE_PREFIX=Freezing +VIDEO_SPECIFIERS=720P60_H264_2M,720P60_VP9_2M,720P60_VP8_2M,720P60_H265_2M,720P60_H265_2M_HDR10
diff --git a/lab_system/master/config/tests/av_sync/atv_mz_av_sync_720p_60fps.cfg b/lab_system/master/config/tests/av_sync/atv_mz_av_sync_720p_60fps.cfg new file mode 100644 index 0000000..e6b04d9 --- /dev/null +++ b/lab_system/master/config/tests/av_sync/atv_mz_av_sync_720p_60fps.cfg
@@ -0,0 +1,35 @@ +# Config file for presence test using conducted audio on android devices +# +# Do not modify property names +# Run make reconfig if you change a value +# and buildbot is running +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.avsync.av_sync_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=MultizoneAVSyncTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.avsync.av_quality_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=AndroidAvQualityTestSequence + +# Specify the av channel based on video and testbed +AUDIO_CHANNEL=0 +VIDEO_CHANNEL=7 + +# Test parameters depending on the video provided above +NOISE_MEASUREMENT_DURATION_SEC=30 +PLAY_DURATION_NO_ACTION_SEC=300 +SEEK_FORWARD_SEC=10 +SYNC_MEASUREMENT_AFTER_ACTION_SEC=32 +ITERATION_PAUSE=10 +ITERATION_SEEK=10 +DURATION_BEFORE_RESUME_SEC=32 + +TEST_CASE_PREFIX=AVSync +VIDEO_SPECIFIERS=720P60_H264_2M,720P60_VP9_2M,720P60_VP8_2M,720P60_H265_2M,720P60_H265_2M_HDR10
diff --git a/lab_system/master/config/tests/av_sync/atv_smoothness_720p_60fps.cfg b/lab_system/master/config/tests/av_sync/atv_smoothness_720p_60fps.cfg new file mode 100644 index 0000000..924881f --- /dev/null +++ b/lab_system/master/config/tests/av_sync/atv_smoothness_720p_60fps.cfg
@@ -0,0 +1,26 @@ +# Config file for presence test using conducted audio on android devices +# +# Do not modify property names +# Run make reconfig if you change a value +# and buildbot is running +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.avsync.video_smoothness_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=VideoSmoothnessTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.avsync.av_quality_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=AndroidAvQualityTestSequence + +# Test parameters depending on the video provided above +NOISE_MEASUREMENT_DURATION_SEC=10 +PLAY_DURATION_SEC=300 + +TEST_CASE_PREFIX=Smoothness +VIDEO_SPECIFIERS=720P60_H264_2M,720P60_VP9_2M,720P60_H265_2M,720P60_H265_2M_HDR10
diff --git a/lab_system/master/config/tests/av_sync/cast_av_sync_720p_30fps.cfg b/lab_system/master/config/tests/av_sync/cast_av_sync_720p_30fps.cfg new file mode 100644 index 0000000..e136333 --- /dev/null +++ b/lab_system/master/config/tests/av_sync/cast_av_sync_720p_30fps.cfg
@@ -0,0 +1,33 @@ +# Config file for avsync test on cast devices setup with barcode testbed +# Vertical barcode video is used correspond to the refresh orientation +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class +TEST_CASE_MODULE=eurtest.tests.avsync.av_sync_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=AVSyncTestCase + +# Dot-notation path to the module containing the TestSequence class +TEST_SEQUENCE_MODULE=eurtest.tests.avsync.av_quality_test_sequence + +# Name of the TestSequence sub-class +TEST_SEQUENCE_CLASS=AvQualityTestSequence + +# Specify the av channel based on video and testbed +AUDIO_CHANNEL=0 +VIDEO_CHANNEL=7 + +# Test parameters depending on the video provided above +NOISE_MEASUREMENT_DURATION_SEC=10 +PLAY_DURATION_NO_ACTION_SEC=300 +SEEK_FORWARD_SEC=10 +SYNC_MEASUREMENT_AFTER_ACTION_SEC=32 +ITERATION_PAUSE=10 +ITERATION_SEEK=10 +DURATION_BEFORE_RESUME_SEC=32 + +SIGNED_IN=True +TEST_CASE_PREFIX=AVSync +VIDEO_SPECIFIERS=720P30_H264_2M_VERTICAL
diff --git a/lab_system/master/config/tests/av_sync/cast_av_sync_720p_60fps.cfg b/lab_system/master/config/tests/av_sync/cast_av_sync_720p_60fps.cfg new file mode 100644 index 0000000..1fb07c1 --- /dev/null +++ b/lab_system/master/config/tests/av_sync/cast_av_sync_720p_60fps.cfg
@@ -0,0 +1,33 @@ +# Config file for avsync test on cast devices setup with barcode testbed +# Vertical barcode video is used correspond to the refresh orientation +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class +TEST_CASE_MODULE=eurtest.tests.avsync.av_sync_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=AVSyncTestCase + +# Dot-notation path to the module containing the TestSequence class +TEST_SEQUENCE_MODULE=eurtest.tests.avsync.av_quality_test_sequence + +# Name of the TestSequence sub-class +TEST_SEQUENCE_CLASS=AvQualityTestSequence + +# Specify the av channel based on video and testbed +AUDIO_CHANNEL=0 +VIDEO_CHANNEL=7 + +# Test parameters depending on the video provided above +NOISE_MEASUREMENT_DURATION_SEC=10 +PLAY_DURATION_NO_ACTION_SEC=300 +SEEK_FORWARD_SEC=10 +SYNC_MEASUREMENT_AFTER_ACTION_SEC=32 +ITERATION_PAUSE=10 +ITERATION_SEEK=10 +DURATION_BEFORE_RESUME_SEC=32 + +SIGNED_IN=True +TEST_CASE_PREFIX=AVSync +VIDEO_SPECIFIERS=720P60_H264_2M_VERTICAL
diff --git a/lab_system/master/config/tests/av_sync/cast_freezing_720p_60fps.cfg b/lab_system/master/config/tests/av_sync/cast_freezing_720p_60fps.cfg new file mode 100644 index 0000000..26c5394 --- /dev/null +++ b/lab_system/master/config/tests/av_sync/cast_freezing_720p_60fps.cfg
@@ -0,0 +1,25 @@ +# Config file for avsync test on cast devices setup with barcode testbed +# Vertical barcode video is used correspond to the refresh orientation +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.avsync.video_freezing_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=VideoFreezingTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.avsync.av_quality_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=AvQualityTestSequence + +# Test parameters +PLAYBACK_DURATION_SEC=900 +RECORD_DELAY_SEC=20 +WAIT_FOR_BUFFER_SEC=30 + +SIGNED_IN=True +TEST_CASE_PREFIX=Freezing +VIDEO_SPECIFIERS=720P60_H264_2M_VERTICAL
diff --git a/lab_system/master/config/tests/av_sync/exoplayer_av_sync_720p_60fps.cfg b/lab_system/master/config/tests/av_sync/exoplayer_av_sync_720p_60fps.cfg new file mode 100644 index 0000000..29cba3d --- /dev/null +++ b/lab_system/master/config/tests/av_sync/exoplayer_av_sync_720p_60fps.cfg
@@ -0,0 +1,36 @@ +# Config file for presence test using conducted audio on android devices +# +# Do not modify property names +# Run make reconfig if you change a value +# and buildbot is running +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.avsync.exoplayer_av_sync_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=ExoplayerAVSyncTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.avsync.av_quality_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=AndroidAvQualityTestSequence + +# Specify the av channel based on video and testbed +AUDIO_CHANNEL=0 +VIDEO_CHANNEL=7 + +# Test parameters depending on the video provided above +NOISE_MEASUREMENT_DURATION_SEC=30 +PLAY_DURATION_NO_ACTION_SEC=300 +SEEK_FORWARD_SEC=10 +SYNC_MEASUREMENT_AFTER_ACTION_SEC=32 +ITERATION_PAUSE=10 +ITERATION_SEEK=10 +DURATION_BEFORE_RESUME_SEC=32 + +TEST_CASE_PREFIX=AVSync +VIDEO_SPECIFIERS=720P60_H264_2M,720P60_VP9_2M,720P60_VP8_2M,720P60_H265_2M,720P60_H265_2M_HDR10 +VIDEO_SPECIFIERS_BOREAL=720P60_AV1_2M
diff --git a/lab_system/master/config/tests/av_sync/exoplayer_freezing_720p_60fps.cfg b/lab_system/master/config/tests/av_sync/exoplayer_freezing_720p_60fps.cfg new file mode 100644 index 0000000..989aa91 --- /dev/null +++ b/lab_system/master/config/tests/av_sync/exoplayer_freezing_720p_60fps.cfg
@@ -0,0 +1,32 @@ +# Config file for presence test using conducted audio on android devices +# +# Do not modify property names +# Run make reconfig if you change a value +# and buildbot is running +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.avsync.exoplayer_video_freezing_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=ExoplayerVideoFreezingTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.avsync.av_quality_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=AndroidAvQualityTestSequence + +# Specify the av channel based on video and testbed +AUDIO_CHANNEL=0 +VIDEO_CHANNEL=7 + +# Test parameters +PLAYBACK_DURATION_SEC=900 +RECORD_DELAY_SEC=20 +WAIT_FOR_BUFFER_SEC=0 + +TEST_CASE_PREFIX=Freezing +VIDEO_SPECIFIERS=720P60_H264_2M,720P60_VP9_2M,720P60_VP8_2M,720P60_H265_2M,720P60_H265_2M_HDR10 +VIDEO_SPECIFIERS_BOREAL=720P60_AV1_2M
diff --git a/lab_system/master/config/tests/av_sync/gq_live_view_quality.cfg b/lab_system/master/config/tests/av_sync/gq_live_view_quality.cfg new file mode 100644 index 0000000..45f0953 --- /dev/null +++ b/lab_system/master/config/tests/av_sync/gq_live_view_quality.cfg
@@ -0,0 +1,37 @@ +# Config file for presence test using conducted auido +# +# Do not modify property names +# Run make reconfig if you change a value +# and buildbot is running +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.avsync.av_live_view_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=AVLiveViewTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.avsync.av_live_view_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=AVLiveViewTestSequence + +# The build that needs to be installed on each display type +# The master builds are for local streaming tests +ELAINE_1_56=gs://gtv-eureka/internal/1.56/elaine-user/265669 +NEWMAN_1_56=gs://gtv-eureka/internal/1.56/newman-user/265669 +ELAINE_MASTER=gs://gtv-eureka/internal/master/elaine-user/271523 +NEWMAN_MASTER=gs://gtv-eureka/internal/master/newman-user/271523 + +# Test identifiers for all scenarios +# Each Key should be usnique and starts with 'TEST_SCENARIO_' prefix +# Format:<battery/line>-power_<high/low>-lux_<30/15>-fps_<premium/balanced>-quality_nv-<on/off>_talkback-<on/off>_<local/remote>-streaming +# Example: line-power_high-lux_30-fps_premium-quality_nv-off_talkback-off_remote-streaming +TEST_SCENARIO_1=battery-power_high-lux_30-fps_premium-quality_nv-off_talkback-on_remote-streaming +TEST_SCENARIO_2=battery-power_low-lux_15-fps_premium-quality_nv-off_talkback-on_remote-streaming +TEST_SCENARIO_3=battery-power_high-lux_30-fps_premium-quality_nv-on_talkback-on_remote-streaming +TEST_SCENARIO_4=line-power_high-lux_30-fps_premium-quality_nv-off_talkback-on_remote-streaming +TEST_SCENARIO_5=line-power_low-lux_15-fps_premium-quality_nv-off_talkback-on_remote-streaming +TEST_SCENARIO_6=line-power_high-lux_30-fps_premium-quality_nv-on_talkback-on_remote-streaming
diff --git a/lab_system/master/config/tests/av_sync/legacy_av_sync_1080p_60fps.cfg b/lab_system/master/config/tests/av_sync/legacy_av_sync_1080p_60fps.cfg new file mode 100644 index 0000000..c7dbe00 --- /dev/null +++ b/lab_system/master/config/tests/av_sync/legacy_av_sync_1080p_60fps.cfg
@@ -0,0 +1,36 @@ +# Config file for presence test using conducted auido +# +# Do not modify property names +# Run make reconfig if you change a value +# and buildbot is running +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.avsync.av_sync_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=AVSyncTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.avsync.av_quality_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=AvQualityTestSequence + +# Specify the av channel based on video and testbed +AUDIO_CHANNEL=0 +VIDEO_CHANNEL=1 + +# Test parameters depending on the video provided above +NOISE_MEASUREMENT_DURATION_SEC=10 +PLAY_DURATION_NO_ACTION_SEC=300 +SEEK_FORWARD_SEC=14 +SYNC_MEASUREMENT_AFTER_ACTION_SEC=30 +ITERATION_PAUSE=15 +ITERATION_SEEK=10 +DURATION_BEFORE_RESUME_SEC=30 + +SIGNED_IN=True +TEST_CASE_PREFIX=AVSync +VIDEO_SPECIFIERS=LEGACY_1080P60_AVSYNC
diff --git a/lab_system/master/config/tests/av_sync/legacy_av_sync_1080p_60fps_180phase.cfg b/lab_system/master/config/tests/av_sync/legacy_av_sync_1080p_60fps_180phase.cfg new file mode 100644 index 0000000..c44c6f7 --- /dev/null +++ b/lab_system/master/config/tests/av_sync/legacy_av_sync_1080p_60fps_180phase.cfg
@@ -0,0 +1,36 @@ +# Config file for presence test using conducted auido +# +# Do not modify property names +# Run make reconfig if you change a value +# and buildbot is running +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.avsync.av_sync_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=AVSyncTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.avsync.av_quality_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=AvQualityTestSequence + +# Specify the av channel based on video and testbed +AUDIO_CHANNEL=0 +VIDEO_CHANNEL=1 + +# Test parameters depending on the video provided above +NOISE_MEASUREMENT_DURATION_SEC=10 +PLAY_DURATION_NO_ACTION_SEC=300 +SEEK_FORWARD_SEC=14 +SYNC_MEASUREMENT_AFTER_ACTION_SEC=30 +ITERATION_PAUSE=15 +ITERATION_SEEK=10 +DURATION_BEFORE_RESUME_SEC=30 + +SIGNED_IN=True +TEST_CASE_PREFIX=AVSync +VIDEO_SPECIFIERS=LEGACY_1080P60_AVSYNC_180PHASE
diff --git a/lab_system/master/config/tests/av_sync/legacy_av_sync_720p_30fps.cfg b/lab_system/master/config/tests/av_sync/legacy_av_sync_720p_30fps.cfg new file mode 100644 index 0000000..0d978e1 --- /dev/null +++ b/lab_system/master/config/tests/av_sync/legacy_av_sync_720p_30fps.cfg
@@ -0,0 +1,36 @@ +# Config file for presence test using conducted auido +# +# Do not modify property names +# Run make reconfig if you change a value +# and buildbot is running +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.avsync.av_sync_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=AVSyncTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.avsync.av_quality_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=AvQualityTestSequence + +# Specify the av channel based on video and testbed +AUDIO_CHANNEL=0 +VIDEO_CHANNEL=1 + +# Test parameters depending on the video provided above +NOISE_MEASUREMENT_DURATION_SEC=10 +PLAY_DURATION_NO_ACTION_SEC=300 +SEEK_FORWARD_SEC=14 +SYNC_MEASUREMENT_AFTER_ACTION_SEC=30 +ITERATION_PAUSE=15 +ITERATION_SEEK=10 +DURATION_BEFORE_RESUME_SEC=30 + +SIGNED_IN=True +TEST_CASE_PREFIX=AVSync +VIDEO_SPECIFIERS=LEGACY_720P30_AVSYNC
diff --git a/lab_system/master/config/tests/av_sync/legacy_av_sync_720p_60fps.cfg b/lab_system/master/config/tests/av_sync/legacy_av_sync_720p_60fps.cfg new file mode 100644 index 0000000..b999697 --- /dev/null +++ b/lab_system/master/config/tests/av_sync/legacy_av_sync_720p_60fps.cfg
@@ -0,0 +1,36 @@ +# Config file for presence test using conducted auido +# +# Do not modify property names +# Run make reconfig if you change a value +# and buildbot is running +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.avsync.av_sync_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=AVSyncTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.avsync.av_quality_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=AvQualityTestSequence + +# Specify the av channel based on video and testbed +AUDIO_CHANNEL=0 +VIDEO_CHANNEL=1 + +# Test parameters depending on the video provided above +NOISE_MEASUREMENT_DURATION_SEC=10 +PLAY_DURATION_NO_ACTION_SEC=300 +SEEK_FORWARD_SEC=14 +SYNC_MEASUREMENT_AFTER_ACTION_SEC=30 +ITERATION_PAUSE=15 +ITERATION_SEEK=10 +DURATION_BEFORE_RESUME_SEC=30 + +SIGNED_IN=True +TEST_CASE_PREFIX=AVSync +VIDEO_SPECIFIERS=LEGACY_720P60_AVSYNC
diff --git a/lab_system/master/config/tests/av_sync/legacy_smoothness_720p_60fps.cfg b/lab_system/master/config/tests/av_sync/legacy_smoothness_720p_60fps.cfg new file mode 100644 index 0000000..73e8406 --- /dev/null +++ b/lab_system/master/config/tests/av_sync/legacy_smoothness_720p_60fps.cfg
@@ -0,0 +1,27 @@ +# Config file for presence test using conducted auido +# +# Do not modify property names +# Run make reconfig if you change a value +# and buildbot is running +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.avsync.video_smoothness_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=VideoSmoothnessTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.avsync.av_quality_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=AvQualityTestSequence + +# Test parameters depending on the video provided above +NOISE_MEASUREMENT_DURATION_SEC=0 +PLAY_DURATION_SEC=300 + +SIGNED_IN=True +TEST_CASE_PREFIX=Smoothness +VIDEO_SPECIFIERS=LEGACY_720P60_SMOOTHNESS
diff --git a/lab_system/master/config/tests/av_sync/nq_live_view_quality.cfg b/lab_system/master/config/tests/av_sync/nq_live_view_quality.cfg new file mode 100644 index 0000000..cc1d7d5 --- /dev/null +++ b/lab_system/master/config/tests/av_sync/nq_live_view_quality.cfg
@@ -0,0 +1,37 @@ +# Config file for presence test using conducted auido +# +# Do not modify property names +# Run make reconfig if you change a value +# and buildbot is running +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.avsync.av_live_view_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=AVLiveViewTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.avsync.av_live_view_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=AVLiveViewTestSequence + +# The build that needs to be installed on each display type +# The master builds are for local streaming tests +ELAINE_1_56=gs://gtv-eureka/internal/1.56/elaine-user/265669 +NEWMAN_1_56=gs://gtv-eureka/internal/1.56/newman-user/265669 +ELAINE_MASTER=gs://gtv-eureka/internal/master/elaine-user/271523 +NEWMAN_MASTER=gs://gtv-eureka/internal/master/newman-user/271523 + +# Test identifiers for all scenarios +# Each Key should be usnique and starts with 'TEST_SCENARIO_' prefix +# Format:<battery/line>-power_<high/low>-lux_<30/15>-fps_<premium/balanced>-quality_nv-<on/off>_talkback-<on/off>_<local/remote>-streaming +# Example: line-power_high-lux_30-fps_premium-quality_nv-off_talkback-off_remote-streaming +TEST_SCENARIO_1=battery-power_high-lux_30-fps_premium-quality_nv-off_talkback-off_remote-streaming +TEST_SCENARIO_2=battery-power_low-lux_15-fps_premium-quality_nv-off_talkback-off_remote-streaming +TEST_SCENARIO_3=battery-power_high-lux_30-fps_premium-quality_nv-on_talkback-off_remote-streaming +TEST_SCENARIO_4=line-power_high-lux_30-fps_premium-quality_nv-off_talkback-off_remote-streaming +TEST_SCENARIO_5=line-power_low-lux_15-fps_premium-quality_nv-off_talkback-off_remote-streaming +TEST_SCENARIO_6=line-power_high-lux_30-fps_premium-quality_nv-on_talkback-off_remote-streaming
diff --git a/lab_system/master/config/tests/av_sync/spencer_live_view_quality.cfg b/lab_system/master/config/tests/av_sync/spencer_live_view_quality.cfg new file mode 100644 index 0000000..b74129d --- /dev/null +++ b/lab_system/master/config/tests/av_sync/spencer_live_view_quality.cfg
@@ -0,0 +1,34 @@ +# Config file for presence test using conducted auido +# +# Do not modify property names +# Run make reconfig if you change a value +# and buildbot is running +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.avsync.av_live_view_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=AVLiveViewTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.avsync.av_live_view_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=AVLiveViewTestSequence + +# The build that needs to be installed on each display type +# The master builds are for local streaming tests +ELAINE_1_56=gs://gtv-eureka/internal/1.56/elaine-user/265669 +NEWMAN_1_56=gs://gtv-eureka/internal/1.56/newman-user/265669 +ELAINE_MASTER=gs://gtv-eureka/internal/master/elaine-user/271523 +NEWMAN_MASTER=gs://gtv-eureka/internal/master/newman-user/271523 + +# Test identifiers for all scenarios +# Each Key should be usnique and starts with 'TEST_SCENARIO_' prefix +# Format:<battery/line>-power_<high/low>-lux_<30/15>-fps_<premium/balanced>-quality_nv-<on/off>_talkback-<on/off>_<local/remote>-streaming +# Example: line-power_high-lux_30-fps_premium-quality_nv-off_talkback-off_remote-streaming +TEST_SCENARIO_1=line-power_high-lux_30-fps_premium-quality_nv-off_talkback-off_remote-streaming +TEST_SCENARIO_2=line-power_low-lux_15-fps_premium-quality_nv-off_talkback-off_remote-streaming +TEST_SCENARIO_3=line-power_high-lux_30-fps_premium-quality_nv-on_talkback-off_remote-streaming
diff --git a/lab_system/master/config/tests/av_sync/venus_live_view_quality.cfg b/lab_system/master/config/tests/av_sync/venus_live_view_quality.cfg new file mode 100644 index 0000000..214219d --- /dev/null +++ b/lab_system/master/config/tests/av_sync/venus_live_view_quality.cfg
@@ -0,0 +1,26 @@ +# Config file for live view quality test on Venus. + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.avsync.av_live_view_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=AVLiveViewTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.avsync.av_live_view_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=AVLiveViewTestSequence + +# The build that needs to be installed on each display type +# The master builds are for local streaming tests +ELAINE_1_56=gs://gtv-eureka/internal/1.56.3/elaine-user/308003 +ELAINE_MASTER=gs://gtv-eureka/internal/master/elaine-user/271523 + +# Test identifiers for all scenarios +# Each Key should be usnique and starts with 'TEST_SCENARIO_' prefix +# Format:<battery/line>-power_<high/low>-lux_<30/15>-fps_<premium/balanced>-quality_nv-<on/off>_talkback-<on/off>_<local/remote>-streaming +# Example: line-power_high-lux_30-fps_premium-quality_nv-off_talkback-off_remote-streaming +TEST_SCENARIO_1=line-power_high-lux_30-fps_premium-quality_nv-off_talkback-on_remote-streaming +TEST_SCENARIO_2=line-power_low-lux_15-fps_premium-quality_nv-off_talkback-on_remote-streaming +TEST_SCENARIO_3=line-power_high-lux_30-fps_premium-quality_nv-on_talkback-on_remote-streaming
diff --git a/lab_system/master/config/tests/av_sync/youtube_av_sync_720p_60fps.cfg b/lab_system/master/config/tests/av_sync/youtube_av_sync_720p_60fps.cfg new file mode 100644 index 0000000..a1b9283 --- /dev/null +++ b/lab_system/master/config/tests/av_sync/youtube_av_sync_720p_60fps.cfg
@@ -0,0 +1,35 @@ +# Config file for presence test using conducted audio on android devices +# +# Do not modify property names +# Run make reconfig if you change a value +# and buildbot is running +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.avsync.youtube_av_sync_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=YoutubeAVSyncTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.avsync.av_quality_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=AndroidAvQualityTestSequence + +# Specify the av channel based on video and testbed +AUDIO_CHANNEL=0 +VIDEO_CHANNEL=7 + +# Test parameters depending on the video provided above +NOISE_MEASUREMENT_DURATION_SEC=30 +PLAY_DURATION_NO_ACTION_SEC=300 +SEEK_FORWARD_SEC=10 +SYNC_MEASUREMENT_AFTER_ACTION_SEC=32 +ITERATION_PAUSE=10 +ITERATION_SEEK=10 +DURATION_BEFORE_RESUME_SEC=32 + +TEST_CASE_PREFIX=AVSync +VIDEO_SPECIFIERS=720P60_YOUTUBE_2M
diff --git a/lab_system/master/config/tests/av_sync/youtube_freezing_720p_60fps.cfg b/lab_system/master/config/tests/av_sync/youtube_freezing_720p_60fps.cfg new file mode 100644 index 0000000..1e9e03a --- /dev/null +++ b/lab_system/master/config/tests/av_sync/youtube_freezing_720p_60fps.cfg
@@ -0,0 +1,31 @@ +# Config file for presence test using conducted audio on android devices +# +# Do not modify property names +# Run make reconfig if you change a value +# and buildbot is running +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.avsync.youtube_video_freezing_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=YoutubeVideoFreezingTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.avsync.av_quality_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=AndroidAvQualityTestSequence + +# Specify the av channel based on video and testbed +AUDIO_CHANNEL=0 +VIDEO_CHANNEL=7 + +# Test parameters +PLAYBACK_DURATION_SEC=900 +RECORD_DELAY_SEC=20 +WAIT_FOR_BUFFER_SEC=0 + +TEST_CASE_PREFIX=Freezing +VIDEO_SPECIFIERS=720P60_YOUTUBE_2M
diff --git a/lab_system/master/config/tests/bluetooth_a2dp/bluetooth_a2dp.cfg b/lab_system/master/config/tests/bluetooth_a2dp/bluetooth_a2dp.cfg new file mode 100644 index 0000000..ec6478a --- /dev/null +++ b/lab_system/master/config/tests/bluetooth_a2dp/bluetooth_a2dp.cfg
@@ -0,0 +1,19 @@ +# Config file for Bluetooth A2DP test suite. +# +# Do not modify property names +# Run make reconfig if you change a value +# and buildbot is running +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.bluetooth_a2dp.bluetooth_a2dp_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=BluetoothDiscoveryTestCases,BluetoothApiTestCases,BluetoothStreamingTestCases + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.framework.test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=TestSequence
diff --git a/lab_system/master/config/tests/bluetooth_a2dp/test_defs.json b/lab_system/master/config/tests/bluetooth_a2dp/test_defs.json new file mode 100644 index 0000000..8b71a2f --- /dev/null +++ b/lab_system/master/config/tests/bluetooth_a2dp/test_defs.json
@@ -0,0 +1,74 @@ +[ + { + "group_name": "bluetooth_a2dp", + "slave_name": "bluetooth_a2dp_enclosure", + "test_name": "bluetooth_a2dp", + "identifier": "bluetooth_a2dp_chirp", + "device_type": "chirp_b3", + "device_group": "setup_enclosure_chirp", + "branch": ["master"], + "build_flavor": "user", + "scheduler": "0 6,15,8 * * *", + "step_factories_recipe": "step_factories_recipes/bringup_ethernet_port.json" + }, + { + "group_name": "bluetooth_a2dp", + "slave_name": "bluetooth_a2dp_enclosure", + "test_name": "bluetooth_a2dp", + "identifier": "bluetooth_a2dp_chirp", + "device_type": "chirp_b3", + "device_group": "setup_enclosure_chirp", + "branch": ["next_release"], + "build_flavor": "user", + "scheduler": "0 7,16,17 * * *", + "step_factories_recipe": "step_factories_recipes/bringup_ethernet_port.json" + }, + { + "group_name": "bluetooth_a2dp", + "slave_name": "bluetooth_a2dp_enclosure", + "test_name": "bluetooth_a2dp", + "identifier": "bluetooth_a2dp_joplin", + "device_type": "joplin", + "device_group": "setup_enclosure_joplin", + "branch": ["master"], + "build_flavor": "user", + "scheduler": "0 6,15,8 * * *", + "step_factories_recipe": "step_factories_recipes/bringup_ethernet_port.json" + }, + { + "group_name": "bluetooth_a2dp", + "slave_name": "bluetooth_a2dp_enclosure", + "test_name": "bluetooth_a2dp", + "identifier": "bluetooth_a2dp_joplin", + "device_type": "joplin", + "device_group": "setup_enclosure_joplin", + "branch": ["next_release"], + "build_flavor": "user", + "scheduler": "0 7,16,17 * * *", + "step_factories_recipe": "step_factories_recipes/bringup_ethernet_port.json" + }, + { + "group_name": "bluetooth_a2dp", + "slave_name": "bluetooth_a2dp_enclosure", + "test_name": "bluetooth_a2dp", + "identifier": "bluetooth_a2dp_biggie", + "device_type": "biggie", + "device_group": "setup_enclosure_biggie", + "branch": ["master"], + "build_flavor": "user", + "scheduler": "0 6,15,8 * * *", + "step_factories_recipe": "step_factories_recipes/bringup_ethernet_port.json" + }, + { + "group_name": "bluetooth_a2dp", + "slave_name": "bluetooth_a2dp_enclosure", + "test_name": "bluetooth_a2dp", + "identifier": "bluetooth_a2dp_biggie", + "device_type": "biggie", + "device_group": "setup_enclosure_biggie", + "branch": ["next_release"], + "build_flavor": "user", + "scheduler": "0 7,16,17 * * *", + "step_factories_recipe": "step_factories_recipes/bringup_ethernet_port.json" + } +]
diff --git a/lab_system/master/config/tests/build_upgrade/build_upgrade.cfg b/lab_system/master/config/tests/build_upgrade/build_upgrade.cfg new file mode 100644 index 0000000..743dbea --- /dev/null +++ b/lab_system/master/config/tests/build_upgrade/build_upgrade.cfg
@@ -0,0 +1,15 @@ +# Config file for BuildUpgrade tests. +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.fdr.build_upgrade_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=BuildUpgradeTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.fdr.fdr_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=FdrTestSequence
diff --git a/lab_system/master/config/tests/build_upgrade/test_defs.json b/lab_system/master/config/tests/build_upgrade/test_defs.json new file mode 100644 index 0000000..816baaf --- /dev/null +++ b/lab_system/master/config/tests/build_upgrade/test_defs.json
@@ -0,0 +1,30 @@ +[ + { + "group_name": "build_upgrade", + "slave_name": "build_upgrade", + "test_name": "build_upgrade", + "identifier": "build_upgrade_v3", + "device_type": "earth", + "device_group": "earth_fdr", + "branch": ["master", "release", "on_demand"] + }, + { + "group_name": "build_upgrade", + "slave_name": "build_upgrade", + "test_name": "build_upgrade", + "identifier": "build_upgrade_chirp", + "device_type": "chirp", + "device_group": "chirp", + "branch": ["master", "release"] + }, + { + "group_name": "build_upgrade", + "slave_name": "build_upgrade", + "test_name": "build_upgrade", + "identifier": "build_upgrade_v4", + "device_type": "luther_b2", + "device_group": "luther_eth", + "branch": ["master", "release"], + "hidden": "true" + } +]
diff --git a/lab_system/master/config/tests/cache_test/cache_test.cfg b/lab_system/master/config/tests/cache_test/cache_test.cfg new file mode 100644 index 0000000..3a6bb81 --- /dev/null +++ b/lab_system/master/config/tests/cache_test/cache_test.cfg
@@ -0,0 +1,16 @@ +# Config file for javascript CacheTestCase Suite +# It still requires --disable-web-security flag. +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.cache.cache_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=CacheTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.framework.javascript_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=JavascriptTestSequence
diff --git a/lab_system/master/config/tests/caf/caf_staging.cfg b/lab_system/master/config/tests/caf/caf_staging.cfg new file mode 100644 index 0000000..a821744 --- /dev/null +++ b/lab_system/master/config/tests/caf/caf_staging.cfg
@@ -0,0 +1,17 @@ +# Config file cafe2e tests using staging version of caf. +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.caf.caf_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=CafBasicStagingTestCase,CafEventsStagingTestCase,CafFastplayStagingTestCase,CafInterceptorsStagingTestCase,CafLoadStagingTestCase,CafLoadWithInitialTimeStagingTestCase,CafPlayToEndStagingTestCase,CafQueuingStagingTestCase,CafSeekStagingTestCase,CafStitchingPlayerStagingTestCase,CafTracksStagingTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.framework.javascript_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=JavascriptTestSequence + +
diff --git a/lab_system/master/config/tests/canvas_benchmarks/canvas_benchmarks.cfg b/lab_system/master/config/tests/canvas_benchmarks/canvas_benchmarks.cfg new file mode 100644 index 0000000..fd7e6de --- /dev/null +++ b/lab_system/master/config/tests/canvas_benchmarks/canvas_benchmarks.cfg
@@ -0,0 +1,17 @@ +# Config file for the canvas render performance tests. +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.canvas_benchmarks.canvas_render_performance_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=CanvasRenderPerformanceTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.framework.test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=TestSequence + +
diff --git a/lab_system/master/config/tests/canvas_mark/canvas_mark.cfg b/lab_system/master/config/tests/canvas_mark/canvas_mark.cfg new file mode 100644 index 0000000..37e5c2d --- /dev/null +++ b/lab_system/master/config/tests/canvas_mark/canvas_mark.cfg
@@ -0,0 +1,17 @@ +# Config file for Canvas Mark benchmark tests. +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.canvas_mark.canvas_mark_benchmark_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=CanvasMarkBenchmarkTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.canvas_mark.canvas_mark_benchmark_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=CanvasMarkBenchmarkTestSequence + +
diff --git a/lab_system/master/config/tests/canvas_mark/test_defs.json b/lab_system/master/config/tests/canvas_mark/test_defs.json new file mode 100644 index 0000000..8a27f88 --- /dev/null +++ b/lab_system/master/config/tests/canvas_mark/test_defs.json
@@ -0,0 +1,105 @@ +[ + { + "group_name": "canvas_mark", + "slave_name": "octane_canvas_mark", + "test_name": "canvas_mark", + "identifier": "canvas_mark", + "device_type": "eureka", + "device_group": "eureka_debug", + "branch": ["master", "release", "1_22"], + "build_flavor": "user" + }, + { + "group_name": "canvas_mark", + "slave_name": "octane_canvas_mark", + "test_name": "canvas_mark", + "identifier": "canvas_mark_v2", + "device_type": "lexx", + "device_group": "lexx_eth", + "branch": ["master", "release", "1_22"], + "build_flavor": "user" + }, + { + "group_name": "canvas_mark", + "slave_name": "octane_canvas_mark", + "test_name": "canvas_mark", + "identifier": "canvas_mark_v3", + "device_type": "earth", + "device_group": "earth_eth", + "branch": ["master", "release", "1_22"], + "build_flavor": "user" + }, + { + "group_name": "canvas_mark", + "slave_name": "octane_canvas_mark", + "test_name": "canvas_mark", + "identifier": "canvas_mark_v4", + "device_type": "luther_b2", + "device_group": "luther_eth", + "branch": ["master", "release", "1_22"], + "build_flavor": "user" + }, + { + "group_name": "canvas_mark", + "slave_name": "eurtest_canvas_mark", + "test_name": "canvas_mark", + "identifier": "canvas_mark_bubbletea", + "device_type": "bubbletea", + "device_group": "bubbletea", + "branch": ["cast_tv_mstar_master", "cast_tv_mstar_release", "cast_tv_mstar_next_release"] + }, + { + "group_name": "canvas_mark", + "slave_name": "eurtest_canvas_mark", + "test_name": "canvas_mark", + "identifier": "canvas_mark_entourage", + "device_type": "dragonfly", + "device_group": "entourage", + "branch": ["cast_tv_dragonfly_master", "cast_tv_dragonfly_release", "cast_tv_dragonfly_next_release"] + }, + { + "group_name": "canvas_mark", + "slave_name": "eurtest_canvas_mark", + "test_name": "canvas_mark", + "identifier": "canvas_mark_guabao", + "device_type": "guabao", + "device_group": "entourage", + "branch": ["cast_tv_mstar_master", "cast_tv_mstar_release", "cast_tv_mstar_next_release"] + }, + { + "group_name": "canvas_mark", + "slave_name": "eurtest_canvas_mark", + "test_name": "canvas_mark", + "identifier": "canvas_mark_mars_us", + "device_type": "Mars_US", + "device_group": "entourage", + "branch": ["cast_tv_mediatek_master", "cast_tv_mediatek_release", "cast_tv_mediatek_next_release"] + }, + { + "group_name": "canvas_mark", + "slave_name": "eurtest_canvas_mark", + "test_name": "canvas_mark", + "identifier": "canvas_mark_N00007", + "device_type": "N00007", + "device_group": "entourage", + "branch": ["cast_tv_novatek_master", "cast_tv_novatek_release", "cast_tv_novatek_next_release"] + }, + { + "group_name": "canvas_mark", + "slave_name": "eurtest_canvas_mark", + "test_name": "canvas_mark", + "identifier": "canvas_mark_suncake", + "device_type": "suncake", + "device_group": "entourage", + "branch": ["cast_tv_mstar_master", "cast_tv_mstar_release", "cast_tv_mstar_next_release"] + }, + { + "group_name": "canvas_mark", + "slave_name": "eurtest_canvas_mark", + "test_name": "canvas_mark", + "identifier": "canvas_mark_taroball", + "device_type": "taroball", + "device_group": "entourage", + "branch": ["cast_tv_mstar_master", "cast_tv_mstar_release", "cast_tv_mstar_next_release"] + } +]
diff --git a/lab_system/master/config/tests/cast/atv_receiver.cfg b/lab_system/master/config/tests/cast/atv_receiver.cfg new file mode 100644 index 0000000..93da18e --- /dev/null +++ b/lab_system/master/config/tests/cast/atv_receiver.cfg
@@ -0,0 +1,40 @@ +# Config file for the Cast receiver tests running on Android TV +# +# Do not modify property names +# Run make reconfig if you change a value +# and buildbot is running +# +# PROPERTIES + +# Remote Test Setup +USER_NAME=gtvchrome +REMOTE_TEST_ROOT=/home/gtvchrome/repositories/HEAD +REMOTE_RESULT_DIR=/home/gtvchrome/results + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.cast.receiver.atv_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=CastReceiverComplianceTestCase,CastReceiverMirroringProtocolTestCase,CastReceiverVolumeControlTestCase,CastReceiverMultipleSendersTestCase,CastReceiverMediaProtocolMP4TestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.framework.android_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=AndroidTestSequence + +# Receiver app ids: +CAST_V2_DEBUG_APP_ID=C566BECD +CAST_V2_PLAYER_APP_ID=BE6E4473 +CHROME_MIRRORING_APP_ID=0F5096E8 + +# Test specific configuration values: +MP4_MEDIA_URL=http://commondatastorage.googleapis.com/android-tv/Sample%20videos/Zeitgeist/Zeitgeist%202010_%20Year%20in%20Review.mp4 +MP4_MEDIA_MIME_TYPE=video/mp4 +DASH_MEDIA_URL=https://home-media-server.sandbox.google.com/static/receiver/dash/sample-dash-list.mpd +DASH_MEDIA_MIME_TYPE=application/dash+xml +HLS_MEDIA_URL=https://home-media-server.sandbox.google.com/static/receiver/hls/bbb/bbb_hls.m3u8 +HLS_MEDIA_MIME_TYPE=application/x-mpegurl +SMOOTH_STREAMING_MEDIA_URL=https://home-media-server.sandbox.google.com/static/receiver/smooth/BBB_H264_AACL/big_buck_bunny_1080p_stereo.ism/manifest +SMOOTH_STREAMING_MEDIA_MIME_TYPE=application/vnd.ms-sstr+xml +MEDIA_LOAD_TIMEOUT_SECS=30
diff --git a/lab_system/master/config/tests/cast/atv_receiver_c2n_media_launch.cfg b/lab_system/master/config/tests/cast/atv_receiver_c2n_media_launch.cfg new file mode 100644 index 0000000..1daaa42 --- /dev/null +++ b/lab_system/master/config/tests/cast/atv_receiver_c2n_media_launch.cfg
@@ -0,0 +1,29 @@ +# Config file for Cast Connect media launch test on android devices +# +# Do not modify property names +# Run make reconfig if you change a value +# and buildbot is running +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.cast.receiver.cast_connect_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=CastConnectMediaControlTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.framework.android_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=AndroidTestSequence + +# Path and type of video for media launch test +VIDEO_PATH=http://commondatastorage.googleapis.com/android-tv/Sample%20videos/April%20Fool%27s%202013/Introducing%20Google%20Nose.mp4 +VIDEO_TYPE=video/mp4 +VIDEO_5S_1920_1080=gs://home_media_server/media/static/samples/cast_connect_test_data/video_play_5s_1920x1080.png +VIDEO_5S_720_576=gs://home_media_server/media/static/samples/cast_connect_test_data/video_play_5s_720x576.png + +# Gs url path of test demo app installed on android devices +C2N_TEST_DEMO_APP_APK_URL=gs://android-build-artifacts/c2n-demo.apk +
diff --git a/lab_system/master/config/tests/cast/atv_receiver_compliance.cfg b/lab_system/master/config/tests/cast/atv_receiver_compliance.cfg new file mode 100644 index 0000000..b4d86a1 --- /dev/null +++ b/lab_system/master/config/tests/cast/atv_receiver_compliance.cfg
@@ -0,0 +1,29 @@ +# Config file for the Cast receiver compliance tests running on Android TV +# +# Do not modify property names +# Run make reconfig if you change a value +# and buildbot is running +# +# PROPERTIES + +# Remote Test Setup +USER_NAME=gtvchrome +REMOTE_TEST_ROOT=/home/gtvchrome/repositories/HEAD +REMOTE_RESULT_DIR=/home/gtvchrome/results + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.cast.receiver.atv_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=CastReceiverComplianceTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.framework.android_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=AndroidTestSequence + +# Receiver app ids: +CAST_V2_DEBUG_APP_ID=C566BECD +CAST_V2_PLAYER_APP_ID=BE6E4473 +CHROME_MIRRORING_APP_ID=0F5096E8
diff --git a/lab_system/master/config/tests/cast/atv_receiver_mirroring.cfg b/lab_system/master/config/tests/cast/atv_receiver_mirroring.cfg new file mode 100644 index 0000000..628d17b --- /dev/null +++ b/lab_system/master/config/tests/cast/atv_receiver_mirroring.cfg
@@ -0,0 +1,32 @@ +# Config file for the Cast receiver mirroring tests running on Android TV +# +# Do not modify property names +# Run make reconfig if you change a value +# and buildbot is running +# +# PROPERTIES + +# Remote Test Setup +USER_NAME=gtvchrome +REMOTE_TEST_ROOT=/home/gtvchrome/repositories/HEAD +REMOTE_RESULT_DIR=/home/gtvchrome/results + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.cast.receiver.atv_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=CastReceiverMirroringProtocolTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.framework.android_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=AndroidTestSequence + +# Receiver app ids: +CAST_V2_DEBUG_APP_ID=C566BECD +CAST_V2_PLAYER_APP_ID=BE6E4473 +CHROME_MIRRORING_APP_ID=0F5096E8 + +# Test specific configuration values: +MEDIA_LOAD_TIMEOUT_SECS=30
diff --git a/lab_system/master/config/tests/cast/atv_receiver_mp4_protocol.cfg b/lab_system/master/config/tests/cast/atv_receiver_mp4_protocol.cfg new file mode 100644 index 0000000..2373259 --- /dev/null +++ b/lab_system/master/config/tests/cast/atv_receiver_mp4_protocol.cfg
@@ -0,0 +1,34 @@ +# Config file for the Cast receiver media protocol MP4 tests running on Android TV +# +# Do not modify property names +# Run make reconfig if you change a value +# and buildbot is running +# +# PROPERTIES + +# Remote Test Setup +USER_NAME=gtvchrome +REMOTE_TEST_ROOT=/home/gtvchrome/repositories/HEAD +REMOTE_RESULT_DIR=/home/gtvchrome/results + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.cast.receiver.atv_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=CastReceiverMediaProtocolMP4TestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.framework.android_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=AndroidTestSequence + +# Receiver app ids: +CAST_V2_DEBUG_APP_ID=C566BECD +CAST_V2_PLAYER_APP_ID=BE6E4473 +CHROME_MIRRORING_APP_ID=0F5096E8 + +# Test specific configuration values: +MP4_MEDIA_URL=http://commondatastorage.googleapis.com/android-tv/Sample%20videos/Zeitgeist/Zeitgeist%202010_%20Year%20in%20Review.mp4 +MP4_MEDIA_MIME_TYPE=video/mp4 +MEDIA_LOAD_TIMEOUT_SECS=30
diff --git a/lab_system/master/config/tests/cast/atv_receiver_multi_senders.cfg b/lab_system/master/config/tests/cast/atv_receiver_multi_senders.cfg new file mode 100644 index 0000000..fb14bca --- /dev/null +++ b/lab_system/master/config/tests/cast/atv_receiver_multi_senders.cfg
@@ -0,0 +1,29 @@ +# Config file for the Cast receiver multi-senders tests running on Android TV +# +# Do not modify property names +# Run make reconfig if you change a value +# and buildbot is running +# +# PROPERTIES + +# Remote Test Setup +USER_NAME=gtvchrome +REMOTE_TEST_ROOT=/home/gtvchrome/repositories/HEAD +REMOTE_RESULT_DIR=/home/gtvchrome/results + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.cast.receiver.atv_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=CastReceiverMultipleSendersTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.framework.android_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=AndroidTestSequence + +# Receiver app ids: +CAST_V2_DEBUG_APP_ID=C566BECD +CAST_V2_PLAYER_APP_ID=BE6E4473 +CHROME_MIRRORING_APP_ID=0F5096E8
diff --git a/lab_system/master/config/tests/cast/atv_receiver_volume.cfg b/lab_system/master/config/tests/cast/atv_receiver_volume.cfg new file mode 100644 index 0000000..756e00f --- /dev/null +++ b/lab_system/master/config/tests/cast/atv_receiver_volume.cfg
@@ -0,0 +1,34 @@ +# Config file for the Cast receiver volume control tests running on Android TV +# +# Do not modify property names +# Run make reconfig if you change a value +# and buildbot is running +# +# PROPERTIES + +# Remote Test Setup +USER_NAME=gtvchrome +REMOTE_TEST_ROOT=/home/gtvchrome/repositories/HEAD +REMOTE_RESULT_DIR=/home/gtvchrome/results + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.cast.receiver.atv_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=CastReceiverVolumeControlTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.framework.android_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=AndroidTestSequence + +# Receiver app ids: +CAST_V2_DEBUG_APP_ID=C566BECD +CAST_V2_PLAYER_APP_ID=BE6E4473 +CHROME_MIRRORING_APP_ID=0F5096E8 + +# Test specific configuration values: +MP4_MEDIA_URL=http://commondatastorage.googleapis.com/android-tv/Sample%20videos/Zeitgeist/Zeitgeist%202010_%20Year%20in%20Review.mp4 +MP4_MEDIA_MIME_TYPE=video/mp4 +MEDIA_LOAD_TIMEOUT_SECS=30
diff --git a/lab_system/master/config/tests/cast/discovery.cfg b/lab_system/master/config/tests/cast/discovery.cfg new file mode 100644 index 0000000..703c5c4 --- /dev/null +++ b/lab_system/master/config/tests/cast/discovery.cfg
@@ -0,0 +1,69 @@ +# Configuration values for the Cast V2 mDNS test. +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.cast.discovery.receiver_discovery_mdns_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=ReceiverDiscoveryMdnsTestCase + +# Name of the device type to host the server +SERVER_DEVICE_TYPE=ubuntu-x86 + +# Name of the device group to host the server +SERVER_DEVICE_GROUP=ubuntu + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.framework.test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=TestSequence + +# These properties are required by CopyRepositoriesStepFactory step. +# The properties should have had REMOTE_ prefix because the provided info +# is for remote machine. Bug id 17896008. +# TODO(khai): remove this block when the bug is fixed. +SELF_IP=100.107.131.248 +USER_NAME=cctestdriver +HOME_DIR=/home/cctestdriver +ROOT_REPO=repository/eureka + +# IP address of the test driver +REMOTE_IP=100.107.131.248 + +# User name on the test driver +REMOTE_USER_NAME=cctestdriver + +# Home directory of the user on the test driver +REMOTE_HOME_DIR=/home/cctestdriver + +# Repository root on the test driver +REMOTE_REPO_ROOT=repository/eureka + +# Directory for log files on the test driver +REMOTE_LOG_DIR=/tmp/logs + +# Temporary directory on the test driver +REMOTE_TMP_DIR=/tmp/temp + +# Test driver needs to know where to upload the execution results to. This is +# the path test driver should use to point to correct db. +REMOTE_SERVER_DB_CONFIG_PATH=/home/cctestdriver/repository/eureka/continuous-tests/db/db.config + +# Information of the test driver network interfaces. This must be in JSON +# format {"ip_address_0": "iface_a", "ip_address_1": "iface_b", ...}. +# Note: +# 1) Keys and values must be strings using double quotes (") instead of single +# quotes because JSON parser doesn't understand them. +# 2) Make sure there are no duplicate keys (i.e., same IP addresses) in the +# dictionary. The config file reader uses JSON parser for this property. +# If there are duplicate keys, the latter will override the previous ones. +# For example, {'127.0.0.1': 'localhost', '127.0.0.1': 'myhostname'} will +# result in {'127.0.0.1': 'myhostname'}. +REMOTE_IFACES={"192.168.0.2": "eth2"} + +# Device under test, prefix must match the device_type in test_def.json +# For example, if device_type in test_def.json is "lexx' then the device +# IP is from LEXX_DEVICE_IP. +LEXX_DEVICE_IP=192.168.0.100
diff --git a/lab_system/master/config/tests/cast/discovery/test_defs.json b/lab_system/master/config/tests/cast/discovery/test_defs.json new file mode 100644 index 0000000..ce6b9f9 --- /dev/null +++ b/lab_system/master/config/tests/cast/discovery/test_defs.json
@@ -0,0 +1,55 @@ +[ + { + "branch": [ + "master", + "release" + ], + "device_group": "lexx_eth", + "device_type": "lexx", + "group_name": "cast", + "hidden": "true", + "identifier": "discovery", + "slave_name": "discovery", + "step_factories": [ + { + "step_description": "Allocates devices for the testrun", + "step_factories": [ + { + "class_name": "AllocateTestDriverAndDutStepFactory", + "module_path": "lab_system.master.steps.factory.device.cloud_allocator" + } + ], + "step_identifier": "device_allocation" + }, + { + "step_description": "Copying build to test slave and installing on device", + "step_factories": [ + { + "class_name": "CopyRepositoriesStepFactory", + "module_path": "lab_system.master.steps.factory.build.copy_test_repo" + }, + { + "class_name": "BuildFetcherStepFactory", + "module_path": "lab_system.master.steps.factory.build.fetcher" + }, + { + "class_name": "TestDriverBuildInstallerStepFactory", + "module_path": "lab_system.master.steps.factory.build.installer_eurlab" + } + ], + "step_identifier": "build_handling" + }, + { + "step_description": "Executes test_runner on hard-coded remote workstation.", + "step_factories": [ + { + "class_name": "ReceiverDiscoveryRemoteRunner", + "module_path": "lab_system.master.steps.factory.run.receiver_discovery_remote_runner" + } + ], + "step_identifier": "test_running" + } + ], + "test_name": "discovery" + } +]
diff --git a/lab_system/master/config/tests/cast/fuchsia_receiver.cfg b/lab_system/master/config/tests/cast/fuchsia_receiver.cfg new file mode 100644 index 0000000..4ae4f65 --- /dev/null +++ b/lab_system/master/config/tests/cast/fuchsia_receiver.cfg
@@ -0,0 +1,44 @@ +# Config file for the Cast receiver tests on fuchsia devices +# +# Do not modify property names +# Run make reconfig if you change a value +# and buildbot is running +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.cast.receiver.fuchsia_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=CastReceiverComplianceTestCase,CastReceiverMultipleSendersTestCase,CastReceiverMirroringProtocolTestCase,CastReceiverVolumeControlTestCase,CastReceiverStressTestCase,CastReceiverMediaProtocolMP4TestCase,CastReceiverMediaProtocolDASHTestCase,CastReceiverMediaProtocolHLSTestCase,CastReceiverMediaProtocolSmoothStreamingTestCase,CastReceiverBenchmarkTestCase,CastReceiverQueueTestCase,CastReceiverCapabilityTestCase + +# BUG(b/171057532): OOBE required to bypass kronk for cast tests. +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.framework.fuchsia_oobe_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=FuchsiaOobeTestSequence + +# Receiver app ids: +CAST_V2_DEBUG_APP_ID=C566BECD +CAST_V2_PLAYER_APP_ID=BE6E4473 +CHROME_MIRRORING_APP_ID=0F5096E8 + +# Test specific configuration values: +MP4_MEDIA_URL=https://home-media-server.sandbox.google.com/static/receiver/mp4/bbb_1080p_30fps_x264_high_41_mp3.mp4 +MP4_MEDIA_MIME_TYPE=video/mp4 +DASH_MEDIA_URL=https://home-media-server.sandbox.google.com/static/receiver/dash/sample-dash-list.mpd +DASH_MEDIA_MIME_TYPE=application/dash+xml +HLS_MEDIA_URL=https://home-media-server.sandbox.google.com/static/receiver/hls/bbb/bbb_hls.m3u8 +HLS_MEDIA_MIME_TYPE=application/x-mpegurl +SMOOTH_STREAMING_MEDIA_URL=https://home-media-server.sandbox.google.com/static/receiver/smooth/BBB_H264_AACL/big_buck_bunny_1080p_stereo.ism/manifest +SMOOTH_STREAMING_MEDIA_MIME_TYPE=application/vnd.ms-sstr+xml +MEDIA_LOAD_TIMEOUT_SECS=30 + +# This config is used to determine if cast operations should be allowed even if +# device is not signed-in using a gaia account. +ENABLE_CAST_WITHOUT_SIGN_IN=True + +# Whether or not the list of test classes should be filtered. This is to be able to pass +# the extraction_path modifier. +SHOULD_NOT_FILTER=True
diff --git a/lab_system/master/config/tests/cast/mdns.cfg b/lab_system/master/config/tests/cast/mdns.cfg new file mode 100644 index 0000000..dd4a557 --- /dev/null +++ b/lab_system/master/config/tests/cast/mdns.cfg
@@ -0,0 +1,34 @@ +# Configuration values for the Cast V2 mDNS test. + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.cast.mdns.mdns_remote_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=CastMdnsRemoteTestCase + +# Name of the device type to host the server +SERVER_DEVICE_TYPE=ubuntu-x86 + +# Name of the device group to host the server +SERVER_DEVICE_GROUP=DEFAULT + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.framework.test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=TestSequence + +# must be in-sync with +# continuous-test/lab_system/master/config/groups/cast_mdns.cfg +REMOTE_SERVER_IP=172.17.23.200 +REMOTE_SERVER_USERNAME=gtvchrome + +# path that remote server should use to point to db.config +REMOTE_SERVER_DB_CONFIG_PATH=/home/gtvchrome/repository/eureka/continuous-tests/db/db.config + +# PROPERTIES +SELF_IP=172.17.23.200 +HOME_DIR=/home/gtvchrome +USER_NAME=gtvchrome +REPO_ROOT=repository/eureka +
diff --git a/lab_system/master/config/tests/cast/mdns/test_defs.json b/lab_system/master/config/tests/cast/mdns/test_defs.json new file mode 100644 index 0000000..ab93a5e --- /dev/null +++ b/lab_system/master/config/tests/cast/mdns/test_defs.json
@@ -0,0 +1,42 @@ +[ + { + "group_name": "cast", + "slave_name": "cast_mdns", + "test_name": "mdns", + "identifier": "cast_mdns", + "device_type": "eureka", + "device_group": "eureka_debug_23", + "hidden": "true", + "branch": ["master", "release"], + "step_factories": [ + { + "step_description": "Copying Build to test slave and installing on device", + "step_identifier": "build_handling", + "step_factories": [ + { + "module_path": "lab_system.master.steps.factory.build.copy_test_repo", + "class_name": "CopyRepositoriesStepFactory" + }, + { + "module_path": "lab_system.master.steps.factory.build.fetcher", + "class_name": "BuildFetcherStepFactory" + }, + { + "module_path": "lab_system.master.steps.factory.build.installer_eurlab", + "class_name": "BuildInstallerStepFactory" + } + ] + }, + { + "step_description": "Executes test_runner on hard-coded remote workstation.", + "step_identifier": "test_running", + "step_factories": [ + { + "module_path": "lab_system.master.steps.factory.run.cast_mdns_remote_runner", + "class_name": "CastMdnsRemoteRunnerHack" + } + ] + } + ] + } +]
diff --git a/lab_system/master/config/tests/cast/movies.cfg b/lab_system/master/config/tests/cast/movies.cfg new file mode 100644 index 0000000..15677ce --- /dev/null +++ b/lab_system/master/config/tests/cast/movies.cfg
@@ -0,0 +1,28 @@ +# Config file for the Google Play Movies cast tests +# +# Do not modify property names +# Run make reconfig if you change a value +# and buildbot is running +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.cast.apps.movies.play_movies_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=PlayMoviesTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.framework.test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=TestSequence + +# Receiver app ids: +CAST_V2_DEBUG_APP_ID=C566BECD +CAST_V2_PLAYER_APP_ID=BE6E4473 + +# oauth credential file location. The default test account. +OAUTH_CREDENTIAL_FILE=~/.config/google-avi/default.oauth2.dat +# oauth credential file location. The test account for Multi-player testing. +OAUTH_CREDENTIAL_FILE_SECOND=~/.config/google-avi/multi_player.oauth2.dat
diff --git a/lab_system/master/config/tests/cast/movies/test_defs.json b/lab_system/master/config/tests/cast/movies/test_defs.json new file mode 100644 index 0000000..e59d0ee --- /dev/null +++ b/lab_system/master/config/tests/cast/movies/test_defs.json
@@ -0,0 +1,22 @@ +[ + { + "group_name": "cast", + "slave_name": "play_movies", + "test_name": "movies", + "identifier": "play_movies", + "device_type": "eureka", + "device_group": "play_movie_app_test", + "hidden": "true", + "branch": ["master", "release"] + }, + { + "group_name": "cast", + "slave_name": "play_movies_v2", + "test_name": "movies", + "identifier": "play_movies_v2", + "device_type": "lexx", + "device_group": "play_movie_app_test", + "hidden": "true", + "branch": ["master", "release"] + } +]
diff --git a/lab_system/master/config/tests/cast/opencast.cfg b/lab_system/master/config/tests/cast/opencast.cfg new file mode 100644 index 0000000..93bb9d0 --- /dev/null +++ b/lab_system/master/config/tests/cast/opencast.cfg
@@ -0,0 +1,32 @@ +# Config file for the Opencast receiver tests +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.cast.receiver.opencast_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=OpencastReceiverComplianceTestCase,OpencastMultipleSendersTestCase,OpencastReceiverBenchmarkTestCase,OpencastReceiverMediaProtocolTestCase,OpencastReceiverStressTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.cast.receiver.opencast_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=OpencastTestSequence + +# Receiver app ids: +CAST_V2_DEBUG_APP_ID=C566BECD +CAST_V2_PLAYER_APP_ID=BE6E4473 + +# Test specific configuration values: +MP4_MEDIA_URL=https://home-media-server.sandbox.google.com/static/media/car-1920x1080.mp4 +MP4_MEDIA_MIME_TYPE=video/mp4 +DASH_MEDIA_URL=https://home-media-server.sandbox.google.com/static/tests/js_mse_eme/media/car-20120827-manifest.mpd +DASH_MEDIA_MIME_TYPE=application/dash+xml +HLS_MEDIA_URL=https://home-media-server.sandbox.google.com/static/dumps/media/hls/unicornmedia/demo.umedia.com/cast/testfiles/preroll_midroll60s_postroll.zip/manifest.m3u8 +HLS_MEDIA_MIME_TYPE=application/x-mpegurl +SMOOTH_STREAMING_MEDIA_URL=https://home-media-server.sandbox.google.com/static/receiver/smooth/BBB_H264_AACL/big_buck_bunny_1080p_stereo.ism/manifest +SMOOTH_STREAMING_MEDIA_MIME_TYPE=application/vnd.ms-sstr+xml +MEDIA_LOAD_TIMEOUT_SECS=30 + +
diff --git a/lab_system/master/config/tests/cast/opencast/test_defs.json b/lab_system/master/config/tests/cast/opencast/test_defs.json new file mode 100644 index 0000000..aa72851 --- /dev/null +++ b/lab_system/master/config/tests/cast/opencast/test_defs.json
@@ -0,0 +1,57 @@ +[ + { + "group_name": "cast", + "slave_name": "eurtest_opencast", + "test_name": "opencast", + "identifier": "opencast_receiver", + "device_type": "eureka", + "device_group": "hdmi_plugged_with_cec_100", + "branch": ["master", "release"] + }, + { + "group_name": "cast", + "slave_name": "eurtest_opencast", + "test_name": "opencast", + "identifier": "opencast_receiver_v2", + "device_type": "lexx", + "device_group": "hdmi_plugged_with_cec_100", + "branch": ["master", "release"] + }, + { + "group_name": "cast", + "slave_name": "eurtest_opencast", + "test_name": "opencast", + "identifier": "opencast_receiver_v3", + "device_type": "earth", + "device_group": "hdmi_plugged_with_cec_100", + "branch": ["master", "release"] + }, + { + "group_name": "cast", + "slave_name": "eurtest_opencast", + "test_name": "opencast_c4a", + "identifier": "opencast_receiver_hendrix", + "device_type": "hendrix", + "device_group": "hendrix_eth", + "branch": ["master", "release"] + }, + { + "group_name": "cast", + "slave_name": "eurtest_opencast", + "test_name": "opencast", + "identifier": "opencast_receiver_v4", + "device_type": "luther_b2", + "device_group": "luther_eth", + "branch": ["master", "release"] + }, + { + "group_name": "cast", + "slave_name": "eurtest_opencast", + "test_name": "opencast_c4a", + "identifier": "opencast_receiver_chirp", + "device_type": "chirp", + "device_group": "chirp", + "build_flavor": "user", + "branch": ["master", "release"] + } +]
diff --git a/lab_system/master/config/tests/cast/opencast_c4a.cfg b/lab_system/master/config/tests/cast/opencast_c4a.cfg new file mode 100644 index 0000000..922515f --- /dev/null +++ b/lab_system/master/config/tests/cast/opencast_c4a.cfg
@@ -0,0 +1,41 @@ +# Config file for the Opencast receiver tests +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.cast.receiver.opencast_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=OpencastReceiverComplianceTestCase,OpencastMultipleSendersTestCase,OpencastReceiverBenchmarkTestCase,OpencastReceiverMediaProtocolTestCase,OpencastReceiverStressTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.cast.receiver.opencast_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=OpencastTestSequence + +# Receiver app ids: +CAST_V2_DEBUG_APP_ID=C566BECD +CAST_V2_PLAYER_APP_ID=BE6E4473 + +# Test specific configuration values: +MP4_MEDIA_URL=https://storage.googleapis.com/cast_media/format_tests/audio/stereo_guitar.mp3 +MP4_MEDIA_MIME_TYPE=audio/mp3 + +DASH_MEDIA_URL=https://home-media-server.sandbox.google.com/static/formats/audio/stereo_guitar.mpd +DASH_MEDIA_MIME_TYPE=application/dash+xml + +HLS_MEDIA_URL=https://home-media-server.sandbox.google.com/static/formats/audio/hls_aac_he/stereo_guitar.m3u8 +HLS_MEDIA_MIME_TYPE=application/x-mpegurl + +SMOOTH_STREAMING_MEDIA_URL=https://home-media-server.sandbox.google.com/static/formats/audio/stereo_guitar.ism/Manifest +SMOOTH_STREAMING_MEDIA_MIME_TYPE=application/vnd.ms-sstr+xml + +MEDIA_LOAD_TIMEOUT_SECS=30 + +# Flag to skip tests that require a display and can't be run in C4A devices. +NO_DISPLAY=1 + +# This config is used to determine if cast operations should be allowed even if +# device is not signed-in using a gaia account. +ENABLE_CAST_WITHOUT_SIGN_IN=True
diff --git a/lab_system/master/config/tests/cast/receiver.cfg b/lab_system/master/config/tests/cast/receiver.cfg new file mode 100644 index 0000000..7caf323 --- /dev/null +++ b/lab_system/master/config/tests/cast/receiver.cfg
@@ -0,0 +1,41 @@ +# Config file for the Cast receiver tests +# +# Do not modify property names +# Run make reconfig if you change a value +# and buildbot is running +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.cast.receiver.compliance_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=CastReceiverComplianceTestCase,CastReceiverMultipleSendersTestCase,CastReceiverMirroringProtocolTestCase,CastReceiverVolumeControlTestCase,CastReceiverStressTestCase,CastReceiverMediaProtocolMP4TestCase,CastReceiverMediaProtocolDASHTestCase,CastReceiverMediaProtocolHLSTestCase,CastReceiverMediaProtocolSmoothStreamingTestCase,CastReceiverBenchmarkTestCase,CastReceiverQueueTestCase,CastReceiverCapabilityTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.framework.test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=TestSequence + +# Receiver app ids: +CAST_V2_DEBUG_APP_ID=C566BECD +CAST_V2_PLAYER_APP_ID=BE6E4473 +CHROME_MIRRORING_APP_ID=0F5096E8 + +# Test specific configuration values: +MP4_MEDIA_URL=https://home-media-server.sandbox.google.com/static/receiver/mp4/bbb_1080p_30fps_x264_high_41_mp3.mp4 +MP4_MEDIA_MIME_TYPE=video/mp4 +DASH_MEDIA_URL=https://home-media-server.sandbox.google.com/static/receiver/dash/sample-dash-list.mpd +DASH_MEDIA_MIME_TYPE=application/dash+xml +HLS_MEDIA_URL=https://home-media-server.sandbox.google.com/static/receiver/hls/bbb/bbb_hls.m3u8 +HLS_MEDIA_MIME_TYPE=application/x-mpegurl +SMOOTH_STREAMING_MEDIA_URL=https://home-media-server.sandbox.google.com/static/receiver/smooth/BBB_H264_AACL/big_buck_bunny_1080p_stereo.ism/manifest +SMOOTH_STREAMING_MEDIA_MIME_TYPE=application/vnd.ms-sstr+xml +MEDIA_LOAD_TIMEOUT_SECS=30 + +# This config is used to determine if cast operations should be allowed even if +# device is not signed-in using a gaia account. +ENABLE_CAST_WITHOUT_SIGN_IN=True + +
diff --git a/lab_system/master/config/tests/cast/receiver/test_defs.json b/lab_system/master/config/tests/cast/receiver/test_defs.json new file mode 100644 index 0000000..95f330c --- /dev/null +++ b/lab_system/master/config/tests/cast/receiver/test_defs.json
@@ -0,0 +1,83 @@ +[ + { + "group_name": "cast", + "slave_name": "eurtest_cast", + "test_name": "receiver_c4a_master_vol", + "identifier": "cast_receiver_assistantdefault", + "device_type": "assistantdefault", + "device_group": "oem_assistant", + "branch": ["1_26a", "master", "release", "next_release"] + }, + { + "group_name": "cast", + "slave_name": "eurtest_cast", + "test_name": "receiver_tv_master_vol", + "identifier": "cast_receiver_compliance_bubbletea", + "device_type": "bubbletea", + "device_group": "bubbletea", + "branch": ["cast_tv_mstar_master", "cast_tv_mstar_release", "cast_tv_mstar_next_release"] + }, + { + "group_name": "cast", + "slave_name": "eurtest_cast", + "test_name": "receiver_tv_master_vol", + "identifier": "cast_receiver_compliance_entourage", + "device_type": "dragonfly", + "device_group": "entourage", + "branch": ["cast_tv_dragonfly_master", "cast_tv_dragonfly_release", "cast_tv_dragonfly_next_release"] + }, + { + "group_name": "cast", + "slave_name": "eurtest_cast", + "test_name": "receiver_tv_master_vol", + "identifier": "cast_receiver_compliance_guabao", + "device_type": "guabao", + "device_group": "entourage", + "branch": ["cast_tv_mstar_master", "cast_tv_mstar_release", "cast_tv_mstar_next_release"] + }, + { + "group_name": "cast", + "slave_name": "eurtest_cast", + "test_name": "receiver_tv_master_vol", + "identifier": "cast_receiver_compliance_mars_us", + "device_type": "Mars_US", + "device_group": "entourage", + "branch": ["cast_tv_mediatek_master", "cast_tv_mediatek_release", "cast_tv_mediatek_next_release"] + }, + { + "group_name": "cast", + "slave_name": "eurtest_cast", + "test_name": "receiver_tv_master_vol", + "identifier": "cast_receiver_compliance_N00007", + "device_type": "N00007", + "device_group": "entourage", + "branch": ["cast_tv_novatek_master", "cast_tv_novatek_release", "cast_tv_novatek_next_release"] + }, + { + "group_name": "cast", + "slave_name": "eurtest_cast", + "test_name": "receiver_tv_master_vol", + "identifier": "cast_receiver_compliance_suncake", + "device_type": "suncake", + "device_group": "entourage", + "branch": ["cast_tv_mstar_master", "cast_tv_mstar_release", "cast_tv_mstar_next_release"] + }, + { + "group_name": "cast", + "slave_name": "eurtest_cast", + "test_name": "receiver_tv_master_vol", + "identifier": "cast_receiver_compliance_redwood", + "device_type": "redwood", + "device_group": "redwood", + "branch": ["cast_tv_marvell_master", "cast_tv_marvell_release", "cast_tv_marvell_next_release"] + }, + { + "group_name": "cast", + "slave_name": "eurtest_cast", + "test_name": "receiver_tv_master_vol", + "identifier": "cast_receiver_compliance_taroball", + "device_type": "taroball", + "device_group": "entourage", + "branch": ["cast_tv_mstar_master", "cast_tv_mstar_release", "cast_tv_mstar_next_release"] + } +]
diff --git a/lab_system/master/config/tests/cast/receiver_c4a.cfg b/lab_system/master/config/tests/cast/receiver_c4a.cfg new file mode 100644 index 0000000..7878c60 --- /dev/null +++ b/lab_system/master/config/tests/cast/receiver_c4a.cfg
@@ -0,0 +1,47 @@ +# Config file for the Cast receiver tests on audio devices +# +# Do not modify property names +# Run make reconfig if you change a value +# and buildbot is running +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.cast.receiver.compliance_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=CastReceiverComplianceTestCase,CastReceiverMultipleSendersTestCase,CastReceiverMirroringProtocolTestCase,CastReceiverVolumeControlTestCase,CastReceiverStressTestCase,CastReceiverMediaProtocolMP4TestCase,CastReceiverMediaProtocolSmoothStreamingTestCase,CastReceiverBenchmarkTestCase,CastReceiverQueueTestCase,CastReceiverCapabilityTestCase,CastReceiverMediaProtocolHLSTestCase,CastReceiverMediaProtocolDASHTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.framework.test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=TestSequence + +# Receiver app ids: +CAST_V2_DEBUG_APP_ID=C566BECD +CAST_V2_PLAYER_APP_ID=BE6E4473 +CHROME_MIRRORING_APP_ID=85CDB22F + +# Test specific configuration values: +MP4_MEDIA_URL=https://storage.googleapis.com/cast_media/format_tests/audio/stereo_guitar.mp3 +MP4_MEDIA_MIME_TYPE=video/mp4 + +# Temporary fix +DASH_MEDIA_URL=https://home-media-server.sandbox.google.com/static/receiver/dash/sample-dash-list.mpd +DASH_MEDIA_MIME_TYPE=application/dash+xml +HLS_MEDIA_URL=https://home-media-server.sandbox.google.com/static/receiver/hls/bbb/bbb_hls.m3u8 +HLS_MEDIA_MIME_TYPE=application/x-mpegurl +SMOOTH_STREAMING_MEDIA_URL=https://home-media-server.sandbox.google.com/static/receiver/smooth/BBB_H264_AACL/big_buck_bunny_1080p_stereo.ism/manifest +SMOOTH_STREAMING_MEDIA_MIME_TYPE=application/vnd.ms-sstr+xml + +MEDIA_LOAD_TIMEOUT_SECS=30 + +# Flag to skip tests that require a display and can't be run in C4A devices. +NO_DISPLAY=1 + +# This config is used to determine if cast operations should be allowed even if +# device is not signed-in using a gaia account. +ENABLE_CAST_WITHOUT_SIGN_IN=True + +
diff --git a/lab_system/master/config/tests/cast/receiver_c4a_master_vol.cfg b/lab_system/master/config/tests/cast/receiver_c4a_master_vol.cfg new file mode 100644 index 0000000..9ee2c71 --- /dev/null +++ b/lab_system/master/config/tests/cast/receiver_c4a_master_vol.cfg
@@ -0,0 +1,49 @@ +# Config file for the Cast receiver tests on audio devices with +# master volume control +# +# Do not modify property names +# Run make reconfig if you change a value +# and buildbot is running +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.cast.receiver.compliance_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=CastReceiverComplianceTestCase,CastReceiverMultipleSendersTestCase,CastReceiverMirroringProtocolTestCase,CastReceiverVolumeControlTestCase,CastReceiverStressTestCase,CastReceiverMediaProtocolMP4TestCase,CastReceiverMediaProtocolDASHTestCase,CastReceiverMediaProtocolHLSTestCase,CastReceiverMediaProtocolSmoothStreamingTestCase,CastReceiverBenchmarkTestCase,CastReceiverQueueTestCase,CastReceiverCapabilityTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.framework.test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=TestSequence + +# Receiver app ids: +CAST_V2_DEBUG_APP_ID=C566BECD +CAST_V2_PLAYER_APP_ID=BE6E4473 + +# Test specific configuration values: +MP4_MEDIA_URL=https://storage.googleapis.com/cast_media/format_tests/audio/stereo_guitar.mp3 +MP4_MEDIA_MIME_TYPE=video/mp4 + +DASH_MEDIA_URL=https://home-media-server.sandbox.google.com/static/formats/audio/stereo_guitar.mpd +DASH_MEDIA_MIME_TYPE=application/dash+xml + +HLS_MEDIA_URL=https://home-media-server.sandbox.google.com/static/formats/audio/hls_aac_he/stereo_guitar.m3u8 +HLS_MEDIA_MIME_TYPE=application/x-mpegurl + +SMOOTH_STREAMING_MEDIA_URL=https://home-media-server.sandbox.google.com/static/formats/audio/stereo_guitar.ism/Manifest +SMOOTH_STREAMING_MEDIA_MIME_TYPE=application/vnd.ms-sstr+xml + +MEDIA_LOAD_TIMEOUT_SECS=30 + +# Flag to skip tests that require a display and can't be run in C4A devices. +NO_DISPLAY=1 + +# This config is used to determine if cast operations should be allowed even if +# device is not signed-in using a gaia account. +ENABLE_CAST_WITHOUT_SIGN_IN=True + +# Master volume control +ANALOG_VOLUME=1
diff --git a/lab_system/master/config/tests/cast/receiver_dogfood.cfg b/lab_system/master/config/tests/cast/receiver_dogfood.cfg new file mode 100644 index 0000000..c43ad53 --- /dev/null +++ b/lab_system/master/config/tests/cast/receiver_dogfood.cfg
@@ -0,0 +1,38 @@ +# Config file for the dogfood Cast receiver tests +# +# These tests run on dogfood versions of the Cast +# Media Receiver, Media Player Library and Test +# Cast Client Receiver. +# +# Do not modify property names +# Run make reconfig if you change a value +# and buildbot is running +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.cast.receiver.compliance_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=CastReceiverComplianceTestCase,CastReceiverMultipleSendersTestCase,CastReceiverMirroringProtocolTestCase,CastReceiverVolumeControlTestCase,CastReceiverStressTestCase,CastReceiverMediaProtocolMP4TestCase,CastReceiverMediaProtocolDASHTestCase,CastReceiverMediaProtocolHLSTestCase,CastReceiverMediaProtocolSmoothStreamingTestCase,CastReceiverBenchmarkTestCase,CastReceiverQueueTestCase,CastReceiverCapabilityTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.framework.test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=TestSequence + +# Receiver app ids: +CAST_V2_DEBUG_APP_ID=F83E3215 +CAST_V2_PLAYER_APP_ID=9B04B019 + +# Test specific configuration values: +MP4_MEDIA_URL=https://home-media-server.sandbox.google.com/static/media/car-1920x1080.mp4 +MP4_MEDIA_MIME_TYPE=video/mp4 +DASH_MEDIA_URL=https://home-media-server.sandbox.google.com/static/receiver/dash/sample-dash-list.mpd +DASH_MEDIA_MIME_TYPE=application/dash+xml +HLS_MEDIA_URL=https://home-media-server.sandbox.google.com/static/dumps/media/hls/unicornmedia/demo.umedia.com/cast/testfiles/preroll_midroll60s_postroll.zip/manifest.m3u8 +HLS_MEDIA_MIME_TYPE=application/x-mpegurl +SMOOTH_STREAMING_MEDIA_URL=https://home-media-server.sandbox.google.com/static/receiver/smooth/BBB_H264_AACL/big_buck_bunny_1080p_stereo.ism/manifest +SMOOTH_STREAMING_MEDIA_MIME_TYPE=application/vnd.ms-sstr+xml +MEDIA_LOAD_TIMEOUT_SECS=30
diff --git a/lab_system/master/config/tests/cast/receiver_tv_master_vol.cfg b/lab_system/master/config/tests/cast/receiver_tv_master_vol.cfg new file mode 100644 index 0000000..e926757 --- /dev/null +++ b/lab_system/master/config/tests/cast/receiver_tv_master_vol.cfg
@@ -0,0 +1,38 @@ +# Config file for the Cast receiver tests for TVs with +# master volume control +# +# Do not modify property names +# Run make reconfig if you change a value +# and buildbot is running +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.cast.receiver.compliance_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=CastReceiverComplianceTestCase,CastReceiverMultipleSendersTestCase,CastReceiverMirroringProtocolTestCase,CastReceiverVolumeControlTestCase,CastReceiverStressTestCase,CastReceiverMediaProtocolMP4TestCase,CastReceiverMediaProtocolDASHTestCase,CastReceiverMediaProtocolHLSTestCase,CastReceiverMediaProtocolSmoothStreamingTestCase,CastReceiverBenchmarkTestCase,CastReceiverQueueTestCase,CastReceiverCapabilityTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.framework.test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=TestSequence + +# Receiver app ids: +CAST_V2_DEBUG_APP_ID=C566BECD +CAST_V2_PLAYER_APP_ID=BE6E4473 + +# Test specific configuration values: +MP4_MEDIA_URL=https://home-media-server.sandbox.google.com/static/receiver/mp4/bbb_1080p_30fps_x264_high_41_mp3.mp4 +MP4_MEDIA_MIME_TYPE=video/mp4 +DASH_MEDIA_URL=https://home-media-server.sandbox.google.com/static/receiver/dash/sample-dash-list.mpd +DASH_MEDIA_MIME_TYPE=application/dash+xml +HLS_MEDIA_URL=https://home-media-server.sandbox.google.com/static/receiver/hls/bbb/bbb_hls.m3u8 +HLS_MEDIA_MIME_TYPE=application/x-mpegurl +SMOOTH_STREAMING_MEDIA_URL=https://home-media-server.sandbox.google.com/static/receiver/smooth/BBB_H264_AACL/big_buck_bunny_1080p_stereo.ism/manifest +SMOOTH_STREAMING_MEDIA_MIME_TYPE=application/vnd.ms-sstr+xml +MEDIA_LOAD_TIMEOUT_SECS=30 + +# Master volume control +ANALOG_VOLUME=1
diff --git a/lab_system/master/config/tests/cast/receiver_x86.cfg b/lab_system/master/config/tests/cast/receiver_x86.cfg new file mode 100644 index 0000000..4b3f724 --- /dev/null +++ b/lab_system/master/config/tests/cast/receiver_x86.cfg
@@ -0,0 +1,41 @@ +# Config file to run the Cast receiver tests against a local x86 cast shell. +# +# Do not modify property names +# Run make reconfig if you change a value +# and buildbot is running +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.cast.receiver.compliance_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=CastReceiverComplianceTestCase,CastReceiverMultipleSendersTestCase,CastReceiverMirroringProtocolTestCase,CastReceiverVolumeControlTestCase,CastReceiverStressTestCase,CastReceiverMediaProtocolMP4TestCase,CastReceiverMediaProtocolDASHTestCase,CastReceiverMediaProtocolHLSTestCase,CastReceiverMediaProtocolSmoothStreamingTestCase,CastReceiverBenchmarkTestCase,CastReceiverQueueTestCase,CastReceiverCapabilityTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.framework.disabled_logging_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=X86DisabledLoggingTestSequence + +# Receiver app ids: +CAST_V2_DEBUG_APP_ID=C566BECD +CAST_V2_PLAYER_APP_ID=BE6E4473 + +# Test specific configuration values: +MP4_MEDIA_URL=https://storage.googleapis.com/cast_media/format_tests/video/bbb_1080p_30fps_x264_high_41_mp3.mp4 +MP4_MEDIA_MIME_TYPE=video/mp4 +DASH_MEDIA_URL=https://home-media-server.sandbox.google.com/static/receiver/dash/sample-dash-list.mpd +DASH_MEDIA_MIME_TYPE=application/dash+xml +HLS_MEDIA_URL=https://home-media-server.sandbox.google.com/static/receiver/hls/bbb/bbb_hls.m3u8 +HLS_MEDIA_MIME_TYPE=application/x-mpegurl +SMOOTH_STREAMING_MEDIA_URL=https://home-media-server.sandbox.google.com/static/receiver/smooth/BBB_H264_AACL/big_buck_bunny_1080p_stereo.ism/manifest +SMOOTH_STREAMING_MEDIA_MIME_TYPE=application/vnd.ms-sstr+xml +MEDIA_LOAD_TIMEOUT_SECS=30 +ANALOG_VOLUME=1 + +# Tests that are not applicable for x86 cast shell (b/25285537) +TESTS_TO_SKIP=CastReceiverComplianceTestCase.testIsActiveInput + +# Skip SSH communication +SKIP_SSH=True
diff --git a/lab_system/master/config/tests/cast_androidthings/cast_androidthings.cfg b/lab_system/master/config/tests/cast_androidthings/cast_androidthings.cfg new file mode 100644 index 0000000..cb270ba --- /dev/null +++ b/lab_system/master/config/tests/cast_androidthings/cast_androidthings.cfg
@@ -0,0 +1,53 @@ +# Config file for Cast receiver tests on Android Things devices. +# +# Do not modify property names +# Run make reconfig if you change a value +# and buildbot is running +# +# PROPERTIES + +# Remote Test Setup +USER_NAME=gtvchrome +REMOTE_TEST_ROOT=/home/gtvchrome/repositories/HEAD +REMOTE_RESULT_DIR=/home/gtvchrome/results + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.cast.receiver.athings_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=CastReceiverComplianceTestCase,CastReceiverCapabilityTestCase,CastReceiverMultipleSendersTestCase,CastReceiverVolumeControlTestCase,CastReceiverMediaProtocolMP4TestCase,CastReceiverMediaProtocolHLSTestCase,CastReceiverMediaProtocolDASHTestCase,CastReceiverMediaProtocolSmoothStreamingTestCase,CastReceiverStressTestCase,CastReceiverBenchmarkTestCase,CastReceiverQueueTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.cast.receiver.athings_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=TestSequence + +# Default ports on receiver +DEFAULT_HTTP_PORT=8008 +DEFAULT_RECEIVER_PORT=8009 +DEFAULT_DEBUG_PORT=9222 +USE_ADB_FORWARD=True + +# Receiver app ids: +CAST_V2_DEBUG_APP_ID=C566BECD +CAST_V2_PLAYER_APP_ID=BE6E4473 + +# Test specific configuration values: +MP4_MEDIA_URL=https://storage.googleapis.com/cast_media/format_tests/audio/stereo_guitar.mp3 +MP4_MEDIA_MIME_TYPE=video/mp4 +DASH_MEDIA_URL=https://storage.googleapis.com/cast_media/format_tests/audio/stereo_guitar.mpd +DASH_MEDIA_MIME_TYPE=application/dash+xml +HLS_MEDIA_URL=https://storage.googleapis.com/cast_media/format_tests/audio/hls_aac_he/stereo_guitar.m3u8 +HLS_MEDIA_MIME_TYPE=application/x-mpegurl +SMOOTH_STREAMING_MEDIA_URL=https://storage.googleapis.com/cast_media/format_tests/audio/stereo_guitar.ism/Manifest +SMOOTH_STREAMING_MEDIA_MIME_TYPE=application/vnd.ms-sstr+xml + +MEDIA_LOAD_TIMEOUT_SECS=30 + +# Flag to skip tests that require a display and can't be run in C4A devices. +NO_DISPLAY=1 + +# # This config is used to determine if cast operations should be allowed even if +# # device is not signed-in using a gaia account. +ENABLE_CAST_WITHOUT_SIGN_IN=True
diff --git a/lab_system/master/config/tests/cast_androidthings/cast_androidthings_cq_presubmit.cfg b/lab_system/master/config/tests/cast_androidthings/cast_androidthings_cq_presubmit.cfg new file mode 100644 index 0000000..0af2771 --- /dev/null +++ b/lab_system/master/config/tests/cast_androidthings/cast_androidthings_cq_presubmit.cfg
@@ -0,0 +1,49 @@ +# Config file for the Cast receiver tests running on AndroidThings. +# +# This config file is used in CQ presubmit. +# +# PROPERTIES + +# Remote Test Setup +USER_NAME=gtvchrome +REMOTE_TEST_ROOT=/home/gtvchrome/repositories/HEAD +REMOTE_RESULT_DIR=/home/gtvchrome/results + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.cast.receiver.athings_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=CastReceiverComplianceTestCase,CastReceiverCapabilityTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.cast.receiver.athings_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=TestSequence + +# Default ports on receiver +DEFAULT_HTTP_PORT=8008 +DEFAULT_RECEIVER_PORT=8009 +DEFAULT_DEBUG_PORT=9222 +USE_ADB_FORWARD=True + +# Receiver app ids: +CAST_V2_DEBUG_APP_ID=C566BECD +CAST_V2_PLAYER_APP_ID=BE6E4473 + +# Test specific configuration values: +MP4_MEDIA_URL=https://storage.googleapis.com/cast_media/format_tests/audio/stereo_guitar.mp3 +MP4_MEDIA_MIME_TYPE=video/mp4 +DASH_MEDIA_URL=https://storage.googleapis.com/cast_media/format_tests/audio/stereo_guitar.mpd +DASH_MEDIA_MIME_TYPE=application/dash+xml +HLS_MEDIA_URL=https://storage.googleapis.com/cast_media/format_tests/audio/hls_aac_he/stereo_guitar.m3u8 +HLS_MEDIA_MIME_TYPE=application/x-mpegurl +SMOOTH_STREAMING_MEDIA_URL=https://storage.googleapis.com/cast_media/format_tests/audio/stereo_guitar.ism/Manifest +SMOOTH_STREAMING_MEDIA_MIME_TYPE=application/vnd.ms-sstr+xml + +# Flag to skip tests that require a display and can't be run in C4A devices. +NO_DISPLAY=1 + +# # This config is used to determine if cast operations should be allowed even if +# # device is not signed-in using a gaia account. +ENABLE_CAST_WITHOUT_SIGN_IN=True
diff --git a/lab_system/master/config/tests/cast_androidthings/test_defs.json b/lab_system/master/config/tests/cast_androidthings/test_defs.json new file mode 100644 index 0000000..e0d80ee --- /dev/null +++ b/lab_system/master/config/tests/cast_androidthings/test_defs.json
@@ -0,0 +1,12 @@ +[ + { + "group_name": "cast_androidthings", + "slave_name": "androidthings_receiver", + "test_name": "androidthings_receiver", + "identifier": "androidthings_receiver", + "device_type": "imx7d_pico", + "device_group": "unit_test", + "branch": ["master", "androidthings_release", "androidthings_next_release"], + "step_factories_recipe": "step_factories_recipes/androidthings_cast_test_recipe.json" + } +]
diff --git a/lab_system/master/config/tests/cast_atv/test_defs.json b/lab_system/master/config/tests/cast_atv/test_defs.json new file mode 100644 index 0000000..54bbf48 --- /dev/null +++ b/lab_system/master/config/tests/cast_atv/test_defs.json
@@ -0,0 +1,22 @@ +[ + { + "group_name": "cast_atv", + "slave_name": "atv_receiver", + "test_name": "atv_receiver", + "identifier": "atv_receiver", + "device_type": "fugu", + "device_group": "cast_fugu", + "branch": ["master", "release", "next_release"], + "step_factories_recipe": "step_factories_recipes/atv_cast_test_recipe.json" + }, + { + "group_name": "cast_atv", + "slave_name": "atv_receiver_shieldtv", + "test_name": "atv_receiver", + "identifier": "atv_receiver_shieldtv", + "device_type": "darcy", + "device_group": "unit_test", + "branch": ["master", "release", "next_release"], + "step_factories_recipe": "step_factories_recipes/atv_cast_test_recipe.json" + } +]
diff --git a/lab_system/master/config/tests/cast_tv_unit_test/test_defs.json b/lab_system/master/config/tests/cast_tv_unit_test/test_defs.json new file mode 100644 index 0000000..18d86f5 --- /dev/null +++ b/lab_system/master/config/tests/cast_tv_unit_test/test_defs.json
@@ -0,0 +1,114 @@ +[ + { + "branch": ["cast_tv_dragonfly_master", "cast_tv_dragonfly_release", "cast_tv_dragonfly_next_release"], + "build_flavor": "eng", + "device_group": "unit_test", + "device_type": "dragonfly", + "identifier": "dragonfly_eng", + "scheduler": "*/10 * * * *", + "slave_name": "dragonfly_eng", + "slave_number": [ + 1, + 2 + ], + "step_factories_recipe": "step_factories_recipes/unit_test_no_usb_check_recipe.json" + }, + { + "branch": ["cast_tv_marvell_master", "cast_tv_marvell_release", "cast_tv_marvell_next_release"], + "build_flavor": "eng", + "device_group": "unit_test", + "device_type": "redwood", + "identifier": "redwood_eng", + "scheduler": "*/10 * * * *", + "slave_name": "redwood_eng", + "slave_number": [ + 1, + 2 + ], + "step_factories_recipe": "step_factories_recipes/unit_test_no_usb_check_recipe.json" + }, + { + "branch": ["cast_tv_mstar_master", "cast_tv_mstar_release", "cast_tv_mstar_next_release"], + "build_flavor": "eng", + "device_group": "unit_test", + "device_type": "bubbletea", + "identifier": "bubbletea_eng", + "scheduler": "*/10 * * * *", + "slave_name": "bubbletea_eng", + "slave_number": [ + 1, + 2 + ], + "step_factories_recipe": "step_factories_recipes/claim_hint_unit_test_recipe.json" + }, + { + "branch": ["cast_tv_mstar_master", "cast_tv_mstar_release", "cast_tv_mstar_next_release"], + "build_flavor": "eng", + "device_group": "unit_test", + "device_type": "guabao", + "identifier": "guabao_eng", + "scheduler": "*/10 * * * *", + "slave_name": "guabao_eng", + "slave_number": [ + 1, + 2 + ], + "step_factories_recipe": "step_factories_recipes/claim_hint_unit_test_recipe.json" + }, + { + "branch": ["cast_tv_mstar_master", "cast_tv_mstar_release", "cast_tv_mstar_next_release"], + "build_flavor": "eng", + "device_group": "unit_test", + "device_type": "suncake", + "identifier": "suncake_eng", + "scheduler": "*/10 * * * *", + "slave_name": "suncake_eng", + "slave_number": [ + 1, + 2 + ], + "step_factories_recipe": "step_factories_recipes/claim_hint_unit_test_recipe.json" + }, + { + "branch": ["cast_tv_mstar_master", "cast_tv_mstar_release", "cast_tv_mstar_next_release"], + "build_flavor": "eng", + "device_group": "unit_test", + "device_type": "taroball", + "identifier": "taroball_eng", + "scheduler": "*/10 * * * *", + "slave_name": "taroball_eng", + "slave_number": [ + 1, + 2 + ], + "step_factories_recipe": "step_factories_recipes/claim_hint_unit_test_recipe.json" + }, + { + "branch": ["cast_tv_mstar_master", "cast_tv_mstar_release", "cast_tv_mstar_next_release"], + "build_flavor": "eng", + "device_group": "unit_test", + "device_type": "Mars_US", + "identifier": "Mars_US_eng", + "scheduler": "*/10 * * * *", + "slave_name": "Mars_US_eng", + "slave_number": [ + 1, + 2 + ], + "step_factories_recipe": "step_factories_recipes/unit_test_lower_case_product_name_recipe.json" + }, + { + "branch": ["cast_tv_novatek_master", "cast_tv_novatek_release", "cast_tv_novatek_next_release"], + "build_flavor": "eng", + "device_group": "unit_test", + "device_type": "N00007", + "identifier": "N00007_eng", + "scheduler": "*/10 * * * *", + "slave_name": "N00007_eng", + "slave_number": [ + 1, + 2 + ], + "step_factories_recipe": "step_factories_recipes/unit_test_lower_case_product_name_recipe.json" + } +]
diff --git a/lab_system/master/config/tests/cast_video/video_decode_accelerator.cfg b/lab_system/master/config/tests/cast_video/video_decode_accelerator.cfg new file mode 100644 index 0000000..95895c6 --- /dev/null +++ b/lab_system/master/config/tests/cast_video/video_decode_accelerator.cfg
@@ -0,0 +1,16 @@ +# Config file for video decode accelerator tests. +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.cast_video.video_decode_accelerator_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=VideoDecodeAcceleratorTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.cast_video.video_decode_accelerator_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=VideoDecodeAcceleratorTestSequence +
diff --git a/lab_system/master/config/tests/cast_video/video_encode_accelerator.cfg b/lab_system/master/config/tests/cast_video/video_encode_accelerator.cfg new file mode 100644 index 0000000..78ea1f3 --- /dev/null +++ b/lab_system/master/config/tests/cast_video/video_encode_accelerator.cfg
@@ -0,0 +1,16 @@ +# Config file for video encode accelerator tests. +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.cast_video.video_encode_accelerator_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=VideoEncodeAcceleratorTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.cast_video.video_encode_accelerator_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=VideoEncodeAcceleratorTestSequence +
diff --git a/lab_system/master/config/tests/check_logs/test_check_logs.cfg b/lab_system/master/config/tests/check_logs/test_check_logs.cfg new file mode 100644 index 0000000..a5ceb21 --- /dev/null +++ b/lab_system/master/config/tests/check_logs/test_check_logs.cfg
@@ -0,0 +1,14 @@ +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.locate_string.simple_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=GetBadBlocks + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.locate_string.locate_string_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=CheckLogsTestSequence + +# Set to true to disable check logs: +# DISABLE_CHECK_LOGS_FOR_STRINGS=True
diff --git a/lab_system/master/config/tests/cloudcast/cloudcast.cfg b/lab_system/master/config/tests/cloudcast/cloudcast.cfg new file mode 100644 index 0000000..9786038 --- /dev/null +++ b/lab_system/master/config/tests/cloudcast/cloudcast.cfg
@@ -0,0 +1,17 @@ +# Config file for the Cast Action Script tests. + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.cloudcast.cast_action_script_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=CastActionScriptRunnerTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.framework.test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=TestSequence + +# Comma-separated list of apps to test. +# YT Music, YT, GPM, Spotify, TuneIn +APP_ID_LIST=2DB7CC49,233637DE,F05C50C9,DF630089,12F05308
diff --git a/lab_system/master/config/tests/cloudcast/cloudcast_c4a.cfg b/lab_system/master/config/tests/cloudcast/cloudcast_c4a.cfg new file mode 100644 index 0000000..5a6f337 --- /dev/null +++ b/lab_system/master/config/tests/cloudcast/cloudcast_c4a.cfg
@@ -0,0 +1,17 @@ +# Config file for the Cast Action Script tests. + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.cloudcast.cast_action_script_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=CastActionScriptRunnerTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.framework.test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=TestSequence + +# Comma-separated list of apps to test. +# YT Music, GPM, Pandora, Spotify, TuneIn +APP_ID_LIST=2DB7CC49,F05C50C9,36061251,DF630089,12F05308
diff --git a/lab_system/master/config/tests/cloudcast/test_defs.json b/lab_system/master/config/tests/cloudcast/test_defs.json new file mode 100644 index 0000000..475be1c --- /dev/null +++ b/lab_system/master/config/tests/cloudcast/test_defs.json
@@ -0,0 +1,47 @@ +[ + { + "group_name": "cloudcast", + "slave_name": "cloudcast_video", + "test_name": "cloudcast", + "identifier": "cloudcast_eureka", + "device_type": "eureka", + "device_group": "eureka_debug", + "branch": ["master"] + }, + { + "group_name": "cloudcast", + "slave_name": "cloudcast_video", + "test_name": "cloudcast", + "identifier": "cloudcast_lexx", + "device_type": "lexx", + "device_group": "lexx_eth", + "branch": ["master"] + }, + { + "group_name": "cloudcast", + "slave_name": "cloudcast_video", + "test_name": "cloudcast", + "identifier": "cloudcast_earth", + "device_type": "earth", + "device_group": "earth_eth", + "branch": ["master"] + }, + { + "group_name": "cloudcast", + "slave_name": "cloudcast_audio", + "test_name": "cloudcast_c4a", + "identifier": "cloudcast_hendrix", + "device_type": "hendrix", + "device_group": "hendrix_eth", + "branch": ["master"] + }, + { + "group_name": "cloudcast", + "slave_name": "cloudcast_audio", + "test_name": "cloudcast_c4a", + "identifier": "cloudcast_chirp", + "device_type": "chirp", + "device_group": "chirp", + "branch": ["master"] + } +]
diff --git a/lab_system/master/config/tests/comms/comms_back_to_back_telstra_audio_call.cfg b/lab_system/master/config/tests/comms/comms_back_to_back_telstra_audio_call.cfg new file mode 100644 index 0000000..0b7a877 --- /dev/null +++ b/lab_system/master/config/tests/comms/comms_back_to_back_telstra_audio_call.cfg
@@ -0,0 +1,31 @@ +# Config file for multiple back to back telstra audio calls tests. +# In this test case, we collect system performance metrics during the test. +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.comms.carrier_audio_call_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=CommsTelstraBackToBackAudioCallsTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.comms.comms_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=CommsTestSequence + +# Carrier testing provider +CALL_PROVIDER=telstra + +# Carrier callee +CALL_DESTINATION=+61393888068 + +# Carrier caller +CALL_CALLER=+17735550111 + +# Max duration in seconds for each carrier call in the test +CALL_DURATION_SECS=20 + +# Number of the carrier calls being made in the test +CALL_REPEAT_TIMES=30
diff --git a/lab_system/master/config/tests/comms/comms_long_duo_audio_call.cfg b/lab_system/master/config/tests/comms/comms_long_duo_audio_call.cfg new file mode 100644 index 0000000..e57a4bb --- /dev/null +++ b/lab_system/master/config/tests/comms/comms_long_duo_audio_call.cfg
@@ -0,0 +1,25 @@ +# Config file for system perf duo video call tests. +# In this test case, we collect system performance metrics for a duo video call. +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.comms.duo_audio_call_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=CommsDuoLongAudioCallTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.comms.comms_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=CommsTestSequence + +# Duo testing code Bot ID +CALL_PROVIDER=bot:duo-bot-router-speech-bot + +# Max duration in seconds for each duo call in the test +CALL_DURATION_SECS=3300 + +# Number of the Duo calls being made in the test +CALL_REPEAT_TIMES=1
diff --git a/lab_system/master/config/tests/comms/comms_long_duo_video_call.cfg b/lab_system/master/config/tests/comms/comms_long_duo_video_call.cfg new file mode 100644 index 0000000..97af7d0 --- /dev/null +++ b/lab_system/master/config/tests/comms/comms_long_duo_video_call.cfg
@@ -0,0 +1,26 @@ +# Config file for system perf duo video call tests. +# In this test case, we collect system performance metrics for a duo video call. +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.comms.duo_video_call_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=CommsDuoLongVideoCallTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.comms.comms_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=CommsTestSequence + +# Duo testing code Bot ID +CALL_PROVIDER=bot:duo-bot-router-speech-bot + +# Max duration in seconds for each duo call in the test +CALL_DURATION_SECS=3300 + +# Number of the Duo calls being made in the test +CALL_REPEAT_TIMES=1 +
diff --git a/lab_system/master/config/tests/comms/comms_long_telstra_audio_call.cfg b/lab_system/master/config/tests/comms/comms_long_telstra_audio_call.cfg new file mode 100644 index 0000000..7b60390 --- /dev/null +++ b/lab_system/master/config/tests/comms/comms_long_telstra_audio_call.cfg
@@ -0,0 +1,32 @@ +# Config file for long telstra audio call tests. +# In this test case, we collect system performance metrics for a telstra audio call. +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.comms.carrier_audio_call_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=CommsTelstraLongAudioCallTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.comms.comms_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=CommsTestSequence + +# Carrier testing provider +CALL_PROVIDER=telstra + +# Carrier testing provider +CALL_DESTINATION=+61267714906 + +# Carrier testing provider +CALL_CALLER=+17735550111 + +# Max duration in seconds for each carrier call in the test +CALL_DURATION_SECS=1800 + +# Number of the carrier calls being made in the test +CALL_REPEAT_TIMES=1 +
diff --git a/lab_system/master/config/tests/comms/comms_short_duo_audio_call.cfg b/lab_system/master/config/tests/comms/comms_short_duo_audio_call.cfg new file mode 100644 index 0000000..906618e --- /dev/null +++ b/lab_system/master/config/tests/comms/comms_short_duo_audio_call.cfg
@@ -0,0 +1,25 @@ +# Config file for short duo audio call tests. +# In this test case, we collect system performance metrics for a duo video call. +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.comms.duo_audio_call_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=CommsDuoShortAudioCallTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.comms.comms_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=CommsTestSequence + +# Duo testing code Bot ID +CALL_PROVIDER=bot:duo-bot-router-speech-bot + +# Max duration in seconds for each duo call in the test +CALL_DURATION_SECS=300 + +# Number of the Duo calls being made in the test +CALL_REPEAT_TIMES=1
diff --git a/lab_system/master/config/tests/comms/comms_short_duo_video_call.cfg b/lab_system/master/config/tests/comms/comms_short_duo_video_call.cfg new file mode 100644 index 0000000..79f8c53 --- /dev/null +++ b/lab_system/master/config/tests/comms/comms_short_duo_video_call.cfg
@@ -0,0 +1,26 @@ +# Config file for short duo video call tests. +# In this test case, we collect system performance metrics for a duo video call. +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.comms.duo_video_call_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=CommsDuoShortVideoCallTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.comms.comms_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=CommsTestSequence + +# Duo testing code Bot ID +CALL_PROVIDER=bot:duo-bot-router-speech-bot + +# Max duration in seconds for each duo call in the test +CALL_DURATION_SECS=300 + +# Number of the Duo calls being made in the test +CALL_REPEAT_TIMES=1 +
diff --git a/lab_system/master/config/tests/comms/comms_short_telstra_audio_call.cfg b/lab_system/master/config/tests/comms/comms_short_telstra_audio_call.cfg new file mode 100644 index 0000000..d6b54de --- /dev/null +++ b/lab_system/master/config/tests/comms/comms_short_telstra_audio_call.cfg
@@ -0,0 +1,32 @@ +# Config file for short telstra audio call tests. +# In this test case, we collect system performance metrics for a telstra audio call. +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.comms.carrier_audio_call_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=CommsTelstraShortAudioCallTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.comms.comms_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=CommsTestSequence + +# Carrier testing provider +CALL_PROVIDER=telstra + +# Carrier testing provider +CALL_DESTINATION=+61267714906 + +# Carrier testing provider +CALL_CALLER=+17735550111 + +# Max duration in seconds for each carrier call in the test +CALL_DURATION_SECS=300 + +# Number of the carrier calls being made in the test +CALL_REPEAT_TIMES=1 +
diff --git a/lab_system/master/config/tests/cpu_load/cpu_load.cfg b/lab_system/master/config/tests/cpu_load/cpu_load.cfg new file mode 100644 index 0000000..dd227aa --- /dev/null +++ b/lab_system/master/config/tests/cpu_load/cpu_load.cfg
@@ -0,0 +1,13 @@ +# Configuration values for the cpu_load benchmarks test. + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.cpu_load.cpu_load_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=CpuLoadTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.cpu_load.cpu_load_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=CpuLoadTestSequence
diff --git a/lab_system/master/config/tests/cpu_load/test_defs.json b/lab_system/master/config/tests/cpu_load/test_defs.json new file mode 100644 index 0000000..5420743 --- /dev/null +++ b/lab_system/master/config/tests/cpu_load/test_defs.json
@@ -0,0 +1,57 @@ +[ + { + "group_name": "cpu_load", + "slave_name": "cpu_load", + "test_name": "cpu_load", + "identifier": "cpu_load", + "device_type": "eureka", + "device_group": "eureka_debug", + "hidden": "true", + "branch": ["master", "release"], + "build_flavor": "user" + }, + { + "group_name": "cpu_load", + "slave_name": "cpu_load_v2", + "test_name": "cpu_load", + "identifier": "cpu_load_v2", + "device_type": "lexx", + "device_group": "lexx_eth", + "hidden": "true", + "branch": ["master", "release"], + "build_flavor": "user" + }, + { + "group_name": "cpu_load", + "slave_name": "cpu_load_v3", + "test_name": "cpu_load", + "identifier": "cpu_load_v3", + "device_type": "earth", + "device_group": "earth_eth", + "hidden": "true", + "branch": ["master", "release"], + "build_flavor": "user" + }, + { + "group_name": "cpu_load", + "slave_name": "cpu_load_audio", + "test_name": "cpu_load", + "identifier": "cpu_load_hendrix", + "device_type": "hendrix", + "device_group": "hendrix_eth", + "hidden": "true", + "branch": ["master", "release"], + "build_flavor": "user" + }, + { + "group_name": "cpu_load", + "slave_name": "cpu_load", + "test_name": "cpu_load", + "identifier": "cpu_load_v4", + "device_type": "luther_b2", + "device_group": "luther_eth", + "hidden": "true", + "branch": ["master", "release"], + "build_flavor": "user" + } +]
diff --git a/lab_system/master/config/tests/crash_loop/crash_checks.cfg b/lab_system/master/config/tests/crash_loop/crash_checks.cfg new file mode 100644 index 0000000..4ac9ea6 --- /dev/null +++ b/lab_system/master/config/tests/crash_loop/crash_checks.cfg
@@ -0,0 +1,17 @@ +# Config file for the Crash/Boot loop tests +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.ota_installable.crash_checks_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=CrashChecksTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.ota_installable.ota_installable_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=OtaInstallableTestSequence + +
diff --git a/lab_system/master/config/tests/crash_loop/crash_loop.cfg b/lab_system/master/config/tests/crash_loop/crash_loop.cfg new file mode 100644 index 0000000..cf4b1b7 --- /dev/null +++ b/lab_system/master/config/tests/crash_loop/crash_loop.cfg
@@ -0,0 +1,17 @@ +# Config file for the Crash/Boot loop tests +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.ota_installable.crash_loop_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=CrashLoopTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.ota_installable.ota_installable_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=OtaInstallableTestSequence + +
diff --git a/lab_system/master/config/tests/crash_loop/fuchsia_crash_loop.cfg b/lab_system/master/config/tests/crash_loop/fuchsia_crash_loop.cfg new file mode 100644 index 0000000..5492b81 --- /dev/null +++ b/lab_system/master/config/tests/crash_loop/fuchsia_crash_loop.cfg
@@ -0,0 +1,17 @@ +# Config file for the Crash/Boot loop tests on Fuchsia devices +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.ota_installable.fuchsia_crash_loop_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=FuchsiaCrashLoopTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.ota_installable.fuchsia_ota_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=FuchsiaOtaInstallableTestSequence + +
diff --git a/lab_system/master/config/tests/cycle_bitrates/cycle_bitrates.cfg b/lab_system/master/config/tests/cycle_bitrates/cycle_bitrates.cfg new file mode 100644 index 0000000..b077223 --- /dev/null +++ b/lab_system/master/config/tests/cycle_bitrates/cycle_bitrates.cfg
@@ -0,0 +1,17 @@ +# Config file for JavaScript video tests. +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.cycle_bitrates.cycle_bitrates_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=CycleBitRatesTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.framework.javascript_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=JavascriptTestSequence + +
diff --git a/lab_system/master/config/tests/cycle_bitrates/fuchsia_cycle_bitrates.cfg b/lab_system/master/config/tests/cycle_bitrates/fuchsia_cycle_bitrates.cfg new file mode 100644 index 0000000..b4d90b1 --- /dev/null +++ b/lab_system/master/config/tests/cycle_bitrates/fuchsia_cycle_bitrates.cfg
@@ -0,0 +1,17 @@ +# Config file for JavaScript video tests. +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.cycle_bitrates.cycle_bitrates_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=CycleBitRatesTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.framework.fuchsia_javascript_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=FuchsiaJavascriptTestSequence + +
diff --git a/lab_system/master/config/tests/cycle_bitrates/test_defs.json b/lab_system/master/config/tests/cycle_bitrates/test_defs.json new file mode 100644 index 0000000..0b1c865 --- /dev/null +++ b/lab_system/master/config/tests/cycle_bitrates/test_defs.json
@@ -0,0 +1,11 @@ +[ + { + "group_name": "cycle_bitrates", + "slave_name": "cycle_bitrates", + "test_name": "cycle_bitrates", + "identifier": "cycle_bitrates_cast_tv", + "device_type": "dragonfly", + "device_group": "av_drm", + "branch": ["cast_tv_dragonfly_master", "cast_tv_dragonfly_release", "cast_tv_dragonfly_next_release"] + } +]
diff --git a/lab_system/master/config/tests/dcs/atv_dcs.cfg b/lab_system/master/config/tests/dcs/atv_dcs.cfg new file mode 100644 index 0000000..addeacc --- /dev/null +++ b/lab_system/master/config/tests/dcs/atv_dcs.cfg
@@ -0,0 +1,15 @@ +# Configuration values for the dcs test. +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.dcs.atv_dcs_e2e_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=AtvDcsE2eTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.framework.android_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=AndroidTestSequence
diff --git a/lab_system/master/config/tests/dcs/dcs.cfg b/lab_system/master/config/tests/dcs/dcs.cfg new file mode 100644 index 0000000..4748ac6 --- /dev/null +++ b/lab_system/master/config/tests/dcs/dcs.cfg
@@ -0,0 +1,17 @@ +# Configuration values for the dcs test. +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.dcs.dcs_e2e_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=DcsE2eTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.framework.test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=TestSequence + +
diff --git a/lab_system/master/config/tests/dcs/fuchsia_dcs.cfg b/lab_system/master/config/tests/dcs/fuchsia_dcs.cfg new file mode 100644 index 0000000..85b90f2 --- /dev/null +++ b/lab_system/master/config/tests/dcs/fuchsia_dcs.cfg
@@ -0,0 +1,17 @@ +# Configuration values for the Fuchsia dcs test. +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.dcs.fuchsia_dcs_e2e_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=FuchsiaDcsE2eTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.framework.fuchsia_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=FuchsiaTestSequence + +
diff --git a/lab_system/master/config/tests/dcs/test_defs.json b/lab_system/master/config/tests/dcs/test_defs.json new file mode 100644 index 0000000..65cd508 --- /dev/null +++ b/lab_system/master/config/tests/dcs/test_defs.json
@@ -0,0 +1,47 @@ +[ + { + "group_name": "dcs", + "slave_name": "eurtest_dcs", + "test_name": "dcs", + "identifier": "dcs_v2", + "device_type": "lexx", + "device_group": "lexx_eth", + "branch": ["master", "release"] + }, + { + "group_name": "dcs", + "slave_name": "eurtest_dcs", + "test_name": "dcs", + "identifier": "dcs_v3", + "device_type": "earth", + "device_group": "earth_eth", + "branch": ["master", "release"] + }, + { + "group_name": "dcs", + "slave_name": "eurtest_dcs", + "test_name": "dcs", + "identifier": "dcs_hendrix", + "device_type": "hendrix", + "device_group": "hendrix_eth", + "branch": ["master", "release"] + }, + { + "group_name": "dcs", + "slave_name": "eurtest_dcs", + "test_name": "dcs", + "identifier": "dcs_v4", + "device_type": "luther_b2", + "device_group": "luther_eth", + "branch": ["master", "release"] + }, + { + "group_name": "dcs", + "slave_name": "eurtest_dcs", + "test_name": "dcs", + "identifier": "dcs_chirp", + "device_type": "chirp", + "device_group": "chirp", + "branch": ["master", "release"] + } +]
diff --git a/lab_system/master/config/tests/display_assistant_screen/display_assistant_screen.cfg b/lab_system/master/config/tests/display_assistant_screen/display_assistant_screen.cfg new file mode 100644 index 0000000..50603f6 --- /dev/null +++ b/lab_system/master/config/tests/display_assistant_screen/display_assistant_screen.cfg
@@ -0,0 +1,10 @@ +# Config file for display assistant screen tests. + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.display_assistant_screen.display_assistant_screen_test_case +# Name of the TestCase sub-class: +TEST_CASE_CLASS=DisplayAssistantScreenTestCase +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.framework.test_sequence +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=TestSequence
diff --git a/lab_system/master/config/tests/drm/drm.cfg b/lab_system/master/config/tests/drm/drm.cfg new file mode 100644 index 0000000..6c6cef1 --- /dev/null +++ b/lab_system/master/config/tests/drm/drm.cfg
@@ -0,0 +1,17 @@ +# Config file for JavaScript video tests. +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.drm.drm_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=DrmPlayreadySmoothTestCase,DrmPlayreadyTestCase,DrmTestCase,DrmUnprefixedTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.framework.javascript_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=JavascriptTestSequence + +
diff --git a/lab_system/master/config/tests/drm/test_defs.json b/lab_system/master/config/tests/drm/test_defs.json new file mode 100644 index 0000000..fbb425e --- /dev/null +++ b/lab_system/master/config/tests/drm/test_defs.json
@@ -0,0 +1,11 @@ +[ + { + "group_name": "drm", + "slave_name": "drm", + "test_name": "drm", + "identifier": "drm_cast_tv", + "device_type": "dragonfly", + "device_group": "av_drm", + "branch": ["cast_tv_dragonfly_master", "cast_tv_dragonfly_release", "cast_tv_dragonfly_next_release"] + } +]
diff --git a/lab_system/master/config/tests/e2e_latency/e2e_latency.cfg b/lab_system/master/config/tests/e2e_latency/e2e_latency.cfg new file mode 100644 index 0000000..c9f9ed1 --- /dev/null +++ b/lab_system/master/config/tests/e2e_latency/e2e_latency.cfg
@@ -0,0 +1,26 @@ +# Config file for Chirp End 2 End latency tests. +# +# Do not modify property names +# Run make reconfig if you change a value +# and buildbot is running +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.assistant.e2e_latency.e2e_query_latency_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=E2eQueryLatencyTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.assistant.e2e_latency.e2e_query_latency_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=E2eQueryLatencyTestSequence + +# Never backtrack so service-related failures have a +# chronological correspondence to build numbers. +BUILD_SELECTION_POLICY=always_use_latest + +# Use Tunnel where applicable +
diff --git a/lab_system/master/config/tests/e2e_latency/e2e_latency_reduced.cfg b/lab_system/master/config/tests/e2e_latency/e2e_latency_reduced.cfg new file mode 100644 index 0000000..c834bd3 --- /dev/null +++ b/lab_system/master/config/tests/e2e_latency/e2e_latency_reduced.cfg
@@ -0,0 +1,26 @@ +# Config file for Chirp End 2 End latency tests. +# +# Do not modify property names +# Run make reconfig if you change a value +# and buildbot is running +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.assistant.e2e_latency.e2e_query_latency_reduced_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=E2eQueryLatencyReducedTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.assistant.e2e_latency.e2e_query_latency_reduced_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=E2eQueryLatencyReducedTestSequence + +# Never backtrack so service-related failures have a +# chronological correspondence to build numbers. +BUILD_SELECTION_POLICY=always_use_latest + +# Use Tunnel where applicable +
diff --git a/lab_system/master/config/tests/e2e_latency/imx7d_e2e_latency.cfg b/lab_system/master/config/tests/e2e_latency/imx7d_e2e_latency.cfg new file mode 100644 index 0000000..14721c0 --- /dev/null +++ b/lab_system/master/config/tests/e2e_latency/imx7d_e2e_latency.cfg
@@ -0,0 +1,24 @@ +# Config file for Chirp End 2 End latency tests. +# +# Do not modify property names +# Run make reconfig if you change a value +# and buildbot is running +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.assistant.e2e_latency.e2e_query_latency_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=E2eQueryLatencyTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.assistant.e2e_latency.e2e_query_latency_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=E2eQueryLatencyTestSequence + +# Never backtrack so service-related failures have a +# chronological correspondence to build numbers. +BUILD_SELECTION_POLICY=always_use_latest +
diff --git a/lab_system/master/config/tests/e2e_latency/test_defs.json b/lab_system/master/config/tests/e2e_latency/test_defs.json new file mode 100644 index 0000000..16b5d95 --- /dev/null +++ b/lab_system/master/config/tests/e2e_latency/test_defs.json
@@ -0,0 +1,156 @@ +[ + { + "group_name": "e2e_latency", + "slave_name": "chirp_e2e_enclosures", + "test_name": "e2e_latency_reduced", + "identifier": "chirp_e2e_latency_reduced_master", + "device_type": "chirp_b3", + "device_group": "chirp_e2e_enclosure", + "branch": "master", + "scheduler": "30 * * * *", + "step_factories": [ + { + "step_description": "Allocates devices for the testrun", + "step_identifier": "device_allocation", + "step_factories": [ + { + "module_path": "lab_system.master.steps.factory.device.cloud_allocator", + "class_name": "TwoHourLeaseShortTimeoutAllocatorStepFactory" + } + ] + } + ] + }, + { + "group_name": "e2e_latency", + "slave_name": "chirp_e2e_enclosures", + "test_name": "e2e_latency_reduced", + "identifier": "chirp_e2e_latency_reduced_next_release", + "device_type": "chirp_b3", + "device_group": "chirp_e2e_enclosure", + "branch": "next_release", + "scheduler": "0 * * * *", + "step_factories": [ + { + "step_description": "Allocates devices for the testrun", + "step_identifier": "device_allocation", + "step_factories": [ + { + "module_path": "lab_system.master.steps.factory.device.cloud_allocator", + "class_name": "TwoHourLeaseShortTimeoutAllocatorStepFactory" + } + ] + } + ] + }, + { + "group_name": "e2e_latency", + "slave_name": "chirp_e2e_enclosures", + "test_name": "e2e_latency_reduced", + "identifier": "chirp_e2e_latency_reduced_release", + "device_type": "chirp_b3", + "device_group": "chirp_e2e_enclosure", + "branch": "release", + "scheduler": "30 0,6,12,18 * * *", + "step_factories": [ + { + "step_description": "Allocates devices for the testrun", + "step_identifier": "device_allocation", + "step_factories": [ + { + "module_path": "lab_system.master.steps.factory.device.cloud_allocator", + "class_name": "TwoHourLeaseShortTimeoutAllocatorStepFactory" + } + ] + } + ] + }, + { + "group_name": "e2e_latency", + "slave_name": "joplin_e2e_enclosures", + "test_name": "e2e_latency_reduced", + "identifier": "joplin_e2e_latency_reduced_master", + "device_type": "joplin", + "device_group": "joplin_e2e_enclosure", + "branch": "master", + "scheduler": "30 * * * *", + "step_factories": [ + { + "step_description": "Allocates devices for the testrun", + "step_identifier": "device_allocation", + "step_factories": [ + { + "module_path": "lab_system.master.steps.factory.device.cloud_allocator", + "class_name": "TwoHourLeaseShortTimeoutAllocatorStepFactory" + } + ] + } + ] + }, + { + "group_name": "e2e_latency", + "slave_name": "joplin_e2e_enclosures", + "test_name": "e2e_latency_reduced", + "identifier": "joplin_e2e_latency_reduced_next_release", + "device_type": "joplin", + "device_group": "joplin_e2e_enclosure", + "branch": "1_28a", + "scheduler": "0 * * * *", + "step_factories": [ + { + "step_description": "Allocates devices for the testrun", + "step_identifier": "device_allocation", + "step_factories": [ + { + "module_path": "lab_system.master.steps.factory.device.cloud_allocator", + "class_name": "TwoHourLeaseShortTimeoutAllocatorStepFactory" + } + ] + } + ] + }, + { + "group_name": "e2e_latency", + "slave_name": "biggie_e2e_enclosures", + "test_name": "e2e_latency_reduced", + "identifier": "biggie_e2e_latency_reduced_master", + "device_type": "biggie", + "device_group": "biggie_e2e_enclosure", + "branch": "master", + "scheduler": "30 * * * *", + "step_factories": [ + { + "step_description": "Allocates devices for the testrun", + "step_identifier": "device_allocation", + "step_factories": [ + { + "module_path": "lab_system.master.steps.factory.device.cloud_allocator", + "class_name": "TwoHourLeaseShortTimeoutAllocatorStepFactory" + } + ] + } + ] + }, + { + "group_name": "e2e_latency", + "slave_name": "biggie_e2e_enclosures", + "test_name": "e2e_latency_reduced", + "identifier": "biggie_e2e_latency_reduced_next_release", + "device_type": "biggie", + "device_group": "biggie_e2e_enclosure", + "branch": "next_release", + "scheduler": "0 * * * *", + "step_factories": [ + { + "step_description": "Allocates devices for the testrun", + "step_identifier": "device_allocation", + "step_factories": [ + { + "module_path": "lab_system.master.steps.factory.device.cloud_allocator", + "class_name": "TwoHourLeaseShortTimeoutAllocatorStepFactory" + } + ] + } + ] + } +]
diff --git a/lab_system/master/config/tests/eraser_for_hotword/eraser.cfg b/lab_system/master/config/tests/eraser_for_hotword/eraser.cfg new file mode 100644 index 0000000..42b5d20 --- /dev/null +++ b/lab_system/master/config/tests/eraser_for_hotword/eraser.cfg
@@ -0,0 +1,32 @@ +# Config file for Eraser tests on Biggie. +# +# Do not modify property names +# Run make reconfig if you change a value +# and buildbot is running +# +# PROPERTIES + +# Device options +CHIRP_VOL_MIN=0 +CHIRP_VOL_MAX=11 +CHIRP_VOL_STEP=1 +RPI_VOL_MIN=1 +RPI_VOL_MAX=100 + +# Indicates whether or not we should sign the device in +SIGNED_IN=True + +# Use Tunnel where applicable +TCP_TUNNEL_TIMEOUT_SECS=1800 + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=EraserForHotwordTestCase + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.assistant.eraser.eraser_for_hotword_test_case + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=EraserForHotwordTestSequence + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.assistant.eraser.eraser_for_hotword_test_sequence
diff --git a/lab_system/master/config/tests/eraser_for_hotword/eraser_alignment.cfg b/lab_system/master/config/tests/eraser_for_hotword/eraser_alignment.cfg new file mode 100644 index 0000000..274a56a --- /dev/null +++ b/lab_system/master/config/tests/eraser_for_hotword/eraser_alignment.cfg
@@ -0,0 +1,24 @@ +# Config file for Eraser alignment tests. +# +# Do not modify property names +# Run make reconfig if you change a value +# and buildbot is running +# +# PROPERTIES + +ENABLE_CAST_WITHOUT_SIGN_IN=True + +# Indicates whether or not we should sign the device in +SIGNED_IN=True + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=EraserAlignmentTestCase + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.assistant.eraser.eraser_alignment_test_case + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=EraserAlignmentTestSequence + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.assistant.eraser.eraser_alignment_test_sequence \ No newline at end of file
diff --git a/lab_system/master/config/tests/eraser_for_hotword/eraser_alignment_fuchsia.cfg b/lab_system/master/config/tests/eraser_for_hotword/eraser_alignment_fuchsia.cfg new file mode 100644 index 0000000..03bba24 --- /dev/null +++ b/lab_system/master/config/tests/eraser_for_hotword/eraser_alignment_fuchsia.cfg
@@ -0,0 +1,19 @@ +# Config file for Eraser alignment tests. +# +# Do not modify property names +# Run make reconfig if you change a value +# and buildbot is running +# +# PROPERTIES + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=EraserAlignmentTestCase + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.assistant.eraser.eraser_alignment_test_case + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=FuchsiaEraserAlignmentTestSequence + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.assistant.eraser.fuchsia_eraser_alignment_test_sequence \ No newline at end of file
diff --git a/lab_system/master/config/tests/eraser_for_hotword/eraser_fuchsia.cfg b/lab_system/master/config/tests/eraser_for_hotword/eraser_fuchsia.cfg new file mode 100644 index 0000000..c692c99 --- /dev/null +++ b/lab_system/master/config/tests/eraser_for_hotword/eraser_fuchsia.cfg
@@ -0,0 +1,29 @@ +# Config file for Eraser tests on Fuchsia. +# +# Do not modify property names +# Run make reconfig if you change a value +# and buildbot is running +# +# PROPERTIES + +# Device options +CHIRP_VOL_MIN=0 +CHIRP_VOL_MAX=11 +CHIRP_VOL_STEP=1 +RPI_VOL_MIN=1 +RPI_VOL_MAX=100 + +# Use Tunnel where applicable +TCP_TUNNEL_TIMEOUT_SECS=1800 + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=EraserForHotwordTestCase + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.assistant.eraser.eraser_for_hotword_test_case + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=FuchsiaEraserForHotwordTestSequence + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.assistant.eraser.fuchsia_eraser_for_hotword_test_sequence
diff --git a/lab_system/master/config/tests/eraser_for_hotword/eraser_realignment.cfg b/lab_system/master/config/tests/eraser_for_hotword/eraser_realignment.cfg new file mode 100644 index 0000000..ac1965c --- /dev/null +++ b/lab_system/master/config/tests/eraser_for_hotword/eraser_realignment.cfg
@@ -0,0 +1,22 @@ +# Config file for Eraser Realignment test. +# +# Do not modify property names +# Run make reconfig if you change a value +# and buildbot is running +# +# PROPERTIES + +# Indicates whether or not we should sign the device in +SIGNED_IN=True + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.assistant.eraser.eraser_alignment_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=EraserRealignmentTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.assistant.eraser.eraser_alignment_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=EraserRealignmentTestSequence
diff --git a/lab_system/master/config/tests/eraser_for_hotword/eraser_reset_realignment.cfg b/lab_system/master/config/tests/eraser_for_hotword/eraser_reset_realignment.cfg new file mode 100644 index 0000000..8b8d719 --- /dev/null +++ b/lab_system/master/config/tests/eraser_for_hotword/eraser_reset_realignment.cfg
@@ -0,0 +1,22 @@ +# Config file for Eraser Realignment test. +# +# Do not modify property names +# Run make reconfig if you change a value +# and buildbot is running +# +# PROPERTIES + +# Indicates whether or not we should sign the device in +SIGNED_IN=True + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.assistant.eraser.eraser_alignment_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=EraserResetRealignmentTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.assistant.eraser.eraser_alignment_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=EraserResetRealignmentTestSequence
diff --git a/lab_system/master/config/tests/eraser_for_hotword/eraser_reset_realignment_fuchsia.cfg b/lab_system/master/config/tests/eraser_for_hotword/eraser_reset_realignment_fuchsia.cfg new file mode 100644 index 0000000..7769e92 --- /dev/null +++ b/lab_system/master/config/tests/eraser_for_hotword/eraser_reset_realignment_fuchsia.cfg
@@ -0,0 +1,19 @@ +# Config file for Eraser Realignment test. +# +# Do not modify property names +# Run make reconfig if you change a value +# and buildbot is running +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.assistant.eraser.eraser_alignment_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=EraserResetRealignmentTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.assistant.eraser.fuchsia_eraser_alignment_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=FuchsiaEraserResetRealignmentTestSequence
diff --git a/lab_system/master/config/tests/eraser_for_hotword/eraser_suppression.cfg b/lab_system/master/config/tests/eraser_for_hotword/eraser_suppression.cfg new file mode 100644 index 0000000..00c91fb --- /dev/null +++ b/lab_system/master/config/tests/eraser_for_hotword/eraser_suppression.cfg
@@ -0,0 +1,22 @@ +# Config file for Eraser suppression tests. +# +# Do not modify property names +# Run make reconfig if you change a value +# and buildbot is running +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.assistant.eraser.eraser_suppression_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=EraserAlignmentSuppressionTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.assistant.eraser.eraser_suppression_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=EraserAlignmentSuppressionTestSequence + + +ENABLE_CAST_WITHOUT_SIGN_IN=True
diff --git a/lab_system/master/config/tests/eraser_for_hotword/test_defs.json b/lab_system/master/config/tests/eraser_for_hotword/test_defs.json new file mode 100644 index 0000000..80dfde5 --- /dev/null +++ b/lab_system/master/config/tests/eraser_for_hotword/test_defs.json
@@ -0,0 +1,156 @@ +[ + { + "group_name": "eraser_for_hotword", + "slave_name": "chirp_eraser_linda_vista", + "test_name": "eraser", + "identifier": "chirp_eraser_linda_vista_master", + "device_type": "chirp_b3", + "device_group": "chirp_eraser_linda_vista", + "branch": "master", + "scheduler": "0 0,3,6,9,12,15,18,21 * * *", + "step_factories": [ + { + "step_description": "Allocates devices for the testrun", + "step_identifier": "device_allocation", + "step_factories": [ + { + "module_path": "lab_system.master.steps.factory.device.cloud_allocator", + "class_name": "TwoHourLeaseShortTimeoutAllocatorStepFactory" + } + ] + } + ] + }, + { + "group_name": "eraser_for_hotword", + "slave_name": "chirp_eraser_linda_vista", + "test_name": "eraser", + "identifier": "chirp_eraser_linda_vista_next_release", + "device_type": "chirp_b3", + "device_group": "chirp_eraser_linda_vista", + "branch": "next_release", + "scheduler": "0 1,4,7,10,13,16,19,22 * * *", + "step_factories": [ + { + "step_description": "Allocates devices for the testrun", + "step_identifier": "device_allocation", + "step_factories": [ + { + "module_path": "lab_system.master.steps.factory.device.cloud_allocator", + "class_name": "TwoHourLeaseShortTimeoutAllocatorStepFactory" + } + ] + } + ] + }, + { + "group_name": "eraser_for_hotword", + "slave_name": "chirp_eraser_linda_vista", + "test_name": "eraser", + "identifier": "chirp_eraser_linda_vista_release", + "device_type": "chirp_b3", + "device_group": "chirp_eraser_linda_vista", + "branch": "release", + "scheduler": "0 2,5,8,11,14,17,20,23 * * *", + "step_factories": [ + { + "step_description": "Allocates devices for the testrun", + "step_identifier": "device_allocation", + "step_factories": [ + { + "module_path": "lab_system.master.steps.factory.device.cloud_allocator", + "class_name": "TwoHourLeaseShortTimeoutAllocatorStepFactory" + } + ] + } + ] + }, + { + "group_name": "eraser_for_hotword", + "slave_name": "joplin_eraser_linda_vista", + "test_name": "eraser", + "identifier": "joplin_eraser_linda_vista_master", + "device_type": "joplin", + "device_group": "joplin_eraser_linda_vista", + "branch": "master", + "scheduler": "0 0,2,4,6,8,10,12,14,16,18,20,22 * * *", + "step_factories": [ + { + "step_description": "Allocates devices for the testrun", + "step_identifier": "device_allocation", + "step_factories": [ + { + "module_path": "lab_system.master.steps.factory.device.cloud_allocator", + "class_name": "TwoHourLeaseShortTimeoutAllocatorStepFactory" + } + ] + } + ] + }, + { + "group_name": "eraser_for_hotword", + "slave_name": "joplin_eraser_linda_vista", + "test_name": "eraser", + "identifier": "joplin_eraser_linda_vista_next_release", + "device_type": "joplin", + "device_group": "joplin_eraser_linda_vista", + "branch": "1_28a", + "scheduler": "0 1,3,5,7,9,11,13,15,17,19,21,23 * * *", + "step_factories": [ + { + "step_description": "Allocates devices for the testrun", + "step_identifier": "device_allocation", + "step_factories": [ + { + "module_path": "lab_system.master.steps.factory.device.cloud_allocator", + "class_name": "TwoHourLeaseShortTimeoutAllocatorStepFactory" + } + ] + } + ] + }, + { + "group_name": "eraser_for_hotword", + "slave_name": "biggie_eraser_linda_vista", + "test_name": "eraser", + "identifier": "biggie_eraser_linda_vista_master", + "device_type": "biggie_b3", + "device_group": "biggie_eraser_linda_vista", + "branch": "master", + "scheduler": "0 0,2,4,18,20,22 * * *", + "step_factories": [ + { + "step_description": "Allocates devices for the testrun", + "step_identifier": "device_allocation", + "step_factories": [ + { + "module_path": "lab_system.master.steps.factory.device.cloud_allocator", + "class_name": "TwoHourLeaseShortTimeoutAllocatorStepFactory" + } + ] + } + ] + }, + { + "group_name": "eraser_for_hotword", + "slave_name": "biggie_eraser_linda_vista", + "test_name": "eraser", + "identifier": "biggie_eraser_linda_vista_eraser_next_release", + "device_type": "biggie_b3", + "device_group": "biggie_eraser_linda_vista", + "branch": "next_release", + "scheduler": "0 1,3,19,21,23 * * *", + "step_factories": [ + { + "step_description": "Allocates devices for the testrun", + "step_identifier": "device_allocation", + "step_factories": [ + { + "module_path": "lab_system.master.steps.factory.device.cloud_allocator", + "class_name": "TwoHourLeaseShortTimeoutAllocatorStepFactory" + } + ] + } + ] + } +]
diff --git a/lab_system/master/config/tests/factory/fct_biggie.cfg b/lab_system/master/config/tests/factory/fct_biggie.cfg new file mode 100644 index 0000000..d0b7774 --- /dev/null +++ b/lab_system/master/config/tests/factory/fct_biggie.cfg
@@ -0,0 +1,29 @@ +# Config file for factory tests using biggie. +# +# PROPERTIES +USER_NAME=root +# Test work directory on remote slave +REMOTE_FCT_TEST_DIR=/root/biggie_fct +REMOTE_FCT_LOAD_SCRIPT=/root/biggie_fct/aml-usb-boot/linux/aml-usb-fct-boot.sh +FCT_BUILD_INSTALLER_PATH=/usr/local/google/repositories/HEAD/test/ota/fct_update.py +# Scripts path avialable on the target device. +FCT_SCRIPT_NAME=/home/flex/bin/fct.sh +FCT_USE_ADB_SHELL=True + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.factory.fct_hw_test_cases + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=FctHwCheckTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.factory.fct_test_sequence + +# # Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=FctTestSequence + +# Devices group +DEVICES_GROUP=fct_test_box + +# Use Tunnel where applicable +
diff --git a/lab_system/master/config/tests/factory/test_defs.json b/lab_system/master/config/tests/factory/test_defs.json new file mode 100644 index 0000000..288c0df --- /dev/null +++ b/lab_system/master/config/tests/factory/test_defs.json
@@ -0,0 +1,13 @@ +[ + { + "branch": ["master", "1_28_factory"], + "build_flavor": "eng", + "device_group": "fct_test_box", + "device_type": "biggie", + "identifier": "fct_biggie", + "slave_name": "factory", + "group_name": "factory", + "test_name": "fct_biggie", + "step_factories_recipe": "step_factories_recipes/fct_test_recipe.json" + } +]
diff --git a/lab_system/master/config/tests/fakeoculus_reconnect_proxy/fakeoculus_reconnect_proxy.cfg b/lab_system/master/config/tests/fakeoculus_reconnect_proxy/fakeoculus_reconnect_proxy.cfg new file mode 100644 index 0000000..947fff5 --- /dev/null +++ b/lab_system/master/config/tests/fakeoculus_reconnect_proxy/fakeoculus_reconnect_proxy.cfg
@@ -0,0 +1,22 @@ +# Configuration values for FakeOculus Reconnect Proxy test. +# +# PROPERTIES +# Name of the TestCase sub-class: +TEST_CASE_CLASS=FakeOculusReconnectTestCase + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.fakeoculus_reconnect_proxy.fakeoculus_reconnect_test_case + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=FakeoculusReconnectTestSequence + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.fakeoculus_reconnect_proxy.fakeoculus_reconnect_test_sequence + +# If running in the lab, set to True as it will use the LAB default +# IP instead of using shortleash gateway IP +LAB_HOST_IP=true + +# Specifies which folder to consider for JSON test flow files. +# This is under the fakeoculus_test_scenarios folder. +TEST_JSON_LOCATION=functional_tests \ No newline at end of file
diff --git a/lab_system/master/config/tests/fakeoculus_reconnect_proxy/fakeoculus_stress_tests.cfg b/lab_system/master/config/tests/fakeoculus_reconnect_proxy/fakeoculus_stress_tests.cfg new file mode 100644 index 0000000..e3caff5 --- /dev/null +++ b/lab_system/master/config/tests/fakeoculus_reconnect_proxy/fakeoculus_stress_tests.cfg
@@ -0,0 +1,22 @@ +# Configuration values for FakeOculus Reconnect Proxy test. +# +# PROPERTIES +# Name of the TestCase sub-class: +TEST_CASE_CLASS=FakeOculusReconnectStressTestCase + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.fakeoculus_reconnect_proxy.fakeoculus_reconnect_test_case + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=FakeoculusReconnectTestSequence + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.fakeoculus_reconnect_proxy.fakeoculus_reconnect_test_sequence + +# If running in the lab, set to True as it will use the LAB default +# IP instead of using shortleash gateway IP +LAB_HOST_IP=true + +# Specifies which folder to consider for JSON test flow files. +# This is under the fakeoculus_test_scenarios folder. +TEST_JSON_LOCATION=stream_stress_tests \ No newline at end of file
diff --git a/lab_system/master/config/tests/fdr/fdr.cfg b/lab_system/master/config/tests/fdr/fdr.cfg new file mode 100644 index 0000000..c9a5386 --- /dev/null +++ b/lab_system/master/config/tests/fdr/fdr.cfg
@@ -0,0 +1,18 @@ +# Config file for FDR tests. +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.fdr.fdr_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=FdrTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.framework.disabled_logging_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=DisabledLoggingTestSequence + +# Use Tunnel where applicable +
diff --git a/lab_system/master/config/tests/fuchsia_audio_formats/fuchsia_audio_formats.cfg b/lab_system/master/config/tests/fuchsia_audio_formats/fuchsia_audio_formats.cfg new file mode 100644 index 0000000..6297ef0 --- /dev/null +++ b/lab_system/master/config/tests/fuchsia_audio_formats/fuchsia_audio_formats.cfg
@@ -0,0 +1,14 @@ +# Config file for JavaScript audio format tests on Fuchsia devices. +# +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.audio_formats.audio_formats_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=SupportedAudioFormatsTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.framework.fuchsia_javascript_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=FuchsiaJavascriptTestSequence +
diff --git a/lab_system/master/config/tests/fuchsia_drm/fuchsia_drm.cfg b/lab_system/master/config/tests/fuchsia_drm/fuchsia_drm.cfg new file mode 100644 index 0000000..ab47016 --- /dev/null +++ b/lab_system/master/config/tests/fuchsia_drm/fuchsia_drm.cfg
@@ -0,0 +1,16 @@ +# Config file for JavaScript tests on Fuchsia devices. +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.drm.fuchsia_drm_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=FuchsiaDrmTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.framework.fuchsia_javascript_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=FuchsiaJavascriptTestSequence +
diff --git a/lab_system/master/config/tests/fuchsia_gunit/fuchsia_gunit.cfg b/lab_system/master/config/tests/fuchsia_gunit/fuchsia_gunit.cfg new file mode 100644 index 0000000..dbdcf73 --- /dev/null +++ b/lab_system/master/config/tests/fuchsia_gunit/fuchsia_gunit.cfg
@@ -0,0 +1,14 @@ +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.fuchsia_gunit.fuchsia_gunit_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=FuchsiagUnitTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.fuchsia_gunit.fuchsia_gunit_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=FuchsiagUnitTestSequence +ITERATION_COUNT=10
diff --git a/lab_system/master/config/tests/fuchsia_migration/fuchsia_migration.cfg b/lab_system/master/config/tests/fuchsia_migration/fuchsia_migration.cfg new file mode 100644 index 0000000..116131d --- /dev/null +++ b/lab_system/master/config/tests/fuchsia_migration/fuchsia_migration.cfg
@@ -0,0 +1,22 @@ +# Config file for OTA update test suite on master branch. +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.fuchsia_migration.fuchsia_migration_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=FuchsiaMigrationTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.fuchsia_migration.fuchsia_migration_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=FuchsiaMigrationTestSequence + +# OTA update master version. fetcher will use the value to download latest OTA. +BRANCH_TO_TEST=master + +BUILD_SIGNATURE=dev_signed + +USE_WIFI=True
diff --git a/lab_system/master/config/tests/gating/dcs.cfg b/lab_system/master/config/tests/gating/dcs.cfg new file mode 100644 index 0000000..4748ac6 --- /dev/null +++ b/lab_system/master/config/tests/gating/dcs.cfg
@@ -0,0 +1,17 @@ +# Configuration values for the dcs test. +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.dcs.dcs_e2e_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=DcsE2eTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.framework.test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=TestSequence + +
diff --git a/lab_system/master/config/tests/gating/fdr.cfg b/lab_system/master/config/tests/gating/fdr.cfg new file mode 100644 index 0000000..c9a5386 --- /dev/null +++ b/lab_system/master/config/tests/gating/fdr.cfg
@@ -0,0 +1,18 @@ +# Config file for FDR tests. +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.fdr.fdr_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=FdrTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.framework.disabled_logging_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=DisabledLoggingTestSequence + +# Use Tunnel where applicable +
diff --git a/lab_system/master/config/tests/gating/hs3_assistant_test.cfg b/lab_system/master/config/tests/gating/hs3_assistant_test.cfg new file mode 100644 index 0000000..5a09d15 --- /dev/null +++ b/lab_system/master/config/tests/gating/hs3_assistant_test.cfg
@@ -0,0 +1,17 @@ +# Config file for hermetic S3 smoke tests. +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.assistant.hs3_assistant_test.hs3_assistant_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=Hs3AssistantTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.assistant.hs3_assistant_test.hs3_assistant_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=Hs3AssistantTestSequence + +BUILD_SELECTION_POLICY=backtrack_then_latest
diff --git a/lab_system/master/config/tests/gating/ota_update.cfg b/lab_system/master/config/tests/gating/ota_update.cfg new file mode 100644 index 0000000..b9d8d3a --- /dev/null +++ b/lab_system/master/config/tests/gating/ota_update.cfg
@@ -0,0 +1,23 @@ +# Config file for OTA update test suite on master branch. +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.ota_update.ota_update_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=OtaUpdateTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.framework.disabled_logging_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=DisabledLoggingTestSequence + +# Get second to latest build +BUILD_SELECTION_POLICY=second_to_latest + +# OTA update master version. fetcher will use the value to download latest OTA. +BRANCH_TO_TEST=master + +
diff --git a/lab_system/master/config/tests/gating/receiver.cfg b/lab_system/master/config/tests/gating/receiver.cfg new file mode 100644 index 0000000..df33a7c --- /dev/null +++ b/lab_system/master/config/tests/gating/receiver.cfg
@@ -0,0 +1,41 @@ +# Config file for the Cast receiver tests +# +# Do not modify property names +# Run make reconfig if you change a value +# and buildbot is running +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.cast.receiver.compliance_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=CastReceiverComplianceTestCase,CastReceiverMultipleSendersTestCase,CastReceiverVolumeControlTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.framework.test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=TestSequence + +# Receiver app ids: +CAST_V2_DEBUG_APP_ID=C566BECD +CAST_V2_PLAYER_APP_ID=BE6E4473 +CHROME_MIRRORING_APP_ID=0F5096E8 + +# Test specific configuration values: +MP4_MEDIA_URL=https://home-media-server.sandbox.google.com/static/receiver/mp4/bbb_1080p_30fps_x264_high_41_mp3.mp4 +MP4_MEDIA_MIME_TYPE=video/mp4 +DASH_MEDIA_URL=https://home-media-server.sandbox.google.com/static/receiver/dash/sample-dash-list.mpd +DASH_MEDIA_MIME_TYPE=application/dash+xml +HLS_MEDIA_URL=https://home-media-server.sandbox.google.com/static/receiver/hls/bbb/bbb_hls.m3u8 +HLS_MEDIA_MIME_TYPE=application/x-mpegurl +SMOOTH_STREAMING_MEDIA_URL=https://home-media-server.sandbox.google.com/static/receiver/smooth/BBB_H264_AACL/big_buck_bunny_1080p_stereo.ism/manifest +SMOOTH_STREAMING_MEDIA_MIME_TYPE=application/vnd.ms-sstr+xml +MEDIA_LOAD_TIMEOUT_SECS=30 + +# This config is used to determine if cast operations should be allowed even if +# device is not signed-in using a gaia account. +ENABLE_CAST_WITHOUT_SIGN_IN=True + +
diff --git a/lab_system/master/config/tests/gating/receiver_c4a.cfg b/lab_system/master/config/tests/gating/receiver_c4a.cfg new file mode 100644 index 0000000..3450125 --- /dev/null +++ b/lab_system/master/config/tests/gating/receiver_c4a.cfg
@@ -0,0 +1,46 @@ +# Config file for the Cast receiver tests on audio devices +# +# Do not modify property names +# Run make reconfig if you change a value +# and buildbot is running +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.cast.receiver.compliance_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=CastReceiverComplianceTestCase,CastReceiverMultipleSendersTestCase,CastReceiverVolumeControlTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.framework.test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=TestSequence + +# Receiver app ids: +CAST_V2_DEBUG_APP_ID=C566BECD +CAST_V2_PLAYER_APP_ID=BE6E4473 +CHROME_MIRRORING_APP_ID=85CDB22F + +# Test specific configuration values: +MP4_MEDIA_URL=https://storage.googleapis.com/cast_media/format_tests/audio/stereo_guitar.mp3 +MP4_MEDIA_MIME_TYPE=video/mp4 + +# Temporary fix +DASH_MEDIA_URL=https://home-media-server.sandbox.google.com/static/receiver/dash/sample-dash-list.mpd +DASH_MEDIA_MIME_TYPE=application/dash+xml +HLS_MEDIA_URL=https://home-media-server.sandbox.google.com/static/receiver/hls/bbb/bbb_hls.m3u8 +HLS_MEDIA_MIME_TYPE=application/x-mpegurl +SMOOTH_STREAMING_MEDIA_URL=https://home-media-server.sandbox.google.com/static/receiver/smooth/BBB_H264_AACL/big_buck_bunny_1080p_stereo.ism/manifest +SMOOTH_STREAMING_MEDIA_MIME_TYPE=application/vnd.ms-sstr+xml + +MEDIA_LOAD_TIMEOUT_SECS=30 + +# Flag to skip tests that require a display and can't be run in C4A devices. +NO_DISPLAY=1 + +# This config is used to determine if cast operations should be allowed even if +# device is not signed-in using a gaia account. +ENABLE_CAST_WITHOUT_SIGN_IN=True +
diff --git a/lab_system/master/config/tests/gating/setup.cfg b/lab_system/master/config/tests/gating/setup.cfg new file mode 100644 index 0000000..fb80ae7 --- /dev/null +++ b/lab_system/master/config/tests/gating/setup.cfg
@@ -0,0 +1,20 @@ +# Config file for setup tests +# +# Do not modify property names +# Run make reconfig if you change a value +# and buildbot is running +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.setup.setup_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=SetupTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.framework.test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=TestSequence +
diff --git a/lab_system/master/config/tests/gating/setup_api_wifi.cfg b/lab_system/master/config/tests/gating/setup_api_wifi.cfg new file mode 100644 index 0000000..1e014a4 --- /dev/null +++ b/lab_system/master/config/tests/gating/setup_api_wifi.cfg
@@ -0,0 +1,19 @@ +# Config file for setup tests +# +# Do not modify property names +# Run make reconfig if you change a value +# and buildbot is running +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.setup_api_wifi.setup_api_wifi_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=SetupApiWifiTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.framework.disabled_logging_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=DisabledLoggingCollectLogcatTestSequence
diff --git a/lab_system/master/config/tests/gating/setup_reboot.cfg b/lab_system/master/config/tests/gating/setup_reboot.cfg new file mode 100644 index 0000000..bd43770 --- /dev/null +++ b/lab_system/master/config/tests/gating/setup_reboot.cfg
@@ -0,0 +1,21 @@ +# Config file for setup reboot tests +# +# Do not modify property names +# Run make reconfig if you change a value +# and buildbot is running +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.setup.setup_reboot_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=SetupRebootTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.framework.disabled_logging_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=DisabledLoggingCollectLogcatTestSequence + +
diff --git a/lab_system/master/config/tests/gating/volume.cfg b/lab_system/master/config/tests/gating/volume.cfg new file mode 100644 index 0000000..7ed8b1f --- /dev/null +++ b/lab_system/master/config/tests/gating/volume.cfg
@@ -0,0 +1,17 @@ +# Config file for JavaScript video tests. +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.volume.volume_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=VolumeTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.framework.javascript_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=JavascriptTestSequence + +
diff --git a/lab_system/master/config/tests/gqnq_contract_executor/gqnq_contract_executor_paired.cfg b/lab_system/master/config/tests/gqnq_contract_executor/gqnq_contract_executor_paired.cfg new file mode 100644 index 0000000..74cdc9a --- /dev/null +++ b/lab_system/master/config/tests/gqnq_contract_executor/gqnq_contract_executor_paired.cfg
@@ -0,0 +1,18 @@ +# Configuration values for NTI Contract Exec test. +# +# PROPERTIES +# Name of the TestCase sub-class: +TEST_CASE_CLASS=PairedNTIContractTestCase + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.gqnq_contract_executor.nti_contract_exec_test_case + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=NTIContractExecTestSequence + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.gqnq_contract_executor.nti_contract_exec_sequence + +# Points to the folder containing JSON contracts in the GCS bucket +# gs://cast-test-data/nti_contract_executor +TEST_JSON_LOCATION=test_contracts/paired_tests
diff --git a/lab_system/master/config/tests/gqnq_contract_executor/gqnq_contract_executor_presubmit.cfg b/lab_system/master/config/tests/gqnq_contract_executor/gqnq_contract_executor_presubmit.cfg new file mode 100644 index 0000000..bd52cb3 --- /dev/null +++ b/lab_system/master/config/tests/gqnq_contract_executor/gqnq_contract_executor_presubmit.cfg
@@ -0,0 +1,18 @@ +# Configuration values for NTI Contract Exec test. +# +# PROPERTIES +# Name of the TestCase sub-class: +TEST_CASE_CLASS=NTIContractExecTestCase + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.gqnq_contract_executor.nti_contract_exec_test_case + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=NTIContractExecTestSequence + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.gqnq_contract_executor.nti_contract_exec_sequence + +# Points to the folder containing JSON contracts in the GCS bucket +# gs://cast-test-data/nti_contract_executor +TEST_JSON_LOCATION=test_contracts/presubmit_unpaired_tests
diff --git a/lab_system/master/config/tests/gqnq_contract_executor/gqnq_contract_executor_unpaired.cfg b/lab_system/master/config/tests/gqnq_contract_executor/gqnq_contract_executor_unpaired.cfg new file mode 100644 index 0000000..a1e6e84 --- /dev/null +++ b/lab_system/master/config/tests/gqnq_contract_executor/gqnq_contract_executor_unpaired.cfg
@@ -0,0 +1,18 @@ +# Configuration values for NTI Contract Exec test. +# +# PROPERTIES +# Name of the TestCase sub-class: +TEST_CASE_CLASS=UnpairedNTIContractTestCase + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.gqnq_contract_executor.nti_contract_exec_test_case + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=NTIContractExecTestSequence + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.gqnq_contract_executor.nti_contract_exec_sequence + +# Points to the folder containing JSON contracts in the GCS bucket +# gs://cast-test-data/nti_contract_executor +TEST_JSON_LOCATION=test_contracts/unpaired_tests
diff --git a/lab_system/master/config/tests/gqnq_contract_executor/gqnq_contract_executor_virtual_paired.cfg b/lab_system/master/config/tests/gqnq_contract_executor/gqnq_contract_executor_virtual_paired.cfg new file mode 100644 index 0000000..b1d4498 --- /dev/null +++ b/lab_system/master/config/tests/gqnq_contract_executor/gqnq_contract_executor_virtual_paired.cfg
@@ -0,0 +1,18 @@ +# Configuration values for Virtual NTI Contract Exec test. +# +# PROPERTIES +# Name of the TestCase sub-class: +TEST_CASE_CLASS=PairedVirtualNTIContractTestCase + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.gqnq_contract_executor.nti_contract_exec_test_case + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=NTIContractExecVirtualTestSequence + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.gqnq_contract_executor.nti_contract_exec_sequence + +# Points to the folder containing JSON contracts in the GCS bucket +# gs://cast-test-data/nti_contract_executor +TEST_JSON_LOCATION=test_contracts/paired_tests
diff --git a/lab_system/master/config/tests/gqnq_contract_executor/gqnq_contract_executor_virtual_presubmit.cfg b/lab_system/master/config/tests/gqnq_contract_executor/gqnq_contract_executor_virtual_presubmit.cfg new file mode 100644 index 0000000..ed4d6ef --- /dev/null +++ b/lab_system/master/config/tests/gqnq_contract_executor/gqnq_contract_executor_virtual_presubmit.cfg
@@ -0,0 +1,18 @@ +# Configuration values for Virtual NTI Contract Exec test. +# +# PROPERTIES +# Name of the TestCase sub-class: +TEST_CASE_CLASS=UnpairedVirtualNTIContractTestCase + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.gqnq_contract_executor.nti_contract_exec_test_case + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=NTIContractExecVirtualTestSequence + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.gqnq_contract_executor.nti_contract_exec_sequence + +# Points to the folder containing JSON contracts in the GCS bucket +# gs://cast-test-data/nti_contract_executor +TEST_JSON_LOCATION=test_contracts/presubmit_unpaired_tests
diff --git a/lab_system/master/config/tests/gqnq_contract_executor/gqnq_contract_executor_virtual_unpaired.cfg b/lab_system/master/config/tests/gqnq_contract_executor/gqnq_contract_executor_virtual_unpaired.cfg new file mode 100644 index 0000000..857f5aa --- /dev/null +++ b/lab_system/master/config/tests/gqnq_contract_executor/gqnq_contract_executor_virtual_unpaired.cfg
@@ -0,0 +1,18 @@ +# Configuration values for Virtual NTI Contract Exec test. +# +# PROPERTIES +# Name of the TestCase sub-class: +TEST_CASE_CLASS=UnpairedVirtualNTIContractTestCase + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.gqnq_contract_executor.nti_contract_exec_test_case + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=NTIContractExecVirtualTestSequence + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.gqnq_contract_executor.nti_contract_exec_sequence + +# Points to the folder containing JSON contracts in the GCS bucket +# gs://cast-test-data/nti_contract_executor +TEST_JSON_LOCATION=test_contracts/unpaired_tests
diff --git a/lab_system/master/config/tests/hotmatch_samples_regression/hotmatch_samples_regression.cfg b/lab_system/master/config/tests/hotmatch_samples_regression/hotmatch_samples_regression.cfg new file mode 100644 index 0000000..3d49662 --- /dev/null +++ b/lab_system/master/config/tests/hotmatch_samples_regression/hotmatch_samples_regression.cfg
@@ -0,0 +1,40 @@ +# Config file for hotmatch samples regression on conducted audio. +# +# Do not modify property names +# Run make reconfig if you change a value +# and buildbot is running +# +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.assistant.hotmatch_samples_regression.hotmatch_samples_regression_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=HotmatchSamplesRegressionTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.assistant.hotmatch_samples_regression.hotmatch_samples_regression_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=HotmatchSamplesRegressionTestSequence + +# PROPERTIES +# Location of wav files on RPI +HOTMATCH_SERVER_DIR=/home/pi/hotmatch_samples/server +HOTMATCH_DEVICE_DIR=/home/pi/hotmatch_samples/device + +# Type of Hotword samples being tested. +SAMPLE_TYPE=HotmatchSamples + +# Indicates whether or not we should sign the device in +SIGNED_IN=True + +# Test suite name of test being run +SUITE_NAME=HotmatchSamplesRegression + +# Timeout for complete test run. +# Currently, it takes 3.5 hrs including failures. +SUITE_TIMEOUT_SECS=14400 + +# Use Tunnel where applicable + +TCP_TUNNEL_TIMEOUT_SECS=1800 +
diff --git a/lab_system/master/config/tests/hotword_detection_latency/hotword_detection_latency.cfg b/lab_system/master/config/tests/hotword_detection_latency/hotword_detection_latency.cfg new file mode 100644 index 0000000..8b5697b --- /dev/null +++ b/lab_system/master/config/tests/hotword_detection_latency/hotword_detection_latency.cfg
@@ -0,0 +1,22 @@ +# Config file for Hotword detection latency test on Chirp. +# +# Do not modify property names +# Run make reconfig if you change a value +# and buildbot is running +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.assistant.e2e_latency.hotword_detection_latency_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=HotwordDetectionLatencyTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.assistant.e2e_latency.hotword_detection_latency_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=HotwordDetectionLatencyTestSequence + +# Use Tunnel where applicable +
diff --git a/lab_system/master/config/tests/hotword_detection_latency/hotword_detection_latency_fuchsia.cfg b/lab_system/master/config/tests/hotword_detection_latency/hotword_detection_latency_fuchsia.cfg new file mode 100644 index 0000000..6de2482 --- /dev/null +++ b/lab_system/master/config/tests/hotword_detection_latency/hotword_detection_latency_fuchsia.cfg
@@ -0,0 +1,22 @@ +# Config file for Hotword detection latency test on Chirp. +# +# Do not modify property names +# Run make reconfig if you change a value +# and buildbot is running +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.assistant.e2e_latency.hotword_detection_latency_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=HotwordDetectionLatencyTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.assistant.e2e_latency.fuchsia_hotword_detection_latency_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=FuchsiaHotwordDetectionLatencyTestSequence + +# Use Tunnel where applicable +
diff --git a/lab_system/master/config/tests/hotword_detection_latency/test_defs.json b/lab_system/master/config/tests/hotword_detection_latency/test_defs.json new file mode 100644 index 0000000..7e76508 --- /dev/null +++ b/lab_system/master/config/tests/hotword_detection_latency/test_defs.json
@@ -0,0 +1,178 @@ +[ + { + "group_name": "hotword_detection_latency", + "slave_name": "chirp_hotword_detection_latency_enclosures", + "test_name": "hotword_detection_latency", + "identifier": "chirp_hotword_detection_latency_master", + "device_type": "chirp_b3", + "device_group": "chirp_e2e_enclosure", + "branch": "master", + "scheduler": "30 0,3,19 * * *", + "step_factories": [ + { + "step_description": "Allocates devices for the testrun", + "step_identifier": "device_allocation", + "step_factories": [ + { + "module_path": "lab_system.master.steps.factory.device.cloud_allocator", + "class_name": "TwoHourLeaseShortTimeoutAllocatorStepFactory" + } + ] + } + ] + }, + { + "group_name": "hotword_detection_latency", + "slave_name": "chirp_hotword_detection_latency_enclosures", + "test_name": "hotword_detection_latency", + "identifier": "chirp_hotword_detection_latency_next_release", + "device_type": "chirp_b3", + "device_group": "chirp_e2e_enclosure", + "branch": "next_release", + "scheduler": "30 1,4,20 * * *", + "step_factories": [ + { + "step_description": "Allocates devices for the testrun", + "step_identifier": "device_allocation", + "step_factories": [ + { + "module_path": "lab_system.master.steps.factory.device.cloud_allocator", + "class_name": "TwoHourLeaseShortTimeoutAllocatorStepFactory" + } + ] + } + ] + }, + { + "group_name": "hotword_detection_latency", + "slave_name": "chirp_hotword_detection_latency_enclosures", + "test_name": "hotword_detection_latency", + "identifier": "chirp_hotword_detection_latency_release", + "device_type": "chirp_b3", + "device_group": "chirp_e2e_enclosure", + "branch": "release", + "scheduler": "30 2,5,21 * * *", + "step_factories": [ + { + "step_description": "Allocates devices for the testrun", + "step_identifier": "device_allocation", + "step_factories": [ + { + "module_path": "lab_system.master.steps.factory.device.cloud_allocator", + "class_name": "TwoHourLeaseShortTimeoutAllocatorStepFactory" + } + ] + } + ] + }, + { + "group_name": "hotword_detection_latency", + "slave_name": "joplin_hotword_detection_latency_enclosures", + "test_name": "hotword_detection_latency", + "identifier": "joplin_hotword_detection_latency_master", + "device_type": "joplin", + "device_group": "joplin_e2e_enclosure", + "branch": "master", + "scheduler": "30 0,3,19 * * *", + "step_factories": [ + { + "step_description": "Allocates devices for the testrun", + "step_identifier": "device_allocation", + "step_factories": [ + { + "module_path": "lab_system.master.steps.factory.device.cloud_allocator", + "class_name": "TwoHourLeaseShortTimeoutAllocatorStepFactory" + } + ] + } + ] + }, + { + "group_name": "hotword_detection_latency", + "slave_name": "joplin_hotword_detection_latency_enclosures", + "test_name": "hotword_detection_latency", + "identifier": "joplin_hotword_detection_latency_next_release", + "device_type": "joplin", + "device_group": "joplin_e2e_enclosure", + "branch": "1_28a", + "scheduler": "30 1,4,20 * * *", + "step_factories": [ + { + "step_description": "Allocates devices for the testrun", + "step_identifier": "device_allocation", + "step_factories": [ + { + "module_path": "lab_system.master.steps.factory.device.cloud_allocator", + "class_name": "TwoHourLeaseShortTimeoutAllocatorStepFactory" + } + ] + } + ] + }, + { + "group_name": "hotword_detection_latency", + "slave_name": "joplin_hotword_detection_latency_enclosures", + "test_name": "hotword_detection_latency", + "identifier": "joplin_hotword_detection_latency_release", + "device_type": "joplin", + "device_group": "joplin_e2e_enclosure", + "branch": "release", + "scheduler": "30 2,5,21 * * *", + "step_factories": [ + { + "step_description": "Allocates devices for the testrun", + "step_identifier": "device_allocation", + "step_factories": [ + { + "module_path": "lab_system.master.steps.factory.device.cloud_allocator", + "class_name": "TwoHourLeaseShortTimeoutAllocatorStepFactory" + } + ] + } + ] + }, + { + "group_name": "hotword_detection_latency", + "slave_name": "biggie_hotword_detection_latency_enclosures", + "test_name": "hotword_detection_latency", + "identifier": "biggie_hotword_detection_latency_master", + "device_type": "biggie", + "device_group": "biggie_e2e_enclosure", + "branch": "master", + "scheduler": "30 0,3,19 * * *", + "step_factories": [ + { + "step_description": "Allocates devices for the testrun", + "step_identifier": "device_allocation", + "step_factories": [ + { + "module_path": "lab_system.master.steps.factory.device.cloud_allocator", + "class_name": "TwoHourLeaseShortTimeoutAllocatorStepFactory" + } + ] + } + ] + }, + { + "group_name": "hotword_detection_latency", + "slave_name": "biggie_hotword_detection_latency_enclosures", + "test_name": "hotword_detection_latency", + "identifier": "biggie_hotword_detection_latency_next_release", + "device_type": "biggie", + "device_group": "biggie_e2e_enclosure", + "branch": "next_release", + "scheduler": "30 1,4,20 * * *", + "step_factories": [ + { + "step_description": "Allocates devices for the testrun", + "step_identifier": "device_allocation", + "step_factories": [ + { + "module_path": "lab_system.master.steps.factory.device.cloud_allocator", + "class_name": "TwoHourLeaseShortTimeoutAllocatorStepFactory" + } + ] + } + ] + } +]
diff --git a/lab_system/master/config/tests/hotword_samples_regression/hotword_samples_conducted_audio_regression.cfg b/lab_system/master/config/tests/hotword_samples_regression/hotword_samples_conducted_audio_regression.cfg new file mode 100644 index 0000000..d26ef30 --- /dev/null +++ b/lab_system/master/config/tests/hotword_samples_regression/hotword_samples_conducted_audio_regression.cfg
@@ -0,0 +1,35 @@ +# Config file for hotword samples regression for conducted audio. +# +# Do not modify property names +# Run make reconfig if you change a value +# and buildbot is running +# +# PROPERTIES +# Type of Hotword samples being tested. +SAMPLE_TYPE=OkGoogleSamples + +# Location of wav files on RPI. +RPI_AUDIO_SAMPLES_DIR=/home/pi/ok_google_samples + +# Test suite name of test being run. +SUITE_NAME=HotwordCASamplesRegression + +# Timeout for complete test run. +# Currently, it takes 3.5 hrs including failures. +SUITE_TIMEOUT_SECS=14400 + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.assistant.hotword_samples_regression.hotword_samples_regression_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=HotwordSamplesTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.assistant.hotword_samples_regression.hotword_samples_regression_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=HotwordSamplesRegressionTestSequence + +# Use Tunnel where applicable + +TCP_TUNNEL_TIMEOUT_SECS=1800
diff --git a/lab_system/master/config/tests/hotword_samples_regression/hotword_samples_regression.cfg b/lab_system/master/config/tests/hotword_samples_regression/hotword_samples_regression.cfg new file mode 100644 index 0000000..8e2f8b9 --- /dev/null +++ b/lab_system/master/config/tests/hotword_samples_regression/hotword_samples_regression.cfg
@@ -0,0 +1,41 @@ +# Config file for hotword samples regression on Chirp in the enclosure. +# +# Do not modify property names +# Run make reconfig if you change a value +# and buildbot is running +# +# PROPERTIES + +# Hotword speaker volume +HW_SPEAKER_VOL=94 + +# Type of Hotword samples being tested. +SAMPLE_TYPE=OkGoogleSamples + +# Location of wav files on RPI +RPI_AUDIO_SAMPLES_DIR=/home/pi/ok_google_samples + +# Indicates whether or not we should sign the device in +SIGNED_IN=True + +# Test suite name of test being run +SUITE_NAME=HotwordSamplesRegression + +# Timeout for complete test run. +# Currently, it takes 3.5 hrs including failures. +SUITE_TIMEOUT_SECS=14400 + +# Use Tunnel where applicable +TCP_TUNNEL_TIMEOUT_SECS=1800 + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=HotwordSamplesTestCase + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.assistant.hotword_samples_regression.hotword_samples_regression_test_case + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=HotwordSamplesRegressionTestSequence + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.assistant.hotword_samples_regression.hotword_samples_regression_test_sequence \ No newline at end of file
diff --git a/lab_system/master/config/tests/hotword_samples_regression/hotword_samples_regression_fuchsia.cfg b/lab_system/master/config/tests/hotword_samples_regression/hotword_samples_regression_fuchsia.cfg new file mode 100644 index 0000000..01eb762 --- /dev/null +++ b/lab_system/master/config/tests/hotword_samples_regression/hotword_samples_regression_fuchsia.cfg
@@ -0,0 +1,38 @@ +# Config file for hotword samples regression on Chirp in the enclosure. +# +# Do not modify property names +# Run make reconfig if you change a value +# and buildbot is running +# +# PROPERTIES + +# Hotword speaker volume +HW_SPEAKER_VOL=94 + +# Type of Hotword samples being tested. +SAMPLE_TYPE=OkGoogleSamples + +# Location of wav files on RPI +RPI_AUDIO_SAMPLES_DIR=/home/pi/ok_google_samples + +# Test suite name of test being run +SUITE_NAME=HotwordSamplesRegression + +# Timeout for complete test run. +# Currently, it takes 3.5 hrs including failures. +SUITE_TIMEOUT_SECS=14400 + +# Use Tunnel where applicable +TCP_TUNNEL_TIMEOUT_SECS=1800 + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=HotwordSamplesTestCase + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.assistant.hotword_samples_regression.hotword_samples_regression_test_case + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=FuchsiaHotwordSamplesRegressionTestSequence + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.assistant.hotword_samples_regression.fuchsia_hotword_samples_regression_test_sequence
diff --git a/lab_system/master/config/tests/hotword_samples_regression/noisy_hotword_samples_regression.cfg b/lab_system/master/config/tests/hotword_samples_regression/noisy_hotword_samples_regression.cfg new file mode 100644 index 0000000..662e690 --- /dev/null +++ b/lab_system/master/config/tests/hotword_samples_regression/noisy_hotword_samples_regression.cfg
@@ -0,0 +1,47 @@ +# Config file for testing hotword samples with noise. +# +# Do not modify property names +# Run make reconfig if you change a value +# and buildbot is running +# +# PROPERTIES + +# Hotword speaker volume +HW_SPEAKER_VOL=94 + +# Type of Hotword samples being tested. +SAMPLE_TYPE=NoisySamples + +# Location of wav files on RPI +RPI_AUDIO_SAMPLES_DIR=/home/pi/art_query_samples + +# Location of noise files on RPI +RPI_NOISE_DIR=/home/pi/art_noise_samples + +# Noise gain to apply to noise samples +NOISE_GAIN=0.2 + +# Indicates whether or not we should sign the device in +SIGNED_IN=True + +# Test suite name of test being run +SUITE_NAME=HotwordSamplesRegression + +# Timeout for complete test run. +# Currently, it takes 3.5 hrs including failures. +SUITE_TIMEOUT_SECS=14400 + +# Use Tunnel where applicable +TCP_TUNNEL_TIMEOUT_SECS=1800 + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=HotwordSamplesTestCase + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.assistant.hotword_samples_regression.hotword_samples_regression_test_case + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=HotwordSamplesRegressionTestSequence + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.assistant.hotword_samples_regression.hotword_samples_regression_test_sequence \ No newline at end of file
diff --git a/lab_system/master/config/tests/hotword_samples_regression/test_defs.json b/lab_system/master/config/tests/hotword_samples_regression/test_defs.json new file mode 100644 index 0000000..3f6128b --- /dev/null +++ b/lab_system/master/config/tests/hotword_samples_regression/test_defs.json
@@ -0,0 +1,72 @@ +[ + { + "group_name": "hotword_samples_regression", + "slave_name": "chirp_eraser_enclosure", + "test_name": "hotword_samples_regression", + "identifier": "chirp_hotword_samples_regression_master", + "device_type": "chirp_b3", + "device_group": "chirp_hotword_samples_enclosure", + "branch": "master", + "scheduler": "0 2 1,4,7,10,13,16,19,22,25,28,31 * *" + }, + { + "group_name": "hotword_samples_regression", + "slave_name": "chirp_eraser_enclosure", + "test_name": "hotword_samples_regression", + "identifier": "chirp_hotword_samples_regression_next_release", + "device_type": "chirp_b3", + "device_group": "chirp_hotword_samples_enclosure", + "branch": "next_release", + "scheduler": "0 2 2,5,8,11,14,17,20,23,26,29 * *" + }, + { + "group_name": "hotword_samples_regression", + "slave_name": "chirp_eraser_enclosure", + "test_name": "hotword_samples_regression", + "identifier": "chirp_hotword_samples_regression_release", + "device_type": "chirp_b3", + "device_group": "chirp_hotword_samples_enclosure", + "branch": "release", + "scheduler": "0 2 3,6,9,12,15,18,21,24,27,30 * *" + }, + { + "group_name": "hotword_samples_regression", + "slave_name": "joplin_eraser_enclosure", + "test_name": "hotword_samples_regression", + "identifier": "joplin_hotword_samples_regression_master", + "device_type": "joplin", + "device_group": "joplin_hotword_samples_enclosure", + "branch": "master", + "scheduler": "0 2 1,5,9,13,17,21,25,29 * *" + }, + { + "group_name": "hotword_samples_regression", + "slave_name": "joplin_eraser_enclosure", + "test_name": "hotword_samples_regression", + "identifier": "joplin_hotword_samples_regression_next_release", + "device_type": "joplin", + "device_group": "joplin_hotword_samples_enclosure", + "branch": "1_28a", + "scheduler": "0 2 2,4,6,8,10,12,14,16,18,20,22,24,26,28,30 * *" + }, + { + "group_name": "hotword_samples_regression", + "slave_name": "biggie_eraser_enclosure", + "test_name": "hotword_samples_regression", + "identifier": "biggie_hotword_samples_regression_master", + "device_type": "biggie_b3", + "device_group": "biggie_hotword_samples_enclosure", + "branch": "master", + "scheduler": "0 2 1,5,9,13,17,21,25,29 * *" + }, + { + "group_name": "hotword_samples_regression", + "slave_name": "biggie_eraser_enclosure", + "test_name": "hotword_samples_regression", + "identifier": "biggie_hotword_samples_regression_next_release", + "device_type": "biggie_b3", + "device_group": "biggie_hotword_samples_enclosure", + "branch": "next_release", + "scheduler": "0 2 2,4,6,8,10,12,14,16,18,20,22,24,26,28,30 * *" + } +]
diff --git a/lab_system/master/config/tests/hotword_samples_regression_art_clean/hotword_samples_regression_art_clean.cfg b/lab_system/master/config/tests/hotword_samples_regression_art_clean/hotword_samples_regression_art_clean.cfg new file mode 100755 index 0000000..94c13a8 --- /dev/null +++ b/lab_system/master/config/tests/hotword_samples_regression_art_clean/hotword_samples_regression_art_clean.cfg
@@ -0,0 +1,38 @@ +# Config file for hotword samples regression on Chirp in the enclosure. +# +# Do not modify property names +# Run make reconfig if you change a value +# and buildbot is running +# +# PROPERTIES + +# Location of wav files on RPI. +RPI_AUDIO_SAMPLES_DIR=/home/pi/hotword_art_clean_samples + +# Type of Hotword samples being tested. +SAMPLE_TYPE=ArtCleanSamples + +# Indicates whether or not we should sign the device in +SIGNED_IN=True + +# Test suite name of test being run. +SUITE_NAME=HotwordSamplesRegression + +# Timeout for complete test run. +# Currently, it takes 8 hrs including failures. +SUITE_TIMEOUT_SECS=43800 + +# Use Tunnel where applicable +TCP_TUNNEL_TIMEOUT_SECS=1800 + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=HotwordSamplesTestCase + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.assistant.hotword_samples_regression.hotword_samples_regression_test_case + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=HotwordSamplesRegressionTestSequence + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.assistant.hotword_samples_regression.hotword_samples_regression_test_sequence \ No newline at end of file
diff --git a/lab_system/master/config/tests/hotword_samples_regression_art_clean/hotword_samples_regression_art_clean_fuchsia.cfg b/lab_system/master/config/tests/hotword_samples_regression_art_clean/hotword_samples_regression_art_clean_fuchsia.cfg new file mode 100755 index 0000000..45f7257 --- /dev/null +++ b/lab_system/master/config/tests/hotword_samples_regression_art_clean/hotword_samples_regression_art_clean_fuchsia.cfg
@@ -0,0 +1,35 @@ +# Config file for hotword samples regression on Chirp in the enclosure. +# +# Do not modify property names +# Run make reconfig if you change a value +# and buildbot is running +# +# PROPERTIES + +# Location of wav files on RPI. +RPI_AUDIO_SAMPLES_DIR=/home/pi/hotword_art_clean_samples + +# Type of Hotword samples being tested. +SAMPLE_TYPE=ArtCleanSamples + +# Test suite name of test being run. +SUITE_NAME=HotwordSamplesRegression + +# Timeout for complete test run. +# Currently, it takes 8 hrs including failures. +SUITE_TIMEOUT_SECS=43800 + +# Use Tunnel where applicable +TCP_TUNNEL_TIMEOUT_SECS=1800 + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=HotwordSamplesTestCase + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.assistant.hotword_samples_regression.hotword_samples_regression_test_case + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=FuchsiaHotwordSamplesRegressionTestSequence + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.assistant.hotword_samples_regression.fuchsia_hotword_samples_regression_test_sequence
diff --git a/lab_system/master/config/tests/hotword_samples_regression_artmusic/hotword_samples_conducted_audio_regression_artmusic.cfg b/lab_system/master/config/tests/hotword_samples_regression_artmusic/hotword_samples_conducted_audio_regression_artmusic.cfg new file mode 100644 index 0000000..6e46146 --- /dev/null +++ b/lab_system/master/config/tests/hotword_samples_regression_artmusic/hotword_samples_conducted_audio_regression_artmusic.cfg
@@ -0,0 +1,35 @@ +# Config file for hotword samples regression for conducted audio. +# +# Do not modify property names +# Run make reconfig if you change a value +# and buildbot is running +# +# PROPERTIES +# Type of Hotword samples being tested. +SAMPLE_TYPE=ARTMixedWithMusic + +# Location of wav files on RPI. +RPI_AUDIO_SAMPLES_DIR=/home/pi/art_mixed_music + +# Test suite name of test being run. +SUITE_NAME=HotwordSamplesRegression + +# Timeout for complete test run. +# Currently, it takes 8 hrs including failures. +SUITE_TIMEOUT_SECS=28800 + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.assistant.hotword_samples_regression.hotword_samples_regression_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=HotwordSamplesTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.assistant.hotword_samples_regression.hotword_samples_regression_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=HotwordSamplesRegressionTestSequence + +# Use Tunnel where applicable + +TCP_TUNNEL_TIMEOUT_SECS=1800
diff --git a/lab_system/master/config/tests/hotword_samples_regression_artmusic/hotword_samples_regression_artmusic.cfg b/lab_system/master/config/tests/hotword_samples_regression_artmusic/hotword_samples_regression_artmusic.cfg new file mode 100644 index 0000000..e72cb47 --- /dev/null +++ b/lab_system/master/config/tests/hotword_samples_regression_artmusic/hotword_samples_regression_artmusic.cfg
@@ -0,0 +1,35 @@ +# Config file for hotword samples regression on Chirp in the enclosure. +# +# Do not modify property names +# Run make reconfig if you change a value +# and buildbot is running +# +# PROPERTIES +# Type of Hotword samples being tested. +SAMPLE_TYPE=ARTMixedWithMusic + +# Location of wav files on RPI. +RPI_AUDIO_SAMPLES_DIR=/home/pi/art_mixed_music + +# Test suite name of test being run. +SUITE_NAME=HotwordSamplesRegression + +# Timeout for complete test run. +# Currently, it takes 8 hrs including failures. +SUITE_TIMEOUT_SECS=28800 + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.assistant.hotword_samples_regression.hotword_samples_regression_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=HotwordSamplesTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.assistant.hotword_samples_regression.hotword_samples_regression_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=HotwordSamplesRegressionTestSequence + +# Use Tunnel where applicable + +TCP_TUNNEL_TIMEOUT_SECS=1800
diff --git a/lab_system/master/config/tests/hotword_samples_regression_clean/hotword_samples_conducted_audio_regression_clean.cfg b/lab_system/master/config/tests/hotword_samples_regression_clean/hotword_samples_conducted_audio_regression_clean.cfg new file mode 100644 index 0000000..9dacca7 --- /dev/null +++ b/lab_system/master/config/tests/hotword_samples_regression_clean/hotword_samples_conducted_audio_regression_clean.cfg
@@ -0,0 +1,35 @@ +# Config file for hotword samples regression for conducted audio. +# +# Do not modify property names +# Run make reconfig if you change a value +# and buildbot is running +# +# PROPERTIES +# Type of Hotword samples being tested. +SAMPLE_TYPE=CleanSamples + +# Location of wav files on RPI. +RPI_AUDIO_SAMPLES_DIR=/home/pi/clean_audio_hotword_samples + +# Test suite name of test being run. +SUITE_NAME=HotwordCASamplesRegression + +# Timeout for complete test run. +# Currently, it takes 0.5 hrs including failures. +SUITE_TIMEOUT_SECS=1800 + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.assistant.hotword_samples_regression.hotword_samples_regression_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=HotwordSamplesTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.assistant.hotword_samples_regression.hotword_samples_regression_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=HotwordSamplesRegressionTestSequence + +# Use Tunnel where applicable + +TCP_TUNNEL_TIMEOUT_SECS=1800
diff --git a/lab_system/master/config/tests/hotword_samples_regression_clean/hotword_samples_regression_clean.cfg b/lab_system/master/config/tests/hotword_samples_regression_clean/hotword_samples_regression_clean.cfg new file mode 100644 index 0000000..92ac71c --- /dev/null +++ b/lab_system/master/config/tests/hotword_samples_regression_clean/hotword_samples_regression_clean.cfg
@@ -0,0 +1,35 @@ +# Config file for hotword samples regression on Chirp in the enclosure. +# +# Do not modify property names +# Run make reconfig if you change a value +# and buildbot is running +# +# PROPERTIES +# Type of Hotword samples being tested. +SAMPLE_TYPE=CleanSamples + +# Location of wav files on RPI +RPI_AUDIO_SAMPLES_DIR=/home/pi/clean_audio_hotword_samples + +# Test suite name of test being run +SUITE_NAME=HotwordSamplesRegression + +# Timeout for complete test run. +# Currently, it takes 0.5 hrs including failures. +SUITE_TIMEOUT_SECS=1800 + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.assistant.hotword_samples_regression.hotword_samples_regression_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=HotwordSamplesTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.assistant.hotword_samples_regression.hotword_samples_regression_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=HotwordSamplesRegressionTestSequence + +# Use Tunnel where applicable + +TCP_TUNNEL_TIMEOUT_SECS=1800
diff --git a/lab_system/master/config/tests/hotword_samples_regression_heyg/hotword_samples_conducted_audio_regression_heyg.cfg b/lab_system/master/config/tests/hotword_samples_regression_heyg/hotword_samples_conducted_audio_regression_heyg.cfg new file mode 100644 index 0000000..ab22a18 --- /dev/null +++ b/lab_system/master/config/tests/hotword_samples_regression_heyg/hotword_samples_conducted_audio_regression_heyg.cfg
@@ -0,0 +1,35 @@ +# Config file for hotword samples regression for conducted audio. +# +# Do not modify property names +# Run make reconfig if you change a value +# and buildbot is running +# +# PROPERTIES +# Type of Hotword samples being tested. +SAMPLE_TYPE=HeyGoogleSamples + +# Location of wav files on RPI. +RPI_AUDIO_SAMPLES_DIR=/home/pi/hey_google_samples + +# Test suite name of test being run. +SUITE_NAME=HotwordCASamplesRegression + +# Timeout for complete test run. +# Currently, it takes 11.5 hrs including failures. +SUITE_TIMEOUT_SECS=43200 + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.assistant.hotword_samples_regression.hotword_samples_regression_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=HotwordSamplesTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.assistant.hotword_samples_regression.hotword_samples_regression_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=HotwordSamplesRegressionTestSequence + +# Use Tunnel where applicable + +TCP_TUNNEL_TIMEOUT_SECS=1800
diff --git a/lab_system/master/config/tests/hotword_samples_regression_heyg/hotword_samples_regression_heyg.cfg b/lab_system/master/config/tests/hotword_samples_regression_heyg/hotword_samples_regression_heyg.cfg new file mode 100644 index 0000000..4d85ddc --- /dev/null +++ b/lab_system/master/config/tests/hotword_samples_regression_heyg/hotword_samples_regression_heyg.cfg
@@ -0,0 +1,41 @@ +# Config file for hotword samples regression on Chirp in the enclosure. +# +# Do not modify property names +# Run make reconfig if you change a value +# and buildbot is running +# +# PROPERTIES + +# Hotword speaker volume +HW_SPEAKER_VOL=94 + +# Location of wav files on RPI. +RPI_AUDIO_SAMPLES_DIR=/home/pi/hey_google_samples + +# Type of Hotword samples being tested. +SAMPLE_TYPE=HeyGoogleSamples + +# Indicates whether or not we should sign the device in +SIGNED_IN=True + +# Test suite name of test being run. +SUITE_NAME=HotwordSamplesRegression + +# Timeout for complete test run. +# Currently, it takes 11.5 hrs including failures. +SUITE_TIMEOUT_SECS=43200 + +# Use Tunnel where applicable +TCP_TUNNEL_TIMEOUT_SECS=1800 + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=HotwordSamplesTestCase + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.assistant.hotword_samples_regression.hotword_samples_regression_test_case + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=HotwordSamplesRegressionTestSequence + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.assistant.hotword_samples_regression.hotword_samples_regression_test_sequence \ No newline at end of file
diff --git a/lab_system/master/config/tests/hotword_samples_regression_heyg/hotword_samples_regression_heyg_fuchsia.cfg b/lab_system/master/config/tests/hotword_samples_regression_heyg/hotword_samples_regression_heyg_fuchsia.cfg new file mode 100644 index 0000000..d7abb29 --- /dev/null +++ b/lab_system/master/config/tests/hotword_samples_regression_heyg/hotword_samples_regression_heyg_fuchsia.cfg
@@ -0,0 +1,38 @@ +# Config file for hotword samples regression on Chirp in the enclosure. +# +# Do not modify property names +# Run make reconfig if you change a value +# and buildbot is running +# +# PROPERTIES + +# Hotword speaker volume +HW_SPEAKER_VOL=94 + +# Location of wav files on RPI. +RPI_AUDIO_SAMPLES_DIR=/home/pi/hey_google_samples + +# Type of Hotword samples being tested. +SAMPLE_TYPE=HeyGoogleSamples + +# Test suite name of test being run. +SUITE_NAME=HotwordSamplesRegression + +# Timeout for complete test run. +# Currently, it takes 11.5 hrs including failures. +SUITE_TIMEOUT_SECS=43200 + +# Use Tunnel where applicable +TCP_TUNNEL_TIMEOUT_SECS=1800 + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=HotwordSamplesTestCase + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.assistant.hotword_samples_regression.hotword_samples_regression_test_case + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=FuchsiaHotwordSamplesRegressionTestSequence + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.assistant.hotword_samples_regression.fuchsia_hotword_samples_regression_test_sequence
diff --git a/lab_system/master/config/tests/hotword_samples_regression_noisy/hotword_samples_regression_no_noise.cfg b/lab_system/master/config/tests/hotword_samples_regression_noisy/hotword_samples_regression_no_noise.cfg new file mode 100644 index 0000000..6f5cc2d --- /dev/null +++ b/lab_system/master/config/tests/hotword_samples_regression_noisy/hotword_samples_regression_no_noise.cfg
@@ -0,0 +1,41 @@ +# Config file for testing noisy hotword samples without noise for baselining. +# +# Do not modify property names +# Run make reconfig if you change a value +# and buildbot is running +# +# PROPERTIES + +# Hotword speaker volume +HW_SPEAKER_VOL=94 + +# Type of Hotword samples being tested. +SAMPLE_TYPE=NoisySamples + +# Location of wav files on RPI +RPI_AUDIO_SAMPLES_DIR=/home/pi/art_query_samples + +# Indicates whether or not we should sign the device in +SIGNED_IN=True + +# Test suite name of test being run +SUITE_NAME=HotwordSamplesRegression + +# Timeout for complete test run. +# Currently, it takes 3.5 hrs including failures. +SUITE_TIMEOUT_SECS=14400 + +# Use Tunnel where applicable +TCP_TUNNEL_TIMEOUT_SECS=1800 + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=HotwordSamplesTestCase + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.assistant.hotword_samples_regression.hotword_samples_regression_test_case + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=HotwordSamplesRegressionTestSequence + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.assistant.hotword_samples_regression.hotword_samples_regression_test_sequence \ No newline at end of file
diff --git a/lab_system/master/config/tests/hotword_samples_regression_noisy/hotword_samples_regression_noisy.cfg b/lab_system/master/config/tests/hotword_samples_regression_noisy/hotword_samples_regression_noisy.cfg new file mode 100644 index 0000000..662e690 --- /dev/null +++ b/lab_system/master/config/tests/hotword_samples_regression_noisy/hotword_samples_regression_noisy.cfg
@@ -0,0 +1,47 @@ +# Config file for testing hotword samples with noise. +# +# Do not modify property names +# Run make reconfig if you change a value +# and buildbot is running +# +# PROPERTIES + +# Hotword speaker volume +HW_SPEAKER_VOL=94 + +# Type of Hotword samples being tested. +SAMPLE_TYPE=NoisySamples + +# Location of wav files on RPI +RPI_AUDIO_SAMPLES_DIR=/home/pi/art_query_samples + +# Location of noise files on RPI +RPI_NOISE_DIR=/home/pi/art_noise_samples + +# Noise gain to apply to noise samples +NOISE_GAIN=0.2 + +# Indicates whether or not we should sign the device in +SIGNED_IN=True + +# Test suite name of test being run +SUITE_NAME=HotwordSamplesRegression + +# Timeout for complete test run. +# Currently, it takes 3.5 hrs including failures. +SUITE_TIMEOUT_SECS=14400 + +# Use Tunnel where applicable +TCP_TUNNEL_TIMEOUT_SECS=1800 + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=HotwordSamplesTestCase + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.assistant.hotword_samples_regression.hotword_samples_regression_test_case + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=HotwordSamplesRegressionTestSequence + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.assistant.hotword_samples_regression.hotword_samples_regression_test_sequence \ No newline at end of file
diff --git a/lab_system/master/config/tests/hotword_samples_regression_noisy/hotword_samples_regression_noisy_fuchsia.cfg b/lab_system/master/config/tests/hotword_samples_regression_noisy/hotword_samples_regression_noisy_fuchsia.cfg new file mode 100644 index 0000000..d25d2c3 --- /dev/null +++ b/lab_system/master/config/tests/hotword_samples_regression_noisy/hotword_samples_regression_noisy_fuchsia.cfg
@@ -0,0 +1,47 @@ +# Config file for testing hotword samples with noise. +# +# Do not modify property names +# Run make reconfig if you change a value +# and buildbot is running +# +# PROPERTIES + +# Hotword speaker volume +HW_SPEAKER_VOL=94 + +# Type of Hotword samples being tested. +SAMPLE_TYPE=NoisySamples + +# Location of wav files on RPI +RPI_AUDIO_SAMPLES_DIR=/home/pi/art_query_samples + +# Location of noise files on RPI +RPI_NOISE_DIR=/home/pi/art_noise_samples + +# Noise gain to apply to noise samples +NOISE_GAIN=0.2 + +# Indicates whether or not we should sign the device in +SIGNED_IN=True + +# Test suite name of test being run +SUITE_NAME=HotwordSamplesRegression + +# Timeout for complete test run. +# Currently, it takes 3.5 hrs including failures. +SUITE_TIMEOUT_SECS=14400 + +# Use Tunnel where applicable +TCP_TUNNEL_TIMEOUT_SECS=1800 + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=HotwordSamplesTestCase + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.assistant.hotword_samples_regression.hotword_samples_regression_test_case + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=FuchsiaHotwordSamplesRegressionTestSequence + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.assistant.hotword_samples_regression.fuchsia_hotword_samples_regression_test_sequence
diff --git a/lab_system/master/config/tests/hotwording/hotword_sensitivity_CA.cfg b/lab_system/master/config/tests/hotwording/hotword_sensitivity_CA.cfg new file mode 100644 index 0000000..476811d --- /dev/null +++ b/lab_system/master/config/tests/hotwording/hotword_sensitivity_CA.cfg
@@ -0,0 +1,26 @@ +# Config file for Hotword Sensitivity on Nest Assistant devices +# +# First four fields should always be present + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.assistant.hotwording.hotword_sensitivity_test_case +# Name of the TestCase sub-class: +TEST_CASE_CLASS=HotwordSensitivityTestCase +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.assistant.hotwording.hotword_sensitivity_test_sequence +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=HotwordSensitivityTestSequence + +# All other test-specific fields should be placed in alphabetical order after +# Location of hotword samples +GCS_AUDIO_DIR_PATH=assistant/hotword_samples_silence_2_channels + +# Level at which to mix pink noise with utterances +NOISE_LEVEL=.000001 + +# Options are 'S', 'M', 'L' (Small, Medium, Large) +# For debugging, can instead use a partial match string (e.g. 'speaker12', 'hey_google', etc.) +RUN_SIZE=M + +# Options are 'Jabberjay', 'ConductedAudio', and 'Chatterbox' +STIMULUS_TYPE=ConductedAudio \ No newline at end of file
diff --git a/lab_system/master/config/tests/hotwording/hotword_sensitivity_jabberjay.cfg b/lab_system/master/config/tests/hotwording/hotword_sensitivity_jabberjay.cfg new file mode 100644 index 0000000..41a5657 --- /dev/null +++ b/lab_system/master/config/tests/hotwording/hotword_sensitivity_jabberjay.cfg
@@ -0,0 +1,26 @@ +# Config file for Hotword Sensitivity on Nest Assistant devices +# +# First four fields should always be present + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.assistant.hotwording.hotword_sensitivity_test_case +# Name of the TestCase sub-class: +TEST_CASE_CLASS=HotwordSensitivityTestCase +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.assistant.hotwording.hotword_sensitivity_test_sequence +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=HotwordSensitivityTestSequence + +# All other test-specific fields should be placed in alphabetical order after +# Location of hotword samples +GCS_AUDIO_DIR_PATH=assistant/assistant_hotword_sample_recordings_added_silence + +# Level at which to mix pink noise with utterances +NOISE_LEVEL=.001 + +# Options are 'S', 'M', 'L' (Small, Medium, Large) +# For debugging, can instead use a partial match string (e.g. 'speaker12', 'hey_google', etc.) +RUN_SIZE=L + +# Options are 'Jabberjay', 'ConductedAudio', and 'Chatterbox' +STIMULUS_TYPE=Jabberjay \ No newline at end of file
diff --git a/lab_system/master/config/tests/hotwording/hotword_sensitivity_jabberjay_fuchsia.cfg b/lab_system/master/config/tests/hotwording/hotword_sensitivity_jabberjay_fuchsia.cfg new file mode 100644 index 0000000..611a854 --- /dev/null +++ b/lab_system/master/config/tests/hotwording/hotword_sensitivity_jabberjay_fuchsia.cfg
@@ -0,0 +1,26 @@ +# Config file for Hotword Sensitivity on Nest Assistant devices +# +# First four fields should always be present + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.assistant.hotwording.hotword_sensitivity_test_case +# Name of the TestCase sub-class: +TEST_CASE_CLASS=HotwordSensitivityTestCase +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.assistant.hotwording.fuchsia_hotword_sensitivity_test_sequence +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=FuchsiaHotwordSensitivityTestSequence + +# All other test-specific fields should be placed in alphabetical order after +# Location of hotword samples +GCS_AUDIO_DIR_PATH=assistant/assistant_hotword_sample_recordings_added_silence + +# Level at which to mix pink noise with utterances +NOISE_LEVEL=.001 + +# Options are 'S', 'M', 'L' (Small, Medium, Large) +# For debugging, can instead use a partial match string (e.g. 'speaker12', 'hey_google', etc.) +RUN_SIZE=L + +# Options are 'Jabberjay', 'ConductedAudio', and 'Chatterbox' +STIMULUS_TYPE=Jabberjay \ No newline at end of file
diff --git a/lab_system/master/config/tests/hotwording/hotword_sensitivity_levels.cfg b/lab_system/master/config/tests/hotwording/hotword_sensitivity_levels.cfg new file mode 100644 index 0000000..01c0dc1 --- /dev/null +++ b/lab_system/master/config/tests/hotwording/hotword_sensitivity_levels.cfg
@@ -0,0 +1,32 @@ +# Config file for Hotword Sensitivity on Nest Assistant devices +# +# First four fields should always be present + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.assistant.hotwording.hotword_sensitivity_test_case +# Name of the TestCase sub-class: +TEST_CASE_CLASS=HotwordSensitivityLevelsTestCase +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.assistant.hotwording.hotword_sensitivity_test_sequence +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=HotwordSensitivityTestSequence + +# All other test-specific fields should be placed in alphabetical order after +# Location of hotword samples +GCS_AUDIO_DIR_PATH=assistant/hotwording/hotword_sensitivity_levels_samples + +# Level at which to mix pink noise with utterances +NOISE_LEVEL=.001 + +# If a custom Range is used for a test, it can be optionally be defined here +RANGE=.003, .004 + +# Options are 'S', 'M', 'L' (Small, Medium, Large) +# For debugging, can instead use a partial match string (e.g. 'speaker12', 'hey_google', etc.) +RUN_SIZE=L + +# These fields are defined in the HwSensitivity enum in device_attribute_helper +SENSITIVITY_LEVEL=1,2,3,4,5 + +# Options are 'Jabberjay', 'ConductedAudio', and 'Chatterbox' +STIMULUS_TYPE=Jabberjay \ No newline at end of file
diff --git a/lab_system/master/config/tests/hotwording/hotwording.cfg b/lab_system/master/config/tests/hotwording/hotwording.cfg new file mode 100644 index 0000000..967f5bc --- /dev/null +++ b/lab_system/master/config/tests/hotwording/hotwording.cfg
@@ -0,0 +1,22 @@ +# Config file for Hotwording on Joplin. +# +# Do not modify property names +# Run make reconfig if you change a value +# and buildbot is running +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.assistant.hotwording.hotwording_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=HotwordingTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.assistant.hotwording.hotwording_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=HotwordingTestSequence + +# Use Tunnel where applicable +
diff --git a/lab_system/master/config/tests/hotwording/test_defs.json b/lab_system/master/config/tests/hotwording/test_defs.json new file mode 100644 index 0000000..c5d6a2d --- /dev/null +++ b/lab_system/master/config/tests/hotwording/test_defs.json
@@ -0,0 +1,178 @@ +[ + { + "group_name": "hotwording", + "slave_name": "chirp_hotwording_enclosures", + "test_name": "hotwording", + "identifier": "chirp_hotwording_master", + "device_type": "chirp_b3", + "device_group": "chirp_e2e_enclosure", + "branch": "master", + "scheduler": "0 3,12,15 * * *", + "step_factories": [ + { + "step_description": "Allocates devices for the testrun", + "step_identifier": "device_allocation", + "step_factories": [ + { + "module_path": "lab_system.master.steps.factory.device.cloud_allocator", + "class_name": "TwoHourLeaseShortTimeoutAllocatorStepFactory" + } + ] + } + ] + }, + { + "group_name": "hotwording", + "slave_name": "chirp_hotwording_enclosures", + "test_name": "hotwording", + "identifier": "chirp_hotwording_next_release", + "device_type": "chirp_b3", + "device_group": "chirp_e2e_enclosure", + "branch": "next_release", + "scheduler": "0 4,13,16 * * *", + "step_factories": [ + { + "step_description": "Allocates devices for the testrun", + "step_identifier": "device_allocation", + "step_factories": [ + { + "module_path": "lab_system.master.steps.factory.device.cloud_allocator", + "class_name": "TwoHourLeaseShortTimeoutAllocatorStepFactory" + } + ] + } + ] + }, + { + "group_name": "hotwording", + "slave_name": "chirp_hotwording_enclosures", + "test_name": "hotwording", + "identifier": "chirp_hotwording_release", + "device_type": "chirp_b3", + "device_group": "chirp_e2e_enclosure", + "branch": "release", + "scheduler": "0 5,14,17 * * *", + "step_factories": [ + { + "step_description": "Allocates devices for the testrun", + "step_identifier": "device_allocation", + "step_factories": [ + { + "module_path": "lab_system.master.steps.factory.device.cloud_allocator", + "class_name": "TwoHourLeaseShortTimeoutAllocatorStepFactory" + } + ] + } + ] + }, + { + "group_name": "hotwording", + "slave_name": "joplin_hotwording_enclosures", + "test_name": "hotwording", + "identifier": "joplin_hotwording_master", + "device_type": "joplin", + "device_group": "joplin_e2e_enclosure", + "branch": "master", + "scheduler": "0 3,12,15 * * *", + "step_factories": [ + { + "step_description": "Allocates devices for the testrun", + "step_identifier": "device_allocation", + "step_factories": [ + { + "module_path": "lab_system.master.steps.factory.device.cloud_allocator", + "class_name": "TwoHourLeaseShortTimeoutAllocatorStepFactory" + } + ] + } + ] + }, + { + "group_name": "hotwording", + "slave_name": "joplin_hotwording_enclosures", + "test_name": "hotwording", + "identifier": "joplin_hotwording_next_release", + "device_type": "joplin", + "device_group": "joplin_e2e_enclosure", + "branch": "1_28a", + "scheduler": "0 4,13,16 * * *", + "step_factories": [ + { + "step_description": "Allocates devices for the testrun", + "step_identifier": "device_allocation", + "step_factories": [ + { + "module_path": "lab_system.master.steps.factory.device.cloud_allocator", + "class_name": "TwoHourLeaseShortTimeoutAllocatorStepFactory" + } + ] + } + ] + }, + { + "group_name": "hotwording", + "slave_name": "joplin_hotwording_enclosures", + "test_name": "hotwording", + "identifier": "joplin_hotwording_release", + "device_type": "joplin", + "device_group": "joplin_e2e_enclosure", + "branch": "release", + "scheduler": "0 5,14,17 * * *", + "step_factories": [ + { + "step_description": "Allocates devices for the testrun", + "step_identifier": "device_allocation", + "step_factories": [ + { + "module_path": "lab_system.master.steps.factory.device.cloud_allocator", + "class_name": "TwoHourLeaseShortTimeoutAllocatorStepFactory" + } + ] + } + ] + }, + { + "group_name": "hotwording", + "slave_name": "biggie_hotwording_enclosures", + "test_name": "hotwording", + "identifier": "biggie_hotwording_master", + "device_type": "biggie", + "device_group": "biggie_e2e_enclosure", + "branch": "master", + "scheduler": "0 3,12,15 * * *", + "step_factories": [ + { + "step_description": "Allocates devices for the testrun", + "step_identifier": "device_allocation", + "step_factories": [ + { + "module_path": "lab_system.master.steps.factory.device.cloud_allocator", + "class_name": "TwoHourLeaseShortTimeoutAllocatorStepFactory" + } + ] + } + ] + }, + { + "group_name": "hotwording", + "slave_name": "biggie_hotwording_enclosures", + "test_name": "hotwording", + "identifier": "biggie_hotwording_next_release", + "device_type": "biggie", + "device_group": "biggie_e2e_enclosure", + "branch": "next_release", + "scheduler": "0 4,13,16 * * *", + "step_factories": [ + { + "step_description": "Allocates devices for the testrun", + "step_identifier": "device_allocation", + "step_factories": [ + { + "module_path": "lab_system.master.steps.factory.device.cloud_allocator", + "class_name": "TwoHourLeaseShortTimeoutAllocatorStepFactory" + } + ] + } + ] + } +]
diff --git a/lab_system/master/config/tests/hs3_assistant/hs3_assistant_test.cfg b/lab_system/master/config/tests/hs3_assistant/hs3_assistant_test.cfg new file mode 100644 index 0000000..5a09d15 --- /dev/null +++ b/lab_system/master/config/tests/hs3_assistant/hs3_assistant_test.cfg
@@ -0,0 +1,17 @@ +# Config file for hermetic S3 smoke tests. +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.assistant.hs3_assistant_test.hs3_assistant_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=Hs3AssistantTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.assistant.hs3_assistant_test.hs3_assistant_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=Hs3AssistantTestSequence + +BUILD_SELECTION_POLICY=backtrack_then_latest
diff --git a/lab_system/master/config/tests/imax/imax.cfg b/lab_system/master/config/tests/imax/imax.cfg new file mode 100644 index 0000000..d047b2e --- /dev/null +++ b/lab_system/master/config/tests/imax/imax.cfg
@@ -0,0 +1,27 @@ +# Config file for the imax tests +# +# Do not modify property names +# Run make reconfig if you change a value +# and buildbot is running +# +# PROPERTIES +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.imax.imax_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=ImaxTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.imax.imax_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=ImaxTestSequence + +# The server to use for Imax Actions +SERVER_URL=chromecast-alpha.sandbox.google.com + +# App config path for the given server. +APP_CONFIG_PATH=chrome://home?remote_url=https%3A%2F%2Fchromecast-alpha.sandbox.google.com%2Fcast%2Fchromecast%2Fhome%3Fclient-logging-level%3Dall%26slideshow-period%3D1 + +# Gaia ID for prod test account +GAIA_ID=473911208807
diff --git a/lab_system/master/config/tests/imax/imax_prod.cfg b/lab_system/master/config/tests/imax/imax_prod.cfg new file mode 100644 index 0000000..84bc708 --- /dev/null +++ b/lab_system/master/config/tests/imax/imax_prod.cfg
@@ -0,0 +1,27 @@ +# Config file for the imax tests in production environment +# +# Do not modify property names +# Run make reconfig if you change a value +# and buildbot is running +# +# PROPERTIES +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.imax.imax_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=ImaxTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.imax.imax_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=ImaxTestSequence + +# The server to use for Imax Actions +SERVER_URL=clients3.google.com + +# App config path for the given server. +APP_CONFIG_PATH=chrome://home?remote_url=https%3A%2F%2Fclients3.google.com%2Fcast%2Fchromecast%2Fhome%3Fclient-logging-level%3Dall%26slideshow-period%3D1 + +# Gaia ID for prod test account +GAIA_ID=473911208807
diff --git a/lab_system/master/config/tests/imax/imax_staging.cfg b/lab_system/master/config/tests/imax/imax_staging.cfg new file mode 100644 index 0000000..43981a7 --- /dev/null +++ b/lab_system/master/config/tests/imax/imax_staging.cfg
@@ -0,0 +1,27 @@ +# Config file for the imax tests for staging environment +# +# Do not modify property names +# Run make reconfig if you change a value +# and buildbot is running +# +# PROPERTIES +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.imax.imax_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=ImaxTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.imax.imax_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=ImaxTestSequence + +# The server to use for Imax Actions +SERVER_URL=chromecast-staging.sandbox.google.com + +# App config path for the given server. +APP_CONFIG_PATH=chrome://home?remote_url=https%3A%2F%2Fchromecast-staging.sandbox.google.com%2Fcast%2Fchromecast%2Fhome%3Fclient-logging-level%3Dall%26slideshow-period%3D1 + +# Gaia ID for prod test account +GAIA_ID=473911208807
diff --git a/lab_system/master/config/tests/imax/test_defs.json b/lab_system/master/config/tests/imax/test_defs.json new file mode 100644 index 0000000..3be4eda --- /dev/null +++ b/lab_system/master/config/tests/imax/test_defs.json
@@ -0,0 +1,80 @@ +[ + { + "branch": [ + "master", + "release" + ], + "device_group": "eureka_debug", + "device_type": "eureka", + "group_name": "imax", + "identifier": "imax_staging", + "slave_name": "imax", + "hidden": "true", + "test_name": "imax_staging" + }, + { + "branch": [ + "master", + "release" + ], + "device_group": "eureka_debug", + "device_type": "eureka", + "group_name": "imax", + "identifier": "imax", + "slave_name": "imax", + "hidden": "true", + "test_name": "imax" + }, + { + "branch": [ + "master", + "release" + ], + "device_group": "eureka_debug", + "device_type": "eureka", + "group_name": "imax", + "identifier": "imax_prod", + "slave_name": "imax", + "hidden": "true", + "test_name": "imax_prod" + }, + { + "branch": [ + "master", + "release" + ], + "device_group": "lexx_eth", + "device_type": "lexx", + "group_name": "imax", + "identifier": "imax_staging_v2", + "slave_name": "imax", + "hidden": "true", + "test_name": "imax_staging" + }, + { + "branch": [ + "master", + "release" + ], + "device_group": "lexx_eth", + "device_type": "lexx", + "group_name": "imax", + "identifier": "imax_v2", + "slave_name": "imax", + "hidden": "true", + "test_name": "imax" + }, + { + "branch": [ + "master", + "release" + ], + "device_group": "lexx_eth", + "device_type": "lexx", + "group_name": "imax", + "identifier": "imax_prod_v2", + "slave_name": "imax", + "hidden": "true", + "test_name": "imax_prod" + } +]
diff --git a/lab_system/master/config/tests/js_features/js_features.cfg b/lab_system/master/config/tests/js_features/js_features.cfg new file mode 100644 index 0000000..a91c244 --- /dev/null +++ b/lab_system/master/config/tests/js_features/js_features.cfg
@@ -0,0 +1,16 @@ +# Config file for testing enabled/disabled JavaScript app features. + +# Type of test used by the fr cli tool to run javascript tests: +TEST_TYPE=javascript + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.js_features.js_features_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=FeaturesEnabledTestCase,FeaturesDisabledTestCase + + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.js_features.js_features_test_sequence +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=JsFeaturesTestSequence
diff --git a/lab_system/master/config/tests/locale_string/locale_string.cfg b/lab_system/master/config/tests/locale_string/locale_string.cfg new file mode 100644 index 0000000..d67fc2f --- /dev/null +++ b/lab_system/master/config/tests/locale_string/locale_string.cfg
@@ -0,0 +1,15 @@ +# Config file for JavaScript audio format tests. +# +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.locale_string.locale_string_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=BasicStringTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.framework.javascript_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=JavascriptTestSequence + +
diff --git a/lab_system/master/config/tests/long_audio_play/long_audio_play.cfg b/lab_system/master/config/tests/long_audio_play/long_audio_play.cfg new file mode 100644 index 0000000..faff9d0 --- /dev/null +++ b/lab_system/master/config/tests/long_audio_play/long_audio_play.cfg
@@ -0,0 +1,18 @@ +# Config file for testing RebootLoop. +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.long_audio_play.long_audio_play_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=LongAudioPlayTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.framework.disabled_logging_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=DisabledLoggingTestSequence + +# Plot data +PLOT=False \ No newline at end of file
diff --git a/lab_system/master/config/tests/magic_mic_test/magic_mic_test.cfg b/lab_system/master/config/tests/magic_mic_test/magic_mic_test.cfg new file mode 100644 index 0000000..8cdcb08 --- /dev/null +++ b/lab_system/master/config/tests/magic_mic_test/magic_mic_test.cfg
@@ -0,0 +1,13 @@ +# Config file for magic mic query tests + +TEST_CASE_MODULE=eurtest.tests.assistant.magic_mic_test_case + +TEST_CASE_CLASS=MagicMicTest + +TEST_SEQUENCE_MODULE=eurtest.tests.assistant.assistant_test_sequence + +TEST_SEQUENCE_CLASS=AssistantTestSequence + +GCS_AUDIO_DIR_PATH=assistant/pineapple-p2-rerecordings/synthetic_speech/magic_mic + +ASSISTANT_BACKEND=DOGFOOD_SERVER
diff --git a/lab_system/master/config/tests/manhattan_ui_perf/manhattan_ambient.cfg b/lab_system/master/config/tests/manhattan_ui_perf/manhattan_ambient.cfg new file mode 100644 index 0000000..eece3eb --- /dev/null +++ b/lab_system/master/config/tests/manhattan_ui_perf/manhattan_ambient.cfg
@@ -0,0 +1,15 @@ +# Config file for Manhattan Ambient UI Performance Test Suite +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.manhattan.perf.manhattan_ui_perf_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=ManhattanUiPerfTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.manhattan.perf.ambient_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=AmbientTestSequence
diff --git a/lab_system/master/config/tests/manhattan_ui_perf/manhattan_animations.cfg b/lab_system/master/config/tests/manhattan_ui_perf/manhattan_animations.cfg new file mode 100644 index 0000000..919253f --- /dev/null +++ b/lab_system/master/config/tests/manhattan_ui_perf/manhattan_animations.cfg
@@ -0,0 +1,15 @@ +# Config file for Manhattan Animations UI Performance Test Suite +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.manhattan.perf.manhattan_ui_perf_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=ManhattanUiPerfTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.manhattan.perf.animations_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=AnimationsTestSequence
diff --git a/lab_system/master/config/tests/manhattan_ui_perf/manhattan_back_gestures.cfg b/lab_system/master/config/tests/manhattan_ui_perf/manhattan_back_gestures.cfg new file mode 100644 index 0000000..1f9cc10 --- /dev/null +++ b/lab_system/master/config/tests/manhattan_ui_perf/manhattan_back_gestures.cfg
@@ -0,0 +1,15 @@ +# Config file for Manhattan Back Gestures UI Performance Test Suite +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.manhattan.perf.manhattan_ui_perf_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=ManhattanUiPerfTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.manhattan.perf.back_gestures_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=BackGesturesTestSequence
diff --git a/lab_system/master/config/tests/manhattan_ui_perf/manhattan_carousel_load.cfg b/lab_system/master/config/tests/manhattan_ui_perf/manhattan_carousel_load.cfg new file mode 100644 index 0000000..7b09d6b --- /dev/null +++ b/lab_system/master/config/tests/manhattan_ui_perf/manhattan_carousel_load.cfg
@@ -0,0 +1,15 @@ +# Config file for Manhattan Carousel UI Performance Test Suite +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.manhattan.perf.manhattan_ui_perf_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=ManhattanUiPerfTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.manhattan.perf.carousel_loading_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=CarouselLoadingTestSequence
diff --git a/lab_system/master/config/tests/manhattan_ui_perf/manhattan_carousel_scroll.cfg b/lab_system/master/config/tests/manhattan_ui_perf/manhattan_carousel_scroll.cfg new file mode 100644 index 0000000..fa154d0 --- /dev/null +++ b/lab_system/master/config/tests/manhattan_ui_perf/manhattan_carousel_scroll.cfg
@@ -0,0 +1,15 @@ +# Config file for Manhattan Carousel UI Performance Test Suite +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.manhattan.perf.manhattan_ui_perf_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=ManhattanUiPerfTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.manhattan.perf.carousel_scrolling_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=CarouselScrollingTestSequence
diff --git a/lab_system/master/config/tests/manhattan_ui_perf/manhattan_coin_tray_gestures.cfg b/lab_system/master/config/tests/manhattan_ui_perf/manhattan_coin_tray_gestures.cfg new file mode 100644 index 0000000..4625054 --- /dev/null +++ b/lab_system/master/config/tests/manhattan_ui_perf/manhattan_coin_tray_gestures.cfg
@@ -0,0 +1,15 @@ +# Config file for Manhattan System Gestures UI Performance Test Suite +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.manhattan.perf.manhattan_ui_perf_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=ManhattanUiPerfTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.manhattan.perf.coin_tray_gestures_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=CoinTrayGesturesTestSequence
diff --git a/lab_system/master/config/tests/manhattan_ui_perf/manhattan_flutter_bridge_screenshot.cfg b/lab_system/master/config/tests/manhattan_ui_perf/manhattan_flutter_bridge_screenshot.cfg new file mode 100644 index 0000000..f866a27 --- /dev/null +++ b/lab_system/master/config/tests/manhattan_ui_perf/manhattan_flutter_bridge_screenshot.cfg
@@ -0,0 +1,15 @@ +# Config file for Opal UI screenshot test. +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.manhattan.perf.opal_ui_perf_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=OpalUiPerfTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.manhattan.perf.flutter_bridge_screenshot + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=FlutterBridgeScreenshotTestSequence
diff --git a/lab_system/master/config/tests/manhattan_ui_perf/manhattan_form_filling.cfg b/lab_system/master/config/tests/manhattan_ui_perf/manhattan_form_filling.cfg new file mode 100644 index 0000000..3f02433 --- /dev/null +++ b/lab_system/master/config/tests/manhattan_ui_perf/manhattan_form_filling.cfg
@@ -0,0 +1,15 @@ +# Config file for Manhattan Form Filling UI Performance Test Suite +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.manhattan.perf.manhattan_ui_perf_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=ManhattanUiPerfTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.manhattan.perf.form_filling_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=FormFillingTestSequence
diff --git a/lab_system/master/config/tests/manhattan_ui_perf/manhattan_go_back.cfg b/lab_system/master/config/tests/manhattan_ui_perf/manhattan_go_back.cfg new file mode 100644 index 0000000..1d184e5 --- /dev/null +++ b/lab_system/master/config/tests/manhattan_ui_perf/manhattan_go_back.cfg
@@ -0,0 +1,15 @@ +# Config file for Manhattan 'go back' UI Performance Test Suite +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.manhattan.perf.manhattan_ui_perf_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=ManhattanUiPerfTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.manhattan.perf.go_back_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=GoBackTestSequence
diff --git a/lab_system/master/config/tests/manhattan_ui_perf/manhattan_home_scrolling.cfg b/lab_system/master/config/tests/manhattan_ui_perf/manhattan_home_scrolling.cfg new file mode 100644 index 0000000..be99d4a --- /dev/null +++ b/lab_system/master/config/tests/manhattan_ui_perf/manhattan_home_scrolling.cfg
@@ -0,0 +1,15 @@ +# Config file for Manhattan Home Scrolling Performance Test Suite +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.manhattan.perf.manhattan_ui_perf_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=ManhattanUiPerfTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.manhattan.perf.home_scrolling_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=HomeScrollingTestSequence
diff --git a/lab_system/master/config/tests/manhattan_ui_perf/manhattan_idle.cfg b/lab_system/master/config/tests/manhattan_ui_perf/manhattan_idle.cfg new file mode 100644 index 0000000..bd7bb24 --- /dev/null +++ b/lab_system/master/config/tests/manhattan_ui_perf/manhattan_idle.cfg
@@ -0,0 +1,15 @@ +# Config file for Manhattan Idle UI Performance Test Suite +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.manhattan.perf.manhattan_ui_perf_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=ManhattanUiPerfTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.manhattan.perf.idle_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=IdleTestSequence
diff --git a/lab_system/master/config/tests/manhattan_ui_perf/manhattan_knowledge.cfg b/lab_system/master/config/tests/manhattan_ui_perf/manhattan_knowledge.cfg new file mode 100644 index 0000000..f77d4d4 --- /dev/null +++ b/lab_system/master/config/tests/manhattan_ui_perf/manhattan_knowledge.cfg
@@ -0,0 +1,18 @@ +# Config file for Knowledge Card Tests +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.manhattan.perf.opal_ui_perf_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=OpalUiPerfTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.manhattan.perf.knowledge_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=KnowledgeTestSequence + +# Indicates whether or not we should sign the device in +SIGNED_IN=True
diff --git a/lab_system/master/config/tests/manhattan_ui_perf/manhattan_knowledge_master_latest.cfg b/lab_system/master/config/tests/manhattan_ui_perf/manhattan_knowledge_master_latest.cfg new file mode 100644 index 0000000..9d53159 --- /dev/null +++ b/lab_system/master/config/tests/manhattan_ui_perf/manhattan_knowledge_master_latest.cfg
@@ -0,0 +1,21 @@ +# Config file for Knowledge Card Tests +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.manhattan.perf.opal_ui_perf_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=OpalUiPerfTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.manhattan.perf.knowledge_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=KnowledgeTestSequence + +# Indicates whether or not we should sign the device in +SIGNED_IN=True + +# Override the prebuilt image of Opal +OPAL_REF=master_latest
diff --git a/lab_system/master/config/tests/manhattan_ui_perf/manhattan_knowledge_tsmc.cfg b/lab_system/master/config/tests/manhattan_ui_perf/manhattan_knowledge_tsmc.cfg new file mode 100644 index 0000000..f77d4d4 --- /dev/null +++ b/lab_system/master/config/tests/manhattan_ui_perf/manhattan_knowledge_tsmc.cfg
@@ -0,0 +1,18 @@ +# Config file for Knowledge Card Tests +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.manhattan.perf.opal_ui_perf_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=OpalUiPerfTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.manhattan.perf.knowledge_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=KnowledgeTestSequence + +# Indicates whether or not we should sign the device in +SIGNED_IN=True
diff --git a/lab_system/master/config/tests/manhattan_ui_perf/manhattan_music_playback.cfg b/lab_system/master/config/tests/manhattan_ui_perf/manhattan_music_playback.cfg new file mode 100644 index 0000000..eae5bf9 --- /dev/null +++ b/lab_system/master/config/tests/manhattan_ui_perf/manhattan_music_playback.cfg
@@ -0,0 +1,15 @@ +# Config file for Manhattan Music Playback UI Performance Test Suite +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.manhattan.perf.manhattan_ui_perf_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=ManhattanUiPerfTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.manhattan.perf.music_playback_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=MusicPlaybackTestSequence
diff --git a/lab_system/master/config/tests/manhattan_ui_perf/manhattan_navigation.cfg b/lab_system/master/config/tests/manhattan_ui_perf/manhattan_navigation.cfg new file mode 100644 index 0000000..29f4aff --- /dev/null +++ b/lab_system/master/config/tests/manhattan_ui_perf/manhattan_navigation.cfg
@@ -0,0 +1,15 @@ +# Config file for Manhattan Navigation UI Performance Test Suite +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.manhattan.perf.manhattan_ui_perf_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=ManhattanUiPerfTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.manhattan.perf.navigation_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=NavigationTestSequence
diff --git a/lab_system/master/config/tests/manhattan_ui_perf/manhattan_perception_ambient.cfg b/lab_system/master/config/tests/manhattan_ui_perf/manhattan_perception_ambient.cfg new file mode 100644 index 0000000..e9bf790 --- /dev/null +++ b/lab_system/master/config/tests/manhattan_ui_perf/manhattan_perception_ambient.cfg
@@ -0,0 +1,19 @@ +# Config file for Manhattan Perception Ambient UI Performance Test Suite +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.manhattan.perf.manhattan_ui_perf_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=ManhattanUiPerfTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.manhattan.perf.ambient_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=AmbientTestSequence + +# GCS bucket and path for the perception video +GCS_VIDEO_PATH=perception/test_videos/motion/03ft_3p_bd_2_edit.mp4 +GCS_BUCKET=catatester_test_deps
diff --git a/lab_system/master/config/tests/manhattan_ui_perf/manhattan_perception_animations.cfg b/lab_system/master/config/tests/manhattan_ui_perf/manhattan_perception_animations.cfg new file mode 100644 index 0000000..678c5f8 --- /dev/null +++ b/lab_system/master/config/tests/manhattan_ui_perf/manhattan_perception_animations.cfg
@@ -0,0 +1,19 @@ +# Config file for Manhattan Perception Animations UI Performance Test Suite +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.manhattan.perf.manhattan_ui_perf_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=ManhattanUiPerfTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.manhattan.perf.animations_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=AnimationsTestSequence + +# GCS bucket and path for the perception video +GCS_VIDEO_PATH=perception/test_videos/motion/03ft_3p_bd_2_edit.mp4 +GCS_BUCKET=catatester_test_deps \ No newline at end of file
diff --git a/lab_system/master/config/tests/manhattan_ui_perf/manhattan_perception_carousel_load.cfg b/lab_system/master/config/tests/manhattan_ui_perf/manhattan_perception_carousel_load.cfg new file mode 100644 index 0000000..225f0bd --- /dev/null +++ b/lab_system/master/config/tests/manhattan_ui_perf/manhattan_perception_carousel_load.cfg
@@ -0,0 +1,19 @@ +# Config file for Manhattan Perception Carousel UI Performance Test Suite +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.manhattan.perf.manhattan_ui_perf_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=ManhattanUiPerfTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.manhattan.perf.carousel_loading_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=CarouselLoadingTestSequence + +# GCS bucket and path for the perception video +GCS_VIDEO_PATH=perception/test_videos/motion/03ft_3p_bd_2_edit.mp4 +GCS_BUCKET=catatester_test_deps \ No newline at end of file
diff --git a/lab_system/master/config/tests/manhattan_ui_perf/manhattan_perception_carousel_scroll.cfg b/lab_system/master/config/tests/manhattan_ui_perf/manhattan_perception_carousel_scroll.cfg new file mode 100644 index 0000000..d284963 --- /dev/null +++ b/lab_system/master/config/tests/manhattan_ui_perf/manhattan_perception_carousel_scroll.cfg
@@ -0,0 +1,19 @@ +# Config file for Manhattan Perception Carousel UI Performance Test Suite +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.manhattan.perf.manhattan_ui_perf_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=ManhattanUiPerfTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.manhattan.perf.carousel_scrolling_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=CarouselScrollingTestSequence + +# GCS bucket and path for the perception video +GCS_VIDEO_PATH=perception/test_videos/motion/03ft_3p_bd_2_edit.mp4 +GCS_BUCKET=catatester_test_deps \ No newline at end of file
diff --git a/lab_system/master/config/tests/manhattan_ui_perf/manhattan_perception_form_filling.cfg b/lab_system/master/config/tests/manhattan_ui_perf/manhattan_perception_form_filling.cfg new file mode 100644 index 0000000..03074a6 --- /dev/null +++ b/lab_system/master/config/tests/manhattan_ui_perf/manhattan_perception_form_filling.cfg
@@ -0,0 +1,19 @@ +# Config file for Manhattan Perception Form Filling UI Performance Test Suite +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.manhattan.perf.manhattan_ui_perf_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=ManhattanUiPerfTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.manhattan.perf.form_filling_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=FormFillingTestSequence + +# GCS bucket and path for the perception video +GCS_VIDEO_PATH=perception/test_videos/motion/03ft_3p_bd_2_edit.mp4 +GCS_BUCKET=catatester_test_deps \ No newline at end of file
diff --git a/lab_system/master/config/tests/manhattan_ui_perf/manhattan_perception_go_back.cfg b/lab_system/master/config/tests/manhattan_ui_perf/manhattan_perception_go_back.cfg new file mode 100644 index 0000000..49ef6d7 --- /dev/null +++ b/lab_system/master/config/tests/manhattan_ui_perf/manhattan_perception_go_back.cfg
@@ -0,0 +1,19 @@ +# Config file for Manhattan Perception 'go back' UI Performance Test Suite +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.manhattan.perf.manhattan_ui_perf_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=ManhattanUiPerfTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.manhattan.perf.go_back_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=GoBackTestSequence + +# GCS bucket and path for the perception video +GCS_VIDEO_PATH=perception/test_videos/motion/03ft_3p_bd_2_edit.mp4 +GCS_BUCKET=catatester_test_deps \ No newline at end of file
diff --git a/lab_system/master/config/tests/manhattan_ui_perf/manhattan_perception_home_scrolling.cfg b/lab_system/master/config/tests/manhattan_ui_perf/manhattan_perception_home_scrolling.cfg new file mode 100644 index 0000000..e948b75 --- /dev/null +++ b/lab_system/master/config/tests/manhattan_ui_perf/manhattan_perception_home_scrolling.cfg
@@ -0,0 +1,19 @@ +# Config file for Manhattan Perception Home Scrolling Performance Test Suite +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.manhattan.perf.manhattan_ui_perf_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=ManhattanUiPerfTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.manhattan.perf.home_scrolling_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=HomeScrollingTestSequence + +# GCS bucket and path for the perception video +GCS_VIDEO_PATH=perception/test_videos/motion/03ft_3p_bd_2_edit.mp4 +GCS_BUCKET=catatester_test_deps \ No newline at end of file
diff --git a/lab_system/master/config/tests/manhattan_ui_perf/manhattan_perception_music_playback.cfg b/lab_system/master/config/tests/manhattan_ui_perf/manhattan_perception_music_playback.cfg new file mode 100644 index 0000000..61d19af --- /dev/null +++ b/lab_system/master/config/tests/manhattan_ui_perf/manhattan_perception_music_playback.cfg
@@ -0,0 +1,19 @@ +# Config file for Manhattan Perception Music Playback UI Performance Test Suite +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.manhattan.perf.manhattan_ui_perf_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=ManhattanUiPerfTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.manhattan.perf.music_playback_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=MusicPlaybackTestSequence + +# GCS bucket and path for the perception video +GCS_VIDEO_PATH=perception/test_videos/motion/03ft_3p_bd_2_edit.mp4 +GCS_BUCKET=catatester_test_deps \ No newline at end of file
diff --git a/lab_system/master/config/tests/manhattan_ui_perf/manhattan_perception_navigation.cfg b/lab_system/master/config/tests/manhattan_ui_perf/manhattan_perception_navigation.cfg new file mode 100644 index 0000000..0b3b156 --- /dev/null +++ b/lab_system/master/config/tests/manhattan_ui_perf/manhattan_perception_navigation.cfg
@@ -0,0 +1,19 @@ +# Config file for Manhattan Perception Navigation UI Performance Test Suite +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.manhattan.perf.manhattan_ui_perf_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=ManhattanUiPerfTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.manhattan.perf.navigation_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=NavigationTestSequence + +# GCS bucket and path for the perception video +GCS_VIDEO_PATH=perception/test_videos/motion/03ft_3p_bd_2_edit.mp4 +GCS_BUCKET=catatester_test_deps \ No newline at end of file
diff --git a/lab_system/master/config/tests/manhattan_ui_perf/manhattan_perception_recipes.cfg b/lab_system/master/config/tests/manhattan_ui_perf/manhattan_perception_recipes.cfg new file mode 100644 index 0000000..f2db1f0 --- /dev/null +++ b/lab_system/master/config/tests/manhattan_ui_perf/manhattan_perception_recipes.cfg
@@ -0,0 +1,19 @@ +# Config file for Manhattan Perception Recipes UI Performance Test Suite +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.manhattan.perf.manhattan_ui_perf_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=ManhattanUiPerfTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.manhattan.perf.recipes_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=RecipesTestSequence + +# GCS bucket and path for the perception video +GCS_VIDEO_PATH=perception/test_videos/motion/03ft_3p_bd_2_edit.mp4 +GCS_BUCKET=catatester_test_deps \ No newline at end of file
diff --git a/lab_system/master/config/tests/manhattan_ui_perf/manhattan_perception_youtube.cfg b/lab_system/master/config/tests/manhattan_ui_perf/manhattan_perception_youtube.cfg new file mode 100644 index 0000000..29692e1 --- /dev/null +++ b/lab_system/master/config/tests/manhattan_ui_perf/manhattan_perception_youtube.cfg
@@ -0,0 +1,19 @@ +# Config file for Manhattan Perception YouTube Playback UI Performance Test Suite +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.manhattan.perf.manhattan_ui_perf_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=ManhattanUiPerfTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.manhattan.perf.youtube_playback_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=YouTubePlaybackTestSequence + +# GCS bucket and path for the perception video +GCS_VIDEO_PATH=perception/test_videos/motion/03ft_3p_bd_2_edit.mp4 +GCS_BUCKET=catatester_test_deps \ No newline at end of file
diff --git a/lab_system/master/config/tests/manhattan_ui_perf/manhattan_recipes.cfg b/lab_system/master/config/tests/manhattan_ui_perf/manhattan_recipes.cfg new file mode 100644 index 0000000..6c26489 --- /dev/null +++ b/lab_system/master/config/tests/manhattan_ui_perf/manhattan_recipes.cfg
@@ -0,0 +1,15 @@ +# Config file for Manhattan Recipes UI Performance Test Suite +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.manhattan.perf.manhattan_ui_perf_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=ManhattanUiPerfTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.manhattan.perf.recipes_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=RecipesTestSequence
diff --git a/lab_system/master/config/tests/manhattan_ui_perf/manhattan_system_gestures.cfg b/lab_system/master/config/tests/manhattan_ui_perf/manhattan_system_gestures.cfg new file mode 100644 index 0000000..45ac8ca --- /dev/null +++ b/lab_system/master/config/tests/manhattan_ui_perf/manhattan_system_gestures.cfg
@@ -0,0 +1,15 @@ +# Config file for Manhattan System Gestures UI Performance Test Suite +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.manhattan.perf.manhattan_ui_perf_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=ManhattanUiPerfTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.manhattan.perf.system_gestures_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=SystemGesturesTestSequence
diff --git a/lab_system/master/config/tests/manhattan_ui_perf/manhattan_weather.cfg b/lab_system/master/config/tests/manhattan_ui_perf/manhattan_weather.cfg new file mode 100644 index 0000000..8206556 --- /dev/null +++ b/lab_system/master/config/tests/manhattan_ui_perf/manhattan_weather.cfg
@@ -0,0 +1,18 @@ +# Config file for Weather Tests +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.manhattan.perf.opal_ui_perf_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=OpalUiPerfTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.manhattan.perf.weather_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=WeatherTestSequence + +# Indicates whether or not we should sign the device in +SIGNED_IN=True
diff --git a/lab_system/master/config/tests/manhattan_ui_perf/manhattan_weather_master_latest.cfg b/lab_system/master/config/tests/manhattan_ui_perf/manhattan_weather_master_latest.cfg new file mode 100644 index 0000000..28caf02 --- /dev/null +++ b/lab_system/master/config/tests/manhattan_ui_perf/manhattan_weather_master_latest.cfg
@@ -0,0 +1,21 @@ +# Config file for Weather Tests +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.manhattan.perf.opal_ui_perf_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=OpalUiPerfTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.manhattan.perf.weather_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=WeatherTestSequence + +# Indicates whether or not we should sign the device in +SIGNED_IN=True + +# Override the prebuilt image of Opal +OPAL_REF=master_latest
diff --git a/lab_system/master/config/tests/manhattan_ui_perf/manhattan_weather_tsmc.cfg b/lab_system/master/config/tests/manhattan_ui_perf/manhattan_weather_tsmc.cfg new file mode 100644 index 0000000..8206556 --- /dev/null +++ b/lab_system/master/config/tests/manhattan_ui_perf/manhattan_weather_tsmc.cfg
@@ -0,0 +1,18 @@ +# Config file for Weather Tests +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.manhattan.perf.opal_ui_perf_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=OpalUiPerfTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.manhattan.perf.weather_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=WeatherTestSequence + +# Indicates whether or not we should sign the device in +SIGNED_IN=True
diff --git a/lab_system/master/config/tests/manhattan_ui_perf/manhattan_youtube.cfg b/lab_system/master/config/tests/manhattan_ui_perf/manhattan_youtube.cfg new file mode 100644 index 0000000..c9190db --- /dev/null +++ b/lab_system/master/config/tests/manhattan_ui_perf/manhattan_youtube.cfg
@@ -0,0 +1,15 @@ +# Config file for Manhattan YouTube Playback UI Performance Test Suite +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.manhattan.perf.manhattan_ui_perf_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=ManhattanUiPerfTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.manhattan.perf.youtube_playback_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=YouTubePlaybackTestSequence
diff --git a/lab_system/master/config/tests/manhattan_ui_perf/opal_ambient.cfg b/lab_system/master/config/tests/manhattan_ui_perf/opal_ambient.cfg new file mode 100644 index 0000000..192d15d --- /dev/null +++ b/lab_system/master/config/tests/manhattan_ui_perf/opal_ambient.cfg
@@ -0,0 +1,18 @@ +# Config file for Manhattan Ambient UI Performance Test Suite +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.manhattan.perf.opal_ui_perf_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=OpalUiPerfTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.manhattan.perf.ambient_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=AmbientTestSequence + +# Indicates whether or not we should sign the device in +SIGNED_IN=True
diff --git a/lab_system/master/config/tests/manhattan_ui_perf/opal_animations.cfg b/lab_system/master/config/tests/manhattan_ui_perf/opal_animations.cfg new file mode 100644 index 0000000..6a8d75d --- /dev/null +++ b/lab_system/master/config/tests/manhattan_ui_perf/opal_animations.cfg
@@ -0,0 +1,18 @@ +# Config file for Manhattan Animations UI Performance Test Suite +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.manhattan.perf.opal_ui_perf_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=OpalUiPerfTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.manhattan.perf.animations_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=AnimationsTestSequence + +# Indicates whether or not we should sign the device in +SIGNED_IN=True
diff --git a/lab_system/master/config/tests/manhattan_ui_perf/opal_animations_master_latest.cfg b/lab_system/master/config/tests/manhattan_ui_perf/opal_animations_master_latest.cfg new file mode 100644 index 0000000..4838365 --- /dev/null +++ b/lab_system/master/config/tests/manhattan_ui_perf/opal_animations_master_latest.cfg
@@ -0,0 +1,21 @@ +# Config file for Manhattan Animations UI Performance Test Suite +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.manhattan.perf.opal_ui_perf_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=OpalUiPerfTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.manhattan.perf.animations_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=AnimationsTestSequence + +# Indicates whether or not we should sign the device in +SIGNED_IN=True + +# Override the prebuilt image of Opal +OPAL_REF=master_latest
diff --git a/lab_system/master/config/tests/manhattan_ui_perf/opal_animations_tsmc.cfg b/lab_system/master/config/tests/manhattan_ui_perf/opal_animations_tsmc.cfg new file mode 100644 index 0000000..6a8d75d --- /dev/null +++ b/lab_system/master/config/tests/manhattan_ui_perf/opal_animations_tsmc.cfg
@@ -0,0 +1,18 @@ +# Config file for Manhattan Animations UI Performance Test Suite +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.manhattan.perf.opal_ui_perf_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=OpalUiPerfTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.manhattan.perf.animations_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=AnimationsTestSequence + +# Indicates whether or not we should sign the device in +SIGNED_IN=True
diff --git a/lab_system/master/config/tests/manhattan_ui_perf/opal_back_gestures.cfg b/lab_system/master/config/tests/manhattan_ui_perf/opal_back_gestures.cfg new file mode 100644 index 0000000..164a68f --- /dev/null +++ b/lab_system/master/config/tests/manhattan_ui_perf/opal_back_gestures.cfg
@@ -0,0 +1,18 @@ +# Config file for Manhattan Ambient UI Performance Test Suite +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.manhattan.perf.opal_ui_perf_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=OpalUiPerfTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.manhattan.perf.back_gestures_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=BackGesturesTestSequence + +# Indicates whether or not we should sign the device in +SIGNED_IN=True
diff --git a/lab_system/master/config/tests/manhattan_ui_perf/opal_back_gestures_master_latest.cfg b/lab_system/master/config/tests/manhattan_ui_perf/opal_back_gestures_master_latest.cfg new file mode 100644 index 0000000..a8ff8e2 --- /dev/null +++ b/lab_system/master/config/tests/manhattan_ui_perf/opal_back_gestures_master_latest.cfg
@@ -0,0 +1,21 @@ +# Config file for Manhattan Ambient UI Performance Test Suite +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.manhattan.perf.opal_ui_perf_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=OpalUiPerfTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.manhattan.perf.opal_back_gestures_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=BackGesturesTestSequence + +# Indicates whether or not we should sign the device in +SIGNED_IN=True + +# Override the prebuilt image of Opal +OPAL_REF=master_latest
diff --git a/lab_system/master/config/tests/manhattan_ui_perf/opal_back_gestures_tsmc.cfg b/lab_system/master/config/tests/manhattan_ui_perf/opal_back_gestures_tsmc.cfg new file mode 100644 index 0000000..164a68f --- /dev/null +++ b/lab_system/master/config/tests/manhattan_ui_perf/opal_back_gestures_tsmc.cfg
@@ -0,0 +1,18 @@ +# Config file for Manhattan Ambient UI Performance Test Suite +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.manhattan.perf.opal_ui_perf_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=OpalUiPerfTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.manhattan.perf.back_gestures_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=BackGesturesTestSequence + +# Indicates whether or not we should sign the device in +SIGNED_IN=True
diff --git a/lab_system/master/config/tests/manhattan_ui_perf/opal_carousel_load.cfg b/lab_system/master/config/tests/manhattan_ui_perf/opal_carousel_load.cfg new file mode 100644 index 0000000..57bd0e0 --- /dev/null +++ b/lab_system/master/config/tests/manhattan_ui_perf/opal_carousel_load.cfg
@@ -0,0 +1,18 @@ +# Config file for Manhattan Carousel UI Performance Test Suite +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.manhattan.perf.opal_ui_perf_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=OpalUiPerfTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.manhattan.perf.carousel_loading_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=CarouselLoadingTestSequence + +# Indicates whether or not we should sign the device in +SIGNED_IN=True
diff --git a/lab_system/master/config/tests/manhattan_ui_perf/opal_carousel_load_master_latest.cfg b/lab_system/master/config/tests/manhattan_ui_perf/opal_carousel_load_master_latest.cfg new file mode 100644 index 0000000..489fbb9 --- /dev/null +++ b/lab_system/master/config/tests/manhattan_ui_perf/opal_carousel_load_master_latest.cfg
@@ -0,0 +1,21 @@ +# Config file for Manhattan Carousel UI Performance Test Suite +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.manhattan.perf.opal_ui_perf_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=OpalUiPerfTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.manhattan.perf.carousel_loading_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=CarouselLoadingTestSequence + +# Indicates whether or not we should sign the device in +SIGNED_IN=True + +# Override the prebuilt image of Opal +OPAL_REF=master_latest
diff --git a/lab_system/master/config/tests/manhattan_ui_perf/opal_carousel_load_tsmc.cfg b/lab_system/master/config/tests/manhattan_ui_perf/opal_carousel_load_tsmc.cfg new file mode 100644 index 0000000..57bd0e0 --- /dev/null +++ b/lab_system/master/config/tests/manhattan_ui_perf/opal_carousel_load_tsmc.cfg
@@ -0,0 +1,18 @@ +# Config file for Manhattan Carousel UI Performance Test Suite +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.manhattan.perf.opal_ui_perf_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=OpalUiPerfTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.manhattan.perf.carousel_loading_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=CarouselLoadingTestSequence + +# Indicates whether or not we should sign the device in +SIGNED_IN=True
diff --git a/lab_system/master/config/tests/manhattan_ui_perf/opal_carousel_scroll.cfg b/lab_system/master/config/tests/manhattan_ui_perf/opal_carousel_scroll.cfg new file mode 100644 index 0000000..1729edc --- /dev/null +++ b/lab_system/master/config/tests/manhattan_ui_perf/opal_carousel_scroll.cfg
@@ -0,0 +1,18 @@ +# Config file for Manhattan Carousel UI Performance Test Suite +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.manhattan.perf.opal_ui_perf_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=OpalUiPerfTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.manhattan.perf.carousel_scrolling_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=CarouselScrollingTestSequence + +# Indicates whether or not we should sign the device in +SIGNED_IN=True
diff --git a/lab_system/master/config/tests/manhattan_ui_perf/opal_carousel_scroll_master_latest.cfg b/lab_system/master/config/tests/manhattan_ui_perf/opal_carousel_scroll_master_latest.cfg new file mode 100644 index 0000000..db28a3f --- /dev/null +++ b/lab_system/master/config/tests/manhattan_ui_perf/opal_carousel_scroll_master_latest.cfg
@@ -0,0 +1,21 @@ +# Config file for Manhattan Carousel UI Performance Test Suite +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.manhattan.perf.opal_ui_perf_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=OpalUiPerfTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.manhattan.perf.carousel_scrolling_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=CarouselScrollingTestSequence + +# Indicates whether or not we should sign the device in +SIGNED_IN=True + +# Override the prebuilt image of Opal +OPAL_REF=master_latest
diff --git a/lab_system/master/config/tests/manhattan_ui_perf/opal_carousel_scroll_tsmc.cfg b/lab_system/master/config/tests/manhattan_ui_perf/opal_carousel_scroll_tsmc.cfg new file mode 100644 index 0000000..1729edc --- /dev/null +++ b/lab_system/master/config/tests/manhattan_ui_perf/opal_carousel_scroll_tsmc.cfg
@@ -0,0 +1,18 @@ +# Config file for Manhattan Carousel UI Performance Test Suite +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.manhattan.perf.opal_ui_perf_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=OpalUiPerfTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.manhattan.perf.carousel_scrolling_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=CarouselScrollingTestSequence + +# Indicates whether or not we should sign the device in +SIGNED_IN=True
diff --git a/lab_system/master/config/tests/manhattan_ui_perf/opal_coin_tray_gestures.cfg b/lab_system/master/config/tests/manhattan_ui_perf/opal_coin_tray_gestures.cfg new file mode 100644 index 0000000..9cf439d --- /dev/null +++ b/lab_system/master/config/tests/manhattan_ui_perf/opal_coin_tray_gestures.cfg
@@ -0,0 +1,18 @@ +# Config file for Manhattan System Gestures UI Performance Test Suite +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.manhattan.perf.opal_ui_perf_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=OpalUiPerfTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.manhattan.perf.coin_tray_gestures_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=CoinTrayGesturesTestSequence + +# Indicates whether or not we should sign the device in +SIGNED_IN=True
diff --git a/lab_system/master/config/tests/manhattan_ui_perf/opal_cujs.cfg b/lab_system/master/config/tests/manhattan_ui_perf/opal_cujs.cfg new file mode 100644 index 0000000..7dfac86 --- /dev/null +++ b/lab_system/master/config/tests/manhattan_ui_perf/opal_cujs.cfg
@@ -0,0 +1,18 @@ +# Config file for Opal CUJ Tests +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.manhattan.perf.opal_ui_perf_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=OpalUiPerfTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.manhattan.perf.opal_cuj_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=OpalCujTestSequence + +# Indicates whether or not we should sign the device in +SIGNED_IN=True
diff --git a/lab_system/master/config/tests/manhattan_ui_perf/opal_cujs_master_latest.cfg b/lab_system/master/config/tests/manhattan_ui_perf/opal_cujs_master_latest.cfg new file mode 100644 index 0000000..30275f0 --- /dev/null +++ b/lab_system/master/config/tests/manhattan_ui_perf/opal_cujs_master_latest.cfg
@@ -0,0 +1,21 @@ +# Config file for Opal CUJ Tests +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.manhattan.perf.opal_ui_perf_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=OpalUiPerfTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.manhattan.perf.opal_cuj_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=OpalCujTestSequence + +# Indicates whether or not we should sign the device in +SIGNED_IN=True + +# Override the prebuilt image of Opal +OPAL_REF=master_latest
diff --git a/lab_system/master/config/tests/manhattan_ui_perf/opal_cujs_tsmc.cfg b/lab_system/master/config/tests/manhattan_ui_perf/opal_cujs_tsmc.cfg new file mode 100644 index 0000000..7dfac86 --- /dev/null +++ b/lab_system/master/config/tests/manhattan_ui_perf/opal_cujs_tsmc.cfg
@@ -0,0 +1,18 @@ +# Config file for Opal CUJ Tests +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.manhattan.perf.opal_ui_perf_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=OpalUiPerfTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.manhattan.perf.opal_cuj_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=OpalCujTestSequence + +# Indicates whether or not we should sign the device in +SIGNED_IN=True
diff --git a/lab_system/master/config/tests/manhattan_ui_perf/opal_form_filling.cfg b/lab_system/master/config/tests/manhattan_ui_perf/opal_form_filling.cfg new file mode 100644 index 0000000..6dc12d8 --- /dev/null +++ b/lab_system/master/config/tests/manhattan_ui_perf/opal_form_filling.cfg
@@ -0,0 +1,18 @@ +# Config file for Manhattan Form Filling UI Performance Test Suite +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.manhattan.perf.opal_ui_perf_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=OpalUiPerfTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.manhattan.perf.form_filling_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=FormFillingTestSequence + +# Indicates whether or not we should sign the device in +SIGNED_IN=True
diff --git a/lab_system/master/config/tests/manhattan_ui_perf/opal_form_filling_master_latest.cfg b/lab_system/master/config/tests/manhattan_ui_perf/opal_form_filling_master_latest.cfg new file mode 100644 index 0000000..6a72ad9 --- /dev/null +++ b/lab_system/master/config/tests/manhattan_ui_perf/opal_form_filling_master_latest.cfg
@@ -0,0 +1,21 @@ +# Config file for Manhattan Form Filling UI Performance Test Suite +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.manhattan.perf.opal_ui_perf_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=OpalUiPerfTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.manhattan.perf.form_filling_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=FormFillingTestSequence + +# Indicates whether or not we should sign the device in +SIGNED_IN=True + +# Override the prebuilt image of Opal +OPAL_REF=master_latest
diff --git a/lab_system/master/config/tests/manhattan_ui_perf/opal_form_filling_tsmc.cfg b/lab_system/master/config/tests/manhattan_ui_perf/opal_form_filling_tsmc.cfg new file mode 100644 index 0000000..6dc12d8 --- /dev/null +++ b/lab_system/master/config/tests/manhattan_ui_perf/opal_form_filling_tsmc.cfg
@@ -0,0 +1,18 @@ +# Config file for Manhattan Form Filling UI Performance Test Suite +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.manhattan.perf.opal_ui_perf_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=OpalUiPerfTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.manhattan.perf.form_filling_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=FormFillingTestSequence + +# Indicates whether or not we should sign the device in +SIGNED_IN=True
diff --git a/lab_system/master/config/tests/manhattan_ui_perf/opal_go_back.cfg b/lab_system/master/config/tests/manhattan_ui_perf/opal_go_back.cfg new file mode 100644 index 0000000..73779b4 --- /dev/null +++ b/lab_system/master/config/tests/manhattan_ui_perf/opal_go_back.cfg
@@ -0,0 +1,18 @@ +# Config file for Manhattan 'go back' UI Performance Test Suite +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.manhattan.perf.opal_ui_perf_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=OpalUiPerfTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.manhattan.perf.go_back_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=GoBackTestSequence + +# Indicates whether or not we should sign the device in +SIGNED_IN=True
diff --git a/lab_system/master/config/tests/manhattan_ui_perf/opal_go_back_master_latest.cfg b/lab_system/master/config/tests/manhattan_ui_perf/opal_go_back_master_latest.cfg new file mode 100644 index 0000000..bea9a89 --- /dev/null +++ b/lab_system/master/config/tests/manhattan_ui_perf/opal_go_back_master_latest.cfg
@@ -0,0 +1,21 @@ +# Config file for Manhattan 'go back' UI Performance Test Suite +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.manhattan.perf.opal_ui_perf_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=OpalUiPerfTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.manhattan.perf.go_back_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=GoBackTestSequence + +# Indicates whether or not we should sign the device in +SIGNED_IN=True + +# Override the prebuilt image of Opal +OPAL_REF=master_latest
diff --git a/lab_system/master/config/tests/manhattan_ui_perf/opal_go_back_tsmc.cfg b/lab_system/master/config/tests/manhattan_ui_perf/opal_go_back_tsmc.cfg new file mode 100644 index 0000000..73779b4 --- /dev/null +++ b/lab_system/master/config/tests/manhattan_ui_perf/opal_go_back_tsmc.cfg
@@ -0,0 +1,18 @@ +# Config file for Manhattan 'go back' UI Performance Test Suite +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.manhattan.perf.opal_ui_perf_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=OpalUiPerfTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.manhattan.perf.go_back_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=GoBackTestSequence + +# Indicates whether or not we should sign the device in +SIGNED_IN=True
diff --git a/lab_system/master/config/tests/manhattan_ui_perf/opal_home_scrolling.cfg b/lab_system/master/config/tests/manhattan_ui_perf/opal_home_scrolling.cfg new file mode 100644 index 0000000..61d4112 --- /dev/null +++ b/lab_system/master/config/tests/manhattan_ui_perf/opal_home_scrolling.cfg
@@ -0,0 +1,18 @@ +# Config file for Manhattan Home Scrolling Performance Test Suite +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.manhattan.perf.opal_ui_perf_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=OpalUiPerfTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.manhattan.perf.home_scrolling_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=HomeScrollingTestSequence + +# Indicates whether or not we should sign the device in +SIGNED_IN=True
diff --git a/lab_system/master/config/tests/manhattan_ui_perf/opal_idle.cfg b/lab_system/master/config/tests/manhattan_ui_perf/opal_idle.cfg new file mode 100644 index 0000000..f7ea411 --- /dev/null +++ b/lab_system/master/config/tests/manhattan_ui_perf/opal_idle.cfg
@@ -0,0 +1,18 @@ +# Config file for Manhattan Idle UI Performance Test Suite +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.manhattan.perf.opal_ui_perf_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=OpalUiPerfTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.manhattan.perf.idle_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=IdleTestSequence + +# Indicates whether or not we should sign the device in +SIGNED_IN=True
diff --git a/lab_system/master/config/tests/manhattan_ui_perf/opal_idle_master_latest.cfg b/lab_system/master/config/tests/manhattan_ui_perf/opal_idle_master_latest.cfg new file mode 100644 index 0000000..d9d6fc0 --- /dev/null +++ b/lab_system/master/config/tests/manhattan_ui_perf/opal_idle_master_latest.cfg
@@ -0,0 +1,21 @@ +# Config file for Manhattan Idle UI Performance Test Suite +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.manhattan.perf.opal_ui_perf_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=OpalUiPerfTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.manhattan.perf.idle_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=IdleTestSequence + +# Indicates whether or not we should sign the device in +SIGNED_IN=True + +# Override the prebuilt image of Opal +OPAL_REF=master_latest
diff --git a/lab_system/master/config/tests/manhattan_ui_perf/opal_idle_tsmc.cfg b/lab_system/master/config/tests/manhattan_ui_perf/opal_idle_tsmc.cfg new file mode 100644 index 0000000..f7ea411 --- /dev/null +++ b/lab_system/master/config/tests/manhattan_ui_perf/opal_idle_tsmc.cfg
@@ -0,0 +1,18 @@ +# Config file for Manhattan Idle UI Performance Test Suite +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.manhattan.perf.opal_ui_perf_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=OpalUiPerfTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.manhattan.perf.idle_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=IdleTestSequence + +# Indicates whether or not we should sign the device in +SIGNED_IN=True
diff --git a/lab_system/master/config/tests/manhattan_ui_perf/opal_music_playback.cfg b/lab_system/master/config/tests/manhattan_ui_perf/opal_music_playback.cfg new file mode 100644 index 0000000..2adc794 --- /dev/null +++ b/lab_system/master/config/tests/manhattan_ui_perf/opal_music_playback.cfg
@@ -0,0 +1,18 @@ +# Config file for Manhattan Navigation UI Performance Test Suite +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.manhattan.perf.opal_ui_perf_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=OpalUiPerfTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.manhattan.perf.music_playback_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=MusicPlaybackTestSequence + +# Indicates whether or not we should sign the device in +SIGNED_IN=True
diff --git a/lab_system/master/config/tests/manhattan_ui_perf/opal_music_playback_master_latest.cfg b/lab_system/master/config/tests/manhattan_ui_perf/opal_music_playback_master_latest.cfg new file mode 100644 index 0000000..16fdebd --- /dev/null +++ b/lab_system/master/config/tests/manhattan_ui_perf/opal_music_playback_master_latest.cfg
@@ -0,0 +1,21 @@ +# Config file for Manhattan Navigation UI Performance Test Suite +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.manhattan.perf.opal_ui_perf_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=OpalUiPerfTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.manhattan.perf.music_playback_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=MusicPlaybackTestSequence + +# Indicates whether or not we should sign the device in +SIGNED_IN=True + +# Override the prebuilt image of Opal +OPAL_REF=master_latest
diff --git a/lab_system/master/config/tests/manhattan_ui_perf/opal_music_playback_tsmc.cfg b/lab_system/master/config/tests/manhattan_ui_perf/opal_music_playback_tsmc.cfg new file mode 100644 index 0000000..2adc794 --- /dev/null +++ b/lab_system/master/config/tests/manhattan_ui_perf/opal_music_playback_tsmc.cfg
@@ -0,0 +1,18 @@ +# Config file for Manhattan Navigation UI Performance Test Suite +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.manhattan.perf.opal_ui_perf_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=OpalUiPerfTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.manhattan.perf.music_playback_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=MusicPlaybackTestSequence + +# Indicates whether or not we should sign the device in +SIGNED_IN=True
diff --git a/lab_system/master/config/tests/manhattan_ui_perf/opal_navigation.cfg b/lab_system/master/config/tests/manhattan_ui_perf/opal_navigation.cfg new file mode 100644 index 0000000..ed81c0f --- /dev/null +++ b/lab_system/master/config/tests/manhattan_ui_perf/opal_navigation.cfg
@@ -0,0 +1,18 @@ +# Config file for Manhattan Navigation UI Performance Test Suite +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.manhattan.perf.opal_ui_perf_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=OpalUiPerfTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.manhattan.perf.navigation_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=NavigationTestSequence + +# Indicates whether or not we should sign the device in +SIGNED_IN=True
diff --git a/lab_system/master/config/tests/manhattan_ui_perf/opal_navigation_master_latest.cfg b/lab_system/master/config/tests/manhattan_ui_perf/opal_navigation_master_latest.cfg new file mode 100644 index 0000000..ca25841 --- /dev/null +++ b/lab_system/master/config/tests/manhattan_ui_perf/opal_navigation_master_latest.cfg
@@ -0,0 +1,21 @@ +# Config file for Manhattan Navigation UI Performance Test Suite +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.manhattan.perf.opal_ui_perf_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=OpalUiPerfTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.manhattan.perf.navigation_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=NavigationTestSequence + +# Indicates whether or not we should sign the device in +SIGNED_IN=True + +# Override the prebuilt image of Opal +OPAL_REF=master_latest
diff --git a/lab_system/master/config/tests/manhattan_ui_perf/opal_navigation_tsmc.cfg b/lab_system/master/config/tests/manhattan_ui_perf/opal_navigation_tsmc.cfg new file mode 100644 index 0000000..ed81c0f --- /dev/null +++ b/lab_system/master/config/tests/manhattan_ui_perf/opal_navigation_tsmc.cfg
@@ -0,0 +1,18 @@ +# Config file for Manhattan Navigation UI Performance Test Suite +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.manhattan.perf.opal_ui_perf_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=OpalUiPerfTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.manhattan.perf.navigation_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=NavigationTestSequence + +# Indicates whether or not we should sign the device in +SIGNED_IN=True
diff --git a/lab_system/master/config/tests/manhattan_ui_perf/opal_recipes.cfg b/lab_system/master/config/tests/manhattan_ui_perf/opal_recipes.cfg new file mode 100644 index 0000000..d6a257e --- /dev/null +++ b/lab_system/master/config/tests/manhattan_ui_perf/opal_recipes.cfg
@@ -0,0 +1,18 @@ +# Config file for Manhattan Recipes UI Performance Test Suite +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.manhattan.perf.opal_ui_perf_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=OpalUiPerfTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.manhattan.perf.recipes_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=RecipesTestSequence + +# Indicates whether or not we should sign the device in +SIGNED_IN=True
diff --git a/lab_system/master/config/tests/manhattan_ui_perf/opal_recipes_master_latest.cfg b/lab_system/master/config/tests/manhattan_ui_perf/opal_recipes_master_latest.cfg new file mode 100644 index 0000000..d023c13 --- /dev/null +++ b/lab_system/master/config/tests/manhattan_ui_perf/opal_recipes_master_latest.cfg
@@ -0,0 +1,21 @@ +# Config file for Manhattan Recipes UI Performance Test Suite +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.manhattan.perf.opal_ui_perf_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=OpalUiPerfTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.manhattan.perf.recipes_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=RecipesTestSequence + +# Indicates whether or not we should sign the device in +SIGNED_IN=True + +# Override the prebuilt image of Opal +OPAL_REF=master_latest
diff --git a/lab_system/master/config/tests/manhattan_ui_perf/opal_recipes_tsmc.cfg b/lab_system/master/config/tests/manhattan_ui_perf/opal_recipes_tsmc.cfg new file mode 100644 index 0000000..d6a257e --- /dev/null +++ b/lab_system/master/config/tests/manhattan_ui_perf/opal_recipes_tsmc.cfg
@@ -0,0 +1,18 @@ +# Config file for Manhattan Recipes UI Performance Test Suite +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.manhattan.perf.opal_ui_perf_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=OpalUiPerfTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.manhattan.perf.recipes_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=RecipesTestSequence + +# Indicates whether or not we should sign the device in +SIGNED_IN=True
diff --git a/lab_system/master/config/tests/manhattan_ui_perf/opal_shader_collection.cfg b/lab_system/master/config/tests/manhattan_ui_perf/opal_shader_collection.cfg new file mode 100644 index 0000000..9fdc3c5 --- /dev/null +++ b/lab_system/master/config/tests/manhattan_ui_perf/opal_shader_collection.cfg
@@ -0,0 +1,18 @@ +# Config file for Opal shader collection +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.manhattan.perf.opal_ui_perf_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=OpalUiPerfTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.manhattan.perf.shader_collection_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=ShaderCollectionTestSequence + +# Indicates whether or not we should sign the device in +SIGNED_IN=True
diff --git a/lab_system/master/config/tests/manhattan_ui_perf/opal_shader_collection_master_latest.cfg b/lab_system/master/config/tests/manhattan_ui_perf/opal_shader_collection_master_latest.cfg new file mode 100644 index 0000000..70a940e --- /dev/null +++ b/lab_system/master/config/tests/manhattan_ui_perf/opal_shader_collection_master_latest.cfg
@@ -0,0 +1,21 @@ +# Config file for Opal shader collection +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.manhattan.perf.opal_ui_perf_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=OpalUiPerfTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.manhattan.perf.shader_collection_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=ShaderCollectionTestSequence + +# Indicates whether or not we should sign the device in +SIGNED_IN=True + +# Override the prebuilt image of Opal +OPAL_REF=master_latest
diff --git a/lab_system/master/config/tests/manhattan_ui_perf/opal_stargazer.cfg b/lab_system/master/config/tests/manhattan_ui_perf/opal_stargazer.cfg new file mode 100644 index 0000000..216a30b --- /dev/null +++ b/lab_system/master/config/tests/manhattan_ui_perf/opal_stargazer.cfg
@@ -0,0 +1,18 @@ +# Config file for Manhattan Stargazer Performance Test Suite +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.manhattan.perf.opal_ui_perf_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=OpalUiPerfTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.manhattan.perf.stargazer_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=StargazerTestSequence + +# Indicates whether or not we should sign the device in +SIGNED_IN=True
diff --git a/lab_system/master/config/tests/manhattan_ui_perf/opal_stargazer_master_latest.cfg b/lab_system/master/config/tests/manhattan_ui_perf/opal_stargazer_master_latest.cfg new file mode 100644 index 0000000..a9090ba --- /dev/null +++ b/lab_system/master/config/tests/manhattan_ui_perf/opal_stargazer_master_latest.cfg
@@ -0,0 +1,21 @@ +# Config file for Manhattan Stargazer Performance Test Suite +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.manhattan.perf.opal_ui_perf_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=OpalUiPerfTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.manhattan.perf.stargazer_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=StargazerTestSequence + +# Indicates whether or not we should sign the device in +SIGNED_IN=True + +# Override the prebuilt image of Opal +OPAL_REF=master_latest
diff --git a/lab_system/master/config/tests/manhattan_ui_perf/opal_stargazer_tsmc.cfg b/lab_system/master/config/tests/manhattan_ui_perf/opal_stargazer_tsmc.cfg new file mode 100644 index 0000000..216a30b --- /dev/null +++ b/lab_system/master/config/tests/manhattan_ui_perf/opal_stargazer_tsmc.cfg
@@ -0,0 +1,18 @@ +# Config file for Manhattan Stargazer Performance Test Suite +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.manhattan.perf.opal_ui_perf_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=OpalUiPerfTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.manhattan.perf.stargazer_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=StargazerTestSequence + +# Indicates whether or not we should sign the device in +SIGNED_IN=True
diff --git a/lab_system/master/config/tests/manhattan_ui_perf/opal_system_gestures.cfg b/lab_system/master/config/tests/manhattan_ui_perf/opal_system_gestures.cfg new file mode 100644 index 0000000..b1a3508 --- /dev/null +++ b/lab_system/master/config/tests/manhattan_ui_perf/opal_system_gestures.cfg
@@ -0,0 +1,18 @@ +# Config file for Manhattan System Gestures UI Performance Test Suite +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.manhattan.perf.opal_ui_perf_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=OpalUiPerfTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.manhattan.perf.system_gestures_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=SystemGesturesTestSequence + +# Indicates whether or not we should sign the device in +SIGNED_IN=True
diff --git a/lab_system/master/config/tests/manhattan_ui_perf/opal_system_gestures_master_latest.cfg b/lab_system/master/config/tests/manhattan_ui_perf/opal_system_gestures_master_latest.cfg new file mode 100644 index 0000000..f1ef205 --- /dev/null +++ b/lab_system/master/config/tests/manhattan_ui_perf/opal_system_gestures_master_latest.cfg
@@ -0,0 +1,21 @@ +# Config file for Manhattan System Gestures UI Performance Test Suite +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.manhattan.perf.opal_ui_perf_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=OpalUiPerfTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.manhattan.perf.system_gestures_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=SystemGesturesTestSequence + +# Indicates whether or not we should sign the device in +SIGNED_IN=True + +# Override the prebuilt image of Opal +OPAL_REF=master_latest
diff --git a/lab_system/master/config/tests/manhattan_ui_perf/opal_system_gestures_tsmc.cfg b/lab_system/master/config/tests/manhattan_ui_perf/opal_system_gestures_tsmc.cfg new file mode 100644 index 0000000..b1a3508 --- /dev/null +++ b/lab_system/master/config/tests/manhattan_ui_perf/opal_system_gestures_tsmc.cfg
@@ -0,0 +1,18 @@ +# Config file for Manhattan System Gestures UI Performance Test Suite +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.manhattan.perf.opal_ui_perf_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=OpalUiPerfTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.manhattan.perf.system_gestures_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=SystemGesturesTestSequence + +# Indicates whether or not we should sign the device in +SIGNED_IN=True
diff --git a/lab_system/master/config/tests/ml_framework/ml_framework_power_test.cfg b/lab_system/master/config/tests/ml_framework/ml_framework_power_test.cfg new file mode 100644 index 0000000..6065687 --- /dev/null +++ b/lab_system/master/config/tests/ml_framework/ml_framework_power_test.cfg
@@ -0,0 +1,17 @@ +# Configuration values for ML Framework Power test. +# +# PROPERTIES +# Name of the TestCase sub-class: +TEST_CASE_CLASS=PowerMlFramework + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.ml_framework.ml_framework_power_test_case + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=NdmTestSequence + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=experimental.ndm.ndm_test_sequence + +# Seconds to sleep between inferences +TEST_SLEEP_TIME=15
diff --git a/lab_system/master/config/tests/ml_framework/ml_framework_sysmon_test.cfg b/lab_system/master/config/tests/ml_framework/ml_framework_sysmon_test.cfg new file mode 100644 index 0000000..bc92a8f --- /dev/null +++ b/lab_system/master/config/tests/ml_framework/ml_framework_sysmon_test.cfg
@@ -0,0 +1,14 @@ +# Configuration values for MojoSpy Sysmon test. +# +# PROPERTIES +# Name of the TestCase sub-class: +TEST_CASE_CLASS=MlFrameworkSysmonTestCase + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.ml_framework.ml_framework_sysmon_test_case + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=NdmTestSequence + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=experimental.ndm.ndm_test_sequence
diff --git a/lab_system/master/config/tests/mojo_spy_tests/mojo_spy_sysmom_test.cfg b/lab_system/master/config/tests/mojo_spy_tests/mojo_spy_sysmom_test.cfg new file mode 100644 index 0000000..926a450 --- /dev/null +++ b/lab_system/master/config/tests/mojo_spy_tests/mojo_spy_sysmom_test.cfg
@@ -0,0 +1,18 @@ +# Configuration values for MojoSpy Sysmon test. +# +# PROPERTIES +# Name of the TestCase sub-class: +TEST_CASE_CLASS=SysmonMlFramework + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.mojo_spy_tests.sysmon_mojo_spy_test_case + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=NdmTestSequence + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=experimental.ndm.ndm_test_sequence + +# Points to the folder containing JSON and raw images located in +# gs://cast-test-data gcs bucket. +RAW_DATA_PATH=mojospy/sysmon_test/default/
diff --git a/lab_system/master/config/tests/monitoring/playback.cfg b/lab_system/master/config/tests/monitoring/playback.cfg new file mode 100644 index 0000000..93860e3 --- /dev/null +++ b/lab_system/master/config/tests/monitoring/playback.cfg
@@ -0,0 +1,15 @@ +# Config file for video playback profiler test +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.monitoring.playback_profiler_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=PlaybackProfilerTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.framework.test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=TestSequence
diff --git a/lab_system/master/config/tests/monitoring/playback/test_defs.json b/lab_system/master/config/tests/monitoring/playback/test_defs.json new file mode 100644 index 0000000..dcdb51e --- /dev/null +++ b/lab_system/master/config/tests/monitoring/playback/test_defs.json
@@ -0,0 +1,44 @@ +[ + { + "group_name": "monitoring", + "slave_name": "playback_profiler", + "test_name": "playback", + "identifier": "playback_profiler", + "device_type": "eureka", + "device_group": "eureka_debug", + "hidden": "true", + "branch": ["master", "release"] + }, + { + "group_name": "monitoring", + "slave_name": "playback_profiler_v2", + "test_name": "playback", + "identifier": "playback_profiler_v2", + "device_type": "lexx", + "device_group": "lexx_eth", + "hidden": "true", + "branch": ["master", "release"] + }, + { + "group_name": "monitoring", + "slave_name": "playback_profiler", + "test_name": "playback", + "identifier": "playback_profiler_prod", + "device_type": "eureka", + "device_group": "eureka_debug", + "branch": "on_demand", + "hidden": "true", + "scheduler": "0 20 * * *" + }, + { + "group_name": "monitoring", + "slave_name": "playback_profiler_v2", + "test_name": "playback", + "identifier": "playback_profiler_prod_v2", + "device_type": "lexx", + "device_group": "lexx_eth", + "branch": "on_demand", + "hidden": "true", + "scheduler": "0 20 * * *" + } +]
diff --git a/lab_system/master/config/tests/monitoring/youtube/test_defs.json b/lab_system/master/config/tests/monitoring/youtube/test_defs.json new file mode 100644 index 0000000..aa584c3 --- /dev/null +++ b/lab_system/master/config/tests/monitoring/youtube/test_defs.json
@@ -0,0 +1,154 @@ +[ + { + "group_name": "monitoring", + "slave_name": "youtube_profiler", + "test_name": "youtube_live_only", + "identifier": "youtube_live_only", + "device_type": "eureka", + "device_group": "eureka_debug", + "hidden": "true", + "branch": ["master", "release"], + "scheduler": "0 0,12 * * *" + }, + { + "group_name": "monitoring", + "slave_name": "youtube_profiler_v2", + "test_name": "youtube_live_only", + "identifier": "youtube_live_only_v2", + "device_type": "lexx", + "device_group": "lexx_eth", + "hidden": "true", + "branch": ["master", "release"], + "scheduler": "0 0,12 * * *" + }, + { + "group_name": "monitoring", + "slave_name": "youtube_profiler_v3", + "test_name": "youtube_live_only", + "identifier": "youtube_live_only_v3", + "device_type": "earth", + "device_group": "earth_eth", + "hidden": "true", + "branch": ["master", "release"], + "scheduler": "0 0,12 * * *" + }, + { + "group_name": "monitoring", + "slave_name": "youtube_profiler", + "test_name": "youtube_live_dvr", + "identifier": "youtube_live_dvr", + "device_type": "eureka", + "device_group": "eureka_debug", + "hidden": "true", + "branch": ["master", "release"], + "scheduler": "0 4,16 * * *" + }, + { + "group_name": "monitoring", + "slave_name": "youtube_profiler_v2", + "test_name": "youtube_live_dvr", + "identifier": "youtube_live_dvr_v2", + "device_type": "lexx", + "device_group": "lexx_eth", + "hidden": "true", + "branch": ["master", "release"], + "scheduler": "0 4,16 * * *" + }, + { + "group_name": "monitoring", + "slave_name": "youtube_profiler_v3", + "test_name": "youtube_live_dvr", + "identifier": "youtube_live_dvr_v3", + "device_type": "earth", + "device_group": "earth_eth", + "hidden": "true", + "branch": ["master", "release"], + "scheduler": "0 4,16 * * *" + }, + { + "group_name": "monitoring", + "slave_name": "youtube_profiler", + "test_name": "youtube_live_hfr_dvr", + "identifier": "youtube_live_hfr_dvr", + "device_type": "eureka", + "device_group": "eureka_debug", + "hidden": "true", + "branch": ["master", "release"], + "scheduler": "0 8,20 * * *" + }, + { + "group_name": "monitoring", + "slave_name": "youtube_profiler_v2", + "test_name": "youtube_live_hfr_dvr", + "identifier": "youtube_live_hfr_dvr_v2", + "device_type": "lexx", + "device_group": "lexx_eth", + "hidden": "true", + "branch": ["master", "release"], + "scheduler": "0 8,20 * * *" + }, + { + "group_name": "monitoring", + "slave_name": "youtube_profiler_v3", + "test_name": "youtube_live_hfr_dvr", + "identifier": "youtube_live_hfr_dvr_v3", + "device_type": "earth", + "device_group": "earth_eth", + "hidden": "true", + "branch": ["master", "release"], + "scheduler": "0 8,20 * * *" + }, + { + "group_name": "monitoring", + "slave_name": "youtube_profiler_v2", + "test_name": "youtube", + "identifier": "youtube_profiler_prod_v2", + "device_type": "lexx", + "device_group": "lexx_eth", + "hidden": "true", + "branch": "on_demand" + }, + { + "group_name": "monitoring", + "slave_name": "youtube_profiler", + "test_name": "playback", + "identifier": "youtube_playback", + "device_type": "eureka", + "device_group": "eureka_debug", + "hidden": "true", + "branch": ["master", "release"], + "scheduler": "0 0,12 * * *" + }, + { + "group_name": "monitoring", + "slave_name": "youtube_profiler_v2", + "test_name": "playback", + "identifier": "youtube_playback_v2", + "device_type": "lexx", + "device_group": "lexx_eth", + "hidden": "true", + "branch": ["master", "release"], + "scheduler": "0 0,12 * * *" + }, + { + "group_name": "monitoring", + "slave_name": "youtube_profiler_v3", + "test_name": "playback", + "identifier": "youtube_playback_v3", + "device_type": "earth", + "device_group": "earth_eth", + "hidden": "true", + "branch": ["master", "release"], + "scheduler": "0 0,12 * * *" + }, + { + "group_name": "monitoring", + "slave_name": "youtube_profiler_v2", + "test_name": "playback", + "identifier": "youtube_playback_prod_v2", + "device_type": "lexx", + "device_group": "lexx_eth", + "hidden": "true", + "branch": "on_demand" + } +]
diff --git a/lab_system/master/config/tests/monitoring/youtube_live_dvr.cfg b/lab_system/master/config/tests/monitoring/youtube_live_dvr.cfg new file mode 100644 index 0000000..f0ce7a0 --- /dev/null +++ b/lab_system/master/config/tests/monitoring/youtube_live_dvr.cfg
@@ -0,0 +1,15 @@ +# Config file for YouTube profiler test with DVR live stream +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.monitoring.youtube_profiler_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=YoutubeLiveDvrProfilerTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.framework.test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=TestSequence
diff --git a/lab_system/master/config/tests/monitoring/youtube_live_hfr_dvr.cfg b/lab_system/master/config/tests/monitoring/youtube_live_hfr_dvr.cfg new file mode 100644 index 0000000..c0e7299 --- /dev/null +++ b/lab_system/master/config/tests/monitoring/youtube_live_hfr_dvr.cfg
@@ -0,0 +1,15 @@ +# Config file for YouTube profiler test with Live HFR DVR stream +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.monitoring.youtube_profiler_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=YoutubeLiveHfrDvrProfilerTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.framework.test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=TestSequence
diff --git a/lab_system/master/config/tests/monitoring/youtube_live_only.cfg b/lab_system/master/config/tests/monitoring/youtube_live_only.cfg new file mode 100644 index 0000000..27122d7 --- /dev/null +++ b/lab_system/master/config/tests/monitoring/youtube_live_only.cfg
@@ -0,0 +1,15 @@ +# Config file for YouTube profiler test for live only stream +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.monitoring.youtube_profiler_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=YoutubeLiveOnlyProfilerTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.framework.test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=TestSequence
diff --git a/lab_system/master/config/tests/mpl/mpl_dogfood_4k.cfg b/lab_system/master/config/tests/mpl/mpl_dogfood_4k.cfg new file mode 100644 index 0000000..d6950f0 --- /dev/null +++ b/lab_system/master/config/tests/mpl/mpl_dogfood_4k.cfg
@@ -0,0 +1,18 @@ +# Config file for 4K mple2e tests using dogfood version of mpl. +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.mpl.mpl_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=MplPlayToEndDogfood4KTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.framework.mpl_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=MplTestSequence + +# Use SSH tunnel when connecting to DUT. +
diff --git a/lab_system/master/config/tests/mpl/mpl_dogfood_dv.cfg b/lab_system/master/config/tests/mpl/mpl_dogfood_dv.cfg new file mode 100644 index 0000000..1dde1f1 --- /dev/null +++ b/lab_system/master/config/tests/mpl/mpl_dogfood_dv.cfg
@@ -0,0 +1,16 @@ +# Config file for Dolby Vision Tests using dogfood version of MPL. +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.mpl.mpl_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=MplBasicDogfoodDVTestCase,MplGetQualityLevelDogfoodDVTestCase,MplLoadDogfoodDVTestCase,MplLoadWithInitialTimeDogfoodDVTestCase,MplPlayToEndDogfoodDVTestCase,MplPreloadDogfoodDVTestCase,MplSeekDogfoodDVTestCase,MplSkipRequestDogfoodDVTestCase,MplSkipRequestFailDogfoodDVTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.framework.mpl_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=MplTestSequence +
diff --git a/lab_system/master/config/tests/mpl/mpl_dogfood_lg.cfg b/lab_system/master/config/tests/mpl/mpl_dogfood_lg.cfg new file mode 100644 index 0000000..bfeb199 --- /dev/null +++ b/lab_system/master/config/tests/mpl/mpl_dogfood_lg.cfg
@@ -0,0 +1,15 @@ +# Config file for Dolby Vision Tests using dogfood version of MPL. +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.mpl.mpl_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=MplBasicDogfoodLGTestCase,MplGetQualityLevelDogfoodLGTestCase,MplLoadDogfoodLGTestCase,MplLoadWithInitialTimeDogfoodLGTestCase,MplPlayToEndDogfoodLGTestCase,MplPreloadDogfoodLGTestCase,MplSeekDogfoodLGTestCase,MplSkipRequestDogfoodLGTestCase,MplSkipRequestFailDogfoodLGTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.framework.mpl_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=MplTestSequence
diff --git a/lab_system/master/config/tests/mpl/mpl_release.cfg b/lab_system/master/config/tests/mpl/mpl_release.cfg new file mode 100644 index 0000000..3499516 --- /dev/null +++ b/lab_system/master/config/tests/mpl/mpl_release.cfg
@@ -0,0 +1,18 @@ +# Config file for mple2e tests using the release version of mpl. +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.mpl.mpl_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=MplBasicReleaseTestCase,MplEnableCaptionsReleaseTestCase,MplGetQualityLevelReleaseTestCase,MplInstantPlayReleaseTestCase,MplLoadReleaseTestCase,MplLoadWithInitialTimeReleaseTestCase,MplPlayToEndReleaseTestCase,MplPreloadReleaseTestCase,MplProcessMetadataReleaseTestCase,MplReloadReleaseTestCase,MplSeekReleaseTestCase,MplSkipRequestReleaseTestCase,MplSkipRequestFailReleaseTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.framework.mpl_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=MplTestSequence + +# Use SSH tunnel when connecting to DUT. +
diff --git a/lab_system/master/config/tests/mpl/mpl_release_4k.cfg b/lab_system/master/config/tests/mpl/mpl_release_4k.cfg new file mode 100644 index 0000000..bba4e67 --- /dev/null +++ b/lab_system/master/config/tests/mpl/mpl_release_4k.cfg
@@ -0,0 +1,18 @@ +# Config file for 4K mple2e tests using the release version of mpl. +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.mpl.mpl_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=MplPlayToEndRelease4KTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.framework.mpl_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=MplTestSequence + +# Use SSH tunnel when connecting to DUT. +
diff --git a/lab_system/master/config/tests/mpl/mpl_release_dv.cfg b/lab_system/master/config/tests/mpl/mpl_release_dv.cfg new file mode 100644 index 0000000..d5709b0 --- /dev/null +++ b/lab_system/master/config/tests/mpl/mpl_release_dv.cfg
@@ -0,0 +1,15 @@ +# Config file for Dolby Vision tests using the release version of MPL. +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.mpl.mpl_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=MplBasicReleaseDVTestCase,MplGetQualityLevelReleaseDVTestCase,MplLoadReleaseDVTestCase,MplLoadWithInitialTimeReleaseDVTestCase,MplPlayToEndReleaseDVTestCase,MplPreloadReleaseDVTestCase,MplSeekReleaseDVTestCase,MplSkipRequestReleaseDVTestCase,MplSkipRequestFailReleaseDVTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.framework.mpl_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=MplTestSequence
diff --git a/lab_system/master/config/tests/mpl/mpl_release_lg.cfg b/lab_system/master/config/tests/mpl/mpl_release_lg.cfg new file mode 100644 index 0000000..3f1e1ea --- /dev/null +++ b/lab_system/master/config/tests/mpl/mpl_release_lg.cfg
@@ -0,0 +1,15 @@ +# Config file for Dolby Vision tests using the release version of MPL. +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.mpl.mpl_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=MplBasicReleaseLGTestCase,MplGetQualityLevelReleaseLGTestCase,MplLoadReleaseLGTestCase,MplLoadWithInitialTimeReleaseLGTestCase,MplPlayToEndReleaseLGTestCase,MplPreloadReleaseLGTestCase,MplSeekReleaseLGTestCase,MplSkipRequestReleaseLGTestCase,MplSkipRequestFailReleaseLGTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.framework.mpl_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=MplTestSequence
diff --git a/lab_system/master/config/tests/mpl/mpl_staging_4k.cfg b/lab_system/master/config/tests/mpl/mpl_staging_4k.cfg new file mode 100644 index 0000000..6801d53 --- /dev/null +++ b/lab_system/master/config/tests/mpl/mpl_staging_4k.cfg
@@ -0,0 +1,18 @@ +# Config file 4K mple2e tests using development version of mpl. +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.mpl.mpl_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=MplPlayToEndDevelopment4KTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.framework.mpl_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=MplTestSequence + +# Use SSH tunnel when connecting to DUT +
diff --git a/lab_system/master/config/tests/mpl/mpl_staging_dv.cfg b/lab_system/master/config/tests/mpl/mpl_staging_dv.cfg new file mode 100644 index 0000000..2e31b72 --- /dev/null +++ b/lab_system/master/config/tests/mpl/mpl_staging_dv.cfg
@@ -0,0 +1,16 @@ +# Config for Dolby Vision tests using development version of MPL. +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.mpl.mpl_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=MplBasicDevelopmentDVTestCase,MplGetQualityLevelDevelopmentDVTestCase,MplLoadDevelopmentDVTestCase,MplLoadWithInitialTimeDevelopmentDVTestCase,MplPlayToEndDevelopmentDVTestCase,MplPreloadDevelopmentDVTestCase,MplSeekDevelopmentDVTestCase,MplSkipRequestDevelopmentDVTestCase,MplSkipRequestFailDevelopmentDVTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.framework.mpl_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=MplTestSequence +
diff --git a/lab_system/master/config/tests/mpl/mpl_staging_lg.cfg b/lab_system/master/config/tests/mpl/mpl_staging_lg.cfg new file mode 100644 index 0000000..c75a390 --- /dev/null +++ b/lab_system/master/config/tests/mpl/mpl_staging_lg.cfg
@@ -0,0 +1,15 @@ +# Config for Dolby Vision tests using development version of MPL. +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.mpl.mpl_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=MplBasicDevelopmentLGTestCase,MplGetQualityLevelDevelopmentLGTestCase,MplLoadDevelopmentLGTestCase,MplLoadWithInitialTimeDevelopmentLGTestCase,MplPlayToEndDevelopmentLGTestCase,MplPreloadDevelopmentLGTestCase,MplSeekDevelopmentLGTestCase,MplSkipRequestDevelopmentLGTestCase,MplSkipRequestFailDevelopmentLGTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.framework.mpl_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=MplTestSequence
diff --git a/lab_system/master/config/tests/mpl/test_defs.json b/lab_system/master/config/tests/mpl/test_defs.json new file mode 100644 index 0000000..3d71166 --- /dev/null +++ b/lab_system/master/config/tests/mpl/test_defs.json
@@ -0,0 +1,140 @@ +[ + { + "group_name": "mpl", + "slave_name": "javascript_no_security", + "test_name": "mpl_staging_4k", + "identifier": "mpl_staging_4k_steak", + "device_type": "luther_b2", + "device_group": "av_drm", + "build_flavor": "user", + "branch": ["master", "next_release", "release"] + }, + { + "group_name": "mpl", + "slave_name": "javascript_no_security", + "test_name": "mpl_staging_lg", + "identifier": "mpl_staging_lg_steak", + "device_type": "luther_b2", + "device_group": "luther_lg", + "branch": ["release", "next_release", "master"] + }, + { + "group_name": "mpl", + "slave_name": "javascript_no_security", + "test_name": "mpl_staging_dv", + "identifier": "mpl_staging_dv_steak", + "device_type": "luther_b2", + "device_group": "luther_vizio", + "branch": ["release", "next_release", "master"] + }, + { + "group_name": "mpl", + "slave_name": "javascript_no_security", + "test_name": "mpl_dogfood_4k", + "identifier": "mpl_dogfood_4k_steak", + "device_type": "luther_b2", + "device_group": "av_drm", + "build_flavor": "user", + "branch": ["master", "next_release", "release"] + }, + { + "group_name": "mpl", + "slave_name": "javascript_no_security", + "test_name": "mpl_dogfood_lg", + "identifier": "mpl_dogfood_lg_steak", + "device_type": "luther_b2", + "device_group": "luther_lg", + "branch": ["release", "next_release", "master"] + }, + { + "group_name": "mpl", + "slave_name": "javascript_no_security", + "test_name": "mpl_dogfood_dv", + "identifier": "mpl_dogfood_dv_steak", + "device_type": "luther_b2", + "device_group": "luther_vizio", + "branch": ["release", "next_release", "master"] + }, + { + "group_name": "mpl", + "slave_name": "javascript_no_security", + "test_name": "mpl_release_4k", + "identifier": "mpl_release_4k_steak", + "device_type": "luther_b2", + "device_group": "av_drm", + "build_flavor": "user", + "branch": ["master", "next_release", "release"] + }, + { + "group_name": "mpl", + "slave_name": "javascript_no_security", + "test_name": "mpl_release_lg", + "identifier": "mpl_release_lg_steak", + "device_type": "luther_b2", + "device_group": "luther_lg", + "branch": ["release", "next_release", "master"] + }, + { + "group_name": "mpl", + "slave_name": "javascript_no_security", + "test_name": "mpl_release_dv", + "identifier": "mpl_release_dv_steak", + "device_type": "luther_b2", + "device_group": "luther_vizio", + "branch": ["release", "next_release", "master"] + }, + { + "group_name": "mpl", + "slave_name": "javascript_no_security", + "test_name": "mpl_release", + "identifier": "mpl_release_bubbletea", + "device_type": "bubbletea", + "device_group": "av_drm", + "branch": ["cast_tv_mstar_master", "cast_tv_mstar_release", "cast_tv_mstar_next_release"] + }, + { + "group_name": "mpl", + "slave_name": "javascript_no_security", + "test_name": "mpl_release", + "identifier": "mpl_release_guabao", + "device_type": "guabao", + "device_group": "av_drm", + "branch": ["cast_tv_mstar_master", "cast_tv_mstar_release", "cast_tv_mstar_next_release"] + }, + { + "group_name": "mpl", + "slave_name": "javascript_no_security", + "test_name": "mpl_release", + "identifier": "mpl_release_mars_us", + "device_type": "Mars_US", + "device_group": "av_drm", + "branch": ["cast_tv_mediatek_master", "cast_tv_mediatek_release", "cast_tv_mediatek_next_release"] + }, + { + "group_name": "mpl", + "slave_name": "javascript_no_security", + "test_name": "mpl_release", + "identifier": "mpl_release_N00007", + "device_type": "N00007", + "device_group": "av_drm", + "branch": ["cast_tv_novatek_master", "cast_tv_novatek_release", "cast_tv_novatek_next_release"] + }, + { + "group_name": "mpl", + "slave_name": "javascript_no_security", + "test_name": "mpl_release", + "identifier": "mpl_release_suncake", + "device_type": "suncake", + "device_group": "av_drm", + "branch": ["cast_tv_mstar_master", "cast_tv_mstar_release", "cast_tv_mstar_next_release"] + }, + { + "group_name": "mpl", + "slave_name": "javascript_no_security", + "test_name": "mpl_release", + "identifier": "mpl_release_taroball", + "device_type": "taroball", + "device_group": "av_drm", + "branch": ["cast_tv_mstar_master", "cast_tv_mstar_release", "cast_tv_mstar_next_release"] + } +]
diff --git a/lab_system/master/config/tests/mpl_dogfood/mpl_dogfood.cfg b/lab_system/master/config/tests/mpl_dogfood/mpl_dogfood.cfg new file mode 100644 index 0000000..2a9801f --- /dev/null +++ b/lab_system/master/config/tests/mpl_dogfood/mpl_dogfood.cfg
@@ -0,0 +1,18 @@ +# Config file for mple2e using dogfood version of mpl. +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.mpl.mpl_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=MplBasicDogfoodTestCase,MplEnableCaptionsDogfoodTestCase,MplGetQualityLevelDogfoodTestCase,MplInstantPlayDogfoodTestCase,MplLoadDogfoodTestCase,MplLoadWithInitialTimeDogfoodTestCase,MplPlayToEndDogfoodTestCase,MplPreloadDogfoodTestCase,MplProcessMetadataDogfoodTestCase,MplReloadDogfoodTestCase,MplSeekDogfoodTestCase,MplSkipRequestDogfoodTestCase,MplSkipRequestFailDogfoodTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.framework.mpl_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=MplTestSequence + +# Use SSH tunnel when connecting to DUT. +
diff --git a/lab_system/master/config/tests/mpl_staging/mpl_staging.cfg b/lab_system/master/config/tests/mpl_staging/mpl_staging.cfg new file mode 100644 index 0000000..86e8aaf --- /dev/null +++ b/lab_system/master/config/tests/mpl_staging/mpl_staging.cfg
@@ -0,0 +1,18 @@ +# Config file mple2e tests using development version of mpl. +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.mpl.mpl_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=MplBasicDevelopmentTestCase,MplEnableCaptionsDevelopmentTestCase,MplGetQualityLevelDevelopmentTestCase,MplInstantPlayDevelopmentTestCase,MplLoadDevelopmentTestCase,MplLoadWithInitialTimeDevelopmentTestCase,MplPlayToEndDevelopmentTestCase,MplPreloadDevelopmentTestCase,MplProcessMetadataDevelopmentTestCase,MplReloadDevelopmentTestCase,MplSeekDevelopmentTestCase,MplSkipRequestDevelopmentTestCase,MplSkipRequestFailDevelopmentTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.framework.mpl_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=MplTestSequence + +# Use SSH tunnel when connecting to DUT. +
diff --git a/lab_system/master/config/tests/mse_eme/mse_eme.cfg b/lab_system/master/config/tests/mse_eme/mse_eme.cfg new file mode 100644 index 0000000..486e3d5 --- /dev/null +++ b/lab_system/master/config/tests/mse_eme/mse_eme.cfg
@@ -0,0 +1,18 @@ +# Config file for MSE-EME JavaScript test suite. +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.mse_eme.mse_eme_tip_test_case + +# Name of the TestCase sub-class: +# b/27450353 EmeVP9TestCase has to be reactivated once it is fixed +TEST_CASE_CLASS=MSEConformanceTestCase,EMEConformanceTestCase,ProgressiveTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.mse_eme.mse_eme_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=MseEmeTestSequence + +
diff --git a/lab_system/master/config/tests/mse_eme/test_defs.json b/lab_system/master/config/tests/mse_eme/test_defs.json new file mode 100644 index 0000000..39db4a1 --- /dev/null +++ b/lab_system/master/config/tests/mse_eme/test_defs.json
@@ -0,0 +1,11 @@ +[ + { + "group_name": "mse_eme", + "slave_name": "eurtest_mse_eme_tv", + "test_name": "mse_eme", + "identifier": "mse_eme_dragonfly", + "device_type": "dragonfly", + "device_group": "av_drm", + "branch": ["cast_tv_dragonfly_master", "cast_tv_dragonfly_release", "cast_tv_dragonfly_next_release"] + } +]
diff --git a/lab_system/master/config/tests/mse_eme_legacy/mse_eme_legacy.cfg b/lab_system/master/config/tests/mse_eme_legacy/mse_eme_legacy.cfg new file mode 100644 index 0000000..0106b32 --- /dev/null +++ b/lab_system/master/config/tests/mse_eme_legacy/mse_eme_legacy.cfg
@@ -0,0 +1,17 @@ +# Config file for MSE-EME JavaScript test suite. +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.mse_eme.mse_eme_legacy_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=MSEConformanceTestCase,EMEConformanceTestCase,ProgressiveTestCase,MSEConformance2016TestCase,EMEConformance2016TestCase,Progressive2016TestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.mse_eme.mse_eme_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=MseEmeTestSequence + +
diff --git a/lab_system/master/config/tests/mse_eme_legacy/test_defs.json b/lab_system/master/config/tests/mse_eme_legacy/test_defs.json new file mode 100644 index 0000000..206e8ad --- /dev/null +++ b/lab_system/master/config/tests/mse_eme_legacy/test_defs.json
@@ -0,0 +1,47 @@ +[ + { + "group_name": "mse_eme", + "slave_name": "eurtest_mse_eme_tv_legacy", + "test_name": "mse_eme_legacy", + "identifier": "mse_eme_guabao", + "device_type": "guabao", + "device_group": "av_drm", + "branch": ["cast_tv_mstar_master", "cast_tv_mstar_release", "cast_tv_mstar_next_release"] + }, + { + "group_name": "mse_eme", + "slave_name": "eurtest_mse_eme_tv_legacy", + "test_name": "mse_eme_legacy", + "identifier": "mse_eme_mars_us", + "device_type": "Mars_US", + "device_group": "av_drm", + "branch": ["cast_tv_mediatek_master", "cast_tv_mediatek_release", "cast_tv_mediatek_next_release"] + }, + { + "group_name": "mse_eme", + "slave_name": "eurtest_mse_eme_tv_legacy", + "test_name": "mse_eme_legacy", + "identifier": "mse_eme_N00007", + "device_type": "N00007", + "device_group": "av_drm", + "branch": ["cast_tv_novatek_master", "cast_tv_novatek_release", "cast_tv_novatek_next_release"] + }, + { + "group_name": "mse_eme", + "slave_name": "eurtest_mse_eme_tv_legacy", + "test_name": "mse_eme_legacy", + "identifier": "mse_eme_suncake", + "device_type": "suncake", + "device_group": "av_drm", + "branch": ["cast_tv_mstar_master", "cast_tv_mstar_release", "cast_tv_mstar_next_release"] + }, + { + "group_name": "mse_eme", + "slave_name": "eurtest_mse_eme_tv_legacy", + "test_name": "mse_eme_legacy", + "identifier": "mse_eme_taroball", + "device_type": "taroball", + "device_group": "av_drm", + "branch": ["cast_tv_mstar_master", "cast_tv_mstar_release", "cast_tv_mstar_next_release"] + } +]
diff --git a/lab_system/master/config/tests/multizone/dli_power_switch.json b/lab_system/master/config/tests/multizone/dli_power_switch.json new file mode 100644 index 0000000..8d0c726 --- /dev/null +++ b/lab_system/master/config/tests/multizone/dli_power_switch.json
@@ -0,0 +1,54 @@ +[ + { + "ip": "100.107.130.213", + "username": "admin", + "password": "password", + "receiver_id_to_port_map": + { + "100.107.130.226": 3, + "100.107.130.228": 8, + "100.107.130.229": 4, + "100.107.130.230": 7 + } + }, + { + "ip": "100.107.130.215", + "username": "admin", + "password": "password", + "receiver_id_to_port_map": + { + "100.107.130.216": 7, + "100.107.130.217": 2, + "100.107.130.219": 6, + "100.107.130.222": 3 + } + }, + { + "ip": "100.107.130.237", + "username": "admin", + "password": "chrome4all", + "receiver_id_to_port_map": + { + "100.107.130.204": 6, + "100.107.130.205": 8, + "100.107.130.218": 3, + "100.107.130.220": 4, + "100.107.130.221": 7, + "100.107.130.231": 1, + "100.107.130.233": 2, + "100.107.130.234": 5 + } + }, + { + "ip": "100.107.130.214", + "username": "admin", + "password": "chrome4all", + "receiver_id_to_port_map": + { + "100.107.130.74": 1, + "100.107.130.75": 2, + "100.107.130.76": 3, + "100.107.130.77": 4 + } + } +]
diff --git a/lab_system/master/config/tests/multizone/hp_procurve_switch_config.json b/lab_system/master/config/tests/multizone/hp_procurve_switch_config.json new file mode 100644 index 0000000..8ee15bd --- /dev/null +++ b/lab_system/master/config/tests/multizone/hp_procurve_switch_config.json
@@ -0,0 +1,27 @@ +[ + { + "host": "100.107.130.211", + "username": "admin", + "password": "chrome4all", + "receiver_id_to_port_map": + { + "100.107.130.204": "4", + "100.107.130.205": "5", + "100.107.130.216": "19", + "100.107.130.217": "21", + "100.107.130.218": "17", + "100.107.130.219": "23", + "100.107.130.220": "16", + "100.107.130.221": "15", + "100.107.130.222": "22", + "100.107.130.226": "7", + "100.107.130.228": "10", + "100.107.130.229": "8", + "100.107.130.230": "9", + "100.107.130.231": "12", + "100.107.130.233": "13", + "100.107.130.234": "14" + }, + "infrastructure_ports": [] + } +]
diff --git a/lab_system/master/config/tests/multizone/multizone.cfg b/lab_system/master/config/tests/multizone/multizone.cfg new file mode 100644 index 0000000..7e9ce16 --- /dev/null +++ b/lab_system/master/config/tests/multizone/multizone.cfg
@@ -0,0 +1,97 @@ +# Config file for multizone tests that need equipment other than the +# receivers (e.g., power or network switches, etc.) but don't need Wi-Fi +# connectivity. + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.multizone.test_cases + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=MultizoneSyncMeasurementTestCase,MultizoneOpusSyncMeasurementTestCase,MultizoneAacSyncMeasurementTestCase,MultizoneCastTerminationTestCase,MultizoneDeviceDiscoveryTestCase,MultizoneGroupingTestCase,MultizoneLatencyCalibrationTestCase,MultizoneMultipleMediaControllersTestCase,MultizoneMultiplePartiesTestCase,MultizoneGroupMuteTestCaseUsingReceiverNamespace,MultizoneSingleDeviceMuteTestCaseUsingMultizoneNamespace,MultizoneSingleDeviceMuteTestCaseUsingReceiverNamespace + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.multizone.test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=MultizoneTestSequence + +# Path to the JSON file (relative to the location of this config file) +# with the description of the power switch host and its configuration. +# The remote system is assumed to allow a login by providing username and +# password. +# +# The file has the following format: +# [ +# { +# "ip": "<IP>", +# "username": "<username>", +# "password": "<password>", +# "receiver_id_to_port_map": +# { +# "<receiver eth IP address>": "<power switch port>", +# ... +# } +# }, +# ... +# ] +POWER_SWITCH_CONFIG_FILENAME=dli_power_switch.json + +# Path to the JSON file (relative to the location of this config file) +# with the description of the managed network switch and its configuration. +# The remote system is assumed to allow a login by providing username and +# password. +# +# The file has the following format: +# [ +# { +# "host": "<hostname or IP address>", +# "username": "<username used to login>", +# "password": "<password for the user>", +# "receiver_id_to_port_map": +# { +# "<receiver ID>": "<receiver's corresponding ethernet port>", +# }, +# "infrastructure_ports": ["<number of always on port>", ...] +# } +# ] +NETWORK_SWITCH_CONFIG_FILENAME=hp_procurve_switch_config.json + +# Path in the media server to the audio file to play in the group. The audio must consist +# of pulsed sine waves, like: +# +# _ _ _ +# / \ / \ / \ +#~~~~~ \ ~~~~~~~~~~ \ ~~~~~~~~~~ \ ~~~~~ ... +# \_/ \_/ \/ +#|---------------| |-----| +# fundamental sine +# period pulse +# |--------| +# low volume noise +# or silence +TESTFILE_PATH=static/multizone/sine_noise_s48k_p100msecs_d90sec.mp3 +# Duration of the media in seconds. +TESTFILE_LENGTH_SECS=90 +# Mime type of the media file. +TESTFILE_MIME_TYPE=audio/mp3 +THREE_MINS_TESTFILE_PATH=static/multizone/noise-sine_500Hz_100msec_44.1kHz_180secs.mp3 +THREE_MINS_TESTFILE_LENGTH_SECS=180 +THREE_MINS_TESTFILE_MIME_TYPE=audio/mp3 +OPUS_TESTFILE_PATH=static/multizone/sine_noise_s48k_p100msecs_d90sec.opus +OPUS_TESTFILE_MIME_TYPE=audio/ogg +OPUS_TESTFILE_LENGTH_SECS=90 +AAC_TESTFILE_PATH=static/multizone/sine_noise_s48k_p100msecs_d90sec.mp4 +AAC_TESTFILE_MIME_TYPE=audio/mp4 +AAC_TESTFILE_LENGTH_SECS=90 + +# Period of the pulses in the media file. +TESTFILE_FUNDAMENTAL_PERIOD_SEC=0.1 +# Duration of the sine pulse. +TESTFILE_PULSE_DURATION_SEC=0.002 +# Amplitude below which the receiver is considered to not be playing back. +TESTFILE_DROPOUT_TRESHOLD=0.3 +# Amplitude for silence value. Adapt to noise level. +TESTFILE_SILENCE_TRESHOLD=0.05 +# Minimum silence length to be interpreted as dropout in seconds +MIN_SILENCE_LENGTH_SEC=0.005 + +
diff --git a/lab_system/master/config/tests/multizone/multizone_sync_test.cfg b/lab_system/master/config/tests/multizone/multizone_sync_test.cfg new file mode 100644 index 0000000..ae80bf2 --- /dev/null +++ b/lab_system/master/config/tests/multizone/multizone_sync_test.cfg
@@ -0,0 +1,54 @@ +# Config file for sync tests + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.multizone.test_cases + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=MultizoneSyncMeasurementTestCase,MultizoneOpusSyncMeasurementTestCase,MultizoneAacSyncMeasurementTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.multizone.test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=MultizoneTestSequence + +# Path in the media server to the audio file to play in the group. The audio must consist +# of pulsed sine waves, like: +# +# _ _ _ +# / \ / \ / \ +#~~~~~ \ ~~~~~~~~~~ \ ~~~~~~~~~~ \ ~~~~~ ... +# \_/ \_/ \/ +#|---------------| |-----| +# fundamental sine +# period pulse +# |--------| +# low volume noise +# or silence +TESTFILE_PATH=static/multizone/sine_noise_s48k_p100msecs_d90sec.mp3 +# Duration of the media in seconds. +TESTFILE_LENGTH_SECS=90 +# Mime type of the media file. +TESTFILE_MIME_TYPE=audio/mp3 +THREE_MINS_TESTFILE_PATH=static/multizone/noise-sine_500Hz_100msec_44.1kHz_180secs.mp3 +THREE_MINS_TESTFILE_LENGTH_SECS=180 +THREE_MINS_TESTFILE_MIME_TYPE=audio/mp3 +OPUS_TESTFILE_PATH=static/multizone/sine_noise_s48k_p100msecs_d90sec.opus +OPUS_TESTFILE_MIME_TYPE=audio/ogg +OPUS_TESTFILE_LENGTH_SECS=90 +AAC_TESTFILE_PATH=static/multizone/sine_noise_s48k_p100msecs_d90sec.mp4 +AAC_TESTFILE_MIME_TYPE=audio/mp4 +AAC_TESTFILE_LENGTH_SECS=90 + +# Period of the pulses in the media file. +TESTFILE_FUNDAMENTAL_PERIOD_SEC=0.1 +# Duration of the sine pulse. +TESTFILE_PULSE_DURATION_SEC=0.002 +# Amplitude below which the receiver is considered to not be playing back. +TESTFILE_DROPOUT_TRESHOLD=0.3 +# Amplitude for silence value. Adapt to noise level. +TESTFILE_SILENCE_TRESHOLD=0.05 +# Minimum silence length to be interpreted as dropout in seconds +MIN_SILENCE_LENGTH_SEC=0.005 + +
diff --git a/lab_system/master/config/tests/multizone/wifi_config.json b/lab_system/master/config/tests/multizone/wifi_config.json new file mode 100644 index 0000000..707fa93 --- /dev/null +++ b/lab_system/master/config/tests/multizone/wifi_config.json
@@ -0,0 +1,52 @@ +{ + "box1": + { + "networks": + [ + { + "ssid": "mz_airport_box1_2.4ghz", + "psk": "chrome4all", + "band": "2.4", + "tags": ["router_quality_high"] + }, + { + "ssid": "mz_airport_box1_5ghz", + "psk": "chrome4all", + "band": "5", + "tags": ["router_quality_high"] + } + ], + "device_ids": + [ + "100.107.130.216", + "100.107.130.217", + "100.107.130.219", + "100.107.130.222" + ] + }, + "box2": + { + "networks": + [ + { + "ssid": "mz_airport_box2_2.4ghz", + "psk": "chrome4all", + "band": "2.4", + "tags": ["router_quality_high"] + }, + { + "ssid": "mz_airport_box2_5ghz", + "psk": "chrome4all", + "band": "5", + "tags": ["router_quality_high"] + } + ], + "device_ids": + [ + "100.107.130.226", + "100.107.130.228", + "100.107.130.229", + "100.107.130.230" + ] + } +}
diff --git a/lab_system/master/config/tests/multizone_sw/multizone_sw.cfg b/lab_system/master/config/tests/multizone_sw/multizone_sw.cfg new file mode 100644 index 0000000..891def9 --- /dev/null +++ b/lab_system/master/config/tests/multizone_sw/multizone_sw.cfg
@@ -0,0 +1,23 @@ +# Config file for multizone tests that can be run with only the receivers +# and no additional equipment (power or network switches, access points, etc.). + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.multizone.test_cases_sw + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=MultizoneGroupStatusTestCase,MultizoneGroupVolumeMultizoneNamespaceTestCase,MultizoneGroupVolumeReceiverNamespaceTestCase,MultizoneMultipleVolumeControllersMultizoneTestCase,MultizoneMultipleVolumeControllersReceiverTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.multizone.test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=MultizoneTestSequence + +# Path in the media server to the audio file to play in the group. +TESTFILE_PATH=static/multizone/tone_440hz_f48k_d60sec.mp3 +# Duration of the media in seconds. +TESTFILE_LENGTH_SECS=10 +# Mime type of the media file. +TESTFILE_MIME_TYPE=audio/mp3 + +
diff --git a/lab_system/master/config/tests/ndm/crash_loop.cfg b/lab_system/master/config/tests/ndm/crash_loop.cfg new file mode 100644 index 0000000..6da7edd --- /dev/null +++ b/lab_system/master/config/tests/ndm/crash_loop.cfg
@@ -0,0 +1,13 @@ +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=experimental.ndm.crash_loop_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=CrashLoopTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=experimental.ndm.ota_install_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=OtaInstallableTestSequence
diff --git a/lab_system/master/config/tests/ndm/crash_loop_battery_mode.cfg b/lab_system/master/config/tests/ndm/crash_loop_battery_mode.cfg new file mode 100644 index 0000000..2eb7d09 --- /dev/null +++ b/lab_system/master/config/tests/ndm/crash_loop_battery_mode.cfg
@@ -0,0 +1,13 @@ +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=experimental.ndm.crash_loop_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=BatteryModeCrashLoopTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=experimental.ndm.ota_install_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=OtaInstallableTestSequence
diff --git a/lab_system/master/config/tests/ndm/fdr.cfg b/lab_system/master/config/tests/ndm/fdr.cfg new file mode 100644 index 0000000..f1547af --- /dev/null +++ b/lab_system/master/config/tests/ndm/fdr.cfg
@@ -0,0 +1,13 @@ +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=experimental.ndm.fdr_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=FdrTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=experimental.ndm.ndm_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=NdmTestSequence
diff --git a/lab_system/master/config/tests/ndm/fdr_ndm.cfg b/lab_system/master/config/tests/ndm/fdr_ndm.cfg new file mode 100644 index 0000000..ad290d8 --- /dev/null +++ b/lab_system/master/config/tests/ndm/fdr_ndm.cfg
@@ -0,0 +1,13 @@ +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=experimental.ndm.fdr_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=NdmFdrTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=experimental.ndm.ndm_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=NdmTestSequence
diff --git a/lab_system/master/config/tests/ndm/metrics.cfg b/lab_system/master/config/tests/ndm/metrics.cfg new file mode 100644 index 0000000..24b77e9 --- /dev/null +++ b/lab_system/master/config/tests/ndm/metrics.cfg
@@ -0,0 +1,13 @@ +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=experimental.ndm.metrics_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=MetricsTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=experimental.ndm.ndm_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=NdmTestSequence
diff --git a/lab_system/master/config/tests/ndm/ota_installable.cfg b/lab_system/master/config/tests/ndm/ota_installable.cfg new file mode 100644 index 0000000..9ae3f42 --- /dev/null +++ b/lab_system/master/config/tests/ndm/ota_installable.cfg
@@ -0,0 +1,13 @@ +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=experimental.ndm.ota_installable_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=OtaInstallableTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=experimental.ndm.ota_install_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=OtaInstallableTestSequence
diff --git a/lab_system/master/config/tests/ndm/ota_installable_battery_mode.cfg b/lab_system/master/config/tests/ndm/ota_installable_battery_mode.cfg new file mode 100644 index 0000000..6f1e645 --- /dev/null +++ b/lab_system/master/config/tests/ndm/ota_installable_battery_mode.cfg
@@ -0,0 +1,13 @@ +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=experimental.ndm.ota_installable_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=BatteryModeOtaInstallableTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=experimental.ndm.ota_install_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=OtaInstallableTestSequence
diff --git a/lab_system/master/config/tests/ndm/ota_update.cfg b/lab_system/master/config/tests/ndm/ota_update.cfg new file mode 100644 index 0000000..0e3236c --- /dev/null +++ b/lab_system/master/config/tests/ndm/ota_update.cfg
@@ -0,0 +1,16 @@ +# Config file for OTA update test suite on master branch. +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=experimental.ndm.ota_update_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=OtaUpdateTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=experimental.ndm.ndm_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=NdmTestSequence +
diff --git a/lab_system/master/config/tests/ndm/ota_update_network_disconnect.cfg b/lab_system/master/config/tests/ndm/ota_update_network_disconnect.cfg new file mode 100644 index 0000000..f586228 --- /dev/null +++ b/lab_system/master/config/tests/ndm/ota_update_network_disconnect.cfg
@@ -0,0 +1,16 @@ +# Config file for OTA update test suite on master branch. +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=experimental.ndm.ota_update_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=OtaUpdateNetworkDisconnectTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=experimental.ndm.ndm_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=NdmTestSequence +
diff --git a/lab_system/master/config/tests/ndm/wifi_connectivity.cfg b/lab_system/master/config/tests/ndm/wifi_connectivity.cfg new file mode 100644 index 0000000..d6bbbe2 --- /dev/null +++ b/lab_system/master/config/tests/ndm/wifi_connectivity.cfg
@@ -0,0 +1,13 @@ +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=experimental.ndm.wifi_interface_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=WifiInterfaceConnectivityTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=experimental.ndm.ndm_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=NdmTestSequence
diff --git a/lab_system/master/config/tests/ndm_integration/ndm_integration.cfg b/lab_system/master/config/tests/ndm_integration/ndm_integration.cfg new file mode 100644 index 0000000..8d0d34d --- /dev/null +++ b/lab_system/master/config/tests/ndm_integration/ndm_integration.cfg
@@ -0,0 +1,16 @@ +# Configuration values for ndm integration test. +# +# PROPERTIES +# Name of the TestCase sub-class: +TEST_CASE_CLASS=NDMIntegrationTestCase + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.ndm_integration.ndm_integration_test_case + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=CopyCurlTestSequence + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.ndm_integration.copy_curl_test_sequence + +
diff --git a/lab_system/master/config/tests/octane/octane.cfg b/lab_system/master/config/tests/octane/octane.cfg new file mode 100644 index 0000000..5a73ab1 --- /dev/null +++ b/lab_system/master/config/tests/octane/octane.cfg
@@ -0,0 +1,16 @@ +# Config file for Octane benchmark tests. +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.octane.octane_benchmark_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=OctaneBenchmarkTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.octane.octane_benchmark_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=OctaneBenchmarkTestSequence +
diff --git a/lab_system/master/config/tests/octane/test_defs.json b/lab_system/master/config/tests/octane/test_defs.json new file mode 100644 index 0000000..d215d61 --- /dev/null +++ b/lab_system/master/config/tests/octane/test_defs.json
@@ -0,0 +1,105 @@ +[ + { + "group_name": "octane", + "slave_name": "octane", + "test_name": "octane", + "identifier": "octane", + "device_type": "eureka", + "device_group": "eureka_debug", + "branch": ["master", "release", "next_release", "on_demand"], + "build_flavor": "user" + }, + { + "group_name": "octane", + "slave_name": "octane_v2", + "test_name": "octane", + "identifier": "octane_v2", + "device_type": "lexx", + "device_group": "lexx_eth", + "branch": ["master", "release", "next_release"], + "build_flavor": "user" + }, + { + "group_name": "octane", + "slave_name": "octane_v3", + "test_name": "octane", + "identifier": "octane_v3", + "device_type": "earth", + "device_group": "earth_eth", + "branch": ["master", "release", "next_release"], + "build_flavor": "user" + }, + { + "group_name": "octane", + "slave_name": "octane_v4", + "test_name": "octane", + "identifier": "octane_v4", + "device_type": "luther_b2", + "device_group": "luther_eth", + "branch": ["master", "release", "next_release"], + "build_flavor": "user" + }, + { + "group_name": "octane", + "slave_name": "eurtest_tv", + "test_name": "octane", + "identifier": "octane_bubbletea", + "device_type": "bubbletea", + "device_group": "bubbletea", + "branch": ["cast_tv_mstar_master", "cast_tv_mstar_release", "cast_tv_mstar_next_release"] + }, + { + "group_name": "octane", + "slave_name": "eurtest_tv", + "test_name": "octane", + "identifier": "octane_entourage", + "device_type": "dragonfly", + "device_group": "entourage", + "branch": ["cast_tv_dragonfly_master", "cast_tv_dragonfly_release", "cast_tv_dragonfly_next_release"] + }, + { + "group_name": "octane", + "slave_name": "eurtest_tv", + "test_name": "octane", + "identifier": "octane_guabao", + "device_type": "guabao", + "device_group": "entourage", + "branch": ["cast_tv_mstar_master", "cast_tv_mstar_release", "cast_tv_mstar_next_release"] + }, + { + "group_name": "octane", + "slave_name": "eurtest_tv", + "test_name": "octane", + "identifier": "octane_mars_us", + "device_type": "Mars_US", + "device_group": "entourage", + "branch": ["cast_tv_mediatek_master", "cast_tv_mediatek_release", "cast_tv_mediatek_next_release"] + }, + { + "group_name": "octane", + "slave_name": "eurtest_tv", + "test_name": "octane", + "identifier": "octane_N00007", + "device_type": "N00007", + "device_group": "entourage", + "branch": ["cast_tv_novatek_master", "cast_tv_novatek_release", "cast_tv_novatek_next_release"] + }, + { + "group_name": "octane", + "slave_name": "eurtest_tv", + "test_name": "octane", + "identifier": "octane_suncake", + "device_type": "suncake", + "device_group": "entourage", + "branch": ["cast_tv_mstar_master", "cast_tv_mstar_release", "cast_tv_mstar_next_release"] + }, + { + "group_name": "octane", + "slave_name": "eurtest_tv", + "test_name": "octane", + "identifier": "octane_taroball", + "device_type": "taroball", + "device_group": "entourage", + "branch": ["cast_tv_mstar_master", "cast_tv_mstar_release", "cast_tv_mstar_next_release"] + } +]
diff --git a/lab_system/master/config/tests/ota_clearspace/ota_clearspace.cfg b/lab_system/master/config/tests/ota_clearspace/ota_clearspace.cfg new file mode 100644 index 0000000..e59a940 --- /dev/null +++ b/lab_system/master/config/tests/ota_clearspace/ota_clearspace.cfg
@@ -0,0 +1,21 @@ +# Config file for OTA clear space test suite on master branch. +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.ota_clearspace.ota_clearspace + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=OtaClearSpaceTestCase,OtaNotEnoughSpaceTestCase,OtaDownloadInterruptTestCase,OtaServerInterruptTestCase,OtaCorruptFileDownloadTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.framework.disabled_logging_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=DisabledLoggingCollectLogcatTestSequence + +# Get second to latest build +BUILD_SELECTION_POLICY=second_to_latest + +# OTA update master version. fetcher will use the value to download latest OTA. +BRANCH_TO_TEST=master
diff --git a/lab_system/master/config/tests/ota_installable/atv_ota_installable.cfg b/lab_system/master/config/tests/ota_installable/atv_ota_installable.cfg new file mode 100644 index 0000000..77d821b --- /dev/null +++ b/lab_system/master/config/tests/ota_installable/atv_ota_installable.cfg
@@ -0,0 +1,21 @@ +# Config file for the OTA installable tests +# +# Do not modify property names +# Run make reconfig if you change a value +# and buildbot is running +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.ota_installable.android_ota_installable_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=AndroidOtaInstallableTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.framework.android_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=AndroidTestSequence + +
diff --git a/lab_system/master/config/tests/ota_installable/fuchsia_ota_installable.cfg b/lab_system/master/config/tests/ota_installable/fuchsia_ota_installable.cfg new file mode 100644 index 0000000..edf8a73 --- /dev/null +++ b/lab_system/master/config/tests/ota_installable/fuchsia_ota_installable.cfg
@@ -0,0 +1,21 @@ +# Config file for the Fuchsia OTA installable tests +# +# Do not modify property names +# Run make reconfig if you change a value +# and buildbot is running +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.ota_installable.fuchsia_ota_installable_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=FuchsiaOtaInstallableTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.ota_installable.fuchsia_ota_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=FuchsiaOtaInstallableTestSequence + +
diff --git a/lab_system/master/config/tests/ota_installable/ota_installable.cfg b/lab_system/master/config/tests/ota_installable/ota_installable.cfg new file mode 100644 index 0000000..321652b --- /dev/null +++ b/lab_system/master/config/tests/ota_installable/ota_installable.cfg
@@ -0,0 +1,21 @@ +# Config file for the OTA installable tests +# +# Do not modify property names +# Run make reconfig if you change a value +# and buildbot is running +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.ota_installable.ota_installable_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=OtaInstallableTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.ota_installable.ota_installable_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=OtaInstallableTestSequence + +
diff --git a/lab_system/master/config/tests/ota_installable/test_defs.json b/lab_system/master/config/tests/ota_installable/test_defs.json new file mode 100644 index 0000000..7647b08 --- /dev/null +++ b/lab_system/master/config/tests/ota_installable/test_defs.json
@@ -0,0 +1,293 @@ +[ + { + "branch": [ + "master", + "release", + "next_release" + ], + "build_flavor": "eng", + "device_group": "ota_test", + "device_type": "eureka", + "group_name": "ota_installable", + "identifier": "anchovy_ota_eng", + "scheduler": "55 * * * *", + "slave_name": "anchovy_ota_eng", + "step_factories_recipe": "step_factories_recipes/ota_installable_test_recipe.json", + "test_name": "ota_installable" + }, + { + "branch": [ + "master", + "release", + "next_release" + ], + "build_flavor": "user", + "device_group": "ota_test", + "device_type": "eureka", + "group_name": "ota_installable", + "identifier": "anchovy_ota_user", + "scheduler": "50 * * * *", + "slave_name": "anchovy_ota_user", + "step_factories_recipe": "step_factories_recipes/ota_installable_test_recipe.json", + "test_name": "ota_installable" + }, + { + "branch": [ + "master", + "release", + "next_release" + ], + "build_flavor": "eng", + "device_group": "ota_test", + "device_type": "lexx", + "group_name": "ota_installable", + "identifier": "salami_ota_eng", + "scheduler": "45 * * * *", + "slave_name": "salami_ota_eng", + "step_factories_recipe": "step_factories_recipes/ota_installable_test_recipe.json", + "test_name": "ota_installable" + }, + { + "branch": [ + "master", + "release", + "next_release" + ], + "build_flavor": "user", + "device_group": "ota_test", + "device_type": "lexx", + "group_name": "ota_installable", + "identifier": "salami_ota_user", + "num_devices": "1", + "scheduler": "40 * * * *", + "slave_name": "salami_ota_user", + "step_factories_recipe": "step_factories_recipes/ota_installable_test_recipe.json", + "test_name": "ota_installable" + }, + { + "branch": [ + "master", + "release", + "next_release" + ], + "build_flavor": "eng", + "device_group": "ota_test", + "device_type": "luther_b2", + "group_name": "ota_installable", + "identifier": "luther_ota_eng", + "scheduler": "35 * * * *", + "slave_name": "luther_ota_eng", + "step_factories_recipe": "step_factories_recipes/ota_installable_test_recipe.json", + "test_name": "ota_installable" + }, + { + "branch": [ + "master", + "release", + "next_release" + ], + "build_flavor": "user", + "device_group": "ota_test", + "device_type": "luther_b2", + "group_name": "ota_installable", + "identifier": "luther_ota_user", + "scheduler": "30 * * * *", + "slave_name": "luther_ota_user", + "step_factories_recipe": "step_factories_recipes/ota_installable_test_recipe.json", + "test_name": "ota_installable" + }, + { + "branch": [ + "master", + "release", + "next_release", + "1_28a" + ], + "build_flavor": "eng", + "device_group": "ota_test", + "device_type": "chirp", + "group_name": "ota_installable", + "identifier": "pineapple_ota_eng", + "scheduler": "25 * * * *", + "slave_name": "pineapple_ota_eng", + "step_factories_recipe": "step_factories_recipes/ota_installable_test_recipe.json", + "test_name": "ota_installable" + }, + { + "branch": [ + "master", + "release", + "next_release", + "1_28a" + ], + "build_flavor": "user", + "device_group": "ota_test", + "device_type": "chirp", + "group_name": "ota_installable", + "identifier": "pineapple_ota_user", + "scheduler": "20 * * * *", + "slave_name": "pineapple_ota_user", + "step_factories_recipe": "step_factories_recipes/ota_installable_test_recipe.json", + "test_name": "ota_installable" + }, + { + "branch": [ + "master", + "release", + "next_release" + ], + "build_flavor": "eng", + "device_group": "ota_test", + "device_type": "hendrix", + "group_name": "ota_installable", + "identifier": "pepperoni_ota_eng", + "scheduler": "15 * * * *", + "slave_name": "pepperoni_ota_eng", + "step_factories_recipe": "step_factories_recipes/ota_installable_test_recipe.json", + "test_name": "ota_installable" + }, + { + "branch": [ + "master", + "release", + "next_release" + ], + "build_flavor": "user", + "device_group": "ota_test", + "device_type": "hendrix", + "group_name": "ota_installable", + "identifier": "pepperoni_ota_user", + "scheduler": "10 * * * *", + "slave_name": "pepperoni_ota_user", + "step_factories_recipe": "step_factories_recipes/ota_installable_test_recipe.json", + "test_name": "ota_installable" + }, + { + "branch": [ + "master", + "release", + "next_release" + ], + "build_flavor": "eng", + "device_group": "ota_test", + "device_type": "earth", + "group_name": "ota_installable", + "identifier": "chorizo_ota_eng", + "scheduler": "5 * * * *", + "slave_name": "chorizo_ota_eng", + "step_factories_recipe": "step_factories_recipes/ota_installable_test_recipe.json", + "test_name": "ota_installable" + }, + { + "branch": [ + "master", + "release", + "next_release" + ], + "build_flavor": "user", + "device_group": "ota_test", + "device_type": "earth", + "group_name": "ota_installable", + "identifier": "chorizo_ota_user", + "scheduler": "0 * * * *", + "slave_name": "chorizo_ota_user", + "step_factories_recipe": "step_factories_recipes/ota_installable_test_recipe.json", + "test_name": "ota_installable" + }, + { + "branch": [ + "master", + "release", + "next_release" + ], + "build_flavor": "eng", + "device_group": "ota_test", + "device_type": "assistantdefault", + "group_name": "ota_installable", + "identifier": "assistantdefault_ota_eng", + "scheduler": "55 * * * *", + "slave_name": "assistantdefault_ota_eng", + "step_factories_recipe": "step_factories_recipes/ota_installable_test_recipe.json", + "test_name": "ota_installable" + }, + { + "branch": [ + "master", + "release", + "next_release" + ], + "build_flavor": "user", + "device_group": "ota_test", + "device_type": "assistantdefault", + "group_name": "ota_installable", + "identifier": "assistantdefault_ota_user", + "scheduler": "50 * * * *", + "slave_name": "assistantdefault_ota_user", + "step_factories_recipe": "step_factories_recipes/ota_installable_test_recipe.json", + "test_name": "ota_installable" + }, + { + "branch": [ + "master", + "release", + "next_release" + ], + "build_flavor": "eng", + "device_group": "ota_test", + "device_type": "joplin", + "group_name": "ota_installable", + "identifier": "joplin_ota_eng", + "scheduler": "55 * * * *", + "slave_name": "joplin_ota_eng", + "step_factories_recipe": "step_factories_recipes/ota_installable_test_recipe.json", + "test_name": "ota_installable" + }, + { + "branch": [ + "master", + "release", + "next_release" + ], + "build_flavor": "user", + "device_group": "ota_test", + "device_type": "joplin", + "group_name": "ota_installable", + "identifier": "joplin_ota_user", + "scheduler": "50 * * * *", + "slave_name": "joplin_ota_user", + "step_factories_recipe": "step_factories_recipes/ota_installable_test_recipe.json", + "test_name": "ota_installable" + }, + { + "branch": [ + "master", + "release", + "next_release" + ], + "build_flavor": "eng", + "device_group": "ota_test", + "device_type": "biggie", + "group_name": "ota_installable", + "identifier": "biggie_ota_eng", + "scheduler": "0 * * * *", + "slave_name": "biggie_ota_eng", + "step_factories_recipe": "step_factories_recipes/ota_installable_test_recipe.json", + "test_name": "ota_installable" + }, + { + "branch": [ + "master", + "release", + "next_release" + ], + "build_flavor": "user", + "device_group": "ota_test", + "device_type": "biggie", + "group_name": "ota_installable", + "identifier": "biggie_ota_user", + "scheduler": "5 * * * *", + "slave_name": "biggie_ota_user", + "step_factories_recipe": "step_factories_recipes/ota_installable_test_recipe.json", + "test_name": "ota_installable" + } +]
diff --git a/lab_system/master/config/tests/ota_update/ota_update.cfg b/lab_system/master/config/tests/ota_update/ota_update.cfg new file mode 100644 index 0000000..b9d8d3a --- /dev/null +++ b/lab_system/master/config/tests/ota_update/ota_update.cfg
@@ -0,0 +1,23 @@ +# Config file for OTA update test suite on master branch. +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.ota_update.ota_update_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=OtaUpdateTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.framework.disabled_logging_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=DisabledLoggingTestSequence + +# Get second to latest build +BUILD_SELECTION_POLICY=second_to_latest + +# OTA update master version. fetcher will use the value to download latest OTA. +BRANCH_TO_TEST=master + +
diff --git a/lab_system/master/config/tests/ota_update/ota_update_factory.cfg b/lab_system/master/config/tests/ota_update/ota_update_factory.cfg new file mode 100644 index 0000000..f2f0521 --- /dev/null +++ b/lab_system/master/config/tests/ota_update/ota_update_factory.cfg
@@ -0,0 +1,21 @@ +# Config file for OTA update test suite on 1.27 factory branch. +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.ota_update.ota_update_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=OtaUpdateTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.framework.disabled_logging_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=DisabledLoggingTestSequence + +# Get second to latest build +BUILD_SELECTION_POLICY=second_to_latest + +# OTA update factory version. fetcher will use the value to download latest OTA. +BRANCH_TO_TEST=1.27f
diff --git a/lab_system/master/config/tests/ota_update/ota_update_master.cfg b/lab_system/master/config/tests/ota_update/ota_update_master.cfg new file mode 100644 index 0000000..b9d8d3a --- /dev/null +++ b/lab_system/master/config/tests/ota_update/ota_update_master.cfg
@@ -0,0 +1,23 @@ +# Config file for OTA update test suite on master branch. +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.ota_update.ota_update_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=OtaUpdateTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.framework.disabled_logging_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=DisabledLoggingTestSequence + +# Get second to latest build +BUILD_SELECTION_POLICY=second_to_latest + +# OTA update master version. fetcher will use the value to download latest OTA. +BRANCH_TO_TEST=master + +
diff --git a/lab_system/master/config/tests/ota_update/ota_update_release.cfg b/lab_system/master/config/tests/ota_update/ota_update_release.cfg new file mode 100644 index 0000000..0d4e246 --- /dev/null +++ b/lab_system/master/config/tests/ota_update/ota_update_release.cfg
@@ -0,0 +1,20 @@ +# Config file for OTA update test suite on release branches. +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.ota_update.ota_update_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=OtaUpdateTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.framework.disabled_logging_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=DisabledLoggingTestSequence + +# Get second to latest build +BUILD_SELECTION_POLICY=second_to_latest + +
diff --git a/lab_system/master/config/tests/perception_activity_zones/perception_activity_zones.cfg b/lab_system/master/config/tests/perception_activity_zones/perception_activity_zones.cfg new file mode 100644 index 0000000..028bca6 --- /dev/null +++ b/lab_system/master/config/tests/perception_activity_zones/perception_activity_zones.cfg
@@ -0,0 +1,24 @@ +# +#Configuration values for the event detection test. +# +# PROPERTIES + +API_PATH=stellar +GCS_BUCKET=catatester_test_deps +GCS_VIDEO_DIR_PATH=perception/activity_zones +ITERATIONS=1 +USER=cast.test.dev23@gmail.com +# Name of the TestCase sub-class: +TEST_CASE_CLASS=PerceptionActivityZonesTestCase + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.perception_activity_zones.perception_activity_zones_test_case + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=PerceptionEventDetectionTestSequence + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.perception_event_detection.perception_event_detection_test_sequence + + +
diff --git a/lab_system/master/config/tests/perception_event_detection/perception_event_detection.cfg b/lab_system/master/config/tests/perception_event_detection/perception_event_detection.cfg new file mode 100644 index 0000000..ab8f7c9 --- /dev/null +++ b/lab_system/master/config/tests/perception_event_detection/perception_event_detection.cfg
@@ -0,0 +1,24 @@ +# +#Configuration values for the event detection test. +# +# PROPERTIES + +API_PATH=stellar +GCS_BUCKET=catatester_test_deps +GCS_VIDEO_DIR_PATH=perception/event_detection +ITERATIONS=1 +USER=cast.test.dev23@gmail.com +# Name of the TestCase sub-class: +TEST_CASE_CLASS=PerceptionEventDetectionTestCase + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.perception_event_detection.perception_event_detection_test_case + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=PerceptionEventDetectionTestSequence + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.perception_event_detection.perception_event_detection_test_sequence + + +
diff --git a/lab_system/master/config/tests/perception_face_detection/perception_face_detection.cfg b/lab_system/master/config/tests/perception_face_detection/perception_face_detection.cfg new file mode 100644 index 0000000..2b9040f --- /dev/null +++ b/lab_system/master/config/tests/perception_face_detection/perception_face_detection.cfg
@@ -0,0 +1,24 @@ +# +#Configuration values for the face detection test. +# +# PROPERTIES + +API_PATH=stellar +GCS_BUCKET=catatester_test_deps +GCS_VIDEO_DIR_PATH=perception/familiar_face +ITERATIONS=1 +USER=cast.test.dev23@gmail.com +# Name of the TestCase sub-class: +TEST_CASE_CLASS=PerceptionFaceDetectionTestCase + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.perception_face_detection.perception_face_detection_test_case + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=PerceptionEventDetectionTestSequence + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.perception_event_detection.perception_event_detection_test_sequence + + +
diff --git a/lab_system/master/config/tests/perception_latency/perception_latency.cfg b/lab_system/master/config/tests/perception_latency/perception_latency.cfg new file mode 100644 index 0000000..e4bdd14 --- /dev/null +++ b/lab_system/master/config/tests/perception_latency/perception_latency.cfg
@@ -0,0 +1,24 @@ +# Configuration values for the perception latency test. +# +# PROPERTIES + +API_PATH=stellar +DEVICE_ENROLL_DIR=/data/chrome/chirp/gallery +ENROLLMENT_DIR_PATH=perception/enrollment_gallery +GCS_BUCKET=catatester_test_deps +GCS_VIDEO_DIR_PATH=perception/test_videos/motion +ITERATIONS=15 +# Name of the TestCase sub-class: +TEST_CASE_CLASS=PerceptionLatencyTestCaseMotion + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.perception_latency.perception_latency_test_case + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=PerceptionLatencyTestSequence + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.perception_latency.perception_latency_test_sequence + + +
diff --git a/lab_system/master/config/tests/perception_latency/perception_latency_fuchsia.cfg b/lab_system/master/config/tests/perception_latency/perception_latency_fuchsia.cfg new file mode 100644 index 0000000..63f7165 --- /dev/null +++ b/lab_system/master/config/tests/perception_latency/perception_latency_fuchsia.cfg
@@ -0,0 +1,25 @@ +# Configuration values for the perception latency test. +# +# PROPERTIES + +API_PATH=ml_framework +API_PORT=8805 +DEVICE_ENROLL_DIR=/data/persistent/253a01f8ffb9be3d543731594c39c80b3548cb953319cdbc719fb7ffc7f32ed2/kronk/gallery +ENROLLMENT_DIR_PATH=perception/enrollment_gallery +GCS_BUCKET=catatester_test_deps +GCS_VIDEO_DIR_PATH=perception/test_videos/motion +ITERATIONS=25 +# Name of the TestCase sub-class: +TEST_CASE_CLASS=PerceptionLatencyTestCaseMotion + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.perception_latency.perception_latency_test_case + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=FuchsiaPerceptionLatencyTestSequence + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.perception_latency.fuchsia_perception_latency_test_sequence + + +
diff --git a/lab_system/master/config/tests/perception_latency_ndm/perception_latency.cfg b/lab_system/master/config/tests/perception_latency_ndm/perception_latency.cfg new file mode 100644 index 0000000..538e26a --- /dev/null +++ b/lab_system/master/config/tests/perception_latency_ndm/perception_latency.cfg
@@ -0,0 +1,25 @@ +# Configuration values for the perception latency test. +# +# PROPERTIES + +API_PATH=stellar +DEVICE_ENROLL_DIR=/data/chrome/chirp/gallery +ENROLLMENT_DIR_PATH=perception/enrollment_gallery +GCS_BUCKET=catatester_test_deps +GCS_VIDEO_DIR_PATH=perception/test_videos/motion +ITERATIONS=1 +POWER_MODE=line_power +# Name of the TestCase sub-class: +TEST_CASE_CLASS=PerceptionLatencyTestCaseMotion + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.perception_latency_ndm.perception_latency_test_case + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=PerceptionLatencyTestSequence + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.perception_latency_ndm.perception_latency_test_sequence + + +
diff --git a/lab_system/master/config/tests/perception_latency_ndm/perception_latency_battery.cfg b/lab_system/master/config/tests/perception_latency_ndm/perception_latency_battery.cfg new file mode 100644 index 0000000..f189a3a --- /dev/null +++ b/lab_system/master/config/tests/perception_latency_ndm/perception_latency_battery.cfg
@@ -0,0 +1,25 @@ +# Configuration values for the perception latency test. +# +# PROPERTIES + +API_PATH=stellar +DEVICE_ENROLL_DIR=/data/chrome/chirp/gallery +ENROLLMENT_DIR_PATH=perception/enrollment_gallery +GCS_BUCKET=catatester_test_deps +GCS_VIDEO_DIR_PATH=perception/test_videos/motion +ITERATIONS=1 +POWER_MODE=battery +# Name of the TestCase sub-class: +TEST_CASE_CLASS=PerceptionLatencyTestCaseMotion + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.perception_latency_ndm.perception_latency_test_case + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=PerceptionLatencyTestSequence + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.perception_latency_ndm.perception_latency_test_sequence + + +
diff --git a/lab_system/master/config/tests/perception_stability/perception_stability.cfg b/lab_system/master/config/tests/perception_stability/perception_stability.cfg new file mode 100644 index 0000000..5d864a9 --- /dev/null +++ b/lab_system/master/config/tests/perception_stability/perception_stability.cfg
@@ -0,0 +1,25 @@ +# +#Configuration values for the perception stability test. +# +# PROPERTIES + +API_PATH=stellar +GCS_BUCKET=catatester_test_deps +GCS_VIDEO_DIR_PATH=perception/stability +ITERATIONS=1 +SCENE_TYPE=motion +USER=cast.test.dev23@gmail.com +# Name of the TestCase sub-class: +TEST_CASE_CLASS=PerceptionStabilityTestCase + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.perception_stability.perception_stability_test_case + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=PerceptionEventDetectionTestSequence + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.perception_event_detection.perception_event_detection_test_sequence + + +
diff --git a/lab_system/master/config/tests/perception_stability/perception_stability_static.cfg b/lab_system/master/config/tests/perception_stability/perception_stability_static.cfg new file mode 100644 index 0000000..de1c3c1 --- /dev/null +++ b/lab_system/master/config/tests/perception_stability/perception_stability_static.cfg
@@ -0,0 +1,25 @@ +# +#Configuration values for the perception stability test. +# +# PROPERTIES + +API_PATH=stellar +GCS_BUCKET=catatester_test_deps +GCS_VIDEO_DIR_PATH=perception/stability_static_person +ITERATIONS=1 +SCENE_TYPE=static +USER=cast.test.dev23@gmail.com +# Name of the TestCase sub-class: +TEST_CASE_CLASS=PerceptionStabilityTestCase + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.perception_stability.perception_stability_test_case + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=PerceptionEventDetectionTestSequence + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.perception_event_detection.perception_event_detection_test_sequence + + +
diff --git a/lab_system/master/config/tests/perception_stability/perception_stability_static_person.cfg b/lab_system/master/config/tests/perception_stability/perception_stability_static_person.cfg new file mode 100644 index 0000000..cf37a14 --- /dev/null +++ b/lab_system/master/config/tests/perception_stability/perception_stability_static_person.cfg
@@ -0,0 +1,25 @@ +# +#Configuration values for the perception stability test. +# +# PROPERTIES + +API_PATH=stellar +GCS_BUCKET=catatester_test_deps +GCS_VIDEO_DIR_PATH=perception/stability_static_person +ITERATIONS=1 +SCENE_TYPE=static_person +USER=cast.test.dev23@gmail.com +# Name of the TestCase sub-class: +TEST_CASE_CLASS=PerceptionStabilityTestCase + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.perception_stability.perception_stability_test_case + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=PerceptionEventDetectionTestSequence + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.perception_event_detection.perception_event_detection_test_sequence + + +
diff --git a/lab_system/master/config/tests/pog/audio_formats.cfg b/lab_system/master/config/tests/pog/audio_formats.cfg new file mode 100644 index 0000000..d1ddd89 --- /dev/null +++ b/lab_system/master/config/tests/pog/audio_formats.cfg
@@ -0,0 +1,15 @@ +# Config file for JavaScript audio format tests. +# +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.audio_formats.audio_formats_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=SupportedAudioFormatsTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.framework.javascript_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=JavascriptTestSequence + +DISABLED_TESTS=SupportedAudioFormatsHiResTestCase,AudioBitRatesTestCase
diff --git a/lab_system/master/config/tests/pog/properties.cfg b/lab_system/master/config/tests/pog/properties.cfg new file mode 100644 index 0000000..cce5bc1 --- /dev/null +++ b/lab_system/master/config/tests/pog/properties.cfg
@@ -0,0 +1,21 @@ +# Config file for properties tests +# +# Do not modify property names +# Run make reconfig if you change a value +# and buildbot is running +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.properties.properties_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=PropertiesTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.framework.disabled_logging_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=DisabledLoggingCollectLogcatTestSequence + +
diff --git a/lab_system/master/config/tests/pog/reboot_metrics.cfg b/lab_system/master/config/tests/pog/reboot_metrics.cfg new file mode 100644 index 0000000..8675c9e --- /dev/null +++ b/lab_system/master/config/tests/pog/reboot_metrics.cfg
@@ -0,0 +1,14 @@ +# Config file for testing RebootLoop. +# +# PROPERTIES +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.reboot_timer.reboot_metrics_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=RebootMetricsTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.framework.disabled_logging_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=DisabledLoggingTestSequence
diff --git a/lab_system/master/config/tests/pog/receiver_c4a.cfg b/lab_system/master/config/tests/pog/receiver_c4a.cfg new file mode 100644 index 0000000..722a5cd --- /dev/null +++ b/lab_system/master/config/tests/pog/receiver_c4a.cfg
@@ -0,0 +1,47 @@ +# Config file for the Cast receiver tests on audio devices +# +# Do not modify property names +# Run make reconfig if you change a value +# and buildbot is running +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.cast.receiver.compliance_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=CastReceiverMirroringProtocolTestCase,CastReceiverStressTestCase,CastReceiverMediaProtocolMP4TestCase,CastReceiverMediaProtocolSmoothStreamingTestCase,CastReceiverBenchmarkTestCase,CastReceiverQueueTestCase,CastReceiverCapabilityTestCase,CastReceiverMediaProtocolHLSTestCase,CastReceiverMediaProtocolDASHTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.framework.test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=TestSequence + +# Receiver app ids: +CAST_V2_DEBUG_APP_ID=C566BECD +CAST_V2_PLAYER_APP_ID=BE6E4473 +CHROME_MIRRORING_APP_ID=85CDB22F + +# Test specific configuration values: +MP4_MEDIA_URL=https://storage.googleapis.com/cast_media/format_tests/audio/stereo_guitar.mp3 +MP4_MEDIA_MIME_TYPE=video/mp4 + +# Temporary fix +DASH_MEDIA_URL=https://home-media-server.sandbox.google.com/static/receiver/dash/sample-dash-list.mpd +DASH_MEDIA_MIME_TYPE=application/dash+xml +HLS_MEDIA_URL=https://home-media-server.sandbox.google.com/static/receiver/hls/bbb/bbb_hls.m3u8 +HLS_MEDIA_MIME_TYPE=application/x-mpegurl +SMOOTH_STREAMING_MEDIA_URL=https://home-media-server.sandbox.google.com/static/receiver/smooth/BBB_H264_AACL/big_buck_bunny_1080p_stereo.ism/manifest +SMOOTH_STREAMING_MEDIA_MIME_TYPE=application/vnd.ms-sstr+xml + +MEDIA_LOAD_TIMEOUT_SECS=30 + +# Flag to skip tests that require a display and can't be run in C4A devices. +NO_DISPLAY=1 + +# This config is used to determine if cast operations should be allowed even if +# device is not signed-in using a gaia account. +ENABLE_CAST_WITHOUT_SIGN_IN=True + +
diff --git a/lab_system/master/config/tests/pog/setup_wifi_channel.cfg b/lab_system/master/config/tests/pog/setup_wifi_channel.cfg new file mode 100644 index 0000000..f5ce52c --- /dev/null +++ b/lab_system/master/config/tests/pog/setup_wifi_channel.cfg
@@ -0,0 +1,22 @@ +# Config file for setup wifi channel tests +# +# Do not modify property names +# Run make reconfig if you change a value +# and buildbot is running +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.setup.setup_wifi_channel_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=SetupWifiChannelTestCase,SetupWifiChannel5GHzTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.framework.disabled_logging_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=DisabledLoggingTestSequence + + +
diff --git a/lab_system/master/config/tests/pog/wifi_interface_connectivity.cfg b/lab_system/master/config/tests/pog/wifi_interface_connectivity.cfg new file mode 100644 index 0000000..88b47d2 --- /dev/null +++ b/lab_system/master/config/tests/pog/wifi_interface_connectivity.cfg
@@ -0,0 +1,13 @@ +# PROPERTIES +# +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.setup_api_wifi.wifi_interface_connectivity_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=WifiInterfaceConnectivityTestCase,WifiInterfaceRebootTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.setup_api_wifi.wifi_interface_connectivity_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=WifiConnectivityTestSequence
diff --git a/lab_system/master/config/tests/presence_detection/presence_detection.cfg b/lab_system/master/config/tests/presence_detection/presence_detection.cfg new file mode 100644 index 0000000..a811e03 --- /dev/null +++ b/lab_system/master/config/tests/presence_detection/presence_detection.cfg
@@ -0,0 +1,33 @@ +# Config file for presence test using conducted auido +# +# Do not modify property names +# Run make reconfig if you change a value +# and buildbot is running +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.presence_detection.presence_detection_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=PresenceDetectionTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.assistant.presence_detection.presence_detection_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=PresenceDetectionTestSequence + +# the test audio config files. +GCS_AUDIO_DIR_PATH=assistant/presence_detection_samples + +# Use Tunnel where applicable + +TCP_TUNNEL_TIMEOUT_SECS=1800 + +# Threshold and timeout value for test +PRESENCE_DETECTION_THRESHOLD=0.3 +PRESENCE_DETECTION_TIMEOUT=10 + +# Endpoint API path +API_PATH=stellar/presence \ No newline at end of file
diff --git a/lab_system/master/config/tests/preview_test/preview_test.cfg b/lab_system/master/config/tests/preview_test/preview_test.cfg new file mode 100644 index 0000000..5e895f1 --- /dev/null +++ b/lab_system/master/config/tests/preview_test/preview_test.cfg
@@ -0,0 +1,16 @@ +# Config file for preview channel test suite. +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.preview.preview_channel_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=PreviewChannelTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.preview.preview_channel_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=PreviewChannelTestSequence +
diff --git a/lab_system/master/config/tests/preview_test/test_defs.json b/lab_system/master/config/tests/preview_test/test_defs.json new file mode 100644 index 0000000..f7e6b50 --- /dev/null +++ b/lab_system/master/config/tests/preview_test/test_defs.json
@@ -0,0 +1,12 @@ +[ + { + "group_name": "preview_test", + "slave_name": "preview_test", + "test_name": "preview_test", + "identifier": "preview_test", + "device_type": ["earth", "hendrix"], + "device_group": "preview_dvt", + "branch": ["master", "release"], + "build_flavor": "user" + } +]
diff --git a/lab_system/master/config/tests/properties/properties.cfg b/lab_system/master/config/tests/properties/properties.cfg new file mode 100644 index 0000000..cce5bc1 --- /dev/null +++ b/lab_system/master/config/tests/properties/properties.cfg
@@ -0,0 +1,21 @@ +# Config file for properties tests +# +# Do not modify property names +# Run make reconfig if you change a value +# and buildbot is running +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.properties.properties_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=PropertiesTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.framework.disabled_logging_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=DisabledLoggingCollectLogcatTestSequence + +
diff --git a/lab_system/master/config/tests/proximity/proximity_observer_fan.cfg b/lab_system/master/config/tests/proximity/proximity_observer_fan.cfg new file mode 100644 index 0000000..646881c --- /dev/null +++ b/lab_system/master/config/tests/proximity/proximity_observer_fan.cfg
@@ -0,0 +1,41 @@ +# Config file for proximity test using Fan +# +# Do not modify property names +# Run make reconfig if you change a value +# and buildbot is running +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.proximity.proximity_fan_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=ProximityFanTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.proximity.proximity_fan_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=ProximityFanTestSequence + +# Use Tunnel where applicable +USE_TUNNEL=False + +#Fan Socket Number +SOCKET_ONE_P_FIVE_FEET=1 +SOCKET_ONE_P_FIVE_FEET_PASSRATE=98 +SOCKET_THREE_FEET=2 +SOCKET_THREE_FEET_PASSRATE=98 +SOCKET_SEVEN_FEET=3 +SOCKET_SEVEN_FEET_PASSRATE=98 + +#Test Duration +TEST_DURATION_HOUR=0.5 + +AUDIO_PATH=https://home-media-server.sandbox.google.com/static/proximity_background.mp3 +AUDIO_TYPE=audio/mp3 + +#Detection Type +DETECTION_TYPE=observer + +SIGNED_IN=True \ No newline at end of file
diff --git a/lab_system/master/config/tests/proximity/proximity_observer_negative.cfg b/lab_system/master/config/tests/proximity/proximity_observer_negative.cfg new file mode 100644 index 0000000..0581b13 --- /dev/null +++ b/lab_system/master/config/tests/proximity/proximity_observer_negative.cfg
@@ -0,0 +1,53 @@ +# Config file for proximity test using Fan +# +# Do not modify property names +# Run make reconfig if you change a value +# and buildbot is running +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.proximity.proximity_neg_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=ProximityNegTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.proximity.proximity_neg_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=ProximityNegTestSequence + +# Use Tunnel where applicable +USE_TUNNEL=False + +PASSRATE=98 + +TEST_VOLUME_NUM=4 +# Play Back Volume +PLAYBACK_VOLUME_1=0.1 +PLAYBACK_VOLUME_2=0.4 +PLAYBACK_VOLUME_3=0.8 +PLAYBACK_VOLUME_4=1.0 + +#Test Duration +TEST_DURATION_HOUR=0.2 + +#Detection Type +DETECTION_TYPE=observer + +TEST_AUDIO_NUM=10 +TEST_AUDIO_1=https://home-media-server.sandbox.google.com/static/proximity_neg/Bad_Guy.mp3 +TEST_AUDIO_2=https://home-media-server.sandbox.google.com/static/proximity_neg/Beautiful_People.mp3 +TEST_AUDIO_3=https://home-media-server.sandbox.google.com/static/proximity_neg/Boy_Friend.mp3 +TEST_AUDIO_4=https://home-media-server.sandbox.google.com/static/proximity_neg/Fading.mp3 +TEST_AUDIO_5=https://home-media-server.sandbox.google.com/static/proximity_neg/Going_Bad.mp3 +TEST_AUDIO_6=https://home-media-server.sandbox.google.com/static/proximity_neg/I_Donot_Care.mp3 +TEST_AUDIO_7=https://home-media-server.sandbox.google.com/static/proximity_neg/Panini.mp3 +TEST_AUDIO_8=https://home-media-server.sandbox.google.com/static/proximity_neg/Ransom.mp3 +TEST_AUDIO_9=https://home-media-server.sandbox.google.com/static/proximity_neg/Sucker.mp3 +TEST_AUDIO_10=https://home-media-server.sandbox.google.com/static/proximity_neg/Without_Me.mp3 + +AUDIO_TYPE=audio/mp3 + +SIGNED_IN=True \ No newline at end of file
diff --git a/lab_system/master/config/tests/proximity/proximity_observer_skim.cfg b/lab_system/master/config/tests/proximity/proximity_observer_skim.cfg new file mode 100644 index 0000000..7c77f1e --- /dev/null +++ b/lab_system/master/config/tests/proximity/proximity_observer_skim.cfg
@@ -0,0 +1,50 @@ +# Config file for proximity test using Fan +# +# Do not modify property names +# Run make reconfig if you change a value +# and buildbot is running +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.proximity.proximity_skim_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=ProximitySkimTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.proximity.proximity_skim_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=ProximitySkimTestSequence + +# Use Tunnel where applicable +USE_TUNNEL=False + +# In Range / Out of Range Pass Rate +PLAYBACK_VOLUME_1_PASSRATE=99 +PLAYBACK_VOLUME_2_PASSRATE=99 +PLAYBACK_VOLUME_3_PASSRATE=99 +PLAYBACK_VOLUME_4_PASSRATE=99 + +#Test Duration +TEST_DURATION_HOUR=0.05 + +AUDIO_PATH=https://home-media-server.sandbox.google.com/static/proximity_neg/Panini.mp3 +AUDIO_TYPE=audio/mp3 + +#Detection Type +DETECTION_TYPE=observer + +# Play Back Volume +TEST_VOLUME_NUM=4 +PLAYBACK_VOLUME_1=0.1 +PLAYBACK_VOLUME_2=0.4 +PLAYBACK_VOLUME_3=0.8 +PLAYBACK_VOLUME_4=1.0 + +ITERATION=100 + +BUFFER_CLEANUP_DELAY_SEC=25 + +SIGNED_IN=True \ No newline at end of file
diff --git a/lab_system/master/config/tests/query_reboot_loop/query_reboot_loop.cfg b/lab_system/master/config/tests/query_reboot_loop/query_reboot_loop.cfg new file mode 100644 index 0000000..e089230 --- /dev/null +++ b/lab_system/master/config/tests/query_reboot_loop/query_reboot_loop.cfg
@@ -0,0 +1,18 @@ +# Config file for testing RebootLoop. +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.query_reboot_loop.query_reboot_loop_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=QueryRebootLoopTestCase,QueryRebootLoopWifiTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.query_reboot_loop.query_reboot_loop_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=QueryRebootLoopTestSequence + +# Relative GCS path (from the cast-test-data bucket) to the directory containing +GCS_AUDIO_DIR_PATH=assistant/pineapple-p2-rerecordings/synthetic_speech/chirp_marketing_golden/follow_up/answers \ No newline at end of file
diff --git a/lab_system/master/config/tests/reboot_loop/reboot_loop.cfg b/lab_system/master/config/tests/reboot_loop/reboot_loop.cfg new file mode 100644 index 0000000..b4d99b8 --- /dev/null +++ b/lab_system/master/config/tests/reboot_loop/reboot_loop.cfg
@@ -0,0 +1,15 @@ +# Config file for testing RebootLoop. +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.reboot_loop.reboot_loop_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=RebootLoopTestCase,RebootLoopWifiTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.reboot_loop.reboot_loop_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=RebootLoopTestSequence \ No newline at end of file
diff --git a/lab_system/master/config/tests/reboot_metrics/reboot_metrics.cfg b/lab_system/master/config/tests/reboot_metrics/reboot_metrics.cfg new file mode 100644 index 0000000..8675c9e --- /dev/null +++ b/lab_system/master/config/tests/reboot_metrics/reboot_metrics.cfg
@@ -0,0 +1,14 @@ +# Config file for testing RebootLoop. +# +# PROPERTIES +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.reboot_timer.reboot_metrics_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=RebootMetricsTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.framework.disabled_logging_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=DisabledLoggingTestSequence
diff --git a/lab_system/master/config/tests/reboot_timer/dumpstate_timer.cfg b/lab_system/master/config/tests/reboot_timer/dumpstate_timer.cfg new file mode 100644 index 0000000..b73dbf3 --- /dev/null +++ b/lab_system/master/config/tests/reboot_timer/dumpstate_timer.cfg
@@ -0,0 +1,15 @@ +# Configuration values for TimeDumpstateTestCase. +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.reboot_timer.dumpstate_timer_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=DumpstateTimerTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.framework.disabled_logging_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=DisabledLoggingTestSequence
diff --git a/lab_system/master/config/tests/reboot_timer/reboot_timer.cfg b/lab_system/master/config/tests/reboot_timer/reboot_timer.cfg new file mode 100644 index 0000000..d916265 --- /dev/null +++ b/lab_system/master/config/tests/reboot_timer/reboot_timer.cfg
@@ -0,0 +1,17 @@ +# Configuration values for the reboot_timer test. +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.reboot_timer.reboot_timer_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=RebootTimeMeasurementTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.framework.disabled_logging_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=DisabledLoggingTestSequence + +
diff --git a/lab_system/master/config/tests/reboot_timer/reboot_timer_c4a.cfg b/lab_system/master/config/tests/reboot_timer/reboot_timer_c4a.cfg new file mode 100644 index 0000000..c70f41a --- /dev/null +++ b/lab_system/master/config/tests/reboot_timer/reboot_timer_c4a.cfg
@@ -0,0 +1,16 @@ +# Configuration values for the reboot_timer test for audio devices. +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.reboot_timer.reboot_timer_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=RebootTimeMeasurementTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.framework.disabled_logging_test_sequence +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=DisabledLoggingTestSequence + +
diff --git a/lab_system/master/config/tests/reboot_timer/test_defs.json b/lab_system/master/config/tests/reboot_timer/test_defs.json new file mode 100644 index 0000000..378041f --- /dev/null +++ b/lab_system/master/config/tests/reboot_timer/test_defs.json
@@ -0,0 +1,29 @@ +[ + { + "group_name": "reboot_timer", + "slave_name": "reboot_timer_v3", + "test_name": "reboot_timer", + "identifier": "reboot_timer_entourage", + "device_type": "dragonfly", + "device_group": "entourage", + "branch": "cast_tv_dragonfly_master" + }, + { + "group_name": "reboot_timer", + "slave_name": "reboot_timer_biggie", + "test_name": "reboot_timer", + "identifier": "reboot_timer_biggie", + "device_type": "biggie", + "device_group": "biggie", + "branch": ["master", "release", "next_release"] + }, + { + "group_name": "reboot_timer", + "slave_name": "reboot_timer_joplin", + "test_name": "reboot_timer", + "identifier": "reboot_timer_joplin", + "device_type": "joplin", + "device_group": "joplin", + "branch": ["master", "release", "next_release"] + } +]
diff --git a/lab_system/master/config/tests/reconnect_test/reconnect_test.cfg b/lab_system/master/config/tests/reconnect_test/reconnect_test.cfg new file mode 100644 index 0000000..f439ece --- /dev/null +++ b/lab_system/master/config/tests/reconnect_test/reconnect_test.cfg
@@ -0,0 +1,14 @@ +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.reconnect_test.reconnect_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=ReconnectTest + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.framework.test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=TestSequence +
diff --git a/lab_system/master/config/tests/remote_controller/atv_remote_ota_installable.cfg b/lab_system/master/config/tests/remote_controller/atv_remote_ota_installable.cfg new file mode 100644 index 0000000..438ad28 --- /dev/null +++ b/lab_system/master/config/tests/remote_controller/atv_remote_ota_installable.cfg
@@ -0,0 +1,19 @@ +# Config file for the OTA installable tests +# +# Do not modify property names +# Run make reconfig if you change a value +# and buildbot is running +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.remote_controller.atv_remote_ota_installable_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=AtvRemoteOtaInstallableTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.framework.android_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=AndroidTestSequence
diff --git a/lab_system/master/config/tests/selina/fuchsia_sleep_chester.cfg b/lab_system/master/config/tests/selina/fuchsia_sleep_chester.cfg new file mode 100644 index 0000000..22a6bcc --- /dev/null +++ b/lab_system/master/config/tests/selina/fuchsia_sleep_chester.cfg
@@ -0,0 +1,30 @@ +# Config file for sleep tracking test using chester +# +# Do not modify property names +# Run make reconfig if you change a value +# and buildbot is running +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.selina.sleep_chester_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=SleepChesterTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.selina.fuchsia_sleep_chester_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=FuchsiaSleepChesterTestSequence + +SLEEP_STATE=SUBJECT_STATUS_ABSENT,SUBJECT_STATUS_AWAKE,SUBJECT_STATUS_ASLEEP,SUBJECT_STATUS_AWAKE,SUBJECT_STATUS_ABSENT +SLEEP_DURATION=5,10,60,5,130 +EXPECTED_SLEEP_SESSION_NUM=1 +EXPECTED_SLEEP_LENGTH=60 +SLEEP_LENGTH_ERROR=5 + +# refer to go/sleep_seq_test +TEST_SEQ_NAME=Simplest_seq + +SIGNED_IN=True
diff --git a/lab_system/master/config/tests/selina/fuchsia_sleep_chester_1_1.cfg b/lab_system/master/config/tests/selina/fuchsia_sleep_chester_1_1.cfg new file mode 100644 index 0000000..eaf289b --- /dev/null +++ b/lab_system/master/config/tests/selina/fuchsia_sleep_chester_1_1.cfg
@@ -0,0 +1,30 @@ +# Config file for sleep tracking test using chester +# +# Do not modify property names +# Run make reconfig if you change a value +# and buildbot is running +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.selina.sleep_chester_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=SleepChesterTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.selina.fuchsia_sleep_chester_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=FuchsiaSleepChesterTestSequence + +SLEEP_STATE=SUBJECT_STATUS_ABSENT,SUBJECT_STATUS_AWAKE,SUBJECT_STATUS_ASLEEP,SUBJECT_STATUS_AWAKE,SUBJECT_STATUS_ASLEEP,SUBJECT_STATUS_AWAKE,SUBJECT_STATUS_ABSENT,SUBJECT_STATUS_AWAKE,SUBJECT_STATUS_ASLEEP,SUBJECT_STATUS_AWAKE,SUBJECT_STATUS_ABSENT +SLEEP_DURATION=5,10,60,10,30,10,10,5,20,5,130 +EXPECTED_SLEEP_SESSION_NUM=1 +EXPECTED_SLEEP_LENGTH=105 +SLEEP_LENGTH_ERROR=5 + +# refer to go/sleep_seq_test +TEST_SEQ_NAME=Sleep_seq_1_1 + +SIGNED_IN=True
diff --git a/lab_system/master/config/tests/selina/fuchsia_sleep_chester_2_1.cfg b/lab_system/master/config/tests/selina/fuchsia_sleep_chester_2_1.cfg new file mode 100644 index 0000000..1578f83 --- /dev/null +++ b/lab_system/master/config/tests/selina/fuchsia_sleep_chester_2_1.cfg
@@ -0,0 +1,30 @@ +# Config file for sleep tracking test using chester +# +# Do not modify property names +# Run make reconfig if you change a value +# and buildbot is running +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.selina.sleep_chester_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=SleepChesterTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.selina.fuchsia_sleep_chester_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=FuchsiaSleepChesterTestSequence + +SLEEP_STATE=SUBJECT_STATUS_ABSENT,SUBJECT_STATUS_AWAKE,SUBJECT_STATUS_ASLEEP,SUBJECT_STATUS_AWAKE,SUBJECT_STATUS_ABSENT,SUBJECT_STATUS_AWAKE,SUBJECT_STATUS_ASLEEP,SUBJECT_STATUS_AWAKE,SUBJECT_STATUS_ABSENT +SLEEP_DURATION=5,10,60,5,130,10,50,5,130 +EXPECTED_SLEEP_SESSION_NUM=2 +EXPECTED_SLEEP_LENGTH=60,50 +SLEEP_LENGTH_ERROR=5 + +# refer to go/sleep_seq_test +TEST_SEQ_NAME=Sleep_seq_2_1 + +SIGNED_IN=True
diff --git a/lab_system/master/config/tests/selina/gesture_data_injection.cfg b/lab_system/master/config/tests/selina/gesture_data_injection.cfg new file mode 100644 index 0000000..ae86358 --- /dev/null +++ b/lab_system/master/config/tests/selina/gesture_data_injection.cfg
@@ -0,0 +1,27 @@ +# Config file for presence test using conducted auido +# +# Do not modify property names +# Run make reconfig if you change a value +# and buildbot is running +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.selina.gesture_data_injection_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=GestureDataInjectionTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.selina.gesture_data_injection_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=GestureDataInjectionTestSequence + +# the test audio config files. +GCS_SELINA_DATA_DIR_PATH=assistant/selina_gesture_data + +# number of iteration +TEST_ITERATION_COUNT=10 + +SIGNED_IN=True \ No newline at end of file
diff --git a/lab_system/master/config/tests/selina/sleep_chester.cfg b/lab_system/master/config/tests/selina/sleep_chester.cfg new file mode 100644 index 0000000..5f75bf7 --- /dev/null +++ b/lab_system/master/config/tests/selina/sleep_chester.cfg
@@ -0,0 +1,30 @@ +# Config file for sleep tracking test using chester +# +# Do not modify property names +# Run make reconfig if you change a value +# and buildbot is running +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.selina.sleep_chester_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=SleepChesterTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.selina.sleep_chester_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=SleepChesterTestSequence + +SLEEP_STATE=SUBJECT_STATUS_ABSENT,SUBJECT_STATUS_AWAKE,SUBJECT_STATUS_ASLEEP,SUBJECT_STATUS_AWAKE,SUBJECT_STATUS_ABSENT +SLEEP_DURATION=5,10,60,5,130 +EXPECTED_SLEEP_SESSION_NUM=1 +EXPECTED_SLEEP_LENGTH=60 +SLEEP_LENGTH_ERROR=5 + +# refer to go/sleep_seq_test +TEST_SEQ_NAME=Simplest_seq + +SIGNED_IN=True \ No newline at end of file
diff --git a/lab_system/master/config/tests/selina/sleep_chester_1_1.cfg b/lab_system/master/config/tests/selina/sleep_chester_1_1.cfg new file mode 100644 index 0000000..c0e3adf --- /dev/null +++ b/lab_system/master/config/tests/selina/sleep_chester_1_1.cfg
@@ -0,0 +1,30 @@ +# Config file for sleep tracking test using chester +# +# Do not modify property names +# Run make reconfig if you change a value +# and buildbot is running +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.selina.sleep_chester_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=SleepChesterTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.selina.sleep_chester_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=SleepChesterTestSequence + +SLEEP_STATE=SUBJECT_STATUS_ABSENT,SUBJECT_STATUS_AWAKE,SUBJECT_STATUS_ASLEEP,SUBJECT_STATUS_AWAKE,SUBJECT_STATUS_ASLEEP,SUBJECT_STATUS_AWAKE,SUBJECT_STATUS_ABSENT,SUBJECT_STATUS_AWAKE,SUBJECT_STATUS_ASLEEP,SUBJECT_STATUS_AWAKE,SUBJECT_STATUS_ABSENT +SLEEP_DURATION=5,10,60,10,30,10,10,5,20,5,130 +EXPECTED_SLEEP_SESSION_NUM=1 +EXPECTED_SLEEP_LENGTH=105 +SLEEP_LENGTH_ERROR=5 + +# refer to go/sleep_seq_test +TEST_SEQ_NAME=Sleep_seq_1_1 + +SIGNED_IN=True \ No newline at end of file
diff --git a/lab_system/master/config/tests/selina/sleep_chester_2_1.cfg b/lab_system/master/config/tests/selina/sleep_chester_2_1.cfg new file mode 100644 index 0000000..89059aa --- /dev/null +++ b/lab_system/master/config/tests/selina/sleep_chester_2_1.cfg
@@ -0,0 +1,30 @@ +# Config file for sleep tracking test using chester +# +# Do not modify property names +# Run make reconfig if you change a value +# and buildbot is running +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.selina.sleep_chester_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=SleepChesterTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.selina.sleep_chester_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=SleepChesterTestSequence + +SLEEP_STATE=SUBJECT_STATUS_ABSENT,SUBJECT_STATUS_AWAKE,SUBJECT_STATUS_ASLEEP,SUBJECT_STATUS_AWAKE,SUBJECT_STATUS_ABSENT,SUBJECT_STATUS_AWAKE,SUBJECT_STATUS_ASLEEP,SUBJECT_STATUS_AWAKE,SUBJECT_STATUS_ABSENT +SLEEP_DURATION=5,10,60,5,130,10,50,5,130 +EXPECTED_SLEEP_SESSION_NUM=2 +EXPECTED_SLEEP_LENGTH=60,50 +SLEEP_LENGTH_ERROR=5 + +# refer to go/sleep_seq_test +TEST_SEQ_NAME=Sleep_seq_2_1 + +SIGNED_IN=True \ No newline at end of file
diff --git a/lab_system/master/config/tests/selina/sleep_data_injection.cfg b/lab_system/master/config/tests/selina/sleep_data_injection.cfg new file mode 100644 index 0000000..97e796c --- /dev/null +++ b/lab_system/master/config/tests/selina/sleep_data_injection.cfg
@@ -0,0 +1,24 @@ +# Config file for presence test using conducted auido +# +# Do not modify property names +# Run make reconfig if you change a value +# and buildbot is running +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.selina.sleep_data_injection_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=SleepDataInjectionTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.selina.sleep_data_injection_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=SleepDataInjectionTestSequence + +SLEEP_STATE=SUBJECT_STATUS_ABSENT,SUBJECT_STATUS_AWAKE,SUBJECT_STATUS_ASLEEP,SUBJECT_STATUS_AWAKE,SUBJECT_STATUS_ABSENT +SLEEP_DURATION=5,10,40,5,130 + +SIGNED_IN=True \ No newline at end of file
diff --git a/lab_system/master/config/tests/settings/atv_settings.cfg b/lab_system/master/config/tests/settings/atv_settings.cfg new file mode 100644 index 0000000..3ec3627 --- /dev/null +++ b/lab_system/master/config/tests/settings/atv_settings.cfg
@@ -0,0 +1,15 @@ +# Config file for Android TV settings tests. +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.settings.atv_settings_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=AtvSettingsTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.framework.android_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=AndroidTestSequence
diff --git a/lab_system/master/config/tests/settings/settings.cfg b/lab_system/master/config/tests/settings/settings.cfg new file mode 100644 index 0000000..bf1b02e --- /dev/null +++ b/lab_system/master/config/tests/settings/settings.cfg
@@ -0,0 +1,17 @@ +# Configuration values for the settings test. +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.settings.settings_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=SettingsTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.settings.settings_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=SettingsTestSequence + +
diff --git a/lab_system/master/config/tests/settings/test_defs.json b/lab_system/master/config/tests/settings/test_defs.json new file mode 100644 index 0000000..3ecd6d1 --- /dev/null +++ b/lab_system/master/config/tests/settings/test_defs.json
@@ -0,0 +1,42 @@ +[ + { + "group_name": "settings", + "slave_name": "settings", + "test_name": "settings", + "device_type": "eureka", + "device_group": "eureka_debug", + "identifier": "settings", + "hidden": "true", + "branch": ["master", "release"] + }, + { + "group_name": "settings", + "slave_name": "settings_v2", + "test_name": "settings", + "device_type": "lexx", + "device_group": "lexx_eth", + "identifier": "settings_v2", + "hidden": "true", + "branch": ["master", "release"] + }, + { + "group_name": "settings", + "slave_name": "settings_v3", + "test_name": "settings", + "device_type": "earth", + "device_group": "earth_eth", + "identifier": "settings_v3", + "hidden": "true", + "branch": ["master", "release"] + }, + { + "group_name": "settings", + "slave_name": "settings", + "test_name": "settings", + "device_type": "luther_b2", + "device_group": "luther_eth", + "identifier": "settings_v4", + "branch": ["master", "release"], + "step_factories_recipe": "step_factories_recipes/default_with_new_device_allocation.json" + } +]
diff --git a/lab_system/master/config/tests/setup/atv_setup.cfg b/lab_system/master/config/tests/setup/atv_setup.cfg new file mode 100644 index 0000000..b38540c --- /dev/null +++ b/lab_system/master/config/tests/setup/atv_setup.cfg
@@ -0,0 +1,15 @@ +# Config file for Cast Shell APK setup tests. +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.setup.atv_setup_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=SetupTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.framework.android_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=AndroidTestSequence \ No newline at end of file
diff --git a/lab_system/master/config/tests/setup/fuchsia_setup.cfg b/lab_system/master/config/tests/setup/fuchsia_setup.cfg new file mode 100644 index 0000000..d632c87 --- /dev/null +++ b/lab_system/master/config/tests/setup/fuchsia_setup.cfg
@@ -0,0 +1,19 @@ +# Config file for setup tests on Fuchsia +# +# Do not modify property names +# Run make reconfig if you change a value +# and buildbot is running +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.setup.setup_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=SetupTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.framework.fuchsia_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=FuchsiaTestSequence
diff --git a/lab_system/master/config/tests/setup/setup.cfg b/lab_system/master/config/tests/setup/setup.cfg new file mode 100644 index 0000000..af3db39 --- /dev/null +++ b/lab_system/master/config/tests/setup/setup.cfg
@@ -0,0 +1,31 @@ +# Config file for setup tests +# +# Do not modify property names +# Run make reconfig if you change a value +# and buildbot is running +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.setup.setup_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=SetupTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.framework.test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=TestSequence + +# Wifi ssid +WIFI_SSID=setup_ap + +# Wifi Wpa Auth +WPA_AUTH=7 + +# Wifi Wpa Cipher +WPA_CIPHER=4 + +# Wifi password +WIFI_PASSWD=/MagicRoom5!
diff --git a/lab_system/master/config/tests/setup_api_wifi/fuchsia_setup_api_wifi.cfg b/lab_system/master/config/tests/setup_api_wifi/fuchsia_setup_api_wifi.cfg new file mode 100644 index 0000000..7f27ab9 --- /dev/null +++ b/lab_system/master/config/tests/setup_api_wifi/fuchsia_setup_api_wifi.cfg
@@ -0,0 +1,19 @@ +# Config file for setup tests +# +# Do not modify property names +# Run make reconfig if you change a value +# and buildbot is running +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.setup_api_wifi.fuchsia_setup_api_wifi_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=FuchsiaSetupApiWifiTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.framework.fuchsia_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=FuchsiaTestSequence
diff --git a/lab_system/master/config/tests/setup_api_wifi/setup_api_wifi.cfg b/lab_system/master/config/tests/setup_api_wifi/setup_api_wifi.cfg new file mode 100644 index 0000000..1e014a4 --- /dev/null +++ b/lab_system/master/config/tests/setup_api_wifi/setup_api_wifi.cfg
@@ -0,0 +1,19 @@ +# Config file for setup tests +# +# Do not modify property names +# Run make reconfig if you change a value +# and buildbot is running +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.setup_api_wifi.setup_api_wifi_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=SetupApiWifiTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.framework.disabled_logging_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=DisabledLoggingCollectLogcatTestSequence
diff --git a/lab_system/master/config/tests/setup_reboot/fuchsia_setup_reboot.cfg b/lab_system/master/config/tests/setup_reboot/fuchsia_setup_reboot.cfg new file mode 100644 index 0000000..6b21d12 --- /dev/null +++ b/lab_system/master/config/tests/setup_reboot/fuchsia_setup_reboot.cfg
@@ -0,0 +1,21 @@ +# Config file for setup reboot tests on Fuchsia devices +# +# Do not modify property names +# Run make reconfig if you change a value +# and buildbot is running +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.setup.fuchsia_setup_reboot_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=FuchsiaSetupRebootTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.framework.fuchsia_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=FuchsiaTestSequence + +
diff --git a/lab_system/master/config/tests/setup_reboot/setup_reboot.cfg b/lab_system/master/config/tests/setup_reboot/setup_reboot.cfg new file mode 100644 index 0000000..bd43770 --- /dev/null +++ b/lab_system/master/config/tests/setup_reboot/setup_reboot.cfg
@@ -0,0 +1,21 @@ +# Config file for setup reboot tests +# +# Do not modify property names +# Run make reconfig if you change a value +# and buildbot is running +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.setup.setup_reboot_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=SetupRebootTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.framework.disabled_logging_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=DisabledLoggingCollectLogcatTestSequence + +
diff --git a/lab_system/master/config/tests/setup_wifi_channel/setup_wifi_channel.cfg b/lab_system/master/config/tests/setup_wifi_channel/setup_wifi_channel.cfg new file mode 100644 index 0000000..f5ce52c --- /dev/null +++ b/lab_system/master/config/tests/setup_wifi_channel/setup_wifi_channel.cfg
@@ -0,0 +1,22 @@ +# Config file for setup wifi channel tests +# +# Do not modify property names +# Run make reconfig if you change a value +# and buildbot is running +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.setup.setup_wifi_channel_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=SetupWifiChannelTestCase,SetupWifiChannel5GHzTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.framework.disabled_logging_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=DisabledLoggingTestSequence + + +
diff --git a/lab_system/master/config/tests/short_audio_play/short_audio_play.cfg b/lab_system/master/config/tests/short_audio_play/short_audio_play.cfg new file mode 100644 index 0000000..0aeb13c --- /dev/null +++ b/lab_system/master/config/tests/short_audio_play/short_audio_play.cfg
@@ -0,0 +1,18 @@ +# Config file for testing RebootLoop. +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.short_audio_play.short_audio_play_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=ShortAudioPlayTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.framework.disabled_logging_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=DisabledLoggingTestSequence + +# Plot data +PLOT=False \ No newline at end of file
diff --git a/lab_system/master/config/tests/simple_command/simple_command.cfg b/lab_system/master/config/tests/simple_command/simple_command.cfg new file mode 100644 index 0000000..33ec1dd --- /dev/null +++ b/lab_system/master/config/tests/simple_command/simple_command.cfg
@@ -0,0 +1,15 @@ +# Configuration values for the simple command test. +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.simple_command.simple_command_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=SimpleCommandTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.framework.disabled_logging_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=DisabledLoggingTestSequence
diff --git a/lab_system/master/config/tests/simple_query/simple_query.cfg b/lab_system/master/config/tests/simple_query/simple_query.cfg new file mode 100644 index 0000000..af47f77 --- /dev/null +++ b/lab_system/master/config/tests/simple_query/simple_query.cfg
@@ -0,0 +1,26 @@ +# Config file for testing SimpleQuery. +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.simple_query.simple_query_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=SimpleQueryTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.simple_query.simple_query_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=SimpleQueryTestSequence + +# Relative GCS path (from the cast-test-data bucket) to the directory containing +GCS_AUDIO_DIR_PATH=assistant/pineapple-p2-rerecordings/synthetic_speech/chirp_marketing_golden/follow_up/answers + +# Assistant backend server to use. Valid values are : +# "NIGHTLY_DEV_SERVER", "TEAMFOOD_SERVER", "DOGFOOD_SERVER" and "PROD_SERVER" +# These values are defined in +# continuous-tests/internal/eurtest/device/assistant_device.py +ASSISTANT_BACKEND=DOGFOOD_SERVER + +SIGNED_IN=True \ No newline at end of file
diff --git a/lab_system/master/config/tests/smoke_tests/crash_loop.cfg b/lab_system/master/config/tests/smoke_tests/crash_loop.cfg new file mode 100644 index 0000000..cf4b1b7 --- /dev/null +++ b/lab_system/master/config/tests/smoke_tests/crash_loop.cfg
@@ -0,0 +1,17 @@ +# Config file for the Crash/Boot loop tests +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.ota_installable.crash_loop_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=CrashLoopTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.ota_installable.ota_installable_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=OtaInstallableTestSequence + +
diff --git a/lab_system/master/config/tests/smoke_tests/ota_installable.cfg b/lab_system/master/config/tests/smoke_tests/ota_installable.cfg new file mode 100644 index 0000000..321652b --- /dev/null +++ b/lab_system/master/config/tests/smoke_tests/ota_installable.cfg
@@ -0,0 +1,21 @@ +# Config file for the OTA installable tests +# +# Do not modify property names +# Run make reconfig if you change a value +# and buildbot is running +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.ota_installable.ota_installable_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=OtaInstallableTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.ota_installable.ota_installable_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=OtaInstallableTestSequence + +
diff --git a/lab_system/master/config/tests/sound_sensing/sound_sensing.cfg b/lab_system/master/config/tests/sound_sensing/sound_sensing.cfg new file mode 100644 index 0000000..26deb0d --- /dev/null +++ b/lab_system/master/config/tests/sound_sensing/sound_sensing.cfg
@@ -0,0 +1,30 @@ +# Config file for presence test using conducted auido +# +# Do not modify property names +# Run make reconfig if you change a value +# and buildbot is running +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.sound_sensing.sound_sensing_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=SoundSensingTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.sound_sensing.sound_sensing_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=SoundSensingTestSequence + +# the test audio config files. +GCS_AUDIO_DIR_PATH=assistant/sound_sensing_recordings + +# number of iteration +TEST_ITERATION_COUNT=5 + +# Use Tunnel where applicable + +TCP_TUNNEL_TIMEOUT_SECS=1800 +
diff --git a/lab_system/master/config/tests/sound_sensing/sound_sensing_mic_writer.cfg b/lab_system/master/config/tests/sound_sensing/sound_sensing_mic_writer.cfg new file mode 100644 index 0000000..8fb4c46 --- /dev/null +++ b/lab_system/master/config/tests/sound_sensing/sound_sensing_mic_writer.cfg
@@ -0,0 +1,28 @@ +# Config file for presence test using conducted auido +# +# Do not modify property names +# Run make reconfig if you change a value +# and buildbot is running +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.sound_sensing.sound_sensing_mic_writer_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=SoundSensingMicWriterTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.sound_sensing.sound_sensing_mic_writer_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=SoundSensingMicWriterTestSequence + +# the test audio config files. +GCS_AUDIO_DIR_PATH=assistant/sound_sensing_recordings + +# number of iteration +TEST_ITERATION_COUNT=10 + +# Use Tunnel where applicable +TCP_TUNNEL_TIMEOUT_SECS=1800
diff --git a/lab_system/master/config/tests/sound_sensing/sound_sensing_mic_writer_p1.cfg b/lab_system/master/config/tests/sound_sensing/sound_sensing_mic_writer_p1.cfg new file mode 100644 index 0000000..307f964 --- /dev/null +++ b/lab_system/master/config/tests/sound_sensing/sound_sensing_mic_writer_p1.cfg
@@ -0,0 +1,28 @@ +# Config file for presence test using conducted auido +# +# Do not modify property names +# Run make reconfig if you change a value +# and buildbot is running +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.sound_sensing.sound_sensing_mic_writer_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=SoundSensingMicWriterTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.sound_sensing.sound_sensing_mic_writer_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=SoundSensingMicWriterTestSequence + +# the test audio config files for P1 recordings. +GCS_AUDIO_DIR_PATH=assistant/sound_sensing_recordings_p1 + +# number of iteration +TEST_ITERATION_COUNT=10 + +# Use Tunnel where applicable +TCP_TUNNEL_TIMEOUT_SECS=1800
diff --git a/lab_system/master/config/tests/sound_sensing/sound_sensing_mic_writer_p2.cfg b/lab_system/master/config/tests/sound_sensing/sound_sensing_mic_writer_p2.cfg new file mode 100644 index 0000000..dc7827a --- /dev/null +++ b/lab_system/master/config/tests/sound_sensing/sound_sensing_mic_writer_p2.cfg
@@ -0,0 +1,28 @@ +# Config file for presence test using conducted auido +# +# Do not modify property names +# Run make reconfig if you change a value +# and buildbot is running +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.sound_sensing.sound_sensing_mic_writer_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=SoundSensingMicWriterTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.sound_sensing.sound_sensing_mic_writer_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=SoundSensingMicWriterTestSequence + +# the test audio config files for P2 recordings. +GCS_AUDIO_DIR_PATH=assistant/sound_sensing_recordings_p2 + +# number of iteration +TEST_ITERATION_COUNT=10 + +# Use Tunnel where applicable +TCP_TUNNEL_TIMEOUT_SECS=1800
diff --git a/lab_system/master/config/tests/sound_sensing/sound_sensing_mic_writer_small_pool.cfg b/lab_system/master/config/tests/sound_sensing/sound_sensing_mic_writer_small_pool.cfg new file mode 100644 index 0000000..32f068d --- /dev/null +++ b/lab_system/master/config/tests/sound_sensing/sound_sensing_mic_writer_small_pool.cfg
@@ -0,0 +1,28 @@ +# Config file for presence test using conducted auido +# +# Do not modify property names +# Run make reconfig if you change a value +# and buildbot is running +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.sound_sensing.sound_sensing_mic_writer_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=SoundSensingMicWriterTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.sound_sensing.sound_sensing_mic_writer_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=SoundSensingMicWriterTestSequence + +# the test audio config files. +GCS_AUDIO_DIR_PATH=assistant/sound_sensing_recordings_small_pool + +# number of iteration +TEST_ITERATION_COUNT=10 + +# Use Tunnel where applicable +TCP_TUNNEL_TIMEOUT_SECS=1800
diff --git a/lab_system/master/config/tests/system_perf/system_perf_duo_video_call.cfg b/lab_system/master/config/tests/system_perf/system_perf_duo_video_call.cfg new file mode 100644 index 0000000..fe42e7e --- /dev/null +++ b/lab_system/master/config/tests/system_perf/system_perf_duo_video_call.cfg
@@ -0,0 +1,20 @@ +# Config file for system perf duo video call tests. +# In this test case, we collect system performance metrics for a duo video call. +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.system_perf.duo_video_call_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=SystemPerfDuoVideoCallTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.framework.test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=TestSequence + +# Max duo call duration for testing in seconds +MAX_DUO_CALL_DURATION_SECS=30 +
diff --git a/lab_system/master/config/tests/system_perf/system_perf_long_duo_video_call.cfg b/lab_system/master/config/tests/system_perf/system_perf_long_duo_video_call.cfg new file mode 100644 index 0000000..39320d4 --- /dev/null +++ b/lab_system/master/config/tests/system_perf/system_perf_long_duo_video_call.cfg
@@ -0,0 +1,26 @@ +# Config file for system perf duo video call tests. +# In this test case, we collect system performance metrics for a duo video call. +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.system_perf.long_duo_video_call_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=SystemPerfLongDuoVideoCallTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.framework.test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=TestSequence + +# Duo testing code Bot ID +DUO_CALL_BOT_ID=bot:duo-bot-router-gfile-bot+/x20/teams/home-newman-ee/duo-bot/pinknoise.mkv+loop + +# Max duration in seconds for each duo call in the test +MAX_DUO_CALL_DURATION_SECS=600 + +# Number of the Duo calls being made in the test +DUO_CALL_REPEAT_TIMES=12 +
diff --git a/lab_system/master/config/tests/system_perf/system_perf_long_duo_video_call_short.cfg b/lab_system/master/config/tests/system_perf/system_perf_long_duo_video_call_short.cfg new file mode 100644 index 0000000..6ec9092 --- /dev/null +++ b/lab_system/master/config/tests/system_perf/system_perf_long_duo_video_call_short.cfg
@@ -0,0 +1,26 @@ +# Config file for system perf duo video call tests. +# In this test case, we collect system performance metrics for a duo video call. +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.system_perf.long_duo_video_call_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=SystemPerfLongDuoVideoCallTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.framework.test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=TestSequence + +# Duo testing code Bot ID +DUO_CALL_BOT_ID=bot:duo-bot-router-gfile-bot+/x20/teams/home-newman-ee/duo-bot/pinknoise.mkv+loop + +# Max duration in seconds for each duo call in the test +MAX_DUO_CALL_DURATION_SECS=300 + +# Number of the Duo calls being made in the test +DUO_CALL_REPEAT_TIMES=1 +
diff --git a/lab_system/master/config/tests/system_perf/system_perf_sound_sensing.cfg b/lab_system/master/config/tests/system_perf/system_perf_sound_sensing.cfg new file mode 100644 index 0000000..fba5419 --- /dev/null +++ b/lab_system/master/config/tests/system_perf/system_perf_sound_sensing.cfg
@@ -0,0 +1,20 @@ +# Config file for system perf duo video call tests. +# In this test case, we collect system performance metrics for a duo video call. +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.system_perf.sound_sensing_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=SystemPerfSoundSensingTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.framework.test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=TestSequence + +# Total Wait time in seconds to measure the system performance +SOUND_SENSING_WAIT_TIME_SECS=60 +
diff --git a/lab_system/master/config/tests/system_perf/system_perf_video_playback.cfg b/lab_system/master/config/tests/system_perf/system_perf_video_playback.cfg new file mode 100644 index 0000000..c74e80e --- /dev/null +++ b/lab_system/master/config/tests/system_perf/system_perf_video_playback.cfg
@@ -0,0 +1,41 @@ +# Config file for system perf video playback tests. +# In this test case, we collect system performance metrics when playing different video playbacks. +# The video formats include youtube video and web media from different codec. +# Including 4k video test on 4k supported devices. +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.system_perf.video_playback_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=SystemPerfVideoPlaybackTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.framework.test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=TestSequence + +# Test case timeout secs +TEST_CASE_TIMEOUT_SECS=1800 + +# Video start timeout secs +VIDEO_START_TIMEOUT_SECS=30 + +# The number of seconds the video play. +SHORT_VIDEO_DURATION_SECS=100 +LONG_VIDEO_DURATION_SECS=180 + + +# The number of seconds for cold start time. Should be long enough to prevent cast failure. +COLD_START_TIME_SECS=8 + +# 4K VP9 web media +WEB_MEDIA_4K_VP9=https://storage.googleapis.com/vp9-4k-stream/phfx_4KHD_VP9TestFootage.webm + +# FHD web media +WEB_MEDIA_FHD=https://home-media-server.sandbox.google.com/static/media/car-1920x1080.mp4 + +# 4K Youtube video +YOUTUBE_4K_VIDEO_ID=ftlvreFtA2A
diff --git a/lab_system/master/config/tests/system_perf/system_perf_video_playback_android.cfg b/lab_system/master/config/tests/system_perf/system_perf_video_playback_android.cfg new file mode 100644 index 0000000..40d5187 --- /dev/null +++ b/lab_system/master/config/tests/system_perf/system_perf_video_playback_android.cfg
@@ -0,0 +1,28 @@ +# Config file for system perf video playback tests. +# In this test case, we collect system performance metrics when playing YouTube +# video on Android devices. + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.system_perf.android_youtube_playback_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=SystemPerfAndroidYoutubePlaybackTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.framework.android_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=AndroidTestSequence + +# Test case timeout secs +TEST_CASE_TIMEOUT_SECS=1800 + +# The number of seconds the video play. +VIDEO_DURATION_SECS=120 + +# The number of seconds for cold start time. Should be long enough for the +# video to start. +COLD_START_TIME_SECS=8 + +# Target Video on YouTube +YOUTUBE_VIDEO_ID=ftlvreFtA2A
diff --git a/lab_system/master/config/tests/test_beds/eraser_biggie_100_115_57_2.json b/lab_system/master/config/tests/test_beds/eraser_biggie_100_115_57_2.json new file mode 100644 index 0000000..16a855a --- /dev/null +++ b/lab_system/master/config/tests/test_beds/eraser_biggie_100_115_57_2.json
@@ -0,0 +1,26 @@ +{ + "rpi_hotword": { + "host": "100.115.57.4", + "username": "pi", + "password": "casting", + "sound_meter_program": "python /home/pi/sound_meter/sound_meter.py", + "hotword_file": "/home/pi/test_tones/okgoogle-ken_trim.wav", + "hotword_level_file": "/home/pi/test_tones/okgoogle-ken_trim_6_repeat.wav", + "ok_google_samples_dir" : "/home/pi/ok_google_samples", + "hey_google_samples_dir" : "/home/pi/hey_google_samples", + "speaker_volume": "100", + "record_device": "sysdefault:CARD=1" + }, + "rpi_chirp": { + "host": "100.115.57.3", + "username": "pi", + "password": "casting", + "sound_meter_program": "python /home/pi/sound_meter/sound_meter.py", + "speaker_volume": "100", + "record_device": "sysdefault:CARD=1" + }, + "chirp": { + "host": "100.115.57.2" + } +} +
diff --git a/lab_system/master/config/tests/test_beds/eraser_biggie_100_115_60_69.json b/lab_system/master/config/tests/test_beds/eraser_biggie_100_115_60_69.json new file mode 100644 index 0000000..2625b11 --- /dev/null +++ b/lab_system/master/config/tests/test_beds/eraser_biggie_100_115_60_69.json
@@ -0,0 +1,24 @@ +{ + "rpi_hotword": { + "host": "100.115.60.70", + "username": "pi", + "password": "casting", + "sound_meter_program": "python /home/pi/sound_meter/sound_meter.py", + "hotword_file": "/home/pi/test_tones/okgoogle-ken_trim.wav", + "hotword_level_file": "/home/pi/test_tones/okgoogle-ken_trim_6_repeat.wav", + "ok_google_samples_dir" : "/home/pi/ok_google_samples", + "hey_google_samples_dir" : "/home/pi/hey_google_samples", + "speaker_volume": "95" + }, + "dut_sound_meter_host": { + "host": "100.115.60.71", + "username": "pi", + "password": "casting", + "sound_meter_program": "python /home/pi/sound_meter/sound_meter.py", + "speaker_volume": "95" + }, + "chirp": { + "host": "100.115.60.69" + } +} +
diff --git a/lab_system/master/config/tests/test_beds/eraser_chirp_100_115_121_11.json b/lab_system/master/config/tests/test_beds/eraser_chirp_100_115_121_11.json new file mode 100644 index 0000000..f3fb6c4 --- /dev/null +++ b/lab_system/master/config/tests/test_beds/eraser_chirp_100_115_121_11.json
@@ -0,0 +1,26 @@ +{ + "rpi_hotword": { + "host": "100.115.121.4", + "username": "pi", + "password": "casting", + "sound_meter_program": "python /home/pi/sound_meter/sound_meter.py", + "hotword_file": "/home/pi/test_tones/okgoogle-ken_trim.wav", + "hotword_level_file": "/home/pi/test_tones/okgoogle-ken_trim_6_repeat.wav", + "ok_google_samples_dir" : "/home/pi/ok_google_samples", + "hey_google_samples_dir" : "/home/pi/hey_google_samples", + "speaker_volume": "95", + "record_device": "sysdefault:CARD=1" + }, + "rpi_chirp": { + "host": "100.115.121.4", + "username": "pi", + "password": "casting", + "sound_meter_program": "python /home/pi/sound_meter/sound_meter.py", + "speaker_volume": "95", + "record_device": "sysdefault:CARD=1" + }, + "chirp": { + "host": "100.115.121.11" + } +} +
diff --git a/lab_system/master/config/tests/test_beds/eraser_joplin_100_115_121_9.json b/lab_system/master/config/tests/test_beds/eraser_joplin_100_115_121_9.json new file mode 100644 index 0000000..7d0834b --- /dev/null +++ b/lab_system/master/config/tests/test_beds/eraser_joplin_100_115_121_9.json
@@ -0,0 +1,26 @@ +{ + "rpi_hotword": { + "host": "100.115.121.5", + "username": "pi", + "password": "casting", + "sound_meter_program": "python /home/pi/sound_meter/sound_meter.py", + "hotword_file": "/home/pi/test_tones/okgoogle-ken_trim.wav", + "hotword_level_file": "/home/pi/test_tones/okgoogle-ken_trim_6_repeat.wav", + "ok_google_samples_dir" : "/home/pi/ok_google_samples", + "hey_google_samples_dir" : "/home/pi/hey_google_samples", + "speaker_volume": "95", + "record_device": "sysdefault:CARD=1" + }, + "rpi_chirp": { + "host": "100.115.121.5", + "username": "pi", + "password": "casting", + "sound_meter_program": "python /home/pi/sound_meter/sound_meter.py", + "speaker_volume": "95", + "record_device": "sysdefault:CARD=1" + }, + "chirp": { + "host": "100.115.121.9" + } +} +
diff --git a/lab_system/master/config/tests/test_beds/hotword_samples_biggie_100_115_122_19.json.disabled b/lab_system/master/config/tests/test_beds/hotword_samples_biggie_100_115_122_19.json.disabled new file mode 100644 index 0000000..425aab6 --- /dev/null +++ b/lab_system/master/config/tests/test_beds/hotword_samples_biggie_100_115_122_19.json.disabled
@@ -0,0 +1,27 @@ +{ + "rpi_hotword": { + "host": "100.115.121.3", + "username": "pi", + "password": "casting", + "temp_dir": "/tmp", + "sound_meter_program": "python /home/pi/sound_meter/sound_meter.py", + "hotword_file": "/home/pi/test_tones/okgoogle-ken_trim.wav", + "hotword_level_file": "/home/pi/test_tones/okgoogle-ken_trim_6_repeat.wav", + "ok_google_samples_dir" : "/home/pi/ok_google_samples", + "hey_google_samples_dir" : "/home/pi/hey_google_samples", + "speaker_volume": "100", + "record_device": "sysdefault:CARD=1" + }, + "rpi_chirp": { + "host": "100.115.121.3", + "username": "pi", + "password": "casting", + "temp_dir": "/tmp", + "sound_meter_program": "python /home/pi/sound_meter/sound_meter.py", + "speaker_volume": "100", + "record_device": "sysdefault:CARD=1" + }, + "chirp": { + "host": "100.115.122.19" + } +}
diff --git a/lab_system/master/config/tests/test_beds/hotword_samples_chirp_100_115_122_125.json.disabled b/lab_system/master/config/tests/test_beds/hotword_samples_chirp_100_115_122_125.json.disabled new file mode 100644 index 0000000..394080a --- /dev/null +++ b/lab_system/master/config/tests/test_beds/hotword_samples_chirp_100_115_122_125.json.disabled
@@ -0,0 +1,27 @@ +{ + "rpi_hotword": { + "host": "100.115.122.126", + "username": "pi", + "password": "casting", + "temp_dir": "/tmp", + "sound_meter_program": "python /home/pi/sound_meter/sound_meter.py", + "hotword_file": "/home/pi/test_tones/okgoogle-ken_trim.wav", + "hotword_level_file": "/home/pi/test_tones/okgoogle-ken_trim_6_repeat.wav", + "ok_google_samples_dir" : "/home/pi/ok_google_samples", + "hey_google_samples_dir" : "/home/pi/hey_google_samples", + "speaker_volume": "100", + "record_device": "sysdefault:CARD=1" + }, + "rpi_chirp": { + "host": "100.115.122.126", + "username": "pi", + "password": "casting", + "temp_dir": "/tmp", + "sound_meter_program": "python /home/pi/sound_meter/sound_meter.py", + "speaker_volume": "100", + "record_device": "sysdefault:CARD=1" + }, + "chirp": { + "host": "100.115.122.125" + } +}
diff --git a/lab_system/master/config/tests/test_beds/hotword_samples_estelle_100_115_122_93.json.disabled b/lab_system/master/config/tests/test_beds/hotword_samples_estelle_100_115_122_93.json.disabled new file mode 100644 index 0000000..637e714 --- /dev/null +++ b/lab_system/master/config/tests/test_beds/hotword_samples_estelle_100_115_122_93.json.disabled
@@ -0,0 +1,27 @@ +{ + "rpi_hotword": { + "host": "100.115.122.97", + "username": "pi", + "password": "casting", + "temp_dir": "/tmp", + "sound_meter_program": "python /home/pi/sound_meter/sound_meter.py", + "hotword_file": "/home/pi/test_tones/okgoogle-ken_trim.wav", + "hotword_level_file": "/home/pi/test_tones/okgoogle-ken_trim_6_repeat.wav", + "ok_google_samples_dir" : "/home/pi/ok_google_samples", + "hey_google_samples_dir" : "/home/pi/hey_google_samples", + "speaker_volume": "100", + "record_device": "sysdefault:CARD=1" + }, + "rpi_chirp": { + "host": "100.115.122.97", + "username": "pi", + "password": "casting", + "temp_dir": "/tmp", + "sound_meter_program": "python /home/pi/sound_meter/sound_meter.py", + "speaker_volume": "100", + "record_device": "sysdefault:CARD=1" + }, + "chirp": { + "host": "100.115.122.93" + } +}
diff --git a/lab_system/master/config/tests/test_beds/hotword_samples_joplin_100_115_120_255.json.disabled b/lab_system/master/config/tests/test_beds/hotword_samples_joplin_100_115_120_255.json.disabled new file mode 100644 index 0000000..95ec3dd --- /dev/null +++ b/lab_system/master/config/tests/test_beds/hotword_samples_joplin_100_115_120_255.json.disabled
@@ -0,0 +1,27 @@ +{ + "rpi_hotword": { + "host": "100.115.120.254", + "username": "pi", + "password": "casting", + "temp_dir": "/tmp", + "sound_meter_program": "python /home/pi/sound_meter/sound_meter.py", + "hotword_file": "/home/pi/test_tones/okgoogle-ken_trim.wav", + "hotword_level_file": "/home/pi/test_tones/okgoogle-ken_trim_6_repeat.wav", + "ok_google_samples_dir" : "/home/pi/ok_google_samples", + "hey_google_samples_dir" : "/home/pi/hey_google_samples", + "speaker_volume": "100", + "record_device": "sysdefault:CARD=1" + }, + "rpi_chirp": { + "host": "100.115.120.254", + "username": "pi", + "password": "casting", + "temp_dir": "/tmp", + "sound_meter_program": "python /home/pi/sound_meter/sound_meter.py", + "speaker_volume": "100", + "record_device": "sysdefault:CARD=1" + }, + "chirp": { + "host": "100.115.120.255" + } +}
diff --git a/lab_system/master/config/tests/test_beds/latency_biggie_100_115_121_12.json b/lab_system/master/config/tests/test_beds/latency_biggie_100_115_121_12.json new file mode 100644 index 0000000..6278d5f --- /dev/null +++ b/lab_system/master/config/tests/test_beds/latency_biggie_100_115_121_12.json
@@ -0,0 +1,35 @@ +{ + "rpi_hotword": { + "host": "100.115.121.6", + "username": "pi", + "password": "casting", + "temp_dir": "/tmp", + "sound_meter_program": "python /home/pi/sound_meter/sound_meter.py", + "hotword_file": "/home/pi/test_tones/okgoogle-ken_trim.wav", + "hotword_level_file": "/home/pi/test_tones/okgoogle-ken_trim_6_repeat.wav", + "ok_google_samples_dir" : "/home/pi/ok_google_samples", + "hey_google_samples_dir" : "/home/pi/hey_google_samples", + "speaker_volume": "80", + "playout_config": { + "card_number": 1, + "device_number": 0 + }, + "recording_config": { + "card_number": 1, + "device_number": 0 + } + }, + "rpi_chirp": { + "host": "100.115.121.6", + "username": "pi", + "password": "casting", + "temp_dir": "/tmp", + "sound_meter_program": "python /home/pi/sound_meter/sound_meter.py", + "speaker_volume": "100", + "record_device": "sysdefault:CARD=1" + }, + "chirp": { + "host": "100.115.121.12" + } +} +
diff --git a/lab_system/master/config/tests/test_beds/latency_chirp_100_115_122_90.json b/lab_system/master/config/tests/test_beds/latency_chirp_100_115_122_90.json new file mode 100644 index 0000000..f4b6f62 --- /dev/null +++ b/lab_system/master/config/tests/test_beds/latency_chirp_100_115_122_90.json
@@ -0,0 +1,32 @@ +{ + "rpi_hotword": { + "host": "100.115.122.94", + "username": "pi", + "password": "casting", + "temp_dir": "/tmp", + "sound_meter_program": "python /home/pi/sound_meter/sound_meter.py", + "hotword_file": "/home/pi/test_tones/okgoogle-ken_trim.wav", + "hotword_level_file": "/home/pi/test_tones/okgoogle-ken_trim_6_repeat.wav", + "ok_google_samples_dir": "/home/pi/ok_google_samples", + "hey_google_samples_dir": "/home/pi/hey_google_samples", + "speaker_volume": "100", + "recording_config": { + "card_number": 1 + }, + "playout_config": { + "card_number": 1, + "device_number": 0 + } + }, + "rpi_chirp": { + "host": "100.115.122.94", + "username": "pi", + "password": "casting", + "temp_dir": "/tmp", + "sound_meter_program": "python /home/pi/sound_meter/sound_meter.py", + "speaker_volume": "100" + }, + "chirp": { + "host": "100.115.122.90" + } +}
diff --git a/lab_system/master/config/tests/test_beds/latency_imx7d_192_168_1_216.json b/lab_system/master/config/tests/test_beds/latency_imx7d_192_168_1_216.json new file mode 100644 index 0000000..eff831c --- /dev/null +++ b/lab_system/master/config/tests/test_beds/latency_imx7d_192_168_1_216.json
@@ -0,0 +1,27 @@ +{ + "rpi_hotword": { + "host": "192.168.1.114", + "username": "pi", + "password": "casting", + "temp_dir": "/tmp", + "sound_meter_program": "python /home/pi/sound_meter/sound_meter.py", + "hotword_file": "/home/pi/test_tones/okgoogle-ken_trim.wav", + "hotword_level_file": "/home/pi/test_tones/okgoogle-ken_trim_6_repeat.wav", + "ok_google_samples_dir" : "/home/pi/ok_google_samples", + "hey_google_samples_dir" : "/home/pi/hey_google_samples", + "speaker_volume": "100", + "record_device": "sysdefault:CARD=1" + }, + "rpi_chirp": { + "host": "192.168.1.114", + "username": "pi", + "password": "casting", + "tmp_dir": "/tmp", + "sound_meter_program": "python /home/pi/sound_meter/sound_meter.py", + "speaker_volume": "100", + "record_device": "sysdefault:CARD=1" + }, + "chirp": { + "host": "192.168.1.216" + } +}
diff --git a/lab_system/master/config/tests/test_beds/latency_joplin_100_115_122_91.json b/lab_system/master/config/tests/test_beds/latency_joplin_100_115_122_91.json new file mode 100644 index 0000000..fe11487 --- /dev/null +++ b/lab_system/master/config/tests/test_beds/latency_joplin_100_115_122_91.json
@@ -0,0 +1,27 @@ +{ + "rpi_hotword": { + "host": "100.115.122.95", + "username": "pi", + "password": "casting", + "temp_dir": "/tmp", + "sound_meter_program": "python /home/pi/sound_meter/sound_meter.py", + "hotword_file": "/home/pi/test_tones/okgoogle-ken_trim.wav", + "hotword_level_file": "/home/pi/test_tones/okgoogle-ken_trim_6_repeat.wav", + "ok_google_samples_dir" : "/home/pi/ok_google_samples", + "hey_google_samples_dir" : "/home/pi/hey_google_samples", + "speaker_volume": "100", + "record_device": "sysdefault:CARD=0" + }, + "rpi_chirp": { + "host": "100.115.122.95", + "username": "pi", + "password": "casting", + "temp_dir": "/tmp", + "sound_meter_program": "python /home/pi/sound_meter/sound_meter.py", + "speaker_volume": "100", + "record_device": "sysdefault:CARD=0" + }, + "chirp": { + "host": "100.115.122.91" + } +}
diff --git a/lab_system/master/config/tests/testingrepounittests/test_defs.json b/lab_system/master/config/tests/testingrepounittests/test_defs.json new file mode 100644 index 0000000..bc25aa7 --- /dev/null +++ b/lab_system/master/config/tests/testingrepounittests/test_defs.json
@@ -0,0 +1,92 @@ +[ + { + "group_name": "testingrepounittests", + "slave_name": "testingrepounittests", + "test_name": "testingrepounittests", + "branch": "master", + "device_type": "dummy", + "identifier": "testingrepounittests", + "step_factories": [ + { + "step_description": "Overrides property setting - not necessary for server", + "step_identifier": "properties", + "step_factories": [ + { + "module_path": "lab_system.master.steps.factory.common.noop", + "class_name": "NoopStepFactory" + } + ] + }, + { + "step_description": "Replaces device allocation with a no-op", + "step_identifier": "device_allocation", + "step_factories": [ + { + "module_path": "lab_system.master.steps.factory.common.noop", + "class_name": "NoopStepFactory" + } + ] + }, + { + "step_description": "Replaces build handling with a no-op", + "step_identifier": "build_handling", + "step_factories": [ + { + "module_path": "lab_system.master.steps.factory.common.noop", + "class_name": "NoopStepFactory" + } + ] + }, + { + "step_description": "Replaces testrun setup with a no-op", + "step_identifier": "testrun_setup", + "step_factories": [ + { + "module_path": "lab_system.master.steps.factory.common.noop", + "class_name": "NoopStepFactory" + } + ] + }, + { + "step_description": "Runs the unit tests", + "step_identifier": "test_running", + "step_factories": [ + { + "module_path": "lab_system.master.steps.factory.run.unit", + "class_name": "UnitTestRunnerStepFactory" + } + ] + }, + { + "step_description": "Copies logs to the Cloud Storage", + "step_identifier": "logs_copy", + "step_factories": [ + { + "module_path": "lab_system.master.steps.factory.output.cloud_logs", + "class_name": "CopyLogsToRepositoryStepFactory" + } + ] + }, + { + "step_description": "Replaces output processing with a no-op", + "step_identifier": "output_processing", + "step_factories": [ + { + "module_path": "lab_system.master.steps.factory.common.noop", + "class_name": "NoopStepFactory" + } + ] + }, + { + "step_description": "Replaces cleanup with a no-op", + "step_identifier": "testrun_cleanup", + "step_factories": [ + { + "module_path": "lab_system.master.steps.factory.common.noop", + "class_name": "NoopStepFactory" + } + ] + } + ] + } +]
diff --git a/lab_system/master/config/tests/thread/thread.cfg b/lab_system/master/config/tests/thread/thread.cfg new file mode 100644 index 0000000..4cc3964 --- /dev/null +++ b/lab_system/master/config/tests/thread/thread.cfg
@@ -0,0 +1,13 @@ +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.thread.thread_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=ThreadTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.framework.test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=TestSequence
diff --git a/lab_system/master/config/tests/time_bound_connectivity/time_bound_connectivity.cfg b/lab_system/master/config/tests/time_bound_connectivity/time_bound_connectivity.cfg new file mode 100644 index 0000000..acddcac --- /dev/null +++ b/lab_system/master/config/tests/time_bound_connectivity/time_bound_connectivity.cfg
@@ -0,0 +1,19 @@ +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.time_bound_connectivity.time_bound_connectivity_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=TimeBoundConnectivityTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.time_bound_connectivity.time_bound_connectivity_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=TimeBoundConnectivityTestSequence + +# Devices metadata +SSID=test_wifi_setup +PSK=password + +
diff --git a/lab_system/master/config/tests/uma_logging/mpl/test_defs.json b/lab_system/master/config/tests/uma_logging/mpl/test_defs.json new file mode 100644 index 0000000..e8e050d --- /dev/null +++ b/lab_system/master/config/tests/uma_logging/mpl/test_defs.json
@@ -0,0 +1,38 @@ +[ + { + "group_name": "uma_logging", + "slave_name": "uma_logging_mpl", + "test_name": "uma_logging_mpl", + "identifier": "uma_logging_mpl", + "device_type": "eureka", + "device_group": "eureka_background_tab_enabled", + "branch": ["master", "release"] + }, + { + "group_name": "uma_logging", + "slave_name": "uma_logging_mpl", + "test_name": "uma_logging_mpl", + "identifier": "uma_logging_mpl_v2", + "device_type": "lexx", + "device_group": "lexx_background_tab_enabled", + "branch": ["master", "release"] + }, + { + "group_name": "uma_logging", + "slave_name": "uma_logging_mpl", + "test_name": "uma_logging_mpl", + "identifier": "uma_logging_mpl_v3", + "device_type": "earth", + "device_group": "earth_background_tab_enabled", + "branch": ["master", "release"] + }, + { + "group_name": "uma_logging", + "slave_name": "uma_logging_mpl", + "test_name": "uma_logging_mpl", + "identifier": "uma_logging_mpl_hendrix", + "device_type": "hendrix", + "device_group": "hendrix_background_tab_enabled", + "branch": ["master", "release"] + } +]
diff --git a/lab_system/master/config/tests/uma_logging/test_defs.json b/lab_system/master/config/tests/uma_logging/test_defs.json new file mode 100644 index 0000000..ba10674 --- /dev/null +++ b/lab_system/master/config/tests/uma_logging/test_defs.json
@@ -0,0 +1,84 @@ +[ + { + "group_name": "uma_logging", + "slave_name": "uma_logging", + "test_name": "uma_logging", + "identifier": "uma_logging", + "device_type": "eureka", + "device_group": "eureka_background_tab_enabled", + "branch": ["master", "release"] + }, + { + "group_name": "uma_logging", + "slave_name": "uma_logging", + "test_name": "uma_logging", + "identifier": "uma_logging_v2", + "device_type": "lexx", + "device_group": "lexx_background_tab_enabled", + "branch": ["master", "release"] + }, + { + "group_name": "uma_logging", + "slave_name": "uma_logging", + "test_name": "uma_logging", + "identifier": "uma_logging_v3", + "device_type": "earth", + "device_group": "earth_background_tab_enabled", + "branch": ["master", "release"] + }, + { + "group_name": "uma_logging", + "slave_name": "uma_logging", + "test_name": "uma_logging", + "identifier": "uma_logging_hendrix", + "device_type": "hendrix", + "device_group": "hendrix_background_tab_enabled", + "branch": ["master", "release"] + }, + { + "group_name": "uma_logging", + "slave_name": "uma_logging", + "test_name": "uma_logging_multizone", + "identifier": "uma_logging_multizone", + "device_type": "hendrix", + "device_group": "multizone_wifi1", + "num_devices": "4", + "scheduler": "0 0,12 * * *", + "branch": ["next_release"], + "step_factories": [ + { + "step_description": "Allocates devices for the testrun", + "step_identifier": "device_allocation", + "step_factories": [ + { + "module_path": "lab_system.master.steps.factory.device.cloud_allocator", + "class_name": "StrictDeviceAllocatorStepFactory" + } + ] + } + ] + }, + { + "group_name": "uma_logging", + "slave_name": "uma_logging", + "test_name": "uma_logging_multizone", + "identifier": "uma_logging_multizone", + "device_type": "hendrix", + "device_group": "multizone_wifi1", + "num_devices": "4", + "scheduler": "0 6,18 * * *", + "branch": ["master"], + "step_factories": [ + { + "step_description": "Allocates devices for the testrun", + "step_identifier": "device_allocation", + "step_factories": [ + { + "module_path": "lab_system.master.steps.factory.device.cloud_allocator", + "class_name": "StrictDeviceAllocatorStepFactory" + } + ] + } + ] + } +]
diff --git a/lab_system/master/config/tests/uma_logging/uma_logging.cfg b/lab_system/master/config/tests/uma_logging/uma_logging.cfg new file mode 100644 index 0000000..2ca6fc6 --- /dev/null +++ b/lab_system/master/config/tests/uma_logging/uma_logging.cfg
@@ -0,0 +1,27 @@ +# Config file for the uma logging tests +# +# Do not modify property names +# Run make reconfig if you change a value +# and buildbot is running +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.uma_logging.uma_logging_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=UmaLoggingTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.uma_logging.uma_logging_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=UmaLoggingTestSequence + +# App Ids for Testing +BG1_APP_ID=F05C50C9 +BG2_APP_ID=C566BECD +BACKDROP_APP_ID=E8C28D3C + +# Platform names +CHROMECAST_AUDIO_PLATFORM=hendrix
diff --git a/lab_system/master/config/tests/uma_logging/uma_logging_mpl.cfg b/lab_system/master/config/tests/uma_logging/uma_logging_mpl.cfg new file mode 100644 index 0000000..6a5f6db --- /dev/null +++ b/lab_system/master/config/tests/uma_logging/uma_logging_mpl.cfg
@@ -0,0 +1,22 @@ +# Config file for the uma logging tests for MPL. +# +# Do not modify property names +# Run make reconfig if you change a value +# and buildbot is running +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.uma_logging.uma_logging_mpl_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=UmaLoggingMplTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.uma_logging.uma_logging_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=UmaLoggingTestSequence + +# Platform names +CHROMECAST_AUDIO_PLATFORM=hendrix
diff --git a/lab_system/master/config/tests/uma_logging/uma_logging_multizone.cfg b/lab_system/master/config/tests/uma_logging/uma_logging_multizone.cfg new file mode 100644 index 0000000..0e7cd35 --- /dev/null +++ b/lab_system/master/config/tests/uma_logging/uma_logging_multizone.cfg
@@ -0,0 +1,25 @@ +# Config file for the uma logging tests +# +# Do not modify property names +# Run make reconfig if you change a value +# and buildbot is running +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.uma_logging.uma_logging_multizone_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=UmaLoggingMultizoneLeaderTestCase,UmaLoggingMultizoneFollowerTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.multizone.test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=MultizoneTestSequence + +# Parameters for the media file to use for playback. +MEDIA_URL=https://storage.googleapis.com/cast_media/crt_files/SarabandefromPartitaNo.1InBMinor.mp3 +MEDIA_MIME_TYPE=audio/mp3 + +NETWORK_SWITCH_CONFIG_FILENAME=../multizone/hp_procurve_switch_config.json
diff --git a/lab_system/master/config/tests/uma_logging_wifi/test_defs.json b/lab_system/master/config/tests/uma_logging_wifi/test_defs.json new file mode 100644 index 0000000..de361e3 --- /dev/null +++ b/lab_system/master/config/tests/uma_logging_wifi/test_defs.json
@@ -0,0 +1,56 @@ +[ + { + "group_name": "uma_logging_wifi", + "slave_name": "uma_logging_wifi", + "test_name": "uma_logging_wifi", + "identifier": "uma_logging_wifi", + "device_type": "eureka", + "device_group": "eureka_wifi", + "branch": ["master", "release"] + }, + { + "group_name": "uma_logging_wifi", + "slave_name": "uma_logging_wifi_v2", + "test_name": "uma_logging_wifi", + "identifier": "uma_logging_wifi_v2", + "device_type": "lexx", + "device_group": "lexx_wifi", + "branch": ["master", "release"] + }, + { + "group_name": "uma_logging_wifi", + "slave_name": "uma_logging_wifi", + "test_name": "uma_logging_wifi", + "identifier": "uma_logging_wifi_v3", + "device_type": "earth", + "device_group": "earth_wifi", + "branch": ["master", "release"] + }, + { + "group_name": "uma_logging_wifi", + "slave_name": "uma_logging_wifi", + "test_name": "uma_logging_wifi", + "identifier": "uma_logging_wifi_hendrix", + "device_type": "hendrix", + "device_group": "hendrix_wifi", + "branch": ["master", "release"] + }, + { + "group_name": "uma_logging_wifi", + "slave_name": "uma_logging_wifi", + "test_name": "uma_logging_wifi", + "identifier": "uma_logging_wifi_chirp", + "device_type": "chirp", + "device_group": "chirp_wifi", + "branch": ["master", "release"] + }, + { + "group_name": "uma_logging_wifi", + "slave_name": "uma_logging_wifi", + "test_name": "uma_logging_wifi", + "identifier": "uma_logging_wifi_v4", + "device_type": "luther_b2", + "device_group": "luther_wifi", + "branch": ["master", "release"] + } +]
diff --git a/lab_system/master/config/tests/uma_logging_wifi/uma_logging_wifi.cfg b/lab_system/master/config/tests/uma_logging_wifi/uma_logging_wifi.cfg new file mode 100644 index 0000000..f5cf7e2 --- /dev/null +++ b/lab_system/master/config/tests/uma_logging_wifi/uma_logging_wifi.cfg
@@ -0,0 +1,23 @@ +# Config file for the uma logging wifi tests: +# Those test cases will rely on devices with only wifi connection. +# +# Do not modify property names +# Run make reconfig if you change a value +# and buildbot is running +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.uma_logging.uma_logging_wifi_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=UmaLoggingWifiTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.uma_logging.uma_logging_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=UmaLoggingTestSequence + +AP_MAC=10:0D:7F:51:76:72 +CHANNEL=1
diff --git a/lab_system/master/config/tests/unit_test/chromium.cfg b/lab_system/master/config/tests/unit_test/chromium.cfg new file mode 100644 index 0000000..9845432 --- /dev/null +++ b/lab_system/master/config/tests/unit_test/chromium.cfg
@@ -0,0 +1,4 @@ +#Configuration file for Chromium test suites. +TEST_NAME=Chromium Unit Tests +ENABLE_FILTER_LIST=True +EXCLUDE_SUITES_IN_LIST=True
diff --git a/lab_system/master/config/tests/unit_test/internal.cfg b/lab_system/master/config/tests/unit_test/internal.cfg new file mode 100644 index 0000000..34df576 --- /dev/null +++ b/lab_system/master/config/tests/unit_test/internal.cfg
@@ -0,0 +1,4 @@ +#Configuration file for internal test suites. +TEST_NAME=Chromecast Unit Tests +ENABLE_FILTER_LIST=True +EXCLUDE_SUITES_IN_LIST=False
diff --git a/lab_system/master/config/tests/unit_test/internal_camera.cfg b/lab_system/master/config/tests/unit_test/internal_camera.cfg new file mode 100644 index 0000000..029420f --- /dev/null +++ b/lab_system/master/config/tests/unit_test/internal_camera.cfg
@@ -0,0 +1,5 @@ +#Configuration file for internal test suites. +TEST_NAME=Chromecast Unit Tests +ENABLE_FILTER_LIST=True +EXCLUDE_SUITES_IN_LIST=False +LD_PATH=/chrome/lib
diff --git a/lab_system/master/config/tests/unit_test/internal_mclean.cfg b/lab_system/master/config/tests/unit_test/internal_mclean.cfg new file mode 100644 index 0000000..1822c3e --- /dev/null +++ b/lab_system/master/config/tests/unit_test/internal_mclean.cfg
@@ -0,0 +1,4 @@ +#Configuration file for internal test suites. Different group. +TEST_NAME=Chromecast Unit Tests +ENABLE_FILTER_LIST=True +EXCLUDE_SUITES_IN_LIST=False
diff --git a/lab_system/master/config/tests/video_formats/video_formats.cfg b/lab_system/master/config/tests/video_formats/video_formats.cfg new file mode 100644 index 0000000..2d6ee5a --- /dev/null +++ b/lab_system/master/config/tests/video_formats/video_formats.cfg
@@ -0,0 +1,15 @@ +# Config file for JavaScript video format tests. +# +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.video_formats.video_formats_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=SupportedVideoFormatsTestCase,SupportedFormatCombinationsTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.framework.javascript_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=JavascriptTestSequence + +
diff --git a/lab_system/master/config/tests/video_formats/video_formats_4k.cfg b/lab_system/master/config/tests/video_formats/video_formats_4k.cfg new file mode 100644 index 0000000..b9f5177 --- /dev/null +++ b/lab_system/master/config/tests/video_formats/video_formats_4k.cfg
@@ -0,0 +1,15 @@ +# Config File for JavaScript UHD 4K Video Format Tests. +# +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.video_formats.video_formats_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=SupportedUHD4KVideoFormatsTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.framework.javascript_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=JavascriptTestSequence + +
diff --git a/lab_system/master/config/tests/video_formats/video_formats_dv.cfg b/lab_system/master/config/tests/video_formats/video_formats_dv.cfg new file mode 100644 index 0000000..94071f2 --- /dev/null +++ b/lab_system/master/config/tests/video_formats/video_formats_dv.cfg
@@ -0,0 +1,15 @@ +# Config File for JavaScript Dolby Vision Format Tests. +# +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.video_formats.video_formats_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=SupportedDolbyVisionFormatsTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.framework.javascript_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=JavascriptTestSequence + +
diff --git a/lab_system/master/config/tests/video_rotation_playback/video_rotation_playback.cfg b/lab_system/master/config/tests/video_rotation_playback/video_rotation_playback.cfg new file mode 100644 index 0000000..d7d08b9 --- /dev/null +++ b/lab_system/master/config/tests/video_rotation_playback/video_rotation_playback.cfg
@@ -0,0 +1,15 @@ +# Config file for video rotation tests. +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.video_rotation.video_rotation_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=VideoRotationPlaybackTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.framework.javascript_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=JavascriptTestSequence
diff --git a/lab_system/master/config/tests/video_rotation_playback/video_rotation_playback/test_defs.json b/lab_system/master/config/tests/video_rotation_playback/video_rotation_playback/test_defs.json new file mode 100644 index 0000000..c4205ce --- /dev/null +++ b/lab_system/master/config/tests/video_rotation_playback/video_rotation_playback/test_defs.json
@@ -0,0 +1,32 @@ +[ + { + "group_name": "video_rotation_playback", + "slave_name": "video_rotation_playback", + "test_name": "video_rotation_playback", + "identifier": "video_rotation_playback", + "device_type": ["eureka", "lexx", "earth", "luther_b2"], + "device_group": "av_drm", + "branch": ["master", "release", "next_release"] + }, + { + "group_name": "video_rotation_playback", + "slave_name": "video_rotation_playback", + "test_name": "video_rotation_playback", + "identifier": "video_rotation_playback_entourage", + "device_type": "dragonfly", + "device_group": "entourage", + "hidden": "true", + "branch": "cast_tv_dragonfly_master" + }, + { + "group_name": "video_rotation_playback", + "slave_name": "video_rotation_playback", + "test_name": "video_rotation_playback", + "identifier": "video_rotation_playback_prod", + "device_type": ["eureka", "lexx"], + "device_group": "av_drm", + "branch": "on_demand", + "hidden": "true", + "scheduler": "0 3 * * *" + } +]
diff --git a/lab_system/master/config/tests/volume/atv_volume.cfg b/lab_system/master/config/tests/volume/atv_volume.cfg new file mode 100644 index 0000000..676fe96 --- /dev/null +++ b/lab_system/master/config/tests/volume/atv_volume.cfg
@@ -0,0 +1,15 @@ +# Config file for Android TV volume tests. +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.volume.atv_volume_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=VolumeTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.framework.android_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=AndroidTestSequence \ No newline at end of file
diff --git a/lab_system/master/config/tests/volume/fuchsia_volume.cfg b/lab_system/master/config/tests/volume/fuchsia_volume.cfg new file mode 100644 index 0000000..2ec207c --- /dev/null +++ b/lab_system/master/config/tests/volume/fuchsia_volume.cfg
@@ -0,0 +1,17 @@ +# Config file for JavaScript video tests on Fuchsia devices. +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.volume.volume_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=VolumeTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.framework.fuchsia_javascript_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=FuchsiaJavascriptTestSequence + +
diff --git a/lab_system/master/config/tests/volume/test_defs.json b/lab_system/master/config/tests/volume/test_defs.json new file mode 100644 index 0000000..2373cf9 --- /dev/null +++ b/lab_system/master/config/tests/volume/test_defs.json
@@ -0,0 +1,11 @@ +[ + { + "group_name": "volume", + "slave_name": "volume", + "test_name": "volume", + "identifier": "volume_cast_tv", + "device_type": "dragonfly", + "device_group": "av_drm", + "branch": ["cast_tv_dragonfly_master", "cast_tv_dragonfly_release", "cast_tv_dragonfly_next_release"] + } +]
diff --git a/lab_system/master/config/tests/volume/volume.cfg b/lab_system/master/config/tests/volume/volume.cfg new file mode 100644 index 0000000..7ed8b1f --- /dev/null +++ b/lab_system/master/config/tests/volume/volume.cfg
@@ -0,0 +1,17 @@ +# Config file for JavaScript video tests. +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.volume.volume_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=VolumeTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.framework.javascript_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=JavascriptTestSequence + +
diff --git a/lab_system/master/config/tests/webgl_conformance/test_defs.json b/lab_system/master/config/tests/webgl_conformance/test_defs.json new file mode 100644 index 0000000..367a9b2 --- /dev/null +++ b/lab_system/master/config/tests/webgl_conformance/test_defs.json
@@ -0,0 +1,47 @@ +[ + { + "group_name": "webgl_conformance", + "slave_name": "webgl_conformance", + "test_name": "webgl_conformance", + "identifier": "webgl_conformance", + "device_type": "eureka", + "device_group": "eureka_debug", + "branch": ["master", "release"] + }, + { + "group_name": "webgl_conformance", + "slave_name": "webgl_conformance_v2", + "test_name": "webgl_conformance", + "identifier": "webgl_conformance_v2", + "device_type": "lexx", + "device_group": "lexx_eth", + "branch": ["master", "release"] + }, + { + "group_name": "webgl_conformance", + "slave_name": "webgl_conformance_v3", + "test_name": "webgl_conformance", + "identifier": "webgl_conformance_v3", + "device_type": "earth", + "device_group": "earth_eth", + "branch": ["master", "release"] + }, + { + "group_name": "webgl_conformance", + "slave_name": "webgl_conformance_v4", + "test_name": "webgl_conformance", + "identifier": "webgl_conformance_v4", + "device_type": "luther_b2", + "device_group": "luther_eth", + "branch": ["master", "release"] + }, + { + "group_name": "webgl_conformance", + "slave_name": "webgl_conformance_v3", + "test_name": "webgl_conformance", + "identifier": "webgl_conformance_entourage", + "device_type": "dragonfly", + "device_group": "entourage", + "branch": "cast_tv_dragonfly_master" + } +]
diff --git a/lab_system/master/config/tests/webgl_conformance/webgl_conformance.cfg b/lab_system/master/config/tests/webgl_conformance/webgl_conformance.cfg new file mode 100644 index 0000000..356f47d --- /dev/null +++ b/lab_system/master/config/tests/webgl_conformance/webgl_conformance.cfg
@@ -0,0 +1,25 @@ +# Config file for the WebGL conformance tests. +# +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.webgl_conformance.webgl_conformance_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=WebGLConformanceTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.framework.javascript_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=JavascriptTestSequence + +# Path in the media server (relative to continuous-tests/src) to the +# WebGL conformance suite text file specifying tests to run +WEBGL_CONFORMANCE_SUITE_PATH=tests/webgl-conformance-suites/1.0.1/00_test_list.txt + +# Version of WebGL conformance tests +WEBGL_CONFORMANCE_VERSION=1.0.1 + +# Comma-separated list of regular expressions to match the tests to skip. +SKIPPED_TESTS=premultiplyalpha-test,gl-pixelstorei,tex-image-and-sub-image-2d-with-video,texture-npot-video
diff --git a/lab_system/master/config/tests/wifi_interface_connectivity/wifi_interface_connectivity.cfg b/lab_system/master/config/tests/wifi_interface_connectivity/wifi_interface_connectivity.cfg new file mode 100644 index 0000000..88b47d2 --- /dev/null +++ b/lab_system/master/config/tests/wifi_interface_connectivity/wifi_interface_connectivity.cfg
@@ -0,0 +1,13 @@ +# PROPERTIES +# +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.setup_api_wifi.wifi_interface_connectivity_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=WifiInterfaceConnectivityTestCase,WifiInterfaceRebootTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.setup_api_wifi.wifi_interface_connectivity_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=WifiConnectivityTestSequence
diff --git a/lab_system/master/config/tests/wifi_multiconfig/wifi_multiconfig.cfg b/lab_system/master/config/tests/wifi_multiconfig/wifi_multiconfig.cfg new file mode 100644 index 0000000..d16fa33 --- /dev/null +++ b/lab_system/master/config/tests/wifi_multiconfig/wifi_multiconfig.cfg
@@ -0,0 +1,19 @@ +# PROPERTIES + +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.wifi_multiconfig.wifi_multiconfig_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=WiFiMultiConfigTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.wifi_multiconfig.wifi_multiconfig_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=WiFiMultiConfigTestSequence + +# Numbers of random configurations to run +ITERATIONS_COUNT=4 + + +
diff --git a/lab_system/master/config/tests/wifi_security_type/wifi_security_type.cfg b/lab_system/master/config/tests/wifi_security_type/wifi_security_type.cfg new file mode 100644 index 0000000..0ee3847 --- /dev/null +++ b/lab_system/master/config/tests/wifi_security_type/wifi_security_type.cfg
@@ -0,0 +1,13 @@ +# PROPERTIES +# +# Dot-notation path to the module containing the TestCase class: +TEST_CASE_MODULE=eurtest.tests.setup_api_wifi.wifi_security_type_test_case + +# Name of the TestCase sub-class: +TEST_CASE_CLASS=WifiSecurityTypeTestCase + +# Dot-notation path to the module containing the TestSequence class: +TEST_SEQUENCE_MODULE=eurtest.tests.setup_api_wifi.wifi_interface_connectivity_test_sequence + +# Name of the TestSequence sub-class: +TEST_SEQUENCE_CLASS=WifiConnectivityTestSequence
diff --git a/lab_system/update_fr.sh b/lab_system/update_fr.sh new file mode 100755 index 0000000..2bfb5eb --- /dev/null +++ b/lab_system/update_fr.sh
@@ -0,0 +1,58 @@ +#!/bin/bash +# Copyright 2013 Google Inc. All Rights Reserved. +# Author: billiani@google.com (Leonardo Billiani) +# +# Script to update repositories and FR. +# It assumes all the repositories are in the same root directory + +ACTION=$1 +SERVER=$2 +REPOSITORY_PATH=$3 +FR_DIRECTORY=$4 +FR_CONFIG_DIRECTORY=$5 +EXPECTED_ARGS=5 + +function usage { + echo "Usage: $0 <restart|reconfig> <server> <repository_path> <fr_directory> <fr_config_directory>" + echo " restart|reconfig : 'restart' will restart the master and slaves." + echo " 'reconfig' will update the master." + echo " Use reconfig when no changes to sequences have been made." + echo " server : Server name to update." + echo " repository_path : Root Location of all repositories to update." + echo " fr_directory : Path to fr installation" + echo " fr_config_directory : Path to fr config directory" +} + +if [ $# -lt $EXPECTED_ARGS ] +then + usage + exit 0 +fi +if [ $ACTION != 'restart' -a $ACTION != 'reconfig' ] +then + usage + exit 0 +fi + +# Update repositories and do not output stdout +source $HOME/.bashrc +for repository in 'test' 'continuous-tests' 'autotest' 'fragglerock' 'chromite/chromite' 'chromium/src' +do + cd $REPOSITORY_PATH/$repository && /usr/bin/git clean -f -d -x 1> /dev/null && /usr/bin/git fetch 1> /dev/null && /usr/bin/git reset --hard FETCH_HEAD 1> /dev/null +done + +if [ $ACTION = 'restart' ] +then + # Stop all the slaves to return all the devices + echo "Stopping the slaves" + curl http://$SERVER:8010/builders/_all/stopall + sleep 10 +fi +cd $REPOSITORY_PATH/test && . ./setup_env.sh $FR_CONFIG_DIRECTORY +PYTHONPATH=$PYTHONPATH:/usr/local/autotest +cd $FR_DIRECTORY/buildbot/master && $FR_DIRECTORY/python-sandbox/bin/buildbot $ACTION +if [ $ACTION = 'restart' ] +then + # Start all the slaves after the restart + curl http://$SERVER:8010/builders/_all/forceall +fi
diff --git a/lib/Makefile b/lib/Makefile new file mode 100644 index 0000000..3f27d3e --- /dev/null +++ b/lib/Makefile
@@ -0,0 +1,48 @@ +# Makefile to create & manage python pip packages. +# +# Currently this only supports a single package but we can extend that similar +# to https://eureka-internal.git.corp.google.com/fragglerock/+/master/Makefile +# +# Clean the generated files +# $ make clean +# +# Create the pip package +# $ make dist +# +# Deploy the package. Note you must be in the cast-test mdb and have valid loas +# credentials to deploy. +# $ make deploy +# +# Or just run make to deploy everything +# $ make + +# The hostname where this file is being run. +HOST=$(shell hostname) + +# The current folder. +CWD=$(shell pwd) + +DEPLOYDIR=/cns/pf-d/home/cast-test/media/static/packages/ +PIP_TOOL=/google/data/ro/teams/chromecast/platform/tools/update_pip.par + +all: deploy + +clean: + rm -rf $(CWD)/dist + rm -rf $(CWD)/*.egg-info + +dist: + python setup.py sdist + +copy_package: + fileutil cp -f \ + $(CWD)/dist/* \ + $(DEPLOYDIR) \ + --gfs_user cast-test + +update_repo: + $(PIP_TOOL) --nodry_run \ + --package home-monitoring \ + --environment prod + +deploy: dist copy_package update_repo clean
diff --git a/lib/README.md b/lib/README.md new file mode 100644 index 0000000..4e628e1 --- /dev/null +++ b/lib/README.md
@@ -0,0 +1,17 @@ +# Home Libraries + +A collection of shared libraries used across home infrastructure that can be +deployed via pip packages. + +## Versioning + +Currently we have no set versioning scheme. If we make fundamentally breaking +changes that would require a refactor we should update the minor version number. + +## Adding new libs + +1. Refactor the home dir into another sub dir - home-monitoring - and include + the setup.py file in that folders root +2. Create the equivalent folder structure for the new lib +3. Update the Makefile as described to include multiple packages +4. Update these instructions
diff --git a/lib/__init__.py b/lib/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/lib/__init__.py
diff --git a/lib/home/__init__.py b/lib/home/__init__.py new file mode 100644 index 0000000..a232304 --- /dev/null +++ b/lib/home/__init__.py
@@ -0,0 +1,3 @@ +"""Declare namespace for shared packages.""" + +__import__('pkg_resources').declare_namespace(__name__)
diff --git a/lib/home/monitoring/__init__.py b/lib/home/monitoring/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/lib/home/monitoring/__init__.py
diff --git a/lib/home/monitoring/cloud_logging.py b/lib/home/monitoring/cloud_logging.py new file mode 100644 index 0000000..2f20930 --- /dev/null +++ b/lib/home/monitoring/cloud_logging.py
@@ -0,0 +1,640 @@ +"""Module for recording metrics and uploading to Google Cloud Logging. + +There are 3 methods of logging: +1) Stackdriver / Cloud Logging API +2) Local Logging +3) Fluentd Agent + +Setup: + 1) Stackdriver / Cloud Logging API, during application setup you should call: + + project_name = 'google.com:cast-cq-staging' + logger_name = 'cast_cq.master' + cloud_logging.ConfigureLogger(project_name, logger_name) + + 2) Local Logging, this is used by default if you do not configure the cloud + logger or enable the fluentd logger + + 3) For Fluentd Agent, during application setup you should call: + + namespace = "buildbot" + host = "127.0.0.0" + port = 24224 + cloud_logging.EnableFluentdLogger(namespace, host, port) + + There are few caveats when using the fluentd agent: + - The Google Cloud project will be inferred by the agent (either by explicitly + setting the project in the configuration or implicitly by the IAM Role) + that's how it determines which project to upload the logs to. + - Since we're using a version of the Google Cloud agent, it assumes that the + host it's running on is a GCE instance (which it may not). The consequence + of this is that the logs will be grouped into a GCE resource log like + "GCE VM Instance, <id>" and NOT "Global" + - Severity is ignored when using the agent + - Additional labels are also not passed to the agent + +Usage: + Then, throughout your application, you can use: + + import cloud_logging + + t = cloud_logging.Timer('test_timer').Start() + # do something interesting... + t.Stop() + + with cloud_logging.Timer('test_timer') as t: + # do something interesting... + t.AddAttribute('a', 'b') + + ev = cloud_logging.LogEvent('test_msg', value='Something to log').Log() + cloud_logging.Info('info_message', value='Something to log').Log() + cloud_logging.Error('error_message', value='Something to log').Log() +""" +import atexit +import logging +import os +import socket +import threading +import time +import traceback + +from fluent import event as fluentd_event +from fluent import sender as fluentd # TODO(b/70284159): switch to asyncsender + +from google.cloud import logging as gcl # pylint: disable=ungrouped-imports +from google.gax import errors +from google.gax import grpc +from google.protobuf import json_format +import six + +# Subset of supported severity levels: +# https://cloud.google.com/logging/docs/api/reference/rest/v2/LogEntry#LogSeverity +DEBUG = 'DEBUG' +INFO = 'INFO' +WARNING = 'WARNING' +ERROR = 'ERROR' + +SEVERITY_LEVELS = [DEBUG, INFO, WARNING, ERROR] +# Global instances of configured cloud client/loggers +_GLOBAL_CLIENT = None +_GLOBAL_LOGGER = None +_GLOBAL_THREAD = None +_GLOBAL_LABELS = {} + + +class BaseError(Exception): + """Base error.""" + + +class ConfigurationError(BaseError): + """Base error for invalid log configurations.""" + + +class EventError(BaseError): + """Base error for Metrics.""" + + +class TimerError(BaseError): + """Base error for Timers.""" + + +class StrictAttributesError(BaseError): + """Base Error for StrictAttributes decorator.""" + + +class LoggerError(BaseError): + """Base error for errors raised in logger.""" + + def __init__(self, original_error): + super(LoggerError, self).__init__(self) + self.original_error = original_error + self.original_trace = traceback.format_exc() + + def __str__(self): + return self.original_trace + + +class LoggerGaxError(LoggerError): + """Class for gax errors raised in logger.""" + + +class LogEvent(object): + """A high level LogEvent class used for logging events and data.""" + + def __init__(self, name, attributes=None, value=None, severity=None): + """Initialize a LogEvent. + + Args: + name: The name of the event being timed. + attributes: A dict representing attributes to be recorded with this timer. + value: A value to include in the Metric. + severity: A string representing the log severity. One of: + 'DEBUG', 'INFO', 'WARNING', 'ERROR' or None. + """ + self._name = self._Sanitize(name) + self._attributes = {} + if not attributes: + attributes = {} + self.AddAttributes(attributes) + self._host = socket.getfqdn() + self._recorded_at = self._Now() + self._logged = False + self._value = self._Sanitize(value) + self._type = 'general' + self._severity = severity + + @property + def type(self): + """Returns the type of event.""" + return self._type + + @property + def value(self): + """Returns the value for this event.""" + return self._value + + @value.setter + def value(self, value): + """Sets the value for this event.""" + self._value = self._Sanitize(value) + + @property + def severity(self): + """Returns the severity of event.""" + return self._severity + + @severity.setter + def severity(self, severity): + """Sets the severity of this event. + + Only valid severity values will be accepted, all others will fail silently. + + Args: + severity: A string representing the log severity. One of: + 'DEBUG', 'INFO', 'WARNING', 'ERROR' or None. + """ + self._severity = None + if severity in SEVERITY_LEVELS: + self._severity = severity + + @property + def recorded_at(self): + """Get the timestamp for when this event was recorded.""" + return self._recorded_at + + @property + def name(self): + return self._name + + @property + def host(self): + return self._host + + @property + def attributes(self): + return self._attributes + + def _Sanitize(self, value): + """Sanitizes arguments so they can be uploaded to GCL. + + If it is a supported primitive that will be returned, otherwise its str + representation will be used. + + This will also iterate through lists & dicts and sanitize their values. + + Args: + value: The value to sanitize. + + Returns: + The sanitized version of value. + """ + if isinstance(value, (six.integer_types, float, bool)): + return value + if isinstance(value, list): + return [self._Sanitize(v) for v in value] + if isinstance(value, dict): + return {self._Sanitize(key): self._Sanitize(v) + for key, v in six.iteritems(value)} + try: + return str(value) + except Exception as e: # pylint: disable=broad-except + return 'Could not sanitize object of type %s: %s' % (type(value), e) + + def AddAttributes(self, attributes): + """Add more attributes to the event. + + Args: + attributes: A dict of attributes to add to the current attribute list. + They will override other attributes with the same keys. + + Returns: + self. + """ + if not attributes: + return self + for key, value in six.iteritems(attributes): + self.AddAttribute(key, value) + return self + + def AddAttribute(self, name, value): + """Add a single attribute to the event. + + Args: + name: The key to be used in the attribute dict. + value: The value to put for the given key. Note, if the key already + existed its value will be overridden. + + Returns: + self. + """ + self._attributes[self._Sanitize(name)] = self._Sanitize(value) + return self + + def AsDict(self): + """Returns a dictionary representation of this event.""" + result = { + 'name': self.name, + 'recorded_at_utc_usec': self.recorded_at, + 'value': self.value, + 'type': self.type, + 'host': self.host, + 'attributes': self.attributes + } + return result + + def Valid(self): + """Returns if this event is valid.""" + return True + + def Log(self): + """Log this event. + + Raises: + EventError: If the event is invalid. + """ + if not self.Valid(): + raise EventError('Event not valid.') + if not self._logged: + _SendEvent(self, severity=self._severity) + self._logged = True + + def _Now(self): + """Returns the UTC usec timestamp for now.""" + return time.time() * 1000 * 1000 + + +class Timer(LogEvent): + """A simpler timer object to record & log the duration of something.""" + + def __init__(self, name, attributes=None, severity=None): + """Initialize a timer. + + Remember to call Start() to begin timing. + + Args: + name: The name of the event being timed. + attributes: A dict representing attributes to be recorded with this timer. + severity: A string representing the log severity. One of: + 'DEBUG', 'INFO', 'WARNING', 'ERROR' or None. + """ + super(Timer, self).__init__(name, attributes=attributes, severity=severity) + self._started_at = None + self._finished_at = None + self._type = 'timer' + + def Start(self): + """Starts the timer. + + Returns: + self. + """ + self._started_at = self._Now() + return self + + def Stop(self): + """Stops the timer and records the result. + + Note that the timer must have been started. + + Returns: + self. + + Raises: + TimerError: If the timer has not yet been started. + """ + if not self.started: + raise TimerError('Timer not yet started.') + self._finished_at = self._Now() + self.Log() + return self + + @property + def started(self): + """Returns boolean if this timer has been started.""" + return self._started_at is not None + + @property + def finished(self): + """Returns boolean if this timer has been completed.""" + return self._finished_at is not None + + def Time(self): + """Returns the value recorded by this timer. + + Returns: + The timed value. + + Raises: + TimerError: If the timer has not been started or completed. + """ + if not self.started: + raise TimerError('Timer not yet started.') + if not self.finished: + raise TimerError('Timer not yet finished.') + return self._finished_at - self._started_at + + @property + def value(self): + return self.Time() + + @property + def recorded_at(self): + return self._finished_at + + def Valid(self): + try: + self.Time() + return True + except TimerError: + return False + + def __enter__(self): + self.Start() + return self + + def __exit__(self, *args): + self.Stop() + + +class StrictAttributes(object): + """Decorator for LogEvents that require a fixed set of attributes. + + This decorator should be used when collecting metrics to be uploaded to + BigQuery. All attributes to be collected must be included in valid_attributes, + mapped to their default values. Any valid_attributes not added before Log() + will be included with the specified default value. + + Sample Usage: + + VALID_ATTRIBUTES = { + 'status': StrictAttributes.DEFAULT_STRING, + 'count': StrictAttributes.DEFAULT_INT } + + @StrictAttributes(VALID_ATTRIBUTES) + class MyLogger(Timer): + ... + """ + # TODO(adrexler): Migrate valid_attributes to protobuf. + + # Default values for all accepted attribute datatypes. + DEFAULT_STRING = '' + DEFAULT_BOOL = False + DEFAULT_LIST = [] + DEFAULT_DICT = {} + DEFAULT_INT = -1 + DEFAULT_FLOAT = float(DEFAULT_INT) + try: + DEFAULT_LONG = long(DEFAULT_INT) + except NameError: + DEFAULT_LONG = int(DEFAULT_INT) # pylint: disable=redefined-variable-type + + def __init__(self, valid_attributes): + """Constructor. + + Args: + valid_attributes: All acceptable attributes, mapped to default values. + """ + self._valid_attributes = valid_attributes + + def __call__(self, cls, *args, **kwargs): + """Returns MetricsCollector class, extending cls.""" + if not issubclass(cls, LogEvent): + raise StrictAttributesError('%s does not extend LogEvent!', cls) + valid_attributes = self._valid_attributes + + class MetricsCollector(cls): + """Extension of LogEvent child cls, with strict attributes.""" + + def __init__(self, *args, **kwargs): + self._valid_attributes = valid_attributes + super(MetricsCollector, self).__init__(*args, **kwargs) + + def AddAttribute(self, name, value): + """Adds value for attribute after checking that attribute is valid.""" + if name not in self._valid_attributes: + logging.error('%s is not a valid attribute!', name) + return + super(MetricsCollector, self).AddAttribute(name, value) + + def Log(self): + """Adds specified default values for missing attributes and logs.""" + for attribute in self._valid_attributes: + if attribute not in self._attributes: + self.AddAttribute(attribute, self._valid_attributes[attribute]) + super(MetricsCollector, self).Log() + return MetricsCollector + + +class BatchThread(threading.Thread): + """A simple thread worker to call commit on the Batch Logger.""" + + def __init__(self, duration, err_limit=3, sleep=2.0): + super(BatchThread, self).__init__() + self._duration = duration + self._sleep = sleep + self._stop = threading.Event() + self._err_limit = err_limit + + def run(self): + while not self._stop.isSet(): + time.sleep(self._duration) + if not _CommitWithRetry(self._sleep, self._err_limit): + logging.error('Terminated cloud logging due to non-transient error') + self._stop.set() + + def join(self, timeout=None): + self._stop.set() + super(BatchThread, self).join(timeout) + + +def Debug(*args, **kwargs): + return LogEvent(*args, severity=DEBUG, **kwargs) + + +def Info(*args, **kwargs): + return LogEvent(*args, severity=INFO, **kwargs) + + +def Warn(*args, **kwargs): + return LogEvent(*args, severity=WARNING, **kwargs) + + +def Error(*args, **kwargs): + return LogEvent(*args, severity=ERROR, **kwargs) + + +def _SendEvent(event, severity=None): + """Log a metric. + + Args: + event: A LogEvent to log. Must have an AsDict method implemented. + severity: A string representing the log severity. This will be ignored if + fluentd is enabled. + + Raises: + LoggerGaxError: If GaxError other then DEADLINE_EXCEEDED was + raised during logger call. + LoggerError: If any error other then ParseError or GaxError was + raised during logger call. + """ + if fluentd.get_global_sender(): + fluentd_event.Event(None, event.AsDict()) + elif _GLOBAL_LOGGER: + try: + _GLOBAL_LOGGER.log_struct( + event.AsDict(), labels=_GLOBAL_LABELS, severity=severity) + except errors.GaxError as e: + if grpc.exc_to_code(e.cause) != grpc.StatusCode.DEADLINE_EXCEEDED: + raise LoggerGaxError(e) + logging.exception('Gax RPC Deadline exceeded while push to log event %s' + ' with labels %s, not expecting event loss in cloud', + event.AsDict(), _GLOBAL_LABELS) + except json_format.ParseError as e: + logging.exception('Unable to log event %s with labels %s' + ' event will not be reported to cloud', + event.AsDict(), _GLOBAL_LABELS) + except Exception as e: # pylint: disable=broad-except + raise LoggerError(e) + else: + logging.info(event.AsDict()) + + +def _CommitWithRetry(sleep=2.0, retries=3): + """Commiting event queue. Dispatching errors and recover if possible. + + The only transient error we are aware of is a Gax RetryError. + In 99% cases we succeed from 3rd commit and will not succeed after that + without clearing commit queue. + For other then Gax Retry Error we will not recover, so returning False + + Args: + sleep: Sleep period between retries in case of error. + retries: Maximum number of commits before clearing queue. + Return: + Boolean if the batch process should continue + """ + while retries > 0: + try: + _GLOBAL_LOGGER.commit() + return True + except errors.RetryError as e: + retries -= 1 + queue_size = len(_GLOBAL_LOGGER.entries[:]) + err = str(e) + logging.exception('Gax Retry Error while commit log buffer,' + ' %d retries left,%s %d events in queue', retries, + '' if retries else ' dropping', queue_size) + if retries > 0: + Warn('RetryError', value=queue_size, attributes={ + 'retries_left': retries, 'error': err, + 'dropping_queue': False}).Log() + time.sleep(sleep) + else: + del _GLOBAL_LOGGER.entries[:] + Warn('RetryError', value=queue_size, attributes={ + 'retries_left': 0, 'error': err, + 'dropping_queue': True}).Log() + except errors.GaxError as e: + logging.exception('Gax Error while commit log buffer, stopping batch') + return False + except Exception as e: # pylint: disable=broad-except + logging.exception('Unexpected Error while commit log buffer,' + ' stopping batch') + return False + return True + +def ConfigureLogger(project_name, logger_name, labels=None, batch_time=None, + batch_err_limit=3): + """Configure a Cloud Logger. + + Does NOT enable logging to a fluentd agent. See EnableFluentdLogger() + + Args: + project_name: The name of the project to log to. + logger_name: The name of the logger. + labels: An optional dict of labels to apply to each message. + batch_time: use a batch logger to send logs every n seconds. + batch_err_limit: max consecutive errors before batch logging is terminated. + + Raises: + ConfigurationError: If no credentials were found. + """ + if 'GOOGLE_APPLICATION_CREDENTIALS' not in os.environ: + raise ConfigurationError( + ('No credentials found. Make sure a json based key is available in the ' + 'GOOGLE_APPLICATION_CREDENTIALS env var.') + ) + + global _GLOBAL_CLIENT + global _GLOBAL_LOGGER + global _GLOBAL_THREAD + _GLOBAL_CLIENT = gcl.Client(project=project_name) + _GLOBAL_LOGGER = _GLOBAL_CLIENT.logger(logger_name) + if batch_time: + _GLOBAL_LOGGER = _GLOBAL_LOGGER.batch() + _GLOBAL_THREAD = BatchThread(batch_time, batch_err_limit) + _GLOBAL_THREAD.start() + _GLOBAL_LABELS['host'] = socket.getfqdn() + if labels: + _GLOBAL_LABELS.update(labels) + +def SafeConfigureLogger(*args, **kwargs): + """Configures a Cloud Logger, if possible. Otherwise fails silently. + + Does NOT enable logging to a fluentd agent. See EnableFluentdLogger() + """ + try: + ConfigureLogger(*args, **kwargs) + except ConfigurationError: + logging.error('Unable to configure cloud logging: No GAE credentials ' + 'found. Logging to console only.') + +def EnableFluentdLogger(namespace, host="127.0.0.1", port=24224): + """Enable logging to a fluentd agent for logging to Google Cloud. + + This disables any other form of logging, including both the Cloud Logging API + and local logging. + + Args: + namespace: The namespace for logs in this application. For example + "buildbot", which becomes referenced in Google Cloud as + logName: "projects/<project>/logs/<namespace>" + host: The hostname or IP the fluentd agent lives on. + port: The port the fluentd agent is listening on. + """ + if fluentd.get_global_sender() is None: + fluentd.setup(namespace, host=host, port=port) + +@atexit.register +def StopLogger(): + """ + Stop the batch logger thread and/or fluentd logger if started. No more + logs will be sent. + + This will be executed on application termination + """ + if _GLOBAL_THREAD: + _GLOBAL_THREAD.join() + + if fluentd.get_global_sender(): + fluentd.close()
diff --git a/lib/home/monitoring/cloud_logging_test.py b/lib/home/monitoring/cloud_logging_test.py new file mode 100644 index 0000000..5185755 --- /dev/null +++ b/lib/home/monitoring/cloud_logging_test.py
@@ -0,0 +1,51 @@ +"""Tests for cloud_logging.""" + +from __future__ import absolute_import +import unittest +from . import cloud_logging + +try: + from unittest import mock # pylint: disable=wrong-import-order +except ImportError: + import mock + +class StrictAttributesTest(unittest.TestCase): + + def setUp(self): + self.valid_attributes = { + 'status': cloud_logging.StrictAttributes.DEFAULT_STRING, + 'count': cloud_logging.StrictAttributes.DEFAULT_INT, + } + + @cloud_logging.StrictAttributes(self.valid_attributes) + class Collector(cloud_logging.LogEvent): + """Extends LogEvent.""" + + self.collector = Collector('test_logger') + + def testVerifySubclass(self): + """Verify that output class is a subclass of LogEvent.""" + self.assertIsInstance(self.collector, cloud_logging.LogEvent) + + def testAddAttribute(self): + """Add a valid attribute to the dict of _attributes.""" + self.collector.AddAttribute('status', 'SUCCESS') + + self.assertIn('status', self.collector._attributes) + self.assertEqual(self.collector._attributes['status'], 'SUCCESS') + + def testAddInvalidAttribute(self): + """Attempt to add an invalid attribute.""" + self.collector.AddAttribute('invalid', True) + self.assertNotIn('invalid', self.collector._attributes) + + @mock.patch.object(cloud_logging.LogEvent, 'Log') + def testLog(self, mock_log): + self.collector.Log() + mock_log.assert_called_once() + for attribute in self.valid_attributes: + self.assertIn(attribute, self.collector._attributes) + + +if __name__ == '__main__': + unittest.main()
diff --git a/lib/setup.py b/lib/setup.py new file mode 100644 index 0000000..8700d8f --- /dev/null +++ b/lib/setup.py
@@ -0,0 +1,15 @@ +"""Setup script for home based libraries.""" + +from __future__ import absolute_import +from setuptools import find_packages +from setuptools import setup + +setup( + name='home-monitoring', + version='0.15.dev', + packages=find_packages(), + install_requires=['google-cloud-logging'], + namespace_packages=['home'], + maintainer='Home EngProd', + maintainer_email='home-engprod-infra@google.com' +)
diff --git a/pylintrc b/pylintrc new file mode 100644 index 0000000..942d8ff --- /dev/null +++ b/pylintrc
@@ -0,0 +1,345 @@ +[MASTER] + +# Specify a configuration file. +#rcfile= + +# Python code to execute, usually for sys.path manipulation such as +# pygtk.require(). +#init-hook= + +# Profiled execution. +profile=no + +# Add files or directories to the blacklist. They should be base names, not +# paths. +ignore=CVS +ignore-patterns=.*_pb2.py # Ignore proto genfiles. + +# Pickle collected data for later comparisons. +persistent=no + +# List of plugins (as comma separated values of python modules names) to load, +# usually to register additional checkers. +load-plugins= + + +[MESSAGES CONTROL] + +# Enable the message, report, category or checker with the given id(s). You can +# either give multiple identifier separated by comma (,) or put this option +# multiple time. +#enable= + +# Disable the message, report, category or checker with the given id(s). You +# can either give multiple identifier separated by comma (,) or put this option +# multiple time (only on the command line, not in the configuration file where +# it should appear only once). +# +# +# These were disabled specificially for continuous-tests/: +# attribute-defined-outside-init, +# bad-option-value, +# method-hidden, +# +# These were inherited from depot_tools and should be audited, to see if +# continuous-tests/ could benefit from them: +# anomalous-backslash-in-string +# bad-context-manager +# bad-continuation +# bad-indentation +# bad-str-strip-call +# bad-whitespace +# cell-var-from-loop +# deprecated-lambda +# eval-used +# function-redefined +# import-error +# locally-enabled +# missing-final-newline +# no-init +# no-name-in-module +# no-self-use +# not-callable +# old-style-class +# protected-access +# super-on-old-class +# superfluous-parens +# too-many-function-args +# trailing-whitespace +# unnecessary-semicolon +# unpacking-non-sequence +# unused-import +# useless-else-on-loop +# +disable= + abstract-class-little-used, + abstract-class-not-used, + anomalous-backslash-in-string, + attribute-defined-outside-init, + bad-builtin, + bad-context-manager, + bad-continuation, + bad-indentation, + bad-inline-option, + bad-option-value, + bad-str-strip-call, + bad-whitespace, + broad-except, + cell-var-from-loop, + deprecated-lambda, + deprecated-module, + duplicate-code, + eval-used, + exec-used, + fixme, + function-redefined, + global-statement, + import-error, + invalid-name, + locally-disabled, + locally-enabled, + logging-not-lazy, + method-hidden, + missing-docstring, + missing-final-newline, + no-init, + no-name-in-module, + no-self-use, + not-callable, + old-style-class, + protected-access, + reimported, + star-args, + super-on-old-class, + superfluous-parens, + too-few-public-methods, + too-many-ancestors, + too-many-arguments, + too-many-branches, + too-many-function-args, + too-many-instance-attributes, + too-many-lines, + too-many-locals, + too-many-public-methods, + too-many-return-statements, + too-many-statements, + trailing-whitespace, + unnecessary-semicolon, + unpacking-non-sequence, + unused-import, + useless-else-on-loop, + # Disabled while we run pylint 2 against the code. + # these should be disabled after upgrade to Python 3 + # is complete. + useless-object-inheritance + +[REPORTS] + +# Set the output format. Available formats are text, parseable, colorized, msvs +# (visual studio) and html +output-format=text + +# Put messages in a separate file for each module / package specified on the +# command line instead of printing them on stdout. Reports (if any) will be +# written in a file name "pylint_global.[txt|html]". +files-output=no + +# Tells whether to display a full report or only the messages +# CHANGED: +reports=no + +# Python expression which should return a note less than 10 (10 is the highest +# note). You have access to the variables errors warning, statement which +# respectively contain the number of errors / warnings messages and the total +# number of statements analyzed. This is used by the global evaluation report +# (RP0004). +evaluation=10.0 - ((float(5 * error + warning + refactor + convention) / statement) * 10) + +# Add a comment according to your evaluation note. This is used by the global +# evaluation report (RP0004). +comment=no + + +[VARIABLES] + +# Tells whether we should check for unused import in __init__ files. +init-import=no + +# A regular expression matching the beginning of the name of dummy variables +# (i.e. not used). +dummy-variables-rgx=_|dummy + +# List of additional names supposed to be defined in builtins. Remember that +# you should avoid to define new builtins when possible. +additional-builtins= + + +[TYPECHECK] + +# Tells whether missing members accessed in mixin class should be ignored. A +# mixin class is detected if its name ends with "mixin" (case insensitive). +ignore-mixin-members=yes + +# List of classes names for which member attributes should not be checked +# (useful for classes with attributes dynamically set). +ignored-classes=SQLObject,twisted.internet.reactor,hashlib,google.appengine.api.memcache + +# When zope mode is activated, add a predefined set of Zope acquired attributes +# to generated-members. +zope=no + +# List of members which are set dynamically and missed by pylint inference +# system, and so shouldn't trigger E0201 when accessed. Python regular +# expressions are accepted. +generated-members=REQUEST,acl_users,aq_parent,multiprocessing.managers.SyncManager + + +[MISCELLANEOUS] + +# List of note tags to take in consideration, separated by a comma. +notes=FIXME,XXX,TODO + + +[SIMILARITIES] + +# Minimum lines number of a similarity. +min-similarity-lines=4 + +# Ignore comments when computing similarities. +ignore-comments=yes + +# Ignore docstrings when computing similarities. +ignore-docstrings=yes + + +[FORMAT] + +# Maximum number of characters on a single line. +max-line-length=80 + +# Maximum number of lines in a module +max-module-lines=1000 + +# String used as indentation unit. This is usually " " (4 spaces) or "\t" (1 +# tab). +# CHANGED: +indent-string=' ' + + +[BASIC] + +# Required attributes for module, separated by a comma +required-attributes= + +# List of builtins function names that should not be used, separated by a comma +bad-functions=map,filter,apply,input,reduce + +# Regular expression which should only match correct module names +module-rgx=(([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+))$ + +# Regular expression which should only match correct module level names +const-rgx=((_?[A-Z_][A-Z0-9_]*)|(__.*__))$ + +# Regular expression which should only match correct class names +class-rgx=[A-Z_][a-zA-Z0-9]+$ + +# Regular expression which should only match correct function names +function-rgx=^(?:(?P<camel_case>_?[A-Z][a-zA-Z0-9]*)|(?P<snake_case>_?[a-z][a-z0-9_]*))$ + +# Regular expression which should only match correct method names +method-rgx=^(?:(?P<exempt>__[a-z0-9_]+__|next)|(?P<camel_case>_{0,2}[A-Z][a-zA-Z0-9]*)|(?P<snake_case>_{0,2}[a-z][a-z0-9_]*)|(?P<testcsae>test[A-Z][a-zA-Z0-9_]*))$ + +# Regular expression which should only match correct instance attribute names +attr-rgx=^_{0,2}[a-z_][a-z0-9_]{2,30}$ + +# Regular expression which should only match correct argument names +argument-rgx=^[a-z][a-z0-9_]{2,30}$ + +# Regular expression which should only match correct variable names +variable-rgx=^[a-z_][a-z0-9_]*$ + +# Regular expression which should only match correct list comprehension / +# generator expression variable names +inlinevar-rgx=[A-Za-z_][A-Za-z0-9_]*$ + +# Good variable names which should always be accepted, separated by a comma +good-names=i,j,k,main,Run,_ + +# Bad variable names which should always be refused, separated by a comma +bad-names=foo,bar,baz,toto,tutu,tata + +# Regular expression which should only match functions or classes name which do +# not require a docstring +no-docstring-rgx=__.*__ + + +[DESIGN] + +# Maximum number of arguments for function / method +max-args=5 + +# Argument names that match this expression will be ignored. Default to name +# with leading underscore +ignored-argument-names= + +# Maximum number of locals for function / method body +max-locals=15 + +# Maximum number of return / yield for function / method body +max-returns=6 + +# Maximum number of branch for function / method body +max-branchs=12 + +# Maximum number of statements in function / method body +max-statements=50 + +# Maximum number of parents for a class (see R0901). +max-parents=7 + +# Maximum number of attributes for a class (see R0902). +max-attributes=7 + +# Minimum number of public methods for a class (see R0903). +min-public-methods=2 + +# Maximum number of public methods for a class (see R0904). +max-public-methods=20 + + +[CLASSES] + +# List of interface methods to ignore, separated by a comma. This is used for +# instance to not check methods defines in Zope's Interface base class. +ignore-iface-methods=isImplementedBy,deferred,extends,names,namesAndDescriptions,queryDescriptionFor,getBases,getDescriptionFor,getDoc,getName,getTaggedValue,getTaggedValueTags,isEqualOrExtendedBy,setTaggedValue,isImplementedByInstancesOf,adaptWith,is_implemented_by + +# List of method names used to declare (i.e. assign) instance attributes. +defining-attr-methods=__init__,__new__,setUp + +# List of valid names for the first argument in a class method. +valid-classmethod-first-arg=cls + + +[IMPORTS] + +# Deprecated modules which should not be used, separated by a comma +deprecated-modules=regsub,string,TERMIOS,Bastion,rexec + +# Create a graph of every (i.e. internal and external) dependencies in the +# given file (report RP0402 must not be disabled) +import-graph= + +# Create a graph of external dependencies in the given file (report RP0402 must +# not be disabled) +ext-import-graph= + +# Create a graph of internal dependencies in the given file (report RP0402 must +# not be disabled) +int-import-graph= + + +[EXCEPTIONS] + +# Exceptions that will emit a warning when being caught. Defaults to +# "Exception" +overgeneral-exceptions=StandardError,Exception,BaseException
diff --git a/test_data/README b/test_data/README new file mode 100644 index 0000000..d81f35e --- /dev/null +++ b/test_data/README
@@ -0,0 +1,2 @@ +Test data used by unit tests in the test/ repo that +cannot be shared with partners.
diff --git a/test_data/androidthings/dev.keystore b/test_data/androidthings/dev.keystore new file mode 100644 index 0000000..45bb740 --- /dev/null +++ b/test_data/androidthings/dev.keystore Binary files differ
diff --git a/test_data/assistant_audios/audio_metadata_format.md b/test_data/assistant_audios/audio_metadata_format.md new file mode 100644 index 0000000..454e712 --- /dev/null +++ b/test_data/assistant_audios/audio_metadata_format.md
@@ -0,0 +1,29 @@ +# Assistant Audio Metadata File Format. + +Each audio metadata file is used to describe the recorded audio samples. These +metadata files should be of json format. + +## Allowed field names and value formats + +The following field names and corresponding value formats are allowed in the +metadata file: + +* audio_file_path - A string; This should be the absolute path/uri of the + recorded audio sample. +* script - A string; This should be the text used to record the audio sample. + eg: Who is obama? +* number_of_channels - An Integer; The number of channels, the recorded audio + sample has. +* sample_format - A string; The sample format of recorded stream container. + eg: S32LE +* sample_rate - An Integer; The sampling rate of recorded audio sample in hertz. + +## Sample File + + { + "audio_file_path": "okgooglesetalarmat5am.raw", + "script": "set alarm at 5 a.m.", + "number_of_channels": "8", + "sample_format": "S32LE", + "sample_rate": "48000" + } \ No newline at end of file
diff --git a/test_data/assistant_audios/hotword_effort_level_high.json b/test_data/assistant_audios/hotword_effort_level_high.json new file mode 100644 index 0000000..9b415ee --- /dev/null +++ b/test_data/assistant_audios/hotword_effort_level_high.json
@@ -0,0 +1,8 @@ +{ + "audio_file_path": "hotword_effort_level_high.wav", + "script": "what's the time", + "number_of_channels": "2", + "sample_format": "InterleavedInt32", + "sample_rate": "16000" +} +
diff --git a/test_data/assistant_audios/hotword_effort_level_high.wav b/test_data/assistant_audios/hotword_effort_level_high.wav new file mode 100644 index 0000000..b55dccd --- /dev/null +++ b/test_data/assistant_audios/hotword_effort_level_high.wav Binary files differ
diff --git a/test_data/assistant_audios/hotword_effort_level_low.json b/test_data/assistant_audios/hotword_effort_level_low.json new file mode 100644 index 0000000..fcb18d5 --- /dev/null +++ b/test_data/assistant_audios/hotword_effort_level_low.json
@@ -0,0 +1,8 @@ +{ + "audio_file_path": "hotword_effort_level_low.wav", + "script": "what's the time", + "number_of_channels": "2", + "sample_format": "InterleavedInt32", + "sample_rate": "16000" +} +
diff --git a/test_data/assistant_audios/hotword_effort_level_low.wav b/test_data/assistant_audios/hotword_effort_level_low.wav new file mode 100644 index 0000000..e081dd3 --- /dev/null +++ b/test_data/assistant_audios/hotword_effort_level_low.wav Binary files differ
diff --git a/test_data/assistant_audios/hotword_effort_level_medium.json b/test_data/assistant_audios/hotword_effort_level_medium.json new file mode 100644 index 0000000..3a03add --- /dev/null +++ b/test_data/assistant_audios/hotword_effort_level_medium.json
@@ -0,0 +1,8 @@ +{ + "audio_file_path": "hotword_effort_level_medium.wav", + "script": "what's the time", + "number_of_channels": "2", + "sample_format": "InterleavedInt32", + "sample_rate": "16000" +} +
diff --git a/test_data/assistant_audios/hotword_effort_level_medium.wav b/test_data/assistant_audios/hotword_effort_level_medium.wav new file mode 100644 index 0000000..dcf446e --- /dev/null +++ b/test_data/assistant_audios/hotword_effort_level_medium.wav Binary files differ
diff --git a/test_data/assistant_audios/okgoogleplayladygaga.wav b/test_data/assistant_audios/okgoogleplayladygaga.wav new file mode 100644 index 0000000..86c1e9e --- /dev/null +++ b/test_data/assistant_audios/okgoogleplayladygaga.wav Binary files differ
diff --git a/test_data/assistant_audios/okgooglesetalarmat5am.wav b/test_data/assistant_audios/okgooglesetalarmat5am.wav new file mode 100644 index 0000000..9c166cf --- /dev/null +++ b/test_data/assistant_audios/okgooglesetalarmat5am.wav Binary files differ
diff --git a/test_data/assistant_audios/okgooglesettimerfor5seconds.wav b/test_data/assistant_audios/okgooglesettimerfor5seconds.wav new file mode 100644 index 0000000..251e931 --- /dev/null +++ b/test_data/assistant_audios/okgooglesettimerfor5seconds.wav Binary files differ
diff --git a/test_data/assistant_audios/okgooglewhatistheweather.wav b/test_data/assistant_audios/okgooglewhatistheweather.wav new file mode 100644 index 0000000..99f54e1 --- /dev/null +++ b/test_data/assistant_audios/okgooglewhatistheweather.wav Binary files differ
diff --git a/test_data/assistant_audios/okgooglewhattimeisit.wav b/test_data/assistant_audios/okgooglewhattimeisit.wav new file mode 100644 index 0000000..88a4af5 --- /dev/null +++ b/test_data/assistant_audios/okgooglewhattimeisit.wav Binary files differ
diff --git a/test_data/assistant_audios/play_lady_gaga.json b/test_data/assistant_audios/play_lady_gaga.json new file mode 100644 index 0000000..b6d7d1f --- /dev/null +++ b/test_data/assistant_audios/play_lady_gaga.json
@@ -0,0 +1,8 @@ +{ + "audio_file_path": "okgoogleplayladygaga.wav", + "script": "play lady gaga", + "number_of_channels": "2", + "sample_format": "InterleavedInt32", + "sample_rate": "16000" +} +
diff --git a/test_data/assistant_audios/set_alarm.json b/test_data/assistant_audios/set_alarm.json new file mode 100644 index 0000000..05f89a4 --- /dev/null +++ b/test_data/assistant_audios/set_alarm.json
@@ -0,0 +1,8 @@ +{ + "audio_file_path": "okgooglesetalarmat5am.wav", + "script": "set alarm at 5 a.m.", + "number_of_channels": "2", + "sample_format": "InterleavedInt32", + "sample_rate": "16000" +} +
diff --git a/test_data/assistant_audios/set_timer.json b/test_data/assistant_audios/set_timer.json new file mode 100644 index 0000000..93609fe --- /dev/null +++ b/test_data/assistant_audios/set_timer.json
@@ -0,0 +1,9 @@ +{ + "audio_file_path": "okgooglesettimerfor5seconds.wav", + "script": "set timer for 5 seconds", + "number_of_channels": "2", + "sample_format": "InterleavedInt32", + "sample_rate": "16000" + +} +
diff --git a/test_data/assistant_audios/what_is_the_weather.json b/test_data/assistant_audios/what_is_the_weather.json new file mode 100644 index 0000000..b2aa1b8 --- /dev/null +++ b/test_data/assistant_audios/what_is_the_weather.json
@@ -0,0 +1,8 @@ +{ + "audio_file_path": "okgooglewhatistheweather.wav", + "script": "what's the weather in San Francisco", + "number_of_channels": "2", + "sample_format": "InterleavedInt32", + "sample_rate": "16000" +} +
diff --git a/test_data/assistant_audios/what_time_is_it.json b/test_data/assistant_audios/what_time_is_it.json new file mode 100644 index 0000000..9446818 --- /dev/null +++ b/test_data/assistant_audios/what_time_is_it.json
@@ -0,0 +1,8 @@ +{ + "audio_file_path": "okgooglewhattimeisit.wav", + "script": "what time is it", + "number_of_channels": "2", + "sample_format": "InterleavedInt32", + "sample_rate": "16000" +} +
diff --git a/test_data/cast_ota_installer/README b/test_data/cast_ota_installer/README new file mode 100644 index 0000000..51579dc --- /dev/null +++ b/test_data/cast_ota_installer/README
@@ -0,0 +1,3 @@ +Test files for eurtest.tests.cast_audio.cast_ota_installer tests. + +Signed OTA packaged obtained from the master/26752 build.
diff --git a/test_data/cast_ota_installer/cast_receiver_signed-test_private_key.zip b/test_data/cast_ota_installer/cast_receiver_signed-test_private_key.zip new file mode 100644 index 0000000..33ed1b3 --- /dev/null +++ b/test_data/cast_ota_installer/cast_receiver_signed-test_private_key.zip Binary files differ
diff --git a/test_data/cast_ota_installer/cast_receiver_signed.zip b/test_data/cast_ota_installer/cast_receiver_signed.zip new file mode 100644 index 0000000..c9d31e1 --- /dev/null +++ b/test_data/cast_ota_installer/cast_receiver_signed.zip Binary files differ
diff --git a/test_data/cast_ota_installer/cast_receiver_unsigned.zip b/test_data/cast_ota_installer/cast_receiver_unsigned.zip new file mode 100644 index 0000000..2572b6e --- /dev/null +++ b/test_data/cast_ota_installer/cast_receiver_unsigned.zip Binary files differ
diff --git a/test_data/test_audio_samples/empty_sequence.wav b/test_data/test_audio_samples/empty_sequence.wav new file mode 100644 index 0000000..878bf23 --- /dev/null +++ b/test_data/test_audio_samples/empty_sequence.wav Binary files differ
diff --git a/test_data/test_audio_samples/fine_aligner_ref.wav b/test_data/test_audio_samples/fine_aligner_ref.wav new file mode 100644 index 0000000..a8eeb98 --- /dev/null +++ b/test_data/test_audio_samples/fine_aligner_ref.wav Binary files differ
diff --git a/test_data/test_audio_samples/fine_aligner_src.wav b/test_data/test_audio_samples/fine_aligner_src.wav new file mode 100644 index 0000000..a273758 --- /dev/null +++ b/test_data/test_audio_samples/fine_aligner_src.wav Binary files differ
diff --git a/test_data/test_audio_samples/sign_check_ref.wav b/test_data/test_audio_samples/sign_check_ref.wav new file mode 100644 index 0000000..a5803db --- /dev/null +++ b/test_data/test_audio_samples/sign_check_ref.wav Binary files differ
diff --git a/test_data/test_audio_samples/sign_check_src.wav b/test_data/test_audio_samples/sign_check_src.wav new file mode 100644 index 0000000..f0d0166 --- /dev/null +++ b/test_data/test_audio_samples/sign_check_src.wav Binary files differ
diff --git a/test_data/test_audio_samples/sunshine-reference-test.wav b/test_data/test_audio_samples/sunshine-reference-test.wav new file mode 100644 index 0000000..49a41e9 --- /dev/null +++ b/test_data/test_audio_samples/sunshine-reference-test.wav Binary files differ
diff --git a/test_data/test_audio_samples/sunshine-reference.wav b/test_data/test_audio_samples/sunshine-reference.wav new file mode 100644 index 0000000..a885951 --- /dev/null +++ b/test_data/test_audio_samples/sunshine-reference.wav Binary files differ
diff --git a/test_data/test_audio_samples/sunshine-v2.wav b/test_data/test_audio_samples/sunshine-v2.wav new file mode 100644 index 0000000..66ae364 --- /dev/null +++ b/test_data/test_audio_samples/sunshine-v2.wav Binary files differ
diff --git a/test_data/test_audio_samples/sunshine_record.wav b/test_data/test_audio_samples/sunshine_record.wav new file mode 100644 index 0000000..8d259d2 --- /dev/null +++ b/test_data/test_audio_samples/sunshine_record.wav Binary files differ
diff --git a/test_data/test_audio_samples/synthesized-sequence.wav b/test_data/test_audio_samples/synthesized-sequence.wav new file mode 100644 index 0000000..2d57396 --- /dev/null +++ b/test_data/test_audio_samples/synthesized-sequence.wav Binary files differ
diff --git a/test_data/test_audio_samples/test_sequence.wav b/test_data/test_audio_samples/test_sequence.wav new file mode 100644 index 0000000..9bc13fb --- /dev/null +++ b/test_data/test_audio_samples/test_sequence.wav Binary files differ