From patchwork Thu Sep 22 15:38:22 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul Larson X-Patchwork-Id: 4276 Return-Path: X-Original-To: patchwork@peony.canonical.com Delivered-To: patchwork@peony.canonical.com Received: from fiordland.canonical.com (fiordland.canonical.com [91.189.94.145]) by peony.canonical.com (Postfix) with ESMTP id C712F23EF6 for ; Thu, 22 Sep 2011 15:38:26 +0000 (UTC) Received: from mail-fx0-f52.google.com (mail-fx0-f52.google.com [209.85.161.52]) by fiordland.canonical.com (Postfix) with ESMTP id AF25CA1867C for ; Thu, 22 Sep 2011 15:38:26 +0000 (UTC) Received: by fxe23 with SMTP id 23so4023610fxe.11 for ; Thu, 22 Sep 2011 08:38:26 -0700 (PDT) Received: by 10.223.5.76 with SMTP id 12mr3208595fau.103.1316705906473; Thu, 22 Sep 2011 08:38:26 -0700 (PDT) X-Forwarded-To: linaro-patchwork@canonical.com X-Forwarded-For: patch@linaro.org linaro-patchwork@canonical.com Delivered-To: patches@linaro.org Received: by 10.152.18.198 with SMTP id y6cs173042lad; Thu, 22 Sep 2011 08:38:26 -0700 (PDT) Received: by 10.216.178.144 with SMTP id f16mr2307337wem.104.1316705905844; Thu, 22 Sep 2011 08:38:25 -0700 (PDT) Received: from indium.canonical.com (indium.canonical.com. [91.189.90.7]) by mx.google.com with ESMTPS id e47si7402898wed.137.2011.09.22.08.38.25 (version=TLSv1/SSLv3 cipher=OTHER); Thu, 22 Sep 2011 08:38:25 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of bounces@canonical.com designates 91.189.90.7 as permitted sender) client-ip=91.189.90.7; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of bounces@canonical.com designates 91.189.90.7 as permitted sender) smtp.mail=bounces@canonical.com Received: from ackee.canonical.com ([91.189.89.26]) by indium.canonical.com with esmtp (Exim 4.71 #1 (Debian)) id 1R6lM0-00057E-SG for ; Thu, 22 Sep 2011 15:38:25 +0000 Received: from ackee.canonical.com (localhost [127.0.0.1]) by ackee.canonical.com (Postfix) with ESMTP id 863AEE185B for ; Thu, 22 Sep 2011 15:38:22 +0000 (UTC) MIME-Version: 1.0 X-Launchpad-Project: lava-dispatcher X-Launchpad-Branch: ~linaro-validation/lava-dispatcher/trunk X-Launchpad-Message-Rationale: Subscriber X-Launchpad-Branch-Revision-Number: 118 X-Launchpad-Notification-Type: branch-revision To: Linaro Patch Tracker From: noreply@launchpad.net Subject: [Branch ~linaro-validation/lava-dispatcher/trunk] Rev 118: Support lava-android-test in lava-dispatcher for android testing Message-Id: <20110922153822.12195.15423.launchpad@ackee.canonical.com> Date: Thu, 22 Sep 2011 15:38:22 -0000 Reply-To: noreply@launchpad.net Sender: bounces@canonical.com Errors-To: bounces@canonical.com Precedence: bulk X-Generated-By: Launchpad (canonical.com); Revision="13996"; Instance="initZopeless config overlay" X-Launchpad-Hash: 6b0ef54b9f7ab2f95750e3f0023c46be9553d4e7 Merge authors: Yongqin Liu (liuyq0307) Yongqin Liu (liuyq0307) Related merge proposals: https://code.launchpad.net/~liuyq0307/lava-dispatcher/lava-android-test-new/+merge/76240 proposed by: Yongqin Liu (liuyq0307) review: Needs Fixing - Spring Zhang (qzhang) ------------------------------------------------------------ revno: 118 [merge] committer: Paul Larson branch nick: big-dispatcher-merge timestamp: Thu 2011-09-22 09:55:52 -0500 message: Support lava-android-test in lava-dispatcher for android testing added: doc/lava-android-test-leb-panda.json lava_dispatcher/actions/lava-android-test.py modified: lava_dispatcher/android_client.py --- lp:lava-dispatcher https://code.launchpad.net/~linaro-validation/lava-dispatcher/trunk You are subscribed to branch lp:lava-dispatcher. To unsubscribe from this branch go to https://code.launchpad.net/~linaro-validation/lava-dispatcher/trunk/+edit-subscription === added file 'doc/lava-android-test-leb-panda.json' --- doc/lava-android-test-leb-panda.json 1970-01-01 00:00:00 +0000 +++ doc/lava-android-test-leb-panda.json 2011-09-20 06:14:43 +0000 @@ -0,0 +1,54 @@ +{ + "job_name": "android_monkey_test2", + "image_type": "android", + "target": "panda01", + "timeout": 18000, + "actions": [ + { + "command": "deploy_linaro_android_image", + "parameters": + { + "boot": "https://android-build.linaro.org/jenkins/job/linaro-android_leb-panda/246/artifact/build/out/target/product/pandaboard/boot.tar.bz2", + "system": "https://android-build.linaro.org/jenkins/job/linaro-android_leb-panda/246/artifact/build/out/target/product/pandaboard/system.tar.bz2", + "data": "https://android-build.linaro.org/jenkins/job/linaro-android_leb-panda/246/artifact/build/out/target/product/pandaboard/userdata.tar.bz2" + }, + "metadata": + { + "rootfs.type": "android", + "rootfs.build": "246" + } + }, + { + "command": "boot_linaro_android_image" + }, + { + "command": "lava_android_test_install", + "parameters": + { + "tests": ["monkey", "0xbench"] + } + }, + { + "command": "lava_android_test_run", + "parameters": + { + "test_name": "monkey" + } + }, + { + "command": "lava_android_test_run", + "parameters": + { + "test_name": "0xbench" + } + }, + { + "command": "submit_results_on_host", + "parameters": + { + "server": "http://validation.linaro.org/lava-server/RPC2/", + "stream": "/anonymous/lava-android-leb-panda/" + } + } + ] +} === added file 'lava_dispatcher/actions/lava-android-test.py' --- lava_dispatcher/actions/lava-android-test.py 1970-01-01 00:00:00 +0000 +++ lava_dispatcher/actions/lava-android-test.py 2011-09-20 06:14:43 +0000 @@ -0,0 +1,86 @@ +#!/usr/bin/python + +# Copyright (C) 2011 Linaro Limited +# +# Author: Linaro Validation Team +# +# This file is part of LAVA Dispatcher. +# +# LAVA Dispatcher is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# LAVA Dispatcher is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, see . +import sys +import pexpect +import time +from datetime import datetime +from lava_dispatcher.actions import BaseAction +from lava_dispatcher.client import OperationFailed, NetworkError + +class AndroidTestAction(BaseAction): + + def wait_devices_attached(self, dev_name): + for count in range(3): + if self.check_device_state(dev_name): + return + time.sleep(1) + + raise NetworkError("The android device(%s) isn't attached" % self.client.hostname) + + def check_device_state(self, dev_name): + (output, rc) = pexpect.run('adb devices', timeout=None, logfile=sys.stdout, withexitstatus=True) + if rc != 0: + return False + expect_line = '%s\tdevice' % dev_name + for line in output.splitlines(): + if line.strip() == expect_line: + return True + return False + + def check_lava_android_test_installed(self): + rc = pexpect.run('which lava-android-test', timeout=None, logfile=sys.stdout, withexitstatus=True)[1] + if rc != 0: + raise OperationFailed('lava-android-test has not been installed') + + def is_ready_for_test(self): + self.check_lava_android_test_installed() + dev_name = self.client.android_adb_connect_over_default_nic_ip() + if dev_name is None: + raise NetworkError("The android device(%s) isn't attached over tcpip" % self.client.hostname) + + self.wait_devices_attached(dev_name) + self.client.wait_home_screen() + return dev_name + +class cmd_lava_android_test_run(AndroidTestAction): + def run(self, test_name, timeout= -1): + #Make sure in test image now + dev_name = self.is_ready_for_test() + bundle_name = test_name + "-" + datetime.now().strftime("%H%M%S") + cmd = 'lava-android-test run %s -s %s -o /tmp/%s/%s.bundle' % ( + test_name, dev_name, self.context.lava_result_dir, bundle_name) + + rc = pexpect.run(cmd, timeout=None, logfile=sys.stdout, withexitstatus=True)[1] + if rc != 0: + raise OperationFailed("Failed to run test case(%s) on device(%s) with return value: %s" % (test_name, dev_name, rc)) + +class cmd_lava_android_test_install(AndroidTestAction): + """ + lava-test deployment to test image rootfs by chroot + """ + def run(self, tests, timeout=2400): + dev_name = self.is_ready_for_test() + for test in tests: + cmd = 'lava-android-test install %s -s %s' % (test, dev_name) + rc = pexpect.run(cmd, timeout=None, logfile=sys.stdout, withexitstatus=True)[1] + if rc != 0: + raise OperationFailed("Failed to install test case(%s) on device(%s) with return value: %s" % (test, dev_name, rc)) + === modified file 'lava_dispatcher/android_client.py' --- lava_dispatcher/android_client.py 2011-09-08 04:28:39 +0000 +++ lava_dispatcher/android_client.py 2011-09-20 06:14:43 +0000 @@ -19,17 +19,19 @@ import pexpect import sys -from lava_dispatcher.client import LavaClient, OperationFailed +import time +from lava_dispatcher.client import LavaClient, OperationFailed, NetworkError, GeneralError + from utils import string_to_list class LavaAndroidClient(LavaClient): - def run_adb_shell_command(self, dev_id, cmd, response, timeout=-1): + def run_adb_shell_command(self, dev_id, cmd, response, timeout= -1): adb_cmd = "adb -s %s shell %s" % (dev_id, cmd) try: adb_proc = pexpect.spawn(adb_cmd, logfile=sys.stdout) - id = adb_proc.expect([response, pexpect.EOF], timeout=timeout) - if id == 0: + match_id = adb_proc.expect([response, pexpect.EOF], timeout=timeout) + if match_id == 0: return True except pexpect.TIMEOUT: pass @@ -39,8 +41,8 @@ """ Check that we are in a shell on the test image """ self.proc.sendline("") - id = self.proc.expect([self.tester_str , pexpect.TIMEOUT]) - if id == 1: + match_id = self.proc.expect([self.tester_str , pexpect.TIMEOUT]) + if match_id == 1: raise OperationFailed def boot_linaro_android_image(self): @@ -60,6 +62,9 @@ self.in_test_shell() self.proc.sendline("export PS1=\"root@linaro: \"") + self.enable_adb_over_tcpip() + self.android_adb_disconnect_over_default_nic_ip() + def android_logcat_clear(self): cmd = "logcat -c" self.proc.sendline(cmd) @@ -68,12 +73,12 @@ cmd = "logcat" self.proc.sendline(cmd) - def android_logcat_monitor(self, pattern, timeout=-1): + def android_logcat_monitor(self, pattern, timeout= -1): self.android_logcat_stop() cmd = 'logcat' self.proc.sendline(cmd) - id = self.proc.expect(pattern, timeout=timeout) - if id == 0: + match_id = self.proc.expect(pattern, timeout=timeout) + if match_id == 0: return True else: return False @@ -90,45 +95,90 @@ cmd = "adb connect %s" % dev_ip adb_proc = pexpect.spawn(cmd, timeout=300, logfile=sys.stdout) - id = adb_proc.expect([pattern1, pattern2, pattern3, pexpect.EOF]) - if id == 0: + match_id = adb_proc.expect([pattern1, pattern2, pattern3, pexpect.EOF]) + if match_id == 0 or match_id == 1: dev_name = adb_proc.match.groups()[0] - return True, dev_name + return dev_name else: - return False, None + return None def android_adb_disconnect(self, dev_ip): cmd = "adb disconnect %s" % dev_ip adb_proc = pexpect.run(cmd, timeout=300, logfile=sys.stdout) def check_adb_status(self): + device_ip = self.get_default_nic_ip() + if device_ip is not None: + dev_name = self.android_adb_connect(device_ip) + if dev_name is not None: + print "dev_name = " + dev_name + result = self.run_adb_shell_command(dev_name, "echo 1", "1") + self.android_adb_disconnect(device_ip) + return result + return False + + def get_default_nic_ip(self): # XXX: IP could be assigned in other way in the validation farm network_interface = self.default_network_interface + ip = None try: - self.run_cmd_tester( - 'netcfg %s dhcp' % network_interface, timeout=60) + ip = self._get_default_nic_ip_by_ifconfig(network_interface) except: - print "netcfg %s dhcp exception" % network_interface - return False - + pass + + if ip is None: + self.get_ip_via_dhcp(network_interface) + ip = self._get_default_nic_ip_by_ifconfig(network_interface) + return ip + + def _get_default_nic_ip_by_ifconfig(self, nic_name): # Check network ip and setup adb connection - ip_pattern = "(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})" - cmd = "ifconfig %s" % network_interface + ip_pattern = "%s: ip (\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}) mask" % nic_name + cmd = "ifconfig %s" % nic_name self.proc.sendline('') self.proc.sendline(cmd) + match_id = 0 try: - id = self.proc.expect([ip_pattern, pexpect.EOF], timeout=60) - except: - print "ifconfig can not match ip pattern" - return False - if id == 0: + match_id = self.proc.expect([ip_pattern, pexpect.EOF], timeout=60) + except Exception as e: + raise NetworkError("ifconfig can not match ip pattern for %s:%s" % (nic_name, e)) + + if match_id == 0: match_group = self.proc.match.groups() if len(match_group) > 0: - device_ip = match_group[0] - adb_status, dev_name = self.android_adb_connect(device_ip) - if adb_status == True: - print "dev_name = " + dev_name - result = self.run_adb_shell_command(dev_name, "echo 1", "1") - self.android_adb_disconnect(device_ip) - return result - return False + return match_group[0] + return None + + def get_ip_via_dhcp(self, nic): + try: + self.run_cmd_tester('netcfg %s dhcp' % nic, timeout=60) + except: + raise NetworkError("netcfg %s dhcp exception" % nic) + + + def android_adb_connect_over_default_nic_ip(self): + dev_ip = self.get_default_nic_ip() + if dev_ip is not None: + return self.android_adb_connect(dev_ip) + + def android_adb_disconnect_over_default_nic_ip(self): + dev_ip = self.get_default_nic_ip() + if dev_ip is not None: + self.android_adb_disconnect(dev_ip) + + def enable_adb_over_tcpip(self): + self.proc.sendline('echo 0>/sys/class/android_usb/android0/enable') + self.proc.sendline('setprop service.adb.tcp.port 5555') + self.proc.sendline('stop adbd') + self.proc.sendline('start adbd') + + def wait_home_screen(self): + cmd = 'getprop init.svc.bootanim' + for count in range(100): + self.proc.sendline(cmd) + match_id = self.proc.expect('stopped') + if match_id == 0: + return True + time.sleep(1) + raise GeneralError('The home screen does not displayed') +