blob: 3d6de2665dd27d8471b4e78bc859b4aabb74f7f7 [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
Callum Ryan04efea32019-10-31 07:21:42 -0700284 @unittest.skipUnless(
285 os.name == "posix",
286 "adb doesn't yet support IPv6 on Windows",
287 )
288 def test_starts_on_ipv6_localhost(self):
289 """
290 Tests that the server can start up on ::1 and that it's accessible
291 """
292 server_port = 5037
293 # Kill any existing server on this non-default port.
294 subprocess.check_output(
295 ["adb", "-P", str(server_port), "kill-server"],
296 stderr=subprocess.STDOUT,
297 )
298 try:
299 subprocess.check_output(
300 ["adb", "-L", "tcp:[::1]:{}".format(server_port), "server"],
301 stderr=subprocess.STDOUT,
302 )
303 with fake_adbd() as (port, _):
304 with adb_connect(self, serial="localhost:{}".format(port)):
305 pass
306 finally:
307 # If we started a server, kill it.
308 subprocess.check_output(
309 ["adb", "-P", str(server_port), "kill-server"],
310 stderr=subprocess.STDOUT,
311 )
312
313
314
Luis Hector Chavez947b2132018-05-02 09:10:29 -0700315
316class EmulatorTest(unittest.TestCase):
317 """Tests for the emulator connection."""
318
Spencer Lowcc4a4b12015-10-14 17:32:44 -0700319 def _reset_socket_on_close(self, sock):
Luis Hector Chavez947b2132018-05-02 09:10:29 -0700320 """Use SO_LINGER to cause TCP RST segment to be sent on socket close."""
Spencer Lowcc4a4b12015-10-14 17:32:44 -0700321 # The linger structure is two shorts on Windows, but two ints on Unix.
Josh Gao4db70c52018-08-08 13:08:08 -0700322 linger_format = "hh" if os.name == "nt" else "ii"
Spencer Lowcc4a4b12015-10-14 17:32:44 -0700323 l_onoff = 1
324 l_linger = 0
325
326 sock.setsockopt(socket.SOL_SOCKET, socket.SO_LINGER,
327 struct.pack(linger_format, l_onoff, l_linger))
328 # Verify that we set the linger structure properly by retrieving it.
329 linger = sock.getsockopt(socket.SOL_SOCKET, socket.SO_LINGER, 16)
330 self.assertEqual((l_onoff, l_linger),
331 struct.unpack_from(linger_format, linger))
332
333 def test_emu_kill(self):
334 """Ensure that adb emu kill works.
335
336 Bug: https://code.google.com/p/android/issues/detail?id=21021
337 """
Spencer Lowcc4a4b12015-10-14 17:32:44 -0700338 with contextlib.closing(
Luis Hector Chavez947b2132018-05-02 09:10:29 -0700339 socket.socket(socket.AF_INET, socket.SOCK_STREAM)) as listener:
Spencer Lowcc4a4b12015-10-14 17:32:44 -0700340 # Use SO_REUSEADDR so subsequent runs of the test can grab the port
341 # even if it is in TIME_WAIT.
342 listener.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
Josh Gao4db70c52018-08-08 13:08:08 -0700343 listener.bind(("127.0.0.1", 0))
Spencer Lowcc4a4b12015-10-14 17:32:44 -0700344 listener.listen(4)
Josh Gao13781e82018-04-03 12:55:18 -0700345 port = listener.getsockname()[1]
Spencer Lowcc4a4b12015-10-14 17:32:44 -0700346
347 # Now that listening has started, start adb emu kill, telling it to
348 # connect to our mock emulator.
Luis Hector Chavez947b2132018-05-02 09:10:29 -0700349 proc = subprocess.Popen(
Josh Gao4db70c52018-08-08 13:08:08 -0700350 ["adb", "-s", "emulator-" + str(port), "emu", "kill"],
Spencer Lowcc4a4b12015-10-14 17:32:44 -0700351 stderr=subprocess.STDOUT)
352
353 accepted_connection, addr = listener.accept()
354 with contextlib.closing(accepted_connection) as conn:
355 # If WSAECONNABORTED (10053) is raised by any socket calls,
356 # then adb probably isn't reading the data that we sent it.
Josh Gao4db70c52018-08-08 13:08:08 -0700357 conn.sendall(("Android Console: type 'help' for a list "
358 "of commands\r\n").encode("utf8"))
359 conn.sendall(b"OK\r\n")
Spencer Lowcc4a4b12015-10-14 17:32:44 -0700360
Luis Hector Chavez947b2132018-05-02 09:10:29 -0700361 with contextlib.closing(conn.makefile()) as connf:
362 line = connf.readline()
Josh Gao4db70c52018-08-08 13:08:08 -0700363 if line.startswith("auth"):
Luis Hector Chavez947b2132018-05-02 09:10:29 -0700364 # Ignore the first auth line.
365 line = connf.readline()
Josh Gao4db70c52018-08-08 13:08:08 -0700366 self.assertEqual("kill\n", line)
367 self.assertEqual("quit\n", connf.readline())
Spencer Lowcc4a4b12015-10-14 17:32:44 -0700368
Josh Gao4db70c52018-08-08 13:08:08 -0700369 conn.sendall(b"OK: killing emulator, bye bye\r\n")
Spencer Lowcc4a4b12015-10-14 17:32:44 -0700370
371 # Use SO_LINGER to send TCP RST segment to test whether adb
372 # ignores WSAECONNRESET on Windows. This happens with the
373 # real emulator because it just calls exit() without closing
374 # the socket or calling shutdown(SD_SEND). At process
375 # termination, Windows sends a TCP RST segment for every
376 # open socket that shutdown(SD_SEND) wasn't used on.
377 self._reset_socket_on_close(conn)
378
379 # Wait for adb to finish, so we can check return code.
Luis Hector Chavez947b2132018-05-02 09:10:29 -0700380 proc.communicate()
Spencer Lowcc4a4b12015-10-14 17:32:44 -0700381
382 # If this fails, adb probably isn't ignoring WSAECONNRESET when
383 # reading the response from the adb emu kill command (on Windows).
Luis Hector Chavez947b2132018-05-02 09:10:29 -0700384 self.assertEqual(0, proc.returncode)
385
Luis Hector Chaveza452f0e2018-05-02 10:47:01 -0700386 def test_emulator_connect(self):
387 """Ensure that the emulator can connect.
388
389 Bug: http://b/78991667
390 """
391 with adb_server() as server_port:
Josh Gao13cb8c02018-08-10 14:44:54 -0700392 with fake_adbd() as (port, _):
Josh Gao4db70c52018-08-08 13:08:08 -0700393 serial = "emulator-{}".format(port - 1)
Luis Hector Chaveza452f0e2018-05-02 10:47:01 -0700394 # Ensure that the emulator is not there.
395 try:
Josh Gao4db70c52018-08-08 13:08:08 -0700396 subprocess.check_output(["adb", "-P", str(server_port),
397 "-s", serial, "get-state"],
Luis Hector Chaveza452f0e2018-05-02 10:47:01 -0700398 stderr=subprocess.STDOUT)
Josh Gao4db70c52018-08-08 13:08:08 -0700399 self.fail("Device should not be available")
Luis Hector Chaveza452f0e2018-05-02 10:47:01 -0700400 except subprocess.CalledProcessError as err:
401 self.assertEqual(
402 err.output.strip(),
Josh Gao4db70c52018-08-08 13:08:08 -0700403 "error: device '{}' not found".format(serial).encode("utf8"))
Luis Hector Chaveza452f0e2018-05-02 10:47:01 -0700404
405 # Let the ADB server know that the emulator has started.
406 with contextlib.closing(
Josh Gaob1df00e2018-08-07 14:31:17 -0700407 socket.socket(socket.AF_INET, socket.SOCK_STREAM)) as sock:
Josh Gao4db70c52018-08-08 13:08:08 -0700408 sock.connect(("localhost", server_port))
409 command = "host:emulator:{}".format(port).encode("utf8")
410 sock.sendall(b"%04x%s" % (len(command), command))
Luis Hector Chaveza452f0e2018-05-02 10:47:01 -0700411
412 # Ensure the emulator is there.
Josh Gao4db70c52018-08-08 13:08:08 -0700413 subprocess.check_call(["adb", "-P", str(server_port),
414 "-s", serial, "wait-for-device"])
415 output = subprocess.check_output(["adb", "-P", str(server_port),
416 "-s", serial, "get-state"])
417 self.assertEqual(output.strip(), b"device")
Luis Hector Chaveza452f0e2018-05-02 10:47:01 -0700418
Luis Hector Chavez947b2132018-05-02 09:10:29 -0700419
420class ConnectionTest(unittest.TestCase):
421 """Tests for adb connect."""
Spencer Lowcc4a4b12015-10-14 17:32:44 -0700422
Josh Gao50bde8d2016-09-01 14:54:18 -0700423 def test_connect_ipv4_ipv6(self):
424 """Ensure that `adb connect localhost:1234` will try both IPv4 and IPv6.
425
426 Bug: http://b/30313466
427 """
Luis Hector Chavezbf8a7222018-04-17 19:25:33 -0700428 for protocol in (socket.AF_INET, socket.AF_INET6):
429 try:
Josh Gao13cb8c02018-08-10 14:44:54 -0700430 with fake_adbd(protocol=protocol) as (port, _):
Josh Gao4db70c52018-08-08 13:08:08 -0700431 serial = "localhost:{}".format(port)
Luis Hector Chavez0aeda102018-04-20 10:31:29 -0700432 with adb_connect(self, serial):
433 pass
Luis Hector Chavezbf8a7222018-04-17 19:25:33 -0700434 except socket.error:
435 print("IPv6 not available, skipping")
436 continue
Josh Gao50bde8d2016-09-01 14:54:18 -0700437
Luis Hector Chavezbf8a7222018-04-17 19:25:33 -0700438 def test_already_connected(self):
Luis Hector Chavez0aeda102018-04-20 10:31:29 -0700439 """Ensure that an already-connected device stays connected."""
440
Josh Gao13cb8c02018-08-10 14:44:54 -0700441 with fake_adbd() as (port, _):
Josh Gao4db70c52018-08-08 13:08:08 -0700442 serial = "localhost:{}".format(port)
Luis Hector Chavez0aeda102018-04-20 10:31:29 -0700443 with adb_connect(self, serial):
444 # b/31250450: this always returns 0 but probably shouldn't.
Josh Gao4db70c52018-08-08 13:08:08 -0700445 output = subprocess.check_output(["adb", "connect", serial])
Luis Hector Chavez0aeda102018-04-20 10:31:29 -0700446 self.assertEqual(
Josh Gaob1df00e2018-08-07 14:31:17 -0700447 output.strip(),
Josh Gao4db70c52018-08-08 13:08:08 -0700448 "already connected to {}".format(serial).encode("utf8"))
Josh Gao50bde8d2016-09-01 14:54:18 -0700449
Julien Desprez0e8a0a02019-02-20 09:42:49 -0800450 @unittest.skip("Currently failing b/123247844")
Luis Hector Chavez0aeda102018-04-20 10:31:29 -0700451 def test_reconnect(self):
452 """Ensure that a disconnected device reconnects."""
Josh Gao50bde8d2016-09-01 14:54:18 -0700453
Josh Gao13cb8c02018-08-10 14:44:54 -0700454 with fake_adbd() as (port, _):
Josh Gao4db70c52018-08-08 13:08:08 -0700455 serial = "localhost:{}".format(port)
Luis Hector Chavez0aeda102018-04-20 10:31:29 -0700456 with adb_connect(self, serial):
Josh Gao2645b0a2019-02-07 17:53:29 -0800457 # Wait a bit to give adb some time to connect.
458 time.sleep(0.25)
459
Josh Gao4db70c52018-08-08 13:08:08 -0700460 output = subprocess.check_output(["adb", "-s", serial,
461 "get-state"])
462 self.assertEqual(output.strip(), b"device")
Josh Gao13781e82018-04-03 12:55:18 -0700463
Luis Hector Chavez0aeda102018-04-20 10:31:29 -0700464 # This will fail.
Josh Gao4db70c52018-08-08 13:08:08 -0700465 proc = subprocess.Popen(["adb", "-s", serial, "shell", "true"],
Luis Hector Chavez947b2132018-05-02 09:10:29 -0700466 stdout=subprocess.PIPE,
467 stderr=subprocess.STDOUT)
468 output, _ = proc.communicate()
Josh Gao4db70c52018-08-08 13:08:08 -0700469 self.assertEqual(output.strip(), b"error: closed")
Luis Hector Chavez0aeda102018-04-20 10:31:29 -0700470
Josh Gao4db70c52018-08-08 13:08:08 -0700471 subprocess.check_call(["adb", "-s", serial, "wait-for-device"])
Luis Hector Chavez0aeda102018-04-20 10:31:29 -0700472
Josh Gao4db70c52018-08-08 13:08:08 -0700473 output = subprocess.check_output(["adb", "-s", serial,
474 "get-state"])
475 self.assertEqual(output.strip(), b"device")
Luis Hector Chavez0aeda102018-04-20 10:31:29 -0700476
477 # Once we explicitly kick a device, it won't attempt to
478 # reconnect.
Josh Gao4db70c52018-08-08 13:08:08 -0700479 output = subprocess.check_output(["adb", "disconnect", serial])
Luis Hector Chavez0aeda102018-04-20 10:31:29 -0700480 self.assertEqual(
Josh Gaob1df00e2018-08-07 14:31:17 -0700481 output.strip(),
Josh Gao4db70c52018-08-08 13:08:08 -0700482 "disconnected {}".format(serial).encode("utf8"))
Luis Hector Chavez0aeda102018-04-20 10:31:29 -0700483 try:
Josh Gao4db70c52018-08-08 13:08:08 -0700484 subprocess.check_output(["adb", "-s", serial, "get-state"],
Luis Hector Chavez0aeda102018-04-20 10:31:29 -0700485 stderr=subprocess.STDOUT)
Josh Gao4db70c52018-08-08 13:08:08 -0700486 self.fail("Device should not be available")
Luis Hector Chavez947b2132018-05-02 09:10:29 -0700487 except subprocess.CalledProcessError as err:
Luis Hector Chavez0aeda102018-04-20 10:31:29 -0700488 self.assertEqual(
Luis Hector Chavez947b2132018-05-02 09:10:29 -0700489 err.output.strip(),
Josh Gao4db70c52018-08-08 13:08:08 -0700490 "error: device '{}' not found".format(serial).encode("utf8"))
Spencer Lowcc4a4b12015-10-14 17:32:44 -0700491
Luis Hector Chavez947b2132018-05-02 09:10:29 -0700492
Josh Gao13cb8c02018-08-10 14:44:54 -0700493class DisconnectionTest(unittest.TestCase):
494 """Tests for adb disconnect."""
495
496 def test_disconnect(self):
497 """Ensure that `adb disconnect` takes effect immediately."""
498
499 def _devices(port):
500 output = subprocess.check_output(["adb", "-P", str(port), "devices"])
501 return [x.split("\t") for x in output.decode("utf8").strip().splitlines()[1:]]
502
503 with adb_server() as server_port:
504 with fake_adbd() as (port, sock):
505 device_name = "localhost:{}".format(port)
506 output = subprocess.check_output(["adb", "-P", str(server_port),
507 "connect", device_name])
508 self.assertEqual(output.strip(),
509 "connected to {}".format(device_name).encode("utf8"))
510
511
512 self.assertEqual(_devices(server_port), [[device_name, "device"]])
513
514 # Send a deliberately malformed packet to make the device go offline.
515 packet = struct.pack("IIIIII", 0, 0, 0, 0, 0, 0)
516 sock.sendall(packet)
517
518 # Wait a bit.
519 time.sleep(0.1)
520
521 self.assertEqual(_devices(server_port), [[device_name, "offline"]])
522
523 # Disconnect the device.
524 output = subprocess.check_output(["adb", "-P", str(server_port),
525 "disconnect", device_name])
526
527 # Wait a bit.
528 time.sleep(0.1)
529
530 self.assertEqual(_devices(server_port), [])
531
532
Spencer Lowebd8d322018-08-31 19:49:46 -0700533@unittest.skipUnless(sys.platform == "win32", "requires Windows")
534class PowerTest(unittest.TestCase):
535 def test_resume_usb_kick(self):
536 """Resuming from sleep/hibernate should kick USB devices."""
537 try:
538 usb_serial = subprocess.check_output(["adb", "-d", "get-serialno"]).strip()
539 except subprocess.CalledProcessError:
540 # If there are multiple USB devices, we don't have a way to check whether the selected
541 # device is USB.
542 raise unittest.SkipTest('requires single USB device')
543
544 try:
545 serial = subprocess.check_output(["adb", "get-serialno"]).strip()
546 except subprocess.CalledProcessError:
547 # Did you forget to select a device with $ANDROID_SERIAL?
548 raise unittest.SkipTest('requires $ANDROID_SERIAL set to a USB device')
549
550 # Test only works with USB devices because adb _power_notification_thread does not kick
551 # non-USB devices on resume event.
552 if serial != usb_serial:
553 raise unittest.SkipTest('requires USB device')
554
555 # Run an adb shell command in the background that takes a while to complete.
556 proc = subprocess.Popen(['adb', 'shell', 'sleep', '5'])
557
558 # Wait for startup of adb server's _power_notification_thread.
559 time.sleep(0.1)
560
561 # Simulate resuming from sleep/hibernation by sending Windows message.
562 import ctypes
563 from ctypes import wintypes
564 HWND_BROADCAST = 0xffff
565 WM_POWERBROADCAST = 0x218
566 PBT_APMRESUMEAUTOMATIC = 0x12
567
568 PostMessageW = ctypes.windll.user32.PostMessageW
569 PostMessageW.restype = wintypes.BOOL
570 PostMessageW.argtypes = (wintypes.HWND, wintypes.UINT, wintypes.WPARAM, wintypes.LPARAM)
571 result = PostMessageW(HWND_BROADCAST, WM_POWERBROADCAST, PBT_APMRESUMEAUTOMATIC, 0)
572 if not result:
573 raise ctypes.WinError()
574
575 # Wait for connection to adb shell to be broken by _power_notification_thread detecting the
576 # Windows message.
577 start = time.time()
578 proc.wait()
579 end = time.time()
580
581 # If the power event was detected, the adb shell command should be broken very quickly.
582 self.assertLess(end - start, 2)
583
584
Dan Alberta4169f92015-07-24 17:08:33 -0700585def main():
Luis Hector Chavez947b2132018-05-02 09:10:29 -0700586 """Main entrypoint."""
Dan Alberta4169f92015-07-24 17:08:33 -0700587 random.seed(0)
Luis Hector Chavez947b2132018-05-02 09:10:29 -0700588 unittest.main(verbosity=3)
Dan Alberta4169f92015-07-24 17:08:33 -0700589
590
Josh Gao4db70c52018-08-08 13:08:08 -0700591if __name__ == "__main__":
Dan Alberta4169f92015-07-24 17:08:33 -0700592 main()