1 # Copyright 2015 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 5 import base64 6 import datetime 7 import glob 8 import os 9 import shutil 10 11 from autotest_lib.client.bin import utils 12 from autotest_lib.client.cros import constants 13 from string import Template 14 15 class ImageDiffPublisher(object): 16 """ 17 Class that takes care of creating the HTML file output when a pdiff 18 comparison fails. It moves each of the three images to a folder in the 19 results directory. It then writes a html file that references these images. 20 21 """ 22 23 VIEWER_FILES = '/usr/local/autotest/cros/image_comparison/diffviewer/*' 24 25 26 def __init__(self, results_folder): 27 """ 28 @param results_folder: path, where to publish to 29 """ 30 self.results_folder = results_folder 31 # Copy files needed to the results dir 32 for diff_viewer_file in glob.glob(self.VIEWER_FILES): 33 shutil.copy(diff_viewer_file, self.results_folder) 34 35 36 def publish(self, golden_image_path, test_image_path, diff_image_path, 37 tags): 38 """ 39 Move viewer files to the results folder and base64 encode the images. 40 Write tags to HTML file. 41 42 @param golden_image_path: path, complete path to a golden image. 43 @param test_image_path: path, complete path to a test image. 44 @param diff_image_path: path, complete path to a diff image. 45 @param tags: list, run information. 46 """ 47 48 # Encode the images to base64 49 base64_images = {} 50 with open(golden_image_path, "rb") as image_file: 51 base64_images["golden"] = base64.b64encode(image_file.read()) 52 with open(test_image_path, "rb") as image_file: 53 base64_images["test"] = base64.b64encode(image_file.read()) 54 with open(diff_image_path, "rb") as image_file: 55 base64_images["diff"] = base64.b64encode(image_file.read()) 56 57 # Append all of the things we push to the html template 58 tags.update(base64_images) 59 60 html_file_fullpath = os.path.join(self.results_folder, 'index.html') 61 self._write_tags_to_html(tags, html_file_fullpath) 62 63 64 def publish_paths(self, image_paths, testname): 65 """ 66 Creates a results page for an array of images. 67 68 Move viewer files to the results folder and base64 encode the images. 69 Write tags to HTML file. 70 71 @param image_paths: an array of paths 72 @param testname: name of current test. 73 """ 74 75 img_tags = [] 76 for img in image_paths: 77 with open(img, "rb") as image_file: 78 b64img = base64.b64encode(image_file.read()) 79 b64imgsrc = "data:image/png;base64, " + b64img 80 img_tags.append(b64imgsrc) 81 82 tags = self._generate_tags(testname) 83 tags['images'] = img_tags 84 html_file_fullpath = os.path.join(self.results_folder, 'slideshow.html') 85 self._write_tags_to_html(tags, html_file_fullpath) 86 87 88 def _write_tags_to_html(self, tags, html_filename): 89 """ 90 Writes tags to the HTML file 91 92 @param tags the tags to write into the html template 93 @param html_filename the full path to the html template 94 """ 95 96 with open(html_filename, 'r+') as f: 97 html = Template(f.read()) 98 formatted_html = html.substitute(tags) 99 f.seek(0) 100 f.write(formatted_html) 101 102 103 def _generate_tags(self, testname): 104 """ 105 Generate tags for the current test run 106 107 @param testname the name of the current test 108 @return an array of tags 109 """ 110 # get chrome version 111 version_string = utils.system_output( 112 constants.CHROME_VERSION_COMMAND, ignore_status=True) 113 version_string = utils.parse_chrome_version(version_string)[0] 114 115 return { 116 'testname': testname, 117 'chromeos_version': utils.get_chromeos_release_version(), 118 'chrome_version': version_string, 119 'board': utils.get_board(), 120 'date': datetime.date.today().strftime("%m/%d/%y"), 121 } 122