1
1
import json
2
2
import argparse
3
3
import time
4
+ import psycopg
5
+ import uuid
4
6
import subprocess
5
7
import numpy as np
6
8
7
-
8
9
from hp .tools .crawler .desktop_selenium import CustomErrorTimeout , CustomTimeout
9
10
from hp .tools .crawler .utils import get_tests , get_or_create_browser
10
11
from multiprocessing import Pool
11
- import psycopg
12
- import uuid
13
12
14
13
15
14
# Setup the config
@@ -37,10 +36,23 @@ def __init__(self, package_name, activity_name, test_url):
37
36
self .test_url = test_url
38
37
39
38
def send_url_intent (device_id , package_name , activity_name , url ):
39
+ """Send VIEW intent to open a URL in a browser
40
+
41
+ Args:
42
+ device_id (str): ID of an android emulator device
43
+ package_name (str): Name of the package to open
44
+ activity_name (str): Name of the activity to open
45
+ url (str): The test URL to visit
46
+ """
40
47
cmd_text = f'adb -s { device_id } shell am start -n { package_name } /{ activity_name } -a android.intent.action.VIEW -d "{ url } "'
41
48
subprocess .run (cmd_text , shell = True )
42
49
43
50
def get_available_device ():
51
+ """Get a list of available Android Emulator devices
52
+
53
+ Returns:
54
+ list[str]: List of devices IDs
55
+ """
44
56
cmd_text = f'adb devices'
45
57
cmd_output = subprocess .run (cmd_text , shell = True , check = True , capture_output = True , text = True ).stdout .strip ()
46
58
device_id_list = []
@@ -54,6 +66,11 @@ def get_available_device():
54
66
return device_id_list
55
67
56
68
def force_stop_emulators (device_avd_name = None ):
69
+ """Force stop one or all Android Emulators
70
+
71
+ Args:
72
+ device_avd_name (str, optional): Name of an avd device. Defaults to None.
73
+ """
57
74
print (f'Stop the enumator name: { device_avd_name } ' )
58
75
if device_avd_name :
59
76
kill_current_devices_cmd = "kill -9 $(ps aux | grep '[e]mulator/qemu/linux-x86_64/qemu-system-i386-headless @device_" + device_avd_name + " ' | awk '{print $2}')"
@@ -71,19 +88,40 @@ def force_stop_emulators(device_avd_name = None):
71
88
time .sleep (2 )
72
89
73
90
def get_emulator_avd_name (device_id ):
91
+ """Convert a device_id to avd_name
92
+
93
+ Args:
94
+ device_id (str): ID of an Emulator device
95
+
96
+ Returns:
97
+ str: AVD name of the device
98
+ """
74
99
# device id format: emulator-5554
75
100
emulator_port = int (device_id .split ('-' )[- 1 ])
76
101
start_port = 5554
77
102
device_name = int ((emulator_port - start_port )/ 2 + 1 )
78
103
return str (device_name )
79
104
80
105
def get_port_by_emulator_avd_name (device_avd_name ):
106
+ """Convert devive_avd_name to the correct port
107
+
108
+ Args:
109
+ device_avd_name (str): name of the avd device
110
+
111
+ Returns:
112
+ int: Corresponding port
113
+ """
81
114
port = 5552
82
115
for i in range (1 ,int (device_avd_name ) + 1 ):
83
116
port += 2
84
117
return port
85
118
86
119
def start_emulator_by_avd_name (device_avd_name ):
120
+ """Start android emulator with a given name
121
+
122
+ Args:
123
+ device_avd_name (str): Name of the avd device to start
124
+ """
87
125
print (f'Starting the emulator: { device_avd_name } ' )
88
126
port = get_port_by_emulator_avd_name (device_avd_name )
89
127
cmd_text = f'nohup emulator @device_{ device_avd_name } -no-snapshot -screen multi-touch -no-window -port { port } &'
@@ -108,6 +146,11 @@ def start_emulator_by_avd_name(device_avd_name):
108
146
time .sleep (10 )
109
147
110
148
def start_emulators (num_devices ):
149
+ """Start as many emulators as requested
150
+
151
+ Args:
152
+ num_devices (int): Number of emulators to start
153
+ """
111
154
port = 5554
112
155
for device in range (1 ,num_devices + 1 ):
113
156
cmd_text = f'nohup emulator @device_{ device } -no-snapshot -screen multi-touch -no-window -port { port } &'
@@ -135,13 +178,18 @@ def start_emulators(num_devices):
135
178
cmd_text = f'adb -s { device_id } root'
136
179
subprocess .run (cmd_text , shell = True )
137
180
138
- # run on each emulator
139
181
def run_test (parameter ):
182
+ """Visit test URLs on a single emulator
183
+
184
+ Args:
185
+ parameter (PARAMATER): Includes app_list (URLs to visit in certain browsers), the emulator device id, and the autorestart setting
186
+ """
140
187
device_id = parameter .device_id
141
188
device_avd_name = get_emulator_avd_name (device_id )
142
189
print (f'Testing: on device ID: { device_id } , with number of URLs: { len (parameter .app_list )} ' )
143
190
144
191
run_times = 0
192
+ # Visit all test URLs, app_list contains the package_name/intent and the test_url to visit
145
193
for app in parameter .app_list :
146
194
print (f'Testing: { app .package_name } , on device ID: { device_id } , with URL: { app .test_url } , test run number: { run_times } ' )
147
195
run_times += 1
@@ -157,8 +205,10 @@ def run_test(parameter):
157
205
conn .execute ("LISTEN page_runner" )
158
206
gen = conn .notifies ()
159
207
208
+ # Sent the Intent to visit the URL
160
209
send_url_intent (device_id , app .package_name , app .activity_name , encoded_test_url )
161
210
211
+ # Go to the next test as soon as the current one is finished
162
212
for notify in gen :
163
213
if notify .payload == run_id :
164
214
print (notify )
@@ -170,6 +220,7 @@ def run_test(parameter):
170
220
print (e )
171
221
print ('Timeout exception!' )
172
222
223
+ # Restart every 100 intents
173
224
if run_times >= 100 and parameter .auto_restart :
174
225
run_times = 0
175
226
print (f'Restarting the emulator: { device_id } , AVD: { device_avd_name } ' )
@@ -179,50 +230,70 @@ def run_test(parameter):
179
230
180
231
force_stop_emulators (device_avd_name )
181
232
182
-
183
233
def main (browser_list , url_dict , repeat_times , num_devices , resp_type , auto_restart , config_dict ):
234
+ """Start all emulators and distribute the test_url visits among them
235
+
236
+ Args:
237
+ browser_list (List[str]): List of browsers to test
238
+ url_dict (JSON dict/optional): Optional dict of URLs to tests (for the repeat mode)
239
+ repeat_times (int): How often each URL should be visited
240
+ num_devices (int): How many emulators to start
241
+ resp_type (str): One of debug, basic, parsing
242
+ auto_restart (bool): Whether to automatically restart emulators every 100 URLs
243
+ config_dict (dict): Additional informatino about the browsers
244
+ """
184
245
app_list = list ()
185
246
url_list = list ()
186
247
248
+ # Create tests for each specified browser
187
249
for browser_name in browser_list :
188
250
browser_config = config_dict [browser_name ]
189
251
252
+ # Get the browser_id from the database
190
253
browser_id = get_or_create_browser (browser_name , browser_config ['version' ], 'Android 11' , 'real' , 'intent' , '' )
191
254
255
+ # Normal mode: load the URLs from the DB (get_tests)
192
256
if not url_dict :
193
257
for scheme in ["http" , "https" ]:
194
258
urls = get_tests (resp_type = resp_type , browser_id = browser_id , scheme = scheme , max_popups = 1 , browser_modifier = 2 )
195
259
url_list .extend (urls )
260
+ # Repeat mode: visit the URLs of the dict
196
261
else :
197
262
browser_id_key = str (browser_id )
198
263
if browser_id_key in url_dict :
199
264
url_list .extend (url_dict [browser_id_key ])
200
265
266
+ # Repeat each URL up to repeat_times
201
267
for i in range (0 , repeat_times ):
202
268
for url in url_list :
203
269
app_list .append (APP (browser_config ['package_name' ], browser_config ['intent' ], url ))
204
270
205
271
print (f'Total number of URLs: { len (app_list )} ' )
206
272
273
+ # Stop old emulators
207
274
device_ids = get_available_device ()
208
275
while len (device_ids ) > 0 :
209
276
print ('Force stop current emulators ...' )
210
277
force_stop_emulators ()
211
278
device_ids = get_available_device ()
212
279
time .sleep (2 )
213
280
281
+ # Start num_devices new emulators
214
282
print ('Starting emulators ...' )
215
283
start_emulators (num_devices )
216
284
time .sleep (5 )
217
285
device_ids = get_available_device ()
218
286
287
+ # Split the URLs that have to be visited in equal chunks
219
288
chunked_app_lists = np .array_split (app_list , len (device_ids ))
220
289
parameters = []
221
290
291
+ # Each chunk needs to know on which device it should run
222
292
for index , working_list in enumerate (chunked_app_lists ):
223
293
device_id = device_ids [index ]
224
294
parameters .append (PARAMETER (working_list , device_id , auto_restart ))
225
295
296
+ # Start the work in each emulator
226
297
start_time = time .time ()
227
298
print (start_time )
228
299
pool = Pool ()
@@ -232,19 +303,21 @@ def main(browser_list, url_dict, repeat_times, num_devices, resp_type, auto_rest
232
303
print (f'{ (time .time () - start_time )} ' )
233
304
234
305
if __name__ == '__main__' :
306
+ """Execute all test runs as specified in the lauch arguments
307
+ """
308
+ # Load all possible browsers
235
309
with open ('android_config.json' ) as file :
236
310
config_dict = json .load (file )
237
-
238
311
browser_list = list (config_dict .keys ())
239
312
browser_list .append ('all' )
240
313
241
314
ap = argparse .ArgumentParser (description = 'Tester for Android devices' )
242
315
ap .add_argument ('-browsers' , '--browsers' , dest = 'browsers' , type = str , required = True , nargs = '+' , choices = browser_list )
243
- ap .add_argument ('-url_json' , '--url_json' , default = '' , type = str , help = 'Path to a json list of create_repeat.py tests' )
244
- ap .add_argument ('-repeat' , '--repeat' , default = 1 , type = int , help = 'Repeat x times' )
245
- ap .add_argument ('-num_devices' , '--num_devices' , dest = 'num_devices' , type = int )
316
+ ap .add_argument ('-url_json' , '--url_json' , default = '' , type = str , help = 'Optional path to a json list of create_repeat.py tests' )
317
+ ap .add_argument ('-repeat' , '--repeat' , default = 1 , type = int , help = 'Repeat each test x times. ' )
318
+ ap .add_argument ('-num_devices' , '--num_devices' , dest = 'num_devices' , type = int , help = 'How many emulators to start/use' )
246
319
ap .add_argument ('-type' , '--resp_type' , choices = ['basic' , 'debug' , 'parsing' ], default = 'basic' , help = 'Specify the response type (default: basic)' )
247
- ap .add_argument ('-auto_restart' , action = 'store_true' , help = 'Auto restart' )
320
+ ap .add_argument ('-auto_restart' , action = 'store_true' , help = 'Automatically restart the emulator every 100 URLs. ' )
248
321
249
322
args = ap .parse_args ()
250
323
0 commit comments