aboutsummaryrefslogtreecommitdiff
path: root/testing/tools/pngdiffer.py
blob: a469506d3462c2fdfb54fa8f8f962fe2c1177b25 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
#!/usr/bin/env python
# Copyright 2015 The PDFium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

import distutils.spawn
import itertools
import os
import shutil
import sys

# pylint: disable=relative-import
import common


class PNGDiffer():

  def __init__(self, finder, reverse_byte_order):
    self.pdfium_diff_path = finder.ExecutablePath('pdfium_diff')
    self.os_name = finder.os_name
    self.reverse_byte_order = reverse_byte_order

  def CheckMissingTools(self, regenerate_expected):
    if (regenerate_expected and self.os_name == 'linux' and
        not distutils.spawn.find_executable('optipng')):
      return 'Please install "optipng" to regenerate expected images.'
    return None

  def GetActualFiles(self, input_filename, source_dir, working_dir):
    actual_paths = []
    path_templates = PathTemplates(input_filename, source_dir, working_dir)

    for page in itertools.count():
      actual_path = path_templates.GetActualPath(page)
      expected_path = path_templates.GetExpectedPath(page)
      platform_expected_path = path_templates.GetPlatformExpectedPath(
          self.os_name, page)
      if os.path.exists(platform_expected_path):
        expected_path = platform_expected_path
      elif not os.path.exists(expected_path):
        break
      actual_paths.append(actual_path)

    return actual_paths

  def HasDifferences(self, input_filename, source_dir, working_dir):
    path_templates = PathTemplates(input_filename, source_dir, working_dir)

    for page in itertools.count():
      actual_path = path_templates.GetActualPath(page)
      expected_path = path_templates.GetExpectedPath(page)
      # PDFium tests should be platform independent. Platform based results are
      # used to capture platform dependent implementations.
      platform_expected_path = path_templates.GetPlatformExpectedPath(
          self.os_name, page)
      if (not os.path.exists(expected_path) and
          not os.path.exists(platform_expected_path)):
        if page == 0:
          print "WARNING: no expected results files for " + input_filename
        if os.path.exists(actual_path):
          print('FAILURE: Missing expected result for 0-based page %d of %s' %
                (page, input_filename))
          return True
        break
      print "Checking " + actual_path
      sys.stdout.flush()
      if os.path.exists(expected_path):
        cmd = [self.pdfium_diff_path]
        if self.reverse_byte_order:
          cmd.append('--reverse-byte-order')
        cmd.extend([expected_path, actual_path])
        error = common.RunCommand(cmd)
      else:
        error = 1
      if error:
        # When failed, we check against platform based results.
        if os.path.exists(platform_expected_path):
          cmd = [self.pdfium_diff_path]
          if self.reverse_byte_order:
            cmd.append('--reverse-byte-order')
          cmd.extend([platform_expected_path, actual_path])
          error = common.RunCommand(cmd)
        if error:
          print "FAILURE: " + input_filename + "; " + str(error)
          return True

    return False

  def Regenerate(self, input_filename, source_dir, working_dir, platform_only):
    path_templates = PathTemplates(input_filename, source_dir, working_dir)

    for page in itertools.count():
      # Loop through the generated page images. Stop when there is a page
      # missing a png, which means the document ended.
      actual_path = path_templates.GetActualPath(page)
      if not os.path.isfile(actual_path):
        break

      platform_expected_path = path_templates.GetPlatformExpectedPath(
          self.os_name, page)

      # If there is a platform expected png, we will overwrite it. Otherwise,
      # overwrite the generic png in "all" mode, or do nothing in "platform"
      # mode.
      if os.path.exists(platform_expected_path):
        expected_path = platform_expected_path
      elif not platform_only:
        expected_path = path_templates.GetExpectedPath(page)
      else:
        continue

      shutil.copyfile(actual_path, expected_path)
      common.RunCommand(['optipng', expected_path])


ACTUAL_TEMPLATE = '.pdf.%d.png'
EXPECTED_TEMPLATE = '_expected' + ACTUAL_TEMPLATE
PLATFORM_EXPECTED_TEMPLATE = '_expected_%s' + ACTUAL_TEMPLATE


class PathTemplates(object):

  def __init__(self, input_filename, source_dir, working_dir):
    input_root, _ = os.path.splitext(input_filename)
    self.actual_path_template = os.path.join(working_dir,
                                             input_root + ACTUAL_TEMPLATE)
    self.expected_path = os.path.join(source_dir,
                                      input_root + EXPECTED_TEMPLATE)
    self.platform_expected_path = os.path.join(
        source_dir, input_root + PLATFORM_EXPECTED_TEMPLATE)

  def GetActualPath(self, page):
    return self.actual_path_template % page

  def GetExpectedPath(self, page):
    return self.expected_path % page

  def GetPlatformExpectedPath(self, platform, page):
    return self.platform_expected_path % (platform, page)