Flutter Engine
The Flutter Engine
collect_data.py
Go to the documentation of this file.
1#!/usr/bin/env python3
2# Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
3# for details. All rights reserved. Use of this source code is governed by a
4# BSD-style license that can be found in the LICENSE file.
5#
6"""Webscraper for make_a_fuzz nightly cluster run results.
7
8Given the uri of a make_a_fuzz run, this script will first
9extract the links pointing to each of the individual shards
10and then parse the output generated by each shard to
11find divergences reported by the dartfuzz_test.dart program,
12concatenate all output, or summarize all test results.
13
14Example:
15 collect_data.py --type sum
16 https://ci.chromium.org/p/dart/builders/ci.sandbox/fuzz-linux/303
17"""
18
19# This script may require a one time install of BeautifulSoup:
20# sudo apt-get install python3-bs4
21
22import argparse
23import re
24import sys
25
26from bs4 import BeautifulSoup
27
28import requests
29
30
31# Matches shard raw stdout to extract divergence reports.
32P_DIV = re.compile("(Isolate.+? !DIVERGENCE! (\n|.)+?)Isolate ", re.MULTILINE)
33
34# Matches shard raw stdout to extract report summaries.
35P_SUM = re.compile(
36 r"^Tests: (\d+) Success: (\d+) "
37 r"\‍(Rerun: (\d+)\‍) Skipped: (\d+) "
38 r"Timeout: (\d+) Divergences: (\d+)", re.MULTILINE)
39
40# Matches uri to extract shard number.
41P_SHARD = re.compile(r".*make_a_fuzz_shard_(\d+)")
42
43
45 links = []
46 resp = requests.get(uri)
47 soup = BeautifulSoup(resp.text, "html.parser")
48 for a in soup.findAll("a"):
49 if "stdout" in a.text:
50 href = a["href"]
51 if ("make_a_fuzz_shard" in href and "__trigger__" not in href):
52 links.append(href + "?format=raw")
53 return links
54
55
57 # Re-encoding avoids breaking some terminals.
58 print(text.encode("ascii", errors="ignore").decode("unicode-escape"))
59
60
62 print_reencoded(text)
63
64
65def print_output_div(shard, text, keywords):
66 sys.stderr.write("Shard: " + shard + " \r")
67 m = P_DIV.findall(text)
68 if m:
69 for x in m:
70 keep = True
71 for word in keywords:
72 if word in x[0]:
73 keep = False
74 break
75 if keep:
76 print_reencoded(x[0])
77
78
79def get_output_sum(shard, text, should_print, s=[0, 0, 0, 0, 0, 0], divs=[]):
80 m = P_SUM.findall(text)
81 if not m:
82 sys.stderr.write("Failed to parse shard %s stdout for summary" % shard)
83 return
84 for test in m:
85 if int(test[-1]) == 1:
86 divs.append(shard)
87 for i in range(len(s)):
88 s[i] += int(test[i])
89 if should_print:
90 print(
91 "Tests: %d Success: %d (Rerun: %d) Skipped: %d Timeout: %d "
92 "Divergences: %d (failing shards: %s) \r" %
93 tuple(s + [", ".join(divs) if divs else "none"]),
94 end="")
95 return s
96
97
98def get_stats(uri, output_type, keywords, output_csv):
99 resp = requests.get(uri)
100
101 if output_type == "all":
102 print_output_all(resp.text)
103 elif output_type == "div":
104 shard = P_SHARD.findall(uri)[0]
105 print_output_div(shard, resp.text, keywords)
106 elif output_type == "sum":
107 shard = P_SHARD.findall(uri)[0]
108 should_print = not output_csv
109 return get_output_sum(shard, resp.text, should_print)
110 return None
111
112
113def main():
114 parser = argparse.ArgumentParser(description=__doc__)
115 parser.add_argument(
116 "--type",
117 choices=("div", "sum", "all"),
118 required=True,
119 help=
120 "Select output type (div: divergence report, sum: summary, all: complete stdout)"
121 )
122 parser.add_argument(
123 "--filter",
124 nargs="+",
125 default=[],
126 help="Do not include divergences containing these keywords.")
127 parser.add_argument(
128 "--output-csv",
129 dest="output_csv",
130 action="store_true",
131 default=False,
132 help=
133 "Print output in CSV format to stdout. Only supported for --type=sum")
134 parser.add_argument(
135 "uri",
136 type=str,
137 help=
138 "Uri of one make_a_fuzz run from https://ci.chromium.org/p/dart/builders/ci.sandbox/fuzz-linux."
139 )
140 args = parser.parse_args()
141 if args.type != 'sum' and args.output_csv:
142 print('Error: --output-csv can only be provided for --type=sum')
143 return
144
145 shard_links = get_shard_links(args.uri)
146
147 if len(shard_links) == 0:
148 print("Invalid run")
149 sys.exit(-1)
150 return
151
152 for link in shard_links:
153 stats = get_stats(link, args.type, args.filter, args.output_csv)
154 if args.output_csv:
155 print("%d,%d,%d,%d,%d,%d" % tuple(stats))
156 else:
157 print("")
158 sys.exit(0)
159
160
161if __name__ == "__main__":
162 main()
def get_stats(uri, output_type, keywords, output_csv)
Definition: collect_data.py:98
def get_shard_links(uri)
Definition: collect_data.py:44
def get_output_sum(shard, text, should_print, s=[0, 0, 0, 0, 0, 0], divs=[])
Definition: collect_data.py:79
def print_output_all(text)
Definition: collect_data.py:61
def print_output_div(shard, text, keywords)
Definition: collect_data.py:65
def print_reencoded(text)
Definition: collect_data.py:56
Definition: main.py:1
def print(*args, **kwargs)
Definition: run_tests.py:49
static DecodeResult decode(std::string path)
Definition: png_codec.cpp:124
static SkString join(const CommandLineFlags::StringArray &)
Definition: skpbench.cpp:741