[CFE] Check class hierarchy in incremental compiler test

Change-Id: I963716d36bec213739bbc266f9494885edd0aa08
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/133104
Commit-Queue: Jens Johansen <jensj@google.com>
Reviewed-by: Johnni Winther <johnniwinther@google.com>
This commit is contained in:
Jens Johansen
2020-01-31 10:38:41 +00:00
committed by commit-bot@chromium.org
parent 5e38b59740
commit 3f3d3dfa12
8 changed files with 218 additions and 35 deletions
@@ -40,12 +40,14 @@ import 'package:front_end/src/fasta/incremental_compiler.dart'
import 'package:front_end/src/fasta/incremental_serializer.dart'
show IncrementalSerializer;
import 'package:front_end/src/fasta/kernel/kernel_api.dart';
import 'package:front_end/src/fasta/kernel/utils.dart' show ByteSink;
import 'package:kernel/binary/ast_from_binary.dart' show BinaryBuilder;
import 'package:kernel/binary/ast_to_binary.dart' show BinaryPrinter;
import 'package:kernel/class_hierarchy.dart';
import 'package:kernel/kernel.dart'
show
@@ -55,6 +57,7 @@ import 'package:kernel/kernel.dart'
Field,
Library,
LibraryDependency,
Member,
Name,
Procedure;
@@ -608,25 +611,8 @@ Future<Null> newWorldTest(
}
}
Uri uri = data.loadedFrom
.resolve(data.loadedFrom.pathSegments.last + ".world.$worldNum.expect");
String expected;
File file = new File.fromUri(uri);
if (context.updateExpectations) {
file.writeAsStringSync(actualSerialized);
}
if (file.existsSync()) {
expected = file.readAsStringSync();
}
if (context.updateExpectations) {
file.writeAsStringSync(actualSerialized);
} else if (expected != actualSerialized) {
String extra = "";
if (expected == null) extra = "Expect file did not exist.\n";
throw "${extra}Unexpected serialized representation. "
"Fix or update $uri to contain the below:\n\n"
"$actualSerialized";
}
checkExpectFile(data, worldNum, context, actualSerialized);
checkClassHierarchy(compiler, component, data, worldNum, context);
int nonSyntheticLibraries = countNonSyntheticLibraries(component);
int nonSyntheticPlatformLibraries =
@@ -848,6 +834,166 @@ Future<Null> newWorldTest(
}
}
void checkExpectFile(
TestData data, int worldNum, Context context, String actualSerialized) {
Uri uri = data.loadedFrom
.resolve(data.loadedFrom.pathSegments.last + ".world.$worldNum.expect");
String expected;
File file = new File.fromUri(uri);
if (file.existsSync()) {
expected = file.readAsStringSync();
}
if (expected != actualSerialized) {
if (context.updateExpectations) {
file.writeAsStringSync(actualSerialized);
} else {
String extra = "";
if (expected == null) extra = "Expect file did not exist.\n";
throw "${extra}Unexpected serialized representation. "
"Fix or update $uri to contain the below:\n\n"
"$actualSerialized";
}
}
}
/// 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,
{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}";
}
List<ForTestingClassInfo> classHierarchyData =
(classHierarchy as ClosedWorldClassHierarchy).getTestingClassInfo();
Map<Class, ForTestingClassInfo> classHierarchyMap =
new Map<Class, ForTestingClassInfo>();
for (ForTestingClassInfo info in classHierarchyData) {
if (classHierarchyMap[info.classNode] != null) {
throw "Two entries for ${info.classNode}";
}
classHierarchyMap[info.classNode] = info;
}
StringBuffer sb = new StringBuffer();
for (Library library in component.libraries) {
if (library.importUri.scheme == "dart") continue;
sb.writeln("Library ${library.importUri}");
for (Class c in library.classes) {
sb.writeln(" - Class ${c.name}");
ForTestingClassInfo info = classHierarchyMap[c];
if (info == null) {
throw "Didn't find any class hierarchy info for $c";
}
if (info.lazyDeclaredGettersAndCalls != null) {
sb.writeln(" - lazyDeclaredGettersAndCalls:");
for (Member member in info.lazyDeclaredGettersAndCalls) {
sb.writeln(" - ${member.name.name}");
}
// Expect these to be the same as in the class.
Set<Member> members = info.lazyDeclaredGettersAndCalls.toSet();
for (Field f in c.fields) {
if (f.isStatic) continue;
if (!f.hasImplicitGetter) continue;
if (!members.remove(f)) {
throw "Didn't find ${f.name.name} 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.name} in lazyDeclaredGettersAndCalls "
"for ${c.name} in ${library.importUri}";
}
}
if (members.isNotEmpty) {
throw "Still have ${members.map((m) => m.name.name)} left "
"for ${c.name} in ${library.importUri}";
}
}
if (info.lazyDeclaredSetters != null) {
sb.writeln(" - lazyDeclaredSetters:");
for (Member member in info.lazyDeclaredSetters) {
sb.writeln(" - ${member.name.name}");
}
// Expect these to be the same as in the class.
Set<Member> members = info.lazyDeclaredSetters.toSet();
for (Field f in c.fields) {
if (f.isStatic) continue;
if (!f.hasImplicitSetter) continue;
if (!members.remove(f)) {
throw "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";
}
}
if (members.isNotEmpty) {
throw "Still have ${members.map((m) => m.name.name)} left "
"for ${c.name} in ${library.importUri}";
}
}
if (info.lazyImplementedGettersAndCalls != null) {
sb.writeln(" - lazyImplementedGettersAndCalls:");
for (Member member in info.lazyImplementedGettersAndCalls) {
sb.writeln(" - ${member.name.name}");
}
}
if (info.lazyImplementedSetters != null) {
sb.writeln(" - lazyImplementedSetters:");
for (Member member in info.lazyImplementedSetters) {
sb.writeln(" - ${member.name.name}");
}
}
if (info.lazyInterfaceGettersAndCalls != null) {
sb.writeln(" - lazyInterfaceGettersAndCalls:");
for (Member member in info.lazyInterfaceGettersAndCalls) {
sb.writeln(" - ${member.name.name}");
}
}
if (info.lazyInterfaceSetters != null) {
sb.writeln(" - lazyInterfaceSetters:");
for (Member member in info.lazyInterfaceSetters) {
sb.writeln(" - ${member.name.name}");
}
}
}
}
if (checkExpectFile) {
String actualClassHierarchy = sb.toString();
Uri uri = data.loadedFrom.resolve(data.loadedFrom.pathSegments.last +
".world.$worldNum.class_hierarchy.expect");
String expected;
File file = new File.fromUri(uri);
if (file.existsSync()) {
expected = file.readAsStringSync();
}
if (expected != actualClassHierarchy) {
if (context.updateExpectations) {
file.writeAsStringSync(actualClassHierarchy);
} else {
String extra = "";
if (expected == null) extra = "Expect file did not exist.\n";
throw "${extra}Unexpected serialized representation. "
"Fix or update $uri to contain the below:\n\n"
"$actualClassHierarchy";
}
}
}
}
void checkErrorsAndWarnings(
Set<String> prevFormattedErrors,
Set<String> formattedErrors,
@@ -899,14 +1045,14 @@ List<int> checkIncrementalSerialization(
throw "Incremental serialization didn't remove any libraries!";
}
if (librariesAfter < librariesBefore && sink.builder.isEmpty) {
throw "Incremental serialization din't output any bytes, "
throw "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";
}
if (librariesAfter < librariesBefore) {
// If we actually did incremenally serialize anything, check the output!
// If we actually did incrementally serialize anything, check the output!
BinaryPrinter printer = new BinaryPrinter(sink);
printer.writeComponentFile(c);
List<int> bytes = sink.builder.takeBytes();
@@ -1389,10 +1535,10 @@ class TestIncrementalCompiler extends IncrementalCompiler {
void doSimulateTransformer(Component c) {
for (Library lib in c.libraries) {
if (lib.fields
.where((f) => f.name.name == "lalala_SimulateTransformer")
.where((f) => f.name.name == "unique_SimulateTransformer")
.toList()
.isNotEmpty) continue;
Name fieldName = new Name("lalala_SimulateTransformer");
Name fieldName = new Name("unique_SimulateTransformer");
Field field = new Field(fieldName,
isFinal: true,
reference: lib.reference.canonicalName
@@ -1401,10 +1547,10 @@ void doSimulateTransformer(Component c) {
lib.addMember(field);
for (Class c in lib.classes) {
if (c.fields
.where((f) => f.name.name == "lalala_SimulateTransformer")
.where((f) => f.name.name == "unique_SimulateTransformer")
.toList()
.isNotEmpty) continue;
fieldName = new Name("lalala_SimulateTransformer");
fieldName = new Name("unique_SimulateTransformer");
field = new Field(fieldName,
isFinal: true,
reference: c.reference.canonicalName
@@ -57,6 +57,7 @@ boo
bootstrap
bots
bowtie
brand
brave
brown
builddir
@@ -111,6 +112,7 @@ dartfile
dashes
day
db
debugger
decrease
decrements
def
@@ -190,6 +192,7 @@ func
futures
gallery
gamma
gave
gc
gen
generators
@@ -201,6 +204,7 @@ gulp
gunk
hackish
harness
helper2
hest
heuristics
hi
@@ -276,6 +280,8 @@ moo
mx
mysdk
negatable
newest
newworld
ninja
nonexisting
noo
@@ -359,6 +365,8 @@ shipped
shortest
shot
signalled
slight
smoke
somehow
spans
spell
@@ -434,6 +442,7 @@ whitelist
whitelisting
wins
workflow
worlds
ws
x's
xxx
@@ -35,10 +35,10 @@ worlds:
expectedContent:
org-dartlang-test:///main.dart:
- Procedure main
- Field lalala_SimulateTransformer
- Field unique_SimulateTransformer
package:foo/foo.dart:
- Field foo
- Field lalala_SimulateTransformer
- Field unique_SimulateTransformer
neededDillLibraries:
- package:foo/foo.dart
- entry: main.dart
@@ -61,7 +61,7 @@ worlds:
expectedContent:
org-dartlang-test:///main.dart:
- Procedure main
- Field lalala_SimulateTransformer
- Field unique_SimulateTransformer
package:foo/foo.dart:
- Field foo2
- Field lalala_SimulateTransformer
- Field unique_SimulateTransformer
@@ -2,13 +2,13 @@ main = <No Member>;
library from "package:foo/foo.dart" as foo {
static field dart.core::bool* foo = true;
final field dynamic lalala_SimulateTransformer /* from null */;
final field dynamic unique_SimulateTransformer /* from null */;
}
library from "org-dartlang-test:///main.dart" as main {
import "package:foo/foo.dart";
final field dynamic lalala_SimulateTransformer /* from null */;
final field dynamic unique_SimulateTransformer /* from null */;
static method main() → dynamic {
dart.core::print(foo::foo);
}
@@ -2,13 +2,13 @@ main = <No Member>;
library from "package:foo/foo.dart" as foo {
static field dart.core::bool* foo2 = true;
final field dynamic lalala_SimulateTransformer /* from null */;
final field dynamic unique_SimulateTransformer /* from null */;
}
library from "org-dartlang-test:///main.dart" as main {
import "package:foo/foo.dart";
final field dynamic lalala_SimulateTransformer /* from null */;
final field dynamic unique_SimulateTransformer /* from null */;
static method main() → dynamic {
dart.core::print(foo::foo2);
}
@@ -4,6 +4,9 @@
# Status file for the test suite ../test/incremental_load_from_dill_test.dart.
ffi_01: Crash # Class hierarchy is out of date.
ffi_02: Crash # Class hierarchy is out of date.
no_outline_change_1: Crash # Doesn't work on DillLibraryBuilders.
no_outline_change_2: Crash # Doesn't work on DillLibraryBuilders.
no_outline_change_6: Crash # Doesn't work on DillLibraryBuilders.
-2
View File
@@ -284,8 +284,6 @@
"test/fasta/super_mixins_test\\.dart$",
"test/fasta/types/subtypes_benchmark\\.dart$",
"test/fasta/unlinked_scope_test\\.dart$",
"test/incremental_load_from_dill_suite\\.dart$",
"test/incremental_load_from_invalid_dill_test\\.dart$",
"test/memory_file_system_test\\.dart$",
"test/scanner_fasta_test\\.dart$",
"test/scanner_test\\.dart$",
+27
View File
@@ -451,6 +451,14 @@ class ClosedWorldClassHierarchy implements ClassHierarchy {
final Map<Class, _ClassInfo> _infoMap =
new LinkedHashMap<Class, _ClassInfo>();
List<ForTestingClassInfo> getTestingClassInfo() {
List<ForTestingClassInfo> result = new List<ForTestingClassInfo>();
for (_ClassInfo info in _infoMap.values) {
result.add(new ForTestingClassInfo._(info));
}
return result;
}
_ClassInfo infoFor(Class c) {
_ClassInfo info = _infoMap[c];
info?.used = true;
@@ -1444,6 +1452,25 @@ int _intervalListSize(Uint32List intervalList) {
return size;
}
class ForTestingClassInfo {
final Class classNode;
final List<Member> lazyDeclaredGettersAndCalls;
final List<Member> lazyDeclaredSetters;
final List<Member> lazyImplementedGettersAndCalls;
final List<Member> lazyImplementedSetters;
final List<Member> lazyInterfaceGettersAndCalls;
final List<Member> lazyInterfaceSetters;
ForTestingClassInfo._(_ClassInfo c)
: classNode = c.classNode,
lazyDeclaredGettersAndCalls = c.lazyDeclaredGettersAndCalls,
lazyDeclaredSetters = c.lazyDeclaredSetters,
lazyImplementedGettersAndCalls = c.lazyImplementedGettersAndCalls,
lazyImplementedSetters = c.lazyImplementedSetters,
lazyInterfaceGettersAndCalls = c.lazyInterfaceGettersAndCalls,
lazyInterfaceSetters = c.lazyInterfaceSetters;
}
class _ClassInfo {
bool used = false;
final Class classNode;