File: result_output.py

package info (click to toggle)
chromium 139.0.7258.127-1
  • links: PTS, VCS
  • area: main
  • in suites:
  • size: 6,122,068 kB
  • sloc: cpp: 35,100,771; ansic: 7,163,530; javascript: 4,103,002; python: 1,436,920; asm: 946,517; xml: 746,709; pascal: 187,653; perl: 88,691; sh: 88,436; objc: 79,953; sql: 51,488; cs: 44,583; fortran: 24,137; makefile: 22,147; tcl: 15,277; php: 13,980; yacc: 8,984; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (140 lines) | stat: -rw-r--r-- 4,829 bytes parent folder | download | duplicates (6)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
# Copyright 2021 The Chromium Authors
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""Module for outputting results in a human-readable format."""

import tempfile
from typing import Dict, IO, List, Optional, Union

# //testing imports.
from flake_suppressor_common import common_typing as ct

UrlListType = List[str]
StringTagsToUrlsType = Dict[str, UrlListType]
TestToStringTagsType = Dict[str, StringTagsToUrlsType]
StringMapType = Dict[str, TestToStringTagsType]

TestToUrlListType = Dict[str, UrlListType]
SuiteToTestsType = Dict[str, TestToUrlListType]
ConfigGroupedStringMapType = Dict[str, SuiteToTestsType]

NodeType = Union[UrlListType, StringTagsToUrlsType, TestToStringTagsType,
                 StringMapType, TestToUrlListType, SuiteToTestsType,
                 ConfigGroupedStringMapType]


def GenerateHtmlOutputFile(aggregated_results: ct.AggregatedResultsType,
                           outfile: Optional[IO] = None) -> None:
  """Generates an HTML results file.

  Args:
    aggregated_results: A map containing the aggregated test results.
    outfile: A file-like object to output to. Will create one if not provided.
  """
  outfile = outfile or tempfile.NamedTemporaryFile(
      mode='w', delete=False, suffix='.html')
  try:
    outfile.write('<html>\n<body>\n')
    string_map = _ConvertAggregatedResultsToStringMap(aggregated_results)
    _OutputMapToHtmlFile(string_map, 'Grouped By Test', outfile)
    config_map = _ConvertFromTestGroupingToConfigGrouping(string_map)
    _OutputMapToHtmlFile(config_map, 'Grouped By Config', outfile)
    outfile.write('</body>\n</html>\n')
  finally:
    outfile.close()
  print('HTML results: %s' % outfile.name)


def _OutputMapToHtmlFile(string_map: StringMapType, result_header: str,
                         output_file: IO) -> None:
  """Outputs a map to a file as a nested list.

  Args:
    string_map: The string map to output.
    result_header: A string containing the header contents placed before the
        nested list.
    output_file: A file-like object to output the map to.
  """
  output_file.write('<h1>%s</h1>\n' % result_header)
  output_file.write('<ul>\n')
  _RecursiveHtmlToFile(string_map, output_file)
  output_file.write('</ul>\n')


def _RecursiveHtmlToFile(node: NodeType, output_file: IO) -> None:
  """Recursively outputs a string map to an output file as HTML.

  Specifically, contents are output as an unordered list (<ul>).

  Args:
    node: The current node to output. Must be either a dict or list.
    output_file: A file-like object to output the HTML to.
  """
  if isinstance(node, dict):
    for key, value in node.items():
      output_file.write('<li>%s</li>\n' % key)
      output_file.write('<ul>\n')
      _RecursiveHtmlToFile(value, output_file)
      output_file.write('</ul>\n')
  elif isinstance(node, list):
    for element in node:
      output_file.write('<li><a href="%s">%s</a></li>\n' % (element, element))
  else:
    raise RuntimeError('Unsupported type %s' % type(node).__name__)


def _ConvertAggregatedResultsToStringMap(
    aggregated_results: ct.AggregatedResultsType) -> StringMapType:
  """Converts aggregated results to a format usable by _RecursiveHtmlToFile.

  Specifically, updates the string representation of the typ tags and replaces
  the lowest level dict with the build URL list.

  Args:
    aggregated_results: A map containing the aggregated test results.

  Returns:
    A map in the format:
    {
      'suite': {
        'test': {
          'space separated typ tags': ['build', 'url', 'list']
        }
      }
    }
  """
  string_map = {}
  for suite, test_map in aggregated_results.items():
    for test, tag_map in test_map.items():
      for typ_tags, build_url_list in tag_map.items():
        str_typ_tags = ' '.join(typ_tags)
        string_map.setdefault(suite,
                              {}).setdefault(test,
                                             {})[str_typ_tags] = build_url_list
  return string_map


def _ConvertFromTestGroupingToConfigGrouping(string_map: StringMapType
                                             ) -> ConfigGroupedStringMapType:
  """Converts |string| map to be grouped by typ tags/configuration.

  Args:
    string_map: The output of _ConvertAggregatedResultsToStringMap.

  Returns:
    A map in the format:
    {
      'space separated typ tags': {
        'suite': {
          'test': ['build', 'url', 'list']
        }
      }
    }
  """
  converted_map = {}
  for suite, test_map in string_map.items():
    for test, tag_map in test_map.items():
      for typ_tags, build_urls in tag_map.items():
        converted_map.setdefault(typ_tags, {}).setdefault(suite,
                                                          {})[test] = build_urls
  return converted_map