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:io'; | 7 import 'dart:io'; |
8 | 8 |
9 import 'package:analyzer/plugin/options.dart'; | 9 import 'package:analyzer/plugin/options.dart'; |
10 import 'package:analyzer/source/analysis_options_provider.dart'; | 10 import 'package:analyzer/source/analysis_options_provider.dart'; |
11 import 'package:analyzer/src/generated/engine.dart'; | 11 import 'package:analyzer/src/generated/engine.dart'; |
12 import 'package:analyzer/src/generated/error.dart'; | 12 import 'package:analyzer/src/generated/error.dart'; |
13 import 'package:analyzer/src/generated/source.dart'; | 13 import 'package:analyzer/src/generated/source.dart'; |
14 import 'package:analyzer/src/plugin/plugin_configuration.dart'; | 14 import 'package:analyzer/src/plugin/plugin_configuration.dart'; |
15 import 'package:analyzer/src/services/lint.dart'; | 15 import 'package:analyzer/src/services/lint.dart'; |
16 import 'package:analyzer_cli/src/bootloader.dart'; | 16 import 'package:analyzer_cli/src/bootloader.dart'; |
17 import 'package:analyzer_cli/src/driver.dart'; | 17 import 'package:analyzer_cli/src/driver.dart'; |
18 import 'package:analyzer_cli/src/options.dart'; | 18 import 'package:analyzer_cli/src/options.dart'; |
19 import 'package:path/path.dart' as path; | 19 import 'package:path/path.dart' as path; |
20 import 'package:plugin/plugin.dart'; | 20 import 'package:plugin/plugin.dart'; |
21 import 'package:unittest/unittest.dart'; | 21 import 'package:unittest/unittest.dart'; |
22 import 'package:yaml/src/yaml_node.dart'; | 22 import 'package:yaml/src/yaml_node.dart'; |
23 | 23 |
24 import 'utils.dart'; | 24 // TODO(pq): fix tests to run safely on the bots |
| 25 // https://github.com/dart-lang/sdk/issues/25001 |
| 26 main() {} |
| 27 const emptyOptionsFile = 'test/data/empty_options.yaml'; |
25 | 28 |
26 main() { | 29 /// Start a driver for the given [source], optionally providing additional |
| 30 /// [args] and an [options] file path. The value of [options] defaults to |
| 31 /// an empty options file to avoid unwanted configuration from an otherwise |
| 32 /// discovered options file. |
| 33 void drive(String source, |
| 34 {String options: emptyOptionsFile, |
| 35 List<String> args: const <String>[]}) => |
| 36 new Driver().start(['--options', options, source]..addAll(args)); |
| 37 |
| 38 not_main() { |
27 group('Driver', () { | 39 group('Driver', () { |
| 40 StringSink savedOutSink, savedErrorSink; |
| 41 int savedExitCode; |
| 42 setUp(() { |
| 43 savedOutSink = outSink; |
| 44 savedErrorSink = errorSink; |
| 45 savedExitCode = exitCode; |
| 46 outSink = new StringBuffer(); |
| 47 errorSink = new StringBuffer(); |
| 48 }); |
| 49 tearDown(() { |
| 50 outSink = savedOutSink; |
| 51 errorSink = savedErrorSink; |
| 52 exitCode = savedExitCode; |
| 53 }); |
| 54 |
28 group('options', () { | 55 group('options', () { |
29 test('custom processor', () { | 56 test('custom processor', () { |
30 Driver driver = new Driver(); | 57 Driver driver = new Driver(); |
31 TestProcessor processor = new TestProcessor(); | 58 TestProcessor processor = new TestProcessor(); |
32 driver.userDefinedPlugins = [new TestPlugin(processor)]; | 59 driver.userDefinedPlugins = [new TestPlugin(processor)]; |
33 driver.start([ | 60 driver.start([ |
34 '--options', | 61 '--options', |
35 path.join(testDirectory, 'data/test_options.yaml'), | 62 'test/data/test_options.yaml', |
36 path.join(testDirectory, 'data/test_file.dart') | 63 'test/data/test_file.dart' |
37 ]); | 64 ]); |
38 expect(processor.options['test_plugin'], isNotNull); | 65 expect(processor.options['test_plugin'], isNotNull); |
39 expect(processor.exception, isNull); | 66 expect(processor.exception, isNull); |
40 }); | 67 }); |
41 }); | 68 }); |
42 | 69 |
43 //TODO(pq): refactor to NOT set actual error codes to play nice with bots | |
44 group('exit codes', () { | 70 group('exit codes', () { |
45 StringSink savedOutSink, savedErrorSink; | 71 StringSink savedOutSink, savedErrorSink; |
46 int savedExitCode; | 72 int savedExitCode; |
47 ExitHandler savedExitHandler; | 73 ExitHandler savedExitHandler; |
48 setUp(() { | 74 setUp(() { |
49 savedOutSink = outSink; | 75 savedOutSink = outSink; |
50 savedErrorSink = errorSink; | 76 savedErrorSink = errorSink; |
51 savedExitCode = exitCode; | 77 savedExitCode = exitCode; |
52 savedExitHandler = exitHandler; | 78 savedExitHandler = exitHandler; |
53 exitHandler = (code) => exitCode = code; | 79 exitHandler = (code) => exitCode = code; |
54 outSink = new StringBuffer(); | 80 outSink = new StringBuffer(); |
55 errorSink = new StringBuffer(); | 81 errorSink = new StringBuffer(); |
56 }); | 82 }); |
57 tearDown(() { | 83 tearDown(() { |
58 outSink = savedOutSink; | 84 outSink = savedOutSink; |
59 errorSink = savedErrorSink; | 85 errorSink = savedErrorSink; |
60 exitCode = savedExitCode; | 86 exitCode = savedExitCode; |
61 exitHandler = savedExitHandler; | 87 exitHandler = savedExitHandler; |
62 }); | 88 }); |
63 | 89 |
64 test('fatal hints', () { | 90 test('fatal hints', () { |
65 drive('data/file_with_hint.dart', args: ['--fatal-hints']); | 91 drive('test/data/file_with_hint.dart', args: ['--fatal-hints']); |
66 expect(exitCode, 3); | 92 expect(exitCode, 3); |
67 }); | 93 }); |
68 | 94 |
69 test('not fatal hints', () { | 95 test('not fatal hints', () { |
70 drive('data/file_with_hint.dart'); | 96 drive('test/data/file_with_hint.dart'); |
71 expect(exitCode, 0); | 97 expect(exitCode, 0); |
72 }); | 98 }); |
73 | 99 |
74 test('fatal errors', () { | 100 test('fatal errors', () { |
75 drive('data/file_with_error.dart'); | 101 drive('test/data/file_with_error.dart'); |
76 expect(exitCode, 3); | 102 expect(exitCode, 3); |
77 }); | 103 }); |
78 | 104 |
79 test('not fatal warnings', () { | 105 test('not fatal warnings', () { |
80 drive('data/file_with_warning.dart'); | 106 drive('test/data/file_with_warning.dart'); |
81 expect(exitCode, 0); | 107 expect(exitCode, 0); |
82 }); | 108 }); |
83 | 109 |
84 test('fatal warnings', () { | 110 test('fatal warnings', () { |
85 drive('data/file_with_warning.dart', args: ['--fatal-warnings']); | 111 drive('test/data/file_with_warning.dart', args: ['--fatal-warnings']); |
86 expect(exitCode, 3); | 112 expect(exitCode, 3); |
87 }); | 113 }); |
88 | 114 |
89 test('missing options file', () { | 115 test('missing options file', () { |
90 drive('data/test_file.dart', options: 'data/NO_OPTIONS_HERE'); | 116 drive('test/data/test_file.dart', options: 'test/data/NO_OPTIONS_HERE'); |
91 expect(exitCode, 3); | 117 expect(exitCode, 3); |
92 }); | 118 }); |
93 | 119 |
94 test('missing dart file', () { | 120 test('missing dart file', () { |
95 drive('data/NO_DART_FILE_HERE.dart'); | 121 drive('test/data/NO_DART_FILE_HERE.dart'); |
96 expect(exitCode, 3); | 122 expect(exitCode, 3); |
97 }); | 123 }); |
98 | 124 |
99 test('part file', () { | 125 test('part file', () { |
100 drive('data/library_and_parts/part2.dart'); | 126 drive('test/data/library_and_parts/part2.dart'); |
101 expect(exitCode, 3); | 127 expect(exitCode, 3); |
102 }); | 128 }); |
103 | 129 |
104 test('non-dangling part file', () { | 130 test('non-dangling part file', () { |
105 Driver driver = new Driver(); | 131 Driver driver = new Driver(); |
106 driver.start([ | 132 driver.start([ |
107 path.join(testDirectory, 'data/library_and_parts/lib.dart'), | 133 'test/data/library_and_parts/lib.dart', |
108 path.join(testDirectory, 'data/library_and_parts/part1.dart') | 134 'test/data/library_and_parts/part1.dart', |
109 ]); | 135 ]); |
110 expect(exitCode, 0); | 136 expect(exitCode, 0); |
111 }); | 137 }); |
112 | 138 |
113 test('extra part file', () { | 139 test('extra part file', () { |
114 Driver driver = new Driver(); | 140 Driver driver = new Driver(); |
115 driver.start([ | 141 driver.start([ |
116 path.join(testDirectory, 'data/library_and_parts/lib.dart'), | 142 'test/data/library_and_parts/lib.dart', |
117 path.join(testDirectory, 'data/library_and_parts/part1.dart'), | 143 'test/data/library_and_parts/part1.dart', |
118 path.join(testDirectory, 'data/library_and_parts/part2.dart') | 144 'test/data/library_and_parts/part2.dart', |
119 ]); | 145 ]); |
120 expect(exitCode, 3); | 146 expect(exitCode, 3); |
121 }); | 147 }); |
122 }); | 148 }); |
123 | 149 |
124 group('linter', () { | 150 group('linter', () { |
125 group('lints in options', () { | 151 group('lints in options', () { |
126 StringSink savedOutSink; | 152 StringSink savedOutSink; |
| 153 Driver driver; |
127 | 154 |
128 setUp(() { | 155 setUp(() { |
129 savedOutSink = outSink; | 156 savedOutSink = outSink; |
130 outSink = new StringBuffer(); | 157 outSink = new StringBuffer(); |
131 | 158 |
132 drive('data/linter_project/test_file.dart', | 159 driver = new Driver(); |
133 options: 'data/linter_project/.analysis_options', | 160 driver.start([ |
134 args: ['--lints']); | 161 '--options', |
| 162 'test/data/linter_project/.analysis_options', |
| 163 '--lints', |
| 164 'test/data/linter_project/test_file.dart' |
| 165 ]); |
135 }); | 166 }); |
136 | |
137 tearDown(() { | 167 tearDown(() { |
138 outSink = savedOutSink; | 168 outSink = savedOutSink; |
139 }); | 169 }); |
140 | 170 |
141 test('gets analysis options', () { | 171 test('gets analysis options', () { |
142 /// Lints should be enabled. | 172 /// Lints should be enabled. |
143 expect(driver.context.analysisOptions.lint, isTrue); | 173 expect(driver.context.analysisOptions.lint, isTrue); |
144 | 174 |
145 /// The .analysis_options file only specifies 'camel_case_types'. | 175 /// The .analysis_options file only specifies 'camel_case_types'. |
146 var lintNames = getLints(driver.context).map((r) => r.name); | 176 var lintNames = getLints(driver.context).map((r) => r.name); |
147 expect(lintNames, orderedEquals(['camel_case_types'])); | 177 expect(lintNames, orderedEquals(['camel_case_types'])); |
148 }); | 178 }); |
149 | 179 |
150 test('generates lints', () { | 180 test('generates lints', () { |
151 expect(outSink.toString(), | 181 expect(outSink.toString(), |
152 contains('[lint] Name types using UpperCamelCase.')); | 182 contains('[lint] Name types using UpperCamelCase.')); |
153 }); | 183 }); |
154 }); | 184 }); |
155 | 185 |
156 group('default lints', () { | 186 group('default lints', () { |
157 StringSink savedOutSink; | 187 StringSink savedOutSink; |
| 188 Driver driver; |
158 | 189 |
159 setUp(() { | 190 setUp(() { |
160 savedOutSink = outSink; | 191 savedOutSink = outSink; |
161 outSink = new StringBuffer(); | 192 outSink = new StringBuffer(); |
162 | 193 |
163 drive('data/linter_project/test_file.dart', | 194 driver = new Driver(); |
164 options: 'data/linter_project/.analysis_options', | 195 driver.start([ |
165 args: ['--lints']); | 196 '--lints', |
| 197 'test/data/linter_project/test_file.dart', |
| 198 '--options', |
| 199 'test/data/linter_project/.analysis_options' |
| 200 ]); |
166 }); | 201 }); |
167 tearDown(() { | 202 tearDown(() { |
168 outSink = savedOutSink; | 203 outSink = savedOutSink; |
169 }); | 204 }); |
170 | 205 |
171 test('gets default lints', () { | 206 test('gets default lints', () { |
172 /// Lints should be enabled. | 207 /// Lints should be enabled. |
173 expect(driver.context.analysisOptions.lint, isTrue); | 208 expect(driver.context.analysisOptions.lint, isTrue); |
174 | 209 |
175 /// Default list should include camel_case_types. | 210 /// Default list should include camel_case_types. |
176 var lintNames = getLints(driver.context).map((r) => r.name); | 211 var lintNames = getLints(driver.context).map((r) => r.name); |
177 expect(lintNames, contains('camel_case_types')); | 212 expect(lintNames, contains('camel_case_types')); |
178 }); | 213 }); |
179 | 214 |
180 test('generates lints', () { | 215 test('generates lints', () { |
181 expect(outSink.toString(), | 216 expect(outSink.toString(), |
182 contains('[lint] Name types using UpperCamelCase.')); | 217 contains('[lint] Name types using UpperCamelCase.')); |
183 }); | 218 }); |
184 }); | 219 }); |
185 | 220 |
186 group('no `--lints` flag (none in options)', () { | 221 group('no `--lints` flag (none in options)', () { |
187 StringSink savedOutSink; | 222 StringSink savedOutSink; |
| 223 Driver driver; |
188 | 224 |
189 setUp(() { | 225 setUp(() { |
190 savedOutSink = outSink; | 226 savedOutSink = outSink; |
191 outSink = new StringBuffer(); | 227 outSink = new StringBuffer(); |
192 | 228 |
193 drive('data/no_lints_project/test_file.dart', | 229 driver = new Driver(); |
194 options: 'data/no_lints_project/.analysis_options'); | 230 driver.start([ |
| 231 'test/data/no_lints_project/test_file.dart', |
| 232 '--options', |
| 233 'test/data/no_lints_project/.analysis_options' |
| 234 ]); |
195 }); | 235 }); |
196 tearDown(() { | 236 tearDown(() { |
197 outSink = savedOutSink; | 237 outSink = savedOutSink; |
198 }); | 238 }); |
199 | 239 |
200 test('lints disabled', () { | 240 test('lints disabled', () { |
201 expect(driver.context.analysisOptions.lint, isFalse); | 241 expect(driver.context.analysisOptions.lint, isFalse); |
202 }); | 242 }); |
203 | 243 |
204 test('no registered lints', () { | 244 test('no registered lints', () { |
(...skipping 27 matching lines...) Expand all Loading... |
232 linter: | 272 linter: |
233 # rules: | 273 # rules: |
234 # - foo | 274 # - foo |
235 '''); | 275 '''); |
236 expect(containsLintRuleEntry(options), false); | 276 expect(containsLintRuleEntry(options), false); |
237 }); | 277 }); |
238 | 278 |
239 group('options processing', () { | 279 group('options processing', () { |
240 group('error filters', () { | 280 group('error filters', () { |
241 StringSink savedOutSink; | 281 StringSink savedOutSink; |
| 282 Driver driver; |
242 | 283 |
243 setUp(() { | 284 setUp(() { |
244 savedOutSink = outSink; | 285 savedOutSink = outSink; |
245 outSink = new StringBuffer(); | 286 outSink = new StringBuffer(); |
246 | 287 |
247 drive('data/options_tests_project/test_file.dart', | 288 driver = new Driver(); |
248 options: 'data/options_tests_project/.analysis_options'); | 289 driver.start([ |
| 290 'test/data/options_tests_project/test_file.dart', |
| 291 '--options', |
| 292 'test/data/options_tests_project/.analysis_options' |
| 293 ]); |
249 }); | 294 }); |
250 tearDown(() { | 295 tearDown(() { |
251 outSink = savedOutSink; | 296 outSink = savedOutSink; |
252 }); | 297 }); |
253 | 298 |
254 test('filters', () { | 299 test('filters', () { |
255 var processors = | 300 var processors = |
256 driver.context.getConfigurationData(CONFIGURED_ERROR_PROCESSORS); | 301 driver.context.getConfigurationData(CONFIGURED_ERROR_PROCESSORS); |
257 expect(processors, hasLength(1)); | 302 expect(processors, hasLength(1)); |
258 | 303 |
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
346 savedErrorSink = errorSink; | 391 savedErrorSink = errorSink; |
347 errorSink = new StringBuffer(); | 392 errorSink = new StringBuffer(); |
348 }); | 393 }); |
349 tearDown(() { | 394 tearDown(() { |
350 errorSink = savedErrorSink; | 395 errorSink = savedErrorSink; |
351 }); | 396 }); |
352 test('bad format', () { | 397 test('bad format', () { |
353 BootLoader loader = new BootLoader(); | 398 BootLoader loader = new BootLoader(); |
354 loader.createImage([ | 399 loader.createImage([ |
355 '--options', | 400 '--options', |
356 path.join(testDirectory, 'data/bad_plugin_options.yaml'), | 401 'test/data/bad_plugin_options.yaml', |
357 path.join(testDirectory, 'data/test_file.dart') | 402 'test/data/test_file.dart' |
358 ]); | 403 ]); |
359 expect( | 404 expect( |
360 errorSink.toString(), | 405 errorSink.toString(), |
361 equals('Plugin configuration skipped: Unrecognized plugin config ' | 406 equals('Plugin configuration skipped: Unrecognized plugin config ' |
362 'format, expected `YamlMap`, got `YamlList` ' | 407 'format, expected `YamlMap`, got `YamlList` ' |
363 '(line 2, column 4)\n')); | 408 '(line 2, column 4)\n')); |
364 }); | 409 }); |
365 test('plugin config', () { | 410 test('plugin config', () { |
366 BootLoader loader = new BootLoader(); | 411 BootLoader loader = new BootLoader(); |
367 Image image = loader.createImage([ | 412 Image image = loader.createImage([ |
368 '--options', | 413 '--options', |
369 path.join(testDirectory, 'data/plugin_options.yaml'), | 414 'test/data/plugin_options.yaml', |
370 path.join(testDirectory, 'data/test_file.dart') | 415 'test/data/test_file.dart' |
371 ]); | 416 ]); |
372 var plugins = image.config.plugins; | 417 var plugins = image.config.plugins; |
373 expect(plugins, hasLength(1)); | 418 expect(plugins, hasLength(1)); |
374 expect(plugins.first.name, equals('my_plugin1')); | 419 expect(plugins.first.name, equals('my_plugin1')); |
375 }); | 420 }); |
376 group('plugin validation', () { | 421 group('plugin validation', () { |
377 test('requires class name', () { | 422 test('requires class name', () { |
378 expect( | 423 expect( |
379 validate(new PluginInfo( | 424 validate(new PluginInfo( |
380 name: 'test_plugin', libraryUri: 'my_package/foo.dart')), | 425 name: 'test_plugin', libraryUri: 'my_package/foo.dart')), |
(...skipping 11 matching lines...) Expand all Loading... |
392 name: 'test_plugin', | 437 name: 'test_plugin', |
393 className: 'MyPlugin', | 438 className: 'MyPlugin', |
394 libraryUri: 'my_package/foo.dart')), | 439 libraryUri: 'my_package/foo.dart')), |
395 isNull); | 440 isNull); |
396 }); | 441 }); |
397 }); | 442 }); |
398 }); | 443 }); |
399 }); | 444 }); |
400 } | 445 } |
401 | 446 |
402 const emptyOptionsFile = 'data/empty_options.yaml'; | |
403 | |
404 /// Shared driver. | |
405 Driver driver; | |
406 | |
407 /// Start a driver for the given [source], optionally providing additional | |
408 /// [args] and an [options] file path. The value of [options] defaults to | |
409 /// an empty options file to avoid unwanted configuration from an otherwise | |
410 /// discovered options file. | |
411 void drive(String source, | |
412 {String options: emptyOptionsFile, List<String> args: const <String>[]}) { | |
413 driver = new Driver(); | |
414 var cmd = [ | |
415 '--options', | |
416 path.join(testDirectory, options), | |
417 path.join(testDirectory, source) | |
418 ]..addAll(args); | |
419 driver.start(cmd); | |
420 } | |
421 | |
422 Map<String, YamlNode> parseOptions(String src) => | 447 Map<String, YamlNode> parseOptions(String src) => |
423 new AnalysisOptionsProvider().getOptionsFromString(src); | 448 new AnalysisOptionsProvider().getOptionsFromString(src); |
424 | 449 |
425 class TestPlugin extends Plugin { | 450 class TestPlugin extends Plugin { |
426 TestProcessor processor; | 451 TestProcessor processor; |
427 TestPlugin(this.processor); | 452 TestPlugin(this.processor); |
428 | 453 |
429 @override | 454 @override |
430 String get uniqueIdentifier => 'test_plugin.core'; | 455 String get uniqueIdentifier => 'test_plugin.core'; |
431 | 456 |
(...skipping 23 matching lines...) Expand all Loading... |
455 this.options = options; | 480 this.options = options; |
456 } | 481 } |
457 } | 482 } |
458 | 483 |
459 class TestSource implements Source { | 484 class TestSource implements Source { |
460 TestSource(); | 485 TestSource(); |
461 | 486 |
462 @override | 487 @override |
463 noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation); | 488 noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation); |
464 } | 489 } |
OLD | NEW |