blob: cde2b22ea229e75717aa03e238fdbf2c77eb492f [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
34
Dan Alberta4169f92015-07-24 17:08:33 -070035
Luis Hector Chavezbf8a7222018-04-17 19:25:33 -070036@contextlib.contextmanager
Luis Hector Chavez947b2132018-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 Chavezbf8a7222018-04-17 19:25:33 -070039
40 serversock = socket.socket(protocol, socket.SOCK_STREAM)
Luis Hector Chavez947b2132018-05-02 09:10:29 -070041 serversock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
Luis Hector Chavezbf8a7222018-04-17 19:25:33 -070042 if protocol == socket.AF_INET:
Josh Gao4db70c52018-08-08 13:08:08 -070043 serversock.bind(("127.0.0.1", port))
Luis Hector Chavezbf8a7222018-04-17 19:25:33 -070044 else:
Josh Gao4db70c52018-08-08 13:08:08 -070045 serversock.bind(("::1", port))
Luis Hector Chavezbf8a7222018-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 Gao6afbf792018-08-07 16:07:25 -070049 readsock, writesock = socket.socketpair()
Luis Hector Chavezbf8a7222018-04-17 19:25:33 -070050
Josh Gaob1df00e2018-08-07 14:31:17 -070051 def _adb_packet(command: bytes, arg0: int, arg1: int, data: bytes) -> bytes:
Josh Gao4db70c52018-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 Chavezda74b902018-04-17 14:25:04 -070054 bin_command ^ 0xffffffff)
55 buf += data
56 return buf
57
Josh Gaob1df00e2018-08-07 14:31:17 -070058 def _handle(sock):
59 with contextlib.closing(sock) as serversock:
Josh Gao6afbf792018-08-07 16:07:25 -070060 rlist = [readsock, serversock]
Josh Gaob1df00e2018-08-07 14:31:17 -070061 cnxn_sent = {}
62 while True:
63 read_ready, _, _ = select.select(rlist, [], [])
64 for ready in read_ready:
Josh Gao6afbf792018-08-07 16:07:25 -070065 if ready == readsock:
Josh Gaob1df00e2018-08-07 14:31:17 -070066 # Closure pipe
Josh Gaob1df00e2018-08-07 14:31:17 -070067 for f in rlist:
Josh Gao6afbf792018-08-07 16:07:25 -070068 f.close()
Josh Gaob1df00e2018-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 Gao4db70c52018-08-08 13:08:08 -070077 if not data or data.startswith(b"OPEN"):
Josh Gaob1df00e2018-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 Chavez947b2132018-05-02 09:10:29 -070084 if ready in cnxn_sent:
Josh Gaob1df00e2018-08-07 14:31:17 -070085 continue
86 cnxn_sent[ready] = True
Josh Gao4db70c52018-08-08 13:08:08 -070087 ready.sendall(_adb_packet(b"CNXN", 0x01000001, 1024 * 1024,
88 b"device::ro.product.name=fakeadb"))
Luis Hector Chavezbf8a7222018-04-17 19:25:33 -070089
90 port = serversock.getsockname()[1]
Josh Gaob1df00e2018-08-07 14:31:17 -070091 server_thread = threading.Thread(target=_handle, args=(serversock,))
Luis Hector Chavezbf8a7222018-04-17 19:25:33 -070092 server_thread.start()
93
94 try:
Josh Gao13cb8c02018-08-10 14:44:54 -070095 yield port, writesock
Luis Hector Chavezbf8a7222018-04-17 19:25:33 -070096 finally:
Josh Gao6afbf792018-08-07 16:07:25 -070097 writesock.close()
Luis Hector Chavezbf8a7222018-04-17 19:25:33 -070098 server_thread.join()
99
100
Luis Hector Chavez0aeda102018-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 Gao4db70c52018-08-08 13:08:08 -0700108 output = subprocess.check_output(["adb", "connect", serial])
Josh Gaob1df00e2018-08-07 14:31:17 -0700109 unittest.assertEqual(output.strip(),
Josh Gao4db70c52018-08-08 13:08:08 -0700110 "connected to {}".format(serial).encode("utf8"))
Luis Hector Chavez0aeda102018-04-20 10:31:29 -0700111
112 try:
113 yield
114 finally:
115 # Perform best-effort disconnection. Discard the output.
Josh Gao4db70c52018-08-08 13:08:08 -0700116 subprocess.Popen(["adb", "disconnect", serial],
Luis Hector Chavez947b2132018-05-02 09:10:29 -0700117 stdout=subprocess.PIPE,
118 stderr=subprocess.PIPE).communicate()
Luis Hector Chavez0aeda102018-04-20 10:31:29 -0700119
120
Luis Hector Chaveza452f0e2018-05-02 10:47:01 -0700121@contextlib.contextmanager
122def adb_server():
123 """Context manager for an ADB server.
124
Josh Gao13cb8c02018-08-10 14:44:54 -0700125 This creates an ADB server and returns the port it's listening on.
Luis Hector Chaveza452f0e2018-05-02 10:47:01 -0700126 """
127
128 port = 5038
129 # Kill any existing server on this non-default port.
Josh Gao4db70c52018-08-08 13:08:08 -0700130 subprocess.check_output(["adb", "-P", str(port), "kill-server"],
Luis Hector Chaveza452f0e2018-05-02 10:47:01 -0700131 stderr=subprocess.STDOUT)
132 read_pipe, write_pipe = os.pipe()
Josh Gao6d7b9652018-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 Gao4db70c52018-08-08 13:08:08 -0700143 proc = subprocess.Popen(["adb", "-L", "tcp:localhost:{}".format(port),
144 "fork-server", "server",
Josh Gao6d7b9652018-08-21 14:25:05 -0700145 "--reply-fd", reply_fd], close_fds=False)
Luis Hector Chaveza452f0e2018-05-02 10:47:01 -0700146 try:
147 os.close(write_pipe)
148 greeting = os.read(read_pipe, 1024)
Josh Gao4db70c52018-08-08 13:08:08 -0700149 assert greeting == b"OK\n", repr(greeting)
Luis Hector Chaveza452f0e2018-05-02 10:47:01 -0700150 yield port
151 finally:
152 proc.terminate()
153 proc.wait()
154
155
Luis Hector Chavez947b2132018-05-02 09:10:29 -0700156class CommandlineTest(unittest.TestCase):
157 """Tests for the ADB commandline."""
Dan Alberta4169f92015-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 Gao4db70c52018-08-08 13:08:08 -0700162 ["adb", "help"], stderr=subprocess.STDOUT)
Dan Alberta4169f92015-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 Gao4db70c52018-08-08 13:08:08 -0700167 lines = subprocess.check_output(["adb", "version"]).splitlines()
Dan Alberta4169f92015-07-24 17:08:33 -0700168 version_line = lines[0]
Josh Gaob1df00e2018-08-07 14:31:17 -0700169 self.assertRegex(
Josh Gao4db70c52018-08-08 13:08:08 -0700170 version_line, rb"^Android Debug Bridge version \d+\.\d+\.\d+$")
Dan Alberta4169f92015-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 Gaob1df00e2018-08-07 14:31:17 -0700175 self.assertRegex(
Josh Gao4db70c52018-08-08 13:08:08 -0700176 revision_line, rb"^Revision [0-9a-f]{12}-android$")
Dan Alberta4169f92015-07-24 17:08:33 -0700177
178 def test_tcpip_error_messages(self):
Luis Hector Chavez947b2132018-05-02 09:10:29 -0700179 """Make sure 'adb tcpip' parsing is sane."""
Josh Gao4db70c52018-08-08 13:08:08 -0700180 proc = subprocess.Popen(["adb", "tcpip"],
Josh Gaob1df00e2018-08-07 14:31:17 -0700181 stdout=subprocess.PIPE,
Luis Hector Chavez947b2132018-05-02 09:10:29 -0700182 stderr=subprocess.STDOUT)
183 out, _ = proc.communicate()
184 self.assertEqual(1, proc.returncode)
Josh Gao4db70c52018-08-08 13:08:08 -0700185 self.assertIn(b"requires an argument", out)
Dan Alberta4169f92015-07-24 17:08:33 -0700186
Josh Gao4db70c52018-08-08 13:08:08 -0700187 proc = subprocess.Popen(["adb", "tcpip", "foo"],
Josh Gaob1df00e2018-08-07 14:31:17 -0700188 stdout=subprocess.PIPE,
Luis Hector Chavez947b2132018-05-02 09:10:29 -0700189 stderr=subprocess.STDOUT)
190 out, _ = proc.communicate()
191 self.assertEqual(1, proc.returncode)
Josh Gao4db70c52018-08-08 13:08:08 -0700192 self.assertIn(b"invalid port", out)
Dan Alberta4169f92015-07-24 17:08:33 -0700193
Luis Hector Chavez947b2132018-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 Low9a999242015-09-16 20:45:53 -0700202 event.set()
203
Spencer Low9a999242015-09-16 20:45:53 -0700204 def test_handle_inheritance(self):
Luis Hector Chavez947b2132018-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 Low9a999242015-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 Gao4db70c52018-08-08 13:08:08 -0700228 subprocess.check_output(["adb", "-P", str(port), "kill-server"],
Spencer Low9a999242015-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 Gao4db70c52018-08-08 13:08:08 -0700233 proc = subprocess.Popen(["adb", "-P", str(port), "start-server"],
Luis Hector Chavez947b2132018-05-02 09:10:29 -0700234 stdin=subprocess.PIPE,
235 stdout=subprocess.PIPE,
236 stderr=subprocess.PIPE)
Spencer Low9a999242015-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 Chavez947b2132018-05-02 09:10:29 -0700241 target=ServerTest._read_pipe_and_set_event,
242 args=(proc.stdout, stdout_event))
Spencer Low9a999242015-09-16 20:45:53 -0700243 stdout_thread.start()
244
245 stderr_event = threading.Event()
246 stderr_thread = threading.Thread(
Luis Hector Chavez947b2132018-05-02 09:10:29 -0700247 target=ServerTest._read_pipe_and_set_event,
248 args=(proc.stderr, stderr_event))
Spencer Low9a999242015-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 Chavez947b2132018-05-02 09:10:29 -0700254 proc.wait()
Spencer Low9a999242015-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 Gao4db70c52018-08-08 13:08:08 -0700262 proc.stdin.write(b"x")
Josh Gaob1df00e2018-08-07 14:31:17 -0700263 proc.stdin.flush()
Spencer Low9a999242015-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 Gaob1df00e2018-08-07 14:31:17 -0700272 stdout_thread.join()
273 stderr_thread.join()
Spencer Low9a999242015-09-16 20:45:53 -0700274 finally:
275 # If we started a server, kill it.
Josh Gao4db70c52018-08-08 13:08:08 -0700276 subprocess.check_output(["adb", "-P", str(port), "kill-server"],
Spencer Low9a999242015-09-16 20:45:53 -0700277 stderr=subprocess.STDOUT)
Dan Alberta4169f92015-07-24 17:08:33 -0700278
Luis Hector Chavez947b2132018-05-02 09:10:29 -0700279
280class EmulatorTest(unittest.TestCase):
281 """Tests for the emulator connection."""
282
Spencer Lowcc4a4b12015-10-14 17:32:44 -0700283 def _reset_socket_on_close(self, sock):
Luis Hector Chavez947b2132018-05-02 09:10:29 -0700284 """Use SO_LINGER to cause TCP RST segment to be sent on socket close."""
Spencer Lowcc4a4b12015-10-14 17:32:44 -0700285 # The linger structure is two shorts on Windows, but two ints on Unix.
Josh Gao4db70c52018-08-08 13:08:08 -0700286 linger_format = "hh" if os.name == "nt" else "ii"
Spencer Lowcc4a4b12015-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 Lowcc4a4b12015-10-14 17:32:44 -0700302 with contextlib.closing(
Luis Hector Chavez947b2132018-05-02 09:10:29 -0700303 socket.socket(socket.AF_INET, socket.SOCK_STREAM)) as listener:
Spencer Lowcc4a4b12015-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 Gao4db70c52018-08-08 13:08:08 -0700307 listener.bind(("127.0.0.1", 0))
Spencer Lowcc4a4b12015-10-14 17:32:44 -0700308 listener.listen(4)
Josh Gao13781e82018-04-03 12:55:18 -0700309 port = listener.getsockname()[1]
Spencer Lowcc4a4b12015-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 Chavez947b2132018-05-02 09:10:29 -0700313 proc = subprocess.Popen(
Josh Gao4db70c52018-08-08 13:08:08 -0700314 ["adb", "-s", "emulator-" + str(port), "emu", "kill"],
Spencer Lowcc4a4b12015-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 Gao4db70c52018-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 Lowcc4a4b12015-10-14 17:32:44 -0700324
Luis Hector Chavez947b2132018-05-02 09:10:29 -0700325 with contextlib.closing(conn.makefile()) as connf:
326 line = connf.readline()
Josh Gao4db70c52018-08-08 13:08:08 -0700327 if line.startswith("auth"):
Luis Hector Chavez947b2132018-05-02 09:10:29 -0700328 # Ignore the first auth line.
329 line = connf.readline()
Josh Gao4db70c52018-08-08 13:08:08 -0700330 self.assertEqual("kill\n", line)
331 self.assertEqual("quit\n", connf.readline())
Spencer Lowcc4a4b12015-10-14 17:32:44 -0700332
Josh Gao4db70c52018-08-08 13:08:08 -0700333 conn.sendall(b"OK: killing emulator, bye bye\r\n")
Spencer Lowcc4a4b12015-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 Chavez947b2132018-05-02 09:10:29 -0700344 proc.communicate()
Spencer Lowcc4a4b12015-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 Chavez947b2132018-05-02 09:10:29 -0700348 self.assertEqual(0, proc.returncode)
349
Luis Hector Chaveza452f0e2018-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 Gao13cb8c02018-08-10 14:44:54 -0700356 with fake_adbd() as (port, _):
Josh Gao4db70c52018-08-08 13:08:08 -0700357 serial = "emulator-{}".format(port - 1)
Luis Hector Chaveza452f0e2018-05-02 10:47:01 -0700358 # Ensure that the emulator is not there.
359 try:
Josh Gao4db70c52018-08-08 13:08:08 -0700360 subprocess.check_output(["adb", "-P", str(server_port),
361 "-s", serial, "get-state"],
Luis Hector Chaveza452f0e2018-05-02 10:47:01 -0700362 stderr=subprocess.STDOUT)
Josh Gao4db70c52018-08-08 13:08:08 -0700363 self.fail("Device should not be available")
Luis Hector Chaveza452f0e2018-05-02 10:47:01 -0700364 except subprocess.CalledProcessError as err:
365 self.assertEqual(
366 err.output.strip(),
Josh Gao4db70c52018-08-08 13:08:08 -0700367 "error: device '{}' not found".format(serial).encode("utf8"))
Luis Hector Chaveza452f0e2018-05-02 10:47:01 -0700368
369 # Let the ADB server know that the emulator has started.
370 with contextlib.closing(
Josh Gaob1df00e2018-08-07 14:31:17 -0700371 socket.socket(socket.AF_INET, socket.SOCK_STREAM)) as sock:
Josh Gao4db70c52018-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 Chaveza452f0e2018-05-02 10:47:01 -0700375
376 # Ensure the emulator is there.
Josh Gao4db70c52018-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 Chaveza452f0e2018-05-02 10:47:01 -0700382
Luis Hector Chavez947b2132018-05-02 09:10:29 -0700383
384class ConnectionTest(unittest.TestCase):
385 """Tests for adb connect."""
Spencer Lowcc4a4b12015-10-14 17:32:44 -0700386
Josh Gao50bde8d2016-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 Chavezbf8a7222018-04-17 19:25:33 -0700392 for protocol in (socket.AF_INET, socket.AF_INET6):
393 try:
Josh Gao13cb8c02018-08-10 14:44:54 -0700394 with fake_adbd(protocol=protocol) as (port, _):
Josh Gao4db70c52018-08-08 13:08:08 -0700395 serial = "localhost:{}".format(port)
Luis Hector Chavez0aeda102018-04-20 10:31:29 -0700396 with adb_connect(self, serial):
397 pass
Luis Hector Chavezbf8a7222018-04-17 19:25:33 -0700398 except socket.error:
399 print("IPv6 not available, skipping")
400 continue
Josh Gao50bde8d2016-09-01 14:54:18 -0700401
Luis Hector Chavezbf8a7222018-04-17 19:25:33 -0700402 def test_already_connected(self):
Luis Hector Chavez0aeda102018-04-20 10:31:29 -0700403 """Ensure that an already-connected device stays connected."""
404
Josh Gao13cb8c02018-08-10 14:44:54 -0700405 with fake_adbd() as (port, _):
Josh Gao4db70c52018-08-08 13:08:08 -0700406 serial = "localhost:{}".format(port)
Luis Hector Chavez0aeda102018-04-20 10:31:29 -0700407 with adb_connect(self, serial):
408 # b/31250450: this always returns 0 but probably shouldn't.
Josh Gao4db70c52018-08-08 13:08:08 -0700409 output = subprocess.check_output(["adb", "connect", serial])
Luis Hector Chavez0aeda102018-04-20 10:31:29 -0700410 self.assertEqual(
Josh Gaob1df00e2018-08-07 14:31:17 -0700411 output.strip(),
Josh Gao4db70c52018-08-08 13:08:08 -0700412 "already connected to {}".format(serial).encode("utf8"))
Josh Gao50bde8d2016-09-01 14:54:18 -0700413
Luis Hector Chavez0aeda102018-04-20 10:31:29 -0700414 def test_reconnect(self):
415 """Ensure that a disconnected device reconnects."""
Josh Gao50bde8d2016-09-01 14:54:18 -0700416
Josh Gao13cb8c02018-08-10 14:44:54 -0700417 with fake_adbd() as (port, _):
Josh Gao4db70c52018-08-08 13:08:08 -0700418 serial = "localhost:{}".format(port)
Luis Hector Chavez0aeda102018-04-20 10:31:29 -0700419 with adb_connect(self, serial):
Josh Gao4db70c52018-08-08 13:08:08 -0700420 output = subprocess.check_output(["adb", "-s", serial,
421 "get-state"])
422 self.assertEqual(output.strip(), b"device")
Josh Gao13781e82018-04-03 12:55:18 -0700423
Luis Hector Chavez0aeda102018-04-20 10:31:29 -0700424 # This will fail.
Josh Gao4db70c52018-08-08 13:08:08 -0700425 proc = subprocess.Popen(["adb", "-s", serial, "shell", "true"],
Luis Hector Chavez947b2132018-05-02 09:10:29 -0700426 stdout=subprocess.PIPE,
427 stderr=subprocess.STDOUT)
428 output, _ = proc.communicate()
Josh Gao4db70c52018-08-08 13:08:08 -0700429 self.assertEqual(output.strip(), b"error: closed")
Luis Hector Chavez0aeda102018-04-20 10:31:29 -0700430
Josh Gao4db70c52018-08-08 13:08:08 -0700431 subprocess.check_call(["adb", "-s", serial, "wait-for-device"])
Luis Hector Chavez0aeda102018-04-20 10:31:29 -0700432
Josh Gao4db70c52018-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 Chavez0aeda102018-04-20 10:31:29 -0700436
437 # Once we explicitly kick a device, it won't attempt to
438 # reconnect.
Josh Gao4db70c52018-08-08 13:08:08 -0700439 output = subprocess.check_output(["adb", "disconnect", serial])
Luis Hector Chavez0aeda102018-04-20 10:31:29 -0700440 self.assertEqual(
Josh Gaob1df00e2018-08-07 14:31:17 -0700441 output.strip(),
Josh Gao4db70c52018-08-08 13:08:08 -0700442 "disconnected {}".format(serial).encode("utf8"))
Luis Hector Chavez0aeda102018-04-20 10:31:29 -0700443 try:
Josh Gao4db70c52018-08-08 13:08:08 -0700444 subprocess.check_output(["adb", "-s", serial, "get-state"],
Luis Hector Chavez0aeda102018-04-20 10:31:29 -0700445 stderr=subprocess.STDOUT)
Josh Gao4db70c52018-08-08 13:08:08 -0700446 self.fail("Device should not be available")
Luis Hector Chavez947b2132018-05-02 09:10:29 -0700447 except subprocess.CalledProcessError as err:
Luis Hector Chavez0aeda102018-04-20 10:31:29 -0700448 self.assertEqual(
Luis Hector Chavez947b2132018-05-02 09:10:29 -0700449 err.output.strip(),
Josh Gao4db70c52018-08-08 13:08:08 -0700450 "error: device '{}' not found".format(serial).encode("utf8"))
Spencer Lowcc4a4b12015-10-14 17:32:44 -0700451
Luis Hector Chavez947b2132018-05-02 09:10:29 -0700452
Josh Gao13cb8c02018-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
Dan Alberta4169f92015-07-24 17:08:33 -0700493def main():
Luis Hector Chavez947b2132018-05-02 09:10:29 -0700494 """Main entrypoint."""
Dan Alberta4169f92015-07-24 17:08:33 -0700495 random.seed(0)
Luis Hector Chavez947b2132018-05-02 09:10:29 -0700496 unittest.main(verbosity=3)
Dan Alberta4169f92015-07-24 17:08:33 -0700497
498
Josh Gao4db70c52018-08-08 13:08:08 -0700499if __name__ == "__main__":
Dan Alberta4169f92015-07-24 17:08:33 -0700500 main()