08855df46a
Reviewed-by: vlivanov, erikj, mseledtsov, gthornbr
235 lines
9.1 KiB
Java
235 lines
9.1 KiB
Java
/*
|
|
* Copyright (c) 2006, 2018, Oracle and/or its affiliates. All rights reserved.
|
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
|
*
|
|
* This code is free software; you can redistribute it and/or modify it
|
|
* under the terms of the GNU General Public License version 2 only, as
|
|
* published by the Free Software Foundation.
|
|
*
|
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
* version 2 for more details (a copy is included in the LICENSE file that
|
|
* accompanied this code).
|
|
*
|
|
* You should have received a copy of the GNU General Public License version
|
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
*
|
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
|
* or visit www.oracle.com if you need additional information or have any
|
|
* questions.
|
|
*/
|
|
package nsk.share.jdi;
|
|
|
|
import java.io.*;
|
|
import java.util.*;
|
|
import com.sun.jdi.*;
|
|
|
|
import nsk.share.Consts;
|
|
|
|
/*
|
|
* Class is used as base debugger in tests for ThreadReference.ownedMonitorsAndFrames().
|
|
*
|
|
* In all this test similar scenario is used:
|
|
* - debugger VM force debugge VM to create test thread which acquires different monitors
|
|
* - when test thread acquire all monitors debuggee save information about all acquired monitors in special array 'monitorsInfo'
|
|
* - debugger read data from 'monitorsInfo' and compare it with data returned by ThreadReference.ownedMonitorsAndFrames()
|
|
*/
|
|
public class OwnedMonitorsDebugger extends TestDebuggerType2 {
|
|
|
|
/*
|
|
* debug data about monitor acquired by debuggee test thread,
|
|
* intended to compare with data returned by ThreadReference.ownedMonitorsAndFrames
|
|
*/
|
|
public static class DebugMonitorInfo {
|
|
// create DebugMonitorInfo using mirror of instance of nsk.share.locks.LockingThread.DebugMonitorInfo
|
|
DebugMonitorInfo(ObjectReference debuggeeMirror) {
|
|
monitor = (ObjectReference) debuggeeMirror.getValue(debuggeeMirror.referenceType().fieldByName("monitor"));
|
|
stackDepth = ((IntegerValue) debuggeeMirror.getValue(debuggeeMirror.referenceType().fieldByName("stackDepth"))).intValue();
|
|
thread = (ThreadReference) debuggeeMirror.getValue(debuggeeMirror.referenceType().fieldByName("thread"));
|
|
}
|
|
|
|
public DebugMonitorInfo(ObjectReference monitor, int stackDepth, ThreadReference thread) {
|
|
this.monitor = monitor;
|
|
this.stackDepth = stackDepth;
|
|
this.thread = thread;
|
|
}
|
|
|
|
public ObjectReference monitor;
|
|
|
|
public int stackDepth;
|
|
|
|
public ThreadReference thread;
|
|
}
|
|
|
|
public static void main(String argv[]) {
|
|
System.exit(run(argv, System.out) + Consts.JCK_STATUS_BASE);
|
|
}
|
|
|
|
public static int run(String argv[], PrintStream out) {
|
|
return new OwnedMonitorsDebugger().runIt(argv, out);
|
|
}
|
|
|
|
protected boolean canRunTest() {
|
|
if (!vm.canGetMonitorFrameInfo()) {
|
|
log.display("TEST CANCELED due to: vm.canGetMonitorFrameInfo() = false");
|
|
return false;
|
|
} else
|
|
return super.canRunTest();
|
|
}
|
|
|
|
protected String debuggeeClassName() {
|
|
return OwnedMonitorsDebuggee.class.getName();
|
|
}
|
|
|
|
// read debuggee's array 'monitorsInfo' containing information about acquired monitors
|
|
protected List<DebugMonitorInfo> getDebugMonitorsInfo() {
|
|
List<DebugMonitorInfo> result = new ArrayList<DebugMonitorInfo>();
|
|
|
|
ReferenceType referenceType = debuggee.classByName(debuggeeClassNameWithoutArgs());
|
|
ArrayReference monitorsInfo = (ArrayReference) referenceType.getValue(referenceType.fieldByName("monitorsInfo"));
|
|
|
|
for (int i = 0; i < monitorsInfo.length(); i++)
|
|
result.add(new DebugMonitorInfo((ObjectReference) monitorsInfo.getValue(i)));
|
|
|
|
return result;
|
|
}
|
|
|
|
private boolean compare(MonitorInfo actual, DebugMonitorInfo expected) {
|
|
boolean success = true;
|
|
|
|
if (actual.stackDepth() != expected.stackDepth) {
|
|
setSuccess(false);
|
|
success = false;
|
|
log.complain("Expected and actual monitor(" + actual.monitor() + ") stack depth differs, expected: " + expected.stackDepth + " actual: "
|
|
+ actual.stackDepth());
|
|
}
|
|
|
|
if (!actual.thread().equals(expected.thread)) {
|
|
setSuccess(false);
|
|
success = false;
|
|
log.complain("Expected and actual monitor(" + actual.monitor() + " thread differs, expected: " + expected.thread + " actual: "
|
|
+ actual.thread());
|
|
}
|
|
|
|
return success;
|
|
}
|
|
|
|
protected void compare(List<MonitorInfo> actualData, List<DebugMonitorInfo> expectedData) {
|
|
boolean success = true;
|
|
|
|
// compare total amount of monitors
|
|
if (actualData.size() != expectedData.size()) {
|
|
setSuccess(false);
|
|
success = false;
|
|
log.complain("Number of expected monitors and actual ones differs");
|
|
log.complain("Expected: " + expectedData.size() + ", actual: " + actualData.size());
|
|
}
|
|
|
|
// check that all expected monitors are contained in 'actualData'
|
|
for (DebugMonitorInfo expectedMonitorInfo : expectedData) {
|
|
boolean isMonitorFound = false;
|
|
|
|
for (MonitorInfo actualMonitorInfo : actualData) {
|
|
if (expectedMonitorInfo.monitor.equals(actualMonitorInfo.monitor())) {
|
|
isMonitorFound = true;
|
|
|
|
if (!compare(actualMonitorInfo, expectedMonitorInfo))
|
|
success = false;
|
|
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (!isMonitorFound) {
|
|
setSuccess(false);
|
|
success = false;
|
|
log.complain("Expected monitor not found in result of ownedMonitorsAndFrames(): " + expectedMonitorInfo.monitor);
|
|
}
|
|
}
|
|
|
|
// check that all monitors from 'actualData' are contained in
|
|
// 'expectedData'
|
|
for (MonitorInfo actualMonitorInfo : actualData) {
|
|
boolean isMonitorFound = false;
|
|
|
|
for (DebugMonitorInfo expectedMonitorInfo : expectedData) {
|
|
if (actualMonitorInfo.monitor().equals(expectedMonitorInfo.monitor)) {
|
|
isMonitorFound = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (!isMonitorFound) {
|
|
setSuccess(false);
|
|
success = false;
|
|
log.complain("Unexpected monitor in result of ownedMonitorsAndFrames(): " + actualMonitorInfo.monitor() + " Depth: "
|
|
+ actualMonitorInfo.stackDepth() + " Thread: " + actualMonitorInfo.thread());
|
|
}
|
|
}
|
|
|
|
if (!success)
|
|
logDebugInfo(actualData, expectedData);
|
|
}
|
|
|
|
private void logDebugInfo(List<MonitorInfo> actualData, List<DebugMonitorInfo> expectedData) {
|
|
log.display("ACTUAL MONITORS (total " + actualData.size() + "):");
|
|
|
|
ThreadReference thread = null;
|
|
|
|
for (MonitorInfo monitorInfo : actualData) {
|
|
log.display("Monitor: " + monitorInfo.monitor());
|
|
log.display("Depth: " + monitorInfo.stackDepth());
|
|
log.display("Thread: " + monitorInfo.thread());
|
|
if (thread == null)
|
|
thread = monitorInfo.thread();
|
|
}
|
|
|
|
log.display("EXPECTED MONITORS (total " + expectedData.size() + "):");
|
|
|
|
for (DebugMonitorInfo monitorInfo : expectedData) {
|
|
log.display("Monitor: " + monitorInfo.monitor);
|
|
log.display("Depth: " + monitorInfo.stackDepth);
|
|
log.display("Thread: " + monitorInfo.thread);
|
|
if (thread == null)
|
|
thread = monitorInfo.thread;
|
|
}
|
|
|
|
if (thread != null) {
|
|
try {
|
|
log.display("Thread frames:");
|
|
for (StackFrame frame : thread.frames()) {
|
|
Location location = frame.location();
|
|
log.display(location.declaringType().name() + "." + location.method().name() + ", line: " + location.lineNumber());
|
|
}
|
|
} catch (Exception e) {
|
|
unexpectedException(e);
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Check that ThreadReference.ownedMonitorsAndFrames() returns correct
|
|
* data before calling this method debuggee should save information about
|
|
* acquired monitors in special array 'monitorsInfo',
|
|
* debugger forces debuggee to do it using command 'COMMAND_UPDATE_MONITOR_INFO'
|
|
*/
|
|
protected void checkMonitorInfo(ThreadReference threadReference) {
|
|
List<MonitorInfo> actualData = null;
|
|
|
|
try {
|
|
actualData = threadReference.ownedMonitorsAndFrames();
|
|
} catch (Exception e) {
|
|
setSuccess(false);
|
|
log.complain("Unexpected exception: " + e);
|
|
e.printStackTrace(log.getOutStream());
|
|
}
|
|
|
|
List<DebugMonitorInfo> expectedData = getDebugMonitorsInfo();
|
|
|
|
compare(actualData, expectedData);
|
|
}
|
|
|
|
}
|