1
2 import requests
3 import time
4
5 import pytest
6 import re
7 from _pytest import runner
8 from tlib.base import TestHelper
9 import logging
10
11 DEVICE_UNPLUGGED = "disconnected"
12 DEVICE_OFFLINE = "offline"
13 DEVICE_UNAUTHORIZED = "unauthorized"
14 DEVICE_ONLINE = "online"
15
17 """
18 Function to validate if webdriver is running and a connection can be established
19
20 @param tlib_logger: TLib logger
21 @type tlib_logger: logging.logger
22 @param adb_logger: ADB logger
23 @type adb_logger: logging.logger
24 @param log: When true, log debugging information
25 @type log: bool
26 """
27 try:
28 if log: tlib_logger.debug("Checking if Webdriver is running")
29 response = requests.get("http://localhost:8080/wd/hub/status", timeout=10)
30 except requests.ConnectionError as e:
31 if log: adb_logger.debug("Connection to Webdriver failed:\n%s" % e)
32 return False
33
34 return response.status_code == 200
35
36
38 """
39 Get status of a device using it's serial id\n
40 Serial id can be either a ID (for devices connected to USB) or an IP and port (For devices connected via IP)
41
42 @param tlib_logger: TLib logger
43 @type tlib_logger: logging.logger
44 @param adb_logger: ADB logger
45 @type adb_logger: logging.logger
46 @param serial_id: Device's serial number
47 @type serial_id: str
48 """
49
50 out = TestHelper.run_command(adb_logger, ["adb", "devices"], fail_on_error=False)
51 if re.search(serial_id, out[0]) is None:
52 tlib_logger.debug("Device {serial_id} is not connected".format(serial_id=serial_id))
53 return DEVICE_UNPLUGGED
54 elif re.search("{serial_id}\s+offline".format(serial_id=serial_id), out[0]) is not None:
55 tlib_logger.debug("Device {serial_id} is offline".format(serial_id=serial_id))
56 return DEVICE_OFFLINE
57 elif re.search("{serial_id}\s+unauthorized".format(serial_id=serial_id), out[0]) is not None:
58 tlib_logger.debug("Device {serial_id} is offline".format(serial_id=serial_id))
59 return DEVICE_UNAUTHORIZED
60 elif re.search("{serial_id}\s+device".format(serial_id=serial_id), out[0]) is not None:
61 tlib_logger.debug("Device {serial_id} is online".format(serial_id=serial_id))
62 return DEVICE_ONLINE
63 else:
64 tlib_logger.error("Unknown device status\n%s" % out[0])
65 pytest.fail("Unknown device status\n%s" % out[0])
66
67
69 """
70 Connects to an android device via IP and waits for the connection to be established.
71
72 @param tlib_logger: TLib logger
73 @type tlib_logger: logging.logger
74 @param adb_logger: ADB logger
75 @type adb_logger: logging.logger
76 @param serial_id: Device's serial number
77 @type serial_id: str
78 """
79
80 tlib_logger.debug("Setting up IP connection to device {serial_id}".format(serial_id=serial_id))
81 status = get_device_status(tlib_logger, adb_logger, serial_id)
82
83 if status == DEVICE_ONLINE:
84 tlib_logger.debug("Device is already online".format(serial_id=serial_id))
85 return
86
87
88 if status == DEVICE_OFFLINE:
89 tlib_logger.warn("Device {serial_id} is offline, disconnecting and retrying".format(serial_id=serial_id))
90 terminate_ip_connection(tlib_logger, adb_logger, serial_id)
91 elif status == DEVICE_UNAUTHORIZED:
92 terminate_ip_connection(tlib_logger, adb_logger, serial_id)
93 tlib_logger.error("Device {serial_id} is not authorized, aborting".format(serial_id=serial_id))
94 pytest.fail("Device {serial_id} is not authorized, aborting".format(serial_id=serial_id))
95 elif status == DEVICE_UNPLUGGED:
96 tlib_logger.warn("Device {serial_id} is disconecting, resetting connection".format(serial_id=serial_id))
97 terminate_ip_connection(tlib_logger, adb_logger, serial_id)
98
99 timeout = 0.5
100
101
102 for i in range(1, int(3 / timeout)):
103 out = TestHelper.run_command(adb_logger, ["adb", "connect", serial_id])
104 log_adb_output(adb_logger, out)
105
106 if get_device_status(tlib_logger, adb_logger, serial_id) == DEVICE_ONLINE:
107 tlib_logger.debug("Connected to device")
108 return
109 else:
110 tlib_logger.debug("Not yet connected")
111 time.sleep(timeout)
112
113
114 adb_logger.error(r"Timeout while connecting to device {serial_id}\nADB output:\n{out}".format(serial_id=serial_id, out=out))
115
116 pytest.fail(r"Timeout while connecting to device {serial_id}\nADB output:\n{out}".format(serial_id=serial_id, out=out))
117
118
120 """
121 Disconnects from device
122
123 @param tlib_logger: TLib logger
124 @type tlib_logger: logging.logger
125 @param adb_logger: ADB logger
126 @type adb_logger: logging.logger
127 @param serial_id: Device's serial number
128 @type serial_id: str
129 """
130 tlib_logger.debug("Disconnecting from device {serial_id}".format(serial_id=serial_id))
131 out = TestHelper.run_command(adb_logger, ["adb", "disconnect", serial_id])
132 log_adb_output(adb_logger, out)
133
134
136 """
137 Stops Webdriver app o the device
138
139 @param tlib_logger: TLib logger
140 @type tlib_logger: logging.logger
141 @param adb_logger: ADB logger
142 @type adb_logger: logging.logger
143 @param serial_id: Device's serial number
144 @type serial_id: str
145 """
146 tlib_logger.debug("Closing Webdriver on {serial_id}".format(serial_id=serial_id))
147 if serial_id is None or serial_id == "":
148 out = TestHelper.run_command(adb_logger,
149 "adb shell am force-stop org.openqa.selenium.android.app", shell=True)
150 else:
151 out = TestHelper.run_command(adb_logger,
152 "adb -s %s shell am force-stop org.openqa.selenium.android.app" % serial_id, shell=True)
153 log_adb_output(adb_logger, out)
154
155
157 """
158 Setup port forwarding between computer and device.
159
160 @param tlib_logger: TLib logger
161 @type tlib_logger: logging.logger
162 @param adb_logger: ADB logger
163 @type adb_logger: logging.logger
164 @param serial_id: Device's serial number
165 @type serial_id: str
166 """
167 tlib_logger.info("Setting up port forwarding")
168 if serial_id is None or serial_id == "":
169 out = TestHelper.run_command(adb_logger, "adb forward tcp:8080 tcp:8080", shell=True)
170 else:
171 out = TestHelper.run_command(adb_logger, "adb -s %s forward tcp:8080 tcp:8080" % serial_id, shell=True)
172 log_adb_output(adb_logger, out)
173
174
176 """
177 Terminates all port forwarding connections
178
179 @param tlib_logger: TLib logger
180 @type tlib_logger: logging.logger
181 @param adb_logger: ADB logger
182 @type adb_logger: logging.logger
183 """
184 tlib_logger.info("Tearing down port forwarding")
185 out = TestHelper.run_command(adb_logger, "adb forward --remove-all", shell=True)
186 log_adb_output(adb_logger, out)
187
189 """
190 Stops adb on the machine\n
191 This can be required by TeamCity so some folders are not locked
192
193 @param tlib_logger: TLib logger
194 @type tlib_logger: logging.logger
195 @param adb_logger: ADB logger
196 @type adb_logger: logging.logger
197 """
198 tlib_logger.info("Starting ADB")
199 out = TestHelper.run_command(adb_logger, ["adb", "start-server"], fail_on_error=False)
200 log_adb_output(adb_logger, out)
201
203 """
204 Stops adb on the machine\n
205 This can be required by TeamCity so some folders are not locked
206
207 @param tlib_logger: TLib logger
208 @type tlib_logger: logging.logger
209 @param adb_logger: ADB logger
210 @type adb_logger: logging.logger
211 """
212 tlib_logger.info("Stopping ADB")
213 out = TestHelper.run_command(adb_logger, ["adb", "kill-server"], fail_on_error=False)
214 log_adb_output(adb_logger, out)
215
216
218 """
219 Starts Webdriver app on the device
220
221 @param tlib_logger: TLib logger
222 @type tlib_logger: logging.logger
223 @param adb_logger: ADB logger
224 @type adb_logger: logging.logger
225 @param serial_id: Device's serial number
226 @type serial_id: str
227 """
228 tlib_logger.info("Starting webdriver on the device")
229 if serial_id is None or serial_id == "":
230 out = TestHelper.run_command(adb_logger,
231 "adb shell am start -a android.intent.action.MAIN -n org.openqa.selenium.android.app/.MainActivity -e debug true",
232 shell=True)
233 else:
234 out = TestHelper.run_command(adb_logger,
235 "adb -s %s shell am start -a android.intent.action.MAIN -n org.openqa.selenium.android.app/.MainActivity -e debug true" % serial_id,
236 shell=True)
237 log_adb_output(adb_logger, out)
238
239
241 """
242 Waits up to 3 seconds for a connection to Webdriver
243
244 @param tlib_logger: TLib logger
245 @type tlib_logger: logging.logger
246 @param adb_logger: ADB logger
247 @type adb_logger: logging.logger
248 """
249
250 tlib_logger.debug("Waiting for connection to Webdriver")
251 timeout = 0.5
252 for i in range(1, int(3 / timeout)):
253 if is_webdriver_running(tlib_logger, adb_logger, False):
254 tlib_logger.debug("Webdriver started successfully")
255 break
256 tlib_logger.debug("Can't connect to Webdriver, retrying in {timeout} seconds".format(timeout=timeout))
257 time.sleep(timeout)
258
259 if not is_webdriver_running(tlib_logger, adb_logger, False):
260 tlib_logger.error("Couldn't start Webdriver. Make sure it's installed and running\n"
261 "See https://code.google.com/p/selenium/wiki/AndroidDriver#Setup_the_Emulator for more details")
262
263 pytest.fail("Couldn't start Webdriver. Make sure it's installed and running\n"
264 "See https://code.google.com/p/selenium/wiki/AndroidDriver#Setup_the_Emulator for more details")
265
266
267
269 """
270 Connects to a device and starts webdriver
271
272 @param tlib_logger: TLib logger
273 @type tlib_logger: logging.logger
274 @param adb_logger: ADB logger
275 @type adb_logger: logging.logger
276 @param serial_id: Device's serial number
277 @type serial_id: str
278 """
279
280 if is_webdriver_running(tlib_logger, adb_logger, log=False):
281 tlib_logger.debug("Already connected to device")
282 return
283
284 tlib_logger.info("Connecting to Webdriver")
285
286
287 if TestHelper.is_valid_ip(serial_id):
288 setup_ip_connection(tlib_logger, adb_logger, serial_id)
289
290 setup_port_forwarding(tlib_logger, adb_logger, serial_id)
291
292
293 if is_webdriver_running(tlib_logger, adb_logger):
294 tlib_logger.debug("Connected to Webdriver")
295 return
296
297
298 start_webdriver(tlib_logger, adb_logger, serial_id)
299
300
301 wait_for_connection_to_webdriver(tlib_logger, adb_logger)
302
303 tlib_logger.info("Connection to Webdriver established")
304
305
306
308 """
309 Closes webdriver and disconnects from device
310
311 @param tlib_logger: TLib logger
312 @type tlib_logger: logging.logger
313 @param adb_logger: ADB logger
314 @type adb_logger: logging.logger
315 @param serial_id: Device's serial number
316 @type serial_id: str
317 """
318
319 tlib_logger.info("Disconnecting from Webdriver")
320 close_webdriver(tlib_logger, adb_logger, serial_id)
321
322
323 if TestHelper.is_valid_ip(serial_id):
324 terminate_ip_connection(tlib_logger, adb_logger, serial_id)
325
326
327 try:
328 stop_adb_server(tlib_logger, adb_logger)
329 except runner.Failed:
330
331 adb_logger.warn("Error stopping ADB server")
332
333 tlib_logger.info("Disconnected from Webdriver")
334
335
336
359
360
362 """
363 Function to validate if webdriver is running and a connection can be established
364
365 @param tlib_logger: TLib logger
366 @type tlib_logger: logging.logger
367 @param adb_logger: ADB logger
368 @type adb_logger: logging.logger
369 @param log: When true, log debugging information
370 @type log: bool
371 """
372 try:
373 if log: tlib_logger.debug("Checking if Selendroid server is running")
374 response = requests.get("http://localhost:4444/wd/hub/status", timeout=10)
375 except requests.ConnectionError as e:
376 if log: adb_logger.debug("Connection to Selendroid failed:\n%s" % e)
377 return False
378
379 return response.status_code == 200
380
381
383 response = requests.get("http://localhost:4444/wd/hub/status")
384 if not response:
385 return None
386 from jsonpath_rw import jsonpath
387 apps = jsonpath(response.json(), '$.value.supportedApps[*].appId')
388 for app in apps:
389 if not app.startswith('io.selendroid.androiddriver'):
390 return app
391 return None
392
394 """
395 Logs ADB output
396
397 @param logger: ADB logger
398 @type logger: logging.logger
399 """
400 if out[0] is not None and out[0] != '':
401 logger.debug("\n" + out[0])
402
403 if out[1] is not None and out[1] != '':
404 logger.debug("\n" + out[1])
405