| OLD | NEW |
| (Empty) | |
| 1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file |
| 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. |
| 4 |
| 5 #library("test_runner"); |
| 6 |
| 7 |
| 8 #import("status_file_parser.dart"); |
| 9 |
| 10 /** |
| 11 * Classes and methods for executing tests. |
| 12 * |
| 13 * This module includes: |
| 14 * - Managing parallel execution of tests, including timeout checks. |
| 15 * - Evaluating the output of each test as pass/fail/crash/timeout. |
| 16 */ |
| 17 |
| 18 // Possible outcomes of running a test. |
| 19 final CRASH = "Crash"; |
| 20 final TIMEOUT = "Timeout"; |
| 21 final FAIL = "Fail"; |
| 22 final PASS = "Pass"; |
| 23 // An indication to skip the test. The caller is responsible for skipping it. |
| 24 final SKIP = "Skip"; |
| 25 |
| 26 String getDartShellFileName() { |
| 27 var names = ["out/Debug_ia32/dart_bin", |
| 28 "out/Release_ia32/dart_bin", |
| 29 "xcodebuild/Debug_ia32/dart_bin", |
| 30 "xcodebuild/Release_ia32/dart_bin", |
| 31 "Debug_ia32/dart_bin.exe", |
| 32 "Release_ia32/dart_bin.exe"]; |
| 33 for (var name in names) { |
| 34 if (new File(name).existsSync()) { |
| 35 return name; |
| 36 } |
| 37 } |
| 38 Expect.fail("Cound not find the Dart shell executable."); |
| 39 } |
| 40 |
| 41 |
| 42 class TestCase { |
| 43 String executablePath; |
| 44 List<String> arguments; |
| 45 String commandLine; |
| 46 TestOutput output; |
| 47 Set<String> expectedOutcomes; |
| 48 Function completedHandler; |
| 49 |
| 50 TestCase(this.executablePath, this.arguments, |
| 51 this.completedHandler, this.expectedOutcomes) { |
| 52 commandLine = executablePath; |
| 53 for (var arg in arguments) { |
| 54 commandLine += " " + arg; |
| 55 } |
| 56 } |
| 57 |
| 58 bool get isNegative() => false; |
| 59 |
| 60 void completed() { completedHandler(this); } |
| 61 } |
| 62 |
| 63 |
| 64 class TestOutput { |
| 65 // The TestCase this is the output from. |
| 66 TestCase testCase; |
| 67 int exitCode; |
| 68 bool timedOut; |
| 69 bool failed = false; |
| 70 List<String> stdout; |
| 71 List<String> stderr; |
| 72 Duration time; |
| 73 |
| 74 TestOutput(this.testCase, this.exitCode, this.timedOut, this.stdout, |
| 75 this.stderr, this.time) { |
| 76 testCase.output = this; |
| 77 } |
| 78 |
| 79 String get result() => |
| 80 hasCrashed ? CRASH : (hasTimedOut ? TIMEOUT : (hasFailed ? FAIL : PASS)); |
| 81 |
| 82 bool get unexpectedOutput() => !testCase.expectedOutcomes.contains(result); |
| 83 |
| 84 bool get hasCrashed() => !timedOut && exitCode != 255 && exitCode != 0; |
| 85 |
| 86 bool get hasTimedOut() => timedOut; |
| 87 |
| 88 bool get didFail() => exitCode != 0 && !hasCrashed; |
| 89 |
| 90 // Reverse result of a negative test. |
| 91 bool get hasFailed() => (testCase.isNegative ? !didFail : didFail); |
| 92 } |
| 93 |
| 94 |
| 95 class RunningProcess { |
| 96 Process process; |
| 97 TestCase testCase; |
| 98 int timeout; |
| 99 bool timedOut = false; |
| 100 Date startTime; |
| 101 Timer timeoutTimer; |
| 102 List<String> stdout; |
| 103 List<String> stderr; |
| 104 List<Function> handlers; |
| 105 |
| 106 static final int NO_TIMEOUT = 0; |
| 107 |
| 108 RunningProcess(this.testCase, [this.timeout = NO_TIMEOUT]); |
| 109 |
| 110 void exitHandler(int exitCode) { |
| 111 new TestOutput(testCase, exitCode, timedOut, stdout, |
| 112 stderr, new Date.now().difference(startTime)); |
| 113 process.close(); |
| 114 timeoutTimer.cancel(); |
| 115 testCase.completed(); |
| 116 } |
| 117 |
| 118 void makeReadHandler(StringInputStream source, List<String> destination) { |
| 119 return () { |
| 120 if (source.closed) return; // TODO(whesse): Remove when bug is fixed. |
| 121 var line = source.readLine(); |
| 122 while (null != line) { |
| 123 destination.add(line); |
| 124 line = source.readLine(); |
| 125 } |
| 126 }; |
| 127 } |
| 128 |
| 129 void start() { |
| 130 Expect.isFalse(testCase.expectedOutcomes.contains(SKIP)); |
| 131 process = new Process(testCase.executablePath, testCase.arguments); |
| 132 process.exitHandler = exitHandler; |
| 133 startTime = new Date.now(); |
| 134 process.start(); |
| 135 |
| 136 InputStream stdoutStream = process.stdout; |
| 137 InputStream stderrStream = process.stderr; |
| 138 stdout = new List<String>(); |
| 139 stderr = new List<String>(); |
| 140 StringInputStream stdoutStringStream = new StringInputStream(stdoutStream); |
| 141 StringInputStream stderrStringStream = new StringInputStream(stderrStream); |
| 142 stdoutStringStream.dataHandler = |
| 143 makeReadHandler(stdoutStringStream, stdout); |
| 144 stderrStringStream.dataHandler = |
| 145 makeReadHandler(stderrStringStream, stderr); |
| 146 if (timeout != NO_TIMEOUT) { |
| 147 timeoutTimer = new Timer(timeoutHandler, 1000 * timeout, false); |
| 148 } |
| 149 } |
| 150 |
| 151 void timeoutHandler(Timer unusedTimer) { |
| 152 timedOut = true; |
| 153 process.kill(); |
| 154 } |
| 155 } |
| 156 |
| OLD | NEW |