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 17 matching lines...) Expand all Loading... |
28 | 28 |
29 main() { | 29 main() { |
30 defineReflectiveSuite(() { | 30 defineReflectiveSuite(() { |
31 defineReflectiveTests(BuildModeTest); | 31 defineReflectiveTests(BuildModeTest); |
32 defineReflectiveTests(ExitCodesTest); | 32 defineReflectiveTests(ExitCodesTest); |
33 defineReflectiveTests(LinterTest); | 33 defineReflectiveTests(LinterTest); |
34 defineReflectiveTests(OptionsTest); | 34 defineReflectiveTests(OptionsTest); |
35 }, name: 'Driver'); | 35 }, name: 'Driver'); |
36 } | 36 } |
37 | 37 |
| 38 class BaseTest { |
| 39 static const emptyOptionsFile = 'data/empty_options.yaml'; |
| 40 |
| 41 StringSink _savedOutSink, _savedErrorSink; |
| 42 int _savedExitCode; |
| 43 ExitHandler _savedExitHandler; |
| 44 |
| 45 Driver driver; |
| 46 |
| 47 /// Normalize text with bullets. |
| 48 String bulletToDash(item) => '$item'.replaceAll('•', '-'); |
| 49 |
| 50 /// Start a driver for the given [source], optionally providing additional |
| 51 /// [args] and an [options] file path. The value of [options] defaults to |
| 52 /// an empty options file to avoid unwanted configuration from an otherwise |
| 53 /// discovered options file. |
| 54 Future<Null> drive(String source, |
| 55 {String options: emptyOptionsFile, |
| 56 List<String> args: const <String>[]}) async { |
| 57 driver = new Driver(isTesting: true); |
| 58 var cmd = [ |
| 59 '--options', |
| 60 path.join(testDirectory, options), |
| 61 _adjustFileSpec(source) |
| 62 ]..addAll(args); |
| 63 await driver.start(cmd); |
| 64 } |
| 65 |
| 66 void setUp() { |
| 67 ansi.runningTests = true; |
| 68 _savedOutSink = outSink; |
| 69 _savedErrorSink = errorSink; |
| 70 _savedExitHandler = exitHandler; |
| 71 _savedExitCode = exitCode; |
| 72 exitHandler = (code) => exitCode = code; |
| 73 outSink = new StringBuffer(); |
| 74 errorSink = new StringBuffer(); |
| 75 } |
| 76 |
| 77 void tearDown() { |
| 78 outSink = _savedOutSink; |
| 79 errorSink = _savedErrorSink; |
| 80 exitCode = _savedExitCode; |
| 81 exitHandler = _savedExitHandler; |
| 82 ansi.runningTests = false; |
| 83 } |
| 84 |
| 85 /// Convert a file specification from a relative path to an absolute path. |
| 86 /// Handles the case where the file specification is of the form "$uri|$path". |
| 87 String _adjustFileSpec(String fileSpec) { |
| 88 int uriPrefixLength = fileSpec.indexOf('|') + 1; |
| 89 String uriPrefix = fileSpec.substring(0, uriPrefixLength); |
| 90 String relativePath = fileSpec.substring(uriPrefixLength); |
| 91 return '$uriPrefix${path.join(testDirectory, relativePath)}'; |
| 92 } |
| 93 } |
| 94 |
38 @reflectiveTest | 95 @reflectiveTest |
39 class BuildModeTest extends _BaseTest { | 96 class BuildModeTest extends BaseTest { |
40 test_buildLinked() async { | 97 test_buildLinked() async { |
41 await withTempDirAsync((tempDir) async { | 98 await withTempDirAsync((tempDir) async { |
42 var outputPath = path.join(tempDir, 'test_file.dart.sum'); | 99 var outputPath = path.join(tempDir, 'test_file.dart.sum'); |
43 await _doDrive(path.join('data', 'test_file.dart'), additionalArgs: [ | 100 await _doDrive(path.join('data', 'test_file.dart'), additionalArgs: [ |
44 '--build-summary-only', | 101 '--build-summary-only', |
45 '--build-summary-output=$outputPath' | 102 '--build-summary-output=$outputPath' |
46 ]); | 103 ]); |
47 var output = new File(outputPath); | 104 var output = new File(outputPath); |
48 expect(output.existsSync(), isTrue); | 105 expect(output.existsSync(), isTrue); |
49 PackageBundle bundle = | 106 PackageBundle bundle = |
(...skipping 238 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
288 } | 345 } |
289 } | 346 } |
290 } | 347 } |
291 } | 348 } |
292 throw new Exception('Could not find an SDK directory containing summaries.' | 349 throw new Exception('Could not find an SDK directory containing summaries.' |
293 ' Tried: ${triedDirectories.toList()}'); | 350 ' Tried: ${triedDirectories.toList()}'); |
294 } | 351 } |
295 } | 352 } |
296 | 353 |
297 @reflectiveTest | 354 @reflectiveTest |
298 class ExitCodesTest extends _BaseTest { | 355 class ExitCodesTest extends BaseTest { |
299 test_bazelWorkspace_relativePath() async { | 356 test_bazelWorkspace_relativePath() async { |
300 // Copy to temp dir so that existing analysis options | 357 // Copy to temp dir so that existing analysis options |
301 // in the test directory hierarchy do not interfere | 358 // in the test directory hierarchy do not interfere |
302 await withTempDirAsync((String tempDirPath) async { | 359 await withTempDirAsync((String tempDirPath) async { |
303 String dartSdkPath = path.absolute(getSdkPath()); | 360 String dartSdkPath = path.absolute(getSdkPath()); |
304 await recursiveCopy( | 361 await recursiveCopy( |
305 new Directory(path.join(testDirectory, 'data', 'bazel')), | 362 new Directory(path.join(testDirectory, 'data', 'bazel')), |
306 tempDirPath); | 363 tempDirPath); |
307 Directory origWorkingDir = Directory.current; | 364 Directory origWorkingDir = Directory.current; |
308 try { | 365 try { |
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
389 await driver.start([ | 446 await driver.start([ |
390 path.join(testDirectory, 'data/library_and_parts/lib.dart'), | 447 path.join(testDirectory, 'data/library_and_parts/lib.dart'), |
391 path.join(testDirectory, 'data/library_and_parts/part1.dart'), | 448 path.join(testDirectory, 'data/library_and_parts/part1.dart'), |
392 path.join(testDirectory, 'data/library_and_parts/part2.dart') | 449 path.join(testDirectory, 'data/library_and_parts/part2.dart') |
393 ]); | 450 ]); |
394 expect(exitCode, 3); | 451 expect(exitCode, 3); |
395 } | 452 } |
396 } | 453 } |
397 | 454 |
398 @reflectiveTest | 455 @reflectiveTest |
399 class LinterTest extends _BaseTest { | 456 class LinterTest extends BaseTest { |
400 String get optionsFileName => AnalysisEngine.ANALYSIS_OPTIONS_YAML_FILE; | 457 String get optionsFileName => AnalysisEngine.ANALYSIS_OPTIONS_YAML_FILE; |
401 | 458 |
402 test_containsLintRuleEntry() async { | 459 test_containsLintRuleEntry() async { |
403 Map<String, YamlNode> options; | 460 Map<String, YamlNode> options; |
404 options = _parseOptions(''' | 461 options = _parseOptions(''' |
405 linter: | 462 linter: |
406 rules: | 463 rules: |
407 - foo | 464 - foo |
408 '''); | 465 '''); |
409 expect(containsLintRuleEntry(options), true); | 466 expect(containsLintRuleEntry(options), true); |
410 options = _parseOptions(''' | 467 options = _parseOptions(''' |
411 '''); | 468 '''); |
412 expect(containsLintRuleEntry(options), false); | 469 expect(containsLintRuleEntry(options), false); |
413 options = _parseOptions(''' | 470 options = _parseOptions(''' |
414 linter: | 471 linter: |
415 rules: | 472 rules: |
416 # - foo | 473 # - foo |
417 '''); | 474 '''); |
418 expect(containsLintRuleEntry(options), true); | 475 expect(containsLintRuleEntry(options), true); |
419 options = _parseOptions(''' | 476 options = _parseOptions(''' |
420 linter: | 477 linter: |
421 # rules: | 478 # rules: |
422 # - foo | 479 # - foo |
423 '''); | 480 '''); |
424 expect(containsLintRuleEntry(options), false); | 481 expect(containsLintRuleEntry(options), false); |
425 } | 482 } |
426 | 483 |
427 test_defaultLints_generatedLints() async { | 484 test_defaultLints_generatedLints() async { |
428 await _runLinter_defaultLints(); | 485 await _runLinter_defaultLints(); |
429 expect(_bulletToDash(outSink), | 486 expect(bulletToDash(outSink), |
430 contains('lint - Name types using UpperCamelCase')); | 487 contains('lint - Name types using UpperCamelCase')); |
431 } | 488 } |
432 | 489 |
433 test_defaultLints_getsDefaultLints() async { | 490 test_defaultLints_getsDefaultLints() async { |
434 await _runLinter_defaultLints(); | 491 await _runLinter_defaultLints(); |
435 | 492 |
436 /// Lints should be enabled. | 493 /// Lints should be enabled. |
437 expect(driver.context.analysisOptions.lint, isTrue); | 494 expect(driver.context.analysisOptions.lint, isTrue); |
438 | 495 |
439 /// Default list should include camel_case_types. | 496 /// Default list should include camel_case_types. |
440 var lintNames = getLints(driver.context).map((r) => r.name); | 497 var lintNames = getLints(driver.context).map((r) => r.name); |
441 expect(lintNames, contains('camel_case_types')); | 498 expect(lintNames, contains('camel_case_types')); |
442 } | 499 } |
443 | 500 |
444 test_lintsInOptions_generatedLints() async { | 501 test_lintsInOptions_generatedLints() async { |
445 await _runLinter_lintsInOptions(); | 502 await _runLinter_lintsInOptions(); |
446 expect(_bulletToDash(outSink), | 503 expect(bulletToDash(outSink), |
447 contains('lint - Name types using UpperCamelCase')); | 504 contains('lint - Name types using UpperCamelCase')); |
448 } | 505 } |
449 | 506 |
450 test_lintsInOptions_getAnalysisOptions() async { | 507 test_lintsInOptions_getAnalysisOptions() async { |
451 await _runLinter_lintsInOptions(); | 508 await _runLinter_lintsInOptions(); |
452 | 509 |
453 /// Lints should be enabled. | 510 /// Lints should be enabled. |
454 expect(driver.context.analysisOptions.lint, isTrue); | 511 expect(driver.context.analysisOptions.lint, isTrue); |
455 | 512 |
456 /// The analysis options file only specifies 'camel_case_types'. | 513 /// The analysis options file only specifies 'camel_case_types'. |
(...skipping 29 matching lines...) Expand all Loading... |
486 options: 'data/linter_project/$optionsFileName', args: ['--lints']); | 543 options: 'data/linter_project/$optionsFileName', args: ['--lints']); |
487 } | 544 } |
488 | 545 |
489 Future<Null> _runLinter_noLintsFlag() async { | 546 Future<Null> _runLinter_noLintsFlag() async { |
490 await drive('data/no_lints_project/test_file.dart', | 547 await drive('data/no_lints_project/test_file.dart', |
491 options: 'data/no_lints_project/$optionsFileName'); | 548 options: 'data/no_lints_project/$optionsFileName'); |
492 } | 549 } |
493 } | 550 } |
494 | 551 |
495 @reflectiveTest | 552 @reflectiveTest |
496 class OptionsTest extends _BaseTest { | 553 class OptionsTest extends BaseTest { |
497 String get optionsFileName => AnalysisEngine.ANALYSIS_OPTIONS_YAML_FILE; | 554 String get optionsFileName => AnalysisEngine.ANALYSIS_OPTIONS_YAML_FILE; |
498 | 555 |
499 List<ErrorProcessor> get processors => | 556 List<ErrorProcessor> get processors => |
500 driver.context.analysisOptions.errorProcessors; | 557 driver.context.analysisOptions.errorProcessors; |
501 | 558 |
502 ErrorProcessor processorFor(AnalysisError error) => | 559 ErrorProcessor processorFor(AnalysisError error) => |
503 processors.firstWhere((p) => p.appliesTo(error)); | 560 processors.firstWhere((p) => p.appliesTo(error)); |
504 | 561 |
505 test_basic_filters() async { | 562 test_basic_filters() async { |
506 await _driveBasic(); | 563 await _driveBasic(); |
507 expect(processors, hasLength(3)); | 564 expect(processors, hasLength(3)); |
508 | 565 |
509 // unused_local_variable: ignore | 566 // unused_local_variable: ignore |
510 var unused_local_variable = new AnalysisError( | 567 var unused_local_variable = new AnalysisError( |
511 new TestSource(), 0, 1, HintCode.UNUSED_LOCAL_VARIABLE, [ | 568 new TestSource(), 0, 1, HintCode.UNUSED_LOCAL_VARIABLE, [ |
512 ['x'] | 569 ['x'] |
513 ]); | 570 ]); |
514 expect(processorFor(unused_local_variable).severity, isNull); | 571 expect(processorFor(unused_local_variable).severity, isNull); |
515 | 572 |
516 // missing_return: error | 573 // missing_return: error |
517 var missing_return = | 574 var missing_return = |
518 new AnalysisError(new TestSource(), 0, 1, HintCode.MISSING_RETURN, [ | 575 new AnalysisError(new TestSource(), 0, 1, HintCode.MISSING_RETURN, [ |
519 ['x'] | 576 ['x'] |
520 ]); | 577 ]); |
521 expect(processorFor(missing_return).severity, ErrorSeverity.ERROR); | 578 expect(processorFor(missing_return).severity, ErrorSeverity.ERROR); |
522 expect(_bulletToDash(outSink), | 579 expect(bulletToDash(outSink), |
523 contains("error - This function declares a return type of 'int'")); | 580 contains("error - This function declares a return type of 'int'")); |
524 expect(outSink.toString(), contains("1 error and 1 warning found.")); | 581 expect(outSink.toString(), contains("1 error and 1 warning found.")); |
525 } | 582 } |
526 | 583 |
527 test_basic_language() async { | 584 test_basic_language() async { |
528 await _driveBasic(); | 585 await _driveBasic(); |
529 expect(driver.context.analysisOptions.enableSuperMixins, isTrue); | 586 expect(driver.context.analysisOptions.enableSuperMixins, isTrue); |
530 } | 587 } |
531 | 588 |
532 test_basic_strongMode() async { | 589 test_basic_strongMode() async { |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
574 args: ['--fatal-warnings'], | 631 args: ['--fatal-warnings'], |
575 options: 'data/options_tests_project/$optionsFileName'); | 632 options: 'data/options_tests_project/$optionsFileName'); |
576 | 633 |
577 // missing_return: error | 634 // missing_return: error |
578 var undefined_function = new AnalysisError( | 635 var undefined_function = new AnalysisError( |
579 new TestSource(), 0, 1, StaticTypeWarningCode.UNDEFINED_FUNCTION, [ | 636 new TestSource(), 0, 1, StaticTypeWarningCode.UNDEFINED_FUNCTION, [ |
580 ['x'] | 637 ['x'] |
581 ]); | 638 ]); |
582 expect(processorFor(undefined_function).severity, ErrorSeverity.WARNING); | 639 expect(processorFor(undefined_function).severity, ErrorSeverity.WARNING); |
583 // Should not be made fatal by `--fatal-warnings`. | 640 // Should not be made fatal by `--fatal-warnings`. |
584 expect(_bulletToDash(outSink), | 641 expect(bulletToDash(outSink), |
585 contains("warning - The function 'baz' isn't defined")); | 642 contains("warning - The function 'baz' isn't defined")); |
586 expect(outSink.toString(), contains("1 error and 1 warning found.")); | 643 expect(outSink.toString(), contains("1 error and 1 warning found.")); |
587 } | 644 } |
588 | 645 |
589 Future<Null> _driveBasic() async { | 646 Future<Null> _driveBasic() async { |
590 await drive('data/options_tests_project/test_file.dart', | 647 await drive('data/options_tests_project/test_file.dart', |
591 options: 'data/options_tests_project/$optionsFileName'); | 648 options: 'data/options_tests_project/$optionsFileName'); |
592 } | 649 } |
593 } | 650 } |
594 | 651 |
595 class TestSource implements Source { | 652 class TestSource implements Source { |
596 TestSource(); | 653 TestSource(); |
597 | 654 |
598 @override | 655 @override |
599 noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation); | 656 noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation); |
600 } | 657 } |
601 | |
602 class _BaseTest { | |
603 static const emptyOptionsFile = 'data/empty_options.yaml'; | |
604 | |
605 StringSink _savedOutSink, _savedErrorSink; | |
606 int _savedExitCode; | |
607 ExitHandler _savedExitHandler; | |
608 | |
609 Driver driver; | |
610 | |
611 /// Start a driver for the given [source], optionally providing additional | |
612 /// [args] and an [options] file path. The value of [options] defaults to | |
613 /// an empty options file to avoid unwanted configuration from an otherwise | |
614 /// discovered options file. | |
615 Future<Null> drive(String source, | |
616 {String options: emptyOptionsFile, | |
617 List<String> args: const <String>[]}) async { | |
618 driver = new Driver(isTesting: true); | |
619 var cmd = [ | |
620 '--options', | |
621 path.join(testDirectory, options), | |
622 _adjustFileSpec(source) | |
623 ]..addAll(args); | |
624 await driver.start(cmd); | |
625 } | |
626 | |
627 void setUp() { | |
628 ansi.runningTests = true; | |
629 _savedOutSink = outSink; | |
630 _savedErrorSink = errorSink; | |
631 _savedExitHandler = exitHandler; | |
632 _savedExitCode = exitCode; | |
633 exitHandler = (code) => exitCode = code; | |
634 outSink = new StringBuffer(); | |
635 errorSink = new StringBuffer(); | |
636 } | |
637 | |
638 void tearDown() { | |
639 outSink = _savedOutSink; | |
640 errorSink = _savedErrorSink; | |
641 exitCode = _savedExitCode; | |
642 exitHandler = _savedExitHandler; | |
643 ansi.runningTests = false; | |
644 } | |
645 | |
646 /// Convert a file specification from a relative path to an absolute path. | |
647 /// Handles the case where the file specification is of the form "$uri|$path". | |
648 String _adjustFileSpec(String fileSpec) { | |
649 int uriPrefixLength = fileSpec.indexOf('|') + 1; | |
650 String uriPrefix = fileSpec.substring(0, uriPrefixLength); | |
651 String relativePath = fileSpec.substring(uriPrefixLength); | |
652 return '$uriPrefix${path.join(testDirectory, relativePath)}'; | |
653 } | |
654 | |
655 /// Normalize text with bullets. | |
656 String _bulletToDash(item) => '$item'.replaceAll('•', '-'); | |
657 } | |
OLD | NEW |