Beispiel #1
0
def main():
    parser = optparse.OptionParser()
    parser.add_option('--build-dir',
                      default=os.path.join('out', 'Debug'),
                      help='relative path from the base source directory')
    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$')
    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):
                    result = test_one_file(input_filename, source_dir,
                                           working_dir, pdfium_test_path,
                                           image_differ)
                    if test_suppressor.IsSuppressed(input_filename):
                        if result:
                            surprises.append(input_path)
                    else:
                        if not result:
                            failures.append(input_path)

    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
Beispiel #2
0
def main():
    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(
        '--wrapper',
        default='',
        dest="wrapper",
        help='Dr. Memory wrapper for running test under Dr. Memory')
    options, args = parser.parse_args()
    finder = common.DirectoryFinder(options.build_dir)
    fixup_path = finder.ScriptPath('fixup_pdf_template.py')
    source_dir = finder.TestingDir(os.path.join('resources', 'pixel'))
    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', 'pixel'))
    if not os.path.exists(working_dir):
        os.makedirs(working_dir)

    test_suppressor = suppressor.Suppressor(finder)
    image_differ = pngdiffer.PNGDiffer(finder)

    input_files = []
    if len(args):
        for file_name in args:
            input_files.append(file_name.replace(".pdf", ".in"))
    else:
        input_files = os.listdir(source_dir)

    failures = []
    input_file_re = re.compile('^[a-zA-Z0-9_.]+[.]in$')
    for input_filename in input_files:
        if input_file_re.match(input_filename):
            input_path = os.path.join(source_dir, input_filename)
            if os.path.isfile(input_path):
                if test_suppressor.IsSuppressed(input_filename):
                    continue
                if not generate_and_test(
                        input_filename, source_dir, working_dir, fixup_path,
                        pdfium_test_path, image_differ, options.wrapper):
                    failures.append(input_path)

    if failures:
        failures.sort()
        print '\n\nSummary of Failures:'
        for failure in failures:
            print failure
        return 1
    return 0
Beispiel #3
0
def main():
    parser = optparse.OptionParser()
    parser.add_option('--build-dir',
                      default=os.path.join('out', 'Debug'),
                      help='relative path from the base source directory')
    options, args = parser.parse_args()
    finder = common.DirectoryFinder(options.build_dir)
    fixup_path = finder.ScriptPath('fixup_pdf_template.py')
    source_dir = finder.TestingDir(os.path.join('resources', 'pixel'))
    pdfium_test_path = finder.ExecutablePath('pdfium_test')
    working_dir = finder.WorkingDir(os.path.join('testing', 'pixel'))
    if not os.path.exists(working_dir):
        os.makedirs(working_dir)

    test_suppressor = suppressor.Suppressor(finder)
    image_differ = pngdiffer.PNGDiffer(finder)

    failures = []
    input_file_re = re.compile('^[a-zA-Z0-9_.]+[.]in$')
    for input_filename in os.listdir(source_dir):
        if input_file_re.match(input_filename):
            input_path = os.path.join(source_dir, input_filename)
            if os.path.isfile(input_path):
                if test_suppressor.IsSuppressed(input_filename):
                    continue
                if not generate_and_test(input_filename, source_dir,
                                         working_dir, fixup_path,
                                         pdfium_test_path, image_differ):
                    failures.append(input_path)

    if failures:
        print '\n\nSummary of Failures:'
        for failure in failures:
            print failure
        return 1
    return 0
