first step to bring debugging code to j2me
This commit is contained in:
@@ -6,7 +6,5 @@
|
||||
<classpathentry kind="src" path="src/test/res"/>
|
||||
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
|
||||
<classpathentry kind="con" path="org.eclipse.jdt.junit.JUNIT_CONTAINER/3.8.1"/>
|
||||
<classpathentry kind="lib" path="src/test/res/standard-tests.zip"/>
|
||||
<classpathentry kind="lib" path="lib/commons-cli-1.1.jar"/>
|
||||
<classpathentry kind="output" path="bin"/>
|
||||
</classpath>
|
||||
|
||||
@@ -7,8 +7,7 @@
|
||||
|
||||
<target name="compile">
|
||||
<mkdir dir="build/classes"/>
|
||||
<javac destdir="build/classes" encoding="utf-8" source="1.3" target="1.1"
|
||||
classpath="lib/commons-cli-1.1.jar" >
|
||||
<javac destdir="build/classes" encoding="utf-8" source="1.3" target="1.1">
|
||||
<src path="src/main/java"/>
|
||||
<src path="src/addon/java"/>
|
||||
</javac>
|
||||
@@ -46,7 +45,7 @@
|
||||
|
||||
<!-- Compile everything, but don't preverify (yet). -->
|
||||
<mkdir dir="build/classes-j2me" />
|
||||
<wtkbuild destdir="build/classes-j2me" preverify="false" srcdir="build/src-j2me" />
|
||||
<wtkbuild destdir="build/classes-j2me" preverify="false" srcdir="build/src-j2me" source="1.3" />
|
||||
|
||||
<!-- create the jar -->
|
||||
<jar destfile="luaj-vm-j2me-${version}.jar" basedir="build/classes-j2me" />
|
||||
|
||||
Binary file not shown.
@@ -21,11 +21,12 @@
|
||||
******************************************************************************/
|
||||
package lua.debug;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
public class DebugEvent implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = -6167781055176807311L;
|
||||
protected DebugEventType type;
|
||||
|
||||
public DebugEvent(DebugEventType type) {
|
||||
@@ -45,5 +46,15 @@ public class DebugEvent implements Serializable {
|
||||
*/
|
||||
public String toString() {
|
||||
return type.toString();
|
||||
}
|
||||
}
|
||||
|
||||
public static void serialize(DataOutputStream out, DebugEvent object)
|
||||
throws IOException {
|
||||
SerializationHelper.serialize(object.getType(), out);
|
||||
}
|
||||
|
||||
public static DebugEvent deserialize(DataInputStream in) throws IOException {
|
||||
DebugEventType type = (DebugEventType) SerializationHelper.deserialize(in);
|
||||
return new DebugEvent(type);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,13 +21,24 @@
|
||||
******************************************************************************/
|
||||
package lua.debug;
|
||||
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
public class DebugEventBreakpoint extends DebugEvent {
|
||||
private static final long serialVersionUID = -7573362646669094458L;
|
||||
protected String source;
|
||||
protected int lineNumber;
|
||||
|
||||
public DebugEventBreakpoint(String source, int lineNumber) {
|
||||
super(DebugEventType.suspendedOnBreakpoint);
|
||||
if (source == null) {
|
||||
throw new IllegalArgumentException("argument source cannot be null");
|
||||
}
|
||||
|
||||
if (lineNumber <= 0) {
|
||||
throw new IllegalArgumentException("argument lineNumber must be positive integer");
|
||||
}
|
||||
|
||||
this.source = source;
|
||||
this.lineNumber = lineNumber;
|
||||
}
|
||||
@@ -46,4 +57,17 @@ public class DebugEventBreakpoint extends DebugEvent {
|
||||
public String toString() {
|
||||
return super.toString() + " source:" + getSource() + " line:" + getLineNumber();
|
||||
}
|
||||
|
||||
public static void serialize(DataOutputStream out, DebugEventBreakpoint object)
|
||||
throws IOException {
|
||||
out.writeUTF(object.getSource());
|
||||
out.writeInt(object.getLineNumber());
|
||||
}
|
||||
|
||||
public static DebugEvent deserialize(DataInputStream in) throws IOException {
|
||||
String source = in.readUTF();
|
||||
int lineNo = in.readInt();
|
||||
|
||||
return new DebugEventBreakpoint(source, lineNo);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,8 +21,11 @@
|
||||
******************************************************************************/
|
||||
package lua.debug;
|
||||
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
public class DebugEventError extends DebugEvent {
|
||||
private static final long serialVersionUID = -7911842790951966147L;
|
||||
protected String detail;
|
||||
|
||||
public DebugEventError(String detail) {
|
||||
@@ -40,4 +43,15 @@ public class DebugEventError extends DebugEvent {
|
||||
public String toString() {
|
||||
return super.toString() + " detail: " + getDetail();
|
||||
}
|
||||
|
||||
public static void serialize(DataOutputStream out, DebugEventError object)
|
||||
throws IOException {
|
||||
//TODO implement
|
||||
}
|
||||
|
||||
public static DebugEvent deserialize(DataInputStream in)
|
||||
throws IOException {
|
||||
//TODO implement
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,8 +21,12 @@
|
||||
******************************************************************************/
|
||||
package lua.debug;
|
||||
|
||||
import java.io.DataInputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
|
||||
public class DebugEventType extends EnumType {
|
||||
public static DebugEventType started = new DebugEventType("started", 0);
|
||||
public static DebugEventType started = new DebugEventType("started", 0);
|
||||
public static DebugEventType suspendedByClient = new DebugEventType("suspendedByClient", 1);
|
||||
public static DebugEventType suspendedOnBreakpoint = new DebugEventType("suspendedOnBreakpoint", 2);
|
||||
public static DebugEventType suspendedOnWatchpoint = new DebugEventType("suspendedOnWatchpoint", 3);
|
||||
@@ -34,7 +38,30 @@ public class DebugEventType extends EnumType {
|
||||
public static DebugEventType error = new DebugEventType("error", 9);
|
||||
public static DebugEventType terminated = new DebugEventType("terminated", 10);
|
||||
|
||||
protected static DebugEventType[] ENUMS = new DebugEventType[] {
|
||||
started,
|
||||
suspendedByClient,
|
||||
suspendedOnBreakpoint,
|
||||
suspendedOnWatchpoint,
|
||||
suspendedOnStepping,
|
||||
suspendedOnError,
|
||||
resumedByClient,
|
||||
resumedOnStepping,
|
||||
resumedOnError,
|
||||
error,
|
||||
terminated
|
||||
};
|
||||
|
||||
protected DebugEventType(String name, int ordinal) {
|
||||
super(name, ordinal);
|
||||
}
|
||||
|
||||
public static DebugEventType deserialize(DataInputStream in)
|
||||
throws IOException {
|
||||
int ordinal = in.readInt();
|
||||
if (ordinal < 0 || ordinal >= ENUMS.length) {
|
||||
throw new RuntimeException("ordinal is out of the range.");
|
||||
}
|
||||
return ENUMS[ordinal];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,10 +21,11 @@
|
||||
******************************************************************************/
|
||||
package lua.debug;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
public class DebugRequest implements Serializable {
|
||||
private static final long serialVersionUID = 2741129244733000595L;
|
||||
protected DebugRequestType type;
|
||||
|
||||
public DebugRequest(DebugRequestType type) {
|
||||
@@ -41,4 +42,15 @@ public class DebugRequest implements Serializable {
|
||||
public String toString() {
|
||||
return type.toString();
|
||||
}
|
||||
|
||||
public static void serialize(DataOutputStream out, DebugRequest request)
|
||||
throws IOException {
|
||||
DebugRequestType type = request.getType();
|
||||
SerializationHelper.serialize(type, out);
|
||||
}
|
||||
|
||||
public static DebugRequest deserialize(DataInputStream in) throws IOException {
|
||||
DebugRequestType type = (DebugRequestType) SerializationHelper.deserialize(in);
|
||||
return new DebugRequest(type);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,8 +21,11 @@
|
||||
******************************************************************************/
|
||||
package lua.debug;
|
||||
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
public class DebugRequestLineBreakpointToggle extends DebugRequest {
|
||||
private static final long serialVersionUID = -3954500569399285372L;
|
||||
protected String source;
|
||||
protected int lineNumber;
|
||||
|
||||
@@ -49,4 +52,19 @@ public class DebugRequestLineBreakpointToggle extends DebugRequest {
|
||||
public String toString() {
|
||||
return super.toString() + " Source:" + getSource() + " lineNumber:" + getLineNumber();
|
||||
}
|
||||
|
||||
public static void serialize(DataOutputStream out, DebugRequestLineBreakpointToggle request)
|
||||
throws IOException {
|
||||
SerializationHelper.serialize(request.getType(), out);
|
||||
out.writeUTF(request.getSource());
|
||||
out.writeInt(request.getLineNumber());
|
||||
}
|
||||
|
||||
public static DebugRequest deserialize(DataInputStream in) throws IOException {
|
||||
DebugRequestType type = (DebugRequestType)SerializationHelper.deserialize(in);
|
||||
String source = in.readUTF();
|
||||
int lineNo = in.readInt();
|
||||
|
||||
return new DebugRequestLineBreakpointToggle(type, source, lineNo);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,8 +21,11 @@
|
||||
******************************************************************************/
|
||||
package lua.debug;
|
||||
|
||||
public class DebugRequestStack extends DebugRequest {
|
||||
private static final long serialVersionUID = 6270383432060791307L;
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
public class DebugRequestStack extends DebugRequest implements Serializable {
|
||||
protected int index;
|
||||
|
||||
public DebugRequestStack(int index) {
|
||||
@@ -40,4 +43,15 @@ public class DebugRequestStack extends DebugRequest {
|
||||
public String toString() {
|
||||
return super.toString() + " stack frame:" + getIndex();
|
||||
}
|
||||
|
||||
public static void serialize(DataOutputStream out, DebugRequestStack request)
|
||||
throws IOException {
|
||||
out.writeInt(request.getIndex());
|
||||
}
|
||||
|
||||
public static DebugRequest deserialize(DataInputStream in) throws IOException {
|
||||
int index = in.readInt();
|
||||
|
||||
return new DebugRequestStack(index);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,9 +21,11 @@
|
||||
******************************************************************************/
|
||||
package lua.debug;
|
||||
|
||||
import java.io.DataInputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
|
||||
public class DebugRequestType extends EnumType {
|
||||
private static final long serialVersionUID = 2829883820534540402L;
|
||||
|
||||
public static final DebugRequestType suspend = new DebugRequestType("suspend", 0);
|
||||
public static final DebugRequestType resume = new DebugRequestType("resume", 1);
|
||||
public static final DebugRequestType exit = new DebugRequestType("exit", 2);
|
||||
@@ -34,8 +36,29 @@ public class DebugRequestType extends EnumType {
|
||||
public static final DebugRequestType callgraph = new DebugRequestType("callgraph", 7);
|
||||
public static final DebugRequestType stack = new DebugRequestType("stack", 8);
|
||||
public static final DebugRequestType step = new DebugRequestType("step", 9);
|
||||
|
||||
protected static final DebugRequestType[] ENUMS = new DebugRequestType[] {
|
||||
suspend,
|
||||
resume,
|
||||
exit,
|
||||
lineBreakpointSet,
|
||||
lineBreakpointClear,
|
||||
watchpointSet,
|
||||
watchpointClear,
|
||||
callgraph,
|
||||
stack,
|
||||
step
|
||||
};
|
||||
|
||||
public DebugRequestType(String name, int ordinal) {
|
||||
super(name, ordinal);
|
||||
}
|
||||
|
||||
public static DebugRequestType deserialize(DataInputStream in) throws IOException {
|
||||
int ordinal = in.readInt();
|
||||
if (ordinal < 0 || ordinal >= ENUMS.length) {
|
||||
throw new RuntimeException("ordinal is out of the range.");
|
||||
}
|
||||
return ENUMS[ordinal];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,8 +22,6 @@
|
||||
package lua.debug;
|
||||
|
||||
public class DebugRequestWatchpointToggle extends DebugRequest {
|
||||
private static final long serialVersionUID = -2978341358052851046L;
|
||||
|
||||
public static class AccessType extends EnumType {
|
||||
private static final long serialVersionUID = 3523086189648091587L;
|
||||
|
||||
@@ -64,4 +62,6 @@ public class DebugRequestWatchpointToggle extends DebugRequest {
|
||||
public String toString() {
|
||||
return super.toString() + " functionName:" + getFunctionName() + " variableName:" + getVariableName();
|
||||
}
|
||||
|
||||
// TODO: add the serialization stuff
|
||||
}
|
||||
|
||||
@@ -21,4 +21,4 @@
|
||||
******************************************************************************/
|
||||
package lua.debug;
|
||||
|
||||
public interface DebugResponse {}
|
||||
public interface DebugResponse extends Serializable {}
|
||||
|
||||
@@ -21,13 +21,19 @@
|
||||
******************************************************************************/
|
||||
package lua.debug;
|
||||
|
||||
public class DebugResponseCallgraph extends DebugResponseSimple {
|
||||
private static final long serialVersionUID = -7761865402188853413L;
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
public class DebugResponseCallgraph implements DebugResponse {
|
||||
protected StackFrame[] stackFrames;
|
||||
|
||||
public DebugResponseCallgraph(StackFrame[] callgraph) {
|
||||
super(true);
|
||||
this.stackFrames = callgraph;
|
||||
if (callgraph == null) {
|
||||
this.stackFrames = new StackFrame[0];
|
||||
} else {
|
||||
this.stackFrames = callgraph;
|
||||
}
|
||||
}
|
||||
|
||||
public StackFrame[] getCallgraph() {
|
||||
@@ -36,11 +42,30 @@ public class DebugResponseCallgraph extends DebugResponseSimple {
|
||||
|
||||
public String toString() {
|
||||
StringBuilder buffer = new StringBuilder();
|
||||
for (int i = 0; stackFrames != null && i < stackFrames.length; i++) {
|
||||
for (int i = 0; i < stackFrames.length; i++) {
|
||||
StackFrame frame = stackFrames[i];
|
||||
buffer.append(frame.toString());
|
||||
buffer.append("\n");
|
||||
}
|
||||
return buffer.toString();
|
||||
}
|
||||
|
||||
public static void serialize(DataOutputStream out, DebugResponseCallgraph response)
|
||||
throws IOException {
|
||||
StackFrame[] stackFrames = response.getCallgraph();
|
||||
out.writeInt(stackFrames == null ? 0 : stackFrames.length);
|
||||
for (int i = 0; stackFrames != null && i < stackFrames.length; i++) {
|
||||
StackFrame.serialize(out, stackFrames[i]);
|
||||
}
|
||||
}
|
||||
|
||||
public static DebugResponseCallgraph deserialize(DataInputStream in) throws IOException {
|
||||
int count = in.readInt();
|
||||
StackFrame[] stackFrames = new StackFrame[count];
|
||||
for (int i = 0; i < count; i++) {
|
||||
stackFrames[i] = StackFrame.deserialize(in);
|
||||
}
|
||||
|
||||
return new DebugResponseCallgraph(stackFrames);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,11 +21,11 @@
|
||||
******************************************************************************/
|
||||
package lua.debug;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
public class DebugResponseSimple implements DebugResponse, Serializable {
|
||||
private static final long serialVersionUID = 7042417813840650230L;
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
public class DebugResponseSimple implements DebugResponse {
|
||||
protected boolean isSuccessful;
|
||||
|
||||
public static final DebugResponseSimple SUCCESS = new DebugResponseSimple(true);
|
||||
@@ -45,4 +45,15 @@ public class DebugResponseSimple implements DebugResponse, Serializable {
|
||||
public String toString() {
|
||||
return String.valueOf(isSuccessful);
|
||||
}
|
||||
|
||||
public static void serialize(DataOutputStream out, DebugResponseSimple response)
|
||||
throws IOException {
|
||||
out.writeBoolean(response.isSuccessful());
|
||||
}
|
||||
|
||||
public static DebugResponseSimple deserialize(DataInputStream in)
|
||||
throws IOException {
|
||||
boolean value = in.readBoolean();
|
||||
return value ? SUCCESS : FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,13 +21,19 @@
|
||||
******************************************************************************/
|
||||
package lua.debug;
|
||||
|
||||
public class DebugResponseStack extends DebugResponseSimple {
|
||||
private static final long serialVersionUID = -2108425321162834731L;
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
public class DebugResponseStack implements DebugResponse {
|
||||
protected Variable[] variables;
|
||||
|
||||
public DebugResponseStack(Variable[] variables) {
|
||||
super(true);
|
||||
this.variables = variables;
|
||||
if (variables == null) {
|
||||
this.variables = new Variable[0];
|
||||
} else {
|
||||
this.variables = variables;
|
||||
}
|
||||
}
|
||||
|
||||
public Variable[] getVariables() {
|
||||
@@ -44,4 +50,22 @@ public class DebugResponseStack extends DebugResponseSimple {
|
||||
}
|
||||
return buffer.toString();
|
||||
}
|
||||
|
||||
public static void serialize(DataOutputStream out, DebugResponseStack response)
|
||||
throws IOException {
|
||||
Variable[] variables = response.getVariables();
|
||||
out.writeInt(variables == null ? 0 : variables.length);
|
||||
for (int i = 0; i < variables.length; i++) {
|
||||
SerializationHelper.serialize(variables[i], out);
|
||||
}
|
||||
}
|
||||
|
||||
public static DebugResponseStack deserialize(DataInputStream in) throws IOException {
|
||||
int count = in.readInt();
|
||||
Variable[] variables = new Variable[count];
|
||||
for (int i = 0; i < count; i++) {
|
||||
variables[i] = (Variable) SerializationHelper.deserialize(in);
|
||||
}
|
||||
return new DebugResponseStack(variables);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,12 +21,8 @@
|
||||
******************************************************************************/
|
||||
package lua.debug;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.Hashtable;
|
||||
import java.util.Vector;
|
||||
|
||||
import lua.CallInfo;
|
||||
import lua.Lua;
|
||||
@@ -41,12 +37,12 @@ public class DebugStackState extends StackState implements DebugRequestListener
|
||||
|
||||
private static final boolean DEBUG = false;
|
||||
|
||||
protected Map breakpoints = new HashMap();
|
||||
protected Hashtable breakpoints = new Hashtable();
|
||||
protected boolean exiting = false;
|
||||
protected boolean suspended = false;
|
||||
protected boolean stepping = false;
|
||||
protected int lastline = -1;
|
||||
protected List debugEventListeners = new ArrayList();
|
||||
protected Vector debugEventListeners = new Vector();
|
||||
|
||||
public DebugStackState() {
|
||||
}
|
||||
@@ -130,25 +126,26 @@ public class DebugStackState extends StackState implements DebugRequestListener
|
||||
|
||||
// anytime the line doesn't change we keep going
|
||||
int line = getLineNumber(calls[cc]);
|
||||
if(DebugUtils.IS_DEBUG)
|
||||
DebugUtils.println("debugHook - executing line: " + line);
|
||||
if ( !stepping && lastline == line ) {
|
||||
return;
|
||||
}
|
||||
if(DebugUtils.IS_DEBUG)
|
||||
DebugUtils.println("debugHook - executing line: " + line);
|
||||
|
||||
// save line in case next op is a step
|
||||
lastline = line;
|
||||
|
||||
if ( stepping ) {
|
||||
DebugUtils.println("suspended by stepping at pc=" + pc);
|
||||
notifyDebugEventListeners(new DebugEventStepping());
|
||||
//TODO: notifyDebugEventListeners(new DebugEventStepping());
|
||||
suspended = true;
|
||||
} else if ( !suspended ) {
|
||||
// check for a break point if we aren't suspended already
|
||||
Proto p = calls[cc].closure.p;
|
||||
String source = DebugUtils.getSourceFileName(p.source);
|
||||
if ( breakpoints.containsKey(constructBreakpointKey(source, line))){
|
||||
DebugUtils.println("hitting breakpoint " + constructBreakpointKey(source, line));
|
||||
if(DebugUtils.IS_DEBUG)
|
||||
DebugUtils.println("hitting breakpoint " + constructBreakpointKey(source, line));
|
||||
notifyDebugEventListeners(
|
||||
new DebugEventBreakpoint(source, line));
|
||||
suspended = true;
|
||||
@@ -161,7 +158,8 @@ public class DebugStackState extends StackState implements DebugRequestListener
|
||||
while (suspended && !exiting ) {
|
||||
try {
|
||||
this.wait();
|
||||
DebugUtils.println("resuming execution...");
|
||||
if(DebugUtils.IS_DEBUG)
|
||||
DebugUtils.println("resuming execution...");
|
||||
} catch ( InterruptedException ie ) {
|
||||
ie.printStackTrace();
|
||||
}
|
||||
@@ -271,7 +269,8 @@ public class DebugStackState extends StackState implements DebugRequestListener
|
||||
* clear breakpoint at line lineNumber of source source
|
||||
*/
|
||||
public void clearBreakpoint(String source, int lineNumber) {
|
||||
DebugUtils.println("removing breakpoint " + constructBreakpointKey(source, lineNumber));
|
||||
if(DebugUtils.IS_DEBUG)
|
||||
DebugUtils.println("removing breakpoint " + constructBreakpointKey(source, lineNumber));
|
||||
synchronized ( this ) {
|
||||
breakpoints.remove(constructBreakpointKey(source, lineNumber));
|
||||
}
|
||||
@@ -302,24 +301,27 @@ public class DebugStackState extends StackState implements DebugRequestListener
|
||||
}
|
||||
|
||||
CallInfo callInfo = calls[index];
|
||||
DebugUtils.println("Stack Frame: " + index + "[" + callInfo.base + "," + callInfo.top + "]");
|
||||
if(DebugUtils.IS_DEBUG)
|
||||
DebugUtils.println("Stack Frame: " + index + "[" + callInfo.base + "," + callInfo.top + "]");
|
||||
int top = callInfo.top < callInfo.base ? callInfo.base : callInfo.top;
|
||||
Proto prototype = callInfo.closure.p;
|
||||
LocVars[] localVariables = prototype.locvars;
|
||||
List variables = new ArrayList();
|
||||
Vector variables = new Vector();
|
||||
int localVariableCount = 0;
|
||||
Set variablesSeen = new HashSet();
|
||||
Hashtable variablesSeen = new Hashtable();
|
||||
for (int i = 0; localVariables != null && i < localVariables.length && i <= top; i++) {
|
||||
String varName = localVariables[i].varname.toString();
|
||||
DebugUtils.print("\tVariable: " + varName);
|
||||
DebugUtils.print("\tValue: " + stack[callInfo.base + i]);
|
||||
if(DebugUtils.IS_DEBUG) {
|
||||
DebugUtils.print("\tVariable: " + varName);
|
||||
DebugUtils.print("\tValue: " + stack[callInfo.base + i]);
|
||||
}
|
||||
if (!variablesSeen.contains(varName) &&
|
||||
!LexState.isReservedKeyword(varName)) {
|
||||
variablesSeen.add(varName);
|
||||
variablesSeen.put(varName, varName);
|
||||
LValue value = stack[callInfo.base + i];
|
||||
if (value != null) {
|
||||
int type = value.luaGetType();
|
||||
DebugUtils.print("\tType: " + type);
|
||||
DebugUtils.print("\tType: " + Lua.TYPE_NAMES[type]);
|
||||
if (type == Lua.LUA_TTABLE) {
|
||||
DebugUtils.println(" (selected)");
|
||||
variables.add(
|
||||
|
||||
@@ -21,24 +21,36 @@
|
||||
******************************************************************************/
|
||||
package lua.debug;
|
||||
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.EOFException;
|
||||
import java.io.IOException;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.ObjectOutputStream;
|
||||
import java.net.ServerSocket;
|
||||
import java.net.Socket;
|
||||
|
||||
public class DebugSupport implements DebugEventListener {
|
||||
public static class State extends EnumType {
|
||||
private static final long serialVersionUID = 3657364516937093612L;
|
||||
|
||||
public static final State UNKNOWN = new State("UNKNOWN", 0);
|
||||
public static final State RUNNING = new State("RUNNING", 1);
|
||||
public static final State STOPPED = new State("STOPPED", 2);
|
||||
|
||||
protected static final State[] ENUMS = new State[] {
|
||||
UNKNOWN,
|
||||
RUNNING,
|
||||
STOPPED
|
||||
};
|
||||
|
||||
public State(String name, int ordinal) {
|
||||
super(name, ordinal);
|
||||
}
|
||||
|
||||
public static State deserialize(DataInputStream in) throws IOException {
|
||||
int ordinal = in.readInt();
|
||||
if (ordinal < 0 || ordinal >= ENUMS.length) {
|
||||
throw new RuntimeException("ordinal is out of the range.");
|
||||
}
|
||||
return ENUMS[ordinal];
|
||||
}
|
||||
}
|
||||
|
||||
protected DebugRequestListener listener;
|
||||
@@ -49,12 +61,12 @@ public class DebugSupport implements DebugEventListener {
|
||||
|
||||
protected ServerSocket requestSocket;
|
||||
protected Socket clientRequestSocket;
|
||||
protected ObjectInputStream requestReader;
|
||||
protected ObjectOutputStream requestWriter;
|
||||
protected DataInputStream requestReader;
|
||||
protected DataOutputStream requestWriter;
|
||||
|
||||
protected ServerSocket eventSocket;
|
||||
protected Socket clientEventSocket;
|
||||
protected ObjectOutputStream eventWriter;
|
||||
protected DataOutputStream eventWriter;
|
||||
|
||||
public DebugSupport(DebugRequestListener listener,
|
||||
int requestPort,
|
||||
@@ -117,14 +129,14 @@ public class DebugSupport implements DebugEventListener {
|
||||
this.requestSocket = new ServerSocket(requestPort);
|
||||
this.clientRequestSocket = requestSocket.accept();
|
||||
this.requestReader
|
||||
= new ObjectInputStream(clientRequestSocket.getInputStream());
|
||||
= new DataInputStream(clientRequestSocket.getInputStream());
|
||||
this.requestWriter
|
||||
= new ObjectOutputStream(clientRequestSocket.getOutputStream());
|
||||
= new DataOutputStream(clientRequestSocket.getOutputStream());
|
||||
|
||||
this.eventSocket = new ServerSocket(eventPort);
|
||||
this.clientEventSocket = eventSocket.accept();
|
||||
this.eventWriter
|
||||
= new ObjectOutputStream(clientEventSocket.getOutputStream());
|
||||
= new DataOutputStream(clientEventSocket.getOutputStream());
|
||||
|
||||
this.requestWatcherThread = new Thread(new Runnable() {
|
||||
public void run() {
|
||||
@@ -151,11 +163,17 @@ public class DebugSupport implements DebugEventListener {
|
||||
synchronized (clientRequestSocket) {
|
||||
try {
|
||||
while (getState() != State.STOPPED) {
|
||||
int size = requestReader.readInt();
|
||||
byte[] data = new byte[size];
|
||||
requestReader.readFully(data);
|
||||
DebugRequest request
|
||||
= (DebugRequest) requestReader.readObject();
|
||||
= (DebugRequest) SerializationHelper.deserialize(data);
|
||||
DebugUtils.println("SERVER receives request: " + request.toString());
|
||||
|
||||
DebugResponse response = listener.handleRequest(request);
|
||||
requestWriter.writeObject(response);
|
||||
data = SerializationHelper.serialize(response);
|
||||
requestWriter.writeInt(data.length);
|
||||
requestWriter.write(data);
|
||||
requestWriter.flush();
|
||||
DebugUtils.println("SERVER sends response: " + response);
|
||||
}
|
||||
@@ -167,8 +185,6 @@ public class DebugSupport implements DebugEventListener {
|
||||
cleanup();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
} catch (ClassNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -203,7 +219,9 @@ public class DebugSupport implements DebugEventListener {
|
||||
DebugUtils.println("SERVER sending event: " + event.toString());
|
||||
synchronized (eventSocket) {
|
||||
try {
|
||||
eventWriter.writeObject(event);
|
||||
byte[] data = SerializationHelper.serialize(event);
|
||||
eventWriter.writeInt(data.length);
|
||||
eventWriter.write(data);
|
||||
eventWriter.flush();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
|
||||
@@ -27,7 +27,7 @@ import lua.io.LoadState;
|
||||
import lua.value.LString;
|
||||
|
||||
public class DebugUtils {
|
||||
public static final boolean IS_DEBUG = false;
|
||||
public static final boolean IS_DEBUG = true;
|
||||
|
||||
public static void println(String message) {
|
||||
if (IS_DEBUG) {
|
||||
|
||||
@@ -21,24 +21,17 @@
|
||||
******************************************************************************/
|
||||
package lua.debug;
|
||||
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.ObjectOutputStream;
|
||||
import java.io.Serializable;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class EnumType implements Serializable {
|
||||
private static final long serialVersionUID = -496099911938395074L;
|
||||
|
||||
|
||||
public abstract class EnumType implements Serializable {
|
||||
protected String name;
|
||||
protected int ordinal;
|
||||
protected static Map lookup = new HashMap();
|
||||
|
||||
public EnumType(String name, int ordinal) {
|
||||
this.name = name;
|
||||
this.ordinal = ordinal;
|
||||
lookup.put(name, this);
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
@@ -60,4 +53,8 @@ public class EnumType implements Serializable {
|
||||
public final int ordinal() {
|
||||
return this.ordinal;
|
||||
}
|
||||
|
||||
public static void serialize(DataOutputStream out, EnumType enumType) throws IOException {
|
||||
out.writeInt(enumType.ordinal());
|
||||
}
|
||||
}
|
||||
|
||||
53
src/main/java/lua/debug/NullableString.java
Normal file
53
src/main/java/lua/debug/NullableString.java
Normal file
@@ -0,0 +1,53 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2007 LuaJ. All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
******************************************************************************/
|
||||
package lua.debug;
|
||||
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
public class NullableString implements Serializable {
|
||||
protected String string;
|
||||
|
||||
public NullableString(String someString) {
|
||||
this.string = someString;
|
||||
}
|
||||
|
||||
public String getNullableString() {
|
||||
return (this.string == null) ? "[NULL]" : this.string;
|
||||
}
|
||||
|
||||
public String getRawString() {
|
||||
return (this.string.equals("[NULL]")) ? null : this.string;
|
||||
}
|
||||
|
||||
public static void serialize(DataOutputStream out, NullableString string)
|
||||
throws IOException {
|
||||
out.writeUTF(string.getNullableString());
|
||||
}
|
||||
|
||||
public static NullableString deserialize(DataInputStream in)
|
||||
throws IOException {
|
||||
String string = in.readUTF();
|
||||
return new NullableString(string);
|
||||
}
|
||||
}
|
||||
@@ -21,10 +21,6 @@
|
||||
******************************************************************************/
|
||||
package lua.debug;
|
||||
|
||||
public class DebugEventStepping extends DebugEvent {
|
||||
private static final long serialVersionUID = 3902898567880012107L;
|
||||
|
||||
public DebugEventStepping() {
|
||||
super(DebugEventType.suspendedOnStepping);
|
||||
}
|
||||
}
|
||||
|
||||
public interface Serializable { }
|
||||
163
src/main/java/lua/debug/SerializationHelper.java
Normal file
163
src/main/java/lua/debug/SerializationHelper.java
Normal file
@@ -0,0 +1,163 @@
|
||||
package lua.debug;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
public class SerializationHelper {
|
||||
|
||||
public static byte[] serialize(Serializable object) throws IOException {
|
||||
ByteArrayOutputStream bout = new ByteArrayOutputStream();
|
||||
DataOutputStream dout = new DataOutputStream(bout);
|
||||
|
||||
serialize(object, dout);
|
||||
|
||||
byte[] data = bout.toByteArray();
|
||||
|
||||
bout.close();
|
||||
dout.close();
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
public static Serializable deserialize(byte[] data) throws IOException {
|
||||
ByteArrayInputStream bin = new ByteArrayInputStream(data);
|
||||
DataInputStream din = new DataInputStream(bin);
|
||||
|
||||
Serializable object = deserialize(din);
|
||||
|
||||
bin.close();
|
||||
din.close();
|
||||
|
||||
return object;
|
||||
}
|
||||
|
||||
|
||||
static final int SERIAL_TYPE_NullableString = 0;
|
||||
static final int SERIAL_TYPE_TableVariable = 1;
|
||||
static final int SERIAL_TYPE_Variable = 2;
|
||||
static final int SERIAL_TYPE_DebugResponseCallgraph = 3;
|
||||
static final int SERIAL_TYPE_DebugResponseStack = 4;
|
||||
static final int SERIAL_TYPE_DebugResponseSimple = 5;
|
||||
static final int SERIAL_TYPE_DebugSupportState = 6;
|
||||
static final int SERIAL_TYPE_StackFrame = 7;
|
||||
static final int SERIAL_TYPE_DebugRequestType = 8;
|
||||
static final int SERIAL_TYPE_DebugRequest = 9;
|
||||
static final int SERIAL_TYPE_DebugRequestStack = 10;
|
||||
static final int SERIAL_TYPE_DebugRequestLineBreakpointToggle = 11;
|
||||
static final int SERIAL_TYPE_DebugEventType = 12;
|
||||
static final int SERIAL_TYPE_DebugEvent = 13;
|
||||
static final int SERIAL_TYPE_DebugEventBreakpoint = 14;
|
||||
|
||||
public static void serialize(Serializable object, DataOutputStream dout)
|
||||
throws IOException {
|
||||
if (object instanceof NullableString) {
|
||||
dout.writeInt(SERIAL_TYPE_NullableString);
|
||||
NullableString.serialize(dout, (NullableString)object);
|
||||
} else if (object instanceof TableVariable) {
|
||||
dout.writeInt(SERIAL_TYPE_TableVariable);
|
||||
TableVariable.serialize(dout, (TableVariable)object);
|
||||
} else if (object instanceof Variable) {
|
||||
dout.writeInt(SERIAL_TYPE_Variable);
|
||||
Variable.serialize(dout, (Variable)object);
|
||||
} else if (object instanceof StackFrame) {
|
||||
dout.writeInt(SERIAL_TYPE_StackFrame);
|
||||
StackFrame.serialize(dout, (StackFrame)object);
|
||||
} else if (object instanceof DebugResponseSimple) {
|
||||
dout.writeInt(SERIAL_TYPE_DebugResponseSimple);
|
||||
DebugResponseSimple.serialize(dout, (DebugResponseSimple)object);
|
||||
} else if (object instanceof DebugResponseStack) {
|
||||
dout.writeInt(SERIAL_TYPE_DebugResponseStack);
|
||||
DebugResponseStack.serialize(dout, (DebugResponseStack)object);
|
||||
} else if (object instanceof DebugResponseCallgraph) {
|
||||
dout.writeInt(SERIAL_TYPE_DebugResponseCallgraph);
|
||||
DebugResponseCallgraph.serialize(dout, (DebugResponseCallgraph)object);
|
||||
} else if (object instanceof DebugSupport.State) {
|
||||
dout.writeInt(SERIAL_TYPE_DebugSupportState);
|
||||
DebugSupport.State.serialize(dout, (DebugSupport.State)object);
|
||||
} else if (object instanceof DebugRequestType) {
|
||||
dout.writeInt(SERIAL_TYPE_DebugRequestType);
|
||||
DebugRequestType.serialize(dout, (DebugRequestType)object);
|
||||
} else if (object instanceof DebugRequestStack) {
|
||||
dout.writeInt(SERIAL_TYPE_DebugRequestStack);
|
||||
DebugRequestStack.serialize(dout, (DebugRequestStack)object);
|
||||
} else if (object instanceof DebugRequestLineBreakpointToggle) {
|
||||
dout.writeInt(SERIAL_TYPE_DebugRequestLineBreakpointToggle);
|
||||
DebugRequestLineBreakpointToggle.serialize(dout, (DebugRequestLineBreakpointToggle)object);
|
||||
} else if (object instanceof DebugRequest) {
|
||||
dout.writeInt(SERIAL_TYPE_DebugRequest);
|
||||
DebugRequest.serialize(dout, (DebugRequest)object);
|
||||
} else if (object instanceof DebugEventType) {
|
||||
dout.writeInt(SERIAL_TYPE_DebugEventType);
|
||||
DebugEventType.serialize(dout, (DebugEventType)object);
|
||||
} else if (object instanceof DebugEventBreakpoint) {
|
||||
dout.writeInt(SERIAL_TYPE_DebugEventBreakpoint);
|
||||
DebugEventBreakpoint.serialize(dout, (DebugEventBreakpoint)object);
|
||||
} else if (object instanceof DebugEvent) {
|
||||
dout.writeInt(SERIAL_TYPE_DebugEvent);
|
||||
DebugEvent.serialize(dout, (DebugEvent)object);
|
||||
} else {
|
||||
// catch the errors: forgot to implement serialization/deserialization
|
||||
throw new RuntimeException("serialization operation is not supported");
|
||||
}
|
||||
}
|
||||
|
||||
public static Serializable deserialize(DataInputStream din)
|
||||
throws IOException {
|
||||
Serializable object = null;
|
||||
int type = din.readInt();
|
||||
switch (type) {
|
||||
case SERIAL_TYPE_NullableString:
|
||||
object = NullableString.deserialize(din);
|
||||
break;
|
||||
case SERIAL_TYPE_TableVariable:
|
||||
object = TableVariable.deserialize(din);
|
||||
break;
|
||||
case SERIAL_TYPE_Variable:
|
||||
object = Variable.deserialize(din);
|
||||
break;
|
||||
case SERIAL_TYPE_StackFrame:
|
||||
object = StackFrame.deserialize(din);
|
||||
break;
|
||||
case SERIAL_TYPE_DebugResponseSimple:
|
||||
object = DebugResponseSimple.deserialize(din);
|
||||
break;
|
||||
case SERIAL_TYPE_DebugResponseCallgraph:
|
||||
object = DebugResponseCallgraph.deserialize(din);
|
||||
break;
|
||||
case SERIAL_TYPE_DebugResponseStack:
|
||||
object = DebugResponseStack.deserialize(din);
|
||||
break;
|
||||
case SERIAL_TYPE_DebugSupportState:
|
||||
object = DebugSupport.State.deserialize(din);
|
||||
break;
|
||||
case SERIAL_TYPE_DebugRequestType:
|
||||
object = DebugRequestType.deserialize(din);
|
||||
break;
|
||||
case SERIAL_TYPE_DebugRequestStack:
|
||||
object = DebugRequestStack.deserialize(din);
|
||||
break;
|
||||
case SERIAL_TYPE_DebugRequestLineBreakpointToggle:
|
||||
object = DebugRequestLineBreakpointToggle.deserialize(din);
|
||||
break;
|
||||
case SERIAL_TYPE_DebugRequest:
|
||||
object = DebugRequest.deserialize(din);
|
||||
break;
|
||||
case SERIAL_TYPE_DebugEventType:
|
||||
object = DebugEventType.deserialize(din);
|
||||
break;
|
||||
case SERIAL_TYPE_DebugEventBreakpoint:
|
||||
object = DebugEventBreakpoint.deserialize(din);
|
||||
break;
|
||||
case SERIAL_TYPE_DebugEvent:
|
||||
object = DebugEvent.deserialize(din);
|
||||
break;
|
||||
default:
|
||||
throw new RuntimeException("deserialization operation is not supported");
|
||||
}
|
||||
|
||||
return object;
|
||||
}
|
||||
}
|
||||
@@ -42,23 +42,25 @@
|
||||
******************************************************************************/
|
||||
package lua.debug;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
import lua.CallInfo;
|
||||
import lua.io.Proto;
|
||||
|
||||
public class StackFrame implements Serializable {
|
||||
private static final long serialVersionUID = 2102834561519501432L;
|
||||
protected int lineNumber;
|
||||
protected String source;
|
||||
|
||||
public StackFrame(CallInfo callInfo, int lineNumber) {
|
||||
Proto prototype = callInfo.closure.p;
|
||||
|
||||
this.lineNumber = lineNumber;
|
||||
this.source = DebugUtils.getSourceFileName(prototype.source);
|
||||
this(lineNumber, DebugUtils.getSourceFileName(callInfo.closure.p.source));
|
||||
}
|
||||
|
||||
StackFrame(int lineNumber, String source) {
|
||||
this.lineNumber = lineNumber;
|
||||
this.source = source;
|
||||
}
|
||||
|
||||
public int getLineNumber() {
|
||||
return this.lineNumber;
|
||||
}
|
||||
@@ -73,4 +75,41 @@ public class StackFrame implements Serializable {
|
||||
public String toString() {
|
||||
return getSource() + ":" + getLineNumber();
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
result = prime * result + lineNumber;
|
||||
result = prime * result + ((source == null) ? 0 : source.hashCode());
|
||||
return result;
|
||||
}
|
||||
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj)
|
||||
return true;
|
||||
if (obj == null)
|
||||
return false;
|
||||
if (getClass() != obj.getClass())
|
||||
return false;
|
||||
final StackFrame other = (StackFrame) obj;
|
||||
if (lineNumber != other.lineNumber)
|
||||
return false;
|
||||
if (source == null) {
|
||||
if (other.source != null)
|
||||
return false;
|
||||
} else if (!source.equals(other.source))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
public static void serialize(DataOutputStream out, StackFrame stackFrame) throws IOException {
|
||||
out.writeInt(stackFrame.getLineNumber());
|
||||
out.writeUTF(stackFrame.getSource());
|
||||
}
|
||||
|
||||
public static StackFrame deserialize(DataInputStream in) throws IOException {
|
||||
int lineNumber = in.readInt();
|
||||
String source = in.readUTF();
|
||||
return new StackFrame(lineNumber, source);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,22 +40,13 @@ import lua.io.Proto;
|
||||
import lua.value.LString;
|
||||
import lua.value.LValue;
|
||||
|
||||
import org.apache.commons.cli.CommandLine;
|
||||
import org.apache.commons.cli.CommandLineParser;
|
||||
import org.apache.commons.cli.GnuParser;
|
||||
import org.apache.commons.cli.HelpFormatter;
|
||||
import org.apache.commons.cli.OptionBuilder;
|
||||
import org.apache.commons.cli.Options;
|
||||
import org.apache.commons.cli.ParseException;
|
||||
|
||||
/**
|
||||
* StandardLuaJVM executes a lua program in normal run mode or debug mode.
|
||||
*
|
||||
* @author: Shu Lei
|
||||
* @version: 1.0
|
||||
*/
|
||||
public class StandardLuaJVM implements DebugRequestListener {
|
||||
protected Options options = new Options();
|
||||
public class StandardLuaJVM implements DebugRequestListener {
|
||||
protected boolean isDebugMode = false;
|
||||
protected DebugSupport debugSupport;
|
||||
protected int requestPort;
|
||||
@@ -64,88 +55,104 @@ public class StandardLuaJVM implements DebugRequestListener {
|
||||
protected String[] scriptArgs;
|
||||
protected StackState state;
|
||||
protected boolean isReady = false;
|
||||
protected boolean isTerminated = false;
|
||||
|
||||
public StandardLuaJVM() {
|
||||
options.addOption(OptionBuilder.withArgName("requestPort eventPort").
|
||||
hasArgs(2).
|
||||
isRequired(false).
|
||||
withValueSeparator(' ').
|
||||
withDescription("run LuaJ VM in debug mode").
|
||||
create("debug"));
|
||||
options.addOption(OptionBuilder.withArgName("LuaJProgram").
|
||||
withDescription("lua program to be executed").
|
||||
isRequired().
|
||||
hasArgs().
|
||||
withValueSeparator(' ').
|
||||
create("file"));
|
||||
protected boolean isTerminated = false;
|
||||
|
||||
// command line parsing utilities
|
||||
class ParseException extends Exception {
|
||||
private static final long serialVersionUID = -3134938136698856577L;
|
||||
|
||||
public ParseException(String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
||||
|
||||
protected void printUsage() {
|
||||
HelpFormatter formatter = new HelpFormatter();
|
||||
formatter.printHelp("java StandardLuaJVM", options);
|
||||
System.out.println("Usage:");
|
||||
System.out.println("\t java StandardLuaJVM [-debug <requestPort> <eventPort>] <script> [<script arguments>]");
|
||||
System.out.println("where [] denotes an optional argument and <> denotes a placeholder.");
|
||||
}
|
||||
|
||||
protected void parse(String[] args) throws ParseException {
|
||||
CommandLineParser parser = new GnuParser();
|
||||
try {
|
||||
CommandLine line = parser.parse(options, args);
|
||||
if (line.hasOption("debug")) {
|
||||
this.isDebugMode = true;
|
||||
String[] ports = line.getOptionValues("debug");
|
||||
|
||||
this.requestPort = Integer.parseInt(ports[0]);
|
||||
if (this.requestPort <= 0) {
|
||||
throw new ParseException("Invalid request port: it must be greater than zero.");
|
||||
}
|
||||
|
||||
this.eventPort = Integer.parseInt(ports[1]);
|
||||
if (this.eventPort <= 0) {
|
||||
throw new ParseException("Invalid event port: it must be greater than zero.");
|
||||
}
|
||||
|
||||
if (this.requestPort == this.eventPort) {
|
||||
throw new ParseException("Invalid ports: request port and event port must be different");
|
||||
}
|
||||
}
|
||||
void parse(String[] args) throws ParseException {
|
||||
if (args == null || args.length < 1) {
|
||||
throw new ParseException("Invalid command line arguments.");
|
||||
}
|
||||
|
||||
if (line.hasOption("file")) {
|
||||
String[] fileArgs = line.getOptionValues("file");
|
||||
this.script = URLDecoder.decode(fileArgs[0], "UTF-8");
|
||||
DebugUtils.println("Lua script to run: " + this.script);
|
||||
this.scriptArgs = new String[fileArgs.length - 1];
|
||||
for (int i = 1; i < fileArgs.length; i++) {
|
||||
this.scriptArgs[i-1] = URLDecoder.decode(fileArgs[i], "UTF-8");
|
||||
}
|
||||
if ("-debug".equals(args[0])) {
|
||||
if (args.length < 4) {
|
||||
throw new ParseException("Invalid command line arguments.");
|
||||
}
|
||||
|
||||
this.isDebugMode = true;
|
||||
try {
|
||||
this.requestPort = Integer.parseInt(args[1]);
|
||||
if (this.requestPort <= 0) {
|
||||
throw new ParseException("Invalid request port: it must be greater than zero.");
|
||||
}
|
||||
|
||||
this.eventPort = Integer.parseInt(args[2]);
|
||||
if (this.eventPort <= 0) {
|
||||
throw new ParseException("Invalid event port: it must be greater than zero.");
|
||||
}
|
||||
} catch(NumberFormatException e) {
|
||||
throw new ParseException("Invalid port number: " + e.getMessage());
|
||||
}
|
||||
|
||||
if (this.requestPort == this.eventPort) {
|
||||
throw new ParseException("Invalid ports: request port and event port must be different");
|
||||
}
|
||||
} catch(NumberFormatException e) {
|
||||
throw new ParseException("Invalid port number: " + e.getMessage());
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
throw new ParseException("Malformed program argument strings: " + e.getMessage());
|
||||
}
|
||||
|
||||
int tempArgsCount = args.length - 3;
|
||||
String[] tempArgs = new String[tempArgsCount];
|
||||
System.arraycopy(args, 3, tempArgs, 0, tempArgsCount);
|
||||
parseScriptArgs(tempArgs);
|
||||
} else {
|
||||
parseScriptArgs(args);
|
||||
}
|
||||
}
|
||||
|
||||
protected boolean isDebug() {
|
||||
|
||||
private void parseScriptArgs(String[] args)
|
||||
throws lua.debug.StandardLuaJVM.ParseException {
|
||||
if (args == null || args.length < 1) {
|
||||
throw new ParseException("script is missing.");
|
||||
}
|
||||
|
||||
try {
|
||||
this.script = URLDecoder.decode(args[0], "UTF-8");
|
||||
DebugUtils.println("Lua script to run: " + this.script);
|
||||
int scriptArgsLength = args.length - 1;
|
||||
if (scriptArgsLength > 0) {
|
||||
this.scriptArgs = new String[scriptArgsLength];
|
||||
for (int i = 1; i < args.length; i++) {
|
||||
this.scriptArgs[i - 1] = URLDecoder.decode(args[i], "UTF-8");
|
||||
}
|
||||
}
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
throw new ParseException("Malformed program argument strings: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
// end of command line parsing utilities
|
||||
|
||||
boolean isDebug() {
|
||||
return this.isDebugMode;
|
||||
}
|
||||
|
||||
protected int getRequestPort() {
|
||||
int getRequestPort() {
|
||||
return this.requestPort;
|
||||
}
|
||||
|
||||
protected int getEventPort() {
|
||||
int getEventPort() {
|
||||
return this.eventPort;
|
||||
}
|
||||
|
||||
protected String getScript() {
|
||||
String getScript() {
|
||||
return this.script;
|
||||
}
|
||||
|
||||
protected boolean hasScriptArgs() {
|
||||
boolean hasScriptArgs() {
|
||||
return (this.scriptArgs != null && this.scriptArgs.length > 0);
|
||||
}
|
||||
|
||||
protected String[] getScriptArgs() {
|
||||
String[] getScriptArgs() {
|
||||
return this.scriptArgs;
|
||||
}
|
||||
|
||||
@@ -175,7 +182,8 @@ public class StandardLuaJVM implements DebugRequestListener {
|
||||
state = new StackState();
|
||||
|
||||
// convert args to lua
|
||||
int numOfScriptArgs = getScriptArgs().length;
|
||||
String[] scriptArgs = getScriptArgs();
|
||||
int numOfScriptArgs = (scriptArgs == null) ? 0 : scriptArgs.length;
|
||||
LValue[] vargs = new LValue[numOfScriptArgs];
|
||||
for (int i = 0; i < numOfScriptArgs; i++) {
|
||||
vargs[i] = new LString(getScriptArgs()[i]);
|
||||
@@ -191,35 +199,36 @@ public class StandardLuaJVM implements DebugRequestListener {
|
||||
state.doCall(c, vargs);
|
||||
}
|
||||
|
||||
private void doDebug() throws IOException {
|
||||
DebugUtils.println("start debugging...");
|
||||
this.debugSupport = new DebugSupport(this, getRequestPort(), getEventPort());
|
||||
DebugUtils.println("created client request socket connection...");
|
||||
debugSupport.start();
|
||||
|
||||
DebugUtils.println("setting up LuaJava and debug stack state...");
|
||||
|
||||
private void doDebug() throws IOException {
|
||||
DebugUtils.println("setting up LuaJava and debug stack state...");
|
||||
init();
|
||||
|
||||
// new lua state
|
||||
state = new DebugStackState();
|
||||
getDebugState().addDebugEventListener(debugSupport);
|
||||
|
||||
|
||||
// load the Lua file
|
||||
DebugUtils.println("loading Lua script '" + getScript() + "'");
|
||||
InputStream is = new FileInputStream(new File(getScript()));
|
||||
Proto p = LoadState.undump(state, is, getScript());
|
||||
|
||||
// set up debug support if the file is successfully loaded
|
||||
DebugUtils.println("start debugging...");
|
||||
this.debugSupport = new DebugSupport(this, getRequestPort(), getEventPort());
|
||||
DebugUtils.println("created client request socket connection...");
|
||||
debugSupport.start();
|
||||
|
||||
// new lua debug state
|
||||
state = new DebugStackState();
|
||||
getDebugState().addDebugEventListener(debugSupport);
|
||||
getDebugState().suspend();
|
||||
|
||||
// create closure and execute
|
||||
final Closure c = new Closure(state, p);
|
||||
getDebugState().suspend();
|
||||
|
||||
new Thread(new Runnable() {
|
||||
public void run() {
|
||||
int numOfScriptArgs = getScriptArgs().length;
|
||||
public void run() {
|
||||
String[] args = getScriptArgs();
|
||||
int numOfScriptArgs = (args != null ? args.length : 0);
|
||||
LValue[] vargs = new LValue[numOfScriptArgs];
|
||||
for (int i = 0; i < numOfScriptArgs; i++) {
|
||||
vargs[i] = new LString(getScriptArgs()[i]);
|
||||
vargs[i] = new LString(args[i]);
|
||||
}
|
||||
|
||||
getDebugState().doCall(c, vargs);
|
||||
@@ -281,25 +290,21 @@ public class StandardLuaJVM implements DebugRequestListener {
|
||||
/**
|
||||
* Parses the command line arguments and executes/debugs the lua program.
|
||||
* @param args -- command line arguments:
|
||||
* [-debug requestPort eventPort] -file luaProgram args
|
||||
* @throws IOException
|
||||
* [-debug <requestPort> <eventPort>] <script> <script arguments separated by a whitespace>
|
||||
*/
|
||||
public static void main(String[] args) {
|
||||
StandardLuaJVM vm = new StandardLuaJVM();
|
||||
|
||||
try {
|
||||
vm.parse(args);
|
||||
vm.run();
|
||||
} catch (ParseException e) {
|
||||
DebugUtils.println(e.getMessage());
|
||||
System.out.println("Error: " + e.getMessage());
|
||||
vm.printUsage();
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
vm.run();
|
||||
} catch (IOException e) {
|
||||
//TODO: handle the error
|
||||
e.printStackTrace();
|
||||
System.out.println("Error: " + e.getMessage());
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,16 +21,16 @@
|
||||
******************************************************************************/
|
||||
package lua.debug;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.Vector;
|
||||
|
||||
import lua.Lua;
|
||||
import lua.value.LTable;
|
||||
import lua.value.LValue;
|
||||
|
||||
public class TableVariable extends Variable {
|
||||
|
||||
private static final long serialVersionUID = 1194778378382802700L;
|
||||
public class TableVariable extends Variable {
|
||||
protected String[] keys;
|
||||
protected Object[] values;
|
||||
|
||||
@@ -39,8 +39,8 @@ public class TableVariable extends Variable {
|
||||
|
||||
int size = table.size();
|
||||
DebugUtils.println("table size:" + size);
|
||||
List keyArray = new ArrayList();
|
||||
List valueArray = new ArrayList();
|
||||
Vector keyArray = new Vector();
|
||||
Vector valueArray = new Vector();
|
||||
LValue[] keyValues = table.getKeys();
|
||||
for (int i = 0; i < size; i++) {
|
||||
|
||||
@@ -60,14 +60,73 @@ public class TableVariable extends Variable {
|
||||
}
|
||||
|
||||
this.keys = (String[])keyArray.toArray(new String[0]);
|
||||
this.values = valueArray.toArray();
|
||||
this.values = (Object[]) valueArray.toArray(new Object[0]);
|
||||
if (this.keys.length != this.values.length) {
|
||||
throw new RuntimeException("Internal Error: key.length must equal to values.length");
|
||||
}
|
||||
}
|
||||
|
||||
public TableVariable(int index, String name, int type, String[] keys, Object[] values) {
|
||||
super(index, name, type, null);
|
||||
this.keys = keys;
|
||||
this.values = values;
|
||||
}
|
||||
|
||||
public String[] getKeys() {
|
||||
return this.keys;
|
||||
return this.keys == null ? new String[0] : this.keys;
|
||||
}
|
||||
|
||||
public Object[] getValues() {
|
||||
return this.values;
|
||||
return this.values == null ? new Object[0] : this.values;
|
||||
}
|
||||
|
||||
public static void serialize(DataOutputStream out, TableVariable variable) throws IOException {
|
||||
out.writeInt(variable.getIndex());
|
||||
out.writeUTF(variable.getName());
|
||||
out.writeInt(variable.getType());
|
||||
|
||||
String[] keys = variable.getKeys();
|
||||
out.writeInt(keys.length);
|
||||
for (int i = 0; keys != null && i < keys.length; i++) {
|
||||
SerializationHelper.serialize(new NullableString(keys[i]), out);
|
||||
}
|
||||
|
||||
Object[] values = variable.getValues();
|
||||
for (int i = 0; values != null && i < values.length; i++) {
|
||||
if (values[i] instanceof String) {
|
||||
SerializationHelper.serialize(new NullableString((String)values[i]), out);
|
||||
} else if (values[i] instanceof TableVariable) {
|
||||
SerializationHelper.serialize((TableVariable)values[i], out);
|
||||
} else {
|
||||
throw new RuntimeException("Internal Error: values array should only contain String and TableVariable");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static Variable deserialize(DataInputStream in) throws IOException {
|
||||
int index = in.readInt();
|
||||
String name = in.readUTF();
|
||||
int type = in.readInt();
|
||||
|
||||
String[] keys = null;
|
||||
Object[] values = null;
|
||||
int count = in.readInt();
|
||||
keys = new String[count];
|
||||
for (int i = 0; i < count; i++) {
|
||||
keys[i] = ((NullableString) SerializationHelper.deserialize(in)).getRawString();
|
||||
}
|
||||
|
||||
values = new Object[count];
|
||||
for (int i = 0; i < count; i++) {
|
||||
int serialType = in.readInt();
|
||||
if (serialType == SerializationHelper.SERIAL_TYPE_NullableString) {
|
||||
values[i] = NullableString.deserialize(in).getRawString();
|
||||
} else if (serialType == SerializationHelper.SERIAL_TYPE_TableVariable) {
|
||||
values[i] = TableVariable.deserialize(in);
|
||||
}
|
||||
}
|
||||
|
||||
TableVariable variable = new TableVariable(index, name, type, keys, values);
|
||||
return variable;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,19 +21,27 @@
|
||||
******************************************************************************/
|
||||
package lua.debug;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
import lua.Lua;
|
||||
|
||||
public class Variable implements Serializable {
|
||||
private static final long serialVersionUID = 8194091816623233934L;
|
||||
|
||||
public class Variable implements Serializable {
|
||||
protected int index;
|
||||
protected String name;
|
||||
protected String value;
|
||||
protected int type;
|
||||
protected int type;
|
||||
|
||||
public Variable(int index, String name, int type, String value) {
|
||||
if (name == null) {
|
||||
throw new IllegalArgumentException("argument name is null");
|
||||
}
|
||||
|
||||
if (type < Lua.LUA_TNIL || type > Lua.LUA_TTHREAD) {
|
||||
throw new IllegalArgumentException("invalid LValue type: " + type);
|
||||
}
|
||||
|
||||
this.index = index;
|
||||
this.name = name;
|
||||
this.type = type;
|
||||
@@ -59,4 +67,57 @@ public class Variable implements Serializable {
|
||||
public String toString() {
|
||||
return "index: " + getIndex() + " name:" + getName() + " type: " + Lua.TYPE_NAMES[getType()] + " value:" + getValue();
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
result = prime * result + index;
|
||||
result = prime * result + ((name == null) ? 0 : name.hashCode());
|
||||
result = prime * result + type;
|
||||
result = prime * result + ((value == null) ? 0 : value.hashCode());
|
||||
return result;
|
||||
}
|
||||
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj)
|
||||
return true;
|
||||
if (obj == null)
|
||||
return false;
|
||||
if (getClass() != obj.getClass())
|
||||
return false;
|
||||
final Variable other = (Variable) obj;
|
||||
if (index != other.index)
|
||||
return false;
|
||||
if (name == null) {
|
||||
if (other.name != null)
|
||||
return false;
|
||||
} else if (!name.equals(other.name))
|
||||
return false;
|
||||
if (type != other.type)
|
||||
return false;
|
||||
if (value == null) {
|
||||
if (other.value != null)
|
||||
return false;
|
||||
} else if (!value.equals(other.value))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
public static void serialize(DataOutputStream out, Variable variable)
|
||||
throws IOException {
|
||||
out.writeInt(variable.getIndex());
|
||||
out.writeUTF(variable.getName());
|
||||
out.writeInt(variable.getType());
|
||||
SerializationHelper.serialize(new NullableString(variable.getValue()), out);
|
||||
}
|
||||
|
||||
public static Variable deserialize(DataInputStream in) throws IOException {
|
||||
int index = in.readInt();
|
||||
String name = in.readUTF();
|
||||
int type = in.readInt();
|
||||
NullableString value = (NullableString)SerializationHelper.deserialize(in);
|
||||
|
||||
Variable variable = new Variable(index, name, type, value.getRawString());
|
||||
return variable;
|
||||
}
|
||||
}
|
||||
|
||||
33
src/test/java/lua/debug/DebugEventTest.java
Normal file
33
src/test/java/lua/debug/DebugEventTest.java
Normal file
@@ -0,0 +1,33 @@
|
||||
package lua.debug;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
public class DebugEventTest extends TestCase {
|
||||
public void testDebugEventSerialization() {
|
||||
try {
|
||||
DebugEvent event = new DebugEvent(DebugEventType.started);
|
||||
byte[] data = SerializationHelper.serialize(event);
|
||||
DebugEvent eventOut = (DebugEvent)SerializationHelper.deserialize(data);
|
||||
assertNotNull(eventOut);
|
||||
assertEquals(event.getType(), eventOut.getType());
|
||||
} catch (IOException e) {
|
||||
fail(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public void testDebugEventBreakpointSerialization() {
|
||||
try {
|
||||
DebugEventBreakpoint event = new DebugEventBreakpoint("test.lua", 100);
|
||||
byte[] data = SerializationHelper.serialize(event);
|
||||
DebugEventBreakpoint eventOut
|
||||
= (DebugEventBreakpoint) SerializationHelper.deserialize(data);
|
||||
assertNotNull(eventOut);
|
||||
assertEquals(event.getSource(), eventOut.getSource());
|
||||
assertEquals(event.getLineNumber(), eventOut.getLineNumber());
|
||||
} catch (IOException e) {
|
||||
fail(e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
56
src/test/java/lua/debug/DebugRequestTest.java
Normal file
56
src/test/java/lua/debug/DebugRequestTest.java
Normal file
@@ -0,0 +1,56 @@
|
||||
package lua.debug;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
public class DebugRequestTest extends TestCase {
|
||||
public void testDebugRequestSerialization() {
|
||||
try {
|
||||
DebugRequest request = new DebugRequest(DebugRequestType.resume);
|
||||
byte[] data = SerializationHelper.serialize(request);
|
||||
DebugRequest requestOut
|
||||
= (DebugRequest)SerializationHelper.deserialize(data);
|
||||
assertNotNull(requestOut);
|
||||
assertEquals(request.getType(), requestOut.getType());
|
||||
} catch (IOException e) {
|
||||
fail(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public void testDebugRequestStackSerialization() {
|
||||
try {
|
||||
DebugRequestStack request = new DebugRequestStack(1);
|
||||
byte[] data = SerializationHelper.serialize(request);
|
||||
DebugRequestStack requestOut
|
||||
= (DebugRequestStack) SerializationHelper.deserialize(data);
|
||||
assertNotNull(requestOut);
|
||||
assertEquals(requestOut.getIndex(), 1);
|
||||
} catch (IOException e) {
|
||||
fail(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public void testDebugRequestLineBreakpointToggleSerialization() {
|
||||
try
|
||||
{
|
||||
doTestDebugRequestLineBreakpointToggleSerialization(DebugRequestType.lineBreakpointSet, "test.lua", 100);
|
||||
doTestDebugRequestLineBreakpointToggleSerialization(DebugRequestType.lineBreakpointClear, "test.lua", 50);
|
||||
} catch (IOException e) {
|
||||
fail(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
private void doTestDebugRequestLineBreakpointToggleSerialization(
|
||||
DebugRequestType type, String source, int lineNo) throws IOException {
|
||||
DebugRequestLineBreakpointToggle request
|
||||
= new DebugRequestLineBreakpointToggle(DebugRequestType.lineBreakpointSet, "test.lua", 100);
|
||||
byte[] data = SerializationHelper.serialize(request);
|
||||
DebugRequestLineBreakpointToggle requestOut =
|
||||
(DebugRequestLineBreakpointToggle) SerializationHelper.deserialize(data);
|
||||
assertNotNull(requestOut);
|
||||
assertEquals(request.getType(), requestOut.getType());
|
||||
assertEquals(request.getSource(), requestOut.getSource());
|
||||
assertEquals(request.getLineNumber(), requestOut.getLineNumber());
|
||||
}
|
||||
}
|
||||
88
src/test/java/lua/debug/DebugResponseTest.java
Normal file
88
src/test/java/lua/debug/DebugResponseTest.java
Normal file
@@ -0,0 +1,88 @@
|
||||
package lua.debug;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
import lua.Lua;
|
||||
|
||||
public class DebugResponseTest extends TestCase {
|
||||
public void testDebugResponseSimpleSerialization() {
|
||||
try {
|
||||
DebugResponseSimple responseIn = DebugResponseSimple.SUCCESS;
|
||||
byte[] data = SerializationHelper.serialize(responseIn);
|
||||
DebugResponseSimple responseOut
|
||||
= (DebugResponseSimple)SerializationHelper.deserialize(data);
|
||||
assertEquals(responseIn, responseOut);
|
||||
} catch (IOException e) {
|
||||
fail(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public void testDebugResponseStackSerialization() {
|
||||
try {
|
||||
doTestDebugResponseStackSerialization(null);
|
||||
|
||||
doTestDebugResponseStackSerialization(new Variable[0]);
|
||||
|
||||
Variable[] variables = new Variable[5];
|
||||
variables[0] = new Variable(0, "variable1", Lua.LUA_TSTRING, "value1");
|
||||
variables[1] = new Variable(1, "variable2", Lua.LUA_TNIL, "nil");
|
||||
variables[2] = new Variable(2, "variable3", Lua.LUA_TBOOLEAN, "false");
|
||||
|
||||
TableVariable childTable = new TableVariable(0, "child", Lua.LUA_TTABLE, new String[0], new Object[0]);
|
||||
String[] keys = new String[] {"key1", "key2"};
|
||||
Object[] values = new Object[] {"value1", childTable};
|
||||
variables[3] = new TableVariable(2, "variable4", Lua.LUA_TTABLE, keys, values);
|
||||
|
||||
variables[4] = new Variable(2, "variable3", Lua.LUA_TNUMBER, "10");
|
||||
doTestDebugResponseStackSerialization(variables);
|
||||
} catch (IOException e) {
|
||||
fail(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
private void doTestDebugResponseStackSerialization(Variable[] variables)
|
||||
throws IOException {
|
||||
DebugResponseStack stackIn = new DebugResponseStack(variables);
|
||||
byte[] data = SerializationHelper.serialize(stackIn);
|
||||
DebugResponseStack stackOut
|
||||
= (DebugResponseStack) SerializationHelper.deserialize(data);
|
||||
Variable[] variablesIn = stackIn.getVariables();
|
||||
Variable[] variablesOut = stackOut.getVariables();
|
||||
assertNotNull(variablesIn);
|
||||
assertNotNull(variablesOut);
|
||||
assertEquals(variablesIn.length, variablesOut.length);
|
||||
for (int i = 0; i < variablesIn.length; i++) {
|
||||
assertEquals(variablesIn[i], variablesOut[i]);
|
||||
}
|
||||
}
|
||||
|
||||
public void testDebugResponseCallgraphSerialization() {
|
||||
try {
|
||||
doTestDebugResponseCallgraphSerialization(null);
|
||||
doTestDebugResponseCallgraphSerialization(new StackFrame[0]);
|
||||
|
||||
StackFrame[] frames = new StackFrame[1];
|
||||
frames[0] = new StackFrame(100, "test.lua");
|
||||
doTestDebugResponseCallgraphSerialization(frames);
|
||||
} catch (IOException e) {
|
||||
fail(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
private void doTestDebugResponseCallgraphSerialization(StackFrame[] frames)
|
||||
throws IOException {
|
||||
DebugResponseCallgraph responseIn = new DebugResponseCallgraph(frames);
|
||||
byte[] data = SerializationHelper.serialize(responseIn);
|
||||
DebugResponseCallgraph responseOut =
|
||||
(DebugResponseCallgraph) SerializationHelper.deserialize(data);
|
||||
assertNotNull(responseOut);
|
||||
StackFrame[] inFrames = responseIn.getCallgraph();
|
||||
StackFrame[] outFrames = responseOut.getCallgraph();
|
||||
assertNotNull(outFrames);
|
||||
assertEquals(inFrames.length, outFrames.length);
|
||||
for (int i = 0; i < inFrames.length; i++) {
|
||||
assertEquals(inFrames[i], outFrames[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
41
src/test/java/lua/debug/EnumTypeTest.java
Normal file
41
src/test/java/lua/debug/EnumTypeTest.java
Normal file
@@ -0,0 +1,41 @@
|
||||
package lua.debug;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
public class EnumTypeTest extends TestCase {
|
||||
public void testDebugSupportStateSerialization() {
|
||||
try {
|
||||
DebugSupport.State stateIn = DebugSupport.State.RUNNING;
|
||||
byte[] data = SerializationHelper.serialize(stateIn);
|
||||
DebugSupport.State stateOut
|
||||
= (DebugSupport.State) SerializationHelper.deserialize(data);
|
||||
assertEquals(stateIn, stateOut);
|
||||
} catch (Exception e) {
|
||||
fail(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public void testDebugRequestTypeSerialization() {
|
||||
try {
|
||||
DebugRequestType type = DebugRequestType.lineBreakpointClear;
|
||||
byte[] data = SerializationHelper.serialize(type);
|
||||
DebugRequestType typeOut
|
||||
= (DebugRequestType) SerializationHelper.deserialize(data);
|
||||
assertEquals(type, typeOut);
|
||||
} catch (Exception e) {
|
||||
fail(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public void testDebugEventTypeSerialization() {
|
||||
try {
|
||||
DebugEventType type = DebugEventType.error;
|
||||
byte[] data = SerializationHelper.serialize(type);
|
||||
DebugEventType typeOut = (DebugEventType) SerializationHelper.deserialize(data);
|
||||
assertNotNull(typeOut);
|
||||
assertEquals(type, typeOut);
|
||||
} catch (Exception e) {
|
||||
fail(e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -21,29 +21,99 @@
|
||||
******************************************************************************/
|
||||
package lua.debug;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.URL;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
import lua.debug.StandardLuaJVM.ParseException;
|
||||
|
||||
/**
|
||||
* Sanity test for StandardLuaJVM.
|
||||
*/
|
||||
public class LuaJVMTest extends TestCase {
|
||||
protected void doTestRun(String testName) {
|
||||
String[] args = new String[2];
|
||||
args[0] = "-file";
|
||||
URL filePath = getClass().getResource("/"+ testName);
|
||||
if (filePath != null) {
|
||||
args[1] = filePath.getPath();
|
||||
try {
|
||||
StandardLuaJVM.main(args);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
fail("Test " + testName + " failed due to " + e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void testCommandLineParse() {
|
||||
// null arguments
|
||||
String[] args = null;
|
||||
StandardLuaJVM vm = new StandardLuaJVM();
|
||||
try {
|
||||
vm.parse(args);
|
||||
fail("Bad parsing program. Should never reach this line.");
|
||||
} catch (ParseException e) {}
|
||||
|
||||
// empty arguments
|
||||
args = new String[] {};
|
||||
try {
|
||||
vm.parse(args);
|
||||
fail("Bad parsing program. Should never reach this line.");
|
||||
} catch (ParseException e) {}
|
||||
|
||||
// incomplete arguments
|
||||
args = new String[] { "-debug" };
|
||||
try {
|
||||
vm.parse(args);
|
||||
fail("Bad parsing program. Should never reach this line.");
|
||||
} catch (ParseException e) {}
|
||||
|
||||
// incomplete arguments
|
||||
args = new String[] { "-debug", "1046" };
|
||||
try {
|
||||
vm.parse(args);
|
||||
fail("Bad parsing program. Should never reach this line.");
|
||||
} catch (ParseException e) {}
|
||||
|
||||
// missing script name
|
||||
args = new String[] { "-debug", "1046", "1047"};
|
||||
try {
|
||||
vm.parse(args);
|
||||
fail("Bad parsing program. Should never reach this line.");
|
||||
} catch (ParseException e) {}
|
||||
|
||||
// malformed request port
|
||||
args = new String[] { "-debug", "104x", "1046", "dummy.lua"};
|
||||
try {
|
||||
vm.parse(args);
|
||||
fail("Bad parsing program. Should never reach this line.");
|
||||
} catch (ParseException e) {}
|
||||
|
||||
// malformed event port
|
||||
args = new String[] { "-debug", "1046", "104x", "dummy.lua"};
|
||||
try {
|
||||
vm.parse(args);
|
||||
fail("Bad parsing program. Should never reach this line.");
|
||||
} catch (ParseException e) {}
|
||||
|
||||
// event port == request port
|
||||
args = new String[] { "-debug", "1046", "1046", "dummy.lua"};
|
||||
try {
|
||||
vm.parse(args);
|
||||
fail("Bad parsing program. Should never reach this line.");
|
||||
} catch (ParseException e) {}
|
||||
|
||||
// lua script cannot be found
|
||||
args = new String[] { "-debug", "1046", "1047", "dummy.lua"};
|
||||
try {
|
||||
vm.parse(args);
|
||||
vm.run();
|
||||
fail("Should never reach this line.");
|
||||
} catch (ParseException e) {
|
||||
fail("Should never reach this line.");
|
||||
} catch (IOException e) {
|
||||
//expected
|
||||
}
|
||||
|
||||
// lua script cannot be found
|
||||
args = new String[] {"dummy.lua"};
|
||||
try {
|
||||
vm.parse(args);
|
||||
vm.run();
|
||||
fail("Bad parsing program. Should never reach this line.");
|
||||
} catch (ParseException e) {
|
||||
fail("Should never reach this line.");
|
||||
} catch (IOException e) {
|
||||
//expected
|
||||
}
|
||||
}
|
||||
|
||||
public void testRun() {
|
||||
String[] tests = new String[] {
|
||||
"autoload",
|
||||
@@ -78,4 +148,18 @@ public class LuaJVMTest extends TestCase {
|
||||
System.out.println();
|
||||
}
|
||||
}
|
||||
|
||||
protected void doTestRun(String testName) {
|
||||
String[] args = new String[1];
|
||||
URL filePath = getClass().getResource("/"+ testName);
|
||||
if (filePath != null) {
|
||||
args[0] = filePath.getPath();
|
||||
try {
|
||||
StandardLuaJVM.main(args);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
fail("Test " + testName + " failed due to " + e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
19
src/test/java/lua/debug/StackFrameTest.java
Normal file
19
src/test/java/lua/debug/StackFrameTest.java
Normal file
@@ -0,0 +1,19 @@
|
||||
package lua.debug;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
public class StackFrameTest extends TestCase {
|
||||
public void testSerialization() {
|
||||
try {
|
||||
StackFrame stackIn = new StackFrame(10, "test.lua");
|
||||
byte[] data = SerializationHelper.serialize(stackIn);
|
||||
StackFrame stackOut = (StackFrame) SerializationHelper.deserialize(data);
|
||||
assertNotNull(stackOut);
|
||||
assertEquals(stackIn, stackOut);
|
||||
} catch (IOException e) {
|
||||
fail(e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
134
src/test/java/lua/debug/TableVariableTest.java
Normal file
134
src/test/java/lua/debug/TableVariableTest.java
Normal file
@@ -0,0 +1,134 @@
|
||||
package lua.debug;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
import lua.Lua;
|
||||
import lua.value.LBoolean;
|
||||
import lua.value.LDouble;
|
||||
import lua.value.LInteger;
|
||||
import lua.value.LNil;
|
||||
import lua.value.LString;
|
||||
import lua.value.LTable;
|
||||
|
||||
public class TableVariableTest extends TestCase {
|
||||
public void testCreate() {
|
||||
LTable table = new LTable();
|
||||
table.put("key1", new LString("value1"));
|
||||
table.put("key2", new LNil());
|
||||
table.put("key3", LBoolean.TRUE);
|
||||
table.put("key4", LInteger.valueOf(10));
|
||||
table.put("key5", new LDouble(0.5));
|
||||
LTable childTable = new LTable();
|
||||
childTable.put("childKey1", new LString("childValue1"));
|
||||
table.put("key6", childTable);
|
||||
|
||||
TableVariable tableVariable = new TableVariable(0, "tableVar", Lua.LUA_TTABLE, table);
|
||||
String[] keys = tableVariable.getKeys();
|
||||
assertNotNull(keys);
|
||||
assertEquals(keys.length, 6);
|
||||
for (int i = 0; i < 6; i++) {
|
||||
assertTrue(keys[i].startsWith("key"));
|
||||
}
|
||||
Object[] values = tableVariable.getValues();
|
||||
assertNotNull(values);
|
||||
assertEquals(values.length, 6);
|
||||
for (int i = 0; i < 6; i++) {
|
||||
if (values[i] instanceof String) {
|
||||
assertTrue(values[i].equals("value1") ||
|
||||
values[i].equals("nil") ||
|
||||
values[i].equals("true") ||
|
||||
values[i].equals("10") ||
|
||||
values[i].equals("0.5"));
|
||||
} else if (values[i] instanceof TableVariable) {
|
||||
TableVariable child = (TableVariable) values[i];
|
||||
|
||||
String[] childKeys = child.getKeys();
|
||||
assertNotNull(childKeys);
|
||||
assertEquals(childKeys.length, 1);
|
||||
assertEquals(childKeys[0], "childKey1");
|
||||
|
||||
Object[] childValues = child.getValues();
|
||||
assertNotNull(childValues);
|
||||
assertEquals(childValues.length, 1);
|
||||
assertEquals(childValues[0], "childValue1");
|
||||
} else {
|
||||
fail("bad value type");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void testSerialization() {
|
||||
String[] keys = null;
|
||||
Object[] values = null;
|
||||
try {
|
||||
doTestSerialization(0, "name", Lua.LUA_TTABLE, keys, values);
|
||||
} catch (IOException e) {
|
||||
fail(e.getMessage());
|
||||
}
|
||||
|
||||
keys = new String[0];
|
||||
values = new String[0];
|
||||
try {
|
||||
doTestSerialization(0, "name", Lua.LUA_TTABLE, keys, values);
|
||||
} catch (IOException e) {
|
||||
fail(e.getMessage());
|
||||
}
|
||||
|
||||
keys = new String[] {"key1", "key2"};
|
||||
values = new String[] {"value1", "value2"};
|
||||
try {
|
||||
doTestSerialization(0, "name", Lua.LUA_TTABLE, keys, values);
|
||||
} catch (IOException e) {
|
||||
fail(e.getMessage());
|
||||
}
|
||||
|
||||
TableVariable grandchild = new TableVariable(1, "child", Lua.LUA_TTABLE, keys, values);
|
||||
keys = new String[] {"grandchild1", "grandchild2", "grandchild3"};
|
||||
values = new Object[] {"value1", "value2", grandchild};
|
||||
TableVariable child = new TableVariable(1, "child", Lua.LUA_TTABLE, keys, values);
|
||||
keys = new String[] {"child1", "child2"};
|
||||
values = new Object[] {"value1", child};
|
||||
try {
|
||||
doTestSerialization(0, "name", Lua.LUA_TTABLE, keys, values);
|
||||
} catch (IOException e) {
|
||||
fail(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
protected void doTestSerialization(int index, String name, int type,
|
||||
String[] keys, Object[] values)
|
||||
throws IOException {
|
||||
TableVariable in = new TableVariable(index, name, type, keys, values);
|
||||
byte[] data = SerializationHelper.serialize(in);
|
||||
TableVariable out = (TableVariable) SerializationHelper.deserialize(data);
|
||||
|
||||
assertTableVariable(in, out);
|
||||
}
|
||||
|
||||
private void assertTableVariable(TableVariable in, TableVariable out) {
|
||||
assertEquals(in.getIndex(), out.getIndex());
|
||||
assertEquals(in.getType(), out.getType());
|
||||
assertEquals(in.getName(), out.getName());
|
||||
|
||||
String[] inKeys = in.getKeys();
|
||||
String[] outKeys = out.getKeys();
|
||||
assertEquals(inKeys == null ? 0 : inKeys.length, outKeys == null ? 0 : outKeys.length);
|
||||
for (int i = 0; inKeys != null && i < inKeys.length; i++) {
|
||||
assertEquals(inKeys[i], outKeys[i]);
|
||||
}
|
||||
|
||||
Object[] inValues = in.getValues();
|
||||
Object[] outValues = out.getValues();
|
||||
assertEquals(inValues == null ? 0 : inValues.length, outValues == null ? 0 : outValues.length);
|
||||
for (int i = 0; inValues != null && i < inValues.length; i++) {
|
||||
if (inValues[i] instanceof String && outValues[i] instanceof String) {
|
||||
assertEquals(inValues[i], outValues[i]);
|
||||
} else if (inValues[i] instanceof TableVariable && outValues[i] instanceof TableVariable) {
|
||||
assertTableVariable((TableVariable)inValues[i], (TableVariable)outValues[i]);
|
||||
} else {
|
||||
fail("bad serialization");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
26
src/test/java/lua/debug/VariableTest.java
Normal file
26
src/test/java/lua/debug/VariableTest.java
Normal file
@@ -0,0 +1,26 @@
|
||||
package lua.debug;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
import lua.Lua;
|
||||
|
||||
public class VariableTest extends TestCase {
|
||||
public void testSerialization() {
|
||||
doTestSerialization(0, "varName", Lua.LUA_TSTRING, null);
|
||||
doTestSerialization(0, "varName", Lua.LUA_TSTRING, "varValue");
|
||||
}
|
||||
|
||||
protected void doTestSerialization(int index, String varName, int type, String varValue) {
|
||||
Variable varIn = new Variable(index, varName, type, varValue);
|
||||
Variable varOut = null;
|
||||
try {
|
||||
byte[] data = SerializationHelper.serialize(varIn);
|
||||
varOut = (Variable) SerializationHelper.deserialize(data);
|
||||
} catch (IOException e) {
|
||||
fail(e.getMessage());
|
||||
}
|
||||
assertNotNull(varOut);
|
||||
assertEquals(varIn, varOut);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user