blob: 6989e3ba9232acdd61edadf7b16f09e7c11ca652 [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
Josh Gaoe8829c62020-02-27 14:29:38 -080036def find_open_port():
37 # Find an open port.
38 with socket.socket() as s:
39 s.bind(("localhost", 0))
40 return s.getsockname()[1]
Dan Albert8e1fdd72015-07-24 17:08:33 -070041
Luis Hector Chavez8b67c522018-04-17 19:25:33 -070042@contextlib.contextmanager
Luis Hector Chavezfbee0a92018-05-02 09:10:29 -070043def fake_adbd(protocol=socket.AF_INET, port=0):
44 """Creates a fake ADB daemon that just replies with a CNXN packet."""
Luis Hector Chavez8b67c522018-04-17 19:25:33 -070045
46 serversock = socket.socket(protocol, socket.SOCK_STREAM)
Luis Hector Chavezfbee0a92018-05-02 09:10:29 -070047 serversock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
Luis Hector Chavez8b67c522018-04-17 19:25:33 -070048 if protocol == socket.AF_INET:
Josh Gaob3610732018-08-08 13:08:08 -070049 serversock.bind(("127.0.0.1", port))
Luis Hector Chavez8b67c522018-04-17 19:25:33 -070050 else:
Josh Gaob3610732018-08-08 13:08:08 -070051 serversock.bind(("::1", port))
Luis Hector Chavez8b67c522018-04-17 19:25:33 -070052 serversock.listen(1)
53
54 # A pipe that is used to signal the thread that it should terminate.
Josh Gao676f375d2018-08-07 16:07:25 -070055 readsock, writesock = socket.socketpair()
Luis Hector Chavez8b67c522018-04-17 19:25:33 -070056
Josh Gao9b6522b2018-08-07 14:31:17 -070057 def _adb_packet(command: bytes, arg0: int, arg1: int, data: bytes) -> bytes:
Josh Gaob3610732018-08-08 13:08:08 -070058 bin_command = struct.unpack("I", command)[0]
59 buf = struct.pack("IIIIII", bin_command, arg0, arg1, len(data), 0,
Luis Hector Chavez56fe7532018-04-17 14:25:04 -070060 bin_command ^ 0xffffffff)
61 buf += data
62 return buf
63
Josh Gao9b6522b2018-08-07 14:31:17 -070064 def _handle(sock):
65 with contextlib.closing(sock) as serversock:
Josh Gao676f375d2018-08-07 16:07:25 -070066 rlist = [readsock, serversock]
Josh Gao9b6522b2018-08-07 14:31:17 -070067 cnxn_sent = {}
68 while True:
69 read_ready, _, _ = select.select(rlist, [], [])
70 for ready in read_ready:
Josh Gao676f375d2018-08-07 16:07:25 -070071 if ready == readsock:
Josh Gao9b6522b2018-08-07 14:31:17 -070072 # Closure pipe
Josh Gao9b6522b2018-08-07 14:31:17 -070073 for f in rlist:
Josh Gao676f375d2018-08-07 16:07:25 -070074 f.close()
Josh Gao9b6522b2018-08-07 14:31:17 -070075 return
76 elif ready == serversock:
77 # Server socket
78 conn, _ = ready.accept()
79 rlist.append(conn)
80 else:
81 # Client socket
82 data = ready.recv(1024)
Josh Gaob3610732018-08-08 13:08:08 -070083 if not data or data.startswith(b"OPEN"):
Josh Gao9b6522b2018-08-07 14:31:17 -070084 if ready in cnxn_sent:
85 del cnxn_sent[ready]
86 ready.shutdown(socket.SHUT_RDWR)
87 ready.close()
88 rlist.remove(ready)
89 continue
Luis Hector Chavezfbee0a92018-05-02 09:10:29 -070090 if ready in cnxn_sent:
Josh Gao9b6522b2018-08-07 14:31:17 -070091 continue
92 cnxn_sent[ready] = True
Josh Gaob3610732018-08-08 13:08:08 -070093 ready.sendall(_adb_packet(b"CNXN", 0x01000001, 1024 * 1024,
94 b"device::ro.product.name=fakeadb"))
Luis Hector Chavez8b67c522018-04-17 19:25:33 -070095
96 port = serversock.getsockname()[1]
Josh Gao9b6522b2018-08-07 14:31:17 -070097 server_thread = threading.Thread(target=_handle, args=(serversock,))
Luis Hector Chavez8b67c522018-04-17 19:25:33 -070098 server_thread.start()
99
100 try:
Josh Gao902dace2018-08-10 14:44:54 -0700101 yield port, writesock
Luis Hector Chavez8b67c522018-04-17 19:25:33 -0700102 finally:
Josh Gao676f375d2018-08-07 16:07:25 -0700103 writesock.close()
Luis Hector Chavez8b67c522018-04-17 19:25:33 -0700104 server_thread.join()
105
106
Luis Hector Chavez454bc7c2018-04-20 10:31:29 -0700107@contextlib.contextmanager
108def adb_connect(unittest, serial):
109 """Context manager for an ADB connection.
110
111 This automatically disconnects when done with the connection.
112 """
113
Josh Gaob3610732018-08-08 13:08:08 -0700114 output = subprocess.check_output(["adb", "connect", serial])
Josh Gao9b6522b2018-08-07 14:31:17 -0700115 unittest.assertEqual(output.strip(),
Josh Gaob3610732018-08-08 13:08:08 -0700116 "connected to {}".format(serial).encode("utf8"))
Luis Hector Chavez454bc7c2018-04-20 10:31:29 -0700117
118 try:
119 yield
120 finally:
121 # Perform best-effort disconnection. Discard the output.
Josh Gaob3610732018-08-08 13:08:08 -0700122 subprocess.Popen(["adb", "disconnect", serial],
Luis Hector Chavezfbee0a92018-05-02 09:10:29 -0700123 stdout=subprocess.PIPE,
124 stderr=subprocess.PIPE).communicate()
Luis Hector Chavez454bc7c2018-04-20 10:31:29 -0700125
126
Luis Hector Chavez32559742018-05-02 10:47:01 -0700127@contextlib.contextmanager
128def adb_server():
129 """Context manager for an ADB server.
130
Josh Gao902dace2018-08-10 14:44:54 -0700131 This creates an ADB server and returns the port it's listening on.
Luis Hector Chavez32559742018-05-02 10:47:01 -0700132 """
133
Josh Gaoe8829c62020-02-27 14:29:38 -0800134 port = find_open_port()
Luis Hector Chavez32559742018-05-02 10:47:01 -0700135 read_pipe, write_pipe = os.pipe()
Josh Gao92cd59f2018-08-21 14:25:05 -0700136
137 if sys.platform == "win32":
138 import msvcrt
139 write_handle = msvcrt.get_osfhandle(write_pipe)
140 os.set_handle_inheritable(write_handle, True)
141 reply_fd = str(write_handle)
142 else:
143 os.set_inheritable(write_pipe, True)
144 reply_fd = str(write_pipe)
145
Josh Gaob3610732018-08-08 13:08:08 -0700146 proc = subprocess.Popen(["adb", "-L", "tcp:localhost:{}".format(port),
147 "fork-server", "server",
Josh Gao92cd59f2018-08-21 14:25:05 -0700148 "--reply-fd", reply_fd], close_fds=False)
Luis Hector Chavez32559742018-05-02 10:47:01 -0700149 try:
150 os.close(write_pipe)
151 greeting = os.read(read_pipe, 1024)
Josh Gaob3610732018-08-08 13:08:08 -0700152 assert greeting == b"OK\n", repr(greeting)
Luis Hector Chavez32559742018-05-02 10:47:01 -0700153 yield port
154 finally:
155 proc.terminate()
156 proc.wait()
157
158
Luis Hector Chavezfbee0a92018-05-02 09:10:29 -0700159class CommandlineTest(unittest.TestCase):
160 """Tests for the ADB commandline."""
Dan Albert8e1fdd72015-07-24 17:08:33 -0700161
162 def test_help(self):
163 """Make sure we get _something_ out of help."""
164 out = subprocess.check_output(
Josh Gaob3610732018-08-08 13:08:08 -0700165 ["adb", "help"], stderr=subprocess.STDOUT)
Dan Albert8e1fdd72015-07-24 17:08:33 -0700166 self.assertGreater(len(out), 0)
167
168 def test_version(self):
169 """Get a version number out of the output of adb."""
Josh Gaob3610732018-08-08 13:08:08 -0700170 lines = subprocess.check_output(["adb", "version"]).splitlines()
Dan Albert8e1fdd72015-07-24 17:08:33 -0700171 version_line = lines[0]
Josh Gao9b6522b2018-08-07 14:31:17 -0700172 self.assertRegex(
Josh Gaob3610732018-08-08 13:08:08 -0700173 version_line, rb"^Android Debug Bridge version \d+\.\d+\.\d+$")
Dan Albert8e1fdd72015-07-24 17:08:33 -0700174 if len(lines) == 2:
175 # Newer versions of ADB have a second line of output for the
176 # version that includes a specific revision (git SHA).
177 revision_line = lines[1]
Josh Gao9b6522b2018-08-07 14:31:17 -0700178 self.assertRegex(
Josh Gaob3610732018-08-08 13:08:08 -0700179 revision_line, rb"^Revision [0-9a-f]{12}-android$")
Dan Albert8e1fdd72015-07-24 17:08:33 -0700180
181 def test_tcpip_error_messages(self):
Luis Hector Chavezfbee0a92018-05-02 09:10:29 -0700182 """Make sure 'adb tcpip' parsing is sane."""
Josh Gaob3610732018-08-08 13:08:08 -0700183 proc = subprocess.Popen(["adb", "tcpip"],
Josh Gao9b6522b2018-08-07 14:31:17 -0700184 stdout=subprocess.PIPE,
Luis Hector Chavezfbee0a92018-05-02 09:10:29 -0700185 stderr=subprocess.STDOUT)
186 out, _ = proc.communicate()
187 self.assertEqual(1, proc.returncode)
Josh Gaob3610732018-08-08 13:08:08 -0700188 self.assertIn(b"requires an argument", out)
Dan Albert8e1fdd72015-07-24 17:08:33 -0700189
Josh Gaob3610732018-08-08 13:08:08 -0700190 proc = subprocess.Popen(["adb", "tcpip", "foo"],
Josh Gao9b6522b2018-08-07 14:31:17 -0700191 stdout=subprocess.PIPE,
Luis Hector Chavezfbee0a92018-05-02 09:10:29 -0700192 stderr=subprocess.STDOUT)
193 out, _ = proc.communicate()
194 self.assertEqual(1, proc.returncode)
Josh Gaob3610732018-08-08 13:08:08 -0700195 self.assertIn(b"invalid port", out)
Dan Albert8e1fdd72015-07-24 17:08:33 -0700196
Luis Hector Chavezfbee0a92018-05-02 09:10:29 -0700197
198class ServerTest(unittest.TestCase):
199 """Tests for the ADB server."""
200
201 @staticmethod
202 def _read_pipe_and_set_event(pipe, event):
203 """Reads a pipe until it is closed, then sets the event."""
204 pipe.read()
Spencer Low1ce06082015-09-16 20:45:53 -0700205 event.set()
206
Spencer Low1ce06082015-09-16 20:45:53 -0700207 def test_handle_inheritance(self):
Luis Hector Chavezfbee0a92018-05-02 09:10:29 -0700208 """Test that launch_server() does not inherit handles.
209
210 launch_server() should not let the adb server inherit
211 stdin/stdout/stderr handles, which can cause callers of adb.exe to hang.
212 This test also runs fine on unix even though the impetus is an issue
213 unique to Windows.
214 """
Spencer Low1ce06082015-09-16 20:45:53 -0700215 # This test takes 5 seconds to run on Windows: if there is no adb server
216 # running on the the port used below, adb kill-server tries to make a
217 # TCP connection to a closed port and that takes 1 second on Windows;
218 # adb start-server does the same TCP connection which takes another
219 # second, and it waits 3 seconds after starting the server.
220
221 # Start adb client with redirected stdin/stdout/stderr to check if it
222 # passes those redirections to the adb server that it starts. To do
223 # this, run an instance of the adb server on a non-default port so we
224 # don't conflict with a pre-existing adb server that may already be
225 # setup with adb TCP/emulator connections. If there is a pre-existing
226 # adb server, this also tests whether multiple instances of the adb
227 # server conflict on adb.log.
228
Josh Gaoe8829c62020-02-27 14:29:38 -0800229 port = find_open_port()
Spencer Low1ce06082015-09-16 20:45:53 -0700230
231 try:
Josh Gao42c86722018-10-16 11:00:39 -0700232 # We get warnings for unclosed files for the subprocess's pipes,
233 # and it's somewhat cumbersome to close them, so just ignore this.
234 warnings.simplefilter("ignore", ResourceWarning)
235
Spencer Low1ce06082015-09-16 20:45:53 -0700236 # Run the adb client and have it start the adb server.
Josh Gaob3610732018-08-08 13:08:08 -0700237 proc = subprocess.Popen(["adb", "-P", str(port), "start-server"],
Luis Hector Chavezfbee0a92018-05-02 09:10:29 -0700238 stdin=subprocess.PIPE,
239 stdout=subprocess.PIPE,
240 stderr=subprocess.PIPE)
Spencer Low1ce06082015-09-16 20:45:53 -0700241
242 # Start threads that set events when stdout/stderr are closed.
243 stdout_event = threading.Event()
244 stdout_thread = threading.Thread(
Luis Hector Chavezfbee0a92018-05-02 09:10:29 -0700245 target=ServerTest._read_pipe_and_set_event,
246 args=(proc.stdout, stdout_event))
Spencer Low1ce06082015-09-16 20:45:53 -0700247 stdout_thread.start()
248
249 stderr_event = threading.Event()
250 stderr_thread = threading.Thread(
Luis Hector Chavezfbee0a92018-05-02 09:10:29 -0700251 target=ServerTest._read_pipe_and_set_event,
252 args=(proc.stderr, stderr_event))
Spencer Low1ce06082015-09-16 20:45:53 -0700253 stderr_thread.start()
254
255 # Wait for the adb client to finish. Once that has occurred, if
256 # stdin/stderr/stdout are still open, it must be open in the adb
257 # server.
Luis Hector Chavezfbee0a92018-05-02 09:10:29 -0700258 proc.wait()
Spencer Low1ce06082015-09-16 20:45:53 -0700259
260 # Try to write to stdin which we expect is closed. If it isn't
261 # closed, we should get an IOError. If we don't get an IOError,
262 # stdin must still be open in the adb server. The adb client is
263 # probably letting the adb server inherit stdin which would be
264 # wrong.
265 with self.assertRaises(IOError):
Josh Gaob3610732018-08-08 13:08:08 -0700266 proc.stdin.write(b"x")
Josh Gao9b6522b2018-08-07 14:31:17 -0700267 proc.stdin.flush()
Spencer Low1ce06082015-09-16 20:45:53 -0700268
269 # Wait a few seconds for stdout/stderr to be closed (in the success
270 # case, this won't wait at all). If there is a timeout, that means
271 # stdout/stderr were not closed and and they must be open in the adb
272 # server, suggesting that the adb client is letting the adb server
273 # inherit stdout/stderr which would be wrong.
274 self.assertTrue(stdout_event.wait(5), "adb stdout not closed")
275 self.assertTrue(stderr_event.wait(5), "adb stderr not closed")
Josh Gao9b6522b2018-08-07 14:31:17 -0700276 stdout_thread.join()
277 stderr_thread.join()
Spencer Low1ce06082015-09-16 20:45:53 -0700278 finally:
279 # If we started a server, kill it.
Josh Gaob3610732018-08-08 13:08:08 -0700280 subprocess.check_output(["adb", "-P", str(port), "kill-server"],
Spencer Low1ce06082015-09-16 20:45:53 -0700281 stderr=subprocess.STDOUT)
Dan Albert8e1fdd72015-07-24 17:08:33 -0700282
Callum Ryan8539cb32019-10-31 07:21:42 -0700283 @unittest.skipUnless(
284 os.name == "posix",
285 "adb doesn't yet support IPv6 on Windows",
286 )
287 def test_starts_on_ipv6_localhost(self):
288 """
289 Tests that the server can start up on ::1 and that it's accessible
290 """
Josh Gaoe8829c62020-02-27 14:29:38 -0800291
292 server_port = find_open_port()
Callum Ryan8539cb32019-10-31 07:21:42 -0700293 try:
294 subprocess.check_output(
295 ["adb", "-L", "tcp:[::1]:{}".format(server_port), "server"],
296 stderr=subprocess.STDOUT,
297 )
298 with fake_adbd() as (port, _):
299 with adb_connect(self, serial="localhost:{}".format(port)):
300 pass
301 finally:
302 # If we started a server, kill it.
303 subprocess.check_output(
304 ["adb", "-P", str(server_port), "kill-server"],
305 stderr=subprocess.STDOUT,
306 )
307
308
309
Luis Hector Chavezfbee0a92018-05-02 09:10:29 -0700310
311class EmulatorTest(unittest.TestCase):
312 """Tests for the emulator connection."""
313
Spencer Low351ecd12015-10-14 17:32:44 -0700314 def _reset_socket_on_close(self, sock):
Luis Hector Chavezfbee0a92018-05-02 09:10:29 -0700315 """Use SO_LINGER to cause TCP RST segment to be sent on socket close."""
Spencer Low351ecd12015-10-14 17:32:44 -0700316 # The linger structure is two shorts on Windows, but two ints on Unix.
Josh Gaob3610732018-08-08 13:08:08 -0700317 linger_format = "hh" if os.name == "nt" else "ii"
Spencer Low351ecd12015-10-14 17:32:44 -0700318 l_onoff = 1
319 l_linger = 0
320
321 sock.setsockopt(socket.SOL_SOCKET, socket.SO_LINGER,
322 struct.pack(linger_format, l_onoff, l_linger))
323 # Verify that we set the linger structure properly by retrieving it.
324 linger = sock.getsockopt(socket.SOL_SOCKET, socket.SO_LINGER, 16)
325 self.assertEqual((l_onoff, l_linger),
326 struct.unpack_from(linger_format, linger))
327
328 def test_emu_kill(self):
329 """Ensure that adb emu kill works.
330
331 Bug: https://code.google.com/p/android/issues/detail?id=21021
332 """
Spencer Low351ecd12015-10-14 17:32:44 -0700333 with contextlib.closing(
Luis Hector Chavezfbee0a92018-05-02 09:10:29 -0700334 socket.socket(socket.AF_INET, socket.SOCK_STREAM)) as listener:
Spencer Low351ecd12015-10-14 17:32:44 -0700335 # Use SO_REUSEADDR so subsequent runs of the test can grab the port
336 # even if it is in TIME_WAIT.
337 listener.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
Josh Gaob3610732018-08-08 13:08:08 -0700338 listener.bind(("127.0.0.1", 0))
Spencer Low351ecd12015-10-14 17:32:44 -0700339 listener.listen(4)
Josh Gaoc251ec52018-04-03 12:55:18 -0700340 port = listener.getsockname()[1]
Spencer Low351ecd12015-10-14 17:32:44 -0700341
342 # Now that listening has started, start adb emu kill, telling it to
343 # connect to our mock emulator.
Luis Hector Chavezfbee0a92018-05-02 09:10:29 -0700344 proc = subprocess.Popen(
Josh Gaob3610732018-08-08 13:08:08 -0700345 ["adb", "-s", "emulator-" + str(port), "emu", "kill"],
Spencer Low351ecd12015-10-14 17:32:44 -0700346 stderr=subprocess.STDOUT)
347
348 accepted_connection, addr = listener.accept()
349 with contextlib.closing(accepted_connection) as conn:
350 # If WSAECONNABORTED (10053) is raised by any socket calls,
351 # then adb probably isn't reading the data that we sent it.
Josh Gaob3610732018-08-08 13:08:08 -0700352 conn.sendall(("Android Console: type 'help' for a list "
353 "of commands\r\n").encode("utf8"))
354 conn.sendall(b"OK\r\n")
Spencer Low351ecd12015-10-14 17:32:44 -0700355
Luis Hector Chavezfbee0a92018-05-02 09:10:29 -0700356 with contextlib.closing(conn.makefile()) as connf:
357 line = connf.readline()
Josh Gaob3610732018-08-08 13:08:08 -0700358 if line.startswith("auth"):
Luis Hector Chavezfbee0a92018-05-02 09:10:29 -0700359 # Ignore the first auth line.
360 line = connf.readline()
Josh Gaob3610732018-08-08 13:08:08 -0700361 self.assertEqual("kill\n", line)
362 self.assertEqual("quit\n", connf.readline())
Spencer Low351ecd12015-10-14 17:32:44 -0700363
Josh Gaob3610732018-08-08 13:08:08 -0700364 conn.sendall(b"OK: killing emulator, bye bye\r\n")
Spencer Low351ecd12015-10-14 17:32:44 -0700365
366 # Use SO_LINGER to send TCP RST segment to test whether adb
367 # ignores WSAECONNRESET on Windows. This happens with the
368 # real emulator because it just calls exit() without closing
369 # the socket or calling shutdown(SD_SEND). At process
370 # termination, Windows sends a TCP RST segment for every
371 # open socket that shutdown(SD_SEND) wasn't used on.
372 self._reset_socket_on_close(conn)
373
374 # Wait for adb to finish, so we can check return code.
Luis Hector Chavezfbee0a92018-05-02 09:10:29 -0700375 proc.communicate()
Spencer Low351ecd12015-10-14 17:32:44 -0700376
377 # If this fails, adb probably isn't ignoring WSAECONNRESET when
378 # reading the response from the adb emu kill command (on Windows).
Luis Hector Chavezfbee0a92018-05-02 09:10:29 -0700379 self.assertEqual(0, proc.returncode)
380
Luis Hector Chavez32559742018-05-02 10:47:01 -0700381 def test_emulator_connect(self):
382 """Ensure that the emulator can connect.
383
384 Bug: http://b/78991667
385 """
386 with adb_server() as server_port:
Josh Gao902dace2018-08-10 14:44:54 -0700387 with fake_adbd() as (port, _):
Josh Gaob3610732018-08-08 13:08:08 -0700388 serial = "emulator-{}".format(port - 1)
Luis Hector Chavez32559742018-05-02 10:47:01 -0700389 # Ensure that the emulator is not there.
390 try:
Josh Gaob3610732018-08-08 13:08:08 -0700391 subprocess.check_output(["adb", "-P", str(server_port),
392 "-s", serial, "get-state"],
Luis Hector Chavez32559742018-05-02 10:47:01 -0700393 stderr=subprocess.STDOUT)
Josh Gaob3610732018-08-08 13:08:08 -0700394 self.fail("Device should not be available")
Luis Hector Chavez32559742018-05-02 10:47:01 -0700395 except subprocess.CalledProcessError as err:
396 self.assertEqual(
397 err.output.strip(),
Josh Gaob3610732018-08-08 13:08:08 -0700398 "error: device '{}' not found".format(serial).encode("utf8"))
Luis Hector Chavez32559742018-05-02 10:47:01 -0700399
400 # Let the ADB server know that the emulator has started.
401 with contextlib.closing(
Josh Gao9b6522b2018-08-07 14:31:17 -0700402 socket.socket(socket.AF_INET, socket.SOCK_STREAM)) as sock:
Josh Gaob3610732018-08-08 13:08:08 -0700403 sock.connect(("localhost", server_port))
404 command = "host:emulator:{}".format(port).encode("utf8")
405 sock.sendall(b"%04x%s" % (len(command), command))
Luis Hector Chavez32559742018-05-02 10:47:01 -0700406
407 # Ensure the emulator is there.
Josh Gaob3610732018-08-08 13:08:08 -0700408 subprocess.check_call(["adb", "-P", str(server_port),
409 "-s", serial, "wait-for-device"])
410 output = subprocess.check_output(["adb", "-P", str(server_port),
411 "-s", serial, "get-state"])
412 self.assertEqual(output.strip(), b"device")
Luis Hector Chavez32559742018-05-02 10:47:01 -0700413
Luis Hector Chavezfbee0a92018-05-02 09:10:29 -0700414
415class ConnectionTest(unittest.TestCase):
416 """Tests for adb connect."""
Spencer Low351ecd12015-10-14 17:32:44 -0700417
Josh Gao78cc20f2016-09-01 14:54:18 -0700418 def test_connect_ipv4_ipv6(self):
419 """Ensure that `adb connect localhost:1234` will try both IPv4 and IPv6.
420
421 Bug: http://b/30313466
422 """
Luis Hector Chavez8b67c522018-04-17 19:25:33 -0700423 for protocol in (socket.AF_INET, socket.AF_INET6):
424 try:
Josh Gao902dace2018-08-10 14:44:54 -0700425 with fake_adbd(protocol=protocol) as (port, _):
Josh Gaob3610732018-08-08 13:08:08 -0700426 serial = "localhost:{}".format(port)
Luis Hector Chavez454bc7c2018-04-20 10:31:29 -0700427 with adb_connect(self, serial):
428 pass
Luis Hector Chavez8b67c522018-04-17 19:25:33 -0700429 except socket.error:
430 print("IPv6 not available, skipping")
431 continue
Josh Gao78cc20f2016-09-01 14:54:18 -0700432
Luis Hector Chavez8b67c522018-04-17 19:25:33 -0700433 def test_already_connected(self):
Luis Hector Chavez454bc7c2018-04-20 10:31:29 -0700434 """Ensure that an already-connected device stays connected."""
435
Josh Gao902dace2018-08-10 14:44:54 -0700436 with fake_adbd() as (port, _):
Josh Gaob3610732018-08-08 13:08:08 -0700437 serial = "localhost:{}".format(port)
Luis Hector Chavez454bc7c2018-04-20 10:31:29 -0700438 with adb_connect(self, serial):
439 # b/31250450: this always returns 0 but probably shouldn't.
Josh Gaob3610732018-08-08 13:08:08 -0700440 output = subprocess.check_output(["adb", "connect", serial])
Luis Hector Chavez454bc7c2018-04-20 10:31:29 -0700441 self.assertEqual(
Josh Gao9b6522b2018-08-07 14:31:17 -0700442 output.strip(),
Josh Gaob3610732018-08-08 13:08:08 -0700443 "already connected to {}".format(serial).encode("utf8"))
Josh Gao78cc20f2016-09-01 14:54:18 -0700444
Julien Desprezfb4c1352019-02-20 09:42:49 -0800445 @unittest.skip("Currently failing b/123247844")
Luis Hector Chavez454bc7c2018-04-20 10:31:29 -0700446 def test_reconnect(self):
447 """Ensure that a disconnected device reconnects."""
Josh Gao78cc20f2016-09-01 14:54:18 -0700448
Josh Gao902dace2018-08-10 14:44:54 -0700449 with fake_adbd() as (port, _):
Josh Gaob3610732018-08-08 13:08:08 -0700450 serial = "localhost:{}".format(port)
Luis Hector Chavez454bc7c2018-04-20 10:31:29 -0700451 with adb_connect(self, serial):
Josh Gaoaa95aa02019-02-07 17:53:29 -0800452 # Wait a bit to give adb some time to connect.
453 time.sleep(0.25)
454
Josh Gaob3610732018-08-08 13:08:08 -0700455 output = subprocess.check_output(["adb", "-s", serial,
456 "get-state"])
457 self.assertEqual(output.strip(), b"device")
Josh Gaoc251ec52018-04-03 12:55:18 -0700458
Luis Hector Chavez454bc7c2018-04-20 10:31:29 -0700459 # This will fail.
Josh Gaob3610732018-08-08 13:08:08 -0700460 proc = subprocess.Popen(["adb", "-s", serial, "shell", "true"],
Luis Hector Chavezfbee0a92018-05-02 09:10:29 -0700461 stdout=subprocess.PIPE,
462 stderr=subprocess.STDOUT)
463 output, _ = proc.communicate()
Josh Gaob3610732018-08-08 13:08:08 -0700464 self.assertEqual(output.strip(), b"error: closed")
Luis Hector Chavez454bc7c2018-04-20 10:31:29 -0700465
Josh Gaob3610732018-08-08 13:08:08 -0700466 subprocess.check_call(["adb", "-s", serial, "wait-for-device"])
Luis Hector Chavez454bc7c2018-04-20 10:31:29 -0700467
Josh Gaob3610732018-08-08 13:08:08 -0700468 output = subprocess.check_output(["adb", "-s", serial,
469 "get-state"])
470 self.assertEqual(output.strip(), b"device")
Luis Hector Chavez454bc7c2018-04-20 10:31:29 -0700471
472 # Once we explicitly kick a device, it won't attempt to
473 # reconnect.
Josh Gaob3610732018-08-08 13:08:08 -0700474 output = subprocess.check_output(["adb", "disconnect", serial])
Luis Hector Chavez454bc7c2018-04-20 10:31:29 -0700475 self.assertEqual(
Josh Gao9b6522b2018-08-07 14:31:17 -0700476 output.strip(),
Josh Gaob3610732018-08-08 13:08:08 -0700477 "disconnected {}".format(serial).encode("utf8"))
Luis Hector Chavez454bc7c2018-04-20 10:31:29 -0700478 try:
Josh Gaob3610732018-08-08 13:08:08 -0700479 subprocess.check_output(["adb", "-s", serial, "get-state"],
Luis Hector Chavez454bc7c2018-04-20 10:31:29 -0700480 stderr=subprocess.STDOUT)
Josh Gaob3610732018-08-08 13:08:08 -0700481 self.fail("Device should not be available")
Luis Hector Chavezfbee0a92018-05-02 09:10:29 -0700482 except subprocess.CalledProcessError as err:
Luis Hector Chavez454bc7c2018-04-20 10:31:29 -0700483 self.assertEqual(
Luis Hector Chavezfbee0a92018-05-02 09:10:29 -0700484 err.output.strip(),
Josh Gaob3610732018-08-08 13:08:08 -0700485 "error: device '{}' not found".format(serial).encode("utf8"))
Spencer Low351ecd12015-10-14 17:32:44 -0700486
Luis Hector Chavezfbee0a92018-05-02 09:10:29 -0700487
Josh Gao902dace2018-08-10 14:44:54 -0700488class DisconnectionTest(unittest.TestCase):
489 """Tests for adb disconnect."""
490
491 def test_disconnect(self):
492 """Ensure that `adb disconnect` takes effect immediately."""
493
494 def _devices(port):
495 output = subprocess.check_output(["adb", "-P", str(port), "devices"])
496 return [x.split("\t") for x in output.decode("utf8").strip().splitlines()[1:]]
497
498 with adb_server() as server_port:
499 with fake_adbd() as (port, sock):
500 device_name = "localhost:{}".format(port)
501 output = subprocess.check_output(["adb", "-P", str(server_port),
502 "connect", device_name])
503 self.assertEqual(output.strip(),
504 "connected to {}".format(device_name).encode("utf8"))
505
506
507 self.assertEqual(_devices(server_port), [[device_name, "device"]])
508
509 # Send a deliberately malformed packet to make the device go offline.
510 packet = struct.pack("IIIIII", 0, 0, 0, 0, 0, 0)
511 sock.sendall(packet)
512
513 # Wait a bit.
514 time.sleep(0.1)
515
516 self.assertEqual(_devices(server_port), [[device_name, "offline"]])
517
518 # Disconnect the device.
519 output = subprocess.check_output(["adb", "-P", str(server_port),
520 "disconnect", device_name])
521
522 # Wait a bit.
523 time.sleep(0.1)
524
525 self.assertEqual(_devices(server_port), [])
526
527
Spencer Low8f6bdc92018-08-31 19:49:46 -0700528@unittest.skipUnless(sys.platform == "win32", "requires Windows")
529class PowerTest(unittest.TestCase):
530 def test_resume_usb_kick(self):
531 """Resuming from sleep/hibernate should kick USB devices."""
532 try:
533 usb_serial = subprocess.check_output(["adb", "-d", "get-serialno"]).strip()
534 except subprocess.CalledProcessError:
535 # If there are multiple USB devices, we don't have a way to check whether the selected
536 # device is USB.
537 raise unittest.SkipTest('requires single USB device')
538
539 try:
540 serial = subprocess.check_output(["adb", "get-serialno"]).strip()
541 except subprocess.CalledProcessError:
542 # Did you forget to select a device with $ANDROID_SERIAL?
543 raise unittest.SkipTest('requires $ANDROID_SERIAL set to a USB device')
544
545 # Test only works with USB devices because adb _power_notification_thread does not kick
546 # non-USB devices on resume event.
547 if serial != usb_serial:
548 raise unittest.SkipTest('requires USB device')
549
550 # Run an adb shell command in the background that takes a while to complete.
551 proc = subprocess.Popen(['adb', 'shell', 'sleep', '5'])
552
553 # Wait for startup of adb server's _power_notification_thread.
554 time.sleep(0.1)
555
556 # Simulate resuming from sleep/hibernation by sending Windows message.
557 import ctypes
558 from ctypes import wintypes
559 HWND_BROADCAST = 0xffff
560 WM_POWERBROADCAST = 0x218
561 PBT_APMRESUMEAUTOMATIC = 0x12
562
563 PostMessageW = ctypes.windll.user32.PostMessageW
564 PostMessageW.restype = wintypes.BOOL
565 PostMessageW.argtypes = (wintypes.HWND, wintypes.UINT, wintypes.WPARAM, wintypes.LPARAM)
566 result = PostMessageW(HWND_BROADCAST, WM_POWERBROADCAST, PBT_APMRESUMEAUTOMATIC, 0)
567 if not result:
568 raise ctypes.WinError()
569
570 # Wait for connection to adb shell to be broken by _power_notification_thread detecting the
571 # Windows message.
572 start = time.time()
573 proc.wait()
574 end = time.time()
575
576 # If the power event was detected, the adb shell command should be broken very quickly.
577 self.assertLess(end - start, 2)
578
Joshua Duong504d3932020-03-31 10:58:50 -0700579"""Use 'adb mdns check' to see if mdns discovery is available."""
580def is_adb_mdns_available():
581 with adb_server() as server_port:
582 output = subprocess.check_output(["adb", "-P", str(server_port),
583 "mdns", "check"]).strip()
584 return output.startswith(b"mdns daemon version")
585
586@unittest.skipIf(not is_adb_mdns_available(), "mdns feature not available")
587class MdnsTest(unittest.TestCase):
588 """Tests for adb mdns."""
589 pass
Spencer Low8f6bdc92018-08-31 19:49:46 -0700590
Dan Albert8e1fdd72015-07-24 17:08:33 -0700591def main():
Luis Hector Chavezfbee0a92018-05-02 09:10:29 -0700592 """Main entrypoint."""
Dan Albert8e1fdd72015-07-24 17:08:33 -0700593 random.seed(0)
Luis Hector Chavezfbee0a92018-05-02 09:10:29 -0700594 unittest.main(verbosity=3)
Dan Albert8e1fdd72015-07-24 17:08:33 -0700595
596
Josh Gaob3610732018-08-08 13:08:08 -0700597if __name__ == "__main__":
Dan Albert8e1fdd72015-07-24 17:08:33 -0700598 main()