diff --git a/pkg/front_end/test/fasta/testing/suite.dart b/pkg/front_end/test/fasta/testing/suite.dart index ed80870c89f..9e69886d794 100644 --- a/pkg/front_end/test/fasta/testing/suite.dart +++ b/pkg/front_end/test/fasta/testing/suite.dart @@ -1104,7 +1104,6 @@ class Outline extends Step { description, p, userLibraries, options, sourceTarget), context.expectationSet["InstrumentationMismatch"], instrumentation.problemsAsString, - null, autoFixCommand: '${UPDATE_COMMENTS}=true'); } } @@ -1194,8 +1193,7 @@ class Transform extends Step { return new Result( result, context.expectationSet["TransformVerificationError"], - errors.join('\n'), - null); + errors.join('\n')); } return pass(result); } @@ -1236,8 +1234,8 @@ class Verify extends Step { if (messages.isEmpty) { return pass(result); } else { - return new Result(null, - context.expectationSet["VerificationError"], "$messages", null); + return new Result( + null, context.expectationSet["VerificationError"], "$messages"); } }, errorOnMissingInput: false); } diff --git a/pkg/front_end/test/fasta/textual_outline_suite.dart b/pkg/front_end/test/fasta/textual_outline_suite.dart index aeb3343c551..6127a283594 100644 --- a/pkg/front_end/test/fasta/textual_outline_suite.dart +++ b/pkg/front_end/test/fasta/textual_outline_suite.dart @@ -81,8 +81,8 @@ class TextualOutline extends Step { performModelling: modelled, addMarkerForUnknownForTest: modelled); if (result == null) { - return new Result(null, context.expectationSet["EmptyOutput"], - description.uri, StackTrace.current); + return new Result( + null, context.expectationSet["EmptyOutput"], description.uri); } // In an attempt to make it less sensitive to formatting first remove @@ -122,8 +122,9 @@ class TextualOutline extends Step { if (expectMatch.outcome != Expectation.Pass) return expectMatch; if (formatterException != null) { - return new Result(null, context.expectationSet["FormatterCrash"], - formatterException, formatterExceptionSt); + return new Result( + null, context.expectationSet["FormatterCrash"], formatterException, + trace: formatterExceptionSt); } } diff --git a/pkg/front_end/test/incremental_load_from_dill_suite.dart b/pkg/front_end/test/incremental_load_from_dill_suite.dart index 768e1bad14a..c7c6a35bbb2 100644 --- a/pkg/front_end/test/incremental_load_from_dill_suite.dart +++ b/pkg/front_end/test/incremental_load_from_dill_suite.dart @@ -74,7 +74,7 @@ import 'package:kernel/target/targets.dart' import 'package:kernel/text/ast_to_text.dart' show Printer, componentToString; import "package:testing/testing.dart" - show Chain, ChainContext, Result, Step, TestDescription, runMe; + show Chain, ChainContext, Expectation, Result, Step, TestDescription, runMe; import "package:vm/target/vm.dart" show VmTarget; @@ -89,6 +89,43 @@ import 'utils/io_utils.dart' show computeRepoDir; main([List arguments = const []]) => runMe(arguments, createContext, configurationPath: "../testing.json"); +const Expectation ExpectationFileMismatch = + const Expectation.fail("ExpectationFileMismatch"); +const Expectation ExpectationFileMissing = + const Expectation.fail("ExpectationFileMissing"); +const Expectation MissingErrors = const Expectation.fail("MissingErrors"); +const Expectation UnexpectedErrors = const Expectation.fail("UnexpectedErrors"); +const Expectation MissingWarnings = const Expectation.fail("MissingWarnings"); +const Expectation UnexpectedWarnings = + const Expectation.fail("UnexpectedWarnings"); +const Expectation ClassHierarchyError = + const Expectation.fail("ClassHierarchyError"); +const Expectation NeededDillMismatch = + const Expectation.fail("NeededDillMismatch"); +const Expectation IncrementalSerializationError = + const Expectation.fail("IncrementalSerializationError"); +const Expectation ContentDataMismatch = + const Expectation.fail("ContentDataMismatch"); +const Expectation MissingInitializationError = + const Expectation.fail("MissingInitializationError"); +const Expectation UnexpectedInitializationError = + const Expectation.fail("UnexpectedInitializationError"); +const Expectation ReachableLibrariesError = + const Expectation.fail("ReachableLibrariesError"); +const Expectation UriToSourceError = const Expectation.fail("UriToSourceError"); +const Expectation MissingPlatformLibraries = + const Expectation.fail("MissingPlatformLibraries"); +const Expectation UnexpectedPlatformLibraries = + const Expectation.fail("UnexpectedPlatformLibraries"); +const Expectation UnexpectedRebuildBodiesOnly = + const Expectation.fail("UnexpectedRebuildBodiesOnly"); +const Expectation UnexpectedEntryToLibraryCount = + const Expectation.fail("UnexpectedEntryToLibraryCount"); +const Expectation LibraryCountMismatch = + const Expectation.fail("LibraryCountMismatch"); +const Expectation InitializedFromDillMismatch = + const Expectation.fail("InitializedFromDillMismatch"); + Future createContext( Chain suite, Map environment) async { // Disable colors to ensure that expectation files are the same across @@ -152,6 +189,7 @@ class RunCompilations extends Step { String get name => "run compilations"; Future> run(TestData data, Context context) async { + Result result; YamlMap map = data.map; Set keys = new Set.from(map.keys.cast()); keys.remove("type"); @@ -175,7 +213,7 @@ class RunCompilations extends Step { "trackWidgetCreation", "incrementalSerialization" ]); - await new NewWorldTest().newWorldTest( + result = await new NewWorldTest().newWorldTest( data, context, map["worlds"], @@ -192,7 +230,7 @@ class RunCompilations extends Step { } if (keys.isNotEmpty) throw "Unknown toplevel keys: $keys"; - return pass(data); + return result ?? pass(data); } } @@ -340,7 +378,7 @@ class NewWorldTest { return output; } - Future newWorldTest( + Future> newWorldTest( TestData data, Context context, List worlds, @@ -611,8 +649,9 @@ class NewWorldTest { } } } - performErrorAndWarningCheck( - world, gotError, formattedErrors, gotWarning, formattedWarnings); + Result result = performErrorAndWarningCheck(world, data, + gotError, formattedErrors, gotWarning, formattedWarnings); + if (result != null) return result; if (world["expectInitializationError"] != null) { Set seenInitializationError = seenDiagnosticCodes.intersection({ "InitializeFromDillNotSelfContainedNoDump", @@ -622,12 +661,16 @@ class NewWorldTest { }); if (world["expectInitializationError"] == true) { if (seenInitializationError.isEmpty) { - throw "Expected to see an initialization error but didn't."; + return new Result(data, MissingInitializationError, + "Expected to see an initialization error but didn't."); } } else if (world["expectInitializationError"] == false) { if (seenInitializationError.isNotEmpty) { - throw "Expected not to see an initialization error but did: " - "$seenInitializationError."; + return new Result( + data, + UnexpectedInitializationError, + "Expected not to see an initialization error but did: " + "$seenInitializationError."); } } else { throw "Unsupported value for 'expectInitializationError': " @@ -639,8 +682,11 @@ class NewWorldTest { fileSystem: gotError ? null : fs); print("Compile took ${stopwatch.elapsedMilliseconds} ms"); - checkExpectedContent(world, component); - checkNeededDillLibraries(world, compiler.neededDillLibraries, base); + Result contentResult = checkExpectedContent(world, component); + if (contentResult != null) return contentResult.copyWithOutput(data); + result = checkNeededDillLibraries( + world, data, compiler.neededDillLibraries, base); + if (result != null) return result; if (!noFullComponent) { Set allLibraries = new Set(); @@ -648,13 +694,19 @@ class NewWorldTest { computeAllReachableLibrariesFor(lib, allLibraries); } if (allLibraries.length != component.libraries.length) { - Expect.fail("Expected for the reachable stuff to be equal to " + return new Result( + data, + ReachableLibrariesError, + "Expected for the reachable stuff to be equal to " "${component.libraries} but it was $allLibraries"); } Set tooMany = allLibraries.toSet() ..removeAll(component.libraries); if (tooMany.isNotEmpty) { - Expect.fail("Expected for the reachable stuff to be equal to " + return new Result( + data, + ReachableLibrariesError, + "Expected for the reachable stuff to be equal to " "${component.libraries} but these were there too: $tooMany " "(and others were missing)"); } @@ -670,8 +722,11 @@ class NewWorldTest { for (String filename in world["uriToSourcesDoesntInclude"]) { Uri uri = base.resolve(filename); if (component.uriToSource[uri] != null) { - throw "Expected no uriToSource for $uri but found " - "${component.uriToSource[uri]}"; + return new Result( + data, + UriToSourceError, + "Expected no uriToSource for $uri but found " + "${component.uriToSource[uri]}"); } } } @@ -686,14 +741,20 @@ class NewWorldTest { // Dart scheme uris too. if (uri == null || uri.scheme == "org-dartlang-sdk") continue; if (!allowed.contains(uri)) { - throw "Expected no uriToSource for $uri but found " - "${component.uriToSource[uri]}"; + return new Result( + data, + UriToSourceError, + "Expected no uriToSource for $uri but found " + "${component.uriToSource[uri]}"); } } } - checkExpectFile(data, worldNum, "", context, actualSerialized); - checkClassHierarchy(compiler, component, data, worldNum, context); + result = checkExpectFile(data, worldNum, "", context, actualSerialized); + if (result != null) return result; + result = + checkClassHierarchy(compiler, component, data, worldNum, context); + if (result != null) return result; int nonSyntheticLibraries = countNonSyntheticLibraries(component); int nonSyntheticPlatformLibraries = @@ -701,36 +762,54 @@ class NewWorldTest { int syntheticLibraries = countSyntheticLibraries(component); if (world["expectsPlatform"] == true) { if (nonSyntheticPlatformLibraries < 5) { - throw "Expected to have at least 5 platform libraries " + return new Result( + data, + MissingPlatformLibraries, + "Expected to have at least 5 platform libraries " "(actually, the entire sdk), " - "but got $nonSyntheticPlatformLibraries."; + "but got $nonSyntheticPlatformLibraries."); } } else { if (nonSyntheticPlatformLibraries != 0) { - throw "Expected to have 0 platform libraries " - "but got $nonSyntheticPlatformLibraries."; + return new Result( + data, + UnexpectedPlatformLibraries, + "Expected to have 0 platform libraries " + "but got $nonSyntheticPlatformLibraries."); } } if (world["expectedLibraryCount"] != null) { if (nonSyntheticLibraries - nonSyntheticPlatformLibraries != world["expectedLibraryCount"]) { - throw "Expected ${world["expectedLibraryCount"]} non-synthetic " + return new Result( + data, + LibraryCountMismatch, + "Expected ${world["expectedLibraryCount"]} non-synthetic " "libraries, got " "${nonSyntheticLibraries - nonSyntheticPlatformLibraries} " - "(not counting platform libraries)"; + "(not counting platform libraries)"); } } if (world["expectedSyntheticLibraryCount"] != null) { if (syntheticLibraries != world["expectedSyntheticLibraryCount"]) { - throw "Expected ${world["expectedSyntheticLibraryCount"]} synthetic " - "libraries, got ${syntheticLibraries}"; + return new Result( + data, + LibraryCountMismatch, + "Expected ${world["expectedSyntheticLibraryCount"]} synthetic " + "libraries, got ${syntheticLibraries}"); } } if (world["expectsRebuildBodiesOnly"] != null) { bool didRebuildBodiesOnly = compiler.rebuildBodiesCount > 0; - Expect.equals(world["expectsRebuildBodiesOnly"], didRebuildBodiesOnly, - "Whether we expected to rebuild bodies only."); + if (world["expectsRebuildBodiesOnly"] != didRebuildBodiesOnly) { + return new Result( + data, + UnexpectedRebuildBodiesOnly, + "Expected didRebuildBodiesOnly=" + "${world["expectsRebuildBodiesOnly"]}, " + "didRebuildBodiesOnly=${didRebuildBodiesOnly}."); + } } if (!noFullComponent) { @@ -740,14 +819,20 @@ class NewWorldTest { entries.contains(lib.fileUri)) .toList(); if (entryLib.length != entries.length) { - throw "Expected the entries to become libraries. " + return new Result( + data, + UnexpectedEntryToLibraryCount, + "Expected the entries to become libraries. " "Got ${entryLib.length} libraries for the expected " - "${entries.length} entries."; + "${entries.length} entries."); } } if (compiler.initializedFromDill != expectInitializeFromDill) { - throw "Expected that initializedFromDill would be " - "$expectInitializeFromDill but was ${compiler.initializedFromDill}"; + return new Result( + data, + InitializedFromDillMismatch, + "Expected that initializedFromDill would be " + "$expectInitializeFromDill but was ${compiler.initializedFromDill}"); } if (incrementalSerialization == true && compiler.initializedFromDill) { @@ -772,8 +857,12 @@ class NewWorldTest { Expect.isNull(world["expectedInvalidatedUri"]); } } - List incrementalSerializationBytes = checkIncrementalSerialization( + Result> serializationResult = checkIncrementalSerialization( incrementalSerialization, component, incrementalSerializer, world); + if (!serializationResult.isPass) { + return serializationResult.copyWithOutput(data); + } + List incrementalSerializationBytes = serializationResult.output; Set prevFormattedErrors = formattedErrors.toSet(); Set prevFormattedWarnings = formattedWarnings.toSet(); @@ -791,8 +880,9 @@ class NewWorldTest { entryPoints: entries, fullComponent: true, simulateTransformer: world["simulateTransformer"]); - performErrorAndWarningCheck( - world, gotError, formattedErrors, gotWarning, formattedWarnings); + Result result = performErrorAndWarningCheck(world, data, + gotError, formattedErrors, gotWarning, formattedWarnings); + if (result != null) return result; List thisWholeComponent = util.postProcess(component2); print("*****\n\ncomponent2:\n" "${componentToStringSdkFiltered(component2)}\n\n\n"); @@ -801,16 +891,22 @@ class NewWorldTest { prevFormattedWarnings, formattedWarnings); newestWholeComponent = component2; - List incrementalSerializationBytes2 = - checkIncrementalSerialization(incrementalSerialization, component2, - incrementalSerializer, world); + Result> serializationResult = checkIncrementalSerialization( + incrementalSerialization, component2, incrementalSerializer, world); + if (!serializationResult.isPass) { + return serializationResult.copyWithOutput(data); + } + List incrementalSerializationBytes2 = serializationResult.output; if ((incrementalSerializationBytes == null && incrementalSerializationBytes2 != null) || (incrementalSerializationBytes != null && incrementalSerializationBytes2 == null)) { - throw "Incremental serialization gave results in one instance, " - "but not another."; + return new Result( + data, + IncrementalSerializationError, + "Incremental serialization gave results in one instance, " + "but not another."); } if (incrementalSerializationBytes != null) { @@ -837,22 +933,29 @@ class NewWorldTest { Procedure procedure = await compiler.compileExpression( expression, {}, [], "debugExpr", uri); if (gotError && !expectErrors) { - throw "Got error(s) on expression compilation: ${formattedErrors}."; + return new Result(data, UnexpectedErrors, + "Got error(s) on expression compilation: ${formattedErrors}."); } else if (!gotError && expectErrors) { - throw "Didn't get any errors."; + return new Result( + data, MissingErrors, "Didn't get any errors."); } if (gotWarning && !expectWarnings) { - throw "Got warning(s) on expression compilation: " - "${formattedWarnings}."; + return new Result( + data, + UnexpectedWarnings, + "Got warning(s) on expression compilation: " + "${formattedWarnings}."); } else if (!gotWarning && expectWarnings) { - throw "Didn't get any warnings."; + return new Result( + data, MissingWarnings, "Didn't get any warnings."); } - checkExpectFile( + Result result = checkExpectFile( data, worldNum, ".expression.$expressionCompilationNum", context, nodeToString(procedure)); + if (result != null) return result; } } @@ -885,8 +988,9 @@ class NewWorldTest { entryPoints: entries, simulateTransformer: world["simulateTransformer"]); compilerFromScratch = null; - performErrorAndWarningCheck( - world, gotError, formattedErrors, gotWarning, formattedWarnings); + Result result = performErrorAndWarningCheck(world, data, + gotError, formattedErrors, gotWarning, formattedWarnings); + if (result != null) return result; util.throwOnEmptyMixinBodies(component3); await util.throwOnInsufficientUriToSource(component3); print("Compile took ${stopwatch.elapsedMilliseconds} ms"); @@ -897,16 +1001,25 @@ class NewWorldTest { checkErrorsAndWarnings(prevFormattedErrors, formattedErrors, prevFormattedWarnings, formattedWarnings); - List incrementalSerializationBytes3 = - checkIncrementalSerialization(incrementalSerialization, component3, - incrementalSerializer2, world); + Result> serializationResult = checkIncrementalSerialization( + incrementalSerialization, + component3, + incrementalSerializer2, + world); + if (!serializationResult.isPass) { + return serializationResult.copyWithOutput(data); + } + List incrementalSerializationBytes3 = serializationResult.output; if ((incrementalSerializationBytes == null && incrementalSerializationBytes3 != null) || (incrementalSerializationBytes != null && incrementalSerializationBytes3 == null)) { - throw "Incremental serialization gave results in one instance, " - "but not another."; + return new Result( + data, + IncrementalSerializationError, + "Incremental serialization gave results in one instance, " + "but not another."); } if (incrementalSerializationBytes != null) { @@ -930,11 +1043,12 @@ class NewWorldTest { print("Continuing after debug break"); } } + return new Result.pass(data); } } -void checkExpectFile(TestData data, int worldNum, String extraUriString, - Context context, String actualSerialized) { +Result checkExpectFile(TestData data, int worldNum, + String extraUriString, Context context, String actualSerialized) { Uri uri = data.loadedFrom.resolve(data.loadedFrom.pathSegments.last + ".world.$worldNum${extraUriString}.expect"); String expected; @@ -948,24 +1062,32 @@ void checkExpectFile(TestData data, int worldNum, String extraUriString, } else { String extra = ""; if (expected == null) extra = "Expect file did not exist.\n"; - throw "${extra}Unexpected serialized representation. " + return new Result( + data, + expected == null ? ExpectationFileMissing : ExpectationFileMismatch, + "${extra}Unexpected serialized representation. " "Fix or update $uri to contain the below:\n\n" - "$actualSerialized"; + "$actualSerialized", + autoFixCommand: "updateExpectations=true"); } } + return null; } /// Check that the class hierarchy is up-to-date with reality. /// /// This has the option to do expect files, but it's disabled by default /// while we're trying to figure out if it's useful or not. -void checkClassHierarchy(TestIncrementalCompiler compiler, Component component, - TestData data, int worldNum, Context context, +Result checkClassHierarchy(TestIncrementalCompiler compiler, + Component component, TestData data, int worldNum, Context context, {bool checkExpectFile: false}) { ClassHierarchy classHierarchy = compiler.getClassHierarchy(); if (classHierarchy is! ClosedWorldClassHierarchy) { - throw "Expected the class hierarchy to be ClosedWorldClassHierarchy " - "but it wasn't. It was ${classHierarchy.runtimeType}"; + return new Result( + data, + ClassHierarchyError, + "Expected the class hierarchy to be ClosedWorldClassHierarchy " + "but it wasn't. It was ${classHierarchy.runtimeType}"); } List classHierarchyData = (classHierarchy as ClosedWorldClassHierarchy).getTestingClassInfo(); @@ -973,7 +1095,8 @@ void checkClassHierarchy(TestIncrementalCompiler compiler, Component component, new Map(); for (ForTestingClassInfo info in classHierarchyData) { if (classHierarchyMap[info.classNode] != null) { - throw "Two entries for ${info.classNode}"; + return new Result( + data, ClassHierarchyError, "Two entries for ${info.classNode}"); } classHierarchyMap[info.classNode] = info; } @@ -986,28 +1109,35 @@ void checkClassHierarchy(TestIncrementalCompiler compiler, Component component, sb.writeln(" - Class ${c.name}"); Set checkedSupertypes = {}; - void checkSupertype(Supertype supertype) { - if (supertype == null) return; + Result checkSupertype(Supertype supertype) { + if (supertype == null) return null; Class superclass = supertype.classNode; if (checkedSupertypes.add(superclass)) { Supertype asSuperClass = classHierarchy.getClassAsInstanceOf(c, superclass); if (asSuperClass == null) { - throw "${superclass} not found as a superclass of $c"; + return new Result(data, ClassHierarchyError, + "${superclass} not found as a superclass of $c"); } - checkSupertype(superclass.supertype); - checkSupertype(superclass.mixedInType); + Result result = checkSupertype(superclass.supertype); + if (result != null) return result; + result = checkSupertype(superclass.mixedInType); + if (result != null) return result; for (Supertype interface in superclass.implementedTypes) { - checkSupertype(interface); + result = checkSupertype(interface); + if (result != null) return result; } } + return null; } - checkSupertype(c.asThisSupertype); + Result result = checkSupertype(c.asThisSupertype); + if (result != null) return result; ForTestingClassInfo info = classHierarchyMap[c]; if (info == null) { - throw "Didn't find any class hierarchy info for $c"; + return new Result(data, ClassHierarchyError, + "Didn't find any class hierarchy info for $c"); } if (info.lazyDeclaredGettersAndCalls != null) { @@ -1022,21 +1152,30 @@ void checkClassHierarchy(TestIncrementalCompiler compiler, Component component, if (f.isStatic) continue; if (!f.hasImplicitGetter) continue; if (!members.remove(f)) { - throw "Didn't find ${f.name.text} in lazyDeclaredGettersAndCalls " - "for ${c.name} in ${library.importUri}"; + return new Result( + data, + ClassHierarchyError, + "Didn't find ${f.name.text} in lazyDeclaredGettersAndCalls " + "for ${c.name} in ${library.importUri}"); } } for (Procedure p in c.procedures) { if (p.isStatic) continue; if (p.isSetter) continue; if (!members.remove(p)) { - throw "Didn't find ${p.name.text} in lazyDeclaredGettersAndCalls " - "for ${c.name} in ${library.importUri}"; + return new Result( + data, + ClassHierarchyError, + "Didn't find ${p.name.text} in lazyDeclaredGettersAndCalls " + "for ${c.name} in ${library.importUri}"); } } if (members.isNotEmpty) { - throw "Still have ${members.map((m) => m.name.text)} left " - "for ${c.name} in ${library.importUri}"; + return new Result( + data, + ClassHierarchyError, + "Still have ${members.map((m) => m.name.text)} left " + "for ${c.name} in ${library.importUri}"); } } if (info.lazyDeclaredSetters != null) { @@ -1051,19 +1190,24 @@ void checkClassHierarchy(TestIncrementalCompiler compiler, Component component, if (f.isStatic) continue; if (!f.hasImplicitSetter) continue; if (!members.remove(f)) { - throw "Didn't find $f in lazyDeclaredSetters for $c"; + return new Result(data, ClassHierarchyError, + "Didn't find $f in lazyDeclaredSetters for $c"); } } for (Procedure p in c.procedures) { if (p.isStatic) continue; if (!p.isSetter) continue; if (!members.remove(p)) { - throw "Didn't find $p in lazyDeclaredSetters for $c"; + return new Result(data, ClassHierarchyError, + "Didn't find $p in lazyDeclaredSetters for $c"); } } if (members.isNotEmpty) { - throw "Still have ${members.map((m) => m.name.text)} left " - "for ${c.name} in ${library.importUri}"; + return new Result( + data, + ClassHierarchyError, + "Still have ${members.map((m) => m.name.text)} left " + "for ${c.name} in ${library.importUri}"); } } if (info.lazyImplementedGettersAndCalls != null) { @@ -1107,12 +1251,16 @@ void checkClassHierarchy(TestIncrementalCompiler compiler, Component component, } else { String extra = ""; if (expected == null) extra = "Expect file did not exist.\n"; - throw "${extra}Unexpected serialized representation. " + return new Result( + data, + ClassHierarchyError, + "${extra}Unexpected serialized representation. " "Fix or update $uri to contain the below:\n\n" - "$actualClassHierarchy"; + "$actualClassHierarchy"); } } } + return null; } void checkErrorsAndWarnings( @@ -1144,7 +1292,7 @@ void checkErrorsAndWarnings( } } -List checkIncrementalSerialization( +Result> checkIncrementalSerialization( bool incrementalSerialization, Component component, IncrementalSerializer incrementalSerializer, @@ -1159,18 +1307,26 @@ List checkIncrementalSerialization( incrementalSerializer.writePackagesToSinkAndTrimComponent(c, sink); int librariesAfter = c.libraries.length; if (librariesAfter > librariesBefore) { - throw "Incremental serialization added libraries!"; + return new Result>(null, IncrementalSerializationError, + "Incremental serialization added libraries!"); } if (librariesBefore == librariesAfter && world["incrementalSerializationDoesWork"] == true) { - throw "Incremental serialization didn't remove any libraries!"; + return new Result>(null, IncrementalSerializationError, + "Incremental serialization didn't remove any libraries!"); } if (librariesAfter < librariesBefore && sink.builder.isEmpty) { - throw "Incremental serialization didn't output any bytes, " - "but did remove libraries"; + return new Result>( + null, + IncrementalSerializationError, + "Incremental serialization didn't output any bytes, " + "but did remove libraries"); } else if (librariesAfter == librariesBefore && !sink.builder.isEmpty) { - throw "Incremental serialization did output bytes, " - "but didn't remove libraries"; + return new Result>( + null, + IncrementalSerializationError, + "Incremental serialization did output bytes, " + "but didn't remove libraries"); } if (librariesAfter < librariesBefore) { // If we actually did incrementally serialize anything, check the output! @@ -1191,8 +1347,11 @@ List checkIncrementalSerialization( for (String uriString in serializationShouldNotInclude) { Uri uri = Uri.parse(uriString); if (includedImportUris.contains(uri)) { - throw "Incremental serialization shouldn't include " - "$uriString but did."; + return new Result>( + null, + IncrementalSerializationError, + "Incremental serialization shouldn't include " + "$uriString but did."); } } } @@ -1207,18 +1366,20 @@ List checkIncrementalSerialization( for (String key in newKeys) { afterContent.remove(key); } - checkExpectedContentData(afterContent, originalContent); + Result result = checkExpectedContentData(afterContent, originalContent); + if (result != null) return result.copyWithOutput>(null); // Check that the result is self-contained. - checkSelfContained(loadedComponent); + result = checkSelfContained(loadedComponent); + if (result != null) return result.copyWithOutput>(null); - return bytes; + return new Result>.pass(bytes); } } - return null; + return new Result>.pass(null); } -void checkSelfContained(Component component) { +Result checkSelfContained(Component component) { Set got = new Set.from(component.libraries); for (Library lib in component.libraries) { for (LibraryDependency dependency in lib.dependencies) { @@ -1229,11 +1390,15 @@ void checkSelfContained(Component component) { .startsWith("root::dart:")) { continue; } - throw "Component didn't contain ${dependency.importedLibraryReference} " - "and it should have."; + return Result( + null, + IncrementalSerializationError, + "Component didn't contain ${dependency.importedLibraryReference} " + "and it should have."); } } } + return null; } void computeAllReachableLibrariesFor(Library lib, Set allLibraries) { @@ -1254,33 +1419,46 @@ void computeAllReachableLibrariesFor(Library lib, Set allLibraries) { } } -void checkExpectedContent(YamlMap world, Component component) { +Result checkExpectedContent(YamlMap world, Component component) { if (world["expectedContent"] != null) { Map> actualContent = buildMapOfContent(component); Map expectedContent = world["expectedContent"]; - checkExpectedContentData(actualContent, expectedContent); + return checkExpectedContentData(actualContent, expectedContent); } + return null; } -void checkExpectedContentData( +Result checkExpectedContentData( Map> actualContent, Map expectedContent) { - doThrow() { - throw "Expected and actual content not the same.\n" + Result createFailureResult() { + return new Result( + null, + ContentDataMismatch, + "Expected and actual content not the same.\n" "Expected $expectedContent.\n" - "Got $actualContent"; + "Got $actualContent"); } - if (actualContent.length != expectedContent.length) doThrow(); + if (actualContent.length != expectedContent.length) { + return createFailureResult(); + } Set missingKeys = actualContent.keys.toSet() ..removeAll(expectedContent.keys); - if (missingKeys.isNotEmpty) doThrow(); + if (missingKeys.isNotEmpty) { + return createFailureResult(); + } for (String key in expectedContent.keys) { Set expected = new Set.from(expectedContent[key]); Set actual = actualContent[key].toSet(); - if (expected.length != actual.length) doThrow(); + if (expected.length != actual.length) { + return createFailureResult(); + } actual.removeAll(expected); - if (actual.isNotEmpty) doThrow(); + if (actual.isNotEmpty) { + return createFailureResult(); + } } + return null; } Map> buildMapOfContent(Component component) { @@ -1301,8 +1479,8 @@ Map> buildMapOfContent(Component component) { return actualContent; } -void checkNeededDillLibraries( - YamlMap world, Set neededDillLibraries, Uri base) { +Result checkNeededDillLibraries( + YamlMap world, TestData data, Set neededDillLibraries, Uri base) { if (world["neededDillLibraries"] != null) { List actualContent = new List(); for (Library lib in neededDillLibraries) { @@ -1315,20 +1493,30 @@ void checkNeededDillLibraries( expectedContent.add(base.resolve(entry)); } - doThrow() { - throw "Expected and actual content not the same.\n" + Result createFailureResult() { + return new Result( + data, + NeededDillMismatch, + "Expected and actual content not the same.\n" "Expected $expectedContent.\n" - "Got $actualContent"; + "Got $actualContent"); } - if (actualContent.length != expectedContent.length) doThrow(); + if (actualContent.length != expectedContent.length) { + return createFailureResult(); + } Set notInExpected = actualContent.toSet().difference(expectedContent.toSet()); Set notInActual = expectedContent.toSet().difference(actualContent.toSet()); - if (notInExpected.isNotEmpty) doThrow(); - if (notInActual.isNotEmpty) doThrow(); + if (notInExpected.isNotEmpty) { + return createFailureResult(); + } + if (notInActual.isNotEmpty) { + return createFailureResult(); + } } + return null; } String nodeToString(TreeNode node) { @@ -1386,22 +1574,28 @@ int countSyntheticLibraries(Component c) { return result; } -void performErrorAndWarningCheck( +Result performErrorAndWarningCheck( YamlMap world, + TestData data, bool gotError, Set formattedErrors, bool gotWarning, Set formattedWarnings) { if (world["errors"] == true && !gotError) { - throw "Expected error, but didn't get any."; + return new Result( + data, MissingErrors, "Expected error, but didn't get any."); } else if (world["errors"] != true && gotError) { - throw "Got unexpected error(s): $formattedErrors."; + return new Result( + data, UnexpectedErrors, "Got unexpected error(s): $formattedErrors."); } if (world["warnings"] == true && !gotWarning) { - throw "Expected warning, but didn't get any."; + return new Result( + data, MissingWarnings, "Expected warning, but didn't get any."); } else if (world["warnings"] != true && gotWarning) { - throw "Got unexpected warnings(s): $formattedWarnings."; + return new Result(data, UnexpectedWarnings, + "Got unexpected warnings(s): $formattedWarnings."); } + return null; } void checkIsEqual(List a, List b) { diff --git a/pkg/front_end/test/utils/kernel_chain.dart b/pkg/front_end/test/utils/kernel_chain.dart index 804af3cf00d..4b0f44e7758 100644 --- a/pkg/front_end/test/utils/kernel_chain.dart +++ b/pkg/front_end/test/utils/kernel_chain.dart @@ -94,8 +94,8 @@ abstract class MatchContext implements ChainContext { } String diff = await runDiff(expectedFile.uri, actual); onMismatch ??= expectationFileMismatch; - return new Result(output, onMismatch, - "$uri doesn't match ${expectedFile.uri}\n$diff", null, + return new Result( + output, onMismatch, "$uri doesn't match ${expectedFile.uri}\n$diff", autoFixCommand: onMismatch == expectationFileMismatch ? updateExpectationsOption : null); @@ -113,7 +113,6 @@ abstract class MatchContext implements ChainContext { """ Please create file ${expectedFile.path} with this content: $actual""", - null, autoFixCommand: updateExpectationsOption); } } @@ -179,8 +178,7 @@ class TypeCheck extends Step { return new Result( null, context.expectationSet["TypeCheckError"], - '${errorFormatter.numberOfFailures} type errors', - null); + '${errorFormatter.numberOfFailures} type errors'); } } } @@ -377,11 +375,8 @@ class KernelTextSerialization } if (failures.isNotEmpty) { - return new Result( - null, - context.expectationSet["TextSerializationFailure"], - "$messages", - null); + return new Result(null, + context.expectationSet["TextSerializationFailure"], "$messages"); } return pass(result); }); diff --git a/pkg/testing/lib/src/chain.dart b/pkg/testing/lib/src/chain.dart index a6c982d4e79..c6f6c16ef4b 100644 --- a/pkg/testing/lib/src/chain.dart +++ b/pkg/testing/lib/src/chain.dart @@ -358,16 +358,18 @@ class Result { /// update the test to match new expectations. final String autoFixCommand; - Result(this.output, this.outcome, this.error, this.trace, - {this.autoFixCommand}); + Result(this.output, this.outcome, this.error, + {this.trace, this.autoFixCommand}); - Result.pass(O output) : this(output, Expectation.Pass, null, null); + Result.pass(O output) : this(output, Expectation.Pass, null); Result.crash(error, StackTrace trace) - : this(null, Expectation.Crash, error, trace); + : this(null, Expectation.Crash, error, trace: trace); Result.fail(O output, [error, StackTrace trace]) - : this(output, Expectation.Fail, error, trace); + : this(output, Expectation.Fail, error, trace: trace); + + bool get isPass => outcome == Expectation.Pass; String get log => logs.join(); @@ -376,7 +378,14 @@ class Result { } Result copyWithOutcome(Expectation outcome) { - return new Result(output, outcome, error, trace)..logs.addAll(logs); + return new Result(output, outcome, error, trace: trace) + ..logs.addAll(logs); + } + + Result copyWithOutput(O2 output) { + return new Result(output, outcome, error, + trace: trace, autoFixCommand: autoFixCommand) + ..logs.addAll(logs); } } diff --git a/pkg/testing/lib/src/expectation.dart b/pkg/testing/lib/src/expectation.dart index 8c8e7e9d492..58efce8268b 100644 --- a/pkg/testing/lib/src/expectation.dart +++ b/pkg/testing/lib/src/expectation.dart @@ -34,6 +34,8 @@ class Expectation { const Expectation(this.name, this.group); + const Expectation.fail(this.name) : group = ExpectationGroup.Fail; + /// Returns the canonical expectation representing [group]. That is, one of /// the above expectations (except for `Meta` which returns `this`). Expectation get canonical => fromGroup(group) ?? this; diff --git a/pkg/testing/lib/src/stdio_process.dart b/pkg/testing/lib/src/stdio_process.dart index 72b534a0e69..16bbfdfdfb0 100644 --- a/pkg/testing/lib/src/stdio_process.dart +++ b/pkg/testing/lib/src/stdio_process.dart @@ -28,7 +28,7 @@ class StdioProcess { return new Result.pass(exitCode); } else { return new Result( - exitCode, ExpectationSet.Default["RuntimeError"], output, null); + exitCode, ExpectationSet.Default["RuntimeError"], output); } }