| OLD | NEW |
| 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.analysis_server; | 5 library test.analysis_server; |
| 6 | 6 |
| 7 import 'dart:async'; |
| 8 |
| 7 import 'package:analysis_server/src/analysis_server.dart'; | 9 import 'package:analysis_server/src/analysis_server.dart'; |
| 8 import 'package:analysis_server/src/constants.dart'; | 10 import 'package:analysis_server/src/constants.dart'; |
| 9 import 'package:analysis_server/src/domain_server.dart'; | 11 import 'package:analysis_server/src/domain_server.dart'; |
| 10 import 'package:analysis_server/src/operation/operation.dart'; | 12 import 'package:analysis_server/src/operation/operation.dart'; |
| 11 import 'package:analysis_server/src/protocol.dart'; | 13 import 'package:analysis_server/src/protocol.dart'; |
| 12 import 'package:analyzer/file_system/memory_file_system.dart'; | 14 import 'package:analyzer/file_system/memory_file_system.dart'; |
| 13 import 'package:analyzer/instrumentation/instrumentation.dart'; | 15 import 'package:analyzer/instrumentation/instrumentation.dart'; |
| 14 import 'package:analyzer/src/generated/engine.dart'; | 16 import 'package:analyzer/src/generated/engine.dart'; |
| 15 import 'package:analyzer/src/generated/java_engine.dart'; | 17 import 'package:analyzer/src/generated/java_engine.dart'; |
| 16 import 'package:analyzer/src/generated/source.dart'; | 18 import 'package:analyzer/src/generated/source.dart'; |
| 17 import 'package:typed_mock/typed_mock.dart'; | 19 import 'package:typed_mock/typed_mock.dart'; |
| 18 import 'package:unittest/unittest.dart'; | 20 import 'package:unittest/unittest.dart'; |
| 19 | 21 |
| 20 import 'mock_sdk.dart'; | 22 import 'mock_sdk.dart'; |
| 21 import 'mocks.dart'; | 23 import 'mocks.dart'; |
| 24 import 'reflective_tests.dart'; |
| 22 | 25 |
| 23 main() { | 26 main() { |
| 24 group('AnalysisServer', () { | 27 groupSep = ' | '; |
| 25 test('server.status notifications', () { | 28 runReflectiveTests(AnalysisServerTest); |
| 26 AnalysisServerTestHelper helper = new AnalysisServerTestHelper(); | |
| 27 MockAnalysisContext context = new MockAnalysisContext('context'); | |
| 28 MockSource source = new MockSource('source'); | |
| 29 when(source.fullName).thenReturn('foo.dart'); | |
| 30 when(source.isInSystemLibrary).thenReturn(false); | |
| 31 ChangeNoticeImpl notice = new ChangeNoticeImpl(source); | |
| 32 notice.setErrors([], new LineInfo([0])); | |
| 33 AnalysisResult firstResult = new AnalysisResult([notice], 0, '', 0); | |
| 34 AnalysisResult lastResult = new AnalysisResult(null, 1, '', 1); | |
| 35 when( | |
| 36 context.performAnalysisTask).thenReturnList( | |
| 37 [firstResult, firstResult, firstResult, lastResult]); | |
| 38 helper.server.serverServices.add(ServerService.STATUS); | |
| 39 helper.server.schedulePerformAnalysisOperation(context); | |
| 40 // Pump the event queue to make sure the server has finished any | |
| 41 // analysis. | |
| 42 return pumpEventQueue().then((_) { | |
| 43 List<Notification> notifications = helper.channel.notificationsReceived; | |
| 44 expect(notifications, isNotEmpty); | |
| 45 // expect at least one notification indicating analysis is in progress | |
| 46 expect(notifications.any((Notification notification) { | |
| 47 if (notification.event == SERVER_STATUS) { | |
| 48 var params = new ServerStatusParams.fromNotification(notification); | |
| 49 return params.analysis.isAnalyzing; | |
| 50 } | |
| 51 return false; | |
| 52 }), isTrue); | |
| 53 // the last notification should indicate that analysis is complete | |
| 54 Notification notification = notifications[notifications.length - 1]; | |
| 55 var params = new ServerStatusParams.fromNotification(notification); | |
| 56 expect(params.analysis.isAnalyzing, isFalse); | |
| 57 }); | |
| 58 }); | |
| 59 | |
| 60 test('echo', () { | |
| 61 AnalysisServerTestHelper helper = new AnalysisServerTestHelper(); | |
| 62 helper.server.handlers = [new EchoHandler()]; | |
| 63 var request = new Request('my22', 'echo'); | |
| 64 return helper.channel.sendRequest(request).then((Response response) { | |
| 65 expect(response.id, equals('my22')); | |
| 66 expect(response.error, isNull); | |
| 67 }); | |
| 68 }); | |
| 69 | |
| 70 test('shutdown', () { | |
| 71 AnalysisServerTestHelper helper = new AnalysisServerTestHelper(); | |
| 72 helper.server.handlers = [new ServerDomainHandler(helper.server)]; | |
| 73 var request = new Request('my28', SERVER_SHUTDOWN); | |
| 74 return helper.channel.sendRequest(request).then((Response response) { | |
| 75 expect(response.id, equals('my28')); | |
| 76 expect(response.error, isNull); | |
| 77 }); | |
| 78 }); | |
| 79 | |
| 80 test('unknownRequest', () { | |
| 81 AnalysisServerTestHelper helper = new AnalysisServerTestHelper(); | |
| 82 helper.server.handlers = [new EchoHandler()]; | |
| 83 var request = new Request('my22', 'randomRequest'); | |
| 84 return helper.channel.sendRequest(request).then((Response response) { | |
| 85 expect(response.id, equals('my22')); | |
| 86 expect(response.error, isNotNull); | |
| 87 }); | |
| 88 }); | |
| 89 | |
| 90 test('rethrow exceptions', () { | |
| 91 AnalysisServerTestHelper helper = new AnalysisServerTestHelper(); | |
| 92 Exception exceptionToThrow = new Exception('test exception'); | |
| 93 MockServerOperation operation = | |
| 94 new MockServerOperation(ServerOperationPriority.ANALYSIS, (_) { | |
| 95 throw exceptionToThrow; | |
| 96 }); | |
| 97 helper.server.operationQueue.add(operation); | |
| 98 helper.server.performOperationPending = true; | |
| 99 try { | |
| 100 helper.server.performOperation(); | |
| 101 fail('exception not rethrown'); | |
| 102 } on AnalysisException catch (exception) { | |
| 103 expect(exception.cause.exception, equals(exceptionToThrow)); | |
| 104 } | |
| 105 }); | |
| 106 | |
| 107 test('contexts changed event', () { | |
| 108 AnalysisServerTestHelper helper = new AnalysisServerTestHelper(); | |
| 109 helper.resourceProvider.newFolder('/foo'); | |
| 110 | |
| 111 bool wasAdded = false; | |
| 112 bool wasChanged = false; | |
| 113 bool wasRemoved = false; | |
| 114 helper.server.onContextsChanged.listen((ContextsChangedEvent event) { | |
| 115 wasAdded = event.added.length == 1; | |
| 116 if (wasAdded) { | |
| 117 expect(event.added[0], isNotNull); | |
| 118 } | |
| 119 wasChanged = event.changed.length == 1; | |
| 120 if (wasChanged) { | |
| 121 expect(event.changed[0], isNotNull); | |
| 122 } | |
| 123 wasRemoved = event.removed.length == 1; | |
| 124 if (wasRemoved) { | |
| 125 expect(event.removed[0], isNotNull); | |
| 126 } | |
| 127 }); | |
| 128 | |
| 129 helper.server.setAnalysisRoots('0', ['/foo'], [], {}); | |
| 130 return pumpEventQueue().then((_) { | |
| 131 expect(wasAdded, isTrue); | |
| 132 expect(wasChanged, isFalse); | |
| 133 expect(wasRemoved, isFalse); | |
| 134 | |
| 135 wasAdded = false; | |
| 136 wasChanged = false; | |
| 137 wasRemoved = false; | |
| 138 helper.server.setAnalysisRoots('0', ['/foo'], [], { | |
| 139 '/foo': '/bar' | |
| 140 }); | |
| 141 return pumpEventQueue(); | |
| 142 }).then((_) { | |
| 143 expect(wasAdded, isFalse); | |
| 144 expect(wasChanged, isTrue); | |
| 145 expect(wasRemoved, isFalse); | |
| 146 | |
| 147 wasAdded = false; | |
| 148 wasChanged = false; | |
| 149 wasRemoved = false; | |
| 150 helper.server.setAnalysisRoots('0', [], [], {}); | |
| 151 return pumpEventQueue(); | |
| 152 }).then((_) { | |
| 153 expect(wasAdded, isFalse); | |
| 154 expect(wasChanged, isFalse); | |
| 155 expect(wasRemoved, isTrue); | |
| 156 }); | |
| 157 }); | |
| 158 | |
| 159 test('priority sources changed event', () { | |
| 160 AnalysisServerTestHelper helper = new AnalysisServerTestHelper(); | |
| 161 helper.resourceProvider.newFolder('/foo'); | |
| 162 | |
| 163 int eventCount = 0; | |
| 164 Source firstSource = null; | |
| 165 helper.server.onPriorityChange.listen((PriorityChangeEvent event) { | |
| 166 ++eventCount; | |
| 167 firstSource = event.firstSource; | |
| 168 }); | |
| 169 | |
| 170 helper.server.setAnalysisRoots('0', ['/foo'], [], {}); | |
| 171 return pumpEventQueue().then((_) { | |
| 172 expect(eventCount, 0); | |
| 173 | |
| 174 helper.server.setPriorityFiles('1', ['/foo/bar.dart']); | |
| 175 return pumpEventQueue(); | |
| 176 }).then((_) { | |
| 177 expect(eventCount, 1); | |
| 178 expect(firstSource.fullName, '/foo/bar.dart'); | |
| 179 | |
| 180 helper.server.setPriorityFiles('2', ['/foo/b1.dart', '/foo/b2.dart']); | |
| 181 return pumpEventQueue(); | |
| 182 }).then((_) { | |
| 183 expect(eventCount, 2); | |
| 184 expect(firstSource.fullName, '/foo/b1.dart'); | |
| 185 | |
| 186 helper.server.setPriorityFiles('17', []); | |
| 187 return pumpEventQueue(); | |
| 188 }).then((_) { | |
| 189 expect(eventCount, 3); | |
| 190 expect(firstSource, isNull); | |
| 191 }); | |
| 192 }); | |
| 193 }); | |
| 194 } | 29 } |
| 195 | 30 |
| 196 class AnalysisServerTestHelper { | 31 @ReflectiveTestCase() |
| 32 class AnalysisServerTest { |
| 197 MockServerChannel channel; | 33 MockServerChannel channel; |
| 198 AnalysisServer server; | 34 AnalysisServer server; |
| 199 MemoryResourceProvider resourceProvider; | 35 MemoryResourceProvider resourceProvider; |
| 200 | 36 |
| 201 AnalysisServerTestHelper({bool rethrowExceptions: true}) { | 37 void setUp() { |
| 202 channel = new MockServerChannel(); | 38 channel = new MockServerChannel(); |
| 203 resourceProvider = new MemoryResourceProvider(); | 39 resourceProvider = new MemoryResourceProvider(); |
| 204 server = new AnalysisServer( | 40 server = new AnalysisServer( |
| 205 channel, | 41 channel, |
| 206 resourceProvider, | 42 resourceProvider, |
| 207 new MockPackageMapProvider(), | 43 new MockPackageMapProvider(), |
| 208 null, | 44 null, |
| 209 new AnalysisServerOptions(), | 45 new AnalysisServerOptions(), |
| 210 new MockSdk(), | 46 new MockSdk(), |
| 211 InstrumentationService.NULL_SERVICE, | 47 InstrumentationService.NULL_SERVICE, |
| 212 rethrowExceptions: rethrowExceptions); | 48 rethrowExceptions: true); |
| 49 } |
| 50 |
| 51 Future test_contextsChangedEvent() { |
| 52 resourceProvider.newFolder('/foo'); |
| 53 |
| 54 bool wasAdded = false; |
| 55 bool wasChanged = false; |
| 56 bool wasRemoved = false; |
| 57 server.onContextsChanged.listen((ContextsChangedEvent event) { |
| 58 wasAdded = event.added.length == 1; |
| 59 if (wasAdded) { |
| 60 expect(event.added[0], isNotNull); |
| 61 } |
| 62 wasChanged = event.changed.length == 1; |
| 63 if (wasChanged) { |
| 64 expect(event.changed[0], isNotNull); |
| 65 } |
| 66 wasRemoved = event.removed.length == 1; |
| 67 if (wasRemoved) { |
| 68 expect(event.removed[0], isNotNull); |
| 69 } |
| 70 }); |
| 71 |
| 72 server.setAnalysisRoots('0', ['/foo'], [], {}); |
| 73 return pumpEventQueue().then((_) { |
| 74 expect(wasAdded, isTrue); |
| 75 expect(wasChanged, isFalse); |
| 76 expect(wasRemoved, isFalse); |
| 77 |
| 78 wasAdded = false; |
| 79 wasChanged = false; |
| 80 wasRemoved = false; |
| 81 server.setAnalysisRoots('0', ['/foo'], [], { |
| 82 '/foo': '/bar' |
| 83 }); |
| 84 return pumpEventQueue(); |
| 85 }).then((_) { |
| 86 expect(wasAdded, isFalse); |
| 87 expect(wasChanged, isTrue); |
| 88 expect(wasRemoved, isFalse); |
| 89 |
| 90 wasAdded = false; |
| 91 wasChanged = false; |
| 92 wasRemoved = false; |
| 93 server.setAnalysisRoots('0', [], [], {}); |
| 94 return pumpEventQueue(); |
| 95 }).then((_) { |
| 96 expect(wasAdded, isFalse); |
| 97 expect(wasChanged, isFalse); |
| 98 expect(wasRemoved, isTrue); |
| 99 }); |
| 100 } |
| 101 |
| 102 Future test_echo() { |
| 103 server.handlers = [new EchoHandler()]; |
| 104 var request = new Request('my22', 'echo'); |
| 105 return channel.sendRequest(request).then((Response response) { |
| 106 expect(response.id, equals('my22')); |
| 107 expect(response.error, isNull); |
| 108 }); |
| 109 } |
| 110 |
| 111 Future test_prioritySourcesChangedEvent() { |
| 112 resourceProvider.newFolder('/foo'); |
| 113 |
| 114 int eventCount = 0; |
| 115 Source firstSource = null; |
| 116 server.onPriorityChange.listen((PriorityChangeEvent event) { |
| 117 ++eventCount; |
| 118 firstSource = event.firstSource; |
| 119 }); |
| 120 |
| 121 server.setAnalysisRoots('0', ['/foo'], [], {}); |
| 122 return pumpEventQueue().then((_) { |
| 123 expect(eventCount, 0); |
| 124 |
| 125 server.setPriorityFiles('1', ['/foo/bar.dart']); |
| 126 return pumpEventQueue(); |
| 127 }).then((_) { |
| 128 expect(eventCount, 1); |
| 129 expect(firstSource.fullName, '/foo/bar.dart'); |
| 130 |
| 131 server.setPriorityFiles('2', ['/foo/b1.dart', '/foo/b2.dart']); |
| 132 return pumpEventQueue(); |
| 133 }).then((_) { |
| 134 expect(eventCount, 2); |
| 135 expect(firstSource.fullName, '/foo/b1.dart'); |
| 136 |
| 137 server.setPriorityFiles('17', []); |
| 138 return pumpEventQueue(); |
| 139 }).then((_) { |
| 140 expect(eventCount, 3); |
| 141 expect(firstSource, isNull); |
| 142 }); |
| 143 } |
| 144 |
| 145 void test_rethrowExceptions() { |
| 146 Exception exceptionToThrow = new Exception('test exception'); |
| 147 MockServerOperation operation = |
| 148 new MockServerOperation(ServerOperationPriority.ANALYSIS, (_) { |
| 149 throw exceptionToThrow; |
| 150 }); |
| 151 server.operationQueue.add(operation); |
| 152 server.performOperationPending = true; |
| 153 try { |
| 154 server.performOperation(); |
| 155 fail('exception not rethrown'); |
| 156 } on AnalysisException catch (exception) { |
| 157 expect(exception.cause.exception, equals(exceptionToThrow)); |
| 158 } |
| 159 } |
| 160 |
| 161 Future test_serverStatusNotifications() { |
| 162 MockAnalysisContext context = new MockAnalysisContext('context'); |
| 163 MockSource source = new MockSource('source'); |
| 164 when(source.fullName).thenReturn('foo.dart'); |
| 165 when(source.isInSystemLibrary).thenReturn(false); |
| 166 ChangeNoticeImpl notice = new ChangeNoticeImpl(source); |
| 167 notice.setErrors([], new LineInfo([0])); |
| 168 AnalysisResult firstResult = new AnalysisResult([notice], 0, '', 0); |
| 169 AnalysisResult lastResult = new AnalysisResult(null, 1, '', 1); |
| 170 when( |
| 171 context.performAnalysisTask).thenReturnList( |
| 172 [firstResult, firstResult, firstResult, lastResult]); |
| 173 server.serverServices.add(ServerService.STATUS); |
| 174 server.schedulePerformAnalysisOperation(context); |
| 175 // Pump the event queue to make sure the server has finished any |
| 176 // analysis. |
| 177 return pumpEventQueue().then((_) { |
| 178 List<Notification> notifications = channel.notificationsReceived; |
| 179 expect(notifications, isNotEmpty); |
| 180 // expect at least one notification indicating analysis is in progress |
| 181 expect(notifications.any((Notification notification) { |
| 182 if (notification.event == SERVER_STATUS) { |
| 183 var params = new ServerStatusParams.fromNotification(notification); |
| 184 return params.analysis.isAnalyzing; |
| 185 } |
| 186 return false; |
| 187 }), isTrue); |
| 188 // the last notification should indicate that analysis is complete |
| 189 Notification notification = notifications[notifications.length - 1]; |
| 190 var params = new ServerStatusParams.fromNotification(notification); |
| 191 expect(params.analysis.isAnalyzing, isFalse); |
| 192 }); |
| 193 } |
| 194 |
| 195 Future test_shutdown() { |
| 196 server.handlers = [new ServerDomainHandler(server)]; |
| 197 var request = new Request('my28', SERVER_SHUTDOWN); |
| 198 return channel.sendRequest(request).then((Response response) { |
| 199 expect(response.id, equals('my28')); |
| 200 expect(response.error, isNull); |
| 201 }); |
| 202 } |
| 203 |
| 204 Future test_unknownRequest() { |
| 205 server.handlers = [new EchoHandler()]; |
| 206 var request = new Request('my22', 'randomRequest'); |
| 207 return channel.sendRequest(request).then((Response response) { |
| 208 expect(response.id, equals('my22')); |
| 209 expect(response.error, isNotNull); |
| 210 }); |
| 213 } | 211 } |
| 214 } | 212 } |
| 215 | 213 |
| 216 class EchoHandler implements RequestHandler { | 214 class EchoHandler implements RequestHandler { |
| 217 @override | 215 @override |
| 218 Response handleRequest(Request request) { | 216 Response handleRequest(Request request) { |
| 219 if (request.method == 'echo') { | 217 if (request.method == 'echo') { |
| 220 return new Response(request.id, result: { | 218 return new Response(request.id, result: { |
| 221 'echo': true | 219 'echo': true |
| 222 }); | 220 }); |
| 223 } | 221 } |
| 224 return null; | 222 return null; |
| 225 } | 223 } |
| 226 } | 224 } |
| OLD | NEW |