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 library test.backend.metadata; | 5 library test.backend.metadata; |
| 6 | 6 |
| 7 import 'dart:collection'; | |
| 8 | |
| 9 import '../frontend/skip.dart'; | |
| 7 import '../frontend/timeout.dart'; | 10 import '../frontend/timeout.dart'; |
| 11 import '../utils.dart'; | |
| 8 import 'platform_selector.dart'; | 12 import 'platform_selector.dart'; |
| 9 | 13 |
| 10 /// Metadata for a test or test suite. | 14 /// Metadata for a test or test suite. |
| 11 /// | 15 /// |
| 12 /// This metadata comes from declarations on the test itself; it doesn't include | 16 /// This metadata comes from declarations on the test itself; it doesn't include |
| 13 /// configuration from the user. | 17 /// configuration from the user. |
| 14 class Metadata { | 18 class Metadata { |
| 15 /// The selector indicating which platforms the suite supports. | 19 /// The selector indicating which platforms the suite supports. |
| 16 final PlatformSelector testOn; | 20 final PlatformSelector testOn; |
| 17 | 21 |
| 18 /// The modification to the timeout for the test or suite. | 22 /// The modification to the timeout for the test or suite. |
| 19 final Timeout timeout; | 23 final Timeout timeout; |
| 20 | 24 |
| 21 /// Whether the test or suite should be skipped. | 25 /// Whether the test or suite should be skipped. |
| 22 final bool skip; | 26 final bool skip; |
| 23 | 27 |
| 24 /// The reason the test or suite should be skipped, if given. | 28 /// The reason the test or suite should be skipped, if given. |
| 25 final String skipReason; | 29 final String skipReason; |
| 26 | 30 |
| 31 /// Platform-specific metadata. | |
| 32 /// | |
| 33 /// Each key identifies a platform, and its value identifies the specific | |
| 34 /// metadata for that platform. These can be applied by calling [forPlatform]. | |
| 35 final Map<PlatformSelector, Metadata> onPlatform; | |
| 36 | |
| 37 /// Parses a user-provided map into the value for [onPlatform]. | |
| 38 static Map<PlatformSelector, Metadata> _parseOnPlatform( | |
| 39 Map<String, dynamic> onPlatform) { | |
| 40 if (onPlatform == null) return {}; | |
| 41 | |
| 42 var result = {}; | |
| 43 onPlatform.forEach((platform, metadata) { | |
| 44 if (metadata is Timeout || metadata is Skip) { | |
| 45 metadata = [metadata]; | |
| 46 } else if (metadata is! List) { | |
| 47 throw new ArgumentError('Metadata for platform "$platform" must be a ' | |
| 48 'Timeout, Skip, or List of those; was "$metadata".'); | |
| 49 } | |
| 50 | |
| 51 var selector = new PlatformSelector.parse(platform); | |
| 52 | |
| 53 var timeout; | |
| 54 var skip; | |
| 55 for (var metadatum in metadata) { | |
| 56 if (metadatum is Timeout) { | |
| 57 if (timeout != null) { | |
| 58 throw new ArgumentError('Only a single Timeout may be declared for ' | |
| 59 '"$platform".'); | |
| 60 } | |
| 61 | |
| 62 timeout = metadatum; | |
| 63 } else if (metadatum is Skip) { | |
| 64 if (skip != null) { | |
| 65 throw new ArgumentError('Only a single Skip may be declared for ' | |
| 66 '"$platform".'); | |
| 67 } | |
| 68 | |
| 69 skip = metadatum.reason == null ? true : metadatum.reason; | |
| 70 } else { | |
| 71 throw new ArgumentError('Metadata for platform "$platform" must be a ' | |
| 72 'Timeout, Skip, or List of those; was "$metadata".'); | |
| 73 } | |
| 74 } | |
| 75 | |
| 76 result[selector] = new Metadata.parse(timeout: timeout, skip: skip); | |
| 77 }); | |
| 78 return result; | |
| 79 } | |
| 80 | |
| 27 /// Creates new Metadata. | 81 /// Creates new Metadata. |
| 28 /// | 82 /// |
| 29 /// [testOn] defaults to [PlatformSelector.all]. | 83 /// [testOn] defaults to [PlatformSelector.all]. |
| 30 Metadata({PlatformSelector testOn, Timeout timeout, bool skip: false, | 84 Metadata({PlatformSelector testOn, Timeout timeout, bool skip: false, |
| 31 this.skipReason}) | 85 this.skipReason, Map<PlatformSelector, Metadata> onPlatform}) |
| 32 : testOn = testOn == null ? PlatformSelector.all : testOn, | 86 : testOn = testOn == null ? PlatformSelector.all : testOn, |
| 33 timeout = timeout == null ? const Timeout.factor(1) : timeout, | 87 timeout = timeout == null ? const Timeout.factor(1) : timeout, |
| 34 skip = skip; | 88 skip = skip, |
| 89 onPlatform = onPlatform == null | |
| 90 ? const {} | |
| 91 : new UnmodifiableMapView(onPlatform); | |
| 35 | 92 |
| 36 /// Creates a new Metadata, but with fields parsed from strings where | 93 /// Creates a new Metadata, but with fields parsed from caller-friendly values |
| 37 /// applicable. | 94 /// where applicable. |
| 38 /// | 95 /// |
| 39 /// Throws a [FormatException] if any field is invalid. | 96 /// Throws a [FormatException] if any field is invalid. |
| 40 Metadata.parse({String testOn, Timeout timeout, skip}) | 97 Metadata.parse({String testOn, Timeout timeout, skip, |
| 98 Map<String, dynamic> onPlatform}) | |
| 41 : testOn = testOn == null | 99 : testOn = testOn == null |
| 42 ? PlatformSelector.all | 100 ? PlatformSelector.all |
| 43 : new PlatformSelector.parse(testOn), | 101 : new PlatformSelector.parse(testOn), |
| 44 timeout = timeout == null ? const Timeout.factor(1) : timeout, | 102 timeout = timeout == null ? const Timeout.factor(1) : timeout, |
| 45 skip = skip != null && skip != false, | 103 skip = skip != null && skip != false, |
| 46 skipReason = skip is String ? skip : null { | 104 skipReason = skip is String ? skip : null, |
| 105 onPlatform = _parseOnPlatform(onPlatform) { | |
| 47 if (skip != null && skip is! String && skip is! bool) { | 106 if (skip != null && skip is! String && skip is! bool) { |
| 48 throw new ArgumentError( | 107 throw new ArgumentError( |
| 49 '"skip" must be a String or a bool, was "$skip".'); | 108 '"skip" must be a String or a bool, was "$skip".'); |
| 50 } | 109 } |
| 51 } | 110 } |
| 52 | 111 |
| 53 /// Dezerializes the result of [Metadata.serialize] into a new [Metadata]. | 112 /// Dezerializes the result of [Metadata.serialize] into a new [Metadata]. |
| 54 Metadata.deserialize(serialized) | 113 Metadata.deserialize(serialized) |
| 55 : this.parse( | 114 : testOn = serialized['testOn'] == null |
| 56 testOn: serialized['testOn'], | 115 ? PlatformSelector.all |
| 57 timeout: serialized['timeout']['duration'] == null | 116 : new PlatformSelector.parse(serialized['testOn']), |
| 58 ? new Timeout.factor(serialized['timeout']['scaleFactor']) | 117 timeout = serialized['timeout']['duration'] == null |
| 59 : new Timeout(new Duration( | 118 ? new Timeout.factor(serialized['timeout']['scaleFactor']) |
| 60 microseconds: serialized['timeout']['duration'])), | 119 : new Timeout(new Duration( |
| 61 skip: serialized['skipReason'] == null | 120 microseconds: serialized['timeout']['duration'])), |
| 62 ? serialized['skip'] | 121 skip = serialized['skip'], |
| 63 : serialized['skipReason']); | 122 skipReason = serialized['skipReason'], |
| 123 onPlatform = new Map.fromIterable(serialized['onPlatform'], | |
| 124 key: (pair) => new PlatformSelector.parse(pair.first), | |
| 125 value: (pair) => new Metadata.deserialize(pair.last)); | |
| 64 | 126 |
| 65 /// Return a new [Metadata] that merges [this] with [other]. | 127 /// Return a new [Metadata] that merges [this] with [other]. |
| 66 /// | 128 /// |
| 67 /// If the two [Metadata]s have conflicting properties, [other] wins. | 129 /// If the two [Metadata]s have conflicting properties, [other] wins. |
| 68 Metadata merge(Metadata other) => | 130 Metadata merge(Metadata other) => |
| 69 new Metadata( | 131 new Metadata( |
| 70 testOn: testOn.intersect(other.testOn), | 132 testOn: testOn.intersect(other.testOn), |
| 71 timeout: timeout.merge(other.timeout), | 133 timeout: timeout.merge(other.timeout), |
| 72 skip: skip || other.skip, | 134 skip: skip || other.skip, |
| 73 skipReason: other.skipReason == null ? skipReason : other.skipReason); | 135 skipReason: other.skipReason == null ? skipReason : other.skipReason, |
| 136 onPlatform: mergeMaps(onPlatform, other.onPlatform)); | |
| 137 | |
| 138 /// Returns a copy of [this] with the given fields changed. | |
| 139 Metadata change({PlatformSelector testOn, Timeout timeout, bool skip, | |
| 140 String skipReason, Map<PlatformSelector, Metadata> onPlatform}) { | |
| 141 if (testOn == null) testOn = this.testOn; | |
| 142 if (timeout == null) timeout = this.timeout; | |
| 143 if (skip == null) skip = this.skip; | |
| 144 if (skipReason == null) skipReason = this.skipReason; | |
| 145 if (onPlatform == null) onPlatform = this.onPlatform; | |
| 146 return new Metadata(testOn: testOn, timeout: timeout, skip: skip, | |
| 147 skipReason: skipReason, onPlatform: onPlatform); | |
| 148 } | |
| 149 | |
| 150 /// Returns a copy of [this] with all platform-specific metadata from | |
| 151 /// [onPlatform] resolved. | |
| 152 Metadata forPlatform(TestPlatform platform, {OperatingSystem os}) { | |
|
kevmoo
2015/04/20 22:42:30
TestPlatform and OperatingSystem are not defined
nweiz
2015/04/20 22:57:53
Done.
| |
| 153 var metadata = this; | |
| 154 test.metadata.onPlatform.forEach((platformSelector, platformMetadata) { | |
|
kevmoo
2015/04/20 22:42:30
test is not defined
nweiz
2015/04/20 22:57:53
Done.
| |
| 155 if (!platformSelector.evaluate(platform, os: os)) return; | |
| 156 metadata = metadata.merge(platformMetadata); | |
| 157 }); | |
| 158 return metadata.change(onPlatform: {}); | |
| 159 } | |
| 74 | 160 |
| 75 /// Serializes [this] into a JSON-safe object that can be deserialized using | 161 /// Serializes [this] into a JSON-safe object that can be deserialized using |
| 76 /// [new Metadata.deserialize]. | 162 /// [new Metadata.deserialize]. |
| 77 serialize() => { | 163 serialize() { |
| 78 'testOn': testOn == PlatformSelector.all ? null : testOn.toString(), | 164 // Make this a list to guarantee that the order is preserved. |
| 79 'timeout': { | 165 var serializedOnPlatform = []; |
| 80 'duration': timeout.duration == null | 166 onPlatform.forEach((key, value) { |
| 81 ? null | 167 serializedOnPlatform.add([key.toString(), value.serialize()]); |
| 82 : timeout.duration.inMicroseconds, | 168 }); |
| 83 'scaleFactor': timeout.scaleFactor | 169 |
| 84 }, | 170 return { |
| 85 'skip': skip, | 171 'testOn': testOn == PlatformSelector.all ? null : testOn.toString(), |
| 86 'skipReason': skipReason | 172 'timeout': { |
| 87 }; | 173 'duration': timeout.duration == null |
| 174 ? null | |
| 175 : timeout.duration.inMicroseconds, | |
| 176 'scaleFactor': timeout.scaleFactor | |
| 177 }, | |
| 178 'skip': skip, | |
| 179 'skipReason': skipReason, | |
| 180 'onPlatform': serializedOnPlatform | |
| 181 }; | |
| 182 } | |
| 88 } | 183 } |
| OLD | NEW |