| 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'; | 7 import 'dart:async'; |
| 8 | 8 |
| 9 import 'package:analyzer/src/generated/engine.dart'; | 9 import 'package:analyzer/src/generated/engine.dart'; |
| 10 import 'package:analyzer/src/generated/error.dart'; | 10 import 'package:analyzer/src/generated/error.dart'; |
| 11 import 'package:analysis_server/src/analysis_server.dart'; | 11 import 'package:analysis_server/src/analysis_server.dart'; |
| 12 import 'package:analysis_server/src/constants.dart'; | 12 import 'package:analysis_server/src/constants.dart'; |
| 13 import 'package:analysis_server/src/domain_server.dart'; | 13 import 'package:analysis_server/src/domain_server.dart'; |
| 14 import 'package:analysis_server/src/protocol.dart'; | 14 import 'package:analysis_server/src/protocol.dart'; |
| 15 import 'package:analysis_server/src/resource.dart'; | 15 import 'package:analysis_server/src/resource.dart'; |
| 16 import 'package:mock/mock.dart'; | 16 import 'package:mock/mock.dart'; |
| 17 import 'package:unittest/unittest.dart'; | 17 import 'package:unittest/unittest.dart'; |
| 18 | 18 |
| 19 import 'mocks.dart'; | 19 import 'mocks.dart'; |
| 20 | 20 |
| 21 main() { | 21 class AnalysisServerTestHelper { |
| 22 group('AnalysisServer', () { | 22 MockServerChannel channel; |
| 23 setUp(AnalysisServerTest.setUp); | 23 AnalysisServer server; |
| 24 test('addContextToWorkQueue_twice', | 24 MockAnalysisLogger logger; |
| 25 AnalysisServerTest.addContextToWorkQueue_twice); | |
| 26 test('addContextToWorkQueue_whenNotRunning', | |
| 27 AnalysisServerTest.addContextToWorkQueue_whenNotRunning); | |
| 28 // TODO(scheglov) remove or move to the 'analysis' domain | |
| 29 // test('addContextToWorkQueue_whenRunning', | |
| 30 // AnalysisServerTest.addContextToWorkQueue_whenRunning); | |
| 31 // test('createContext', AnalysisServerTest.createContext); | |
| 32 test('echo', AnalysisServerTest.echo); | |
| 33 test('errorToJson_formattingApplied', | |
| 34 AnalysisServerTest.errorToJson_formattingApplied); | |
| 35 test('errorToJson_noCorrection', | |
| 36 AnalysisServerTest.errorToJson_noCorrection); | |
| 37 test('errorToJson_withCorrection', | |
| 38 AnalysisServerTest.errorToJson_withCorrection); | |
| 39 test('performTask_whenNotRunning', | |
| 40 AnalysisServerTest.performTask_whenNotRunning); | |
| 41 test('shutdown', AnalysisServerTest.shutdown); | |
| 42 test('unknownRequest', AnalysisServerTest.unknownRequest); | |
| 43 }); | |
| 44 } | |
| 45 | 25 |
| 46 class AnalysisServerTest { | 26 AnalysisServerTestHelper() { |
| 47 static MockServerChannel channel; | |
| 48 static AnalysisServer server; | |
| 49 static MockAnalysisLogger logger; | |
| 50 | |
| 51 static void setUp() { | |
| 52 channel = new MockServerChannel(); | 27 channel = new MockServerChannel(); |
| 53 server = new AnalysisServer(channel, PhysicalResourceProvider.INSTANCE); | 28 server = new AnalysisServer(channel, PhysicalResourceProvider.INSTANCE); |
| 54 logger = new MockAnalysisLogger(); | 29 logger = new MockAnalysisLogger(); |
| 55 AnalysisEngine.instance.logger = logger; | 30 AnalysisEngine.instance.logger = logger; |
| 56 } | 31 } |
| 57 | |
| 58 static Future addContextToWorkQueue_whenNotRunning() { | |
| 59 server.running = false; | |
| 60 MockAnalysisContext context = new MockAnalysisContext(); | |
| 61 server.addContextToWorkQueue(context); | |
| 62 // Pump the event queue to make sure the server doesn't try to do any | |
| 63 // analysis. | |
| 64 return pumpEventQueue(); | |
| 65 } | |
| 66 | |
| 67 // TODO(scheglov) remove after implementing "setAnalysisRoots" API | |
| 68 // static Future addContextToWorkQueue_whenRunning() { | |
| 69 // MockAnalysisContext context = new MockAnalysisContext(); | |
| 70 // server.addContextToWorkQueue(context); | |
| 71 // server.contextIdMap[context] = 'context-27'; | |
| 72 // MockSource source = new MockSource(); | |
| 73 // source.when(callsTo('get encoding')).alwaysReturn('foo.dart'); | |
| 74 // ChangeNoticeImpl changeNoticeImpl = new ChangeNoticeImpl(source); | |
| 75 // LineInfo lineInfo = new LineInfo([0]); | |
| 76 // AnalysisError analysisError = new AnalysisError.con1(source, | |
| 77 // CompileTimeErrorCode.CONST_CONSTRUCTOR_WITH_NON_CONST_SUPER, ['Foo']); | |
| 78 // changeNoticeImpl.setErrors([analysisError], lineInfo); | |
| 79 // context.when(callsTo('performAnalysisTask')).thenReturn( | |
| 80 // new AnalysisResult([changeNoticeImpl], 0, 'myClass', 0)); | |
| 81 // context.when(callsTo('performAnalysisTask')).thenReturn( | |
| 82 // new AnalysisResult(null, 0, null, 0)); | |
| 83 // return pumpEventQueue().then((_) { | |
| 84 // context.getLogs(callsTo('performAnalysisTask')).verify(happenedExactly(2
)); | |
| 85 // List<Notification> notifications = channel.notificationsReceived; | |
| 86 // expect(notifications, hasLength(4)); | |
| 87 // | |
| 88 // expect(notifications[0].event, equals('server.connected')); | |
| 89 // | |
| 90 // assertStatusNotification(notifications[1], true); | |
| 91 // | |
| 92 // expect(notifications[2].event, equals('context.errors')); | |
| 93 // expect(notifications[2].params['source'], equals('foo.dart')); | |
| 94 // expect(notifications[2].params['contextId'], equals('context-27')); | |
| 95 // List<AnalysisError> errors = notifications[2].params['errors']; | |
| 96 // expect(errors, hasLength(1)); | |
| 97 // expect(errors[0], equals(AnalysisServer.errorToJson(analysisError))); | |
| 98 // | |
| 99 // assertStatusNotification(notifications[3], false); | |
| 100 // }); | |
| 101 // } | |
| 102 // | |
| 103 // static void assertStatusNotification(Notification notification, bool expectA
nalyzing) { | |
| 104 // expect(notification.event, equals('server.status')); | |
| 105 // Map<String, Object> analysis = notification.params['analysis']; | |
| 106 // expect(analysis['analyzing'], expectAnalyzing); | |
| 107 // expect(analysis.containsKey('analysisTarget'), expectAnalyzing); | |
| 108 // if (expectAnalyzing) { | |
| 109 // var analysisTarget = analysis['analysisTarget']; | |
| 110 // expect((analysisTarget is String), isTrue); | |
| 111 // expect(analysisTarget.length > 0, isTrue); | |
| 112 // } | |
| 113 // } | |
| 114 | |
| 115 static Future addContextToWorkQueue_twice() { | |
| 116 // TODO(scheglov) remove after implementing "setAnalysisRoots" API | |
| 117 return new Future.value(); | |
| 118 // // The context should only be asked to perform its analysis task once. | |
| 119 // MockAnalysisContext context = new MockAnalysisContext(); | |
| 120 // server.addContextToWorkQueue(context); | |
| 121 // server.addContextToWorkQueue(context); | |
| 122 // context.when(callsTo('performAnalysisTask')).thenReturn( | |
| 123 // new AnalysisResult(null, 0, null, 0)); | |
| 124 // return pumpEventQueue().then((_) => | |
| 125 // context.getLogs(callsTo('performAnalysisTask')).verify(happenedExactly
(1))); | |
| 126 } | |
| 127 | |
| 128 // TODO(scheglov) remove or move to the 'analysis' domain | |
| 129 // static Future createContext() { | |
| 130 // server.handlers = [new ServerDomainHandler(server)]; | |
| 131 // var request = new Request('my27', ServerDomainHandler.CREATE_CONTEXT_METHO
D); | |
| 132 // request.setParameter(ServerDomainHandler.SDK_DIRECTORY_PARAM, sdkPath); | |
| 133 // request.setParameter(AnalysisServer.CONTEXT_ID_PARAM, 'ctx'); | |
| 134 // return channel.sendRequest(request) | |
| 135 // .then((Response response) { | |
| 136 // expect(response.id, equals('my27')); | |
| 137 // expect(response.error, isNull); | |
| 138 // }); | |
| 139 // } | |
| 140 | |
| 141 static Future echo() { | |
| 142 server.handlers = [new EchoHandler()]; | |
| 143 var request = new Request('my22', 'echo'); | |
| 144 return channel.sendRequest(request) | |
| 145 .then((Response response) { | |
| 146 expect(response.id, equals('my22')); | |
| 147 expect(response.error, isNull); | |
| 148 }); | |
| 149 } | |
| 150 | |
| 151 static void errorToJson_formattingApplied() { | |
| 152 MockSource source = new MockSource(); | |
| 153 source.when(callsTo('get encoding')).alwaysReturn('foo.dart'); | |
| 154 CompileTimeErrorCode errorCode = CompileTimeErrorCode.AMBIGUOUS_EXPORT; | |
| 155 AnalysisError analysisError = | |
| 156 new AnalysisError.con1(source, errorCode, ['foo', 'bar', 'baz']); | |
| 157 Map<String, Object> json = AnalysisServer.errorToJson(analysisError); | |
| 158 | |
| 159 expect(json['message'], | |
| 160 equals("The name 'foo' is defined in the libraries 'bar' and 'baz'")); | |
| 161 } | |
| 162 | |
| 163 static void errorToJson_noCorrection() { | |
| 164 MockSource source = new MockSource(); | |
| 165 source.when(callsTo('get fullName')).alwaysReturn('foo.dart'); | |
| 166 CompileTimeErrorCode errorCode = | |
| 167 CompileTimeErrorCode.CONST_CONSTRUCTOR_WITH_NON_CONST_SUPER; | |
| 168 AnalysisError analysisError = | |
| 169 new AnalysisError.con2(source, 10, 5, errorCode, ['Foo']); | |
| 170 Map<String, Object> json = AnalysisServer.errorToJson(analysisError); | |
| 171 expect(json, hasLength(5)); | |
| 172 expect(json['file'], equals('foo.dart')); | |
| 173 expect(json['errorCode'], 'CompileTimeErrorCode.CONST_CONSTRUCTOR_WITH_NON_C
ONST_SUPER'); | |
| 174 expect(json['offset'], equals(analysisError.offset)); | |
| 175 expect(json['length'], equals(analysisError.length)); | |
| 176 expect(json['message'], equals(errorCode.message.replaceAll('%s', 'Foo'))); | |
| 177 } | |
| 178 | |
| 179 static void errorToJson_withCorrection() { | |
| 180 MockSource source = new MockSource(); | |
| 181 source.when(callsTo('get encoding')).alwaysReturn('foo.dart'); | |
| 182 | |
| 183 // TODO(paulberry): in principle we should test an error or hint that uses | |
| 184 // %s formatting in its correction string. But no such errors or hints | |
| 185 // currently exist! | |
| 186 HintCode errorCode = HintCode.MISSING_RETURN; | |
| 187 | |
| 188 AnalysisError analysisError = | |
| 189 new AnalysisError.con2(source, 10, 5, errorCode, ['int']); | |
| 190 Map<String, Object> json = AnalysisServer.errorToJson(analysisError); | |
| 191 expect(json['correction'], equals(errorCode.correction)); | |
| 192 } | |
| 193 | |
| 194 static Future performTask_whenNotRunning() { | |
| 195 // If the server is shut down while there is analysis still pending, | |
| 196 // performTask() should notice that the server is no longer running and | |
| 197 // do no analysis. | |
| 198 MockAnalysisContext context = new MockAnalysisContext(); | |
| 199 server.addContextToWorkQueue(context); | |
| 200 server.running = false; | |
| 201 // Pump the event queue to make sure the server doesn't try to do any | |
| 202 // analysis. | |
| 203 return pumpEventQueue(); | |
| 204 } | |
| 205 | |
| 206 static Future shutdown() { | |
| 207 server.handlers = [new ServerDomainHandler(server)]; | |
| 208 var request = new Request('my28', METHOD_SHUTDOWN); | |
| 209 return channel.sendRequest(request) | |
| 210 .then((Response response) { | |
| 211 expect(response.id, equals('my28')); | |
| 212 expect(response.error, isNull); | |
| 213 }); | |
| 214 } | |
| 215 | |
| 216 static Future unknownRequest() { | |
| 217 server.handlers = [new EchoHandler()]; | |
| 218 var request = new Request('my22', 'randomRequest'); | |
| 219 return channel.sendRequest(request) | |
| 220 .then((Response response) { | |
| 221 expect(response.id, equals('my22')); | |
| 222 expect(response.error, isNotNull); | |
| 223 }); | |
| 224 } | |
| 225 } | 32 } |
| 226 | 33 |
| 34 main() { |
| 35 group('AnalysisServer', () { |
| 36 test('addContextToWorkQueue_whenNotRunning', () { |
| 37 AnalysisServerTestHelper helper = new AnalysisServerTestHelper(); |
| 38 helper.server.running = false; |
| 39 MockAnalysisContext context = new MockAnalysisContext(); |
| 40 helper.server.addContextToWorkQueue(context); |
| 41 // Pump the event queue to make sure the server doesn't try to do any |
| 42 // analysis. |
| 43 return pumpEventQueue(); |
| 44 }); |
| 45 |
| 46 test('echo', () { |
| 47 AnalysisServerTestHelper helper = new AnalysisServerTestHelper(); |
| 48 helper.server.handlers = [new EchoHandler()]; |
| 49 var request = new Request('my22', 'echo'); |
| 50 return helper.channel.sendRequest(request) |
| 51 .then((Response response) { |
| 52 expect(response.id, equals('my22')); |
| 53 expect(response.error, isNull); |
| 54 }); |
| 55 }); |
| 56 |
| 57 test('errorToJson_formattingApplied', () { |
| 58 MockSource source = new MockSource(); |
| 59 source.when(callsTo('get encoding')).alwaysReturn('foo.dart'); |
| 60 CompileTimeErrorCode errorCode = CompileTimeErrorCode.AMBIGUOUS_EXPORT; |
| 61 AnalysisError analysisError = |
| 62 new AnalysisError.con1(source, errorCode, ['foo', 'bar', 'baz']); |
| 63 Map<String, Object> json = AnalysisServer.errorToJson(analysisError); |
| 64 |
| 65 expect(json['message'], |
| 66 equals("The name 'foo' is defined in the libraries 'bar' and 'baz'")); |
| 67 }); |
| 68 |
| 69 test('errorToJson_noCorrection', () { |
| 70 MockSource source = new MockSource(); |
| 71 source.when(callsTo('get fullName')).alwaysReturn('foo.dart'); |
| 72 CompileTimeErrorCode errorCode = |
| 73 CompileTimeErrorCode.CONST_CONSTRUCTOR_WITH_NON_CONST_SUPER; |
| 74 AnalysisError analysisError = |
| 75 new AnalysisError.con2(source, 10, 5, errorCode, ['Foo']); |
| 76 Map<String, Object> json = AnalysisServer.errorToJson(analysisError); |
| 77 expect(json, hasLength(5)); |
| 78 expect(json['file'], equals('foo.dart')); |
| 79 expect(json['errorCode'], 'CompileTimeErrorCode.CONST_CONSTRUCTOR_WITH_NON
_CONST_SUPER'); |
| 80 expect(json['offset'], equals(analysisError.offset)); |
| 81 expect(json['length'], equals(analysisError.length)); |
| 82 expect(json['message'], equals(errorCode.message.replaceAll('%s', 'Foo')))
; |
| 83 }); |
| 84 |
| 85 test('errorToJson_withCorrection', () { |
| 86 MockSource source = new MockSource(); |
| 87 source.when(callsTo('get encoding')).alwaysReturn('foo.dart'); |
| 88 |
| 89 // TODO(paulberry): in principle we should test an error or hint that uses |
| 90 // %s formatting in its correction string. But no such errors or hints |
| 91 // currently exist! |
| 92 HintCode errorCode = HintCode.MISSING_RETURN; |
| 93 |
| 94 AnalysisError analysisError = |
| 95 new AnalysisError.con2(source, 10, 5, errorCode, ['int']); |
| 96 Map<String, Object> json = AnalysisServer.errorToJson(analysisError); |
| 97 expect(json['correction'], equals(errorCode.correction)); |
| 98 }); |
| 99 |
| 100 test('performTask_whenNotRunning', () { |
| 101 AnalysisServerTestHelper helper = new AnalysisServerTestHelper(); |
| 102 // If the server is shut down while there is analysis still pending, |
| 103 // performTask() should notice that the server is no longer running and |
| 104 // do no analysis. |
| 105 MockAnalysisContext context = new MockAnalysisContext(); |
| 106 helper.server.addContextToWorkQueue(context); |
| 107 helper.server.running = false; |
| 108 // Pump the event queue to make sure the server doesn't try to do any |
| 109 // analysis. |
| 110 return pumpEventQueue(); |
| 111 }); |
| 112 |
| 113 test('shutdown', () { |
| 114 AnalysisServerTestHelper helper = new AnalysisServerTestHelper(); |
| 115 helper.server.handlers = [new ServerDomainHandler(helper.server)]; |
| 116 var request = new Request('my28', METHOD_SHUTDOWN); |
| 117 return helper.channel.sendRequest(request) |
| 118 .then((Response response) { |
| 119 expect(response.id, equals('my28')); |
| 120 expect(response.error, isNull); |
| 121 }); |
| 122 }); |
| 123 |
| 124 test('unknownRequest', () { |
| 125 AnalysisServerTestHelper helper = new AnalysisServerTestHelper(); |
| 126 helper.server.handlers = [new EchoHandler()]; |
| 127 var request = new Request('my22', 'randomRequest'); |
| 128 return helper.channel.sendRequest(request) |
| 129 .then((Response response) { |
| 130 expect(response.id, equals('my22')); |
| 131 expect(response.error, isNotNull); |
| 132 }); |
| 133 }); |
| 134 }); |
| 135 } |
| 227 | 136 |
| 228 class EchoHandler implements RequestHandler { | 137 class EchoHandler implements RequestHandler { |
| 229 @override | 138 @override |
| 230 Response handleRequest(Request request) { | 139 Response handleRequest(Request request) { |
| 231 if (request.method == 'echo') { | 140 if (request.method == 'echo') { |
| 232 var response = new Response(request.id); | 141 var response = new Response(request.id); |
| 233 response.setResult('echo', true); | 142 response.setResult('echo', true); |
| 234 return response; | 143 return response; |
| 235 } | 144 } |
| 236 return null; | 145 return null; |
| 237 } | 146 } |
| 238 } | 147 } |
| OLD | NEW |