summaryrefslogtreecommitdiff
path: root/emu_test/test_console/utils/util.py
blob: 8efa0fdd66b0d730024b61d670800ab6ff119b9a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
"""This module contains utility helper functions and constants for console test.

Particularly, parseOutput(telnet) function is extensively used
throughout the entire console test in order to parse the console output until
"OK" message.
"""

import os
from os.path import expanduser
import re
import subprocess
import sys
import telnetlib
import time

NEWLINE = '\n'
OK = 'OK'
STATUS = 'status: '
AC = 'AC: '
PRESENT = 'present: '
HEALTH = 'health: '
CAPACITY = 'capacity: '
REGEX_PWR_DISPLAY = 'AC:.*\nstatus:.*\nhealth:.*\npresent:.*\ncapacity:.*\nOK'
COMPARE_CMD = ''
WINDOWS_OS_NAME = 'nt'
if os.name == WINDOWS_OS_NAME:
  COMPARE_CMD = 'FC'
else:
  COMPARE_CMD = 'diff'

SERVER_NAME = 'localhost'
CONSOLE_PORT = 5554

NUM_MAX_TRIALS = 3
TRIAL_WAIT_TIMEOUT_S = 0.5
CMD_WAIT_TIMEOUT_S = 3
SETUP_WAIT_TIMEOUT_S = 5

ADB_TRIAL_WAIT_TIME_S = 2
ADB_NUM_MAX_TRIALS = 5

TIMEOUT_S = 1

HOME = expanduser('~')
CONSOLE_AUTH_TOKEN_FILE_NAME = '.emulator_console_auth_token'
TOKEN_PATH = os.path.join(HOME, CONSOLE_AUTH_TOKEN_FILE_NAME)

UTILS_DIR = os.path.dirname(os.path.realpath(__file__))
EVENT_DIR = os.path.join(UTILS_DIR, 'constants')
EVENTS_CODE_NO_ALIAS = 'no code aliases defined for this type\r\nOK'
EVENTS_CODE_EV_KEY_FILENAME = os.path.join(EVENT_DIR, 'EVENTS_CODE_EV_KEY')
EVENTS_CODE_EV_REL_FILENAME = os.path.join(EVENT_DIR, 'EVENTS_CODE_EV_REL')
EVENTS_CODE_EV_ABS_FILENAME = os.path.join(EVENT_DIR, 'EVENTS_CODE_EV_ABS')
EVENTS_CODE_EV_SW_FILENAME = os.path.join(EVENT_DIR, 'EVENTS_CODE_EV_SW')
EVENTS_EV_TYPES_FILENAME = os.path.join(EVENT_DIR, 'EVENTS_EV_TYPES')
PORT_NO_REDIR = 'no active redirections\r\nOK'
PORT_REDIR_ADD = 'tcp:5556  => 5554 \r\nOK'
CMD_HELP = 'help\n'
REGEX_HELP_DISPLAY_NO_AUTH = (r'.*\n.*help.*\n.*help-verbose.*\n.*ping.*\n'
                              r'.*avd.*\n.*auth.*\n.*quit\|exit.*\n.*\n.*\n.*\nOK')
REGEX_HELP_DISPLAY_AUTH = (r'.*\n.*help.*\n.*help-verbose.*\n.*ping.*\n.*event.*\n'
                           r'.*geo.*\n.*gsm.*\n.*cdma.*\n.*crash.*\n.*crash-on-exit.*\n'
                           r'.*kill.*\n.*network.*\n'
                           r'.*power.*\n.*quit\|exit.*\n.*redir.*\n'
                           r'.*sms.*\n.*avd.*\n.*qemu.*\n.*sensor.*\n.'
                           r'*finger.*\n.*debug.*\n.*rotate.*\n.*\n.*\n.*\nOK')
CMD_HELP_VERBOSE = 'help-verbose\n'
REGEX_HELP_VERBOSE_DISPLAY_NO_AUTH = (
        r'.*\n.*\n.*help.*\n.*help-verbose.*\n.*ping.*\n'
        r'.*avd.*\n.*auth.*\n.*quit\|exit.*\n.*\n.*\nOK')
