blob: bc6f13ef97b8194078d15c998ff3a8570552e3d0 [file] [log] [blame]
# Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""Touchpad firmware test report in html format."""
import json
import os
import re
import sys
import time
import urllib
import common_util
import firmware_log
import test_conf as conf
from firmware_constants import VLOG
from string import Template
class TemplateHtml:
"""An html Template."""
def __init__(self, image_width, image_height, score_colors):
self.score_colors = score_colors
# Define the template of the doc
self.doc = Template('$head $summary $logs $tail')
self.table = Template('<table border="3" width="100%"> $gestures '
'</table>')
self.gestures = []
# Define a template to show a gesture information including
# the gesture name, variation, prompt, image, and test results.
self.gesture_template = Template('''
<tr>
<td><table>
<tr>
<h3> $gesture_name.$variation </h3>
<h5> $prompt </h5>
</tr>
<tr>
<img src="data:image/png;base64,\n$image"
alt="$filename" width="%d" height="%d" />
</tr>
</table></td>
<td><table>
$vlogs
</table></td>
</tr>
''' % (image_width, image_height))
self.validator_template = Template('''
<tr>
<pre><span style="color:$color"><b>$name</b></span>
$details
criteria: $criteria
<span style="color:$color"><b>score: $score</b></span></pre>
</tr>
''')
self.detail_template = Template('<tr><h5> $detail </h5></tr>')
self._fill_doc()
def _html_head(self):
"""Fill the head of an html document."""
head = '\n'.join(['<!DOCTYPE html>', '<html>', '<body>'])
return head
def _html_tail(self):
"""Fill the tail of an html document."""
tail = '\n'.join(['</body>', '</html>'])
return tail
def _fill_doc(self):
"""Fill in fields into the doc."""
self.doc = Template(self.doc.safe_substitute(head=self._html_head(),
tail=self._html_tail()))
def get_score_color(self, score):
"""Present the score in different colors."""
for s, c in self.score_colors:
if score >= s:
return c
def _insert_details(self, details):
details_content = []
for detail in details:
details_content.append(' ' * 4 + detail.strip())
return '<br>'.join(details_content)
def _insert_vlog(self, vlog):
"""Insert a single vlog."""
score=vlog.get_score()
vlog_content = self.validator_template.safe_substitute(
name=vlog.get_name(),
details=self._insert_details(vlog.get_details()),
criteria=vlog.get_criteria(),
color=self.get_score_color(score),
score=score)
return vlog_content
def _insert_vlogs(self, vlogs):
"""Insert multiple vlogs."""
vlogs_content = []
for vlog in vlogs:
vlogs_content.append(self._insert_vlog(vlog))
return '<hr>'.join(vlogs_content)
def insert_gesture(self, glog, image, image_filename, vlogs):
"""Insert glog, image, and vlogs."""
vlogs_content = self._insert_vlogs(vlogs)
gesture = self.gesture_template.safe_substitute(
gesture_name=glog.get_name(),
variation=glog.get_variation(),
prompt=glog.get_prompt(),
image=image,
filename=image_filename,
vlogs=vlogs_content)
self.gestures.append(gesture)
def get_doc(self):
gestures = ''.join(self.gestures)
new_table = self.table.safe_substitute(gestures=gestures)
new_doc = self.doc.safe_substitute(logs=new_table)
return new_doc
class ReportHtml:
"""Firmware Report in html format."""
def __init__(self, filename, screen_size, touchpad_window_size,
score_colors):
self.html_filename = filename
self.screen_size = screen_size
self.image_width = self.screen_size[0] * 0.5
touchpad_width, touchpad_height = touchpad_window_size
self.image_height = self.image_width / touchpad_width * touchpad_height
self.doc = TemplateHtml(self.image_width, self.image_height,
score_colors)
self._reset_content()
self.log_dict = {}
self.log_dict[VLOG.DICT] = {}
self.log_dict[VLOG.GV_LIST] = []
def __del__(self):
self.stop()
def stop(self):
"""Close the file."""
with open(self.html_filename, 'w') as report_file:
report_file.write(self.doc.get_doc())
# Make a copy to /tmp so that it could be viewed in Chrome.
tmp_copy = os.path.join(conf.docroot,
os.path.basename(self.html_filename))
copy_cmd = 'cp %s %s' % (self.html_filename, tmp_copy)
common_util.simple_system(copy_cmd)
# Dump the logs to a json file
log_file_root = os.path.splitext(self.html_filename)[0]
log_file_name = os.extsep.join([log_file_root, 'log'])
with open(log_file_name, 'w') as log_file:
json.dump(self.log_dict, log_file)
def _reset_content(self):
self.glog = firmware_log.GestureLog()
self.encoded_image=''
self.image_filename=''
self.vlogs = []
def _get_content(self):
return [self.glog, self.encoded_image, self.image_filename, self.vlogs]
def _encode_base64(self, filename):
"""Encode a file in base 64 format."""
if not os.path.isfile(filename):
return None
encoded = urllib.quote(open(filename, "rb").read().encode("base64"))
return encoded
def reset_logs(self):
"Reset the details of vlogs."
for vlog in self.vlogs:
vlog.reset()
def _insert_log_dict(self, glog, vlogs):
"""Insert the glog and vlogs key value pair into the log dictionary."""
vlogs_scores = []
for vlog in vlogs:
vlog_score = {vlog.get_name(): vlog.get_score()}
vlogs_scores.append(vlog_score)
glog_key = str([glog.get_name(), glog.get_variation()])
self.log_dict[VLOG.DICT][glog_key] = vlogs_scores
self.log_dict[VLOG.GV_LIST].append(glog_key)
def flush(self):
"""Flush the current gesture including gesture log, image and
validator logs.
"""
content = self._get_content()
if all(content):
self.doc.insert_gesture(*content)
self._insert_log_dict(self.glog, self.vlogs)
self.reset_logs()
self._reset_content()
def insert_image(self, filename):
"""Insert an image into the document."""
self.encoded_image = self._encode_base64(filename)
self.image_filename = filename
def insert_result(self, text):
"""Insert the text into the document."""
self.result += text
def insert_gesture_log(self, log):
"""Update the gesture log."""
self.glog.update(log)
def insert_validator_logs(self, logs):
"""Update the validator logs."""
self.vlogs = logs