| OLD | NEW |
| 1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2016, 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.md file. | 3 // BSD-style license that can be found in the LICENSE.md file. |
| 4 | 4 |
| 5 library testing.chain; | 5 library testing.chain; |
| 6 | 6 |
| 7 import 'dart:async' show | 7 import 'dart:async' show |
| 8 Future, | 8 Future, |
| 9 Stream; | 9 Stream; |
| 10 | 10 |
| (...skipping 27 matching lines...) Expand all Loading... |
| 38 import 'log.dart' show | 38 import 'log.dart' show |
| 39 logMessage, | 39 logMessage, |
| 40 logStepComplete, | 40 logStepComplete, |
| 41 logStepStart, | 41 logStepStart, |
| 42 logSuiteComplete, | 42 logSuiteComplete, |
| 43 logTestComplete, | 43 logTestComplete, |
| 44 logUnexpectedResult, | 44 logUnexpectedResult, |
| 45 splitLines; | 45 splitLines; |
| 46 | 46 |
| 47 import 'multitest.dart' show | 47 import 'multitest.dart' show |
| 48 MultitestTransformer; | 48 MultitestTransformer, |
| 49 isError; |
| 49 | 50 |
| 50 typedef Future<ChainContext> CreateContext( | 51 typedef Future<ChainContext> CreateContext( |
| 51 Chain suite, Map<String, String> environment); | 52 Chain suite, Map<String, String> environment); |
| 52 | 53 |
| 53 /// A test suite for tool chains, for example, a compiler. | 54 /// A test suite for tool chains, for example, a compiler. |
| 54 class Chain extends Suite { | 55 class Chain extends Suite { |
| 55 final Uri source; | 56 final Uri source; |
| 56 | 57 |
| 57 final Uri uri; | 58 final Uri uri; |
| 58 | 59 |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 133 <TestDescription, Set<Expectation>>{}; | 134 <TestDescription, Set<Expectation>>{}; |
| 134 int completed = 0; | 135 int completed = 0; |
| 135 List<Future> futures = <Future>[]; | 136 List<Future> futures = <Future>[]; |
| 136 for (TestDescription description in descriptions) { | 137 for (TestDescription description in descriptions) { |
| 137 String selector = "${suite.name}/${description.shortName}"; | 138 String selector = "${suite.name}/${description.shortName}"; |
| 138 if (selectors.isNotEmpty && | 139 if (selectors.isNotEmpty && |
| 139 !selectors.contains(selector) && | 140 !selectors.contains(selector) && |
| 140 !selectors.contains(suite.name)) { | 141 !selectors.contains(suite.name)) { |
| 141 continue; | 142 continue; |
| 142 } | 143 } |
| 143 Set<Expectation> expectedOutcomes = | 144 final Set<Expectation> expectedOutcomes = |
| 144 expectations.expectations(description.shortName); | 145 expectations.expectations(description.shortName); |
| 146 final StringBuffer sb = new StringBuffer(); |
| 147 final Step lastStep = steps.isNotEmpty ? steps.last : null; |
| 148 final Iterator<Step> iterator = steps.iterator; |
| 149 |
| 145 Result result; | 150 Result result; |
| 146 StringBuffer sb = new StringBuffer(); | |
| 147 // Records the outcome of the last step that was run. | 151 // Records the outcome of the last step that was run. |
| 148 Step lastStep = null; | 152 Step lastStepRun; |
| 149 Iterator<Step> iterator = steps.iterator; | |
| 150 | 153 |
| 151 /// Performs one step of [iterator]. | 154 /// Performs one step of [iterator]. |
| 152 /// | 155 /// |
| 153 /// If `step.isAsync` is true, the corresponding step is said to be | 156 /// If `step.isAsync` is true, the corresponding step is said to be |
| 154 /// asynchronous. | 157 /// asynchronous. |
| 155 /// | 158 /// |
| 156 /// If a step is asynchrouns the future returned from this function will | 159 /// If a step is asynchrouns the future returned from this function will |
| 157 /// complete after the the first asynchronous step is scheduled. This | 160 /// complete after the the first asynchronous step is scheduled. This |
| 158 /// allows us to start processing the next test while an external process | 161 /// allows us to start processing the next test while an external process |
| 159 /// completes as steps can be interleaved. To ensure all steps are | 162 /// completes as steps can be interleaved. To ensure all steps are |
| 160 /// completed, wait for [futures]. | 163 /// completed, wait for [futures]. |
| 161 /// | 164 /// |
| 162 /// Otherwise, the future returned will complete when all steps are | 165 /// Otherwise, the future returned will complete when all steps are |
| 163 /// completed. This ensures that tests are run in sequence without | 166 /// completed. This ensures that tests are run in sequence without |
| 164 /// interleaving steps. | 167 /// interleaving steps. |
| 165 Future doStep(dynamic input) async { | 168 Future doStep(dynamic input) async { |
| 166 Future future; | 169 Future future; |
| 167 bool isAsync = false; | 170 bool isAsync = false; |
| 168 if (iterator.moveNext()) { | 171 if (iterator.moveNext()) { |
| 169 Step step = iterator.current; | 172 Step step = iterator.current; |
| 170 lastStep = step; | 173 lastStepRun = step; |
| 171 isAsync = step.isAsync; | 174 isAsync = step.isAsync; |
| 172 logStepStart(completed, unexpectedResults.length, descriptions.length, | 175 logStepStart(completed, unexpectedResults.length, descriptions.length, |
| 173 suite, description, step); | 176 suite, description, step); |
| 174 future = runGuarded(() async { | 177 future = runGuarded(() async { |
| 175 try { | 178 try { |
| 176 return await step.run(input, this); | 179 return await step.run(input, this); |
| 177 } catch (error, trace) { | 180 } catch (error, trace) { |
| 178 return step.unhandledError(error, trace); | 181 return step.unhandledError(error, trace); |
| 179 } | 182 } |
| 180 }, printLineOnStdout: sb.writeln); | 183 }, printLineOnStdout: sb.writeln); |
| 181 } else { | 184 } else { |
| 182 future = new Future.value(null); | 185 future = new Future.value(null); |
| 183 } | 186 } |
| 184 future = future.then((Result currentResult) { | 187 future = future.then((Result currentResult) { |
| 185 if (currentResult != null) { | 188 if (currentResult != null) { |
| 186 logStepComplete(completed, unexpectedResults.length, | 189 logStepComplete(completed, unexpectedResults.length, |
| 187 descriptions.length, suite, description, lastStep); | 190 descriptions.length, suite, description, lastStepRun); |
| 188 result = currentResult; | 191 result = currentResult; |
| 189 if (currentResult.outcome == Expectation.PASS) { | 192 if (currentResult.outcome == Expectation.PASS) { |
| 190 // The input to the next step is the output of this step. | 193 // The input to the next step is the output of this step. |
| 191 return doStep(result.output); | 194 return doStep(result.output); |
| 192 } | 195 } |
| 193 } | 196 } |
| 194 if (steps.isNotEmpty && steps.last == lastStep && | 197 if (description.multitestExpectations != null) { |
| 198 if (isError(description.multitestExpectations)) { |
| 199 result = result.toNegativeTestResult(); |
| 200 } |
| 201 } else if (lastStep == lastStepRun && |
| 195 description.shortName.endsWith("negative_test")) { | 202 description.shortName.endsWith("negative_test")) { |
| 196 if (result.outcome == Expectation.PASS) { | 203 if (result.outcome == Expectation.PASS) { |
| 197 result.addLog("Negative test didn't report an error.\n"); | 204 result.addLog("Negative test didn't report an error.\n"); |
| 198 } else if (result.outcome == Expectation.FAIL) { | 205 } else if (result.outcome == Expectation.FAIL) { |
| 199 result.addLog("Negative test reported an error as expeceted.\n"); | 206 result.addLog("Negative test reported an error as expeceted.\n"); |
| 200 } | 207 } |
| 201 result = result.toNegativeTestResult(); | 208 result = result.toNegativeTestResult(); |
| 202 } | 209 } |
| 203 if (!expectedOutcomes.contains(result.outcome)) { | 210 if (!expectedOutcomes.contains(result.outcome)) { |
| 204 result.addLog("$sb"); | 211 result.addLog("$sb"); |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 255 } | 262 } |
| 256 } | 263 } |
| 257 | 264 |
| 258 abstract class Step<I, O, C extends ChainContext> { | 265 abstract class Step<I, O, C extends ChainContext> { |
| 259 const Step(); | 266 const Step(); |
| 260 | 267 |
| 261 String get name; | 268 String get name; |
| 262 | 269 |
| 263 bool get isAsync => false; | 270 bool get isAsync => false; |
| 264 | 271 |
| 272 bool get isCompiler => false; |
| 273 |
| 274 bool get isRuntime => false; |
| 275 |
| 265 Future<Result<O>> run(I input, C context); | 276 Future<Result<O>> run(I input, C context); |
| 266 | 277 |
| 267 Result<O> unhandledError(error, StackTrace trace) { | 278 Result<O> unhandledError(error, StackTrace trace) { |
| 268 return new Result<O>.crash(error, trace); | 279 return new Result<O>.crash(error, trace); |
| 269 } | 280 } |
| 270 | 281 |
| 271 Result<O> pass(O output) => new Result<O>.pass(output); | 282 Result<O> pass(O output) => new Result<O>.pass(output); |
| 272 | 283 |
| 273 Result<O> crash(error, StackTrace trace) => new Result<O>.crash(error, trace); | 284 Result<O> crash(error, StackTrace trace) => new Result<O>.crash(error, trace); |
| 274 | 285 |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 321 Future<Null> runChain( | 332 Future<Null> runChain( |
| 322 CreateContext f, Map<String, String> environment, Set<String> selectors, | 333 CreateContext f, Map<String, String> environment, Set<String> selectors, |
| 323 String json) { | 334 String json) { |
| 324 return withErrorHandling(() async { | 335 return withErrorHandling(() async { |
| 325 Chain suite = new Suite.fromJsonMap(Uri.base, JSON.decode(json)); | 336 Chain suite = new Suite.fromJsonMap(Uri.base, JSON.decode(json)); |
| 326 print("Running ${suite.name}"); | 337 print("Running ${suite.name}"); |
| 327 ChainContext context = await f(suite, environment); | 338 ChainContext context = await f(suite, environment); |
| 328 return context.run(suite, selectors); | 339 return context.run(suite, selectors); |
| 329 }); | 340 }); |
| 330 } | 341 } |
| OLD | NEW |