Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(80)

Side by Side Diff: tools/testing/dart/status_file.dart

Issue 2880203004: Re-apply status file parser changes from 0b7728da1bef08c1c1e092005d9fd8c8bff5fa6c. (Closed)
Patch Set: Explicitly stringify variable in status expressions. Created 3 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « tools/testing/dart/status_expression.dart ('k') | tools/testing/dart/status_file_parser.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file.
4
5 import 'dart:io';
6
7 import 'expectation.dart';
8 import 'status_expression.dart';
9
10 /// Splits out a trailing line comment
11 final _commentPattern = new RegExp("^([^#]*)(#.*)?\$");
12
13 /// Matches the header that begins a new section, like:
14 ///
15 /// [ $compiler == dart2js && $minified ]
16 final _sectionPattern = new RegExp(r"^\[([^\]]+)\]");
17
18 /// Matches an entry that defines the status for a path in the current section,
19 /// like:
20 ///
21 /// some/path/to/some_test: Pass || Fail
22 final _entryPattern = new RegExp(r"\s*([^: ]*)\s*:(.*)");
23
24 /// Matches an issue number in a comment, like:
25 ///
26 /// blah_test: Fail # Issue 1234
27 /// ^^^^
28 final _issuePattern = new RegExp("[Ii]ssue ([0-9]+)");
29
30 /// A parsed status file, which describes how a collection of tests are
31 /// expected to behave under various configurations and conditions.
32 ///
33 /// Each status file is made of a series of sections. Each section begins with
34 /// a header, followed by a series of entries. A header is enclosed in square
35 /// brackets and contains a Boolean expression. That expression is evaluated in
36 /// an environment. If it evaluates to true, then the entries after the header
37 /// take effect.
38 ///
39 /// Each entry is a glob-like file path followed by a colon and then a
40 /// comma-separated list of [Expectation]s. The path may point to an individual
41 /// file, or a directory, in which case it applies to all files under that path.
42 ///
43 /// Entries may also appear before any section header, in which case they
44 /// always apply.
45 class StatusFile {
46 final List<StatusSection> sections = [];
47
48 /// Parses the status file at [path].
49 StatusFile.read(String path) {
50 var lines = new File(path).readAsLinesSync();
51
52 // The current section whose rules are being parsed.
53 StatusSection section;
54
55 var lineNumber = 0;
56 for (var line in lines) {
57 lineNumber++;
58
59 // Strip off the comment and whitespace.
60 var match = _commentPattern.firstMatch(line);
61 var source = "";
62 var comment = "";
63 if (match != null) {
64 source = match[1].trim();
65 comment = match[2] ?? "";
66 }
67
68 // Ignore empty (or comment-only) lines.
69 if (source.isEmpty) continue;
70
71 // See if we are starting a new section.
72 match = _sectionPattern.firstMatch(source);
73 if (match != null) {
74 var condition = Expression.parse(match[1].trim());
75 section = new StatusSection(condition);
76 sections.add(section);
77 continue;
78 }
79
80 // Otherwise, it should be a new entry under the current section.
81 match = _entryPattern.firstMatch(source);
82 if (match != null) {
83 var path = match[1].trim();
84 // TODO(whesse): Handle test names ending in a wildcard (*).
85 var expectations = _parseExpectations(match[2]);
86 var issue = _issueNumber(comment);
87
88 // If we haven't found a section header yet, create an implicit section
89 // that matches everything.
90 if (section == null) {
91 section = new StatusSection(null);
92 sections.add(section);
93 }
94
95 section.entries.add(new StatusEntry(path, expectations, issue));
96 continue;
97 }
98
99 throw new FormatException(
100 "Could not parse line $lineNumber of status file '$path':\n$line");
101 }
102 }
103
104 /// Parses a comma-separated list of expectation names from [text].
105 List<Expectation> _parseExpectations(String text) {
106 return text
107 .split(",")
108 .map((name) => Expectation.find(name.trim()))
109 .toList();
110 }
111
112 /// Returns the issue number embedded in [comment] or `null` if there is none.
113 int _issueNumber(String comment) {
114 var match = _issuePattern.firstMatch(comment);
115 if (match == null) return null;
116
117 return int.parse(match[1], onError: (_) => null);
118 }
119
120 String toString() {
121 var buffer = new StringBuffer();
122 for (var section in sections) {
123 buffer.writeln("[${section._condition}]");
124
125 for (var entry in section.entries) {
126 buffer.write("${entry.path}: ${entry.expectations.join(', ')}");
127 if (entry.issue != null) buffer.write(" # Issue ${entry.issue}");
128 buffer.writeln();
129 }
130
131 buffer.writeln();
132 }
133
134 return buffer.toString();
135 }
136 }
137
138 /// One section in a status file.
139 ///
140 /// Contains the condition from the header that begins the section, then all of
141 /// the entries within the section.
142 class StatusSection {
143 /// The expression that determines when this section is applied.
144 ///
145 /// May be `null` for paths that appear before any section header in the file.
146 /// In that case, the section always applies.
147 final Expression _condition;
148 final List<StatusEntry> entries = [];
149
150 /// Returns true if this section should apply in the given [environment].
151 bool isEnabled(Map<String, dynamic> environment) =>
152 _condition == null || _condition.evaluate(environment);
153
154 StatusSection(this._condition);
155 }
156
157 /// Describes the test status of the file or files at a given path.
158 class StatusEntry {
159 final String path;
160 final List<Expectation> expectations;
161 final int issue;
162
163 StatusEntry(this.path, this.expectations, this.issue);
164 }
OLDNEW
« no previous file with comments | « tools/testing/dart/status_expression.dart ('k') | tools/testing/dart/status_file_parser.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698