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