blob: 3ebe1258fd81c1a36cbdf21a0f403e47595351f1 [file] [log] [blame]
#!/usr/bin/env python
# Copyright 2015 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.
"""Starts or ends a station-based test.
This factory test invokes functions to setup or teardown a station-based
test list.
"""
import threading
import unittest
import factory_common # pylint: disable=unused-import
from cros.factory.device import device_utils
from cros.factory.test import countdown_timer
from cros.factory.test import factory
from cros.factory.test.i18n import test_ui as i18n_test_ui
from cros.factory.test import test_ui
from cros.factory.test import ui_templates
from cros.factory.utils.arg_utils import Arg
from cros.factory.utils import sync_utils
_CSS = """
.prompt {
font-size: 2em;
}
.warning {
color: red;
}
"""
_TITLE_START = i18n_test_ui.MakeI18nLabel('Start Station Test')
_TITLE_END = i18n_test_ui.MakeI18nLabel('End Station Test')
_ID_MSG_DIV = 'msg'
_ID_COUNTDOWN_DIV = 'countdown'
_STATE_HTML = """
<div id='%s'></div>
<div id='%s'></div>
""" % (_ID_MSG_DIV, _ID_COUNTDOWN_DIV)
_MSG_INSERT = i18n_test_ui.MakeI18nLabelWithClass(
'Please attach DUT.', 'prompt')
_MSG_PRESS_SPACE = i18n_test_ui.MakeI18nLabelWithClass(
'Press SPACE to start the test.', 'prompt')
_MSG_PRESS_SPACE_TO_END = i18n_test_ui.MakeI18nLabelWithClass(
'Press SPACE to end the test.', 'prompt')
_MSG_SEND_RESULT = i18n_test_ui.MakeI18nLabelWithClass(
'Sending test results to shopfloor...', 'prompt')
_MSG_REMOVE_DUT = i18n_test_ui.MakeI18nLabelWithClass(
'Please remove DUT.', 'prompt')
_MSG_RESTART_TESTS = i18n_test_ui.MakeI18nLabelWithClass(
'Restarting all tests...', 'prompt')
class StationEntry(unittest.TestCase):
"""The factory test to start station test process."""
ARGS = [
Arg('start_station_tests', bool,
'To start or stop the factory station tests.',
default=True, optional=True),
Arg('prompt_start', bool,
'Prompt for spacebar before starting test.',
default=False, optional=True),
Arg('timeout_secs', int,
'Timeout for waiting the device. Set to None for waiting forever.',
default=None, optional=True),
Arg('disconnect_dut', bool,
'Ask operator to disconnect DUT or not',
default=True, optional=True),
# TODO(hungte) When device_data and dut_storage has been synced, we should
# change this to "clear_dut_storage" since testlog will still try to
# reload device data from storage before invocation of next test.
Arg('load_dut_storage', bool,
'To load DUT storage into station session (DeviceData).',
default=True, optional=True),
]
def setUp(self):
self._dut = device_utils.CreateDUTInterface()
self._state = factory.get_state_instance()
self._ui = test_ui.UI()
self._ui.AppendCSS(_CSS)
self._template = ui_templates.OneSection(self._ui)
self._template.SetTitle(_TITLE_START if self.args.start_station_tests else
_TITLE_END)
self._space_event = threading.Event()
def RestartAllTests(self):
self._state.ScheduleRestart()
def SendTestResult(self):
self._dut.hooks.SendTestResult(self._state.get_test_states())
def runTest(self):
self._template.SetState(_STATE_HTML)
self._ui.Run(blocking=False)
self._ui.BindKey(test_ui.SPACE_KEY, lambda _: self._space_event.set())
if self.args.start_station_tests:
# Clear dut.info data.
factory.console.info('Clearing dut.info data...')
self._dut.info.Invalidate()
self.Start()
# TODO(hungte): Change to reload all dut.storage into device data.
if self.args.load_dut_storage:
factory.console.info('Loading serial numbers...')
self._dut.info.GetAllSerialNumbers()
else:
self.End()
# Clear dut.info data.
factory.console.info('Clearing dut.info data...')
self._dut.info.Invalidate()
def Start(self):
self._ui.SetHTML(_MSG_INSERT, id=_ID_MSG_DIV)
disable_event = threading.Event()
if self.args.timeout_secs:
countdown_timer.StartCountdownTimer(
self.args.timeout_secs,
lambda: (self._ui.Fail('DUT is not connected in %d seconds' %
self.args.timeout_secs)),
self._ui,
_ID_COUNTDOWN_DIV,
disable_event=disable_event)
def _IsReady():
try:
self._dut.CheckCall(['true'])
return True
except: # pylint: disable=bare-except
return False
sync_utils.WaitFor(_IsReady, self.args.timeout_secs, poll_interval=1)
disable_event.set()
if self.args.prompt_start:
self._ui.SetHTML(_MSG_PRESS_SPACE, id=_ID_MSG_DIV)
sync_utils.WaitFor(self._space_event.isSet, None)
self._space_event.clear()
def End(self):
self._ui.SetHTML(_MSG_SEND_RESULT, id=_ID_MSG_DIV)
self.SendTestResult()
self._ui.SetHTML(_MSG_REMOVE_DUT, id=_ID_MSG_DIV)
if not self._dut.link.IsLocal():
if self.args.disconnect_dut:
sync_utils.WaitFor(lambda: not self._dut.link.IsReady(),
self.args.timeout_secs,
poll_interval=1)
else:
self._ui.SetHTML(_MSG_PRESS_SPACE_TO_END, id=_ID_MSG_DIV)
sync_utils.WaitFor(self._space_event.isSet, None)
self._space_event.clear()
self._ui.SetHTML(_MSG_RESTART_TESTS, id=_ID_MSG_DIV)
# TODO(hungte): Clear all device data.
self.RestartAllTests()