blob: 86c13d0ad51214b5026718919f5a2aa406d41063 [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
Spencer Low9a999242015-09-16 20:45:53 -070030import threading
Josh Gao13cb8c02018-08-10 14:44:54 -070031import time
Dan Alberta4169f92015-07-24 17:08:33 -070032import unittest
33
Dan Alberta4169f92015-07-24 17:08:33 -070034
Luis Hector Chavezbf8a7222018-04-17 19:25:33 -070035@contextlib.contextmanager
Luis Hector Chavez947b2132018-05-02 09:10:29 -070036def fake_adbd(protocol=socket.AF_INET, port=0):
37 """Creates a fake ADB daemon that just replies with a CNXN packet."""
Luis Hector Chavezbf8a7222018-04-17 19:25:33 -070038
39 serversock = socket.socket(protocol, socket.SOCK_STREAM)
Luis Hector Chavez947b2132018-05-02 09:10:29 -070040 serversock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
Luis Hector Chavezbf8a7222018-04-17 19:25:33 -070041 if protocol == socket.AF_INET:
Josh Gao4db70c52018-08-08 13:08:08 -070042 serversock.bind(("127.0.0.1", port))
Luis Hector Chavezbf8a7222018-04-17 19:25:33 -070043 else:
Josh Gao4db70c52018-08-08 13:08:08 -070044 serversock.bind(("::1", port))
Luis Hector Chavezbf8a7222018-04-17 19:25:33 -070045 serversock.listen(1)
46
47 # A pipe that is used to signal the thread that it should terminate.
Josh Gao6afbf792018-08-07 16:07:25 -070048 readsock, writesock = socket.socketpair()
Luis Hector Chavezbf8a7222018-04-17 19:25:33 -070049
Josh Gaob1df00e2018-08-07 14:31:17 -070050 def _adb_packet(command: bytes, arg0: int, arg1: int, data: bytes) -> bytes:
Josh Gao4db70c52018-08-08 13:08:08 -070051 bin_command = struct.unpack("I", command)[0]
52 buf = struct.pack("IIIIII", bin_command, arg0, arg1, len(data), 0,
Luis Hector Chavezda74b902018-04-17 14:25:04 -070053 bin_command ^ 0xffffffff)
54 buf += data
55 return buf
56
Josh Gaob1df00e2018-08-07 14:31:17 -070057 def _handle(sock):
58 with contextlib.closing(sock) as serversock:
Josh Gao6afbf792018-08-07 16:07:25 -070059 rlist = [readsock, serversock]
Josh Gaob1df00e2018-08-07 14:31:17 -070060 cnxn_sent = {}
61 while True:
62 read_ready, _, _ = select.select(rlist, [], [])
63 for ready in read_ready:
Josh Gao6afbf792018-08-07 16:07:25 -070064 if ready == readsock:
Josh Gaob1df00e2018-08-07 14:31:17 -070065 # Closure pipe
Josh Gaob1df00e2018-08-07 14:31:17 -070066 for f in rlist:
Josh Gao6afbf792018-08-07 16:07:25 -070067 f.close()
Josh Gaob1df00e2018-08-07 14:31:17 -070068 return
69 elif ready == serversock:
70 # Server socket
71 conn, _ = ready.accept()
72 rlist.append(conn)
73 else:
74 # Client socket
75 data = ready.recv(1024)
Josh Gao4db70c52018-08-08 13:08:08 -070076 if not data or data.startswith(b"OPEN"):
Josh Gaob1df00e2018-08-07 14:31:17 -070077 if ready in cnxn_sent:
78 del cnxn_sent[ready]
79 ready.shutdown(socket.SHUT_RDWR)
80 ready.close()
81 rlist.remove(ready)
82 continue
Luis Hector Chavez947b2132018-05-02 09:10:29 -070083 if ready in cnxn_sent:
Josh Gaob1df00e2018-08-07 14:31:17 -070084 continue
85 cnxn_sent[ready] = True
Josh Gao4db70c52018-08-08 13:08:08 -070086 ready.sendall(_adb_packet(b"CNXN", 0x01000001, 1024 * 1024,
87 b"device::ro.product.name=fakeadb"))
Luis Hector Chavezbf8a7222018-04-17 19:25:33 -070088
89 port = serversock.getsockname()[1]
Josh Gaob1df00e2018-08-07 14:31:17 -070090 server_thread = threading.Thread(target=_handle, args=(serversock,))
Luis Hector Chavezbf8a7222018-04-17 19:25:33 -070091 server_thread.start()
92
93 try:
Josh Gao13cb8c02018-08-10 14:44:54 -070094 yield port, writesock
Luis Hector Chavezbf8a7222018-04-17 19:25:33 -070095 finally:
Josh Gao6afbf792018-08-07 16:07:25 -070096 writesock.close()
Luis Hector Chavezbf8a7222018-04-17 19:25:33 -070097 server_thread.join()
98
99
Luis Hector Chavez0aeda102018-04-20 10:31:29 -0700100@contextlib.contextmanager
101def adb_connect(unittest, serial):
102 """Context manager for an ADB connection.
103
104 This automatically disconnects when done with the connection.
105 """
106
Josh Gao4db70c52018-08-08 13:08:08 -0700107 output = subprocess.check_output(["adb", "connect", serial])
Josh Gaob1df00e2018-08-07 14:31:17 -0700108 unittest.assertEqual(output.strip(),
Josh Gao4db70c52018-08-08 13:08:08 -0700109 "connected to {}".format(serial).encode("utf8"))
Luis Hector Chavez0aeda102018-04-20 10:31:29 -0700110
111 try:
112 yield
113 finally:
114 # Perform best-effort disconnection. Discard the output.
Josh Gao4db70c52018-08-08 13:08:08 -0700115 subprocess.Popen(["adb", "disconnect", serial],
Luis Hector Chavez947b2132018-05-02 09:10:29 -0700116 stdout=subprocess.PIPE,
117 stderr=subprocess.PIPE).communicate()
Luis Hector Chavez0aeda102018-04-20 10:31:29 -0700118
119
Luis Hector Chaveza452f0e2018-05-02 10:47:01 -0700120@contextlib.contextmanager
121def adb_server():
122 """Context manager for an ADB server.
123
Josh Gao13cb8c02018-08-10 14:44:54 -0700124 This creates an ADB server and returns the port it's listening on.
Luis Hector Chaveza452f0e2018-05-02 10:47:01 -0700125 """
126
127 port = 5038
128 # Kill any existing server on this non-default port.
Josh Gao4db70c52018-08-08 13:08:08 -0700129 subprocess.check_output(["adb", "-P", str(port), "kill-server"],
Luis Hector Chaveza452f0e2018-05-02 10:47:01 -0700130 stderr=subprocess.STDOUT)
131 read_pipe, write_pipe = os.pipe()
Josh Gaob1df00e2018-08-07 14:31:17 -0700132 os.set_inheritable(write_pipe, True)
Josh Gao4db70c52018-08-08 13:08:08 -0700133 proc = subprocess.Popen(["adb", "-L", "tcp:localhost:{}".format(port),
134 "fork-server", "server",
135 "--reply-fd", str(write_pipe)], close_fds=False)
Luis Hector Chaveza452f0e2018-05-02 10:47:01 -0700136 try:
137 os.close(write_pipe)
138 greeting = os.read(read_pipe, 1024)
Josh Gao4db70c52018-08-08 13:08:08 -0700139 assert greeting == b"OK\n", repr(greeting)
Luis Hector Chaveza452f0e2018-05-02 10:47:01 -0700140 yield port
141 finally:
142 proc.terminate()
143 proc.wait()
144
145
Luis Hector Chavez947b2132018-05-02 09:10:29 -0700146class CommandlineTest(unittest.TestCase):
147 """Tests for the ADB commandline."""
Dan Alberta4169f92015-07-24 17:08:33 -0700148
149 def test_help(self):
150 """Make sure we get _something_ out of help."""
151 out = subprocess.check_output(
Josh Gao4db70c52018-08-08 13:08:08 -0700152 ["adb", "help"], stderr=subprocess.STDOUT)
Dan Alberta4169f92015-07-24 17:08:33 -0700153 self.assertGreater(len(out), 0)
154
155 def test_version(self):
156 """Get a version number out of the output of adb."""
Josh Gao4db70c52018-08-08 13:08:08 -0700157 lines = subprocess.check_output(["adb", "version"]).splitlines()
Dan Alberta4169f92015-07-24 17:08:33 -0700158 version_line = lines[0]
Josh Gaob1df00e2018-08-07 14:31:17 -0700159 self.assertRegex(
Josh Gao4db70c52018-08-08 13:08:08 -0700160 version_line, rb"^Android Debug Bridge version \d+\.\d+\.\d+$")
Dan Alberta4169f92015-07-24 17:08:33 -0700161 if len(lines) == 2:
162 # Newer versions of ADB have a second line of output for the
163 # version that includes a specific revision (git SHA).
164 revision_line = lines[1]
Josh Gaob1df00e2018-08-07 14:31:17 -0700165 self.assertRegex(
Josh Gao4db70c52018-08-08 13:08:08 -0700166 revision_line, rb"^Revision [0-9a-f]{12}-android$")
Dan Alberta4169f92015-07-24 17:08:33 -0700167
168 def test_tcpip_error_messages(self):
Luis Hector Chavez947b2132018-05-02 09:10:29 -0700169 """Make sure 'adb tcpip' parsing is sane."""
Josh Gao4db70c52018-08-08 13:08:08 -0700170 proc = subprocess.Popen(["adb", "tcpip"],
Josh Gaob1df00e2018-08-07 14:31:17 -0700171 stdout=subprocess.PIPE,
Luis Hector Chavez947b2132018-05-02 09:10:29 -0700172 stderr=subprocess.STDOUT)
173 out, _ = proc.communicate()
174 self.assertEqual(1, proc.returncode)
Josh Gao4db70c52018-08-08 13:08:08 -0700175 self.assertIn(b"requires an argument", out)
Dan Alberta4169f92015-07-24 17:08:33 -0700176
Josh Gao4db70c52018-08-08 13:08:08 -0700177 proc = subprocess.Popen(["adb", "tcpip", "foo"],
Josh Gaob1df00e2018-08-07 14:31:17 -0700178 stdout=subprocess.PIPE,
Luis Hector Chavez947b2132018-05-02 09:10:29 -0700179 stderr=subprocess.STDOUT)
180 out, _ = proc.communicate()
181 self.assertEqual(1, proc.returncode)
Josh Gao4db70c52018-08-08 13:08:08 -0700182 self.assertIn(b"invalid port", out)
Dan Alberta4169f92015-07-24 17:08:33 -0700183
Luis Hector Chavez947b2132018-05-02 09:10:29 -0700184
185class ServerTest(unittest.TestCase):
186 """Tests for the ADB server."""
187
188 @staticmethod
189 def _read_pipe_and_set_event(pipe, event):
190 """Reads a pipe until it is closed, then sets the event."""
191 pipe.read()
Spencer Low9a999242015-09-16 20:45:53 -0700192 event.set()
193
Spencer Low9a999242015-09-16 20:45:53 -0700194 def test_handle_inheritance(self):
Luis Hector Chavez947b2132018-05-02 09:10:29 -0700195 """Test that launch_server() does not inherit handles.
196
197 launch_server() should not let the adb server inherit
198 stdin/stdout/stderr handles, which can cause callers of adb.exe to hang.
199 This test also runs fine on unix even though the impetus is an issue
200 unique to Windows.
201 """
Spencer Low9a999242015-09-16 20:45:53 -0700202 # This test takes 5 seconds to run on Windows: if there is no adb server
203 # running on the the port used below, adb kill-server tries to make a
204 # TCP connection to a closed port and that takes 1 second on Windows;
205 # adb start-server does the same TCP connection which takes another
206 # second, and it waits 3 seconds after starting the server.
207
208 # Start adb client with redirected stdin/stdout/stderr to check if it
209 # passes those redirections to the adb server that it starts. To do
210 # this, run an instance of the adb server on a non-default port so we
211 # don't conflict with a pre-existing adb server that may already be
212 # setup with adb TCP/emulator connections. If there is a pre-existing
213 # adb server, this also tests whether multiple instances of the adb
214 # server conflict on adb.log.
215
216 port = 5038
217 # Kill any existing server on this non-default port.
Josh Gao4db70c52018-08-08 13:08:08 -0700218 subprocess.check_output(["adb", "-P", str(port), "kill-server"],
Spencer Low9a999242015-09-16 20:45:53 -0700219 stderr=subprocess.STDOUT)
220
221 try:
222 # Run the adb client and have it start the adb server.
Josh Gao4db70c52018-08-08 13:08:08 -0700223 proc = subprocess.Popen(["adb", "-P", str(port), "start-server"],
Luis Hector Chavez947b2132018-05-02 09:10:29 -0700224 stdin=subprocess.PIPE,
225 stdout=subprocess.PIPE,
226 stderr=subprocess.PIPE)
Spencer Low9a999242015-09-16 20:45:53 -0700227
228 # Start threads that set events when stdout/stderr are closed.
229 stdout_event = threading.Event()
230 stdout_thread = threading.Thread(
Luis Hector Chavez947b2132018-05-02 09:10:29 -0700231 target=ServerTest._read_pipe_and_set_event,
232 args=(proc.stdout, stdout_event))
Spencer Low9a999242015-09-16 20:45:53 -0700233 stdout_thread.start()
234
235 stderr_event = threading.Event()
236 stderr_thread = threading.Thread(
Luis Hector Chavez947b2132018-05-02 09:10:29 -0700237 target=ServerTest._read_pipe_and_set_event,
238 args=(proc.stderr, stderr_event))
Spencer Low9a999242015-09-16 20:45:53 -0700239 stderr_thread.start()
240
241 # Wait for the adb client to finish. Once that has occurred, if
242 # stdin/stderr/stdout are still open, it must be open in the adb
243 # server.
Luis Hector Chavez947b2132018-05-02 09:10:29 -0700244 proc.wait()
Spencer Low9a999242015-09-16 20:45:53 -0700245
246 # Try to write to stdin which we expect is closed. If it isn't
247 # closed, we should get an IOError. If we don't get an IOError,
248 # stdin must still be open in the adb server. The adb client is
249 # probably letting the adb server inherit stdin which would be
250 # wrong.
251 with self.assertRaises(IOError):
Josh Gao4db70c52018-08-08 13:08:08 -0700252 proc.stdin.write(b"x")
Josh Gaob1df00e2018-08-07 14:31:17 -0700253 proc.stdin.flush()
Spencer Low9a999242015-09-16 20:45:53 -0700254
255 # Wait a few seconds for stdout/stderr to be closed (in the success
256 # case, this won't wait at all). If there is a timeout, that means
257 # stdout/stderr were not closed and and they must be open in the adb
258 # server, suggesting that the adb client is letting the adb server
259 # inherit stdout/stderr which would be wrong.
260 self.assertTrue(stdout_event.wait(5), "adb stdout not closed")
261 self.assertTrue(stderr_event.wait(5), "adb stderr not closed")
Josh Gaob1df00e2018-08-07 14:31:17 -0700262 stdout_thread.join()
263 stderr_thread.join()
Spencer Low9a999242015-09-16 20:45:53 -0700264 finally:
265 # If we started a server, kill it.
Josh Gao4db70c52018-08-08 13:08:08 -0700266 subprocess.check_output(["adb", "-P", str(port), "kill-server"],
Spencer Low9a999242015-09-16 20:45:53 -0700267 stderr=subprocess.STDOUT)
Dan Alberta4169f92015-07-24 17:08:33 -0700268
Luis Hector Chavez947b2132018-05-02 09:10:29 -0700269
270class EmulatorTest(unittest.TestCase):
271 """Tests for the emulator connection."""
272
Spencer Lowcc4a4b12015-10-14 17:32:44 -0700273 def _reset_socket_on_close(self, sock):
Luis Hector Chavez947b2132018-05-02 09:10:29 -0700274 """Use SO_LINGER to cause TCP RST segment to be sent on socket close."""
Spencer Lowcc4a4b12015-10-14 17:32:44 -0700275 # The linger structure is two shorts on Windows, but two ints on Unix.
Josh Gao4db70c52018-08-08 13:08:08 -0700276 linger_format = "hh" if os.name == "nt" else "ii"
Spencer Lowcc4a4b12015-10-14 17:32:44 -0700277 l_onoff = 1
278 l_linger = 0
279
280 sock.setsockopt(socket.SOL_SOCKET, socket.SO_LINGER,
281 struct.pack(linger_format, l_onoff, l_linger))
282 # Verify that we set the linger structure properly by retrieving it.
283 linger = sock.getsockopt(socket.SOL_SOCKET, socket.SO_LINGER, 16)
284 self.assertEqual((l_onoff, l_linger),
285 struct.unpack_from(linger_format, linger))
286
287 def test_emu_kill(self):
288 """Ensure that adb emu kill works.
289
290 Bug: https://code.google.com/p/android/issues/detail?id=21021
291 """
Spencer Lowcc4a4b12015-10-14 17:32:44 -0700292 with contextlib.closing(
Luis Hector Chavez947b2132018-05-02 09:10:29 -0700293 socket.socket(socket.AF_INET, socket.SOCK_STREAM)) as listener:
Spencer Lowcc4a4b12015-10-14 17:32:44 -0700294 # Use SO_REUSEADDR so subsequent runs of the test can grab the port
295 # even if it is in TIME_WAIT.
296 listener.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
Josh Gao4db70c52018-08-08 13:08:08 -0700297 listener.bind(("127.0.0.1", 0))
Spencer Lowcc4a4b12015-10-14 17:32:44 -0700298 listener.listen(4)
Josh Gao13781e82018-04-03 12:55:18 -0700299 port = listener.getsockname()[1]
Spencer Lowcc4a4b12015-10-14 17:32:44 -0700300
301 # Now that listening has started, start adb emu kill, telling it to
302 # connect to our mock emulator.
Luis Hector Chavez947b2132018-05-02 09:10:29 -0700303 proc = subprocess.Popen(
Josh Gao4db70c52018-08-08 13:08:08 -0700304 ["adb", "-s", "emulator-" + str(port), "emu", "kill"],
Spencer Lowcc4a4b12015-10-14 17:32:44 -0700305 stderr=subprocess.STDOUT)
306
307 accepted_connection, addr = listener.accept()
308 with contextlib.closing(accepted_connection) as conn:
309 # If WSAECONNABORTED (10053) is raised by any socket calls,
310 # then adb probably isn't reading the data that we sent it.
Josh Gao4db70c52018-08-08 13:08:08 -0700311 conn.sendall(("Android Console: type 'help' for a list "
312 "of commands\r\n").encode("utf8"))
313 conn.sendall(b"OK\r\n")
Spencer Lowcc4a4b12015-10-14 17:32:44 -0700314
Luis Hector Chavez947b2132018-05-02 09:10:29 -0700315 with contextlib.closing(conn.makefile()) as connf:
316 line = connf.readline()
Josh Gao4db70c52018-08-08 13:08:08 -0700317 if line.startswith("auth"):
Luis Hector Chavez947b2132018-05-02 09:10:29 -0700318 # Ignore the first auth line.
319 line = connf.readline()
Josh Gao4db70c52018-08-08 13:08:08 -0700320 self.assertEqual("kill\n", line)
321 self.assertEqual("quit\n", connf.readline())
Spencer Lowcc4a4b12015-10-14 17:32:44 -0700322
Josh Gao4db70c52018-08-08 13:08:08 -0700323 conn.sendall(b"OK: killing emulator, bye bye\r\n")
Spencer Lowcc4a4b12015-10-14 17:32:44 -0700324
325 # Use SO_LINGER to send TCP RST segment to test whether adb
326 # ignores WSAECONNRESET on Windows. This happens with the
327 # real emulator because it just calls exit() without closing
328 # the socket or calling shutdown(SD_SEND). At process
329 # termination, Windows sends a TCP RST segment for every
330 # open socket that shutdown(SD_SEND) wasn't used on.
331 self._reset_socket_on_close(conn)
332
333 # Wait for adb to finish, so we can check return code.
Luis Hector Chavez947b2132018-05-02 09:10:29 -0700334 proc.communicate()
Spencer Lowcc4a4b12015-10-14 17:32:44 -0700335
336 # If this fails, adb probably isn't ignoring WSAECONNRESET when
337 # reading the response from the adb emu kill command (on Windows).
Luis Hector Chavez947b2132018-05-02 09:10:29 -0700338 self.assertEqual(0, proc.returncode)
339
Luis Hector Chaveza452f0e2018-05-02 10:47:01 -0700340 def test_emulator_connect(self):
341 """Ensure that the emulator can connect.
342
343 Bug: http://b/78991667
344 """
345 with adb_server() as server_port:
Josh Gao13cb8c02018-08-10 14:44:54 -0700346 with fake_adbd() as (port, _):
Josh Gao4db70c52018-08-08 13:08:08 -0700347 serial = "emulator-{}".format(port - 1)
Luis Hector Chaveza452f0e2018-05-02 10:47:01 -0700348 # Ensure that the emulator is not there.
349 try:
Josh Gao4db70c52018-08-08 13:08:08 -0700350 subprocess.check_output(["adb", "-P", str(server_port),
351 "-s", serial, "get-state"],
Luis Hector Chaveza452f0e2018-05-02 10:47:01 -0700352 stderr=subprocess.STDOUT)
Josh Gao4db70c52018-08-08 13:08:08 -0700353 self.fail("Device should not be available")
Luis Hector Chaveza452f0e2018-05-02 10:47:01 -0700354 except subprocess.CalledProcessError as err:
355 self.assertEqual(
356 err.output.strip(),
Josh Gao4db70c52018-08-08 13:08:08 -0700357 "error: device '{}' not found".format(serial).encode("utf8"))
Luis Hector Chaveza452f0e2018-05-02 10:47:01 -0700358
359 # Let the ADB server know that the emulator has started.
360 with contextlib.closing(
Josh Gaob1df00e2018-08-07 14:31:17 -0700361 socket.socket(socket.AF_INET, socket.SOCK_STREAM)) as sock:
Josh Gao4db70c52018-08-08 13:08:08 -0700362 sock.connect(("localhost", server_port))
363 command = "host:emulator:{}".format(port).encode("utf8")
364 sock.sendall(b"%04x%s" % (len(command), command))
Luis Hector Chaveza452f0e2018-05-02 10:47:01 -0700365
366 # Ensure the emulator is there.
Josh Gao4db70c52018-08-08 13:08:08 -0700367 subprocess.check_call(["adb", "-P", str(server_port),
368 "-s", serial, "wait-for-device"])
369 output = subprocess.check_output(["adb", "-P", str(server_port),
370 "-s", serial, "get-state"])
371 self.assertEqual(output.strip(), b"device")
Luis Hector Chaveza452f0e2018-05-02 10:47:01 -0700372
Luis Hector Chavez947b2132018-05-02 09:10:29 -0700373
374class ConnectionTest(unittest.TestCase):
375 """Tests for adb connect."""
Spencer Lowcc4a4b12015-10-14 17:32:44 -0700376
Josh Gao50bde8d2016-09-01 14:54:18 -0700377 def test_connect_ipv4_ipv6(self):
378 """Ensure that `adb connect localhost:1234` will try both IPv4 and IPv6.
379
380 Bug: http://b/30313466
381 """
Luis Hector Chavezbf8a7222018-04-17 19:25:33 -0700382 for protocol in (socket.AF_INET, socket.AF_INET6):
383 try:
Josh Gao13cb8c02018-08-10 14:44:54 -0700384 with fake_adbd(protocol=protocol) as (port, _):
Josh Gao4db70c52018-08-08 13:08:08 -0700385 serial = "localhost:{}".format(port)
Luis Hector Chavez0aeda102018-04-20 10:31:29 -0700386 with adb_connect(self, serial):
387 pass
Luis Hector Chavezbf8a7222018-04-17 19:25:33 -0700388 except socket.error:
389 print("IPv6 not available, skipping")
390 continue
Josh Gao50bde8d2016-09-01 14:54:18 -0700391
Luis Hector Chavezbf8a7222018-04-17 19:25:33 -0700392 def test_already_connected(self):
Luis Hector Chavez0aeda102018-04-20 10:31:29 -0700393 """Ensure that an already-connected device stays connected."""
394
Josh Gao13cb8c02018-08-10 14:44:54 -0700395 with fake_adbd() as (port, _):
Josh Gao4db70c52018-08-08 13:08:08 -0700396 serial = "localhost:{}".format(port)
Luis Hector Chavez0aeda102018-04-20 10:31:29 -0700397 with adb_connect(self, serial):
398 # b/31250450: this always returns 0 but probably shouldn't.
Josh Gao4db70c52018-08-08 13:08:08 -0700399 output = subprocess.check_output(["adb", "connect", serial])
Luis Hector Chavez0aeda102018-04-20 10:31:29 -0700400 self.assertEqual(
Josh Gaob1df00e2018-08-07 14:31:17 -0700401 output.strip(),
Josh Gao4db70c52018-08-08 13:08:08 -0700402 "already connected to {}".format(serial).encode("utf8"))
Josh Gao50bde8d2016-09-01 14:54:18 -0700403
Luis Hector Chavez0aeda102018-04-20 10:31:29 -0700404 def test_reconnect(self):
405 """Ensure that a disconnected device reconnects."""
Josh Gao50bde8d2016-09-01 14:54:18 -0700406
Josh Gao13cb8c02018-08-10 14:44:54 -0700407 with fake_adbd() as (port, _):
Josh Gao4db70c52018-08-08 13:08:08 -0700408 serial = "localhost:{}".format(port)
Luis Hector Chavez0aeda102018-04-20 10:31:29 -0700409 with adb_connect(self, serial):
Josh Gao4db70c52018-08-08 13:08:08 -0700410 output = subprocess.check_output(["adb", "-s", serial,
411 "get-state"])
412 self.assertEqual(output.strip(), b"device")
Josh Gao13781e82018-04-03 12:55:18 -0700413
Luis Hector Chavez0aeda102018-04-20 10:31:29 -0700414 # This will fail.
Josh Gao4db70c52018-08-08 13:08:08 -0700415 proc = subprocess.Popen(["adb", "-s", serial, "shell", "true"],
Luis Hector Chavez947b2132018-05-02 09:10:29 -0700416 stdout=subprocess.PIPE,
417 stderr=subprocess.STDOUT)
418 output, _ = proc.communicate()
Josh Gao4db70c52018-08-08 13:08:08 -0700419 self.assertEqual(output.strip(), b"error: closed")
Luis Hector Chavez0aeda102018-04-20 10:31:29 -0700420
Josh Gao4db70c52018-08-08 13:08:08 -0700421 subprocess.check_call(["adb", "-s", serial, "wait-for-device"])
Luis Hector Chavez0aeda102018-04-20 10:31:29 -0700422
Josh Gao4db70c52018-08-08 13:08:08 -0700423 output = subprocess.check_output(["adb", "-s", serial,
424 "get-state"])
425 self.assertEqual(output.strip(), b"device")
Luis Hector Chavez0aeda102018-04-20 10:31:29 -0700426
427 # Once we explicitly kick a device, it won't attempt to
428 # reconnect.
Josh Gao4db70c52018-08-08 13:08:08 -0700429 output = subprocess.check_output(["adb", "disconnect", serial])
Luis Hector Chavez0aeda102018-04-20 10:31:29 -0700430 self.assertEqual(
Josh Gaob1df00e2018-08-07 14:31:17 -0700431 output.strip(),
Josh Gao4db70c52018-08-08 13:08:08 -0700432 "disconnected {}".format(serial).encode("utf8"))
Luis Hector Chavez0aeda102018-04-20 10:31:29 -0700433 try:
Josh Gao4db70c52018-08-08 13:08:08 -0700434 subprocess.check_output(["adb", "-s", serial, "get-state"],
Luis Hector Chavez0aeda102018-04-20 10:31:29 -0700435 stderr=subprocess.STDOUT)
Josh Gao4db70c52018-08-08 13:08:08 -0700436 self.fail("Device should not be available")
Luis Hector Chavez947b2132018-05-02 09:10:29 -0700437 except subprocess.CalledProcessError as err:
Luis Hector Chavez0aeda102018-04-20 10:31:29 -0700438 self.assertEqual(
Luis Hector Chavez947b2132018-05-02 09:10:29 -0700439 err.output.strip(),
Josh Gao4db70c52018-08-08 13:08:08 -0700440 "error: device '{}' not found".format(serial).encode("utf8"))
Spencer Lowcc4a4b12015-10-14 17:32:44 -0700441
Luis Hector Chavez947b2132018-05-02 09:10:29 -0700442
Josh Gao13cb8c02018-08-10 14:44:54 -0700443class DisconnectionTest(unittest.TestCase):
444 """Tests for adb disconnect."""
445
446 def test_disconnect(self):
447 """Ensure that `adb disconnect` takes effect immediately."""
448
449 def _devices(port):
450 output = subprocess.check_output(["adb", "-P", str(port), "devices"])
451 return [x.split("\t") for x in output.decode("utf8").strip().splitlines()[1:]]
452
453 with adb_server() as server_port:
454 with fake_adbd() as (port, sock):
455 device_name = "localhost:{}".format(port)
456 output = subprocess.check_output(["adb", "-P", str(server_port),
457 "connect", device_name])
458 self.assertEqual(output.strip(),
459 "connected to {}".format(device_name).encode("utf8"))
460
461
462 self.assertEqual(_devices(server_port), [[device_name, "device"]])
463
464 # Send a deliberately malformed packet to make the device go offline.
465 packet = struct.pack("IIIIII", 0, 0, 0, 0, 0, 0)
466 sock.sendall(packet)
467
468 # Wait a bit.
469 time.sleep(0.1)
470
471 self.assertEqual(_devices(server_port), [[device_name, "offline"]])
472
473 # Disconnect the device.
474 output = subprocess.check_output(["adb", "-P", str(server_port),
475 "disconnect", device_name])
476
477 # Wait a bit.
478 time.sleep(0.1)
479
480 self.assertEqual(_devices(server_port), [])
481
482
Dan Alberta4169f92015-07-24 17:08:33 -0700483def main():
Luis Hector Chavez947b2132018-05-02 09:10:29 -0700484 """Main entrypoint."""
Dan Alberta4169f92015-07-24 17:08:33 -0700485 random.seed(0)
Luis Hector Chavez947b2132018-05-02 09:10:29 -0700486 unittest.main(verbosity=3)
Dan Alberta4169f92015-07-24 17:08:33 -0700487
488
Josh Gao4db70c52018-08-08 13:08:08 -0700489if __name__ == "__main__":
Dan Alberta4169f92015-07-24 17:08:33 -0700490 main()