blob: 22f9361b3b67883bfea878030164cc710f372395 [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 logging
import os
import time
from autotest_lib.client.common_lib import error
from autotest_lib.client.common_lib import file_utils
from autotest_lib.client.common_lib.cros import system_metrics_collector
from autotest_lib.server.cros.cfm import cfm_base_test
from autotest_lib.server.cros.cfm.utils import bond_http_api
from autotest_lib.server.cros.cfm.utils import perf_metrics_collector
_BOT_PARTICIPANTS_COUNT = 10
_TOTAL_TEST_DURATION_SECONDS = 15 * 60 # 15 minutes
_DOWNLOAD_BASE = ('http://commondatastorage.googleapis.com/'
'chromiumos-test-assets-public/crowd/')
_VIDEO_NAME = 'crowd720_25frames.y4m'
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 _download_test_video(self):
"""
Downloads the test video to a temporary directory on host.
@return the remote path of the downloaded video.
"""
url = _DOWNLOAD_BASE + _VIDEO_NAME
local_path = os.path.join(self.tmpdir, _VIDEO_NAME)
logging.info('Downloading %s to %s', url, local_path)
file_utils.download_file(url, local_path)
# The directory returned by get_tmp_dir() is automatically deleted.
tmp_dir = self._host.get_tmp_dir()
remote_path = os.path.join(tmp_dir, _VIDEO_NAME)
# The temporary directory has mode 700 by default. Chrome runs with a
# different user so cannot access it unless we change the permissions.
logging.info('chmodding tmpdir %s to 755', tmp_dir)
self._host.run('chmod 755 %s' % tmp_dir)
logging.info('Sending %s to %s on DUT', local_path, remote_path)
self._host.send_file(local_path, remote_path)
os.remove(local_path)
return remote_path
def initialize(self, host, run_test_only=False, use_bond=True):
"""
Initializes common test properties.
@param host: a host object representing the DUT.
@param run_test_only: Whether to run only the test or to also perform
deprovisioning, enrollment and system reboot. See cfm_base_test.
@param use_bond: Whether to use BonD to add bots to the meeting. Useful
for local testing.
"""
super(enterprise_CFM_Perf, self).initialize(host, run_test_only)
self._host = host
self._use_bond = use_bond
system_facade = self._facade_factory.create_system_facade()
self._perf_metrics_collector = (
perf_metrics_collector.PerfMetricsCollector(
system_facade,
self.cfm_facade,
self.output_perf_value,
additional_system_metrics=[
ParticipantCountMetric(self.cfm_facade),
]))
def setup(self):
"""
Download video for fake media and restart Chrome with fake media flags.
This runs after initialize().
"""
super(enterprise_CFM_Perf, self).setup()
remote_video_path = self._download_test_video()
# Restart chrome with fake media flags.
extra_chrome_args=[
'--use-fake-device-for-media-stream',
'--use-file-for-fake-video-capture=%s' % remote_video_path
]
self.cfm_facade.restart_chrome_for_cfm(extra_chrome_args)
if self._use_bond:
self.bond = bond_http_api.BondHttpApi()
def run_once(self):
"""Joins a meeting and collects perf data."""
self.cfm_facade.wait_for_meetings_landing_page()
if self._use_bond:
meeting_code = self.bond.CreateConference()
logging.info('Started meeting "%s"', meeting_code)
self._add_bots(_BOT_PARTICIPANTS_COUNT, meeting_code)
self.cfm_facade.join_meeting_session(meeting_code)
else:
self.cfm_facade.start_meeting_session()
self.cfm_facade.unmute_mic()
self._perf_metrics_collector.start()
time.sleep(_TOTAL_TEST_DURATION_SECONDS)
self._perf_metrics_collector.stop()
self.cfm_facade.end_meeting_session()
self._perf_metrics_collector.upload_metrics()
def _add_bots(self, bot_count, meeting_code):
"""Adds bots to a meeting and configures audio and pinning settings.
If we were not able to start enough bots end the test run.
"""
botIds = self.bond.AddBotsRequest(
meeting_code,
bot_count,
_TOTAL_TEST_DURATION_SECONDS + 30);
if len(botIds) < bot_count:
# If we did not manage to start enough bots, free up the
# resources and end the test run.
self.bond.ExecuteScript('@all leave', meeting_code)
raise error.TestNAError("Not enough bot resources.\n"
"Wanted: %d. Started: %d" % (bot_count, len(botIds)))
# Configure philosopher audio for one bot.
self._start_philosopher_audio(botIds[0], meeting_code)
# Pin the CfM from one bot so the device always sends HD.
self.bond.ExecuteScript(
'@b%d pin_participant_by_name "Unknown"' % botIds[0], meeting_code)
# Explicitly request HD video from the CfM.
self.bond.ExecuteScript(
'@b%d set_resolution 1280 720' % botIds[0], meeting_code)
def _start_philosopher_audio(self, bot_id, meeting_code):
self.bond.ExecuteScript(
'@b%d start_philosopher_audio' % bot_id, meeting_code)