[w32handle] Unify WaitHandle.Wait{One,Any,All} icalls (#5051)
[mono.git] / mcs / class / Mono.Debugger.Soft / Test / dtest.cs
index 1933fc5e827372129731655297986401622ff064..7a16e5dcb83b1927bff434a6abb6604646d2845e 100644 (file)
@@ -63,17 +63,30 @@ public class DebuggerTests
                Start (false, args);
        }
 
+       Diag.ProcessStartInfo CreateStartInfo (string[] args) {
+               var pi = new Diag.ProcessStartInfo ();
+
+               if (runtime != null) {
+                       pi.FileName = runtime;
+               } else if (Path.DirectorySeparatorChar == '\\') {
+                       string processExe = Diag.Process.GetCurrentProcess ().MainModule.FileName;
+                       if (processExe != null) {
+                               string fileName = Path.GetFileName (processExe);
+                               if (fileName.StartsWith ("mono") && fileName.EndsWith (".exe"))
+                                       pi.FileName = processExe;
+                       }
+               }
+               if (string.IsNullOrEmpty (pi.FileName))
+                       pi.FileName = "mono";
+               pi.Arguments = String.Join (" ", args);
+               return pi;
+       }
+
        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);
+                       var pi = CreateStartInfo (args);
                        vm = VirtualMachineManager.Launch (pi, new LaunchOptions { AgentArgs = agent_args });
                } else {
                        var ep = new IPEndPoint (IPAddress.Any, 10000);
@@ -550,7 +563,11 @@ public class DebuggerTests
                MethodMirror m = entry_point.DeclaringType.Assembly.GetType ("LocalReflectClass").GetMethod ("RunMe");
 
                Assert.IsNotNull (m);
-               //Console.WriteLine ("X: " + name + " " + m.ILOffsets.Count + " " + m.Locations.Count);
+
+//             foreach (var x in m.Locations) {
+//                     Console.WriteLine (x);
+//             }
+
                var offset = -1;
                int method_base_linum = m.Locations [0].LineNumber;
                foreach (var location in m.Locations)
@@ -578,7 +595,11 @@ public class DebuggerTests
                e = single_step (e.Thread);
 
                var frame = e.Thread.GetFrames ()[0];
-               Value variable = frame.GetValue (frame.Method.GetLocal ("reflectMe"));
+
+               Assert.IsNotNull (frame);
+               var field = frame.Method.GetLocal ("reflectMe");
+               Assert.IsNotNull (field);
+               Value variable = frame.GetValue (field);
 
                ObjectMirror thisObj = (ObjectMirror)variable;
                TypeMirror thisType = thisObj.Type;
@@ -707,23 +728,53 @@ public class DebuggerTests
                assert_location (e, "ss6");
                req.Disable ();
 
-               // Check that a step over stops at an EH clause
+               // Testing stepping in, over and out with exception handlers in same or caller method
+
+               //stepout in ss7_2, which may not go to catch(instead out to ss7)
                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 ();
+               create_step (e);
+               assert_location (step_out(), "ss7");
+
+               //stepout in ss7_2_1, which must go to catch
+               run_until ("ss7_2_1");
+               assert_location (step_out (), "ss7_2");
+
+               //stepover over ss7_2, which must go to catch
+               run_until ("ss7_2");
+               assert_location (step_over (), "ss7_2");//move to "try {" line
+               assert_location (step_over (), "ss7_2");//move to "ss7_2_2();" line
+               assert_location (step_over (), "ss7_2");//step over ss7_2_2();, assume we are at "catch" now
+               assert_location (step_over (), "ss7_2");//move to { of catch
+               assert_location (step_over (), "ss7_2");//move to } of catch
+               assert_location (step_over (), "ss7_2");//move to } of method
+               assert_location (step_over (), "ss7");//finish method
+
+               //stepover over ss7_2_1, which must go to catch
+               run_until ("ss7_2_1");
+               assert_location (step_over (), "ss7_2_1");//move from { of method to "throw new Exception ();"
+               assert_location (step_over (), "ss7_2");//step over exception, being in ss7_2 means we are at catch
+
+               //stepin in ss7_3, which must go to catch
+               run_until ("ss7_3");
+               assert_location (step_into (), "ss7_3");//move to "try {"
+               assert_location (step_into (), "ss7_3");//move to "throw new Exception ();"
+               step_req.Disable ();
+               step_req.AssemblyFilter = new AssemblyMirror [] { (e as BreakpointEvent).Method.DeclaringType.Assembly };
+               assert_location (step_into (), "ss7_3");//call "throw new Exception ();", we assume we end up at "catch"
+               assert_location (step_into (), "ss7_3");//move to { of catch
+               assert_location (step_into (), "ss7_3");//move to } of catch
+               assert_location (step_into (), "ss7_3");//move to } of method
+               assert_location (step_into (), "ss7");//move out to ss7
+
+               //stepover in ss7_2_1, which must go to catch
+               run_until ("ss7_2_1");
+               assert_location (step_into (), "ss7_2_1");//move from { of method to "throw new Exception ();"
+               assert_location (step_into (), "ss7_2");//step in exception, being in ss7_2 means we are at catch
+               step_req.Disable ();
 
                // Check that stepping stops between nested calls
                e = run_until ("ss_nested_2");
+               req = create_step (e);
                e = step_out ();
                assert_location (e, "ss_nested");
                e = step_into ();
@@ -734,6 +785,14 @@ public class DebuggerTests
                e = step_over ();
                assert_location (e, "ss_nested");
                e = step_into ();
+               assert_location (e, "ss_nested_2");
+               e = step_into ();
+               assert_location (e, "ss_nested_2");
+               e = step_into ();
+               assert_location (e, "ss_nested_2");
+               e = step_into ();
+               assert_location (e, "ss_nested");
+               e = step_into ();
                assert_location (e, "ss_nested_1");
                e = step_into ();
                assert_location (e, "ss_nested_1");
@@ -802,6 +861,7 @@ public class DebuggerTests
                                req.Size = StepSize.Line;
 
                                e = step_out ();
+                               e = step_over ();//Stepout gets us to ss_recursive2_trap ();, move to ss_recursive2 (next); line
                                assert_location (e, "ss_recursive2");
 
                                // Stack should consist of Main + single_stepping + (1 ss_recursive2 frame per loop iteration)
@@ -888,6 +948,164 @@ public class DebuggerTests
                f = e.Thread.GetFrames ()[0];
                AssertValue (7.0, f.GetValue (f.Method.GetParameters ()[0]));
                req.Disable ();
+
+               e = run_until ("ss_await");
+               e = step_in_await ("ss_await", e);//ss_await_1 ().Wait ();//in
+               e = step_in_await ("MoveNext", e);//{
+               e = step_in_await ("MoveNext", e);//var a = 1;
+               e = step_in_await ("MoveNext", e);//await Task.Delay (10);
+               e = step_in_await ("MoveNext", e);//return a + 2;
+               e = step_in_await ("MoveNext", e);//}
+               e = step_in_await ("ss_await", e);//ss_await_1 ().Wait ();//in
+
+               e = step_in_await ("ss_await", e);//ss_await_1 ().Wait ();//over
+               e = step_in_await ("MoveNext", e);//{
+               e = step_over_await ("MoveNext", e);//var a = 1;
+               e = step_over_await ("MoveNext", e);//await Task.Delay (10);
+               e = step_over_await ("MoveNext", e);//return a + 2;
+               e = step_over_await ("MoveNext", e);//}
+               e = step_over_await ("ss_await", e);//ss_await_1 ().Wait ();//over
+
+               e = step_in_await ("ss_await", e);//ss_await_1 ().Wait ();//out before
+               e = step_in_await ("MoveNext", e);//{
+               e = step_out_await ("ss_await", e);//ss_await_1 ().Wait ();//out before
+
+               e = step_in_await ("ss_await", e);//ss_await_1 ().Wait ();//out after
+               e = step_in_await ("MoveNext", e);//{
+               e = step_in_await ("MoveNext", e);//var a = 1;
+               e = step_in_await ("MoveNext", e);//await Task.Delay (10);
+               e = step_in_await ("MoveNext", e);//return a + 2;
+               e = step_out_await ("ss_await", e);//ss_await_1 ().Wait ();//out after
+
+               e = step_in_await ("ss_await", e);//ss_await_1_exc (true, true).Wait ();//in
+               e = step_in_await ("MoveNext", e);//{
+               e = step_in_await ("MoveNext", e);//var a = 1;
+               e = step_in_await ("MoveNext", e);//await Task.Delay (10);
+               e = step_in_await ("MoveNext", e);//if (exc)
+               e = step_in_await ("MoveNext", e);//{
+               e = step_in_await ("MoveNext", e);//if (handled)
+               e = step_in_await ("MoveNext", e);//{
+               e = step_in_await ("MoveNext", e);//try {
+               e = step_in_await ("MoveNext", e);//throw new Exception ();
+               e = step_in_await ("MoveNext", e);//catch
+               e = step_in_await ("MoveNext", e);//{
+               e = step_in_await ("MoveNext", e);//}
+               e = step_in_await ("MoveNext", e);//}
+               e = step_in_await ("MoveNext", e);//}
+               e = step_in_await ("MoveNext", e);//return a + 2;
+               e = step_in_await ("MoveNext", e);//}
+               e = step_in_await ("ss_await", e);//ss_await_1_exc (true, true).Wait ();//in
+
+               e = step_in_await ("ss_await", e);//ss_await_1_exc (true, true).Wait ();//over
+               e = step_in_await ("MoveNext", e);//{
+               e = step_over_await ("MoveNext", e);//var a = 1;
+               e = step_over_await ("MoveNext", e);//await Task.Delay (10);
+               e = step_over_await ("MoveNext", e);//if (exc)
+               e = step_over_await ("MoveNext", e);//{
+               e = step_over_await ("MoveNext", e);//if (handled)
+               e = step_over_await ("MoveNext", e);//{
+               e = step_over_await ("MoveNext", e);//try {
+               e = step_over_await ("MoveNext", e);//throw new Exception ();
+               e = step_over_await ("MoveNext", e);//catch
+               e = step_over_await ("MoveNext", e);//{
+               e = step_over_await ("MoveNext", e);//}
+               e = step_over_await ("MoveNext", e);//}
+               e = step_over_await ("MoveNext", e);//}
+               e = step_over_await ("MoveNext", e);//return a + 2;
+               e = step_over_await ("MoveNext", e);//}
+               e = step_over_await ("ss_await", e);//ss_await_1_exc (true, true).Wait ();//over
+
+               e = step_in_await ("ss_await", e);//ss_await_1_exc (true, true).Wait ();//out
+               e = step_in_await ("MoveNext", e);//{
+               e = step_out_await ("ss_await", e);//ss_await_1_exc (true, true).Wait ();//out
+
+               e = step_in_await ("ss_await", e);//try {
+               e = step_in_await ("ss_await", e);//ss_await_1_exc (true, false).Wait ();//in
+               e = step_in_await ("MoveNext", e);//{
+               e = step_in_await ("MoveNext", e);//var a = 1;
+               e = step_in_await ("MoveNext", e);//await Task.Delay (10);
+               e = step_in_await ("MoveNext", e);//if (exc)
+               e = step_in_await ("MoveNext", e);//{
+               e = step_in_await ("MoveNext", e);//if (handled)
+               e = step_in_await ("MoveNext", e);//} else {
+               e = step_in_await ("MoveNext", e);//throw new Exception ();
+               e = step_in_await ("ss_await", e);//catch
+               e = step_in_await ("ss_await", e);//{
+               e = step_in_await ("ss_await", e);//}
+               e = step_in_await ("ss_await", e);//try {
+
+               e = step_in_await ("ss_await", e);//ss_await_1_exc (true, false).Wait ();//over
+               e = step_in_await ("MoveNext", e);//{
+               e = step_over_await ("MoveNext", e);//var a = 1;
+               e = step_over_await ("MoveNext", e);//await Task.Delay (10);
+               e = step_over_await ("MoveNext", e);//if (exc)
+               e = step_over_await ("MoveNext", e);//{
+               e = step_over_await ("MoveNext", e);//if (handled)
+               e = step_over_await ("MoveNext", e);//} else {
+               e = step_over_await ("MoveNext", e);//throw new Exception ();
+               e = step_over_await ("ss_await", e);//catch
+               e = step_over_await ("ss_await", e);//{
+               e = step_over_await ("ss_await", e);//}
+               e = step_over_await ("ss_await", e);//try {
+
+               e = step_in_await ("ss_await", e);//ss_await_1_exc (true, false).Wait ();//out
+               e = step_in_await ("MoveNext", e);//{
+               e = step_out_await ("ss_await", e);//ss_await_1_exc (true, true).Wait ();//out
+       }
+
+       Event step_in_await (string method, Event e)
+       {
+               if (step_req != null)
+                       step_req.Disable ();
+               create_step (e);
+               step_req.AssemblyFilter = new List<AssemblyMirror> () { entry_point.DeclaringType.Assembly };
+               var ef = step_into ();
+               assert_location (ef, method);
+               return ef;
+       }
+
+       Event step_over_await (string method, Event e)
+       {
+               if (step_req != null)
+                       step_req.Disable ();
+               create_step (e);
+               step_req.AssemblyFilter = new List<AssemblyMirror> () { entry_point.DeclaringType.Assembly };
+               var ef = step_over ();
+               assert_location (ef, method);
+               return ef;
+       }
+
+       Event step_out_await (string method, Event e)
+       {
+               if (step_req != null)
+                       step_req.Disable ();
+               create_step (e);
+               step_req.AssemblyFilter = new List<AssemblyMirror> () { entry_point.DeclaringType.Assembly };
+               var ef = step_out ();
+               assert_location (ef, method);
+               return ef;
+       }
+
+       [Test]
+       public void SingleSteppingNoFrames () {
+               //
+               // Test what happens when starting a single step operation on a thread
+               // with no managed frames
+               //
+               // Run a delegate on a tp thread
+               var e = run_until ("ss_no_frames_2");
+
+               var this_type = e.Thread.GetFrames ()[0].Method.DeclaringType;
+               this_type.SetValue (this_type.GetField ("static_i"), vm.CreateValue (56));
+
+               var thread = e.Thread;
+               var e2 = run_until ("ss_no_frames_3");
+               // The tp thread should be idle now
+               step_req = vm.CreateStepRequest (thread);
+               step_req.Depth = StepDepth.Over;
+               AssertThrows<Exception> (delegate {
+                       step_req.Enable ();
+                       });
        }
 
        [Test]
