Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(270)

Side by Side Diff: third_party/WebKit/Tools/Scripts/print-stale-test-expectations-entries

Issue 2256773004: Add more informtion to the CSV generated (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Ready to land Created 4 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 #!/usr/bin/python 1 #!/usr/bin/python
2 # 2 #
3 # Copyright (C) 2013 Google Inc. All rights reserved. 3 # Copyright (C) 2013 Google Inc. All rights reserved.
4 # 4 #
5 # Redistribution and use in source and binary forms, with or without 5 # Redistribution and use in source and binary forms, with or without
6 # modification, are permitted provided that the following conditions are 6 # modification, are permitted provided that the following conditions are
7 # met: 7 # met:
8 # 8 #
9 # * Redistributions of source code must retain the above copyright 9 # * Redistributions of source code must retain the above copyright
10 # notice, this list of conditions and the following disclaimer. 10 # notice, this list of conditions and the following disclaimer.
(...skipping 12 matching lines...) Expand all
23 # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 30
31 """Prints a list of test expectations for tests whose bugs haven't been modified recently.""" 31 """Prints a list of test expectations for tests whose bugs haven't been modified recently."""
32 32
33 import csv
33 import datetime 34 import datetime
34 import json 35 import json
35 import optparse 36 import optparse
37 import StringIO
36 import sys 38 import sys
37 import urllib2 39 import urllib2
38 40
39 from webkitpy.common.host import Host 41 from webkitpy.common.host import Host
40 from webkitpy.layout_tests.models.test_expectations import TestExpectationParser 42 from webkitpy.layout_tests.models.test_expectations import TestExpectationParser
41 43
42 # FIXME: Make this a direct request to Monorail. 44 # FIXME: Make this a direct request to Monorail.
43 GOOGLE_CODE_URL = 'https://www.googleapis.com/projecthosting/v2/projects/chromiu m/issues/%s?key=AIzaSyDgCqT1Dt5AZWLHo4QJjyMHaCjhnFacGF0' 45 GOOGLE_CODE_URL = 'https://www.googleapis.com/projecthosting/v2/projects/chromiu m/issues/%s?key=AIzaSyDgCqT1Dt5AZWLHo4QJjyMHaCjhnFacGF0'
44 CRBUG_PREFIX = 'crbug.com/' 46 CRBUG_PREFIX = 'crbug.com/'
47 CSV_ROW_HEADERS = ['crbug link', 'test file', 'days since last update', 'owner', 'status']
45 48
49 class BugInfo():
50 def __init__(self, bug_link, filename, days_since_last_update, owner, status ):
51 self.bug_link = bug_link
52 self.filename = filename
53 self.days_since_last_update = days_since_last_update
54 self.owner = owner
55 self.status = status
46 56
47 class StaleTestPrinter(object): 57 class StaleTestPrinter(object):
48 58
49 def __init__(self, options): 59 def __init__(self, options):
50 self.days = options.days 60 self.days = options.days
51 self.csv_filename = options.create_csv 61 self.csv_filename = options.create_csv
52 self.host = Host() 62 self.host = Host()
53 self.is_stale_results = {} 63 self.bug_info = {}
54 64
55 def print_stale_tests(self): 65 def print_stale_tests(self):
56 port = self.host.port_factory.get() 66 port = self.host.port_factory.get()
57 expectations = port.expectations_dict() 67 expectations = port.expectations_dict()
58 parser = TestExpectationParser(port, all_tests=(), is_lint_mode=False) 68 parser = TestExpectationParser(port, all_tests=(), is_lint_mode=False)
59 expectations_file, expectations_contents = expectations.items()[0] 69 expectations_file, expectations_contents = expectations.items()[0]
60 expectation_lines = parser.parse(expectations_file, expectations_content s) 70 expectation_lines = parser.parse(expectations_file, expectations_content s)
61 csv_rows = [] 71 csv_rows = []
62 for line in expectation_lines: 72 for line in expectation_lines:
63 row = self.check_expectations_line(line) 73 row = self.check_expectations_line(line)
64 if row: 74 if row:
65 csv_rows.append(row) 75 csv_rows.append(row)
66 if self.csv_filename: 76 if self.csv_filename:
67 self.write_csv(csv_rows) 77 self.write_csv(csv_rows)
68 78
69 def write_csv(self, rows): 79 def write_csv(self, rows):
70 row_strings = [', '.join(r) for r in rows] 80 out = StringIO.StringIO()
71 contents = '\n'.join(row_strings) + '\n' 81 writer = csv.writer(out)
72 self.host.filesystem.write_text_file(self.csv_filename, contents) 82 writer.writerow(CSV_ROW_HEADERS)
83 for row in rows:
84 writer.writerow(row)
85 self.host.filesystem.write_text_file(self.csv_filename, out.getvalue())
73 86
74 def check_expectations_line(self, line): 87 def check_expectations_line(self, line):
75 """Checks the bugs in one test expectations line to see if they're stale . 88 """Checks the bugs in one test expectations line to see if they're stale .
76 89
77 Args: 90 Args:
78 line: A TestExpectationsLine instance. 91 line: A TestExpectationsLine instance.
79 92
80 Returns: 93 Returns:
81 A CSV row (a list of strings), or None if there are no stale bugs. 94 A CSV row (a list of strings), or None if there are no stale bugs.
82 """ 95 """
83 bug_links, test_name = line.bugs, line.name 96 bug_links, test_name = line.bugs, line.name
84 try: 97 try:
85 if bug_links and all(self.is_stale(bug_link) for bug_link in bug_lin ks): 98 if bug_links:
86 print line.original_string.strip() 99 # Prepopulate bug info.
87 return [bug_links[0], test_name] 100 for bug_link in bug_links:
101 self.populate_bug_info(bug_link, test_name);
102 # Return the stale bug's information.
103 if all(self.is_stale(bug_link) for bug_link in bug_links):
104 print line.original_string.strip()
105 return [bug_links[0], self.bug_info[bug_links[0]].filename,
106 self.bug_info[bug_links[0]].days_since_last_update,
107 self.bug_info[bug_links[0]].owner,
108 self.bug_info[bug_links[0]].status]
88 except urllib2.HTTPError as error: 109 except urllib2.HTTPError as error:
89 if error.code == 404: 110 if error.code == 404:
90 message = 'got 404, bug does not exist.' 111 message = 'got 404, bug does not exist.'
91 elif error.code == 403: 112 elif error.code == 403:
92 message = 'got 403, not accessible. Not able to tell if it\'s st ale.' 113 message = 'got 403, not accessible. Not able to tell if it\'s st ale.'
93 else: 114 else:
94 message = str(error) 115 message = str(error)
95 print >> sys.stderr, 'Error when checking %s: %s' % (','.join(bug_li nks), message) 116 print >> sys.stderr, 'Error when checking %s: %s' % (','.join(bug_li nks), message)
96 return None 117 return None
97 118
98 def is_stale(self, bug_link): 119 def populate_bug_info(self, bug_link, test_name):
99 if bug_link in self.is_stale_results: 120 if bug_link in self.bug_info:
100 return self.is_stale_results[bug_link] 121 return
101 # In case there's an error in the request, don't make the same request a gain. 122 # In case there's an error in the request, don't make the same request a gain.
102 self.is_stale_results[bug_link] = False
103 bug_number = bug_link.strip(CRBUG_PREFIX) 123 bug_number = bug_link.strip(CRBUG_PREFIX)
104 url = GOOGLE_CODE_URL % bug_number 124 url = GOOGLE_CODE_URL % bug_number
105 response = urllib2.urlopen(url) 125 response = urllib2.urlopen(url)
106 parsed = json.loads(response.read()) 126 parsed = json.loads(response.read())
107 last_updated = parsed['updated'] 127 parsed_time = datetime.datetime.strptime(parsed['updated'].split(".")[0] + "UTC", "%Y-%m-%dT%H:%M:%S%Z")
108 parsed_time = datetime.datetime.strptime(last_updated.split(".")[0] + "U TC", "%Y-%m-%dT%H:%M:%S%Z")
109 time_delta = datetime.datetime.now() - parsed_time 128 time_delta = datetime.datetime.now() - parsed_time
110 self.is_stale_results[bug_link] = time_delta.days > self.days 129 owner = 'none'
111 return self.is_stale_results[bug_link] 130 if 'owner' in parsed.keys():
131 owner = parsed['owner']['name']
132 self.bug_info[bug_link] = BugInfo(bug_link, test_name, time_delta.days, owner, parsed['state'])
133
134 def is_stale(self, bug_link):
135 return self.bug_info[bug_link].days_since_last_update > self.days
112 136
113 137
114 def main(argv): 138 def main(argv):
115 option_parser = optparse.OptionParser() 139 option_parser = optparse.OptionParser()
116 option_parser.add_option( 140 option_parser.add_option(
117 '--days', type='int', default=90, 141 '--days', type='int', default=90,
118 help='Number of days to consider a bug stale.') 142 help='Number of days to consider a bug stale.')
119 option_parser.add_option( 143 option_parser.add_option(
120 '--create-csv', type='string', default='', 144 '--create-csv', type='string', default='',
121 help='Filename of CSV file to write stale entries to. No file will be wr itten if no name specified.') 145 help='Filename of CSV file to write stale entries to. No file will be wr itten if no name specified.')
122 options, _ = option_parser.parse_args(argv) 146 options, _ = option_parser.parse_args(argv)
123 printer = StaleTestPrinter(options) 147 printer = StaleTestPrinter(options)
124 printer.print_stale_tests() 148 printer.print_stale_tests()
125 return 0 149 return 0
126 150
127 151
128 if __name__ == '__main__': 152 if __name__ == '__main__':
129 sys.exit(main(sys.argv[1:])) 153 sys.exit(main(sys.argv[1:]))
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698