blob: cc8448c594cea71e70e00d8864ddd36939d50591 [file] [log] [blame]
# Copyright (c) 2014 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.
from collections import namedtuple
from itertools import chain
import sys
from mtlib.cros_remote import CrOSRemote
from mtlib.log import DeviceLog
from mtreplay import MTReplay
from test_case import TestCase
from test_factory import TestFactory
def UserConfirm(msg=None):
if msg:
print msg
print "Are you sure you wish to continue? [y/N]"
response = sys.stdin.readline()
if response.strip() not in ('y', 'Y', 'yes', 'Yes'):
sys.exit(1)
class TestRobot(object):
def __init__(self, ip, calib, slow=None, manual_fingertips=False):
self.ip = ip
self.slow = slow
self.manual_fingertips = manual_fingertips
self.remote = CrOSRemote(self.ip)
self.current_finger_size = None
self.current_tip_mask = None
self.dir = self.FindRobotDir()
name = self.remote.GetDeviceInfo().board_variant
self.spec_file = "device_specs/{}".format(name)
if not calib:
if not self.remote.Execute(["test", "-e", self.spec_file + ".p"],
cwd=self.dir) is not False:
calib = True
if calib:
UserConfirm("Starting calibration for new device")
cmd = "python calibrate_for_new_device.py " + self.spec_file
if manual_fingertips:
cmd = cmd + " --manual-fingertips"
self.Execute(cmd)
def FindRobotDir(self):
search_dirs = [
"/usr/lib64/python2.7/site-packages/touchbotII",
"/usr/lib/python2.7/site-packages/touchbotII",
"/usr/local/lib64/python2.7/site-packages/touchbotII",
"/usr/local/lib/python2.7/site-packages/touchbotII"]
for dir in search_dirs:
if self.remote.Execute("test -e %s/calibrate_for_new_device.py"
% dir) is not False:
return dir
print "Cannot find robot directory"
sys.exit(1)
def CheckFingersOn(self):
if not self.current_finger_size and not self.manual_fingertips:
print "Select finger size before gesture"
sys.exit(1)
def CheckFingersOff(self):
if self.current_finger_size and not self.manual_fingertips:
print "Select finger size before gesture"
sys.exit(1)
def CleanUp(self):
if self.manual_fingertips:
return
if self.current_finger_size is not None:
print "### Removing finger tips (size %d)" % self.current_finger_size
self.Execute("python manipulate_fingertips.py %s %d False --fast-check"
% (self.current_tip_mask, self.current_finger_size))
self.current_finger_size = None
self.current_tip_mask = None
def SetupFingerSize(self, size, tips=(1, 1, 1, 1)):
if self.manual_fingertips:
return
mask = " ".join(map(lambda i: str(i), tips))
fast_check = ""
if self.current_finger_size != size or self.current_tip_mask != mask:
if (self.current_finger_size is not None
and self.current_tip_mask is not None):
print "### Removing finger tips (size %d)" % self.current_finger_size
self.Execute("python manipulate_fingertips.py %s %d False --fast-check"
% (self.current_tip_mask, self.current_finger_size))
fast_check = "--fast-check"
print "### Picking finger tips (size %d)" % size
self.Execute("python manipulate_fingertips.py %s %d True %s"
% (mask, size, fast_check))
self.current_finger_size = size
self.current_tip_mask = mask
def Line(self, start, end, tips, speed, type, delay=0.0):
self.CheckFingersOn()
if self.slow:
speed = 5
self.ExecuteScript("line.py", start, end, tips, (speed, type, delay))
def Tap(self, pos, tips, count, delay=0.0):
self.CheckFingersOn()
self.ExecuteScript("tap.py", pos, tips, (count, "tap", delay))
def Click(self, pos, tips, size=1):
self.CheckFingersOff()
self.SetupFingerSize(size, tips)
self.ExecuteScript("click.py", pos, tips)
self.CleanUp()
def Execute(self, cmd):
return self.remote.SafeExecute(cmd, cwd=self.dir, interactive=True)
def ExecuteScript(self, file, *param_tuples):
base = ("python", file, self.spec_file + ".p")
args = map(lambda s: str(s), chain(base, *param_tuples))
cmd = " ".join(args)
self.Execute(cmd)
def ClearLog(self):
self.remote.Execute(
"/opt/google/touchpad/tpcontrol set \"Logging Reset\" 1")
def GetLog(self):
replay = MTReplay()
log = DeviceLog(self.ip, new=True)
return replay.TrimEvdev(log)
class RobotTestGenerator(object):
def __init__(self, ip, calib, slow, manual_fingertips, tests_dir):
self.tests_dir = tests_dir
self.robot = TestRobot(ip, calib, slow, manual_fingertips)
def GenerateCase(self, test_case):
print "Instructing robot to generate test", test_case.name
self.robot.ClearLog()
test_case.instruct_robot(self.robot)
log = self.robot.GetLog()
if not log:
print "Nothing happened... is the robot set up?"
return
factory = TestFactory(self.tests_dir)
case = factory.CreateTest(test_case.name, log, False)
def GenerateAll(self, glob, overwrite=False):
cases = RobotTestGenerator.DiscoverRobotCases(self.tests_dir, glob)
if not overwrite:
cases = filter(lambda c: not c.IsComplete(), cases)
expanded = []
for case in cases:
if case.is_virtual:
continue
# per default tests are performed with the finger size 1
if hasattr(case.instruct_robot, "finger_size"):
size = case.instruct_robot.finger_size
else:
size = 1
expanded.append((TestCase(self.tests_dir, case.name), size))
expanded.sort(key=lambda entry: entry[1])
print "Instructing robot to generate the following tests:"
for case, fingersize in expanded:
if fingersize is None:
print " - %s (custom)" % (case.name)
else:
print " - %s (%d)" % (case.name, fingersize)
UserConfirm()
# run tests with configured finger sizes
for case, fingersize in expanded:
if fingersize is None:
continue
self.robot.SetupFingerSize(fingersize)
self.GenerateCase(case)
self.robot.CleanUp()
# run tests that have customized finger size setup
for case, fingersize in expanded:
if fingersize is None:
self.GenerateCase(case)
@staticmethod
def DiscoverRobotCases(tests_dir, glob=None):
cases = TestCase.DiscoverTestCases(tests_dir, glob)
return filter(lambda c: c.instruct_robot is not None, cases)