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

Side by Side Diff: testing/tools/test_runner.py

Issue 1430623006: One test runner to rule them all. (Closed) Base URL: https://pdfium.googlesource.com/pdfium.git@master
Patch Set: Created 5 years, 1 month 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 | « testing/tools/run_pixel_tests.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/env python
2 # Copyright 2015 The PDFium 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 import cStringIO
7 import functools
8 import multiprocessing
9 import optparse
10 import os
11 import re
12 import shutil
13 import subprocess
14 import sys
15
16 import common
17 import pngdiffer
18 import suppressor
19
20 class KeyboardInterruptError(Exception): pass
21
22 # Nomenclature:
23 # x_root - "x"
24 # x_filename - "x.ext"
25 # x_path - "path/to/a/b/c/x.ext"
26 # c_dir - "path/to/a/b/c"
27
28 def TestOneFileParallel(this, test_case):
29 """Wrapper function to call GenerateAndTest() and redirect output
30 to stdout."""
31 try:
32 old_stdout = sys.stdout
33 old_stderr = sys.stderr
34 sys.stdout = cStringIO.StringIO()
35 sys.stderr = sys.stdout
36
37 input_filename, source_dir = test_case
38 result = this.GenerateAndTest(input_filename, source_dir, True);
39
40 output = sys.stdout
41 sys.stdout = old_stdout
42 sys.stderr = old_stderr
43 return (result, output.getvalue(), input_filename, source_dir)
44 except KeyboardInterrupt:
45 raise KeyboardInterruptError()
46
47
48 class TestRunner:
49 def __init__(self, dirname):
50 self.test_dir = dirname
51
52
53 def GenerateAndTest(self, input_filename, source_dir, redirect_output=False):
54 input_root, _ = os.path.splitext(input_filename)
55 expected_txt_path = os.path.join(source_dir, input_root + '_expected.txt')
56
57 pdf_path = os.path.join(self.working_dir, input_root + '.pdf')
58
59 # Remove any existing generated images from previous runs.
60 actual_images = self.image_differ.GetActualFiles(
61 input_filename, source_dir, self.working_dir)
62
Lei Zhang 2015/11/03 03:11:21 no need for indentation since the above code is re
dsinclair 2015/11/03 14:29:12 Which indentation, the for is at the same level as
Lei Zhang 2015/11/03 14:41:03 Sorry, I meant no need for blank line.
dsinclair 2015/11/03 15:10:21 Done.
63 for image in actual_images:
64 if os.path.exists(image):
65 os.remove(image)
66
67 sys.stdout.flush()
68
69 raised_exception = self.Generate(source_dir, input_filename, input_root,
70 pdf_path, redirect_output)
Lei Zhang 2015/11/03 03:11:21 Indent with "source_dir" from the line above? Ditt
dsinclair 2015/11/03 14:29:12 Done.
71
72 if raised_exception != None:
73 print "FAILURE: " + input_filename + "; " + str(raised_exception)
74 return False
75
76 if os.path.exists(expected_txt_path):
77 raised_exception = self.TestText(input_root, expected_txt_path, pdf_path,
78 redirect_output)
79 else:
80 raised_exception = self.TestPixel(pdf_path, redirect_output)
81
82 if raised_exception != None:
83 print "FAILURE: " + input_filename + "; " + str(raised_exception)
84 return False
85
86 if len(actual_images):
87 if self.image_differ.HasDifferences(input_filename, source_dir,
88 self.working_dir, redirect_output):
89 return False
90
91 return True
92
93
94 def Generate(self, source_dir, input_filename, input_root, pdf_path,
95 redirect_output):
Lei Zhang 2015/11/03 03:11:21 funny indentation?
dsinclair 2015/11/03 14:29:12 That about sums up python, heh.
96 original_path = os.path.join(source_dir, input_filename)
97 input_path = os.path.join(source_dir, input_root + '.in')
98
99 if os.path.exists(original_path) and not os.path.exists(input_path):
100 shutil.copyfile(original_path, pdf_path)
101
102 if not os.path.exists(input_path):
103 return None
104
105 return common.RunCommand(
106 [sys.executable, self.fixup_path, '--output-dir=' + self.working_dir,
Lei Zhang 2015/11/03 03:11:21 May be easier to read here if we build a cmd varia
dsinclair 2015/11/03 14:29:12 Done.
107 input_path], redirect_output)
108
109
110 def TestText(self, input_root, expected_txt_path, pdf_path, redirect_output):
111 txt_path = os.path.join(self.working_dir, input_root + '.txt')
112 with open(txt_path, 'w') as outfile:
113 subprocess.check_call([self.pdfium_test_path, pdf_path], stdout=outfile)
114
115 return common.RunCommand(
116 [sys.executable, self.text_diff_path, expected_txt_path, txt_path],
117 redirect_output)
Lei Zhang 2015/11/03 03:11:21 4 spaces too many
dsinclair 2015/11/03 14:29:12 Done.
118
119
120 def TestPixel(self, pdf_path, redirect_output):
121 return common.RunCommand(
122 [self.pdfium_test_path, '--png', pdf_path], redirect_output)
123
124
125 def HandleResult(self, input_filename, input_path, result):
126 if self.test_suppressor.IsSuppressed(input_filename):
127 if result:
128 self.surprises.append(input_path)
129 else:
130 if not result:
131 self.failures.append(input_path)
132
133
134 def Run(self):
135 parser = optparse.OptionParser()
136 parser.add_option('--build-dir', default=os.path.join('out', 'Debug'),
137 help='relative path from the base source directory')
138 parser.add_option('-j', default=multiprocessing.cpu_count(),
139 dest='num_workers', type='int',
140 help='run NUM_WORKERS jobs in parallel')
141 options, args = parser.parse_args()
142
143 finder = common.DirectoryFinder(options.build_dir)
144 self.fixup_path = finder.ScriptPath('fixup_pdf_template.py')
145 self.text_diff_path = finder.ScriptPath('text_diff.py')
146
147 self.source_dir = finder.TestingDir()
148
149 if self.test_dir != 'corpus':
150 test_dir = finder.TestingDir(os.path.join('resources', self.test_dir))
151 else:
152 test_dir = finder.TestingDir(self.test_dir)
153
154 self.pdfium_test_path = finder.ExecutablePath('pdfium_test')
155 if not os.path.exists(self.pdfium_test_path):
156 print "FAILURE: Can't find test executable '%s'" % self.pdfium_test_path
157 print "Use --build-dir to specify its location."
158 return 1
159
160 self.working_dir = finder.WorkingDir(os.path.join('testing', self.test_dir))
161 if not os.path.exists(self.working_dir):
162 os.makedirs(self.working_dir)
163
164 self.test_suppressor = suppressor.Suppressor(finder)
165 self.image_differ = pngdiffer.PNGDiffer(finder)
166
167 walk_from_dir = finder.TestingDir(test_dir);
168
169 test_cases = []
170 input_file_re = re.compile('^[a-zA-Z0-9_.]+[.](in|pdf)$')
171
172 if len(args):
173 for file_name in args:
174 file_name.replace(".pdf", ".in")
175 input_path = os.path.join(walk_from_dir, file_name)
176 if not os.path.isfile(input_path):
177 print "Can't find test file '%s'" % file_name
178 return 1
179
180 test_cases.append((os.path.basename(input_path),
181 os.path.dirname(input_path)))
182 else:
183 for file_dir, _, filename_list in os.walk(walk_from_dir):
184 for input_filename in filename_list:
185 if input_file_re.match(input_filename):
186 input_path = os.path.join(file_dir, input_filename)
187 if os.path.isfile(input_path):
188 test_cases.append((input_filename, file_dir))
189
190 self.failures = []
191 self.surprises = []
192
193 if options.num_workers > 1 and not len(args):
194 try:
195 pool = multiprocessing.Pool(options.num_workers)
196 worker_func = functools.partial(TestOneFileParallel, self)
197
198 worker_results = pool.imap(worker_func, test_cases)
199 for worker_result in worker_results:
200 result, output, input_filename, source_dir = worker_result
201 input_path = os.path.join(source_dir, input_filename)
202 sys.stdout.write(output)
203
204 self.HandleResult(input_filename, input_path, result)
205 except KeyboardInterrupt:
206 pool.terminate()
207 finally:
208 pool.close()
209 pool.join()
210 else:
211 for test_case in test_cases:
212 input_filename, input_file_dir = test_case
213 result = self.GenerateAndTest(input_filename, input_file_dir)
214 self.HandleResult(input_filename,
215 os.path.join(input_file_dir, input_filename), result)
216
217 if self.surprises:
218 self.surprises.sort()
219 print '\n\nUnexpected Successes:'
220 for surprise in self.surprises:
221 print surprise;
222
223 if self.failures:
224 self.failures.sort()
225 print '\n\nSummary of Failures:'
226 for failure in self.failures:
227 print failure
228 return 1
229
230 return 0
231
OLDNEW
« no previous file with comments | « testing/tools/run_pixel_tests.py ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698