Merge tag 'dm-9oct18' of git://git.denx.de/u-boot-dm
[platform/kernel/u-boot.git] / test / py / multiplexed_log.py
index 35a32fb..637a3bd 100644 (file)
@@ -1,12 +1,12 @@
+# SPDX-License-Identifier: GPL-2.0
 # Copyright (c) 2015 Stephen Warren
 # Copyright (c) 2015-2016, NVIDIA CORPORATION. All rights reserved.
-#
-# SPDX-License-Identifier: GPL-2.0
 
 # Generate an HTML-formatted log file containing multiple streams of data,
 # each represented in a well-delineated/-structured fashion.
 
 import cgi
+import datetime
 import os.path
 import shutil
 import subprocess
@@ -102,6 +102,7 @@ class RunAndLog(object):
         self.name = name
         self.chained_file = chained_file
         self.output = None
+        self.exit_status = None
 
     def close(self):
         """Clean up any resources managed by this object."""
@@ -163,9 +164,11 @@ class RunAndLog(object):
         self.logfile.write(self, output)
         if self.chained_file:
             self.chained_file.write(output)
+        self.logfile.timestamp()
 
         # Store the output so it can be accessed if we raise an exception.
         self.output = output
+        self.exit_status = exit_status
         if exception:
             raise exception
         return output
@@ -217,6 +220,10 @@ class Logfile(object):
         self.blocks = []
         self.cur_evt = 1
         self.anchor = 0
+        self.timestamp_start = self._get_time()
+        self.timestamp_prev = self.timestamp_start
+        self.timestamp_blocks = []
+        self.seen_warning = False
 
         shutil.copy(mod_dir + '/multiplexed_log.css', os.path.dirname(fn))
         self.f.write('''\
@@ -245,6 +252,7 @@ $(document).ready(function () {
     passed_bcs = passed_bcs.not(":has(.status-xfail)");
     passed_bcs = passed_bcs.not(":has(.status-xpass)");
     passed_bcs = passed_bcs.not(":has(.status-skipped)");
+    passed_bcs = passed_bcs.not(":has(.status-warning)");
     // Hide the passed blocks
     passed_bcs.addClass("hidden");
     // Flip the expand/contract button hiding for those blocks.
@@ -306,8 +314,9 @@ $(document).ready(function () {
 
     # The set of characters that should be represented as hexadecimal codes in
     # the log file.
-    _nonprint = ('%' + ''.join(chr(c) for c in range(0, 32) if c not in (9, 10)) +
-                 ''.join(chr(c) for c in range(127, 256)))
+    _nonprint = {ord('%')}
+    _nonprint.update({c for c in range(0, 32) if c not in (9, 10)})
+    _nonprint.update({c for c in range(127, 256)})
 
     def _escape(self, data):
         """Render data format suitable for inclusion in an HTML document.
@@ -323,7 +332,7 @@ $(document).ready(function () {
         """
 
         data = data.replace(chr(13), '')
-        data = ''.join((c in self._nonprint) and ('%%%02x' % ord(c)) or
+        data = ''.join((ord(c) in self._nonprint) and ('%%%02x' % ord(c)) or
                        c for c in data)
         data = cgi.escape(data)
         return data
@@ -363,13 +372,13 @@ $(document).ready(function () {
 
         self._terminate_stream()
         self.f.write('<div class="' + note_type + '">\n')
-        if anchor:
-            self.f.write('<a href="#%s">\n' % anchor)
         self.f.write('<pre>')
+        if anchor:
+            self.f.write('<a href="#%s">' % anchor)
         self.f.write(self._escape(msg))
-        self.f.write('\n</pre>\n')
         if anchor:
-            self.f.write('</a>\n')
+            self.f.write('</a>')
+        self.f.write('\n</pre>\n')
         self.f.write('</div>\n')
 
     def start_section(self, marker, anchor=None):
@@ -386,6 +395,7 @@ $(document).ready(function () {
 
         self._terminate_stream()
         self.blocks.append(marker)
+        self.timestamp_blocks.append(self._get_time())
         if not anchor:
             self.anchor += 1
             anchor = str(self.anchor)
@@ -394,6 +404,7 @@ $(document).ready(function () {
         self.f.write('<div class="section-header block-header">Section: ' +
                      blk_path + '</div>\n')
         self.f.write('<div class="section-content block-content">\n')
+        self.timestamp()
 
         return anchor
 
@@ -414,6 +425,11 @@ $(document).ready(function () {
             raise Exception('Block nesting mismatch: "%s" "%s"' %
                             (marker, '/'.join(self.blocks)))
         self._terminate_stream()
+        timestamp_now = self._get_time()
+        timestamp_section_start = self.timestamp_blocks.pop()
+        delta_section = timestamp_now - timestamp_section_start
+        self._note("timestamp",
+            "TIME: SINCE-SECTION: " + str(delta_section))
         blk_path = '/'.join(self.blocks)
         self.f.write('<div class="section-trailer block-trailer">' +
                      'End section: ' + blk_path + '</div>\n')
@@ -464,8 +480,23 @@ $(document).ready(function () {
             Nothing.
         """
 
+        self.seen_warning = True
         self._note("warning", msg)
 
+    def get_and_reset_warning(self):
+        """Get and reset the log warning flag.
+
+        Args:
+            None
+
+        Returns:
+            Whether a warning was seen since the last call.
+        """
+
+        ret = self.seen_warning
+        self.seen_warning = False
+        return ret
+
     def info(self, msg):
         """Write an informational note to the log file.
 
@@ -490,6 +521,31 @@ $(document).ready(function () {
 
         self._note("action", msg)
 
+    def _get_time(self):
+        return datetime.datetime.now()
+
+    def timestamp(self):
+        """Write a timestamp to the log file.
+
+        Args:
+            None
+
+        Returns:
+            Nothing.
+        """
+
+        timestamp_now = self._get_time()
+        delta_prev = timestamp_now - self.timestamp_prev
+        delta_start = timestamp_now - self.timestamp_start
+        self.timestamp_prev = timestamp_now
+
+        self._note("timestamp",
+            "TIME: NOW: " + timestamp_now.strftime("%Y/%m/%d %H:%M:%S.%f"))
+        self._note("timestamp",
+            "TIME: SINCE-PREV: " + str(delta_prev))
+        self._note("timestamp",
+            "TIME: SINCE-START: " + str(delta_start))
+
     def status_pass(self, msg, anchor=None):
         """Write a note to the log file describing test(s) which passed.
 
@@ -503,6 +559,19 @@ $(document).ready(function () {
 
         self._note("status-pass", msg, anchor)
 
+    def status_warning(self, msg, anchor=None):
+        """Write a note to the log file describing test(s) which passed.
+
+        Args:
+            msg: A message describing the passed test(s).
+            anchor: Optional internal link target.
+
+        Returns:
+            Nothing.
+        """
+
+        self._note("status-warning", msg, anchor)
+
     def status_skipped(self, msg, anchor=None):
         """Write a note to the log file describing skipped test(s).