xref: /aosp_15_r20/external/angle/build/android/pylib/utils/gold_utils_test.py (revision 8975f5c5ed3d1c378011245431ada316dfb6f244)
1#!/usr/bin/env vpython3
2# Copyright 2020 The Chromium Authors
3# Use of this source code is governed by a BSD-style license that can be
4# found in the LICENSE file.
5"""Tests for gold_utils."""
6
7#pylint: disable=protected-access
8
9import contextlib
10import os
11import tempfile
12import unittest
13
14from pylib.constants import host_paths
15from pylib.utils import gold_utils
16
17with host_paths.SysPath(host_paths.BUILD_PATH):
18  from skia_gold_common import unittest_utils
19
20import mock  # pylint: disable=import-error
21from pyfakefs import fake_filesystem_unittest  # pylint: disable=import-error
22
23createSkiaGoldArgs = unittest_utils.createSkiaGoldArgs
24
25
26def assertArgWith(test, arg_list, arg, value):
27  i = arg_list.index(arg)
28  test.assertEqual(arg_list[i + 1], value)
29
30
31class AndroidSkiaGoldSessionDiffTest(fake_filesystem_unittest.TestCase):
32  def setUp(self):
33    self.setUpPyfakefs()
34    self._working_dir = tempfile.mkdtemp()
35    self._json_keys = tempfile.NamedTemporaryFile(delete=False).name
36
37  @mock.patch.object(gold_utils.AndroidSkiaGoldSession, '_RunCmdForRcAndOutput')
38  def test_commandCommonArgs(self, cmd_mock):
39    cmd_mock.return_value = (None, None)
40    args = createSkiaGoldArgs(git_revision='a', local_pixel_tests=False)
41    sgp = gold_utils.AndroidSkiaGoldProperties(args)
42    session = gold_utils.AndroidSkiaGoldSession(self._working_dir,
43                                                sgp,
44                                                self._json_keys,
45                                                'corpus',
46                                                instance='instance')
47    session.Diff('name', 'png_file', None)
48    call_args = cmd_mock.call_args[0][0]
49    self.assertIn('diff', call_args)
50    assertArgWith(self, call_args, '--corpus', 'corpus')
51    # TODO(skbug.com/10610): Remove the -public once we go back to using the
52    # non-public instance, or add a second test for testing that the correct
53    # instance is chosen if we decide to support both depending on what the
54    # user is authenticated for.
55    assertArgWith(self, call_args, '--instance', 'instance-public')
56    assertArgWith(self, call_args, '--input', 'png_file')
57    assertArgWith(self, call_args, '--test', 'name')
58    # TODO(skbug.com/10611): Re-add this assert and remove the check for the
59    # absence of the directory once we switch back to using the proper working
60    # directory.
61    # assertArgWith(self, call_args, '--work-dir', self._working_dir)
62    self.assertNotIn(self._working_dir, call_args)
63    i = call_args.index('--out-dir')
64    # The output directory should be a subdirectory of the working directory.
65    self.assertIn(self._working_dir, call_args[i + 1])
66
67
68class AndroidSkiaGoldSessionDiffLinksTest(fake_filesystem_unittest.TestCase):
69  class FakeArchivedFile:
70    def __init__(self, path):
71      self.name = path
72
73    def Link(self):
74      return 'file://' + self.name
75
76  class FakeOutputManager:
77    def __init__(self):
78      self.output_dir = tempfile.mkdtemp()
79
80    @contextlib.contextmanager
81    def ArchivedTempfile(self, image_name, _, __):
82      filepath = os.path.join(self.output_dir, image_name)
83      yield AndroidSkiaGoldSessionDiffLinksTest.FakeArchivedFile(filepath)
84
85  def setUp(self):
86    self.setUpPyfakefs()
87    self._working_dir = tempfile.mkdtemp()
88    self._json_keys = tempfile.NamedTemporaryFile(delete=False).name
89    self._timestamp_patcher = mock.patch.object(gold_utils, '_GetTimestamp')
90    self._timestamp_mock = self._timestamp_patcher.start()
91    self.addCleanup(self._timestamp_patcher.stop)
92
93  def test_outputManagerUsed(self):
94    self._timestamp_mock.return_value = 'ts0'
95    args = createSkiaGoldArgs(git_revision='a', local_pixel_tests=True)
96    sgp = gold_utils.AndroidSkiaGoldProperties(args)
97    session = gold_utils.AndroidSkiaGoldSession(self._working_dir, sgp,
98                                                self._json_keys, None, None)
99    with open(os.path.join(self._working_dir, 'input-inputhash.png'), 'w') as f:
100      f.write('input')
101    with open(os.path.join(self._working_dir, 'closest-closesthash.png'),
102              'w') as f:
103      f.write('closest')
104    with open(os.path.join(self._working_dir, 'diff.png'), 'w') as f:
105      f.write('diff')
106
107    output_manager = AndroidSkiaGoldSessionDiffLinksTest.FakeOutputManager()
108    session._StoreDiffLinks('foo', output_manager, self._working_dir)
109
110    copied_input = os.path.join(output_manager.output_dir, 'given_foo_ts0.png')
111    copied_closest = os.path.join(output_manager.output_dir,
112                                  'closest_foo_ts0.png')
113    copied_diff = os.path.join(output_manager.output_dir, 'diff_foo_ts0.png')
114    with open(copied_input) as f:
115      self.assertEqual(f.read(), 'input')
116    with open(copied_closest) as f:
117      self.assertEqual(f.read(), 'closest')
118    with open(copied_diff) as f:
119      self.assertEqual(f.read(), 'diff')
120
121    self.assertEqual(session.GetGivenImageLink('foo'), 'file://' + copied_input)
122    self.assertEqual(session.GetClosestImageLink('foo'),
123                     'file://' + copied_closest)
124    self.assertEqual(session.GetDiffImageLink('foo'), 'file://' + copied_diff)
125
126  def test_diffLinksDoNotClobber(self):
127    """Tests that multiple calls to store links does not clobber files."""
128
129    def side_effect():
130      side_effect.count += 1
131      return f'ts{side_effect.count}'
132
133    side_effect.count = -1
134    self._timestamp_mock.side_effect = side_effect
135
136    args = createSkiaGoldArgs(git_revision='a', local_pixel_tests=True)
137    sgp = gold_utils.AndroidSkiaGoldProperties(args)
138    session = gold_utils.AndroidSkiaGoldSession(self._working_dir, sgp,
139                                                self._json_keys, None, None)
140    with open(os.path.join(self._working_dir, 'input-inputhash.png'), 'w') as f:
141      f.write('first input')
142    with open(os.path.join(self._working_dir, 'closest-closesthash.png'),
143              'w') as f:
144      f.write('first closest')
145    with open(os.path.join(self._working_dir, 'diff.png'), 'w') as f:
146      f.write('first diff')
147
148    output_manager = AndroidSkiaGoldSessionDiffLinksTest.FakeOutputManager()
149    session._StoreDiffLinks('foo', output_manager, self._working_dir)
150
151    # Store links normally once.
152    first_copied_input = os.path.join(output_manager.output_dir,
153                                      'given_foo_ts0.png')
154    first_copied_closest = os.path.join(output_manager.output_dir,
155                                        'closest_foo_ts0.png')
156    first_copied_diff = os.path.join(output_manager.output_dir,
157                                     'diff_foo_ts0.png')
158    with open(first_copied_input) as f:
159      self.assertEqual(f.read(), 'first input')
160    with open(first_copied_closest) as f:
161      self.assertEqual(f.read(), 'first closest')
162    with open(first_copied_diff) as f:
163      self.assertEqual(f.read(), 'first diff')
164
165    with open(os.path.join(self._working_dir, 'input-inputhash.png'), 'w') as f:
166      f.write('second input')
167    with open(os.path.join(self._working_dir, 'closest-closesthash.png'),
168              'w') as f:
169      f.write('second closest')
170    with open(os.path.join(self._working_dir, 'diff.png'), 'w') as f:
171      f.write('second diff')
172
173    self.assertEqual(session.GetGivenImageLink('foo'),
174                     'file://' + first_copied_input)
175    self.assertEqual(session.GetClosestImageLink('foo'),
176                     'file://' + first_copied_closest)
177    self.assertEqual(session.GetDiffImageLink('foo'),
178                     'file://' + first_copied_diff)
179
180    # Store links again and check that the new data is surfaced.
181    session._StoreDiffLinks('foo', output_manager, self._working_dir)
182
183    second_copied_input = os.path.join(output_manager.output_dir,
184                                       'given_foo_ts1.png')
185    second_copied_closest = os.path.join(output_manager.output_dir,
186                                         'closest_foo_ts1.png')
187    second_copied_diff = os.path.join(output_manager.output_dir,
188                                      'diff_foo_ts1.png')
189    with open(second_copied_input) as f:
190      self.assertEqual(f.read(), 'second input')
191    with open(second_copied_closest) as f:
192      self.assertEqual(f.read(), 'second closest')
193    with open(second_copied_diff) as f:
194      self.assertEqual(f.read(), 'second diff')
195
196    self.assertEqual(session.GetGivenImageLink('foo'),
197                     'file://' + second_copied_input)
198    self.assertEqual(session.GetClosestImageLink('foo'),
199                     'file://' + second_copied_closest)
200    self.assertEqual(session.GetDiffImageLink('foo'),
201                     'file://' + second_copied_diff)
202
203    # Check to make sure the first images still exist on disk and are unchanged.
204    with open(first_copied_input) as f:
205      self.assertEqual(f.read(), 'first input')
206    with open(first_copied_closest) as f:
207      self.assertEqual(f.read(), 'first closest')
208    with open(first_copied_diff) as f:
209      self.assertEqual(f.read(), 'first diff')
210
211
212if __name__ == '__main__':
213  unittest.main(verbosity=2)
214