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 (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 (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 ClassLocalReflection () { MethodMirror m = entry_point.DeclaringType.Assembly.GetType ("LocalReflectClass").GetMethod ("RunMe"); Assert.IsNotNull (m); //Console.WriteLine ("X: " + name + " " + m.ILOffsets.Count + " " + m.Locations.Count); var offset = -1; int method_base_linum = m.Locations [0].LineNumber; foreach (var location in m.Locations) if (location.LineNumber == method_base_linum + 2) { offset = location.ILOffset; break; } var req = vm.SetBreakpoint (m, offset); 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); e = single_step (e.Thread); var frame = e.Thread.GetFrames ()[0]; Value variable = frame.GetValue (frame.Method.GetLocal ("reflectMe")); ObjectMirror thisObj = (ObjectMirror)variable; TypeMirror thisType = thisObj.Type; FieldInfoMirror thisFi = null; foreach (var fi in thisType.GetFields ()) if (fi.Name == "someField") thisFi = fi; var gotVal = thisObj.GetValue (thisFi); // If we got this far, we're good. } [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 next line e = step_into (); 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_1"); e = step_into (); assert_location (e, "ss_nested_1"); e = step_into (); assert_location (e, "ss_nested"); 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 (delegate () { val = arr [2]; }); AssertThrows (delegate () { val = arr [Int32.MinValue]; }); AssertThrows (delegate () { vals = arr.GetValues (0, 3); }); AssertThrows (delegate () { arr [2] = vm.CreateValue (null); }); AssertThrows (delegate () { arr [Int32.MinValue] = vm.CreateValue (null); }); AssertThrows (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 (delegate () { arr.GetLength (-1); }); AssertThrows (delegate () { arr.GetLength (2); }); AssertThrows (delegate () { arr.GetLowerBound (-1); }); AssertThrows (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 (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 (delegate () { o.GetValues (null); }); AssertThrows (delegate () { o.GetValues (new FieldInfoMirror [] { null }); }); // field of another class AssertThrows (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 (delegate () { o.SetValues (null, new Value [0]); }); AssertThrows (delegate () { o.SetValues (new FieldInfoMirror [0], null); }); AssertThrows (delegate () { o.SetValues (new FieldInfoMirror [] { null }, new Value [1] { null }); }); // vtype with a wrong type AssertThrows (delegate () { o.SetValue (o.Type.GetField ("field_struct"), o.GetValue (o.Type.GetField ("field_enum"))); }); // reference type not assignment compatible AssertThrows (delegate () { o.SetValue (o.Type.GetField ("field_class"), o); }); // field of another class AssertThrows (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 (delegate () { o.Type.SetValue (null, vm.CreateValue (0)); }); AssertThrows (delegate () { o.Type.SetValue (o.Type.GetField ("static_i"), null); }); // field of another class AssertThrows (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); // TypedReferences t = frame.Method.GetParameters ()[11].ParameterType; Assert.AreEqual ("TypedReference", t.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 (delegate () { t.GetValue (null); }); // instance fields AssertThrows (delegate () { t.GetValue (o.Type.GetField ("field_i")); }); // field on another type AssertThrows (delegate () { t.GetValue (val2.Type.GetField ("static_field_j")); }); // special static field AssertThrows (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 (delegate () { t.GetValues (null); }); AssertThrows (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 (delegate () { TypeMirror t = child.Type; }); */ /* AssertThrows (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"]); // typedbyref var typedref = frame.GetArgument (2) as StructMirror; Assert.IsTrue (typedref is StructMirror); // Argument checking s = frame.GetArgument (0) as StructMirror; AssertThrows (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 (9, locals.Length); for (int i = 0; i < 9; ++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 if (locals [i].Name == "alist") { } 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]); if (locals [i].Name == "alist") { } } // Argument checking // GetValue () null AssertThrows (delegate () { frame.GetValue ((LocalVariable)null); }); // GetValue () local from another method AssertThrows (delegate () { frame.GetValue (m1.GetLocal ("foo")); }); // GetValue () null AssertThrows (delegate () { frame.GetValue ((ParameterInfoMirror)null); }); // GetValue () local from another method AssertThrows (delegate () { frame.GetValue (m1.GetParameters ()[0]); }); // GetValues () null AssertThrows (delegate () { frame.GetValues (null); }); // GetValues () embedded null AssertThrows (delegate () { frame.GetValues (new LocalVariable [] { null }); }); // GetValues () local from another method AssertThrows (delegate () { frame.GetValues (new LocalVariable [] { m1.GetLocal ("foo") }); }); // return value AssertThrows (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 (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 (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 (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 (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 (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 (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 (delegate () { vm.RootDomain.CreateBoxedValue (null); }); AssertThrows (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); } #if NET_4_5 // out argument m = t.GetMethod ("invoke_out"); var out_task = this_obj.InvokeMethodAsyncWithResult (e.Thread, m, new Value [] { vm.CreateValue (1), vm.CreateValue (null) }, InvokeOptions.ReturnOutArgs); var out_args = out_task.Result.OutArgs; AssertValue (5, out_args [0]); Assert.IsTrue (out_args [1] is ArrayMirror); Assert.AreEqual (10, (out_args [1] as ArrayMirror).Length); // without ReturnOutArgs flag out_task = this_obj.InvokeMethodAsyncWithResult (e.Thread, m, new Value [] { vm.CreateValue (1), vm.CreateValue (null) }); out_args = out_task.Result.OutArgs; Assert.IsNull (out_args); #endif // 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); // virtual call m = t.BaseType.GetMethod ("virtual_method"); v = this_obj.InvokeMethod (e.Thread, m, null, InvokeOptions.Virtual); AssertValue ("V2", v); // virtual call on static method m = t.GetMethod ("invoke_static_pass_ref"); v = t.InvokeMethod (e.Thread, m, new Value [] { vm.RootDomain.CreateString ("ABC") }, InvokeOptions.Virtual); AssertValue ("ABC", 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 (delegate { m = t.GetMethod ("invoke_pass_ref"); v = this_obj.InvokeMethod (null, m, new Value [] { vm.CreateValue (null) }); }); // null method AssertThrows (delegate { v = this_obj.InvokeMethod (e.Thread, null, new Value [] { vm.CreateValue (null) }); }); // invalid number of arguments m = t.GetMethod ("invoke_pass_ref"); AssertThrows (delegate { v = this_obj.InvokeMethod (e.Thread, m, null); }); // invalid type of argument (ref != primitive) m = t.GetMethod ("invoke_pass_ref"); AssertThrows (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 (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 (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 (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 boxed struct as this var boxed_this = t.NewInstance () as ObjectMirror; m = t.GetMethod ("invoke_return_int"); v = boxed_this.InvokeMethod (e.Thread, m, null); AssertValue (0, 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); // .ctor s = frame.GetArgument (1) as StructMirror; t = s.Type; m = t.GetMethods ().First (method => method.Name == ".ctor" && method.GetParameters ().Length == 1); v = t.InvokeMethod (e.Thread, m, new Value [] { vm.CreateValue (1) }); AssertValue (1, (v as StructMirror)["i"]); #if NET_4_5 // Invoke a method which changes state s = frame.GetArgument (1) as StructMirror; t = s.Type; m = t.GetMethod ("invoke_mutate"); var task = s.InvokeMethodAsyncWithResult (e.Thread, m, null, InvokeOptions.ReturnOutThis); var out_this = task.Result.OutThis as StructMirror; AssertValue (5, out_this ["l"]); // Without the ReturnOutThis flag s = frame.GetArgument (1) as StructMirror; t = s.Type; m = t.GetMethod ("invoke_mutate"); task = s.InvokeMethodAsyncWithResult (e.Thread, m, null); out_this = task.Result.OutThis as StructMirror; Assert.AreEqual (null, out_this); // interface method var cl1 = frame.Method.DeclaringType.Assembly.GetType ("ITest2"); m = cl1.GetMethod ("invoke_iface"); v = s.InvokeMethod (e.Thread, m, null); AssertValue (42, v); // virtual method m = vm.RootDomain.Corlib.GetType ("System.Object").GetMethod ("ToString"); v = s.InvokeMethod (e.Thread, m, null, InvokeOptions.Virtual); AssertValue ("42", v); #endif } [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 (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 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 (); 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 InvokeAbort () { vm.Detach (); Start (new string [] { "dtest-app.exe", "invoke-abort" }); Event e = run_until ("invoke_abort"); StackFrame f = e.Thread.GetFrames ()[0]; var obj = f.GetThis () as ObjectMirror; var t = obj.Type; var m = t.GetMethod ("invoke_abort_2"); // Invoke multiple times to check that the subsequent invokes are aborted too var res = (IInvokeAsyncResult)obj.BeginInvokeMultiple (e.Thread, new MethodMirror[] { m, m, m, m }, null, InvokeOptions.None, delegate { }, null); Thread.Sleep (500); res.Abort (); AssertThrows (delegate { obj.EndInvokeMethod (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 (delegate () { frame.SetValue ((LocalVariable)null, vm.CreateValue (55)); }); // value null AssertThrows (delegate () { l = frame.Method.GetLocal ("i"); frame.SetValue (l, null); }); // value of invalid type AssertThrows (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 (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 MemberInOtherDomain () { vm.Detach (); Start (new string [] { "dtest-app.exe", "domain-test" }); vm.EnableEvents (EventType.AppDomainCreate, EventType.AppDomainUnload, EventType.AssemblyUnload); Event e = run_until ("domains_print_across"); var frame = e.Thread.GetFrames ()[0]; var inOtherDomain = frame.GetArgument (0) as ObjectMirror; var crossDomainField = (ObjectMirror) inOtherDomain.GetValue (inOtherDomain.Type.GetField("printMe")); Assert.AreEqual ("SentinelClass", crossDomainField.Type.Name); } [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 (domain, frames [0].Domain); Assert.AreEqual ("invoke", frames [1].Method.Name); Assert.AreEqual ("domains", frames [2].Method.Name); Assert.AreEqual (vm.RootDomain, frames [2].Domain); // 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 (delegate { d_method.DeclaringType.GetValue (d_method.DeclaringType.GetField ("static_i")); }); // Check that .Domain is accessible for stack frames with native transitions e = run_until ("called_from_invoke"); ThreadMirror.NativeTransitions = true; foreach (var f in e.Thread.GetFrames ()) { var dom = f.Domain; } } [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 (delegate { t.InvokeMethod (e.Thread, m, null); }); // Check that the frame info is invalidated run_until ("frames_in_native_2"); AssertThrows (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 (delegate () { vm.CreateEnumMirror (enumType, null); }); AssertThrows (delegate () { vm.CreateEnumMirror (null, vm.CreateValue (1)); }); // null value AssertThrows (delegate () { vm.CreateEnumMirror (enumType, vm.CreateValue (null)); }); // value of a wrong type AssertThrows (delegate () { vm.CreateEnumMirror (enumType, vm.CreateValue ((long)1)); }); } [Test] public void VirtualMachine_EnableEvents_Breakpoint () { AssertThrows (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_GetValue () { // Embedded nulls object val; // Reuse this test var e = run_until ("arg2"); var frame = e.Thread.GetFrames () [0]; val = frame.GetArgument (6); Assert.AreEqual ('\0'.ToString () + "A", (val as StringMirror).Value); } [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 (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 () { 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 (delegate { gm.MakeGenericMethod (null); }); AssertThrows (delegate { gm.MakeGenericMethod (new TypeMirror [] { null }); }); AssertThrows (delegate { gm.MakeGenericMethod (new TypeMirror [] { stringm, stringm }); }); AssertThrows (delegate { gm.MakeGenericMethod (new TypeMirror [] { intm }); }); AssertThrows (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 ++; j = 5; was skipped */ bevent = run_until ("set_ip_2"); var f = bevent.Thread.GetFrames ()[1]; AssertValue (2, f.GetValue (f.Method.GetLocal ("i"))); AssertValue (0, f.GetValue (f.Method.GetLocal ("j"))); // Error handling AssertThrows (delegate { e.Thread.SetIP (null); }); AssertThrows (delegate { e.Thread.SetIP (invalid_loc); }); } [Test] public void SetIPSingleStep () { // Check that single stepping after set-ip steps from the new ip var bevent = run_until ("set_ip_1"); var invalid_loc = bevent.Thread.GetFrames ()[0].Location; var req = create_step (bevent); req.Size = StepSize.Line; var e = step_out (); req.Disable (); var frames = e.Thread.GetFrames (); var locs = frames [0].Method.Locations; var prev_loc = locs.First (l => (l.LineNumber == frames [0].Location.LineNumber - 3)); AssertValue (2, frames [0].GetValue (frames [0].Method.GetLocal ("i"))); // Set back the ip to the first i ++; line e.Thread.SetIP (prev_loc); e = step_over (); var f = e.Thread.GetFrames ()[0]; AssertValue (3, f.GetValue (f.Method.GetLocal ("i"))); } [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); } [Test] public void StaticCtorFilterInCctor () { // Check that single stepping when in a cctor only ignores // other cctors, not the current one var bevent = run_until ("step_filters"); var assembly = entry_point.DeclaringType.Assembly; var type = assembly.GetType ("Tests/ClassWithCctor"); var cctor = type.GetMethod (".cctor"); vm.SetBreakpoint (cctor, 0); vm.Resume (); var e = vm.GetNextEvent (); Assert.IsTrue (e is BreakpointEvent); var req = create_step (e); req.Filter = StepFilter.StaticCtor; e = step_into (); // Make sure we are still in the cctor Assert.AreEqual (".cctor", e.Thread.GetFrames ()[0].Location.Method.Name); } } }