REGEX_HELP_VERBOSE_DISPLAY_AUTH = (
        r'.*\n.*\n.*help.*\n.*help-verbose.*\n.*ping.*\n.*event.*\n'
        r'.*geo.*\n.*gsm.*\n.*cdma.*\n.*crash.*\n.*crash-on-exit.*\n'
        r'.*kill.*\n.*network.*\n'
        r'.*power.*\n.*quit\|exit.*\n.*redir.*\n'
        r'.*sms.*\n.*avd.*\n.*qemu.*\n.*sensor.*\n.'
        r'*finger.*\n.*debug.*\n.*rotate.*\n.*\n.*\nOK')
AUTH = 'auth'
CMD_RANDOM_AUTH_TOKEN = '%s axxB123cc\n' % AUTH
CMD_EMPTY_AUTH_TOKEN = '%s \n' % AUTH
CMD_EXIT = 'exit\n'
SCRIPT_TO_INSTALL_APK = 'install_apk.py'
SCRIPT_TO_RUN_ADB_SHELL = 'run_adb_shell.py'
SCRIPT_TO_UNINSTALL_APP = 'uninstall_app.py'
PYTHON_INTERPRETER = 'python'
CMD_ROTATE = 'rotate\n'
MAIN_APK_PACKAGE = 'com.android.devtools.server'


def check_read_until(console_output):
  """Checks whether the console output ends with 'OK' message.

  Args:
    console_output: The console output to be checked.

  Returns:
    A boolean value: It indicates the console output ends with 'OK' message
    or not.
  """
  console_output = console_output.strip()
  index_ok = console_output.rfind(OK)
  return index_ok == len(console_output) - len(OK)


def parse_output(telnet):
  """Parses console output until 'OK' appears.

  Args:
    telnet: The telnet connection to emulator.

  Returns:
    parsed_output: The parsed output until 'OK' message.
  """
  parsed_output = telnet.read_until(OK).strip()
  return parsed_output


def extract_field_from_output(output, keyword):
  """Extract value of specific field from battery command.

  Args:
    output: The output for extracting certain field.
    keyword: The keyword for searching.

  Returns:
    A string value: The field from output searching by given keyword.
  """
  keyword_idx = output.find(keyword)
  return (output[keyword_idx + len(keyword):output.find(NEWLINE, keyword_idx)]
          .strip())


def pattern_match_output(output, regex):
  """Check whether console output matches with a given regex.

  Args:
    output: The console output of a command.
    regex: The regular pattern to use for searching.

  Returns:
    A boolean value: It indicates the pattern is found in the output or not.
  """
  if re.match(regex, output):
    return True
  else:
    return False


def check_battery_status(status):
  """Checking each battery status, used in testcase_battery.py.

  Args:
    status: A battery status to map.

  Returns:
    A string value: The capitalized/mapped battery status.
  """
  if status == 'not-charging':
    return 'Not charging'
  if status == 'failure':
    return 'Unspecified failure'
  if status == 'overheat':
    return 'Overheat'
  return status.capitalize()


def parse_output_for_ev(telnet):
  """Parses console output until 'OK' appears for 'event' command.

  Args:
    telnet: The telnet connection to emulator.

  Returns:
    parsed_output: The parsed console output.
  """
  parsed_output = telnet.read_until('\n%s' % OK).strip()
  return parsed_output


def get_events_code_ev_key():
  """Gets event codes from a static file.

  Returns:
    A string value: The event codes getting from a static file.
  """
  with open(EVENTS_CODE_EV_KEY_FILENAME) as f:
    lines = f.readlines()
  events_code_ev_key = ''
  for line in lines:
    events_code_ev_key += ('\r\n    %s' % line.strip())
  return '%s\r\n%s' % (events_code_ev_key.strip(), OK)


def read_string_from_file(filename):
  """Reads strings written in the file by appending each line.

  Args:
    filename: The file name to read strings from.

  Returns:
    stringRead: A single string value containing each line in the file.
  """
  with open(filename) as f:
    lines = f.readlines()
  string_read = ''
  for line in lines:
    string_read += line
  return string_read


