VirtualMachine vm;
MethodMirror entry_point;
StepEventRequest step_req;
+ bool forceExit;
void AssertThrows<ExType> (Action del) where ExType : Exception {
bool thrown = false;
return es [0];
}
- void Start (string[] args) {
+ void Start (params string[] args) {
+ Start (false, args);
+ }
+
+ void Start (bool forceExit, params string[] args) {
+ this.forceExit = forceExit;
+
if (!listening) {
var pi = new Diag.ProcessStartInfo ();
MethodMirror m = entry_point.DeclaringType.GetMethod (name);
Assert.IsNotNull (m);
//Console.WriteLine ("X: " + name + " " + m.ILOffsets.Count + " " + m.Locations.Count);
- vm.SetBreakpoint (m, m.ILOffsets [0]);
+ var req = vm.SetBreakpoint (m, m.ILOffsets [0]);
Event e = null;
break;
}
+ req.Disable ();
+
Assert.IsInstanceOfType (typeof (BreakpointEvent), e);
Assert.AreEqual (m.Name, (e as BreakpointEvent).Method.Name);
return e;
}
+ Event step_until (ThreadMirror t, string method_name) {
+ Event e;
+ while (true) {
+ e = single_step (t);
+ if ((e as StepEvent).Method.Name == method_name)
+ break;
+ }
+ return e;
+ }
+
void check_arg_val (StackFrame frame, int pos, Type type, object eval) {
object val = frame.GetArgument (pos);
Assert.IsTrue (val is PrimitiveValue);
[SetUp]
public void SetUp () {
+ ThreadMirror.NativeTransitions = false;
Start (new string [] { "dtest-app.exe" });
}
step_req.Disable ();
vm.Resume ();
+ if (forceExit)
+ vm.Exit (0);
+
while (true) {
Event e = GetNextEvent ();
vm.Resume ();
}
+ vm = null;
}
[Test]
Assert.AreEqual (method, (e as StepEvent).Method.Name);
}
+ StepEventRequest create_step (Event e) {
+ var req = vm.CreateStepRequest (e.Thread);
+ step_req = req;
+ return req;
+ }
+
[Test]
public void SingleStepping () {
Event e = run_until ("single_stepping");
- var req = vm.CreateStepRequest (e.Thread);
+ var req = create_step (e);
req.Enable ();
- step_req = req;
-
// Step over 'bool b = true'
e = step_once ();
assert_location (e, "single_stepping");
e = step_once ();
assert_location (e, "single_stepping");
- // Change to step over
- req.Disable ();
- req.Depth = StepDepth.Over;
- req.Enable ();
-
// Step over ss2
- e = step_once ();
+ e = step_over ();
assert_location (e, "single_stepping");
- // Change to step into
- req.Disable ();
- req.Depth = StepDepth.Into;
- req.Enable ();
-
// Step into ss3
- e = step_once ();
+ e = step_into ();
assert_location (e, "ss3");
- // Change to step out
- req.Disable ();
- req.Depth = StepDepth.Out;
- req.Enable ();
-
// Step back into single_stepping
- e = step_once ();
+ e = step_out ();
assert_location (e, "single_stepping");
- // Change to step into
- req.Disable ();
- req.Depth = StepDepth.Into;
- req.Enable ();
-
// Step into ss3_2 ()
- e = step_once ();
+ e = step_into ();
assert_location (e, "ss3_2");
- // Change to step over
- req.Disable ();
- req.Depth = StepDepth.Over;
- req.Enable ();
-
// Step over ss3_2_2 ()
- e = step_once ();
+ e = step_over ();
assert_location (e, "ss3_2");
// Recreate the request
e = step_once ();
assert_location (e, "single_stepping");
- // Change to step into
- req.Disable ();
- req.Depth = StepDepth.Into;
- req.Enable ();
-
// Step into ss4 ()
- e = step_once ();
+ e = step_into ();
assert_location (e, "ss4");
// Skip nop
assert_location (e, "is_even");
// FIXME: Check that single stepping works with lock (obj)
-
req.Disable ();
// Run until ss6
e = run_until ("ss6");
- req = vm.CreateStepRequest (e.Thread);
+ req = create_step (e);
req.Depth = StepDepth.Over;
req.Enable ();
// Check that a step over stops at an EH clause
e = run_until ("ss7_2");
- req = vm.CreateStepRequest (e.Thread);
+ req = create_step (e);
req.Depth = StepDepth.Out;
req.Enable ();
e = step_once ();
assert_location (e, "ss7");
req.Disable ();
- req = vm.CreateStepRequest (e.Thread);
+ req = create_step (e);
req.Depth = StepDepth.Over;
req.Enable ();
e = step_once ();
assert_location (e, "ss7");
req.Disable ();
+
+ // Check that stepping stops between nested calls
+ e = run_until ("ss_nested_2");
+ e = step_out ();
+ assert_location (e, "ss_nested");
+ e = step_into ();
+ assert_location (e, "ss_nested_1");
+ e = step_out ();
+ assert_location (e, "ss_nested");
+ // Check that step over steps over nested calls
+ e = step_over ();
+ assert_location (e, "ss_nested");
+ e = step_into ();
+ assert_location (e, "ss_nested_3");
+ req.Disable ();
+
+ // Check DebuggerStepThrough support
+ e = run_until ("ss_step_through");
+ req = create_step (e);
+ req.Filter = StepFilter.DebuggerStepThrough;
+ e = step_into ();
+ // Step through step_through_1 ()
+ e = step_into ();
+ assert_location (e, "ss_step_through");
+ // Step through StepThroughClass.step_through_2 ()
+ e = step_into ();
+ assert_location (e, "ss_step_through");
+ req.Disable ();
+ req.Filter = StepFilter.None;
+ e = step_into ();
+ assert_location (e, "step_through_3");
+ req.Disable ();
+
+ // Check that step-over doesn't stop at inner frames with recursive functions
+ e = run_until ("ss_recursive");
+ req = create_step (e);
+ e = step_over ();
+ e = step_over ();
+ e = step_over ();
+ var f = e.Thread.GetFrames () [0];
+ assert_location (e, "ss_recursive");
+ AssertValue (1, f.GetValue (f.Method.GetLocal ("n")));
+ req.Disable ();
+
+ // Check that single stepping doesn't clobber fp values
+ e = run_until ("ss_fp_clobber");
+ req = create_step (e);
+ while (true) {
+ f = e.Thread.GetFrames ()[0];
+ e = step_into ();
+ if ((e as StepEvent).Method.Name == "ss_fp_clobber_2")
+ break;
+ e = step_into ();
+ }
+ f = e.Thread.GetFrames ()[0];
+ AssertValue (7.0, f.GetValue (f.Method.GetParameters ()[0]));
+ req.Disable ();
}
[Test]
t = frame.Method.GetParameters ()[8].ParameterType;
Assert.AreEqual ("Tests2", t.Name);
var attrs = t.GetCustomAttributes (true);
- Assert.AreEqual (3, attrs.Length);
+ Assert.AreEqual (5, attrs.Length);
foreach (var attr in attrs) {
if (attr.Constructor.DeclaringType.Name == "DebuggerDisplayAttribute") {
Assert.AreEqual (1, attr.ConstructorArguments.Count);
Assert.AreEqual (2, attr.NamedArguments.Count);
Assert.AreEqual ("afield", attr.NamedArguments [0].Field.Name);
Assert.AreEqual ("bfield", attr.NamedArguments [1].Field.Name);
+ } else if (attr.Constructor.DeclaringType.Name == "ClassInterfaceAttribute") {
+ // inherited from System.Object
+ //} else if (attr.Constructor.DeclaringType.Name == "Serializable") {
+ // inherited from System.Object
+ } else if (attr.Constructor.DeclaringType.Name == "ComVisibleAttribute") {
+ // inherited from System.Object
} else {
Assert.Fail (attr.Constructor.DeclaringType.Name);
}
Assert.AreEqual ("AStruct", s.Type.Name);
AssertValue (42, s ["i"]);
+ // Check decoding of nested structs (#14942)
+ obj = o.GetValue (o.Type.GetField ("nested_struct"));
+ o.SetValue (o.Type.GetField ("nested_struct"), obj);
+
+ // Check round tripping of boxed struct fields (#12354)
+ obj = o.GetValue (o.Type.GetField ("boxed_struct_field"));
+ o.SetValue (o.Type.GetField ("boxed_struct_field"), obj);
+ obj = o.GetValue (o.Type.GetField ("boxed_struct_field"));
+ s = obj as StructMirror;
+ AssertValue (1, s ["key"]);
+ obj = s ["value"];
+ Assert.IsTrue (obj is StructMirror);
+ s = obj as StructMirror;
+ AssertValue (42, s ["m_value"]);
+
// vtypes as arguments
s = frame.GetArgument (0) as StructMirror;
AssertValue (44, s ["i"]);
// this on vtype methods
e = run_until ("vtypes2");
-
- // Skip nop
- e = single_step (e.Thread);
-
- e = single_step (e.Thread);
+ e = step_until (e.Thread, "foo");
frame = e.Thread.GetFrames () [0];
// this on static vtype methods
e = run_until ("vtypes3");
-
- // Skip nop
- e = single_step (e.Thread);
-
- e = single_step (e.Thread);
+ e = step_until (e.Thread, "static_foo");
frame = e.Thread.GetFrames () [0];
StackFrame frame = e.Thread.GetFrames () [0];
var locals = frame.Method.GetLocals ();
- Assert.AreEqual (7, locals.Length);
- for (int i = 0; i < 7; ++i) {
+ Assert.AreEqual (8, locals.Length);
+ for (int i = 0; i < 8; ++i) {
if (locals [i].Name == "args") {
Assert.IsTrue (locals [i].IsArg);
Assert.AreEqual ("String[]", locals [i].Type.Name);
} else if (locals [i].Name == "rs") {
Assert.IsTrue (locals [i].IsArg);
Assert.AreEqual ("String", locals [i].Type.Name);
+ } else if (locals [i].Name == "astruct") {
} else {
Assert.Fail ();
}
return e;
}
+ Event step_into () {
+ step_req.Disable ();
+ step_req.Depth = StepDepth.Into;
+ step_req.Enable ();
+ return step_once ();
+ }
+
+ Event step_over () {
+ step_req.Disable ();
+ step_req.Depth = StepDepth.Over;
+ step_req.Enable ();
+ return step_once ();
+ }
+
+ Event step_out () {
+ step_req.Disable ();
+ step_req.Depth = StepDepth.Out;
+ step_req.Enable ();
+ return step_once ();
+ }
+
[Test]
public void Locals () {
var be = run_until ("locals1");
object val = frame.GetValue (frame.Method.GetLocal ("i"));
AssertValue (0, val);
- var req = vm.CreateStepRequest (be.Thread);
+ var req = create_step (be);
req.Enable ();
- step_req = req;
// Skip nop
step_once ();
});
req.Disable ();
+
+ // gsharedvt
+ be = run_until ("locals7");
+
+ req = create_step (be);
+ req.Enable ();
+
+ // Skip nop
+ e = step_once ();
+
+ // Test that locals are initialized
+ frame = e.Thread.GetFrames () [0];
+ val = frame.GetValue (frame.Method.GetLocal ("t"));
+ AssertValue (0, val);
+
+ // Execute t = arg
+ e = step_once ();
+ Assert.AreEqual ("locals7", (e as StepEvent).Method.Name);
+
+ // Execute t2 = t
+ e = step_once ();
+ Assert.AreEqual ("locals7", (e as StepEvent).Method.Name);
+
+ frame = e.Thread.GetFrames () [0];
+ val = frame.GetValue (frame.Method.GetParameters ()[0]);
+ AssertValue (22, val);
+ val = frame.GetValue (frame.Method.GetLocal ("t"));
+ AssertValue (22, val);
+ val = frame.GetValue (frame.Method.GetLocal ("t2"));
+ AssertValue (22, val);
}
[Test]
var e = GetNextEvent ();
Assert.IsInstanceOfType (typeof (VMDeathEvent), e);
+ Assert.AreEqual (5, (e as VMDeathEvent).ExitCode);
+
var p = vm.Process;
/* Could be a remote vm with no process */
if (p != null) {
// FIXME: Merge this with LineNumbers () when its fixed
- step_req = vm.CreateStepRequest (e.Thread);
+ step_req = create_step (e);
step_req.Depth = StepDepth.Into;
step_req.Enable ();
Location l;
- vm.Resume ();
+ while (true) {
+ vm.Resume ();
+
+ e = GetNextEvent ();
+ Assert.IsTrue (e is StepEvent);
+ if (e.Thread.GetFrames ()[0].Method.Name == "ln1")
+ break;
+ }
+ // Do an additional step over so we are not on the beginning line of the method
+ step_req.Disable ();
+ step_req.Depth = StepDepth.Over;
+ step_req.Enable ();
+ vm.Resume ();
e = GetNextEvent ();
- Assert.IsTrue (e is StepEvent);
+ Assert.IsTrue (e is StepEvent);
l = e.Thread.GetFrames ()[0].Location;
public void LineNumbers () {
Event e = run_until ("line_numbers");
- step_req = vm.CreateStepRequest (e.Thread);
+ step_req = create_step (e);
step_req.Depth = StepDepth.Into;
step_req.Enable ();
Assert.IsInstanceOfType (typeof (ObjectMirror), v);
Assert.AreEqual ("Tests", (v as ObjectMirror).Type.Name);
+ // interface method
+ var cl1 = frame.Method.DeclaringType.Assembly.GetType ("ITest2");
+ m = cl1.GetMethod ("invoke_iface");
+ v = this_obj.InvokeMethod (e.Thread, m, null);
+ AssertValue (42, v);
+
+#if NET_4_5
+ // instance
+ m = t.GetMethod ("invoke_pass_ref");
+ var task = this_obj.InvokeMethodAsync (e.Thread, m, new Value [] { vm.RootDomain.CreateString ("ABC") });
+ AssertValue ("ABC", task.Result);
+
+ // static
+ m = t.GetMethod ("invoke_static_pass_ref");
+ task = t.InvokeMethodAsync (e.Thread, m, new Value [] { vm.RootDomain.CreateString ("ABC") });
+ AssertValue ("ABC", task.Result);
+#endif
+
// Argument checking
// null thread
while (invoke_results.Count < 2) {
Thread.Sleep (100);
}
- AssertValue ("ABC", invoke_results [0]);
- AssertValue (42, invoke_results [1]);
+ if (invoke_results [0] is PrimitiveValue) {
+ AssertValue ("ABC", invoke_results [1]);
+ AssertValue (42, invoke_results [0]);
+ } else {
+ AssertValue ("ABC", invoke_results [0]);
+ AssertValue (42, invoke_results [1]);
+ }
}
void invoke_multiple_cb (IAsyncResult ar) {
frame.SetValue (p, vm.RootDomain.CreateString ("DEF2"));
AssertValue ("DEF2", frame.GetValue (p));
+ // byref struct
+ p = frame.Method.GetParameters ()[4];
+ var v = frame.GetValue (p) as StructMirror;
+ v ["i"] = vm.CreateValue (43);
+ frame.SetValue (p, v);
+ v = frame.GetValue (p) as StructMirror;
+ AssertValue (43, v ["i"]);
+
// argument checking
// variable null
Assert.IsNull (v);
// Try a single step after the invoke
- var req = vm.CreateStepRequest (e.Thread);
+ var req = create_step (e);
req.Depth = StepDepth.Into;
req.Size = StepSize.Line;
req.Enable ();
- step_req = req;
-
// Skip nop
step_once ();
Assert.AreEqual ("OverflowException", (e as ExceptionEvent).Exception.Type.Name);
req.Disable ();
+ // no subclasses
+ req.IncludeSubclasses = false;
+ req.Enable ();
+
+ vm.Resume ();
+
+ e = GetNextEvent ();
+ Assert.IsInstanceOfType (typeof (ExceptionEvent), e);
+ Assert.AreEqual ("Exception", (e as ExceptionEvent).Exception.Type.Name);
+ req.Disable ();
+
// Implicit exceptions
req = vm.CreateExceptionRequest (null);
req.Enable ();
Assert.AreEqual ("exceptions2", frames [0].Method.Name);
req.Disable ();
- var sreq = vm.CreateStepRequest (e.Thread);
+ var sreq = create_step (e);
sreq.Depth = StepDepth.Over;
sreq.Size = StepSize.Line;
sreq.Enable ();
e = GetNextEvent ();
Assert.IsTrue (e is BreakpointEvent);
- var req = vm.CreateStepRequest (e.Thread);
+ var req = create_step (e);
req.Depth = StepDepth.Over;
req.Size = StepSize.Line;
req.Enable ();
entry_point.DeclaringType.GetMethod ("Main").MakeGenericMethod (new TypeMirror [] { intm });
});
}
+
+ [Test]
+ public void InspectThreadSuspenedOnWaitOne () {
+ TearDown ();
+ Start (true, "dtest-app.exe", "wait-one" );
+
+ ThreadMirror.NativeTransitions = true;
+
+ var evt = run_until ("wait_one");
+ Assert.IsNotNull (evt, "#1");
+
+ var thread = evt.Thread;
+ Assert.AreEqual (ThreadState.Running, thread.ThreadState, "#1.1");
+
+ var frames = thread.GetFrames ();
+ Assert.IsNotNull (frames, "#2");
+ Assert.AreEqual (2, frames.Length, "#3");
+ Assert.AreEqual ("wait_one", frames [0].Method.Name, "#4");
+ Assert.AreEqual ("Main", frames [1].Method.Name, "#5");
+
+ vm.Resume ();
+
+ Thread.Sleep (500); //FIXME this is racy, maybe single step? or something?
+
+ vm.Suspend ();
+ Assert.AreEqual (ThreadState.WaitSleepJoin, thread.ThreadState, "#6");
+
+ frames = thread.GetFrames ();
+ Assert.AreEqual (4, frames.Length, "#7");
+ Assert.AreEqual ("WaitOne_internal", frames [0].Method.Name, "#8");
+ Assert.AreEqual ("WaitOne", frames [1].Method.Name, "#8.1");
+ Assert.AreEqual ("wait_one", frames [2].Method.Name, "#9");
+ Assert.AreEqual ("Main", frames [3].Method.Name, "#10");
+
+
+ var frame = frames [0];
+ Assert.IsTrue (frame.IsNativeTransition, "#11.1");
+ try {
+ frame.GetThis ();
+ Assert.Fail ("Known limitation - can't get info from m2n frames");
+ } catch (AbsentInformationException) {}
+
+ frame = frames [1];
+ Assert.IsFalse (frame.IsNativeTransition, "#12.1");
+ var wait_one_this = frame.GetThis ();
+ Assert.IsNotNull (wait_one_this, "#12.2");
+
+ frame = frames [2];
+ var locals = frame.GetVisibleVariables ();
+ Assert.AreEqual (1, locals.Count, "#13.1");
+
+ var local_0 = frame.GetValue (locals [0]);
+ Assert.IsNotNull (local_0, "#13.2");
+
+ Assert.AreEqual (wait_one_this, local_0, "#14.2");
+ }
}
}