blob: f00e9778e52c4205988b201a081ced36610407b0 [file] [log] [blame]
// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
import 'dart:io';
import 'package:test/test.dart';
import 'package:vm_snapshot_analysis/precompiler_trace.dart';
import 'package:vm_snapshot_analysis/program_info.dart';
import 'utils.dart';
final testSource = {
'input.dart': """
class K {
final value;
const K(this.value);
}
@pragma('vm:never-inline')
dynamic makeSomeClosures() {
return [
() => const K(0),
() => const K(1),
() => 11,
];
}
class A {
@pragma('vm:never-inline')
dynamic tornOff() {
return const K(2);
}
}
class B {
@pragma('vm:never-inline')
dynamic tornOff() {
return const K(3);
}
}
class C {
static dynamic tornOff() async {
return const K(4);
}
}
@pragma('vm:never-inline')
Function tearOff(dynamic o) {
return o.tornOff;
}
void main(List<String> args) {
for (var cl in makeSomeClosures()) {
print(cl());
}
print(tearOff(args.isEmpty ? A() : B()));
print(C.tornOff);
}
"""
};
void main() async {
if (!Platform.executable.contains('dart-sdk')) {
// If we are not running from the prebuilt SDK then this test does nothing.
return;
}
group('precompiler-trace', () {
test('basic-parsing', () async {
await withFlag(testSource, '--trace_precompiler_to', (json) async {
final jsonRaw = await loadJson(File(json));
final callGraph = loadTrace(jsonRaw);
callGraph.computeDominators();
final main = callGraph.program
.lookup(['package:input', 'package:input/input.dart', '', 'main'])!;
final mainNode = callGraph.lookup(main);
final retainedClasses = mainNode.dominated
.where((n) => n.isClassNode)
.map((n) => n.data.name)
.toList();
final retainedFunctions = mainNode.dominated
.where((n) => n.isFunctionNode)
.map((n) => n.data.name)
.toList();
expect(retainedClasses, containsAll(['A', 'B', 'K']));
expect(retainedFunctions, containsAll(['print', 'tearOff']));
final getTearOffCall = callGraph.dynamicCalls
.firstWhere((n) => n.data == 'dyn:get:tornOff');
expect(
getTearOffCall.dominated.map((n) => n.data.qualifiedName),
equals([
'package:input/input.dart::B.[tear-off-extractor] get:tornOff',
'package:input/input.dart::A.[tear-off-extractor] get:tornOff',
]));
});
});
test('collapse-by-package', () async {
await withFlag(testSource, '--trace_precompiler_to', (json) async {
final jsonRaw = await loadJson(File(json));
final callGraph = loadTrace(jsonRaw).collapse(NodeType.packageNode);
// Collapsing by package should not collapse dart:* libraries into root
// node and create predecessors for the root node.
expect(callGraph.root.pred, isEmpty);
});
});
});
}