blob: 984ee89ccfc449a811bf4ea338cff8d7530843e8 [file] [log] [blame]
"""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.*\n.*help.*\n.*avd.*\n.*auth.*\n'
r'.*quit\|exit.*\n.*\n.*\nOK')
REGEX_HELP_DISPLAY_AUTH = (r'.*\n.*\n.*help.*\n.*event.*\n.*geo.*\n.*gsm.*\n'
r'.*cdma.*\n.*crash.*\n.*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)