Version 2.12.0-271.0.dev
Merge commit 'c9da4cb2574d1fb4afa483605fb98cdc48c480bd' into 'dev'
diff --git a/pkg/_fe_analyzer_shared/tool/smoke_test_quick.dart b/pkg/_fe_analyzer_shared/tool/smoke_test_quick.dart
index 2c7025c..c5cc34f 100644
--- a/pkg/_fe_analyzer_shared/tool/smoke_test_quick.dart
+++ b/pkg/_fe_analyzer_shared/tool/smoke_test_quick.dart
@@ -14,7 +14,7 @@
futures.add(run("pkg/front_end/test/spelling_test_src_suite.dart",
["--", "spelling_test_src/_fe_analyzer_shared/..."]));
futures.add(run(
- "pkg/front_end/test/explicit_creation_test.dart", ["--shared-only"],
+ "pkg/front_end/test/explicit_creation_git_test.dart", ["--shared-only"],
filter: false));
futures.add(run("pkg/front_end/test/lint_suite.dart",
["--", "lint/_fe_analyzer_shared/..."]));
diff --git a/pkg/analysis_server/lib/src/computer/computer_outline.dart b/pkg/analysis_server/lib/src/computer/computer_outline.dart
index e36aed7..01a7d23 100644
--- a/pkg/analysis_server/lib/src/computer/computer_outline.dart
+++ b/pkg/analysis_server/lib/src/computer/computer_outline.dart
@@ -237,23 +237,33 @@
}
Outline _newGenericTypeAliasOutline(GenericTypeAlias node) {
- var functionType = node.functionType;
- var returnType = functionType?.returnType;
var nameNode = node.name;
var name = nameNode.name;
- var parameters = functionType?.parameters;
- var parametersStr = _safeToSource(parameters);
- var returnTypeStr = _safeToSource(returnType);
+
+ var aliasedType = node.type;
+ var aliasedFunctionType =
+ aliasedType is GenericFunctionType ? aliasedType : null;
+
var element = Element(
- ElementKind.FUNCTION_TYPE_ALIAS,
- name,
- Element.makeFlags(
- isPrivate: Identifier.isPrivateName(name),
- isDeprecated: _isDeprecated(node)),
- location: _getLocationNode(nameNode),
- parameters: parametersStr,
- returnType: returnTypeStr,
- typeParameters: _getTypeParametersStr(node.typeParameters));
+ aliasedFunctionType != null
+ ? ElementKind.FUNCTION_TYPE_ALIAS
+ : ElementKind.TYPE_ALIAS,
+ name,
+ Element.makeFlags(
+ isPrivate: Identifier.isPrivateName(name),
+ isDeprecated: _isDeprecated(node),
+ ),
+ aliasedType: _safeToSource(aliasedType),
+ location: _getLocationNode(nameNode),
+ parameters: aliasedFunctionType != null
+ ? _safeToSource(aliasedFunctionType.parameters)
+ : null,
+ returnType: aliasedFunctionType != null
+ ? _safeToSource(aliasedFunctionType.returnType)
+ : null,
+ typeParameters: _getTypeParametersStr(node.typeParameters),
+ );
+
return _nodeOutline(node, element);
}
diff --git a/pkg/analysis_server/test/src/computer/outline_computer_test.dart b/pkg/analysis_server/test/src/computer/outline_computer_test.dart
index 6bdeff5..7c3ca64 100644
--- a/pkg/analysis_server/test/src/computer/outline_computer_test.dart
+++ b/pkg/analysis_server/test/src/computer/outline_computer_test.dart
@@ -17,7 +17,8 @@
});
}
-class AbstractOutlineComputerTest extends AbstractContextTest {
+class AbstractOutlineComputerTest extends AbstractContextTest
+ with WithNonFunctionTypeAliasesMixin {
String testPath;
String testCode;
@@ -471,27 +472,7 @@
}
}
- Future<void> test_genericTypeAlias_incomplete() async {
- var unitOutline = await _computeOutline('''
-typedef F = Object;
-''');
- var topOutlines = unitOutline.children;
- expect(topOutlines, hasLength(1));
- // F
- var outline_F = topOutlines[0];
- var element_F = outline_F.element;
- expect(element_F.kind, ElementKind.FUNCTION_TYPE_ALIAS);
- expect(element_F.name, 'F');
- {
- var location = element_F.location;
- expect(location.offset, testCode.indexOf('F ='));
- expect(location.length, 'F'.length);
- }
- expect(element_F.parameters, '');
- expect(element_F.returnType, '');
- }
-
- Future<void> test_genericTypeAlias_minimal() async {
+ Future<void> test_genericTypeAlias_functionType() async {
var unitOutline = await _computeOutline('''
typedef F = void Function();
''');
@@ -507,11 +488,13 @@
expect(location.offset, testCode.indexOf('F ='));
expect(location.length, 'F'.length);
}
+ expect(element_F.aliasedType, 'void Function()');
expect(element_F.parameters, '()');
expect(element_F.returnType, 'void');
+ expect(element_F.typeParameters, isNull);
}
- Future<void> test_genericTypeAlias_noReturnType() async {
+ Future<void> test_genericTypeAlias_functionType_noReturnType() async {
var unitOutline = await _computeOutline('''
typedef F = Function();
''');
@@ -527,8 +510,32 @@
expect(location.offset, testCode.indexOf('F ='));
expect(location.length, 'F'.length);
}
+ expect(element_F.aliasedType, ' Function()');
expect(element_F.parameters, '()');
expect(element_F.returnType, '');
+ expect(element_F.typeParameters, isNull);
+ }
+
+ Future<void> test_genericTypeAlias_interfaceType() async {
+ var unitOutline = await _computeOutline('''
+typedef F<T> = Map<int, T>;
+''');
+ var topOutlines = unitOutline.children;
+ expect(topOutlines, hasLength(1));
+ // F
+ var outline_F = topOutlines[0];
+ var element_F = outline_F.element;
+ expect(element_F.kind, ElementKind.TYPE_ALIAS);
+ expect(element_F.name, 'F');
+ {
+ var location = element_F.location;
+ expect(location.offset, testCode.indexOf('F<T> ='));
+ expect(location.length, 'F'.length);
+ }
+ expect(element_F.aliasedType, 'Map<int, T>');
+ expect(element_F.parameters, isNull);
+ expect(element_F.returnType, isNull);
+ expect(element_F.typeParameters, '<T>');
}
Future<void> test_groupAndTest() async {
diff --git a/pkg/analyzer/lib/src/dart/analysis/index.dart b/pkg/analyzer/lib/src/dart/analysis/index.dart
index 1df5522..821fe60 100644
--- a/pkg/analyzer/lib/src/dart/analysis/index.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/index.dart
@@ -492,9 +492,6 @@
elementKind == ElementKind.FUNCTION &&
element is FunctionElement &&
element.enclosingElement is ExecutableElement ||
- elementKind == ElementKind.PARAMETER &&
- element is ParameterElement &&
- !element.isOptional ||
false) {
return;
}
diff --git a/pkg/analyzer/test/src/dart/analysis/index_test.dart b/pkg/analyzer/test/src/dart/analysis/index_test.dart
index 1f5499e..3ba7ab9 100644
--- a/pkg/analyzer/test/src/dart/analysis/index_test.dart
+++ b/pkg/analyzer/test/src/dart/analysis/index_test.dart
@@ -17,7 +17,6 @@
main() {
defineReflectiveSuite(() {
defineReflectiveTests(IndexTest);
- defineReflectiveTests(IndexWithNonFunctionTypeAliasesTest);
});
}
@@ -35,7 +34,8 @@
}
@reflectiveTest
-class IndexTest extends PubPackageResolutionTest with _IndexMixin {
+class IndexTest extends PubPackageResolutionTest
+ with _IndexMixin, WithNonFunctionTypeAliasesMixin {
test_fieldFormalParameter_noSuchField() async {
await _indexTestUnit('''
class B<T> {
@@ -128,6 +128,18 @@
assertThat(elementObject).isExtendedAt('A {}', true, length: 0);
}
+ test_isExtendedBy_ClassDeclaration_TypeAliasElement() async {
+ await _indexTestUnit('''
+class A<T> {}
+typedef B = A<int>;
+class C extends B {}
+''');
+ var B = findElement.typeAlias('B');
+ assertThat(B)
+ ..isExtendedAt('B {}', false)
+ ..isReferencedAt('B {}', false);
+ }
+
test_isExtendedBy_ClassTypeAlias() async {
await _indexTestUnit('''
class A {}
@@ -180,6 +192,18 @@
..isReferencedAt('A {} // 2', true);
}
+ test_isImplementedBy_ClassDeclaration_TypeAliasElement() async {
+ await _indexTestUnit('''
+class A<T> {}
+typedef B = A<int>;
+class C implements B {}
+''');
+ var B = findElement.typeAlias('B');
+ assertThat(B)
+ ..isImplementedAt('B {}', false)
+ ..isReferencedAt('B {}', false);
+ }
+
test_isImplementedBy_ClassTypeAlias() async {
await _indexTestUnit('''
class A {} // 1
@@ -378,6 +402,18 @@
assertThat(element).isInvokedAt('~a', true, length: 1);
}
+ test_isMixedBy_ClassDeclaration_TypeAliasElement() async {
+ await _indexTestUnit('''
+class A<T> {}
+typedef B = A<int>;
+class C extends Object with B {}
+''');
+ var B = findElement.typeAlias('B');
+ assertThat(B)
+ ..isMixedInAt('B {}', false)
+ ..isReferencedAt('B {}', false);
+ }
+
test_isMixedInBy_ClassDeclaration_class() async {
await _indexTestUnit('''
class A {} // 1
@@ -517,6 +553,16 @@
assertThat(element).isReferencedAt('A();', false);
}
+ test_isReferencedBy_ClassElement_inTypeAlias() async {
+ await _indexTestUnit('''
+class A<T> {}
+
+typedef B = A<int>;
+''');
+ assertThat(findElement.class_('A')).isReferencedAt('A<int', false);
+ assertThat(intElement).isReferencedAt('int>;', false);
+ }
+
test_isReferencedBy_ClassElement_invocation_isQualified() async {
newFile('$testPackageLibPath/lib.dart', content: '''
class A {}
@@ -961,7 +1007,7 @@
test_isReferencedBy_ParameterElement_genericFunctionType() async {
await _indexTestUnit('''
-typedef F = void Function({int p});
+typedef F = void Function({int? p});
void main(F f) {
f(p: 0);
@@ -973,7 +1019,7 @@
test_isReferencedBy_ParameterElement_genericFunctionType_call() async {
await _indexTestUnit('''
-typedef F<T> = void Function({T test});
+typedef F<T> = void Function({T? test});
main(F<int> f) {
f.call(test: 0);
@@ -984,10 +1030,10 @@
test_isReferencedBy_ParameterElement_multiplyDefined_generic() async {
newFile('/test/lib/a.dart', content: r'''
-void foo<T>({T a}) {}
+void foo<T>({T? a}) {}
''');
newFile('/test/lib/b.dart', content: r'''
-void foo<T>({T a}) {}
+void foo<T>({T? a}) {}
''');
await _indexTestUnit(r"""
import 'a.dart';
@@ -1000,10 +1046,10 @@
// No exceptions.
}
- test_isReferencedBy_ParameterElement_named_ofConstructor_genericClass() async {
+ test_isReferencedBy_ParameterElement_optionalNamed_ofConstructor_genericClass() async {
await _indexTestUnit('''
class A<T> {
- A({T test});
+ A({T? test});
}
main() {
@@ -1014,10 +1060,10 @@
assertThat(element)..isReferencedAt('test: 0', true);
}
- test_isReferencedBy_ParameterElement_named_ofMethod_genericClass() async {
+ test_isReferencedBy_ParameterElement_optionalNamed_ofMethod_genericClass() async {
await _indexTestUnit('''
class A<T> {
- void foo({T test}) {}
+ void foo({T? test}) {}
}
main(A<int> a) {
@@ -1028,6 +1074,18 @@
assertThat(element)..isReferencedAt('test: 0', true);
}
+ test_isReferencedBy_ParameterElement_optionalNamed_ofTopFunction() async {
+ await _indexTestUnit('''
+void foo({int? test}) {}
+
+void() {
+ foo(test: 0);
+}
+''');
+ Element element = findElement.parameter('test');
+ assertThat(element)..isReferencedAt('test: 0', true);
+ }
+
test_isReferencedBy_ParameterElement_optionalPositional() async {
await _indexTestUnit('''
foo([p]) {
@@ -1043,6 +1101,18 @@
..isReferencedAt('1); // 2', true, length: 0);
}
+ test_isReferencedBy_ParameterElement_requiredNamed_ofTopFunction() async {
+ await _indexTestUnit('''
+void foo({required int test}) {}
+
+void() {
+ foo(test: 0);
+}
+''');
+ Element element = findElement.parameter('test');
+ assertThat(element)..isReferencedAt('test: 0', true);
+ }
+
test_isReferencedBy_PropertyAccessor_ofNamedExtension_instance() async {
await _indexTestUnit('''
extension E on int {
@@ -1173,6 +1243,33 @@
assertThat(element).isReferencedAt('V;', true);
}
+ test_isReferencedBy_TypeAliasElement() async {
+ await _indexTestUnit('''
+class A<T> {
+ static int field = 0;
+ static void method() {}
+}
+
+typedef B = A<int>;
+
+void f(B p) {
+ B v;
+ B(); // 2
+ B.field = 1;
+ B.field; // 3
+ B.method(); // 4
+}
+''');
+ var element = findElement.typeAlias('B');
+ assertThat(element)
+ ..isReferencedAt('B p) {', false)
+ ..isReferencedAt('B v;', false)
+ ..isReferencedAt('B(); // 2', false)
+ ..isReferencedAt('B.field = 1;', false)
+ ..isReferencedAt('B.field; // 3', false)
+ ..isReferencedAt('B.method(); // 4', false);
+ }
+
test_isReferencedBy_typeInVariableList() async {
await _indexTestUnit('''
class A {}
@@ -1397,83 +1494,6 @@
}
}
-@reflectiveTest
-class IndexWithNonFunctionTypeAliasesTest extends PubPackageResolutionTest
- with WithNonFunctionTypeAliasesMixin, _IndexMixin {
- test_isExtendedBy_ClassDeclaration_TypeAliasElement() async {
- await _indexTestUnit('''
-class A<T> {}
-typedef B = A<int>;
-class C extends B {}
-''');
- var B = findElement.typeAlias('B');
- assertThat(B)
- ..isExtendedAt('B {}', false)
- ..isReferencedAt('B {}', false);
- }
-
- test_isImplementedBy_ClassDeclaration_TypeAliasElement() async {
- await _indexTestUnit('''
-class A<T> {}
-typedef B = A<int>;
-class C implements B {}
-''');
- var B = findElement.typeAlias('B');
- assertThat(B)
- ..isImplementedAt('B {}', false)
- ..isReferencedAt('B {}', false);
- }
-
- test_isMixedBy_ClassDeclaration_TypeAliasElement() async {
- await _indexTestUnit('''
-class A<T> {}
-typedef B = A<int>;
-class C extends Object with B {}
-''');
- var B = findElement.typeAlias('B');
- assertThat(B)
- ..isMixedInAt('B {}', false)
- ..isReferencedAt('B {}', false);
- }
-
- test_isReferencedBy_ClassElement_inTypeAlias() async {
- await _indexTestUnit('''
-class A<T> {}
-
-typedef B = A<int>;
-''');
- assertThat(findElement.class_('A')).isReferencedAt('A<int', false);
- assertThat(intElement).isReferencedAt('int>;', false);
- }
-
- test_isReferencedBy_TypeAliasElement() async {
- await _indexTestUnit('''
-class A<T> {
- static int field = 0;
- static void method() {}
-}
-
-typedef B = A<int>;
-
-void f(B p) {
- B v;
- B(); // 2
- B.field = 1;
- B.field; // 3
- B.method(); // 4
-}
-''');
- var element = findElement.typeAlias('B');
- assertThat(element)
- ..isReferencedAt('B p) {', false)
- ..isReferencedAt('B v;', false)
- ..isReferencedAt('B(); // 2', false)
- ..isReferencedAt('B.field = 1;', false)
- ..isReferencedAt('B.field; // 3', false)
- ..isReferencedAt('B.method(); // 4', false);
- }
-}
-
class _ElementIndexAssert {
final _IndexMixin test;
final Element element;
diff --git a/pkg/analyzer/test/src/diagnostics/non_constant_type_argument_test.dart b/pkg/analyzer/test/src/diagnostics/non_constant_type_argument_test.dart
index f783c71..b94d780 100644
--- a/pkg/analyzer/test/src/diagnostics/non_constant_type_argument_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/non_constant_type_argument_test.dart
@@ -9,53 +9,12 @@
main() {
defineReflectiveSuite(() {
- defineReflectiveTests(NonConstantTypeArgumentNoWarningTest);
- defineReflectiveTests(NonConstantTypeArgumentNoWarningTest2);
defineReflectiveTests(NonConstantTypeArgumentTest);
defineReflectiveTests(NonConstantTypeArgumentWarningTest);
});
}
@reflectiveTest
-class NonConstantTypeArgumentNoWarningTest extends PubPackageResolutionTest {
- test_asFunction_R() async {
- await assertNoErrorsInCode(r'''
-import 'dart:ffi';
-
-class MyStruct extends Struct {
- @Uint8()
- int myField;
-}
-
-void main(){
- final pointer = Pointer<MyStruct>.fromAddress(0);
- pointer.ref.myField = 1;
-}
-''');
- }
-}
-
-@reflectiveTest
-class NonConstantTypeArgumentNoWarningTest2 extends PubPackageResolutionTest {
- test_asFunction_R() async {
- await assertNoErrorsInCode(r'''
-import 'dart:ffi';
-
-class MyStruct extends Struct {
- @Uint8()
- int myField;
-}
-
-void main(){
- final pointer = Pointer<MyStruct>.fromAddress(0)
- ..ref.myField = 1;
- print(pointer);
-}
-''');
- }
-}
-
-@reflectiveTest
class NonConstantTypeArgumentTest extends PubPackageResolutionTest {
test_asFunction_R() async {
await assertErrorsInCode(r'''
@@ -74,7 +33,40 @@
@reflectiveTest
class NonConstantTypeArgumentWarningTest extends PubPackageResolutionTest {
- test_asFunction_R() async {
+ test_ref_class() async {
+ await assertNoErrorsInCode(r'''
+import 'dart:ffi';
+
+class MyStruct extends Struct {
+ @Uint8()
+ int myField;
+}
+
+void main() {
+ final pointer = Pointer<MyStruct>.fromAddress(0);
+ pointer.ref.myField = 1;
+}
+''');
+ }
+
+ test_ref_class_cascade() async {
+ await assertNoErrorsInCode(r'''
+import 'dart:ffi';
+
+class MyStruct extends Struct {
+ @Uint8()
+ int myField;
+}
+
+void main() {
+ final pointer = Pointer<MyStruct>.fromAddress(0)
+ ..ref.myField = 1;
+ print(pointer);
+}
+''');
+ }
+
+ test_ref_typeParameter() async {
await assertErrorsInCode(r'''
import 'dart:ffi';
diff --git a/pkg/front_end/test/binary_md_vm_tags_and_version_test.dart b/pkg/front_end/test/binary_md_vm_tags_and_version_git_test.dart
similarity index 100%
rename from pkg/front_end/test/binary_md_vm_tags_and_version_test.dart
rename to pkg/front_end/test/binary_md_vm_tags_and_version_git_test.dart
diff --git a/pkg/front_end/test/deps_test.dart b/pkg/front_end/test/deps_git_test.dart
similarity index 100%
rename from pkg/front_end/test/deps_test.dart
rename to pkg/front_end/test/deps_git_test.dart
diff --git a/pkg/front_end/test/explicit_creation_test.dart b/pkg/front_end/test/explicit_creation_git_test.dart
similarity index 100%
rename from pkg/front_end/test/explicit_creation_test.dart
rename to pkg/front_end/test/explicit_creation_git_test.dart
diff --git a/pkg/front_end/test/fasta/analyze_test.dart b/pkg/front_end/test/fasta/analyze_git_test.dart
similarity index 100%
rename from pkg/front_end/test/fasta/analyze_test.dart
rename to pkg/front_end/test/fasta/analyze_git_test.dart
diff --git a/pkg/front_end/test/fasta/analyze_src_with_lints_test.dart b/pkg/front_end/test/fasta/analyze_src_with_lints_git_test.dart
similarity index 100%
rename from pkg/front_end/test/fasta/analyze_src_with_lints_test.dart
rename to pkg/front_end/test/fasta/analyze_src_with_lints_git_test.dart
diff --git a/pkg/front_end/test/fasta/tool_test.dart b/pkg/front_end/test/fasta/tool_git_test.dart
similarity index 100%
rename from pkg/front_end/test/fasta/tool_test.dart
rename to pkg/front_end/test/fasta/tool_git_test.dart
diff --git a/pkg/front_end/test/language_versioning/language_versioning_up_to_date_test.dart b/pkg/front_end/test/language_versioning/language_versioning_up_to_date_git_test.dart
similarity index 100%
rename from pkg/front_end/test/language_versioning/language_versioning_up_to_date_test.dart
rename to pkg/front_end/test/language_versioning/language_versioning_up_to_date_git_test.dart
diff --git a/pkg/front_end/test/read_dill_from_binary_md_test.dart b/pkg/front_end/test/read_dill_from_binary_md_git_test.dart
similarity index 100%
rename from pkg/front_end/test/read_dill_from_binary_md_test.dart
rename to pkg/front_end/test/read_dill_from_binary_md_git_test.dart
diff --git a/pkg/front_end/test/unit_test_suites.dart b/pkg/front_end/test/unit_test_suites.dart
index fde99ac..3968363 100644
--- a/pkg/front_end/test/unit_test_suites.dart
+++ b/pkg/front_end/test/unit_test_suites.dart
@@ -1,432 +1,11 @@
-// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2021, 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
-import 'dart:async' show Timer;
-import 'dart:convert' show jsonEncode;
-import 'dart:io' show File, Platform, exitCode;
-import 'dart:isolate' show Isolate, ReceivePort, SendPort;
+// This is a work-around for the automagically selecting weak/strong mode.
+// By marking this file (the entry) as non-nnbd, it becomes weak mode which
+// is required because many of the imports are not (yet) nnbd.
-import 'package:args/args.dart' show ArgParser;
-import 'package:testing/src/chain.dart' show CreateContext, Result, Step;
-import 'package:testing/src/expectation.dart' show Expectation;
-import 'package:testing/src/log.dart' show Logger;
-import 'package:testing/src/run.dart' show runMe;
-import 'package:testing/src/suite.dart' as testing show Suite;
-import 'package:testing/src/test_description.dart' show TestDescription;
-
-import 'fasta/expression_suite.dart' as expression show createContext;
-import 'fasta/fast_strong_suite.dart' as fast_strong show createContext;
-import 'fasta/incremental_suite.dart' as incremental show createContext;
-import 'fasta/messages_suite.dart' as messages show createContext;
-import 'fasta/outline_suite.dart' as outline show createContext;
-import 'fasta/strong_tester.dart' as strong show createContext;
-import 'fasta/text_serialization_tester.dart' as text_serialization
- show createContext;
-import 'fasta/textual_outline_suite.dart' as textual_outline show createContext;
-import 'fasta/weak_suite.dart' as weak show createContext;
-import 'incremental_bulk_compiler_smoke_suite.dart' as incremental_bulk_compiler
- show createContext;
-import 'incremental_load_from_dill_suite.dart' as incremental_load
- show createContext;
-import 'lint_suite.dart' as lint show createContext;
-import 'parser_suite.dart' as parser show createContext;
-import 'parser_all_suite.dart' as parserAll show createContext;
-import 'spelling_test_not_src_suite.dart' as spelling_not_src
- show createContext;
-import 'spelling_test_src_suite.dart' as spelling_src show createContext;
-
-const suiteNamePrefix = "pkg/front_end/test";
-
-class Options {
- final String configurationName;
- final bool verbose;
- final bool printFailureLog;
- final Uri outputDirectory;
- final String testFilter;
- final List<String> environmentOptions;
-
- Options(this.configurationName, this.verbose, this.printFailureLog,
- this.outputDirectory, this.testFilter, this.environmentOptions);
-
- static Options parse(List<String> args) {
- var parser = new ArgParser()
- ..addOption("named-configuration",
- abbr: "n",
- help: "configuration name to use for emitting json result files")
- ..addOption("output-directory",
- help: "directory to which results.json and logs.json are written")
- ..addFlag("verbose",
- abbr: "v", help: "print additional information", defaultsTo: false)
- ..addFlag("print",
- abbr: "p", help: "print failure logs", defaultsTo: false)
- ..addMultiOption('environment',
- abbr: 'D', help: "environment options for the test suite");
- var parsedArguments = parser.parse(args);
- String outputPath = parsedArguments["output-directory"] ?? ".";
- Uri outputDirectory = Uri.base.resolveUri(Uri.directory(outputPath));
- String filter;
- if (parsedArguments.rest.length == 1) {
- filter = parsedArguments.rest.single;
- if (filter.startsWith("$suiteNamePrefix/")) {
- filter = filter.substring(suiteNamePrefix.length + 1);
- }
- }
- return Options(
- parsedArguments["named-configuration"],
- parsedArguments["verbose"],
- parsedArguments["print"],
- outputDirectory,
- filter,
- parsedArguments['environment']);
- }
-}
-
-class ResultLogger implements Logger {
- final String prefix;
- final bool verbose;
- final bool printFailureLog;
- final SendPort resultsPort;
- final SendPort logsPort;
- final Map<String, Stopwatch> stopwatches = {};
- final String configurationName;
- final Set<String> seenTests = {};
-
- ResultLogger(this.prefix, this.resultsPort, this.logsPort, this.verbose,
- this.printFailureLog, this.configurationName);
-
- String getTestName(TestDescription description) {
- return "$prefix/${description.shortName}";
- }
-
- @override
- void logMessage(Object message) {}
-
- @override
- void logNumberedLines(String text) {}
-
- @override
- void logProgress(String message) {}
-
- @override
- void logStepComplete(int completed, int failed, int total,
- testing.Suite suite, TestDescription description, Step step) {}
-
- @override
- void logStepStart(int completed, int failed, int total, testing.Suite suite,
- TestDescription description, Step step) {}
-
- @override
- void logSuiteStarted(testing.Suite suite) {}
-
- @override
- void logSuiteComplete(testing.Suite suite) {}
-
- handleTestResult(TestDescription testDescription, Result result,
- String fullSuiteName, bool matchedExpectations) {
- String testName = getTestName(testDescription);
- String suite = "pkg";
- String shortTestName = testName.substring(suite.length + 1);
- resultsPort.send(jsonEncode({
- "name": testName,
- "configuration": configurationName,
- "suite": suite,
- "test_name": shortTestName,
- "time_ms": stopwatches[testName].elapsedMilliseconds,
- "expected": "Pass",
- "result": matchedExpectations ? "Pass" : "Fail",
- "matches": matchedExpectations,
- }));
- if (!matchedExpectations) {
- StringBuffer sb = new StringBuffer();
- sb.write(result.log);
- if (result.error != null) {
- sb.write("\n\n${result.error}");
- }
- if (result.trace != null) {
- sb.write("\n\n${result.trace}");
- }
- sb.write("\n\nTo re-run this test, run:");
- sb.write("\n\n dart pkg/front_end/test/unit_test_suites.dart -p "
- "$testName");
- if (result.autoFixCommand != null) {
- sb.write("\n\nTo automatically update the test expectations, run:");
- sb.write("\n\n dart pkg/front_end/test/unit_test_suites.dart -p "
- "$testName -D${result.autoFixCommand}");
- if (result.canBeFixWithUpdateExpectations) {
- sb.write('\n\nTo update test expectations for all tests at once, '
- 'run:');
- sb.write('\n\n dart pkg/front_end/tool/update_expectations.dart');
- sb.write('\n\nNote that this takes a long time and should only be '
- 'used when many tests need updating.\n');
- }
- }
- String failureLog = sb.toString();
- String outcome = "${result.outcome}";
- logsPort.send(jsonEncode({
- "name": testName,
- "configuration": configurationName,
- "result": outcome,
- "log": failureLog,
- }));
- if (printFailureLog) {
- print('FAILED: $testName: $outcome');
- print(failureLog);
- }
- }
- if (verbose) {
- String result = matchedExpectations ? "PASS" : "FAIL";
- print("${testName}: ${result}");
- }
- }
-
- void logTestStart(int completed, int failed, int total, testing.Suite suite,
- TestDescription description) {
- String name = getTestName(description);
- stopwatches[name] = Stopwatch()..start();
- }
-
- @override
- void logTestComplete(int completed, int failed, int total,
- testing.Suite suite, TestDescription description) {}
-
- @override
- void logUncaughtError(error, StackTrace stackTrace) {}
-
- void logExpectedResult(testing.Suite suite, TestDescription description,
- Result result, Set<Expectation> expectedOutcomes) {
- handleTestResult(description, result, prefix, true);
- }
-
- @override
- void logUnexpectedResult(testing.Suite suite, TestDescription description,
- Result result, Set<Expectation> expectedOutcomes) {
- // The test framework (pkg/testing) calls the logger with an unexpected
- // results a second time to create a summary. We ignore the second call
- // here.
- String testName = getTestName(description);
- if (seenTests.contains(testName)) return;
- seenTests.add(testName);
- handleTestResult(description, result, prefix, false);
- }
-}
-
-class Suite {
- final String name;
- final CreateContext createContext;
- final String testingRootPath;
- final String path;
- final int shardCount;
- final int shard;
- final String prefix;
-
- const Suite(this.name, this.createContext, this.testingRootPath,
- {this.path, this.shardCount: 1, this.shard: 0, String prefix})
- : prefix = prefix ?? name;
-}
-
-const List<Suite> suites = [
- const Suite(
- "fasta/expression", expression.createContext, "../../testing.json"),
- const Suite("fasta/outline", outline.createContext, "../../testing.json"),
- const Suite(
- "fasta/fast_strong", fast_strong.createContext, "../../testing.json"),
- const Suite(
- "fasta/incremental", incremental.createContext, "../../testing.json"),
- const Suite("fasta/messages", messages.createContext, "../../testing.json"),
- const Suite("fasta/text_serialization1", text_serialization.createContext,
- "../../testing.json",
- path: "fasta/text_serialization_tester.dart",
- shardCount: 4,
- shard: 0,
- prefix: "fasta/text_serialization"),
- const Suite("fasta/text_serialization2", text_serialization.createContext,
- "../../testing.json",
- path: "fasta/text_serialization_tester.dart",
- shardCount: 4,
- shard: 1,
- prefix: "fasta/text_serialization"),
- const Suite("fasta/text_serialization3", text_serialization.createContext,
- "../../testing.json",
- path: "fasta/text_serialization_tester.dart",
- shardCount: 4,
- shard: 2,
- prefix: "fasta/text_serialization"),
- const Suite("fasta/text_serialization4", text_serialization.createContext,
- "../../testing.json",
- path: "fasta/text_serialization_tester.dart",
- shardCount: 4,
- shard: 3,
- prefix: "fasta/text_serialization"),
- const Suite("fasta/strong1", strong.createContext, "../../testing.json",
- path: "fasta/strong_tester.dart",
- shardCount: 4,
- shard: 0,
- prefix: "fasta/strong"),
- const Suite("fasta/strong2", strong.createContext, "../../testing.json",
- path: "fasta/strong_tester.dart",
- shardCount: 4,
- shard: 1,
- prefix: "fasta/strong"),
- const Suite("fasta/strong3", strong.createContext, "../../testing.json",
- path: "fasta/strong_tester.dart",
- shardCount: 4,
- shard: 2,
- prefix: "fasta/strong"),
- const Suite("fasta/strong4", strong.createContext, "../../testing.json",
- path: "fasta/strong_tester.dart",
- shardCount: 4,
- shard: 3,
- prefix: "fasta/strong"),
- const Suite("incremental_bulk_compiler_smoke",
- incremental_bulk_compiler.createContext, "../testing.json"),
- const Suite("incremental_load_from_dill", incremental_load.createContext,
- "../testing.json"),
- const Suite("lint", lint.createContext, "../testing.json"),
- const Suite("parser", parser.createContext, "../testing.json"),
- const Suite("parser_all", parserAll.createContext, "../testing.json"),
- const Suite("spelling_test_not_src", spelling_not_src.createContext,
- "../testing.json"),
- const Suite(
- "spelling_test_src", spelling_src.createContext, "../testing.json"),
- const Suite("fasta/weak", weak.createContext, "../../testing.json"),
- const Suite("fasta/textual_outline", textual_outline.createContext,
- "../../testing.json"),
-];
-
-const Duration timeoutDuration = Duration(minutes: 30);
-
-class SuiteConfiguration {
- final String name;
- final SendPort resultsPort;
- final SendPort logsPort;
- final bool verbose;
- final bool printFailureLog;
- final String configurationName;
- final String testFilter;
- final List<String> environmentOptions;
-
- const SuiteConfiguration(
- this.name,
- this.resultsPort,
- this.logsPort,
- this.verbose,
- this.printFailureLog,
- this.configurationName,
- this.testFilter,
- this.environmentOptions);
-}
-
-void runSuite(SuiteConfiguration configuration) {
- Suite suite = suites.where((s) => s.name == configuration.name).single;
- String name = suite.prefix;
- String fullSuiteName = "$suiteNamePrefix/$name";
- Uri suiteUri = Platform.script.resolve(suite.path ?? "${name}_suite.dart");
- if (!new File.fromUri(suiteUri).existsSync()) {
- throw "File doesn't exist: $suiteUri";
- }
- ResultLogger logger = ResultLogger(
- fullSuiteName,
- configuration.resultsPort,
- configuration.logsPort,
- configuration.verbose,
- configuration.printFailureLog,
- configuration.configurationName);
- runMe(<String>[
- if (configuration.testFilter != null) configuration.testFilter,
- if (configuration.environmentOptions != null)
- for (String option in configuration.environmentOptions) '-D${option}',
- ], suite.createContext,
- me: suiteUri,
- configurationPath: suite.testingRootPath,
- logger: logger,
- shards: suite.shardCount,
- shard: suite.shard);
-}
-
-void writeLinesToFile(Uri uri, List<String> lines) async {
- await File.fromUri(uri).writeAsString(lines.map((line) => "$line\n").join());
-}
-
-main([List<String> arguments = const <String>[]]) async {
- List<String> results = [];
- List<String> logs = [];
- Options options = Options.parse(arguments);
- ReceivePort resultsPort = new ReceivePort()
- ..listen((resultEntry) => results.add(resultEntry));
- ReceivePort logsPort = new ReceivePort()
- ..listen((logEntry) => logs.add(logEntry));
- List<Future<bool>> futures = [];
- // Run test suites and record the results and possible failure logs.
- for (Suite suite in suites) {
- String name = suite.name;
- String filter = options.testFilter;
- if (filter != null) {
- // Skip suites that are not hit by the test filter, is there is one.
- if (!filter.startsWith(suite.prefix)) {
- continue;
- }
- // Remove the 'fasta/' from filters, if there, because it is not used
- // in the name defined in testing.json.
- if (filter.startsWith("fasta/")) {
- filter = filter.substring("fasta/".length);
- }
- }
- // Start the test suite in a new isolate.
- ReceivePort exitPort = new ReceivePort();
- SuiteConfiguration configuration = SuiteConfiguration(
- name,
- resultsPort.sendPort,
- logsPort.sendPort,
- options.verbose,
- options.printFailureLog,
- options.configurationName,
- filter,
- options.environmentOptions);
- Future future = Future<bool>(() async {
- Stopwatch stopwatch = Stopwatch()..start();
- print("Running suite $name");
- Isolate isolate = await Isolate.spawn<SuiteConfiguration>(
- runSuite, configuration,
- onExit: exitPort.sendPort);
- bool timedOut = false;
- Timer timer = Timer(timeoutDuration, () {
- timedOut = true;
- print("Suite $name timed out after "
- "${timeoutDuration.inMilliseconds}ms");
- isolate.kill(priority: Isolate.immediate);
- });
- await exitPort.first;
- timer.cancel();
- if (!timedOut) {
- int seconds = stopwatch.elapsedMilliseconds ~/ 1000;
- print("Suite $name finished (took ${seconds} seconds)");
- }
- return timedOut;
- });
- futures.add(future);
- }
- // Wait for isolates to terminate and clean up.
- Iterable<bool> timeouts = await Future.wait(futures);
- resultsPort.close();
- logsPort.close();
- // Write results.json and logs.json.
- Uri resultJsonUri = options.outputDirectory.resolve("results.json");
- Uri logsJsonUri = options.outputDirectory.resolve("logs.json");
- await writeLinesToFile(resultJsonUri, results);
- await writeLinesToFile(logsJsonUri, logs);
- print("Log files written to ${resultJsonUri.toFilePath()} and"
- " ${logsJsonUri.toFilePath()}");
- // Return with exit code 1 if at least one suite timed out.
- bool timeout = timeouts.any((timeout) => timeout);
- if (timeout) {
- exitCode = 1;
- } else {
- // The testing framework (package:testing) sets the exitCode to `1` if any
- // test failed, so we reset it here to indicate that the test runner was
- // successful.
- exitCode = 0;
- }
-}
+export 'unit_test_suites_impl.dart';
diff --git a/pkg/front_end/test/unit_test_suites_impl.dart b/pkg/front_end/test/unit_test_suites_impl.dart
new file mode 100644
index 0000000..fde99ac
--- /dev/null
+++ b/pkg/front_end/test/unit_test_suites_impl.dart
@@ -0,0 +1,432 @@
+// Copyright (c) 2019, 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
+
+import 'dart:async' show Timer;
+import 'dart:convert' show jsonEncode;
+import 'dart:io' show File, Platform, exitCode;
+import 'dart:isolate' show Isolate, ReceivePort, SendPort;
+
+import 'package:args/args.dart' show ArgParser;
+import 'package:testing/src/chain.dart' show CreateContext, Result, Step;
+import 'package:testing/src/expectation.dart' show Expectation;
+import 'package:testing/src/log.dart' show Logger;
+import 'package:testing/src/run.dart' show runMe;
+import 'package:testing/src/suite.dart' as testing show Suite;
+import 'package:testing/src/test_description.dart' show TestDescription;
+
+import 'fasta/expression_suite.dart' as expression show createContext;
+import 'fasta/fast_strong_suite.dart' as fast_strong show createContext;
+import 'fasta/incremental_suite.dart' as incremental show createContext;
+import 'fasta/messages_suite.dart' as messages show createContext;
+import 'fasta/outline_suite.dart' as outline show createContext;
+import 'fasta/strong_tester.dart' as strong show createContext;
+import 'fasta/text_serialization_tester.dart' as text_serialization
+ show createContext;
+import 'fasta/textual_outline_suite.dart' as textual_outline show createContext;
+import 'fasta/weak_suite.dart' as weak show createContext;
+import 'incremental_bulk_compiler_smoke_suite.dart' as incremental_bulk_compiler
+ show createContext;
+import 'incremental_load_from_dill_suite.dart' as incremental_load
+ show createContext;
+import 'lint_suite.dart' as lint show createContext;
+import 'parser_suite.dart' as parser show createContext;
+import 'parser_all_suite.dart' as parserAll show createContext;
+import 'spelling_test_not_src_suite.dart' as spelling_not_src
+ show createContext;
+import 'spelling_test_src_suite.dart' as spelling_src show createContext;
+
+const suiteNamePrefix = "pkg/front_end/test";
+
+class Options {
+ final String configurationName;
+ final bool verbose;
+ final bool printFailureLog;
+ final Uri outputDirectory;
+ final String testFilter;
+ final List<String> environmentOptions;
+
+ Options(this.configurationName, this.verbose, this.printFailureLog,
+ this.outputDirectory, this.testFilter, this.environmentOptions);
+
+ static Options parse(List<String> args) {
+ var parser = new ArgParser()
+ ..addOption("named-configuration",
+ abbr: "n",
+ help: "configuration name to use for emitting json result files")
+ ..addOption("output-directory",
+ help: "directory to which results.json and logs.json are written")
+ ..addFlag("verbose",
+ abbr: "v", help: "print additional information", defaultsTo: false)
+ ..addFlag("print",
+ abbr: "p", help: "print failure logs", defaultsTo: false)
+ ..addMultiOption('environment',
+ abbr: 'D', help: "environment options for the test suite");
+ var parsedArguments = parser.parse(args);
+ String outputPath = parsedArguments["output-directory"] ?? ".";
+ Uri outputDirectory = Uri.base.resolveUri(Uri.directory(outputPath));
+ String filter;
+ if (parsedArguments.rest.length == 1) {
+ filter = parsedArguments.rest.single;
+ if (filter.startsWith("$suiteNamePrefix/")) {
+ filter = filter.substring(suiteNamePrefix.length + 1);
+ }
+ }
+ return Options(
+ parsedArguments["named-configuration"],
+ parsedArguments["verbose"],
+ parsedArguments["print"],
+ outputDirectory,
+ filter,
+ parsedArguments['environment']);
+ }
+}
+
+class ResultLogger implements Logger {
+ final String prefix;
+ final bool verbose;
+ final bool printFailureLog;
+ final SendPort resultsPort;
+ final SendPort logsPort;
+ final Map<String, Stopwatch> stopwatches = {};
+ final String configurationName;
+ final Set<String> seenTests = {};
+
+ ResultLogger(this.prefix, this.resultsPort, this.logsPort, this.verbose,
+ this.printFailureLog, this.configurationName);
+
+ String getTestName(TestDescription description) {
+ return "$prefix/${description.shortName}";
+ }
+
+ @override
+ void logMessage(Object message) {}
+
+ @override
+ void logNumberedLines(String text) {}
+
+ @override
+ void logProgress(String message) {}
+
+ @override
+ void logStepComplete(int completed, int failed, int total,
+ testing.Suite suite, TestDescription description, Step step) {}
+
+ @override
+ void logStepStart(int completed, int failed, int total, testing.Suite suite,
+ TestDescription description, Step step) {}
+
+ @override
+ void logSuiteStarted(testing.Suite suite) {}
+
+ @override
+ void logSuiteComplete(testing.Suite suite) {}
+
+ handleTestResult(TestDescription testDescription, Result result,
+ String fullSuiteName, bool matchedExpectations) {
+ String testName = getTestName(testDescription);
+ String suite = "pkg";
+ String shortTestName = testName.substring(suite.length + 1);
+ resultsPort.send(jsonEncode({
+ "name": testName,
+ "configuration": configurationName,
+ "suite": suite,
+ "test_name": shortTestName,
+ "time_ms": stopwatches[testName].elapsedMilliseconds,
+ "expected": "Pass",
+ "result": matchedExpectations ? "Pass" : "Fail",
+ "matches": matchedExpectations,
+ }));
+ if (!matchedExpectations) {
+ StringBuffer sb = new StringBuffer();
+ sb.write(result.log);
+ if (result.error != null) {
+ sb.write("\n\n${result.error}");
+ }
+ if (result.trace != null) {
+ sb.write("\n\n${result.trace}");
+ }
+ sb.write("\n\nTo re-run this test, run:");
+ sb.write("\n\n dart pkg/front_end/test/unit_test_suites.dart -p "
+ "$testName");
+ if (result.autoFixCommand != null) {
+ sb.write("\n\nTo automatically update the test expectations, run:");
+ sb.write("\n\n dart pkg/front_end/test/unit_test_suites.dart -p "
+ "$testName -D${result.autoFixCommand}");
+ if (result.canBeFixWithUpdateExpectations) {
+ sb.write('\n\nTo update test expectations for all tests at once, '
+ 'run:');
+ sb.write('\n\n dart pkg/front_end/tool/update_expectations.dart');
+ sb.write('\n\nNote that this takes a long time and should only be '
+ 'used when many tests need updating.\n');
+ }
+ }
+ String failureLog = sb.toString();
+ String outcome = "${result.outcome}";
+ logsPort.send(jsonEncode({
+ "name": testName,
+ "configuration": configurationName,
+ "result": outcome,
+ "log": failureLog,
+ }));
+ if (printFailureLog) {
+ print('FAILED: $testName: $outcome');
+ print(failureLog);
+ }
+ }
+ if (verbose) {
+ String result = matchedExpectations ? "PASS" : "FAIL";
+ print("${testName}: ${result}");
+ }
+ }
+
+ void logTestStart(int completed, int failed, int total, testing.Suite suite,
+ TestDescription description) {
+ String name = getTestName(description);
+ stopwatches[name] = Stopwatch()..start();
+ }
+
+ @override
+ void logTestComplete(int completed, int failed, int total,
+ testing.Suite suite, TestDescription description) {}
+
+ @override
+ void logUncaughtError(error, StackTrace stackTrace) {}
+
+ void logExpectedResult(testing.Suite suite, TestDescription description,
+ Result result, Set<Expectation> expectedOutcomes) {
+ handleTestResult(description, result, prefix, true);
+ }
+
+ @override
+ void logUnexpectedResult(testing.Suite suite, TestDescription description,
+ Result result, Set<Expectation> expectedOutcomes) {
+ // The test framework (pkg/testing) calls the logger with an unexpected
+ // results a second time to create a summary. We ignore the second call
+ // here.
+ String testName = getTestName(description);
+ if (seenTests.contains(testName)) return;
+ seenTests.add(testName);
+ handleTestResult(description, result, prefix, false);
+ }
+}
+
+class Suite {
+ final String name;
+ final CreateContext createContext;
+ final String testingRootPath;
+ final String path;
+ final int shardCount;
+ final int shard;
+ final String prefix;
+
+ const Suite(this.name, this.createContext, this.testingRootPath,
+ {this.path, this.shardCount: 1, this.shard: 0, String prefix})
+ : prefix = prefix ?? name;
+}
+
+const List<Suite> suites = [
+ const Suite(
+ "fasta/expression", expression.createContext, "../../testing.json"),
+ const Suite("fasta/outline", outline.createContext, "../../testing.json"),
+ const Suite(
+ "fasta/fast_strong", fast_strong.createContext, "../../testing.json"),
+ const Suite(
+ "fasta/incremental", incremental.createContext, "../../testing.json"),
+ const Suite("fasta/messages", messages.createContext, "../../testing.json"),
+ const Suite("fasta/text_serialization1", text_serialization.createContext,
+ "../../testing.json",
+ path: "fasta/text_serialization_tester.dart",
+ shardCount: 4,
+ shard: 0,
+ prefix: "fasta/text_serialization"),
+ const Suite("fasta/text_serialization2", text_serialization.createContext,
+ "../../testing.json",
+ path: "fasta/text_serialization_tester.dart",
+ shardCount: 4,
+ shard: 1,
+ prefix: "fasta/text_serialization"),
+ const Suite("fasta/text_serialization3", text_serialization.createContext,
+ "../../testing.json",
+ path: "fasta/text_serialization_tester.dart",
+ shardCount: 4,
+ shard: 2,
+ prefix: "fasta/text_serialization"),
+ const Suite("fasta/text_serialization4", text_serialization.createContext,
+ "../../testing.json",
+ path: "fasta/text_serialization_tester.dart",
+ shardCount: 4,
+ shard: 3,
+ prefix: "fasta/text_serialization"),
+ const Suite("fasta/strong1", strong.createContext, "../../testing.json",
+ path: "fasta/strong_tester.dart",
+ shardCount: 4,
+ shard: 0,
+ prefix: "fasta/strong"),
+ const Suite("fasta/strong2", strong.createContext, "../../testing.json",
+ path: "fasta/strong_tester.dart",
+ shardCount: 4,
+ shard: 1,
+ prefix: "fasta/strong"),
+ const Suite("fasta/strong3", strong.createContext, "../../testing.json",
+ path: "fasta/strong_tester.dart",
+ shardCount: 4,
+ shard: 2,
+ prefix: "fasta/strong"),
+ const Suite("fasta/strong4", strong.createContext, "../../testing.json",
+ path: "fasta/strong_tester.dart",
+ shardCount: 4,
+ shard: 3,
+ prefix: "fasta/strong"),
+ const Suite("incremental_bulk_compiler_smoke",
+ incremental_bulk_compiler.createContext, "../testing.json"),
+ const Suite("incremental_load_from_dill", incremental_load.createContext,
+ "../testing.json"),
+ const Suite("lint", lint.createContext, "../testing.json"),
+ const Suite("parser", parser.createContext, "../testing.json"),
+ const Suite("parser_all", parserAll.createContext, "../testing.json"),
+ const Suite("spelling_test_not_src", spelling_not_src.createContext,
+ "../testing.json"),
+ const Suite(
+ "spelling_test_src", spelling_src.createContext, "../testing.json"),
+ const Suite("fasta/weak", weak.createContext, "../../testing.json"),
+ const Suite("fasta/textual_outline", textual_outline.createContext,
+ "../../testing.json"),
+];
+
+const Duration timeoutDuration = Duration(minutes: 30);
+
+class SuiteConfiguration {
+ final String name;
+ final SendPort resultsPort;
+ final SendPort logsPort;
+ final bool verbose;
+ final bool printFailureLog;
+ final String configurationName;
+ final String testFilter;
+ final List<String> environmentOptions;
+
+ const SuiteConfiguration(
+ this.name,
+ this.resultsPort,
+ this.logsPort,
+ this.verbose,
+ this.printFailureLog,
+ this.configurationName,
+ this.testFilter,
+ this.environmentOptions);
+}
+
+void runSuite(SuiteConfiguration configuration) {
+ Suite suite = suites.where((s) => s.name == configuration.name).single;
+ String name = suite.prefix;
+ String fullSuiteName = "$suiteNamePrefix/$name";
+ Uri suiteUri = Platform.script.resolve(suite.path ?? "${name}_suite.dart");
+ if (!new File.fromUri(suiteUri).existsSync()) {
+ throw "File doesn't exist: $suiteUri";
+ }
+ ResultLogger logger = ResultLogger(
+ fullSuiteName,
+ configuration.resultsPort,
+ configuration.logsPort,
+ configuration.verbose,
+ configuration.printFailureLog,
+ configuration.configurationName);
+ runMe(<String>[
+ if (configuration.testFilter != null) configuration.testFilter,
+ if (configuration.environmentOptions != null)
+ for (String option in configuration.environmentOptions) '-D${option}',
+ ], suite.createContext,
+ me: suiteUri,
+ configurationPath: suite.testingRootPath,
+ logger: logger,
+ shards: suite.shardCount,
+ shard: suite.shard);
+}
+
+void writeLinesToFile(Uri uri, List<String> lines) async {
+ await File.fromUri(uri).writeAsString(lines.map((line) => "$line\n").join());
+}
+
+main([List<String> arguments = const <String>[]]) async {
+ List<String> results = [];
+ List<String> logs = [];
+ Options options = Options.parse(arguments);
+ ReceivePort resultsPort = new ReceivePort()
+ ..listen((resultEntry) => results.add(resultEntry));
+ ReceivePort logsPort = new ReceivePort()
+ ..listen((logEntry) => logs.add(logEntry));
+ List<Future<bool>> futures = [];
+ // Run test suites and record the results and possible failure logs.
+ for (Suite suite in suites) {
+ String name = suite.name;
+ String filter = options.testFilter;
+ if (filter != null) {
+ // Skip suites that are not hit by the test filter, is there is one.
+ if (!filter.startsWith(suite.prefix)) {
+ continue;
+ }
+ // Remove the 'fasta/' from filters, if there, because it is not used
+ // in the name defined in testing.json.
+ if (filter.startsWith("fasta/")) {
+ filter = filter.substring("fasta/".length);
+ }
+ }
+ // Start the test suite in a new isolate.
+ ReceivePort exitPort = new ReceivePort();
+ SuiteConfiguration configuration = SuiteConfiguration(
+ name,
+ resultsPort.sendPort,
+ logsPort.sendPort,
+ options.verbose,
+ options.printFailureLog,
+ options.configurationName,
+ filter,
+ options.environmentOptions);
+ Future future = Future<bool>(() async {
+ Stopwatch stopwatch = Stopwatch()..start();
+ print("Running suite $name");
+ Isolate isolate = await Isolate.spawn<SuiteConfiguration>(
+ runSuite, configuration,
+ onExit: exitPort.sendPort);
+ bool timedOut = false;
+ Timer timer = Timer(timeoutDuration, () {
+ timedOut = true;
+ print("Suite $name timed out after "
+ "${timeoutDuration.inMilliseconds}ms");
+ isolate.kill(priority: Isolate.immediate);
+ });
+ await exitPort.first;
+ timer.cancel();
+ if (!timedOut) {
+ int seconds = stopwatch.elapsedMilliseconds ~/ 1000;
+ print("Suite $name finished (took ${seconds} seconds)");
+ }
+ return timedOut;
+ });
+ futures.add(future);
+ }
+ // Wait for isolates to terminate and clean up.
+ Iterable<bool> timeouts = await Future.wait(futures);
+ resultsPort.close();
+ logsPort.close();
+ // Write results.json and logs.json.
+ Uri resultJsonUri = options.outputDirectory.resolve("results.json");
+ Uri logsJsonUri = options.outputDirectory.resolve("logs.json");
+ await writeLinesToFile(resultJsonUri, results);
+ await writeLinesToFile(logsJsonUri, logs);
+ print("Log files written to ${resultJsonUri.toFilePath()} and"
+ " ${logsJsonUri.toFilePath()}");
+ // Return with exit code 1 if at least one suite timed out.
+ bool timeout = timeouts.any((timeout) => timeout);
+ if (timeout) {
+ exitCode = 1;
+ } else {
+ // The testing framework (package:testing) sets the exitCode to `1` if any
+ // test failed, so we reset it here to indicate that the test runner was
+ // successful.
+ exitCode = 0;
+ }
+}
diff --git a/pkg/front_end/testing.json b/pkg/front_end/testing.json
index edd1e75..8bd4c7e 100644
--- a/pkg/front_end/testing.json
+++ b/pkg/front_end/testing.json
@@ -336,6 +336,7 @@
"test/tool/reload\\.dart$",
"test/type_labeler_test\\.dart$",
"test/unit_test_suites\\.dart$",
+ "test/unit_test_suites_impl\\.dart$",
"testcases/expression/main\\.dart$",
"testcases/general/DeltaBlue\\.dart$",
"testcases/general/annotation_variable_declaration\\.dart$",
diff --git a/pkg/front_end/tool/smoke_test_quick.dart b/pkg/front_end/tool/smoke_test_quick.dart
index 7427ee3..e942ef1 100644
--- a/pkg/front_end/tool/smoke_test_quick.dart
+++ b/pkg/front_end/tool/smoke_test_quick.dart
@@ -15,8 +15,8 @@
main(List<String> args) async {
Stopwatch stopwatch = new Stopwatch()..start();
List<Future> futures = <Future>[];
- futures.add(run(
- "pkg/front_end/test/explicit_creation_test.dart", ["--front-end-only"],
+ futures.add(run("pkg/front_end/test/explicit_creation_git_test.dart",
+ ["--front-end-only"],
filter: false));
futures.add(run(
"pkg/front_end/test/fasta/messages_suite.dart",
@@ -27,7 +27,7 @@
["--", "spelling_test_src/front_end/..."]));
futures.add(
run("pkg/front_end/test/lint_suite.dart", ["--", "lint/front_end/..."]));
- futures.add(run("pkg/front_end/test/deps_test.dart", [], filter: false));
+ futures.add(run("pkg/front_end/test/deps_git_test.dart", [], filter: false));
futures.add(run(
"pkg/front_end/tool/_fasta/generate_experimental_flags_test.dart", [],
filter: false));
diff --git a/pkg/pkg.status b/pkg/pkg.status
index da7fa09..18c8c4a 100644
--- a/pkg/pkg.status
+++ b/pkg/pkg.status
@@ -68,7 +68,7 @@
dev_compiler/test/sourcemap/*: SkipByDesign # Skip sourcemap tests
dev_compiler/test/sourcemap/testfiles/*: SkipByDesign # Skip dev_compiler codegen tests
dev_compiler/test/worker/*: Skip # test needs fixes
-front_end/test/fasta/analyze_test: Pass, Slow
+front_end/test/fasta/analyze_git_test: Pass, Slow
front_end/test/fasta/ast_builder_test: Pass, Slow
front_end/test/fasta/bootstrap_test: Pass, Slow
front_end/test/fasta/fast_legacy_test: Pass, Slow
diff --git a/runtime/vm/type_testing_stubs.cc b/runtime/vm/type_testing_stubs.cc
index 5fe1f7c..34e5f63 100644
--- a/runtime/vm/type_testing_stubs.cc
+++ b/runtime/vm/type_testing_stubs.cc
@@ -499,6 +499,9 @@
__ CompareImmediate(TTSInternalRegs::kScratchReg, kNullCid);
__ BranchIf(EQUAL, &is_subtype);
}
+ // Never is a bottom type.
+ __ CompareImmediate(TTSInternalRegs::kScratchReg, kNeverCid);
+ __ BranchIf(EQUAL, &is_subtype);
FlowGraphCompiler::GenerateCidRangesCheck(
assembler, TTSInternalRegs::kScratchReg, ranges, &is_subtype,
check_failed, true);
diff --git a/runtime/vm/type_testing_stubs_test.cc b/runtime/vm/type_testing_stubs_test.cc
index 04e4012..e00f107 100644
--- a/runtime/vm/type_testing_stubs_test.cc
+++ b/runtime/vm/type_testing_stubs_test.cc
@@ -407,6 +407,7 @@
createI2() => I2();
createBaseInt() => Base<int>();
createBaseNull() => Base<Null>();
+ createBaseNever() => Base<Never>();
createA() => A();
createA1() => A1();
createA2() => A2<int>();
@@ -433,6 +434,8 @@
Object::Handle(Invoke(root_library, "createBaseInt"));
const auto& obj_base_null =
Object::Handle(Invoke(root_library, "createBaseNull"));
+ const auto& obj_base_never =
+ Object::Handle(Invoke(root_library, "createBaseNever"));
const auto& obj_a = Object::Handle(Invoke(root_library, "createA"));
const auto& obj_a1 = Object::Handle(Invoke(root_library, "createA1"));
const auto& obj_a2 = Object::Handle(Invoke(root_library, "createA2"));
@@ -516,20 +519,42 @@
RunTTSTest(obj_b2, type_base, tav_null, tav_null, ExpectLazilyHandledViaTTS,
ExpectHandledViaTTS);
- // Base<Null> as Base<int?>
- // This is a regression test verifying that Null is included in
- // class-id ranges for int?.
- auto& type_int = Type::Handle(Type::IntType());
- type_int = type_int.ToNullability(
+ // Base<Null|Never> as Base<int?>
+ // This is a regression test verifying that we don't fall through into
+ // runtime for Null and Never.
+ auto& type_nullable_int = Type::Handle(Type::IntType());
+ type_nullable_int = type_nullable_int.ToNullability(
TestCase::IsNNBD() ? Nullability::kNullable : Nullability::kLegacy,
Heap::kNew);
- auto& tav_int = TypeArguments::Handle(TypeArguments::New(1));
- tav_int.SetTypeAt(0, type_int);
- CanonicalizeTAV(&tav_int);
- auto& type_base_int = AbstractType::Handle(Type::New(class_base, tav_int));
- FinalizeAndCanonicalize(&type_base_int);
- RunTTSTest(obj_base_null, type_base_int, tav_null, tav_null,
+ auto& tav_nullable_int = TypeArguments::Handle(TypeArguments::New(1));
+ tav_nullable_int.SetTypeAt(0, type_nullable_int);
+ CanonicalizeTAV(&tav_nullable_int);
+ auto& type_base_nullable_int =
+ AbstractType::Handle(Type::New(class_base, tav_nullable_int));
+ FinalizeAndCanonicalize(&type_base_nullable_int);
+ RunTTSTest(obj_base_null, type_base_nullable_int, tav_null, tav_null,
ExpectLazilyHandledViaTTS, ExpectHandledViaTTS);
+ RunTTSTest(obj_base_never, type_base_nullable_int, tav_null, tav_null,
+ ExpectLazilyHandledViaTTS, ExpectHandledViaTTS);
+
+ if (TestCase::IsNNBD()) {
+ // Base<Null|Never> as Base<int>
+ auto& type_int = Type::Handle(Type::IntType());
+ type_int = type_int.ToNullability(Nullability::kNonNullable, Heap::kNew);
+ auto& tav_int = TypeArguments::Handle(TypeArguments::New(1));
+ tav_int.SetTypeAt(0, type_int);
+ CanonicalizeTAV(&tav_int);
+ auto& type_base_int = Type::Handle(Type::New(class_base, tav_int));
+ type_base_int =
+ type_base_int.ToNullability(Nullability::kNonNullable, Heap::kNew);
+ FinalizeAndCanonicalize(&type_base_int);
+ if (IsolateGroup::Current()->null_safety()) {
+ RunTTSTest(obj_base_null, type_base_int, tav_null, tav_null,
+ ExpectLazilyFailedViaTTS, ExpectFailedViaTTS);
+ }
+ RunTTSTest(obj_base_never, type_base_int, tav_null, tav_null,
+ ExpectLazilyHandledViaTTS, ExpectHandledViaTTS);
+ }
// <...> as I2
const auto& type_i2 = AbstractType::Handle(class_i2.RareType());
diff --git a/tools/VERSION b/tools/VERSION
index bc70d09..f6cc11d 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
MAJOR 2
MINOR 12
PATCH 0
-PRERELEASE 270
+PRERELEASE 271
PRERELEASE_PATCH 0
\ No newline at end of file
diff --git a/tools/bots/test_matrix.json b/tools/bots/test_matrix.json
index f3980bc..12f746b 100644
--- a/tools/bots/test_matrix.json
+++ b/tools/bots/test_matrix.json
@@ -978,7 +978,7 @@
"name": "unit tests",
"arguments": [
"-ncfe-unittest-asserts-${mode}-${system}",
- "pkg/(kernel|front_end|fasta)"
+ "pkg/pkg/(kernel|front_end|fasta)/"
]
},
{