blob: 0eefee39a02396fd4ca9c2ce040b43e5a4b44d4e [file] [log] [blame]
# Copyright (c) 2017 The Chromium OS 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 datetime
import glob
import os
import time
from autotest_lib.client.common_lib import error
from autotest_lib.client.common_lib.cros import system_metrics_collector
from autotest_lib.server.cros import cfm_jmidata_log_collector
from autotest_lib.server.cros.cfm import cfm_base_test
_SHORT_TIMEOUT = 5
_MEASUREMENT_DURATION_SECONDS = 10
_TOTAL_TEST_DURATION_SECONDS = 900
_BASE_DIR = '/home/chronos/user/Storage/ext/'
_EXT_ID = 'ikfcpmgefdpheiiomgmhlmmkihchmdlj'
_JMI_DIR = '/0*/File\ System/000/t/00/*'
_JMI_SOURCE_DIR = _BASE_DIR + _EXT_ID + _JMI_DIR
class ParticipantCountMetric(system_metrics_collector.Metric):
"""
Metric for getting the current participant count in a call.
"""
def __init__(self, cfm_facade):
"""
Initializes with a cfm_facade.
@param cfm_facade object having a get_participant_count() method.
"""
super(ParticipantCountMetric, self).__init__(
'participant_count',
'participants',
higher_is_better=True)
self.cfm_facade = cfm_facade
def collect_metric(self):
"""
Collects one metric value.
"""
self.values.append(self.cfm_facade.get_participant_count())
class enterprise_CFM_Perf(cfm_base_test.CfmBaseTest):
"""This is a server test which clears device TPM and runs
enterprise_RemoraRequisition client test to enroll the device in to hotrod
mode. After enrollment is successful, it collects and logs cpu, memory and
temperature data from the device under test."""
version = 1
def start_hangout(self):
"""Waits for the landing page and starts a hangout session."""
self.cfm_facade.wait_for_hangouts_telemetry_commands()
current_date = datetime.datetime.now().strftime("%Y-%m-%d")
hangout_name = current_date + '-cfm-perf'
self.cfm_facade.start_new_hangout_session(hangout_name)
def join_meeting(self):
"""Waits for the landing page and joins a meeting session."""
self.cfm_facade.wait_for_meetings_landing_page()
# Daily meeting for perf testing with 9 remote participants.
meeting_code = 'nis-rhmz-dyh'
self.cfm_facade.join_meeting_session(meeting_code)
def collect_perf_data(self):
"""
Collects run time data from the DUT using system_metrics_collector.
Writes the data to the chrome perf dashboard.
"""
start_time = time.time()
while (time.time() - start_time) < _TOTAL_TEST_DURATION_SECONDS:
time.sleep(_MEASUREMENT_DURATION_SECONDS)
self.metrics_collector.collect_snapshot()
self.metrics_collector.write_metrics(self.output_perf_value)
def _get_average(self, data_type, jmidata):
"""Computes mean of a list of numbers.
@param data_type: Type of data to be retrieved from jmi data log.
@param jmidata: Raw jmi data log to parse.
@return Mean computed from the list of numbers.
"""
data = self._get_data_from_jmifile(data_type, jmidata)
if not data:
return 0
return float(sum(data)) / len(data)
def _get_max_value(self, data_type, jmidata):
"""Computes maximum value of a list of numbers.
@param data_type: Type of data to be retrieved from jmi data log.
@param jmidata: Raw jmi data log to parse.
@return Maxium value from the list of numbers.
"""
data = self._get_data_from_jmifile(data_type, jmidata)
if not data:
return 0
return max(data)
def _get_sum(self, data_type, jmidata):
"""Computes sum of a list of numbers.
@param data_type: Type of data to be retrieved from jmi data log.
@param jmidata: Raw jmi data log to parse.
@return Sum computed from the list of numbers.
"""
data = self._get_data_from_jmifile(data_type, jmidata)
if not data:
return 0
return sum(data)
def _get_last_value(self, data_type, jmidata):
"""Gets last value of a list of numbers.
@param data_type: Type of data to be retrieved from jmi data log.
@param jmidata: Raw jmi data log to parse.
@return The last value in the jmidata for the specified data_type. 0 if
there are no values in the jmidata for this data_type.
"""
data = self._get_data_from_jmifile(data_type, jmidata)
if not data:
return 0
return data[-1]
def _get_data_from_jmifile(self, data_type, jmidata):
"""Gets data from jmidata log for given data type.
@param data_type: Type of data to be retrieved from jmi data log.
@param jmidata: Raw jmi data log to parse.
@return Data for given data type from jmidata log.
"""
return cfm_jmidata_log_collector.GetDataFromLogs(
self, data_type, jmidata)
def _get_file_to_parse(self):
"""Copy jmi logs from client to test's results directory.
@return The newest jmi log file.
"""
self._host.get_file(_JMI_SOURCE_DIR, self.resultsdir)
source_jmi_files = self.resultsdir + '/0*'
if not source_jmi_files:
raise error.TestNAError('JMI data file not found.')
newest_file = max(glob.iglob(source_jmi_files), key=os.path.getctime)
return newest_file
def upload_jmidata(self):
"""
Write jmidata results to results-chart.json file for Perf Dashboard.
"""
jmi_file = self._get_file_to_parse()
jmifile_to_parse = open(jmi_file, 'r')
jmidata = jmifile_to_parse.read()
# Compute and save aggregated stats from JMI.
self.output_perf_value(description='sum_vid_in_frames_decoded',
value=self._get_sum('frames_decoded', jmidata), units='frames',
higher_is_better=True)
self.output_perf_value(description='sum_vid_out_frames_encoded',
value=self._get_sum('frames_encoded', jmidata), units='frames',
higher_is_better=True)
self.output_perf_value(description='vid_out_adapt_changes',
value=self._get_last_value('adaptation_changes', jmidata),
units='count', higher_is_better=False)
self.output_perf_value(description='video_out_encode_time',
value=self._get_data_from_jmifile(
'average_encode_time', jmidata),
units='ms', higher_is_better=False)
self.output_perf_value(description='max_video_out_encode_time',
value=self._get_max_value('average_encode_time', jmidata),
units='ms', higher_is_better=False)
self.output_perf_value(description='vid_out_bandwidth_adapt',
value=self._get_average('bandwidth_adaptation', jmidata),
units='bool', higher_is_better=False)
self.output_perf_value(description='vid_out_cpu_adapt',
value=self._get_average('cpu_adaptation', jmidata),
units='bool', higher_is_better=False)
self.output_perf_value(description='video_in_res',
value=self._get_data_from_jmifile(
'video_received_frame_height', jmidata),
units='px', higher_is_better=True)
self.output_perf_value(description='video_out_res',
value=self._get_data_from_jmifile(
'video_sent_frame_height', jmidata),
units='resolution', higher_is_better=True)
self.output_perf_value(description='vid_in_framerate_decoded',
value=self._get_data_from_jmifile(
'framerate_decoded', jmidata),
units='fps', higher_is_better=True)
self.output_perf_value(description='vid_out_framerate_input',
value=self._get_data_from_jmifile(
'framerate_outgoing', jmidata),
units='fps', higher_is_better=True)
self.output_perf_value(description='vid_in_framerate_to_renderer',
value=self._get_data_from_jmifile(
'framerate_to_renderer', jmidata),
units='fps', higher_is_better=True)
self.output_perf_value(description='vid_in_framerate_received',
value=self._get_data_from_jmifile(
'framerate_received', jmidata),
units='fps', higher_is_better=True)
self.output_perf_value(description='vid_out_framerate_sent',
value=self._get_data_from_jmifile('framerate_sent', jmidata),
units='fps', higher_is_better=True)
self.output_perf_value(description='vid_in_frame_width',
value=self._get_data_from_jmifile(
'video_received_frame_width', jmidata),
units='px', higher_is_better=True)
self.output_perf_value(description='vid_out_frame_width',
value=self._get_data_from_jmifile(
'video_sent_frame_width', jmidata),
units='px', higher_is_better=True)
self.output_perf_value(description='vid_out_encode_cpu_usage',
value=self._get_data_from_jmifile(
'video_encode_cpu_usage', jmidata),
units='percent', higher_is_better=False)
total_vid_packets_sent = self._get_sum('video_packets_sent', jmidata)
total_vid_packets_lost = self._get_sum('video_packets_lost', jmidata)
lost_packet_percentage = float(total_vid_packets_lost)*100/ \
float(total_vid_packets_sent) if \
total_vid_packets_sent else 0
self.output_perf_value(description='lost_packet_percentage',
value=lost_packet_percentage, units='percent',
higher_is_better=False)
self.output_perf_value(description='cpu_usage_jmi',
value=self._get_data_from_jmifile('cpu_percent', jmidata),
units='percent', higher_is_better=False)
self.output_perf_value(description='renderer_cpu_usage',
value=self._get_data_from_jmifile(
'renderer_cpu_percent', jmidata),
units='percent', higher_is_better=False)
self.output_perf_value(description='browser_cpu_usage',
value=self._get_data_from_jmifile(
'browser_cpu_percent', jmidata),
units='percent', higher_is_better=False)
self.output_perf_value(description='gpu_cpu_usage',
value=self._get_data_from_jmifile(
'gpu_cpu_percent', jmidata),
units='percent', higher_is_better=False)
self.output_perf_value(description='active_streams',
value=self._get_data_from_jmifile(
'num_active_vid_in_streams', jmidata),
units='count', higher_is_better=True)
def initialize(self, host):
"""
Initializes common test properties.
@param host: a host object representing the DUT.
"""
super(enterprise_CFM_Perf, self).initialize(host)
self.system_facade = self._facade_factory.create_system_facade()
metrics = system_metrics_collector.create_default_metric_set(
self.system_facade)
metrics.append(ParticipantCountMetric(self.cfm_facade))
self.metrics_collector = (system_metrics_collector.
SystemMetricsCollector(self.system_facade,
metrics))
def run_once(self, is_meeting=False):
"""Stays in a meeting/hangout and collects perf data."""
if is_meeting:
self.join_meeting()
else:
self.start_hangout()
self.collect_perf_data()
if is_meeting:
self.cfm_facade.end_meeting_session()
else:
self.cfm_facade.end_hangout_session()
self.upload_jmidata()