def remove_all_spaces(string):
  """Removes all the trailing spaces and spaces within the string.

  Args:
    string: A string to remove training spaces.

  Returns:
    A string value: A parsed string after removing all trailing spaces.
  """
  return re.sub(r'[\s+]', '', string.strip(' \t\n\r'))


def execute_console_command(telnet, command, expected_output):
  """Executes emulator console command.

  Executes emulator console command through telnet connection,
  compare command output and expected command output.

  Args:
    telnet: The telnet connection to emulator.
    command: The console command to execute.
    expected_output: The expected output for the executed command.

  Returns:
    is_command_successful: It indicates command executed successfully or not.
    output: The command output in the terminal.
  """
  is_command_successful = False

  for i in range(NUM_MAX_TRIALS):
    print 'execute console command: %s, trial #%d' % (command.strip(), i)

    telnet.write(command)
    time.sleep(CMD_WAIT_TIMEOUT_S)

    if command == 'crash\n':
      output = telnet.read_all()
    elif command == CMD_ROTATE: # No 'OK' output showing, only new line.
      print 'command is rotate'
      output = telnet.read_until('\n', 10)
      print 'output = "%s"' % output
    elif command == CMD_EMPTY_AUTH_TOKEN:
      output = telnet.read_until('missing authentication token').strip()
    elif command == CMD_RANDOM_AUTH_TOKEN:
      output = telnet.read_until('emulator_console_auth_token').strip()
    else:
      output = parse_output(telnet)

    is_command_successful = pattern_match_output(output, expected_output)

    if is_command_successful:
      break

    time.sleep(TRIAL_WAIT_TIMEOUT_S)

  return is_command_successful, output


def get_auth_token():
  """Gets auth token value from auth token file.

  Returns:
    auth_token: The value of auth token.
  """
  with open(TOKEN_PATH) as f:
    content = f.readlines()
  auth_token = content[0]
  return auth_token


def telnet_emulator():
  """Only telnet to emulator, initially not need to run auth command."""
  telnet = telnetlib.Telnet(SERVER_NAME, CONSOLE_PORT)
  if not check_read_until(telnet.read_until(OK, TIMEOUT_S)):
    sys.exit(-1)

  return telnet


def wait_on_windows():
  """Waits for few seconds on Windows machine."""
  if os.name == WINDOWS_OS_NAME:
    time.sleep(0.5)


def exit_emulator_console(telnet):
  """Exits from emulator console."""
  telnet.write(CMD_EXIT)
  wait_on_windows()
  telnet.close()


def run_script_run_adb_shell(testcase_call_dir):
  """Run Python script to install apk.

  Run Python script to install Rest Service app and corresponding test on
  Emulator; on emulator, do a port forwarding from tcp:8080 to tcp:8081.

  Args:
    testcase_call_dir: The directory where the test case is called from.
  """
  script_run_adb_shell = ('%s/%s' %
                          (testcase_call_dir, SCRIPT_TO_RUN_ADB_SHELL))
  script_install_apk = '%s/%s' % (testcase_call_dir, SCRIPT_TO_INSTALL_APK)

  subprocess.call(['adb', '-s', 'emulator-%s' % str(CONSOLE_PORT),
                   '-e', 'forward', 'tcp:8080', 'tcp:8081'])
  subprocess.call([PYTHON_INTERPRETER, script_install_apk])
  subprocess.Popen([PYTHON_INTERPRETER, script_run_adb_shell])
  time.sleep(SETUP_WAIT_TIMEOUT_S)

def unstall_apps(testcase_call_dir):
  """Run Python script to uninstall apps.

  Args:
    testcase_call_dir: The directory where the test case is called from.
  """
  subprocess.Popen([PYTHON_INTERPRETER,
                    '%s/%s' % (testcase_call_dir, SCRIPT_TO_UNINSTALL_APP)])
  time.sleep(SETUP_WAIT_TIMEOUT_S)