| // 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. |
| |
| import 'dart:async'; |
| import 'dart:collection'; |
| import 'dart:convert'; |
| import 'dart:io'; |
| |
| import 'package:angel3_mock_request/angel3_mock_request.dart'; |
| import 'package:dart_services/src/common.dart'; |
| import 'package:dart_services/src/common_server_api.dart'; |
| import 'package:dart_services/src/common_server_impl.dart'; |
| import 'package:dart_services/src/sdk.dart'; |
| import 'package:dart_services/src/server_cache.dart'; |
| import 'package:logging/logging.dart'; |
| import 'package:shelf/shelf_io.dart' as shelf_io; |
| import 'package:test/test.dart'; |
| |
| const versions = ['v1', 'v2']; |
| |
| const preFormattedCode = r''' |
| void main() |
| { |
| int i = 0; |
| } |
| '''; |
| |
| const postFormattedCode = r''' |
| void main() { |
| int i = 0; |
| } |
| '''; |
| |
| const formatBadCode = r''' |
| void main() |
| { |
| print('foo') |
| } |
| '''; |
| |
| void main() => defineTests(); |
| |
| void defineTests() { |
| late CommonServerApi commonServerApi; |
| late CommonServerImpl commonServerImpl; |
| |
| Future<MockHttpResponse> sendPostRequest( |
| String path, |
| dynamic jsonData, |
| ) async { |
| final uri = Uri.parse('/api/$path'); |
| final request = MockHttpRequest('POST', uri); |
| request.headers.add('content-type', jsonContentType); |
| request.add(utf8.encode(json.encode(jsonData))); |
| await request.close(); |
| await shelf_io.handleRequest(request, commonServerApi.router.call); |
| return request.response; |
| } |
| |
| Future<MockHttpResponse> sendGetRequest( |
| String path, |
| ) async { |
| final uri = Uri.parse('/api/$path'); |
| final request = MockHttpRequest('GET', uri); |
| request.headers.add('content-type', jsonContentType); |
| await request.close(); |
| await shelf_io.handleRequest(request, commonServerApi.router.call); |
| return request.response; |
| } |
| |
| group('CommonServerProto JSON', () { |
| final sdk = |
| Sdk.create(Platform.environment['FLUTTER_CHANNEL'] ?? stableChannel); |
| setUp(() async { |
| final cache = MockCache(); |
| commonServerImpl = CommonServerImpl(cache, sdk); |
| commonServerApi = CommonServerApi(commonServerImpl); |
| await commonServerImpl.init(); |
| |
| // Some piece of initialization doesn't always happen fast enough for this |
| // request to work in time for the test. So try it here until the server |
| // returns something valid. |
| // TODO(jcollins-g): determine which piece of initialization isn't |
| // happening and deal with that in warmup/init. |
| { |
| var decodedJson = <dynamic, dynamic>{}; |
| final jsonData = {'source': sampleCodeError}; |
| while (decodedJson.isEmpty) { |
| final response = |
| await sendPostRequest('dartservices/v2/analyze', jsonData); |
| expect(response.statusCode, 200); |
| expect(response.headers['content-type'], |
| ['application/json; charset=utf-8']); |
| final data = await response.transform(utf8.decoder).join(); |
| decodedJson = json.decode(data) as Map<dynamic, dynamic>; |
| } |
| } |
| }); |
| |
| tearDown(() async { |
| await commonServerImpl.shutdown(); |
| }); |
| |
| setUp(() { |
| log.onRecord.listen((LogRecord rec) { |
| print('${rec.level.name}: ${rec.time}: ${rec.message}'); |
| }); |
| }); |
| |
| tearDown(log.clearListeners); |
| |
| test('analyze Dart', () async { |
| for (final version in versions) { |
| final jsonData = {'source': sampleCode}; |
| final response = |
| await sendPostRequest('dartservices/$version/analyze', jsonData); |
| expect(response.statusCode, 200); |
| final data = await response.transform(utf8.decoder).join(); |
| expect(json.decode(data), <dynamic, dynamic>{}); |
| } |
| }); |
| |
| test('analyze Flutter', () async { |
| for (final version in versions) { |
| final jsonData = {'source': sampleCodeFlutter}; |
| final response = |
| await sendPostRequest('dartservices/$version/analyze', jsonData); |
| expect(response.statusCode, 200); |
| final data = await response.transform(utf8.decoder).join(); |
| expect(json.decode(data), { |
| 'packageImports': ['flutter'] |
| }); |
| } |
| }); |
| |
| test('analyze code with constructor-tearoffs features', () async { |
| for (final version in versions) { |
| final jsonData = { |
| 'source': ''' |
| void main() { |
| List<int>; |
| } |
| ''' |
| }; |
| final response = |
| await sendPostRequest('dartservices/$version/analyze', jsonData); |
| expect(response.statusCode, 200); |
| final data = await response.transform(utf8.decoder).join(); |
| expect(json.decode(data), <dynamic, dynamic>{}); |
| } |
| }); |
| |
| test('analyze counterApp', () async { |
| for (final version in versions) { |
| final jsonData = {'source': sampleCodeFlutterCounter}; |
| final response = |
| await sendPostRequest('dartservices/$version/analyze', jsonData); |
| expect(response.statusCode, 200); |
| final data = await response.transform(utf8.decoder).join(); |
| expect(json.decode(data), { |
| 'packageImports': ['flutter'] |
| }); |
| } |
| }); |
| |
| test('analyze draggableAndPhysicsApp', () async { |
| for (final version in versions) { |
| final jsonData = {'source': sampleCodeFlutterDraggableCard}; |
| final response = |
| await sendPostRequest('dartservices/$version/analyze', jsonData); |
| expect(response.statusCode, 200); |
| final data = await response.transform(utf8.decoder).join(); |
| expect(json.decode(data), { |
| 'packageImports': ['flutter'] |
| }); |
| } |
| }); |
| |
| test('analyze errors', () async { |
| for (final version in versions) { |
| final jsonData = {'source': sampleCodeError}; |
| final response = |
| await sendPostRequest('dartservices/$version/analyze', jsonData); |
| expect(response.statusCode, 200); |
| expect(response.headers['content-type'], |
| ['application/json; charset=utf-8']); |
| final data = await response.transform(utf8.decoder).join(); |
| final dataMap = (json.decode(data) as Map).cast<String, Object>(); |
| expect( |
| dataMap, |
| { |
| 'issues': [ |
| { |
| 'kind': 'error', |
| 'line': 2, |
| 'sourceName': 'main.dart', |
| 'message': "Expected to find ';'.", |
| 'hasFixes': true, |
| 'charStart': 29, |
| 'charLength': 1, |
| 'column': 16, |
| 'code': 'expected_token', |
| } |
| ] |
| }, |
| ); |
| } |
| }); |
| |
| test('analyze negative-test noSource', () async { |
| for (final version in versions) { |
| final jsonData = <dynamic, dynamic>{}; |
| final response = |
| await sendPostRequest('dartservices/$version/analyze', jsonData); |
| expect(response.statusCode, 400); |
| } |
| }); |
| |
| test('compile', () async { |
| for (final version in versions) { |
| final jsonData = {'source': sampleCode}; |
| final response = |
| await sendPostRequest('dartservices/$version/compile', jsonData); |
| expect(response.statusCode, 200); |
| final data = await response.transform(utf8.decoder).join(); |
| expect(json.decode(data), isNotEmpty); |
| } |
| }); |
| |
| test('compile with cache', () async { |
| for (final version in versions) { |
| final jsonData = {'source': sampleCode}; |
| final response1 = |
| await sendPostRequest('dartservices/$version/compile', jsonData); |
| expect(response1.statusCode, 200); |
| final data1 = await response1.transform(utf8.decoder).join(); |
| expect(json.decode(data1), isNotEmpty); |
| |
| final response2 = |
| await sendPostRequest('dartservices/$version/compile', jsonData); |
| expect(response2.statusCode, 200); |
| final data2 = await response2.transform(utf8.decoder).join(); |
| expect(json.decode(data2), isNotEmpty); |
| } |
| }); |
| |
| test('compile error', () async { |
| for (final version in versions) { |
| final jsonData = {'source': sampleCodeError}; |
| final response = |
| await sendPostRequest('dartservices/$version/compile', jsonData); |
| expect(response.statusCode, 400); |
| final encoded = await response.transform(utf8.decoder).join(); |
| final data = json.decode(encoded) as Map<String, dynamic>; |
| expect(data, isNotEmpty); |
| final error = data['error'] as Map<String, dynamic>; |
| expect(error['message'], contains('Error: Expected')); |
| } |
| }); |
| |
| test('compile negative-test noSource', () async { |
| for (final version in versions) { |
| final jsonData = <dynamic, dynamic>{}; |
| final response = |
| await sendPostRequest('dartservices/$version/compile', jsonData); |
| expect(response.statusCode, 400); |
| } |
| }); |
| |
| test('compileDDC', () async { |
| for (final version in versions) { |
| final jsonData = {'source': sampleCode}; |
| final response = |
| await sendPostRequest('dartservices/$version/compileDDC', jsonData); |
| expect(response.statusCode, 200); |
| final data = await response.transform(utf8.decoder).join(); |
| expect(json.decode(data), isNotEmpty); |
| } |
| }); |
| |
| test('compileDDC with cache', () async { |
| for (final version in versions) { |
| final jsonData = {'source': sampleCode}; |
| final response1 = |
| await sendPostRequest('dartservices/$version/compileDDC', jsonData); |
| expect(response1.statusCode, 200); |
| final data1 = await response1.transform(utf8.decoder).join(); |
| expect(json.decode(data1), isNotEmpty); |
| |
| final response2 = |
| await sendPostRequest('dartservices/$version/compileDDC', jsonData); |
| expect(response2.statusCode, 200); |
| final data2 = await response2.transform(utf8.decoder).join(); |
| expect(json.decode(data2), isNotEmpty); |
| } |
| }); |
| |
| test('complete', () async { |
| for (final version in versions) { |
| final jsonData = {'source': 'void main() {print("foo");}', 'offset': 1}; |
| final response = |
| await sendPostRequest('dartservices/$version/complete', jsonData); |
| expect(response.statusCode, 200); |
| final data = json.decode(await response.transform(utf8.decoder).join()); |
| expect(data, isNotEmpty); |
| } |
| }); |
| |
| test('complete no data', () async { |
| for (final version in versions) { |
| final response = await sendPostRequest( |
| 'dartservices/$version/complete', <dynamic, dynamic>{}); |
| expect(response.statusCode, 400); |
| } |
| }); |
| |
| test('complete param missing', () async { |
| for (final version in versions) { |
| final jsonData = {'offset': 1}; |
| final response = |
| await sendPostRequest('dartservices/$version/complete', jsonData); |
| expect(response.statusCode, 400); |
| } |
| }); |
| |
| test('complete param missing 2', () async { |
| for (final version in versions) { |
| final jsonData = {'source': 'void main() {print("foo");}'}; |
| final response = |
| await sendPostRequest('dartservices/$version/complete', jsonData); |
| expect(response.statusCode, 400); |
| final encoded = await response.transform(utf8.decoder).join(); |
| final data = json.decode(encoded) as Map<String, dynamic>; |
| final error = data['error'] as Map<String, dynamic>; |
| expect(error['message'], 'Missing parameter: \'offset\''); |
| } |
| }); |
| |
| test('document', () async { |
| for (final version in versions) { |
| final jsonData = { |
| 'source': 'void main() {print("foo");}', |
| 'offset': 17 |
| }; |
| final response = |
| await sendPostRequest('dartservices/$version/document', jsonData); |
| expect(response.statusCode, 200); |
| final data = json.decode(await response.transform(utf8.decoder).join()); |
| expect(data, isNotEmpty); |
| } |
| }); |
| |
| test('document little data', () async { |
| for (final version in versions) { |
| final jsonData = {'source': 'void main() {print("foo");}', 'offset': 2}; |
| final response = |
| await sendPostRequest('dartservices/$version/document', jsonData); |
| expect(response.statusCode, 200); |
| final data = json.decode(await response.transform(utf8.decoder).join()); |
| expect(data, { |
| 'info': <dynamic, dynamic>{}, |
| }); |
| } |
| }); |
| |
| test('document no data', () async { |
| for (final version in versions) { |
| final jsonData = { |
| 'source': 'void main() {print("foo");}', |
| 'offset': 12 |
| }; |
| final response = |
| await sendPostRequest('dartservices/$version/document', jsonData); |
| expect(response.statusCode, 200); |
| final data = json.decode(await response.transform(utf8.decoder).join()); |
| expect(data, {'info': <dynamic, dynamic>{}}); |
| } |
| }); |
| |
| test('document negative-test noSource', () async { |
| for (final version in versions) { |
| final jsonData = {'offset': 12}; |
| final response = |
| await sendPostRequest('dartservices/$version/document', jsonData); |
| expect(response.statusCode, 400); |
| } |
| }); |
| |
| test('document negative-test noOffset', () async { |
| for (final version in versions) { |
| final jsonData = {'source': 'void main() {print("foo");}'}; |
| final response = |
| await sendPostRequest('dartservices/$version/document', jsonData); |
| expect(response.statusCode, 400); |
| } |
| }); |
| |
| test('format', () async { |
| for (final version in versions) { |
| final jsonData = {'source': preFormattedCode}; |
| final response = |
| await sendPostRequest('dartservices/$version/format', jsonData); |
| expect(response.statusCode, 200); |
| final encoded = await response.transform(utf8.decoder).join(); |
| final data = json.decode(encoded) as Map<String, dynamic>; |
| expect(data['newString'], postFormattedCode); |
| } |
| }); |
| |
| test('format bad code', () async { |
| for (final version in versions) { |
| final jsonData = {'source': formatBadCode}; |
| final response = |
| await sendPostRequest('dartservices/$version/format', jsonData); |
| expect(response.statusCode, 200); |
| final encoded = await response.transform(utf8.decoder).join(); |
| final data = json.decode(encoded) as Map<String, dynamic>; |
| expect(data['newString'], formatBadCode); |
| } |
| }); |
| |
| test('format position', () async { |
| for (final version in versions) { |
| final jsonData = {'source': preFormattedCode, 'offset': 21}; |
| final response = |
| await sendPostRequest('dartservices/$version/format', jsonData); |
| expect(response.statusCode, 200); |
| final encoded = await response.transform(utf8.decoder).join(); |
| final data = json.decode(encoded) as Map<String, dynamic>; |
| expect(data['newString'], postFormattedCode); |
| expect(data['offset'], 24); |
| } |
| }); |
| |
| test('fix', () async { |
| final quickFixesCode = ''' |
| import 'dart:async'; |
| void main() { |
| int i = 0; |
| } |
| '''; |
| for (final version in versions) { |
| final jsonData = {'source': quickFixesCode, 'offset': 10}; |
| final response = |
| await sendPostRequest('dartservices/$version/fixes', jsonData); |
| expect(response.statusCode, 200); |
| final encoded = await response.transform(utf8.decoder).join(); |
| final data = json.decode(encoded) as Map<String, dynamic>; |
| final fixes = data['fixes'] as List<dynamic>; |
| expect(fixes.length, 1); |
| final problemAndFix = fixes[0] as Map<String, dynamic>; |
| expect(problemAndFix['problemMessage'], isNotNull); |
| } |
| }); |
| |
| test('fixes completeness', () async { |
| for (final version in versions) { |
| final jsonData = { |
| 'source': ''' |
| void main() { |
| for (int i = 0; i < 4; i++) { |
| print('hello \$i') |
| } |
| } |
| ''', |
| 'offset': 67, |
| }; |
| final response = |
| await sendPostRequest('dartservices/$version/fixes', jsonData); |
| expect(response.statusCode, 200); |
| final data = json.decode(await response.transform(utf8.decoder).join()); |
| expect(data, { |
| 'fixes': [ |
| { |
| 'fixes': [ |
| { |
| 'message': "Insert ';'", |
| 'edits': [ |
| {'offset': 67, 'length': 0, 'replacement': ';'} |
| ] |
| } |
| ], |
| 'problemMessage': "Expected to find ';'.", |
| 'offset': 66, |
| 'length': 1 |
| } |
| ] |
| }); |
| } |
| }); |
| |
| test('assist', () async { |
| final assistCode = ''' |
| main() { |
| int v = 0; |
| } |
| '''; |
| for (final version in versions) { |
| final jsonData = {'source': assistCode, 'offset': 15}; |
| final response = |
| await sendPostRequest('dartservices/$version/assists', jsonData); |
| expect(response.statusCode, 200); |
| |
| final encoded = await response.transform(utf8.decoder).join(); |
| final data = json.decode(encoded) as Map<String, dynamic>; |
| final assists = data['assists'] as List<dynamic>; |
| if (sdk.masterChannel || sdk.betaChannel) { |
| expect(assists, hasLength(3)); |
| } else { |
| expect(assists, hasLength(2)); |
| } |
| final firstEdit = assists.first as Map<String, dynamic>; |
| expect(firstEdit['edits'], isNotNull); |
| expect(firstEdit['edits'], hasLength(1)); |
| expect(assists.where((m) { |
| final map = m as Map<String, dynamic>; |
| return map['message'] == 'Remove type annotation'; |
| }), isNotEmpty); |
| } |
| }); |
| |
| test('version', () async { |
| for (final version in versions) { |
| final response = await sendGetRequest('dartservices/$version/version'); |
| expect(response.statusCode, 200); |
| final encoded = await response.transform(utf8.decoder).join(); |
| final data = json.decode(encoded) as Map<String, dynamic>; |
| expect(data['sdkVersion'], isNotNull); |
| expect(data['runtimeVersion'], isNotNull); |
| } |
| }); |
| }); |
| |
| //------------------------------------------------------------------------- |
| // Beginning of multi file files={} tests group: |
| group('CommonServerProto JSON for Multi file group files={}', () { |
| final sdk = |
| Sdk.create(Platform.environment['FLUTTER_CHANNEL'] ?? stableChannel); |
| setUp(() async { |
| final cache = MockCache(); |
| commonServerImpl = CommonServerImpl(cache, sdk); |
| commonServerApi = CommonServerApi(commonServerImpl); |
| await commonServerImpl.init(); |
| |
| // Some piece of initialization doesn't always happen fast enough for this |
| // request to work in time for the test. So try it here until the server |
| // returns something valid. |
| // TODO(jcollins-g): determine which piece of initialization isn't |
| // happening and deal with that in warmup/init. |
| { |
| var decodedJson = <dynamic, dynamic>{}; |
| final jsonData = {'source': sampleCodeError}; |
| while (decodedJson.isEmpty) { |
| final response = |
| await sendPostRequest('dartservices/v2/analyze', jsonData); |
| expect(response.statusCode, 200); |
| expect(response.headers['content-type'], |
| ['application/json; charset=utf-8']); |
| final data = await response.transform(utf8.decoder).join(); |
| decodedJson = json.decode(data) as Map<dynamic, dynamic>; |
| } |
| } |
| }); |
| |
| tearDown(() async { |
| await commonServerImpl.shutdown(); |
| }); |
| |
| setUp(() { |
| log.onRecord.listen((LogRecord rec) { |
| print('${rec.level.name}: ${rec.time}: ${rec.message}'); |
| }); |
| }); |
| |
| tearDown(log.clearListeners); |
| |
| test('analyzeFiles Dart files={}', () async { |
| for (final version in versions) { |
| final jsonData = { |
| 'files': {kMainDart: sampleCode} |
| }; |
| final response = await sendPostRequest( |
| 'dartservices/$version/analyzeFiles', jsonData); |
| expect(response.statusCode, 200); |
| final data = await response.transform(utf8.decoder).join(); |
| expect(json.decode(data), <dynamic, dynamic>{}); |
| } |
| }); |
| |
| test('analyzeFiles Flutter files={}', () async { |
| for (final version in versions) { |
| final jsonData = { |
| 'files': {kMainDart: sampleCodeFlutter} |
| }; |
| final response = await sendPostRequest( |
| 'dartservices/$version/analyzeFiles', jsonData); |
| expect(response.statusCode, 200); |
| final data = await response.transform(utf8.decoder).join(); |
| expect(json.decode(data), { |
| 'packageImports': ['flutter'] |
| }); |
| } |
| }); |
| |
| test('analyzeFiles code with constructor-tearoffs features files={}', |
| () async { |
| for (final version in versions) { |
| final jsonData = { |
| 'files': { |
| kMainDart: ''' |
| void main() { |
| List<int>; |
| } |
| ''' |
| } |
| }; |
| final response = await sendPostRequest( |
| 'dartservices/$version/analyzeFiles', jsonData); |
| expect(response.statusCode, 200); |
| final data = await response.transform(utf8.decoder).join(); |
| expect(json.decode(data), <dynamic, dynamic>{}); |
| } |
| }); |
| |
| test('analyzeFiles counterApp files={}', () async { |
| for (final version in versions) { |
| final jsonData = { |
| 'files': {kMainDart: sampleCodeFlutterCounter} |
| }; |
| final response = await sendPostRequest( |
| 'dartservices/$version/analyzeFiles', jsonData); |
| expect(response.statusCode, 200); |
| final data = await response.transform(utf8.decoder).join(); |
| expect(json.decode(data), { |
| 'packageImports': ['flutter'] |
| }); |
| } |
| }); |
| |
| test('analyzeFiles draggableAndPhysicsApp files={}', () async { |
| for (final version in versions) { |
| final jsonData = { |
| 'files': {kMainDart: sampleCodeFlutterDraggableCard} |
| }; |
| final response = await sendPostRequest( |
| 'dartservices/$version/analyzeFiles', jsonData); |
| expect(response.statusCode, 200); |
| final data = await response.transform(utf8.decoder).join(); |
| expect(json.decode(data), { |
| 'packageImports': ['flutter'] |
| }); |
| } |
| }); |
| |
| test('analyzeFiles errors files={}', () async { |
| for (final version in versions) { |
| final jsonData = { |
| 'files': {kMainDart: sampleCodeError} |
| }; |
| final response = await sendPostRequest( |
| 'dartservices/$version/analyzeFiles', jsonData); |
| expect(response.statusCode, 200); |
| expect(response.headers['content-type'], |
| ['application/json; charset=utf-8']); |
| final data = await response.transform(utf8.decoder).join(); |
| final dataMap = (json.decode(data) as Map).cast<String, Object>(); |
| expect( |
| dataMap, |
| { |
| 'issues': [ |
| { |
| 'kind': 'error', |
| 'line': 2, |
| 'sourceName': 'main.dart', |
| 'message': "Expected to find ';'.", |
| 'hasFixes': true, |
| 'charStart': 29, |
| 'charLength': 1, |
| 'column': 16, |
| 'code': 'expected_token', |
| } |
| ] |
| }, |
| ); |
| } |
| }); |
| |
| test('analyzeFiles negative-test noFiles files={}', () async { |
| for (final version in versions) { |
| final jsonData = <dynamic, dynamic>{}; |
| final response = await sendPostRequest( |
| 'dartservices/$version/analyzeFiles', jsonData); |
| expect(response.statusCode, 400); |
| } |
| }); |
| |
| // Begin compileFiles entry point testing: |
| test('compileFiles files={}', () async { |
| for (final version in versions) { |
| final jsonData = { |
| 'files': {kMainDart: sampleCode} |
| }; |
| final response = await sendPostRequest( |
| 'dartservices/$version/compileFiles', jsonData); |
| expect(response.statusCode, 200); |
| final data = await response.transform(utf8.decoder).join(); |
| expect(json.decode(data), isNotEmpty); |
| } |
| }); |
| |
| // 2 separate files, main importing 'various.dart'. |
| test('compileFiles files={} with 2 files using import', () async { |
| for (final version in versions) { |
| final jsonData = { |
| 'files': { |
| kMainDart: sampleCodeMultiFoo, |
| 'bar.dart': sampleCodeMultiBar, |
| } |
| }; |
| final response = await sendPostRequest( |
| 'dartservices/$version/compileFiles', jsonData); |
| expect(response.statusCode, 200); |
| final data = await response.transform(utf8.decoder).join(); |
| expect(json.decode(data), isNotEmpty); |
| } |
| }); |
| |
| // 2 separate files, main importing 'various.dart' but with |
| // up paths in names... test sanitizing filenames of '..\.../..' and '..' |
| // santizing should strip off all up dir chars and leave just the |
| // plain filenames. |
| test('compileFiles files={} with 2 files using import need sanitizing', |
| () async { |
| for (final version in versions) { |
| final jsonData = { |
| 'files': { |
| '..\\.../../$kMainDart': sampleCodeMultiFoo, |
| '../bar.dart': sampleCodeMultiBar |
| } |
| }; |
| final response = await sendPostRequest( |
| 'dartservices/$version/compileFiles', jsonData); |
| expect(response.statusCode, 200); |
| final data = await response.transform(utf8.decoder).join(); |
| expect(json.decode(data), isNotEmpty); |
| } |
| }); |
| |
| // 2 files using "part 'bar.dart'" to bring in second file. |
| test('compileFiles files={} with 2 files using library/part', () async { |
| for (final version in versions) { |
| final jsonData = { |
| 'files': { |
| kMainDart: sampleCodeLibraryMultiFoo, |
| 'bar.dart': sampleCodePartMultiBar |
| } |
| }; |
| final response = await sendPostRequest( |
| 'dartservices/$version/compileFiles', jsonData); |
| expect(response.statusCode, 200); |
| final data = await response.transform(utf8.decoder).join(); |
| expect(json.decode(data), isNotEmpty); |
| } |
| }); |
| |
| test('compileFiles with cache files={}', () async { |
| for (final version in versions) { |
| final jsonData = { |
| 'files': {kMainDart: sampleCode} |
| }; |
| final response1 = await sendPostRequest( |
| 'dartservices/$version/compileFiles', jsonData); |
| expect(response1.statusCode, 200); |
| final data1 = await response1.transform(utf8.decoder).join(); |
| expect(json.decode(data1), isNotEmpty); |
| |
| final response2 = await sendPostRequest( |
| 'dartservices/$version/compileFiles', jsonData); |
| expect(response2.statusCode, 200); |
| final data2 = await response2.transform(utf8.decoder).join(); |
| expect(json.decode(data2), isNotEmpty); |
| } |
| }); |
| |
| test('compileFiles error files={}', () async { |
| for (final version in versions) { |
| final jsonData = { |
| 'files': {kMainDart: sampleCodeError} |
| }; |
| final response = await sendPostRequest( |
| 'dartservices/$version/compileFiles', jsonData); |
| expect(response.statusCode, 400); |
| final encoded = await response.transform(utf8.decoder).join(); |
| final data = json.decode(encoded) as Map<String, dynamic>; |
| expect(data, isNotEmpty); |
| final error = data['error'] as Map<String, dynamic>; |
| expect(error['message'], contains('Error: Expected')); |
| } |
| }); |
| |
| test('compileFiles negative-test noFiles files={}', () async { |
| for (final version in versions) { |
| final jsonData = <dynamic, dynamic>{}; |
| final response = await sendPostRequest( |
| 'dartservices/$version/compileFiles', jsonData); |
| expect(response.statusCode, 400); |
| } |
| }); |
| |
| // Begin compileFilesDDC entry point testing DDC testing: |
| test('compileFilesDDC files={}', () async { |
| for (final version in versions) { |
| final jsonData = { |
| 'files': {kMainDart: sampleCode} |
| }; |
| final response = await sendPostRequest( |
| 'dartservices/$version/compileFilesDDC', jsonData); |
| expect(response.statusCode, 200); |
| final data = await response.transform(utf8.decoder).join(); |
| expect(json.decode(data), isNotEmpty); |
| } |
| }); |
| |
| // 2 separate files, main importing 'various.dart'. |
| test('compileFilesDDC files={} with 2 files using import', () async { |
| for (final version in versions) { |
| final jsonData = { |
| 'files': { |
| kMainDart: sampleCode2PartImportMain, |
| 'various.dart': sampleCode2PartImportVarious |
| } |
| }; |
| final response = await sendPostRequest( |
| 'dartservices/$version/compileFilesDDC', jsonData); |
| expect(response.statusCode, 200); |
| final data = await response.transform(utf8.decoder).join(); |
| expect(json.decode(data), isNotEmpty); |
| } |
| }); |
| |
| // 3 separate files, main importing 'various.dart' and 'discdata.dart'. |
| test('compileFilesDDC files={} with 3 files using import', () async { |
| for (final version in versions) { |
| final jsonData = { |
| 'files': { |
| kMainDart: sampleCode3PartImportMain, |
| 'discdata.dart': sampleCode3PartImportDiscData, |
| 'various.dart': sampleCode3PartImportVarious |
| } |
| }; |
| final response = await sendPostRequest( |
| 'dartservices/$version/compileFilesDDC', jsonData); |
| expect(response.statusCode, 200); |
| final data = await response.transform(utf8.decoder).join(); |
| expect(json.decode(data), isNotEmpty); |
| } |
| }); |
| |
| // 2 separate files, main importing 'various.dart' but with |
| // up paths in names... test sanitizing filenames of '..\.../..' and '..' |
| // santizing should strip off all up dir chars and leave just the |
| // plain filenames. |
| test('compileFilesDDC files={} with 2 files using import need sanitizing', |
| () async { |
| for (final version in versions) { |
| final jsonData = { |
| 'files': { |
| '..\\.../../$kMainDart': sampleCode2PartImportMain, |
| '../various.dart': sampleCode2PartImportVarious |
| } |
| }; |
| final response = await sendPostRequest( |
| 'dartservices/$version/compileFilesDDC', jsonData); |
| expect(response.statusCode, 200); |
| final data = await response.transform(utf8.decoder).join(); |
| expect(json.decode(data), isNotEmpty); |
| } |
| }); |
| |
| // 2 files using "part 'various.dart'" to bring in second file. |
| test('compileFilesDDC files={} with 2 files using import', () async { |
| for (final version in versions) { |
| final jsonData = { |
| 'files': { |
| kMainDart: sampleCode2PartImportMain, |
| 'various.dart': sampleCode2PartImportVarious |
| } |
| }; |
| final response = await sendPostRequest( |
| 'dartservices/$version/compileFilesDDC', jsonData); |
| expect(response.statusCode, 200); |
| final data = await response.transform(utf8.decoder).join(); |
| expect(json.decode(data), isNotEmpty); |
| } |
| }); |
| |
| // 3 files using "part 'various.dart'" and "part 'discdata.dart'" to bring |
| // in second and third files. |
| test('compileFilesDDC files={} with 3 files using import', () async { |
| for (final version in versions) { |
| final jsonData = { |
| 'files': { |
| kMainDart: sampleCode3PartLibraryMain, |
| 'discdata.dart': sampleCode3PartDiscDataPartOfTestAnim, |
| 'various.dart': sampleCode3PartVariousPartOfTestAnim, |
| } |
| }; |
| final response = await sendPostRequest( |
| 'dartservices/$version/compileFilesDDC', jsonData); |
| expect(response.statusCode, 200); |
| final data = await response.transform(utf8.decoder).join(); |
| expect(json.decode(data), isNotEmpty); |
| } |
| }); |
| |
| // Check sanitizing of package:, dart:, http:// from filenames. |
| test('compileFilesDDC files={} with 3 files using import needs sanitizing', |
| () async { |
| for (final version in versions) { |
| final jsonData = { |
| 'files': { |
| 'package:$kMainDart': sampleCode3PartLibraryMain, |
| 'dart:discdata.dart': sampleCode3PartDiscDataPartOfTestAnim, |
| 'http://various.dart': sampleCode3PartVariousPartOfTestAnim, |
| } |
| }; |
| final response = await sendPostRequest( |
| 'dartservices/$version/compileFilesDDC', jsonData); |
| expect(response.statusCode, 200); |
| final data = await response.transform(utf8.decoder).join(); |
| expect(json.decode(data), isNotEmpty); |
| } |
| }); |
| |
| // Test renaming the file with the main function ('mymain.dart') to be |
| // kMainDart when no file named kMainDart is found. |
| test('compileFilesDDC files={} with 3 files using import', () async { |
| for (final version in versions) { |
| final jsonData = { |
| 'files': { |
| 'discdata.dart': sampleCode3PartDiscDataPartOfTestAnim, |
| 'various.dart': sampleCode3PartVariousPartOfTestAnim, |
| 'mymain.dart': sampleCode3PartLibraryMain |
| } |
| }; |
| final response = await sendPostRequest( |
| 'dartservices/$version/compileFilesDDC', jsonData); |
| expect(response.statusCode, 200); |
| final data = await response.transform(utf8.decoder).join(); |
| expect(json.decode(data), isNotEmpty); |
| } |
| }); |
| |
| test('compileFilesDDC with cache files={}', () async { |
| for (final version in versions) { |
| final jsonData = { |
| 'files': {kMainDart: sampleCode} |
| }; |
| final response1 = await sendPostRequest( |
| 'dartservices/$version/compileFilesDDC', jsonData); |
| expect(response1.statusCode, 200); |
| final data1 = await response1.transform(utf8.decoder).join(); |
| expect(json.decode(data1), isNotEmpty); |
| |
| final response2 = await sendPostRequest( |
| 'dartservices/$version/compileFilesDDC', jsonData); |
| expect(response2.statusCode, 200); |
| final data2 = await response2.transform(utf8.decoder).join(); |
| expect(json.decode(data2), isNotEmpty); |
| } |
| }); |
| |
| test('compileFilesDDC 3 files set with cache files={}', () async { |
| for (final version in versions) { |
| final jsonData = { |
| 'files': { |
| kMainDart: sampleCode3PartLibraryMain, |
| 'discdata.dart': sampleCode3PartDiscDataPartOfTestAnim, |
| 'various.dart': sampleCode3PartVariousPartOfTestAnim |
| } |
| }; |
| final response1 = await sendPostRequest( |
| 'dartservices/$version/compileFilesDDC', jsonData); |
| expect(response1.statusCode, 200); |
| final data1 = await response1.transform(utf8.decoder).join(); |
| expect(json.decode(data1), isNotEmpty); |
| |
| final response2 = await sendPostRequest( |
| 'dartservices/$version/compileFilesDDC', jsonData); |
| expect(response2.statusCode, 200); |
| final data2 = await response2.transform(utf8.decoder).join(); |
| expect(json.decode(data2), isNotEmpty); |
| } |
| }); |
| |
| test('compileFilesDDC error files={}', () async { |
| for (final version in versions) { |
| final jsonData = { |
| 'files': {kMainDart: sampleCodeError} |
| }; |
| final response = await sendPostRequest( |
| 'dartservices/$version/compileFilesDDC', jsonData); |
| expect(response.statusCode, 400); |
| final encoded = await response.transform(utf8.decoder).join(); |
| final data = json.decode(encoded) as Map<String, dynamic>; |
| expect(data, isNotEmpty); |
| final error = data['error'] as Map<String, dynamic>; |
| expect(error['message'], contains('Error: Expected')); |
| } |
| }); |
| |
| test('compileFilesDDC negative-test noFiles files={}', () async { |
| for (final version in versions) { |
| final jsonData = <dynamic, dynamic>{}; |
| final response = await sendPostRequest( |
| 'dartservices/$version/compileFilesDDC', jsonData); |
| expect(response.statusCode, 400); |
| } |
| }); |
| |
| test('completeFiles files={}', () async { |
| for (final version in versions) { |
| final jsonData = { |
| 'files': {kMainDart: 'void main() {print("foo");}'}, |
| 'activeSourceName': kMainDart, |
| 'offset': 1 |
| }; |
| final response = await sendPostRequest( |
| 'dartservices/$version/completeFiles', jsonData); |
| expect(response.statusCode, 200); |
| final data = json.decode(await response.transform(utf8.decoder).join()); |
| expect(data, isNotEmpty); |
| } |
| }); |
| |
| test('completeFiles no data files={}', () async { |
| for (final version in versions) { |
| final response = await sendPostRequest( |
| 'dartservices/$version/completeFiles', <dynamic, dynamic>{}); |
| expect(response.statusCode, 400); |
| } |
| }); |
| |
| test('completeFiles param missing files={}', () async { |
| for (final version in versions) { |
| final jsonData = {'offset': 1}; |
| final response = await sendPostRequest( |
| 'dartservices/$version/completeFiles', jsonData); |
| expect(response.statusCode, 400); |
| } |
| }); |
| |
| test('completeFiles param missing 2 files={}', () async { |
| for (final version in versions) { |
| final jsonData = { |
| 'files': {kMainDart: 'void main() {print("foo");}'} |
| }; |
| final response = await sendPostRequest( |
| 'dartservices/$version/completeFiles', jsonData); |
| expect(response.statusCode, 400); |
| final encoded = await response.transform(utf8.decoder).join(); |
| final data = json.decode(encoded) as Map<String, dynamic>; |
| final error = data['error'] as Map<String, dynamic>; |
| expect(error['message'], 'Missing parameter: \'activeSourceName\''); |
| } |
| }); |
| |
| test('documentFiles files={}', () async { |
| for (final version in versions) { |
| final jsonData = { |
| 'files': {kMainDart: 'void main() {print("foo");}'}, |
| 'activeSourceName': kMainDart, |
| 'offset': 17 |
| }; |
| final response = await sendPostRequest( |
| 'dartservices/$version/documentFiles', jsonData); |
| expect(response.statusCode, 200); |
| final data = json.decode(await response.transform(utf8.decoder).join()); |
| expect(data, isNotEmpty); |
| } |
| }); |
| |
| test('documentFiles little data files={}', () async { |
| for (final version in versions) { |
| final jsonData = { |
| 'files': {kMainDart: 'void main() {print("foo");}'}, |
| 'activeSourceName': kMainDart, |
| 'offset': 2 |
| }; |
| final response = await sendPostRequest( |
| 'dartservices/$version/documentFiles', jsonData); |
| expect(response.statusCode, 200); |
| final data = json.decode(await response.transform(utf8.decoder).join()); |
| expect(data, { |
| 'info': <dynamic, dynamic>{}, |
| }); |
| } |
| }); |
| |
| test('documentFiles no data files={}', () async { |
| for (final version in versions) { |
| final jsonData = { |
| 'files': {kMainDart: 'void main() {print("foo");}'}, |
| 'activeSourceName': kMainDart, |
| 'offset': 12 |
| }; |
| final response = await sendPostRequest( |
| 'dartservices/$version/documentFiles', jsonData); |
| expect(response.statusCode, 200); |
| final data = json.decode(await response.transform(utf8.decoder).join()); |
| expect(data, {'info': <dynamic, dynamic>{}}); |
| } |
| }); |
| |
| test('documentFiles negative-test noFiles files={}', () async { |
| for (final version in versions) { |
| final jsonData = {'offset': 12}; |
| final response = await sendPostRequest( |
| 'dartservices/$version/documentFiles', jsonData); |
| expect(response.statusCode, 400); |
| } |
| }); |
| |
| test('documentFiles negative-test noActiveSourceName/noOffset files={}', |
| () async { |
| for (final version in versions) { |
| final jsonData = { |
| 'files': {kMainDart: 'void main() {print("foo");}'} |
| }; |
| final response = await sendPostRequest( |
| 'dartservices/$version/documentFiles', jsonData); |
| expect(response.statusCode, 400); |
| } |
| }); |
| |
| test('fix2 files={}', () async { |
| final quickFixesCode = ''' |
| import 'dart:async'; |
| void main() { |
| int i = 0; |
| } |
| '''; |
| for (final version in versions) { |
| final jsonData = { |
| 'files': {kMainDart: quickFixesCode}, |
| 'activeSourceName': kMainDart, |
| 'offset': 10 |
| }; |
| final response = |
| await sendPostRequest('dartservices/$version/fixesFiles', jsonData); |
| expect(response.statusCode, 200); |
| final encoded = await response.transform(utf8.decoder).join(); |
| final data = json.decode(encoded) as Map<String, dynamic>; |
| final fixes = data['fixes'] as List<dynamic>; |
| expect(fixes.length, 1); |
| final problemAndFix = fixes[0] as Map<String, dynamic>; |
| expect(problemAndFix['problemMessage'], isNotNull); |
| } |
| }); |
| |
| test('fixesFiles completeness files={}', () async { |
| for (final version in versions) { |
| final jsonData = { |
| 'files': { |
| kMainDart: ''' |
| void main() { |
| for (int i = 0; i < 4; i++) { |
| print('hello \$i') |
| } |
| } |
| ''' |
| }, |
| 'activeSourceName': kMainDart, |
| 'offset': 67, |
| }; |
| final response = |
| await sendPostRequest('dartservices/$version/fixesFiles', jsonData); |
| expect(response.statusCode, 200); |
| final data = json.decode(await response.transform(utf8.decoder).join()); |
| expect(data, { |
| 'fixes': [ |
| { |
| 'fixes': [ |
| { |
| 'message': "Insert ';'", |
| 'edits': [ |
| {'offset': 67, 'length': 0, 'replacement': ';'} |
| ] |
| } |
| ], |
| 'problemMessage': "Expected to find ';'.", |
| 'offset': 66, |
| 'length': 1 |
| } |
| ] |
| }); |
| } |
| }); |
| |
| test('assist2 files={}', () async { |
| final assistCode = ''' |
| main() { |
| int v = 0; |
| } |
| '''; |
| for (final version in versions) { |
| final jsonData = { |
| 'files': {kMainDart: assistCode}, |
| 'activeSourceName': kMainDart, |
| 'offset': 15 |
| }; |
| final response = await sendPostRequest( |
| 'dartservices/$version/assistsFiles', jsonData); |
| expect(response.statusCode, 200); |
| |
| final encoded = await response.transform(utf8.decoder).join(); |
| final data = json.decode(encoded) as Map<String, dynamic>; |
| final assists = data['assists'] as List<dynamic>; |
| if (sdk.masterChannel || sdk.betaChannel) { |
| expect(assists, hasLength(3)); |
| } else { |
| expect(assists, hasLength(2)); |
| } |
| final firstEdit = assists.first as Map<String, dynamic>; |
| expect(firstEdit['edits'], isNotNull); |
| expect(firstEdit['edits'], hasLength(1)); |
| expect(assists.where((m) { |
| final map = m as Map<String, dynamic>; |
| return map['message'] == 'Remove type annotation'; |
| }), isNotEmpty); |
| } |
| }); |
| }); |
| // End of multi file files={} tests group. |
| //------------------------------------------------------------------------- |
| } |
| |
| class MockCache implements ServerCache { |
| final _cache = HashMap<String, String>(); |
| |
| @override |
| Future<String?> get(String key) async => _cache[key]; |
| |
| @override |
| Future<void> set(String key, String value, {Duration? expiration}) async => |
| _cache[key] = value; |
| |
| @override |
| Future<void> remove(String key) async => _cache.remove(key); |
| |
| @override |
| Future<void> shutdown() async => _cache.removeWhere((key, value) => true); |
| } |