Jo Shields a575963da9 Imported Upstream version 3.6.0
Former-commit-id: da6be194a6b1221998fc28233f2503bd61dd9d14
2014-08-13 10:39:27 +01:00

3527 lines
96 KiB
C#

using System;
using System.Collections.Generic;
using System.Threading;
using System.Net;
using System.Reflection;
using System.Text;
using Mono.Cecil.Cil;
using Mono.Debugger.Soft;
using Diag = System.Diagnostics;
using System.Linq;
using System.IO;
using System.Security.Cryptography;
using NUnit.Framework;
#pragma warning disable 0219
namespace MonoTests
{
[TestFixture]
public class DebuggerTests
{
VirtualMachine vm;
MethodMirror entry_point;
StepEventRequest step_req;
bool forceExit;
void AssertThrows<ExType> (Action del) where ExType : Exception {
bool thrown = false;
try {
del ();
} catch (ExType) {
thrown = true;
}
Assert.IsTrue (thrown);
}
// No other way to pass arguments to the tests ?
public static bool listening = Environment.GetEnvironmentVariable ("DBG_SUSPEND") != null;
public static string runtime = Environment.GetEnvironmentVariable ("DBG_RUNTIME");
public static string agent_args = Environment.GetEnvironmentVariable ("DBG_AGENT_ARGS");
Event GetNextEvent () {
var es = vm.GetNextEventSet ();
Assert.AreEqual (1, es.Events.Length);
return es [0];
}
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 ();
if (runtime != null)
pi.FileName = runtime;
else
pi.FileName = "mono";
pi.Arguments = String.Join (" ", args);
vm = VirtualMachineManager.Launch (pi, new LaunchOptions { AgentArgs = agent_args });
} else {
var ep = new IPEndPoint (IPAddress.Any, 10000);
Console.WriteLine ("Listening on " + ep + "...");
vm = VirtualMachineManager.Listen (ep);
}
var load_req = vm.CreateAssemblyLoadRequest ();
load_req.Enable ();
Event vmstart = GetNextEvent ();
Assert.AreEqual (EventType.VMStart, vmstart.EventType);
vm.Resume ();
entry_point = null;
step_req = null;
Event e;
/* Find out the entry point */
while (true) {
e = GetNextEvent ();
if (e is AssemblyLoadEvent) {
AssemblyLoadEvent ae = (AssemblyLoadEvent)e;
entry_point = ae.Assembly.EntryPoint;
if (entry_point != null)
break;
}
vm.Resume ();
}
load_req.Disable ();
}
BreakpointEvent run_until (string name) {
// String
MethodMirror m = entry_point.DeclaringType.GetMethod (name);
Assert.IsNotNull (m);
//Console.WriteLine ("X: " + name + " " + m.ILOffsets.Count + " " + m.Locations.Count);
var req = vm.SetBreakpoint (m, m.ILOffsets [0]);
Event e = null;
while (true) {
vm.Resume ();
e = GetNextEvent ();
if (e is BreakpointEvent)
break;
}
req.Disable ();
Assert.IsInstanceOfType (typeof (BreakpointEvent), e);
Assert.AreEqual (m.Name, (e as BreakpointEvent).Method.Name);
return (e as BreakpointEvent);
}
Event single_step (ThreadMirror t) {
var req = vm.CreateStepRequest (t);
req.Enable ();
vm.Resume ();
Event e = GetNextEvent ();
Assert.IsTrue (e is StepEvent);
req.Disable ();
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);
object v = (val as PrimitiveValue).Value;
Assert.AreEqual (type, v.GetType ());
if (eval is float)
Assert.IsTrue (Math.Abs ((float)eval - (float)v) < 0.0001);
else if (eval is double)
Assert.IsTrue (Math.Abs ((double)eval - (double)v) < 0.0001);
else
Assert.AreEqual (eval, v);
}
void AssertValue (object expected, object val) {
if (expected is string) {
Assert.IsTrue (val is StringMirror);
Assert.AreEqual (expected, (val as StringMirror).Value);
} else if (val is StructMirror && (val as StructMirror).Type.Name == "IntPtr") {
AssertValue (expected, (val as StructMirror).Fields [0]);
} else {
Assert.IsTrue (val is PrimitiveValue);
Assert.AreEqual (expected, (val as PrimitiveValue).Value);
}
}
[SetUp]
public void SetUp () {
ThreadMirror.NativeTransitions = false;
Start (new string [] { "dtest-app.exe" });
}
[TearDown]
public void TearDown () {
if (vm == null)
return;
if (step_req != null)
step_req.Disable ();
vm.Resume ();
if (forceExit)
vm.Exit (0);
while (true) {
Event e = GetNextEvent ();
if (e is VMDeathEvent)
break;
vm.Resume ();
}
vm = null;
}
[Test]
public void SimpleBreakpoint () {
Event e;
MethodMirror m = entry_point.DeclaringType.GetMethod ("bp1");
Assert.IsNotNull (m);
vm.SetBreakpoint (m, 0);
vm.Resume ();
e = GetNextEvent ();
Assert.AreEqual (EventType.Breakpoint, e.EventType);
Assert.IsTrue (e is BreakpointEvent);
Assert.AreEqual (m.Name, (e as BreakpointEvent).Method.Name);
// Argument checking
AssertThrows<ArgumentException> (delegate {
// Invalid IL offset
vm.SetBreakpoint (m, 2);
});
}
[Test]
public void BreakpointsSameLocation () {
MethodMirror m = entry_point.DeclaringType.GetMethod ("bp2");
Assert.IsNotNull (m);
vm.SetBreakpoint (m, 0);
vm.SetBreakpoint (m, 0);
vm.Resume ();
var es = vm.GetNextEventSet ();
Assert.AreEqual (2, es.Events.Length);
Assert.IsTrue (es [0] is BreakpointEvent);
Assert.AreEqual (m, (es [0] as BreakpointEvent).Method);
Assert.IsTrue (es [1] is BreakpointEvent);
Assert.AreEqual (m.Name, (es [1] as BreakpointEvent).Method.Name);
}
[Test]
public void BreakpointAlreadyJITted () {
Event e = run_until ("bp1");
/* Place a breakpoint on bp3 */
MethodMirror m = entry_point.DeclaringType.GetMethod ("bp3");
Assert.IsNotNull (m);
vm.SetBreakpoint (m, 0);
/* Same with generic instances */
MethodMirror m2 = entry_point.DeclaringType.GetMethod ("bp7");
Assert.IsNotNull (m2);
vm.SetBreakpoint (m2, 0);
vm.Resume ();
e = GetNextEvent ();
Assert.AreEqual (EventType.Breakpoint, e.EventType);
Assert.AreEqual (m.Name, (e as BreakpointEvent).Method.Name);
vm.Resume ();
/* Non-shared instance */
e = GetNextEvent ();
Assert.AreEqual (EventType.Breakpoint, e.EventType);
Assert.AreEqual (m2.Name, (e as BreakpointEvent).Method.Name);
vm.Resume ();
/* Shared instance */
e = GetNextEvent ();
Assert.AreEqual (EventType.Breakpoint, e.EventType);
Assert.AreEqual (m2.Name, (e as BreakpointEvent).Method.Name);
}
[Test]
public void ClearBreakpoint () {
Event e;
MethodMirror m = entry_point.DeclaringType.GetMethod ("bp4");
Assert.IsNotNull (m);
EventRequest req1 = vm.SetBreakpoint (m, 0);
EventRequest req2 = vm.SetBreakpoint (m, 0);
MethodMirror m2 = entry_point.DeclaringType.GetMethod ("bp5");
Assert.IsNotNull (m2);
vm.SetBreakpoint (m2, 0);
/* Run until bp4 */
vm.Resume ();
var es = vm.GetNextEventSet ();
Assert.AreEqual (2, es.Events.Length);
Assert.AreEqual (EventType.Breakpoint, es [0].EventType);
Assert.AreEqual (m.Name, (es [0] as BreakpointEvent).Method.Name);
Assert.AreEqual (EventType.Breakpoint, es [1].EventType);
Assert.AreEqual (m.Name, (es [1] as BreakpointEvent).Method.Name);
/* Clear one of them */
req1.Disable ();
vm.Resume ();
e = GetNextEvent ();
Assert.AreEqual (EventType.Breakpoint, e.EventType);
Assert.AreEqual (m.Name, (e as BreakpointEvent).Method.Name);
/* Clear the other */
req2.Disable ();
vm.Resume ();
e = GetNextEvent ();
Assert.AreEqual (EventType.Breakpoint, e.EventType);
Assert.AreEqual (m2.Name, (e as BreakpointEvent).Method.Name);
}
[Test]
public void ClearAllBreakpoints () {
Event e;
MethodMirror m = entry_point.DeclaringType.GetMethod ("bp4");
Assert.IsNotNull (m);
vm.SetBreakpoint (m, 0);
MethodMirror m2 = entry_point.DeclaringType.GetMethod ("bp5");
Assert.IsNotNull (m2);
vm.SetBreakpoint (m2, 0);
vm.ClearAllBreakpoints ();
vm.Resume ();
e = GetNextEvent ();
Assert.IsTrue (!(e is BreakpointEvent));
if (e is VMDeathEvent)
vm = null;
}
[Test]
public void BreakpointOnGShared () {
Event e;
MethodMirror m = entry_point.DeclaringType.GetMethod ("bp6");
Assert.IsNotNull (m);
vm.SetBreakpoint (m, 0);
vm.Resume ();
e = GetNextEvent ();
Assert.AreEqual (EventType.Breakpoint, e.EventType);
Assert.IsTrue (e is BreakpointEvent);
Assert.AreEqual (m.Name, (e as BreakpointEvent).Method.Name);
// Breakpoint on an open generic method of a closed generic class (#3422)
var frame = e.Thread.GetFrames ()[0];
var ginst = frame.GetValue (frame.Method.GetLocal ("gc"));
var m2 = (ginst as ObjectMirror).Type.GetMethod ("bp");
vm.SetBreakpoint (m2, 0);
vm.Resume ();
e = GetNextEvent ();
Assert.AreEqual (EventType.Breakpoint, e.EventType);
Assert.IsTrue (e is BreakpointEvent);
Assert.AreEqual (m2.Name, (e as BreakpointEvent).Method.Name);
}
void assert_location (Event e, string method) {
Assert.IsTrue (e is StepEvent);
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 = create_step (e);
req.Enable ();
// Step over 'bool b = true'
e = step_once ();
assert_location (e, "single_stepping");
// Skip nop
step_once ();
// Step into ss1
e = step_once ();
assert_location (e, "ss1");
// Skip }
e = step_once ();
// Step out of ss1
e = step_once ();
assert_location (e, "single_stepping");
// Step over ss2
e = step_over ();
assert_location (e, "single_stepping");
// Step into ss3
e = step_into ();
assert_location (e, "ss3");
// Step back into single_stepping
e = step_out ();
assert_location (e, "single_stepping");
// Step into ss3_2 ()
e = step_into ();
assert_location (e, "ss3_2");
// Step over ss3_2_2 ()
e = step_over ();
assert_location (e, "ss3_2");
// Recreate the request
req.Disable ();
req.Enable ();
// Skip }
e = step_once ();
// Step back into single_stepping () with the new request
e = step_once ();
assert_location (e, "single_stepping");
// Step into ss4 ()
e = step_into ();
assert_location (e, "ss4");
// Skip nop
e = step_once ();
// Change to StepSize.Line
req.Disable ();
req.Depth = StepDepth.Over;
req.Size = StepSize.Line;
req.Enable ();
// Step over ss1 (); ss1 ();
e = step_once ();
// Step into ss2 ()
req.Disable ();
req.Depth = StepDepth.Into;
req.Enable ();
e = step_once ();
assert_location (e, "ss2");
req.Disable ();
// Run until ss5
e = run_until ("ss5");
// Add an assembly filter
req.AssemblyFilter = new AssemblyMirror [] { (e as BreakpointEvent).Method.DeclaringType.Assembly };
req.Enable ();
// Skip nop
e = step_once ();
// Step into is_even, skipping the linq stuff
e = step_once ();
assert_location (e, "is_even");
// FIXME: Check that single stepping works with lock (obj)
req.Disable ();
// Run until ss6
e = run_until ("ss6");
req = create_step (e);
req.Depth = StepDepth.Over;
req.Enable ();
// Check that single stepping works in out-of-line bblocks
e = step_once ();
e = step_once ();
assert_location (e, "ss6");
req.Disable ();
// Check that a step over stops at an EH clause
e = run_until ("ss7_2");
req = create_step (e);
req.Depth = StepDepth.Out;
req.Enable ();
e = step_once ();
assert_location (e, "ss7");
req.Disable ();
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 DebuggerNonUserCode support
e = run_until ("ss_non_user_code");
req = create_step (e);
req.Filter = StepFilter.DebuggerNonUserCode;
e = step_into ();
// Step through non_user_code_1 ()
e = step_into ();
assert_location (e, "ss_non_user_code");
// Step through StepThroughClass.non_user_code_2 ()
e = step_into ();
assert_location (e, "ss_non_user_code");
req.Disable ();
req.Filter = StepFilter.None;
e = step_into ();
assert_location (e, "non_user_code_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]
public void MethodEntryExit () {
run_until ("single_stepping");
var req1 = vm.CreateMethodEntryRequest ();
var req2 = vm.CreateMethodExitRequest ();
req1.Enable ();
req2.Enable ();
vm.Resume ();
Event e = GetNextEvent ();
Assert.IsTrue (e is MethodEntryEvent);
Assert.AreEqual ("ss1", (e as MethodEntryEvent).Method.Name);
vm.Resume ();
e = GetNextEvent ();
Assert.IsTrue (e is MethodExitEvent);
Assert.AreEqual ("ss1", (e as MethodExitEvent).Method.Name);
req1.Disable ();
req2.Disable ();
}
[Test]
public void CountFilter () {
run_until ("single_stepping");
MethodMirror m2 = entry_point.DeclaringType.GetMethod ("ss3");
Assert.IsNotNull (m2);
vm.SetBreakpoint (m2, 0);
var req1 = vm.CreateMethodEntryRequest ();
req1.Count = 2;
req1.Enable ();
// Enter ss2, ss1 is skipped
vm.Resume ();
Event e = GetNextEvent ();
Assert.IsTrue (e is MethodEntryEvent);
Assert.AreEqual ("ss2", (e as MethodEntryEvent).Method.Name);
// Breakpoint on ss3, the entry event is no longer reported
vm.Resume ();
e = GetNextEvent ();
Assert.IsTrue (e is BreakpointEvent);
req1.Disable ();
}
[Test]
public void Arguments () {
object val;
var e = run_until ("arg1");
StackFrame frame = e.Thread.GetFrames () [0];
check_arg_val (frame, 0, typeof (sbyte), SByte.MaxValue - 5);
check_arg_val (frame, 1, typeof (byte), Byte.MaxValue - 5);
check_arg_val (frame, 2, typeof (bool), true);
check_arg_val (frame, 3, typeof (short), Int16.MaxValue - 5);
check_arg_val (frame, 4, typeof (ushort), UInt16.MaxValue - 5);
check_arg_val (frame, 5, typeof (char), 'F');
check_arg_val (frame, 6, typeof (int), Int32.MaxValue - 5);
check_arg_val (frame, 7, typeof (uint), UInt32.MaxValue - 5);
check_arg_val (frame, 8, typeof (long), Int64.MaxValue - 5);
check_arg_val (frame, 9, typeof (ulong), UInt64.MaxValue - 5);
check_arg_val (frame, 10, typeof (float), 1.2345f);
check_arg_val (frame, 11, typeof (double), 6.78910);
e = run_until ("arg2");
frame = e.Thread.GetFrames () [0];
// String
val = frame.GetArgument (0);
AssertValue ("FOO", val);
Assert.AreEqual ("String", (val as ObjectMirror).Type.Name);
// null
val = frame.GetArgument (1);
AssertValue (null, val);
// object
val = frame.GetArgument (2);
AssertValue ("BLA", val);
// byref
val = frame.GetArgument (3);
AssertValue (42, val);
// generic instance
val = frame.GetArgument (4);
Assert.IsTrue (val is ObjectMirror);
Assert.AreEqual ("GClass`1", (val as ObjectMirror).Type.Name);
// System.Object
val = frame.GetArgument (5);
Assert.IsTrue (val is ObjectMirror);
Assert.AreEqual ("Object", (val as ObjectMirror).Type.Name);
// this on static methods
val = frame.GetThis ();
AssertValue (null, val);
e = run_until ("arg3");
frame = e.Thread.GetFrames () [0];
// this
val = frame.GetThis ();
Assert.IsTrue (val is ObjectMirror);
Assert.AreEqual ("Tests", (val as ObjectMirror).Type.Name);
// objref in register
val = frame.GetArgument (0);
AssertValue ("BLA", val);
}
[Test]
public void Arrays () {
object val;
var e = run_until ("o2");
StackFrame frame = e.Thread.GetFrames () [0];
// String[]
val = frame.GetArgument (0);
Assert.IsTrue (val is ArrayMirror);
ArrayMirror arr = val as ArrayMirror;
Assert.AreEqual (2, arr.Length);
AssertValue ("BAR", arr [0]);
AssertValue ("BAZ", arr [1]);
var vals = arr.GetValues (0, 2);
Assert.AreEqual (2, vals.Count);
AssertValue ("BAR", vals [0]);
AssertValue ("BAZ", vals [1]);
arr [0] = vm.RootDomain.CreateString ("ABC");
AssertValue ("ABC", arr [0]);
arr [0] = vm.CreateValue (null);
AssertValue (null, arr [0]);
arr.SetValues (0, new Value [] { vm.RootDomain.CreateString ("D1"), vm.RootDomain.CreateString ("D2") });
AssertValue ("D1", arr [0]);
AssertValue ("D2", arr [1]);
// int
val = frame.GetArgument (1);
Assert.IsTrue (val is ArrayMirror);
arr = val as ArrayMirror;
Assert.AreEqual (2, arr.Length);
AssertValue (42, arr [0]);
AssertValue (43, arr [1]);
// Argument checking
AssertThrows<IndexOutOfRangeException> (delegate () {
val = arr [2];
});
AssertThrows<IndexOutOfRangeException> (delegate () {
val = arr [Int32.MinValue];
});
AssertThrows<IndexOutOfRangeException> (delegate () {
vals = arr.GetValues (0, 3);
});
AssertThrows<IndexOutOfRangeException> (delegate () {
arr [2] = vm.CreateValue (null);
});
AssertThrows<IndexOutOfRangeException> (delegate () {
arr [Int32.MinValue] = vm.CreateValue (null);
});
AssertThrows<IndexOutOfRangeException> (delegate () {
arr.SetValues (0, new Value [] { null, null, null });
});
// Multidim arrays
val = frame.GetArgument (2);
Assert.IsTrue (val is ArrayMirror);
arr = val as ArrayMirror;
Assert.AreEqual (2, arr.Rank);
Assert.AreEqual (4, arr.Length);
Assert.AreEqual (2, arr.GetLength (0));
Assert.AreEqual (2, arr.GetLength (1));
Assert.AreEqual (0, arr.GetLowerBound (0));
Assert.AreEqual (0, arr.GetLowerBound (1));
vals = arr.GetValues (0, 4);
AssertValue (1, vals [0]);
AssertValue (2, vals [1]);
AssertValue (3, vals [2]);
AssertValue (4, vals [3]);
val = frame.GetArgument (3);
Assert.IsTrue (val is ArrayMirror);
arr = val as ArrayMirror;
Assert.AreEqual (2, arr.Rank);
Assert.AreEqual (4, arr.Length);
Assert.AreEqual (2, arr.GetLength (0));
Assert.AreEqual (2, arr.GetLength (1));
Assert.AreEqual (1, arr.GetLowerBound (0));
Assert.AreEqual (3, arr.GetLowerBound (1));
AssertThrows<ArgumentOutOfRangeException> (delegate () {
arr.GetLength (-1);
});
AssertThrows<ArgumentOutOfRangeException> (delegate () {
arr.GetLength (2);
});
AssertThrows<ArgumentOutOfRangeException> (delegate () {
arr.GetLowerBound (-1);
});
AssertThrows<ArgumentOutOfRangeException> (delegate () {
arr.GetLowerBound (2);
});
// arrays treated as generic collections
val = frame.GetArgument (4);
Assert.IsTrue (val is ArrayMirror);
arr = val as ArrayMirror;
}
[Test]
public void Object_GetValue () {
var e = run_until ("o1");
var frame = e.Thread.GetFrames () [0];
object val = frame.GetThis ();
Assert.IsTrue (val is ObjectMirror);
Assert.AreEqual ("Tests", (val as ObjectMirror).Type.Name);
ObjectMirror o = (val as ObjectMirror);
TypeMirror t = o.Type;
// object fields
object f = o.GetValue (t.GetField ("field_i"));
AssertValue (42, f);
f = o.GetValue (t.GetField ("field_s"));
AssertValue ("S", f);
f = o.GetValue (t.GetField ("field_enum"));
Assert.IsTrue (f is EnumMirror);
Assert.AreEqual (1, (f as EnumMirror).Value);
Assert.AreEqual ("B", (f as EnumMirror).StringValue);
// Inherited object fields
TypeMirror parent = t.BaseType;
f = o.GetValue (parent.GetField ("base_field_i"));
AssertValue (43, f);
f = o.GetValue (parent.GetField ("base_field_s"));
AssertValue ("T", f);
// Static fields
f = o.GetValue (o.Type.GetField ("static_i"));
AssertValue (55, f);
// generic instances
ObjectMirror o2 = frame.GetValue (frame.Method.GetParameters ()[1]) as ObjectMirror;
Assert.AreEqual ("GClass`1", o2.Type.Name);
TypeMirror t2 = o2.Type;
f = o2.GetValue (t2.GetField ("field"));
AssertValue (42, f);
ObjectMirror o3 = frame.GetValue (frame.Method.GetParameters ()[2]) as ObjectMirror;
Assert.AreEqual ("GClass`1", o3.Type.Name);
TypeMirror t3 = o3.Type;
f = o3.GetValue (t3.GetField ("field"));
AssertValue ("FOO", f);
// Argument checking
AssertThrows<ArgumentNullException> (delegate () {
o.GetValue (null);
});
}
[Test]
public void Object_GetValues () {
var e = run_until ("o1");
var frame = e.Thread.GetFrames () [0];
object val = frame.GetThis ();
Assert.IsTrue (val is ObjectMirror);
Assert.AreEqual ("Tests", (val as ObjectMirror).Type.Name);
ObjectMirror o = (val as ObjectMirror);
ObjectMirror val2 = frame.GetValue (frame.Method.GetParameters ()[0]) as ObjectMirror;
TypeMirror t = o.Type;
object[] vals = o.GetValues (new FieldInfoMirror [] { t.GetField ("field_i"), t.GetField ("field_s") });
object f = vals [0];
AssertValue (42, f);
f = vals [1];
AssertValue ("S", f);
// Argument checking
AssertThrows<ArgumentNullException> (delegate () {
o.GetValues (null);
});
AssertThrows<ArgumentNullException> (delegate () {
o.GetValues (new FieldInfoMirror [] { null });
});
// field of another class
AssertThrows<ArgumentException> (delegate () {
o.GetValue (val2.Type.GetField ("field_j"));
});
}
void TestSetValue (ObjectMirror o, string field_name, object val) {
if (val is string)
o.SetValue (o.Type.GetField (field_name), vm.RootDomain.CreateString ((string)val));
else
o.SetValue (o.Type.GetField (field_name), vm.CreateValue (val));
Value f = o.GetValue (o.Type.GetField (field_name));
AssertValue (val, f);
}
[Test]
public void Object_SetValues () {
var e = run_until ("o1");
var frame = e.Thread.GetFrames () [0];
object val = frame.GetThis ();
Assert.IsTrue (val is ObjectMirror);
Assert.AreEqual ("Tests", (val as ObjectMirror).Type.Name);
ObjectMirror o = (val as ObjectMirror);
ObjectMirror val2 = frame.GetValue (frame.Method.GetParameters ()[0]) as ObjectMirror;
TestSetValue (o, "field_i", 22);
TestSetValue (o, "field_bool1", false);
TestSetValue (o, "field_bool2", true);
TestSetValue (o, "field_char", 'B');
TestSetValue (o, "field_byte", (byte)129);
TestSetValue (o, "field_sbyte", (sbyte)-33);
TestSetValue (o, "field_short", (short)(Int16.MaxValue - 5));
TestSetValue (o, "field_ushort", (ushort)(UInt16.MaxValue - 5));
TestSetValue (o, "field_long", Int64.MaxValue - 5);
TestSetValue (o, "field_ulong", (ulong)(UInt64.MaxValue - 5));
TestSetValue (o, "field_float", 6.28f);
TestSetValue (o, "field_double", 6.28);
TestSetValue (o, "static_i", 23);
TestSetValue (o, "field_s", "CDEF");
Value f;
// intptrs
f = o.GetValue (o.Type.GetField ("field_intptr"));
Assert.IsInstanceOfType (typeof (StructMirror), f);
AssertValue (Int32.MaxValue - 5, (f as StructMirror).Fields [0]);
// enums
FieldInfoMirror field = o.Type.GetField ("field_enum");
f = o.GetValue (field);
(f as EnumMirror).Value = 5;
o.SetValue (field, f);
f = o.GetValue (field);
Assert.AreEqual (5, (f as EnumMirror).Value);
// null
o.SetValue (o.Type.GetField ("field_s"), vm.CreateValue (null));
f = o.GetValue (o.Type.GetField ("field_s"));
AssertValue (null, f);
// vtype instances
field = o.Type.GetField ("generic_field_struct");
f = o.GetValue (field);
o.SetValue (field, f);
// nullables
field = o.Type.GetField ("field_nullable");
f = o.GetValue (field);
AssertValue (0, (f as StructMirror).Fields [0]);
AssertValue (false, (f as StructMirror).Fields [1]);
o.SetValue (field, vm.CreateValue (6));
f = o.GetValue (field);
AssertValue (6, (f as StructMirror).Fields [0]);
AssertValue (true, (f as StructMirror).Fields [1]);
o.SetValue (field, vm.CreateValue (null));
f = o.GetValue (field);
AssertValue (0, (f as StructMirror).Fields [0]);
AssertValue (false, (f as StructMirror).Fields [1]);
// Argument checking
AssertThrows<ArgumentNullException> (delegate () {
o.SetValues (null, new Value [0]);
});
AssertThrows<ArgumentNullException> (delegate () {
o.SetValues (new FieldInfoMirror [0], null);
});
AssertThrows<ArgumentNullException> (delegate () {
o.SetValues (new FieldInfoMirror [] { null }, new Value [1] { null });
});
// vtype with a wrong type
AssertThrows<ArgumentException> (delegate () {
o.SetValue (o.Type.GetField ("field_struct"), o.GetValue (o.Type.GetField ("field_enum")));
});
// reference type not assignment compatible
AssertThrows<ArgumentException> (delegate () {
o.SetValue (o.Type.GetField ("field_class"), o);
});
// field of another class
AssertThrows<ArgumentException> (delegate () {
o.SetValue (val2.Type.GetField ("field_j"), vm.CreateValue (1));
});
}
[Test]
public void Type_SetValue () {
var e = run_until ("o1");
var frame = e.Thread.GetFrames () [0];
Value f;
object val = frame.GetThis ();
Assert.IsTrue (val is ObjectMirror);
Assert.AreEqual ("Tests", (val as ObjectMirror).Type.Name);
ObjectMirror o = (val as ObjectMirror);
ObjectMirror val2 = frame.GetValue (frame.Method.GetParameters ()[0]) as ObjectMirror;
o.Type.SetValue (o.Type.GetField ("static_i"), vm.CreateValue (55));
f = o.Type.GetValue (o.Type.GetField ("static_i"));
AssertValue (55, f);
o.Type.SetValue (o.Type.GetField ("static_s"), vm.RootDomain.CreateString ("B"));
f = o.Type.GetValue (o.Type.GetField ("static_s"));
AssertValue ("B", f);
// Argument checking
AssertThrows<ArgumentNullException> (delegate () {
o.Type.SetValue (null, vm.CreateValue (0));
});
AssertThrows<ArgumentNullException> (delegate () {
o.Type.SetValue (o.Type.GetField ("static_i"), null);
});
// field of another class
AssertThrows<ArgumentException> (delegate () {
o.SetValue (val2.Type.GetField ("field_j"), vm.CreateValue (1));
});
}
[Test]
public void TypeInfo () {
Event e = run_until ("ti2");
StackFrame frame = e.Thread.GetFrames () [0];
TypeMirror t;
// Array types
t = frame.Method.GetParameters ()[0].ParameterType;
Assert.AreEqual ("String[]", t.Name);
Assert.AreEqual ("string[]", t.CSharpName);
Assert.AreEqual ("Array", t.BaseType.Name);
Assert.AreEqual (true, t.HasElementType);
Assert.AreEqual (true, t.IsArray);
Assert.AreEqual (1, t.GetArrayRank ());
Assert.AreEqual ("String", t.GetElementType ().Name);
t = frame.Method.GetParameters ()[2].ParameterType;
Assert.AreEqual ("Int32[,]", t.Name);
// FIXME:
//Assert.AreEqual ("int[,]", t.CSharpName);
Assert.AreEqual ("Array", t.BaseType.Name);
Assert.AreEqual (true, t.HasElementType);
Assert.AreEqual (true, t.IsArray);
Assert.AreEqual (2, t.GetArrayRank ());
Assert.AreEqual ("Int32", t.GetElementType ().Name);
// Byref types
t = frame.Method.GetParameters ()[3].ParameterType;
// FIXME:
//Assert.AreEqual ("Int32&", t.Name);
//Assert.AreEqual (true, t.IsByRef);
//Assert.AreEqual (true, t.HasElementType);
// Pointer types
t = frame.Method.GetParameters ()[4].ParameterType;
// FIXME:
//Assert.AreEqual ("Int32*", t.Name);
Assert.AreEqual (true, t.IsPointer);
Assert.AreEqual (true, t.HasElementType);
Assert.AreEqual ("Int32", t.GetElementType ().Name);
Assert.AreEqual (false, t.IsPrimitive);
// primitive types
t = frame.Method.GetParameters ()[5].ParameterType;
Assert.AreEqual (true, t.IsPrimitive);
// value types
t = frame.Method.GetParameters ()[6].ParameterType;
Assert.AreEqual ("AStruct", t.Name);
Assert.AreEqual (false, t.IsPrimitive);
Assert.AreEqual (true, t.IsValueType);
Assert.AreEqual (false, t.IsClass);
// reference types
t = frame.Method.GetParameters ()[7].ParameterType;
Assert.AreEqual ("Tests", t.Name);
var nested = (from nt in t.GetNestedTypes () where nt.IsNestedPublic select nt).ToArray ();
Assert.AreEqual (1, nested.Length);
Assert.AreEqual ("NestedClass", nested [0].Name);
Assert.IsTrue (t.BaseType.IsAssignableFrom (t));
Assert.IsTrue (!t.IsAssignableFrom (t.BaseType));
// generic instances
t = frame.Method.GetParameters ()[9].ParameterType;
Assert.AreEqual ("GClass`1", t.Name);
Assert.IsTrue (t.IsGenericType);
Assert.IsFalse (t.IsGenericTypeDefinition);
var args = t.GetGenericArguments ();
Assert.AreEqual (1, args.Length);
Assert.AreEqual ("Int32", args [0].Name);
// generic type definitions
var gtd = t.GetGenericTypeDefinition ();
Assert.AreEqual ("GClass`1", gtd.Name);
Assert.IsTrue (gtd.IsGenericType);
Assert.IsTrue (gtd.IsGenericTypeDefinition);
Assert.AreEqual (gtd, gtd.GetGenericTypeDefinition ());
args = gtd.GetGenericArguments ();
Assert.AreEqual (1, args.Length);
Assert.AreEqual ("T", args [0].Name);
// enums
t = frame.Method.GetParameters ()[10].ParameterType;
Assert.AreEqual ("AnEnum", t.Name);
Assert.IsTrue (t.IsEnum);
Assert.AreEqual ("Int32", t.EnumUnderlyingType.Name);
// properties
t = frame.Method.GetParameters ()[7].ParameterType;
var props = t.GetProperties ();
Assert.AreEqual (3, props.Length);
foreach (PropertyInfoMirror prop in props) {
ParameterInfoMirror[] indexes = prop.GetIndexParameters ();
if (prop.Name == "IntProperty") {
Assert.AreEqual ("Int32", prop.PropertyType.Name);
Assert.AreEqual ("get_IntProperty", prop.GetGetMethod ().Name);
Assert.AreEqual ("set_IntProperty", prop.GetSetMethod ().Name);
Assert.AreEqual (0, indexes.Length);
} else if (prop.Name == "ReadOnlyProperty") {
Assert.AreEqual ("Int32", prop.PropertyType.Name);
Assert.AreEqual ("get_ReadOnlyProperty", prop.GetGetMethod ().Name);
Assert.AreEqual (null, prop.GetSetMethod ());
Assert.AreEqual (0, indexes.Length);
} else if (prop.Name == "IndexedProperty") {
Assert.AreEqual (1, indexes.Length);
Assert.AreEqual ("Int32", indexes [0].ParameterType.Name);
}
}
// custom attributes
t = frame.Method.GetParameters ()[8].ParameterType;
Assert.AreEqual ("Tests2", t.Name);
var attrs = t.GetCustomAttributes (true);
Assert.AreEqual (5, attrs.Length);
foreach (var attr in attrs) {
if (attr.Constructor.DeclaringType.Name == "DebuggerDisplayAttribute") {
Assert.AreEqual (1, attr.ConstructorArguments.Count);
Assert.AreEqual ("Tests", attr.ConstructorArguments [0].Value);
Assert.AreEqual (2, attr.NamedArguments.Count);
Assert.AreEqual ("Name", attr.NamedArguments [0].Property.Name);
Assert.AreEqual ("FOO", attr.NamedArguments [0].TypedValue.Value);
Assert.AreEqual ("Target", attr.NamedArguments [1].Property.Name);
Assert.IsInstanceOfType (typeof (TypeMirror), attr.NamedArguments [1].TypedValue.Value);
Assert.AreEqual ("Int32", (attr.NamedArguments [1].TypedValue.Value as TypeMirror).Name);
} else if (attr.Constructor.DeclaringType.Name == "DebuggerTypeProxyAttribute") {
Assert.AreEqual (1, attr.ConstructorArguments.Count);
Assert.IsInstanceOfType (typeof (TypeMirror), attr.ConstructorArguments [0].Value);
Assert.AreEqual ("Tests", (attr.ConstructorArguments [0].Value as TypeMirror).Name);
} else if (attr.Constructor.DeclaringType.Name == "BAttribute") {
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);
}
}
var assembly = entry_point.DeclaringType.Assembly;
var type = assembly.GetType ("Tests4");
Assert.IsFalse (type.IsInitialized);
}
[Test]
public void FieldInfo () {
Event e = run_until ("ti2");
StackFrame frame = e.Thread.GetFrames () [0];
TypeMirror t;
t = frame.Method.GetParameters ()[8].ParameterType;
Assert.AreEqual ("Tests2", t.Name);
var fi = t.GetField ("field_j");
var attrs = fi.GetCustomAttributes (true);
Assert.AreEqual (1, attrs.Length);
var attr = attrs [0];
Assert.AreEqual ("DebuggerBrowsableAttribute", attr.Constructor.DeclaringType.Name);
Assert.AreEqual (1, attr.ConstructorArguments.Count);
Assert.IsInstanceOfType (typeof (EnumMirror), attr.ConstructorArguments [0].Value);
Assert.AreEqual ((int)System.Diagnostics.DebuggerBrowsableState.Collapsed, (attr.ConstructorArguments [0].Value as EnumMirror).Value);
}
[Test]
public void PropertyInfo () {
Event e = run_until ("ti2");
StackFrame frame = e.Thread.GetFrames () [0];
TypeMirror t;
t = frame.Method.GetParameters ()[8].ParameterType;
Assert.AreEqual ("Tests2", t.Name);
var pi = t.GetProperty ("AProperty");
var attrs = pi.GetCustomAttributes (true);
Assert.AreEqual (1, attrs.Length);
var attr = attrs [0];
Assert.AreEqual ("DebuggerBrowsableAttribute", attr.Constructor.DeclaringType.Name);
Assert.AreEqual (1, attr.ConstructorArguments.Count);
Assert.IsInstanceOfType (typeof (EnumMirror), attr.ConstructorArguments [0].Value);
Assert.AreEqual ((int)System.Diagnostics.DebuggerBrowsableState.Collapsed, (attr.ConstructorArguments [0].Value as EnumMirror).Value);
}
[Test]
[Category ("only5")]
public void Type_GetValue () {
Event e = run_until ("o1");
StackFrame frame = e.Thread.GetFrames () [0];
ObjectMirror o = (frame.GetThis () as ObjectMirror);
TypeMirror t = o.Type;
ObjectMirror val2 = frame.GetValue (frame.Method.GetParameters ()[0]) as ObjectMirror;
// static fields
object f = t.GetValue (o.Type.GetField ("static_i"));
AssertValue (55, f);
f = t.GetValue (o.Type.GetField ("static_s"));
AssertValue ("A", f);
// literal static fields
f = t.GetValue (o.Type.GetField ("literal_i"));
AssertValue (56, f);
f = t.GetValue (o.Type.GetField ("literal_s"));
AssertValue ("B", f);
// Inherited static fields
TypeMirror parent = t.BaseType;
f = t.GetValue (parent.GetField ("base_static_i"));
AssertValue (57, f);
f = t.GetValue (parent.GetField ("base_static_s"));
AssertValue ("C", f);
// thread static field
f = t.GetValue (t.GetField ("tls_i"), e.Thread);
AssertValue (42, f);
// Argument checking
AssertThrows<ArgumentNullException> (delegate () {
t.GetValue (null);
});
// instance fields
AssertThrows<ArgumentException> (delegate () {
t.GetValue (o.Type.GetField ("field_i"));
});
// field on another type
AssertThrows<ArgumentException> (delegate () {
t.GetValue (val2.Type.GetField ("static_field_j"));
});
// special static field
AssertThrows<ArgumentException> (delegate () {
t.GetValue (t.GetField ("tls_i"));
});
}
[Test]
public void Type_GetValues () {
Event e = run_until ("o1");
StackFrame frame = e.Thread.GetFrames () [0];
ObjectMirror o = (frame.GetThis () as ObjectMirror);
TypeMirror t = o.Type;
// static fields
object[] vals = t.GetValues (new FieldInfoMirror [] { t.GetField ("static_i"), t.GetField ("static_s") });
object f = vals [0];
AssertValue (55, f);
f = vals [1];
AssertValue ("A", f);
// Argument checking
AssertThrows<ArgumentNullException> (delegate () {
t.GetValues (null);
});
AssertThrows<ArgumentNullException> (delegate () {
t.GetValues (new FieldInfoMirror [] { null });
});
}
[Test]
public void ObjRefs () {
Event e = run_until ("objrefs1");
StackFrame frame = e.Thread.GetFrames () [0];
ObjectMirror o = frame.GetThis () as ObjectMirror;
ObjectMirror child = o.GetValue (o.Type.GetField ("child")) as ObjectMirror;
Assert.IsTrue (child.Address != 0);
// Check that object references are internalized correctly
Assert.AreEqual (o, frame.GetThis ());
run_until ("objrefs2");
// child should be gc'd now
// This is not deterministic
//Assert.IsTrue (child.IsCollected);
/*
* No longer works since Type is read eagerly
*/
/*
AssertThrows<ObjectCollectedException> (delegate () {
TypeMirror t = child.Type;
});
*/
/*
AssertThrows<ObjectCollectedException> (delegate () {
long addr = child.Address;
});
*/
}
[Test]
public void Type_GetObject () {
Event e = run_until ("o1");
StackFrame frame = e.Thread.GetFrames () [0];
ObjectMirror o = (frame.GetThis () as ObjectMirror);
TypeMirror t = o.Type;
Assert.AreEqual ("MonoType", t.GetTypeObject ().Type.Name);
}
[Test]
public void VTypes () {
Event e = run_until ("vtypes1");
StackFrame frame = e.Thread.GetFrames () [0];
// vtypes as fields
ObjectMirror o = frame.GetThis () as ObjectMirror;
var obj = o.GetValue (o.Type.GetField ("field_struct"));
Assert.IsTrue (obj is StructMirror);
var s = obj as StructMirror;
Assert.AreEqual ("AStruct", s.Type.Name);
AssertValue (42, s ["i"]);
obj = s ["s"];
AssertValue ("S", obj);
AssertValue (43, s ["k"]);
obj = o.GetValue (o.Type.GetField ("field_boxed_struct"));
Assert.IsTrue (obj is StructMirror);
s = obj as StructMirror;
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"]);
obj = s ["s"];
AssertValue ("T", obj);
AssertValue (45, s ["k"]);
// vtypes as array entries
var arr = frame.GetArgument (1) as ArrayMirror;
obj = arr [0];
Assert.IsTrue (obj is StructMirror);
s = obj as StructMirror;
AssertValue (1, s ["i"]);
AssertValue ("S1", s ["s"]);
obj = arr [1];
Assert.IsTrue (obj is StructMirror);
s = obj as StructMirror;
AssertValue (2, s ["i"]);
AssertValue ("S2", s ["s"]);
// Argument checking
s = frame.GetArgument (0) as StructMirror;
AssertThrows<ArgumentException> (delegate () {
obj = s ["FOO"];
});
// generic vtype instances
o = frame.GetThis () as ObjectMirror;
obj = o.GetValue (o.Type.GetField ("generic_field_struct"));
Assert.IsTrue (obj is StructMirror);
s = obj as StructMirror;
Assert.AreEqual ("GStruct`1", s.Type.Name);
AssertValue (42, s ["i"]);
// this on vtype methods
e = run_until ("vtypes2");
e = step_until (e.Thread, "foo");
frame = e.Thread.GetFrames () [0];
Assert.AreEqual ("foo", (e as StepEvent).Method.Name);
obj = frame.GetThis ();
Assert.IsTrue (obj is StructMirror);
s = obj as StructMirror;
AssertValue (44, s ["i"]);
AssertValue ("T", s ["s"]);
AssertValue (45, s ["k"]);
// this on static vtype methods
e = run_until ("vtypes3");
e = step_until (e.Thread, "static_foo");
frame = e.Thread.GetFrames () [0];
Assert.AreEqual ("static_foo", (e as StepEvent).Method.Name);
obj = frame.GetThis ();
AssertValue (null, obj);
// vtypes which reference themselves recursively
e = run_until ("vtypes4_2");
frame = e.Thread.GetFrames () [0];
Assert.IsTrue (frame.GetArgument (0) is StructMirror);
}
[Test]
public void AssemblyInfo () {
Event e = run_until ("single_stepping");
StackFrame frame = e.Thread.GetFrames () [0];
var aname = frame.Method.DeclaringType.Assembly.GetName ();
Assert.AreEqual ("dtest-app, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null", aname.ToString ());
ModuleMirror m = frame.Method.DeclaringType.Module;
Assert.AreEqual ("dtest-app.exe", m.Name);
Assert.AreEqual ("dtest-app.exe", m.ScopeName);
Assert.IsTrue (m.FullyQualifiedName.IndexOf ("dtest-app.exe") != -1);
Guid guid = m.ModuleVersionId;
Assert.AreEqual (frame.Method.DeclaringType.Assembly, m.Assembly);
Assert.AreEqual (frame.Method.DeclaringType.Assembly.ManifestModule, m);
// This is no longer true on 4.0
//Assert.AreEqual ("Assembly", frame.Method.DeclaringType.Assembly.GetAssemblyObject ().Type.Name);
TypeMirror t = vm.RootDomain.Corlib.GetType ("System.Diagnostics.DebuggerDisplayAttribute");
Assert.AreEqual ("DebuggerDisplayAttribute", t.Name);
}
[Test]
public void LocalsInfo () {
Event e = run_until ("locals2");
StackFrame frame = e.Thread.GetFrames () [0];
var locals = frame.Method.GetLocals ();
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 == "arg") {
Assert.IsTrue (locals [i].IsArg);
Assert.AreEqual ("Int32", locals [i].Type.Name);
} else if (locals [i].Name == "i") {
Assert.IsFalse (locals [i].IsArg);
Assert.AreEqual ("Int64", locals [i].Type.Name);
} else if (locals [i].Name == "j") {
Assert.IsFalse (locals [i].IsArg);
Assert.AreEqual ("Int32", locals [i].Type.Name);
} else if (locals [i].Name == "s") {
Assert.IsFalse (locals [i].IsArg);
Assert.AreEqual ("String", locals [i].Type.Name);
} else if (locals [i].Name == "t") {
// gshared
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 ();
}
}
}
Event step_once () {
vm.Resume ();
var e = GetNextEvent ();
Assert.IsTrue (e is StepEvent);
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");
StackFrame frame = be.Thread.GetFrames () [0];
MethodMirror m1 = frame.Method;
// Compiler generated byref local
foreach (var l in m1.GetLocals ()) {
// The byval flag is hidden from the type
if (l.Name != "ri" && l.Type.Name == "Double")
AssertValue (null, frame.GetValue (l));
}
be = run_until ("locals2");
frame = be.Thread.GetFrames () [0];
object val = frame.GetValue (frame.Method.GetLocal ("i"));
AssertValue (0, val);
var req = create_step (be);
req.Enable ();
// Skip nop
step_once ();
// Execute i = 42
var e = step_once ();
Assert.AreEqual ("locals2", (e as StepEvent).Method.Name);
// Execute s = "AB";
e = step_once ();
Assert.AreEqual ("locals2", (e as StepEvent).Method.Name);
frame = e.Thread.GetFrames () [0];
val = frame.GetValue (frame.Method.GetLocal ("i"));
AssertValue (42, val);
LocalVariable[] locals = frame.Method.GetLocals ();
var vals = frame.GetValues (locals);
Assert.AreEqual (locals.Length, vals.Length);
for (int i = 0; i < locals.Length; ++i) {
if (locals [i].Name == "i")
AssertValue (42, vals [i]);
if (locals [i].Name == "s")
AssertValue ("AB", vals [i]);
if (locals [i].Name == "t")
AssertValue ("ABC", vals [i]);
}
// Argument checking
// GetValue () null
AssertThrows<ArgumentNullException> (delegate () {
frame.GetValue ((LocalVariable)null);
});
// GetValue () local from another method
AssertThrows<ArgumentException> (delegate () {
frame.GetValue (m1.GetLocal ("foo"));
});
// GetValue () null
AssertThrows<ArgumentNullException> (delegate () {
frame.GetValue ((ParameterInfoMirror)null);
});
// GetValue () local from another method
AssertThrows<ArgumentException> (delegate () {
frame.GetValue (m1.GetParameters ()[0]);
});
// GetValues () null
AssertThrows<ArgumentNullException> (delegate () {
frame.GetValues (null);
});
// GetValues () embedded null
AssertThrows<ArgumentNullException> (delegate () {
frame.GetValues (new LocalVariable [] { null });
});
// GetValues () local from another method
AssertThrows<ArgumentException> (delegate () {
frame.GetValues (new LocalVariable [] { m1.GetLocal ("foo") });
});
// return value
AssertThrows<ArgumentException> (delegate () {
val = frame.GetValue (frame.Method.ReturnParameter);
});
// invalid stack frames
vm.Resume ();
e = GetNextEvent ();
Assert.IsTrue (e is StepEvent);
Assert.AreEqual ("locals2", (e as StepEvent).Method.Name);
AssertThrows<InvalidStackFrameException> (delegate () {
frame.GetValue (frame.Method.GetLocal ("i"));
});
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]
public void GetVisibleVariables () {
Event e = run_until ("locals4");
// First scope
var locals = e.Thread.GetFrames ()[1].GetVisibleVariables ();
Assert.AreEqual (2, locals.Count);
var loc = locals.First (l => l.Name == "i");
Assert.AreEqual ("Int64", loc.Type.Name);
loc = locals.First (l => l.Name == "s");
Assert.AreEqual ("String", loc.Type.Name);
loc = e.Thread.GetFrames ()[1].GetVisibleVariableByName ("i");
Assert.AreEqual ("i", loc.Name);
Assert.AreEqual ("Int64", loc.Type.Name);
e = run_until ("locals5");
// Second scope
locals = e.Thread.GetFrames ()[1].GetVisibleVariables ();
Assert.AreEqual (2, locals.Count);
loc = locals.First (l => l.Name == "i");
Assert.AreEqual ("String", loc.Type.Name);
loc = locals.First (l => l.Name == "s");
Assert.AreEqual ("String", loc.Type.Name);
loc = e.Thread.GetFrames ()[1].GetVisibleVariableByName ("i");
Assert.AreEqual ("i", loc.Name);
Assert.AreEqual ("String", loc.Type.Name);
// Variable in another scope
loc = e.Thread.GetFrames ()[1].GetVisibleVariableByName ("j");
Assert.IsNull (loc);
}
[Test]
public void Exit () {
run_until ("Main");
vm.Exit (5);
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) {
p.WaitForExit ();
Assert.AreEqual (5, p.ExitCode);
// error handling
AssertThrows<VMDisconnectedException> (delegate () {
vm.Resume ();
});
}
vm = null;
}
[Test]
public void Dispose () {
run_until ("Main");
vm.Detach ();
var e = GetNextEvent ();
Assert.IsInstanceOfType (typeof (VMDisconnectEvent), e);
var p = vm.Process;
/* Could be a remote vm with no process */
if (p != null) {
p.WaitForExit ();
Assert.AreEqual (3, p.ExitCode);
// error handling
AssertThrows<VMDisconnectedException> (delegate () {
vm.Resume ();
});
}
vm = null;
}
[Test]
public void ColumnNumbers () {
Event e = run_until ("line_numbers");
// FIXME: Merge this with LineNumbers () when its fixed
step_req = create_step (e);
step_req.Depth = StepDepth.Into;
step_req.Enable ();
Location l;
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);
l = e.Thread.GetFrames ()[0].Location;
Assert.AreEqual (3, l.ColumnNumber);
step_req.Disable ();
}
[Test]
// Broken by mcs+runtime changes (#5438)
[Category("NotWorking")]
public void LineNumbers () {
Event e = run_until ("line_numbers");
step_req = create_step (e);
step_req.Depth = StepDepth.Into;
step_req.Enable ();
Location l;
vm.Resume ();
e = GetNextEvent ();
Assert.IsTrue (e is StepEvent);
l = e.Thread.GetFrames ()[0].Location;
Assert.IsTrue (l.SourceFile.IndexOf ("dtest-app.cs") != -1);
Assert.AreEqual ("ln1", l.Method.Name);
// Check hash
using (FileStream fs = new FileStream (l.SourceFile, FileMode.Open, FileAccess.Read)) {
MD5 md5 = MD5.Create ();
var hash = md5.ComputeHash (fs);
for (int i = 0; i < 16; ++i)
Assert.AreEqual (hash [i], l.SourceFileHash [i]);
}
int line_base = l.LineNumber;
vm.Resume ();
e = GetNextEvent ();
Assert.IsTrue (e is StepEvent);
l = e.Thread.GetFrames ()[0].Location;
Assert.AreEqual ("ln2", l.Method.Name);
Assert.AreEqual (line_base + 6, l.LineNumber);
vm.Resume ();
e = GetNextEvent ();
Assert.IsTrue (e is StepEvent);
l = e.Thread.GetFrames ()[0].Location;
Assert.AreEqual ("ln1", l.Method.Name);
Assert.AreEqual (line_base + 1, l.LineNumber);
vm.Resume ();
e = GetNextEvent ();
Assert.IsTrue (e is StepEvent);
l = e.Thread.GetFrames ()[0].Location;
Assert.AreEqual ("ln3", l.Method.Name);
Assert.AreEqual (line_base + 11, l.LineNumber);
vm.Resume ();
e = GetNextEvent ();
Assert.IsTrue (e is StepEvent);
l = e.Thread.GetFrames ()[0].Location;
Assert.AreEqual ("ln3", l.Method.Name);
Assert.IsTrue (l.SourceFile.EndsWith ("FOO"));
Assert.AreEqual (55, l.LineNumber);
vm.Resume ();
e = GetNextEvent ();
Assert.IsTrue (e is StepEvent);
l = e.Thread.GetFrames ()[0].Location;
Assert.AreEqual ("ln1", l.Method.Name);
Assert.AreEqual (line_base + 2, l.LineNumber);
// GetSourceFiles ()
string[] sources = l.Method.DeclaringType.GetSourceFiles ();
Assert.AreEqual (2, sources.Length);
Assert.AreEqual ("dtest-app.cs", sources [0]);
Assert.AreEqual ("FOO", sources [1]);
sources = l.Method.DeclaringType.GetSourceFiles (true);
Assert.AreEqual (2, sources.Length);
Assert.IsTrue (sources [0].EndsWith ("dtest-app.cs"));
Assert.IsTrue (sources [1].EndsWith ("FOO"));
}
[Test]
public void Suspend () {
vm.Detach ();
Start (new string [] { "dtest-app.exe", "suspend-test" });
Event e = run_until ("suspend");
ThreadMirror main = e.Thread;
vm.Resume ();
Thread.Sleep (100);
vm.Suspend ();
// The debuggee should be suspended while it is running the infinite loop
// in suspend ()
StackFrame frame = main.GetFrames ()[0];
Assert.AreEqual ("suspend", frame.Method.Name);
vm.Resume ();
// resuming when not suspended
AssertThrows<InvalidOperationException> (delegate () {
vm.Resume ();
});
vm.Exit (0);
vm = null;
}
[Test]
public void AssemblyLoad () {
Event e = run_until ("assembly_load");
var load_req = vm.CreateAssemblyLoadRequest ();
load_req.Enable ();
vm.Resume ();
e = GetNextEvent ();
Assert.IsInstanceOfType (typeof (AssemblyLoadEvent), e);
Assert.IsTrue ((e as AssemblyLoadEvent).Assembly.Location.EndsWith ("System.dll"));
var frames = e.Thread.GetFrames ();
Assert.IsTrue (frames.Length > 0);
Assert.AreEqual ("assembly_load", frames [0].Method.Name);
}
[Test]
public void CreateValue () {
PrimitiveValue v;
v = vm.CreateValue (1);
Assert.AreEqual (vm, v.VirtualMachine);
Assert.AreEqual (1, v.Value);
v = vm.CreateValue (null);
Assert.AreEqual (vm, v.VirtualMachine);
Assert.AreEqual (null, v.Value);
// Argument checking
AssertThrows <ArgumentException> (delegate () {
v = vm.CreateValue ("FOO");
});
}
[Test]
public void CreateString () {
StringMirror s = vm.RootDomain.CreateString ("ABC");
Assert.AreEqual (vm, s.VirtualMachine);
Assert.AreEqual ("ABC", s.Value);
Assert.AreEqual (vm.RootDomain, s.Domain);
// Long strings
StringBuilder sb = new StringBuilder ();
for (int i = 0; i < 1024; ++i)
sb.Append ('A');
s = vm.RootDomain.CreateString (sb.ToString ());
// Argument checking
AssertThrows <ArgumentNullException> (delegate () {
s = vm.RootDomain.CreateString (null);
});
}
[Test]
public void CreateBoxedValue () {
ObjectMirror o = vm.RootDomain.CreateBoxedValue (new PrimitiveValue (vm, 42));
Assert.AreEqual ("Int32", o.Type.Name);
//AssertValue (42, m.GetValue (o.Type.GetField ("m_value")));
// Argument checking
AssertThrows <ArgumentNullException> (delegate () {
vm.RootDomain.CreateBoxedValue (null);
});
AssertThrows <ArgumentException> (delegate () {
vm.RootDomain.CreateBoxedValue (o);
});
}
[Test]
public void Invoke () {
Event e = run_until ("invoke1");
StackFrame frame = e.Thread.GetFrames () [0];
TypeMirror t = frame.Method.DeclaringType;
ObjectMirror this_obj = (ObjectMirror)frame.GetThis ();
TypeMirror t2 = frame.Method.GetParameters ()[0].ParameterType;
MethodMirror m;
Value v;
// return void
m = t.GetMethod ("invoke_return_void");
v = this_obj.InvokeMethod (e.Thread, m, null);
Assert.IsNull (v);
// return ref
m = t.GetMethod ("invoke_return_ref");
v = this_obj.InvokeMethod (e.Thread, m, null);
AssertValue ("ABC", v);
// return null
m = t.GetMethod ("invoke_return_null");
v = this_obj.InvokeMethod (e.Thread, m, null);
AssertValue (null, v);
// return primitive
m = t.GetMethod ("invoke_return_primitive");
v = this_obj.InvokeMethod (e.Thread, m, null);
AssertValue (42, v);
// return nullable
m = t.GetMethod ("invoke_return_nullable");
v = this_obj.InvokeMethod (e.Thread, m, null);
Assert.IsInstanceOfType (typeof (StructMirror), v);
var s = v as StructMirror;
AssertValue (42, s.Fields [0]);
AssertValue (true, s.Fields [1]);
// pass nullable as this
//m = vm.RootDomain.Corlib.GetType ("System.Object").GetMethod ("ToString");
m = s.Type.GetMethod ("ToString");
v = s.InvokeMethod (e.Thread, m, null);
// return nullable null
m = t.GetMethod ("invoke_return_nullable_null");
v = this_obj.InvokeMethod (e.Thread, m, null);
Assert.IsInstanceOfType (typeof (StructMirror), v);
s = v as StructMirror;
AssertValue (0, s.Fields [0]);
AssertValue (false, s.Fields [1]);
// pass nullable as this
//m = vm.RootDomain.Corlib.GetType ("System.Object").GetMethod ("ToString");
m = s.Type.GetMethod ("ToString");
v = s.InvokeMethod (e.Thread, m, null);
// pass primitive
m = t.GetMethod ("invoke_pass_primitive");
Value[] args = new Value [] {
vm.CreateValue ((byte)Byte.MaxValue),
vm.CreateValue ((sbyte)SByte.MaxValue),
vm.CreateValue ((short)1),
vm.CreateValue ((ushort)1),
vm.CreateValue ((int)1),
vm.CreateValue ((uint)1),
vm.CreateValue ((long)1),
vm.CreateValue ((ulong)1),
vm.CreateValue ('A'),
vm.CreateValue (true),
vm.CreateValue (3.14f),
vm.CreateValue (3.14) };
v = this_obj.InvokeMethod (e.Thread, m, args);
AssertValue ((int)Byte.MaxValue + (int)SByte.MaxValue + 1 + 1 + 1 + 1 + 1 + 1 + 'A' + 1 + 3 + 3, v);
// pass ref
m = t.GetMethod ("invoke_pass_ref");
v = this_obj.InvokeMethod (e.Thread, m, new Value [] { vm.RootDomain.CreateString ("ABC") });
AssertValue ("ABC", v);
// pass null
m = t.GetMethod ("invoke_pass_ref");
v = this_obj.InvokeMethod (e.Thread, m, new Value [] { vm.CreateValue (null) });
AssertValue (null, v);
// static
m = t.GetMethod ("invoke_static_pass_ref");
v = t.InvokeMethod (e.Thread, m, new Value [] { vm.RootDomain.CreateString ("ABC") });
AssertValue ("ABC", v);
// static invoked using ObjectMirror.InvokeMethod
m = t.GetMethod ("invoke_static_pass_ref");
v = this_obj.InvokeMethod (e.Thread, m, new Value [] { vm.RootDomain.CreateString ("ABC") });
AssertValue ("ABC", v);
// method which throws an exception
try {
m = t.GetMethod ("invoke_throws");
v = this_obj.InvokeMethod (e.Thread, m, null);
Assert.Fail ();
} catch (InvocationException ex) {
Assert.AreEqual ("Exception", ex.Exception.Type.Name);
}
// newobj
m = t.GetMethod (".ctor");
v = t.InvokeMethod (e.Thread, m, null);
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
AssertThrows<ArgumentNullException> (delegate {
m = t.GetMethod ("invoke_pass_ref");
v = this_obj.InvokeMethod (null, m, new Value [] { vm.CreateValue (null) });
});
// null method
AssertThrows<ArgumentNullException> (delegate {
v = this_obj.InvokeMethod (e.Thread, null, new Value [] { vm.CreateValue (null) });
});
// invalid number of arguments
m = t.GetMethod ("invoke_pass_ref");
AssertThrows<ArgumentException> (delegate {
v = this_obj.InvokeMethod (e.Thread, m, null);
});
// invalid type of argument (ref != primitive)
m = t.GetMethod ("invoke_pass_ref");
AssertThrows<ArgumentException> (delegate {
v = this_obj.InvokeMethod (e.Thread, m, new Value [] { vm.CreateValue (1) });
});
// invalid type of argument (primitive != primitive)
m = t.GetMethod ("invoke_pass_primitive_2");
AssertThrows<ArgumentException> (delegate {
v = this_obj.InvokeMethod (e.Thread, m, new Value [] { vm.CreateValue (1) });
});
// invoking a non-static method as static
m = t.GetMethod ("invoke_pass_ref");
AssertThrows<ArgumentException> (delegate {
v = t.InvokeMethod (e.Thread, m, new Value [] { vm.RootDomain.CreateString ("ABC") });
});
// invoking a method defined in another class
m = t2.GetMethod ("invoke");
AssertThrows<ArgumentException> (delegate {
v = this_obj.InvokeMethod (e.Thread, m, null);
});
}
[Test]
public void InvokeVType () {
Event e = run_until ("invoke1");
StackFrame frame = e.Thread.GetFrames () [0];
var s = frame.GetArgument (1) as StructMirror;
TypeMirror t = s.Type;
MethodMirror m;
Value v;
// Pass struct as this, receive int
m = t.GetMethod ("invoke_return_int");
v = s.InvokeMethod (e.Thread, m, null);
AssertValue (42, v);
// Pass struct as this, receive intptr
m = t.GetMethod ("invoke_return_intptr");
v = s.InvokeMethod (e.Thread, m, null);
AssertValue (43, v);
// Static method
m = t.GetMethod ("invoke_static");
v = t.InvokeMethod (e.Thread, m, null);
AssertValue (5, v);
// Pass generic struct as this
s = frame.GetArgument (2) as StructMirror;
t = s.Type;
m = t.GetMethod ("invoke_return_int");
v = s.InvokeMethod (e.Thread, m, null);
AssertValue (42, v);
}
[Test]
public void BreakpointDuringInvoke () {
Event e = run_until ("invoke1");
MethodMirror m = entry_point.DeclaringType.GetMethod ("invoke2");
Assert.IsNotNull (m);
vm.SetBreakpoint (m, 0);
StackFrame frame = e.Thread.GetFrames () [0];
var o = frame.GetThis () as ObjectMirror;
bool failed = false;
bool finished = false;
object wait = new object ();
// Have to invoke in a separate thread as the invoke is suspended until we
// resume after the breakpoint
Thread t = new Thread (delegate () {
try {
o.InvokeMethod (e.Thread, m, null);
} catch {
failed = true;
}
lock (wait) {
finished = true;
Monitor.Pulse (wait);
}
});
t.Start ();
StackFrame invoke_frame = null;
try {
e = GetNextEvent ();
Assert.IsInstanceOfType (typeof (BreakpointEvent), e);
// Check stack trace support and invokes
var frames = e.Thread.GetFrames ();
invoke_frame = frames [0];
Assert.AreEqual ("invoke2", frames [0].Method.Name);
Assert.IsTrue (frames [0].IsDebuggerInvoke);
Assert.AreEqual ("invoke1", frames [1].Method.Name);
} finally {
vm.Resume ();
}
lock (wait) {
if (!finished)
Monitor.Wait (wait);
}
// Check that the invoke frames are no longer valid
AssertThrows<InvalidStackFrameException> (delegate {
invoke_frame.GetThis ();
});
// Check InvokeOptions.DisableBreakpoints flag
o.InvokeMethod (e.Thread, m, null, InvokeOptions.DisableBreakpoints);
}
[Test]
public void DisabledExceptionDuringInvoke () {
Event e = run_until ("invoke_ex");
MethodMirror m = entry_point.DeclaringType.GetMethod ("invoke_ex_inner");
StackFrame frame = e.Thread.GetFrames () [0];
var o = frame.GetThis () as ObjectMirror;
var req = vm.CreateExceptionRequest (null);
req.Enable ();
// Check InvokeOptions.DisableBreakpoints flag
o.InvokeMethod (e.Thread, m, null, InvokeOptions.DisableBreakpoints);
req.Disable ();
}
[Test]
public void InvokeSingleThreaded () {
vm.Detach ();
Start (new string [] { "dtest-app.exe", "invoke-single-threaded" });
Event e = run_until ("invoke_single_threaded_2");
StackFrame f = e.Thread.GetFrames ()[0];
var obj = f.GetThis () as ObjectMirror;
// Check that the counter value incremented by the other thread does not increase
// during the invoke.
object counter1 = (obj.GetValue (obj.Type.GetField ("counter")) as PrimitiveValue).Value;
var m = obj.Type.GetMethod ("invoke_return_void");
obj.InvokeMethod (e.Thread, m, null, InvokeOptions.SingleThreaded);
object counter2 = (obj.GetValue (obj.Type.GetField ("counter")) as PrimitiveValue).Value;
Assert.AreEqual ((int)counter1, (int)counter2);
// Test multiple invokes done in succession
m = obj.Type.GetMethod ("invoke_return_void");
obj.InvokeMethod (e.Thread, m, null, InvokeOptions.SingleThreaded);
// Test events during single-threaded invokes
vm.EnableEvents (EventType.TypeLoad);
m = obj.Type.GetMethod ("invoke_type_load");
obj.BeginInvokeMethod (e.Thread, m, null, InvokeOptions.SingleThreaded, delegate {
vm.Resume ();
}, null);
e = GetNextEvent ();
Assert.AreEqual (EventType.TypeLoad, e.EventType);
}
List<Value> invoke_results;
[Test]
public void InvokeMultiple () {
Event e = run_until ("invoke1");
StackFrame frame = e.Thread.GetFrames () [0];
TypeMirror t = frame.Method.DeclaringType;
ObjectMirror this_obj = (ObjectMirror)frame.GetThis ();
TypeMirror t2 = frame.Method.GetParameters ()[0].ParameterType;
var methods = new MethodMirror [2];
methods [0] = t.GetMethod ("invoke_return_ref");
methods [1] = t.GetMethod ("invoke_return_primitive");
invoke_results = new List<Value> ();
var r = this_obj.BeginInvokeMultiple (e.Thread, methods, null, InvokeOptions.SingleThreaded, invoke_multiple_cb, this_obj);
WaitHandle.WaitAll (new WaitHandle[] { r.AsyncWaitHandle });
this_obj.EndInvokeMultiple (r);
// The callback might still be running
while (invoke_results.Count < 2) {
Thread.Sleep (100);
}
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) {
ObjectMirror this_obj = (ObjectMirror)ar.AsyncState;
var res = this_obj.EndInvokeMethod (ar);
lock (invoke_results)
invoke_results.Add (res);
}
[Test]
public void GetThreads () {
vm.GetThreads ();
}
[Test]
public void Threads () {
Event e = run_until ("threads");
Assert.AreEqual (ThreadState.Running, e.Thread.ThreadState);
Assert.IsTrue (e.Thread.ThreadId > 0);
Assert.AreEqual (e.Thread.TID, e.Thread.TID);
vm.EnableEvents (EventType.ThreadStart, EventType.ThreadDeath);
vm.Resume ();
e = GetNextEvent ();
Assert.IsInstanceOfType (typeof (ThreadStartEvent), e);
var state = e.Thread.ThreadState;
Assert.IsTrue (state == ThreadState.Running || state == ThreadState.Unstarted);
vm.Resume ();
e = GetNextEvent ();
Assert.IsInstanceOfType (typeof (ThreadDeathEvent), e);
Assert.AreEqual (ThreadState.Stopped, e.Thread.ThreadState);
}
[Test]
public void Frame_SetValue () {
Event e = run_until ("locals2");
StackFrame frame = e.Thread.GetFrames () [0];
// primitive
var l = frame.Method.GetLocal ("i");
frame.SetValue (l, vm.CreateValue ((long)55));
AssertValue (55, frame.GetValue (l));
// reference
l = frame.Method.GetLocal ("s");
frame.SetValue (l, vm.RootDomain.CreateString ("DEF"));
AssertValue ("DEF", frame.GetValue (l));
// argument as local
l = frame.Method.GetLocal ("arg");
frame.SetValue (l, vm.CreateValue (6));
AssertValue (6, frame.GetValue (l));
// argument
var p = frame.Method.GetParameters ()[1];
frame.SetValue (p, vm.CreateValue (7));
AssertValue (7, frame.GetValue (p));
// gshared
p = frame.Method.GetParameters ()[2];
frame.SetValue (p, vm.RootDomain.CreateString ("DEF"));
AssertValue ("DEF", frame.GetValue (p));
// byref
p = frame.Method.GetParameters ()[3];
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
AssertThrows<ArgumentNullException> (delegate () {
frame.SetValue ((LocalVariable)null, vm.CreateValue (55));
});
// value null
AssertThrows<ArgumentNullException> (delegate () {
l = frame.Method.GetLocal ("i");
frame.SetValue (l, null);
});
// value of invalid type
AssertThrows<ArgumentException> (delegate () {
l = frame.Method.GetLocal ("i");
frame.SetValue (l, vm.CreateValue (55));
});
}
[Test]
[Category ("only")]
public void Frame_SetValue_Registers () {
Event e = run_until ("locals6_1");
StackFrame frame = e.Thread.GetFrames () [1];
// Set 'j' to 99
var l = frame.Method.GetLocal ("j");
frame.SetValue (l, vm.CreateValue (99));
AssertValue (99, frame.GetValue (l));
// Check it during execution
e = run_until ("locals6_2");
frame = e.Thread.GetFrames () [0];
AssertValue (99, frame.GetValue (frame.Method.GetParameters ()[0]));
// Set it while in a frame which clobbers its register
e = run_until ("locals6_3");
frame = e.Thread.GetFrames () [1];
frame.SetValue (l, vm.CreateValue (100));
AssertValue (100, frame.GetValue (l));
// Check it during execution
e = run_until ("locals6_4");
frame = e.Thread.GetFrames () [0];
AssertValue (100, frame.GetValue (frame.Method.GetParameters ()[0]));
// Signed byte value
e = run_until ("locals6_5");
frame = e.Thread.GetFrames () [1];
var l2 = frame.Method.GetLocal ("sb");
frame.SetValue (l2, vm.CreateValue ((sbyte)-99));
AssertValue (-99, frame.GetValue (l2));
// Check it during execution
e = run_until ("locals6_6");
frame = e.Thread.GetFrames () [0];
AssertValue (-99, frame.GetValue (frame.Method.GetParameters ()[0]));
}
[Test]
public void InvokeRegress () {
Event e = run_until ("invoke1");
StackFrame frame = e.Thread.GetFrames () [0];
TypeMirror t = frame.Method.DeclaringType;
ObjectMirror this_obj = (ObjectMirror)frame.GetThis ();
TypeMirror t2 = frame.Method.GetParameters ()[0].ParameterType;
MethodMirror m;
Value v;
// do an invoke
m = t.GetMethod ("invoke_return_void");
v = this_obj.InvokeMethod (e.Thread, m, null);
Assert.IsNull (v);
// Check that the stack frames remain valid during the invoke
Assert.AreEqual ("Tests", (frame.GetThis () as ObjectMirror).Type.Name);
// do another invoke
m = t.GetMethod ("invoke_return_void");
v = this_obj.InvokeMethod (e.Thread, m, null);
Assert.IsNull (v);
// Try a single step after the invoke
var req = create_step (e);
req.Depth = StepDepth.Into;
req.Size = StepSize.Line;
req.Enable ();
// Skip nop
step_once ();
// Step into invoke2
vm.Resume ();
e = GetNextEvent ();
Assert.IsTrue (e is StepEvent);
Assert.AreEqual ("invoke2", (e as StepEvent).Method.Name);
req.Disable ();
frame = e.Thread.GetFrames () [0];
}
[Test]
public void Exceptions () {
Event e = run_until ("exceptions");
var req = vm.CreateExceptionRequest (null);
req.Enable ();
vm.Resume ();
e = GetNextEvent ();
Assert.IsInstanceOfType (typeof (ExceptionEvent), e);
Assert.AreEqual ("OverflowException", (e as ExceptionEvent).Exception.Type.Name);
var frames = e.Thread.GetFrames ();
Assert.AreEqual ("exceptions", frames [0].Method.Name);
req.Disable ();
// exception type filter
req = vm.CreateExceptionRequest (vm.RootDomain.Corlib.GetType ("System.ArgumentException"));
req.Enable ();
// Skip the throwing of the second OverflowException
vm.Resume ();
e = GetNextEvent ();
Assert.IsInstanceOfType (typeof (ExceptionEvent), e);
Assert.AreEqual ("ArgumentException", (e as ExceptionEvent).Exception.Type.Name);
req.Disable ();
// exception type filter for subclasses
req = vm.CreateExceptionRequest (vm.RootDomain.Corlib.GetType ("System.Exception"));
req.Enable ();
vm.Resume ();
e = GetNextEvent ();
Assert.IsInstanceOfType (typeof (ExceptionEvent), e);
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 ();
vm.Resume ();
e = GetNextEvent ();
Assert.IsInstanceOfType (typeof (ExceptionEvent), e);
Assert.AreEqual ("NullReferenceException", (e as ExceptionEvent).Exception.Type.Name);
req.Disable ();
// Single stepping after an exception
req = vm.CreateExceptionRequest (null);
req.Enable ();
vm.Resume ();
e = GetNextEvent ();
Assert.IsInstanceOfType (typeof (ExceptionEvent), e);
Assert.AreEqual ("Exception", (e as ExceptionEvent).Exception.Type.Name);
frames = e.Thread.GetFrames ();
Assert.AreEqual ("exceptions2", frames [0].Method.Name);
req.Disable ();
var sreq = create_step (e);
sreq.Depth = StepDepth.Over;
sreq.Size = StepSize.Line;
sreq.Enable ();
vm.Resume ();
e = GetNextEvent ();
Assert.IsInstanceOfType (typeof (StepEvent), e);
frames = e.Thread.GetFrames ();
Assert.AreEqual ("exceptions", frames [0].Method.Name);
sreq.Disable ();
// Argument checking
AssertThrows<ArgumentException> (delegate {
vm.CreateExceptionRequest (e.Thread.Type);
});
}
[Test]
public void ExceptionFilter () {
Event e = run_until ("exception_filter");
MethodMirror m = entry_point.DeclaringType.GetMethod ("exception_filter_filter");
Assert.IsNotNull (m);
vm.SetBreakpoint (m, 0);
vm.Resume ();
e = GetNextEvent ();
Assert.AreEqual (EventType.Breakpoint, e.EventType);
Assert.IsTrue (e is BreakpointEvent);
Assert.AreEqual (m.Name, (e as BreakpointEvent).Method.Name);
var frames = e.Thread.GetFrames ();
Assert.IsTrue (frames [0].Location.SourceFile.IndexOf ("dtest-app.cs") != -1);
Assert.AreEqual ("exception_filter_filter", frames [0].Location.Method.Name);
Assert.AreEqual (0, frames [1].Location.Method.MetadataToken);
Assert.AreEqual (0x0f, frames [1].Location.ILOffset);
Assert.AreEqual ("exception_filter_method", frames [2].Location.Method.Name);
Assert.AreEqual (0x06, frames [2].Location.ILOffset);
Assert.AreEqual (0, frames [3].Location.Method.MetadataToken, 0);
Assert.AreEqual (0, frames [3].Location.ILOffset);
Assert.AreEqual ("exception_filter", frames [4].Location.Method.Name);
}
[Test]
public void ExceptionFilter2 () {
vm.Detach ();
Start (new string [] { "dtest-excfilter.exe" });
MethodMirror filter_method = entry_point.DeclaringType.GetMethod ("Filter");
Assert.IsNotNull (filter_method);
MethodMirror test_method = entry_point.DeclaringType.GetMethod ("Test");
Assert.IsNotNull (test_method);
vm.SetBreakpoint (filter_method, 0);
vm.Resume ();
var e = GetNextEvent ();
Assert.AreEqual (EventType.Breakpoint, e.EventType);
Assert.IsTrue (e is BreakpointEvent);
Assert.AreEqual (filter_method.Name, (e as BreakpointEvent).Method.Name);
var frames = e.Thread.GetFrames ();
Assert.AreEqual (4, frames.Count ());
Assert.AreEqual (filter_method.Name, frames [0].Location.Method.Name);
Assert.AreEqual (20, frames [0].Location.LineNumber);
Assert.AreEqual (0, frames [0].Location.ILOffset);
Assert.AreEqual (test_method.Name, frames [1].Location.Method.Name);
Assert.AreEqual (37, frames [1].Location.LineNumber);
Assert.AreEqual (0x0b, frames [1].Location.ILOffset);
Assert.AreEqual (test_method.Name, frames [2].Location.Method.Name);
Assert.AreEqual (33, frames [2].Location.LineNumber);
Assert.AreEqual (0x05, frames [2].Location.ILOffset);
Assert.AreEqual (entry_point.Name, frames [3].Location.Method.Name);
Assert.AreEqual (14, frames [3].Location.LineNumber);
Assert.AreEqual (0x00, frames [3].Location.ILOffset);
vm.Exit (0);
vm = null;
}
[Test]
public void EventSets () {
//
// Create two filter which both match the same exception
//
Event e = run_until ("exceptions");
var req = vm.CreateExceptionRequest (null);
req.Enable ();
var req2 = vm.CreateExceptionRequest (vm.RootDomain.Corlib.GetType ("System.OverflowException"));
req2.Enable ();
vm.Resume ();
var es = vm.GetNextEventSet ();
Assert.AreEqual (2, es.Events.Length);
e = es [0];
Assert.IsInstanceOfType (typeof (ExceptionEvent), e);
Assert.AreEqual ("OverflowException", (e as ExceptionEvent).Exception.Type.Name);
e = es [1];
Assert.IsInstanceOfType (typeof (ExceptionEvent), e);
Assert.AreEqual ("OverflowException", (e as ExceptionEvent).Exception.Type.Name);
req.Disable ();
req2.Disable ();
}
//
// Test single threaded invokes during processing of nullref exceptions.
// These won't work if the exception handling is done from the sigsegv signal
// handler, since the sigsegv signal is disabled until control returns from the
// signal handler.
//
[Test]
[Category ("only3")]
public void NullRefExceptionAndSingleThreadedInvoke () {
Event e = run_until ("exceptions");
var req = vm.CreateExceptionRequest (vm.RootDomain.Corlib.GetType ("System.NullReferenceException"));
req.Enable ();
vm.Resume ();
e = GetNextEvent ();
Assert.IsInstanceOfType (typeof (ExceptionEvent), e);
Assert.AreEqual ("NullReferenceException", (e as ExceptionEvent).Exception.Type.Name);
var ex = (e as ExceptionEvent).Exception;
var tostring_method = vm.RootDomain.Corlib.GetType ("System.Object").GetMethod ("ToString");
ex.InvokeMethod (e.Thread, tostring_method, null, InvokeOptions.SingleThreaded);
}
[Test]
public void Domains () {
vm.Detach ();
Start (new string [] { "dtest-app.exe", "domain-test" });
vm.EnableEvents (EventType.AppDomainCreate, EventType.AppDomainUnload, EventType.AssemblyUnload);
Event e = run_until ("domains");
vm.Resume ();
e = GetNextEvent ();
Assert.IsInstanceOfType (typeof (AppDomainCreateEvent), e);
var domain = (e as AppDomainCreateEvent).Domain;
// Check the object type
e = run_until ("domains_2");
var frame = e.Thread.GetFrames ()[0];
var o = frame.GetArgument (0) as ObjectMirror;
Assert.AreEqual ("CrossDomain", o.Type.Name);
// Do a remoting invoke
var cross_domain_type = o.Type;
var v = o.InvokeMethod (e.Thread, cross_domain_type.GetMethod ("invoke_3"), null);
AssertValue (42, v);
// Run until the callback in the domain
MethodMirror m = entry_point.DeclaringType.GetMethod ("invoke_in_domain");
Assert.IsNotNull (m);
vm.SetBreakpoint (m, 0);
while (true) {
vm.Resume ();
e = GetNextEvent ();
if (e is BreakpointEvent)
break;
}
Assert.AreEqual ("invoke_in_domain", (e as BreakpointEvent).Method.Name);
// d_method is from another domain
MethodMirror d_method = (e as BreakpointEvent).Method;
Assert.IsTrue (m != d_method);
var frames = e.Thread.GetFrames ();
Assert.AreEqual ("invoke_in_domain", frames [0].Method.Name);
Assert.AreEqual ("invoke", frames [1].Method.Name);
Assert.AreEqual ("domains", frames [2].Method.Name);
// Test breakpoints on already JITted methods in other domains
m = entry_point.DeclaringType.GetMethod ("invoke_in_domain_2");
Assert.IsNotNull (m);
vm.SetBreakpoint (m, 0);
while (true) {
vm.Resume ();
e = GetNextEvent ();
if (e is BreakpointEvent)
break;
}
Assert.AreEqual ("invoke_in_domain_2", (e as BreakpointEvent).Method.Name);
// This is empty when receiving the AppDomainCreateEvent
Assert.AreEqual ("domain", domain.FriendlyName);
// Run until the unload
while (true) {
vm.Resume ();
e = GetNextEvent ();
if (e is AssemblyUnloadEvent) {
continue;
} else {
break;
}
}
Assert.IsInstanceOfType (typeof (AppDomainUnloadEvent), e);
Assert.AreEqual (domain, (e as AppDomainUnloadEvent).Domain);
// Run past the unload
e = run_until ("domains_3");
// Test access to unloaded types
// FIXME: Add an exception type for this
AssertThrows<Exception> (delegate {
d_method.DeclaringType.GetValue (d_method.DeclaringType.GetField ("static_i"));
});
}
[Test]
public void DynamicMethods () {
Event e = run_until ("dyn_call");
var m = e.Thread.GetFrames ()[1].Method;
Assert.AreEqual ("dyn_method", m.Name);
// Test access to IL
var body = m.GetMethodBody ();
ILInstruction ins = body.Instructions [0];
Assert.AreEqual (OpCodes.Ldstr, ins.OpCode);
Assert.AreEqual ("FOO", ins.Operand);
}
[Test]
public void RefEmit () {
vm.Detach ();
Start (new string [] { "dtest-app.exe", "ref-emit-test" });
Event e = run_until ("ref_emit_call");
var m = e.Thread.GetFrames ()[1].Method;
Assert.AreEqual ("ref_emit_method", m.Name);
// Test access to IL
var body = m.GetMethodBody ();
ILInstruction ins;
ins = body.Instructions [0];
Assert.AreEqual (OpCodes.Ldstr, ins.OpCode);
Assert.AreEqual ("FOO", ins.Operand);
ins = body.Instructions [1];
Assert.AreEqual (OpCodes.Call, ins.OpCode);
Assert.IsInstanceOfType (typeof (MethodMirror), ins.Operand);
Assert.AreEqual ("ref_emit_call", (ins.Operand as MethodMirror).Name);
}
[Test]
public void IsAttached () {
var f = entry_point.DeclaringType.GetField ("is_attached");
Event e = run_until ("Main");
AssertValue (true, entry_point.DeclaringType.GetValue (f));
}
[Test]
public void StackTraceInNative () {
// Check that stack traces can be produced for threads in native code
vm.Detach ();
Start (new string [] { "dtest-app.exe", "frames-in-native" });
var e = run_until ("frames_in_native");
// FIXME: This is racy
vm.Resume ();
Thread.Sleep (100);
vm.Suspend ();
StackFrame[] frames = e.Thread.GetFrames ();
int frame_index = -1;
for (int i = 0; i < frames.Length; ++i) {
if (frames [i].Method.Name == "Sleep") {
frame_index = i;
break;
}
}
Assert.IsTrue (frame_index != -1);
Assert.AreEqual ("Sleep", frames [frame_index].Method.Name);
Assert.AreEqual ("frames_in_native", frames [frame_index + 1].Method.Name);
Assert.AreEqual ("Main", frames [frame_index + 2].Method.Name);
// Check that invokes are disabled for such threads
TypeMirror t = frames [frame_index + 1].Method.DeclaringType;
var m = t.GetMethod ("invoke_static_return_void");
AssertThrows<InvalidOperationException> (delegate {
t.InvokeMethod (e.Thread, m, null);
});
// Check that the frame info is invalidated
run_until ("frames_in_native_2");
AssertThrows<InvalidStackFrameException> (delegate {
Console.WriteLine (frames [frame_index].GetThis ());
});
}
[Test]
public void VirtualMachine_CreateEnumMirror () {
var e = run_until ("o1");
var frame = e.Thread.GetFrames () [0];
object val = frame.GetThis ();
Assert.IsTrue (val is ObjectMirror);
Assert.AreEqual ("Tests", (val as ObjectMirror).Type.Name);
ObjectMirror o = (val as ObjectMirror);
FieldInfoMirror field = o.Type.GetField ("field_enum");
Value f = o.GetValue (field);
TypeMirror enumType = (f as EnumMirror).Type;
o.SetValue (field, vm.CreateEnumMirror (enumType, vm.CreateValue (1)));
f = o.GetValue (field);
Assert.AreEqual (1, (f as EnumMirror).Value);
// Argument checking
AssertThrows<ArgumentNullException> (delegate () {
vm.CreateEnumMirror (enumType, null);
});
AssertThrows<ArgumentNullException> (delegate () {
vm.CreateEnumMirror (null, vm.CreateValue (1));
});
// null value
AssertThrows<ArgumentException> (delegate () {
vm.CreateEnumMirror (enumType, vm.CreateValue (null));
});
// value of a wrong type
AssertThrows<ArgumentException> (delegate () {
vm.CreateEnumMirror (enumType, vm.CreateValue ((long)1));
});
}
[Test]
public void VirtualMachine_EnableEvents_Breakpoint () {
AssertThrows<ArgumentException> (delegate () {
vm.EnableEvents (EventType.Breakpoint);
});
}
[Test]
public void SingleStepRegress654694 () {
int il_offset = -1;
MethodMirror m = entry_point.DeclaringType.GetMethod ("ss_regress_654694");
foreach (Location l in m.Locations) {
if (l.ILOffset > 0 && il_offset == -1)
il_offset = l.ILOffset;
}
Event e = run_until ("ss_regress_654694");
Assert.IsNotNull (m);
vm.SetBreakpoint (m, il_offset);
vm.Resume ();
e = GetNextEvent ();
Assert.IsTrue (e is BreakpointEvent);
var req = create_step (e);
req.Depth = StepDepth.Over;
req.Size = StepSize.Line;
req.Enable ();
vm.Resume ();
e = GetNextEvent ();
Assert.IsTrue (e is StepEvent);
req.Disable ();
}
[Test]
public void DebugBreak () {
vm.EnableEvents (EventType.UserBreak);
run_until ("user");
vm.Resume ();
var e = GetNextEvent ();
Assert.IsTrue (e is UserBreakEvent);
}
[Test]
public void DebugLog () {
vm.EnableEvents (EventType.UserLog);
run_until ("user");
vm.Resume ();
var e = GetNextEvent ();
Assert.IsTrue (e is UserLogEvent);
var le = e as UserLogEvent;
Assert.AreEqual (5, le.Level);
Assert.AreEqual ("A", le.Category);
Assert.AreEqual ("B", le.Message);
}
[Test]
public void TypeGetMethodsByNameFlags () {
MethodMirror[] mm;
var assembly = entry_point.DeclaringType.Assembly;
var type = assembly.GetType ("Tests3");
Assert.IsNotNull (type);
mm = type.GetMethodsByNameFlags (null, BindingFlags.Static | BindingFlags.Public, false);
Assert.AreEqual (1, mm.Length, "#1");
Assert.AreEqual ("M1", mm[0].Name, "#2");
mm = type.GetMethodsByNameFlags (null, BindingFlags.Static | BindingFlags.NonPublic, false);
Assert.AreEqual (1, mm.Length, "#3");
Assert.AreEqual ("M2", mm[0].Name, "#4");
mm = type.GetMethodsByNameFlags (null, BindingFlags.Instance | BindingFlags.Public, false);
Assert.AreEqual (7, mm.Length, "#5"); //M3 plus Equals, GetHashCode, GetType, ToString, .ctor
mm = type.GetMethodsByNameFlags (null, BindingFlags.Instance | BindingFlags.Public | BindingFlags.DeclaredOnly, false);
Assert.AreEqual (2, mm.Length, "#7");
mm = type.GetMethodsByNameFlags (null, BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.DeclaredOnly, false);
Assert.AreEqual (1, mm.Length, "#9");
mm = type.GetMethodsByNameFlags (null, BindingFlags.Static | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.DeclaredOnly, false);
Assert.AreEqual (5, mm.Length, "#11");
//Now with name
mm = type.GetMethodsByNameFlags ("M1", BindingFlags.Static | BindingFlags.Public, false);
Assert.AreEqual (1, mm.Length, "#12");
Assert.AreEqual ("M1", mm[0].Name, "#13");
mm = type.GetMethodsByNameFlags ("m1", BindingFlags.Static | BindingFlags.Public, true);
Assert.AreEqual (1, mm.Length, "#14");
Assert.AreEqual ("M1", mm[0].Name, "#15");
mm = type.GetMethodsByNameFlags ("M1", BindingFlags.Static | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, false);
Assert.AreEqual (1, mm.Length, "#16");
Assert.AreEqual ("M1", mm[0].Name, "#17");
}
[Test]
[Category ("only88")]
public void TypeLoadSourceFileFilter () {
Event e = run_until ("type_load");
if (!vm.Version.AtLeast (2, 7))
return;
string srcfile = (e as BreakpointEvent).Method.DeclaringType.GetSourceFiles (true)[0];
var req = vm.CreateTypeLoadRequest ();
req.SourceFileFilter = new string [] { srcfile.ToUpper () };
req.Enable ();
vm.Resume ();
e = GetNextEvent ();
Assert.IsTrue (e is TypeLoadEvent);
Assert.AreEqual ("TypeLoadClass", (e as TypeLoadEvent).Type.FullName);
}
[Test]
public void TypeLoadTypeNameFilter () {
Event e = run_until ("type_load");
var req = vm.CreateTypeLoadRequest ();
req.TypeNameFilter = new string [] { "TypeLoadClass2" };
req.Enable ();
vm.Resume ();
e = GetNextEvent ();
Assert.IsTrue (e is TypeLoadEvent);
Assert.AreEqual ("TypeLoadClass2", (e as TypeLoadEvent).Type.FullName);
}
[Test]
public void GetTypesForSourceFile () {
run_until ("user");
var types = vm.GetTypesForSourceFile ("dtest-app.cs", false);
Assert.IsTrue (types.Any (t => t.FullName == "Tests"));
Assert.IsFalse (types.Any (t => t.FullName == "System.Int32"));
types = vm.GetTypesForSourceFile ("DTEST-app.cs", true);
Assert.IsTrue (types.Any (t => t.FullName == "Tests"));
Assert.IsFalse (types.Any (t => t.FullName == "System.Int32"));
}
[Test]
public void GetTypesNamed () {
run_until ("user");
var types = vm.GetTypes ("Tests", false);
Assert.AreEqual (1, types.Count);
Assert.AreEqual ("Tests", types [0].FullName);
types = vm.GetTypes ("System.Exception", false);
Assert.AreEqual (1, types.Count);
Assert.AreEqual ("System.Exception", types [0].FullName);
}
[Test]
public void String_GetChars () {
object val;
// Reuse this test
var e = run_until ("arg2");
var frame = e.Thread.GetFrames () [0];
val = frame.GetArgument (0);
Assert.IsTrue (val is StringMirror);
AssertValue ("FOO", val);
var s = (val as StringMirror);
Assert.AreEqual (3, s.Length);
var c = s.GetChars (0, 2);
Assert.AreEqual (2, c.Length);
Assert.AreEqual ('F', c [0]);
Assert.AreEqual ('O', c [1]);
AssertThrows<ArgumentException> (delegate () {
s.GetChars (2, 2);
});
}
[Test]
public void GetInterfaces () {
var e = run_until ("arg2");
var frame = e.Thread.GetFrames () [0];
var cl1 = frame.Method.DeclaringType.Assembly.GetType ("TestIfaces");
var ifaces = cl1.GetInterfaces ();
Assert.AreEqual (1, ifaces.Length);
Assert.AreEqual ("ITest", ifaces [0].Name);
var cl2 = cl1.GetMethod ("Baz").ReturnType;
var ifaces2 = cl2.GetInterfaces ();
Assert.AreEqual (1, ifaces2.Length);
Assert.AreEqual ("ITest`1", ifaces2 [0].Name);
}
[Test]
public void GetInterfaceMap () {
var e = run_until ("arg2");
var frame = e.Thread.GetFrames () [0];
var cl1 = frame.Method.DeclaringType.Assembly.GetType ("TestIfaces");
var iface = cl1.Assembly.GetType ("ITest");
var map = cl1.GetInterfaceMap (iface);
Assert.AreEqual (cl1, map.TargetType);
Assert.AreEqual (iface, map.InterfaceType);
Assert.AreEqual (2, map.InterfaceMethods.Length);
Assert.AreEqual (2, map.TargetMethods.Length);
}
[Test]
public void StackAlloc_Breakpoints_Regress2775 () {
// Check that breakpoints on arm don't overwrite stackalloc-ed memory
var e = run_until ("regress_2755");
var frame = e.Thread.GetFrames () [0];
var m = e.Method;
// This breaks at the call site
vm.SetBreakpoint (m, m.Locations [2].ILOffset);
vm.Resume ();
var e2 = GetNextEvent ();
Assert.IsTrue (e2 is BreakpointEvent);
e = run_until ("regress_2755_3");
frame = e.Thread.GetFrames () [1];
var res = frame.GetValue (m.GetLocal ("sum"));
AssertValue (0, res);
}
[Test]
public void MethodInfo () {
Event e = run_until ("locals2");
StackFrame frame = e.Thread.GetFrames () [0];
var m = frame.Method;
Assert.IsTrue (m.IsGenericMethod);
Assert.IsFalse (m.IsGenericMethodDefinition);
var args = m.GetGenericArguments ();
Assert.AreEqual (1, args.Length);
Assert.AreEqual ("String", args [0].Name);
var gmd = m.GetGenericMethodDefinition ();
Assert.IsTrue (gmd.IsGenericMethod);
Assert.IsTrue (gmd.IsGenericMethodDefinition);
Assert.AreEqual (gmd, gmd.GetGenericMethodDefinition ());
args = gmd.GetGenericArguments ();
Assert.AreEqual (1, args.Length);
Assert.AreEqual ("T", args [0].Name);
var attrs = m.GetCustomAttributes (true);
Assert.AreEqual (1, attrs.Length);
Assert.AreEqual ("StateMachineAttribute", attrs [0].Constructor.DeclaringType.Name);
}
[Test]
public void UnhandledException () {
vm.Exit (0);
Start (new string [] { "dtest-app.exe", "unhandled-exception" });
var req = vm.CreateExceptionRequest (null, false, true);
req.Enable ();
var e = run_until ("unhandled_exception");
vm.Resume ();
var e2 = GetNextEvent ();
Assert.IsTrue (e2 is ExceptionEvent);
vm.Exit (0);
vm = null;
}
[Test]
public void UnhandledException_2 () {
vm.Exit (0);
Start (new string [] { "dtest-app.exe", "unhandled-exception-endinvoke" });
var req = vm.CreateExceptionRequest (null, false, true);
req.Enable ();
MethodMirror m = entry_point.DeclaringType.GetMethod ("unhandled_exception_endinvoke_2");
Assert.IsNotNull (m);
vm.SetBreakpoint (m, m.ILOffsets [0]);
var e = run_until ("unhandled_exception_endinvoke");
vm.Resume ();
var e2 = GetNextEvent ();
Assert.IsFalse (e2 is ExceptionEvent);
vm.Exit (0);
vm = null;
}
#if NET_4_5
[Test]
public void UnhandledExceptionUserCode () {
vm.Detach ();
// Exceptions caught in non-user code are treated as unhandled
Start (new string [] { "dtest-app.exe", "unhandled-exception-user" });
var req = vm.CreateExceptionRequest (null, false, true);
req.AssemblyFilter = new List<AssemblyMirror> () { entry_point.DeclaringType.Assembly };
req.Enable ();
var e = run_until ("unhandled_exception_user");
vm.Resume ();
var e2 = GetNextEvent ();
Assert.IsTrue (e2 is ExceptionEvent);
vm.Exit (0);
vm = null;
}
#endif
[Test]
public void GCWhileSuspended () {
// Check that objects are kept alive during suspensions
Event e = run_until ("gc_suspend_1");
MethodMirror m = entry_point.DeclaringType.GetMethod ("gc_suspend_invoke");
var o = entry_point.DeclaringType.GetValue (entry_point.DeclaringType.GetField ("gc_suspend_field")) as ObjectMirror;
//Console.WriteLine (o);
StackFrame frame = e.Thread.GetFrames () [0];
TypeMirror t = frame.Method.DeclaringType;
for (int i = 0; i < 10; ++i)
t.InvokeMethod (e.Thread, m, new Value [] { });
// This throws an exception if the object is collected
long addr = o.Address;
var o2 = entry_point.DeclaringType.GetValue (entry_point.DeclaringType.GetField ("gc_suspend_field")) as ObjectMirror;
Assert.IsNull (o2);
}
[Test]
public void MakeGenericMethod () {
Event e = run_until ("bp1");
var intm = vm.RootDomain.GetCorrespondingType (typeof (int));
var stringm = vm.RootDomain.GetCorrespondingType (typeof (string));
var gm = entry_point.DeclaringType.GetMethod ("generic_method");
var res = gm.MakeGenericMethod (new TypeMirror [] { stringm });
var args = res.GetGenericArguments ();
Assert.AreEqual (1, args.Length);
Assert.AreEqual (stringm, args [0]);
// Error checking
AssertThrows<ArgumentNullException> (delegate {
gm.MakeGenericMethod (null);
});
AssertThrows<ArgumentNullException> (delegate {
gm.MakeGenericMethod (new TypeMirror [] { null });
});
AssertThrows<ArgumentException> (delegate {
gm.MakeGenericMethod (new TypeMirror [] { stringm, stringm });
});
AssertThrows<InvalidOperationException> (delegate {
gm.MakeGenericMethod (new TypeMirror [] { intm });
});
AssertThrows<InvalidOperationException> (delegate {
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");
}
[Test]
public void GetMethodBody () {
var bevent = run_until ("Main");
var m = bevent.Method.DeclaringType.GetMethod ("get_IntProperty");
var body = m.GetMethodBody ();
foreach (var ins in body.Instructions) {
if (ins.OpCode == OpCodes.Ldfld) {
var field = (FieldInfoMirror)ins.Operand;
Assert.AreEqual ("field_i", field.Name);
}
}
}
[Test]
public void EvaluateMethod () {
var bevent = run_until ("evaluate_method_2");
var m = bevent.Method.DeclaringType.GetMethod ("get_IntProperty");
var this_obj = bevent.Thread.GetFrames ()[0].GetThis ();
var v = m.Evaluate (this_obj, null);
AssertValue (42, v);
}
[Test]
public void SetIP () {
var bevent = run_until ("set_ip_1");
var invalid_loc = bevent.Thread.GetFrames ()[0].Location;
var req = create_step (bevent);
var e = step_out ();
req.Disable ();
var frames = e.Thread.GetFrames ();
var locs = frames [0].Method.Locations;
var next_loc = locs.First (l => (l.LineNumber == frames [0].Location.LineNumber + 2));
e.Thread.SetIP (next_loc);
/* Check that i = 5; j = 5; was skipped */
bevent = run_until ("set_ip_2");
var f = bevent.Thread.GetFrames ()[1];
AssertValue (1, f.GetValue (f.Method.GetLocal ("i")));
AssertValue (0, f.GetValue (f.Method.GetLocal ("j")));
// Error handling
AssertThrows<ArgumentNullException> (delegate {
e.Thread.SetIP (null);
});
AssertThrows<ArgumentException> (delegate {
e.Thread.SetIP (invalid_loc);
});
}
[Test]
public void NewInstanceNoCtor () {
var bevent = run_until ("Main");
var stype = bevent.Method.DeclaringType.Assembly.GetType ("AStruct");
var obj = stype.NewInstance ();
Assert.IsTrue (obj is ObjectMirror);
Assert.AreEqual ("AStruct", (obj as ObjectMirror).Type.Name);
}
}
}