Add symbol file testing to compiler tester
[mono.git] / mcs / tools / compiler-tester / compiler-tester.cs
index c5f5fae387200e2d2c526a1a4c7a26ee12b05aff..84d878193cd98153ccff1bd97d874efbaf38be5d 100644 (file)
@@ -4,9 +4,8 @@
 // Author:
 //   Marek Safar (marek.safar@gmail.com)
 //
-
-//
-// Copyright (C) 2008 Novell, Inc (http://www.novell.com)
+// Copyright (C) 2008, 2009 Novell, Inc (http://www.novell.com)
+// Copyright (C) 2012 Xamarin Inc (http://www.xamarin.com)
 //
 // Permission is hereby granted, free of charge, to any person obtaining
 // a copy of this software and associated documentation files (the
@@ -35,6 +34,9 @@ using System.Reflection;
 using System.Text;
 using System.Collections;
 using System.Xml;
+using System.Collections.Generic;
+using Mono.CompilerServices.SymbolWriter;
+using System.Globalization;
 
 namespace TestRunner {
 
@@ -135,7 +137,7 @@ namespace TestRunner {
        }
 #endif
 
-       class TestCase
+       class TestCase : MarshalByRefObject
        {
                public readonly string FileName;
                public readonly string[] CompilerOptions;
@@ -151,9 +153,9 @@ namespace TestRunner {
 
        class PositiveTestCase : TestCase
        {
-               public class VerificationData
+               public class VerificationData : MarshalByRefObject
                {
-                       public class MethodData
+                       public class MethodData : MarshalByRefObject
                        {
                                public MethodData (MethodBase mi, int il_size)
                                {
@@ -180,12 +182,9 @@ namespace TestRunner {
 
                        public VerificationData (string test_file)
                        {
-#if NET_2_0
                                this.test_file = test_file;
-#endif                         
                        }
 
-#if NET_2_0
                        string test_file;
 
                        public static VerificationData FromFile (string name, XmlReader r)
@@ -243,7 +242,6 @@ namespace TestRunner {
 
                                w.WriteEndElement ();
                        }
-#endif
 
                        public MethodData FindMethodData (string method_name, string declaring_type)
                        {
@@ -290,59 +288,9 @@ namespace TestRunner {
                                return verif_data;
                        }
                }
-
-               public bool CompareIL (MethodBase mi, PositiveChecker checker)
-               {
-                       string m_name = mi.ToString ();
-                       string decl_type = mi.DeclaringType.ToString ();
-                       VerificationData.MethodData md = verif_data.FindMethodData (m_name, decl_type);
-                       if (md == null) {
-                               verif_data.AddNewMethod (mi, GetILSize (mi));
-                               if (!verif_data.IsNewSet) {
-                                       checker.HandleFailure (FileName, PositiveChecker.TestResult.ILError, decl_type + ": " + m_name + " (new method?)");
-                                       return false;
-                               }
-
-                               return true;
-                       }
-
-                       if (md.Checked) {
-                               checker.HandleFailure (FileName, PositiveChecker.TestResult.ILError, decl_type + ": " + m_name + " has a duplicate");
-                               return false;
-                       }
-                       
-                       md.Checked = true;
-
-                       int il_size = GetILSize (mi);
-                       if (md.ILSize == il_size)
-                               return true;
-
-                       if (md.ILSize > il_size) {
-                               checker.LogFileLine (FileName, "{0} (code size reduction {1} -> {2})", m_name, md.ILSize, il_size);
-                               md.ILSize = il_size;
-                               return true;
-                       }
-
-                       checker.HandleFailure (FileName, PositiveChecker.TestResult.ILError,
-                               string.Format ("{0} (code size {1} -> {2})", m_name, md.ILSize, il_size));
-
-                       md.ILSize = il_size;
-
-                       return false;
-               }
-
-               static int GetILSize (MethodBase mi)
-               {
-#if NET_2_0
-                       MethodBody body = mi.GetMethodBody ();
-                       if (body != null)
-                               return body.GetILAsByteArray ().Length;
-#endif
-                       return 0;
-               }
        }
 
-       class Checker: IDisposable
+       class Checker: MarshalByRefObject, IDisposable
        {
                protected ITester tester;
                protected int success;
@@ -363,6 +311,7 @@ namespace TestRunner {
                protected ArrayList no_error_list = new ArrayList ();
                
                protected bool verbose;
+               protected bool safe_execution;
                        
                int total_known_issues;
 
@@ -390,6 +339,12 @@ namespace TestRunner {
                        }
                }
 
+               public bool SafeExecution {
+                       set {
+                               safe_execution = value;
+                       }
+               }
+
                public string[] ExtraCompilerOptions {
                        set {
                                extra_compiler_options = value;
@@ -450,6 +405,9 @@ namespace TestRunner {
                        if (test_hash.Contains (filename))
                                return true;
 
+                       if (verbose)
+                               Log (filename + "...\t");
+
                        if (ignore_list.Contains (filename)) {
                                ++ignored;
                                LogFileLine (filename, "NOT TESTED");
@@ -602,7 +560,10 @@ namespace TestRunner {
                
                public void LogFileLine (string file, string msg, params object [] args)
                {
-                       string s = file + "...\t" + string.Format (msg, args); 
+                       string s = verbose ? 
+                               string.Format (msg, args) :
+                               file + "...\t" + string.Format (msg, args); 
+
                        Console.WriteLine (s);
                        if (log_file != null)
                                log_file.WriteLine (s);
@@ -648,7 +609,8 @@ namespace TestRunner {
                        LoadError,
                        XmlError,
                        Success,
-                       ILError
+                       ILError,
+                       DebugError
                }
 
                public PositiveChecker (ITester tester, string verif_file):
@@ -676,6 +638,9 @@ namespace TestRunner {
                        set {
                                update_verif_file = value;
                        }
+                       get {
+                               return update_verif_file;
+                       }
                }
 
                protected override bool GetExtraOptions(string file, out string[] compiler_options,
@@ -695,6 +660,126 @@ namespace TestRunner {
                        return true;
                }
 
+               class DomainTester : MarshalByRefObject
+               {
+                       public bool CheckILSize (PositiveTestCase test, PositiveChecker checker, string file)
+                       {
+                               Assembly assembly = Assembly.LoadFile (file);
+
+                               bool success = true;
+                               Type[] types = assembly.GetTypes ();
+                               foreach (Type t in types) {
+
+                                       // Skip interfaces
+                                       if (!t.IsClass && !t.IsValueType)
+                                               continue;
+
+                                       if (test.VerificationProvider == null) {
+                                               if (!checker.UpdateVerificationDataFile)
+                                                       checker.LogFileLine (test.FileName, "Missing IL verification data");
+                                               test.CreateNewTest ();
+                                       }
+
+                                       foreach (MemberInfo m in t.GetMembers (BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance | BindingFlags.DeclaredOnly)) {
+                                               MethodBase mi = m as MethodBase;
+                                               if (mi == null)
+                                                       continue;
+
+                                               if ((mi.Attributes & (MethodAttributes.PinvokeImpl)) != 0)
+                                                       continue;
+
+                                               success &= CompareIL (mi, test, checker);
+                                       }
+                               }
+
+                               return success;
+                       }
+
+                       bool CompareIL (MethodBase mi, PositiveTestCase test, PositiveChecker checker)
+                       {
+                               string m_name = mi.ToString ();
+                               string decl_type = mi.DeclaringType.ToString ();
+                               PositiveTestCase.VerificationData data_provider = test.VerificationProvider;
+
+                               PositiveTestCase.VerificationData.MethodData md = data_provider.FindMethodData (m_name, decl_type);
+                               if (md == null) {
+                                       data_provider.AddNewMethod (mi, GetILSize (mi));
+                                       if (!data_provider.IsNewSet) {
+                                               checker.HandleFailure (test.FileName, PositiveChecker.TestResult.ILError, decl_type + ": " + m_name + " (new method?)");
+                                               return false;
+                                       }
+
+                                       return true;
+                               }
+
+                               if (md.Checked) {
+                                       checker.HandleFailure (test.FileName, PositiveChecker.TestResult.ILError, decl_type + ": " + m_name + " has a duplicate");
+                                       return false;
+                               }
+
+                               md.Checked = true;
+
+                               int il_size = GetILSize (mi);
+                               if (md.ILSize == il_size)
+                                       return true;
+
+                               if (md.ILSize > il_size) {
+                                       checker.LogFileLine (test.FileName, "{0} (code size reduction {1} -> {2})", decl_type + ": " + m_name, md.ILSize, il_size);
+                                       md.ILSize = il_size;
+                                       return true;
+                               }
+
+                               checker.HandleFailure (test.FileName, PositiveChecker.TestResult.ILError,
+                                       string.Format ("{0} (code size {1} -> {2})", decl_type + ": " + m_name, md.ILSize, il_size));
+
+                               md.ILSize = il_size;
+
+                               return false;
+                       }
+
+                       static int GetILSize (MethodBase mi)
+                       {
+                               MethodBody body = mi.GetMethodBody ();
+                               if (body != null)
+                                       return body.GetILAsByteArray ().Length;
+
+                               return 0;
+                       }
+
+                       bool ExecuteFile (MethodInfo entry_point, string filename)
+                       {
+                               TextWriter stdout = Console.Out;
+                               TextWriter stderr = Console.Error;
+                               Console.SetOut (TextWriter.Null);
+                               Console.SetError (TextWriter.Null);
+                               ParameterInfo[] pi = entry_point.GetParameters ();
+                               object[] args = pi.Length == 0 ? null : default_args;
+
+                               object result = null;
+                               try {
+                                       try {
+                                               result = entry_point.Invoke (null, args);
+                                       } finally {
+                                               Console.SetOut (stdout);
+                                               Console.SetError (stderr);
+                                       }
+                               } catch (Exception e) {
+                                       throw new ApplicationException (e.ToString ());
+                               }
+
+                               if (result is int && (int) result != 0)
+                                       throw new ApplicationException ("Wrong return code: " + result.ToString ());
+
+                               return true;
+                       }
+
+                       public bool Test (string file)
+                       {
+                               Assembly assembly = Assembly.LoadFile (file);
+                               return ExecuteFile (assembly.EntryPoint, file);
+                       }
+               }
+
                protected override bool Check(TestCase test)
                {
                        string filename = test.FileName;
@@ -720,7 +805,6 @@ namespace TestRunner {
                                return true;
                        }
 
-                       MethodInfo mi = null;
                        string file = Path.Combine (files_folder, Path.GetFileNameWithoutExtension (filename) + ".exe");
 
                        // Enable .dll only tests (no execution required)
@@ -729,112 +813,157 @@ namespace TestRunner {
                                return true;
                        }
 
-                       Assembly assembly = null;
-                       try {
-                               assembly = Assembly.LoadFile (file);
-                               mi = assembly.EntryPoint;
-                       }
-                       catch (FileNotFoundException) {
-                               if (File.Exists (file)) {
-                                       Console.WriteLine ("APPDOMAIN LIMIT REACHED");
-                               }
-                       }
-                       catch (Exception e) {
-                               HandleFailure (filename, TestResult.LoadError, e.ToString ());
-                               return false;
+                       AppDomain domain = null;
+#if !NET_2_1
+                       if (safe_execution) {
+                               // Create a new AppDomain, with the current directory as the base.
+                               AppDomainSetup setupInfo = new AppDomainSetup ();
+                               setupInfo.ApplicationBase = AppDomain.CurrentDomain.BaseDirectory;
+                               setupInfo.LoaderOptimization = LoaderOptimization.SingleDomain;
+                               domain = AppDomain.CreateDomain (Path.GetFileNameWithoutExtension (file), null, setupInfo);
                        }
-
-                       if (!ExecuteFile (mi, file, filename))
-                               return false;
-
-                       if (doc_output != null) {
-                               string ref_file = filename.Replace (".cs", "-ref.xml");
+#endif
+                       try {
+                               DomainTester tester;
                                try {
 #if !NET_2_1
-                                       XmlComparer.Compare (ref_file, doc_output);
+                                       if (domain != null)
+                                               tester = (DomainTester) domain.CreateInstanceAndUnwrap (typeof (PositiveChecker).Assembly.FullName, typeof (DomainTester).FullName);
+                                       else
 #endif
-                               }
-                               catch (Exception e) {
-                                       HandleFailure (filename, TestResult.XmlError, e.Message);
+                                               tester = new DomainTester ();
+
+                                       if (!tester.Test (file))
+                                               return false;
+
+                               } catch (ApplicationException e) {
+                                       HandleFailure (filename, TestResult.ExecError, e.Message);
+                                       return false;
+                               } catch (Exception e) {
+                                       HandleFailure (filename, TestResult.LoadError, e.ToString ());
                                        return false;
                                }
-                       } else {
-                               if (verif_file != null) {
-                                       PositiveTestCase pt = (PositiveTestCase) test;
-                                       pt.VerificationProvider = (PositiveTestCase.VerificationData) verif_data [filename];
-                                       if (!CheckILSize (assembly, pt))
+
+                               if (doc_output != null) {
+                                       string ref_file = filename.Replace (".cs", "-ref.xml");
+                                       try {
+#if !NET_2_1
+                                               new XmlComparer ("doc").Compare (ref_file, doc_output);
+#endif
+                                       } catch (Exception e) {
+                                               HandleFailure (filename, TestResult.XmlError, e.Message);
                                                return false;
+                                       }
+                               } else {
+                                       if (verif_file != null) {
+                                               PositiveTestCase pt = (PositiveTestCase) test;
+                                               pt.VerificationProvider = (PositiveTestCase.VerificationData) verif_data[filename];
+
+                                               if (!tester.CheckILSize (pt, this, file))
+                                                       return false;
+                                       }
+
+                                       if (filename.StartsWith ("test-debug", StringComparison.OrdinalIgnoreCase)) {
+                                               MonoSymbolFile mdb_file = MonoSymbolFile.ReadSymbolFile (file + ".mdb");
+                                               var mdb_xml_file = mdb_file.FileName + ".xml";
+                                               ConvertSymbolFileToXml (mdb_file, mdb_xml_file);
+
+                                               var ref_file = filename.Replace(".cs", "-ref.xml");
+                                               try {
+                                                       new XmlComparer ("symbols").Compare (ref_file, mdb_xml_file);
+                                               } catch (Exception e) {
+                                                       HandleFailure (filename, TestResult.DebugError, e.Message);
+                                                       return false;
+                                               }
+                                       }
+
                                }
+                       } finally {
+                               if (domain != null)
+                                       AppDomain.Unload (domain);
                        }
 
                        HandleFailure (filename, TestResult.Success, null);
                        return true;
                }
 
-               protected override TestCase CreateTestCase (string filename, string [] options, string [] deps)
-               {
-                       return new PositiveTestCase (filename, options, deps);
-               }
-
-               bool CheckILSize (Assembly assembly, PositiveTestCase test)
+               static void ConvertSymbolFileToXml (MonoSymbolFile symbolFile, string xmlFile)
                {
-                       bool success = true;
-                       Type[] types = assembly.GetTypes ();
-                       foreach (Type t in types) {
-                               
-                               // Skip interfaces
-                               if (!t.IsClass && !t.IsValueType)
-                                       continue;
+                       using (XmlTextWriter writer = new XmlTextWriter (xmlFile, Encoding.UTF8)) {
+                               writer.Formatting = Formatting.Indented;
 
-                               if (test.VerificationProvider == null) {
-                                       if (!update_verif_file)
-                                               LogFileLine (test.FileName, "Missing IL verification data");
-                                       test.CreateNewTest ();
-                               }
+                               writer.WriteStartDocument ();
 
-                               foreach (MemberInfo m in t.GetMembers (BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance | BindingFlags.DeclaredOnly)) {
-                                       MethodBase mi = m as MethodBase;
-                                       if (mi == null)
-                                               continue;
+                               writer.WriteStartElement ("symbols");
 
-                                       if ((mi.Attributes & (MethodAttributes.PinvokeImpl)) != 0)
-                                               continue;
+                               writer.WriteStartElement ("files");
+                               foreach (var file in symbolFile.Sources) {
+                                       writer.WriteStartElement ("file");
+                                       writer.WriteAttributeString ("id", file.Index.ToString ());
+                                       writer.WriteAttributeString ("name", Path.GetFileName (file.FileName));
+                                       writer.WriteEndElement ();
+                               }
+                               writer.WriteEndElement ();
+
+                               writer.WriteStartElement ("methods");
+                               foreach (var method in symbolFile.Methods) {
+                                       writer.WriteStartElement ("method");
+                                       writer.WriteAttributeString ("token", IntToHex (method.Token));
+
+                                       var il_entries = method.GetLineNumberTable ();
+                                       writer.WriteStartElement ("sequencepoints");
+                                       foreach (var entry in il_entries.LineNumbers) {
+                                               writer.WriteStartElement ("entry");
+                                               writer.WriteAttributeString ("il", IntToHex (entry.Offset));
+                                               writer.WriteAttributeString ("row", entry.Row.ToString ());
+                                               writer.WriteAttributeString ("file_ref", entry.File.ToString ());
+                                               writer.WriteAttributeString ("hidden", BoolToString (entry.IsHidden));
+                                               writer.WriteEndElement ();
+                                       }
+                                       writer.WriteEndElement ();
+
+                                       writer.WriteStartElement ("locals");
+                                       foreach (var local in method.GetLocals ()) {
+                                               writer.WriteStartElement ("entry");
+                                               writer.WriteAttributeString ("name", local.Name);
+                                               writer.WriteAttributeString ("il_index", local.Index.ToString ());
+                                               writer.WriteAttributeString ("scope_ref", local.BlockIndex.ToString ());
+                                               writer.WriteEndElement ();
+                                       }
+                                       writer.WriteEndElement ();
+
+                                       writer.WriteStartElement ("scopes");
+                                       foreach (var scope in method.GetCodeBlocks ()) {
+                                               writer.WriteStartElement ("entry");
+                                               writer.WriteAttributeString ("index", scope.Index.ToString ());
+                                               writer.WriteAttributeString ("start", IntToHex (scope.StartOffset));
+                                               writer.WriteAttributeString ("end", IntToHex (scope.EndOffset));
+                                               writer.WriteEndElement ();
+                                       }
+                                       writer.WriteEndElement ();
 
-                                       success &= test.CompareIL (mi, this);
+                                       writer.WriteEndElement ();
                                }
+                               writer.WriteEndElement ();
+
+                               writer.WriteEndElement ();
+                               writer.WriteEndDocument ();
                        }
+               }
 
-                       return success;
+               static string IntToHex (int value)
+               {
+                       return "0x" + value.ToString ("x", CultureInfo.InvariantCulture);
                }
 
-               bool ExecuteFile (MethodInfo entry_point, string exe_name, string filename)
+               static string BoolToString (bool value)
                {
-                       TextWriter stdout = Console.Out;
-                       TextWriter stderr = Console.Error;
-                       Console.SetOut (TextWriter.Null);
-                       Console.SetError (TextWriter.Null);
-                       ParameterInfo[] pi = entry_point.GetParameters ();
-                       object[] args = pi.Length == 0 ? null : default_args;
-
-                       object result = null;
-                       try {
-                               try {
-                                       result = entry_point.Invoke (null, args);
-                               } finally {
-                                       Console.SetOut (stdout);
-                                       Console.SetError (stderr);
-                               }
-                       }
-                       catch (Exception e) {
-                               HandleFailure (filename, TestResult.ExecError, e.ToString ());
-                               return false;
-                       }
+                       return value ? "true" : "false";
+               }
 
-                       if (result is int && (int)result != 0) {
-                               HandleFailure (filename, TestResult.ExecError, "Wrong return code: " + result.ToString ());
-                               return false;
-                       }
-                       return true;
+               protected override TestCase CreateTestCase (string filename, string [] options, string [] deps)
+               {
+                       return new PositiveTestCase (filename, options, deps);
                }
 
                public void HandleFailure (string file, TestResult status, string extra)
@@ -887,6 +1016,10 @@ namespace TestRunner {
                                        }
                                        extra = null;
                                        break;
+
+                               case TestResult.DebugError:
+                                       LogFileLine (file, "REGRESSION (SUCCESS -> SYMBOL FILE ERROR)");
+                                       break;
                        }
 
                        if (extra != null)
@@ -899,11 +1032,7 @@ namespace TestRunner {
                public override void Initialize ()
                {
                        if (verif_file != null) {
-#if NET_2_0
                                LoadVerificationData (verif_file);
-#else
-                               throw new NotSupportedException ();
-#endif
                        }
 
                        base.Initialize ();
@@ -914,15 +1043,10 @@ namespace TestRunner {
                        base.CleanUp ();
 
                        if (update_verif_file) {
-#if NET_2_0
                                UpdateVerificationData (verif_file);
-#else
-                               throw new NotSupportedException ();
-#endif
                        }
                }
 
-#if NET_2_0
                void LoadVerificationData (string file)
                {
                        LogLine ("Loading verification data from `{0}' ...", file);
@@ -959,7 +1083,6 @@ namespace TestRunner {
                                w.WriteEndElement ();
                        }
                }
-#endif
        }
 
        class NegativeChecker: Checker
@@ -1012,11 +1135,7 @@ namespace TestRunner {
                                // Some error tests require to have different error text for different runtimes.
                                if (filtered.StartsWith ("//GMCS")) {
                                        row = 1;
-#if !NET_2_0
-                                       return true;
-#else
                                        return AnalyzeTestFile(file, ref row, line, ref compiler_options, ref dependencies);
-#endif
                                }
 
                                check_error_line = !filtered.StartsWith ("//Line:0");
@@ -1099,7 +1218,7 @@ namespace TestRunner {
                        ArrayList ld = new ArrayList ();
                        CompilerError result = CompilerError.Missing;
                        while (line != null) {
-                               if (ld.Contains (line)) {
+                               if (ld.Contains (line) && result == CompilerError.Expected) {
                                        if (line.IndexOf ("Location of the symbol related to previous") == -1)
                                                return CompilerError.Duplicate;
                                }
@@ -1110,8 +1229,13 @@ namespace TestRunner {
                                                if (check_msg) {
                                                        int first = line.IndexOf (':');
                                                        int second = line.IndexOf (':', first + 1);
-                                                       if (second == -1 || !check_error_line)
+                                                       if (line.IndexOf ("Warning as Error: ", first, StringComparison.Ordinal) > 0) {
+                                                               if (check_error_line) {
+                                                                       second = line.IndexOf (':', second + 1);
+                                                               }
+                                                       } else if (second == -1 || !check_error_line) {
                                                                second = first;
+                                                       }
 
                                                        string msg = line.Substring (second + 1).TrimEnd ('.').Trim ();
                                                        if (msg != expected_message && msg != expected_message.Replace ('`', '\'')) {
@@ -1278,14 +1402,17 @@ namespace TestRunner {
                        }
 
                        Checker checker;
+                       bool positive;
                        switch (mode) {
                                case "neg":
                                        checker = new NegativeChecker (tester, true);
+                                       positive = false;
                                        break;
                                case "pos":
                                        string iltest;
                                        GetOption ("il", args, false, out iltest);
                                        checker = new PositiveChecker (tester, iltest);
+                                       positive = true;
 
                                        if (iltest != null && GetOption ("update-il", args, false, out temp)) {
                                                ((PositiveChecker) checker).UpdateVerificationDataFile = true;
@@ -1304,6 +1431,8 @@ namespace TestRunner {
                                checker.LogFile = temp;
                        if (GetOption ("verbose", args, false, out temp))
                                checker.Verbose = true;
+                       if (GetOption ("safe-execution", args, false, out temp))
+                               checker.SafeExecution = true;
                        if (GetOption ("compiler-options", args, true, out temp)) {
                                string[] extra = temp.Split (' ');
                                checker.ExtraCompilerOptions = extra;
@@ -1315,14 +1444,41 @@ namespace TestRunner {
                                return 1;
                        }
 
-                       string [] files = Directory.GetFiles (".", test_pattern);
-                       if (files.Length == 0) {
+                       var files = new List<string> ();
+                       switch (test_pattern) {
+                       case "v1":
+                               files.AddRange (Directory.GetFiles (".", positive ? "test*.cs" : "cs*.cs"));
+                               break;
+                       case "v2":
+                               files.AddRange (Directory.GetFiles (".", positive ? "gtest*.cs" : "gcs*.cs"));
+                               goto case "v1";
+                       case "v4":
+                               files.AddRange (Directory.GetFiles (".", positive ? "dtest*.cs" : "dcs*.cs"));
+                               goto case "v2";
+                       default:
+                               files.AddRange (Directory.GetFiles (".", test_pattern));
+                               break;
+                       }
+
+                       if (files.Count == 0) {
                                Console.Error.WriteLine ("No files matching `{0}' found", test_pattern);
                                return 2;
                        }
 
                        checker.Initialize ();
+/*
+                       files.Sort ((a, b) => {
+                               if (a.EndsWith ("-lib.cs", StringComparison.Ordinal)) {
+                                       if (!b.EndsWith ("-lib.cs", StringComparison.Ordinal))
+                                               return -1;
+                               } else if (b.EndsWith ("-lib.cs", StringComparison.Ordinal)) {
+                                       if (!a.EndsWith ("-lib.cs", StringComparison.Ordinal))
+                                               return 1;
+                               }
 
+                               return a.CompareTo (b);
+                       });
+*/
                        foreach (string s in files) {
                                string filename = Path.GetFileName (s);
                                if (Char.IsUpper (filename, 0)) { // Windows hack
@@ -1369,7 +1525,7 @@ namespace TestRunner {
                static void Usage ()
                {
                        Console.WriteLine (
-                               "Mono compiler tester, (C) 2008 Novell, Inc.\n" +
+                               "Mono compiler tester, (C) 2009 Novell, Inc.\n" +
                                "compiler-tester -mode:[pos|neg] -compiler:FILE -files:file-list [options]\n" +
                                "   \n" +
                                "   -compiler:FILE   The file which will be used to compiler tests\n" +
@@ -1379,6 +1535,7 @@ namespace TestRunner {
                                "   -log:FILE        Writes any output also to the file\n" +
                                "   -help            Lists all options\n" +
                                "   -mode:[pos|neg]  Specifies compiler test mode\n" +
+                               "   -safe-execution  Runs compiled executables in separate app-domain\n" +
                                "   -update-il       Updates IL-FILE to match compiler output\n" +
                                "   -verbose         Prints more details during testing\n"
                                );