Beispiel #4
0
  def Run(self):
    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')

    parser.add_option('--gold_properties', default='', dest="gold_properties",
                      help='Key value pairs that are written to the top level '
                           'of the JSON file that is ingested by Gold.')

    parser.add_option('--gold_key', default='', dest="gold_key",
                      help='Key value pairs that are added to the "key" field '
                           'of the JSON file that is ingested by Gold.')

    parser.add_option('--gold_output_dir', default='', dest="gold_output_dir",
                      help='Path of where to write the JSON output to be '
                           'uploaded to Gold.')

    parser.add_option('--gold_ignore_hashes', default='',
                      dest="gold_ignore_hashes",
                      help='Path to a file with MD5 hashes we wish to ignore.')

    parser.add_option('--regenerate_expected', default='',
                      dest="regenerate_expected",
                      help='Regenerates expected images. Valid values are '
                           '"all" to regenerate all expected pngs, and '
                           '"platform" to regenerate only platform-specific '
                           'expected pngs.')

    parser.add_option('--ignore_errors', action="store_true",
                      dest="ignore_errors",
                      help='Prevents the return value from being non-zero '
                           'when image comparison fails.')

    self.options, self.args = parser.parse_args()

    if (self.options.regenerate_expected
        and self.options.regenerate_expected not in ['all', 'platform']) :
      print 'FAILURE: --regenerate_expected must be "all" or "platform"'
      return 1

    finder = common.DirectoryFinder(self.options.build_dir)
    self.fixup_path = finder.ScriptPath('fixup_pdf_template.py')
    self.text_diff_path = finder.ScriptPath('text_diff.py')
    self.font_dir = os.path.join(finder.TestingDir(), 'resources', 'fonts')

    self.source_dir = finder.TestingDir()
    if self.test_dir != 'corpus':
      test_dir = finder.TestingDir(os.path.join('resources', self.test_dir))
    else:
      test_dir = finder.TestingDir(self.test_dir)

    self.pdfium_test_path = finder.ExecutablePath('pdfium_test')
    if not os.path.exists(self.pdfium_test_path):
      print "FAILURE: Can't find test executable '%s'" % self.pdfium_test_path
      print 'Use --build-dir to specify its location.'
      return 1

    self.working_dir = finder.WorkingDir(os.path.join('testing', self.test_dir))
    if not os.path.exists(self.working_dir):
      os.makedirs(self.working_dir)

    self.feature_string = subprocess.check_output([self.pdfium_test_path,
                                                   '--show-config'])
    self.test_suppressor = suppressor.Suppressor(finder, self.feature_string)
    self.image_differ = pngdiffer.PNGDiffer(finder)
    error_message = self.image_differ.CheckMissingTools(
        self.options.regenerate_expected)
    if error_message:
      print "FAILURE: %s" % error_message
      return 1

    self.gold_baseline = gold.GoldBaseline(self.options.gold_properties)

    walk_from_dir = finder.TestingDir(test_dir);

    self.test_cases = []
    self.execution_suppressed_cases = []
    input_file_re = re.compile('^.+[.](in|pdf)$')
    if self.args:
      for file_name in self.args:
        file_name.replace('.pdf', '.in')
        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

        self.test_cases.append((os.path.basename(input_path),
                           os.path.dirname(input_path)))
    else:
      for file_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(file_dir, input_filename)
            if self.test_suppressor.IsExecutionSuppressed(input_path):
              self.execution_suppressed_cases.append(input_path)
            else:
              if os.path.isfile(input_path):
                self.test_cases.append((input_filename, file_dir))

    self.test_cases.sort()
    self.failures = []
    self.surprises = []
    self.result_suppressed_cases = []

    # Collect Gold results if an output directory was named.
    self.gold_results = None
    if self.options.gold_output_dir:
      self.gold_results = gold.GoldResults(self.test_type,
                                           self.options.gold_output_dir,
                                           self.options.gold_properties,
                                           self.options.gold_key,
                                           self.options.gold_ignore_hashes)

    if self.options.num_workers > 1 and len(self.test_cases) > 1:
      try:
        pool = multiprocessing.Pool(self.options.num_workers)
        worker_func = functools.partial(TestOneFileParallel, self)

        worker_results = pool.imap(worker_func, self.test_cases)
        for worker_result in worker_results:
          result, input_filename, source_dir = worker_result
          input_path = os.path.join(source_dir, input_filename)

          self.HandleResult(input_filename, input_path, result)

      except KeyboardInterrupt:
        pool.terminate()
      finally:
        pool.close()
        pool.join()
    else:
      for test_case in self.test_cases:
        input_filename, input_file_dir = test_case
        result = self.GenerateAndTest(input_filename, input_file_dir)
        self.HandleResult(input_filename,
                          os.path.join(input_file_dir, input_filename), result)

    if self.gold_results:
      self.gold_results.WriteResults()

    if self.surprises:
      self.surprises.sort()
      print '\n\nUnexpected Successes:'
      for surprise in self.surprises:
        print surprise

    if self.failures:
      self.failures.sort()
      print '\n\nSummary of Failures:'
      for failure in self.failures:
        print failure

    self._PrintSummary()

    if self.failures:
      if not self.options.ignore_errors:
        return 1

    return 0
