Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(821)

Side by Side Diff: pkg/analysis_server/test/domain_analysis_test.dart

Issue 376693002: Extract testing utilities into a separate package. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 6 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2014, 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 test.domain.analysis; 5 library test.domain.analysis;
6 6
7 import 'dart:async'; 7 import 'dart:async';
8 8
9 import 'package:analyzer/file_system/memory_file_system.dart';
10 import 'package:analysis_server/src/analysis_server.dart'; 9 import 'package:analysis_server/src/analysis_server.dart';
11 import 'package:analysis_server/src/computer/element.dart'; 10 import 'package:analysis_server/src/computer/element.dart';
12 import 'package:analysis_server/src/constants.dart'; 11 import 'package:analysis_server/src/constants.dart';
13 import 'package:analysis_server/src/domain_analysis.dart'; 12 import 'package:analysis_server/src/domain_analysis.dart';
14 import 'package:analysis_server/src/protocol.dart'; 13 import 'package:analysis_server/src/protocol.dart';
14 import 'package:analysis_testing/mock_sdk.dart';
15 import 'package:analysis_testing/reflective_tests.dart';
16 import 'package:analyzer/file_system/memory_file_system.dart';
15 import 'package:analyzer/src/generated/engine.dart'; 17 import 'package:analyzer/src/generated/engine.dart';
16 import 'package:path/path.dart'; 18 import 'package:path/path.dart';
17 import 'package:unittest/unittest.dart'; 19 import 'package:unittest/unittest.dart';
18 20
21 import 'analysis_abstract.dart';
19 import 'mocks.dart'; 22 import 'mocks.dart';
20 import 'analysis_abstract.dart'; 23
21 import 'reflective_tests.dart'; 24
25 AnalysisError jsonToAnalysisError(Map<String, Object> json) {
26 Map<String, Object> jsonLocation = json[LOCATION];
27 Location location = new Location(jsonLocation[FILE], _getSafeInt(jsonLocation,
28 OFFSET, -1), _getSafeInt(jsonLocation, LENGTH, -1), _getSafeInt(jsonLocati on,
29 START_LINE, -1), _getSafeInt(jsonLocation, START_COLUMN, -1));
30 return new AnalysisError(json[ERROR_CODE], json[SEVERITY], json[TYPE], locatio n,
31 json['message'], json['correction']);
32 }
22 33
23 34
24 main() { 35 main() {
25 groupSep = ' | '; 36 groupSep = ' | ';
26 37
27 runReflectiveTests(AnalysisDomainTest); 38 runReflectiveTests(AnalysisDomainTest);
28 39
29 MockServerChannel serverChannel; 40 MockServerChannel serverChannel;
30 MemoryResourceProvider resourceProvider; 41 MemoryResourceProvider resourceProvider;
31 AnalysisServer server; 42 AnalysisServer server;
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after
150 request.setParameter(REMOVED, ['/dart/sdk-1.2']); 161 request.setParameter(REMOVED, ['/dart/sdk-1.2']);
151 request.setParameter(DEFAULT, '/dart/sdk-1.4'); 162 request.setParameter(DEFAULT, '/dart/sdk-1.4');
152 var response = handler.handleRequest(request); 163 var response = handler.handleRequest(request);
153 // TODO(scheglov) implement 164 // TODO(scheglov) implement
154 expect(response, isNull); 165 expect(response, isNull);
155 }); 166 });
156 }); 167 });
157 } 168 }
158 169
159 170
160 class AnalysisError { 171 testNotificationErrors() {
161 final String errorCode; 172 AnalysisTestHelper helper;
162 final String severity;
163 final String type;
164 final Location location;
165 final String message;
166 final String correction;
167 AnalysisError(this.errorCode, this.severity, this.type, this.location,
168 this.message, this.correction);
169 173
170 @override 174 setUp(() {
171 String toString() { 175 helper = new AnalysisTestHelper();
172 return 'AnalysisError(location=$location message=$message); ' 176 });
173 'errorCode=$errorCode; severity=$separator type=$type'; 177
174 } 178 test('ParserErrorCode', () {
179 helper.createSingleFileProject('library lib');
180 return helper.waitForOperationsFinished().then((_) {
181 List<AnalysisError> errors = helper.getTestErrors();
182 expect(errors, hasLength(1));
183 AnalysisError error = errors[0];
184 expect(error.location.file, '/project/bin/test.dart');
185 expect(error.location.offset, isPositive);
186 expect(error.location.length, isNonNegative);
187 expect(error.errorCode, 'ParserErrorCode.EXPECTED_TOKEN');
188 expect(error.severity, 'ERROR');
189 expect(error.type, 'SYNTACTIC_ERROR');
190 expect(error.message, isNotNull);
191 });
192 });
193
194 test('StaticWarningCode', () {
195 helper.createSingleFileProject(['main() {', ' print(unknown);', '}']);
196 return helper.waitForOperationsFinished().then((_) {
197 List<AnalysisError> errors = helper.getTestErrors();
198 expect(errors, hasLength(1));
199 AnalysisError error = errors[0];
200 expect(error.errorCode, 'StaticWarningCode.UNDEFINED_IDENTIFIER');
201 });
202 });
175 } 203 }
176 204
177 205
178 AnalysisError jsonToAnalysisError(Map<String, Object> json) { 206 testUpdateContent() {
179 Map<String, Object> jsonLocation = json[LOCATION]; 207 test('full content', () {
180 Location location = new Location(jsonLocation[FILE], _getSafeInt(jsonLocation, 208 AnalysisTestHelper helper = new AnalysisTestHelper();
181 OFFSET, -1), _getSafeInt(jsonLocation, LENGTH, -1), _getSafeInt(jsonLocati on, 209 helper.createSingleFileProject('// empty');
182 START_LINE, -1), _getSafeInt(jsonLocation, START_COLUMN, -1)); 210 return helper.waitForOperationsFinished().then((_) {
183 return new AnalysisError(json[ERROR_CODE], json[SEVERITY], json[TYPE], locatio n, 211 // no errors initially
184 json['message'], json['correction']); 212 List<AnalysisError> errors = helper.getTestErrors();
213 expect(errors, isEmpty);
214 // update code
215 helper.sendContentChange({
216 CONTENT: 'library lib'
217 });
218 // wait, there is an error
219 return helper.waitForOperationsFinished().then((_) {
220 List<AnalysisError> errors = helper.getTestErrors();
221 expect(errors, hasLength(1));
222 });
223 });
224 });
225
226 test('incremental', () {
227 AnalysisTestHelper helper = new AnalysisTestHelper();
228 helper.createSingleFileProject('library A;');
229 return helper.waitForOperationsFinished().then((_) {
230 // no errors initially
231 List<AnalysisError> errors = helper.getTestErrors();
232 expect(errors, isEmpty);
233 // update code
234 helper.sendContentChange({
235 CONTENT: 'library lib',
236 OFFSET: 'library '.length,
237 OLD_LENGTH: 'A;'.length,
238 NEW_LENGTH: 'lib'.length,
239 });
240 // wait, there is an error
241 return helper.waitForOperationsFinished().then((_) {
242 List<AnalysisError> errors = helper.getTestErrors();
243 expect(errors, hasLength(1));
244 });
245 });
246 });
247
248 test('change on disk, normal', () {
249 AnalysisTestHelper helper = new AnalysisTestHelper();
250 helper.createSingleFileProject('library A;');
251 return helper.waitForOperationsFinished().then((_) {
252 // There should be no errors
253 expect(helper.getTestErrors(), hasLength(0));
254 // Change file on disk, adding a syntax error.
255 helper.resourceProvider.modifyFile(helper.testFile, 'library lib');
256 // There should be errors now.
257 return pumpEventQueue().then((_) {
258 return helper.waitForOperationsFinished().then((_) {
259 expect(helper.getTestErrors(), hasLength(1));
260 });
261 });
262 });
263 });
264
265 test('change on disk, during override', () {
266 AnalysisTestHelper helper = new AnalysisTestHelper();
267 helper.createSingleFileProject('library A;');
268 return helper.waitForOperationsFinished().then((_) {
269 // update code
270 helper.sendContentChange({
271 CONTENT: 'library B;'
272 });
273 // There should be no errors
274 return helper.waitForOperationsFinished().then((_) {
275 expect(helper.getTestErrors(), hasLength(0));
276 // Change file on disk, adding a syntax error.
277 helper.resourceProvider.modifyFile(helper.testFile, 'library lib');
278 // There should still be no errors (file should not have been reread).
279 return helper.waitForOperationsFinished().then((_) {
280 expect(helper.getTestErrors(), hasLength(0));
281 // Send a content change with a null content param--file should be
282 // reread from disk.
283 helper.sendContentChange({
284 CONTENT: null
285 });
286 // There should be errors now.
287 return helper.waitForOperationsFinished().then((_) {
288 expect(helper.getTestErrors(), hasLength(1));
289 });
290 });
291 });
292 });
293 });
185 } 294 }
186 295
187 296
297 void test_setSubscriptions() {
298 test('before analysis', () {
299 AnalysisTestHelper helper = new AnalysisTestHelper();
300 // subscribe
301 helper.addAnalysisSubscriptionHighlights(helper.testFile);
302 // create project
303 helper.createSingleFileProject('int V = 42;');
304 // wait, there are highlight regions
305 helper.waitForOperationsFinished().then((_) {
306 var highlights = helper.getHighlights(helper.testFile);
307 expect(highlights, isNot(isEmpty));
308 });
309 });
310
311 test('after analysis', () {
312 AnalysisTestHelper helper = new AnalysisTestHelper();
313 // create project
314 helper.createSingleFileProject('int V = 42;');
315 // wait, no regions initially
316 return helper.waitForOperationsFinished().then((_) {
317 var highlights = helper.getHighlights(helper.testFile);
318 expect(highlights, isEmpty);
319 // subscribe
320 helper.addAnalysisSubscriptionHighlights(helper.testFile);
321 // wait, has regions
322 return helper.waitForOperationsFinished().then((_) {
323 var highlights = helper.getHighlights(helper.testFile);
324 expect(highlights, isNot(isEmpty));
325 });
326 });
327 });
328 }
329
330
188 int _getSafeInt(Map<String, Object> json, String key, int defaultValue) { 331 int _getSafeInt(Map<String, Object> json, String key, int defaultValue) {
189 Object value = json[key]; 332 Object value = json[key];
190 if (value is int) { 333 if (value is int) {
191 return value; 334 return value;
192 } 335 }
193 return defaultValue; 336 return defaultValue;
194 } 337 }
195 338
196 339
340 @ReflectiveTestCase()
341 class AnalysisDomainTest extends AbstractAnalysisTest {
342 Map<String, List<AnalysisError>> filesErrors = {};
343
344 void processNotification(Notification notification) {
345 if (notification.event == ANALYSIS_ERRORS) {
346 String file = notification.getParameter(FILE);
347 List<Map<String, Object>> errorMaps = notification.getParameter(ERRORS);
348 filesErrors[file] = errorMaps.map(jsonToAnalysisError).toList();
349 }
350 }
351
352 test_packageMapDependencies() {
353 // Prepare a source file that has errors because it refers to an unknown
354 // package.
355 String pkgFile = '/packages/pkgA/libA.dart';
356 resourceProvider.newFile(pkgFile, '''
357 library lib_a;
358 class A {}
359 ''');
360 addTestFile('''
361 import 'package:pkgA/libA.dart';
362 f(A a) {
363 }
364 ''');
365 String pkgDependency = posix.join(projectPath, 'package_dep');
366 resourceProvider.newFile(pkgDependency, 'contents');
367 packageMapProvider.dependencies.add(pkgDependency);
368 // Create project and wait for analysis
369 createProject();
370 return waitForTasksFinished().then((_) {
371 expect(filesErrors[testFile], isNot(isEmpty));
372 // Add the package to the package map and tickle the package dependency.
373 packageMapProvider.packageMap = {
374 'pkgA': [resourceProvider.getResource('/packages/pkgA')]
375 };
376 resourceProvider.modifyFile(pkgDependency, 'new contents');
377 // Let the server time to notice the file has changed, then let
378 // analysis omplete. There should now be no error.
379 return pumpEventQueue().then((_) => waitForTasksFinished()).then((_) {
380 expect(filesErrors[testFile], isEmpty);
381 });
382 });
383 }
384
385 test_setRoots_packages() {
386 // prepare package
387 String pkgFile = '/packages/pkgA/libA.dart';
388 resourceProvider.newFile(pkgFile, '''
389 library lib_a;
390 class A {}
391 ''');
392 packageMapProvider.packageMap['pkgA'] = [resourceProvider.getResource(
393 '/packages/pkgA')];
394 addTestFile('''
395 import 'package:pkgA/libA.dart';
396 main(A a) {
397 }
398 ''');
399 // create project and wait for analysis
400 createProject();
401 return waitForTasksFinished().then((_) {
402 // if 'package:pkgA/libA.dart' was resolved, then there are no errors
403 expect(filesErrors[testFile], isEmpty);
404 // packages file also was resolved
405 expect(filesErrors[pkgFile], isEmpty);
406 });
407 }
408 }
409
410 class AnalysisError {
411 final String errorCode;
412 final String severity;
413 final String type;
414 final Location location;
415 final String message;
416 final String correction;
417 AnalysisError(this.errorCode, this.severity, this.type, this.location,
418 this.message, this.correction);
419
420 @override
421 String toString() {
422 return 'AnalysisError(location=$location message=$message); '
423 'errorCode=$errorCode; severity=$separator type=$type';
424 }
425 }
426
427
197 /** 428 /**
198 * A helper to test 'analysis.*' requests. 429 * A helper to test 'analysis.*' requests.
199 */ 430 */
200 class AnalysisTestHelper { 431 class AnalysisTestHelper {
201 MockServerChannel serverChannel; 432 MockServerChannel serverChannel;
202 MemoryResourceProvider resourceProvider; 433 MemoryResourceProvider resourceProvider;
203 AnalysisServer server; 434 AnalysisServer server;
204 AnalysisDomainHandler handler; 435 AnalysisDomainHandler handler;
205 436
206 Map<String, List<String>> analysisSubscriptions = {}; 437 Map<String, List<String>> analysisSubscriptions = {};
(...skipping 25 matching lines...) Expand all
232 String file = notification.getParameter(FILE); 463 String file = notification.getParameter(FILE);
233 filesHighlights[file] = notification.getParameter(REGIONS); 464 filesHighlights[file] = notification.getParameter(REGIONS);
234 } 465 }
235 if (notification.event == ANALYSIS_NAVIGATION) { 466 if (notification.event == ANALYSIS_NAVIGATION) {
236 String file = notification.getParameter(FILE); 467 String file = notification.getParameter(FILE);
237 filesNavigation[file] = notification.getParameter(REGIONS); 468 filesNavigation[file] = notification.getParameter(REGIONS);
238 } 469 }
239 }); 470 });
240 } 471 }
241 472
242 void addAnalysisSubscriptionHighlights(String file) {
243 addAnalysisSubscription(AnalysisService.HIGHLIGHTS, file);
244 }
245
246 void addAnalysisSubscriptionNavigation(String file) {
247 addAnalysisSubscription(AnalysisService.NAVIGATION, file);
248 }
249
250 void addAnalysisSubscription(AnalysisService service, String file) { 473 void addAnalysisSubscription(AnalysisService service, String file) {
251 // add file to subscription 474 // add file to subscription
252 var files = analysisSubscriptions[service.name]; 475 var files = analysisSubscriptions[service.name];
253 if (files == null) { 476 if (files == null) {
254 files = <String>[]; 477 files = <String>[];
255 analysisSubscriptions[service.name] = files; 478 analysisSubscriptions[service.name] = files;
256 } 479 }
257 files.add(file); 480 files.add(file);
258 // set subscriptions 481 // set subscriptions
259 Request request = new Request('0', ANALYSIS_SET_SUBSCRIPTIONS); 482 Request request = new Request('0', ANALYSIS_SET_SUBSCRIPTIONS);
260 request.setParameter(SUBSCRIPTIONS, analysisSubscriptions); 483 request.setParameter(SUBSCRIPTIONS, analysisSubscriptions);
261 handleSuccessfulRequest(request); 484 handleSuccessfulRequest(request);
262 } 485 }
263 486
264 /** 487 void addAnalysisSubscriptionHighlights(String file) {
265 * Returns a [Future] that completes when this this helper finished all its 488 addAnalysisSubscription(AnalysisService.HIGHLIGHTS, file);
266 * scheduled tasks. 489 }
267 */ 490
268 Future waitForOperationsFinished() { 491 void addAnalysisSubscriptionNavigation(String file) {
269 return waitForServerOperationsPerformed(server); 492 addAnalysisSubscription(AnalysisService.NAVIGATION, file);
270 } 493 }
271 494
272 /** 495 /**
496 * Creates an empty project `/project`.
497 */
498 void createEmptyProject() {
499 resourceProvider.newFolder('/project');
500 Request request = new Request('0', ANALYSIS_SET_ANALYSIS_ROOTS);
501 request.setParameter(INCLUDED, ['/project']);
502 request.setParameter(EXCLUDED, []);
503 handleSuccessfulRequest(request);
504 }
505
506 /**
507 * Creates a project with a single Dart file `/project/bin/test.dart` with
508 * the given [code].
509 */
510 void createSingleFileProject(code) {
511 this.testCode = _getCodeString(code);
512 resourceProvider.newFolder('/project');
513 resourceProvider.newFile(testFile, testCode);
514 Request request = new Request('0', ANALYSIS_SET_ANALYSIS_ROOTS);
515 request.setParameter(INCLUDED, ['/project']);
516 request.setParameter(EXCLUDED, []);
517 handleSuccessfulRequest(request);
518 }
519
520 /**
273 * Returns the offset of [search] in [testCode]. 521 * Returns the offset of [search] in [testCode].
274 * Fails if not found. 522 * Fails if not found.
275 */ 523 */
276 int findOffset(String search) { 524 int findOffset(String search) {
277 int offset = testCode.indexOf(search); 525 int offset = testCode.indexOf(search);
278 expect(offset, isNot(-1)); 526 expect(offset, isNot(-1));
279 return offset; 527 return offset;
280 } 528 }
281 529
282 /** 530 /**
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
333 581
334 /** 582 /**
335 * Returns navigation information recorded for the given [testFile]. 583 * Returns navigation information recorded for the given [testFile].
336 * May be empty, but not `null`. 584 * May be empty, but not `null`.
337 */ 585 */
338 List<Map<String, Object>> getTestNavigation() { 586 List<Map<String, Object>> getTestNavigation() {
339 return getNavigation(testFile); 587 return getNavigation(testFile);
340 } 588 }
341 589
342 /** 590 /**
343 * Creates an empty project `/project`. 591 * Validates that the given [request] is handled successfully.
344 */ 592 */
345 void createEmptyProject() { 593 void handleSuccessfulRequest(Request request) {
346 resourceProvider.newFolder('/project'); 594 Response response = handler.handleRequest(request);
347 Request request = new Request('0', ANALYSIS_SET_ANALYSIS_ROOTS); 595 expect(response, isResponseSuccess('0'));
348 request.setParameter(INCLUDED, ['/project']); 596 }
349 request.setParameter(EXCLUDED, []); 597
598 /**
599 * Send an `updateContent` request for [testFile].
600 */
601 void sendContentChange(Map contentChange) {
602 Request request = new Request('0', ANALYSIS_UPDATE_CONTENT);
603 request.setParameter('files', {
604 testFile: contentChange
605 });
350 handleSuccessfulRequest(request); 606 handleSuccessfulRequest(request);
351 } 607 }
352 608
353 /**
354 * Creates a project with a single Dart file `/project/bin/test.dart` with
355 * the given [code].
356 */
357 void createSingleFileProject(code) {
358 this.testCode = _getCodeString(code);
359 resourceProvider.newFolder('/project');
360 resourceProvider.newFile(testFile, testCode);
361 Request request = new Request('0', ANALYSIS_SET_ANALYSIS_ROOTS);
362 request.setParameter(INCLUDED, ['/project']);
363 request.setParameter(EXCLUDED, []);
364 handleSuccessfulRequest(request);
365 }
366
367 String setFileContent(String path, String content) { 609 String setFileContent(String path, String content) {
368 resourceProvider.newFile(path, content); 610 resourceProvider.newFile(path, content);
369 return path; 611 return path;
370 } 612 }
371 613
372 /** 614 /**
373 * Validates that the given [request] is handled successfully.
374 */
375 void handleSuccessfulRequest(Request request) {
376 Response response = handler.handleRequest(request);
377 expect(response, isResponseSuccess('0'));
378 }
379
380 /**
381 * Stops the associated server. 615 * Stops the associated server.
382 */ 616 */
383 void stopServer() { 617 void stopServer() {
384 server.done(); 618 server.done();
385 } 619 }
386 620
387 /** 621 /**
388 * Send an `updateContent` request for [testFile]. 622 * Returns a [Future] that completes when this this helper finished all its
623 * scheduled tasks.
389 */ 624 */
390 void sendContentChange(Map contentChange) { 625 Future waitForOperationsFinished() {
391 Request request = new Request('0', ANALYSIS_UPDATE_CONTENT); 626 return waitForServerOperationsPerformed(server);
392 request.setParameter('files', {
393 testFile: contentChange
394 });
395 handleSuccessfulRequest(request);
396 } 627 }
397 628
398 static String _getCodeString(code) { 629 static String _getCodeString(code) {
399 if (code is List<String>) { 630 if (code is List<String>) {
400 code = code.join('\n'); 631 code = code.join('\n');
401 } 632 }
402 return code as String; 633 return code as String;
403 } 634 }
404 } 635 }
405
406
407 testNotificationErrors() {
408 AnalysisTestHelper helper;
409
410 setUp(() {
411 helper = new AnalysisTestHelper();
412 });
413
414 test('ParserErrorCode', () {
415 helper.createSingleFileProject('library lib');
416 return helper.waitForOperationsFinished().then((_) {
417 List<AnalysisError> errors = helper.getTestErrors();
418 expect(errors, hasLength(1));
419 AnalysisError error = errors[0];
420 expect(error.location.file, '/project/bin/test.dart');
421 expect(error.location.offset, isPositive);
422 expect(error.location.length, isNonNegative);
423 expect(error.errorCode, 'ParserErrorCode.EXPECTED_TOKEN');
424 expect(error.severity, 'ERROR');
425 expect(error.type, 'SYNTACTIC_ERROR');
426 expect(error.message, isNotNull);
427 });
428 });
429
430 test('StaticWarningCode', () {
431 helper.createSingleFileProject(['main() {', ' print(unknown);', '}']);
432 return helper.waitForOperationsFinished().then((_) {
433 List<AnalysisError> errors = helper.getTestErrors();
434 expect(errors, hasLength(1));
435 AnalysisError error = errors[0];
436 expect(error.errorCode, 'StaticWarningCode.UNDEFINED_IDENTIFIER');
437 });
438 });
439 }
440
441
442 testUpdateContent() {
443 test('full content', () {
444 AnalysisTestHelper helper = new AnalysisTestHelper();
445 helper.createSingleFileProject('// empty');
446 return helper.waitForOperationsFinished().then((_) {
447 // no errors initially
448 List<AnalysisError> errors = helper.getTestErrors();
449 expect(errors, isEmpty);
450 // update code
451 helper.sendContentChange({
452 CONTENT: 'library lib'
453 });
454 // wait, there is an error
455 return helper.waitForOperationsFinished().then((_) {
456 List<AnalysisError> errors = helper.getTestErrors();
457 expect(errors, hasLength(1));
458 });
459 });
460 });
461
462 test('incremental', () {
463 AnalysisTestHelper helper = new AnalysisTestHelper();
464 helper.createSingleFileProject('library A;');
465 return helper.waitForOperationsFinished().then((_) {
466 // no errors initially
467 List<AnalysisError> errors = helper.getTestErrors();
468 expect(errors, isEmpty);
469 // update code
470 helper.sendContentChange({
471 CONTENT: 'library lib',
472 OFFSET: 'library '.length,
473 OLD_LENGTH: 'A;'.length,
474 NEW_LENGTH: 'lib'.length,
475 });
476 // wait, there is an error
477 return helper.waitForOperationsFinished().then((_) {
478 List<AnalysisError> errors = helper.getTestErrors();
479 expect(errors, hasLength(1));
480 });
481 });
482 });
483
484 test('change on disk, normal', () {
485 AnalysisTestHelper helper = new AnalysisTestHelper();
486 helper.createSingleFileProject('library A;');
487 return helper.waitForOperationsFinished().then((_) {
488 // There should be no errors
489 expect(helper.getTestErrors(), hasLength(0));
490 // Change file on disk, adding a syntax error.
491 helper.resourceProvider.modifyFile(helper.testFile, 'library lib');
492 // There should be errors now.
493 return pumpEventQueue().then((_) {
494 return helper.waitForOperationsFinished().then((_) {
495 expect(helper.getTestErrors(), hasLength(1));
496 });
497 });
498 });
499 });
500
501 test('change on disk, during override', () {
502 AnalysisTestHelper helper = new AnalysisTestHelper();
503 helper.createSingleFileProject('library A;');
504 return helper.waitForOperationsFinished().then((_) {
505 // update code
506 helper.sendContentChange({
507 CONTENT: 'library B;'
508 });
509 // There should be no errors
510 return helper.waitForOperationsFinished().then((_) {
511 expect(helper.getTestErrors(), hasLength(0));
512 // Change file on disk, adding a syntax error.
513 helper.resourceProvider.modifyFile(helper.testFile, 'library lib');
514 // There should still be no errors (file should not have been reread).
515 return helper.waitForOperationsFinished().then((_) {
516 expect(helper.getTestErrors(), hasLength(0));
517 // Send a content change with a null content param--file should be
518 // reread from disk.
519 helper.sendContentChange({
520 CONTENT: null
521 });
522 // There should be errors now.
523 return helper.waitForOperationsFinished().then((_) {
524 expect(helper.getTestErrors(), hasLength(1));
525 });
526 });
527 });
528 });
529 });
530 }
531
532 void test_setSubscriptions() {
533 test('before analysis', () {
534 AnalysisTestHelper helper = new AnalysisTestHelper();
535 // subscribe
536 helper.addAnalysisSubscriptionHighlights(helper.testFile);
537 // create project
538 helper.createSingleFileProject('int V = 42;');
539 // wait, there are highlight regions
540 helper.waitForOperationsFinished().then((_) {
541 var highlights = helper.getHighlights(helper.testFile);
542 expect(highlights, isNot(isEmpty));
543 });
544 });
545
546 test('after analysis', () {
547 AnalysisTestHelper helper = new AnalysisTestHelper();
548 // create project
549 helper.createSingleFileProject('int V = 42;');
550 // wait, no regions initially
551 return helper.waitForOperationsFinished().then((_) {
552 var highlights = helper.getHighlights(helper.testFile);
553 expect(highlights, isEmpty);
554 // subscribe
555 helper.addAnalysisSubscriptionHighlights(helper.testFile);
556 // wait, has regions
557 return helper.waitForOperationsFinished().then((_) {
558 var highlights = helper.getHighlights(helper.testFile);
559 expect(highlights, isNot(isEmpty));
560 });
561 });
562 });
563 }
564
565
566 @ReflectiveTestCase()
567 class AnalysisDomainTest extends AbstractAnalysisTest {
568 Map<String, List<AnalysisError>> filesErrors = {};
569
570 void processNotification(Notification notification) {
571 if (notification.event == ANALYSIS_ERRORS) {
572 String file = notification.getParameter(FILE);
573 List<Map<String, Object>> errorMaps = notification.getParameter(ERRORS);
574 filesErrors[file] = errorMaps.map(jsonToAnalysisError).toList();
575 }
576 }
577
578 test_setRoots_packages() {
579 // prepare package
580 String pkgFile = '/packages/pkgA/libA.dart';
581 resourceProvider.newFile(pkgFile, '''
582 library lib_a;
583 class A {}
584 ''');
585 packageMapProvider.packageMap['pkgA'] = [resourceProvider.getResource(
586 '/packages/pkgA')];
587 addTestFile('''
588 import 'package:pkgA/libA.dart';
589 main(A a) {
590 }
591 ''');
592 // create project and wait for analysis
593 createProject();
594 return waitForTasksFinished().then((_) {
595 // if 'package:pkgA/libA.dart' was resolved, then there are no errors
596 expect(filesErrors[testFile], isEmpty);
597 // packages file also was resolved
598 expect(filesErrors[pkgFile], isEmpty);
599 });
600 }
601
602 test_packageMapDependencies() {
603 // Prepare a source file that has errors because it refers to an unknown
604 // package.
605 String pkgFile = '/packages/pkgA/libA.dart';
606 resourceProvider.newFile(pkgFile, '''
607 library lib_a;
608 class A {}
609 ''');
610 addTestFile('''
611 import 'package:pkgA/libA.dart';
612 f(A a) {
613 }
614 ''');
615 String pkgDependency = posix.join(projectPath, 'package_dep');
616 resourceProvider.newFile(pkgDependency, 'contents');
617 packageMapProvider.dependencies.add(pkgDependency);
618 // Create project and wait for analysis
619 createProject();
620 return waitForTasksFinished().then((_) {
621 expect(filesErrors[testFile], isNot(isEmpty));
622 // Add the package to the package map and tickle the package dependency.
623 packageMapProvider.packageMap = {
624 'pkgA': [resourceProvider.getResource('/packages/pkgA')]
625 };
626 resourceProvider.modifyFile(pkgDependency, 'new contents');
627 // Let the server time to notice the file has changed, then let
628 // analysis omplete. There should now be no error.
629 return pumpEventQueue().then((_) => waitForTasksFinished()).then((_) {
630 expect(filesErrors[testFile], isEmpty);
631 });
632 });
633 }
634 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698