2010-06-15 Zoltan Varga <vargaz@gmail.com>
authorZoltan Varga <vargaz@gmail.com>
Tue, 15 Jun 2010 14:56:29 +0000 (14:56 -0000)
committerZoltan Varga <vargaz@gmail.com>
Tue, 15 Jun 2010 14:56:29 +0000 (14:56 -0000)
* *: Add testing infrastructure by moving the tests from mono/tests.

svn path=/trunk/mcs/; revision=158947

mcs/class/Mono.Debugger.Soft/ChangeLog
mcs/class/Mono.Debugger.Soft/Makefile
mcs/class/Mono.Debugger.Soft/Mono.Debugger.Soft_test.dll.sources [new file with mode: 0644]
mcs/class/Mono.Debugger.Soft/Test/ChangeLog [new file with mode: 0644]
mcs/class/Mono.Debugger.Soft/Test/dtest-app.cs [new file with mode: 0644]
mcs/class/Mono.Debugger.Soft/Test/dtest.cs [new file with mode: 0644]

index 26d2fb3667ec3fa9b2c6eb72639c7a1ccd350b7d..d53983913c2c9a4bb20c800115f16ae045b0f204 100644 (file)
@@ -1,3 +1,7 @@
+2010-06-15  Zoltan Varga  <vargaz@gmail.com>
+
+       * *: Add testing infrastructure by moving the tests from mono/tests.
+
 2009-11-03  Zoltan Varga  <vargaz@gmail.com>
 
        * Makefile: Don't define LIBRARY_PACKAGE so it gets installed normally.
index 8cd47da1705439368c9226e03c2319d8d23bc11e..b07afb6694f79fae9786a50ee97f5ade5a0ba3fa 100644 (file)
@@ -6,7 +6,16 @@ LIBRARY_SNK = ../mono.snk
 
 LIB_MCS_FLAGS = /r:$(corlib) /r:System.dll /r:Mono.Cecil.dll /r:System.Core.dll /unsafe -D:MONO_DATACONVERTER_STATIC_METHODS -keyfile:$(LIBRARY_SNK)
 
-NO_TEST = yes
+TEST_MCS_FLAGS = /r:Mono.Cecil.dll
+
+check: dtest-app.exe
+
+dtest-app.exe:
+       $(CSCOMPILE) -out:$@ -unsafe -debug Test/dtest-app.cs
+
+CLEAN_FILES = dtest-app.exe dtest-app.exe.mdb
+
+#NO_TEST = yes
 
 ifneq (net_2_0, $(PROFILE))
 NO_INSTALL = yes
