mirror of
https://github.com/dart-lang/sdk
synced 2024-09-16 00:58:29 +00:00
Start building incremental test suite
Change-Id: I38e969e494c671982ec2cba96d2657a836dd0d49 Reviewed-on: https://dart-review.googlesource.com/24122 Commit-Queue: Peter von der Ahé <ahe@google.com> Reviewed-by: Johnni Winther <johnniwinther@google.com>
This commit is contained in:
parent
a6d422957d
commit
632bba54b9
77
pkg/front_end/test/fasta/incremental_expectations.dart
Normal file
77
pkg/front_end/test/fasta/incremental_expectations.dart
Normal file
|
@ -0,0 +1,77 @@
|
|||
// 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.
|
||||
|
||||
library fasta.test.incremental_expectations;
|
||||
|
||||
import "dart:convert" show JsonDecoder, JsonEncoder;
|
||||
|
||||
const JsonEncoder json = const JsonEncoder.withIndent(" ");
|
||||
|
||||
List<IncrementalExpectation> extractJsonExpectations(String source) {
|
||||
return new List<IncrementalExpectation>.from(source
|
||||
.split("\n")
|
||||
.where((l) => l.startsWith("<<<< ") || l.startsWith("==== "))
|
||||
.map((l) => l.substring("<<<< ".length))
|
||||
.map((l) => new IncrementalExpectation.fromJson(l)));
|
||||
}
|
||||
|
||||
class IncrementalExpectation {
|
||||
final List<String> messages;
|
||||
|
||||
final bool commitChangesShouldFail;
|
||||
|
||||
final bool hasCompileTimeError;
|
||||
|
||||
const IncrementalExpectation(this.messages,
|
||||
{this.commitChangesShouldFail: false, this.hasCompileTimeError: false});
|
||||
|
||||
factory IncrementalExpectation.fromJson(String json) {
|
||||
var data = const JsonDecoder().convert(json);
|
||||
if (data is String) {
|
||||
data = <String>[data];
|
||||
}
|
||||
if (data is List) {
|
||||
return new IncrementalExpectation(data);
|
||||
}
|
||||
return new IncrementalExpectation(extractMessages(data),
|
||||
commitChangesShouldFail: extractCommitChangesShouldFail(data),
|
||||
hasCompileTimeError: extractHasCompileTimeError(data));
|
||||
}
|
||||
|
||||
toJson() {
|
||||
if (!commitChangesShouldFail && !hasCompileTimeError) {
|
||||
return messages.length == 1 ? messages.first : messages;
|
||||
}
|
||||
Map<String, dynamic> result = <String, dynamic>{
|
||||
"messages": messages,
|
||||
};
|
||||
if (commitChangesShouldFail) {
|
||||
result['commitChangesShouldFail'] = 1;
|
||||
}
|
||||
if (hasCompileTimeError) {
|
||||
result['hasCompileTimeError'] = 1;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
String toString() {
|
||||
return """
|
||||
IncrementalExpectation(
|
||||
${json.convert(messages)},
|
||||
commitChangesShouldFail: $commitChangesShouldFail,
|
||||
hasCompileTimeError: $hasCompileTimeError)""";
|
||||
}
|
||||
|
||||
static List<String> extractMessages(Map<String, dynamic> json) {
|
||||
return new List<String>.from(json["messages"]);
|
||||
}
|
||||
|
||||
static bool extractCommitChangesShouldFail(Map<String, dynamic> json) {
|
||||
return json["commitChangesShouldFail"] == 1;
|
||||
}
|
||||
|
||||
static bool extractHasCompileTimeError(Map<String, dynamic> json) {
|
||||
return json["hasCompileTimeError"] == 1;
|
||||
}
|
||||
}
|
87
pkg/front_end/test/fasta/incremental_source_files.dart
Normal file
87
pkg/front_end/test/fasta/incremental_source_files.dart
Normal file
|
@ -0,0 +1,87 @@
|
|||
// 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.md file.
|
||||
|
||||
library fasta.test.incremental_source_files;
|
||||
|
||||
/// Expand a file with diffs in common merge conflict format into a [List] that
|
||||
/// can be passed to [expandUpdates].
|
||||
///
|
||||
/// For example:
|
||||
/// first
|
||||
/// <<<<
|
||||
/// v1
|
||||
/// ====
|
||||
/// v2
|
||||
/// ====
|
||||
/// v3
|
||||
/// >>>>
|
||||
/// last
|
||||
///
|
||||
/// Would be expanded to something equivalent to:
|
||||
///
|
||||
/// ["first\n", ["v1\n", "v2\n", "v3\n"], "last\n"]
|
||||
List expandDiff(String text) {
|
||||
List result = [new StringBuffer()];
|
||||
bool inDiff = false;
|
||||
for (String line in splitLines(text)) {
|
||||
if (inDiff) {
|
||||
if (line.startsWith("====")) {
|
||||
result.last.add(new StringBuffer());
|
||||
} else if (line.startsWith(">>>>")) {
|
||||
inDiff = false;
|
||||
result.add(new StringBuffer());
|
||||
} else {
|
||||
result.last.last.write(line);
|
||||
}
|
||||
} else if (line.startsWith("<<<<")) {
|
||||
inDiff = true;
|
||||
result.add(<StringBuffer>[new StringBuffer()]);
|
||||
} else {
|
||||
result.last.write(line);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/// Returns [updates] expanded to full compilation units/source files.
|
||||
///
|
||||
/// [updates] is a convenient way to write updates/patches to a single source
|
||||
/// file without repeating common parts.
|
||||
///
|
||||
/// For example:
|
||||
/// ["head ", ["v1", "v2"], " tail"]
|
||||
/// expands to:
|
||||
/// ["head v1 tail", "head v2 tail"]
|
||||
List<String> expandUpdates(List updates) {
|
||||
int outputCount = updates.firstWhere((e) => e is Iterable).length;
|
||||
List<StringBuffer> result = new List<StringBuffer>(outputCount);
|
||||
for (int i = 0; i < outputCount; i++) {
|
||||
result[i] = new StringBuffer();
|
||||
}
|
||||
for (var chunk in updates) {
|
||||
if (chunk is Iterable) {
|
||||
int segmentCount = 0;
|
||||
for (var segment in chunk) {
|
||||
result[segmentCount++].write(segment);
|
||||
}
|
||||
if (segmentCount != outputCount) {
|
||||
throw new ArgumentError("Expected ${outputCount} segments, "
|
||||
"but found ${segmentCount} in $chunk");
|
||||
}
|
||||
} else {
|
||||
for (StringBuffer buffer in result) {
|
||||
buffer.write(chunk);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result.map((e) => '$e').toList();
|
||||
}
|
||||
|
||||
/// Split [text] into lines preserving trailing newlines (unlike
|
||||
/// String.split("\n"). Also, if [text] is empty, return an empty list (unlike
|
||||
/// String.split("\n")).
|
||||
List<String> splitLines(String text) {
|
||||
return text.split(new RegExp('^', multiLine: true));
|
||||
}
|
99
pkg/front_end/test/fasta/incremental_test.dart
Normal file
99
pkg/front_end/test/fasta/incremental_test.dart
Normal file
|
@ -0,0 +1,99 @@
|
|||
// 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.md file.
|
||||
|
||||
library fasta.test.incremental_test;
|
||||
|
||||
import "dart:async" show Future;
|
||||
|
||||
import "dart:convert" show JsonEncoder;
|
||||
|
||||
import "dart:io" show File;
|
||||
|
||||
import "package:testing/testing.dart"
|
||||
show Chain, ChainContext, Result, Step, TestDescription, runMe;
|
||||
|
||||
import "package:yaml/yaml.dart" show YamlMap, loadYamlNode;
|
||||
|
||||
import "incremental_expectations.dart"
|
||||
show IncrementalExpectation, extractJsonExpectations;
|
||||
|
||||
import "incremental_source_files.dart" show expandDiff, expandUpdates;
|
||||
|
||||
const JsonEncoder json = const JsonEncoder.withIndent(" ");
|
||||
|
||||
class Context extends ChainContext {
|
||||
final List<Step> steps = const <Step>[
|
||||
const ReadTest(),
|
||||
];
|
||||
|
||||
const Context();
|
||||
}
|
||||
|
||||
class ReadTest extends Step<TestDescription, TestCase, Context> {
|
||||
const ReadTest();
|
||||
|
||||
String get name => "read test";
|
||||
|
||||
Future<Result<TestCase>> run(
|
||||
TestDescription description, Context context) async {
|
||||
Uri uri = description.uri;
|
||||
String contents = await new File.fromUri(uri).readAsString();
|
||||
Map<String, List<String>> sources = <String, List<String>>{};
|
||||
List<IncrementalExpectation> expectations;
|
||||
bool firstPatch = true;
|
||||
YamlMap map = loadYamlNode(contents, sourceUrl: uri);
|
||||
map.forEach((_fileName, _contents) {
|
||||
String fileName = _fileName; // Strong mode hurray!
|
||||
String contents = _contents; // Strong mode hurray!
|
||||
if (fileName.endsWith(".patch")) {
|
||||
if (firstPatch) {
|
||||
expectations = extractJsonExpectations(contents);
|
||||
}
|
||||
sources[fileName] = expandUpdates(expandDiff(contents));
|
||||
firstPatch = false;
|
||||
} else {
|
||||
sources[fileName] = <String>[contents];
|
||||
}
|
||||
});
|
||||
return new TestCase(sources, expectations).validate(this);
|
||||
}
|
||||
}
|
||||
|
||||
class TestCase {
|
||||
final Map<String, List<String>> sources;
|
||||
final List<IncrementalExpectation> expectations;
|
||||
|
||||
const TestCase(this.sources, this.expectations);
|
||||
|
||||
String toString() {
|
||||
return "TestCase(${json.convert(sources)}, ${json.convert(expectations)})";
|
||||
}
|
||||
|
||||
Result<TestCase> validate(Step<dynamic, TestCase, ChainContext> step) {
|
||||
print(this);
|
||||
if (sources == null) {
|
||||
return step.fail(this, "No sources.");
|
||||
}
|
||||
if (expectations == null || expectations.isEmpty) {
|
||||
return step.fail(this, "No expectations.");
|
||||
}
|
||||
for (String name in sources.keys) {
|
||||
List<String> versions = sources[name];
|
||||
if (versions.length != 1 && versions.length != expectations.length) {
|
||||
return step.fail(
|
||||
this,
|
||||
"Found ${versions.length} versions of $name,"
|
||||
" but expected 1 or ${expectations.length}.");
|
||||
}
|
||||
}
|
||||
return step.pass(this);
|
||||
}
|
||||
}
|
||||
|
||||
Future<Context> createContext(Chain suite, Map<String, String> environment) {
|
||||
return new Future<Context>.value(const Context());
|
||||
}
|
||||
|
||||
main([List<String> arguments = const []]) =>
|
||||
runMe(arguments, createContext, "../../testing.json");
|
5
pkg/front_end/testcases/incremental.status
Normal file
5
pkg/front_end/testcases/incremental.status
Normal file
|
@ -0,0 +1,5 @@
|
|||
# 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.md file.
|
||||
|
||||
# Status file for the test suite ../test/fasta/incremental_test.dart.
|
|
@ -123,6 +123,19 @@
|
|||
]
|
||||
},
|
||||
|
||||
{
|
||||
"name": "incremental",
|
||||
"kind": "Chain",
|
||||
"source": "test/fasta/incremental_test.dart",
|
||||
"path": "testcases/",
|
||||
"status": "testcases/incremental.status",
|
||||
"pattern": [
|
||||
"\\.incremental\\.yaml$"
|
||||
],
|
||||
"exclude": [
|
||||
]
|
||||
},
|
||||
|
||||
{
|
||||
"name": "sdk",
|
||||
"kind": "Chain",
|
||||
|
|
Loading…
Reference in a new issue