diff options
Diffstat (limited to 'media')
-rw-r--r-- | media/tools/layout_tests/anno/media.csv (renamed from media/tools/layout_tests/anno/anno.csv) | 0 | ||||
-rw-r--r-- | media/tools/layout_tests/layouttest_analyzer.py | 357 | ||||
-rw-r--r-- | media/tools/layout_tests/layouttest_analyzer_helpers.py | 22 | ||||
-rw-r--r-- | media/tools/layout_tests/layouttest_analyzer_helpers_unittest.py | 20 | ||||
-rw-r--r-- | media/tools/layout_tests/layouttest_analyzer_runner.py | 153 | ||||
-rw-r--r-- | media/tools/layout_tests/runner_config/runner_config.csv | 46 | ||||
-rw-r--r-- | media/tools/layout_tests/trend_graph.py | 23 |
7 files changed, 504 insertions, 117 deletions
diff --git a/media/tools/layout_tests/anno/anno.csv b/media/tools/layout_tests/anno/media.csv index 3447857..3447857 100644 --- a/media/tools/layout_tests/anno/anno.csv +++ b/media/tools/layout_tests/anno/media.csv diff --git a/media/tools/layout_tests/layouttest_analyzer.py b/media/tools/layout_tests/layouttest_analyzer.py index d9171c5..2c97e02 100644 --- a/media/tools/layout_tests/layouttest_analyzer.py +++ b/media/tools/layout_tests/layouttest_analyzer.py @@ -28,7 +28,7 @@ CURRENT_RESULT_FILE_FOR_DEBUG = os.path.join(DEFAULT_RESULT_DIR, PREV_TIME_FOR_DEBUG = '2011-09-11-18' -def parse_option(): +def ParseOption(): """Parse command-line options using OptionParser. Returns: @@ -38,27 +38,27 @@ def parse_option(): option_parser.add_option('-r', '--receiver-email-address', dest='receiver_email_address', - help=('receiver\'s email adddress (defaults to ' - '%default'), - default='imasaki@chromium.org') + help=('receiver\'s email address. ' + 'Result email is not sent if this is not ' + 'specified.')) option_parser.add_option('-g', '--debug-mode', dest='debug', help=('Debug mode is used when you want to debug ' 'the analyzer by using local file rather ' 'than getting data from SVN. This shortens ' - 'the debugging time (off by default)'), + 'the debugging time (off by default).'), action='store_true', default=False) option_parser.add_option('-t', '--trend-graph-location', dest='trend_graph_location', help=('Location of the bug trend file; ' 'file is expected to be in Google ' 'Visualization API trend-line format ' - '(defaults to %default)'), + '(defaults to %default).'), default=DEFAULT_GRAPH_FILE) option_parser.add_option('-a', '--bug-anno-file-location', dest='bug_annotation_file_location', help=('Location of the bug annotation file; ' 'file is expected to be in CSV format ' - '(default to %default)'), + '(default to %default).'), default=DEFAULT_ANNO_FILE) option_parser.add_option('-n', '--test-group-file-location', dest='test_group_file_location', @@ -77,14 +77,14 @@ def parse_option(): option_parser.add_option('-d', '--result-directory-location', dest='result_directory_location', help=('Name of result directory location ' - '(default to %default)'), + '(default to %default).'), default=DEFAULT_RESULT_DIR) option_parser.add_option('-b', '--email-appended-text-file-location', dest='email_appended_text_file_location', help=('File location of the email appended text. ' 'The text is appended in the status email. ' '(default to %default and no text is ' - 'appended in that case.)'), + 'appended in that case).'), default=None) option_parser.add_option('-c', '--email-only-change-mode', dest='email_only_change_mode', @@ -93,24 +93,45 @@ def parse_option(): 'analyzer result compared to the previous ' 'result (off by default)'), action='store_true', default=False) + option_parser.add_option('-q', '--dashboard-file-location', + dest='dashboard_file_location', + help=('Location of dashboard file. The results are ' + 'not reported to the dashboard if this ' + 'option is not specified.')) return option_parser.parse_args()[0] -def main(): - """A main function for the analyzer.""" - options = parse_option() - start_time = datetime.now() - # Do the main analysis. - if not options.debug: - if not options.test_group_file_location and not options.test_group_name: +def GetCurrentAndPreviousResults(debug, test_group_file_location, + test_group_name, result_directory_location): + """Get current and the latest previous analyzer results. + + In debug mode, they are read from predefined files. In non-debug mode, + current analyzer results are dynamically obtained from Webkit SVN and + the latest previous result is read from the corresponding file. + + Args: + debug: please refer to |options|. + test_group_file_location: please refer to |options|. + test_group_name: please refer to |options|. + result_directory_location: please refer to |options|. + + Returns: + a tuple of the following: + prev_time: the previous time string that is compared against. + prev_analyzer_result_map: previous analyzer result map. Please refer to + layouttest_analyzer_helpers.AnalyzerResultMap. + analyzer_result_map: current analyzer result map. Please refer to + layouttest_analyzer_helpers.AnalyzerResultMap. + """ + if not debug: + if not test_group_file_location and not test_group_name: print ('Either --test-group-name or --test_group_file_location must be ' 'specified. Exiting this program.') sys.exit() filter_names = [] - if options.test_group_file_location and ( - os.path.exists(options.test_group_file_location)): + if test_group_file_location and os.path.exists(test_group_file_location): filter_names = LayoutTests.GetLayoutTestNamesFromCSV( - options.test_group_file_location) + test_group_file_location) parent_location_list = LayoutTests.GetParentDirectoryList(filter_names) recursion = False else: @@ -120,7 +141,7 @@ def main(): # http://svn.webkit.org/repository/webkit/trunk/LayoutTests/media # Filtering is not set so all HTML files are considered as valid tests. # Also, we look for the tests recursively. - if not os.path.exists(options.test_group_file_location): + if not os.path.exists(test_group_file_location): print ('Warning: CSV file (%s) does not exist. So it is ignored and ' '%s is used for obtaining test names') % ( options.test_group_file_location, options.test_group_name) @@ -135,9 +156,13 @@ def main(): filter_names=filter_names) analyzer_result_map = layouttest_analyzer_helpers.AnalyzerResultMap( layouttests.JoinWithTestExpectation(TestExpectations())) - (prev_time, prev_analyzer_result_map) = ( - layouttest_analyzer_helpers.FindLatestResult( - options.result_directory_location)) + result = layouttest_analyzer_helpers.FindLatestResult( + result_directory_location) + if result: + (prev_time, prev_analyzer_result_map) = result + else: + prev_time = None + prev_analyzer_result_map = None else: analyzer_result_map = layouttest_analyzer_helpers.AnalyzerResultMap.Load( CURRENT_RESULT_FILE_FOR_DEBUG) @@ -145,12 +170,25 @@ def main(): prev_analyzer_result_map = ( layouttest_analyzer_helpers.AnalyzerResultMap.Load( os.path.join(DEFAULT_RESULT_DIR, prev_time))) + return (prev_time, prev_analyzer_result_map, analyzer_result_map) + - # Read bug annotations and generate an annotation map used for the status - # email. +def ReadEmailInformation(bug_annotation_file_location, + email_appended_text_file_location): + """Read bug annotations and generate an annotation map used for email. + + Args: + bug_annotation_file_location: please refer to |options|. + email_appended_text_file_location: please refer to |options|. + + Returns: + a tuple of the following: + anno_map: a dictionary that maps bug names to their annotations. + appended_text_to_email: the text string to append to the status email. + """ anno_map = {} try: - file_object = open(options.bug_annotation_file_location) + file_object = open(bug_annotation_file_location) except IOError: print 'cannot open annotation file %s. Skipping.' % ( options.bug_annotation_file_location) @@ -161,92 +199,211 @@ def main(): file_object.close() appended_text_to_email = '' - if options.email_appended_text_file_location: + if email_appended_text_file_location: try: - file_object = open(options.email_appended_text_file_location) + file_object = open(email_appended_text_file_location) except IOError: print 'cannot open email appended text file %s. Skipping.' % ( - options.email_appended_text_file_location) + email_appended_text_file_location) else: appended_text_to_email = ''.join(file_object.readlines()) file_object.close() + return (anno_map, appended_text_to_email) + - diff_map = analyzer_result_map.CompareToOtherResultMap( - prev_analyzer_result_map) - result_change = (any(diff_map['whole']) or any(diff_map['skip']) or - any(diff_map['nonskip'])) - # Email only when |email_only_change_mode| is False or there - # is a change in the result compared to the last result. - simple_rev_str = '' - if not options.email_only_change_mode or result_change: - prev_time_in_float = datetime.strptime(prev_time, '%Y-%m-%d-%H') - prev_time_in_float = time.mktime(prev_time_in_float.timetuple()) - if options.debug: - cur_time_in_float = datetime.strptime(CUR_TIME_FOR_DEBUG, '%Y-%m-%d-%H') - cur_time_in_float = time.mktime(cur_time_in_float.timetuple()) +def SendEmail(prev_time, prev_analyzer_result_map, analyzer_result_map, + anno_map, appended_text_to_email, email_only_change_mode, debug, + receiver_email_address, test_group_name): + """Send result status email. + + Args: + prev_time: the previous time string that is compared against. + prev_analyzer_result_map: previous analyzer result map. Please refer to + layouttest_analyzer_helpers.AnalyzerResultMap. + analyzer_result_map: current analyzer result map. Please refer to + layouttest_analyzer_helpers.AnalyzerResultMap. + anno_map: a dictionary that maps bug names to their annotations. + appended_text_to_email: the text string to append to the status email. + email_only_change_mode: please refer to |options|. + debug: please refer to |options|. + receiver_email_address: please refer to |options|. + test_group_name: please refer to |options|. + + Returns: + a tuple of the following: + result_change: a boolean indicating whether there is a change in the + result compared with the latest past result. + diff_map: please refer to + layouttest_analyzer_helpers.SendStatusEmail(). + simple_rev_str: a simple version of revision string that is sent in + the email. + """ + if prev_analyzer_result_map: + diff_map = analyzer_result_map.CompareToOtherResultMap( + prev_analyzer_result_map) + result_change = (any(diff_map['whole']) or any(diff_map['skip']) or + any(diff_map['nonskip'])) + # Email only when |email_only_change_mode| is False or there + # is a change in the result compared to the last result. + simple_rev_str = '' + if not email_only_change_mode or result_change: + prev_time_in_float = datetime.strptime(prev_time, '%Y-%m-%d-%H') + prev_time_in_float = time.mktime(prev_time_in_float.timetuple()) + if debug: + cur_time_in_float = datetime.strptime(CUR_TIME_FOR_DEBUG, + '%Y-%m-%d-%H') + cur_time_in_float = time.mktime(cur_time_in_float.timetuple()) + else: + cur_time_in_float = time.time() + (rev_str, simple_rev_str) = ( + layouttest_analyzer_helpers.GetRevisionString(prev_time_in_float, + cur_time_in_float, + diff_map)) + if receiver_email_address: + layouttest_analyzer_helpers.SendStatusEmail( + prev_time, analyzer_result_map, diff_map, anno_map, + receiver_email_address, test_group_name, + appended_text_to_email, rev_str) + if simple_rev_str: + simple_rev_str = '\'' + simple_rev_str + '\'' else: - cur_time_in_float = time.time() - (rev_str, simple_rev_str) = ( - layouttest_analyzer_helpers.GetRevisionString(prev_time_in_float, - cur_time_in_float, - diff_map)) - layouttest_analyzer_helpers.SendStatusEmail( - prev_time, analyzer_result_map, diff_map, anno_map, - options.receiver_email_address, options.test_group_name, - appended_text_to_email, rev_str) - if simple_rev_str: - simple_rev_str = '\'' + simple_rev_str + '\'' + simple_rev_str = 'undefined' # GViz uses undefined for NONE. else: - simple_rev_str = 'undefined' # GViz uses undefined for NONE. - if not options.debug: - # Save the current result. + # Initial result should be written to tread-graph if there are no previous + # results. + result_change = True + diff_map = None + simple_rev_str = 'undefined' + return (result_change, diff_map, simple_rev_str) + + +def UpdateTrendGraph(start_time, analyzer_result_map, diff_map, simple_rev_str, + trend_graph_location): + """Update trend graph in GViz. + + Annotate the graph with revision information. + + Args: + start_time: the script starting time as a float value. + analyzer_result_map: current analyzer result map. Please refer to + layouttest_analyzer_helpers.AnalyzerResultMap. + diff_map: a map that has 'whole', 'skip' and 'nonskip' as keys. + Please refer to |diff_map| in + |layouttest_analyzer_helpers.SendStatusEmail()|. + simple_rev_str: a simple version of revision string that is sent in + the email. + trend_graph_location: the location of the trend graph that needs to be + updated. + + Returns: + a dictionary that maps result data category ('whole', 'skip', 'nonskip', + 'passingrate') to information tuple (the number of the tests, + annotation, simple_rev_string) of the given result + data category. These tuples are used for trend graph update. + """ + # Trend graph update (if specified in the command-line argument) when + # there is change from the last result. + # Currently, there are two graphs (graph1 is for 'whole', 'skip', + # 'nonskip' and the graph2 is for 'passingrate'). Please refer to + # graph/graph.html. + # Sample JS annotation for graph1: + # [new Date(2011,8,12,10,41,32),224,undefined,'',52,undefined, + # undefined, 12, 'test1,','<a href="http://t</a>,',], + # This example lists 'whole' triple and 'skip' triple and + # 'nonskip' triple. Each triple is (the number of tests that belong to + # the test group, linked text, a link). The following code generates this + # automatically based on rev_string etc. + trend_graph = TrendGraph(trend_graph_location) + datetime_string = start_time.strftime('%Y,%m,%d,%H,%M,%S') + data_map = {} + passingrate_anno = '' + for test_group in ['whole', 'skip', 'nonskip']: + anno = 'undefined' + tests = analyzer_result_map.result_map[test_group].keys() + test_str = '' + links = '' + if diff_map and diff_map[test_group]: + for i in [0, 1]: + for (name, _) in diff_map[test_group][i]: + test_str += name + ',' + # This is link to test HTML in WebKit SVN. + links += ('<a href="http://trac.webkit.org/browser/trunk/' + 'LayoutTests/%s">%s</a>,') % (name, name) + if test_str: + anno = '\'' + test_str + '\'' + # The annotation of passing rate is a union of all annotations. + passingrate_anno += anno + if links: + links = '\'' + links + '\'' + else: + links = 'undefined' + if test_group is 'whole': + data_map[test_group] = (str(len(tests)), anno, links) + else: + data_map[test_group] = (str(len(tests)), anno, simple_rev_str) + if not passingrate_anno: + passingrate_anno = 'undefined' + data_map['passingrate'] = ( + str(analyzer_result_map.GetPassingRate()), passingrate_anno, + simple_rev_str) + trend_graph.Update(datetime_string, data_map) + return data_map + + +def UpdateDashboard(dashboard_file_location, test_group_name, data_map): + """Update dashboard HTML file. + + Args: + dashboard_file_location: the file location for the dashboard file. + test_group_name: please refer to |options|. + data_map: a dictionary that maps result data category + ('whole', 'skip', 'nonskip', 'passingrate') to information tuple (the + number of the tests, annotation, simple_rev_string) of the given result + data category. + """ + new_str = ('<td><a href="%s">%s</a><td>%s</td><td>%s</td><td>%s</td>' + '<td>%s%%</td><tr>\n') % ( + # Dashboard file and graph must be in the same directory + # to make the following link work. + test_group_name.replace('/', '_') + '.html', + test_group_name, data_map['whole'][0], + data_map['skip'][0], data_map['nonskip'][0], + data_map['passingrate'][0]) + layouttest_analyzer_helpers.ReplaceLineInFile( + dashboard_file_location, test_group_name, new_str) + + +def main(): + """A main function for the analyzer.""" + options = ParseOption() + start_time = datetime.now() + + (prev_time, prev_analyzer_result_map, analyzer_result_map) = ( + GetCurrentAndPreviousResults(options.debug, + options.test_group_file_location, + options.test_group_name, + options.result_directory_location)) + (anno_map, appended_text_to_email) = ReadEmailInformation( + options.bug_annotation_file_location, + options.email_appended_text_file_location) + (result_change, diff_map, simple_rev_str) = ( + SendEmail(prev_time, prev_analyzer_result_map, analyzer_result_map, + anno_map, appended_text_to_email, + options.email_only_change_mode, options.debug, + options.receiver_email_address, options.test_group_name)) + if not options.debug and (result_change or not prev_analyzer_result_map): + # Save the current result when result is changed or the script is + # executed for the first time. date = start_time.strftime('%Y-%m-%d-%H') file_path = os.path.join(options.result_directory_location, date) analyzer_result_map.Save(file_path) - - if result_change: - # Trend graph update (if specified in the command-line argument) when - # there is change from the last result. - # Currently, there are two graphs (graph1 is for 'whole', 'skip', - # 'nonskip' and the graph2 is for 'passingrate'). Please refer to - # graph/graph.html. - # Sample JS annotation for graph1: - # [new Date(2011,8,12,10,41,32),224,undefined,'',52,undefined,undefined, - # 12, 'test1,','<a href="http://t</a>,',], - # This example lists 'whole' triple and 'skip' triple and - # 'nonskip' triple. Each triple is (the number of tests that belong to - # the test group, linked text, a link). The following code generates this - # automatically based on rev_string etc. - trend_graph = TrendGraph(options.trend_graph_location) - datetime_string = start_time.strftime('%Y,%m,%d,%H,%M,%S') - data_map = {} - passingrate_anno = '' - for test_group in ['whole', 'skip', 'nonskip']: - anno = 'undefined' - tests = analyzer_result_map.result_map[test_group].keys() - if diff_map[test_group]: - test_str = '' - links = '' - for i in [0, 1]: - for (name, _) in diff_map[test_group][i]: - test_str += name + ',' - # This is link to test HTML in WebKit SVN. - links += ('<a href="http://trac.webkit.org/browser/trunk/' - 'LayoutTests/%s">%s</a>,') % (name, name) - if test_str: - anno = '\'' + test_str + '\'' - # The annotation of passing rate is a union of all annotations. - passingrate_anno += anno - if test_group is 'whole': - data_map[test_group] = (str(len(tests)), anno, '\'' + links + '\'') - else: - data_map[test_group] = (str(len(tests)), anno, simple_rev_str) - if not passingrate_anno: - passingrate_anno = 'undefined' - data_map['passingrate'] = ( - str(analyzer_result_map.GetPassingRate()), passingrate_anno, - simple_rev_str) - trend_graph.Update(datetime_string, data_map) + if result_change or not prev_analyzer_result_map: + data_map = UpdateTrendGraph(start_time, analyzer_result_map, diff_map, + simple_rev_str, options.trend_graph_location) + # Report the result to dashboard. + if options.dashboard_file_location: + UpdateDashboard(options.dashboard_file_location, options.test_group_name, + data_map) if '__main__' == __name__: diff --git a/media/tools/layout_tests/layouttest_analyzer_helpers.py b/media/tools/layout_tests/layouttest_analyzer_helpers.py index 3b30312e..c1d628c 100644 --- a/media/tools/layout_tests/layouttest_analyzer_helpers.py +++ b/media/tools/layout_tests/layouttest_analyzer_helpers.py @@ -8,10 +8,12 @@ from datetime import datetime from email.mime.multipart import MIMEMultipart from email.mime.text import MIMEText +import fileinput import os import pickle import smtplib import socket +import sys import time import urllib @@ -414,6 +416,20 @@ def FindLatestTime(time_list): return None +def ReplaceLineInFile(file_path, search_exp, replace_line): + """Replace line which has |search_exp| with |replace_line| within a file. + + Args: + file_path: the file that is being replaced. + search_exp: search expression to find a line to be replaced. + replace_line: the new line. + """ + for line in fileinput.input(file_path, inplace=1): + if search_exp in line: + line = replace_line + sys.stdout.write(line) + + def FindLatestResult(result_dir): """Find the latest result in |result_dir| and read and return them. @@ -424,10 +440,14 @@ def FindLatestResult(result_dir): result_dir: the result directory. Returns: - a tuple of filename (latest_time) of the and the latest analyzer result. + A tuple of filename (latest_time) and the latest analyzer result. + Returns None if there is no file or no file that matches the file + patterns used ('%Y-%m-%d-%H'). """ dir_list = os.listdir(result_dir) file_name = FindLatestTime(dir_list) + if not file_name: + return None file_path = os.path.join(result_dir, file_name) return (file_name, AnalyzerResultMap.Load(file_path)) diff --git a/media/tools/layout_tests/layouttest_analyzer_helpers_unittest.py b/media/tools/layout_tests/layouttest_analyzer_helpers_unittest.py index da60896..b362228 100644 --- a/media/tools/layout_tests/layouttest_analyzer_helpers_unittest.py +++ b/media/tools/layout_tests/layouttest_analyzer_helpers_unittest.py @@ -160,6 +160,26 @@ class TestLayoutTestAnalyzerHelpers(unittest.TestCase): self.RunTestGetRevisionString('2011-09-01-00', '2011-09-02-00', '', '', 'foo1.html') + def testReplaceLineInFile(self): + file_path = os.path.join('test_data', 'inplace.txt') + f = open(file_path, 'w') + f.write('Hello') + f.close() + layouttest_analyzer_helpers.ReplaceLineInFile( + file_path, 'Hello', 'Goodbye') + f = open(file_path, 'r') + self.assertEquals(f.readline(), 'Goodbye') + f.close() + layouttest_analyzer_helpers.ReplaceLineInFile( + file_path, 'Bye', 'Hello') + f = open(file_path, 'r') + self.assertEquals(f.readline(), 'Goodbye') + f.close() + + def testFindLatestResultWithNoData(self): + self.assertFalse( + layouttest_analyzer_helpers.FindLatestResult('test_data')) + if __name__ == '__main__': unittest.main() diff --git a/media/tools/layout_tests/layouttest_analyzer_runner.py b/media/tools/layout_tests/layouttest_analyzer_runner.py new file mode 100644 index 0000000..dacac1a --- /dev/null +++ b/media/tools/layout_tests/layouttest_analyzer_runner.py @@ -0,0 +1,153 @@ +#!/usr/bin/python +# Copyright (c) 2011 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +"""Main function to run the layout test analyzer. + +The purpose of this script is to run the layout test analyzer for various +teams based on the run configuration file in CSV format. The CSV file is based +on https://sites.google.com/a/chromium.org/dev/developers/testing/ +webkit-layout-tests/layout-test-stats-1. +""" + +import csv +import optparse +import os +import shutil +from subprocess import Popen +import sys + +DEFAULT_RUNNER_CONFIG_FILE = os.path.join('runner_config', + 'runner_config.csv') + +# Predefined result/graph directory. +DEFAULT_RESULT_DIR = 'result' +DEFAULT_GRAPH_DIR = 'graph' +DEFAULT_ANNO_DIR = 'anno' + + +def ParseOption(): + """Parse command-line options using OptionParser. + + Returns: + an object containing all command-line option information. + """ + option_parser = optparse.OptionParser() + + option_parser.add_option('-c', '--runner-config-file-location', + dest='runner_config_file_location', + help=('Location of the bug annotation file; ' + 'file is expected to be in CSV format ' + '(default to %default)'), + default=DEFAULT_RUNNER_CONFIG_FILE) + option_parser.add_option('-x', '--test-group-name', + dest='test_group_name', + help='A name of test group.') + option_parser.add_option('-d', '--result-directory-location', + dest='result_directory_location', + help=('Name of result directory location ' + '(default to %default)'), + default=DEFAULT_RESULT_DIR) + option_parser.add_option('-p', '--graph-directory-location', + dest='graph_directory_location', + help=('Name of graph directory location ' + '(default to %default)'), + default=DEFAULT_GRAPH_DIR) + option_parser.add_option('-a', '--anno-directory-location', + dest='annotation_directory_location', + help=('Name of annotation directory location; ' + 'each annotation file should be the same ' + 'as test group name with replacement of "/"' + 'with "_" (default to %default)'), + default=DEFAULT_ANNO_DIR) + option_parser.add_option('-b', '--email-appended-text-file-location', + dest='email_appended_text_file_location', + help=('File location of the email appended text. ' + 'The text is appended in the status email. ' + '(default to %default and no text is ' + 'appended in that case.)'), + default=None) + return option_parser.parse_args()[0] + + +def GenerateDashboardHTMLFile(file_name, test_group_list): + """Generate dashboard HTML file. + + Currently, it is simple table that shows all the analyzer results. + + Args: + file_name: the file name of the dashboard. + test_group_list: a list of test group names such as 'media' or 'composite'. + """ + file_object = open(file_name, 'wb') + file_object.write('<table border="1">') + file_object.write('<tr><th>test group</th>') + file_object.write('<th>#Tests</th>') + file_object.write('<th>#Skipped Tests</th>') + file_object.write('<th>#Non-Skipped Failing Tests</th>') + file_object.write('<th>Passing Rate</td></tr>') + for test_group in test_group_list: + file_object.write('<tr>\n') + file_object.write('<td>' + test_group + '</td>\n') + file_object.write('</tr>') + file_object.write('</table>') + file_object.close() + + +def main(): + """A main function for the analyzer runner.""" + options = ParseOption() + run_config_map = {} + try: + file_object = open(options.runner_config_file_location) + except IOError: + print 'cannot open runner configuration file %s. Exiting.' % ( + options.runner_config_file_location) + sys.exit() + data = csv.reader(file_object) + # Skip the first row since it is a comment/header line. + data.next() + for row in data: + run_config_map[row[0]] = (row[1], row[2]) + file_object.close() + if options.test_group_name: + test_group_list = [options.test_group_name] + else: + test_group_list = run_config_map.keys() + dashboard_file_location = os.path.join(options.graph_directory_location, + 'index.html') + if not os.path.exists(dashboard_file_location): + GenerateDashboardHTMLFile(dashboard_file_location, test_group_list) + for test_group in test_group_list: + # Prepare the result if it does not exist. + # The directory name should be changed to avoid collision + # with the file separator. + test_group_name_for_data = test_group.replace('/', '_') + result_dir = os.path.join(options.result_directory_location, + test_group_name_for_data) + if not os.path.exists(result_dir): + os.mkdir(result_dir) + graph_file = os.path.join(options.graph_directory_location, + test_group_name_for_data + '.html') + if not os.path.exists(graph_file): + # Copy the template file. + shutil.copy(os.path.join('graph', 'graph.html'), + graph_file) + os.chmod(graph_file, 0744) + anno_file = os.path.join(options.annotation_directory_location, + test_group_name_for_data + '.csv') + cmd = ('python layouttest_analyzer.py -x %s -n %s -r %s -d %s -t %s' + ' -q %s -a %s -c') % ( + test_group, run_config_map[test_group][0], + run_config_map[test_group][1], result_dir, graph_file, + dashboard_file_location, anno_file) + if options.email_appended_text_file_location: + cmd += ' -b ' + options.email_appended_text_file_location + print 'Running ' + cmd + proc = Popen(cmd, shell=True) + proc.communicate() + + +if '__main__' == __name__: + main() diff --git a/media/tools/layout_tests/runner_config/runner_config.csv b/media/tools/layout_tests/runner_config/runner_config.csv new file mode 100644 index 0000000..5d118c9 --- /dev/null +++ b/media/tools/layout_tests/runner_config/runner_config.csv @@ -0,0 +1,46 @@ +test group name, test name configuration file location, contact person name +animations,, +canvas,, +compositing,, +css2.1,, +css3,, +editing,, +fast/backgrounds,, +fast/borders,, +fast/canvas,, +fast/css,, +fast/dom,, +fast/encoding,, +fast/flexbox,, +fast/forms,, +fast/frames,, +fast/html,, +fast/images,, +fast/js,, +fast/loader,, +fast/multicol,, +fast/overflow,, +fast/parser,, +fast/repaint,, +fast/speech,, +fast/table,, +fast/text,, +fast/transforms,, +fast/xsl,, +fonts,, +http/tests/appcache,, +http/tests/inspector,, +http/tests/misc,, +http/tests/navigation,, +http/tests/websocket,, +inspector,, +jquery,, +loader,, +media,testname/media.csv,imasaki@chromium.org +platform/chromium/compositing,, +platform/chromium/fast,, +plugins,, +scrollbars,, +svg,, +tables,, +transforms,, diff --git a/media/tools/layout_tests/trend_graph.py b/media/tools/layout_tests/trend_graph.py index 8406d19..86f857b 100644 --- a/media/tools/layout_tests/trend_graph.py +++ b/media/tools/layout_tests/trend_graph.py @@ -5,10 +5,10 @@ """A module for manipulating trend graph with analyzer result history.""" -import fileinput import os import sys +import layouttest_analyzer_helpers DEFAULT_TREND_GRAPH_PATH = os.path.join('graph', 'graph.html') @@ -61,7 +61,9 @@ class TrendGraph(object): joined_str) new_line_for_numbers += ' %s\n' % ( LINE_INSERT_POINT_FOR_NUMBERS) - self._ReplaceLine(LINE_INSERT_POINT_FOR_NUMBERS, new_line_for_numbers) + layouttest_analyzer_helpers.ReplaceLineInFile( + self._location, LINE_INSERT_POINT_FOR_NUMBERS, + new_line_for_numbers) joined_str = '%s,%s,%s' % ( data_map['passingrate'][0], data_map['nonskip'][1], @@ -70,17 +72,6 @@ class TrendGraph(object): datetime_string, joined_str) new_line_for_passingrate += ' %s\n' % ( LINE_INSERT_POINT_FOR_PASSING_RATE) - self._ReplaceLine(LINE_INSERT_POINT_FOR_PASSING_RATE, - new_line_for_passingrate) - - def _ReplaceLine(self, search_exp, replace_line): - """Replace line which has |search_exp| with |replace_line|. - - Args: - search_exp: search expression to find a line to be replaced. - replace_line: the new line. - """ - for line in fileinput.input(self._location, inplace=1): - if search_exp in line: - line = replace_line - sys.stdout.write(line) + layouttest_analyzer_helpers.ReplaceLineInFile( + self._location, LINE_INSERT_POINT_FOR_PASSING_RATE, + new_line_for_passingrate) |