1# Copyright (c) 2014 The Chromium OS Authors. All rights reserved. 2# Use of this source code is governed by a BSD-style license that can be 3# found in the LICENSE file. 4 5import logging 6from autotest_lib.client.cros.video import method_logger 7from autotest_lib.client.cros.image_comparison import comparison_result 8 9# TODO (mussa): We will use data generated by running tests using this class. 10# If we can do with one comparer we may not need this class. 11 12class UploadOnFailComparer(object): 13 """ 14 Compares a test image against a golden image. 15 16 Uses a local comparer first to do the comparison, for every comparison 17 that return fail, it uses remote comparer. 18 19 """ 20 21 22 @method_logger.log 23 def __init__(self, local_comparer, remote_comparer, threshold=0): 24 """ 25 @param local_comparer: object impementing compare(), local comparer. 26 @param remote_comparer: object implementing compare(), remote comparer. 27 @param threshold: int, a value which the pixel difference between test 28 image and golden image has to exceed before the 29 remote comparer is used. 30 31 """ 32 self.local_comparer = local_comparer 33 self.remote_comparer = remote_comparer 34 self.threshold = threshold 35 36 37 def __enter__(self): 38 return self 39 40 41 @method_logger.log 42 def compare(self, golden_image_path, test_image_path, box=None): 43 """ 44 Compares a test image against a golden image using up to two comparers. 45 46 If the local comparer reports a fail, use the remote comparer to 47 compare the same images. 48 49 E.g of use case: You have two comparers, one is local and another is 50 web-based. Web-based comparer has the advantage of storing information 51 you need to look at the results later. 52 Local comparer is fast and reduces the load on the web-based comparer. 53 54 Use local comparer as primary comparer and only invoke the web-based 55 comparer on test images that differ from their golden counterparts. 56 57 @param golden_image_path: path, complete path to the golden image. 58 @param test_image_path: path, complete path to the test image. 59 @param box: int tuple, left, upper, right, lower pixel coordinates 60 defining a box region within which the comparison is made. 61 62 @return: int, differing pixels as per double check comparer. 63 64 """ 65 logging.debug('Using primary comparer..') 66 67 with self.local_comparer: 68 res = self.local_comparer.compare(golden_image_path, 69 test_image_path, 70 box) 71 diffpx = res.diff_pixel_count 72 logging.debug('Primary comparison complete. Diff pixels = %d', diffpx) 73 74 diffpx2 = -1 75 comp_res = res.comparison_url 76 77 if (diffpx > self.threshold): 78 logging.debug('Threshold diff pixels is %d', self.threshold) 79 logging.debug('Diff pxls > threshold. Using remote comparer.') 80 81 with self.remote_comparer: 82 res_remote = self.remote_comparer.compare(golden_image_path, 83 test_image_path, 84 box) 85 diffpx2 = res_remote.diff_pixel_count 86 87 if not comp_res: 88 comp_res = res_remote.comparison_url 89 90 logging.debug('Secondary comparison complete. Diff pixels = %d', 91 diffpx2) 92 93 diffpx_return = diffpx2 if diffpx2 != -1 else diffpx 94 95 96 return comparison_result.ComparisonResult(diffpx_return, 97 comp_res) 98 99 100 def __exit__(self, exc_type, exc_val, exc_tb): 101 pass 102