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

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

Issue 2323223002: Add a script to update the expected errors for (Closed)
Patch Set: change date Created 4 years, 3 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 | « net/data/verify_certificate_chain_unittest/generate-violates-pathlen-1-constrained-root.py ('k') | 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
(Empty)
1 #!/usr/bin/python
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
4 # found in the LICENSE file.
5
6 """Helper script to update the test error expectations based on actual results.
7
8 This is useful for regenerating test expectations after making changes to the
9 error format.
10
11 To use this run the affected tests, and then pass the input to this script. For
12 instance:
13
14 $ ./out/Release/net_unittests --gtest_filter="*VerifyCertificateChain*" \
15 &> results.txt
16 $ python net/data/verify_certificate_chain_unittest/rebase-errors.py \
17 results.txt
18
19 The script will search the unit-test (results.txt in above example) and look
20 for failure lines and the corresponding actual error string.
21
22 It will then go and update the corresponding .pem and .py file.
23 """
24
25 import common
26 import glob
27 import os
28 import sys
29 import re
30
31
32 def read_file_to_string(path):
33 """Reads a file entirely to a string"""
34 with open(path, 'r') as f:
35 return f.read()
36
37
38 def write_string_to_file(data, path):
39 """Writes a string to a file"""
40 print "Writing file %s ..." % (path)
41 with open(path, "w") as f:
42 f.write(data)
43
44
45 def get_file_paths_for_test(test_name):
46 """Returns the file paths (as a tuple) that define a particular unit test.
47 For instance given test name 'IntermediateLacksBasicConstraints' it would
48 return the paths to:
49
50 * intermediate-lacks-basic-constraints.pem,
51 * generate-intermediate-lacks-basic-constraints.py
52 """
53 # The directory that this python script is stored in.
54 base_dir = os.path.dirname(os.path.realpath(__file__))
55
56 # The C++ test name is just a camel case verson of the file name. Rather than
57 # converting directly from camel case to a file name, it is simpler to just
58 # scan the file list and see which matches. (Not efficient but good enough).
59 paths = glob.glob(os.path.join(base_dir, '*.pem'))
60
61 for pem_path in paths:
62 file_name = os.path.basename(pem_path)
63 file_name_no_extension = os.path.splitext(file_name)[0]
64
65 # Strip the hyphens in file name to bring it closer to the camel case.
66 transformed = file_name_no_extension.replace('-', '')
67
68 # Now all that differs is the case.
69 if transformed.lower() == test_name.lower():
70 py_file_name = 'generate-' + file_name_no_extension + '.py'
71 py_path = os.path.join(base_dir, py_file_name)
72 return (pem_path, py_path)
73
74 return None
75
76
77 def replace_string(original, start, end, replacement):
78 """Replaces the specified range of |original| with |replacement|"""
79 return original[0:start] + replacement + original[end:]
80
81
82 def fixup_pem_file(path, actual_errors):
83 """Updates the ERRORS block in the test .pem file"""
84 contents = read_file_to_string(path)
85
86 # This assumes that ERRORS is the last thing in file, and comes after the
87 # VERIFY_RESULT block.
88 kEndVerifyResult = '-----END VERIFY_RESULT-----'
89 contents = contents[0:contents.index(kEndVerifyResult)]
90 contents += kEndVerifyResult
91 contents += '\n'
92 contents += '\n'
93 contents += common.text_data_to_pem('ERRORS', actual_errors)
94
95 # Update the file.
96 write_string_to_file(contents, path)
97
98
99 def fixup_py_file(path, actual_errors):
100 """Replaces the 'errors = XXX' section of the test's python script"""
101 contents = read_file_to_string(path)
102
103 # This assumes that the errors variable uses triple quotes.
104 prog = re.compile(r'^errors = """(.*)"""', re.MULTILINE | re.DOTALL)
105 result = prog.search(contents)
106
107 # Replace the stuff in between the triple quotes with the actual errors.
108 contents = replace_string(contents, result.start(1), result.end(1),
mattm 2016/09/09 22:18:54 could use re.sub instead of re.search + replace_st
eroman 2016/09/09 23:16:25 My concern with re.sub() is that it processes back
mattm 2016/09/09 23:22:21 ah, I forgot that. I guess there is the 2nd form o
eroman 2016/09/10 00:22:39 Left unchanged.
109 actual_errors)
110
111 # Update the file.
112 write_string_to_file(contents, path)
113
114
115 def fixup_test(test_name, actual_errors):
116 """Updates the test files used by |test_name|, setting the expected error to
117 |actual_errors|"""
118
119 # Determine the paths for the corresponding *.pem file and generate-*.py
120 pem_path, py_path = get_file_paths_for_test(test_name)
121
122 fixup_pem_file(pem_path, actual_errors)
123 fixup_py_file(py_path, actual_errors)
124
125
126 kTestNamePattern = (r'^\[ RUN \] VerifyCertificateChain/'
127 'VerifyCertificateChainSingleRootTest/0\.(.*)$')
128 kValueOfLine = 'Value of: errors.ToDebugString()'
129 kActualPattern = '^ Actual: "(.*)"$'
130
131
132 def main():
133 if len(sys.argv) != 2:
134 print 'Usage: %s <path-to-unittest-stdout>' % (sys.argv[0])
135 sys.exit(1)
136
137 test_stdout = read_file_to_string(sys.argv[1])
mattm 2016/09/09 22:18:54 what do you think about reading from sys.stdin ins
eroman 2016/09/09 23:16:26 Sure, will do.
eroman 2016/09/10 00:22:39 Done.
138 lines = test_stdout.split('\n')
139
140 # Iterate over each line of the unit test stdout.
141 for i in range(len(lines) - 3):
142 # Figure out the name of the test.
143 m = re.search(kTestNamePattern, lines[i])
144 if not m:
145 continue
146 test_name = m.group(1)
147
148 # Confirm that it is a failure having to do with the errors.
149 if lines[i + 2] != kValueOfLine:
150 continue
151
152 # Get the actual error text (which in gtest output is escaped).
153 m = re.search(kActualPattern, lines[i + 3])
154 if not m:
155 continue
156 actual = m.group(1)
157 actual = actual.decode('string-escape')
158
159 fixup_test(test_name, actual)
160
161
162 if __name__ == "__main__":
163 main()
OLDNEW
« no previous file with comments | « net/data/verify_certificate_chain_unittest/generate-violates-pathlen-1-constrained-root.py ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698