blob: dfd0b903a2991e96ea7789f928a4c80a7f5215dc [file] [log] [blame]
// 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 file.
import 'dart:developer';
import 'package:test/test.dart';
import 'package:vm_service/vm_service.dart';
import 'common/service_test_common.dart';
import 'common/test_helper.dart';
class Foo {
Foo() {
print('Foo');
}
}
class Bar {
Bar() {
print('Bar');
}
}
void test() {
final List l = <Object>[];
debugger();
// Toggled on for Foo.
// Traced allocation.
l.add(Foo());
// Untraced allocation.
l.add(Bar());
// Toggled on for Bar.
debugger();
// Traced allocation.
l.add(Bar());
debugger();
}
Future<Class?> getClassFromRootLib(
VmService service,
IsolateRef isolateRef,
String className,
) async {
final isolate = await service.getIsolate(isolateRef.id!);
final Library rootLib =
(await service.getObject(isolate.id!, isolate.rootLib!.id!)) as Library;
for (ClassRef cls in rootLib.classes!) {
if (cls.name == className) {
return (await service.getObject(isolate.id!, cls.id!)) as Class;
}
}
return null;
}
late Class fooClass;
late Class barClass;
final tests = <IsolateTest>[
hasStoppedAtBreakpoint,
stoppedAtLine(27),
// Initial.
(VmService service, IsolateRef isolate) async {
// Verify initial state of 'Foo'.
fooClass = (await getClassFromRootLib(service, isolate, 'Foo'))!;
expect(fooClass.name, equals('Foo'));
expect(fooClass.traceAllocations, false);
await service.setTraceClassAllocation(isolate.id!, fooClass.id!, true);
fooClass = await service.getObject(isolate.id!, fooClass.id!) as Class;
expect(fooClass.traceAllocations, true);
},
resumeIsolate,
hasStoppedAtBreakpoint,
stoppedAtLine(34),
// Allocation profile.
(VmService service, IsolateRef isolate) async {
fooClass = (await getClassFromRootLib(service, isolate, 'Foo'))!;
expect(fooClass.traceAllocations, true);
final profileResponse = await service.getAllocationTraces(isolate.id!);
expect(profileResponse, isNotNull);
expect(profileResponse.samples!.length, 1);
expect(profileResponse.samples!.first.identityHashCode != 0, true);
print(profileResponse.samples);
final instances = await service.getInstances(
isolate.id!,
fooClass.id!,
1,
);
expect(instances.totalCount, 1);
final instance = instances.instances!.first as InstanceRef;
expect(instance.identityHashCode != 0, isTrue);
expect(
instance.identityHashCode,
profileResponse.samples!.first.identityHashCode,
);
await service.setTraceClassAllocation(isolate.id!, fooClass.id!, false);
fooClass = await service.getObject(isolate.id!, fooClass.id!) as Class;
expect(fooClass.traceAllocations, false);
// Trace Bar.
barClass = (await getClassFromRootLib(service, isolate, 'Bar'))!;
expect(barClass.traceAllocations, false);
await service.setTraceClassAllocation(isolate.id!, barClass.id!, true);
barClass = (await getClassFromRootLib(service, isolate, 'Bar'))!;
expect(barClass.traceAllocations, true);
print('Allocation tracing enabled for Bar');
},
resumeIsolate,
hasStoppedAtBreakpoint,
stoppedAtLine(37),
(VmService service, IsolateRef isolate) async {
// Ensure the allocation of `Bar()` was recorded.
final profileResponse = await service.getAllocationTraces(isolate.id!);
final samples = profileResponse.samples!;
if (samples.length != 2) {
print('Foo ID: ${fooClass.id}');
print('Bar ID: ${barClass.id}');
final functions = profileResponse.functions!;
for (final sample in samples) {
print('Sample for CID: ${sample.classId}');
for (int i = 0; i < sample.stack!.length; ++i) {
final frame = sample.stack![i];
final location = (functions[frame].function as FuncRef).location!;
print('$i: ${location.script!.uri}:${location.line}');
}
}
}
expect(profileResponse.samples!.length, 2);
},
];
void main([args = const <String>[]]) => runIsolateTests(
args,
tests,
'get_allocation_traces_test.dart',
testeeConcurrent: test,
);