blob: f6490ab29c0b35ee0186c8786be23e6655e9a418 [file] [log] [blame]
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/"
OPENWEAVE = "virtual-home/cirque-park/openweave/"
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,
OPENWEAVE,
SAMPLE_VIDEO,
SAMPLE_AUDIO,
SAMPLE_JPEG.format(self.product)
]
command += [path.format(TARGET_PRODUCT[self.product] + "-" + BUILD_VARIANT) 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()
target_product = TARGET_PRODUCT[self.product]
env = {
'LD_LIBRARY_PATH': ":".join(
['../../../../prebuilt/toolchain/x86_64/usr/lib64',
os.path.join('../../../../out/target/product',
f'{target_product}-{BUILD_VARIANT}/system/lib')
])
}
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