@@ -1767,6 +1985,16 @@ public class DebuggerTests
                AssertValue ("T", s ["s"]);
                AssertValue (45, s ["k"]);
 
+               // Test SetThis ()
+               s ["i"] = vm.CreateValue (55);
+               frame.SetThis (s);
+               obj = frame.GetThis ();
+               Assert.IsTrue (obj is StructMirror);
+               s = obj as StructMirror;
+               AssertValue (55, 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");
@@ -2389,6 +2617,11 @@ public class DebuggerTests
                m = s.Type.GetMethod ("ToString");
                v = s.InvokeMethod (e.Thread, m, null);
 
+               // pass nullable as argument
+               m = t.GetMethod ("invoke_pass_nullable");
+               v = this_obj.InvokeMethod (e.Thread, m, new Value [] { s });
+               AssertValue (42, v);
+
                // return nullable null
                m = t.GetMethod ("invoke_return_nullable_null");
                v = this_obj.InvokeMethod (e.Thread, m, null);
@@ -2402,6 +2635,24 @@ public class DebuggerTests
                m = s.Type.GetMethod ("ToString");
                v = s.InvokeMethod (e.Thread, m, null);
 
+               // pass nullable null as argument
+               m = t.GetMethod ("invoke_pass_nullable_null");
+               v = this_obj.InvokeMethod (e.Thread, m, new Value [] { s });
+               AssertValue (2, v);
+
+               return;
+
+               // string constructor
+               var stringType = vm.RootDomain.Corlib.GetType ("System.String");
+               var stringConstructor = stringType.GetMethods ().Single (c=>
+                       c.Name == ".ctor" &&
+                       c.GetParameters ().Length == 2 &&
+                       c.GetParameters ()[0].ParameterType.Name == "Char" &&
+                       c.GetParameters ()[1].ParameterType.Name == "Int32");
+               var str = stringType.NewInstance (e.Thread, stringConstructor,  new Value [] { vm.CreateValue ('a'), vm.CreateValue (3)});
+
+               AssertValue("aaa", str);
+
                // pass primitive
                m = t.GetMethod ("invoke_pass_primitive");
                Value[] args = new Value [] {
@@ -3267,6 +3518,7 @@ public class DebuggerTests
                // d_method is from another domain
                MethodMirror d_method = (e as BreakpointEvent).Method;
                Assert.IsTrue (m != d_method);
+               Assert.AreEqual (domain, d_method.DeclaringType.Assembly.Domain);
 
                var frames = e.Thread.GetFrames ();
                Assert.AreEqual ("invoke_in_domain", frames [0].Method.Name);
@@ -3297,6 +3549,9 @@ public class DebuggerTests
                        vm.Resume ();
                        e = GetNextEvent ();
                        if (e is AssemblyUnloadEvent) {
+                               AssertThrows<Exception> (delegate () {
+                                               var assembly_obj = (e as AssemblyUnloadEvent).Assembly.GetAssemblyObject ();
+                                       });
                                continue;
                        } else {
                                break;
@@ -3575,6 +3830,8 @@ public class DebuggerTests
                        return;
 
                string srcfile = (e as BreakpointEvent).Method.DeclaringType.GetSourceFiles (true)[0];
+               srcfile = srcfile.Replace ("dtest-app.cs", "TypeLoadClass.cs");
+               Assert.IsTrue (srcfile.Contains ("TypeLoadClass.cs"));
 
                var req = vm.CreateTypeLoadRequest ();
                req.SourceFileFilter = new string [] { srcfile.ToUpper () };
@@ -3888,7 +4145,7 @@ public class DebuggerTests
 
                frames = thread.GetFrames ();
                Assert.AreEqual (8, frames.Length, "#7");
-               Assert.AreEqual ("WaitOne_internal", frames [0].Method.Name, "#8.0");
+               Assert.AreEqual ("Wait_internal", frames [0].Method.Name, "#8.0");
                Assert.AreEqual ("WaitOneNative", frames [1].Method.Name, "#8.1");
                Assert.AreEqual ("InternalWaitOne", frames [2].Method.Name, "#8.2");
                Assert.AreEqual ("WaitOne", frames [3].Method.Name, "#8.3");
@@ -3955,7 +4212,8 @@ public class DebuggerTests
                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));
+
+               var next_loc = locs.First (l => (l.LineNumber == frames [0].Location.LineNumber + 3));
 
                e.Thread.SetIP (next_loc);
 
@@ -3988,7 +4246,7 @@ public class DebuggerTests
                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));
