blob: 8272722e88ecc842eb34237c00bd0a5f5e458b5d [file] [log] [blame]
Josh Gaob1df00e2018-08-07 14:31:17 -07001#!/usr/bin/env python3
Dan Alberta4169f92015-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 Alberta4169f92015-07-24 17:08:33 -070022
Spencer Lowcc4a4b12015-10-14 17:32:44 -070023import contextlib
Spencer Low9a999242015-09-16 20:45:53 -070024import os
Dan Alberta4169f92015-07-24 17:08:33 -070025import random
Luis Hector Chavezbf8a7222018-04-17 19:25:33 -070026import select
Spencer Lowcc4a4b12015-10-14 17:32:44 -070027import socket
28import struct
Dan Alberta4169f92015-07-24 17:08:33 -070029import subprocess
Josh Gao6d7b9652018-08-21 14:25:05 -070030import sys
Spencer Low9a999242015-09-16 20:45:53 -070031import threading
Josh Gao13cb8c02018-08-10 14:44:54 -070032import time
Dan Alberta4169f92015-07-24 17:08:33 -070033import unittest
Josh Gaobe294912018-10-16 11:00:39 -070034import warnings
Dan Alberta4169f92015-07-24 17:08:33 -070035
Dan Alberta4169f92015-07-24 17:08:33 -070036
Luis Hector Chavezbf8a7222018-04-17 19:25:33 -070037@contextlib.contextmanager
Luis Hector Chavez947b2132018-05-02 09:10:29 -070038def fake_adbd(protocol=socket.AF_INET, port=0):
39 """Creates a fake ADB daemon that just replies with a CNXN packet."""
Luis Hector Chavezbf8a7222018-04-17 19:25:33 -070040
41 serversock = socket.socket(protocol, socket.SOCK_STREAM)
Luis Hector Chavez947b2132018-05-02 09:10:29 -070042 serversock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
Luis Hector Chavezbf8a7222018-04-17 19:25:33 -070043 if protocol == socket.AF_INET:
Josh Gao4db70c52018-08-08 13:08:08 -070044 serversock.bind(("127.0.0.1", port))
Luis Hector Chavezbf8a7222018-04-17 19:25:33 -070045 else:
Josh Gao4db70c52018-08-08 13:08:08 -070046 serversock.bind(("::1", port))
Luis Hector Chavezbf8a7222018-04-17 19:25:33 -070047 serversock.listen(1)
48
49 # A pipe that is used to signal the thread that it should terminate.
Josh Gao6afbf792018-08-07 16:07:25 -070050 readsock, writesock = socket.socketpair()
Luis Hector Chavezbf8a7222018-04-17 19:25:33 -070051
Josh Gaob1df00e2018-08-07 14:31:17 -070052 def _adb_packet(command: bytes, arg0: int, arg1: int, data: bytes) -> bytes:
Josh Gao4db70c52018-08-08 13:08:08 -070053 bin_command = struct.unpack("I", command)[0]
54 buf = struct.pack("IIIIII", bin_command, arg0, arg1, len(data), 0,
Luis Hector Chavezda74b902018-04-17 14:25:04 -070055 bin_command ^ 0xffffffff)
56 buf += data
57 return buf
58
Josh Gaob1df00e2018-08-07 14:31:17 -070059 def _handle(sock):
60 with contextlib.closing(sock) as serversock:
Josh Gao6afbf792018-08-07 16:07:25 -070061 rlist = [readsock, serversock]
Josh Gaob1df00e2018-08-07 14:31:17 -070062 cnxn_sent = {}
63 while True:
64 read_ready, _, _ = select.select(rlist, [], [])
65 for ready in read_ready:
Josh Gao6afbf792018-08-07 16:07:25 -070066 if ready == readsock:
Josh Gaob1df00e2018-08-07 14:31:17 -070067 # Closure pipe
Josh Gaob1df00e2018-08-07 14:31:17 -070068 for f in rlist:
Josh Gao6afbf792018-08-07 16:07:25 -070069 f.close()
Josh Gaob1df00e2018-08-07 14:31:17 -070070 return
71 elif ready == serversock:
72 # Server socket
73 conn, _ = ready.accept()
74 rlist.append(conn)
75 else:
76 # Client socket
77 data = ready.recv(1024)
Josh Gao4db70c52018-08-08 13:08:08 -070078 if not data or data.startswith(b"OPEN"):
Josh Gaob1df00e2018-08-07 14:31:17 -070079 if ready in cnxn_sent:
80 del cnxn_sent[ready]
81 ready.shutdown(socket.SHUT_RDWR)
82 ready.close()
83 rlist.remove(ready)
84 continue
Luis Hector Chavez947b2132018-05-02 09:10:29 -070085 if ready in cnxn_sent:
Josh Gaob1df00e2018-08-07 14:31:17 -070086 continue
87 cnxn_sent[ready] = True
Josh Gao4db70c52018-08-08 13:08:08 -070088 ready.sendall(_adb_packet(b"CNXN", 0x01000001, 1024 * 1024,
89 b"device::ro.product.name=fakeadb"))
Luis Hector Chavezbf8a7222018-04-17 19:25:33 -070090
91 port = serversock.getsockname()[1]
Josh Gaob1df00e2018-08-07 14:31:17 -070092 server_thread = threading.Thread(target=_handle, args=(serversock,))
Luis Hector Chavezbf8a7222018-04-17 19:25:33 -070093 server_thread.start()
94
95 try:
Josh Gao13cb8c02018-08-10 14:44:54 -070096 yield port, writesock
Luis Hector Chavezbf8a7222018-04-17 19:25:33 -070097 finally:
Josh Gao6afbf792018-08-07 16:07:25 -070098 writesock.close()
Luis Hector Chavezbf8a7222018-04-17 19:25:33 -070099 server_thread.join()
100
101
Luis Hector Chavez0aeda102018-04-20 10:31:29 -0700102@contextlib.contextmanager
103def adb_connect(unittest, serial):
104 """Context manager for an ADB connection.
105
106 This automatically disconnects when done with the connection.
107 """
108
Josh Gao4db70c52018-08-08 13:08:08 -0700109 output = subprocess.check_output(["adb", "connect", serial])
Josh Gaob1df00e2018-08-07 14:31:17 -0700110 unittest.assertEqual(output.strip(),
Josh Gao4db70c52018-08-08 13:08:08 -0700111 "connected to {}".format(serial).encode("utf8"))
Luis Hector Chavez0aeda102018-04-20 10:31:29 -0700112
113 try:
114 yield
115 finally:
116 # Perform best-effort disconnection. Discard the output.
Josh Gao4db70c52018-08-08 13:08:08 -0700117 subprocess.Popen(["adb", "disconnect", serial],
Luis Hector Chavez947b2132018-05-02 09:10:29 -0700118 stdout=subprocess.PIPE,
119 stderr=subprocess.PIPE).communicate()
Luis Hector Chavez0aeda102018-04-20 10:31:29 -0700120
121
Luis Hector Chaveza452f0e2018-05-02 10:47:01 -0700122@contextlib.contextmanager
123def adb_server():
124 """Context manager for an ADB server.
125
Josh Gao13cb8c02018-08-10 14:44:54 -0700126 This creates an ADB server and returns the port it's listening on.
Luis Hector Chaveza452f0e2018-05-02 10:47:01 -0700127 """
128
129 port = 5038
130 # Kill any existing server on this non-default port.
Josh Gao4db70c52018-08-08 13:08:08 -0700131 subprocess.check_output(["adb", "-P", str(port), "kill-server"],
Luis Hector Chaveza452f0e2018-05-02 10:47:01 -0700132 stderr=subprocess.STDOUT)
133 read_pipe, write_pipe = os.pipe()
Josh Gao6d7b9652018-08-21 14:25:05 -0700134
135 if sys.platform == "win32":
136 import msvcrt
137 write_handle = msvcrt.get_osfhandle(write_pipe)
138 os.set_handle_inheritable(write_handle, True)
139 reply_fd = str(write_handle)
140 else:
141 os.set_inheritable(write_pipe, True)
142 reply_fd = str(write_pipe)
143
Josh Gao4db70c52018-08-08 13:08:08 -0700144 proc = subprocess.Popen(["adb", "-L", "tcp:localhost:{}".format(port),
145 "fork-server", "server",
Josh Gao6d7b9652018-08-21 14:25:05 -0700146 "--reply-fd", reply_fd], close_fds=False)
Luis Hector Chaveza452f0e2018-05-02 10:47:01 -0700147 try:
148 os.close(write_pipe)
149 greeting = os.read(read_pipe, 1024)
Josh Gao4db70c52018-08-08 13:08:08 -0700150 assert greeting == b"OK\n", repr(greeting)
Luis Hector Chaveza452f0e2018-05-02 10:47:01 -0700151 yield port
152 finally:
153 proc.terminate()
154 proc.wait()
155
156
Luis Hector Chavez947b2132018-05-02 09:10:29 -0700157class CommandlineTest(unittest.TestCase):
158 """Tests for the ADB commandline."""
Dan Alberta4169f92015-07-24 17:08:33 -0700159
160 def test_help(self):
161 """Make sure we get _something_ out of help."""
162 out = subprocess.check_output(
Josh Gao4db70c52018-08-08 13:08:08 -0700163 ["adb", "help"], stderr=subprocess.STDOUT)
Dan Alberta4169f92015-07-24 17:08:33 -0700164 self.assertGreater(len(out), 0)
165
166 def test_version(self):
167 """Get a version number out of the output of adb."""
Josh Gao4db70c52018-08-08 13:08:08 -0700168 lines = subprocess.check_output(["adb", "version"]).splitlines()
Dan Alberta4169f92015-07-24 17:08:33 -0700169 version_line = lines[0]
Josh Gaob1df00e2018-08-07 14:31:17 -0700170 self.assertRegex(
Josh Gao4db70c52018-08-08 13:08:08 -0700171 version_line, rb"^Android Debug Bridge version \d+\.\d+\.\d+$")
Dan Alberta4169f92015-07-24 17:08:33 -0700172 if len(lines) == 2:
173 # Newer versions of ADB have a second line of output for the
174 # version that includes a specific revision (git SHA).
175 revision_line = lines[1]
Josh Gaob1df00e2018-08-07 14:31:17 -0700176 self.assertRegex(
Josh Gao4db70c52018-08-08 13:08:08 -0700177 revision_line, rb"^Revision [0-9a-f]{12}-android$")
Dan Alberta4169f92015-07-24 17:08:33 -0700178
179 def test_tcpip_error_messages(self):
Luis Hector Chavez947b2132018-05-02 09:10:29 -0700180 """Make sure 'adb tcpip' parsing is sane."""
Josh Gao4db70c52018-08-08 13:08:08 -0700181 proc = subprocess.Popen(["adb", "tcpip"],
Josh Gaob1df00e2018-08-07 14:31:17 -0700182 stdout=subprocess.PIPE,
Luis Hector Chavez947b2132018-05-02 09:10:29 -0700183 stderr=subprocess.STDOUT)
184 out, _ = proc.communicate()
185 self.assertEqual(1, proc.returncode)
Josh Gao4db70c52018-08-08 13:08:08 -0700186 self.assertIn(b"requires an argument", out)
Dan Alberta4169f92015-07-24 17:08:33 -0700187
Josh Gao4db70c52018-08-08 13:08:08 -0700188 proc = subprocess.Popen(["adb", "tcpip", "foo"],
Josh Gaob1df00e2018-08-07 14:31:17 -0700189 stdout=subprocess.PIPE,
Luis Hector Chavez947b2132018-05-02 09:10:29 -0700190 stderr=subprocess.STDOUT)
191 out, _ = proc.communicate()
192 self.assertEqual(1, proc.returncode)
Josh Gao4db70c52018-08-08 13:08:08 -0700193 self.assertIn(b"invalid port", out)
Dan Alberta4169f92015-07-24 17:08:33 -0700194
Luis Hector Chavez947b2132018-05-02 09:10:29 -0700195
196class ServerTest(unittest.TestCase):
197 """Tests for the ADB server."""
198
199 @staticmethod
200 def _read_pipe_and_set_event(pipe, event):
201 """Reads a pipe until it is closed, then sets the event."""
202 pipe.read()
Spencer Low9a999242015-09-16 20:45:53 -0700203 event.set()
204
Spencer Low9a999242015-09-16 20:45:53 -0700205 def test_handle_inheritance(self):
Luis Hector Chavez947b2132018-05-02 09:10:29 -0700206 """Test that launch_server() does not inherit handles.
207
208 launch_server() should not let the adb server inherit
209 stdin/stdout/stderr handles, which can cause callers of adb.exe to hang.
210 This test also runs fine on unix even though the impetus is an issue
211 unique to Windows.
212 """
Spencer Low9a999242015-09-16 20:45:53 -0700213 # This test takes 5 seconds to run on Windows: if there is no adb server
214 # running on the the port used below, adb kill-server tries to make a
215 # TCP connection to a closed port and that takes 1 second on Windows;
216 # adb start-server does the same TCP connection which takes another
217 # second, and it waits 3 seconds after starting the server.
218
219 # Start adb client with redirected stdin/stdout/stderr to check if it
220 # passes those redirections to the adb server that it starts. To do
221 # this, run an instance of the adb server on a non-default port so we
222 # don't conflict with a pre-existing adb server that may already be
223 # setup with adb TCP/emulator connections. If there is a pre-existing
224 # adb server, this also tests whether multiple instances of the adb
225 # server conflict on adb.log.
226
227 port = 5038
228 # Kill any existing server on this non-default port.
Josh Gao4db70c52018-08-08 13:08:08 -0700229 subprocess.check_output(["adb", "-P", str(port), "kill-server"],
Spencer Low9a999242015-09-16 20:45:53 -0700230 stderr=subprocess.STDOUT)
231
232 try:
Josh Gaobe294912018-10-16 11:00:39 -0700233 # We get warnings for unclosed files for the subprocess's pipes,
234 # and it's somewhat cumbersome to close them, so just ignore this.
235 warnings.simplefilter("ignore", ResourceWarning)
236
Spencer Low9a999242015-09-16 20:45:53 -0700237 # Run the adb client and have it start the adb server.
Josh Gao4db70c52018-08-08 13:08:08 -0700238 proc = subprocess.Popen(["adb", "-P", str(port), "start-server"],
Luis Hector Chavez947b2132018-05-02 09:10:29 -0700239 stdin=subprocess.PIPE,
240 stdout=subprocess.PIPE,
241 stderr=subprocess.PIPE)
Spencer Low9a999242015-09-16 20:45:53 -0700242
243 # Start threads that set events when stdout/stderr are closed.
244 stdout_event = threading.Event()
245 stdout_thread = threading.Thread(
Luis Hector Chavez947b2132018-05-02 09:10:29 -0700246 target=ServerTest._read_pipe_and_set_event,
247 args=(proc.stdout, stdout_event))
Spencer Low9a999242015-09-16 20:45:53 -0700248 stdout_thread.start()
249
250 stderr_event = threading.Event()
251 stderr_thread = threading.Thread(
Luis Hector Chavez947b2132018-05-02 09:10:29 -0700252 target=ServerTest._read_pipe_and_set_event,
253 args=(proc.stderr, stderr_event))
Spencer Low9a999242015-09-16 20:45:53 -0700254 stderr_thread.start()
255
256 # Wait for the adb client to finish. Once that has occurred, if
257 # stdin/stderr/stdout are still open, it must be open in the adb
258 # server.
Luis Hector Chavez947b2132018-05-02 09:10:29 -0700259 proc.wait()
Spencer Low9a999242015-09-16 20:45:53 -0700260
261 # Try to write to stdin which we expect is closed. If it isn't
262 # closed, we should get an IOError. If we don't get an IOError,
263 # stdin must still be open in the adb server. The adb client is
264 # probably letting the adb server inherit stdin which would be
265 # wrong.
266 with self.assertRaises(IOError):
Josh Gao4db70c52018-08-08 13:08:08 -0700267 proc.stdin.write(b"x")
Josh Gaob1df00e2018-08-07 14:31:17 -0700268 proc.stdin.flush()
Spencer Low9a999242015-09-16 20:45:53 -0700269
270 # Wait a few seconds for stdout/stderr to be closed (in the success
271 # case, this won't wait at all). If there is a timeout, that means
272 # stdout/stderr were not closed and and they must be open in the adb
273 # server, suggesting that the adb client is letting the adb server
274 # inherit stdout/stderr which would be wrong.
275 self.assertTrue(stdout_event.wait(5), "adb stdout not closed")
276 self.assertTrue(stderr_event.wait(5), "adb stderr not closed")
Josh Gaob1df00e2018-08-07 14:31:17 -0700277 stdout_thread.join()
278 stderr_thread.join()
Spencer Low9a999242015-09-16 20:45:53 -0700279 finally:
280 # If we started a server, kill it.
Josh Gao4db70c52018-08-08 13:08:08 -0700281 subprocess.check_output(["adb", "-P", str(port), "kill-server"],
Spencer Low9a999242015-09-16 20:45:53 -0700282 stderr=subprocess.STDOUT)
Dan Alberta4169f92015-07-24 17:08:33 -0700283
Luis Hector Chavez947b2132018-05-02 09:10:29 -0700284
285class EmulatorTest(unittest.TestCase):
286 """Tests for the emulator connection."""
287
Spencer Lowcc4a4b12015-10-14 17:32:44 -0700288 def _reset_socket_on_close(self, sock):
Luis Hector Chavez947b2132018-05-02 09:10:29 -0700289 """Use SO_LINGER to cause TCP RST segment to be sent on socket close."""
Spencer Lowcc4a4b12015-10-14 17:32:44 -0700290 # The linger structure is two shorts on Windows, but two ints on Unix.
Josh Gao4db70c52018-08-08 13:08:08 -0700291 linger_format = "hh" if os.name == "nt" else "ii"
Spencer Lowcc4a4b12015-10-14 17:32:44 -0700292 l_onoff = 1
293 l_linger = 0
294
295 sock.setsockopt(socket.SOL_SOCKET, socket.SO_LINGER,
296 struct.pack(linger_format, l_onoff, l_linger))
297 # Verify that we set the linger structure properly by retrieving it.
298 linger = sock.getsockopt(socket.SOL_SOCKET, socket.SO_LINGER, 16)
299 self.assertEqual((l_onoff, l_linger),
300 struct.unpack_from(linger_format, linger))
301
302 def test_emu_kill(self):
303 """Ensure that adb emu kill works.
304
305 Bug: https://code.google.com/p/android/issues/detail?id=21021
306 """
Spencer Lowcc4a4b12015-10-14 17:32:44 -0700307 with contextlib.closing(
Luis Hector Chavez947b2132018-05-02 09:10:29 -0700308 socket.socket(socket.AF_INET, socket.SOCK_STREAM)) as listener:
Spencer Lowcc4a4b12015-10-14 17:32:44 -0700309 # Use SO_REUSEADDR so subsequent runs of the test can grab the port
310 # even if it is in TIME_WAIT.
311 listener.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
Josh Gao4db70c52018-08-08 13:08:08 -0700312 listener.bind(("127.0.0.1", 0))
Spencer Lowcc4a4b12015-10-14 17:32:44 -0700313 listener.listen(4)
Josh Gao13781e82018-04-03 12:55:18 -0700314 port = listener.getsockname()[1]
Spencer Lowcc4a4b12015-10-14 17:32:44 -0700315
316 # Now that listening has started, start adb emu kill, telling it to
317 # connect to our mock emulator.
Luis Hector Chavez947b2132018-05-02 09:10:29 -0700318 proc = subprocess.Popen(
Josh Gao4db70c52018-08-08 13:08:08 -0700319 ["adb", "-s", "emulator-" + str(port), "emu", "kill"],
Spencer Lowcc4a4b12015-10-14 17:32:44 -0700320 stderr=subprocess.STDOUT)
321
322 accepted_connection, addr = listener.accept()
323 with contextlib.closing(accepted_connection) as conn:
324 # If WSAECONNABORTED (10053) is raised by any socket calls,
325 # then adb probably isn't reading the data that we sent it.
Josh Gao4db70c52018-08-08 13:08:08 -0700326 conn.sendall(("Android Console: type 'help' for a list "
327 "of commands\r\n").encode("utf8"))
328 conn.sendall(b"OK\r\n")
Spencer Lowcc4a4b12015-10-14 17:32:44 -0700329
Luis Hector Chavez947b2132018-05-02 09:10:29 -0700330 with contextlib.closing(conn.makefile()) as connf:
331 line = connf.readline()
Josh Gao4db70c52018-08-08 13:08:08 -0700332 if line.startswith("auth"):
Luis Hector Chavez947b2132018-05-02 09:10:29 -0700333 # Ignore the first auth line.
334 line = connf.readline()
Josh Gao4db70c52018-08-08 13:08:08 -0700335 self.assertEqual("kill\n", line)
336 self.assertEqual("quit\n", connf.readline())
Spencer Lowcc4a4b12015-10-14 17:32:44 -0700337
Josh Gao4db70c52018-08-08 13:08:08 -0700338 conn.sendall(b"OK: killing emulator, bye bye\r\n")
Spencer Lowcc4a4b12015-10-14 17:32:44 -0700339
340 # Use SO_LINGER to send TCP RST segment to test whether adb
341 # ignores WSAECONNRESET on Windows. This happens with the
342 # real emulator because it just calls exit() without closing
343 # the socket or calling shutdown(SD_SEND). At process
344 # termination, Windows sends a TCP RST segment for every
345 # open socket that shutdown(SD_SEND) wasn't used on.
346 self._reset_socket_on_close(conn)
347
348 # Wait for adb to finish, so we can check return code.
Luis Hector Chavez947b2132018-05-02 09:10:29 -0700349 proc.communicate()
Spencer Lowcc4a4b12015-10-14 17:32:44 -0700350
351 # If this fails, adb probably isn't ignoring WSAECONNRESET when
352 # reading the response from the adb emu kill command (on Windows).
Luis Hector Chavez947b2132018-05-02 09:10:29 -0700353 self.assertEqual(0, proc.returncode)
354
Luis Hector Chaveza452f0e2018-05-02 10:47:01 -0700355 def test_emulator_connect(self):
356 """Ensure that the emulator can connect.
357
358 Bug: http://b/78991667
359 """
360 with adb_server() as server_port:
Josh Gao13cb8c02018-08-10 14:44:54 -0700361 with fake_adbd() as (port, _):
Josh Gao4db70c52018-08-08 13:08:08 -0700362 serial = "emulator-{}".format(port - 1)
Luis Hector Chaveza452f0e2018-05-02 10:47:01 -0700363 # Ensure that the emulator is not there.
364 try:
Josh Gao4db70c52018-08-08 13:08:08 -0700365 subprocess.check_output(["adb", "-P", str(server_port),
366 "-s", serial, "get-state"],
Luis Hector Chaveza452f0e2018-05-02 10:47:01 -0700367 stderr=subprocess.STDOUT)
Josh Gao4db70c52018-08-08 13:08:08 -0700368 self.fail("Device should not be available")
Luis Hector Chaveza452f0e2018-05-02 10:47:01 -0700369 except subprocess.CalledProcessError as err:
370 self.assertEqual(
371 err.output.strip(),
Josh Gao4db70c52018-08-08 13:08:08 -0700372 "error: device '{}' not found".format(serial).encode("utf8"))
Luis Hector Chaveza452f0e2018-05-02 10:47:01 -0700373
374 # Let the ADB server know that the emulator has started.
375 with contextlib.closing(
Josh Gaob1df00e2018-08-07 14:31:17 -0700376 socket.socket(socket.AF_INET, socket.SOCK_STREAM)) as sock:
Josh Gao4db70c52018-08-08 13:08:08 -0700377 sock.connect(("localhost", server_port))
378 command = "host:emulator:{}".format(port).encode("utf8")
379 sock.sendall(b"%04x%s" % (len(command), command))
Luis Hector Chaveza452f0e2018-05-02 10:47:01 -0700380
381 # Ensure the emulator is there.
Josh Gao4db70c52018-08-08 13:08:08 -0700382 subprocess.check_call(["adb", "-P", str(server_port),
383 "-s", serial, "wait-for-device"])
384 output = subprocess.check_output(["adb", "-P", str(server_port),
385 "-s", serial, "get-state"])
386 self.assertEqual(output.strip(), b"device")
Luis Hector Chaveza452f0e2018-05-02 10:47:01 -0700387
Luis Hector Chavez947b2132018-05-02 09:10:29 -0700388
389class ConnectionTest(unittest.TestCase):
390 """Tests for adb connect."""
Spencer Lowcc4a4b12015-10-14 17:32:44 -0700391
Josh Gao50bde8d2016-09-01 14:54:18 -0700392 def test_connect_ipv4_ipv6(self):
393 """Ensure that `adb connect localhost:1234` will try both IPv4 and IPv6.
394
395 Bug: http://b/30313466
396 """
Luis Hector Chavezbf8a7222018-04-17 19:25:33 -0700397 for protocol in (socket.AF_INET, socket.AF_INET6):
398 try:
Josh Gao13cb8c02018-08-10 14:44:54 -0700399 with fake_adbd(protocol=protocol) as (port, _):
Josh Gao4db70c52018-08-08 13:08:08 -0700400 serial = "localhost:{}".format(port)
Luis Hector Chavez0aeda102018-04-20 10:31:29 -0700401 with adb_connect(self, serial):
402 pass
Luis Hector Chavezbf8a7222018-04-17 19:25:33 -0700403 except socket.error:
404 print("IPv6 not available, skipping")
405 continue
Josh Gao50bde8d2016-09-01 14:54:18 -0700406
Luis Hector Chavezbf8a7222018-04-17 19:25:33 -0700407 def test_already_connected(self):
Luis Hector Chavez0aeda102018-04-20 10:31:29 -0700408 """Ensure that an already-connected device stays connected."""
409
Josh Gao13cb8c02018-08-10 14:44:54 -0700410 with fake_adbd() as (port, _):
Josh Gao4db70c52018-08-08 13:08:08 -0700411 serial = "localhost:{}".format(port)
Luis Hector Chavez0aeda102018-04-20 10:31:29 -0700412 with adb_connect(self, serial):
413 # b/31250450: this always returns 0 but probably shouldn't.
Josh Gao4db70c52018-08-08 13:08:08 -0700414 output = subprocess.check_output(["adb", "connect", serial])
Luis Hector Chavez0aeda102018-04-20 10:31:29 -0700415 self.assertEqual(
Josh Gaob1df00e2018-08-07 14:31:17 -0700416 output.strip(),
Josh Gao4db70c52018-08-08 13:08:08 -0700417 "already connected to {}".format(serial).encode("utf8"))
Josh Gao50bde8d2016-09-01 14:54:18 -0700418
Julien Desprez0e8a0a02019-02-20 09:42:49 -0800419 @unittest.skip("Currently failing b/123247844")
Luis Hector Chavez0aeda102018-04-20 10:31:29 -0700420 def test_reconnect(self):
421 """Ensure that a disconnected device reconnects."""
Josh Gao50bde8d2016-09-01 14:54:18 -0700422
Josh Gao13cb8c02018-08-10 14:44:54 -0700423 with fake_adbd() as (port, _):
Josh Gao4db70c52018-08-08 13:08:08 -0700424 serial = "localhost:{}".format(port)
Luis Hector Chavez0aeda102018-04-20 10:31:29 -0700425 with adb_connect(self, serial):
Josh Gao2645b0a2019-02-07 17:53:29 -0800426 # Wait a bit to give adb some time to connect.
427 time.sleep(0.25)
428
Josh Gao4db70c52018-08-08 13:08:08 -0700429 output = subprocess.check_output(["adb", "-s", serial,
430 "get-state"])
431 self.assertEqual(output.strip(), b"device")
Josh Gao13781e82018-04-03 12:55:18 -0700432
Luis Hector Chavez0aeda102018-04-20 10:31:29 -0700433 # This will fail.
Josh Gao4db70c52018-08-08 13:08:08 -0700434 proc = subprocess.Popen(["adb", "-s", serial, "shell", "true"],
Luis Hector Chavez947b2132018-05-02 09:10:29 -0700435 stdout=subprocess.PIPE,
436 stderr=subprocess.STDOUT)
437 output, _ = proc.communicate()
Josh Gao4db70c52018-08-08 13:08:08 -0700438 self.assertEqual(output.strip(), b"error: closed")
Luis Hector Chavez0aeda102018-04-20 10:31:29 -0700439
Josh Gao4db70c52018-08-08 13:08:08 -0700440 subprocess.check_call(["adb", "-s", serial, "wait-for-device"])
Luis Hector Chavez0aeda102018-04-20 10:31:29 -0700441
Josh Gao4db70c52018-08-08 13:08:08 -0700442 output = subprocess.check_output(["adb", "-s", serial,
443 "get-state"])
444 self.assertEqual(output.strip(), b"device")
Luis Hector Chavez0aeda102018-04-20 10:31:29 -0700445
446 # Once we explicitly kick a device, it won't attempt to
447 # reconnect.
Josh Gao4db70c52018-08-08 13:08:08 -0700448 output = subprocess.check_output(["adb", "disconnect", serial])
Luis Hector Chavez0aeda102018-04-20 10:31:29 -0700449 self.assertEqual(
Josh Gaob1df00e2018-08-07 14:31:17 -0700450 output.strip(),
Josh Gao4db70c52018-08-08 13:08:08 -0700451 "disconnected {}".format(serial).encode("utf8"))
Luis Hector Chavez0aeda102018-04-20 10:31:29 -0700452 try:
Josh Gao4db70c52018-08-08 13:08:08 -0700453 subprocess.check_output(["adb", "-s", serial, "get-state"],
Luis Hector Chavez0aeda102018-04-20 10:31:29 -0700454 stderr=subprocess.STDOUT)
Josh Gao4db70c52018-08-08 13:08:08 -0700455 self.fail("Device should not be available")
Luis Hector Chavez947b2132018-05-02 09:10:29 -0700456 except subprocess.CalledProcessError as err:
Luis Hector Chavez0aeda102018-04-20 10:31:29 -0700457 self.assertEqual(
Luis Hector Chavez947b2132018-05-02 09:10:29 -0700458 err.output.strip(),
Josh Gao4db70c52018-08-08 13:08:08 -0700459 "error: device '{}' not found".format(serial).encode("utf8"))
Spencer Lowcc4a4b12015-10-14 17:32:44 -0700460
Luis Hector Chavez947b2132018-05-02 09:10:29 -0700461
Josh Gao13cb8c02018-08-10 14:44:54 -0700462class DisconnectionTest(unittest.TestCase):
463 """Tests for adb disconnect."""
464
465 def test_disconnect(self):
466 """Ensure that `adb disconnect` takes effect immediately."""
467
468 def _devices(port):
469 output = subprocess.check_output(["adb", "-P", str(port), "devices"])
470 return [x.split("\t") for x in output.decode("utf8").strip().splitlines()[1:]]
471
472 with adb_server() as server_port:
473 with fake_adbd() as (port, sock):
474 device_name = "localhost:{}".format(port)
475 output = subprocess.check_output(["adb", "-P", str(server_port),
476 "connect", device_name])
477 self.assertEqual(output.strip(),
478 "connected to {}".format(device_name).encode("utf8"))
479
480
481 self.assertEqual(_devices(server_port), [[device_name, "device"]])
482
483 # Send a deliberately malformed packet to make the device go offline.
484 packet = struct.pack("IIIIII", 0, 0, 0, 0, 0, 0)
485 sock.sendall(packet)
486
487 # Wait a bit.
488 time.sleep(0.1)
489
490 self.assertEqual(_devices(server_port), [[device_name, "offline"]])
491
492 # Disconnect the device.
493 output = subprocess.check_output(["adb", "-P", str(server_port),
494 "disconnect", device_name])
495
496 # Wait a bit.
497 time.sleep(0.1)
498
499 self.assertEqual(_devices(server_port), [])
500
501
Spencer Lowebd8d322018-08-31 19:49:46 -0700502@unittest.skipUnless(sys.platform == "win32", "requires Windows")
503class PowerTest(unittest.TestCase):
504 def test_resume_usb_kick(self):
505 """Resuming from sleep/hibernate should kick USB devices."""
506 try:
507 usb_serial = subprocess.check_output(["adb", "-d", "get-serialno"]).strip()
508 except subprocess.CalledProcessError:
509 # If there are multiple USB devices, we don't have a way to check whether the selected
510 # device is USB.
511 raise unittest.SkipTest('requires single USB device')
512
513 try:
514 serial = subprocess.check_output(["adb", "get-serialno"]).strip()
515 except subprocess.CalledProcessError:
516 # Did you forget to select a device with $ANDROID_SERIAL?
517 raise unittest.SkipTest('requires $ANDROID_SERIAL set to a USB device')
518
519 # Test only works with USB devices because adb _power_notification_thread does not kick
520 # non-USB devices on resume event.
521 if serial != usb_serial:
522 raise unittest.SkipTest('requires USB device')
523
524 # Run an adb shell command in the background that takes a while to complete.
525 proc = subprocess.Popen(['adb', 'shell', 'sleep', '5'])
526
527 # Wait for startup of adb server's _power_notification_thread.
528 time.sleep(0.1)
529
530 # Simulate resuming from sleep/hibernation by sending Windows message.
531 import ctypes
532 from ctypes import wintypes
533 HWND_BROADCAST = 0xffff
534 WM_POWERBROADCAST = 0x218
535 PBT_APMRESUMEAUTOMATIC = 0x12
536
537 PostMessageW = ctypes.windll.user32.PostMessageW
538 PostMessageW.restype = wintypes.BOOL
539 PostMessageW.argtypes = (wintypes.HWND, wintypes.UINT, wintypes.WPARAM, wintypes.LPARAM)
540 result = PostMessageW(HWND_BROADCAST, WM_POWERBROADCAST, PBT_APMRESUMEAUTOMATIC, 0)
541 if not result:
542 raise ctypes.WinError()
543
544 # Wait for connection to adb shell to be broken by _power_notification_thread detecting the
545 # Windows message.
546 start = time.time()
547 proc.wait()
548 end = time.time()
549
550 # If the power event was detected, the adb shell command should be broken very quickly.
551 self.assertLess(end - start, 2)
552
553
Dan Alberta4169f92015-07-24 17:08:33 -0700554def main():
Luis Hector Chavez947b2132018-05-02 09:10:29 -0700555 """Main entrypoint."""
Dan Alberta4169f92015-07-24 17:08:33 -0700556 random.seed(0)
Luis Hector Chavez947b2132018-05-02 09:10:29 -0700557 unittest.main(verbosity=3)
Dan Alberta4169f92015-07-24 17:08:33 -0700558
559
Josh Gao4db70c52018-08-08 13:08:08 -0700560if __name__ == "__main__":
Dan Alberta4169f92015-07-24 17:08:33 -0700561 main()