Beispiel #5
0
    def Run(self):
        # Running a test defines a number of attributes on the fly.
        # pylint: disable=attribute-defined-outside-init

        parser = argparse.ArgumentParser()

        parser.add_argument(
            '--build-dir',
            default=os.path.join('out', 'Debug'),
            help='relative path from the base source directory')

        parser.add_argument('-j',
                            default=multiprocessing.cpu_count(),
                            dest='num_workers',
                            type=int,
                            help='run NUM_WORKERS jobs in parallel')

        parser.add_argument(
            '--disable-javascript',
            action="store_true",
            dest="disable_javascript",
            help='Prevents JavaScript from executing in PDF files.')

        parser.add_argument('--disable-xfa',
                            action="store_true",
                            dest="disable_xfa",
                            help='Prevents processing XFA forms.')

        parser.add_argument('--render-oneshot',
                            action="store_true",
                            dest="render_oneshot",
                            help='Sets whether to use the oneshot renderer.')

        parser.add_argument(
            '--run-skia-gold',
            action='store_true',
            default=False,
            help='When flag is on, skia gold tests will be run.')

        # TODO: Remove when pdfium recipe stops passing this argument
        parser.add_argument(
            '--gold_properties',
            default='',
            dest="gold_properties",
            help='Key value pairs that are written to the top level '
            'of the JSON file that is ingested by Gold.')

        # TODO: Remove when pdfium recipe stops passing this argument
        parser.add_argument(
            '--gold_ignore_hashes',
            default='',
            dest="gold_ignore_hashes",
            help='Path to a file with MD5 hashes we wish to ignore.')

        parser.add_argument(
            '--regenerate_expected',
            default='',
            dest="regenerate_expected",
            help='Regenerates expected images. Valid values are '
            '"all" to regenerate all expected pngs, and '
            '"platform" to regenerate only platform-specific '
            'expected pngs.')

        parser.add_argument(
            '--reverse-byte-order',
            action='store_true',
            dest="reverse_byte_order",
            help='Run image-based tests using --reverse-byte-order.')

        parser.add_argument(
            '--ignore_errors',
            action="store_true",
            dest="ignore_errors",
            help='Prevents the return value from being non-zero '
            'when image comparison fails.')

        skia_gold.add_skia_gold_args(parser)

        self.options, self.inputted_file_paths = parser.parse_known_args()

        if (self.options.regenerate_expected and
                self.options.regenerate_expected not in ['all', 'platform']):
            print('FAILURE: --regenerate_expected must be "all" or "platform"')
            return 1

        finder = common.DirectoryFinder(self.options.build_dir)
        self.fixup_path = finder.ScriptPath('fixup_pdf_template.py')
        self.text_diff_path = finder.ScriptPath('text_diff.py')
        self.font_dir = os.path.join(finder.TestingDir(), 'resources', 'fonts')

        self.source_dir = finder.TestingDir()
        if self.test_dir != 'corpus':
            test_dir = finder.TestingDir(
                os.path.join('resources', self.test_dir))
        else:
            test_dir = finder.TestingDir(self.test_dir)

        self.pdfium_test_path = finder.ExecutablePath('pdfium_test')
        if not os.path.exists(self.pdfium_test_path):
            print("FAILURE: Can't find test executable '{}'".format(
                self.pdfium_test_path))
            print('Use --build-dir to specify its location.')
            return 1

        self.working_dir = finder.WorkingDir(
            os.path.join('testing', self.test_dir))
        shutil.rmtree(self.working_dir, ignore_errors=True)
        os.makedirs(self.working_dir)

        self.features = subprocess.check_output(
            [self.pdfium_test_path,
             '--show-config']).decode('utf-8').strip().split(',')
        self.test_suppressor = suppressor.Suppressor(
            finder, self.features, self.options.disable_javascript,
            self.options.disable_xfa)
        self.image_differ = pngdiffer.PNGDiffer(
            finder, self.features, self.options.reverse_byte_order)
        error_message = self.image_differ.CheckMissingTools(
            self.options.regenerate_expected)
        if error_message:
            print('FAILURE:', error_message)
            return 1

        walk_from_dir = finder.TestingDir(test_dir)

        self.test_cases = []
        self.execution_suppressed_cases = []
        input_file_re = re.compile('^.+[.](in|pdf)$')
        if self.inputted_file_paths:
            for file_name in self.inputted_file_paths:
                file_name.replace('.pdf', '.in')
                input_path = os.path.join(walk_from_dir, file_name)
                if not os.path.isfile(input_path):
                    print("Can't find test file '{}'".format(file_name))
                    return 1

                self.test_cases.append((os.path.basename(input_path),
                                        os.path.dirname(input_path)))
        else:
            for file_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(file_dir, input_filename)
                        if self.test_suppressor.IsExecutionSuppressed(
                                input_path):
                            self.execution_suppressed_cases.append(input_path)
                        else:
                            if os.path.isfile(input_path):
                                self.test_cases.append(
                                    (input_filename, file_dir))

        self.test_cases.sort()
        self.failures = []
        self.surprises = []
        self.skia_gold_successes = []
        self.skia_gold_unexpected_successes = []
        self.skia_gold_failures = []
        self.result_suppressed_cases = []

        gold_results = []
        if self.test_type not in TEXT_TESTS and self.options.run_skia_gold:
            assert self.options.gold_output_dir
            # Clear out and create top level gold output directory before starting
            skia_gold.clear_gold_output_dir(self.options.gold_output_dir)

        if self.options.num_workers > 1 and len(self.test_cases) > 1:
            skia_gold_parallel_inputs = []
            try:
                pool = multiprocessing.Pool(self.options.num_workers)
                worker_func = functools.partial(TestOneFileParallel, self)

                worker_results = pool.imap(worker_func, self.test_cases)
                for worker_result in worker_results:
                    result, input_filename, source_dir = worker_result
                    input_path = os.path.join(source_dir, input_filename)

                    self.HandleResult(input_filename, input_path, result)

                    if self.test_type not in TEXT_TESTS and self.options.run_skia_gold:
                        _, image_paths = result
                        if image_paths:
                            path_filename_tuples = [(path, input_filename)
                                                    for path, _ in image_paths]
                            skia_gold_parallel_inputs.extend(
                                path_filename_tuples)

            except KeyboardInterrupt:
                pool.terminate()
            finally:
                pool.close()
                pool.join()

            if skia_gold_parallel_inputs and self.test_type not in TEXT_TESTS:
                try:
                    pool = multiprocessing.Pool(self.options.num_workers)
                    gold_worker_func = functools.partial(RunSkiaWrapper, self)

                    def chunk_input(whole_list):
                        chunked = []
                        size = len(whole_list) // self.options.num_workers
                        for i in range(0, len(whole_list), size):
                            chunked.append(whole_list[i:i + size])
                        return chunked

                    chunked_input = chunk_input(skia_gold_parallel_inputs)
                    pool_results = pool.imap(gold_worker_func, chunked_input)
                    for r in pool_results:
                        gold_results.extend(r)
                except KeyboardInterrupt:
                    pool.terminate()
                finally:
                    pool.close()
                    pool.join()
        else:
            for test_case in self.test_cases:
                input_filename, input_file_dir = test_case
                result = self.GenerateAndTest(input_filename, input_file_dir)
                self.HandleResult(input_filename,
                                  os.path.join(input_file_dir, input_filename),
                                  result)

                _, image_paths = result
                if image_paths and self.test_type not in TEXT_TESTS and \
                    self.options.run_skia_gold:
                    for img_path, _ in image_paths:
                        test_name, skia_success = self.RunSkia(img_path)
                        gold_results.append(
                            (test_name, skia_success, input_filename))

        for r in gold_results:
            test_name, skia_success, input_filename = r
            if skia_success:
                if self.test_suppressor.IsResultSuppressed(input_filename):
                    self.skia_gold_unexpected_successes.append(test_name)
                else:
                    self.skia_gold_successes.append(test_name)
            else:
                self.skia_gold_failures.append(test_name)

        # For some reason, summary will be cut off from stdout on windows if
        # _PrintSummary() is called at the end
        # TODO(crbug.com/pdfium/1657): Once resolved, move _PrintSummary() back
        # down to the end
        self._PrintSummary()

        if self.surprises:
            self.surprises.sort()
            print('\nUnexpected Successes:')
            for surprise in self.surprises:
                print(surprise)

        if self.failures:
            self.failures.sort()
            print('\nSummary of Failures:')
            for failure in self.failures:
                print(failure)

        if self.skia_gold_unexpected_successes:
            self.skia_gold_unexpected_successes.sort()
            print('\nUnexpected Skia Gold Successes:')
            for surprise in self.skia_gold_unexpected_successes:
                print(surprise)

        if self.skia_gold_failures:
            self.skia_gold_failures.sort()
            print('\nSummary of Skia Gold Failures:')
            for failure in self.skia_gold_failures:
                print(failure)

        if self.failures:
            if not self.options.ignore_errors:
                return 1

        return 0
