1# Copyright (C) 2012 Google Inc. All rights reserved. 2# 3# Redistribution and use in source and binary forms, with or without 4# modification, are permitted provided that the following conditions are 5# met: 6# 7# * Redistributions of source code must retain the above copyright 8# notice, this list of conditions and the following disclaimer. 9# * Redistributions in binary form must reproduce the above 10# copyright notice, this list of conditions and the following disclaimer 11# in the documentation and/or other materials provided with the 12# distribution. 13# * Neither the name of Google Inc. nor the names of its 14# contributors may be used to endorse or promote products derived from 15# this software without specific prior written permission. 16# 17# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 29import optparse 30import StringIO 31import time 32import webkitpy.thirdparty.unittest2 as unittest 33import sys 34 35from webkitpy.common.system import executive_mock 36from webkitpy.common.system.executive_mock import MockExecutive2 37from webkitpy.common.system.systemhost_mock import MockSystemHost 38 39from webkitpy.layout_tests.port import android 40from webkitpy.layout_tests.port import chromium_port_testcase 41from webkitpy.layout_tests.port import driver 42from webkitpy.layout_tests.port import driver_unittest 43from webkitpy.tool.mocktool import MockOptions 44 45 46# Any "adb" commands will be interpret by this class instead of executing actual 47# commansd on the file system, which we don't want to do. 48class MockAndroidDebugBridge: 49 def __init__(self, device_count): 50 self._device_count = device_count 51 self._last_command = None 52 53 # Local public methods. 54 55 def run_command(self, args): 56 self._last_command = ' '.join(args) 57 if args[0].startswith('path'): 58 if args[0] == 'path1': 59 return '' 60 if args[0] == 'path2': 61 return 'version 1.1' 62 63 return 'version 1.0' 64 65 if args[0] == 'adb': 66 if len(args) > 1 and args[1] == 'version': 67 return 'version 1.0' 68 if len(args) > 1 and args[1] == 'devices': 69 return self._get_device_output() 70 if len(args) > 3 and args[3] == 'command': 71 return 'mockoutput' 72 if len(args) > 5 and args[5] == 'battery': 73 return 'level: 99' 74 75 return '' 76 77 def last_command(self): 78 return self._last_command 79 80 # Local private methods. 81 82 def _get_device_output(self): 83 serials = ['123456789ABCDEF0', '123456789ABCDEF1', '123456789ABCDEF2', 84 '123456789ABCDEF3', '123456789ABCDEF4', '123456789ABCDEF5'] 85 output = 'List of devices attached\n' 86 for serial in serials[:self._device_count]: 87 output += '%s\tdevice\n' % serial 88 return output 89 90 91class AndroidCommandsTest(unittest.TestCase): 92 def setUp(self): 93 android.AndroidCommands._adb_command_path = None 94 android.AndroidCommands._adb_command_path_options = ['adb'] 95 96 def make_executive(self, device_count): 97 self._mock_executive = MockAndroidDebugBridge(device_count) 98 return MockExecutive2(run_command_fn=self._mock_executive.run_command) 99 100 def make_android_commands(self, device_count, serial): 101 return android.AndroidCommands(self.make_executive(device_count), serial) 102 103 # The "adb" binary with the latest version should be used. 104 def serial_test_adb_command_path(self): 105 executive = self.make_executive(0) 106 107 android.AndroidCommands.set_adb_command_path_options(['path1', 'path2', 'path3']) 108 self.assertEqual('path2', android.AndroidCommands.adb_command_path(executive)) 109 110 # The used adb command should include the device's serial number, and get_serial() should reflect this. 111 def test_adb_command_and_get_serial(self): 112 android_commands = self.make_android_commands(1, '123456789ABCDEF0') 113 self.assertEquals(['adb', '-s', '123456789ABCDEF0'], android_commands.adb_command()) 114 self.assertEquals('123456789ABCDEF0', android_commands.get_serial()) 115 116 # Running an adb command should return the command's output. 117 def test_run_command(self): 118 android_commands = self.make_android_commands(1, '123456789ABCDEF0') 119 120 output = android_commands.run(['command']) 121 self.assertEquals('adb -s 123456789ABCDEF0 command', self._mock_executive.last_command()) 122 self.assertEquals('mockoutput', output) 123 124 # Test that the convenience methods create the expected commands. 125 def test_convenience_methods(self): 126 android_commands = self.make_android_commands(1, '123456789ABCDEF0') 127 128 android_commands.file_exists('/tombstones') 129 self.assertEquals('adb -s 123456789ABCDEF0 shell ls /tombstones', self._mock_executive.last_command()) 130 131 android_commands.push('foo', 'bar') 132 self.assertEquals('adb -s 123456789ABCDEF0 push foo bar', self._mock_executive.last_command()) 133 134 android_commands.pull('bar', 'foo') 135 self.assertEquals('adb -s 123456789ABCDEF0 pull bar foo', self._mock_executive.last_command()) 136 137 138class AndroidPortTest(chromium_port_testcase.ChromiumPortTestCase): 139 port_name = 'android' 140 port_maker = android.AndroidPort 141 142 def make_port(self, **kwargs): 143 port = super(AndroidPortTest, self).make_port(**kwargs) 144 port._mock_adb = MockAndroidDebugBridge(kwargs.get('device_count', 1)) 145 port._executive = MockExecutive2(run_command_fn=port._mock_adb.run_command) 146 return port 147 148 def make_wdiff_available(self, port): 149 port._wdiff_available = True 150 port._host_port._wdiff_available = True 151 152 # Test that content_shell currently is the only supported driver. 153 def test_non_content_shell_driver(self): 154 self.assertRaises(self.make_port, options=optparse.Values({'driver_name': 'foobar'})) 155 156 # Test that the number of child processes to create depends on the devices. 157 def test_default_child_processes(self): 158 port_default = self.make_port(device_count=5) 159 port_fixed_device = self.make_port(device_count=5, options=optparse.Values({'adb_device': '123456789ABCDEF9'})) 160 161 self.assertEquals(5, port_default.default_child_processes()) 162 self.assertEquals(1, port_fixed_device.default_child_processes()) 163 164 # Test that an HTTP server indeed is required by Android (as we serve all tests over them) 165 def test_requires_http_server(self): 166 self.assertTrue(self.make_port(device_count=1).requires_http_server()) 167 168 # Tests the default timeouts for Android, which are different than the rest of Chromium. 169 def test_default_timeout_ms(self): 170 self.assertEqual(self.make_port(options=optparse.Values({'configuration': 'Release'})).default_timeout_ms(), 10000) 171 self.assertEqual(self.make_port(options=optparse.Values({'configuration': 'Debug'})).default_timeout_ms(), 10000) 172 173 174class ChromiumAndroidDriverTest(unittest.TestCase): 175 def setUp(self): 176 self._mock_adb = MockAndroidDebugBridge(1) 177 self._mock_executive = MockExecutive2(run_command_fn=self._mock_adb.run_command) 178 179 android_commands = android.AndroidCommands(self._mock_executive, '123456789ABCDEF0') 180 self._port = android.AndroidPort(MockSystemHost(executive=self._mock_executive), 'android') 181 self._driver = android.ChromiumAndroidDriver(self._port, worker_number=0, 182 pixel_tests=True, driver_details=android.ContentShellDriverDetails(), android_devices=self._port._devices) 183 184 # The cmd_line() method in the Android port is used for starting a shell, not the test runner. 185 def test_cmd_line(self): 186 self.assertEquals(['adb', '-s', '123456789ABCDEF0', 'shell'], self._driver.cmd_line(False, [])) 187 188 # Test that the Chromium Android port can interpret Android's shell output. 189 def test_read_prompt(self): 190 self._driver._server_process = driver_unittest.MockServerProcess(lines=['root@android:/ # ']) 191 self.assertIsNone(self._driver._read_prompt(time.time() + 1)) 192 self._driver._server_process = driver_unittest.MockServerProcess(lines=['$ ']) 193 self.assertIsNone(self._driver._read_prompt(time.time() + 1)) 194 195 196class ChromiumAndroidDriverTwoDriversTest(unittest.TestCase): 197 # Test two drivers getting the right serial numbers, and that we disregard per-test arguments. 198 def test_two_drivers(self): 199 mock_adb = MockAndroidDebugBridge(2) 200 mock_executive = MockExecutive2(run_command_fn=mock_adb.run_command) 201 202 port = android.AndroidPort(MockSystemHost(executive=mock_executive), 'android') 203 driver0 = android.ChromiumAndroidDriver(port, worker_number=0, pixel_tests=True, 204 driver_details=android.ContentShellDriverDetails(), android_devices=port._devices) 205 driver1 = android.ChromiumAndroidDriver(port, worker_number=1, pixel_tests=True, 206 driver_details=android.ContentShellDriverDetails(), android_devices=port._devices) 207 208 self.assertEqual(['adb', '-s', '123456789ABCDEF0', 'shell'], driver0.cmd_line(True, [])) 209 self.assertEqual(['adb', '-s', '123456789ABCDEF1', 'shell'], driver1.cmd_line(True, ['anything'])) 210 211 212class ChromiumAndroidTwoPortsTest(unittest.TestCase): 213 # Test that the driver's command line indeed goes through to the driver. 214 def test_options_with_two_ports(self): 215 mock_adb = MockAndroidDebugBridge(2) 216 mock_executive = MockExecutive2(run_command_fn=mock_adb.run_command) 217 218 port0 = android.AndroidPort(MockSystemHost(executive=mock_executive), 219 'android', options=MockOptions(additional_drt_flag=['--foo=bar'])) 220 port1 = android.AndroidPort(MockSystemHost(executive=mock_executive), 221 'android', options=MockOptions(driver_name='content_shell')) 222 223 self.assertEqual(1, port0.driver_cmd_line().count('--foo=bar')) 224 self.assertEqual(0, port1.driver_cmd_line().count('--create-stdin-fifo')) 225