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

Side by Side Diff: lib/src/backend/metadata.dart

Issue 1405633004: feature: tag tests; choose tags on command line Base URL: git@github.com:yjbanov/test.git@tags
Patch Set: address review comments Created 5 years, 1 month 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
OLDNEW
1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 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. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 library test.backend.metadata; 5 library test.backend.metadata;
6 6
7 import 'dart:collection'; 7 import 'dart:collection';
8 8
9 import '../frontend/skip.dart'; 9 import '../frontend/skip.dart';
10 import '../frontend/timeout.dart'; 10 import '../frontend/timeout.dart';
(...skipping 16 matching lines...) Expand all
27 /// Whether the test or suite should be skipped. 27 /// Whether the test or suite should be skipped.
28 final bool skip; 28 final bool skip;
29 29
30 /// Whether to use verbose stack traces. 30 /// Whether to use verbose stack traces.
31 final bool verboseTrace; 31 final bool verboseTrace;
32 32
33 /// The reason the test or suite should be skipped, if given. 33 /// The reason the test or suite should be skipped, if given.
34 final String skipReason; 34 final String skipReason;
35 35
36 /// A set of tags attached to a test 36 /// A set of tags attached to a test
37 final List<String> tags; 37 final Set<String> tags;
38 38
39 /// Platform-specific metadata. 39 /// Platform-specific metadata.
40 /// 40 ///
41 /// Each key identifies a platform, and its value identifies the specific 41 /// Each key identifies a platform, and its value identifies the specific
42 /// metadata for that platform. These can be applied by calling [forPlatform]. 42 /// metadata for that platform. These can be applied by calling [forPlatform].
43 final Map<PlatformSelector, Metadata> onPlatform; 43 final Map<PlatformSelector, Metadata> onPlatform;
44 44
45 /// Parses a user-provided map into the value for [onPlatform]. 45 /// Parses a user-provided map into the value for [onPlatform].
46 static Map<PlatformSelector, Metadata> _parseOnPlatform( 46 static Map<PlatformSelector, Metadata> _parseOnPlatform(
47 Map<String, dynamic> onPlatform) { 47 Map<String, dynamic> onPlatform) {
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
84 result[selector] = new Metadata.parse(timeout: timeout, skip: skip); 84 result[selector] = new Metadata.parse(timeout: timeout, skip: skip);
85 }); 85 });
86 return result; 86 return result;
87 } 87 }
88 88
89 /// Creates new Metadata. 89 /// Creates new Metadata.
90 /// 90 ///
91 /// [testOn] defaults to [PlatformSelector.all]. 91 /// [testOn] defaults to [PlatformSelector.all].
92 Metadata({PlatformSelector testOn, Timeout timeout, bool skip: false, 92 Metadata({PlatformSelector testOn, Timeout timeout, bool skip: false,
93 this.verboseTrace: false, this.skipReason, 93 this.verboseTrace: false, this.skipReason,
94 Map<PlatformSelector, Metadata> onPlatform, List<String> tags}) 94 Map<PlatformSelector, Metadata> onPlatform, tags})
95 : testOn = testOn == null ? PlatformSelector.all : testOn, 95 : testOn = testOn == null ? PlatformSelector.all : testOn,
96 timeout = timeout == null ? const Timeout.factor(1) : timeout, 96 timeout = timeout == null ? const Timeout.factor(1) : timeout,
97 skip = skip, 97 skip = skip,
98 onPlatform = onPlatform == null 98 onPlatform = onPlatform == null
99 ? const {} 99 ? const {}
100 : new UnmodifiableMapView(onPlatform), 100 : new UnmodifiableMapView(onPlatform),
101 this.tags = tags ?? const <String>[]; 101 this.tags = _makeSetOfTags(tags);
nweiz 2015/11/03 00:43:16 The type-normalization should only happen in [new
yjbanov 2015/11/11 06:40:20 Done.
102 102
103 /// Creates a new Metadata, but with fields parsed from caller-friendly values 103 /// Creates a new Metadata, but with fields parsed from caller-friendly values
104 /// where applicable. 104 /// where applicable.
105 /// 105 ///
106 /// Throws a [FormatException] if any field is invalid. 106 /// Throws a [FormatException] if any field is invalid.
107 Metadata.parse({String testOn, Timeout timeout, skip, 107 Metadata.parse({String testOn, Timeout timeout, skip,
108 this.verboseTrace: false, Map<String, dynamic> onPlatform, 108 this.verboseTrace: false, Map<String, dynamic> onPlatform,
109 List<String> tags}) 109 tags})
110 : testOn = testOn == null 110 : testOn = testOn == null
111 ? PlatformSelector.all 111 ? PlatformSelector.all
112 : new PlatformSelector.parse(testOn), 112 : new PlatformSelector.parse(testOn),
113 timeout = timeout == null ? const Timeout.factor(1) : timeout, 113 timeout = timeout == null ? const Timeout.factor(1) : timeout,
114 skip = skip != null && skip != false, 114 skip = skip != null && skip != false,
115 skipReason = skip is String ? skip : null, 115 skipReason = skip is String ? skip : null,
116 onPlatform = _parseOnPlatform(onPlatform), 116 onPlatform = _parseOnPlatform(onPlatform),
117 this.tags = tags ?? const <String>[] { 117 this.tags = _makeSetOfTags(tags) {
118 if (skip != null && skip is! String && skip is! bool) { 118 if (skip != null && skip is! String && skip is! bool) {
119 throw new ArgumentError( 119 throw new ArgumentError(
120 '"skip" must be a String or a bool, was "$skip".'); 120 '"skip" must be a String or a bool, was "$skip".');
121 } 121 }
122 } 122 }
123 123
124 /// Dezerializes the result of [Metadata.serialize] into a new [Metadata]. 124 /// Deserializes the result of [Metadata.serialize] into a new [Metadata].
125 Metadata.deserialize(serialized) 125 Metadata.deserialize(serialized)
126 : testOn = serialized['testOn'] == null 126 : testOn = serialized['testOn'] == null
127 ? PlatformSelector.all 127 ? PlatformSelector.all
128 : new PlatformSelector.parse(serialized['testOn']), 128 : new PlatformSelector.parse(serialized['testOn']),
129 timeout = _deserializeTimeout(serialized['timeout']), 129 timeout = _deserializeTimeout(serialized['timeout']),
130 skip = serialized['skip'], 130 skip = serialized['skip'],
131 skipReason = serialized['skipReason'], 131 skipReason = serialized['skipReason'],
132 verboseTrace = serialized['verboseTrace'], 132 verboseTrace = serialized['verboseTrace'],
133 tags = serialized['tags'] ?? const <String>[], 133 tags = _makeSetOfTags(serialized['tags']),
134 onPlatform = new Map.fromIterable(serialized['onPlatform'], 134 onPlatform = new Map.fromIterable(serialized['onPlatform'],
135 key: (pair) => new PlatformSelector.parse(pair.first), 135 key: (pair) => new PlatformSelector.parse(pair.first),
136 value: (pair) => new Metadata.deserialize(pair.last)); 136 value: (pair) => new Metadata.deserialize(pair.last));
137 137
138 /// Deserializes timeout from the format returned by [_serializeTimeout]. 138 /// Deserializes timeout from the format returned by [_serializeTimeout].
139 static _deserializeTimeout(serialized) { 139 static _deserializeTimeout(serialized) {
140 if (serialized == 'none') return Timeout.none; 140 if (serialized == 'none') return Timeout.none;
141 var scaleFactor = serialized['scaleFactor']; 141 var scaleFactor = serialized['scaleFactor'];
142 if (scaleFactor != null) return new Timeout.factor(scaleFactor); 142 if (scaleFactor != null) return new Timeout.factor(scaleFactor);
143 return new Timeout( 143 return new Timeout(
144 new Duration(microseconds: serialized['duration'])); 144 new Duration(microseconds: serialized['duration']));
145 } 145 }
146 146
147 /// Return a new [Metadata] that merges [this] with [other]. 147 /// Return a new [Metadata] that merges [this] with [other].
148 /// 148 ///
149 /// If the two [Metadata]s have conflicting properties, [other] wins. 149 /// If the two [Metadata]s have conflicting properties, [other] wins.
150 Metadata merge(Metadata other) => 150 Metadata merge(Metadata other) =>
151 new Metadata( 151 new Metadata(
152 testOn: testOn.intersect(other.testOn), 152 testOn: testOn.intersect(other.testOn),
153 timeout: timeout.merge(other.timeout), 153 timeout: timeout.merge(other.timeout),
154 skip: skip || other.skip, 154 skip: skip || other.skip,
155 verboseTrace: verboseTrace || other.verboseTrace, 155 verboseTrace: verboseTrace || other.verboseTrace,
156 skipReason: other.skipReason == null ? skipReason : other.skipReason, 156 skipReason: other.skipReason == null ? skipReason : other.skipReason,
157 onPlatform: mergeMaps(onPlatform, other.onPlatform), 157 onPlatform: mergeMaps(onPlatform, other.onPlatform),
158 tags: mergeLists(tags, other.tags)); 158 tags: tags.union(other.tags));
159 159
160 /// Returns a copy of [this] with the given fields changed. 160 /// Returns a copy of [this] with the given fields changed.
161 Metadata change({PlatformSelector testOn, Timeout timeout, bool skip, 161 Metadata change({PlatformSelector testOn, Timeout timeout, bool skip,
162 bool verboseTrace, String skipReason, 162 bool verboseTrace, String skipReason,
163 Map<PlatformSelector, Metadata> onPlatform}) { 163 Map<PlatformSelector, Metadata> onPlatform}) {
164 if (testOn == null) testOn = this.testOn; 164 if (testOn == null) testOn = this.testOn;
165 if (timeout == null) timeout = this.timeout; 165 if (timeout == null) timeout = this.timeout;
166 if (skip == null) skip = this.skip; 166 if (skip == null) skip = this.skip;
167 if (verboseTrace == null) verboseTrace = this.verboseTrace; 167 if (verboseTrace == null) verboseTrace = this.verboseTrace;
168 if (skipReason == null) skipReason = this.skipReason; 168 if (skipReason == null) skipReason = this.skipReason;
(...skipping 25 matching lines...) Expand all
194 serializedOnPlatform.add([key.toString(), value.serialize()]); 194 serializedOnPlatform.add([key.toString(), value.serialize()]);
195 }); 195 });
196 196
197 return { 197 return {
198 'testOn': testOn == PlatformSelector.all ? null : testOn.toString(), 198 'testOn': testOn == PlatformSelector.all ? null : testOn.toString(),
199 'timeout': _serializeTimeout(timeout), 199 'timeout': _serializeTimeout(timeout),
200 'skip': skip, 200 'skip': skip,
201 'skipReason': skipReason, 201 'skipReason': skipReason,
202 'verboseTrace': verboseTrace, 202 'verboseTrace': verboseTrace,
203 'onPlatform': serializedOnPlatform, 203 'onPlatform': serializedOnPlatform,
204 'tags': tags.isEmpty ? null : tags, 204 'tags': tags.toList(),
205 }; 205 };
206 } 206 }
207 207
208 /// Serializes timeout into a JSON-safe object. 208 /// Serializes timeout into a JSON-safe object.
209 _serializeTimeout(Timeout timeout) { 209 _serializeTimeout(Timeout timeout) {
210 if (timeout == Timeout.none) return 'none'; 210 if (timeout == Timeout.none) return 'none';
211 return { 211 return {
212 'duration': timeout.duration == null 212 'duration': timeout.duration == null
213 ? null 213 ? null
214 : timeout.duration.inMicroseconds, 214 : timeout.duration.inMicroseconds,
215 'scaleFactor': timeout.scaleFactor 215 'scaleFactor': timeout.scaleFactor
216 }; 216 };
217 } 217 }
218 } 218 }
219
220 /// Converts [tags] to a [Set] of unique tags, unless it is already a [Set].
221 ///
222 /// `null` becomes an empty set. [String] is split on commas.
223 Set<String> _makeSetOfTags(tags) => tags != null
224 ? tags is Iterable
225 ? _tagsFromIterable(tags)
226 : tags is String
227 ? _tagsFromString(tags)
228 : throw new ArgumentError.value(tags, "tags",
229 "must be either String or Iterable")
230 : new Set<String>();
231
232 Set<String> _tagsFromIterable(Iterable tags) {
233 for (var tag in tags) {
234 if (tag is! String) {
235 throw new ArgumentError.value(tags, "tags", "tag name must be String");
236 }
237 if (tag.trim().isEmpty) {
nweiz 2015/11/03 00:43:16 I'd rather not trim here. If users want to use whi
yjbanov 2015/11/11 06:40:20 I thought it would be more practical given we acce
nweiz 2015/11/16 21:59:44 I'd like to keep the semantics on the Dart side in
yjbanov 2015/11/26 06:30:27 Done.
238 throw new ArgumentError.value(tags, "tags",
239 "tag name must contain non-whitespace characters");
240 }
241 }
242 return tags is Set<String> ? tags : new Set<String>.from(tags);
243 }
244
245 Set<String> _tagsFromString(String tags) {
246 if (tags.trim().isEmpty) return new Set<String>();
247 return _tagsFromIterable(
248 tags.split(",").map((tag) => tag.trim()).where((tag) => tag.isNotEmpty));
nweiz 2015/11/03 00:43:16 I'd rather require users to use a real list if the
yjbanov 2015/11/11 06:40:20 I thought it would make it consistent with the com
yjbanov 2015/11/26 06:30:27 Done.
249 }
OLDNEW
« no previous file with comments | « lib/src/backend/declarer.dart ('k') | lib/src/runner.dart » ('j') | test/runner/runner_test.dart » ('J')

Powered by Google App Engine
This is Rietveld 408576698