261 lines
8.0 KiB
Python
261 lines
8.0 KiB
Python
# Copyright 2017 The Chromium Authors. All rights reserved.
|
|
# Use of this source code is governed by a BSD-style license that can be
|
|
# found in the LICENSE file.
|
|
|
|
import glob
|
|
import json
|
|
import os
|
|
|
|
import logging
|
|
|
|
from autotest_lib.site_utils.sponge_lib import autotest_job_info
|
|
|
|
|
|
UNKNOWN_EFFORT_NAME = 'UNKNOWN_BUILD'
|
|
UNKNOWN_ENV_NAME = 'UNKNOWN_BOARD'
|
|
|
|
|
|
class ACTSSummaryEnums(object):
|
|
"""A class contains the attribute names used in a ACTS summary."""
|
|
|
|
Requested = 'Requested'
|
|
Failed = 'Failed'
|
|
Unknown = 'Unknown'
|
|
|
|
|
|
class ACTSRecordEnums(object):
|
|
"""A class contains the attribute names used in an ACTS record."""
|
|
|
|
BeginTime = 'Begin Time'
|
|
Details = 'Details'
|
|
EndTime = 'End Time'
|
|
Extras = 'Extras'
|
|
ExtraErrors = 'Extra Errors'
|
|
Result = 'Result'
|
|
TestClass = 'Test Class'
|
|
TestName = 'Test Name'
|
|
UID = 'UID'
|
|
|
|
|
|
class ACTSTaskInfo(autotest_job_info.AutotestTaskInfo):
|
|
"""Task info for an ACTS test."""
|
|
|
|
tags = autotest_job_info.AutotestTaskInfo.tags + ['acts', 'testtracker']
|
|
logs = autotest_job_info.AutotestTaskInfo.logs + ['results']
|
|
|
|
def __init__(self, test, job):
|
|
"""
|
|
@param test: The autotest test for this ACTS test.
|
|
@param job: The job info that is the parent ot this task.
|
|
"""
|
|
super(ACTSTaskInfo, self).__init__(test, job)
|
|
|
|
summary_location = os.path.join(
|
|
self.results_dir, 'results/latest/test_run_summary.json')
|
|
|
|
build_info_location = os.path.join(self.results_dir,
|
|
'results/BUILD_INFO-*')
|
|
build_info_files = glob.iglob(build_info_location)
|
|
|
|
try:
|
|
build_info_file = next(build_info_files)
|
|
logging.info('Using build info file: %s', build_info_file)
|
|
with open(build_info_file) as fd:
|
|
self.build_info = json.load(fd)
|
|
except Exception as e:
|
|
logging.exception(e)
|
|
logging.error('Bad build info file.')
|
|
self.build_info = {}
|
|
|
|
try:
|
|
build_prop_str = self.build_info['build_prop']
|
|
prop_dict = {}
|
|
self.build_info['build_prop'] = prop_dict
|
|
lines = build_prop_str.splitlines()
|
|
for line in lines:
|
|
parts = line.split('=')
|
|
|
|
if len(parts) != 2:
|
|
continue
|
|
|
|
prop_dict[parts[0]] = parts[1]
|
|
except Exception as e:
|
|
logging.exception(e)
|
|
logging.error('Bad build prop data, using default empty dict')
|
|
self.build_info['build_prop'] = {}
|
|
|
|
try:
|
|
with open(summary_location) as fd:
|
|
self._acts_summary = json.load(fd)
|
|
|
|
self._summary_block = self._acts_summary['Summary']
|
|
|
|
record_block = self._acts_summary['Results']
|
|
self._records = list(ACTSRecord(record) for record in record_block)
|
|
self.is_valid = True
|
|
except Exception as e:
|
|
logging.exception(e)
|
|
logging.error('Bad acts data, reverting to autotest only.')
|
|
self.is_valid = False
|
|
self.tags = autotest_job_info.AutotestTaskInfo.tags
|
|
|
|
@property
|
|
def test_case_count(self):
|
|
"""The number of test cases run."""
|
|
return self._summary_block[ACTSSummaryEnums.Requested]
|
|
|
|
@property
|
|
def failed_case_count(self):
|
|
"""The number of failed test cases."""
|
|
return self._summary_block[ACTSSummaryEnums.Failed]
|
|
|
|
@property
|
|
def error_case_count(self):
|
|
"""The number of errored test cases."""
|
|
return self._summary_block[ACTSSummaryEnums.Unknown]
|
|
|
|
@property
|
|
def records(self):
|
|
"""All records of test cases in the ACTS tests."""
|
|
return self._records
|
|
|
|
@property
|
|
def owner(self):
|
|
"""The owner of the task."""
|
|
if 'param-testtracker_owner' in self.keyvals:
|
|
return self.keyvals['param-testtracker_owner'].strip("'").strip('"')
|
|
elif 'param-test_tracker_owner' in self.keyvals:
|
|
return self.keyvals['param-testtracker_owner'].strip("'").strip('"')
|
|
else:
|
|
return self._job.user.strip("'").strip('"')
|
|
|
|
@property
|
|
def effort_name(self):
|
|
"""The test tracker effort name."""
|
|
build_id = self.build_info.get('build_prop', {}).get('ro.build.id')
|
|
if build_id and any(c.isdigit() for c in build_id):
|
|
return build_id
|
|
else:
|
|
build_version = self.build_info.get('build_prop', {}).get(
|
|
'ro.build.version.incremental', UNKNOWN_EFFORT_NAME)
|
|
return build_version
|
|
|
|
|
|
@property
|
|
def project_id(self):
|
|
"""The test tracker project id."""
|
|
if 'param-testtracker_project_id' in self.keyvals:
|
|
return self.keyvals.get('param-testtracker_project_id')
|
|
else:
|
|
return self.keyvals.get('param-test_tracker_project_id')
|
|
|
|
@property
|
|
def environment(self):
|
|
"""The name of the enviroment for test tracker."""
|
|
build_props = self.build_info.get('build_prop', {})
|
|
|
|
if 'ro.product.board' in build_props:
|
|
board = build_props['ro.product.board']
|
|
elif 'ro.build.product' in build_props:
|
|
board = build_props['ro.build.product']
|
|
else:
|
|
board = UNKNOWN_ENV_NAME
|
|
|
|
return board
|
|
|
|
@property
|
|
def extra_environment(self):
|
|
"""Extra environment info about the task."""
|
|
if 'param-testtracker_extra_env' in self.keyvals:
|
|
extra = self.keyvals.get('param-testtracker_extra_env', [])
|
|
else:
|
|
extra = self.keyvals.get('param-test_tracker_extra_env', [])
|
|
|
|
if not isinstance(extra, list):
|
|
extra = [extra]
|
|
|
|
return extra
|
|
|
|
|
|
class ACTSRecord(object):
|
|
"""A single record of a test case in an ACTS test."""
|
|
|
|
tags = ['acts', 'testtracker']
|
|
|
|
def __init__(self, json_record):
|
|
"""
|
|
@param json_record: The json info for this record
|
|
"""
|
|
self._json_record = json_record
|
|
|
|
@property
|
|
def test_class(self):
|
|
"""The test class that was run."""
|
|
return self._json_record[ACTSRecordEnums.TestClass]
|
|
|
|
@property
|
|
def test_case(self):
|
|
"""The test case that was run. None implies all in the class."""
|
|
return self._json_record.get(ACTSRecordEnums.TestName)
|
|
|
|
@property
|
|
def uid(self):
|
|
"""The uid of the test case."""
|
|
return self._json_record.get(ACTSRecordEnums.UID)
|
|
|
|
@property
|
|
def status(self):
|
|
"""The status of the test case."""
|
|
return self._json_record[ACTSRecordEnums.Result]
|
|
|
|
@property
|
|
def start_time(self):
|
|
"""The start time of the test case."""
|
|
return self._json_record[ACTSRecordEnums.BeginTime] / 1000.0
|
|
|
|
@property
|
|
def end_time(self):
|
|
"""The end time of the test case."""
|
|
return self._json_record[ACTSRecordEnums.EndTime] / 1000.0
|
|
|
|
@property
|
|
def details(self):
|
|
"""Details about the test case."""
|
|
return self._json_record.get(ACTSRecordEnums.Details)
|
|
|
|
@property
|
|
def extras(self):
|
|
"""Extra info about the test case."""
|
|
return self._json_record.get(ACTSRecordEnums.Extras)
|
|
|
|
@property
|
|
def extra_errors(self):
|
|
"""Extra errors about the test case."""
|
|
return self._json_record.get(ACTSRecordEnums.ExtraErrors)
|
|
|
|
@property
|
|
def extra_environment(self):
|
|
"""Extra details about the environment for this test."""
|
|
extras = self.extras
|
|
if not extras:
|
|
return None
|
|
|
|
test_tracker_info = self.extras.get('test_tracker_info')
|
|
if not test_tracker_info:
|
|
return self.extras.get('test_tracker_environment_info')
|
|
|
|
return test_tracker_info.get('extra_environment')
|
|
|
|
@property
|
|
def uuid(self):
|
|
"""The test tracker uuid of the test case."""
|
|
extras = self.extras
|
|
if not extras:
|
|
return None
|
|
|
|
test_tracker_info = self.extras.get('test_tracker_info')
|
|
if not test_tracker_info:
|
|
return self.extras.get('test_tracker_uuid')
|
|
|
|
return test_tracker_info.get('test_tracker_uuid')
|