• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
6import distutils.spawn
7import itertools
8import os
9import shutil
10import sys
11
12# pylint: disable=relative-import
13import common
14
15
16class PNGDiffer():
17
18  def __init__(self, finder, reverse_byte_order):
19    self.pdfium_diff_path = finder.ExecutablePath('pdfium_diff')
20    self.os_name = finder.os_name
21    self.reverse_byte_order = reverse_byte_order
22
23  def CheckMissingTools(self, regenerate_expected):
24    if (regenerate_expected and self.os_name == 'linux' and
25        not distutils.spawn.find_executable('optipng')):
26      return 'Please install "optipng" to regenerate expected images.'
27    return None
28
29  def GetActualFiles(self, input_filename, source_dir, working_dir):
30    actual_paths = []
31    path_templates = PathTemplates(input_filename, source_dir, working_dir)
32
33    for page in itertools.count():
34      actual_path = path_templates.GetActualPath(page)
35      expected_path = path_templates.GetExpectedPath(page)
36      platform_expected_path = path_templates.GetPlatformExpectedPath(
37          self.os_name, page)
38      if os.path.exists(platform_expected_path):
39        expected_path = platform_expected_path
40      elif not os.path.exists(expected_path):
41        break
42      actual_paths.append(actual_path)
43
44    return actual_paths
45
46  def HasDifferences(self, input_filename, source_dir, working_dir):
47    path_templates = PathTemplates(input_filename, source_dir, working_dir)
48
49    for page in itertools.count():
50      actual_path = path_templates.GetActualPath(page)
51      expected_path = path_templates.GetExpectedPath(page)
52      # PDFium tests should be platform independent. Platform based results are
53      # used to capture platform dependent implementations.
54      platform_expected_path = path_templates.GetPlatformExpectedPath(
55          self.os_name, page)
56      if (not os.path.exists(expected_path) and
57          not os.path.exists(platform_expected_path)):
58        if page == 0:
59          print "WARNING: no expected results files for " + input_filename
60        if os.path.exists(actual_path):
61          print('FAILURE: Missing expected result for 0-based page %d of %s' %
62                (page, input_filename))
63          return True
64        break
65      print "Checking " + actual_path
66      sys.stdout.flush()
67      if os.path.exists(expected_path):
68        cmd = [self.pdfium_diff_path]
69        if self.reverse_byte_order:
70          cmd.append('--reverse-byte-order')
71        cmd.extend([expected_path, actual_path])
72        error = common.RunCommand(cmd)
73      else:
74        error = 1
75      if error:
76        # When failed, we check against platform based results.
77        if os.path.exists(platform_expected_path):
78          cmd = [self.pdfium_diff_path]
79          if self.reverse_byte_order:
80            cmd.append('--reverse-byte-order')
81          cmd.extend([platform_expected_path, actual_path])
82          error = common.RunCommand(cmd)
83        if error:
84          print "FAILURE: " + input_filename + "; " + str(error)
85          return True
86
87    return False
88
89  def Regenerate(self, input_filename, source_dir, working_dir, platform_only):
90    path_templates = PathTemplates(input_filename, source_dir, working_dir)
91
92    for page in itertools.count():
93      # Loop through the generated page images. Stop when there is a page
94      # missing a png, which means the document ended.
95      actual_path = path_templates.GetActualPath(page)
96      if not os.path.isfile(actual_path):
97        break
98
99      platform_expected_path = path_templates.GetPlatformExpectedPath(
100          self.os_name, page)
101
102      # If there is a platform expected png, we will overwrite it. Otherwise,
103      # overwrite the generic png in "all" mode, or do nothing in "platform"
104      # mode.
105      if os.path.exists(platform_expected_path):
106        expected_path = platform_expected_path
107      elif not platform_only:
108        expected_path = path_templates.GetExpectedPath(page)
109      else:
110        continue
111
112      shutil.copyfile(actual_path, expected_path)
113      common.RunCommand(['optipng', expected_path])
114
115
116ACTUAL_TEMPLATE = '.pdf.%d.png'
117EXPECTED_TEMPLATE = '_expected' + ACTUAL_TEMPLATE
118PLATFORM_EXPECTED_TEMPLATE = '_expected_%s' + ACTUAL_TEMPLATE
119
120
121class PathTemplates(object):
122
123  def __init__(self, input_filename, source_dir, working_dir):
124    input_root, _ = os.path.splitext(input_filename)
125    self.actual_path_template = os.path.join(working_dir,
126                                             input_root + ACTUAL_TEMPLATE)
127    self.expected_path = os.path.join(source_dir,
128                                      input_root + EXPECTED_TEMPLATE)
129    self.platform_expected_path = os.path.join(
130        source_dir, input_root + PLATFORM_EXPECTED_TEMPLATE)
131
132  def GetActualPath(self, page):
133    return self.actual_path_template % page
134
135  def GetExpectedPath(self, page):
136    return self.expected_path % page
137
138  def GetPlatformExpectedPath(self, platform, page):
139    return self.platform_expected_path % (platform, page)
140