Beispiel #6
0
    def Run(self):
        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')

        parser.add_option('--wrapper',
                          default='',
                          dest="wrapper",
                          help='wrapper for running test under Dr. Memory')

        parser.add_option(
            '--gold_properties',
            default='',
            dest="gold_properties",
            help=
            'Key value pairs that are written to the top level of the JSON file that is ingested by Gold.'
        )

        parser.add_option(
            '--gold_key',
            default='',
            dest="gold_key",
            help=
            'Key value pairs that are added to the "key" field of the JSON file that is ingested by Gold.'
        )

        parser.add_option(
            '--gold_output_dir',
            default='',
            dest="gold_output_dir",
            help=
            'Path of where to write the JSON output to be uploaded to Gold.')

        parser.add_option(
            '--ignore_errors',
            action="store_true",
            dest="ignore_errors",
            help=
            'Prevents the return value from being non-zero when image comparison fails.'
        )

        options, args = parser.parse_args()

        finder = common.DirectoryFinder(options.build_dir)
        self.fixup_path = finder.ScriptPath('fixup_pdf_template.py')
        self.text_diff_path = finder.ScriptPath('text_diff.py')

        self.drmem_wrapper = options.wrapper

        self.source_dir = finder.TestingDir()
        if self.test_dir != 'corpus':
            test_dir = finder.TestingDir(
                os.path.join('resources', self.test_dir))
        else:
            test_dir = finder.TestingDir(self.test_dir)

        self.pdfium_test_path = finder.ExecutablePath('pdfium_test')
        if not os.path.exists(self.pdfium_test_path):
            print "FAILURE: Can't find test executable '%s'" % self.pdfium_test_path
            print "Use --build-dir to specify its location."
            return 1

        self.working_dir = finder.WorkingDir(
            os.path.join('testing', self.test_dir))
        if not os.path.exists(self.working_dir):
            os.makedirs(self.working_dir)

        self.feature_string = subprocess.check_output(
            [self.pdfium_test_path, '--show-config'])
        self.test_suppressor = suppressor.Suppressor(finder,
                                                     self.feature_string)
        self.image_differ = pngdiffer.PNGDiffer(finder)

        walk_from_dir = finder.TestingDir(test_dir)

        test_cases = []
        input_file_re = re.compile('^[a-zA-Z0-9_.]+[.](in|pdf)$')
        if len(args):
            for file_name in args:
                file_name.replace(".pdf", ".in")
                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 file_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(file_dir, input_filename)
                        if not self.test_suppressor.IsExecutionSuppressed(
                                input_path):
                            if os.path.isfile(input_path):
                                test_cases.append((input_filename, file_dir))

        self.failures = []
        self.surprises = []

        # Collect Gold results if an output directory was named.
        self.gold_results = None
        if options.gold_output_dir:
            self.gold_results = gold.GoldResults("pdfium",
                                                 options.gold_output_dir,
                                                 options.gold_properties,
                                                 options.gold_key)

        if options.num_workers > 1 and len(test_cases) > 1:
            try:
                pool = multiprocessing.Pool(options.num_workers)
                worker_func = functools.partial(TestOneFileParallel, self)

                worker_results = pool.imap(worker_func, test_cases)
                for worker_result in worker_results:
                    result, input_filename, source_dir = worker_result
                    input_path = os.path.join(source_dir, input_filename)

                    self.HandleResult(input_filename, input_path, result)

            except KeyboardInterrupt:
                pool.terminate()
            finally:
                pool.close()
                pool.join()
        else:
            for test_case in test_cases:
                input_filename, input_file_dir = test_case
                result = self.GenerateAndTest(input_filename, input_file_dir)
                self.HandleResult(input_filename,
                                  os.path.join(input_file_dir, input_filename),
                                  result)

        if self.gold_results:
            self.gold_results.WriteResults()

        if self.surprises:
            self.surprises.sort()
            print '\n\nUnexpected Successes:'
            for surprise in self.surprises:
                print surprise

        if self.failures:
            self.failures.sort()
            print '\n\nSummary of Failures:'
            for failure in self.failures:
                print failure
                if not options.ignore_errors:
                    return 1
        return 0
def main():
  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')
  parser.add_option('--wrapper', default='', dest="wrapper",
                    help='Dr. Memory wrapper for running test under Dr. Memory')
  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,
                             options.wrapper)
      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