a575963da9
Former-commit-id: da6be194a6b1221998fc28233f2503bd61dd9d14
3527 lines
96 KiB
C#
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);
|
|
}
|
|
}
|
|
|
|
}
|