| Index: testing/tools/run_corpus_tests.py | 
| diff --git a/testing/tools/run_corpus_tests.py b/testing/tools/run_corpus_tests.py | 
| index dd81a2736d8e20ad69c9f0e67a429888aee860e4..29f23b504a5caefbbf2903e23308b48888809a09 100755 | 
| --- a/testing/tools/run_corpus_tests.py | 
| +++ b/testing/tools/run_corpus_tests.py | 
| @@ -3,13 +3,165 @@ | 
| # Use of this source code is governed by a BSD-style license that can be | 
| # found in the LICENSE file. | 
|  | 
| +import cStringIO | 
| +import functools | 
| +import multiprocessing | 
| +import optparse | 
| +import os | 
| +import re | 
| +import shutil | 
| +import subprocess | 
| import sys | 
|  | 
| -import test_runner | 
| +import common | 
| +import pngdiffer | 
| +import suppressor | 
| + | 
| +class KeyboardInterruptError(Exception): pass | 
| + | 
| +# Nomenclature: | 
| +#   x_root - "x" | 
| +#   x_filename - "x.ext" | 
| +#   x_path - "path/to/a/b/c/x.ext" | 
| +#   c_dir - "path/to/a/b/c" | 
| + | 
| +def test_one_file(input_filename, source_dir, working_dir, | 
| +                  pdfium_test_path, image_differ, redirect_output=False): | 
| +  input_path = os.path.join(source_dir, input_filename) | 
| +  pdf_path = os.path.join(working_dir, input_filename) | 
| + | 
| +  # Remove any existing generated images from previous runs. | 
| +  actual_images = image_differ.GetActualFiles( | 
| +      input_filename, source_dir, working_dir) | 
| +  for image in actual_images: | 
| +    if os.path.exists(image): | 
| +      os.remove(image) | 
| + | 
| +  shutil.copyfile(input_path, pdf_path) | 
| +  sys.stdout.flush() | 
| +  error = common.RunCommand([pdfium_test_path, '--png', pdf_path], | 
| +                            redirect_output) | 
| +  if error: | 
| +    print "FAILURE: " + input_filename + "; " + str(error) | 
| +    return False | 
| +  return not image_differ.HasDifferences(input_filename, source_dir, | 
| +                                         working_dir, redirect_output) | 
| + | 
| + | 
| +def test_one_file_parallel(working_dir, pdfium_test_path, image_differ, | 
| +                           test_case): | 
| +  """Wrapper function to call test_one_file() and redirect output to stdout.""" | 
| +  try: | 
| +    old_stdout = sys.stdout | 
| +    old_stderr = sys.stderr | 
| +    sys.stdout = cStringIO.StringIO() | 
| +    sys.stderr = sys.stdout | 
| +    input_filename, source_dir = test_case | 
| +    result = test_one_file(input_filename, source_dir, working_dir, | 
| +                           pdfium_test_path, image_differ, True); | 
| +    output = sys.stdout | 
| +    sys.stdout = old_stdout | 
| +    sys.stderr = old_stderr | 
| +    return (result, output.getvalue(), input_filename, source_dir) | 
| +  except KeyboardInterrupt: | 
| +    raise KeyboardInterruptError() | 
| + | 
| + | 
| +def handle_result(test_suppressor, input_filename, input_path, result, | 
| +                  surprises, failures): | 
| +  if test_suppressor.IsSuppressed(input_filename): | 
| +    if result: | 
| +      surprises.append(input_path) | 
| +  else: | 
| +    if not result: | 
| +      failures.append(input_path) | 
| + | 
|  | 
| def main(): | 
| -  runner = test_runner.TestRunner('corpus') | 
| -  return runner.Run() | 
| +  parser = optparse.OptionParser() | 
| +  parser.add_option('--build-dir', default=os.path.join('out', 'Debug'), | 
| +                    help='relative path from the base source directory') | 
| +  parser.add_option('-j', default=multiprocessing.cpu_count(), | 
| +                    dest='num_workers', type='int', | 
| +                    help='run NUM_WORKERS jobs in parallel') | 
| +  options, args = parser.parse_args() | 
| +  finder = common.DirectoryFinder(options.build_dir) | 
| +  pdfium_test_path = finder.ExecutablePath('pdfium_test') | 
| +  if not os.path.exists(pdfium_test_path): | 
| +    print "FAILURE: Can't find test executable '%s'" % pdfium_test_path | 
| +    print "Use --build-dir to specify its location." | 
| +    return 1 | 
| +  working_dir = finder.WorkingDir(os.path.join('testing', 'corpus')) | 
| +  if not os.path.exists(working_dir): | 
| +    os.makedirs(working_dir) | 
| + | 
| +  test_suppressor = suppressor.Suppressor(finder) | 
| +  image_differ = pngdiffer.PNGDiffer(finder) | 
| + | 
| +  # test files are under .../pdfium/testing/corpus. | 
| +  failures = [] | 
| +  surprises = [] | 
| +  walk_from_dir = finder.TestingDir('corpus'); | 
| +  input_file_re = re.compile('^[a-zA-Z0-9_.]+[.]pdf$') | 
| +  test_cases = [] | 
| + | 
| +  if len(args): | 
| +    for file_name in args: | 
| +      input_path = os.path.join(walk_from_dir, file_name) | 
| +      if not os.path.isfile(input_path): | 
| +        print "Can't find test file '%s'" % file_name | 
| +        return 1 | 
| + | 
| +      test_cases.append((os.path.basename(input_path), | 
| +                         os.path.dirname(input_path))) | 
| +  else: | 
| +    for source_dir, _, filename_list in os.walk(walk_from_dir): | 
| +      for input_filename in filename_list: | 
| +        if input_file_re.match(input_filename): | 
| +          input_path = os.path.join(source_dir, input_filename) | 
| +          if os.path.isfile(input_path): | 
| +            test_cases.append((input_filename, source_dir)) | 
| + | 
| +  if options.num_workers > 1 and len(test_cases) > 1: | 
| +    try: | 
| +      pool = multiprocessing.Pool(options.num_workers) | 
| +      worker_func = functools.partial(test_one_file_parallel, working_dir, | 
| +                                      pdfium_test_path, image_differ) | 
| +      worker_results = pool.imap(worker_func, test_cases) | 
| +      for worker_result in worker_results: | 
| +        result, output, input_filename, source_dir = worker_result | 
| +        input_path = os.path.join(source_dir, input_filename) | 
| +        sys.stdout.write(output) | 
| +        handle_result(test_suppressor, input_filename, input_path, result, | 
| +                      surprises, failures) | 
| +      pool.close() | 
| +    except KeyboardInterrupt: | 
| +      pool.terminate() | 
| +    finally: | 
| +      pool.join() | 
| +  else: | 
| +    for test_case in test_cases: | 
| +      input_filename, source_dir = test_case | 
| +      result = test_one_file(input_filename, source_dir, working_dir, | 
| +                             pdfium_test_path, image_differ) | 
| +      handle_result(test_suppressor, input_filename, input_path, result, | 
| +                    surprises, failures) | 
| + | 
| +  if surprises: | 
| +    surprises.sort() | 
| +    print '\n\nUnexpected Successes:' | 
| +    for surprise in surprises: | 
| +      print surprise; | 
| + | 
| +  if failures: | 
| +    failures.sort() | 
| +    print '\n\nSummary of Failures:' | 
| +    for failure in failures: | 
| +      print failure | 
| +    return 1 | 
| + | 
| +  return 0 | 
| + | 
|  | 
| if __name__ == '__main__': | 
| sys.exit(main()) | 
|  |