OLD | NEW |
| (Empty) |
1 // Copyright (c) 2012, 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 // TODO(gram): | |
6 // Unfortunately I can't seem to test anything that involves timeouts, e.g. | |
7 // insufficient callbacks, because the timeout is controlled externally | |
8 // (test.dart?), and we would need to use a shorter timeout for the inner tests | |
9 // so the outer timeout doesn't fire. So I removed all such tests. | |
10 // I'd like to revisit this at some point. | |
11 | |
12 #library('unittestTest'); | |
13 #import('dart:isolate'); | |
14 #import('../../../pkg/unittest/unittest.dart'); | |
15 | |
16 var tests; // array of test names | |
17 var expected; // array of test expected results (from buildStatusString) | |
18 var actual; // actual test results (from buildStatusString in config.onDone) | |
19 var _testconfig; // test configuration to capture onDone | |
20 | |
21 _defer(void fn()) { | |
22 // Exploit isolate ports as a platform-independent mechanism to queue a | |
23 // message at the end of the event loop. Stolen from unittest.dart. | |
24 final port = new ReceivePort(); | |
25 port.receive((msg, reply) { | |
26 fn(); | |
27 port.close(); | |
28 }); | |
29 port.toSendPort().send(null, null); | |
30 } | |
31 | |
32 String buildStatusString(int passed, int failed, int errors, | |
33 var results, | |
34 [int count = 0, | |
35 String setup = '', String teardown = '', | |
36 String uncaughtError = null, | |
37 String message = '']) { | |
38 var totalTests = 0; | |
39 String testDetails = ''; | |
40 if (results is String) { | |
41 totalTests = passed + failed + errors; | |
42 testDetails = ':$results:$message'; | |
43 } else { | |
44 totalTests = results.length; | |
45 for (var i = 0; i < results.length; i++) { | |
46 testDetails = '$testDetails:${results[i].description}:' | |
47 '${collapseWhitespace(results[i].message)}'; | |
48 } | |
49 } | |
50 var result = '$passed:$failed:$errors:$totalTests:$count:' | |
51 '$setup:$teardown:$uncaughtError$testDetails'; | |
52 return result; | |
53 } | |
54 | |
55 class TestConfiguration extends Configuration { | |
56 | |
57 // Some test state that is captured | |
58 int count = 0; // a count of callbacks | |
59 String setup = ''; // the name of the test group setup function, if any | |
60 String teardown = ''; // the name of the test group teardown function, if any | |
61 | |
62 // The port to communicate with the parent isolate | |
63 SendPort _port; | |
64 | |
65 TestConfiguration(this._port); | |
66 | |
67 void onDone(int passed, int failed, int errors, List<TestCase> results, | |
68 String uncaughtError) { | |
69 var result = buildStatusString(passed, failed, errors, results, count, | |
70 setup, teardown, uncaughtError); | |
71 _port.send(result); | |
72 } | |
73 } | |
74 runTest() { | |
75 port.receive((testName, sendport) { | |
76 configure(_testconfig = new TestConfiguration(sendport)); | |
77 if (testName == 'single correct test') { | |
78 test(testName, () => expect(2 + 3, equals(5))); | |
79 } else if (testName == 'single failing test') { | |
80 test(testName, () => expect(2 + 2, equals(5))); | |
81 } else if (testName == 'exception test') { | |
82 test(testName, () { throw new Exception('Fail.'); }); | |
83 } else if (testName == 'group name test') { | |
84 group('a', () { | |
85 test('a', () {}); | |
86 group('b', () { | |
87 test('b', () {}); | |
88 }); | |
89 }); | |
90 } else if (testName == 'setup test') { | |
91 group('a', () { | |
92 setUp(() { _testconfig.setup = 'setup'; }); | |
93 test(testName, () {}); | |
94 }); | |
95 } else if (testName == 'teardown test') { | |
96 group('a', () { | |
97 tearDown(() { _testconfig.teardown = 'teardown'; }); | |
98 test(testName, () {}); | |
99 }); | |
100 } else if (testName == 'setup and teardown test') { | |
101 group('a', () { | |
102 setUp(() { _testconfig.setup = 'setup'; }); | |
103 tearDown(() { _testconfig.teardown = 'teardown'; }); | |
104 test(testName, () {}); | |
105 }); | |
106 } else if (testName == 'correct callback test') { | |
107 test(testName, | |
108 () =>_defer(expectAsync0((){ ++_testconfig.count;}))); | |
109 } else if (testName == 'excess callback test') { | |
110 test(testName, () { | |
111 var _callback = expectAsync0((){ ++_testconfig.count;}); | |
112 _defer(_callback); | |
113 _defer(_callback); | |
114 }); | |
115 } else if (testName == 'completion test') { | |
116 test(testName, () { | |
117 var _callback; | |
118 _callback = expectAsyncUntil0(() { | |
119 if (++_testconfig.count < 10) { | |
120 _defer(_callback); | |
121 } | |
122 }, | |
123 () => (_testconfig.count == 10)); | |
124 _defer(_callback); | |
125 }); | |
126 } else if (testName == 'async exception test') { | |
127 test(testName, () { | |
128 expectAsync0(() {}); | |
129 _defer(() => guardAsync(() { throw "error!"; })); | |
130 }); | |
131 } else if (testName == 'late exception test') { | |
132 test('testOne', () { | |
133 var f = expectAsync0(() {}); | |
134 _defer(protectAsync0(() { | |
135 _defer(protectAsync0(() => expect(false))); | |
136 expect(false); | |
137 })); | |
138 }); | |
139 test('testTwo', () { | |
140 _defer(expectAsync0(() {})); | |
141 }); | |
142 } | |
143 }); | |
144 } | |
145 | |
146 void nextTest(int testNum) { | |
147 SendPort sport = spawnFunction(runTest); | |
148 sport.call(tests[testNum]).then((msg) { | |
149 actual.add(msg); | |
150 if (actual.length == expected.length) { | |
151 for (var i = 0; i < tests.length; i++) { | |
152 test(tests[i], () => expect(actual[i].trim(), equals(expected[i]))); | |
153 } | |
154 } else { | |
155 nextTest(testNum+1); | |
156 } | |
157 }); | |
158 } | |
159 | |
160 main() { | |
161 tests = [ | |
162 'single correct test', | |
163 'single failing test', | |
164 'exception test', | |
165 'group name test', | |
166 'setup test', | |
167 'teardown test', | |
168 'setup and teardown test', | |
169 'correct callback test', | |
170 'excess callback test', | |
171 'completion test', | |
172 'async exception test', | |
173 'late exception test' | |
174 ]; | |
175 | |
176 expected = [ | |
177 buildStatusString(1, 0, 0, tests[0]), | |
178 buildStatusString(0, 1, 0, tests[1], | |
179 message: 'Expected: <5> but: was <4>.'), | |
180 buildStatusString(0, 1, 0, tests[2], message: 'Caught Exception: Fail.'), | |
181 buildStatusString(2, 0, 0, 'a a::a b b'), | |
182 buildStatusString(1, 0, 0, 'a ${tests[4]}', 0, 'setup'), | |
183 buildStatusString(1, 0, 0, 'a ${tests[5]}', 0, '', 'teardown'), | |
184 buildStatusString(1, 0, 0, 'a ${tests[6]}', 0, | |
185 'setup', 'teardown'), | |
186 buildStatusString(1, 0, 0, tests[7], 1), | |
187 buildStatusString(0, 0, 1, tests[8], 1, | |
188 message: 'Callback called more times than expected (2 > 1).'), | |
189 buildStatusString(1, 0, 0, tests[9], 10), | |
190 buildStatusString(0, 1, 0, tests[10], message: 'Caught error!'), | |
191 buildStatusString(1, 0, 1, 'testOne', message: 'Callback called after alread
y being marked as done (1).:testTwo:') | |
192 ]; | |
193 | |
194 actual = []; | |
195 | |
196 nextTest(0); | |
197 } | |
198 | |
OLD | NEW |