| OLD | NEW |
| (Empty) | |
| 1 library test_case; |
| 2 |
| 3 import 'command.dart'; |
| 4 import 'status_file_parser.dart'; |
| 5 import 'test_information.dart'; |
| 6 import 'test_utils.dart'; |
| 7 import 'utils.dart'; |
| 8 |
| 9 const int SLOW_TIMEOUT_MULTIPLIER = 4; |
| 10 |
| 11 typedef void TestCaseEvent(TestCase testCase); |
| 12 |
| 13 /** |
| 14 * TestCase contains all the information needed to run a test and evaluate |
| 15 * its output. Running a test involves starting a separate process, with |
| 16 * the executable and arguments given by the TestCase, and recording its |
| 17 * stdout and stderr output streams, and its exit code. TestCase only |
| 18 * contains static information about the test; actually running the test is |
| 19 * performed by [ProcessQueue] using a [RunningProcess] object. |
| 20 * |
| 21 * The output information is stored in a [CommandOutput] instance contained |
| 22 * in TestCase.commandOutputs. The last CommandOutput instance is responsible |
| 23 * for evaluating if the test has passed, failed, crashed, or timed out, and the |
| 24 * TestCase has information about what the expected result of the test should |
| 25 * be. |
| 26 * |
| 27 * The TestCase has a callback function, [completedHandler], that is run when |
| 28 * the test is completed. |
| 29 */ |
| 30 class TestCase extends UniqueObject { |
| 31 // Flags set in _expectations from the optional argument info. |
| 32 static final int IS_NEGATIVE = 1 << 0; |
| 33 static final int HAS_RUNTIME_ERROR = 1 << 1; |
| 34 static final int HAS_STATIC_WARNING = 1 << 2; |
| 35 static final int IS_NEGATIVE_IF_CHECKED = 1 << 3; |
| 36 static final int HAS_COMPILE_ERROR = 1 << 4; |
| 37 static final int HAS_COMPILE_ERROR_IF_CHECKED = 1 << 5; |
| 38 static final int EXPECT_COMPILE_ERROR = 1 << 6; |
| 39 /** |
| 40 * A list of commands to execute. Most test cases have a single command. |
| 41 * Dart2js tests have two commands, one to compile the source and another |
| 42 * to execute it. Some isolate tests might even have three, if they require |
| 43 * compiling multiple sources that are run in isolation. |
| 44 */ |
| 45 List<Command> commands; |
| 46 Map<Command, CommandOutput> commandOutputs = new Map<Command,CommandOutput>(); |
| 47 |
| 48 Map configuration; |
| 49 String displayName; |
| 50 int _expectations = 0; |
| 51 int hash = 0; |
| 52 Set<Expectation> expectedOutcomes; |
| 53 |
| 54 TestCase(this.displayName, |
| 55 this.commands, |
| 56 this.configuration, |
| 57 this.expectedOutcomes, |
| 58 {isNegative: false, |
| 59 TestInformation info: null}) { |
| 60 if (isNegative || displayName.contains("negative_test")) { |
| 61 _expectations |= IS_NEGATIVE; |
| 62 } |
| 63 if (info != null) { |
| 64 _setExpectations(info); |
| 65 hash = info.originTestPath.relativeTo(TestUtils.dartDir) |
| 66 .toString().hashCode; |
| 67 } |
| 68 } |
| 69 |
| 70 void _setExpectations(TestInformation info) { |
| 71 // We don't want to keep the entire (large) TestInformation structure, |
| 72 // so we copy the needed bools into flags set in a single integer. |
| 73 if (info.hasRuntimeError) _expectations |= HAS_RUNTIME_ERROR; |
| 74 if (info.hasStaticWarning) _expectations |= HAS_STATIC_WARNING; |
| 75 if (info.isNegativeIfChecked) _expectations |= IS_NEGATIVE_IF_CHECKED; |
| 76 if (info.hasCompileError) _expectations |= HAS_COMPILE_ERROR; |
| 77 if (info.hasCompileErrorIfChecked) { |
| 78 _expectations |= HAS_COMPILE_ERROR_IF_CHECKED; |
| 79 } |
| 80 if (info.hasCompileError || |
| 81 (configuration['checked'] && info.hasCompileErrorIfChecked)) { |
| 82 _expectations |= EXPECT_COMPILE_ERROR; |
| 83 } |
| 84 } |
| 85 |
| 86 bool get isNegative => _expectations & IS_NEGATIVE != 0; |
| 87 bool get hasRuntimeError => _expectations & HAS_RUNTIME_ERROR != 0; |
| 88 bool get hasStaticWarning => _expectations & HAS_STATIC_WARNING != 0; |
| 89 bool get isNegativeIfChecked => _expectations & IS_NEGATIVE_IF_CHECKED != 0; |
| 90 bool get hasCompileError => _expectations & HAS_COMPILE_ERROR != 0; |
| 91 bool get hasCompileErrorIfChecked => |
| 92 _expectations & HAS_COMPILE_ERROR_IF_CHECKED != 0; |
| 93 bool get expectCompileError => _expectations & EXPECT_COMPILE_ERROR != 0; |
| 94 |
| 95 bool get unexpectedOutput { |
| 96 var outcome = lastCommandOutput.result(this); |
| 97 return !expectedOutcomes.any((expectation) { |
| 98 return outcome.canBeOutcomeOf(expectation); |
| 99 }); |
| 100 } |
| 101 |
| 102 Expectation get result => lastCommandOutput.result(this); |
| 103 |
| 104 CommandOutput get lastCommandOutput { |
| 105 if (commandOutputs.length == 0) { |
| 106 throw new Exception("CommandOutputs is empty, maybe no command was run? (" |
| 107 "displayName: '$displayName', " |
| 108 "configurationString: '$configurationString')"); |
| 109 } |
| 110 return commandOutputs[commands[commandOutputs.length - 1]]; |
| 111 } |
| 112 |
| 113 Command get lastCommandExecuted { |
| 114 if (commandOutputs.length == 0) { |
| 115 throw new Exception("CommandOutputs is empty, maybe no command was run? (" |
| 116 "displayName: '$displayName', " |
| 117 "configurationString: '$configurationString')"); |
| 118 } |
| 119 return commands[commandOutputs.length - 1]; |
| 120 } |
| 121 |
| 122 int get timeout { |
| 123 if (expectedOutcomes.contains(Expectation.SLOW)) { |
| 124 return configuration['timeout'] * SLOW_TIMEOUT_MULTIPLIER; |
| 125 } else { |
| 126 return configuration['timeout']; |
| 127 } |
| 128 } |
| 129 |
| 130 String get configurationString { |
| 131 final compiler = configuration['compiler']; |
| 132 final runtime = configuration['runtime']; |
| 133 final mode = configuration['mode']; |
| 134 final arch = configuration['arch']; |
| 135 final checked = configuration['checked'] ? '-checked' : ''; |
| 136 return "$compiler-$runtime$checked ${mode}_$arch"; |
| 137 } |
| 138 |
| 139 List<String> get batchTestArguments { |
| 140 assert(commands.last is ProcessCommand); |
| 141 return (commands.last as ProcessCommand).arguments; |
| 142 } |
| 143 |
| 144 bool get isFlaky { |
| 145 if (expectedOutcomes.contains(Expectation.SKIP) || |
| 146 expectedOutcomes.contains(Expectation.SKIP_BY_DESIGN)) { |
| 147 return false; |
| 148 } |
| 149 |
| 150 return expectedOutcomes |
| 151 .where((expectation) => !expectation.isMetaExpectation).length > 1; |
| 152 } |
| 153 |
| 154 bool get isFinished { |
| 155 return commandOutputs.length > 0 && |
| 156 (!lastCommandOutput.successful || |
| 157 commands.length == commandOutputs.length); |
| 158 } |
| 159 } |
| 160 |
| 161 |
| 162 /** |
| 163 * BrowserTestCase has an extra compilation command that is run in a separate |
| 164 * process, before the regular test is run as in the base class [TestCase]. |
| 165 * If the compilation command fails, then the rest of the test is not run. |
| 166 */ |
| 167 class BrowserTestCase extends TestCase { |
| 168 |
| 169 BrowserTestCase(displayName, commands, configuration, |
| 170 expectedOutcomes, info, isNegative, this._testingUrl) |
| 171 : super(displayName, commands, configuration, |
| 172 expectedOutcomes, isNegative: isNegative, info: info); |
| 173 |
| 174 String _testingUrl; |
| 175 |
| 176 String get testingUrl => _testingUrl; |
| 177 } |
| OLD | NEW |