blob: 7e73818df7c33db48f23c48910cf49828315e036 [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
34
Dan Albert8e1fdd72015-07-24 17:08:33 -070035
Luis Hector Chavez8b67c522018-04-17 19:25:33 -070036@contextlib.contextmanager
Luis Hector Chavezfbee0a92018-05-02 09:10:29 -070037def fake_adbd(protocol=socket.AF_INET, port=0):
38 """Creates a fake ADB daemon that just replies with a CNXN packet."""
Luis Hector Chavez8b67c522018-04-17 19:25:33 -070039
40 serversock = socket.socket(protocol, socket.SOCK_STREAM)
Luis Hector Chavezfbee0a92018-05-02 09:10:29 -070041 serversock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
Luis Hector Chavez8b67c522018-04-17 19:25:33 -070042 if protocol == socket.AF_INET:
Josh Gaob3610732018-08-08 13:08:08 -070043 serversock.bind(("127.0.0.1", port))
Luis Hector Chavez8b67c522018-04-17 19:25:33 -070044 else:
Josh Gaob3610732018-08-08 13:08:08 -070045 serversock.bind(("::1", port))
Luis Hector Chavez8b67c522018-04-17 19:25:33 -070046 serversock.listen(1)
47
48 # A pipe that is used to signal the thread that it should terminate.
Josh Gao676f375d2018-08-07 16:07:25 -070049 readsock, writesock = socket.socketpair()
Luis Hector Chavez8b67c522018-04-17 19:25:33 -070050
Josh Gao9b6522b2018-08-07 14:31:17 -070051 def _adb_packet(command: bytes, arg0: int, arg1: int, data: bytes) -> bytes:
Josh Gaob3610732018-08-08 13:08:08 -070052 bin_command = struct.unpack("I", command)[0]
53 buf = struct.pack("IIIIII", bin_command, arg0, arg1, len(data), 0,
Luis Hector Chavez56fe7532018-04-17 14:25:04 -070054 bin_command ^ 0xffffffff)
55 buf += data
56 return buf
57
Josh Gao9b6522b2018-08-07 14:31:17 -070058 def _handle(sock):
59 with contextlib.closing(sock) as serversock:
Josh Gao676f375d2018-08-07 16:07:25 -070060 rlist = [readsock, serversock]
Josh Gao9b6522b2018-08-07 14:31:17 -070061 cnxn_sent = {}
62 while True:
63 read_ready, _, _ = select.select(rlist, [], [])
64 for ready in read_ready:
Josh Gao676f375d2018-08-07 16:07:25 -070065 if ready == readsock:
Josh Gao9b6522b2018-08-07 14:31:17 -070066 # Closure pipe
Josh Gao9b6522b2018-08-07 14:31:17 -070067 for f in rlist:
Josh Gao676f375d2018-08-07 16:07:25 -070068 f.close()
Josh Gao9b6522b2018-08-07 14:31:17 -070069 return
70 elif ready == serversock:
71 # Server socket
72 conn, _ = ready.accept()
73 rlist.append(conn)
74 else:
75 # Client socket
76 data = ready.recv(1024)
Josh Gaob3610732018-08-08 13:08:08 -070077 if not data or data.startswith(b"OPEN"):
Josh Gao9b6522b2018-08-07 14:31:17 -070078 if ready in cnxn_sent:
79 del cnxn_sent[ready]
80 ready.shutdown(socket.SHUT_RDWR)
81 ready.close()
82 rlist.remove(ready)
83 continue
Luis Hector Chavezfbee0a92018-05-02 09:10:29 -070084 if ready in cnxn_sent:
Josh Gao9b6522b2018-08-07 14:31:17 -070085 continue
86 cnxn_sent[ready] = True
Josh Gaob3610732018-08-08 13:08:08 -070087 ready.sendall(_adb_packet(b"CNXN", 0x01000001, 1024 * 1024,
88 b"device::ro.product.name=fakeadb"))
Luis Hector Chavez8b67c522018-04-17 19:25:33 -070089
90 port = serversock.getsockname()[1]
Josh Gao9b6522b2018-08-07 14:31:17 -070091 server_thread = threading.Thread(target=_handle, args=(serversock,))
Luis Hector Chavez8b67c522018-04-17 19:25:33 -070092 server_thread.start()
93
94 try:
Josh Gao902dace2018-08-10 14:44:54 -070095 yield port, writesock
Luis Hector Chavez8b67c522018-04-17 19:25:33 -070096 finally:
Josh Gao676f375d2018-08-07 16:07:25 -070097 writesock.close()
Luis Hector Chavez8b67c522018-04-17 19:25:33 -070098 server_thread.join()
99
100
Luis Hector Chavez454bc7c2018-04-20 10:31:29 -0700101@contextlib.contextmanager
102def adb_connect(unittest, serial):
103 """Context manager for an ADB connection.
104
105 This automatically disconnects when done with the connection.
106 """
107
Josh Gaob3610732018-08-08 13:08:08 -0700108 output = subprocess.check_output(["adb", "connect", serial])
Josh Gao9b6522b2018-08-07 14:31:17 -0700109 unittest.assertEqual(output.strip(),
Josh Gaob3610732018-08-08 13:08:08 -0700110 "connected to {}".format(serial).encode("utf8"))
Luis Hector Chavez454bc7c2018-04-20 10:31:29 -0700111
112 try:
113 yield
114 finally:
115 # Perform best-effort disconnection. Discard the output.
Josh Gaob3610732018-08-08 13:08:08 -0700116 subprocess.Popen(["adb", "disconnect", serial],
Luis Hector Chavezfbee0a92018-05-02 09:10:29 -0700117 stdout=subprocess.PIPE,
118 stderr=subprocess.PIPE).communicate()
Luis Hector Chavez454bc7c2018-04-20 10:31:29 -0700119
120
Luis Hector Chavez32559742018-05-02 10:47:01 -0700121@contextlib.contextmanager
122def adb_server():
123 """Context manager for an ADB server.
124
Josh Gao902dace2018-08-10 14:44:54 -0700125 This creates an ADB server and returns the port it's listening on.
Luis Hector Chavez32559742018-05-02 10:47:01 -0700126 """
127
128 port = 5038
129 # Kill any existing server on this non-default port.
Josh Gaob3610732018-08-08 13:08:08 -0700130 subprocess.check_output(["adb", "-P", str(port), "kill-server"],
Luis Hector Chavez32559742018-05-02 10:47:01 -0700131 stderr=subprocess.STDOUT)
132 read_pipe, write_pipe = os.pipe()
Josh Gao92cd59f2018-08-21 14:25:05 -0700133
134 if sys.platform == "win32":
135 import msvcrt
136 write_handle = msvcrt.get_osfhandle(write_pipe)
137 os.set_handle_inheritable(write_handle, True)
138 reply_fd = str(write_handle)
139 else:
140 os.set_inheritable(write_pipe, True)
141 reply_fd = str(write_pipe)
142
Josh Gaob3610732018-08-08 13:08:08 -0700143 proc = subprocess.Popen(["adb", "-L", "tcp:localhost:{}".format(port),
144 "fork-server", "server",
Josh Gao92cd59f2018-08-21 14:25:05 -0700145 "--reply-fd", reply_fd], close_fds=False)
Luis Hector Chavez32559742018-05-02 10:47:01 -0700146 try:
147 os.close(write_pipe)
148 greeting = os.read(read_pipe, 1024)
Josh Gaob3610732018-08-08 13:08:08 -0700149 assert greeting == b"OK\n", repr(greeting)
Luis Hector Chavez32559742018-05-02 10:47:01 -0700150 yield port
151 finally:
152 proc.terminate()
153 proc.wait()
154
155
Luis Hector Chavezfbee0a92018-05-02 09:10:29 -0700156class CommandlineTest(unittest.TestCase):
157 """Tests for the ADB commandline."""
Dan Albert8e1fdd72015-07-24 17:08:33 -0700158
159 def test_help(self):
160 """Make sure we get _something_ out of help."""
161 out = subprocess.check_output(
Josh Gaob3610732018-08-08 13:08:08 -0700162 ["adb", "help"], stderr=subprocess.STDOUT)
Dan Albert8e1fdd72015-07-24 17:08:33 -0700163 self.assertGreater(len(out), 0)
164
165 def test_version(self):
166 """Get a version number out of the output of adb."""
Josh Gaob3610732018-08-08 13:08:08 -0700167 lines = subprocess.check_output(["adb", "version"]).splitlines()
Dan Albert8e1fdd72015-07-24 17:08:33 -0700168 version_line = lines[0]
Josh Gao9b6522b2018-08-07 14:31:17 -0700169 self.assertRegex(
Josh Gaob3610732018-08-08 13:08:08 -0700170 version_line, rb"^Android Debug Bridge version \d+\.\d+\.\d+$")
Dan Albert8e1fdd72015-07-24 17:08:33 -0700171 if len(lines) == 2:
172 # Newer versions of ADB have a second line of output for the
173 # version that includes a specific revision (git SHA).
174 revision_line = lines[1]
Josh Gao9b6522b2018-08-07 14:31:17 -0700175 self.assertRegex(
Josh Gaob3610732018-08-08 13:08:08 -0700176 revision_line, rb"^Revision [0-9a-f]{12}-android$")
Dan Albert8e1fdd72015-07-24 17:08:33 -0700177
178 def test_tcpip_error_messages(self):
Luis Hector Chavezfbee0a92018-05-02 09:10:29 -0700179 """Make sure 'adb tcpip' parsing is sane."""
Josh Gaob3610732018-08-08 13:08:08 -0700180 proc = subprocess.Popen(["adb", "tcpip"],
Josh Gao9b6522b2018-08-07 14:31:17 -0700181 stdout=subprocess.PIPE,
Luis Hector Chavezfbee0a92018-05-02 09:10:29 -0700182 stderr=subprocess.STDOUT)
183 out, _ = proc.communicate()
184 self.assertEqual(1, proc.returncode)
Josh Gaob3610732018-08-08 13:08:08 -0700185 self.assertIn(b"requires an argument", out)
Dan Albert8e1fdd72015-07-24 17:08:33 -0700186
Josh Gaob3610732018-08-08 13:08:08 -0700187 proc = subprocess.Popen(["adb", "tcpip", "foo"],
Josh Gao9b6522b2018-08-07 14:31:17 -0700188 stdout=subprocess.PIPE,
Luis Hector Chavezfbee0a92018-05-02 09:10:29 -0700189 stderr=subprocess.STDOUT)
190 out, _ = proc.communicate()
191 self.assertEqual(1, proc.returncode)
Josh Gaob3610732018-08-08 13:08:08 -0700192 self.assertIn(b"invalid port", out)
Dan Albert8e1fdd72015-07-24 17:08:33 -0700193
Luis Hector Chavezfbee0a92018-05-02 09:10:29 -0700194
195class ServerTest(unittest.TestCase):
196 """Tests for the ADB server."""
197
198 @staticmethod
199 def _read_pipe_and_set_event(pipe, event):
200 """Reads a pipe until it is closed, then sets the event."""
201 pipe.read()
Spencer Low1ce06082015-09-16 20:45:53 -0700202 event.set()
203
Spencer Low1ce06082015-09-16 20:45:53 -0700204 def test_handle_inheritance(self):
Luis Hector Chavezfbee0a92018-05-02 09:10:29 -0700205 """Test that launch_server() does not inherit handles.
206
207 launch_server() should not let the adb server inherit
208 stdin/stdout/stderr handles, which can cause callers of adb.exe to hang.
209 This test also runs fine on unix even though the impetus is an issue
210 unique to Windows.
211 """
Spencer Low1ce06082015-09-16 20:45:53 -0700212 # This test takes 5 seconds to run on Windows: if there is no adb server
213 # running on the the port used below, adb kill-server tries to make a
214 # TCP connection to a closed port and that takes 1 second on Windows;
215 # adb start-server does the same TCP connection which takes another
216 # second, and it waits 3 seconds after starting the server.
217
218 # Start adb client with redirected stdin/stdout/stderr to check if it
219 # passes those redirections to the adb server that it starts. To do
220 # this, run an instance of the adb server on a non-default port so we
221 # don't conflict with a pre-existing adb server that may already be
222 # setup with adb TCP/emulator connections. If there is a pre-existing
223 # adb server, this also tests whether multiple instances of the adb
224 # server conflict on adb.log.
225
226 port = 5038
227 # Kill any existing server on this non-default port.
Josh Gaob3610732018-08-08 13:08:08 -0700228 subprocess.check_output(["adb", "-P", str(port), "kill-server"],
Spencer Low1ce06082015-09-16 20:45:53 -0700229 stderr=subprocess.STDOUT)
230
231 try:
232 # Run the adb client and have it start the adb server.
Josh Gaob3610732018-08-08 13:08:08 -0700233 proc = subprocess.Popen(["adb", "-P", str(port), "start-server"],
Luis Hector Chavezfbee0a92018-05-02 09:10:29 -0700234 stdin=subprocess.PIPE,
235 stdout=subprocess.PIPE,
236 stderr=subprocess.PIPE)
Spencer Low1ce06082015-09-16 20:45:53 -0700237
238 # Start threads that set events when stdout/stderr are closed.
239 stdout_event = threading.Event()
240 stdout_thread = threading.Thread(
Luis Hector Chavezfbee0a92018-05-02 09:10:29 -0700241 target=ServerTest._read_pipe_and_set_event,
242 args=(proc.stdout, stdout_event))
Spencer Low1ce06082015-09-16 20:45:53 -0700243 stdout_thread.start()
244
245 stderr_event = threading.Event()
246 stderr_thread = threading.Thread(
Luis Hector Chavezfbee0a92018-05-02 09:10:29 -0700247 target=ServerTest._read_pipe_and_set_event,
248 args=(proc.stderr, stderr_event))
Spencer Low1ce06082015-09-16 20:45:53 -0700249 stderr_thread.start()
250
251 # Wait for the adb client to finish. Once that has occurred, if
252 # stdin/stderr/stdout are still open, it must be open in the adb
253 # server.
Luis Hector Chavezfbee0a92018-05-02 09:10:29 -0700254 proc.wait()
Spencer Low1ce06082015-09-16 20:45:53 -0700255
256 # Try to write to stdin which we expect is closed. If it isn't
257 # closed, we should get an IOError. If we don't get an IOError,
258 # stdin must still be open in the adb server. The adb client is
259 # probably letting the adb server inherit stdin which would be
260 # wrong.
261 with self.assertRaises(IOError):
Josh Gaob3610732018-08-08 13:08:08 -0700262 proc.stdin.write(b"x")
Josh Gao9b6522b2018-08-07 14:31:17 -0700263 proc.stdin.flush()
Spencer Low1ce06082015-09-16 20:45:53 -0700264
265 # Wait a few seconds for stdout/stderr to be closed (in the success
266 # case, this won't wait at all). If there is a timeout, that means
267 # stdout/stderr were not closed and and they must be open in the adb
268 # server, suggesting that the adb client is letting the adb server
269 # inherit stdout/stderr which would be wrong.
270 self.assertTrue(stdout_event.wait(5), "adb stdout not closed")
271 self.assertTrue(stderr_event.wait(5), "adb stderr not closed")
Josh Gao9b6522b2018-08-07 14:31:17 -0700272 stdout_thread.join()
273 stderr_thread.join()
Spencer Low1ce06082015-09-16 20:45:53 -0700274 finally:
275 # If we started a server, kill it.
Josh Gaob3610732018-08-08 13:08:08 -0700276 subprocess.check_output(["adb", "-P", str(port), "kill-server"],
Spencer Low1ce06082015-09-16 20:45:53 -0700277 stderr=subprocess.STDOUT)
Dan Albert8e1fdd72015-07-24 17:08:33 -0700278
Luis Hector Chavezfbee0a92018-05-02 09:10:29 -0700279
280class EmulatorTest(unittest.TestCase):
281 """Tests for the emulator connection."""
282
Spencer Low351ecd12015-10-14 17:32:44 -0700283 def _reset_socket_on_close(self, sock):
Luis Hector Chavezfbee0a92018-05-02 09:10:29 -0700284 """Use SO_LINGER to cause TCP RST segment to be sent on socket close."""
Spencer Low351ecd12015-10-14 17:32:44 -0700285 # The linger structure is two shorts on Windows, but two ints on Unix.
Josh Gaob3610732018-08-08 13:08:08 -0700286 linger_format = "hh" if os.name == "nt" else "ii"
Spencer Low351ecd12015-10-14 17:32:44 -0700287 l_onoff = 1
288 l_linger = 0
289
290 sock.setsockopt(socket.SOL_SOCKET, socket.SO_LINGER,
291 struct.pack(linger_format, l_onoff, l_linger))
292 # Verify that we set the linger structure properly by retrieving it.
293 linger = sock.getsockopt(socket.SOL_SOCKET, socket.SO_LINGER, 16)
294 self.assertEqual((l_onoff, l_linger),
295 struct.unpack_from(linger_format, linger))
296
297 def test_emu_kill(self):
298 """Ensure that adb emu kill works.
299
300 Bug: https://code.google.com/p/android/issues/detail?id=21021
301 """
Spencer Low351ecd12015-10-14 17:32:44 -0700302 with contextlib.closing(
Luis Hector Chavezfbee0a92018-05-02 09:10:29 -0700303 socket.socket(socket.AF_INET, socket.SOCK_STREAM)) as listener:
Spencer Low351ecd12015-10-14 17:32:44 -0700304 # Use SO_REUSEADDR so subsequent runs of the test can grab the port
305 # even if it is in TIME_WAIT.
306 listener.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
Josh Gaob3610732018-08-08 13:08:08 -0700307 listener.bind(("127.0.0.1", 0))
Spencer Low351ecd12015-10-14 17:32:44 -0700308 listener.listen(4)
Josh Gaoc251ec52018-04-03 12:55:18 -0700309 port = listener.getsockname()[1]
Spencer Low351ecd12015-10-14 17:32:44 -0700310
311 # Now that listening has started, start adb emu kill, telling it to
312 # connect to our mock emulator.
Luis Hector Chavezfbee0a92018-05-02 09:10:29 -0700313 proc = subprocess.Popen(
Josh Gaob3610732018-08-08 13:08:08 -0700314 ["adb", "-s", "emulator-" + str(port), "emu", "kill"],
Spencer Low351ecd12015-10-14 17:32:44 -0700315 stderr=subprocess.STDOUT)
316
317 accepted_connection, addr = listener.accept()
318 with contextlib.closing(accepted_connection) as conn:
319 # If WSAECONNABORTED (10053) is raised by any socket calls,
320 # then adb probably isn't reading the data that we sent it.
Josh Gaob3610732018-08-08 13:08:08 -0700321 conn.sendall(("Android Console: type 'help' for a list "
322 "of commands\r\n").encode("utf8"))
323 conn.sendall(b"OK\r\n")
Spencer Low351ecd12015-10-14 17:32:44 -0700324
Luis Hector Chavezfbee0a92018-05-02 09:10:29 -0700325 with contextlib.closing(conn.makefile()) as connf:
326 line = connf.readline()
Josh Gaob3610732018-08-08 13:08:08 -0700327 if line.startswith("auth"):
Luis Hector Chavezfbee0a92018-05-02 09:10:29 -0700328 # Ignore the first auth line.
329 line = connf.readline()
Josh Gaob3610732018-08-08 13:08:08 -0700330 self.assertEqual("kill\n", line)
331 self.assertEqual("quit\n", connf.readline())
Spencer Low351ecd12015-10-14 17:32:44 -0700332
Josh Gaob3610732018-08-08 13:08:08 -0700333 conn.sendall(b"OK: killing emulator, bye bye\r\n")
Spencer Low351ecd12015-10-14 17:32:44 -0700334
335 # Use SO_LINGER to send TCP RST segment to test whether adb
336 # ignores WSAECONNRESET on Windows. This happens with the
337 # real emulator because it just calls exit() without closing
338 # the socket or calling shutdown(SD_SEND). At process
339 # termination, Windows sends a TCP RST segment for every
340 # open socket that shutdown(SD_SEND) wasn't used on.
341 self._reset_socket_on_close(conn)
342
343 # Wait for adb to finish, so we can check return code.
Luis Hector Chavezfbee0a92018-05-02 09:10:29 -0700344 proc.communicate()
Spencer Low351ecd12015-10-14 17:32:44 -0700345
346 # If this fails, adb probably isn't ignoring WSAECONNRESET when
347 # reading the response from the adb emu kill command (on Windows).
Luis Hector Chavezfbee0a92018-05-02 09:10:29 -0700348 self.assertEqual(0, proc.returncode)
349
Luis Hector Chavez32559742018-05-02 10:47:01 -0700350 def test_emulator_connect(self):
351 """Ensure that the emulator can connect.
352
353 Bug: http://b/78991667
354 """
355 with adb_server() as server_port:
Josh Gao902dace2018-08-10 14:44:54 -0700356 with fake_adbd() as (port, _):
Josh Gaob3610732018-08-08 13:08:08 -0700357 serial = "emulator-{}".format(port - 1)
Luis Hector Chavez32559742018-05-02 10:47:01 -0700358 # Ensure that the emulator is not there.
359 try:
Josh Gaob3610732018-08-08 13:08:08 -0700360 subprocess.check_output(["adb", "-P", str(server_port),
361 "-s", serial, "get-state"],
Luis Hector Chavez32559742018-05-02 10:47:01 -0700362 stderr=subprocess.STDOUT)
Josh Gaob3610732018-08-08 13:08:08 -0700363 self.fail("Device should not be available")
Luis Hector Chavez32559742018-05-02 10:47:01 -0700364 except subprocess.CalledProcessError as err:
365 self.assertEqual(
366 err.output.strip(),
Josh Gaob3610732018-08-08 13:08:08 -0700367 "error: device '{}' not found".format(serial).encode("utf8"))
Luis Hector Chavez32559742018-05-02 10:47:01 -0700368
369 # Let the ADB server know that the emulator has started.
370 with contextlib.closing(
Josh Gao9b6522b2018-08-07 14:31:17 -0700371 socket.socket(socket.AF_INET, socket.SOCK_STREAM)) as sock:
Josh Gaob3610732018-08-08 13:08:08 -0700372 sock.connect(("localhost", server_port))
373 command = "host:emulator:{}".format(port).encode("utf8")
374 sock.sendall(b"%04x%s" % (len(command), command))
Luis Hector Chavez32559742018-05-02 10:47:01 -0700375
376 # Ensure the emulator is there.
Josh Gaob3610732018-08-08 13:08:08 -0700377 subprocess.check_call(["adb", "-P", str(server_port),
378 "-s", serial, "wait-for-device"])
379 output = subprocess.check_output(["adb", "-P", str(server_port),
380 "-s", serial, "get-state"])
381 self.assertEqual(output.strip(), b"device")
Luis Hector Chavez32559742018-05-02 10:47:01 -0700382
Luis Hector Chavezfbee0a92018-05-02 09:10:29 -0700383
384class ConnectionTest(unittest.TestCase):
385 """Tests for adb connect."""
Spencer Low351ecd12015-10-14 17:32:44 -0700386
Josh Gao78cc20f2016-09-01 14:54:18 -0700387 def test_connect_ipv4_ipv6(self):
388 """Ensure that `adb connect localhost:1234` will try both IPv4 and IPv6.
389
390 Bug: http://b/30313466
391 """
Luis Hector Chavez8b67c522018-04-17 19:25:33 -0700392 for protocol in (socket.AF_INET, socket.AF_INET6):
393 try:
Josh Gao902dace2018-08-10 14:44:54 -0700394 with fake_adbd(protocol=protocol) as (port, _):
Josh Gaob3610732018-08-08 13:08:08 -0700395 serial = "localhost:{}".format(port)
Luis Hector Chavez454bc7c2018-04-20 10:31:29 -0700396 with adb_connect(self, serial):
397 pass
Luis Hector Chavez8b67c522018-04-17 19:25:33 -0700398 except socket.error:
399 print("IPv6 not available, skipping")
400 continue
Josh Gao78cc20f2016-09-01 14:54:18 -0700401
Luis Hector Chavez8b67c522018-04-17 19:25:33 -0700402 def test_already_connected(self):
Luis Hector Chavez454bc7c2018-04-20 10:31:29 -0700403 """Ensure that an already-connected device stays connected."""
404
Josh Gao902dace2018-08-10 14:44:54 -0700405 with fake_adbd() as (port, _):
Josh Gaob3610732018-08-08 13:08:08 -0700406 serial = "localhost:{}".format(port)
Luis Hector Chavez454bc7c2018-04-20 10:31:29 -0700407 with adb_connect(self, serial):
408 # b/31250450: this always returns 0 but probably shouldn't.
Josh Gaob3610732018-08-08 13:08:08 -0700409 output = subprocess.check_output(["adb", "connect", serial])
Luis Hector Chavez454bc7c2018-04-20 10:31:29 -0700410 self.assertEqual(
Josh Gao9b6522b2018-08-07 14:31:17 -0700411 output.strip(),
Josh Gaob3610732018-08-08 13:08:08 -0700412 "already connected to {}".format(serial).encode("utf8"))
Josh Gao78cc20f2016-09-01 14:54:18 -0700413
Luis Hector Chavez454bc7c2018-04-20 10:31:29 -0700414 def test_reconnect(self):
415 """Ensure that a disconnected device reconnects."""
Josh Gao78cc20f2016-09-01 14:54:18 -0700416
Josh Gao902dace2018-08-10 14:44:54 -0700417 with fake_adbd() as (port, _):
Josh Gaob3610732018-08-08 13:08:08 -0700418 serial = "localhost:{}".format(port)
Luis Hector Chavez454bc7c2018-04-20 10:31:29 -0700419 with adb_connect(self, serial):
Josh Gaob3610732018-08-08 13:08:08 -0700420 output = subprocess.check_output(["adb", "-s", serial,
421 "get-state"])
422 self.assertEqual(output.strip(), b"device")
Josh Gaoc251ec52018-04-03 12:55:18 -0700423
Luis Hector Chavez454bc7c2018-04-20 10:31:29 -0700424 # This will fail.
Josh Gaob3610732018-08-08 13:08:08 -0700425 proc = subprocess.Popen(["adb", "-s", serial, "shell", "true"],
Luis Hector Chavezfbee0a92018-05-02 09:10:29 -0700426 stdout=subprocess.PIPE,
427 stderr=subprocess.STDOUT)
428 output, _ = proc.communicate()
Josh Gaob3610732018-08-08 13:08:08 -0700429 self.assertEqual(output.strip(), b"error: closed")
Luis Hector Chavez454bc7c2018-04-20 10:31:29 -0700430
Josh Gaob3610732018-08-08 13:08:08 -0700431 subprocess.check_call(["adb", "-s", serial, "wait-for-device"])
Luis Hector Chavez454bc7c2018-04-20 10:31:29 -0700432
Josh Gaob3610732018-08-08 13:08:08 -0700433 output = subprocess.check_output(["adb", "-s", serial,
434 "get-state"])
435 self.assertEqual(output.strip(), b"device")
Luis Hector Chavez454bc7c2018-04-20 10:31:29 -0700436
437 # Once we explicitly kick a device, it won't attempt to
438 # reconnect.
Josh Gaob3610732018-08-08 13:08:08 -0700439 output = subprocess.check_output(["adb", "disconnect", serial])
Luis Hector Chavez454bc7c2018-04-20 10:31:29 -0700440 self.assertEqual(
Josh Gao9b6522b2018-08-07 14:31:17 -0700441 output.strip(),
Josh Gaob3610732018-08-08 13:08:08 -0700442 "disconnected {}".format(serial).encode("utf8"))
Luis Hector Chavez454bc7c2018-04-20 10:31:29 -0700443 try:
Josh Gaob3610732018-08-08 13:08:08 -0700444 subprocess.check_output(["adb", "-s", serial, "get-state"],
Luis Hector Chavez454bc7c2018-04-20 10:31:29 -0700445 stderr=subprocess.STDOUT)
Josh Gaob3610732018-08-08 13:08:08 -0700446 self.fail("Device should not be available")
Luis Hector Chavezfbee0a92018-05-02 09:10:29 -0700447 except subprocess.CalledProcessError as err:
Luis Hector Chavez454bc7c2018-04-20 10:31:29 -0700448 self.assertEqual(
Luis Hector Chavezfbee0a92018-05-02 09:10:29 -0700449 err.output.strip(),
Josh Gaob3610732018-08-08 13:08:08 -0700450 "error: device '{}' not found".format(serial).encode("utf8"))
Spencer Low351ecd12015-10-14 17:32:44 -0700451
Luis Hector Chavezfbee0a92018-05-02 09:10:29 -0700452
Josh Gao902dace2018-08-10 14:44:54 -0700453class DisconnectionTest(unittest.TestCase):
454 """Tests for adb disconnect."""
455
456 def test_disconnect(self):
457 """Ensure that `adb disconnect` takes effect immediately."""
458
459 def _devices(port):
460 output = subprocess.check_output(["adb", "-P", str(port), "devices"])
461 return [x.split("\t") for x in output.decode("utf8").strip().splitlines()[1:]]
462
463 with adb_server() as server_port:
464 with fake_adbd() as (port, sock):
465 device_name = "localhost:{}".format(port)
466 output = subprocess.check_output(["adb", "-P", str(server_port),
467 "connect", device_name])
468 self.assertEqual(output.strip(),
469 "connected to {}".format(device_name).encode("utf8"))
470
471
472 self.assertEqual(_devices(server_port), [[device_name, "device"]])
473
474 # Send a deliberately malformed packet to make the device go offline.
475 packet = struct.pack("IIIIII", 0, 0, 0, 0, 0, 0)
476 sock.sendall(packet)
477
478 # Wait a bit.
479 time.sleep(0.1)
480
481 self.assertEqual(_devices(server_port), [[device_name, "offline"]])
482
483 # Disconnect the device.
484 output = subprocess.check_output(["adb", "-P", str(server_port),
485 "disconnect", device_name])
486
487 # Wait a bit.
488 time.sleep(0.1)
489
490 self.assertEqual(_devices(server_port), [])
491
492
Spencer Low8f6bdc92018-08-31 19:49:46 -0700493@unittest.skipUnless(sys.platform == "win32", "requires Windows")
494class PowerTest(unittest.TestCase):
495 def test_resume_usb_kick(self):
496 """Resuming from sleep/hibernate should kick USB devices."""
497 try:
498 usb_serial = subprocess.check_output(["adb", "-d", "get-serialno"]).strip()
499 except subprocess.CalledProcessError:
500 # If there are multiple USB devices, we don't have a way to check whether the selected
501 # device is USB.
502 raise unittest.SkipTest('requires single USB device')
503
504 try:
505 serial = subprocess.check_output(["adb", "get-serialno"]).strip()
506 except subprocess.CalledProcessError:
507 # Did you forget to select a device with $ANDROID_SERIAL?
508 raise unittest.SkipTest('requires $ANDROID_SERIAL set to a USB device')
509
510 # Test only works with USB devices because adb _power_notification_thread does not kick
511 # non-USB devices on resume event.
512 if serial != usb_serial:
513 raise unittest.SkipTest('requires USB device')
514
515 # Run an adb shell command in the background that takes a while to complete.
516 proc = subprocess.Popen(['adb', 'shell', 'sleep', '5'])
517
518 # Wait for startup of adb server's _power_notification_thread.
519 time.sleep(0.1)
520
521 # Simulate resuming from sleep/hibernation by sending Windows message.
522 import ctypes
523 from ctypes import wintypes
524 HWND_BROADCAST = 0xffff
525 WM_POWERBROADCAST = 0x218
526 PBT_APMRESUMEAUTOMATIC = 0x12
527
528 PostMessageW = ctypes.windll.user32.PostMessageW
529 PostMessageW.restype = wintypes.BOOL
530 PostMessageW.argtypes = (wintypes.HWND, wintypes.UINT, wintypes.WPARAM, wintypes.LPARAM)
531 result = PostMessageW(HWND_BROADCAST, WM_POWERBROADCAST, PBT_APMRESUMEAUTOMATIC, 0)
532 if not result:
533 raise ctypes.WinError()
534
535 # Wait for connection to adb shell to be broken by _power_notification_thread detecting the
536 # Windows message.
537 start = time.time()
538 proc.wait()
539 end = time.time()
540
541 # If the power event was detected, the adb shell command should be broken very quickly.
542 self.assertLess(end - start, 2)
543
544
Dan Albert8e1fdd72015-07-24 17:08:33 -0700545def main():
Luis Hector Chavezfbee0a92018-05-02 09:10:29 -0700546 """Main entrypoint."""
Dan Albert8e1fdd72015-07-24 17:08:33 -0700547 random.seed(0)
Luis Hector Chavezfbee0a92018-05-02 09:10:29 -0700548 unittest.main(verbosity=3)
Dan Albert8e1fdd72015-07-24 17:08:33 -0700549
550
Josh Gaob3610732018-08-08 13:08:08 -0700551if __name__ == "__main__":
Dan Albert8e1fdd72015-07-24 17:08:33 -0700552 main()