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

Side by Side Diff: net/data/parse_certificate_unittest/rebase-errors.py

Issue 2805213004: Refactor how net/data/verify_certificate_chain_unittest/* (Closed)
Patch Set: fix android Created 3 years, 7 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
OLDNEW
1 #!/usr/bin/python 1 #!/usr/bin/python
2 # Copyright (c) 2016 The Chromium Authors. All rights reserved. 2 # Copyright (c) 2016 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 """Helper script to update the test error expectations based on actual results. 6 """Helper script to update the test error expectations based on actual results.
7 7
8 This is useful for regenerating test expectations after making changes to the 8 This is useful for regenerating test expectations after making changes to the
9 error format. 9 error format.
10 10
11 To use this run the affected tests, and then pass the input to this script 11 To use this run the affected tests, and then pass the input to this script
12 (either via stdin, or as the first argument). For instance: 12 (either via stdin, or as the first argument). For instance:
13 13
14 $ ./out/Release/net_unittests --gtest_filter="*VerifyCertificateChain*" | \ 14 $ ./out/Release/net_unittests --gtest_filter="*ParseCertificate*" | \
15 net/data/verify_certificate_chain_unittest/rebase-errors.py 15 net/data/parse_certificate_unittest/rebase-errors.py
16 16
17 The script works by scanning the stdout looking for gtest failures when 17 The script works by scanning the stdout looking for gtest failures when
18 comparing "errors.ToDebugString(chain)". The C++ test side should have been 18 comparing "errors.ToDebugString()". The C++ test side should have been
19 instrumented to dump out the test file's path on mismatch. 19 instrumented to dump out the test file's path on mismatch.
20 20
21 This script will then update the corresponding file(s) -- a .pem file, and 21 This script will then update the corresponding .pem file
22 possibly an accompanying .py file.
23 """ 22 """
24 23
24 import sys
25 sys.path += ['../verify_certificate_chain_unittest']
26
25 import common 27 import common
28
26 import os 29 import os
27 import sys 30 import sys
28 import re 31 import re
29 32
30 33
31 # Regular expression to find the failed errors in test stdout. 34 # Regular expression to find the failed errors in test stdout.
32 # * Group 1 of the match is the actual error text (backslash-escaped) 35 # * Group 1 of the match is the actual error text (backslash-escaped)
33 # * Group 2 of the match is file path (relative to //src) where the expected 36 # * Group 2 of the match is file path (relative to //src) where the expected
34 # errors were read from. 37 # errors were read from.
35 failed_test_regex = re.compile(r""" 38 failed_test_regex = re.compile(r"""
36 Value of: errors.ToDebugString\((?:test.chain)?\) 39 Value of: errors.ToDebugString\(\)
37 Actual: "(.*)" 40 Actual: "(.*)"
38 (?:.|\n)+? 41 (?:.|\n)+?
39 Test file: (.*) 42 Test file: (.*[.]pem)
40 """, re.MULTILINE) 43 """, re.MULTILINE)
41 44
42 45
43 # Regular expression to find the ERRORS block (and any text above it) in a PEM 46 # Regular expression to find the ERRORS block (and any text above it) in a PEM
44 # file. The assumption is that ERRORS is not the very first block in the file 47 # file. The assumption is that ERRORS is not the very first block in the file
45 # (since it looks for an -----END to precede it). 48 # (since it looks for an -----END to precede it).
46 # * Group 1 of the match is the ERRORS block content and any comments 49 # * Group 1 of the match is the ERRORS block content and any comments
47 # immediately above it. 50 # immediately above it.
48 errors_block_regex = re.compile(r""".* 51 errors_block_regex = re.compile(r""".*
49 -----END .*?----- 52 -----END .*?-----
(...skipping 11 matching lines...) Expand all
61 return f.read() 64 return f.read()
62 65
63 66
64 def write_string_to_file(data, path): 67 def write_string_to_file(data, path):
65 """Writes a string to a file""" 68 """Writes a string to a file"""
66 print "Writing file %s ..." % (path) 69 print "Writing file %s ..." % (path)
67 with open(path, "w") as f: 70 with open(path, "w") as f:
68 f.write(data) 71 f.write(data)
69 72
70 73
71 def get_py_path(pem_path):
72 """Returns the .py filepath used to generate the given .pem path, which may
73 or may not exist.
74
75 Some test files (notably those in verify_certificate_chain_unittest/ have a
76 "generate-XXX.py" script that builds the "XXX.pem" file. Build the path to
77 the corresponding "generate-XXX.py" (which may or may not exist)."""
78 file_name = os.path.basename(pem_path)
79 file_name_no_extension = os.path.splitext(file_name)[0]
80 py_file_name = 'generate-' + file_name_no_extension + '.py'
81 return os.path.join(os.path.dirname(pem_path), py_file_name)
82
83
84 def replace_string(original, start, end, replacement): 74 def replace_string(original, start, end, replacement):
85 """Replaces the specified range of |original| with |replacement|""" 75 """Replaces the specified range of |original| with |replacement|"""
86 return original[0:start] + replacement + original[end:] 76 return original[0:start] + replacement + original[end:]
87 77
88 78
89 def fixup_pem_file(path, actual_errors): 79 def fixup_pem_file(path, actual_errors):
90 """Updates the ERRORS block in the test .pem file""" 80 """Updates the ERRORS block in the test .pem file"""
91 contents = read_file_to_string(path) 81 contents = read_file_to_string(path)
92 82
93 m = errors_block_regex.search(contents) 83 m = errors_block_regex.search(contents)
94 84
95 if not m: 85 if not m:
96 contents += '\n' + common.text_data_to_pem('ERRORS', actual_errors) 86 contents += '\n' + common.text_data_to_pem('ERRORS', actual_errors)
97 else: 87 else:
98 contents = replace_string(contents, m.start(1), m.end(1), 88 contents = replace_string(contents, m.start(1), m.end(1),
99 common.text_data_to_pem('ERRORS', actual_errors)) 89 common.text_data_to_pem('ERRORS', actual_errors))
100 90
101 # Update the file. 91 # Update the file.
102 write_string_to_file(contents, path) 92 write_string_to_file(contents, path)
103 93
104 94
105 def fixup_py_file(path, actual_errors):
106 """Replaces the 'errors = XXX' section of the test's python script"""
107 contents = read_file_to_string(path)
108
109 # This assumes that the errors variable uses triple quotes.
110 prog = re.compile(r'^errors = (""".*?"""|None)', re.MULTILINE | re.DOTALL)
111 result = prog.search(contents)
112
113 # Replace the stuff in between the triple quotes with the actual errors.
114 contents = replace_string(contents, result.start(1), result.end(1),
115 '"""' + actual_errors + '"""')
116
117 # Update the file.
118 write_string_to_file(contents, path)
119
120
121 def get_src_root(): 95 def get_src_root():
122 """Returns the path to the enclosing //src directory. This assumes the 96 """Returns the path to the enclosing //src directory. This assumes the
123 current script is inside the source tree.""" 97 current script is inside the source tree."""
124 cur_dir = os.path.dirname(os.path.realpath(__file__)) 98 cur_dir = os.path.dirname(os.path.realpath(__file__))
125 99
126 while True: 100 while True:
127 parent_dir, dirname = os.path.split(cur_dir) 101 parent_dir, dirname = os.path.split(cur_dir)
128 # Check if it looks like the src/ root. 102 # Check if it looks like the src/ root.
129 if dirname == "src" and os.path.isdir(os.path.join(cur_dir, "net")): 103 if dirname == "src" and os.path.isdir(os.path.join(cur_dir, "net")):
130 return cur_dir 104 return cur_dir
131 if not parent_dir or parent_dir == cur_dir: 105 if not parent_dir or parent_dir == cur_dir:
132 break 106 break
133 cur_dir = parent_dir 107 cur_dir = parent_dir
134 108
135 print "Couldn't find src dir" 109 print "Couldn't find src dir"
136 sys.exit(1) 110 sys.exit(1)
137 111
138 112
139 def get_abs_path(rel_path): 113 def get_abs_path(rel_path):
140 """Converts |rel_path| (relative to src) to a full path""" 114 """Converts |rel_path| (relative to src) to a full path"""
141 return os.path.join(get_src_root(), rel_path) 115 return os.path.join(get_src_root(), rel_path)
142 116
143 117
144 def fixup_errors_for_file(actual_errors, pem_path):
145 """Updates the errors in |test_file_path| (.pem file) to match
146 |actual_errors|"""
147
148 fixup_pem_file(pem_path, actual_errors)
149
150 # If the test has a generator script update it too.
151 py_path = get_py_path(pem_path)
152 if os.path.isfile(py_path):
153 fixup_py_file(py_path, actual_errors)
154
155
156 def main(): 118 def main():
157 if len(sys.argv) > 2: 119 if len(sys.argv) > 2:
158 print 'Usage: %s [path-to-unittest-stdout]' % (sys.argv[0]) 120 print 'Usage: %s [path-to-unittest-stdout]' % (sys.argv[0])
159 sys.exit(1) 121 sys.exit(1)
160 122
161 # Read the input either from a file, or from stdin. 123 # Read the input either from a file, or from stdin.
162 test_stdout = None 124 test_stdout = None
163 if len(sys.argv) == 2: 125 if len(sys.argv) == 2:
164 test_stdout = read_file_to_string(sys.argv[1]) 126 test_stdout = read_file_to_string(sys.argv[1])
165 else: 127 else:
166 print 'Reading input from stdin...' 128 print 'Reading input from stdin...'
167 test_stdout = sys.stdin.read() 129 test_stdout = sys.stdin.read()
168 130
169 for m in failed_test_regex.finditer(test_stdout): 131 for m in failed_test_regex.finditer(test_stdout):
170 actual_errors = m.group(1) 132 actual_errors = m.group(1)
171 actual_errors = actual_errors.decode('string-escape') 133 actual_errors = actual_errors.decode('string-escape')
172 relative_test_path = m.group(2) 134 relative_test_path = m.group(2)
173 fixup_errors_for_file(actual_errors, get_abs_path(relative_test_path)) 135 fixup_pem_file(get_abs_path(relative_test_path), actual_errors)
174 136
175 137
176 if __name__ == "__main__": 138 if __name__ == "__main__":
177 main() 139 main()
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698