diff --git a/mcs/class/Mono.Debugger.Soft/Mono.Debugger.Soft_test.dll.sources b/mcs/class/Mono.Debugger.Soft/Mono.Debugger.Soft_test.dll.sources
new file mode 100644 (file)
index 0000000..a0dffae
--- /dev/null
@@ -0,0 +1 @@
+dtest.cs
diff --git a/mcs/class/Mono.Debugger.Soft/Test/ChangeLog b/mcs/class/Mono.Debugger.Soft/Test/ChangeLog
new file mode 100644 (file)
index 0000000..01d039e
--- /dev/null
@@ -0,0 +1,5 @@
+2010-06-15  Zoltan Varga  <vargaz@gmail.com>
+
+       * dtest.cs dtest-app.cs: New files containing the soft debugger tests, moved here
+       from mono/tests.
+
diff --git a/mcs/class/Mono.Debugger.Soft/Test/dtest-app.cs b/mcs/class/Mono.Debugger.Soft/Test/dtest-app.cs
new file mode 100644 (file)
index 0000000..6e60b95
--- /dev/null
@@ -0,0 +1,743 @@
+/*
+ * dtest-app.cs:
+ *
+ *   Application program used by the debugger tests.
+ */
+using System;
+using System.Runtime.CompilerServices;
+using System.Reflection;
+using System.Reflection.Emit;
+using System.Diagnostics;
+using System.Threading;
+using System.Collections.Generic;
+using System.Linq;
+
+public class TestsBase
+{
+#pragma warning disable 0414
+#pragma warning disable 0169
+       public int base_field_i;
+       public string base_field_s;
+       static int base_static_i = 57;
+       static string base_static_s = "C";
+#pragma warning restore 0414
+#pragma warning restore 0169
+}
+
+public enum AnEnum {
+       A = 0,
+       B= 1
+}
+
+[DebuggerDisplay ("Tests", Name="FOO", Target=typeof (int))]
+[DebuggerTypeProxy (typeof (Tests))]
+public class Tests2 {
+       [DebuggerBrowsableAttribute (DebuggerBrowsableState.Collapsed)]
+       public int field_j;
+       public static int static_field_j;
+
+       [DebuggerBrowsableAttribute (DebuggerBrowsableState.Collapsed)]
+       public int AProperty {
+               get {
+                       return 0;
+               }
+       }
+
+       public void invoke () {
+       }
+}
+
+public struct AStruct {
+       public int i;
+       public string s;
+       public byte k;
+       public IntPtr j;
+
+       [MethodImplAttribute (MethodImplOptions.NoInlining)]
+       public int foo (int val) {
+               return val;
+       }
+
+       [MethodImplAttribute (MethodImplOptions.NoInlining)]
+       public static int static_foo (int val) {
+               return val;
+       }
+
+       [MethodImplAttribute (MethodImplOptions.NoInlining)]
+       public int invoke_return_int () {
+               return i;
+       }
+
+       [MethodImplAttribute (MethodImplOptions.NoInlining)]
+       public static int invoke_static () {
+               return 5;
+       }
+
+       [MethodImplAttribute (MethodImplOptions.NoInlining)]
+       public IntPtr invoke_return_intptr () {
+               return j;
+       }
+}
+
+public class GClass<T> {
+       public T field;
+       public static T static_field;
+
+       [MethodImplAttribute (MethodImplOptions.NoInlining)]
+       public GClass () {
+       }
+}
+
+public struct GStruct<T> {
+       public T i;
+
+       public int j;
+
+       [MethodImplAttribute (MethodImplOptions.NoInlining)]
+       public int invoke_return_int () {
+               return j;
+       }
+}
+
+public class Tests : TestsBase
+{
+#pragma warning disable 0414
+       int field_i;
+       string field_s;
+       AnEnum field_enum;
+       bool field_bool1, field_bool2;
+       char field_char;
+       byte field_byte;
+       sbyte field_sbyte;
+       short field_short;
+       ushort field_ushort;
+       long field_long;
+       ulong field_ulong;
+       float field_float;
+       double field_double;
+       Thread field_class;
+       IntPtr field_intptr;
+       static int static_i = 55;
+       static string static_s = "A";
+       public const int literal_i = 56;
+       public const string literal_s = "B";
+       public object child;
+       public AStruct field_struct;
+       public object field_boxed_struct;
+       public GStruct<int> generic_field_struct;
+       [ThreadStatic]
+       public static int tls_i;
+       public static bool is_attached = Debugger.IsAttached;
+
+#pragma warning restore 0414
+
+       public class NestedClass {
+       }
+
+       public int IntProperty {
+               get {
+                       return field_i;
+               }
+               set {
+                       field_i = value;
+               }
+       }
+
+       public int ReadOnlyProperty {
+               get {
+                       return field_i;
+               }
+       }
+
+       public int this [int index] {
+               get {
+                       return field_i;
+               }
+       }
+
+       public static int Main (String[] args) {
+               if (args.Length > 0 && args [0] == "suspend-test")
+                       /* This contains an infinite loop, so execute it conditionally */
+                       suspend ();
+               breakpoints ();
+               single_stepping ();
+               arguments ();
+               objects ();
+               objrefs ();
+               vtypes ();
+               locals ();
+               line_numbers ();
+               type_info ();
+               assembly_load ();
+               invoke ();
+               exceptions ();
+               threads ();
+               dynamic_methods ();
+               if (args.Length > 0 && args [0] == "domain-test")
+                       /* This takes a lot of time, so execute it conditionally */
+                       domains ();
+               if (args.Length > 0 && args [0] == "ref-emit-test")
+                       ref_emit ();
+               if (args.Length > 0 && args [0] == "frames-in-native")
+                       frames_in_native ();
+               if (args.Length >0 && args [0] == "invoke-single-threaded")
+                       new Tests ().invoke_single_threaded ();
+               return 3;
+       }
+
+       public static void breakpoints () {
+               /* Call these early so it is JITted by the time a breakpoint is placed on it */
+               bp3 ();
+               bp7<int> ();
+               bp7<string> ();
+
+               bp1 ();
+               bp2 ();
+               bp3 ();
+               bp4 ();
+               bp4 ();
+               bp4 ();
+               bp5 ();
+               bp6<string> ();
+               bp7<int> ();
+               bp7<string> ();
+       }
+
+       [MethodImplAttribute (MethodImplOptions.NoInlining)]
+       public static void bp1 () {
+       }
+
+       [MethodImplAttribute (MethodImplOptions.NoInlining)]
+       public static void bp2 () {
+       }
+
+       [MethodImplAttribute (MethodImplOptions.NoInlining)]
+       public static void bp3 () {
+       }
+
+       [MethodImplAttribute (MethodImplOptions.NoInlining)]
+       public static void bp4 () {
+       }
+
+       [MethodImplAttribute (MethodImplOptions.NoInlining)]
+       public static void bp5 () {
+       }
+
+       [MethodImplAttribute (MethodImplOptions.NoInlining)]
+       public static void bp6<T> () {
+       }
+
+       [MethodImplAttribute (MethodImplOptions.NoInlining)]
+       public static void bp7<T> () {
+       }
+
+       [MethodImplAttribute (MethodImplOptions.NoInlining)]
+       public static void single_stepping () {
+               ss1 ();
+               ss2 ();
+               ss3 ();
+               ss3_2 ();
+               ss4 ();
+               ss5 (new int [] { 1, 2, 3 }, new Func<int, bool> (is_even));
+               try {
+                       ss6 (true);
+               } catch {
+               }
+       }
+
+       [MethodImplAttribute (MethodImplOptions.NoInlining)]
+       public static void ss1 () {
+       }
+
+       [MethodImplAttribute (MethodImplOptions.NoInlining)]
+       public static void ss2 () {
+       }
+
+       [MethodImplAttribute (MethodImplOptions.NoInlining)]
+       public static int ss3 () {
+               int sum = 0;
+
+               for (int i = 0; i < 10; ++i)
+                       sum += i;
+
+               return sum;
+       }
+
+       [MethodImplAttribute (MethodImplOptions.NoInlining)]
+       public static void ss3_2 () {
+               ss3_2_2 ();
+       }
+
+       [MethodImplAttribute (MethodImplOptions.NoInlining)]
+       public static void ss3_2_2 () {
+       }
+
+       [MethodImplAttribute (MethodImplOptions.NoInlining)]
+       public static int ss4 () {
+               ss1 (); ss1 ();
+               ss2 ();
+               return 0;
+       }
+
+       [MethodImplAttribute (MethodImplOptions.NoInlining)]
+       public static void ss5 (int[] arr, Func<int, bool> selector) {
+               // Call into linq which calls back into this assembly
+               arr.Count (selector);
+       }
+
+       [MethodImplAttribute (MethodImplOptions.NoInlining)]
+       public static void ss6 (bool b) {
+               if (b) {
+                       ss7 ();
+                       throw new Exception ();
+               }
+       }
+
+       [MethodImplAttribute (MethodImplOptions.NoInlining)]
+       public static void ss7 () {
+       }
+
+       [MethodImplAttribute (MethodImplOptions.NoInlining)]
+       public static bool is_even (int i) {
+               return i % 2 == 0;
+       }
+
+       /*
+               lock (static_s) {
+                       Console.WriteLine ("HIT!");
+               }
+               return 0;
+       }
+       */
+
+       [MethodImplAttribute (MethodImplOptions.NoInlining)]
+       public static void arguments () {
+               arg1 (SByte.MaxValue - 5, Byte.MaxValue - 5, true, Int16.MaxValue - 5, UInt16.MaxValue - 5, 'F', Int32.MaxValue - 5, UInt32.MaxValue - 5, Int64.MaxValue - 5, UInt64.MaxValue - 5, 1.2345f, 6.78910, new IntPtr (Int32.MaxValue - 5), new UIntPtr (UInt32.MaxValue - 5));
+               int i = 42;
+               arg2 ("FOO", null, "BLA", ref i, new GClass <int> { field = 42 }, new object ());
+               Tests t = new Tests () { field_i = 42, field_s = "S" };
+               t.arg3 ("BLA");
+       }
+
+       [MethodImplAttribute (MethodImplOptions.NoInlining)]
+       public static int arg1 (sbyte sb, byte b, bool bl, short s, ushort us, char c, int i, uint ui, long l, ulong ul, float f, double d, IntPtr ip, UIntPtr uip) {
+               return (int)(sb + b + (bl ? 0 : 1) + s + us + (int)c + i + ui + l + (long)ul + f + d + (int)ip + (int)uip);
+       }
+
+       [MethodImplAttribute (MethodImplOptions.NoInlining)]
+       public static string arg2 (string s, string s3, object o, ref int i, GClass <int> gc, object o2) {
+               return s + (s3 != null ? "" : "") + o + i + gc.field + o2;
+       }
+
+       [MethodImplAttribute (MethodImplOptions.NoInlining)]
+       public object arg3 (string s) {
+               return s + s + s + s + this;
+       }
+
+       [MethodImplAttribute (MethodImplOptions.NoInlining)]
+       public static void objects () {
+               Tests t = new Tests () { field_i = 42, field_bool1 = true, field_bool2 = false, field_char = 'A', field_byte = 129, field_sbyte = -33, field_short = Int16.MaxValue - 5, field_ushort = UInt16.MaxValue - 5, field_long = Int64.MaxValue - 5, field_ulong = UInt64.MaxValue - 5, field_float = 3.14f, field_double = 3.14f, field_s = "S", base_field_i = 43, base_field_s = "T", field_enum = AnEnum.B, field_class = null, field_intptr = new IntPtr (Int32.MaxValue - 5) };
+               t.o1 (new Tests2 () { field_j = 43 }, new GClass <int> { field = 42 }, new GClass <string> { field = "FOO" });
+               o2 (new string [] { "BAR", "BAZ" }, new int[] { 42, 43 }, new int [,] { { 1, 2 }, { 3, 4 }}, (int[,])Array.CreateInstance (typeof (int), new int [] { 2, 2}, new int [] { 1, 3}), new int[] { 0 });
+       }
+
+       [MethodImplAttribute (MethodImplOptions.NoInlining)]
+       public object o1 (Tests2 t, GClass <int> gc1, GClass <string> gc2) {
+               if (t == null || gc1 == null || gc2 == null)
+                       return null;
+               else
+                       return this;
+       }
+
+       [MethodImplAttribute (MethodImplOptions.NoInlining)]
+       public static string o2 (string[] s2, int[] s3, int[,] s4, int[,] s5, IList<int> s6) {
+               return s2 [0] + s3 [0] + s4 [0, 0] + s6 [0];
+       }
+
+       [MethodImplAttribute (MethodImplOptions.NoInlining)]
+       public static void objrefs () {
+               Tests t = new Tests () {};
+               set_child (t);
+               t.objrefs1 ();
+               t.child = null;
+               GC.Collect ();
+               objrefs2 ();
+       }
+
+       [MethodImplAttribute (MethodImplOptions.NoInlining)]
+       public static void set_child (Tests t) {
+               t.child = new Tests ();
+       }
+
+       [MethodImplAttribute (MethodImplOptions.NoInlining)]
+       public void objrefs1 () {
+       }
+
+       [MethodImplAttribute (MethodImplOptions.NoInlining)]
+       public static void objrefs2 () {
+       }
+
+       public static void vtypes () {
+               Tests t = new Tests () { field_struct = new AStruct () { i = 42, s = "S", k = 43 }, generic_field_struct = new GStruct<int> () { i = 42 }, field_boxed_struct = new AStruct () { i = 42 }};
+               AStruct s = new AStruct { i = 44, s = "T", k = 45 };
+               AStruct[] arr = new AStruct[] { 
+                       new AStruct () { i = 1, s = "S1" },
+                       new AStruct () { i = 2, s = "S2" } };
+               t.vtypes1 (s, arr);
+               vtypes2 (s);
+               vtypes3 (s);
+       }
+
+       [MethodImplAttribute (MethodImplOptions.NoInlining)]
+       public object vtypes1 (AStruct s, AStruct[] arr) {
+               if (arr != null)
+                       return this;
+               else
+                       return null;
+       }
+
+       [MethodImplAttribute (MethodImplOptions.NoInlining)]
+       public static void vtypes2 (AStruct s) {
+               s.foo (5);
+       }
+
+       [MethodImplAttribute (MethodImplOptions.NoInlining)]
+       public static void vtypes3 (AStruct s) {
+               AStruct.static_foo (5);
+       }
+
+       [MethodImplAttribute (MethodImplOptions.NoInlining)]
+       public static void locals () {
+               locals1 (null);
+               locals2 (null, 5);
+               locals3 ();
+       }
+
+       [MethodImplAttribute (MethodImplOptions.NoInlining)]
+       public static void locals1 (string[] args) {
+               long foo = 42;
+
+               for (int j = 0; j < 10; ++j) {
+                       foo ++;
+               }
+       }
+
+       [MethodImplAttribute (MethodImplOptions.NoInlining)]
+       public static void locals2 (string[] args, int arg) {
+               long i = 42;
+               string s = "AB";
+
+               for (int j = 0; j < 10; ++j) {
+                       if (s != null)
+                               i ++;
+               }
+       }
+
+       [MethodImplAttribute (MethodImplOptions.NoInlining)]
+       public static void locals3 () {
+               string s = "B";
+               s.ToString ();
+
+               {
+                       long i = 42;
+                       i ++;
+                       locals4 ();
+               }
+               {
+                       string i = "A";
+                       i.ToString ();
+                       locals5 ();
+               }
+               {
+                       long j = 42;
+                       j ++;
+               }
+       }
+
+       [MethodImplAttribute (MethodImplOptions.NoInlining)]
+       public static void locals4 () {
+       }
+
+       [MethodImplAttribute (MethodImplOptions.NoInlining)]
+       public static void locals5 () {
+       }
+
+       [MethodImplAttribute (MethodImplOptions.NoInlining)]
+       public static void line_numbers () {
+               LineNumbers.ln1 ();
+       }
+
+       [MethodImplAttribute (MethodImplOptions.NoInlining)]
+       public static void suspend () {
+               long i = 5;
+
+               while (true) {
+                       i ++;
+               }
+       }
+
+       [MethodImplAttribute (MethodImplOptions.NoInlining)]
+       public static void type_info () {
+               Tests t = new Tests () { field_i = 42, field_s = "S", base_field_i = 43, base_field_s = "T", field_enum = AnEnum.B };
+               t.ti1 (new Tests2 () { field_j = 43 }, new GClass <int> { field = 42 }, new GClass <string> { field = "FOO" });
+               int val = 0;
+               unsafe {
+                       AStruct s = new AStruct () { i = 42, s = "S", k = 43 };
+
+                       ti2 (new string [] { "BAR", "BAZ" }, new int[] { 42, 43 }, new int [,] { { 1, 2 }, { 3, 4 }}, ref val, (int*)IntPtr.Zero, 5, s, new Tests (), new Tests2 (), new GClass <int> (), AnEnum.B);
+               }
+       }
+
+       [MethodImplAttribute (MethodImplOptions.NoInlining)]
+       public object ti1 (Tests2 t, GClass <int> gc1, GClass <string> gc2) {
+               if (t == null || gc1 == null || gc2 == null)
+                       return null;
+               else
+                       return this;
+       }
+
+       [MethodImplAttribute (MethodImplOptions.NoInlining)]
+       public static unsafe string ti2 (string[] s2, int[] s3, int[,] s4, ref int ri, int* ptr, int i, AStruct s, Tests t, Tests2 t2, GClass<int> g, AnEnum ae) {
+               return s2 [0] + s3 [0] + s4 [0, 0];
+       }
+
+       [MethodImplAttribute (MethodImplOptions.NoInlining)]
+       public static void assembly_load () {
+               assembly_load_2 ();
+       }
+
+       [MethodImplAttribute (MethodImplOptions.NoInlining)]
+       public static void assembly_load_2 () {
+               // This will load System.dll while holding the loader lock
+               new Foo ();
+       }
+
+       [MethodImplAttribute (MethodImplOptions.NoInlining)]
+       public static void invoke () {
+               new Tests ().invoke1 (new Tests2 (), new AStruct () { i = 42, j = (IntPtr)43 }, new GStruct<int> { j = 42 });
+       }
+
+       [MethodImplAttribute (MethodImplOptions.NoInlining)]
+       public void invoke1 (Tests2 t, AStruct s, GStruct<int> g) {
+               invoke2 ();
+       }
+
+       [MethodImplAttribute (MethodImplOptions.NoInlining)]
+       public void invoke2 () {
+       }
+
+       int counter;
+
+       [MethodImplAttribute (MethodImplOptions.NoInlining)]
+       public void invoke_single_threaded () {
+               // Spawn a thread incrementing a counter
+               bool finished = false;
+
+               new Thread (delegate () {
+                               while (!finished)
+                                       counter ++;
+               }).Start ();
+
+               Thread.Sleep (100);
+
+               invoke_single_threaded_2 ();
+
+               finished = true;
+       }
+
+       [MethodImplAttribute (MethodImplOptions.NoInlining)]
+       public void invoke_single_threaded_2 () {
+       }
+
+       public void invoke_return_void () {
+       }
+
+       public string invoke_return_ref () {
+               return "ABC";
+       }
+
+       public object invoke_return_null () {
+               return null;
+       }
+
+       public int invoke_return_primitive () {
+               return 42;
+       }
+
+       public void invoke_type_load () {
+               new Class3 ();
+       }
+
+       class Class3 {
+       }
+
+       public long invoke_pass_primitive (byte ub, sbyte sb, short ss, ushort us, int i, uint ui, long l, ulong ul, char c, bool b, float f, double d) {
+               return ub + sb + ss + us + i + ui + l + (long)ul + (int)c + (b ? 1 : 0) + (int)f + (int)d;
+       }
+
+       public int invoke_pass_primitive2 (bool b) {
+               return b ? 1 : 0;
+       }
+
+       public string invoke_pass_ref (string s) {
+               return s;
+       }
+
+       public static string invoke_static_pass_ref (string s) {
+               return s;
+       }
+
+       public static void invoke_static_return_void () {
+       }
+
+       public static void invoke_throws () {
+               throw new Exception ();
+       }
+
+       [MethodImplAttribute (MethodImplOptions.NoInlining)]
+       public static void exceptions () {
+               try {
+                       throw new OverflowException ();
+               } catch (Exception) {
+               }
+               try {
+                       throw new OverflowException ();
+               } catch (Exception) {
+               }
+               try {
+                       throw new ArgumentException ();
+               } catch (Exception) {
+               }
+               try {
+                       throw new OverflowException ();
+               } catch (Exception) {
+               }
+
+               object o = null;
+               try {
+                       o.GetType ();
+               } catch (Exception) {
+               }
+       }
+
+       [MethodImplAttribute (MethodImplOptions.NoInlining)]
+       public static void threads () {
+               Thread t = new Thread (delegate () {});
+
+               t.Start ();
+               t.Join ();
+       }
+
+       [MethodImplAttribute (MethodImplOptions.NoInlining)]
+       public static void domains () {
+               AppDomain domain = AppDomain.CreateDomain ("domain");
+
+               CrossDomain o = (CrossDomain)domain.CreateInstanceAndUnwrap (
+                                  typeof (CrossDomain).Assembly.FullName, "CrossDomain");
+
+               o.invoke_2 ();
+
+               o.invoke ();
+
+               o.invoke_2 ();
+
+               AppDomain.Unload (domain);
+
+               domains_2 ();
+       }
+
+       [MethodImplAttribute (MethodImplOptions.NoInlining)]
+       public static void domains_2 () {
+       }
+
+       [MethodImplAttribute (MethodImplOptions.NoInlining)]
+       public static void invoke_in_domain () {
+       }
+
+       [MethodImplAttribute (MethodImplOptions.NoInlining)]
+       public static void invoke_in_domain_2 () {
+       }
+
+       [MethodImplAttribute (MethodImplOptions.NoInlining)]
+       public static void dynamic_methods () {
+               var m = new DynamicMethod ("dyn_method", typeof (void), new Type []  { typeof (int) }, typeof (object).Module);
+               var ig = m.GetILGenerator ();
+
+               ig.Emit (OpCodes.Ldstr, "FOO");
+               ig.Emit (OpCodes.Call, typeof (Tests).GetMethod ("dyn_call"));
+               ig.Emit (OpCodes.Ret);
+
+               var del = (Action<int>)m.CreateDelegate (typeof (Action<int>));
+
+               del (0);
+       }
+
+       public static void dyn_call (string s) {
+       }
+
+       [MethodImplAttribute (MethodImplOptions.NoInlining)]
+       public static void ref_emit () {
+               AssemblyName assemblyName = new AssemblyName ();
+               assemblyName.Name = "foo";
+
+               AssemblyBuilder assembly =
+                       Thread.GetDomain ().DefineDynamicAssembly (
+                                                                                                          assemblyName, AssemblyBuilderAccess.RunAndSave);
+
+               ModuleBuilder module = assembly.DefineDynamicModule ("foo.dll");
+
+               TypeBuilder tb = module.DefineType ("foo", TypeAttributes.Public, typeof (object));
+               MethodBuilder mb = tb.DefineMethod ("ref_emit_method", MethodAttributes.Public|MethodAttributes.Static, CallingConventions.Standard, typeof (void), new Type [] { });
+               ILGenerator ig = mb.GetILGenerator ();
+               ig.Emit (OpCodes.Ldstr, "FOO");
+               ig.Emit (OpCodes.Call, typeof (Tests).GetMethod ("ref_emit_call"));
+               ig.Emit (OpCodes.Ret);
+
+               Type t = tb.CreateType ();
+
+               t.GetMethod ("ref_emit_method").Invoke (null, null);
+       }
+
+       [MethodImplAttribute (MethodImplOptions.NoInlining)]
+       public static void ref_emit_call (string s) {
+       }
+
+       [MethodImplAttribute (MethodImplOptions.NoInlining)]
+       public static void frames_in_native () {
+               Thread.Sleep (500);
+       }
+}
+
+public class CrossDomain : MarshalByRefObject
+{
+       public void invoke () {
+               Tests.invoke_in_domain ();
+       }
+
+       public void invoke_2 () {
+               Tests.invoke_in_domain_2 ();
+       }
+}      
+
+public class Foo
+{
+       public ProcessStartInfo info;
+}
+
+// Class used for line number info testing, don't change its layout
+public class LineNumbers
+{
+       [MethodImplAttribute (MethodImplOptions.NoInlining)]
+       public static void ln1 () {
+               ln2 ();
+               ln3 ();
+       }
+
+       [MethodImplAttribute (MethodImplOptions.NoInlining)]
+       public static void ln2 () {
+       }
+
+       [MethodImplAttribute (MethodImplOptions.NoInlining)]
+       public static void ln3 () {
+       }
+}
diff --git a/mcs/class/Mono.Debugger.Soft/Test/dtest.cs b/mcs/class/Mono.Debugger.Soft/Test/dtest.cs
new file mode 100644 (file)
index 0000000..3b639ba
--- /dev/null
@@ -0,0 +1,2358 @@
+using System;
+using System.Collections.Generic;
+using System.Threading;
+using System.Net;
+using System.Reflection;
+using Mono.Cecil.Cil;
+using Mono.Debugger.Soft;
+using Diag = System.Diagnostics;
+using System.Linq;
+
+using NUnit.Framework;
+
+#pragma warning disable 0219
+
+[TestFixture]
+public class DebuggerTests
+{
+       VirtualMachine vm;
+       MethodMirror entry_point;
+       StepEventRequest step_req;
+
+       void AssertThrows<ExType> (Action del) where ExType : Exception {
+               bool thrown = false;
+
+               try {
+                       del ();
+               } catch (ExType) {
+                       thrown = true;
+               }
+               Assert.IsTrue (thrown);
+       }
+
+       // No other way to pass arguments to the tests ?
+       public static bool listening = Environment.GetEnvironmentVariable ("DBG_SUSPEND") != null;
+       public static string runtime = Environment.GetEnvironmentVariable ("DBG_RUNTIME");
+       public static string agent_args = Environment.GetEnvironmentVariable ("DBG_AGENT_ARGS");
+
+       void Start (string[] args) {
+               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 {
+                       Console.WriteLine ("Listening...");
+                       vm = VirtualMachineManager.Listen (new IPEndPoint (IPAddress.Any, 10000));
+               }
+
+               vm.EnableEvents (EventType.AssemblyLoad);
+
+               Event vmstart = vm.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 = vm.GetNextEvent ();
+
+                       if (e is AssemblyLoadEvent) {
+                               AssemblyLoadEvent ae = (AssemblyLoadEvent)e;
+                               entry_point = ae.Assembly.EntryPoint;
+                               if (entry_point != null)
+                                       break;
+                       }
+
+                       vm.Resume ();
+               }
+       }
+
+       BreakpointEvent run_until (string name) {
+               // String
+               MethodMirror m = entry_point.DeclaringType.GetMethod (name);
+               Assert.IsNotNull (m);
+               vm.SetBreakpoint (m, 0);
+
+               Event e = null;
+
+               while (true) {
+                       vm.Resume ();
+                       e = vm.GetNextEvent ();
+                       if (e is BreakpointEvent)
+                               break;
+               }
+
+               Assert.IsInstanceOfType (typeof (BreakpointEvent), e);
+               Assert.AreEqual (m, (e as BreakpointEvent).Method);
+
+               return (e as BreakpointEvent);
+       }
+
+       Event single_step (ThreadMirror t) {
+               var req = vm.CreateStepRequest (t);
+               req.Enable ();
+
+               vm.Resume ();
+               Event e = vm.GetNextEvent ();
+               Assert.IsTrue (e is StepEvent);
+
+               req.Disable ();
+
+               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 () {
+               Start (new string [] { "dtest-app.exe" });
+       }
+
+       [TearDown]
+       public void TearDown () {
+               if (vm == null)
+                       return;
+
+               if (step_req != null)
+                       step_req.Disable ();
+
+               vm.Resume ();
+               while (true) {
+                       Event e = vm.GetNextEvent ();
+
+                       if (e is VMDeathEvent)
+                               break;
+
+                       vm.Resume ();
+               }
+       }
+
+       [Test]
+       public void SimpleBreakpoint () {
+               Event e;
+
+               MethodMirror m = entry_point.DeclaringType.GetMethod ("bp1");
+               Assert.IsNotNull (m);
+
+               vm.SetBreakpoint (m, 0);
+
+               vm.Resume ();
+
+               e = vm.GetNextEvent ();
+               Assert.AreEqual (EventType.Breakpoint, e.EventType);
+               Assert.IsTrue (e is BreakpointEvent);
+               Assert.AreEqual (m.Name, (e as BreakpointEvent).Method.Name);
+
+               // Argument checking
+               AssertThrows<ArgumentException> (delegate {
+                               // Invalid IL offset
+                               vm.SetBreakpoint (m, 1);
+                       });
+       }
+
+       [Test]
+       public void BreakpointsSameLocation () {
+               Event e;
+
+               MethodMirror m = entry_point.DeclaringType.GetMethod ("bp2");
+               Assert.IsNotNull (m);
+
+               vm.SetBreakpoint (m, 0);
+               vm.SetBreakpoint (m, 0);
+
+               vm.Resume ();
+
+               e = vm.GetNextEvent ();
+               Assert.IsTrue (e is BreakpointEvent);
+               Assert.AreEqual (m, (e as BreakpointEvent).Method);
+
+               e = vm.GetNextEvent ();
+               Assert.IsTrue (e is BreakpointEvent);
+               Assert.AreEqual (m.Name, (e 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 = vm.GetNextEvent ();
+               Assert.AreEqual (EventType.Breakpoint, e.EventType);
+               Assert.AreEqual (m.Name, (e as BreakpointEvent).Method.Name);
+
+               vm.Resume ();
+
+               /* Non-shared instance */
+               e = vm.GetNextEvent ();
+               Assert.AreEqual (EventType.Breakpoint, e.EventType);
+               Assert.AreEqual (m2.Name, (e as BreakpointEvent).Method.Name);
+
+               vm.Resume ();
+
+               /* Shared instance */
+               e = vm.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 ();
+
+               e = vm.GetNextEvent ();
+               Assert.AreEqual (EventType.Breakpoint, e.EventType);
+               Assert.AreEqual (m.Name, (e as BreakpointEvent).Method.Name);
+               e = vm.GetNextEvent ();
+               Assert.AreEqual (EventType.Breakpoint, e.EventType);
+               Assert.AreEqual (m.Name, (e as BreakpointEvent).Method.Name);
+
+               /* Clear one of them */
+               req1.Disable ();
+
+               vm.Resume ();
+
+               e = vm.GetNextEvent ();
+               Assert.AreEqual (EventType.Breakpoint, e.EventType);
+               Assert.AreEqual (m.Name, (e as BreakpointEvent).Method.Name);
+
+               /* Clear the other */
+               req2.Disable ();
+
+               vm.Resume ();
+
+               e = vm.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 = vm.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 = vm.GetNextEvent ();
+               Assert.AreEqual (EventType.Breakpoint, e.EventType);
+               Assert.IsTrue (e is BreakpointEvent);
+               Assert.AreEqual (m.Name, (e as BreakpointEvent).Method.Name);
+       }
+
+       [Test]
+       public void SingleStepping () {
+               Event e = run_until ("single_stepping");
+
+               var req = vm.CreateStepRequest (e.Thread);
+               req.Enable ();
+
+               step_req = req;
+
+               // Step into ss1
+               vm.Resume ();
+               e = vm.GetNextEvent ();
+               Assert.IsTrue (e is StepEvent);
+               Assert.AreEqual ("ss1", (e as StepEvent).Method.Name);
+
+               // Step out of ss1
+               vm.Resume ();
+               e = vm.GetNextEvent ();
+               Assert.IsTrue (e is StepEvent);
+               Assert.AreEqual ("single_stepping", (e as StepEvent).Method.Name);
+
+               // Change to step over
+               req.Disable ();
+               req.Depth = StepDepth.Over;
+               req.Enable ();
+
+               // Step over ss2
+               vm.Resume ();
+               e = vm.GetNextEvent ();
+               Assert.IsTrue (e is StepEvent);
+               Assert.AreEqual ("single_stepping", (e as StepEvent).Method.Name);
+
+               // Change to step into
+               req.Disable ();
+               req.Depth = StepDepth.Into;
+               req.Enable ();
+
+               // Step into ss3
+               vm.Resume ();
+               e = vm.GetNextEvent ();
+               Assert.IsTrue (e is StepEvent);
+               Assert.AreEqual ("ss3", (e as StepEvent).Method.Name);
+
+               // Change to step out
+               req.Disable ();
+               req.Depth = StepDepth.Out;
+               req.Enable ();
+
+               // Step back into single_stepping
+               vm.Resume ();
+               e = vm.GetNextEvent ();
+               Assert.IsTrue (e is StepEvent);
+               Assert.AreEqual ("single_stepping", (e as StepEvent).Method.Name);
+
+               // Change to step into
+               req.Disable ();
+               req.Depth = StepDepth.Into;
+               req.Enable ();
+
+               // Step into ss3_2 ()
+               vm.Resume ();
+               e = vm.GetNextEvent ();
+               Assert.IsTrue (e is StepEvent);
+               Assert.AreEqual ("ss3_2", (e as StepEvent).Method.Name);
+
+               // Change to step over
+               req.Disable ();
+               req.Depth = StepDepth.Over;
+               req.Enable ();
+
+               // Step over ss3_2_2 ()
+               vm.Resume ();
+               e = vm.GetNextEvent ();
+               Assert.IsTrue (e is StepEvent);
+               Assert.AreEqual ("ss3_2", (e as StepEvent).Method.Name);
+
+               // Recreate the request
+               req.Disable ();
+               req.Enable ();
+
+               // Step back into single_stepping () with the new request
+               vm.Resume ();
+               e = vm.GetNextEvent ();
+               Assert.IsTrue (e is StepEvent);
+               Assert.AreEqual ("single_stepping", (e as StepEvent).Method.Name);
+
+               // Change to step into
+               req.Disable ();
+               req.Depth = StepDepth.Into;
+               req.Enable ();
+
+               // Step into ss4 ()
+               vm.Resume ();
+               e = vm.GetNextEvent ();
+               Assert.IsTrue (e is StepEvent);
+               Assert.AreEqual ("ss4", (e as StepEvent).Method.Name);
+
+               // Change to StepSize.Line
+               req.Disable ();
+               req.Depth = StepDepth.Over;
+               req.Size = StepSize.Line;
+               req.Enable ();
+
+               // Step over ss1 (); ss1 ();
+               vm.Resume ();
+               e = vm.GetNextEvent ();
+               Assert.IsTrue (e is StepEvent);
+
+               // Step into ss2 ()
+               req.Disable ();
+               req.Depth = StepDepth.Into;
+               req.Enable ();
+
+               vm.Resume ();
+               e = vm.GetNextEvent ();
+               Assert.IsTrue (e is StepEvent);
+               Assert.AreEqual ("ss2", (e as StepEvent).Method.Name);
+
+               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 ();
+
+               // Step into is_even, skipping the linq stuff
+               vm.Resume ();
+               e = vm.GetNextEvent ();
+               Assert.IsTrue (e is StepEvent);
+               Assert.AreEqual ("is_even", (e as StepEvent).Method.Name);
+
+               // FIXME: Check that single stepping works with lock (obj)
+               
+               req.Disable ();
+
+               // Run until ss6
+               e = run_until ("ss6");
+
+               req = vm.CreateStepRequest (e.Thread);
+               req.Depth = StepDepth.Over;
+               req.Enable ();
+
+               // Check that single stepping works in out-of-line bblocks
+               vm.Resume ();
+               e = vm.GetNextEvent ();
+               Assert.IsTrue (e is StepEvent);
+               vm.Resume ();
+               e = vm.GetNextEvent ();
+               Assert.IsTrue (e is StepEvent);
+               Assert.AreEqual ("ss6", (e as StepEvent).Method.Name);
+
+               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 = vm.GetNextEvent ();
+               Assert.IsTrue (e is MethodEntryEvent);
+               Assert.AreEqual ("ss1", (e as MethodEntryEvent).Method.Name);
+
+               vm.Resume ();
+               e = vm.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 = vm.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 = vm.GetNextEvent ();
+               Assert.IsTrue (e is BreakpointEvent);
+
+               req1.Disable ();
+       }
+
+       [Test]
+       public void Arguments () {
+               object val;
+
+               var e = run_until ("arg1");
+
+               StackFrame frame = e.Thread.GetFrames () [0];
+
+               check_arg_val (frame, 0, typeof (sbyte), SByte.MaxValue - 5);
+               check_arg_val (frame, 1, typeof (byte), Byte.MaxValue - 5);
+               check_arg_val (frame, 2, typeof (bool), true);
+               check_arg_val (frame, 3, typeof (short), Int16.MaxValue - 5);
+               check_arg_val (frame, 4, typeof (ushort), UInt16.MaxValue - 5);
+               check_arg_val (frame, 5, typeof (char), 'F');
+               check_arg_val (frame, 6, typeof (int), Int32.MaxValue - 5);
+               check_arg_val (frame, 7, typeof (uint), UInt32.MaxValue - 5);
+               check_arg_val (frame, 8, typeof (long), Int64.MaxValue - 5);
+               check_arg_val (frame, 9, typeof (ulong), UInt64.MaxValue - 5);
+               check_arg_val (frame, 10, typeof (float), 1.2345f);
+               check_arg_val (frame, 11, typeof (double), 6.78910);
+
+               e = run_until ("arg2");
+
+               frame = e.Thread.GetFrames () [0];
+
+               // String
+               val = frame.GetArgument (0);
+               AssertValue ("FOO", val);
+               Assert.AreEqual ("String", (val as ObjectMirror).Type.Name);
+
+               // null
+               val = frame.GetArgument (1);
+               AssertValue (null, val);
+
+               // object
+               val = frame.GetArgument (2);
+               AssertValue ("BLA", val);
+
+               // byref
+               val = frame.GetArgument (3);
+               AssertValue (42, val);
+
+               // generic instance
+               val = frame.GetArgument (4);
+               Assert.IsTrue (val is ObjectMirror);
+               Assert.AreEqual ("GClass`1", (val as ObjectMirror).Type.Name);
+
+               // System.Object
+               val = frame.GetArgument (5);
+               Assert.IsTrue (val is ObjectMirror);
+               Assert.AreEqual ("Object", (val as ObjectMirror).Type.Name);
+
+               // this on static methods
+               val = frame.GetThis ();
+               AssertValue (null, val);
+
+               e = run_until ("arg3");
+
+               frame = e.Thread.GetFrames () [0];
+
+               // this
+               val = frame.GetThis ();
+               Assert.IsTrue (val is ObjectMirror);
+               Assert.AreEqual ("Tests", (val as ObjectMirror).Type.Name);
+
+               // objref in register
+               val = frame.GetArgument (0);
+               AssertValue ("BLA", val);
+       }
+
+       [Test]
+       public void Arrays () {
+               object val;
+
+               var e = run_until ("o2");
+
+               StackFrame frame = e.Thread.GetFrames () [0];
+
+               // String[]
+               val = frame.GetArgument (0);
+               Assert.IsTrue (val is ArrayMirror);
+               ArrayMirror arr = val as ArrayMirror;
+               Assert.AreEqual (2, arr.Length);
+               AssertValue ("BAR", arr [0]);
+               AssertValue ("BAZ", arr [1]);
+
+               var vals = arr.GetValues (0, 2);
+               Assert.AreEqual (2, vals.Count);
+               AssertValue ("BAR", vals [0]);
+               AssertValue ("BAZ", vals [1]);
+
+               arr [0] = vm.RootDomain.CreateString ("ABC");
+               AssertValue ("ABC", arr [0]);
+
+               arr [0] = vm.CreateValue (null);
+               AssertValue (null, arr [0]);
+
+               arr.SetValues (0, new Value [] { vm.RootDomain.CreateString ("D1"), vm.RootDomain.CreateString ("D2") });
+               AssertValue ("D1", arr [0]);
+               AssertValue ("D2", arr [1]);
+
+               // int
+               val = frame.GetArgument (1);
+               Assert.IsTrue (val is ArrayMirror);
+               arr = val as ArrayMirror;
+               Assert.AreEqual (2, arr.Length);
+               AssertValue (42, arr [0]);
+               AssertValue (43, arr [1]);
+
+               // Argument checking
+               AssertThrows<IndexOutOfRangeException> (delegate () {
+                               val = arr [2];
+                       });
+
+               AssertThrows<IndexOutOfRangeException> (delegate () {
+                               val = arr [Int32.MinValue];
+                       });
+
+               AssertThrows<IndexOutOfRangeException> (delegate () {
+                               vals = arr.GetValues (0, 3);
+                       });
+
+               AssertThrows<IndexOutOfRangeException> (delegate () {
+                               arr [2] = vm.CreateValue (null);
+                       });
+
+               AssertThrows<IndexOutOfRangeException> (delegate () {
+                               arr [Int32.MinValue] = vm.CreateValue (null);
+                       });
+
+               AssertThrows<IndexOutOfRangeException> (delegate () {
+                               arr.SetValues (0, new Value [] { null, null, null });
+                       });
+
+               // Multidim arrays
+               val = frame.GetArgument (2);
+               Assert.IsTrue (val is ArrayMirror);
+               arr = val as ArrayMirror;
+               Assert.AreEqual (2, arr.Rank);
+               Assert.AreEqual (4, arr.Length);
+               Assert.AreEqual (2, arr.GetLength (0));
+               Assert.AreEqual (2, arr.GetLength (1));
+               Assert.AreEqual (0, arr.GetLowerBound (0));
+               Assert.AreEqual (0, arr.GetLowerBound (1));
+               vals = arr.GetValues (0, 4);
+               AssertValue (1, vals [0]);
+               AssertValue (2, vals [1]);
+               AssertValue (3, vals [2]);
+               AssertValue (4, vals [3]);
+
+               val = frame.GetArgument (3);
+               Assert.IsTrue (val is ArrayMirror);
+               arr = val as ArrayMirror;
+               Assert.AreEqual (2, arr.Rank);
+               Assert.AreEqual (4, arr.Length);
+               Assert.AreEqual (2, arr.GetLength (0));
+               Assert.AreEqual (2, arr.GetLength (1));
+               Assert.AreEqual (1, arr.GetLowerBound (0));
+               Assert.AreEqual (3, arr.GetLowerBound (1));
+
+               AssertThrows<ArgumentOutOfRangeException> (delegate () {
+                               arr.GetLength (-1);
+                       });
+               AssertThrows<ArgumentOutOfRangeException> (delegate () {
+                               arr.GetLength (2);
+                       });
+
+               AssertThrows<ArgumentOutOfRangeException> (delegate () {
+                               arr.GetLowerBound (-1);
+                       });
+               AssertThrows<ArgumentOutOfRangeException> (delegate () {
+                               arr.GetLowerBound (2);
+                       });
+
+               // arrays treated as generic collections
+               val = frame.GetArgument (4);
+               Assert.IsTrue (val is ArrayMirror);
+               arr = val as ArrayMirror;
+       }
+
+       [Test]
+       public void Object_GetValue () {
+               var e = run_until ("o1");
+               var frame = e.Thread.GetFrames () [0];
+
+               object val = frame.GetThis ();
+               Assert.IsTrue (val is ObjectMirror);
+               Assert.AreEqual ("Tests", (val as ObjectMirror).Type.Name);
+               ObjectMirror o = (val as ObjectMirror);
+
+               TypeMirror t = o.Type;
+
+               // object fields
+               object f = o.GetValue (t.GetField ("field_i"));
+               AssertValue (42, f);
+               f = o.GetValue (t.GetField ("field_s"));
+               AssertValue ("S", f);
+               f = o.GetValue (t.GetField ("field_enum"));
+               Assert.IsTrue (f is EnumMirror);
+               Assert.AreEqual (1, (f as EnumMirror).Value);
+               Assert.AreEqual ("B", (f as EnumMirror).StringValue);
+
+               // Inherited object fields
+               TypeMirror parent = t.BaseType;
+               f = o.GetValue (parent.GetField ("base_field_i"));
+               AssertValue (43, f);
+               f = o.GetValue (parent.GetField ("base_field_s"));
+               AssertValue ("T", f);
+
+               // Static fields
+               f = o.GetValue (o.Type.GetField ("static_i"));
+               AssertValue (55, f);
+
+               // generic instances
+               ObjectMirror o2 = frame.GetValue (frame.Method.GetParameters ()[1]) as ObjectMirror;
+               Assert.AreEqual ("GClass`1", o2.Type.Name);
+               TypeMirror t2 = o2.Type;
+               f = o2.GetValue (t2.GetField ("field"));
+               AssertValue (42, f);
+
+               ObjectMirror o3 = frame.GetValue (frame.Method.GetParameters ()[2]) as ObjectMirror;
+               Assert.AreEqual ("GClass`1", o3.Type.Name);
+               TypeMirror t3 = o3.Type;
+               f = o3.GetValue (t3.GetField ("field"));
+               AssertValue ("FOO", f);
+
+               // Argument checking
+               AssertThrows<ArgumentNullException> (delegate () {
+                       o.GetValue (null);
+                       });
+       }
+
+       [Test]
+       public void Object_GetValues () {
+               var e = run_until ("o1");
+               var frame = e.Thread.GetFrames () [0];
+
+               object val = frame.GetThis ();
+               Assert.IsTrue (val is ObjectMirror);
+               Assert.AreEqual ("Tests", (val as ObjectMirror).Type.Name);
+               ObjectMirror o = (val as ObjectMirror);
+
+               ObjectMirror val2 = frame.GetValue (frame.Method.GetParameters ()[0]) as ObjectMirror;
+
+               TypeMirror t = o.Type;
+
+               object[] vals = o.GetValues (new FieldInfoMirror [] { t.GetField ("field_i"), t.GetField ("field_s") });
+               object f = vals [0];
+               AssertValue (42, f);
+               f = vals [1];
+               AssertValue ("S", f);
+
+               // Argument checking
+               AssertThrows<ArgumentNullException> (delegate () {
+                       o.GetValues (null);
+                       });
+
+               AssertThrows<ArgumentNullException> (delegate () {
+                       o.GetValues (new FieldInfoMirror [] { null });
+                       });
+
+               // field of another class
+               AssertThrows<ArgumentException> (delegate () {
+                               o.GetValue (val2.Type.GetField ("field_j"));
+                       });
+       }
+
+       void TestSetValue (ObjectMirror o, string field_name, object val) {
+               if (val is string)
+                       o.SetValue (o.Type.GetField (field_name), vm.RootDomain.CreateString ((string)val));
+               else
+                       o.SetValue (o.Type.GetField (field_name), vm.CreateValue (val));
+               Value f = o.GetValue (o.Type.GetField (field_name));
+               AssertValue (val, f);
+       }
+
+       [Test]
+       public void Object_SetValues () {
+               var e = run_until ("o1");
+               var frame = e.Thread.GetFrames () [0];
+
+               object val = frame.GetThis ();
+               Assert.IsTrue (val is ObjectMirror);
+               Assert.AreEqual ("Tests", (val as ObjectMirror).Type.Name);
+               ObjectMirror o = (val as ObjectMirror);
+
+               ObjectMirror val2 = frame.GetValue (frame.Method.GetParameters ()[0]) as ObjectMirror;
+
+               TestSetValue (o, "field_i", 22);
+               TestSetValue (o, "field_bool1", false);
+               TestSetValue (o, "field_bool2", true);
+               TestSetValue (o, "field_char", 'B');
+               TestSetValue (o, "field_byte", (byte)129);
+               TestSetValue (o, "field_sbyte", (sbyte)-33);
+               TestSetValue (o, "field_short", (short)(Int16.MaxValue - 5));
+               TestSetValue (o, "field_ushort", (ushort)(UInt16.MaxValue - 5));
+               TestSetValue (o, "field_long", Int64.MaxValue - 5);
+               TestSetValue (o, "field_ulong", (ulong)(UInt64.MaxValue - 5));
+               TestSetValue (o, "field_float", 6.28f);
+               TestSetValue (o, "field_double", 6.28);
+               TestSetValue (o, "static_i", 23);
+               TestSetValue (o, "field_s", "CDEF");
+
+               Value f;
+
+               // intptrs
+               f = o.GetValue (o.Type.GetField ("field_intptr"));
+               Assert.IsInstanceOfType (typeof (StructMirror), f);
+               AssertValue (Int32.MaxValue - 5, (f as StructMirror).Fields [0]);
+
+               // enums
+
+               FieldInfoMirror field = o.Type.GetField ("field_enum");
+               f = o.GetValue (field);
+               (f as EnumMirror).Value = 5;
+               o.SetValue (field, f);
+               f = o.GetValue (field);
+               Assert.AreEqual (5, (f as EnumMirror).Value);
+
+               // null
+               o.SetValue (o.Type.GetField ("field_s"), vm.CreateValue (null));
+               f = o.GetValue (o.Type.GetField ("field_s"));
+               AssertValue (null, f);
+
+               // vtype instances
+               field = o.Type.GetField ("generic_field_struct");
+               f = o.GetValue (field);
+               o.SetValue (field, f);
+
+               // Argument checking
+               AssertThrows<ArgumentNullException> (delegate () {
+                               o.SetValues (null, new Value [0]);
+                       });
+
+               AssertThrows<ArgumentNullException> (delegate () {
+                               o.SetValues (new FieldInfoMirror [0], null);
+                       });
+
+               AssertThrows<ArgumentNullException> (delegate () {
+                               o.SetValues (new FieldInfoMirror [] { null }, new Value [1] { null });
+                       });
+
+               // vtype with a wrong type
+               AssertThrows<ArgumentException> (delegate () {
+                               o.SetValue (o.Type.GetField ("field_struct"), o.GetValue (o.Type.GetField ("field_enum")));
+                       });
+
+               // reference type not assignment compatible
+               AssertThrows<ArgumentException> (delegate () {
+                               o.SetValue (o.Type.GetField ("field_class"), o);
+                       });
+
+               // field of another class
+               AssertThrows<ArgumentException> (delegate () {
+                               o.SetValue (val2.Type.GetField ("field_j"), vm.CreateValue (1));
+                       });
+       }
+
+       [Test]
+       [Category ("only")]
+       public void Type_SetValue () {
+               var e = run_until ("o1");
+               var frame = e.Thread.GetFrames () [0];
+               Value f;
+
+               object val = frame.GetThis ();
+               Assert.IsTrue (val is ObjectMirror);
+               Assert.AreEqual ("Tests", (val as ObjectMirror).Type.Name);
+               ObjectMirror o = (val as ObjectMirror);
+
+               ObjectMirror val2 = frame.GetValue (frame.Method.GetParameters ()[0]) as ObjectMirror;
+
+               o.Type.SetValue (o.Type.GetField ("static_i"), vm.CreateValue (55));
+               f = o.Type.GetValue (o.Type.GetField ("static_i"));
+               AssertValue (55, f);
+
+               o.Type.SetValue (o.Type.GetField ("static_s"), vm.RootDomain.CreateString ("B"));
+               f = o.Type.GetValue (o.Type.GetField ("static_s"));
+               AssertValue ("B", f);
+
+               // Argument checking
+               AssertThrows<ArgumentNullException> (delegate () {
+                               o.Type.SetValue (null, vm.CreateValue (0));
+                       });
+
+               AssertThrows<ArgumentNullException> (delegate () {
+                               o.Type.SetValue (o.Type.GetField ("static_i"), null);
+                       });
+
+               // field of another class
+               AssertThrows<ArgumentException> (delegate () {
+                               o.SetValue (val2.Type.GetField ("field_j"), vm.CreateValue (1));
+                       });
+       }
+
+       [Test]
+       public void TypeInfo () {
+               Event e = run_until ("ti2");
+               StackFrame frame = e.Thread.GetFrames () [0];
+
+               TypeMirror t;
+
+               // Array types
+               t = frame.Method.GetParameters ()[0].ParameterType;
+
+               Assert.AreEqual ("String[]", t.Name);
+               Assert.AreEqual ("string[]", t.CSharpName);
+               Assert.AreEqual ("Array", t.BaseType.Name);
+               Assert.AreEqual (true, t.HasElementType);
+               Assert.AreEqual (true, t.IsArray);
+               Assert.AreEqual (1, t.GetArrayRank ());
+               Assert.AreEqual ("String", t.GetElementType ().Name);
+
+               t = frame.Method.GetParameters ()[2].ParameterType;
+
+               Assert.AreEqual ("Int32[,]", t.Name);
+               // FIXME:
+               //Assert.AreEqual ("int[,]", t.CSharpName);
+               Assert.AreEqual ("Array", t.BaseType.Name);
+               Assert.AreEqual (true, t.HasElementType);
+               Assert.AreEqual (true, t.IsArray);
+               Assert.AreEqual (2, t.GetArrayRank ());
+               Assert.AreEqual ("Int32", t.GetElementType ().Name);
+
+               // Byref types
+               t = frame.Method.GetParameters ()[3].ParameterType;
+               // FIXME:
+               //Assert.AreEqual ("Int32&", t.Name);
+               //Assert.AreEqual (true, t.IsByRef);
+               //Assert.AreEqual (true, t.HasElementType);
+
+               // Pointer types
+               t = frame.Method.GetParameters ()[4].ParameterType;
+               // FIXME:
+               //Assert.AreEqual ("Int32*", t.Name);
+               Assert.AreEqual (true, t.IsPointer);
+               Assert.AreEqual (true, t.HasElementType);
+               Assert.AreEqual ("Int32", t.GetElementType ().Name);
+               Assert.AreEqual (false, t.IsPrimitive);
+
+               // primitive types 
+               t = frame.Method.GetParameters ()[5].ParameterType;
+               Assert.AreEqual (true, t.IsPrimitive);
+
+               // value types
+               t = frame.Method.GetParameters ()[6].ParameterType;
+               Assert.AreEqual ("AStruct", t.Name);
+               Assert.AreEqual (false, t.IsPrimitive);
+               Assert.AreEqual (true, t.IsValueType);
+               Assert.AreEqual (false, t.IsClass);
+
+               // reference types
+               t = frame.Method.GetParameters ()[7].ParameterType;
+               Assert.AreEqual ("Tests", t.Name);
+               var nested = (from nt in t.GetNestedTypes () where nt.IsNestedPublic select nt).ToArray ();
+               Assert.AreEqual (1, nested.Length);
+               Assert.AreEqual ("NestedClass", nested [0].Name);
+               Assert.IsTrue (t.BaseType.IsAssignableFrom (t));
+               Assert.IsTrue (!t.IsAssignableFrom (t.BaseType));
+
+               // generic instances
+               t = frame.Method.GetParameters ()[9].ParameterType;
+               Assert.AreEqual ("GClass`1", t.Name);
+
+               // enums
+               t = frame.Method.GetParameters ()[10].ParameterType;
+               Assert.AreEqual ("AnEnum", t.Name);
+               Assert.IsTrue (t.IsEnum);
+               Assert.AreEqual ("Int32", t.EnumUnderlyingType.Name);
+
+               // properties
+               t = frame.Method.GetParameters ()[7].ParameterType;
+
+               var props = t.GetProperties ();
+               Assert.AreEqual (3, props.Length);
+               foreach (PropertyInfoMirror prop in props) {
+                       ParameterInfoMirror[] indexes = prop.GetIndexParameters ();
+
+                       if (prop.Name == "IntProperty") {
+                               Assert.AreEqual ("Int32", prop.PropertyType.Name);
+                               Assert.AreEqual ("get_IntProperty", prop.GetGetMethod ().Name);
+                               Assert.AreEqual ("set_IntProperty", prop.GetSetMethod ().Name);
+                               Assert.AreEqual (0, indexes.Length);
+                       } else if (prop.Name == "ReadOnlyProperty") {
+                               Assert.AreEqual ("Int32", prop.PropertyType.Name);
+                               Assert.AreEqual ("get_ReadOnlyProperty", prop.GetGetMethod ().Name);
+                               Assert.AreEqual (null, prop.GetSetMethod ());
+                               Assert.AreEqual (0, indexes.Length);
+                       } else if (prop.Name == "IndexedProperty") {
+                               Assert.AreEqual (1, indexes.Length);
+                               Assert.AreEqual ("Int32", indexes [0].ParameterType.Name);
+                       }
+               }
+
+               // custom attributes
+               t = frame.Method.GetParameters ()[8].ParameterType;
+               Assert.AreEqual ("Tests2", t.Name);
+               var attrs = t.GetCustomAttributes (true);
+               Assert.AreEqual (2, 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 {
+                               Assert.Fail (attr.Constructor.DeclaringType.Name);
+                       }
+               }
+       }
+
+       [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]
+       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);
+
+               // Argument checking
+               AssertThrows<ArgumentNullException> (delegate () {
+                       t.GetValue (null);
+                       });
+
+               // instance fields
+               AssertThrows<ArgumentException> (delegate () {
+                       t.GetValue (o.Type.GetField ("field_i"));
+                       });
+
+               // field on another type
+               AssertThrows<ArgumentException> (delegate () {
+                               t.GetValue (val2.Type.GetField ("static_field_j"));
+                       });
+
+               // special static field
+               AssertThrows<ArgumentException> (delegate () {
+                               t.GetValue (t.GetField ("tls_i"));
+                       });
+       }
+
+       [Test]
+       public void Type_GetValues () {
+               Event e = run_until ("o1");
+               StackFrame frame = e.Thread.GetFrames () [0];
+
+               ObjectMirror o = (frame.GetThis () as ObjectMirror);
+
+               TypeMirror t = o.Type;
+
+               // static fields
+               object[] vals = t.GetValues (new FieldInfoMirror [] { t.GetField ("static_i"), t.GetField ("static_s") });
+               object f = vals [0];
+               AssertValue (55, f);
+
+               f = vals [1];
+               AssertValue ("A", f);
+
+               // Argument checking
+               AssertThrows<ArgumentNullException> (delegate () {
+                       t.GetValues (null);
+                       });
+
+               AssertThrows<ArgumentNullException> (delegate () {
+                       t.GetValues (new FieldInfoMirror [] { null });
+                       });
+       }
+
+       [Test]
+       public void ObjRefs () {
+               Event e = run_until ("objrefs1");
+               StackFrame frame = e.Thread.GetFrames () [0];
+
+               ObjectMirror o = frame.GetThis () as ObjectMirror;
+               ObjectMirror child = o.GetValue (o.Type.GetField ("child")) as ObjectMirror;
+
+               Assert.IsTrue (child.Address > 0);
+
+               // Check that object references are internalized correctly
+               Assert.AreEqual (o, frame.GetThis ());
+
+               run_until ("objrefs2");
+
+               // child should be gc'd now
+               Assert.IsTrue (child.IsCollected);
+
+               AssertThrows<ObjectCollectedException> (delegate () {
+                       TypeMirror t = child.Type;
+                       });
+
+               AssertThrows<ObjectCollectedException> (delegate () {
+                               long addr = child.Address;
+                       });
+       }
+
+       [Test]
+       public void Type_GetObject () {
+               Event e = run_until ("o1");
+               StackFrame frame = e.Thread.GetFrames () [0];
+
+               ObjectMirror o = (frame.GetThis () as ObjectMirror);
+
+               TypeMirror t = o.Type;
+
+               Assert.AreEqual ("MonoType", t.GetTypeObject ().Type.Name);
+       }
+
+       [Test]
+       public void VTypes () {
+               Event e = run_until ("vtypes1");
+               StackFrame frame = e.Thread.GetFrames () [0];
+
+               // vtypes as fields
+               ObjectMirror o = frame.GetThis () as ObjectMirror;
+               var obj = o.GetValue (o.Type.GetField ("field_struct"));
+               Assert.IsTrue (obj is StructMirror);
+               var s = obj as StructMirror;
+               Assert.AreEqual ("AStruct", s.Type.Name);
+               AssertValue (42, s ["i"]);
+               obj = s ["s"];
+               AssertValue ("S", obj);
+               AssertValue (43, s ["k"]);
+               obj = o.GetValue (o.Type.GetField ("field_boxed_struct"));
+               Assert.IsTrue (obj is StructMirror);
+               s = obj as StructMirror;
+               Assert.AreEqual ("AStruct", s.Type.Name);
+               AssertValue (42, s ["i"]);
+
+               // vtypes as arguments
+               s = frame.GetArgument (0) as StructMirror;
+               AssertValue (44, s ["i"]);
+               obj = s ["s"];
+               AssertValue ("T", obj);
+               AssertValue (45, s ["k"]);
+
+               // vtypes as array entries
+               var arr = frame.GetArgument (1) as ArrayMirror;
+               obj = arr [0];
+               Assert.IsTrue (obj is StructMirror);
+               s = obj as StructMirror;
+               AssertValue (1, s ["i"]);
+               AssertValue ("S1", s ["s"]);
+               obj = arr [1];
+               Assert.IsTrue (obj is StructMirror);
+               s = obj as StructMirror;
+               AssertValue (2, s ["i"]);
+               AssertValue ("S2", s ["s"]);
+
+               // Argument checking
+               s = frame.GetArgument (0) as StructMirror;
+               AssertThrows<ArgumentException> (delegate () {
+                               obj = s ["FOO"];
+                       });
+
+               // generic vtype instances
+               o = frame.GetThis () as ObjectMirror;
+               obj = o.GetValue (o.Type.GetField ("generic_field_struct"));
+               Assert.IsTrue (obj is StructMirror);
+               s = obj as StructMirror;
+               Assert.AreEqual ("GStruct`1", s.Type.Name);
+               AssertValue (42, s ["i"]);
+
+               // this on vtype methods
+               e = run_until ("vtypes2");
+               
+               e = single_step (e.Thread);
+
+               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 = single_step (e.Thread);
+
+               frame = e.Thread.GetFrames () [0];
+
+               Assert.AreEqual ("static_foo", (e as StepEvent).Method.Name);
+               obj = frame.GetThis ();
+               AssertValue (null, obj);
+       }
+
+       [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);
+
+               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 (5, locals.Length);
+               for (int i = 0; i < 5; ++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 {
+                               Assert.Fail ();
+                       }
+               }
+       }
+
+       [Test]
+       public void Locals () {
+               var be = run_until ("locals1");
+
+               StackFrame frame = be.Thread.GetFrames () [0];
+
+               MethodMirror m1 = frame.Method;
+
+               be = run_until ("locals2");
+
+               frame = be.Thread.GetFrames () [0];
+
+               object val = frame.GetValue (frame.Method.GetLocal ("i"));
+               AssertValue (0, val);
+
+               // Execute i = 42
+               var req = vm.CreateStepRequest (be.Thread);
+               req.Enable ();
+
+               vm.Resume ();
+               var e = vm.GetNextEvent ();
+               Assert.IsTrue (e is StepEvent);
+               Assert.AreEqual ("locals2", (e as StepEvent).Method.Name);
+
+               // Execute s = "AB";
+               vm.Resume ();
+               e = vm.GetNextEvent ();
+               Assert.IsTrue (e is StepEvent);
+               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]);
+               }
+
+               // Argument checking
+
+               // GetValue () null
+               AssertThrows<ArgumentNullException> (delegate () {
+                               frame.GetValue ((LocalVariable)null);
+                       });
+               // GetValue () local from another method
+               AssertThrows<ArgumentException> (delegate () {
+                               frame.GetValue (m1.GetLocal ("foo"));
+                       });
+
+               // GetValue () null
+               AssertThrows<ArgumentNullException> (delegate () {
+                               frame.GetValue ((ParameterInfoMirror)null);
+                       });
+               // GetValue () local from another method
+               AssertThrows<ArgumentException> (delegate () {
+                               frame.GetValue (m1.GetParameters ()[0]);
+                       });
+
+               // GetValues () null
+               AssertThrows<ArgumentNullException> (delegate () {
+                               frame.GetValues (null);
+                       });
+               // GetValues () embedded null
+               AssertThrows<ArgumentNullException> (delegate () {
+                               frame.GetValues (new LocalVariable [] { null });
+                       });
+               // GetValues () local from another method
+               AssertThrows<ArgumentException> (delegate () {
+                               frame.GetValues (new LocalVariable [] { m1.GetLocal ("foo") });
+                       });
+               // return value
+               AssertThrows<ArgumentException> (delegate () {
+                               val = frame.GetValue (frame.Method.ReturnParameter);
+                       });
+
+               // invalid stack frames
+               vm.Resume ();
+               e = vm.GetNextEvent ();
+               Assert.IsTrue (e is StepEvent);
+               Assert.AreEqual ("locals2", (e as StepEvent).Method.Name);
+
+               AssertThrows<InvalidStackFrameException> (delegate () {
+                               frame.GetValue (frame.Method.GetLocal ("i"));
+                       });
+
+               req.Disable ();
+       }
+
+       [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 = vm.GetNextEvent ();
+               Assert.IsInstanceOfType (typeof (VMDeathEvent), e);
+
+               var p = vm.Process;
+               /* Could be a remote vm with no process */
+               if (p != null) {
+                       p.WaitForExit ();
+                       Assert.AreEqual (5, p.ExitCode);
+
+                       // error handling
+                       AssertThrows<VMDisconnectedException> (delegate () {
+                                       vm.Resume ();
+                               });
+               }
+
+               vm = null;
+       }
+
+       [Test]
+       public void Dispose () {
+               run_until ("Main");
+
+               vm.Dispose ();
+
+               var e = vm.GetNextEvent ();
+               Assert.IsInstanceOfType (typeof (VMDisconnectEvent), e);
+
+               var p = vm.Process;
+               /* Could be a remote vm with no process */
+               if (p != null) {
+                       p.WaitForExit ();
+                       Assert.AreEqual (3, p.ExitCode);
+
+                       // error handling
+                       AssertThrows<VMDisconnectedException> (delegate () {
+                                       vm.Resume ();
+                               });
+               }
+
+               vm = null;
+       }
+
+       [Test]
+       public void LineNumbers () {
+               Event e = run_until ("line_numbers");
+
+               step_req = vm.CreateStepRequest (e.Thread);
+               step_req.Depth = StepDepth.Into;
+               step_req.Enable ();
+
+               Location l;
+               
+               vm.Resume ();
+
+               e = vm.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);
+               
+               int line_base = l.LineNumber;
+
+               vm.Resume ();
+               e = vm.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 = vm.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 = vm.GetNextEvent ();
+               Assert.IsTrue (e is StepEvent);
+               l = e.Thread.GetFrames ()[0].Location;
+               Assert.AreEqual ("ln3", l.Method.Name);
+               Assert.AreEqual (line_base + 10, l.LineNumber);
+
+               vm.Resume ();
+               e = vm.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 (1, sources.Length);
+               Assert.AreEqual ("dtest-app.cs", sources [0]);
+
+               sources = l.Method.DeclaringType.GetSourceFiles (true);
+               Assert.AreEqual (1, sources.Length);
+               Assert.IsTrue (sources [0].EndsWith ("dtest-app.cs"));
+       }
+
+       [Test]
+       public void Suspend () {
+               vm.Dispose ();
+
+               Start (new string [] { "dtest-app.exe", "suspend-test" });
+
+               Event e = run_until ("suspend");
+
+               ThreadMirror main = e.Thread;
+
+               vm.Resume ();
+
+               Thread.Sleep (100);
+
+               vm.Suspend ();
+
+               // The debuggee should be suspended while it is running the infinite loop
+               // in suspend ()
+               StackFrame frame = main.GetFrames ()[0];
+               Assert.AreEqual ("suspend", frame.Method.Name);
+
+               vm.Resume ();
+
+               // resuming when not suspended
+               AssertThrows<InvalidOperationException> (delegate () {
+                               vm.Resume ();
+                       });
+
+               vm.Exit (0);
+
+               vm = null;
+       }
+
+       [Test]
+       public void AssemblyLoad () {
+               Event e = run_until ("assembly_load");
+
+               vm.Resume ();
+
+               e = vm.GetNextEvent ();
+               Assert.IsInstanceOfType (typeof (AssemblyLoadEvent), e);
+               Assert.IsTrue ((e as AssemblyLoadEvent).Assembly.Location.EndsWith ("System.dll"));
+
+               var frames = e.Thread.GetFrames ();
+               Assert.IsTrue (frames.Length > 0);
+               Assert.AreEqual ("assembly_load", frames [0].Method.Name);
+       }
+
+       [Test]
+       public void CreateValue () {
+               PrimitiveValue v;
+
+               v = vm.CreateValue (1);
+               Assert.AreEqual (vm, v.VirtualMachine);
+               Assert.AreEqual (1, v.Value);
+
+               v = vm.CreateValue (null);
+               Assert.AreEqual (vm, v.VirtualMachine);
+               Assert.AreEqual (null, v.Value);
+
+               // Argument checking
+               AssertThrows <ArgumentException> (delegate () {
+                               v = vm.CreateValue ("FOO");
+                       });
+       }
+
+       [Test]
+       public void CreateString () {
+               StringMirror s = vm.RootDomain.CreateString ("ABC");
+
+               Assert.AreEqual (vm, s.VirtualMachine);
+               Assert.AreEqual ("ABC", s.Value);
+               Assert.AreEqual (vm.RootDomain, s.Domain);
+
+               // Argument checking
+               AssertThrows <ArgumentNullException> (delegate () {
+                               s = vm.RootDomain.CreateString (null);
+                       });
+       }
+
+       [Test]
+       [Category ("only")]
+       public void CreateBoxedValue () {
+               ObjectMirror o = vm.RootDomain.CreateBoxedValue (new PrimitiveValue (vm, 42));
+
+               Assert.AreEqual ("Int32", o.Type.Name);
+               //AssertValue (42, m.GetValue (o.Type.GetField ("m_value")));
+
+               // Argument checking
+               AssertThrows <ArgumentNullException> (delegate () {
+                               vm.RootDomain.CreateBoxedValue (null);
+                       });
+
+               AssertThrows <ArgumentException> (delegate () {
+                               vm.RootDomain.CreateBoxedValue (o);
+                       });
+       }
+
+       [Test]
+       public void Invoke () {
+               Event e = run_until ("invoke1");
+
+               StackFrame frame = e.Thread.GetFrames () [0];
+
+               TypeMirror t = frame.Method.DeclaringType;
+               ObjectMirror this_obj = (ObjectMirror)frame.GetThis ();
+
+               TypeMirror t2 = frame.Method.GetParameters ()[0].ParameterType;
+
+               MethodMirror m;
+               Value v;
+
+               // return void
+               m = t.GetMethod ("invoke_return_void");
+               v = this_obj.InvokeMethod (e.Thread, m, null);
+               Assert.IsNull (v);
+
+               // return ref
+               m = t.GetMethod ("invoke_return_ref");
+               v = this_obj.InvokeMethod (e.Thread, m, null);
+               AssertValue ("ABC", v);
+
+               // return null
+               m = t.GetMethod ("invoke_return_null");
+               v = this_obj.InvokeMethod (e.Thread, m, null);
+               AssertValue (null, v);
+
+               // return primitive
+               m = t.GetMethod ("invoke_return_primitive");
+               v = this_obj.InvokeMethod (e.Thread, m, null);
+               AssertValue (42, v);
+
+               // pass primitive
+               m = t.GetMethod ("invoke_pass_primitive");
+               Value[] args = new Value [] {
+                       vm.CreateValue ((byte)Byte.MaxValue),
+                       vm.CreateValue ((sbyte)SByte.MaxValue),
+                       vm.CreateValue ((short)1),
+                       vm.CreateValue ((ushort)1),
+                       vm.CreateValue ((int)1),
+                       vm.CreateValue ((uint)1),
+                       vm.CreateValue ((long)1),
+                       vm.CreateValue ((ulong)1),
+                       vm.CreateValue ('A'),
+                       vm.CreateValue (true),
+                       vm.CreateValue (3.14f),
+                       vm.CreateValue (3.14) };
+
+               v = this_obj.InvokeMethod (e.Thread, m, args);
+               AssertValue ((int)Byte.MaxValue + (int)SByte.MaxValue + 1 + 1 + 1 + 1 + 1 + 1 + 'A' + 1 + 3 + 3, v);
+
+               // pass ref
+               m = t.GetMethod ("invoke_pass_ref");
+               v = this_obj.InvokeMethod (e.Thread, m, new Value [] { vm.RootDomain.CreateString ("ABC") });
+               AssertValue ("ABC", v);
+
+               // pass null
+               m = t.GetMethod ("invoke_pass_ref");
+               v = this_obj.InvokeMethod (e.Thread, m, new Value [] { vm.CreateValue (null) });
+               AssertValue (null, v);
+
+               // static
+               m = t.GetMethod ("invoke_static_pass_ref");
+               v = t.InvokeMethod (e.Thread, m, new Value [] { vm.RootDomain.CreateString ("ABC") });
+               AssertValue ("ABC", v);
+
+               // static invoked using ObjectMirror.InvokeMethod
+               m = t.GetMethod ("invoke_static_pass_ref");
+               v = this_obj.InvokeMethod (e.Thread, m, new Value [] { vm.RootDomain.CreateString ("ABC") });
+               AssertValue ("ABC", v);
+
+               // method which throws an exception
+               try {
+                       m = t.GetMethod ("invoke_throws");
+                       v = this_obj.InvokeMethod (e.Thread, m, null);
+                       Assert.Fail ();
+               } catch (InvocationException ex) {
+                       Assert.AreEqual ("Exception", ex.Exception.Type.Name);
+               }
+
+               // newobj
+               m = t.GetMethod (".ctor");
+               v = t.InvokeMethod (e.Thread, m, null);
+               Assert.IsInstanceOfType (typeof (ObjectMirror), v);
+               Assert.AreEqual ("Tests", (v as ObjectMirror).Type.Name);
+
+               // Argument checking
+               
+               // null thread
+               AssertThrows<ArgumentNullException> (delegate {
+                               m = t.GetMethod ("invoke_pass_ref");
+                               v = this_obj.InvokeMethod (null, m, new Value [] { vm.CreateValue (null) });                            
+                       });
+
+               // null method
+               AssertThrows<ArgumentNullException> (delegate {
+                               v = this_obj.InvokeMethod (e.Thread, null, new Value [] { vm.CreateValue (null) });                             
+                       });
+
+               // invalid number of arguments
+               m = t.GetMethod ("invoke_pass_ref");
+               AssertThrows<ArgumentException> (delegate {
+                               v = this_obj.InvokeMethod (e.Thread, m, null);
+                       });
+
+               // invalid type of argument (ref != primitive)
+               m = t.GetMethod ("invoke_pass_ref");
+               AssertThrows<ArgumentException> (delegate {
+                               v = this_obj.InvokeMethod (e.Thread, m, new Value [] { vm.CreateValue (1) });
+                       });
+
+               // invalid type of argument (primitive != primitive)
+               m = t.GetMethod ("invoke_pass_primitive_2");
+               AssertThrows<ArgumentException> (delegate {
+                               v = this_obj.InvokeMethod (e.Thread, m, new Value [] { vm.CreateValue (1) });
+                       });
+
+               // invoking a non-static method as static
+               m = t.GetMethod ("invoke_pass_ref");
+               AssertThrows<ArgumentException> (delegate {
+                               v = t.InvokeMethod (e.Thread, m, new Value [] { vm.RootDomain.CreateString ("ABC") });
+                       });
+
+               // invoking a method defined in another class
+               m = t2.GetMethod ("invoke");
+               AssertThrows<ArgumentException> (delegate {
+                               v = this_obj.InvokeMethod (e.Thread, m, null);
+                       });
+       }
+
+       [Test]
+       public void InvokeVType () {
+               Event e = run_until ("invoke1");
+
+               StackFrame frame = e.Thread.GetFrames () [0];
+
+               var s = frame.GetArgument (1) as StructMirror;
+
+               TypeMirror t = s.Type;
+
+               MethodMirror m;
+               Value v;
+
+               // Pass struct as this, receive int
+               m = t.GetMethod ("invoke_return_int");
+               v = s.InvokeMethod (e.Thread, m, null);
+               AssertValue (42, v);
+
+               // Pass struct as this, receive intptr
+               m = t.GetMethod ("invoke_return_intptr");
+               v = s.InvokeMethod (e.Thread, m, null);
+               AssertValue (43, v);
+
+               // Static method
+               m = t.GetMethod ("invoke_static");
+               v = t.InvokeMethod (e.Thread, m, null);
+               AssertValue (5, v);
+
+               // Pass generic struct as this
+               s = frame.GetArgument (2) as StructMirror;
+               t = s.Type;
+               m = t.GetMethod ("invoke_return_int");
+               v = s.InvokeMethod (e.Thread, m, null);
+               AssertValue (42, v);
+       }
+
+       [Test]
+       public void BreakpointDuringInvoke () {
+               Event e = run_until ("invoke1");
+
+               MethodMirror m = entry_point.DeclaringType.GetMethod ("invoke2");
+               Assert.IsNotNull (m);
+               vm.SetBreakpoint (m, 0);
+
+               StackFrame frame = e.Thread.GetFrames () [0];
+               var o = frame.GetThis () as ObjectMirror;
+
+               bool failed = false;
+
+               bool finished = false;
+               object wait = new object ();
+
+               // Have to invoke in a separate thread as the invoke is suspended until we
+               // resume after the breakpoint
+               Thread t = new Thread (delegate () {
+                               try {
+                                       o.InvokeMethod (e.Thread, m, null);
+                               } catch {
+                                       failed = true;
+                               }
+                               lock (wait) {
+                                       finished = true;
+                                       Monitor.Pulse (wait);
+                               }
+                       });
+
+               t.Start ();
+
+               StackFrame invoke_frame = null;
+
+               try {
+                       e = vm.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 ();
+               }
+
+               // Check that the invoke frames are no longer valid
+               AssertThrows<InvalidStackFrameException> (delegate {
+                               invoke_frame.GetThis ();
+                       });
+
+               lock (wait) {
+                       if (!finished)
+                               Monitor.Wait (wait);
+               }
+
+               // Check InvokeOptions.DisableBreakpoints flag
+               o.InvokeMethod (e.Thread, m, null, InvokeOptions.DisableBreakpoints);
+       }
+
+       [Test]
+       public void InvokeSingleThreaded () {
+               vm.Dispose ();
+
+               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 = vm.GetNextEvent ();
+               Assert.AreEqual (EventType.TypeLoad, e.EventType);
+       }
+
+       [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);
+
+               vm.EnableEvents (EventType.ThreadStart, EventType.ThreadDeath);
+
+               vm.Resume ();
+
+               e = vm.GetNextEvent ();
+               Assert.IsInstanceOfType (typeof (ThreadStartEvent), e);
+               var state = e.Thread.ThreadState;
+               Assert.IsTrue (state == ThreadState.Running || state == ThreadState.Unstarted);
+
+               vm.Resume ();
+
+               e = vm.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));
+
+               // argument checking
+
+               // variable null
+               AssertThrows<ArgumentNullException> (delegate () {
+                               frame.SetValue ((LocalVariable)null, vm.CreateValue (55));
+                       });
+
+               // value null
+               AssertThrows<ArgumentNullException> (delegate () {
+                               l = frame.Method.GetLocal ("i");
+                               frame.SetValue (l, null);
+                       });
+
+               // value of invalid type
+               AssertThrows<ArgumentException> (delegate () {
+                               l = frame.Method.GetLocal ("i");
+                               frame.SetValue (l, vm.CreateValue (55));
+                       });
+       }
+
+       [Test]
+       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 = vm.CreateStepRequest (e.Thread);
+               req.Depth = StepDepth.Into;
+               req.Size = StepSize.Line;
+               req.Enable ();
+
+               step_req = req;
+
+               // Step into invoke2
+               vm.Resume ();
+               e = vm.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 = vm.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 = vm.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 = vm.GetNextEvent ();
+               Assert.IsInstanceOfType (typeof (ExceptionEvent), e);
+               Assert.AreEqual ("OverflowException", (e as ExceptionEvent).Exception.Type.Name);
+               req.Disable ();
+
+               // Implicit exceptions
+               req = vm.CreateExceptionRequest (null);
+               req.Enable ();
+
+               vm.Resume ();
+
+               e = vm.GetNextEvent ();
+               Assert.IsInstanceOfType (typeof (ExceptionEvent), e);
+               Assert.AreEqual ("NullReferenceException", (e as ExceptionEvent).Exception.Type.Name);
+               req.Disable ();
+
+               // Argument checking
+               AssertThrows<ArgumentException> (delegate {
+                               vm.CreateExceptionRequest (e.Thread.Type);
+                       });
+       }
+
+       //
+       // 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 = vm.GetNextEvent ();
+               Assert.IsInstanceOfType (typeof (ExceptionEvent), e);
+               Assert.AreEqual ("NullReferenceException", (e as ExceptionEvent).Exception.Type.Name);
+
+               var ex = (e as ExceptionEvent).Exception;
+               var tostring_method = vm.RootDomain.Corlib.GetType ("System.Object").GetMethod ("ToString");
+               ex.InvokeMethod (e.Thread, tostring_method, null, InvokeOptions.SingleThreaded);
+       }
+
+       [Test]
+       public void Domains () {
+               vm.Dispose ();
+
+               Start (new string [] { "dtest-app.exe", "domain-test" });
+
+               vm.EnableEvents (EventType.AppDomainCreate, EventType.AppDomainUnload, EventType.AssemblyUnload);
+
+               Event e = run_until ("domains");
+
+               vm.Resume ();
+               
+               e = vm.GetNextEvent ();
+               Assert.IsInstanceOfType (typeof (AppDomainCreateEvent), e);
+
+               var domain = (e as AppDomainCreateEvent).Domain;
+
+               // 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 = vm.GetNextEvent ();
+                       if (e is BreakpointEvent)
+                               break;
+               }
+
+               Assert.AreEqual ("invoke_in_domain", (e as BreakpointEvent).Method.Name);
+
+               // d_method is from another domain
+               MethodMirror d_method = (e as BreakpointEvent).Method;
+               Assert.IsTrue (m != d_method);
+
+               var frames = e.Thread.GetFrames ();
+               Assert.AreEqual ("invoke_in_domain", frames [0].Method.Name);
+               Assert.AreEqual ("invoke", frames [1].Method.Name);
+               Assert.AreEqual ("domains", frames [2].Method.Name);
+
+               // Test breakpoints on already JITted methods in other domains
+               m = entry_point.DeclaringType.GetMethod ("invoke_in_domain_2");
+               Assert.IsNotNull (m);
+               vm.SetBreakpoint (m, 0);
+
+               while (true) {
+                       vm.Resume ();
+                       e = vm.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 = vm.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_2");
+
+               // Test access to unloaded types
+               // FIXME: Add an exception type for this
+               AssertThrows<Exception> (delegate {
+                               d_method.DeclaringType.GetValue (d_method.DeclaringType.GetField ("static_i"));
+                       });
+       }
+
+       [Test]
+       public void DynamicMethods () {
+               Event e = run_until ("dyn_call");
+
+               var m = e.Thread.GetFrames ()[1].Method;
+               Assert.AreEqual ("dyn_method", m.Name);
+
+               // Test access to IL
+               var body = m.GetMethodBody ();
+
+               ILInstruction ins = body.Instructions [0];
+               Assert.AreEqual (OpCodes.Ldstr, ins.OpCode);
+               Assert.AreEqual ("FOO", ins.Operand);
+       }
+
+       [Test]
+       public void RefEmit () {
+               vm.Dispose ();
+
+               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.Dispose ();
+
+               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;
+
+               // return void
+               var m = t.GetMethod ("invoke_static_return_void");
+               AssertThrows<InvalidOperationException> (delegate {
+                               t.InvokeMethod (e.Thread, m, null);
+                       });
+       }
+
+       [Test]
+       public void VirtualMachine_CreateEnumMirror () {
+               var e = run_until ("o1");
+               var frame = e.Thread.GetFrames () [0];
+
+               object val = frame.GetThis ();
+               Assert.IsTrue (val is ObjectMirror);
+               Assert.AreEqual ("Tests", (val as ObjectMirror).Type.Name);
+               ObjectMirror o = (val as ObjectMirror);
+
+               FieldInfoMirror field = o.Type.GetField ("field_enum");
+               Value f = o.GetValue (field);
+               TypeMirror enumType = (f as EnumMirror).Type;
+
+               o.SetValue (field, vm.CreateEnumMirror (enumType, vm.CreateValue (1)));
+               f = o.GetValue (field);
+               Assert.AreEqual (1, (f as EnumMirror).Value);
+
+               // Argument checking
+               AssertThrows<ArgumentNullException> (delegate () {
+                               vm.CreateEnumMirror (enumType, null);
+                       });
+
+               AssertThrows<ArgumentNullException> (delegate () {
+                               vm.CreateEnumMirror (null, vm.CreateValue (1));
+                       });
+
+               // null value
+               AssertThrows<ArgumentException> (delegate () {
+                               vm.CreateEnumMirror (enumType, vm.CreateValue (null));
+                       });
+
+               // value of a wrong type
+               AssertThrows<ArgumentException> (delegate () {
+                               vm.CreateEnumMirror (enumType, vm.CreateValue ((long)1));
+                       });
+       }
+}
\ No newline at end of file