blob: 59b4cddfa658a6221257d414df9545e0da134148 [file] [log] [blame]
// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
library test.analysis_server;
import 'dart:async';
import 'package:analyzer/src/generated/engine.dart';
import 'package:analyzer/src/generated/source_io.dart';
import 'package:analyzer/src/generated/error.dart';
import 'package:analysis_server/src/analysis_server.dart';
import 'package:analysis_server/src/domain_server.dart';
import 'package:analysis_server/src/protocol.dart';
import 'package:mock/mock.dart';
import 'package:unittest/unittest.dart';
import 'mocks.dart';
main() {
group('AnalysisServer', () {
setUp(AnalysisServerTest.setUp);
test('addContextToWorkQueue_twice',
AnalysisServerTest.addContextToWorkQueue_twice);
test('addContextToWorkQueue_whenNotRunning',
AnalysisServerTest.addContextToWorkQueue_whenNotRunning);
test('addContextToWorkQueue_whenRunning',
AnalysisServerTest.addContextToWorkQueue_whenRunning);
test('createContext', AnalysisServerTest.createContext);
test('echo', AnalysisServerTest.echo);
test('errorToJson_formattingApplied',
AnalysisServerTest.errorToJson_formattingApplied);
test('errorToJson_noCorrection',
AnalysisServerTest.errorToJson_noCorrection);
test('errorToJson_withCorrection',
AnalysisServerTest.errorToJson_withCorrection);
test('performTask_whenNotRunning',
AnalysisServerTest.performTask_whenNotRunning);
test('shutdown', AnalysisServerTest.shutdown);
test('unknownRequest', AnalysisServerTest.unknownRequest);
});
}
class AnalysisServerTest {
static MockServerChannel channel;
static AnalysisServer server;
static MockAnalysisLogger logger;
static void setUp() {
channel = new MockServerChannel();
server = new AnalysisServer(channel);
logger = new MockAnalysisLogger();
AnalysisEngine.instance.logger = logger;
}
static Future addContextToWorkQueue_whenNotRunning() {
server.running = false;
MockAnalysisContext context = new MockAnalysisContext();
server.addContextToWorkQueue(context);
// Pump the event queue to make sure the server doesn't try to do any
// analysis.
return pumpEventQueue();
}
static Future addContextToWorkQueue_whenRunning() {
MockAnalysisContext context = new MockAnalysisContext();
server.addContextToWorkQueue(context);
MockSource source = new MockSource();
source.when(callsTo('get encoding')).alwaysReturn('foo.dart');
ChangeNoticeImpl changeNoticeImpl = new ChangeNoticeImpl(source);
LineInfo lineInfo = new LineInfo([0]);
AnalysisError analysisError = new AnalysisError.con1(source,
CompileTimeErrorCode.CONST_CONSTRUCTOR_WITH_NON_CONST_SUPER, []);
changeNoticeImpl.setErrors([analysisError], lineInfo);
context.when(callsTo('performAnalysisTask')).thenReturn(
new AnalysisResult([changeNoticeImpl], 0, 'myClass', 0));
context.when(callsTo('performAnalysisTask')).thenReturn(
new AnalysisResult(null, 0, null, 0));
return pumpEventQueue().then((_) {
context.getLogs(callsTo('performAnalysisTask')).verify(happenedExactly(2));
expect(channel.notificationsReceived, hasLength(2));
expect(channel.notificationsReceived[0].event, equals('server.connected')
);
expect(channel.notificationsReceived[1].event, equals('context.errors'));
expect(channel.notificationsReceived[1].params['source'], equals(
'foo.dart'));
List<AnalysisError> errors =
channel.notificationsReceived[1].params['errors'];
expect(errors, hasLength(1));
expect(errors[0], equals(AnalysisServer.errorToJson(analysisError)));
});
}
static Future addContextToWorkQueue_twice() {
// The context should only be asked to perform its analysis task once.
MockAnalysisContext context = new MockAnalysisContext();
server.addContextToWorkQueue(context);
server.addContextToWorkQueue(context);
context.when(callsTo('performAnalysisTask')).thenReturn(
new AnalysisResult(null, 0, null, 0));
return pumpEventQueue().then((_) =>
context.getLogs(callsTo('performAnalysisTask')).verify(happenedExactly(1)));
}
static Future createContext() {
server.handlers = [new ServerDomainHandler(server)];
var request = new Request('my27', ServerDomainHandler.CREATE_CONTEXT_METHOD);
request.setParameter(ServerDomainHandler.SDK_DIRECTORY_PARAM, sdkPath);
request.setParameter(ServerDomainHandler.CONTEXT_ID_PARAM, 'ctx');
return channel.sendRequest(request)
.then((Response response) {
expect(response.id, equals('my27'));
expect(response.error, isNull);
});
}
static Future echo() {
server.handlers = [new EchoHandler()];
var request = new Request('my22', 'echo');
return channel.sendRequest(request)
.then((Response response) {
expect(response.id, equals('my22'));
expect(response.error, isNull);
});
}
static void errorToJson_formattingApplied() {
MockSource source = new MockSource();
source.when(callsTo('get encoding')).alwaysReturn('foo.dart');
CompileTimeErrorCode errorCode = CompileTimeErrorCode.AMBIGUOUS_EXPORT;
AnalysisError analysisError =
new AnalysisError.con1(source, errorCode, ['foo', 'bar', 'baz']);
Map<String, Object> json = AnalysisServer.errorToJson(analysisError);
expect(json['message'],
equals("The element 'foo' is defined in the libraries 'bar' and 'baz'"));
}
static void errorToJson_noCorrection() {
MockSource source = new MockSource();
source.when(callsTo('get encoding')).alwaysReturn('foo.dart');
CompileTimeErrorCode errorCode =
CompileTimeErrorCode.CONST_CONSTRUCTOR_WITH_NON_CONST_SUPER;
AnalysisError analysisError =
new AnalysisError.con2(source, 10, 5, errorCode, []);
Map<String, Object> json = AnalysisServer.errorToJson(analysisError);
expect(json, hasLength(5));
expect(json['source'], equals('foo.dart'));
expect(json['errorCode'], equals(errorCode.ordinal));
expect(json['offset'], equals(analysisError.offset));
expect(json['length'], equals(analysisError.length));
expect(json['message'], equals(errorCode.message));
}
static void errorToJson_withCorrection() {
MockSource source = new MockSource();
source.when(callsTo('get encoding')).alwaysReturn('foo.dart');
// TODO(paulberry): in principle we should test an error or hint that uses
// %s formatting in its correction string. But no such errors or hints
// currently exist!
HintCode errorCode = HintCode.MISSING_RETURN;
AnalysisError analysisError =
new AnalysisError.con2(source, 10, 5, errorCode, ['int']);
Map<String, Object> json = AnalysisServer.errorToJson(analysisError);
expect(json['correction'], equals(errorCode.correction));
}
static Future performTask_whenNotRunning() {
// If the server is shut down while there is analysis still pending,
// performTask() should notice that the server is no longer running and
// do no analysis.
MockAnalysisContext context = new MockAnalysisContext();
server.addContextToWorkQueue(context);
server.running = false;
// Pump the event queue to make sure the server doesn't try to do any
// analysis.
return pumpEventQueue();
}
static Future shutdown() {
server.handlers = [new ServerDomainHandler(server)];
var request = new Request('my28', ServerDomainHandler.SHUTDOWN_METHOD);
request.setParameter(ServerDomainHandler.SDK_DIRECTORY_PARAM, '');
return channel.sendRequest(request)
.then((Response response) {
expect(response.id, equals('my28'));
expect(response.error, isNull);
});
}
static Future unknownRequest() {
server.handlers = [new EchoHandler()];
var request = new Request('my22', 'randomRequest');
return channel.sendRequest(request)
.then((Response response) {
expect(response.id, equals('my22'));
expect(response.error, isNotNull);
});
}
}
class EchoHandler implements RequestHandler {
@override
Response handleRequest(Request request) {
if (request.method == 'echo') {
var response = new Response(request.id);
response.setResult('echo', true);
return response;
}
return null;
}
}