[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
State Accepted
Headers show

Commit Message

Paul Larson Sept. 22, 2011, 3:38 p.m.
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 <paul.larson@canonical.com>
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

Patch

=== 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 <linaro-dev@lists.linaro.org>
+#
+# 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 <http://www.gnu.org/licenses>.
+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')
+