blob: 17b65f11d14f4ea09c8c5b84afdbc60f008eb151 [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 file.
import 'package:test/test.dart';
import 'package:vm_service/vm_service.dart';
import 'common/service_test_common.dart';
import 'get_allocation_traces_lib.dart' as testee_lib;
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.libraries!
.firstWhere((l) => l.uri!.contains('get_allocation_traces_lib'))
.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;
void main([args = const <String>[]]) => IsolateTestHarness(
'get_allocation_traces_lib.dart',
args,
)
.hasStoppedAtBreakpoint()
.stoppedAtLine('LINE_A')
// Initial.
.addCustomTest((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('LINE_B')
// Allocation profile.
.addCustomTest((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('LINE_C')
.addCustomTest((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);
})
.run(testeeMain: testee_lib.main);