blob: 0a88cd189f2a9c22d86402913cd1682f778dcf7f [file] [log] [blame]
// Copyright (c) 2020, 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.
// @dart = 2.9
library fasta.test.textual_outline_test;
import 'dart:io';
import 'package:_fe_analyzer_shared/src/scanner/abstract_scanner.dart'
show ScannerConfiguration;
import 'package:dart_style/dart_style.dart' show DartFormatter;
import 'package:front_end/src/fasta/util/textual_outline.dart';
import 'package:testing/testing.dart'
show
Chain,
ChainContext,
Expectation,
ExpectationSet,
Result,
Step,
TestDescription,
runMe;
import '../utils/kernel_chain.dart' show MatchContext;
import 'testing/suite.dart' show UPDATE_EXPECTATIONS;
const List<Map<String, String>> EXPECTATIONS = [
{
"name": "ExpectationFileMismatch",
"group": "Fail",
},
{
"name": "ExpectationFileMissing",
"group": "Fail",
},
{
"name": "EmptyOutput",
"group": "Fail",
},
{
"name": "FormatterCrash",
"group": "Fail",
},
];
Future<Context> createContext(
Chain suite, Map<String, String> environment) async {
return new Context(environment["updateExpectations"] == "true");
}
main([List<String> arguments = const []]) =>
runMe(arguments, createContext, configurationPath: "../../testing.json");
class Context extends ChainContext with MatchContext {
final bool updateExpectations;
@override
String get updateExpectationsOption => '${UPDATE_EXPECTATIONS}=true';
@override
bool get canBeFixWithUpdateExpectations => true;
Context(this.updateExpectations);
final List<Step> steps = const <Step>[
const TextualOutline(),
];
final ExpectationSet expectationSet =
new ExpectationSet.fromJsonList(EXPECTATIONS);
}
class TextualOutline extends Step<TestDescription, TestDescription, Context> {
const TextualOutline();
String get name => "TextualOutline";
Future<Result<TestDescription>> run(
TestDescription description, Context context) async {
List<int> bytes = new File.fromUri(description.uri).readAsBytesSync();
for (bool modelled in [false, true]) {
// TODO(jensj): NNBD should be configured correctly.
String result = textualOutline(
bytes,
const ScannerConfiguration(enableExtensionMethods: true),
throwOnUnexpected: true,
performModelling: modelled,
addMarkerForUnknownForTest: modelled,
returnNullOnError: false,
);
if (result == null) {
return new Result(
null, context.expectationSet["EmptyOutput"], description.uri);
}
// In an attempt to make it less sensitive to formatting first remove
// excess new lines, then format.
List<String> lines = result.split("\n");
bool containsUnknownChunk = false;
StringBuffer sb = new StringBuffer();
for (String line in lines) {
if (line.trim() != "") {
if (line == "---- unknown chunk starts ----") {
containsUnknownChunk = true;
}
sb.writeln(line);
}
}
result = sb.toString().trim();
dynamic formatterException;
StackTrace formatterExceptionSt;
if (!containsUnknownChunk) {
// Try to format only if it doesn't contain the unknown chunk marker.
try {
result = new DartFormatter().format(result);
} catch (e, st) {
formatterException = e;
formatterExceptionSt = st;
}
}
String filename = ".textual_outline.expect";
if (modelled) {
filename = ".textual_outline_modelled.expect";
}
Result expectMatch = await context.match<TestDescription>(
filename, result, description.uri, description);
if (expectMatch.outcome != Expectation.Pass) return expectMatch;
if (formatterException != null) {
return new Result(
null, context.expectationSet["FormatterCrash"], formatterException,
trace: formatterExceptionSt);
}
}
return new Result.pass(description);
}
}