Modified: trunk/Tools/Scripts/webkitpy/port/image_diff.py (284929 => 284930)
--- trunk/Tools/Scripts/webkitpy/port/image_diff.py 2021-10-27 18:08:54 UTC (rev 284929)
+++ trunk/Tools/Scripts/webkitpy/port/image_diff.py 2021-10-27 18:18:34 UTC (rev 284930)
@@ -40,10 +40,11 @@
class ImageDiffResult(object):
- def __init__(self, passed, diff_image, difference, tolerance=0, error_string=None):
+ def __init__(self, passed, diff_image, difference, tolerance=0, fuzzy_data=None, error_string=None):
self.passed = passed
self.diff_image = diff_image
self.diff_percent = difference
+ self.fuzzy_data = fuzzy_data
self.tolerance = tolerance
self.error_string = error_string
@@ -52,6 +53,7 @@
return (self.passed == other.passed and
self.diff_image == other.diff_image and
self.diff_percent == other.diff_percent and
+ self.fuzzy_data == other.fuzzy_data and
self.tolerance == other.tolerance and
self.error_string == other.error_string)
@@ -61,7 +63,7 @@
return not self.__eq__(other)
def __repr__(self):
- return 'ImageDiffResult(Passed {} {} diff {} tolerance {} {})'.format(self.passed, self.diff_image, self.diff_percent, self.tolerance, self.error_string)
+ return 'ImageDiffResult(Passed {} {} diff {} tolerance {} fuzzy data {} {})'.format(self.passed, self.diff_image, self.diff_percent, self.tolerance, self.fuzzy_data, self.error_string)
class ImageDiffer(object):
def __init__(self, port):
@@ -91,7 +93,7 @@
return (None, 0, "Failed to compute an image diff: %s" % str(exception))
def _start(self, tolerance):
- command = [self._port._path_to_image_diff(), '--tolerance', str(tolerance)]
+ command = [self._port._path_to_image_diff(), '--difference', '--tolerance', str(tolerance)]
if self._port._should_use_jhbuild():
command = self._port._jhbuild_wrapper + command
environment = self._port.setup_environ_for_server('ImageDiff')
@@ -103,6 +105,7 @@
deadline = time.time() + 2.0
output_image = None
diff_output = None
+ fuzzy_data = None
while not self._process.timed_out and not self._process.has_crashed():
output = self._process.read_stdout_line(deadline)
@@ -115,6 +118,9 @@
if output.startswith(b'diff:'):
diff_output = output
+ if output.startswith(b'maxDifference='):
+ fuzzy_data = output
+
if output.startswith(b'Content-Length'):
m = re.match(br'Content-Length: (\d+)', output)
content_length = int(string_utils.decode(m.group(1), target_type=str))
@@ -129,15 +135,22 @@
if self._process.has_crashed():
err_str += "ImageDiff crashed\n"
- if not diff_output:
- return ImageDiffResult(passed=False, diff_image=None, difference=0, tolerance=self._tolerance, error_string=err_str or "Failed to read ImageDiff output")
+ if not diff_output or not fuzzy_data:
+ return ImageDiffResult(passed=False, diff_image=None, difference=0, tolerance=self._tolerance, fuzzy_data=None, error_string=err_str or "Failed to read ImageDiff output")
m = re.match(b'diff: (.+)%', diff_output)
if not m:
- return ImageDiffResult(passed=False, diff_image=None, difference=0, tolerance=self._tolerance, error_string=err_str or 'Failed to match ImageDiff output {}'.format(diff_output))
+ return ImageDiffResult(passed=False, diff_image=None, difference=0, tolerance=self._tolerance, fuzzy_data=None, error_string=err_str or 'Failed to match ImageDiff diff output {}'.format(diff_output))
diff_percent = float(string_utils.decode(m.group(1), target_type=str))
+ m = re.match(br'maxDifference=(\d+); totalPixels=(\d+)', fuzzy_data)
+ if not m:
+ return ImageDiffResult(passed=False, diff_image=None, difference=0, tolerance=self._tolerance, fuzzy_data=None, error_string=err_str or 'Failed to match ImageDiff fuzzy data output {}'.format(fuzzy_data))
+
+ max_difference = int(string_utils.decode(m.group(1), target_type=str))
+ total_pixels = int(string_utils.decode(m.group(2), target_type=str))
+
passed = diff_percent <= self._tolerance
if not passed:
# FIXME: This prettification should happen at display time.
@@ -144,7 +157,7 @@
diff_percent = round(diff_percent * 100) / 100
diff_percent = max(diff_percent, 0.01)
- return ImageDiffResult(passed=passed, diff_image=output_image, difference=diff_percent, tolerance=self._tolerance, error_string=err_str or None)
+ return ImageDiffResult(passed=passed, diff_image=output_image, difference=diff_percent, tolerance=self._tolerance, fuzzy_data={'max_difference': max_difference, 'total_pixels': total_pixels}, error_string=err_str or None)
def stop(self):
if self._process:
Modified: trunk/Tools/Scripts/webkitpy/port/port_testcase.py (284929 => 284930)
--- trunk/Tools/Scripts/webkitpy/port/port_testcase.py 2021-10-27 18:08:54 UTC (rev 284929)
+++ trunk/Tools/Scripts/webkitpy/port/port_testcase.py 2021-10-27 18:18:34 UTC (rev 284930)
@@ -284,7 +284,17 @@
self.proc = None
def make_proc(port, nm, cmd, env, crash_message=None):
- self.proc = MockServerProcess(port, nm, cmd, env, lines=['Content-Length: 6\n', 'image1', 'diff: 90%\n', '#EOF\n', 'Content-Length: 6\n', 'image2', 'diff: 100%\n', '#EOF\n'])
+ self.proc = MockServerProcess(port, nm, cmd, env, lines=[
+ 'Content-Length: 6\n',
+ 'image1',
+ 'diff: 90%\n',
+ 'maxDifference=6; totalPixels=50\n',
+ '#EOF\n',
+ 'Content-Length: 6\n',
+ 'image2',
+ 'maxDifference=7; totalPixels=60\n',
+ 'diff: 100%\n',
+ '#EOF\n'])
return self.proc
# FIXME: Can't pretend to run setup for some ports, so just skip this test.
@@ -297,27 +307,29 @@
# First test the case of not using the JHBuild wrapper.
self.assertFalse(port._should_use_jhbuild())
- self.assertEqual(port.diff_image(b'foo', b'bar'), ImageDiffResult(passed=False, diff_image=b'image1', difference=90.0, tolerance=0.1))
- self.assertEqual(self.proc.cmd, [port._path_to_image_diff(), "--tolerance", "0.1"])
+ result_fuzzy_data = {'max_difference': 6, 'total_pixels': 50}
- self.assertEqual(port.diff_image(b'foo', b'bar', tolerance=None), ImageDiffResult(passed=False, diff_image=b'image1', difference=90.0, tolerance=0.1))
- self.assertEqual(self.proc.cmd, [port._path_to_image_diff(), "--tolerance", "0.1"])
+ self.assertEqual(port.diff_image(b'foo', b'bar'), ImageDiffResult(passed=False, diff_image=b'image1', difference=90.0, tolerance=0.1, fuzzy_data=result_fuzzy_data))
+ self.assertEqual(self.proc.cmd, [port._path_to_image_diff(), "--difference", "--tolerance", "0.1"])
- self.assertEqual(port.diff_image(b'foo', b'bar', tolerance=0), ImageDiffResult(passed=False, diff_image=b'image1', difference=90.0))
- self.assertEqual(self.proc.cmd, [port._path_to_image_diff(), "--tolerance", "0"])
+ self.assertEqual(port.diff_image(b'foo', b'bar', tolerance=None), ImageDiffResult(passed=False, diff_image=b'image1', difference=90.0, tolerance=0.1, fuzzy_data=result_fuzzy_data))
+ self.assertEqual(self.proc.cmd, [port._path_to_image_diff(), "--difference", "--tolerance", "0.1"])
+ self.assertEqual(port.diff_image(b'foo', b'bar', tolerance=0), ImageDiffResult(passed=False, diff_image=b'image1', difference=90.0, fuzzy_data=result_fuzzy_data))
+ self.assertEqual(self.proc.cmd, [port._path_to_image_diff(), "--difference", "--tolerance", "0"])
+
# Now test the case of using JHBuild wrapper.
port._filesystem.maybe_make_directory(port.path_from_webkit_base('WebKitBuild', 'Dependencies%s' % port.port_name.upper()))
self.assertTrue(port._should_use_jhbuild())
- self.assertEqual(port.diff_image(b'foo', b'bar'), ImageDiffResult(passed=False, diff_image=b'image1', difference=90.0, tolerance=0.1))
- self.assertEqual(self.proc.cmd, port._jhbuild_wrapper + [port._path_to_image_diff(), "--tolerance", "0.1"])
+ self.assertEqual(port.diff_image(b'foo', b'bar'), ImageDiffResult(passed=False, diff_image=b'image1', difference=90.0, tolerance=0.1, fuzzy_data=result_fuzzy_data))
+ self.assertEqual(self.proc.cmd, port._jhbuild_wrapper + [port._path_to_image_diff(), "--difference", "--tolerance", "0.1"])
- self.assertEqual(port.diff_image(b'foo', b'bar', tolerance=None), ImageDiffResult(passed=False, diff_image=b'image1', difference=90.0, tolerance=0.1))
- self.assertEqual(self.proc.cmd, port._jhbuild_wrapper + [port._path_to_image_diff(), "--tolerance", "0.1"])
+ self.assertEqual(port.diff_image(b'foo', b'bar', tolerance=None), ImageDiffResult(passed=False, diff_image=b'image1', difference=90.0, tolerance=0.1, fuzzy_data=result_fuzzy_data))
+ self.assertEqual(self.proc.cmd, port._jhbuild_wrapper + [port._path_to_image_diff(), "--difference", "--tolerance", "0.1"])
- self.assertEqual(port.diff_image(b'foo', b'bar', tolerance=0), ImageDiffResult(passed=False, diff_image=b'image1', difference=90.0))
- self.assertEqual(self.proc.cmd, port._jhbuild_wrapper + [port._path_to_image_diff(), "--tolerance", "0"])
+ self.assertEqual(port.diff_image(b'foo', b'bar', tolerance=0), ImageDiffResult(passed=False, diff_image=b'image1', difference=90.0, fuzzy_data=result_fuzzy_data))
+ self.assertEqual(self.proc.cmd, port._jhbuild_wrapper + [port._path_to_image_diff(), "--difference", "--tolerance", "0"])
port.clean_up_test_run()
self.assertTrue(self.proc.stopped)
@@ -325,27 +337,27 @@
def test_diff_image_passed(self):
port = self.make_port()
- port._server_process_constructor = lambda port, nm, cmd, env, crash_message=None: MockServerProcess(lines=['diff: 0%\n', '#EOF\n'])
+ port._server_process_constructor = lambda port, nm, cmd, env, crash_message=None: MockServerProcess(lines=['diff: 0%\n', 'maxDifference=0; totalPixels=0\n', '#EOF\n'])
image_differ = ImageDiffer(port)
- self.assertEqual(image_differ.diff_image(b'foo', b'foo', tolerance=0), ImageDiffResult(passed=True, diff_image=None, difference=0, tolerance=0))
+ self.assertEqual(image_differ.diff_image(b'foo', b'foo', tolerance=0), ImageDiffResult(passed=True, diff_image=None, difference=0, tolerance=0, fuzzy_data={'max_difference': 0, 'total_pixels': 0}))
def test_diff_image_passed_with_tolerance(self):
port = self.make_port()
- port._server_process_constructor = lambda port, nm, cmd, env, crash_message=None: MockServerProcess(lines=['Content-Length: 4\n', 'test', 'diff: 0.05%\n', '#EOF\n'])
+ port._server_process_constructor = lambda port, nm, cmd, env, crash_message=None: MockServerProcess(lines=['Content-Length: 4\n', 'test', 'diff: 0.05%\n', 'maxDifference=4; totalPixels=10\n', '#EOF\n'])
image_differ = ImageDiffer(port)
- self.assertEqual(image_differ.diff_image(b'foo', b'bar', tolerance=0.1), ImageDiffResult(passed=True, diff_image=b'test', difference=0.05, tolerance=0.1))
+ self.assertEqual(image_differ.diff_image(b'foo', b'bar', tolerance=0.1), ImageDiffResult(passed=True, diff_image=b'test', difference=0.05, tolerance=0.1, fuzzy_data={'max_difference': 4, 'total_pixels': 10}))
def test_diff_image_failed_with_rounded_diff(self):
port = self.make_port()
- port._server_process_constructor = lambda port, nm, cmd, env, crash_message=None: MockServerProcess(lines=['Content-Length: 4\n', 'test', 'diff: 0.101234%\n', '#EOF\n'])
+ port._server_process_constructor = lambda port, nm, cmd, env, crash_message=None: MockServerProcess(lines=['Content-Length: 4\n', 'test', 'diff: 0.101234%\n', 'maxDifference=8; totalPixels=20\n', '#EOF\n'])
image_differ = ImageDiffer(port)
- self.assertEqual(image_differ.diff_image(b'foo', b'bar', tolerance=0.1), ImageDiffResult(passed=False, diff_image=b'test', difference=0.1, tolerance=0.1))
+ self.assertEqual(image_differ.diff_image(b'foo', b'bar', tolerance=0.1), ImageDiffResult(passed=False, diff_image=b'test', difference=0.1, tolerance=0.1, fuzzy_data={'max_difference': 8, 'total_pixels': 20}))
def test_diff_image_failed(self):
port = self.make_port()
- port._server_process_constructor = lambda port, nm, cmd, env, crash_message=None: MockServerProcess(lines=['Content-Length: 4\n', 'test', 'diff: 10%\n', '#EOF\n'])
+ port._server_process_constructor = lambda port, nm, cmd, env, crash_message=None: MockServerProcess(lines=['Content-Length: 4\n', 'test', 'diff: 10%\n', 'maxDifference=5; totalPixels=13\n', '#EOF\n'])
image_differ = ImageDiffer(port)
- self.assertEqual(image_differ.diff_image(b'foo', b'bar', tolerance=0.1), ImageDiffResult(passed=False, diff_image=b'test', difference=10, tolerance=0.1))
+ self.assertEqual(image_differ.diff_image(b'foo', b'bar', tolerance=0.1), ImageDiffResult(passed=False, diff_image=b'test', difference=10, tolerance=0.1, fuzzy_data={'max_difference': 5, 'total_pixels': 13}))
def test_diff_image_crashed(self):
port = self.make_port()