blob: 56ccd2e63e9ec8f9005a174afd411a13b22760e6 [file] [log] [blame]
// Copyright (c) 2015, 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:observatory_2/service_io.dart';
import 'package:test/test.dart';
import 'test_helper.dart';
class _TestClass {
_TestClass();
// Make sure these fields are not removed by the tree shaker.
@pragma("vm:entry-point") // Prevent obfuscation
var x;
@pragma("vm:entry-point") // Prevent obfuscation
var y;
}
var target1 = new _TestClass();
var target2 = new _TestClass();
var target3 = new _TestClass();
var target4 = new _TestClass();
var target5 = new _TestClass();
var target6 = new _TestClass();
@pragma("vm:entry-point") // Prevent obfuscation
Expando<_TestClass> expando = Expando<_TestClass>();
@pragma("vm:entry-point") // Prevent obfuscation
var globalObject = new _TestClass();
@pragma("vm:entry-point") // Prevent obfuscation
var globalList = new List(100);
@pragma("vm:entry-point") // Prevent obfuscation
var globalMap1 = new Map();
@pragma("vm:entry-point") // Prevent obfuscation
var globalMap2 = new Map();
void warmup() {
globalObject.x = target1;
globalObject.y = target2;
globalList[12] = target3;
globalMap1['key'] = target4;
globalMap2[target5] = 'value';
}
@pragma("vm:entry-point") // Prevent obfuscation
getGlobalObject() => globalObject;
@pragma("vm:entry-point") // Prevent obfuscation
takeTarget1() {
var tmp = target1;
target1 = null;
return tmp;
}
@pragma("vm:entry-point") // Prevent obfuscation
takeTarget2() {
var tmp = target2;
target2 = null;
return tmp;
}
@pragma("vm:entry-point") // Prevent obfuscation
takeTarget3() {
var tmp = target3;
target3 = null;
return tmp;
}
@pragma("vm:entry-point") // Prevent obfuscation
takeTarget4() {
var tmp = target4;
target4 = null;
return tmp;
}
@pragma("vm:entry-point") // Prevent obfuscation
takeTarget5() {
var tmp = target5;
target5 = null;
return tmp;
}
@pragma("vm:entry-point") // Prevent obfuscation
takeExpandoTarget() {
var tmp = target6;
target6 = null;
var tmp2 = _TestClass();
expando[tmp] = tmp2;
return tmp2;
}
@pragma("vm:entry-point") // Prevent obfuscation
getTrue() => true;
invoke(Isolate isolate, String selector) async {
Map params = {
'targetId': isolate.rootLibrary.id,
'selector': selector,
'argumentIds': <String>[],
};
return await isolate.invokeRpcNoUpgrade('invoke', params);
}
var tests = <IsolateTest>[
// simple path
(Isolate isolate) async {
var obj = await invoke(isolate, 'getGlobalObject');
var params = {
'targetId': obj['id'],
'limit': 100,
};
var result = await isolate.invokeRpcNoUpgrade('getRetainingPath', params);
expect(result['gcRootType'], 'user global');
expect(result['elements'].length, equals(2));
expect(result['elements'][1]['value']['name'], equals('globalObject'));
},
// missing limit.
(Isolate isolate) async {
var obj = await invoke(isolate, 'getGlobalObject');
var params = {
'targetId': obj['id'],
};
bool caughtException;
try {
await isolate.invokeRpcNoUpgrade('getRetainingPath', params);
expect(false, isTrue, reason: 'Unreachable');
} on ServerRpcException catch (e) {
caughtException = true;
expect(e.code, equals(ServerRpcException.kInvalidParams));
expect(e.data['details'],
"getRetainingPath expects the \'limit\' parameter");
}
expect(caughtException, isTrue);
},
(Isolate isolate) async {
var target1 = await invoke(isolate, 'takeTarget1');
var params = {
'targetId': target1['id'],
'limit': 100,
};
var result = await isolate.invokeRpcNoUpgrade('getRetainingPath', params);
expect(result['type'], equals('RetainingPath'));
expect(result['gcRootType'], 'user global');
expect(result['elements'].length, equals(3));
expect(result['elements'][1]['parentField'], equals('x'));
expect(result['elements'][2]['value']['name'], equals('globalObject'));
},
(Isolate isolate) async {
var target2 = await invoke(isolate, 'takeTarget2');
var params = {
'targetId': target2['id'],
'limit': 100,
};
var result = await isolate.invokeRpcNoUpgrade('getRetainingPath', params);
expect(result['type'], equals('RetainingPath'));
expect(result['gcRootType'], 'user global');
expect(result['elements'].length, equals(3));
expect(result['elements'][1]['parentField'], equals('y'));
expect(result['elements'][2]['value']['name'], equals('globalObject'));
},
(Isolate isolate) async {
var target3 = await invoke(isolate, 'takeTarget3');
var params = {
'targetId': target3['id'],
'limit': 100,
};
var result = await isolate.invokeRpcNoUpgrade('getRetainingPath', params);
expect(result['type'], equals('RetainingPath'));
expect(result['gcRootType'], 'user global');
expect(result['elements'].length, equals(3));
expect(result['elements'][1]['parentListIndex'], equals(12));
expect(result['elements'][2]['value']['name'], equals('globalList'));
},
(Isolate isolate) async {
var target4 = await invoke(isolate, 'takeTarget4');
var params = {
'targetId': target4['id'],
'limit': 100,
};
var result = await isolate.invokeRpcNoUpgrade('getRetainingPath', params);
expect(result['type'], equals('RetainingPath'));
expect(result['gcRootType'], 'user global');
expect(result['elements'].length, equals(3));
expect(
result['elements'][1]['parentMapKey']['valueAsString'], equals('key'));
expect(result['elements'][2]['value']['name'], equals('globalMap1'));
},
(Isolate isolate) async {
var target5 = await invoke(isolate, 'takeTarget5');
var params = {
'targetId': target5['id'],
'limit': 100,
};
var result = await isolate.invokeRpcNoUpgrade('getRetainingPath', params);
expect(result['type'], equals('RetainingPath'));
expect(result['elements'].length, equals(3));
expect(result['elements'][1]['parentMapKey']['class']['name'],
equals('_TestClass'));
expect(result['elements'][2]['value']['name'], equals('globalMap2'));
},
(Isolate isolate) async {
// Regression test for https://github.com/dart-lang/sdk/issues/44016
var target6 = await invoke(isolate, 'takeExpandoTarget');
var params = {
'targetId': target6['id'],
'limit': 100,
};
var result = await isolate.invokeRpcNoUpgrade('getRetainingPath', params);
expect(result['type'], equals('RetainingPath'));
expect(result['elements'].length, equals(5));
expect(result['elements'][1]['parentMapKey']['class']['name'],
equals('_TestClass'));
expect(result['elements'][2]['parentListIndex'], isNotNull);
expect(result['elements'][4]['value']['name'], 'expando');
},
// object store
(Isolate isolate) async {
var obj = await invoke(isolate, 'getTrue');
var params = {
'targetId': obj['id'],
'limit': 100,
};
var result = await isolate.invokeRpcNoUpgrade('getRetainingPath', params);
expect(
result['gcRootType'] == 'class table' ||
result['gcRootType'] == 'isolate_object store',
true);
expect(result['elements'].length, 0);
},
];
main(args) async => runIsolateTests(args, tests, testeeBefore: warmup);