+               var prev_loc = locs.First (l => (l.LineNumber == frames [0].Location.LineNumber - 1));
                AssertValue (2, frames [0].GetValue (frames [0].Method.GetLocal ("i")));
 
                // Set back the ip to the first i ++; line
@@ -4021,7 +4279,7 @@ public class DebuggerTests
                vm.SetBreakpoint (cctor, 0);
 
                vm.Resume ();
-               var e = vm.GetNextEvent ();
+               var e = GetNextEvent ();
                Assert.IsTrue (e is BreakpointEvent);
 
                var req = create_step (e);
@@ -4046,6 +4304,69 @@ public class DebuggerTests
                e = step_out (); // leave threadpool_bp
                e = step_out (); // leave threadpool_io
        }
+
+       [Test]
+       // Uses a fixed port
+       [Category("NotWorking")]
+       public void Attach () {
+               vm.Exit (0);
+
+               // Launch the app using server=y,suspend=n
+               var pi = CreateStartInfo (new string[] { "--debugger-agent=transport=dt_socket,address=127.0.0.1:10000,server=y,suspend=n", "dtest-app.exe", "attach" });
+               var process = Diag.Process.Start (pi);
+
+               // Wait for the app to reach the Sleep () in attach ().
+               Thread.Sleep (1000);
+               var ep = new IPEndPoint (IPAddress.Loopback, 10000);
+               vm = VirtualMachineManager.Connect (ep);
+
+               var load_req = vm.CreateAssemblyLoadRequest ();
+               load_req.Enable ();
+               vm.EnableEvents (EventType.TypeLoad);
+
+               Event vmstart = GetNextEvent ();
+               Assert.AreEqual (EventType.VMStart, vmstart.EventType);
+
+               // Get collected events
+               bool assembly_load_found = false;
+               bool type_load_found = false;
+               while (true) {
+                       Event e = GetNextEvent ();
+
+                       // AssemblyLoad
+                       if (e is AssemblyLoadEvent) {
+                               var assemblyload = e as AssemblyLoadEvent;
+
+                               var amirror = assemblyload.Assembly;
+
+                               if (amirror.GetName ().Name == "System.Transactions") {
+                                       assembly_load_found = true;
+                                       Assert.AreEqual ("domain", amirror.Domain.FriendlyName);
+                               }
+
+                               if (amirror.GetName ().Name == "dtest-app")
+                                       // Set a bp so we can break the event loop
+                                       vm.SetBreakpoint (amirror.EntryPoint.DeclaringType.GetMethod ("attach_break"), 0);
+                       }
+                       if (e is TypeLoadEvent) {
+                               var typeload = e as TypeLoadEvent;
+
+                               if (typeload.Type.Name == "GCSettings") {
+                                       type_load_found = true;
+                                       Assert.AreEqual ("domain", typeload.Type.Assembly.Domain.FriendlyName);
+                               }
+                       }
+
+                       if (e is BreakpointEvent)
+                               break;
+               }
+               Assert.IsTrue (assembly_load_found);
+               Assert.IsTrue (type_load_found);
+
+               vm.Exit (0);
+               vm = null;
+       }
+
 }
 
 }