OLD | NEW |
| (Empty) |
1 // Copyright (c) 2015, the Dartino 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.md file. | |
4 | |
5 import 'dart:async' show | |
6 Completer, | |
7 Future, | |
8 Stream, | |
9 StreamController, | |
10 Zone; | |
11 | |
12 import 'dart:convert' show | |
13 UTF8; | |
14 | |
15 import 'package:expect/expect.dart' show | |
16 Expect; | |
17 | |
18 import 'package:fletchc/src/diagnostic.dart'; | |
19 | |
20 import 'package:fletchc/src/messages.dart'; | |
21 | |
22 import 'package:fletchc/src/message_examples.dart'; | |
23 | |
24 import 'package:fletchc/src/hub/sentence_parser.dart' show | |
25 NamedTarget, | |
26 Sentence, | |
27 parseSentence; | |
28 | |
29 import 'package:fletchc/src/verbs/actions.dart' show | |
30 Action; | |
31 | |
32 import 'package:fletchc/src/hub/hub_main.dart' show | |
33 ClientLogger, | |
34 ClientConnection, | |
35 IsolatePool, | |
36 handleVerb; | |
37 | |
38 import 'package:fletchc/src/worker/worker_main.dart' show | |
39 workerMain; | |
40 | |
41 import 'package:fletchc/src/hub/session_manager.dart' show | |
42 endAllSessions; | |
43 | |
44 import 'package:fletchc/src/hub/client_commands.dart' show | |
45 ClientCommand, | |
46 ClientCommandCode; | |
47 | |
48 import 'package:fletchc/src/verbs/infrastructure.dart' show | |
49 AnalyzedSentence, | |
50 Options, | |
51 analyzeSentence; | |
52 | |
53 import 'package:fletchc/src/worker/developer.dart' show | |
54 parseSettings; | |
55 | |
56 final IsolatePool pool = new IsolatePool(workerMain); | |
57 | |
58 Future<Null> main() async { | |
59 for (DiagnosticKind kind in DiagnosticKind.values) { | |
60 Expect.isNotNull(getMessage(kind), "$kind"); | |
61 | |
62 List<Example> examples = getExamples(kind); | |
63 Expect.isNotNull(examples, "$kind"); | |
64 Expect.isFalse(examples.isEmpty, "$kind"); | |
65 int exampleCount = 1; | |
66 for (Example example in examples) { | |
67 print("\n\nTesting $kind ${exampleCount++}"); | |
68 Expect.isNotNull(example); | |
69 await checkExample(kind, example); | |
70 endAllSessions(); | |
71 pool.shutdown(); | |
72 } | |
73 print("Done testing $kind"); | |
74 } | |
75 } | |
76 | |
77 Future<Null> checkExample(DiagnosticKind kind, Example example) async { | |
78 if (example is CommandLineExample) { | |
79 await checkCommandLineExample(kind, example); | |
80 } else if (example is SettingsExample) { | |
81 checkSettingsExample(kind, example); | |
82 } else if (example is Untestable) { | |
83 // Ignored. | |
84 } else { | |
85 throw "Unknown kind of example: $example"; | |
86 } | |
87 } | |
88 | |
89 void checkSettingsExample(DiagnosticKind kind, SettingsExample example) { | |
90 Uri mockUri = new Uri(scheme: "org.dartlang.tests.mock"); | |
91 try { | |
92 parseSettings(example.data, mockUri); | |
93 throw "Settings example: '${example.data}' " | |
94 "didn't produce the expected '$kind' error"; | |
95 } on InputError catch (e) { | |
96 Expect.isNotNull(e); | |
97 Expect.equals(kind, e.kind, '$e'); | |
98 // Ensure that the diagnostic can be turned into a formatted error message. | |
99 String message = e.asDiagnostic().formatMessage(); | |
100 Expect.isNotNull(message); | |
101 } | |
102 } | |
103 | |
104 Future<Null> checkCommandLineExample( | |
105 DiagnosticKind kind, | |
106 CommandLineExample example) async { | |
107 List<List<String>> lines = <List<String>>[]; | |
108 if (example.line1 != null) { | |
109 lines.add(example.line1); | |
110 } | |
111 if (example.line2 != null) { | |
112 lines.add(example.line2); | |
113 } | |
114 if (example.line3 != null) { | |
115 lines.add(example.line3); | |
116 } | |
117 List<String> lastLine = lines.removeLast(); | |
118 for (List<String> setup in lines) { | |
119 MockClientConnection mock = await mockCommandLine(setup); | |
120 await mock.done; | |
121 Expect.isNull(mock.recordedError); | |
122 Expect.equals(0, mock.recordedExitCode); | |
123 } | |
124 MockClientConnection mock = await mockCommandLine(lastLine); | |
125 if (kind == DiagnosticKind.socketVmConnectError) { | |
126 await mock.done; | |
127 Options options = Options.parse(lastLine); | |
128 Sentence sentence = parseSentence(options.nonOptionArguments); | |
129 NamedTarget target = sentence.targets.single; | |
130 String message = mock.stderrMessages.single; | |
131 String expectedMessage = new Diagnostic( | |
132 kind, getMessage(kind), | |
133 {DiagnosticParameter.address: target.name, | |
134 DiagnosticParameter.message: '.*'}) | |
135 .formatMessage(); | |
136 Expect.stringEquals( | |
137 message, | |
138 new RegExp(expectedMessage).stringMatch(message)); | |
139 } else if (kind == DiagnosticKind.attachToVmBeforeRun) { | |
140 await mock.done; | |
141 Expect.stringEquals(getMessage(kind), mock.stderrMessages.single); | |
142 } else { | |
143 Expect.isNotNull(mock.recordedError); | |
144 Expect.equals(kind, mock.recordedError.kind, '${mock.recordedError}'); | |
145 // Ensure that the diagnostic can be turned into a formatted error message. | |
146 String message = mock.recordedError.asDiagnostic().formatMessage(); | |
147 Expect.isNotNull(message); | |
148 } | |
149 Expect.equals(1, mock.recordedExitCode); | |
150 } | |
151 | |
152 Future<MockClientConnection> mockCommandLine(List<String> arguments) async { | |
153 print("Command line: ${arguments.join(' ')}"); | |
154 MockClientConnection client = new MockClientConnection(); | |
155 await handleVerb(arguments, client, pool); | |
156 return client; | |
157 } | |
158 | |
159 class MockClientConnection implements ClientConnection { | |
160 InputError recordedError; | |
161 | |
162 int recordedExitCode; | |
163 | |
164 final ClientLogger log = new MockClientLogger(); | |
165 | |
166 final Completer mockCompleter = new Completer(); | |
167 | |
168 final List<String> stderrMessages = <String>[]; | |
169 | |
170 final StreamController<ClientCommand> controller = | |
171 new StreamController<ClientCommand>(); | |
172 | |
173 AnalyzedSentence sentence; | |
174 | |
175 MockClientConnection(); | |
176 | |
177 get completer => mockCompleter; | |
178 | |
179 get done => completer.future; | |
180 | |
181 get commands => controller.stream; | |
182 | |
183 void sendCommandToWorker(ClientCommand command) { | |
184 controller.add(command); | |
185 } | |
186 | |
187 sendCommandToClient(ClientCommand command) { | |
188 switch (command.code) { | |
189 case ClientCommandCode.ExitCode: | |
190 exit(command.data); | |
191 break; | |
192 | |
193 case ClientCommandCode.Stderr: | |
194 printLineOnStderr(mockStripNewline(UTF8.decode(command.data))); | |
195 break; | |
196 | |
197 case ClientCommandCode.Stdout: | |
198 printLineOnStdout(mockStripNewline(UTF8.decode(command.data))); | |
199 break; | |
200 | |
201 default: | |
202 throw "Unexpected command: ${command.code}"; | |
203 } | |
204 } | |
205 | |
206 mockStripNewline(String line) { | |
207 if (line.endsWith("\n")) { | |
208 return line.substring(0, line.length - 1); | |
209 } else { | |
210 return line; | |
211 } | |
212 } | |
213 | |
214 endSession() { | |
215 completer.complete(null); | |
216 } | |
217 | |
218 mockPrintLine(String line) { | |
219 Zone zone = Zone.current.parent; | |
220 if (zone == null) { | |
221 zone = Zone.current; | |
222 } | |
223 zone.print(line); | |
224 } | |
225 | |
226 printLineOnStderr(line) { | |
227 stderrMessages.add(line); | |
228 mockPrintLine('stderr: $line'); | |
229 } | |
230 | |
231 printLineOnStdout(line) { | |
232 mockPrintLine('stdout: $line'); | |
233 } | |
234 | |
235 exit(int exitCode) { | |
236 recordedExitCode = exitCode; | |
237 if (!completer.isCompleted) { | |
238 endSession(); | |
239 } | |
240 } | |
241 | |
242 int reportErrorToClient(InputError error, StackTrace stackTrace) { | |
243 recordedError = error; | |
244 completer.complete(null); | |
245 return 1; | |
246 } | |
247 | |
248 AnalyzedSentence parseArguments(List<String> arguments) { | |
249 Options options = Options.parse(arguments); | |
250 Sentence sentence = parseSentence(options.nonOptionArguments); | |
251 this.sentence = analyzeSentence(sentence, null); | |
252 return this.sentence; | |
253 } | |
254 | |
255 handleClientCommand(_) => throw "not supported"; | |
256 handleClientCommandError(e, s) => throw "not supported"; | |
257 handleClientCommandsDone() => throw "not supported"; | |
258 start() => throw "not supported"; | |
259 get arguments => throw "not supported"; | |
260 get argumentsCompleter => throw "not supported"; | |
261 set argumentsCompleter(_) => throw "not supported"; | |
262 get commandSender => throw "not supported"; | |
263 set commandSender(_) => throw "not supported"; | |
264 set completer(_) => throw "not supported"; | |
265 get fletchVm => throw "not supported"; | |
266 set fletchVm(_) => throw "not supported"; | |
267 get requiresWorker => throw "not supported"; | |
268 get socket => throw "not supported"; | |
269 get subscription => throw "not supported"; | |
270 set subscription(_) => throw "not supported"; | |
271 } | |
272 | |
273 class MockClientLogger implements ClientLogger { | |
274 static int clientsAllocated = 0; | |
275 | |
276 final int id = clientsAllocated++; | |
277 | |
278 void note(object) { | |
279 print("$id: $object"); | |
280 gotArguments(null); // Removes an "unused" warning from dart2js. | |
281 } | |
282 | |
283 void gotArguments(_) { | |
284 } | |
285 | |
286 void done() { | |
287 } | |
288 | |
289 void error(error, StackTrace stackTrace) { | |
290 throw error; | |
291 } | |
292 | |
293 get arguments => throw "not supported"; | |
294 set arguments(_) => throw "not supported"; | |
295 get notes => throw "not supported"; | |
296 } | |
OLD | NEW |