76dc2c4cfa
Originally we didn't use the LSP Request/Response classes, and just exposed the handlers through the legacy request/response. However there were some mismatches (such as legacy protocol always returns Map<String, Object?> but some LSP requests return Lists, LSP using int|String IDs, and LSP having numeric error codes that don't match legacy string error codes). This change uses LSP's request and Response by wrapping them inside a standard (legacy) handler. The LSP-over-Legacy handler has become a standard handler, and the params contain an "lspMessage" field that holds an LSP message, and the result contains an "lspResponse" field that contains an LSP response. If an LSP handler returns an error, it will be returned as an error inside the LSP response, which will be in a _successful_ legacy request (since that's how we can return an LSP response - as the result). Change-Id: I67973590ab32f3543d1a6e1b7279974e5e8832bc Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/315201 Commit-Queue: Brian Wilkerson <brianwilkerson@google.com> Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
131 lines
4.4 KiB
Dart
131 lines
4.4 KiB
Dart
// Copyright (c) 2017, 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:io';
|
|
|
|
import 'package:analyzer_plugin/src/utilities/string_utilities.dart';
|
|
import 'package:path/path.dart' as path;
|
|
import 'package:test/test.dart';
|
|
|
|
import '../../tool/spec/api.dart';
|
|
import '../../tool/spec/from_html.dart';
|
|
|
|
/// Define tests to fail if there's no mention in the coverage file.
|
|
void main() {
|
|
Api api;
|
|
File coverageFile;
|
|
String pathPrefix;
|
|
|
|
// parse the API file
|
|
if (FileSystemEntity.isFileSync(
|
|
path.join('tool', 'spec', 'spec_input.html'))) {
|
|
api = readApi('.');
|
|
pathPrefix = '.';
|
|
} else {
|
|
api = readApi(path.join('pkg', 'analysis_server'));
|
|
pathPrefix = path.join('pkg', 'analysis_server');
|
|
}
|
|
|
|
coverageFile =
|
|
File(path.join(pathPrefix, 'test', 'integration', 'coverage.md'));
|
|
var lines = coverageFile.readAsLinesSync();
|
|
|
|
// ## server domain
|
|
var coveredDomains = lines
|
|
.where((line) => line.startsWith('## ') && line.endsWith(' domain'))
|
|
.map((line) =>
|
|
line.substring('##'.length, line.length - 'domain'.length).trim())
|
|
.toSet();
|
|
|
|
// Remove any ' (test failed)' suffixes.
|
|
lines = lines.map((String line) {
|
|
var index = line.indexOf('(');
|
|
return index != -1 ? line.substring(0, index).trim() : line;
|
|
}).toList();
|
|
|
|
// - [ ] server.getVersion
|
|
var allMembers = lines
|
|
.where((line) => line.startsWith('- '))
|
|
.map((line) => line.substring('- [ ]'.length).trim())
|
|
.toSet();
|
|
var coveredMembers = lines
|
|
.where((line) => line.startsWith('- [x]'))
|
|
.map((line) => line.substring('- [x]'.length).trim())
|
|
.toSet();
|
|
|
|
// generate domain tests
|
|
for (var domain in api.domains) {
|
|
group('integration coverage of ${domain.name}', () {
|
|
// domain
|
|
test('domain', () {
|
|
if (!coveredDomains.contains(domain.name)) {
|
|
fail('${domain.name} domain not found in ${coverageFile.path}');
|
|
}
|
|
});
|
|
|
|
// requests
|
|
group('request', () {
|
|
for (var request in domain.requests) {
|
|
var fullName = '${domain.name}.${request.method}';
|
|
test(fullName, () {
|
|
if (!allMembers.contains(fullName)) {
|
|
fail('$fullName not found in ${coverageFile.path}');
|
|
}
|
|
|
|
var fileName = getCamelWords(request.method)
|
|
.map((s) => s.toLowerCase())
|
|
.join('_');
|
|
var testName = path.join(domain.name, '${fileName}_test.dart');
|
|
var testPath =
|
|
path.join(pathPrefix, 'test', 'integration', testName);
|
|
|
|
// Test that if checked, a test file exists; if not checked, no such
|
|
// file exists.
|
|
var fileExists = FileSystemEntity.isFileSync(testPath);
|
|
var isMarkedAsCovered = coveredMembers.contains(fullName);
|
|
expect(fileExists, isMarkedAsCovered,
|
|
reason: isMarkedAsCovered
|
|
? '$testName marked as covered but has no test at $testPath'
|
|
: '$testName marked as not covered has test at $testPath');
|
|
});
|
|
}
|
|
});
|
|
|
|
// notifications
|
|
group('notification', () {
|
|
for (var notification in domain.notifications) {
|
|
var fullName = '${domain.name}.${notification.event}';
|
|
test(fullName, () {
|
|
if (!allMembers.contains(fullName)) {
|
|
fail('$fullName not found in ${coverageFile.path}');
|
|
}
|
|
|
|
var fileName = getCamelWords(notification.event)
|
|
.map((s) => s.toLowerCase())
|
|
.join('_');
|
|
var testName = path.join(domain.name, '${fileName}_test.dart');
|
|
var testPath =
|
|
path.join(pathPrefix, 'test', 'integration', testName);
|
|
|
|
// Test that if checked, a test file exists; if not checked, no such
|
|
// file exists.
|
|
expect(FileSystemEntity.isFileSync(testPath),
|
|
coveredMembers.contains(fullName),
|
|
reason: '$testName state incorrect');
|
|
});
|
|
}
|
|
});
|
|
});
|
|
}
|
|
|
|
// validate no unexpected domains
|
|
group('integration coverage', () {
|
|
test('no unexpected domains', () {
|
|
for (var domain in coveredDomains) {
|
|
expect(api.domains.map((d) => d.name), contains(domain));
|
|
}
|
|
});
|
|
});
|
|
}
|