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 6#pylint: disable=protected-access 7 8import json 9import os 10import sys 11import tempfile 12from typing import Any 13import unittest 14 15if sys.version_info[0] == 2: 16 import mock 17else: 18 import unittest.mock as mock 19 20from pyfakefs import fake_filesystem_unittest 21 22from skia_gold_common import skia_gold_properties 23from skia_gold_common import skia_gold_session 24from skia_gold_common import unittest_utils 25 26createSkiaGoldArgs = unittest_utils.createSkiaGoldArgs 27 28 29def assertArgWith(test: unittest.TestCase, arg_list: list, arg: Any, 30 value: Any) -> None: 31 i = arg_list.index(arg) 32 test.assertEqual(arg_list[i + 1], value) 33 34 35class SkiaGoldSessionRunComparisonTest(fake_filesystem_unittest.TestCase): 36 """Tests the functionality of SkiaGoldSession.RunComparison.""" 37 38 def setUp(self) -> None: 39 self.setUpPyfakefs() 40 self._working_dir = tempfile.mkdtemp() 41 self._json_keys = tempfile.NamedTemporaryFile(delete=False).name 42 with open(self._json_keys, 'w') as f: 43 json.dump({}, f) 44 45 self.auth_patcher = mock.patch.object(skia_gold_session.SkiaGoldSession, 46 'Authenticate') 47 self.init_patcher = mock.patch.object(skia_gold_session.SkiaGoldSession, 48 'Initialize') 49 self.compare_patcher = mock.patch.object(skia_gold_session.SkiaGoldSession, 50 'Compare') 51 self.diff_patcher = mock.patch.object(skia_gold_session.SkiaGoldSession, 52 'Diff') 53 54 self.auth_mock = self.auth_patcher.start() 55 self.init_mock = self.init_patcher.start() 56 self.compare_mock = self.compare_patcher.start() 57 self.diff_mock = self.diff_patcher.start() 58 59 self.addCleanup(self.auth_patcher.stop) 60 self.addCleanup(self.init_patcher.stop) 61 self.addCleanup(self.compare_patcher.stop) 62 self.addCleanup(self.diff_patcher.stop) 63 64 def test_comparisonSuccess(self) -> None: 65 self.auth_mock.return_value = (0, None) 66 self.init_mock.return_value = (0, None) 67 self.compare_mock.return_value = (0, None) 68 sgp = skia_gold_properties.SkiaGoldProperties(createSkiaGoldArgs()) 69 session = skia_gold_session.SkiaGoldSession(self._working_dir, sgp, 70 self._json_keys, '', '') 71 status, _ = session.RunComparison('', '', None) 72 self.assertEqual(status, 73 skia_gold_session.SkiaGoldSession.StatusCodes.SUCCESS) 74 self.assertEqual(self.auth_mock.call_count, 1) 75 self.assertEqual(self.init_mock.call_count, 1) 76 self.assertEqual(self.compare_mock.call_count, 1) 77 self.assertEqual(self.diff_mock.call_count, 0) 78 79 def test_authFailure(self) -> None: 80 self.auth_mock.return_value = (1, 'Auth failed') 81 sgp = skia_gold_properties.SkiaGoldProperties(createSkiaGoldArgs()) 82 session = skia_gold_session.SkiaGoldSession(self._working_dir, sgp, 83 self._json_keys, '', '') 84 status, error = session.RunComparison('', '', None) 85 self.assertEqual(status, 86 skia_gold_session.SkiaGoldSession.StatusCodes.AUTH_FAILURE) 87 self.assertEqual(error, 'Auth failed') 88 self.assertEqual(self.auth_mock.call_count, 1) 89 self.assertEqual(self.init_mock.call_count, 0) 90 self.assertEqual(self.compare_mock.call_count, 0) 91 self.assertEqual(self.diff_mock.call_count, 0) 92 93 def test_initFailure(self) -> None: 94 self.auth_mock.return_value = (0, None) 95 self.init_mock.return_value = (1, 'Init failed') 96 sgp = skia_gold_properties.SkiaGoldProperties(createSkiaGoldArgs()) 97 session = skia_gold_session.SkiaGoldSession(self._working_dir, sgp, 98 self._json_keys, '', '') 99 status, error = session.RunComparison('', '', None) 100 self.assertEqual(status, 101 skia_gold_session.SkiaGoldSession.StatusCodes.INIT_FAILURE) 102 self.assertEqual(error, 'Init failed') 103 self.assertEqual(self.auth_mock.call_count, 1) 104 self.assertEqual(self.init_mock.call_count, 1) 105 self.assertEqual(self.compare_mock.call_count, 0) 106 self.assertEqual(self.diff_mock.call_count, 0) 107 108 def test_compareFailureRemote(self) -> None: 109 self.auth_mock.return_value = (0, None) 110 self.init_mock.return_value = (0, None) 111 self.compare_mock.return_value = (1, 'Compare failed') 112 args = createSkiaGoldArgs(local_pixel_tests=False) 113 sgp = skia_gold_properties.SkiaGoldProperties(args) 114 session = skia_gold_session.SkiaGoldSession(self._working_dir, sgp, 115 self._json_keys, '', '') 116 status, error = session.RunComparison('', '', None) 117 self.assertEqual( 118 status, 119 skia_gold_session.SkiaGoldSession.StatusCodes.COMPARISON_FAILURE_REMOTE) 120 self.assertEqual(error, 'Compare failed') 121 self.assertEqual(self.auth_mock.call_count, 1) 122 self.assertEqual(self.init_mock.call_count, 1) 123 self.assertEqual(self.compare_mock.call_count, 1) 124 self.assertEqual(self.diff_mock.call_count, 0) 125 126 def test_compareFailureLocal(self) -> None: 127 self.auth_mock.return_value = (0, None) 128 self.init_mock.return_value = (0, None) 129 self.compare_mock.return_value = (1, 'Compare failed') 130 self.diff_mock.return_value = (0, None) 131 args = createSkiaGoldArgs(local_pixel_tests=True) 132 sgp = skia_gold_properties.SkiaGoldProperties(args) 133 session = skia_gold_session.SkiaGoldSession(self._working_dir, sgp, 134 self._json_keys, '', '') 135 status, error = session.RunComparison('', '', 136 'Definitely an output manager') 137 self.assertEqual( 138 status, 139 skia_gold_session.SkiaGoldSession.StatusCodes.COMPARISON_FAILURE_LOCAL) 140 self.assertEqual(error, 'Compare failed') 141 self.assertEqual(self.auth_mock.call_count, 1) 142 self.assertEqual(self.init_mock.call_count, 1) 143 self.assertEqual(self.compare_mock.call_count, 1) 144 self.assertEqual(self.diff_mock.call_count, 1) 145 146 def test_compareInexactMatching(self) -> None: 147 self.auth_mock.return_value = (0, None) 148 self.init_mock.return_value = (0, None) 149 self.compare_mock.return_value = (0, None) 150 self.diff_mock.return_value = (0, None) 151 args = createSkiaGoldArgs(local_pixel_tests=False) 152 sgp = skia_gold_properties.SkiaGoldProperties(args) 153 session = skia_gold_session.SkiaGoldSession(self._working_dir, sgp, 154 self._json_keys, '', '') 155 status, _ = session.RunComparison('', 156 '', 157 None, 158 inexact_matching_args=['--inexact']) 159 self.assertEqual(status, 160 skia_gold_session.SkiaGoldSession.StatusCodes.SUCCESS) 161 self.assertEqual(self.auth_mock.call_count, 1) 162 self.assertEqual(self.init_mock.call_count, 1) 163 self.assertEqual(self.compare_mock.call_count, 1) 164 self.assertEqual(self.diff_mock.call_count, 0) 165 self.compare_mock.assert_called_with(name='', 166 png_file=mock.ANY, 167 inexact_matching_args=['--inexact'], 168 optional_keys=None, 169 force_dryrun=False) 170 171 def test_compareOptionalKeys(self) -> None: 172 self.auth_mock.return_value = (0, None) 173 self.init_mock.return_value = (0, None) 174 self.compare_mock.return_value = (0, None) 175 self.diff_mock.return_value = (0, None) 176 args = createSkiaGoldArgs(local_pixel_tests=False) 177 sgp = skia_gold_properties.SkiaGoldProperties(args) 178 session = skia_gold_session.SkiaGoldSession(self._working_dir, sgp, 179 self._json_keys, '', '') 180 status, _ = session.RunComparison('', 181 '', 182 None, 183 optional_keys={'foo': 'bar'}) 184 self.assertEqual(status, 185 skia_gold_session.SkiaGoldSession.StatusCodes.SUCCESS) 186 self.assertEqual(self.auth_mock.call_count, 1) 187 self.assertEqual(self.init_mock.call_count, 1) 188 self.assertEqual(self.compare_mock.call_count, 1) 189 self.assertEqual(self.diff_mock.call_count, 0) 190 self.compare_mock.assert_called_with(name='', 191 png_file=mock.ANY, 192 inexact_matching_args=None, 193 optional_keys={'foo': 'bar'}, 194 force_dryrun=False) 195 196 def test_compareForceDryrun(self) -> None: 197 self.auth_mock.return_value = (0, None) 198 self.init_mock.return_value = (0, None) 199 self.compare_mock.return_value = (0, None) 200 self.diff_mock.return_value = (0, None) 201 args = createSkiaGoldArgs(local_pixel_tests=False) 202 sgp = skia_gold_properties.SkiaGoldProperties(args) 203 session = skia_gold_session.SkiaGoldSession(self._working_dir, sgp, 204 self._json_keys, '', '') 205 status, _ = session.RunComparison('', '', None, force_dryrun=True) 206 self.assertEqual(status, 207 skia_gold_session.SkiaGoldSession.StatusCodes.SUCCESS) 208 self.assertEqual(self.auth_mock.call_count, 1) 209 self.assertEqual(self.init_mock.call_count, 1) 210 self.assertEqual(self.compare_mock.call_count, 1) 211 self.assertEqual(self.diff_mock.call_count, 0) 212 self.compare_mock.assert_called_with(name='', 213 png_file=mock.ANY, 214 inexact_matching_args=None, 215 optional_keys=None, 216 force_dryrun=True) 217 218 def test_diffFailure(self) -> None: 219 self.auth_mock.return_value = (0, None) 220 self.init_mock.return_value = (0, None) 221 self.compare_mock.return_value = (1, 'Compare failed') 222 self.diff_mock.return_value = (1, 'Diff failed') 223 args = createSkiaGoldArgs(local_pixel_tests=True) 224 sgp = skia_gold_properties.SkiaGoldProperties(args) 225 session = skia_gold_session.SkiaGoldSession(self._working_dir, sgp, 226 self._json_keys, '', '') 227 status, error = session.RunComparison('', '', 228 'Definitely an output manager') 229 self.assertEqual( 230 status, 231 skia_gold_session.SkiaGoldSession.StatusCodes.LOCAL_DIFF_FAILURE) 232 self.assertEqual(error, 'Diff failed') 233 self.assertEqual(self.auth_mock.call_count, 1) 234 self.assertEqual(self.init_mock.call_count, 1) 235 self.assertEqual(self.compare_mock.call_count, 1) 236 self.assertEqual(self.diff_mock.call_count, 1) 237 238 def test_noOutputManagerLocal(self) -> None: 239 self.auth_mock.return_value = (0, None) 240 self.init_mock.return_value = (0, None) 241 self.compare_mock.return_value = (1, 'Compare failed') 242 self.diff_mock.return_value = (0, None) 243 args = createSkiaGoldArgs(local_pixel_tests=True) 244 sgp = skia_gold_properties.SkiaGoldProperties(args) 245 session = skia_gold_session.SkiaGoldSession(self._working_dir, sgp, 246 self._json_keys, '', '') 247 status, error = session.RunComparison('', '', None) 248 self.assertEqual( 249 status, skia_gold_session.SkiaGoldSession.StatusCodes.NO_OUTPUT_MANAGER) 250 self.assertEqual(error, 'No output manager for local diff images') 251 self.assertEqual(self.auth_mock.call_count, 1) 252 self.assertEqual(self.compare_mock.call_count, 1) 253 self.assertEqual(self.diff_mock.call_count, 0) 254 255 256class SkiaGoldSessionAuthenticateTest(fake_filesystem_unittest.TestCase): 257 """Tests the functionality of SkiaGoldSession.Authenticate.""" 258 259 def setUp(self) -> None: 260 self.setUpPyfakefs() 261 self._working_dir = tempfile.mkdtemp() 262 self._json_keys = tempfile.NamedTemporaryFile(delete=False).name 263 264 self.cmd_patcher = mock.patch.object(skia_gold_session.SkiaGoldSession, 265 '_RunCmdForRcAndOutput') 266 self.cmd_mock = self.cmd_patcher.start() 267 self.addCleanup(self.cmd_patcher.stop) 268 269 def test_commandOutputReturned(self) -> None: 270 self.cmd_mock.return_value = (1, 'Something bad :(') 271 args = createSkiaGoldArgs(git_revision='a') 272 sgp = skia_gold_properties.SkiaGoldProperties(args) 273 session = skia_gold_session.SkiaGoldSession(self._working_dir, sgp, 274 self._json_keys, '', '') 275 rc, stdout = session.Authenticate() 276 self.assertEqual(self.cmd_mock.call_count, 1) 277 self.assertEqual(rc, 1) 278 self.assertEqual(stdout, 'Something bad :(') 279 280 def test_bypassSkiaGoldFunctionality(self) -> None: 281 self.cmd_mock.return_value = (None, None) 282 args = createSkiaGoldArgs(git_revision='a', 283 bypass_skia_gold_functionality=True) 284 sgp = skia_gold_properties.SkiaGoldProperties(args) 285 session = skia_gold_session.SkiaGoldSession(self._working_dir, sgp, 286 self._json_keys, '', '') 287 rc, _ = session.Authenticate() 288 self.assertEqual(rc, 0) 289 self.cmd_mock.assert_not_called() 290 291 def test_shortCircuitAlreadyAuthenticated(self) -> None: 292 self.cmd_mock.return_value = (None, None) 293 args = createSkiaGoldArgs(git_revision='a') 294 sgp = skia_gold_properties.SkiaGoldProperties(args) 295 session = skia_gold_session.SkiaGoldSession(self._working_dir, sgp, 296 self._json_keys, '', '') 297 session._authenticated = True 298 rc, _ = session.Authenticate() 299 self.assertEqual(rc, 0) 300 self.cmd_mock.assert_not_called() 301 302 def test_successSetsShortCircuit(self) -> None: 303 self.cmd_mock.return_value = (0, None) 304 args = createSkiaGoldArgs(git_revision='a') 305 sgp = skia_gold_properties.SkiaGoldProperties(args) 306 session = skia_gold_session.SkiaGoldSession(self._working_dir, sgp, 307 self._json_keys, '', '') 308 self.assertFalse(session._authenticated) 309 rc, _ = session.Authenticate() 310 self.assertEqual(rc, 0) 311 self.assertTrue(session._authenticated) 312 self.cmd_mock.assert_called_once() 313 314 def test_failureDoesNotSetShortCircuit(self) -> None: 315 self.cmd_mock.return_value = (1, None) 316 args = createSkiaGoldArgs(git_revision='a') 317 sgp = skia_gold_properties.SkiaGoldProperties(args) 318 session = skia_gold_session.SkiaGoldSession(self._working_dir, sgp, 319 self._json_keys, '', '') 320 self.assertFalse(session._authenticated) 321 rc, _ = session.Authenticate() 322 self.assertEqual(rc, 1) 323 self.assertFalse(session._authenticated) 324 self.cmd_mock.assert_called_once() 325 326 def test_commandWithUseLuciTrue(self) -> None: 327 self.cmd_mock.return_value = (None, None) 328 args = createSkiaGoldArgs(git_revision='a') 329 sgp = skia_gold_properties.SkiaGoldProperties(args) 330 session = skia_gold_session.SkiaGoldSession(self._working_dir, sgp, 331 self._json_keys, '', '') 332 session.Authenticate(use_luci=True) 333 self.assertIn('--luci', self.cmd_mock.call_args[0][0]) 334 335 def test_commandWithUseLuciFalse(self) -> None: 336 self.cmd_mock.return_value = (None, None) 337 args = createSkiaGoldArgs(git_revision='a', local_pixel_tests=True) 338 sgp = skia_gold_properties.SkiaGoldProperties(args) 339 session = skia_gold_session.SkiaGoldSession(self._working_dir, sgp, 340 self._json_keys, '', '') 341 session.Authenticate(use_luci=False) 342 self.assertNotIn('--luci', self.cmd_mock.call_args[0][0]) 343 344 def test_commandWithUseLuciFalseNotLocal(self) -> None: 345 self.cmd_mock.return_value = (None, None) 346 args = createSkiaGoldArgs(git_revision='a', local_pixel_tests=False) 347 sgp = skia_gold_properties.SkiaGoldProperties(args) 348 session = skia_gold_session.SkiaGoldSession(self._working_dir, sgp, 349 self._json_keys, '', '') 350 with self.assertRaises(RuntimeError): 351 session.Authenticate(use_luci=False) 352 353 def test_commandWithUseLuciAndServiceAccount(self) -> None: 354 args = createSkiaGoldArgs(git_revision='a', local_pixel_tests=False) 355 sgp = skia_gold_properties.SkiaGoldProperties(args) 356 session = skia_gold_session.SkiaGoldSession(self._working_dir, sgp, 357 self._json_keys, '', '') 358 with self.assertRaises(AssertionError): 359 session.Authenticate(use_luci=True, service_account='a') 360 361 def test_commandWithServiceAccount(self) -> None: 362 self.cmd_mock.return_value = (None, None) 363 args = createSkiaGoldArgs(git_revision='a', local_pixel_tests=False) 364 sgp = skia_gold_properties.SkiaGoldProperties(args) 365 session = skia_gold_session.SkiaGoldSession(self._working_dir, sgp, 366 self._json_keys, '', '') 367 session.Authenticate(use_luci=False, service_account='service_account') 368 call_args = self.cmd_mock.call_args[0][0] 369 self.assertNotIn('--luci', call_args) 370 assertArgWith(self, call_args, '--service-account', 'service_account') 371 372 def test_commandCommonArgs(self) -> None: 373 self.cmd_mock.return_value = (None, None) 374 args = createSkiaGoldArgs(git_revision='a') 375 sgp = skia_gold_properties.SkiaGoldProperties(args) 376 session = skia_gold_session.SkiaGoldSession(self._working_dir, sgp, 377 self._json_keys, '', '') 378 session.Authenticate() 379 call_args = self.cmd_mock.call_args[0][0] 380 self.assertIn('auth', call_args) 381 assertArgWith(self, call_args, '--work-dir', self._working_dir) 382 383 384class SkiaGoldSessionInitializeTest(fake_filesystem_unittest.TestCase): 385 """Tests the functionality of SkiaGoldSession.Initialize.""" 386 387 def setUp(self) -> None: 388 self.setUpPyfakefs() 389 self._working_dir = tempfile.mkdtemp() 390 self._json_keys = tempfile.NamedTemporaryFile(delete=False).name 391 392 self.cmd_patcher = mock.patch.object(skia_gold_session.SkiaGoldSession, 393 '_RunCmdForRcAndOutput') 394 self.cmd_mock = self.cmd_patcher.start() 395 self.addCleanup(self.cmd_patcher.stop) 396 397 def test_bypassSkiaGoldFunctionality(self) -> None: 398 self.cmd_mock.return_value = (None, None) 399 args = createSkiaGoldArgs(git_revision='a', 400 bypass_skia_gold_functionality=True) 401 sgp = skia_gold_properties.SkiaGoldProperties(args) 402 session = skia_gold_session.SkiaGoldSession(self._working_dir, sgp, 403 self._json_keys, '', '') 404 rc, _ = session.Initialize() 405 self.assertEqual(rc, 0) 406 self.cmd_mock.assert_not_called() 407 408 def test_shortCircuitAlreadyInitialized(self) -> None: 409 self.cmd_mock.return_value = (None, None) 410 args = createSkiaGoldArgs(git_revision='a') 411 sgp = skia_gold_properties.SkiaGoldProperties(args) 412 session = skia_gold_session.SkiaGoldSession(self._working_dir, sgp, 413 self._json_keys, '', '') 414 session._initialized = True 415 rc, _ = session.Initialize() 416 self.assertEqual(rc, 0) 417 self.cmd_mock.assert_not_called() 418 419 def test_successSetsShortCircuit(self) -> None: 420 self.cmd_mock.return_value = (0, None) 421 args = createSkiaGoldArgs(git_revision='a') 422 sgp = skia_gold_properties.SkiaGoldProperties(args) 423 session = skia_gold_session.SkiaGoldSession(self._working_dir, sgp, 424 self._json_keys, '', '') 425 self.assertFalse(session._initialized) 426 rc, _ = session.Initialize() 427 self.assertEqual(rc, 0) 428 self.assertTrue(session._initialized) 429 self.cmd_mock.assert_called_once() 430 431 def test_failureDoesNotSetShortCircuit(self) -> None: 432 self.cmd_mock.return_value = (1, None) 433 args = createSkiaGoldArgs(git_revision='a') 434 sgp = skia_gold_properties.SkiaGoldProperties(args) 435 session = skia_gold_session.SkiaGoldSession(self._working_dir, sgp, 436 self._json_keys, '', '') 437 self.assertFalse(session._initialized) 438 rc, _ = session.Initialize() 439 self.assertEqual(rc, 1) 440 self.assertFalse(session._initialized) 441 self.cmd_mock.assert_called_once() 442 443 def test_commandCommonArgs(self) -> None: 444 self.cmd_mock.return_value = (None, None) 445 args = createSkiaGoldArgs(git_revision='a') 446 sgp = skia_gold_properties.SkiaGoldProperties(args) 447 session = skia_gold_session.SkiaGoldSession(self._working_dir, 448 sgp, 449 self._json_keys, 450 'corpus', 451 instance='instance', 452 bucket='bucket') 453 session.Initialize() 454 call_args = self.cmd_mock.call_args[0][0] 455 self.assertIn('imgtest', call_args) 456 self.assertIn('init', call_args) 457 self.assertIn('--passfail', call_args) 458 assertArgWith(self, call_args, '--instance', 'instance') 459 assertArgWith(self, call_args, '--bucket', 'bucket') 460 assertArgWith(self, call_args, '--corpus', 'corpus') 461 # The keys file should have been copied to the working directory. 462 assertArgWith(self, call_args, '--keys-file', 463 os.path.join(self._working_dir, 'gold_keys.json')) 464 assertArgWith(self, call_args, '--work-dir', self._working_dir) 465 assertArgWith(self, call_args, '--failure-file', session._triage_link_file) 466 assertArgWith(self, call_args, '--commit', 'a') 467 468 def test_commandTryjobArgs(self) -> None: 469 self.cmd_mock.return_value = (None, None) 470 args = createSkiaGoldArgs(git_revision='a', 471 gerrit_issue=1, 472 gerrit_patchset=2, 473 buildbucket_id=3) 474 sgp = skia_gold_properties.SkiaGoldProperties(args) 475 session = skia_gold_session.SkiaGoldSession(self._working_dir, sgp, 476 self._json_keys, '', '') 477 session.Initialize() 478 call_args = self.cmd_mock.call_args[0][0] 479 assertArgWith(self, call_args, '--issue', '1') 480 assertArgWith(self, call_args, '--patchset', '2') 481 assertArgWith(self, call_args, '--jobid', '3') 482 assertArgWith(self, call_args, '--crs', 'gerrit') 483 assertArgWith(self, call_args, '--cis', 'buildbucket') 484 485 def test_commandTryjobArgsNonDefaultCrs(self) -> None: 486 self.cmd_mock.return_value = (None, None) 487 args = createSkiaGoldArgs(code_review_system='foo', 488 git_revision='a', 489 gerrit_issue=1, 490 gerrit_patchset=2, 491 buildbucket_id=3) 492 sgp = skia_gold_properties.SkiaGoldProperties(args) 493 session = skia_gold_session.SkiaGoldSession(self._working_dir, sgp, 494 self._json_keys, '', '') 495 session.Initialize() 496 call_args = self.cmd_mock.call_args[0][0] 497 assertArgWith(self, call_args, '--issue', '1') 498 assertArgWith(self, call_args, '--patchset', '2') 499 assertArgWith(self, call_args, '--jobid', '3') 500 assertArgWith(self, call_args, '--crs', 'foo') 501 assertArgWith(self, call_args, '--cis', 'buildbucket') 502 503 def test_commandTryjobArgsMissing(self) -> None: 504 self.cmd_mock.return_value = (None, None) 505 args = createSkiaGoldArgs(git_revision='a') 506 sgp = skia_gold_properties.SkiaGoldProperties(args) 507 session = skia_gold_session.SkiaGoldSession(self._working_dir, sgp, 508 self._json_keys, '', '') 509 session.Initialize() 510 call_args = self.cmd_mock.call_args[0][0] 511 self.assertNotIn('--issue', call_args) 512 self.assertNotIn('--patchset', call_args) 513 self.assertNotIn('--jobid', call_args) 514 self.assertNotIn('--crs', call_args) 515 self.assertNotIn('--cis', call_args) 516 517 518class SkiaGoldSessionCompareTest(fake_filesystem_unittest.TestCase): 519 """Tests the functionality of SkiaGoldSession.Compare.""" 520 521 def setUp(self) -> None: 522 self.setUpPyfakefs() 523 self._working_dir = tempfile.mkdtemp() 524 self._json_keys = tempfile.NamedTemporaryFile(delete=False).name 525 526 self.cmd_patcher = mock.patch.object(skia_gold_session.SkiaGoldSession, 527 '_RunCmdForRcAndOutput') 528 self.cmd_mock = self.cmd_patcher.start() 529 self.addCleanup(self.cmd_patcher.stop) 530 531 def test_commandOutputReturned(self) -> None: 532 self.cmd_mock.return_value = (1, 'Something bad :(') 533 args = createSkiaGoldArgs(git_revision='a') 534 sgp = skia_gold_properties.SkiaGoldProperties(args) 535 session = skia_gold_session.SkiaGoldSession(self._working_dir, sgp, 536 self._json_keys, '', '') 537 rc, stdout = session.Compare('', '') 538 self.assertEqual(self.cmd_mock.call_count, 1) 539 self.assertEqual(rc, 1) 540 self.assertEqual(stdout, 'Something bad :(') 541 542 def test_bypassSkiaGoldFunctionality(self) -> None: 543 self.cmd_mock.return_value = (None, None) 544 args = createSkiaGoldArgs(git_revision='a', 545 bypass_skia_gold_functionality=True) 546 sgp = skia_gold_properties.SkiaGoldProperties(args) 547 session = skia_gold_session.SkiaGoldSession(self._working_dir, sgp, 548 self._json_keys, '', '') 549 rc, _ = session.Compare('', '') 550 self.assertEqual(rc, 0) 551 self.cmd_mock.assert_not_called() 552 553 def test_commandWithLocalPixelTestsTrue(self) -> None: 554 self.cmd_mock.return_value = (None, None) 555 args = createSkiaGoldArgs(git_revision='a', local_pixel_tests=True) 556 sgp = skia_gold_properties.SkiaGoldProperties(args) 557 session = skia_gold_session.SkiaGoldSession(self._working_dir, sgp, 558 self._json_keys, '', '') 559 session.Compare('', '') 560 self.assertIn('--dryrun', self.cmd_mock.call_args[0][0]) 561 562 def test_commandWithForceDryrunTrue(self) -> None: 563 self.cmd_mock.return_value = (None, None) 564 args = createSkiaGoldArgs(git_revision='a') 565 sgp = skia_gold_properties.SkiaGoldProperties(args) 566 session = skia_gold_session.SkiaGoldSession(self._working_dir, sgp, 567 self._json_keys, '', '') 568 session.Compare('', '', force_dryrun=True) 569 self.assertIn('--dryrun', self.cmd_mock.call_args[0][0]) 570 571 def test_commandWithLocalPixelTestsFalse(self) -> None: 572 self.cmd_mock.return_value = (None, None) 573 args = createSkiaGoldArgs(git_revision='a', local_pixel_tests=False) 574 sgp = skia_gold_properties.SkiaGoldProperties(args) 575 session = skia_gold_session.SkiaGoldSession(self._working_dir, sgp, 576 self._json_keys, '', '') 577 session.Compare('', '') 578 self.assertNotIn('--dryrun', self.cmd_mock.call_args[0][0]) 579 580 def test_commandWithInexactArgs(self) -> None: 581 self.cmd_mock.return_value = (None, None) 582 args = createSkiaGoldArgs(git_revision='a') 583 sgp = skia_gold_properties.SkiaGoldProperties(args) 584 session = skia_gold_session.SkiaGoldSession(self._working_dir, sgp, 585 self._json_keys, '', '') 586 session.Compare('', '', inexact_matching_args=['--inexact', 'foobar']) 587 self.assertIn('--inexact', self.cmd_mock.call_args[0][0]) 588 self.assertIn('foobar', self.cmd_mock.call_args[0][0]) 589 590 def test_commandCommonArgs(self) -> None: 591 self.cmd_mock.return_value = (None, None) 592 args = createSkiaGoldArgs(git_revision='a') 593 sgp = skia_gold_properties.SkiaGoldProperties(args) 594 session = skia_gold_session.SkiaGoldSession(self._working_dir, 595 sgp, 596 self._json_keys, 597 'corpus', 598 instance='instance') 599 session.Compare('name', 'png_file') 600 call_args = self.cmd_mock.call_args[0][0] 601 self.assertIn('imgtest', call_args) 602 self.assertIn('add', call_args) 603 assertArgWith(self, call_args, '--test-name', 'name') 604 assertArgWith(self, call_args, '--png-file', 'png_file') 605 assertArgWith(self, call_args, '--work-dir', self._working_dir) 606 607 def test_noLinkOnSuccess(self) -> None: 608 self.cmd_mock.return_value = (0, None) 609 args = createSkiaGoldArgs(git_revision='a') 610 sgp = skia_gold_properties.SkiaGoldProperties(args) 611 session = skia_gold_session.SkiaGoldSession(self._working_dir, sgp, 612 self._json_keys, '', '') 613 rc, _ = session.Compare('name', 'png_file') 614 self.assertEqual(rc, 0) 615 comparison_result = session._comparison_results['name'] 616 self.assertEqual(comparison_result.public_triage_link, None) 617 self.assertEqual(comparison_result.internal_triage_link, None) 618 self.assertNotEqual(comparison_result.triage_link_omission_reason, None) 619 620 def test_clLinkOnTrybot(self) -> None: 621 self.cmd_mock.return_value = (1, None) 622 args = createSkiaGoldArgs(git_revision='a', 623 gerrit_issue=1, 624 gerrit_patchset=2, 625 buildbucket_id=3) 626 sgp = skia_gold_properties.SkiaGoldProperties(args) 627 session = skia_gold_session.SkiaGoldSession(self._working_dir, 628 sgp, 629 self._json_keys, 630 '', 631 instance='instance') 632 rc, _ = session.Compare('name', 'png_file') 633 self.assertEqual(rc, 1) 634 comparison_result = session._comparison_results['name'] 635 self.assertNotEqual(comparison_result.public_triage_link, None) 636 self.assertNotEqual(comparison_result.internal_triage_link, None) 637 internal_link = 'https://instance-gold.skia.org/cl/gerrit/1' 638 public_link = 'https://instance-public-gold.skia.org/cl/gerrit/1' 639 self.assertEqual(comparison_result.internal_triage_link, internal_link) 640 self.assertEqual(comparison_result.public_triage_link, public_link) 641 self.assertEqual(comparison_result.triage_link_omission_reason, None) 642 self.assertEqual(session.GetTriageLinks('name'), 643 (public_link, internal_link)) 644 645 def test_individualLinkOnCi(self) -> None: 646 args = createSkiaGoldArgs(git_revision='a') 647 sgp = skia_gold_properties.SkiaGoldProperties(args) 648 session = skia_gold_session.SkiaGoldSession(self._working_dir, 649 sgp, 650 self._json_keys, 651 '', 652 instance='foobar') 653 654 internal_link = 'foobar-gold.skia.org' 655 public_link = 'foobar-public-gold.skia.org' 656 657 def WriteTriageLinkFile(_): 658 with open(session._triage_link_file, 'w') as f: 659 f.write(internal_link) 660 return (1, None) 661 662 self.cmd_mock.side_effect = WriteTriageLinkFile 663 rc, _ = session.Compare('name', 'png_file') 664 self.assertEqual(rc, 1) 665 comparison_result = session._comparison_results['name'] 666 self.assertNotEqual(comparison_result.public_triage_link, None) 667 self.assertNotEqual(comparison_result.internal_triage_link, None) 668 self.assertEqual(comparison_result.internal_triage_link, internal_link) 669 self.assertEqual(comparison_result.public_triage_link, public_link) 670 self.assertEqual(comparison_result.triage_link_omission_reason, None) 671 self.assertEqual(session.GetTriageLinks('name'), 672 (public_link, internal_link)) 673 674 def test_validOmissionOnMissingLink(self) -> None: 675 args = createSkiaGoldArgs(git_revision='a') 676 sgp = skia_gold_properties.SkiaGoldProperties(args) 677 session = skia_gold_session.SkiaGoldSession(self._working_dir, sgp, 678 self._json_keys, '', '') 679 680 def WriteTriageLinkFile(_): 681 with open(session._triage_link_file, 'w'): 682 pass 683 return (1, None) 684 685 self.cmd_mock.side_effect = WriteTriageLinkFile 686 rc, _ = session.Compare('name', 'png_file') 687 self.assertEqual(rc, 1) 688 comparison_result = session._comparison_results['name'] 689 self.assertEqual(comparison_result.public_triage_link, None) 690 self.assertEqual(comparison_result.internal_triage_link, None) 691 self.assertIn('Gold did not provide a triage link', 692 comparison_result.triage_link_omission_reason) 693 694 def test_validOmissionOnIoError(self) -> None: 695 self.cmd_mock.return_value = (1, None) 696 args = createSkiaGoldArgs(git_revision='a') 697 sgp = skia_gold_properties.SkiaGoldProperties(args) 698 session = skia_gold_session.SkiaGoldSession(self._working_dir, sgp, 699 self._json_keys, '', '') 700 701 def DeleteTriageLinkFile(_): 702 os.remove(session._triage_link_file) 703 return (1, None) 704 705 self.cmd_mock.side_effect = DeleteTriageLinkFile 706 rc, _ = session.Compare('name', 'png_file') 707 self.assertEqual(rc, 1) 708 comparison_result = session._comparison_results['name'] 709 self.assertEqual(comparison_result.public_triage_link, None) 710 self.assertEqual(comparison_result.internal_triage_link, None) 711 self.assertNotEqual(comparison_result.triage_link_omission_reason, None) 712 self.assertIn('Failed to read', 713 comparison_result.triage_link_omission_reason) 714 715 def test_optionalKeysPassedToGoldctl(self) -> None: 716 self.cmd_mock.return_value = (None, None) 717 args = createSkiaGoldArgs(git_revision='a', local_pixel_tests=True) 718 sgp = skia_gold_properties.SkiaGoldProperties(args) 719 session = skia_gold_session.SkiaGoldSession(self._working_dir, sgp, 720 self._json_keys, '', '') 721 session.Compare('', '', optional_keys={'foo': 'bar'}) 722 assertArgWith(self, self.cmd_mock.call_args[0][0], 723 '--add-test-optional-key', 'foo:bar') 724 725 726class SkiaGoldSessionDiffTest(fake_filesystem_unittest.TestCase): 727 """Tests the functionality of SkiaGoldSession.Diff.""" 728 729 def setUp(self) -> None: 730 self.setUpPyfakefs() 731 self._working_dir = tempfile.mkdtemp() 732 self._json_keys = tempfile.NamedTemporaryFile(delete=False).name 733 734 self.cmd_patcher = mock.patch.object(skia_gold_session.SkiaGoldSession, 735 '_RunCmdForRcAndOutput') 736 self.cmd_mock = self.cmd_patcher.start() 737 self.addCleanup(self.cmd_patcher.stop) 738 739 @mock.patch.object(skia_gold_session.SkiaGoldSession, '_StoreDiffLinks') 740 def test_commandOutputReturned(self, _) -> None: 741 self.cmd_mock.return_value = (1, 'Something bad :(') 742 args = createSkiaGoldArgs(git_revision='a', local_pixel_tests=False) 743 sgp = skia_gold_properties.SkiaGoldProperties(args) 744 session = skia_gold_session.SkiaGoldSession(self._working_dir, sgp, 745 self._json_keys, '', '') 746 rc, stdout = session.Diff('', '', None) 747 self.assertEqual(self.cmd_mock.call_count, 1) 748 self.assertEqual(rc, 1) 749 self.assertEqual(stdout, 'Something bad :(') 750 751 def test_bypassSkiaGoldFunctionality(self) -> None: 752 self.cmd_mock.return_value = (None, None) 753 args = createSkiaGoldArgs(git_revision='a', 754 bypass_skia_gold_functionality=True) 755 sgp = skia_gold_properties.SkiaGoldProperties(args) 756 session = skia_gold_session.SkiaGoldSession(self._working_dir, sgp, 757 self._json_keys, '', '') 758 with self.assertRaises(RuntimeError): 759 session.Diff('', '', None) 760 761 762class SkiaGoldSessionTriageLinkOmissionTest(fake_filesystem_unittest.TestCase): 763 """Tests the functionality of SkiaGoldSession.GetTriageLinkOmissionReason.""" 764 765 def setUp(self) -> None: 766 self.setUpPyfakefs() 767 self._working_dir = tempfile.mkdtemp() 768 769 def _CreateSession(self) -> skia_gold_session.SkiaGoldSession: 770 sgp = skia_gold_properties.SkiaGoldProperties(createSkiaGoldArgs()) 771 json_keys = tempfile.NamedTemporaryFile(delete=False).name 772 session = skia_gold_session.SkiaGoldSession(self._working_dir, sgp, 773 json_keys, '', '') 774 session._comparison_results = { 775 'foo': skia_gold_session.SkiaGoldSession.ComparisonResults(), 776 } 777 return session 778 779 def test_noComparison(self) -> None: 780 session = self._CreateSession() 781 session._comparison_results = {} 782 reason = session.GetTriageLinkOmissionReason('foo') 783 self.assertEqual(reason, 'No image comparison performed for foo') 784 785 def test_validReason(self) -> None: 786 session = self._CreateSession() 787 session._comparison_results['foo'].triage_link_omission_reason = 'bar' 788 reason = session.GetTriageLinkOmissionReason('foo') 789 self.assertEqual(reason, 'bar') 790 791 def test_onlyLocal(self) -> None: 792 session = self._CreateSession() 793 session._comparison_results['foo'].local_diff_given_image = 'bar' 794 reason = session.GetTriageLinkOmissionReason('foo') 795 self.assertEqual(reason, 'Gold only used to do a local image diff') 796 797 def test_onlyWithoutTriageLink(self) -> None: 798 session = self._CreateSession() 799 comparison_result = session._comparison_results['foo'] 800 comparison_result.public_triage_link = 'bar' 801 with self.assertRaises(AssertionError): 802 session.GetTriageLinkOmissionReason('foo') 803 comparison_result.public_triage_link = None 804 comparison_result.internal_triage_link = 'bar' 805 with self.assertRaises(AssertionError): 806 session.GetTriageLinkOmissionReason('foo') 807 808 def test_resultsShouldNotExist(self) -> None: 809 session = self._CreateSession() 810 with self.assertRaises(RuntimeError): 811 session.GetTriageLinkOmissionReason('foo') 812 813 814if __name__ == '__main__': 815 unittest.main(verbosity=2) 816