blob: dd1654a0294bb42e80a8328d8a4cfb050c86c072 [file] [log] [blame]
#!/usr/bin/python
# Copyright 2012 Google Inc. All Rights Reserved.
"""This Class writes test progress/error/result to files.
This file defines the logging function of the automation test. It
logs test progress, results, error/warning to different files:
results.txt: this is the file to log the test output
error.txt: all test errors are logged into this file
prompt.txt: a copy of terminal output, which hints the progress
of the current test.
"""
__author__ = 'Lehan Meng (lmeng@google.com)'
import datetime
import errno
import os
class Logging(object):
"""This Class collects and writes test information to log files."""
def __init__(self, **kwargs):
"""initiate the logging instance.
Args:
kwargs['f_result']: file name for test result
kwargs['f_error']: file name for test errors
kwargs['f_progres']: file name for test progres
kwargs['std_out']: by default, send a copy of the log info to stdout
"""
self.params = {'std_out': '1',
'f_result': 'result.log',
'f_error': 'error.log',
'f_progress': 'progress.log',
'delimiter': '\t',
'out_folder': 'log',
'in_folder': 'data'}
for s in kwargs:
self.params[s] = kwargs[s]
try:
os.makedirs(self.params['out_folder'])
except OSError, e:
if e.errno != errno.EEXIST:
raise
now = datetime.datetime.now()
s_time = now.strftime('%Y-%m-%d_%H:%M:%S.%f')
for f_name in ['f_result', 'f_error', 'f_progress']:
name = self.ParseLogFileName(self.params[f_name], 'w', s_time)
if name:
self.params[f_name] = name
else:
print 'Error! Fail to create log File.'
self.rst_file = open(self.params['f_result'], 'w+')
self.err_file = open(self.params['f_error'], 'w+')
self.prg_file = open(self.params['f_progress'], 'w+')
self.NewTestStart()
def CreateFile(self, f_name, access='r'):
"""Create a file for read/write.
Args:
f_name: the file name that needs to be created
access: 'r': read, input file
'w': write, output file
'rw': read and write
Returns:
f_obj: return the file object
if not succeed, return False
"""
f_obj = None
if access == 'r':
# for input file
try:
f_obj = open(f_name, 'r')
except IOError:
print 'Cannot open the input file, return'
return False
elif access == 'w':
# for input file
try:
os.makedirs(self.params['out_folder'])
except OSError, e:
if e.errno != errno.EEXIST:
print 'Cannot create folder! Return'
return False
full_path = self.ParseLogFileName(f_name, access)
if full_path:
try:
f_obj = open(full_path, 'w+')
except IOError:
print 'Cannot open the given file, return'
return False
else:
# Can not parse file name
print 'Cannot parse given file name'
return False
else:
# read-write file:
try:
f_obj = open(f_name, 'r')
except IOError:
print 'Cannot open the input file, return'
return False
return f_obj
def ParseLogFileName(self, f_name, access='r', time_stamp=None):
"""Generate an uniq log file name for each test case instance.
Args:
f_name: file name
access: 'r': read mode
'w': write mode
'rw': read-write
time_stamp: the time tag used for file name
if None, create a new tag using current time
Returns:
return the parsed file name
"""
if not f_name:
f_name = 'logFile.log'
if not time_stamp:
now = datetime.datetime.now()
s_time = now.strftime('%Y-%m-%d_%H:%M:%S.%f')
else:
s_time = time_stamp
ls = f_name.split('.')
ext_name = ''
name = ''
if len(ls) == 1:
name = ls[0]
else:
ext_name = ls.pop(-1)
for s in ls:
name += (s+'.')
name = name.rstrip('.')
if not ext_name:
ext_name = 'log'
folder = None
if access == 'r':
folder = self.params['in_folder']
elif access == 'w':
folder = self.params['out_folder']
else:
folder = self.params['in_folder']
name = (folder + '/' + name + '_testID-' + self.params['testID']
+ '_'+ s_time + '.' + ext_name)
return name
def SendLineToResult(self, test_info, result_info):
"""Send test result (one-line) information to the result file.
Args:
test_info: test case related info: testID, start_time, key_word, etc
result_info: test results {Pass_Fail: pass, note: Extra_Information}
Returns:
return the status of file write operation
"""
now = datetime.datetime.now()
if test_info is not None:
line = (now.strftime('%Y-%m-%d %H:%M:%S.%f') + self.params['delimiter']
+ 'testID:' + test_info['testID']
+ self.params['delimiter'] + 'TestStartAt:'
+ test_info['start_time']
+ self.params['delimiter'] + 'Keyword:' + test_info['key_word']
+ self.params['delimiter'] + result_info['Pass_Fail']
+ self.params['delimiter'] + result_info['note'] + '\n')
else:
line = ('Result log information should have testInfo available! '
+ self.params['delimiter'] + 'No logging performed')
if self.params['std_out'] > 0:
print line
self.rst_file.write(line)
self.rst_file.flush()
def NewTestStart(self):
"""Mark the start of a new test in the file."""
self.rst_file.write(
'################### NEW TEST STARTED ###################\n')
self.err_file.write(
'################### NEW TEST STARTED ###################\n')
self.prg_file.write(
'################### NEW TEST STARTED ###################\n')
def SendLineToError(self, test_info, error_info):
"""Send test error (one-line) information to the error file.
Args:
test_info: test case related info: testID, start_time, key_word, etc
error_info: test errors, severity: critical/intermediate/low, and info
Returns:
returns the status of file write operation
"""
now = datetime.datetime.now()
if test_info is not None:
line = (now.strftime('%Y-%m-%d %H:%M:%S.%f') + self.params['delimiter']
+ 'testID:' + test_info['testID'] + self.params['delimiter']
+ 'TestStartAt:' + test_info['start_time']
+ self.params['delimiter'] + 'Keyword:'
+ test_info['key_word'] + self.params['delimiter']
+ error_info['severity'] + self.params['delimiter']
+ error_info['note'] + '\n')
else:
line = (now.strftime('%Y-%m-%d %H:%M:%S.%f') + self.params['delimiter'] +
error_info['severity'] + self.params['delimiter']
+ error_info['note'] + '\n')
if self.params['std_out'] > 0:
print line
self.err_file.write(line)
self.err_file.flush()
def SendLineToProgress(self, test_info, progress_info):
"""Send test progress (one-line) information to the progress file.
Args:
test_info: test case related info: testID, start_time, key_word, etc
progress_info: test progress indication
{percent: [0-100]%, note: Information}
Returns:
returns the status of file write operation
"""
now = datetime.datetime.now()
if test_info is not None:
line = (now.strftime('%Y-%m-%d %H:%M:%S.%f') + self.params['delimiter']
+ 'testID:' + test_info['testID'] + self.params['delimiter']
+ 'TestStartAt:'+ test_info['start_time']
+ self.params['delimiter'] + 'Keyword:' + test_info['key_word']
+ self.params['delimiter'] + progress_info['percent']
+ self.params['delimiter'] + progress_info['note'] + '\n')
else:
line = (now.strftime('%Y-%m-%d %H:%M:%S.%f') + self.params['delimiter']
+ progress_info['percent'] + self.params['delimiter']
+ progress_info['note'] + '\n')
if self.params['std_out'] > 0:
print line
self.prg_file.write(line)
self.prg_file.flush()
def SendLine(self, test_info, info):
"""Send test (one-line) information to the corresponding log file.
Args:
test_info: test case related info: testID, start_time, key_word, etc
info: test results/error/progress information (single line)
test_info could be "None" for class other than TestCase
Returns:
return the status of file write operation
"""
if info['type'] == 'result':
return self.SendLineToResult(test_info, info)
elif info['type'] == 'error':
return self.SendLineToError(test_info, info)
elif info['type'] == 'progress':
return self.SendLineToProgress(test_info, info)
def SendTestData(self, data_list):
"""Send test data to result file."""
for line in data_list:
self.rst_file.write(line + '\n')
self.err_file.flush()
def SendLines(self, test_info, info):
"""Send test output (multiple lines) to the corresponding log file.
Args:
test_info: test case related info: testID, start_time, key_word, etc
info: test results/error/progress information
test_info could be "None" for class other than TestCase
Returns:
return 1 when succeed
"""
if info['type'] == 'result':
for line in info['note'].split('\n'):
if line == info['note'].split('\n')[0]:
dup_info = info.copy()
dup_info['note'] = line
self.SendLineToResult(test_info, dup_info)
else:
self.rst_file.write(line + '\n')
if self.params['std_out']: print line
self.rst_file.flush()
elif info['type'] == 'error':
for line in info['note'].split('\n'):
if line == info['note'].split('\n')[0]:
dup_info = info.copy()
dup_info['note'] = line
self.SendLineToError(test_info, dup_info)
else:
self.err_file.write(line + '\n')
if self.params['std_out']: print line
self.err_file.flush()
elif info['type'] == 'progress':
for line in info['note'].split('\n'):
if line == info['note'].split('\n')[0]:
dup_info = info.copy()
dup_info['note'] = line
self.SendLineToProgress(test_info, dup_info)
else:
self.prg_file.write(line + '\n')
if self.params['std_out']: print line
self.prg_file.flush()
return 1
def CreateResultInfo(self, status='Pass', msg=''):
"""Create the result Info structure for logging.
Args:
status: has value 'Pass' or 'Fail'
msg: test results information line(s)
Returns:
returns the infomation structure that should be logged to file
"""
d = {}
d.setdefault('type', 'result')
d.setdefault('Pass_Fail', status)
d.setdefault('note', msg)
return d
def CreateErrorInfo(self, severity='intermediate', msg=''):
"""Create the error Info structure for logging.
Args:
severity: has value 'low', 'intermediate' or 'critical'
msg: test error information line(s)
Returns:
returns the infomation structure that should be logged to file
"""
d = {}
d.setdefault('type', 'error')
d.setdefault('severity', severity)
d.setdefault('note', msg)
return d
def CreateProgressInfo(self, percent='0%', msg=''):
"""Create the progress Info structure for logging.
Args:
percent: completeness of test progress, in %
msg: test progress information line(s)
Returns:
returns the infomation structure that should be logged to file
"""
d = {}
d.setdefault('percent', percent)
d.setdefault('type', 'progress')
d.setdefault('note', msg)
return d
def __del__(self):
"""Close the log files."""
self.rst_file.close()
self.err_file.close()
self.prg_file.close()