OLD | NEW |
1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2015, 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 file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 library analyzer_cli.test.driver; | 5 library analyzer_cli.test.driver; |
6 | 6 |
7 import 'dart:async'; | 7 import 'dart:async'; |
8 import 'dart:io'; | 8 import 'dart:io'; |
9 | 9 |
10 import 'package:analyzer/error/error.dart'; | 10 import 'package:analyzer/error/error.dart'; |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
56 tearDown(() => _tearDown()); | 56 tearDown(() => _tearDown()); |
57 | 57 |
58 group('Driver', () { | 58 group('Driver', () { |
59 group('options', () { | 59 group('options', () { |
60 test('todos', () async { | 60 test('todos', () async { |
61 await drive('data/file_with_todo.dart'); | 61 await drive('data/file_with_todo.dart'); |
62 expect(outSink.toString().contains('[info]'), isFalse); | 62 expect(outSink.toString().contains('[info]'), isFalse); |
63 }); | 63 }); |
64 }); | 64 }); |
65 | 65 |
66 group('exit codes', () { | 66 _test_exitCodes(); |
67 test('fatal hints', () async { | 67 _test_linter(); |
68 await drive('data/file_with_hint.dart', args: ['--fatal-hints']); | 68 _test_optionsProcessing(); |
69 expect(exitCode, 1); | 69 _test_buildMode(); |
70 }); | |
71 | |
72 test('not fatal hints', () async { | |
73 await drive('data/file_with_hint.dart'); | |
74 expect(exitCode, 0); | |
75 }); | |
76 | |
77 test('fatal errors', () async { | |
78 await drive('data/file_with_error.dart'); | |
79 expect(exitCode, 3); | |
80 }); | |
81 | |
82 test('not fatal warnings', () async { | |
83 await drive('data/file_with_warning.dart'); | |
84 expect(exitCode, 0); | |
85 }); | |
86 | |
87 test('fatal warnings', () async { | |
88 await drive('data/file_with_warning.dart', args: ['--fatal-warnings']); | |
89 expect(exitCode, 2); | |
90 }); | |
91 | |
92 test('not parse enableAssertInitializer', () async { | |
93 await drive('data/file_with_assert_initializers.dart', | |
94 args: ['--enable-assert-initializers']); | |
95 expect(exitCode, 0); | |
96 }); | |
97 | |
98 test('missing options file', () async { | |
99 await drive('data/test_file.dart', options: 'data/NO_OPTIONS_HERE'); | |
100 expect(exitCode, 3); | |
101 }); | |
102 | |
103 test('missing dart file', () async { | |
104 await drive('data/NO_DART_FILE_HERE.dart'); | |
105 expect(exitCode, 3); | |
106 }); | |
107 | |
108 test('part file', () async { | |
109 await drive('data/library_and_parts/part2.dart'); | |
110 expect(exitCode, 3); | |
111 }); | |
112 | |
113 test('non-dangling part file', () async { | |
114 Driver driver = new Driver(isTesting: true); | |
115 await driver.start([ | |
116 path.join(testDirectory, 'data/library_and_parts/lib.dart'), | |
117 path.join(testDirectory, 'data/library_and_parts/part1.dart') | |
118 ]); | |
119 expect(exitCode, 0); | |
120 }); | |
121 | |
122 test('extra part file', () async { | |
123 Driver driver = new Driver(isTesting: true); | |
124 await driver.start([ | |
125 path.join(testDirectory, 'data/library_and_parts/lib.dart'), | |
126 path.join(testDirectory, 'data/library_and_parts/part1.dart'), | |
127 path.join(testDirectory, 'data/library_and_parts/part2.dart') | |
128 ]); | |
129 expect(exitCode, 3); | |
130 }); | |
131 | |
132 test('bazel workspace relative path', () async { | |
133 // Copy to temp dir so that existing analysis options | |
134 // in the test directory hierarchy do not interfere | |
135 await withTempDirAsync((String tempDirPath) async { | |
136 String dartSdkPath = path.absolute(getSdkPath()); | |
137 await recursiveCopy( | |
138 new Directory(path.join(testDirectory, 'data', 'bazel')), | |
139 tempDirPath); | |
140 Directory origWorkingDir = Directory.current; | |
141 try { | |
142 Directory.current = path.join(tempDirPath, 'proj'); | |
143 Driver driver = new Driver(isTesting: true); | |
144 try { | |
145 await driver.start([ | |
146 path.join('lib', 'file.dart'), | |
147 '--dart-sdk', | |
148 dartSdkPath, | |
149 ]); | |
150 } catch (e) { | |
151 print('=== debug info ==='); | |
152 print('dartSdkPath: $dartSdkPath'); | |
153 print('stderr:\n${errorSink.toString()}'); | |
154 rethrow; | |
155 } | |
156 expect(errorSink.toString(), isEmpty); | |
157 expect(outSink.toString(), contains('No issues found')); | |
158 expect(exitCode, 0); | |
159 } finally { | |
160 Directory.current = origWorkingDir; | |
161 } | |
162 }); | |
163 }); | |
164 }); | |
165 | |
166 group('linter', () { | |
167 void createTests(String designator, String optionsFileName) { | |
168 group('lints in options - $designator', () { | |
169 // Shared lint command. | |
170 Future<Null> runLinter() async { | |
171 return await drive('data/linter_project/test_file.dart', | |
172 options: 'data/linter_project/$optionsFileName', | |
173 args: ['--lints']); | |
174 } | |
175 | |
176 test('gets analysis options', () async { | |
177 await runLinter(); | |
178 | |
179 /// Lints should be enabled. | |
180 expect(driver.context.analysisOptions.lint, isTrue); | |
181 | |
182 /// The analysis options file only specifies 'camel_case_types'. | |
183 var lintNames = getLints(driver.context).map((r) => r.name); | |
184 expect(lintNames, orderedEquals(['camel_case_types'])); | |
185 }); | |
186 | |
187 test('generates lints', () async { | |
188 await runLinter(); | |
189 expect(_bulletToDash(outSink), | |
190 contains('lint - Name types using UpperCamelCase')); | |
191 }); | |
192 }); | |
193 | |
194 group('default lints - $designator', () { | |
195 // Shared lint command. | |
196 Future<Null> runLinter() async { | |
197 return await drive('data/linter_project/test_file.dart', | |
198 options: 'data/linter_project/$optionsFileName', | |
199 args: ['--lints']); | |
200 } | |
201 | |
202 test('gets default lints', () async { | |
203 await runLinter(); | |
204 | |
205 /// Lints should be enabled. | |
206 expect(driver.context.analysisOptions.lint, isTrue); | |
207 | |
208 /// Default list should include camel_case_types. | |
209 var lintNames = getLints(driver.context).map((r) => r.name); | |
210 expect(lintNames, contains('camel_case_types')); | |
211 }); | |
212 | |
213 test('generates lints', () async { | |
214 await runLinter(); | |
215 expect(_bulletToDash(outSink), | |
216 contains('lint - Name types using UpperCamelCase')); | |
217 }); | |
218 }); | |
219 | |
220 group('no `--lints` flag (none in options) - $designator', () { | |
221 // Shared lint command. | |
222 Future<Null> runLinter() async { | |
223 return await drive('data/no_lints_project/test_file.dart', | |
224 options: 'data/no_lints_project/$optionsFileName'); | |
225 } | |
226 | |
227 test('lints disabled', () async { | |
228 await runLinter(); | |
229 expect(driver.context.analysisOptions.lint, isFalse); | |
230 }); | |
231 | |
232 test('no registered lints', () async { | |
233 await runLinter(); | |
234 expect(getLints(driver.context), isEmpty); | |
235 }); | |
236 | |
237 test('no generated warnings', () async { | |
238 await runLinter(); | |
239 expect(outSink.toString(), contains('No issues found')); | |
240 }); | |
241 }); | |
242 } | |
243 | |
244 createTests('old', AnalysisEngine.ANALYSIS_OPTIONS_FILE); | |
245 createTests('new', AnalysisEngine.ANALYSIS_OPTIONS_YAML_FILE); | |
246 }); | |
247 | |
248 test('containsLintRuleEntry', () { | |
249 Map<String, YamlNode> options; | |
250 options = parseOptions(''' | |
251 linter: | |
252 rules: | |
253 - foo | |
254 '''); | |
255 expect(containsLintRuleEntry(options), true); | |
256 options = parseOptions(''' | |
257 '''); | |
258 expect(containsLintRuleEntry(options), false); | |
259 options = parseOptions(''' | |
260 linter: | |
261 rules: | |
262 # - foo | |
263 '''); | |
264 expect(containsLintRuleEntry(options), true); | |
265 options = parseOptions(''' | |
266 linter: | |
267 # rules: | |
268 # - foo | |
269 '''); | |
270 expect(containsLintRuleEntry(options), false); | |
271 }); | |
272 | |
273 group('options processing', () { | |
274 void createTests(String designator, String optionsFileName) { | |
275 group('basic config - $designator', () { | |
276 // Shared driver command. | |
277 Future<Null> doDrive() async { | |
278 await drive('data/options_tests_project/test_file.dart', | |
279 options: 'data/options_tests_project/$optionsFileName'); | |
280 } | |
281 | |
282 test('filters', () async { | |
283 await doDrive(); | |
284 expect(processors, hasLength(3)); | |
285 | |
286 // unused_local_variable: ignore | |
287 var unused_local_variable = new AnalysisError( | |
288 new TestSource(), 0, 1, HintCode.UNUSED_LOCAL_VARIABLE, [ | |
289 ['x'] | |
290 ]); | |
291 expect(processorFor(unused_local_variable).severity, isNull); | |
292 | |
293 // missing_return: error | |
294 var missing_return = new AnalysisError( | |
295 new TestSource(), 0, 1, HintCode.MISSING_RETURN, [ | |
296 ['x'] | |
297 ]); | |
298 expect(processorFor(missing_return).severity, ErrorSeverity.ERROR); | |
299 expect( | |
300 _bulletToDash(outSink), | |
301 contains( | |
302 "error - This function declares a return type of 'int'")); | |
303 expect( | |
304 outSink.toString(), contains("1 error and 1 warning found.")); | |
305 }); | |
306 | |
307 test('language', () async { | |
308 await doDrive(); | |
309 expect(driver.context.analysisOptions.enableSuperMixins, isTrue); | |
310 }); | |
311 | |
312 test('strongMode', () async { | |
313 await doDrive(); | |
314 expect(driver.context.analysisOptions.strongMode, isTrue); | |
315 //https://github.com/dart-lang/sdk/issues/26129 | |
316 AnalysisContext sdkContext = | |
317 driver.context.sourceFactory.dartSdk.context; | |
318 expect(sdkContext.analysisOptions.strongMode, isTrue); | |
319 }); | |
320 }); | |
321 | |
322 group('with flags - $designator', () { | |
323 // Shared driver command. | |
324 Future<Null> doDrive() async { | |
325 await drive('data/options_tests_project/test_file.dart', | |
326 args: ['--fatal-warnings'], | |
327 options: 'data/options_tests_project/$optionsFileName'); | |
328 } | |
329 | |
330 test('override fatal warning', () async { | |
331 await doDrive(); | |
332 // missing_return: error | |
333 var undefined_function = new AnalysisError(new TestSource(), 0, 1, | |
334 StaticTypeWarningCode.UNDEFINED_FUNCTION, [ | |
335 ['x'] | |
336 ]); | |
337 expect(processorFor(undefined_function).severity, | |
338 ErrorSeverity.WARNING); | |
339 // Should not be made fatal by `--fatal-warnings`. | |
340 expect(_bulletToDash(outSink), | |
341 contains("warning - The function 'baz' isn't defined")); | |
342 expect( | |
343 outSink.toString(), contains("1 error and 1 warning found.")); | |
344 }); | |
345 }); | |
346 } | |
347 | |
348 createTests('old', AnalysisEngine.ANALYSIS_OPTIONS_FILE); | |
349 createTests('new', AnalysisEngine.ANALYSIS_OPTIONS_YAML_FILE); | |
350 | |
351 test('include directive', () async { | |
352 String testDir = path.join( | |
353 testDirectory, 'data', 'options_include_directive_tests_project'); | |
354 await drive( | |
355 path.join(testDir, 'lib', 'test_file.dart'), | |
356 args: [ | |
357 '--fatal-warnings', | |
358 '--packages', | |
359 path.join(testDir, '_packages'), | |
360 ], | |
361 options: path.join(testDir, 'analysis_options.yaml'), | |
362 ); | |
363 expect(exitCode, 3); | |
364 expect(outSink.toString(), | |
365 contains('but doesn\'t end with a return statement')); | |
366 expect(outSink.toString(), contains('isn\'t defined')); | |
367 expect(outSink.toString(), contains('Avoid empty else statements')); | |
368 }); | |
369 | |
370 test('test strong SDK', () async { | |
371 String testDir = path.join(testDirectory, 'data', 'strong_sdk'); | |
372 await drive(path.join(testDir, 'main.dart'), args: ['--strong']); | |
373 expect(driver.context.analysisOptions.strongMode, isTrue); | |
374 expect(outSink.toString(), contains('No issues found')); | |
375 expect(exitCode, 0); | |
376 }); | |
377 }); | |
378 | |
379 void createTests(String designator, String optionsFileName) { | |
380 group('build-mode - $designator', () { | |
381 // Shared driver command. | |
382 Future<Null> doDrive(String filePath, | |
383 {List<String> additionalArgs: const []}) async { | |
384 await drive('file:///test_file.dart|$filePath', | |
385 args: [ | |
386 '--dart-sdk', | |
387 findSdkDirForSummaries(), | |
388 '--build-mode', | |
389 '--format=machine' | |
390 ]..addAll(additionalArgs), | |
391 options: 'data/options_tests_project/$optionsFileName'); | |
392 } | |
393 | |
394 test('no stats', () async { | |
395 await doDrive(path.join('data', 'test_file.dart')); | |
396 // Should not print stat summary. | |
397 expect(outSink.toString(), isEmpty); | |
398 expect(errorSink.toString(), isEmpty); | |
399 expect(exitCode, 0); | |
400 }); | |
401 | |
402 test( | |
403 'Fails if file not found, even when --build-suppress-exit-code is gi
ven', | |
404 () async { | |
405 await doDrive(path.join('data', 'non_existent_file.dart'), | |
406 additionalArgs: ['--build-suppress-exit-code']); | |
407 expect(exitCode, isNot(0)); | |
408 }); | |
409 | |
410 test('Fails if there are errors', () async { | |
411 await doDrive(path.join('data', 'file_with_error.dart')); | |
412 expect(exitCode, isNot(0)); | |
413 }); | |
414 | |
415 test( | |
416 'Succeeds if there are errors, when --build-suppress-exit-code is gi
ven', | |
417 () async { | |
418 await doDrive(path.join('data', 'file_with_error.dart'), | |
419 additionalArgs: ['--build-suppress-exit-code']); | |
420 expect(exitCode, 0); | |
421 }); | |
422 | |
423 test('Linked summary', () async { | |
424 await withTempDirAsync((tempDir) async { | |
425 var outputPath = path.join(tempDir, 'test_file.dart.sum'); | |
426 await doDrive(path.join('data', 'test_file.dart'), additionalArgs: [ | |
427 '--build-summary-only', | |
428 '--build-summary-output=$outputPath' | |
429 ]); | |
430 var output = new File(outputPath); | |
431 expect(output.existsSync(), isTrue); | |
432 PackageBundle bundle = | |
433 new PackageBundle.fromBuffer(await output.readAsBytes()); | |
434 var testFileUri = 'file:///test_file.dart'; | |
435 expect(bundle.unlinkedUnitUris, equals([testFileUri])); | |
436 expect(bundle.linkedLibraryUris, equals([testFileUri])); | |
437 expect(exitCode, 0); | |
438 }); | |
439 }); | |
440 | |
441 test('Unlinked summary only', () async { | |
442 await withTempDirAsync((tempDir) async { | |
443 var outputPath = path.join(tempDir, 'test_file.dart.sum'); | |
444 await doDrive(path.join('data', 'test_file.dart'), additionalArgs: [ | |
445 '--build-summary-only', | |
446 '--build-summary-only-unlinked', | |
447 '--build-summary-output=$outputPath' | |
448 ]); | |
449 var output = new File(outputPath); | |
450 expect(output.existsSync(), isTrue); | |
451 PackageBundle bundle = | |
452 new PackageBundle.fromBuffer(await output.readAsBytes()); | |
453 var testFileUri = 'file:///test_file.dart'; | |
454 expect(bundle.unlinkedUnits.length, 1); | |
455 expect(bundle.unlinkedUnitUris, equals([testFileUri])); | |
456 expect(bundle.linkedLibraryUris, isEmpty); | |
457 expect(exitCode, 0); | |
458 }); | |
459 }); | |
460 }); | |
461 } | |
462 | |
463 createTests('old', AnalysisEngine.ANALYSIS_OPTIONS_FILE); | |
464 createTests('new', AnalysisEngine.ANALYSIS_OPTIONS_YAML_FILE); | |
465 | 70 |
466 //TODO(pq): fix to be bot-friendly (sdk#25258). | 71 //TODO(pq): fix to be bot-friendly (sdk#25258). |
467 // group('in temp directory', () { | 72 // group('in temp directory', () { |
468 // Directory savedCurrentDirectory; | 73 // Directory savedCurrentDirectory; |
469 // Directory tempDir; | 74 // Directory tempDir; |
470 // setUp(() { | 75 // setUp(() { |
471 // // Call base setUp. | 76 // // Call base setUp. |
472 // _setUp(); | 77 // _setUp(); |
473 // savedCurrentDirectory = Directory.current; | 78 // savedCurrentDirectory = Directory.current; |
474 // tempDir = Directory.systemTemp.createTempSync('analyzer_'); | 79 // tempDir = Directory.systemTemp.createTempSync('analyzer_'); |
(...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
606 | 211 |
607 Map<String, YamlNode> parseOptions(String src) => | 212 Map<String, YamlNode> parseOptions(String src) => |
608 new AnalysisOptionsProvider().getOptionsFromString(src); | 213 new AnalysisOptionsProvider().getOptionsFromString(src); |
609 | 214 |
610 ErrorProcessor processorFor(AnalysisError error) => | 215 ErrorProcessor processorFor(AnalysisError error) => |
611 processors.firstWhere((p) => p.appliesTo(error)); | 216 processors.firstWhere((p) => p.appliesTo(error)); |
612 | 217 |
613 /// Normalize text with bullets. | 218 /// Normalize text with bullets. |
614 String _bulletToDash(item) => '$item'.replaceAll('•', '-'); | 219 String _bulletToDash(item) => '$item'.replaceAll('•', '-'); |
615 | 220 |
| 221 void _test_buildMode() { |
| 222 void createTests(String designator, String optionsFileName) { |
| 223 group('build-mode - $designator', () { |
| 224 // Shared driver command. |
| 225 Future<Null> doDrive(String filePath, |
| 226 {List<String> additionalArgs: const []}) async { |
| 227 await drive('file:///test_file.dart|$filePath', |
| 228 args: [ |
| 229 '--dart-sdk', |
| 230 findSdkDirForSummaries(), |
| 231 '--build-mode', |
| 232 '--format=machine' |
| 233 ]..addAll(additionalArgs), |
| 234 options: 'data/options_tests_project/$optionsFileName'); |
| 235 } |
| 236 |
| 237 test('no stats', () async { |
| 238 await doDrive(path.join('data', 'test_file.dart')); |
| 239 // Should not print stat summary. |
| 240 expect(outSink.toString(), isEmpty); |
| 241 expect(errorSink.toString(), isEmpty); |
| 242 expect(exitCode, 0); |
| 243 }); |
| 244 |
| 245 test( |
| 246 'Fails if file not found, even when --build-suppress-exit-code is give
n', |
| 247 () async { |
| 248 await doDrive(path.join('data', 'non_existent_file.dart'), |
| 249 additionalArgs: ['--build-suppress-exit-code']); |
| 250 expect(exitCode, isNot(0)); |
| 251 }); |
| 252 |
| 253 test('Fails if there are errors', () async { |
| 254 await doDrive(path.join('data', 'file_with_error.dart')); |
| 255 expect(exitCode, isNot(0)); |
| 256 }); |
| 257 |
| 258 test( |
| 259 'Succeeds if there are errors, when --build-suppress-exit-code is give
n', |
| 260 () async { |
| 261 await doDrive(path.join('data', 'file_with_error.dart'), |
| 262 additionalArgs: ['--build-suppress-exit-code']); |
| 263 expect(exitCode, 0); |
| 264 }); |
| 265 |
| 266 test('Linked summary', () async { |
| 267 await withTempDirAsync((tempDir) async { |
| 268 var outputPath = path.join(tempDir, 'test_file.dart.sum'); |
| 269 await doDrive(path.join('data', 'test_file.dart'), additionalArgs: [ |
| 270 '--build-summary-only', |
| 271 '--build-summary-output=$outputPath' |
| 272 ]); |
| 273 var output = new File(outputPath); |
| 274 expect(output.existsSync(), isTrue); |
| 275 PackageBundle bundle = |
| 276 new PackageBundle.fromBuffer(await output.readAsBytes()); |
| 277 var testFileUri = 'file:///test_file.dart'; |
| 278 expect(bundle.unlinkedUnitUris, equals([testFileUri])); |
| 279 expect(bundle.linkedLibraryUris, equals([testFileUri])); |
| 280 expect(exitCode, 0); |
| 281 }); |
| 282 }); |
| 283 |
| 284 test('Unlinked summary only', () async { |
| 285 await withTempDirAsync((tempDir) async { |
| 286 var outputPath = path.join(tempDir, 'test_file.dart.sum'); |
| 287 await doDrive(path.join('data', 'test_file.dart'), additionalArgs: [ |
| 288 '--build-summary-only', |
| 289 '--build-summary-only-unlinked', |
| 290 '--build-summary-output=$outputPath' |
| 291 ]); |
| 292 var output = new File(outputPath); |
| 293 expect(output.existsSync(), isTrue); |
| 294 PackageBundle bundle = |
| 295 new PackageBundle.fromBuffer(await output.readAsBytes()); |
| 296 var testFileUri = 'file:///test_file.dart'; |
| 297 expect(bundle.unlinkedUnits.length, 1); |
| 298 expect(bundle.unlinkedUnitUris, equals([testFileUri])); |
| 299 expect(bundle.linkedLibraryUris, isEmpty); |
| 300 expect(exitCode, 0); |
| 301 }); |
| 302 }); |
| 303 }); |
| 304 } |
| 305 |
| 306 createTests('old', AnalysisEngine.ANALYSIS_OPTIONS_FILE); |
| 307 createTests('new', AnalysisEngine.ANALYSIS_OPTIONS_YAML_FILE); |
| 308 } |
| 309 |
| 310 void _test_exitCodes() { |
| 311 group('exit codes', () { |
| 312 test('fatal hints', () async { |
| 313 await drive('data/file_with_hint.dart', args: ['--fatal-hints']); |
| 314 expect(exitCode, 1); |
| 315 }); |
| 316 |
| 317 test('not fatal hints', () async { |
| 318 await drive('data/file_with_hint.dart'); |
| 319 expect(exitCode, 0); |
| 320 }); |
| 321 |
| 322 test('fatal errors', () async { |
| 323 await drive('data/file_with_error.dart'); |
| 324 expect(exitCode, 3); |
| 325 }); |
| 326 |
| 327 test('not fatal warnings', () async { |
| 328 await drive('data/file_with_warning.dart'); |
| 329 expect(exitCode, 0); |
| 330 }); |
| 331 |
| 332 test('fatal warnings', () async { |
| 333 await drive('data/file_with_warning.dart', args: ['--fatal-warnings']); |
| 334 expect(exitCode, 2); |
| 335 }); |
| 336 |
| 337 test('not parse enableAssertInitializer', () async { |
| 338 await drive('data/file_with_assert_initializers.dart', |
| 339 args: ['--enable-assert-initializers']); |
| 340 expect(exitCode, 0); |
| 341 }); |
| 342 |
| 343 test('missing options file', () async { |
| 344 await drive('data/test_file.dart', options: 'data/NO_OPTIONS_HERE'); |
| 345 expect(exitCode, 3); |
| 346 }); |
| 347 |
| 348 test('missing dart file', () async { |
| 349 await drive('data/NO_DART_FILE_HERE.dart'); |
| 350 expect(exitCode, 3); |
| 351 }); |
| 352 |
| 353 test('part file', () async { |
| 354 await drive('data/library_and_parts/part2.dart'); |
| 355 expect(exitCode, 3); |
| 356 }); |
| 357 |
| 358 test('non-dangling part file', () async { |
| 359 Driver driver = new Driver(isTesting: true); |
| 360 await driver.start([ |
| 361 path.join(testDirectory, 'data/library_and_parts/lib.dart'), |
| 362 path.join(testDirectory, 'data/library_and_parts/part1.dart') |
| 363 ]); |
| 364 expect(exitCode, 0); |
| 365 }); |
| 366 |
| 367 test('extra part file', () async { |
| 368 Driver driver = new Driver(isTesting: true); |
| 369 await driver.start([ |
| 370 path.join(testDirectory, 'data/library_and_parts/lib.dart'), |
| 371 path.join(testDirectory, 'data/library_and_parts/part1.dart'), |
| 372 path.join(testDirectory, 'data/library_and_parts/part2.dart') |
| 373 ]); |
| 374 expect(exitCode, 3); |
| 375 }); |
| 376 |
| 377 test('bazel workspace relative path', () async { |
| 378 // Copy to temp dir so that existing analysis options |
| 379 // in the test directory hierarchy do not interfere |
| 380 await withTempDirAsync((String tempDirPath) async { |
| 381 String dartSdkPath = path.absolute(getSdkPath()); |
| 382 await recursiveCopy( |
| 383 new Directory(path.join(testDirectory, 'data', 'bazel')), |
| 384 tempDirPath); |
| 385 Directory origWorkingDir = Directory.current; |
| 386 try { |
| 387 Directory.current = path.join(tempDirPath, 'proj'); |
| 388 Driver driver = new Driver(isTesting: true); |
| 389 try { |
| 390 await driver.start([ |
| 391 path.join('lib', 'file.dart'), |
| 392 '--dart-sdk', |
| 393 dartSdkPath, |
| 394 ]); |
| 395 } catch (e) { |
| 396 print('=== debug info ==='); |
| 397 print('dartSdkPath: $dartSdkPath'); |
| 398 print('stderr:\n${errorSink.toString()}'); |
| 399 rethrow; |
| 400 } |
| 401 expect(errorSink.toString(), isEmpty); |
| 402 expect(outSink.toString(), contains('No issues found')); |
| 403 expect(exitCode, 0); |
| 404 } finally { |
| 405 Directory.current = origWorkingDir; |
| 406 } |
| 407 }); |
| 408 }); |
| 409 }); |
| 410 } |
| 411 |
| 412 void _test_linter() { |
| 413 test('containsLintRuleEntry', () { |
| 414 Map<String, YamlNode> options; |
| 415 options = parseOptions(''' |
| 416 linter: |
| 417 rules: |
| 418 - foo |
| 419 '''); |
| 420 expect(containsLintRuleEntry(options), true); |
| 421 options = parseOptions(''' |
| 422 '''); |
| 423 expect(containsLintRuleEntry(options), false); |
| 424 options = parseOptions(''' |
| 425 linter: |
| 426 rules: |
| 427 # - foo |
| 428 '''); |
| 429 expect(containsLintRuleEntry(options), true); |
| 430 options = parseOptions(''' |
| 431 linter: |
| 432 # rules: |
| 433 # - foo |
| 434 '''); |
| 435 expect(containsLintRuleEntry(options), false); |
| 436 }); |
| 437 |
| 438 group('linter', () { |
| 439 void createTests(String designator, String optionsFileName) { |
| 440 group('lints in options - $designator', () { |
| 441 // Shared lint command. |
| 442 Future<Null> runLinter() async { |
| 443 return await drive('data/linter_project/test_file.dart', |
| 444 options: 'data/linter_project/$optionsFileName', |
| 445 args: ['--lints']); |
| 446 } |
| 447 |
| 448 test('gets analysis options', () async { |
| 449 await runLinter(); |
| 450 |
| 451 /// Lints should be enabled. |
| 452 expect(driver.context.analysisOptions.lint, isTrue); |
| 453 |
| 454 /// The analysis options file only specifies 'camel_case_types'. |
| 455 var lintNames = getLints(driver.context).map((r) => r.name); |
| 456 expect(lintNames, orderedEquals(['camel_case_types'])); |
| 457 }); |
| 458 |
| 459 test('generates lints', () async { |
| 460 await runLinter(); |
| 461 expect(_bulletToDash(outSink), |
| 462 contains('lint - Name types using UpperCamelCase')); |
| 463 }); |
| 464 }); |
| 465 |
| 466 group('default lints - $designator', () { |
| 467 // Shared lint command. |
| 468 Future<Null> runLinter() async { |
| 469 return await drive('data/linter_project/test_file.dart', |
| 470 options: 'data/linter_project/$optionsFileName', |
| 471 args: ['--lints']); |
| 472 } |
| 473 |
| 474 test('gets default lints', () async { |
| 475 await runLinter(); |
| 476 |
| 477 /// Lints should be enabled. |
| 478 expect(driver.context.analysisOptions.lint, isTrue); |
| 479 |
| 480 /// Default list should include camel_case_types. |
| 481 var lintNames = getLints(driver.context).map((r) => r.name); |
| 482 expect(lintNames, contains('camel_case_types')); |
| 483 }); |
| 484 |
| 485 test('generates lints', () async { |
| 486 await runLinter(); |
| 487 expect(_bulletToDash(outSink), |
| 488 contains('lint - Name types using UpperCamelCase')); |
| 489 }); |
| 490 }); |
| 491 |
| 492 group('no `--lints` flag (none in options) - $designator', () { |
| 493 // Shared lint command. |
| 494 Future<Null> runLinter() async { |
| 495 return await drive('data/no_lints_project/test_file.dart', |
| 496 options: 'data/no_lints_project/$optionsFileName'); |
| 497 } |
| 498 |
| 499 test('lints disabled', () async { |
| 500 await runLinter(); |
| 501 expect(driver.context.analysisOptions.lint, isFalse); |
| 502 }); |
| 503 |
| 504 test('no registered lints', () async { |
| 505 await runLinter(); |
| 506 expect(getLints(driver.context), isEmpty); |
| 507 }); |
| 508 |
| 509 test('no generated warnings', () async { |
| 510 await runLinter(); |
| 511 expect(outSink.toString(), contains('No issues found')); |
| 512 }); |
| 513 }); |
| 514 } |
| 515 |
| 516 createTests('old', AnalysisEngine.ANALYSIS_OPTIONS_FILE); |
| 517 createTests('new', AnalysisEngine.ANALYSIS_OPTIONS_YAML_FILE); |
| 518 }); |
| 519 } |
| 520 |
| 521 void _test_optionsProcessing() { |
| 522 group('options processing', () { |
| 523 void createTests(String designator, String optionsFileName) { |
| 524 group('basic config - $designator', () { |
| 525 // Shared driver command. |
| 526 Future<Null> doDrive() async { |
| 527 await drive('data/options_tests_project/test_file.dart', |
| 528 options: 'data/options_tests_project/$optionsFileName'); |
| 529 } |
| 530 |
| 531 test('filters', () async { |
| 532 await doDrive(); |
| 533 expect(processors, hasLength(3)); |
| 534 |
| 535 // unused_local_variable: ignore |
| 536 var unused_local_variable = new AnalysisError( |
| 537 new TestSource(), 0, 1, HintCode.UNUSED_LOCAL_VARIABLE, [ |
| 538 ['x'] |
| 539 ]); |
| 540 expect(processorFor(unused_local_variable).severity, isNull); |
| 541 |
| 542 // missing_return: error |
| 543 var missing_return = new AnalysisError( |
| 544 new TestSource(), 0, 1, HintCode.MISSING_RETURN, [ |
| 545 ['x'] |
| 546 ]); |
| 547 expect(processorFor(missing_return).severity, ErrorSeverity.ERROR); |
| 548 expect( |
| 549 _bulletToDash(outSink), |
| 550 contains( |
| 551 "error - This function declares a return type of 'int'")); |
| 552 expect(outSink.toString(), contains("1 error and 1 warning found.")); |
| 553 }); |
| 554 |
| 555 test('language', () async { |
| 556 await doDrive(); |
| 557 expect(driver.context.analysisOptions.enableSuperMixins, isTrue); |
| 558 }); |
| 559 |
| 560 test('strongMode', () async { |
| 561 await doDrive(); |
| 562 expect(driver.context.analysisOptions.strongMode, isTrue); |
| 563 //https://github.com/dart-lang/sdk/issues/26129 |
| 564 AnalysisContext sdkContext = |
| 565 driver.context.sourceFactory.dartSdk.context; |
| 566 expect(sdkContext.analysisOptions.strongMode, isTrue); |
| 567 }); |
| 568 }); |
| 569 |
| 570 group('with flags - $designator', () { |
| 571 // Shared driver command. |
| 572 Future<Null> doDrive() async { |
| 573 await drive('data/options_tests_project/test_file.dart', |
| 574 args: ['--fatal-warnings'], |
| 575 options: 'data/options_tests_project/$optionsFileName'); |
| 576 } |
| 577 |
| 578 test('override fatal warning', () async { |
| 579 await doDrive(); |
| 580 // missing_return: error |
| 581 var undefined_function = new AnalysisError(new TestSource(), 0, 1, |
| 582 StaticTypeWarningCode.UNDEFINED_FUNCTION, [ |
| 583 ['x'] |
| 584 ]); |
| 585 expect( |
| 586 processorFor(undefined_function).severity, ErrorSeverity.WARNING); |
| 587 // Should not be made fatal by `--fatal-warnings`. |
| 588 expect(_bulletToDash(outSink), |
| 589 contains("warning - The function 'baz' isn't defined")); |
| 590 expect(outSink.toString(), contains("1 error and 1 warning found.")); |
| 591 }); |
| 592 }); |
| 593 } |
| 594 |
| 595 createTests('old', AnalysisEngine.ANALYSIS_OPTIONS_FILE); |
| 596 createTests('new', AnalysisEngine.ANALYSIS_OPTIONS_YAML_FILE); |
| 597 |
| 598 test('include directive', () async { |
| 599 String testDir = path.join( |
| 600 testDirectory, 'data', 'options_include_directive_tests_project'); |
| 601 await drive( |
| 602 path.join(testDir, 'lib', 'test_file.dart'), |
| 603 args: [ |
| 604 '--fatal-warnings', |
| 605 '--packages', |
| 606 path.join(testDir, '_packages'), |
| 607 ], |
| 608 options: path.join(testDir, 'analysis_options.yaml'), |
| 609 ); |
| 610 expect(exitCode, 3); |
| 611 expect(outSink.toString(), |
| 612 contains('but doesn\'t end with a return statement')); |
| 613 expect(outSink.toString(), contains('isn\'t defined')); |
| 614 expect(outSink.toString(), contains('Avoid empty else statements')); |
| 615 }); |
| 616 |
| 617 test('test strong SDK', () async { |
| 618 String testDir = path.join(testDirectory, 'data', 'strong_sdk'); |
| 619 await drive(path.join(testDir, 'main.dart'), args: ['--strong']); |
| 620 expect(driver.context.analysisOptions.strongMode, isTrue); |
| 621 expect(outSink.toString(), contains('No issues found')); |
| 622 expect(exitCode, 0); |
| 623 }); |
| 624 }); |
| 625 } |
| 626 |
616 class TestSource implements Source { | 627 class TestSource implements Source { |
617 TestSource(); | 628 TestSource(); |
618 | 629 |
619 @override | 630 @override |
620 noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation); | 631 noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation); |
621 } | 632 } |
OLD | NEW |