blob: 173251a2f598c47a39cf3247912a66fb64b20ce7 [file] [log] [blame]
Josh Gao9b6522b2018-08-07 14:31:17 -07001#!/usr/bin/env python3
Dan Albert8e1fdd72015-07-24 17:08:33 -07002#
3# Copyright (C) 2015 The Android Open Source Project
4#
5# Licensed under the Apache License, Version 2.0 (the "License");
6# you may not use this file except in compliance with the License.
7# You may obtain a copy of the License at
8#
9# http://www.apache.org/licenses/LICENSE-2.0
10#
11# Unless required by applicable law or agreed to in writing, software
12# distributed under the License is distributed on an "AS IS" BASIS,
13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14# See the License for the specific language governing permissions and
15# limitations under the License.
16#
17"""Tests for the adb program itself.
18
19This differs from things in test_device.py in that there is no API for these
20things. Most of these tests involve specific error messages or the help text.
21"""
Dan Albert8e1fdd72015-07-24 17:08:33 -070022
Spencer Low351ecd12015-10-14 17:32:44 -070023import contextlib
Spencer Low1ce06082015-09-16 20:45:53 -070024import os
Dan Albert8e1fdd72015-07-24 17:08:33 -070025import random
Luis Hector Chavez8b67c522018-04-17 19:25:33 -070026import select
Spencer Low351ecd12015-10-14 17:32:44 -070027import socket
28import struct
Dan Albert8e1fdd72015-07-24 17:08:33 -070029import subprocess
Spencer Low1ce06082015-09-16 20:45:53 -070030import threading
Dan Albert8e1fdd72015-07-24 17:08:33 -070031import unittest
32
Dan Albert8e1fdd72015-07-24 17:08:33 -070033
Luis Hector Chavez8b67c522018-04-17 19:25:33 -070034@contextlib.contextmanager
Luis Hector Chavezfbee0a92018-05-02 09:10:29 -070035def fake_adbd(protocol=socket.AF_INET, port=0):
36 """Creates a fake ADB daemon that just replies with a CNXN packet."""
Luis Hector Chavez8b67c522018-04-17 19:25:33 -070037
38 serversock = socket.socket(protocol, socket.SOCK_STREAM)
Luis Hector Chavezfbee0a92018-05-02 09:10:29 -070039 serversock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
Luis Hector Chavez8b67c522018-04-17 19:25:33 -070040 if protocol == socket.AF_INET:
41 serversock.bind(('127.0.0.1', port))
42 else:
43 serversock.bind(('::1', port))
44 serversock.listen(1)
45
46 # A pipe that is used to signal the thread that it should terminate.
47 readpipe, writepipe = os.pipe()
48
Josh Gao9b6522b2018-08-07 14:31:17 -070049 def _adb_packet(command: bytes, arg0: int, arg1: int, data: bytes) -> bytes:
Luis Hector Chavez56fe7532018-04-17 14:25:04 -070050 bin_command = struct.unpack('I', command)[0]
51 buf = struct.pack('IIIIII', bin_command, arg0, arg1, len(data), 0,
52 bin_command ^ 0xffffffff)
53 buf += data
54 return buf
55
Josh Gao9b6522b2018-08-07 14:31:17 -070056 def _handle(sock):
57 with contextlib.closing(sock) as serversock:
58 rlist = [readpipe, serversock]
59 cnxn_sent = {}
60 while True:
61 read_ready, _, _ = select.select(rlist, [], [])
62 for ready in read_ready:
63 if ready == readpipe:
64 # Closure pipe
65 serversock.shutdown(socket.SHUT_RDWR)
66 for f in rlist:
67 if isinstance(f, int):
68 os.close(f)
69 else:
70 f.close()
71 return
72 elif ready == serversock:
73 # Server socket
74 conn, _ = ready.accept()
75 rlist.append(conn)
76 else:
77 # Client socket
78 data = ready.recv(1024)
79 if not data or data.startswith(b'OPEN'):
80 if ready in cnxn_sent:
81 del cnxn_sent[ready]
82 ready.shutdown(socket.SHUT_RDWR)
83 ready.close()
84 rlist.remove(ready)
85 continue
Luis Hector Chavezfbee0a92018-05-02 09:10:29 -070086 if ready in cnxn_sent:
Josh Gao9b6522b2018-08-07 14:31:17 -070087 continue
88 cnxn_sent[ready] = True
89 ready.sendall(_adb_packet(b'CNXN', 0x01000001, 1024 * 1024,
90 b'device::ro.product.name=fakeadb'))
Luis Hector Chavez8b67c522018-04-17 19:25:33 -070091
92 port = serversock.getsockname()[1]
Josh Gao9b6522b2018-08-07 14:31:17 -070093 server_thread = threading.Thread(target=_handle, args=(serversock,))
Luis Hector Chavez8b67c522018-04-17 19:25:33 -070094 server_thread.start()
95
96 try:
97 yield port
98 finally:
99 os.close(writepipe)
100 server_thread.join()
101
102
Luis Hector Chavez454bc7c2018-04-20 10:31:29 -0700103@contextlib.contextmanager
104def adb_connect(unittest, serial):
105 """Context manager for an ADB connection.
106
107 This automatically disconnects when done with the connection.
108 """
109
110 output = subprocess.check_output(['adb', 'connect', serial])
Josh Gao9b6522b2018-08-07 14:31:17 -0700111 unittest.assertEqual(output.strip(),
112 'connected to {}'.format(serial).encode("utf8"))
Luis Hector Chavez454bc7c2018-04-20 10:31:29 -0700113
114 try:
115 yield
116 finally:
117 # Perform best-effort disconnection. Discard the output.
Luis Hector Chavezfbee0a92018-05-02 09:10:29 -0700118 subprocess.Popen(['adb', 'disconnect', serial],
119 stdout=subprocess.PIPE,
120 stderr=subprocess.PIPE).communicate()
Luis Hector Chavez454bc7c2018-04-20 10:31:29 -0700121
122
Luis Hector Chavez32559742018-05-02 10:47:01 -0700123@contextlib.contextmanager
124def adb_server():
125 """Context manager for an ADB server.
126
127 This creates an ADB server and returns the port it's listening on.
128 """
129
130 port = 5038
131 # Kill any existing server on this non-default port.
132 subprocess.check_output(['adb', '-P', str(port), 'kill-server'],
133 stderr=subprocess.STDOUT)
134 read_pipe, write_pipe = os.pipe()
Josh Gao9b6522b2018-08-07 14:31:17 -0700135 os.set_inheritable(write_pipe, True)
Luis Hector Chavez32559742018-05-02 10:47:01 -0700136 proc = subprocess.Popen(['adb', '-L', 'tcp:localhost:{}'.format(port),
137 'fork-server', 'server',
Josh Gao9b6522b2018-08-07 14:31:17 -0700138 '--reply-fd', str(write_pipe)], close_fds=False)
Luis Hector Chavez32559742018-05-02 10:47:01 -0700139 try:
140 os.close(write_pipe)
141 greeting = os.read(read_pipe, 1024)
Josh Gao9b6522b2018-08-07 14:31:17 -0700142 assert greeting == b'OK\n', repr(greeting)
Luis Hector Chavez32559742018-05-02 10:47:01 -0700143 yield port
144 finally:
145 proc.terminate()
146 proc.wait()
147
148
Luis Hector Chavezfbee0a92018-05-02 09:10:29 -0700149class CommandlineTest(unittest.TestCase):
150 """Tests for the ADB commandline."""
Dan Albert8e1fdd72015-07-24 17:08:33 -0700151
152 def test_help(self):
153 """Make sure we get _something_ out of help."""
154 out = subprocess.check_output(
155 ['adb', 'help'], stderr=subprocess.STDOUT)
156 self.assertGreater(len(out), 0)
157
158 def test_version(self):
159 """Get a version number out of the output of adb."""
160 lines = subprocess.check_output(['adb', 'version']).splitlines()
161 version_line = lines[0]
Josh Gao9b6522b2018-08-07 14:31:17 -0700162 self.assertRegex(
163 version_line, rb'^Android Debug Bridge version \d+\.\d+\.\d+$')
Dan Albert8e1fdd72015-07-24 17:08:33 -0700164 if len(lines) == 2:
165 # Newer versions of ADB have a second line of output for the
166 # version that includes a specific revision (git SHA).
167 revision_line = lines[1]
Josh Gao9b6522b2018-08-07 14:31:17 -0700168 self.assertRegex(
169 revision_line, rb'^Revision [0-9a-f]{12}-android$')
Dan Albert8e1fdd72015-07-24 17:08:33 -0700170
171 def test_tcpip_error_messages(self):
Luis Hector Chavezfbee0a92018-05-02 09:10:29 -0700172 """Make sure 'adb tcpip' parsing is sane."""
Josh Gao9b6522b2018-08-07 14:31:17 -0700173 proc = subprocess.Popen(['adb', 'tcpip'],
174 stdout=subprocess.PIPE,
Luis Hector Chavezfbee0a92018-05-02 09:10:29 -0700175 stderr=subprocess.STDOUT)
176 out, _ = proc.communicate()
177 self.assertEqual(1, proc.returncode)
Josh Gao9b6522b2018-08-07 14:31:17 -0700178 self.assertIn(b'requires an argument', out)
Dan Albert8e1fdd72015-07-24 17:08:33 -0700179
Josh Gao9b6522b2018-08-07 14:31:17 -0700180 proc = subprocess.Popen(['adb', 'tcpip', 'foo'],
181 stdout=subprocess.PIPE,
Luis Hector Chavezfbee0a92018-05-02 09:10:29 -0700182 stderr=subprocess.STDOUT)
183 out, _ = proc.communicate()
184 self.assertEqual(1, proc.returncode)
Josh Gao9b6522b2018-08-07 14:31:17 -0700185 self.assertIn(b'invalid port', out)
Dan Albert8e1fdd72015-07-24 17:08:33 -0700186
Luis Hector Chavezfbee0a92018-05-02 09:10:29 -0700187
188class ServerTest(unittest.TestCase):
189 """Tests for the ADB server."""
190
191 @staticmethod
192 def _read_pipe_and_set_event(pipe, event):
193 """Reads a pipe until it is closed, then sets the event."""
194 pipe.read()
Spencer Low1ce06082015-09-16 20:45:53 -0700195 event.set()
196
Spencer Low1ce06082015-09-16 20:45:53 -0700197 def test_handle_inheritance(self):
Luis Hector Chavezfbee0a92018-05-02 09:10:29 -0700198 """Test that launch_server() does not inherit handles.
199
200 launch_server() should not let the adb server inherit
201 stdin/stdout/stderr handles, which can cause callers of adb.exe to hang.
202 This test also runs fine on unix even though the impetus is an issue
203 unique to Windows.
204 """
Spencer Low1ce06082015-09-16 20:45:53 -0700205 # This test takes 5 seconds to run on Windows: if there is no adb server
206 # running on the the port used below, adb kill-server tries to make a
207 # TCP connection to a closed port and that takes 1 second on Windows;
208 # adb start-server does the same TCP connection which takes another
209 # second, and it waits 3 seconds after starting the server.
210
211 # Start adb client with redirected stdin/stdout/stderr to check if it
212 # passes those redirections to the adb server that it starts. To do
213 # this, run an instance of the adb server on a non-default port so we
214 # don't conflict with a pre-existing adb server that may already be
215 # setup with adb TCP/emulator connections. If there is a pre-existing
216 # adb server, this also tests whether multiple instances of the adb
217 # server conflict on adb.log.
218
219 port = 5038
220 # Kill any existing server on this non-default port.
221 subprocess.check_output(['adb', '-P', str(port), 'kill-server'],
222 stderr=subprocess.STDOUT)
223
224 try:
225 # Run the adb client and have it start the adb server.
Luis Hector Chavezfbee0a92018-05-02 09:10:29 -0700226 proc = subprocess.Popen(['adb', '-P', str(port), 'start-server'],
227 stdin=subprocess.PIPE,
228 stdout=subprocess.PIPE,
229 stderr=subprocess.PIPE)
Spencer Low1ce06082015-09-16 20:45:53 -0700230
231 # Start threads that set events when stdout/stderr are closed.
232 stdout_event = threading.Event()
233 stdout_thread = threading.Thread(
Luis Hector Chavezfbee0a92018-05-02 09:10:29 -0700234 target=ServerTest._read_pipe_and_set_event,
235 args=(proc.stdout, stdout_event))
Spencer Low1ce06082015-09-16 20:45:53 -0700236 stdout_thread.start()
237
238 stderr_event = threading.Event()
239 stderr_thread = threading.Thread(
Luis Hector Chavezfbee0a92018-05-02 09:10:29 -0700240 target=ServerTest._read_pipe_and_set_event,
241 args=(proc.stderr, stderr_event))
Spencer Low1ce06082015-09-16 20:45:53 -0700242 stderr_thread.start()
243
244 # Wait for the adb client to finish. Once that has occurred, if
245 # stdin/stderr/stdout are still open, it must be open in the adb
246 # server.
Luis Hector Chavezfbee0a92018-05-02 09:10:29 -0700247 proc.wait()
Spencer Low1ce06082015-09-16 20:45:53 -0700248
249 # Try to write to stdin which we expect is closed. If it isn't
250 # closed, we should get an IOError. If we don't get an IOError,
251 # stdin must still be open in the adb server. The adb client is
252 # probably letting the adb server inherit stdin which would be
253 # wrong.
254 with self.assertRaises(IOError):
Josh Gao9b6522b2018-08-07 14:31:17 -0700255 proc.stdin.write(b'x')
256 proc.stdin.flush()
Spencer Low1ce06082015-09-16 20:45:53 -0700257
258 # Wait a few seconds for stdout/stderr to be closed (in the success
259 # case, this won't wait at all). If there is a timeout, that means
260 # stdout/stderr were not closed and and they must be open in the adb
261 # server, suggesting that the adb client is letting the adb server
262 # inherit stdout/stderr which would be wrong.
263 self.assertTrue(stdout_event.wait(5), "adb stdout not closed")
264 self.assertTrue(stderr_event.wait(5), "adb stderr not closed")
Josh Gao9b6522b2018-08-07 14:31:17 -0700265 stdout_thread.join()
266 stderr_thread.join()
Spencer Low1ce06082015-09-16 20:45:53 -0700267 finally:
268 # If we started a server, kill it.
269 subprocess.check_output(['adb', '-P', str(port), 'kill-server'],
270 stderr=subprocess.STDOUT)
Dan Albert8e1fdd72015-07-24 17:08:33 -0700271
Luis Hector Chavezfbee0a92018-05-02 09:10:29 -0700272
273class EmulatorTest(unittest.TestCase):
274 """Tests for the emulator connection."""
275
Spencer Low351ecd12015-10-14 17:32:44 -0700276 def _reset_socket_on_close(self, sock):
Luis Hector Chavezfbee0a92018-05-02 09:10:29 -0700277 """Use SO_LINGER to cause TCP RST segment to be sent on socket close."""
Spencer Low351ecd12015-10-14 17:32:44 -0700278 # The linger structure is two shorts on Windows, but two ints on Unix.
279 linger_format = 'hh' if os.name == 'nt' else 'ii'
280 l_onoff = 1
281 l_linger = 0
282
283 sock.setsockopt(socket.SOL_SOCKET, socket.SO_LINGER,
284 struct.pack(linger_format, l_onoff, l_linger))
285 # Verify that we set the linger structure properly by retrieving it.
286 linger = sock.getsockopt(socket.SOL_SOCKET, socket.SO_LINGER, 16)
287 self.assertEqual((l_onoff, l_linger),
288 struct.unpack_from(linger_format, linger))
289
290 def test_emu_kill(self):
291 """Ensure that adb emu kill works.
292
293 Bug: https://code.google.com/p/android/issues/detail?id=21021
294 """
Spencer Low351ecd12015-10-14 17:32:44 -0700295 with contextlib.closing(
Luis Hector Chavezfbee0a92018-05-02 09:10:29 -0700296 socket.socket(socket.AF_INET, socket.SOCK_STREAM)) as listener:
Spencer Low351ecd12015-10-14 17:32:44 -0700297 # Use SO_REUSEADDR so subsequent runs of the test can grab the port
298 # even if it is in TIME_WAIT.
299 listener.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
Josh Gaoc251ec52018-04-03 12:55:18 -0700300 listener.bind(('127.0.0.1', 0))
Spencer Low351ecd12015-10-14 17:32:44 -0700301 listener.listen(4)
Josh Gaoc251ec52018-04-03 12:55:18 -0700302 port = listener.getsockname()[1]
Spencer Low351ecd12015-10-14 17:32:44 -0700303
304 # Now that listening has started, start adb emu kill, telling it to
305 # connect to our mock emulator.
Luis Hector Chavezfbee0a92018-05-02 09:10:29 -0700306 proc = subprocess.Popen(
Spencer Low351ecd12015-10-14 17:32:44 -0700307 ['adb', '-s', 'emulator-' + str(port), 'emu', 'kill'],
308 stderr=subprocess.STDOUT)
309
310 accepted_connection, addr = listener.accept()
311 with contextlib.closing(accepted_connection) as conn:
312 # If WSAECONNABORTED (10053) is raised by any socket calls,
313 # then adb probably isn't reading the data that we sent it.
Josh Gao9b6522b2018-08-07 14:31:17 -0700314 conn.sendall(('Android Console: type \'help\' for a list '
315 'of commands\r\n').encode("utf8"))
316 conn.sendall(b'OK\r\n')
Spencer Low351ecd12015-10-14 17:32:44 -0700317
Luis Hector Chavezfbee0a92018-05-02 09:10:29 -0700318 with contextlib.closing(conn.makefile()) as connf:
319 line = connf.readline()
320 if line.startswith('auth'):
321 # Ignore the first auth line.
322 line = connf.readline()
323 self.assertEqual('kill\n', line)
324 self.assertEqual('quit\n', connf.readline())
Spencer Low351ecd12015-10-14 17:32:44 -0700325
Josh Gao9b6522b2018-08-07 14:31:17 -0700326 conn.sendall(b'OK: killing emulator, bye bye\r\n')
Spencer Low351ecd12015-10-14 17:32:44 -0700327
328 # Use SO_LINGER to send TCP RST segment to test whether adb
329 # ignores WSAECONNRESET on Windows. This happens with the
330 # real emulator because it just calls exit() without closing
331 # the socket or calling shutdown(SD_SEND). At process
332 # termination, Windows sends a TCP RST segment for every
333 # open socket that shutdown(SD_SEND) wasn't used on.
334 self._reset_socket_on_close(conn)
335
336 # Wait for adb to finish, so we can check return code.
Luis Hector Chavezfbee0a92018-05-02 09:10:29 -0700337 proc.communicate()
Spencer Low351ecd12015-10-14 17:32:44 -0700338
339 # If this fails, adb probably isn't ignoring WSAECONNRESET when
340 # reading the response from the adb emu kill command (on Windows).
Luis Hector Chavezfbee0a92018-05-02 09:10:29 -0700341 self.assertEqual(0, proc.returncode)
342
Luis Hector Chavez32559742018-05-02 10:47:01 -0700343 def test_emulator_connect(self):
344 """Ensure that the emulator can connect.
345
346 Bug: http://b/78991667
347 """
348 with adb_server() as server_port:
349 with fake_adbd() as port:
350 serial = 'emulator-{}'.format(port - 1)
351 # Ensure that the emulator is not there.
352 try:
353 subprocess.check_output(['adb', '-P', str(server_port),
354 '-s', serial, 'get-state'],
355 stderr=subprocess.STDOUT)
356 self.fail('Device should not be available')
357 except subprocess.CalledProcessError as err:
358 self.assertEqual(
359 err.output.strip(),
Josh Gao9b6522b2018-08-07 14:31:17 -0700360 'error: device \'{}\' not found'.format(serial).encode("utf8"))
Luis Hector Chavez32559742018-05-02 10:47:01 -0700361
362 # Let the ADB server know that the emulator has started.
363 with contextlib.closing(
Josh Gao9b6522b2018-08-07 14:31:17 -0700364 socket.socket(socket.AF_INET, socket.SOCK_STREAM)) as sock:
Luis Hector Chavez32559742018-05-02 10:47:01 -0700365 sock.connect(('localhost', server_port))
Josh Gao9b6522b2018-08-07 14:31:17 -0700366 command = 'host:emulator:{}'.format(port).encode("utf8")
367 sock.sendall(b'%04x%s' % (len(command), command))
Luis Hector Chavez32559742018-05-02 10:47:01 -0700368
369 # Ensure the emulator is there.
370 subprocess.check_call(['adb', '-P', str(server_port),
371 '-s', serial, 'wait-for-device'])
372 output = subprocess.check_output(['adb', '-P', str(server_port),
373 '-s', serial, 'get-state'])
Josh Gao9b6522b2018-08-07 14:31:17 -0700374 self.assertEqual(output.strip(), b'device')
Luis Hector Chavez32559742018-05-02 10:47:01 -0700375
Luis Hector Chavezfbee0a92018-05-02 09:10:29 -0700376
377class ConnectionTest(unittest.TestCase):
378 """Tests for adb connect."""
Spencer Low351ecd12015-10-14 17:32:44 -0700379
Josh Gao78cc20f2016-09-01 14:54:18 -0700380 def test_connect_ipv4_ipv6(self):
381 """Ensure that `adb connect localhost:1234` will try both IPv4 and IPv6.
382
383 Bug: http://b/30313466
384 """
Luis Hector Chavez8b67c522018-04-17 19:25:33 -0700385 for protocol in (socket.AF_INET, socket.AF_INET6):
386 try:
Luis Hector Chavezfbee0a92018-05-02 09:10:29 -0700387 with fake_adbd(protocol=protocol) as port:
Luis Hector Chavez454bc7c2018-04-20 10:31:29 -0700388 serial = 'localhost:{}'.format(port)
389 with adb_connect(self, serial):
390 pass
Luis Hector Chavez8b67c522018-04-17 19:25:33 -0700391 except socket.error:
392 print("IPv6 not available, skipping")
393 continue
Josh Gao78cc20f2016-09-01 14:54:18 -0700394
Luis Hector Chavez8b67c522018-04-17 19:25:33 -0700395 def test_already_connected(self):
Luis Hector Chavez454bc7c2018-04-20 10:31:29 -0700396 """Ensure that an already-connected device stays connected."""
397
Luis Hector Chavezfbee0a92018-05-02 09:10:29 -0700398 with fake_adbd() as port:
Luis Hector Chavez454bc7c2018-04-20 10:31:29 -0700399 serial = 'localhost:{}'.format(port)
400 with adb_connect(self, serial):
401 # b/31250450: this always returns 0 but probably shouldn't.
402 output = subprocess.check_output(['adb', 'connect', serial])
403 self.assertEqual(
Josh Gao9b6522b2018-08-07 14:31:17 -0700404 output.strip(),
405 'already connected to {}'.format(serial).encode("utf8"))
Josh Gao78cc20f2016-09-01 14:54:18 -0700406
Luis Hector Chavez454bc7c2018-04-20 10:31:29 -0700407 def test_reconnect(self):
408 """Ensure that a disconnected device reconnects."""
Josh Gao78cc20f2016-09-01 14:54:18 -0700409
Luis Hector Chavezfbee0a92018-05-02 09:10:29 -0700410 with fake_adbd() as port:
Luis Hector Chavez454bc7c2018-04-20 10:31:29 -0700411 serial = 'localhost:{}'.format(port)
412 with adb_connect(self, serial):
413 output = subprocess.check_output(['adb', '-s', serial,
414 'get-state'])
Josh Gao9b6522b2018-08-07 14:31:17 -0700415 self.assertEqual(output.strip(), b'device')
Josh Gaoc251ec52018-04-03 12:55:18 -0700416
Luis Hector Chavez454bc7c2018-04-20 10:31:29 -0700417 # This will fail.
Luis Hector Chavezfbee0a92018-05-02 09:10:29 -0700418 proc = subprocess.Popen(['adb', '-s', serial, 'shell', 'true'],
419 stdout=subprocess.PIPE,
420 stderr=subprocess.STDOUT)
421 output, _ = proc.communicate()
Josh Gao9b6522b2018-08-07 14:31:17 -0700422 self.assertEqual(output.strip(), b'error: closed')
Luis Hector Chavez454bc7c2018-04-20 10:31:29 -0700423
424 subprocess.check_call(['adb', '-s', serial, 'wait-for-device'])
425
426 output = subprocess.check_output(['adb', '-s', serial,
427 'get-state'])
Josh Gao9b6522b2018-08-07 14:31:17 -0700428 self.assertEqual(output.strip(), b'device')
Luis Hector Chavez454bc7c2018-04-20 10:31:29 -0700429
430 # Once we explicitly kick a device, it won't attempt to
431 # reconnect.
432 output = subprocess.check_output(['adb', 'disconnect', serial])
433 self.assertEqual(
Josh Gao9b6522b2018-08-07 14:31:17 -0700434 output.strip(),
435 'disconnected {}'.format(serial).encode("utf8"))
Luis Hector Chavez454bc7c2018-04-20 10:31:29 -0700436 try:
437 subprocess.check_output(['adb', '-s', serial, 'get-state'],
438 stderr=subprocess.STDOUT)
439 self.fail('Device should not be available')
Luis Hector Chavezfbee0a92018-05-02 09:10:29 -0700440 except subprocess.CalledProcessError as err:
Luis Hector Chavez454bc7c2018-04-20 10:31:29 -0700441 self.assertEqual(
Luis Hector Chavezfbee0a92018-05-02 09:10:29 -0700442 err.output.strip(),
Josh Gao9b6522b2018-08-07 14:31:17 -0700443 'error: device \'{}\' not found'.format(serial).encode("utf8"))
Spencer Low351ecd12015-10-14 17:32:44 -0700444
Luis Hector Chavezfbee0a92018-05-02 09:10:29 -0700445
Dan Albert8e1fdd72015-07-24 17:08:33 -0700446def main():
Luis Hector Chavezfbee0a92018-05-02 09:10:29 -0700447 """Main entrypoint."""
Dan Albert8e1fdd72015-07-24 17:08:33 -0700448 random.seed(0)
Luis Hector Chavezfbee0a92018-05-02 09:10:29 -0700449 unittest.main(verbosity=3)
Dan Albert8e1fdd72015-07-24 17:08:33 -0700450
451
452if __name__ == '__main__':
453 main()