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
5import base64
6import datetime
7import glob
8import os
9import shutil
10
11from autotest_lib.client.bin import utils
12from autotest_lib.client.cros import constants
13from string import Template
14
15class 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