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

Side by Side Diff: tools/valgrind/drmemory_analyze.py

Issue 8688006: Set up python BROWSER_WRAPPER for ui_tests under Dr. Memory (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: '' Created 9 years 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 | Annotate | Revision Log
OLDNEW
1 #!/usr/bin/python 1 #!/usr/bin/python
2 # Copyright (c) 2011 The Chromium Authors. All rights reserved. 2 # Copyright (c) 2011 The Chromium Authors. All rights reserved.
3 # Use of this source code is governed by a BSD-style license that can be 3 # Use of this source code is governed by a BSD-style license that can be
4 # found in the LICENSE file. 4 # found in the LICENSE file.
5 5
6 # drmemory_analyze.py 6 # drmemory_analyze.py
7 7
8 ''' Given a Dr. Memory output file, parses errors and uniques them.''' 8 ''' Given a Dr. Memory output file, parses errors and uniques them.'''
9 9
10 from collections import defaultdict
11 import common
10 import logging 12 import logging
11 import optparse 13 import optparse
12 import os 14 import os
13 import re 15 import re
14 import subprocess 16 import subprocess
15 import sys 17 import sys
16 import time 18 import time
17 19
18 class _StackTraceLine(object):
Timur Iskhodzhanov 2011/11/24 15:01:14 copy-paste artifact from tsan_analyze.py
19 def __init__(self, line, address, binary):
20 self.raw_line_ = line
21 self.address = address
22 self.binary = binary
23 def __str__(self):
24 return self.raw_line_
25 20
26 class DrMemoryAnalyze: 21 class DrMemoryAnalyzer:
27 ''' Given a set of Dr.Memory output files, parse all the errors out of 22 ''' Given a set of Dr.Memory output files, parse all the errors out of
28 them, unique them and output the results.''' 23 them, unique them and output the results.'''
29 24
30 def __init__(self, source_dir, files): 25 def __init__(self):
31 '''Reads in a set of files. 26 self.known_errors = set()
32
33 Args:
34 source_dir: Path to top of source tree for this build
35 files: A list of filenames.
36 '''
37
38 self.reports = []
39 self.used_suppressions = []
40 for file in files:
41 self.ParseReportFile(file)
42 27
43 def ReadLine(self): 28 def ReadLine(self):
44 self.line_ = self.cur_fd_.readline() 29 self.line_ = self.cur_fd_.readline()
45 30
46 def ReadSection(self): 31 def ReadSection(self):
47 result = [self.line_] 32 result = [self.line_]
48 self.ReadLine() 33 self.ReadLine()
49 while len(self.line_.strip()) > 0: 34 while len(self.line_.strip()) > 0:
50 result.append(self.line_) 35 result.append(self.line_)
51 self.ReadLine() 36 self.ReadLine()
52 return result 37 return result
53 38
54 def ParseReportFile(self, filename): 39 def ParseReportFile(self, filename):
40 ret = []
41
55 self.cur_fd_ = open(filename, 'r') 42 self.cur_fd_ = open(filename, 'r')
56
57 while True: 43 while True:
58 self.ReadLine() 44 self.ReadLine()
59 if (self.line_ == ''): break 45 if (self.line_ == ''): break
60 46
61 match = re.search("^Error #[0-9]+: (.*)", self.line_) 47 match = re.search("^Error #[0-9]+: (.*)", self.line_)
62 if match: 48 if match:
63 self.line_ = match.groups()[0].strip() + "\n" 49 self.line_ = match.groups()[0].strip() + "\n"
64 tmp = self.ReadSection() 50 tmp = self.ReadSection()
65 self.reports.append(tmp) 51 ret.append("".join(tmp).strip())
66 52
67 if re.search("SUPPRESSIONS USED:", self.line_): 53 if re.search("SUPPRESSIONS USED:", self.line_):
68 self.ReadLine() 54 self.ReadLine()
69 while self.line_.strip() != "": 55 while self.line_.strip() != "":
70 line = self.line_.strip() 56 line = self.line_.strip()
71 (count, name) = re.match(" *([0-9]+)x(?: \(leaked .*\))?: (.*)", 57 (count, name) = re.match(" *([0-9]+)x(?: \(leaked .*\))?: (.*)",
72 line).groups() 58 line).groups()
73 self.used_suppressions.append("%7s %s" % (count, name)) 59 count = int(count)
60 self.used_suppressions[name] += count
74 self.ReadLine() 61 self.ReadLine()
75 62
76 if self.line_.startswith("ASSERT FAILURE"): 63 if self.line_.startswith("ASSERT FAILURE"):
77 self.reports.append(self.line_.strip()) 64 ret.append(self.line_.strip())
78 65
79 self.cur_fd_.close() 66 self.cur_fd_.close()
67 return ret
80 68
81 def Report(self, check_sanity): 69 def Report(self, filenames, testcase, check_sanity):
82 sys.stdout.flush() 70 sys.stdout.flush()
83 #TODO(timurrrr): support positive tests / check_sanity==True 71 # TODO(timurrrr): support positive tests / check_sanity==True
84 72
85 if self.used_suppressions: 73 to_report = []
86 print "-----------------------------------------------------" 74 self.used_suppressions = defaultdict(int)
87 # TODO(timurrrr): sum up the counts from different wrappers (e.g. ui_tests ) 75 for f in filenames:
88 # or does it work now already? Or add the memcheck-like per-test printing. 76 cur_reports = self.ParseReportFile(f)
89 print "Suppressions used:\n count name\n%s" % (
90 "\n".join(self.used_suppressions))
91 print "-----------------------------------------------------"
92 sys.stdout.flush()
93 77
94 if len(self.reports) > 0: 78 # Filter out the reports that were there in previous tests.
95 logging.error("Found %i error reports" % len(self.reports)) 79 for r in cur_reports:
96 for report_list in self.reports: 80 if r in self.known_errors:
97 report = '' 81 pass # TODO: print out a hash once we add hashes to the reports.
98 for line in report_list: 82 else:
99 report += str(line) 83 self.known_errors.add(r)
100 logging.error('\n' + report) 84 to_report.append(r)
101 logging.error("Total: %i error reports" % len(self.reports)) 85
102 return -1 86 common.PrintUsedSuppressionsList(self.used_suppressions)
103 logging.info("PASS: No error reports found") 87
104 return 0 88 if not to_report:
89 logging.info("PASS: No error reports found")
90 return 0
91
92 logging.error("Found %i error reports" % len(to_report))
93 for report in to_report:
94 if testcase:
95 logging.error("\n%s\nNote: observed on `%s`\n" %
96 (report, testcase))
97 else:
98 logging.error("\n%s\n" % report)
99 logging.error("Total: %i error reports" % len(to_report))
100 return -1
105 101
106 if __name__ == '__main__': 102 if __name__ == '__main__':
107 '''For testing only. The DrMemoryAnalyze class should be imported instead.''' 103 '''For testing only. The DrMemoryAnalyzer class should be imported instead.'''
108 retcode = 0 104 retcode = 0
109 parser = optparse.OptionParser("usage: %prog [options] <files to analyze>") 105 parser = optparse.OptionParser("usage: %prog <files to analyze>")
110 parser.add_option("", "--source_dir",
Timur Iskhodzhanov 2011/11/24 15:01:14 unused, since Dr. Memory handles this itself.
111 help="path to top of source tree for this build"
112 "(used to normalize source paths in baseline)")
113
114 (options, args) = parser.parse_args() 106 (options, args) = parser.parse_args()
115 if len(args) == 0: 107 if len(args) == 0:
116 parser.error("no filename specified") 108 parser.error("no filename specified")
117 filenames = args 109 filenames = args
118 110
119 analyzer = DrMemoryAnalyze(options.source_dir, filenames) 111 analyzer = DrMemoryAnalyzer()
120 retcode = analyzer.Report(False) 112 retcode = analyzer.Report(filenames, None, False)
121 113
122 sys.exit(retcode) 114 sys.exit(retcode)
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698