-
Notifications
You must be signed in to change notification settings - Fork 1.6k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge 8fa0f56 into dev
- Loading branch information
Showing
24 changed files
with
754 additions
and
143 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,315 @@ | ||
// Copyright (c) 2024, 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'; | ||
|
||
// AUTOGENERATED START | ||
// | ||
// Update these constants by running: | ||
// | ||
// dart pkg/vm_service/test/update_line_numbers.dart <test.dart> | ||
// | ||
const LINE_A = 29; | ||
// AUTOGENERATED END | ||
|
||
class C { | ||
final int x = 123; | ||
} | ||
|
||
void testeeMain() { | ||
// ignore: unused_local_variable | ||
final c = C(); | ||
debugger(); // LINE_A | ||
} | ||
|
||
final tests = <IsolateTest>[ | ||
// TODO(derekxu16): Replace the usages of [callMethod] below with calls to | ||
// dedicated RPC methods once they're available in package:vm_service. | ||
hasStoppedAtBreakpoint, | ||
stoppedAtLine(LINE_A), | ||
// Test the behaviour of an ID Zone with a `backingBufferKind` of `Ring`, an | ||
// `idAssignmentPolicy` of `AlwaysAllocate`, and the default capacity. | ||
(VmService service, IsolateRef isolateRef) async { | ||
final isolateId = isolateRef.id!; | ||
final idZone1 = (await service.callMethod( | ||
'_createIdZone', | ||
isolateId: isolateId, | ||
args: { | ||
'backingBufferKind': 'Ring', | ||
'idAssignmentPolicy': 'AlwaysAllocate', | ||
}, | ||
)) | ||
.json!; | ||
expect(idZone1['type'], '_IdZone'); | ||
expect(idZone1['id'], 'zones/1'); | ||
expect(idZone1['backingBufferKind'], 'Ring'); | ||
expect(idZone1['idAssignmentPolicy'], 'AlwaysAllocate'); | ||
|
||
final cInstanceRef1 = (await service.callMethod( | ||
'evaluateInFrame', | ||
isolateId: isolateId, | ||
args: { | ||
'frameIndex': 0, | ||
'expression': 'c', | ||
'_idZoneId': idZone1['id'], | ||
}, | ||
)) | ||
.json!; | ||
expect(cInstanceRef1['type'], '@Instance'); | ||
final cObjectId1 = cInstanceRef1['id']; | ||
expect(cObjectId1, 'objects/0/1'); | ||
|
||
final cInstance1 = await service.getObject(isolateId, cObjectId1); | ||
expect(cInstance1.type, 'Instance'); | ||
|
||
final cInstanceRef2 = (await service.callMethod( | ||
'evaluateInFrame', | ||
isolateId: isolateId, | ||
args: { | ||
'frameIndex': 0, | ||
'expression': 'c', | ||
'_idZoneId': idZone1['id'], | ||
}, | ||
)) | ||
.json!; | ||
expect(cInstanceRef2['type'], '@Instance'); | ||
final cObjectId2 = cInstanceRef2['id']; | ||
expect(cObjectId2, 'objects/1/1'); | ||
|
||
final cInstance2 = await service.getObject(isolateId, cObjectId2); | ||
expect(cInstance2.type, 'Instance'); | ||
|
||
await service.callMethod( | ||
'_invalidateIdZone', | ||
isolateId: isolateId, | ||
args: { | ||
'_idZoneId': idZone1['id'], | ||
}, | ||
); | ||
|
||
try { | ||
await service.getObject(isolateId, cObjectId1); | ||
fail('successfully retrieved object using expired ID'); | ||
} on SentinelException catch (e) { | ||
expect(e.sentinel.kind, startsWith('Expired')); | ||
expect(e.sentinel.valueAsString, equals('<expired>')); | ||
} | ||
|
||
// Ensure that the zone can be reused after it was invalidated. | ||
final cInstanceRef3 = (await service.callMethod( | ||
'evaluateInFrame', | ||
isolateId: isolateId, | ||
args: { | ||
'frameIndex': 0, | ||
'expression': 'c', | ||
'_idZoneId': idZone1['id'], | ||
}, | ||
)) | ||
.json!; | ||
expect(cInstanceRef3['type'], '@Instance'); | ||
expect(cInstanceRef3['id'], 'objects/0/1'); | ||
}, | ||
|
||
// Test the behaviour of an ID Zone with a `backingBufferKind` of `Ring`, an | ||
// `idAssignmentPolicy` of `AlwaysAllocate`, and a capacity of 1. | ||
(VmService service, IsolateRef isolateRef) async { | ||
final isolateId = isolateRef.id!; | ||
final idZone2 = (await service.callMethod( | ||
'_createIdZone', | ||
isolateId: isolateId, | ||
args: { | ||
'backingBufferKind': 'Ring', | ||
'idAssignmentPolicy': 'AlwaysAllocate', | ||
'capacity': 1, | ||
}, | ||
)) | ||
.json!; | ||
expect(idZone2['type'], '_IdZone'); | ||
expect(idZone2['id'], 'zones/2'); | ||
expect(idZone2['backingBufferKind'], 'Ring'); | ||
expect(idZone2['idAssignmentPolicy'], 'AlwaysAllocate'); | ||
|
||
final cInstanceRef1 = (await service.callMethod( | ||
'evaluateInFrame', | ||
isolateId: isolateId, | ||
args: { | ||
'frameIndex': 0, | ||
'expression': 'c', | ||
'_idZoneId': idZone2['id'], | ||
}, | ||
)) | ||
.json!; | ||
expect(cInstanceRef1['type'], '@Instance'); | ||
final cObjectId1 = cInstanceRef1['id']; | ||
expect(cObjectId1, 'objects/0/2'); | ||
|
||
final cInstance1 = await service.getObject(isolateId, cObjectId1); | ||
expect(cInstance1.type, 'Instance'); | ||
|
||
final cInstanceRef2 = (await service.callMethod( | ||
'evaluateInFrame', | ||
isolateId: isolateId, | ||
args: { | ||
'frameIndex': 0, | ||
'expression': 'c', | ||
'_idZoneId': idZone2['id'], | ||
}, | ||
)) | ||
.json!; | ||
expect(cInstanceRef2['type'], '@Instance'); | ||
final cObjectId2 = cInstanceRef2['id']; | ||
expect(cObjectId2, 'objects/1/2'); | ||
|
||
final cInstance2 = await service.getObject(isolateId, cObjectId2); | ||
expect(cInstance2.type, 'Instance'); | ||
|
||
// [idZone2] only has a capacity of 1, so [cObjectId1] should have been | ||
// evicted when [cObjectId2] was allocated. | ||
try { | ||
await service.getObject(isolateId, cObjectId1); | ||
fail('successfully retrieved object using expired ID'); | ||
} on SentinelException catch (e) { | ||
expect(e.sentinel.kind, startsWith('Expired')); | ||
expect(e.sentinel.valueAsString, equals('<expired>')); | ||
} | ||
}, | ||
|
||
// Test the behaviour of an ID Zone with a `backingBufferKind` of `Ring`, an | ||
// `idAssignmentPolicy` of `ReuseExisting`, and the default capacity. | ||
(VmService service, IsolateRef isolateRef) async { | ||
final isolateId = isolateRef.id!; | ||
final idZone3 = (await service.callMethod( | ||
'_createIdZone', | ||
isolateId: isolateId, | ||
args: { | ||
'backingBufferKind': 'Ring', | ||
'idAssignmentPolicy': 'ReuseExisting', | ||
}, | ||
)) | ||
.json!; | ||
expect(idZone3['type'], '_IdZone'); | ||
expect(idZone3['id'], 'zones/3'); | ||
expect(idZone3['backingBufferKind'], 'Ring'); | ||
expect(idZone3['idAssignmentPolicy'], 'ReuseExisting'); | ||
|
||
final cInstanceRef1 = (await service.callMethod( | ||
'evaluateInFrame', | ||
isolateId: isolateId, | ||
args: { | ||
'frameIndex': 0, | ||
'expression': 'c', | ||
'_idZoneId': idZone3['id'], | ||
}, | ||
)) | ||
.json!; | ||
expect(cInstanceRef1['type'], '@Instance'); | ||
final cObjectId1 = cInstanceRef1['id']; | ||
expect(cObjectId1, 'objects/0/3'); | ||
|
||
final cInstance1 = await service.getObject(isolateId, cObjectId1); | ||
expect(cInstance1.type, 'Instance'); | ||
|
||
final cInstanceRef2 = (await service.callMethod( | ||
'evaluateInFrame', | ||
isolateId: isolateId, | ||
args: { | ||
'frameIndex': 0, | ||
'expression': 'c', | ||
'_idZoneId': idZone3['id'], | ||
}, | ||
)) | ||
.json!; | ||
expect(cInstanceRef2['type'], '@Instance'); | ||
final cObjectId2 = cInstanceRef2['id']; | ||
expect(cObjectId2, 'objects/0/3'); | ||
|
||
final cInstance2 = await service.getObject(isolateId, cObjectId2); | ||
expect(cInstance2.type, 'Instance'); | ||
|
||
await service.callMethod( | ||
'_invalidateIdZone', | ||
isolateId: isolateId, | ||
args: { | ||
'_idZoneId': idZone3['id'], | ||
}, | ||
); | ||
|
||
try { | ||
await service.getObject(isolateId, cObjectId1); | ||
fail('successfully retrieved object using expired ID'); | ||
} on SentinelException catch (e) { | ||
expect(e.sentinel.kind, startsWith('Expired')); | ||
expect(e.sentinel.valueAsString, equals('<expired>')); | ||
} | ||
|
||
// Ensure that the zone can be reused after it was invalidated. | ||
final cInstanceRef3 = (await service.callMethod( | ||
'evaluateInFrame', | ||
isolateId: isolateId, | ||
args: { | ||
'frameIndex': 0, | ||
'expression': 'c', | ||
'_idZoneId': idZone3['id'], | ||
}, | ||
)) | ||
.json!; | ||
expect(cInstanceRef3['type'], '@Instance'); | ||
expect(cInstanceRef3['id'], 'objects/0/3'); | ||
}, | ||
|
||
// Test deleting an ID Zone. | ||
(VmService service, IsolateRef isolateRef) async { | ||
final isolateId = isolateRef.id!; | ||
final idZone4 = (await service.callMethod( | ||
'_createIdZone', | ||
isolateId: isolateId, | ||
args: { | ||
'backingBufferKind': 'Ring', | ||
'idAssignmentPolicy': 'AlwaysAllocate', | ||
}, | ||
)) | ||
.json!; | ||
expect(idZone4['type'], '_IdZone'); | ||
expect(idZone4['id'], 'zones/4'); | ||
expect(idZone4['backingBufferKind'], 'Ring'); | ||
expect(idZone4['idAssignmentPolicy'], 'AlwaysAllocate'); | ||
|
||
await service.callMethod( | ||
'_deleteIdZone', | ||
isolateId: isolateId, | ||
args: { | ||
'_idZoneId': idZone4['id'], | ||
}, | ||
); | ||
|
||
try { | ||
await service.callMethod( | ||
'evaluateInFrame', | ||
isolateId: isolateId, | ||
args: { | ||
'frameIndex': 0, | ||
'expression': 'c', | ||
'_idZoneId': idZone4['id'], | ||
}, | ||
); | ||
fail('successfully used an ID zone that should have been deleted'); | ||
} on RPCError catch (e) { | ||
expect(e.code, RPCErrorKind.kInvalidParams.code); | ||
} | ||
}, | ||
resumeIsolate, | ||
]; | ||
|
||
Future<void> main([args = const <String>[]]) => runIsolateTests( | ||
args, | ||
tests, | ||
'id_zones_test.dart', | ||
testeeConcurrent: testeeMain, | ||
); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.