Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 import 'dart:collection'; | 5 import 'dart:collection'; |
| 6 | 6 |
| 7 import 'package:collection/collection.dart'; | 7 import 'package:collection/collection.dart'; |
| 8 import 'package:boolean_selector/boolean_selector.dart'; | |
|
kevmoo
2016/02/19 00:45:35
sorting
nweiz
2016/02/19 00:54:04
Done.
| |
| 8 | 9 |
| 9 import '../frontend/skip.dart'; | 10 import '../frontend/skip.dart'; |
| 10 import '../frontend/timeout.dart'; | 11 import '../frontend/timeout.dart'; |
| 11 import '../utils.dart'; | 12 import '../utils.dart'; |
| 12 import 'operating_system.dart'; | 13 import 'operating_system.dart'; |
| 13 import 'platform_selector.dart'; | 14 import 'platform_selector.dart'; |
| 14 import 'test_platform.dart'; | 15 import 'test_platform.dart'; |
| 15 | 16 |
| 16 /// Metadata for a test or test suite. | 17 /// Metadata for a test or test suite. |
| 17 /// | 18 /// |
| (...skipping 23 matching lines...) Expand all Loading... | |
| 41 /// Each key identifies a platform, and its value identifies the specific | 42 /// Each key identifies a platform, and its value identifies the specific |
| 42 /// metadata for that platform. These can be applied by calling [forPlatform]. | 43 /// metadata for that platform. These can be applied by calling [forPlatform]. |
| 43 final Map<PlatformSelector, Metadata> onPlatform; | 44 final Map<PlatformSelector, Metadata> onPlatform; |
| 44 | 45 |
| 45 /// Metadata that applies only when specific tags are applied. | 46 /// Metadata that applies only when specific tags are applied. |
| 46 /// | 47 /// |
| 47 /// Tag-specific metadata is applied when merging this with other metadata. | 48 /// Tag-specific metadata is applied when merging this with other metadata. |
| 48 /// Note that unlike [onPlatform], the base metadata takes precedence over any | 49 /// Note that unlike [onPlatform], the base metadata takes precedence over any |
| 49 /// tag-specific metadata. | 50 /// tag-specific metadata. |
| 50 /// | 51 /// |
| 51 /// This is guaranteed not to have any keys that appear in [tags]; those are | 52 /// This is guaranteed not to have any keys that match [tags]; those are |
| 52 /// resolved when the metadata is constructed. | 53 /// resolved when the metadata is constructed. |
| 53 final Map<String, Metadata> forTag; | 54 final Map<BooleanSelector, Metadata> forTag; |
| 54 | 55 |
| 55 /// Parses a user-provided map into the value for [onPlatform]. | 56 /// Parses a user-provided map into the value for [onPlatform]. |
| 56 static Map<PlatformSelector, Metadata> _parseOnPlatform( | 57 static Map<PlatformSelector, Metadata> _parseOnPlatform( |
| 57 Map<String, dynamic> onPlatform) { | 58 Map<String, dynamic> onPlatform) { |
| 58 if (onPlatform == null) return {}; | 59 if (onPlatform == null) return {}; |
| 59 | 60 |
| 60 var result = {}; | 61 var result = {}; |
| 61 onPlatform.forEach((platform, metadata) { | 62 onPlatform.forEach((platform, metadata) { |
| 62 if (metadata is Timeout || metadata is Skip) { | 63 if (metadata is Timeout || metadata is Skip) { |
| 63 metadata = [metadata]; | 64 metadata = [metadata]; |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 111 throw new ArgumentError.value(tags, "tags", "must contain only Strings."); | 112 throw new ArgumentError.value(tags, "tags", "must contain only Strings."); |
| 112 } | 113 } |
| 113 | 114 |
| 114 return new Set.from(tags); | 115 return new Set.from(tags); |
| 115 } | 116 } |
| 116 | 117 |
| 117 /// Creates new Metadata. | 118 /// Creates new Metadata. |
| 118 /// | 119 /// |
| 119 /// [testOn] defaults to [PlatformSelector.all]. | 120 /// [testOn] defaults to [PlatformSelector.all]. |
| 120 /// | 121 /// |
| 121 /// If [forTag] contains metadata for any tags in [tags], that metadata is | 122 /// If [forTag] contains metadata that applies to [tags], that metadata is |
| 122 /// included inline in the returned value. The values directly passed to the | 123 /// included inline in the returned value. The values directly passed to the |
| 123 /// constructor take precedence over tag-specific metadata. | 124 /// constructor take precedence over tag-specific metadata. |
| 124 factory Metadata({PlatformSelector testOn, Timeout timeout, bool skip: false, | 125 factory Metadata({PlatformSelector testOn, Timeout timeout, bool skip: false, |
| 125 bool verboseTrace: false, String skipReason, Iterable<String> tags, | 126 bool verboseTrace: false, String skipReason, Iterable<String> tags, |
| 126 Map<PlatformSelector, Metadata> onPlatform, | 127 Map<PlatformSelector, Metadata> onPlatform, |
| 127 Map<String, Metadata> forTag}) { | 128 Map<BooleanSelector, Metadata> forTag}) { |
| 128 // If there's no tag-specific metadata, or if none of it applies, just | 129 // Returns metadata without forTag resolved at all. |
| 129 // return the metadata as-is. | 130 _unresolved() => new Metadata._( |
| 130 if (forTag == null || tags == null || !tags.any(forTag.containsKey)) { | |
| 131 return new Metadata._( | |
| 132 testOn: testOn, | |
| 133 timeout: timeout, | |
| 134 skip: skip, | |
| 135 verboseTrace: verboseTrace, | |
| 136 skipReason: skipReason, | |
| 137 tags: tags, | |
| 138 onPlatform: onPlatform, | |
| 139 forTag: forTag); | |
| 140 } | |
| 141 | |
| 142 // Otherwise, resolve the tag-specific components. Doing this eagerly means | |
| 143 // we only have to resolve suite- or group-level tags once, rather than | |
| 144 // doing it for every test individually. | |
| 145 forTag = new Map.from(forTag); | |
| 146 var merged = tags.fold(new Metadata._(), (merged, tag) { | |
| 147 var tagMetadata = forTag.remove(tag); | |
| 148 return tagMetadata == null ? merged : merged.merge(tagMetadata); | |
| 149 }); | |
| 150 | |
| 151 return merged.merge(new Metadata._( | |
| 152 testOn: testOn, | 131 testOn: testOn, |
| 153 timeout: timeout, | 132 timeout: timeout, |
| 154 skip: skip, | 133 skip: skip, |
| 155 verboseTrace: verboseTrace, | 134 verboseTrace: verboseTrace, |
| 156 skipReason: skipReason, | 135 skipReason: skipReason, |
| 157 tags: tags, | 136 tags: tags, |
| 158 onPlatform: onPlatform, | 137 onPlatform: onPlatform, |
| 159 forTag: forTag)); | 138 forTag: forTag); |
| 139 | |
| 140 // If there's no tag-specific metadata, or if none of it applies, just | |
| 141 // return the metadata as-is. | |
| 142 if (forTag == null || tags == null) return _unresolved(); | |
| 143 | |
| 144 // Otherwise, resolve the tag-specific components. Doing this eagerly means | |
| 145 // we only have to resolve suite- or group-level tags once, rather than | |
| 146 // doing it for every test individually. | |
| 147 var empty = new Metadata._(); | |
| 148 var merged = forTag.keys.toList().fold(empty, (merged, selector) { | |
| 149 if (!selector.evaluate(tags)) return merged; | |
| 150 return merged.merge(forTag.remove(selector)); | |
| 151 }); | |
| 152 | |
| 153 if (merged == empty) return _unresolved(); | |
| 154 return merged.merge(_unresolved()); | |
| 160 } | 155 } |
| 161 | 156 |
| 162 /// Creates new Metadata. | 157 /// Creates new Metadata. |
| 163 /// | 158 /// |
| 164 /// Unlike [new Metadata], this assumes [forTag] is already resolved. | 159 /// Unlike [new Metadata], this assumes [forTag] is already resolved. |
| 165 Metadata._({PlatformSelector testOn, Timeout timeout, bool skip: false, | 160 Metadata._({PlatformSelector testOn, Timeout timeout, bool skip: false, |
| 166 this.verboseTrace: false, this.skipReason, Iterable<String> tags, | 161 this.verboseTrace: false, this.skipReason, Iterable<String> tags, |
| 167 Map<PlatformSelector, Metadata> onPlatform, | 162 Map<PlatformSelector, Metadata> onPlatform, |
| 168 Map<String, Metadata> forTag}) | 163 Map<BooleanSelector, Metadata> forTag}) |
| 169 : testOn = testOn == null ? PlatformSelector.all : testOn, | 164 : testOn = testOn == null ? PlatformSelector.all : testOn, |
| 170 timeout = timeout == null ? const Timeout.factor(1) : timeout, | 165 timeout = timeout == null ? const Timeout.factor(1) : timeout, |
| 171 skip = skip, | 166 skip = skip, |
| 172 tags = new UnmodifiableSetView( | 167 tags = new UnmodifiableSetView( |
| 173 tags == null ? new Set() : tags.toSet()), | 168 tags == null ? new Set() : tags.toSet()), |
| 174 onPlatform = onPlatform == null | 169 onPlatform = onPlatform == null |
| 175 ? const {} | 170 ? const {} |
| 176 : new UnmodifiableMapView(onPlatform), | 171 : new UnmodifiableMapView(onPlatform), |
| 177 forTag = forTag == null | 172 forTag = forTag == null |
| 178 ? const {} | 173 ? const {} |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 211 : new PlatformSelector.parse(serialized['testOn']), | 206 : new PlatformSelector.parse(serialized['testOn']), |
| 212 timeout = _deserializeTimeout(serialized['timeout']), | 207 timeout = _deserializeTimeout(serialized['timeout']), |
| 213 skip = serialized['skip'], | 208 skip = serialized['skip'], |
| 214 skipReason = serialized['skipReason'], | 209 skipReason = serialized['skipReason'], |
| 215 verboseTrace = serialized['verboseTrace'], | 210 verboseTrace = serialized['verboseTrace'], |
| 216 tags = new Set.from(serialized['tags']), | 211 tags = new Set.from(serialized['tags']), |
| 217 onPlatform = new Map.fromIterable(serialized['onPlatform'], | 212 onPlatform = new Map.fromIterable(serialized['onPlatform'], |
| 218 key: (pair) => new PlatformSelector.parse(pair.first), | 213 key: (pair) => new PlatformSelector.parse(pair.first), |
| 219 value: (pair) => new Metadata.deserialize(pair.last)), | 214 value: (pair) => new Metadata.deserialize(pair.last)), |
| 220 forTag = mapMap(serialized['forTag'], | 215 forTag = mapMap(serialized['forTag'], |
| 216 key: (key, _) => new BooleanSelector.parse(key), | |
| 221 value: (_, nested) => new Metadata.deserialize(nested)); | 217 value: (_, nested) => new Metadata.deserialize(nested)); |
| 222 | 218 |
| 223 /// Deserializes timeout from the format returned by [_serializeTimeout]. | 219 /// Deserializes timeout from the format returned by [_serializeTimeout]. |
| 224 static _deserializeTimeout(serialized) { | 220 static _deserializeTimeout(serialized) { |
| 225 if (serialized == 'none') return Timeout.none; | 221 if (serialized == 'none') return Timeout.none; |
| 226 var scaleFactor = serialized['scaleFactor']; | 222 var scaleFactor = serialized['scaleFactor']; |
| 227 if (scaleFactor != null) return new Timeout.factor(scaleFactor); | 223 if (scaleFactor != null) return new Timeout.factor(scaleFactor); |
| 228 return new Timeout( | 224 return new Timeout( |
| 229 new Duration(microseconds: serialized['duration'])); | 225 new Duration(microseconds: serialized['duration'])); |
| 230 } | 226 } |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 301 }); | 297 }); |
| 302 | 298 |
| 303 return { | 299 return { |
| 304 'testOn': testOn == PlatformSelector.all ? null : testOn.toString(), | 300 'testOn': testOn == PlatformSelector.all ? null : testOn.toString(), |
| 305 'timeout': _serializeTimeout(timeout), | 301 'timeout': _serializeTimeout(timeout), |
| 306 'skip': skip, | 302 'skip': skip, |
| 307 'skipReason': skipReason, | 303 'skipReason': skipReason, |
| 308 'verboseTrace': verboseTrace, | 304 'verboseTrace': verboseTrace, |
| 309 'tags': tags.toList(), | 305 'tags': tags.toList(), |
| 310 'onPlatform': serializedOnPlatform, | 306 'onPlatform': serializedOnPlatform, |
| 311 'forTag': mapMap(forTag, value: (_, metadata) => metadata.serialize()) | 307 'forTag': mapMap(forTag, |
| 308 key: (selector, _) => selector.toString(), | |
| 309 value: (_, metadata) => metadata.serialize()) | |
| 312 }; | 310 }; |
| 313 } | 311 } |
| 314 | 312 |
| 315 /// Serializes timeout into a JSON-safe object. | 313 /// Serializes timeout into a JSON-safe object. |
| 316 _serializeTimeout(Timeout timeout) { | 314 _serializeTimeout(Timeout timeout) { |
| 317 if (timeout == Timeout.none) return 'none'; | 315 if (timeout == Timeout.none) return 'none'; |
| 318 return { | 316 return { |
| 319 'duration': timeout.duration == null | 317 'duration': timeout.duration == null |
| 320 ? null | 318 ? null |
| 321 : timeout.duration.inMicroseconds, | 319 : timeout.duration.inMicroseconds, |
| 322 'scaleFactor': timeout.scaleFactor | 320 'scaleFactor': timeout.scaleFactor |
| 323 }; | 321 }; |
| 324 } | 322 } |
| 325 } | 323 } |
| OLD | NEW |