summaryrefslogtreecommitdiffstats
path: root/o3d/tests/selenium/pdiff_test.py
blob: 0a91f55c90eefd7b11345823512ed3e1e9ed7642 (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
import os
import re
import subprocess
import unittest
import sys

import selenium_utilities
import selenium_constants

class PDiffTest(unittest.TestCase):
  """A perceptual diff test class, for running perceptual diffs on any
  number of screenshots."""
  
  def __init__(self, name, num_screenshots, screenshot_name, pdiff_path,
               gen_dir, ref_dir, options):
    unittest.TestCase.__init__(self, name)
    self.name = name
    self.num_screenshots = num_screenshots
    self.screenshot_name = screenshot_name
    self.pdiff_path = pdiff_path
    self.gen_dir = gen_dir
    self.ref_dir = ref_dir
    self.options = options

  def shortDescription(self):
    """override unittest.TestCase shortDescription for our own descriptions."""
    return "Screenshot comparison for: " + self.name
    
  def PDiffTest(self):
    """Runs a generic Perceptual Diff test."""
    # Get arguments for perceptual diff.
    pixel_threshold = "10"
    alpha_threshold = "1.0"
    use_colorfactor = False
    use_downsample = False
    use_edge = True
    edge_threshold = "5"

    for opt in self.options:
      if opt.startswith("pdiff_threshold"):
        pixel_threshold = selenium_utilities.GetArgument(opt)
      elif (opt.startswith("pdiff_threshold_mac") and
            sys.platform == "darwin"):
        pixel_threshold = selenium_utilities.GetArgument(opt)
      elif (opt.startswith("pdiff_threshold_win") and
            sys.platform == 'win32' or sys.platform == "cygwin"):
        pixel_threshold = selenium_utilities.GetArgument(opt)
      elif (opt.startswith("pdiff_threshold_linux") and
            sys.platform[:5] == "linux"):
        pixel_threshold = selenium_utilities.GetArgument(opt)
      elif (opt.startswith("colorfactor")):
        colorfactor = selenium_utilities.GetArgument(opt)
        use_colorfactor = True
      elif (opt.startswith("downsample")):
        downsample_factor = selenium_utilities.GetArgument(opt)
        use_downsample = True
      elif (opt.startswith("pdiff_edge_ignore_off")):
        use_edge = False
      elif (opt.startswith("pdiff_edge_threshold")):
        edge_threshold = selenium_utilities.GetArgument(opt)

    results = []
    # Loop over number of screenshots.
    for screenshot_no in range(self.num_screenshots):
      # Find reference image.
      shotname = self.screenshot_name + str(screenshot_no + 1)
      J = os.path.join
      platform_img_path = J(self.ref_dir,
                            selenium_constants.PLATFORM_SCREENSHOT_DIR,
                            shotname + '_reference.png')
      reg_img_path = J(self.ref_dir,
                       selenium_constants.DEFAULT_SCREENSHOT_DIR,
                       shotname + '_reference.png')

      if os.path.exists(platform_img_path):
        ref_img_path = platform_img_path
      elif os.path.exists(reg_img_path):
        ref_img_path = reg_img_path
      else:
        self.fail('Reference image for ' + shotname + ' not found.')
  
      # Find generated image.
      gen_img_path = J(self.gen_dir, shotname + '.png')
      diff_img_path = J(self.gen_dir, 'cmp_' + shotname + '.png')
       
      self.assertTrue(os.path.exists(gen_img_path),
                      'Generated screenshot for ' + shotname + ' not found.\n')

      # Run perceptual diff
      arguments = [self.pdiff_path,
                   ref_img_path,
                   gen_img_path,
                   "-output", diff_img_path,
                   "-fov", "45",
                   "-alphaThreshold", alpha_threshold,
                   # Turn on verbose output for the percetual diff so we
                   # can see how far off we are on the threshold.
                   "-verbose",
                   # Set the threshold to zero so we can get a count
                   # of the different pixels.  This causes the program
                   # to return failure for most images, but we can compare
                   # the values ourselves below.
                   "-threshold", "0"]
      if use_colorfactor:
        arguments += ["-colorfactor", colorfactor]
      if use_downsample:
        arguments += ["-downsample", downsample_factor]
      if use_edge:
        arguments += ["-ignoreEdges", edge_threshold]

      pdiff_pipe = subprocess.Popen(arguments,
                                    stdout=subprocess.PIPE,
                                    stderr=subprocess.PIPE)
      (pdiff_stdout, pdiff_stderr) = pdiff_pipe.communicate()
      result = pdiff_pipe.returncode
      # Find out how many pixels were different by looking at the output.
      pixel_re = re.compile("(\d+) pixels are different", re.DOTALL)
      pixel_match = pixel_re.search(pdiff_stdout)
      different_pixels = "0"
      if pixel_match:
        different_pixels = pixel_match.group(1)

      results += [(shotname, int(different_pixels))]

    all_tests_passed = True
    msg = "Pixel threshold is %s. Failing screenshots:\n" % pixel_threshold
    for name, pixels in results:
      if pixels >= int(pixel_threshold):
        all_tests_passed = False
        msg += "     %s, differing by %s\n" % (name, str(pixels))

    self.assertTrue(all_tests_passed, msg)