blob: 8272722e88ecc842eb34237c00bd0a5f5e458b5d [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
Josh Gao92cd59f2018-08-21 14:25:05 -070030import sys
Spencer Low1ce06082015-09-16 20:45:53 -070031import threading
Josh Gao902dace2018-08-10 14:44:54 -070032import time
Dan Albert8e1fdd72015-07-24 17:08:33 -070033import unittest
Josh Gao42c86722018-10-16 11:00:39 -070034import warnings
Dan Albert8e1fdd72015-07-24 17:08:33 -070035
Dan Albert8e1fdd72015-07-24 17:08:33 -070036
Luis Hector Chavez8b67c522018-04-17 19:25:33 -070037@contextlib.contextmanager
Luis Hector Chavezfbee0a92018-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 Chavez8b67c522018-04-17 19:25:33 -070040
41 serversock = socket.socket(protocol, socket.SOCK_STREAM)
Luis Hector Chavezfbee0a92018-05-02 09:10:29 -070042 serversock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
Luis Hector Chavez8b67c522018-04-17 19:25:33 -070043 if protocol == socket.AF_INET:
Josh Gaob3610732018-08-08 13:08:08 -070044 serversock.bind(("127.0.0.1", port))
Luis Hector Chavez8b67c522018-04-17 19:25:33 -070045 else:
Josh Gaob3610732018-08-08 13:08:08 -070046 serversock.bind(("::1", port))
Luis Hector Chavez8b67c522018-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 Gao676f375d2018-08-07 16:07:25 -070050 readsock, writesock = socket.socketpair()
Luis Hector Chavez8b67c522018-04-17 19:25:33 -070051
Josh Gao9b6522b2018-08-07 14:31:17 -070052 def _adb_packet(command: bytes, arg0: int, arg1: int, data: bytes) -> bytes:
Josh Gaob3610732018-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 Chavez56fe7532018-04-17 14:25:04 -070055 bin_command ^ 0xffffffff)
56 buf += data
57 return buf
58
Josh Gao9b6522b2018-08-07 14:31:17 -070059 def _handle(sock):
60 with contextlib.closing(sock) as serversock:
Josh Gao676f375d2018-08-07 16:07:25 -070061 rlist = [readsock, serversock]
Josh Gao9b6522b2018-08-07 14:31:17 -070062 cnxn_sent = {}
63 while True:
64 read_ready, _, _ = select.select(rlist, [], [])
65 for ready in read_ready:
Josh Gao676f375d2018-08-07 16:07:25 -070066 if ready == readsock:
Josh Gao9b6522b2018-08-07 14:31:17 -070067 # Closure pipe
Josh Gao9b6522b2018-08-07 14:31:17 -070068 for f in rlist:
Josh Gao676f375d2018-08-07 16:07:25 -070069 f.close()
Josh Gao9b6522b2018-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 Gaob3610732018-08-08 13:08:08 -070078 if not data or data.startswith(b"OPEN"):
Josh Gao9b6522b2018-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 Chavezfbee0a92018-05-02 09:10:29 -070085 if ready in cnxn_sent:
Josh Gao9b6522b2018-08-07 14:31:17 -070086 continue
87 cnxn_sent[ready] = True
Josh Gaob3610732018-08-08 13:08:08 -070088 ready.sendall(_adb_packet(b"CNXN", 0x01000001, 1024 * 1024,
89 b"device::ro.product.name=fakeadb"))
Luis Hector Chavez8b67c522018-04-17 19:25:33 -070090
91 port = serversock.getsockname()[1]
Josh Gao9b6522b2018-08-07 14:31:17 -070092 server_thread = threading.Thread(target=_handle, args=(serversock,))
Luis Hector Chavez8b67c522018-04-17 19:25:33 -070093 server_thread.start()
94
95 try:
Josh Gao902dace2018-08-10 14:44:54 -070096 yield port, writesock
Luis Hector Chavez8b67c522018-04-17 19:25:33 -070097 finally:
Josh Gao676f375d2018-08-07 16:07:25 -070098 writesock.close()
Luis Hector Chavez8b67c522018-04-17 19:25:33 -070099 server_thread.join()
100
101
Luis Hector Chavez454bc7c2018-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 Gaob3610732018-08-08 13:08:08 -0700109 output = subprocess.check_output(["adb", "connect", serial])
Josh Gao9b6522b2018-08-07 14:31:17 -0700110 unittest.assertEqual(output.strip(),
Josh Gaob3610732018-08-08 13:08:08 -0700111 "connected to {}".format(serial).encode("utf8"))
Luis Hector Chavez454bc7c2018-04-20 10:31:29 -0700112
113 try:
114 yield
115 finally:
116 # Perform best-effort disconnection. Discard the output.
Josh Gaob3610732018-08-08 13:08:08 -0700117 subprocess.Popen(["adb", "disconnect", serial],
Luis Hector Chavezfbee0a92018-05-02 09:10:29 -0700118 stdout=subprocess.PIPE,
119 stderr=subprocess.PIPE).communicate()
Luis Hector Chavez454bc7c2018-04-20 10:31:29 -0700120
121
Luis Hector Chavez32559742018-05-02 10:47:01 -0700122@contextlib.contextmanager
123def adb_server():
124 """Context manager for an ADB server.
125
Josh Gao902dace2018-08-10 14:44:54 -0700126 This creates an ADB server and returns the port it's listening on.
Luis Hector Chavez32559742018-05-02 10:47:01 -0700127 """
128
129 port = 5038
130 # Kill any existing server on this non-default port.
Josh Gaob3610732018-08-08 13:08:08 -0700131 subprocess.check_output(["adb", "-P", str(port), "kill-server"],
Luis Hector Chavez32559742018-05-02 10:47:01 -0700132 stderr=subprocess.STDOUT)
133 read_pipe, write_pipe = os.pipe()
Josh Gao92cd59f2018-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 Gaob3610732018-08-08 13:08:08 -0700144 proc = subprocess.Popen(["adb", "-L", "tcp:localhost:{}".format(port),
145 "fork-server", "server",
Josh Gao92cd59f2018-08-21 14:25:05 -0700146 "--reply-fd", reply_fd], close_fds=False)
Luis Hector Chavez32559742018-05-02 10:47:01 -0700147 try:
148 os.close(write_pipe)
149 greeting = os.read(read_pipe, 1024)
Josh Gaob3610732018-08-08 13:08:08 -0700150 assert greeting == b"OK\n", repr(greeting)
Luis Hector Chavez32559742018-05-02 10:47:01 -0700151 yield port
152 finally:
153 proc.terminate()
154 proc.wait()
155
156
Luis Hector Chavezfbee0a92018-05-02 09:10:29 -0700157class CommandlineTest(unittest.TestCase):
158 """Tests for the ADB commandline."""
Dan Albert8e1fdd72015-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 Gaob3610732018-08-08 13:08:08 -0700163 ["adb", "help"], stderr=subprocess.STDOUT)
Dan Albert8e1fdd72015-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 Gaob3610732018-08-08 13:08:08 -0700168 lines = subprocess.check_output(["adb", "version"]).splitlines()
Dan Albert8e1fdd72015-07-24 17:08:33 -0700169 version_line = lines[0]
Josh Gao9b6522b2018-08-07 14:31:17 -0700170 self.assertRegex(
Josh Gaob3610732018-08-08 13:08:08 -0700171 version_line, rb"^Android Debug Bridge version \d+\.\d+\.\d+$")
Dan Albert8e1fdd72015-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 Gao9b6522b2018-08-07 14:31:17 -0700176 self.assertRegex(
Josh Gaob3610732018-08-08 13:08:08 -0700177 revision_line, rb"^Revision [0-9a-f]{12}-android$")
Dan Albert8e1fdd72015-07-24 17:08:33 -0700178
179 def test_tcpip_error_messages(self):
Luis Hector Chavezfbee0a92018-05-02 09:10:29 -0700180 """Make sure 'adb tcpip' parsing is sane."""
Josh Gaob3610732018-08-08 13:08:08 -0700181 proc = subprocess.Popen(["adb", "tcpip"],
Josh Gao9b6522b2018-08-07 14:31:17 -0700182 stdout=subprocess.PIPE,
Luis Hector Chavezfbee0a92018-05-02 09:10:29 -0700183 stderr=subprocess.STDOUT)
184 out, _ = proc.communicate()
185 self.assertEqual(1, proc.returncode)
Josh Gaob3610732018-08-08 13:08:08 -0700186 self.assertIn(b"requires an argument", out)
Dan Albert8e1fdd72015-07-24 17:08:33 -0700187
Josh Gaob3610732018-08-08 13:08:08 -0700188 proc = subprocess.Popen(["adb", "tcpip", "foo"],
Josh Gao9b6522b2018-08-07 14:31:17 -0700189 stdout=subprocess.PIPE,
Luis Hector Chavezfbee0a92018-05-02 09:10:29 -0700190 stderr=subprocess.STDOUT)
191 out, _ = proc.communicate()
192 self.assertEqual(1, proc.returncode)
Josh Gaob3610732018-08-08 13:08:08 -0700193 self.assertIn(b"invalid port", out)
Dan Albert8e1fdd72015-07-24 17:08:33 -0700194
Luis Hector Chavezfbee0a92018-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 Low1ce06082015-09-16 20:45:53 -0700203 event.set()
204
Spencer Low1ce06082015-09-16 20:45:53 -0700205 def test_handle_inheritance(self):
Luis Hector Chavezfbee0a92018-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 Low1ce06082015-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 Gaob3610732018-08-08 13:08:08 -0700229 subprocess.check_output(["adb", "-P", str(port), "kill-server"],
Spencer Low1ce06082015-09-16 20:45:53 -0700230 stderr=subprocess.STDOUT)
231
232 try:
Josh Gao42c86722018-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 Low1ce06082015-09-16 20:45:53 -0700237 # Run the adb client and have it start the adb server.
Josh Gaob3610732018-08-08 13:08:08 -0700238 proc = subprocess.Popen(["adb", "-P", str(port), "start-server"],
Luis Hector Chavezfbee0a92018-05-02 09:10:29 -0700239 stdin=subprocess.PIPE,
240 stdout=subprocess.PIPE,
241 stderr=subprocess.PIPE)
Spencer Low1ce06082015-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 Chavezfbee0a92018-05-02 09:10:29 -0700246 target=ServerTest._read_pipe_and_set_event,
247 args=(proc.stdout, stdout_event))
Spencer Low1ce06082015-09-16 20:45:53 -0700248 stdout_thread.start()
249
250 stderr_event = threading.Event()
251 stderr_thread = threading.Thread(
Luis Hector Chavezfbee0a92018-05-02 09:10:29 -0700252 target=ServerTest._read_pipe_and_set_event,
253 args=(proc.stderr, stderr_event))
Spencer Low1ce06082015-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 Chavezfbee0a92018-05-02 09:10:29 -0700259 proc.wait()
Spencer Low1ce06082015-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 Gaob3610732018-08-08 13:08:08 -0700267 proc.stdin.write(b"x")
Josh Gao9b6522b2018-08-07 14:31:17 -0700268 proc.stdin.flush()
Spencer Low1ce06082015-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 Gao9b6522b2018-08-07 14:31:17 -0700277 stdout_thread.join()
278 stderr_thread.join()
Spencer Low1ce06082015-09-16 20:45:53 -0700279 finally:
280 # If we started a server, kill it.
Josh Gaob3610732018-08-08 13:08:08 -0700281 subprocess.check_output(["adb", "-P", str(port), "kill-server"],
Spencer Low1ce06082015-09-16 20:45:53 -0700282 stderr=subprocess.STDOUT)
Dan Albert8e1fdd72015-07-24 17:08:33 -0700283
Luis Hector Chavezfbee0a92018-05-02 09:10:29 -0700284
285class EmulatorTest(unittest.TestCase):
286 """Tests for the emulator connection."""
287
Spencer Low351ecd12015-10-14 17:32:44 -0700288 def _reset_socket_on_close(self, sock):
Luis Hector Chavezfbee0a92018-05-02 09:10:29 -0700289 """Use SO_LINGER to cause TCP RST segment to be sent on socket close."""
Spencer Low351ecd12015-10-14 17:32:44 -0700290 # The linger structure is two shorts on Windows, but two ints on Unix.
Josh Gaob3610732018-08-08 13:08:08 -0700291 linger_format = "hh" if os.name == "nt" else "ii"
Spencer Low351ecd12015-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 Low351ecd12015-10-14 17:32:44 -0700307 with contextlib.closing(
Luis Hector Chavezfbee0a92018-05-02 09:10:29 -0700308 socket.socket(socket.AF_INET, socket.SOCK_STREAM)) as listener:
Spencer Low351ecd12015-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 Gaob3610732018-08-08 13:08:08 -0700312 listener.bind(("127.0.0.1", 0))
Spencer Low351ecd12015-10-14 17:32:44 -0700313 listener.listen(4)
Josh Gaoc251ec52018-04-03 12:55:18 -0700314 port = listener.getsockname()[1]
Spencer Low351ecd12015-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 Chavezfbee0a92018-05-02 09:10:29 -0700318 proc = subprocess.Popen(
Josh Gaob3610732018-08-08 13:08:08 -0700319 ["adb", "-s", "emulator-" + str(port), "emu", "kill"],
Spencer Low351ecd12015-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 Gaob3610732018-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 Low351ecd12015-10-14 17:32:44 -0700329
Luis Hector Chavezfbee0a92018-05-02 09:10:29 -0700330 with contextlib.closing(conn.makefile()) as connf:
331 line = connf.readline()
Josh Gaob3610732018-08-08 13:08:08 -0700332 if line.startswith("auth"):
Luis Hector Chavezfbee0a92018-05-02 09:10:29 -0700333 # Ignore the first auth line.
334 line = connf.readline()
Josh Gaob3610732018-08-08 13:08:08 -0700335 self.assertEqual("kill\n", line)
336 self.assertEqual("quit\n", connf.readline())
Spencer Low351ecd12015-10-14 17:32:44 -0700337
Josh Gaob3610732018-08-08 13:08:08 -0700338 conn.sendall(b"OK: killing emulator, bye bye\r\n")
Spencer Low351ecd12015-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 Chavezfbee0a92018-05-02 09:10:29 -0700349 proc.communicate()
Spencer Low351ecd12015-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 Chavezfbee0a92018-05-02 09:10:29 -0700353 self.assertEqual(0, proc.returncode)
354
Luis Hector Chavez32559742018-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 Gao902dace2018-08-10 14:44:54 -0700361 with fake_adbd() as (port, _):
Josh Gaob3610732018-08-08 13:08:08 -0700362 serial = "emulator-{}".format(port - 1)
Luis Hector Chavez32559742018-05-02 10:47:01 -0700363 # Ensure that the emulator is not there.
364 try:
Josh Gaob3610732018-08-08 13:08:08 -0700365 subprocess.check_output(["adb", "-P", str(server_port),
366 "-s", serial, "get-state"],
Luis Hector Chavez32559742018-05-02 10:47:01 -0700367 stderr=subprocess.STDOUT)
Josh Gaob3610732018-08-08 13:08:08 -0700368 self.fail("Device should not be available")
Luis Hector Chavez32559742018-05-02 10:47:01 -0700369 except subprocess.CalledProcessError as err:
370 self.assertEqual(
371 err.output.strip(),
Josh Gaob3610732018-08-08 13:08:08 -0700372 "error: device '{}' not found".format(serial).encode("utf8"))
Luis Hector Chavez32559742018-05-02 10:47:01 -0700373
374 # Let the ADB server know that the emulator has started.
375 with contextlib.closing(
Josh Gao9b6522b2018-08-07 14:31:17 -0700376 socket.socket(socket.AF_INET, socket.SOCK_STREAM)) as sock:
Josh Gaob3610732018-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 Chavez32559742018-05-02 10:47:01 -0700380
381 # Ensure the emulator is there.
Josh Gaob3610732018-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 Chavez32559742018-05-02 10:47:01 -0700387
Luis Hector Chavezfbee0a92018-05-02 09:10:29 -0700388
389class ConnectionTest(unittest.TestCase):
390 """Tests for adb connect."""
Spencer Low351ecd12015-10-14 17:32:44 -0700391
Josh Gao78cc20f2016-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 Chavez8b67c522018-04-17 19:25:33 -0700397 for protocol in (socket.AF_INET, socket.AF_INET6):
398 try:
Josh Gao902dace2018-08-10 14:44:54 -0700399 with fake_adbd(protocol=protocol) as (port, _):
Josh Gaob3610732018-08-08 13:08:08 -0700400 serial = "localhost:{}".format(port)
Luis Hector Chavez454bc7c2018-04-20 10:31:29 -0700401 with adb_connect(self, serial):
402 pass
Luis Hector Chavez8b67c522018-04-17 19:25:33 -0700403 except socket.error:
404 print("IPv6 not available, skipping")
405 continue
Josh Gao78cc20f2016-09-01 14:54:18 -0700406
Luis Hector Chavez8b67c522018-04-17 19:25:33 -0700407 def test_already_connected(self):
Luis Hector Chavez454bc7c2018-04-20 10:31:29 -0700408 """Ensure that an already-connected device stays connected."""
409
Josh Gao902dace2018-08-10 14:44:54 -0700410 with fake_adbd() as (port, _):
Josh Gaob3610732018-08-08 13:08:08 -0700411 serial = "localhost:{}".format(port)
Luis Hector Chavez454bc7c2018-04-20 10:31:29 -0700412 with adb_connect(self, serial):
413 # b/31250450: this always returns 0 but probably shouldn't.
Josh Gaob3610732018-08-08 13:08:08 -0700414 output = subprocess.check_output(["adb", "connect", serial])
Luis Hector Chavez454bc7c2018-04-20 10:31:29 -0700415 self.assertEqual(
Josh Gao9b6522b2018-08-07 14:31:17 -0700416 output.strip(),
Josh Gaob3610732018-08-08 13:08:08 -0700417 "already connected to {}".format(serial).encode("utf8"))
Josh Gao78cc20f2016-09-01 14:54:18 -0700418
Julien Desprezfb4c1352019-02-20 09:42:49 -0800419 @unittest.skip("Currently failing b/123247844")
Luis Hector Chavez454bc7c2018-04-20 10:31:29 -0700420 def test_reconnect(self):
421 """Ensure that a disconnected device reconnects."""
Josh Gao78cc20f2016-09-01 14:54:18 -0700422
Josh Gao902dace2018-08-10 14:44:54 -0700423 with fake_adbd() as (port, _):
Josh Gaob3610732018-08-08 13:08:08 -0700424 serial = "localhost:{}".format(port)
Luis Hector Chavez454bc7c2018-04-20 10:31:29 -0700425 with adb_connect(self, serial):
Josh Gaoaa95aa02019-02-07 17:53:29 -0800426 # Wait a bit to give adb some time to connect.
427 time.sleep(0.25)
428
Josh Gaob3610732018-08-08 13:08:08 -0700429 output = subprocess.check_output(["adb", "-s", serial,
430 "get-state"])
431 self.assertEqual(output.strip(), b"device")
Josh Gaoc251ec52018-04-03 12:55:18 -0700432
Luis Hector Chavez454bc7c2018-04-20 10:31:29 -0700433 # This will fail.
Josh Gaob3610732018-08-08 13:08:08 -0700434 proc = subprocess.Popen(["adb", "-s", serial, "shell", "true"],
Luis Hector Chavezfbee0a92018-05-02 09:10:29 -0700435 stdout=subprocess.PIPE,
436 stderr=subprocess.STDOUT)
437 output, _ = proc.communicate()
Josh Gaob3610732018-08-08 13:08:08 -0700438 self.assertEqual(output.strip(), b"error: closed")
Luis Hector Chavez454bc7c2018-04-20 10:31:29 -0700439
Josh Gaob3610732018-08-08 13:08:08 -0700440 subprocess.check_call(["adb", "-s", serial, "wait-for-device"])
Luis Hector Chavez454bc7c2018-04-20 10:31:29 -0700441
Josh Gaob3610732018-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 Chavez454bc7c2018-04-20 10:31:29 -0700445
446 # Once we explicitly kick a device, it won't attempt to
447 # reconnect.
Josh Gaob3610732018-08-08 13:08:08 -0700448 output = subprocess.check_output(["adb", "disconnect", serial])
Luis Hector Chavez454bc7c2018-04-20 10:31:29 -0700449 self.assertEqual(
Josh Gao9b6522b2018-08-07 14:31:17 -0700450 output.strip(),
Josh Gaob3610732018-08-08 13:08:08 -0700451 "disconnected {}".format(serial).encode("utf8"))
Luis Hector Chavez454bc7c2018-04-20 10:31:29 -0700452 try:
Josh Gaob3610732018-08-08 13:08:08 -0700453 subprocess.check_output(["adb", "-s", serial, "get-state"],
Luis Hector Chavez454bc7c2018-04-20 10:31:29 -0700454 stderr=subprocess.STDOUT)
Josh Gaob3610732018-08-08 13:08:08 -0700455 self.fail("Device should not be available")
Luis Hector Chavezfbee0a92018-05-02 09:10:29 -0700456 except subprocess.CalledProcessError as err:
Luis Hector Chavez454bc7c2018-04-20 10:31:29 -0700457 self.assertEqual(
Luis Hector Chavezfbee0a92018-05-02 09:10:29 -0700458 err.output.strip(),
Josh Gaob3610732018-08-08 13:08:08 -0700459 "error: device '{}' not found".format(serial).encode("utf8"))
Spencer Low351ecd12015-10-14 17:32:44 -0700460
Luis Hector Chavezfbee0a92018-05-02 09:10:29 -0700461
Josh Gao902dace2018-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 Low8f6bdc92018-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 Albert8e1fdd72015-07-24 17:08:33 -0700554def main():
Luis Hector Chavezfbee0a92018-05-02 09:10:29 -0700555 """Main entrypoint."""
Dan Albert8e1fdd72015-07-24 17:08:33 -0700556 random.seed(0)
Luis Hector Chavezfbee0a92018-05-02 09:10:29 -0700557 unittest.main(verbosity=3)
Dan Albert8e1fdd72015-07-24 17:08:33 -0700558
559
Josh Gaob3610732018-08-08 13:08:08 -0700560if __name__ == "__main__":
Dan Albert8e1fdd72015-07-24 17:08:33 -0700561 main()