blob: 334dd1151e87f75198f43c52ce4808e79e5618c8 [file] [log] [blame]
# -*- coding: utf-8 -*-
# Copyright (c) 2012 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.
# DESCRIPTION :
#
# There are test situations that we want to execute certain commands and
# check whether the commands run correctly by human judgement. This is a
# base class provides a generic framework to itemize tests in this category.
import gtk
from autotest_lib.client.bin import test
from autotest_lib.client.cros import factory
from autotest_lib.client.common_lib import error
from autotest_lib.client.common_lib import utils
from autotest_lib.client.cros.factory import task
from autotest_lib.client.cros.factory import ui as ful
def _make_decision_widget(message, key_action_mapping):
'''Returns a widget that display the message and bind proper functions.
@param message: Message to display on the widget.
@param key_release_callback:
A dict of tuples indicates functions and keys
in the format {gtk_keyval: (function, function_parameters)}
@return A widget binds with proper functions.
'''
widget = gtk.VBox()
widget.add(ful.make_label(message))
def key_release_callback(_, event):
if event.keyval in key_action_mapping:
callback, callback_parameters = key_action_mapping[event.keyval]
callback(*callback_parameters)
return True
widget.key_callback = key_release_callback
return widget
class FactoryLineItemCheckBase(test.test):
version = 1
def run_once(self):
raise NotImplementedError
def _next_item(self):
self._item = self._item + 1
if self._item < len(self._items):
# Update the UI.
widget, cmd_line = self._items[self._item]
self._switch_widget(widget)
# Execute command after UI is updated.
if cmd_line:
task.schedule(self._run_cmd, cmd_line)
else:
# No more item.
gtk.main_quit()
def _switch_widget(self, widget_to_display):
if widget_to_display is not self.last_widget:
if self.last_widget:
self.last_widget.hide()
self.test_widget.remove(self.last_widget)
self.last_widget = widget_to_display
self.test_widget.add(widget_to_display)
self.test_widget.show_all()
else:
return
def _register_callbacks(self, window):
def key_press_callback(widget, event):
if hasattr(self.last_widget, 'key_callback'):
return self.last_widget.key_callback(widget, event)
return False
window.connect('key-press-event', key_press_callback)
window.add_events(gtk.gdk.KEY_PRESS_MASK)
def _run_cmd(self, cmd):
factory.log('Running command [%s]' % cmd)
ret = utils.system_output(cmd)
factory.log('Command returns [%s]' % ret)
def _fail_test(self, cmd):
raise error.TestFail('Failed with command [%s]' % cmd)
def _check_line_items(self, item_tuples):
factory.log('%s run_once' % self.__class__)
# Initialize variables.
self.last_widget = None
self.item_tuples = item_tuples
# Line item in (widget, command) format.
self._items = []
# Set up the widgets.
# There are two types of widgets, one gives instructions without
# judgement, the other decides whether the result matches expectations.
self.widgets = []
for idx, _tuple in enumerate(self.item_tuples):
judge, cmd_line, prompt_message = _tuple
if judge:
# Widget involves human judgement.
key_action_mapping = {
gtk.keysyms.Return: (self._next_item, []),
gtk.keysyms.Tab: (self._fail_test, [cmd_line])}
self.widgets.append(_make_decision_widget(
prompt_message + ful.USER_PASS_FAIL_SELECT_STR,
key_action_mapping))
self._items.append(
(self.widgets[idx], cmd_line))
else:
key_action_mapping = {
gtk.keysyms.space: (self._next_item, [])}
self.widgets.append(_make_decision_widget(
prompt_message,
key_action_mapping))
self._items.append((self.widgets[idx], None))
factory.log('Item %d: %s' % (idx, cmd_line))
self.test_widget = gtk.VBox()
self._item = -1
self._next_item()
ful.run_test_widget(
self.job,
self.test_widget,
window_registration_callback=self._register_callbacks)