X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mono%2Ftests%2Ftest-runner.cs;h=af932e2f2907c355b91b4c6d3f5bf5edc190776d;hb=79cc1aeccd086b2d9006d6e549426d4ac1ceb80e;hp=cf62e2d1689ecabb3db43859db72cf2ab5c44a91;hpb=223c12a73c91984b724c5d30d432ddc8f75d9d41;p=mono.git diff --git a/mono/tests/test-runner.cs b/mono/tests/test-runner.cs index cf62e2d1689..af932e2f290 100644 --- a/mono/tests/test-runner.cs +++ b/mono/tests/test-runner.cs @@ -18,7 +18,7 @@ using System.Xml; using System.Text; using System.Text.RegularExpressions; -#if !MOBILE_STATIC +#if !FULL_AOT_DESKTOP && !MOBILE using Mono.Unix.Native; #endif @@ -31,10 +31,12 @@ public class TestRunner const string TEST_TIME_FORMAT = "mm\\:ss\\.fff"; const string ENV_TIMEOUT = "TEST_DRIVER_TIMEOUT_SEC"; const string MONO_PATH = "MONO_PATH"; + const string MONO_GAC_PREFIX = "MONO_GAC_PREFIX"; class ProcessData { public string test; public StringBuilder stdout, stderr; + public object stdoutLock = new object (), stderrLock = new object (); public string stdoutName, stderrName; } @@ -55,11 +57,10 @@ public class TestRunner string runtime = "mono"; string config = null; string mono_path = null; + string runtime_args = null; + string mono_gac_prefix = null; var opt_sets = new List (); - string aot_run_flags = null; - string aot_build_flags = null; - // Process options int i = 0; while (i < args.Length) { @@ -95,6 +96,13 @@ public class TestRunner } runtime = args [i + 1]; i += 2; + } else if (args [i] == "--runtime-args") { + if (i + 1 >= args.Length) { + Console.WriteLine ("Missing argument to --runtime-args command line option."); + return 1; + } + runtime_args = (runtime_args ?? "") + " " + args [i + 1]; + i += 2; } else if (args [i] == "--config") { if (i + 1 >= args.Length) { Console.WriteLine ("Missing argument to --config command line option."); @@ -131,13 +139,6 @@ public class TestRunner } inputFile = args [i + 1]; i += 2; - } else if (args [i] == "--runtime") { - if (i + 1 >= args.Length) { - Console.WriteLine ("Missing argument to --runtime command line option."); - return 1; - } - runtime = args [i + 1]; - i += 2; } else if (args [i] == "--mono-path") { if (i + 1 >= args.Length) { Console.WriteLine ("Missing argument to --mono-path command line option."); @@ -146,19 +147,12 @@ public class TestRunner mono_path = args [i + 1].Substring(0, args [i + 1].Length); i += 2; - } else if (args [i] == "--aot-run-flags") { + } else if (args [i] == "--mono-gac-prefix") { if (i + 1 >= args.Length) { - Console.WriteLine ("Missing argument to --aot-run-flags command line option."); + Console.WriteLine ("Missing argument to --mono-gac-prefix command line option."); return 1; } - aot_run_flags = args [i + 1].Substring(0, args [i + 1].Length); - i += 2; - } else if (args [i] == "--aot-build-flags") { - if (i + 1 >= args.Length) { - Console.WriteLine ("Missing argument to --aot-build-flags command line option."); - return 1; - } - aot_build_flags = args [i + 1].Substring(0, args [i + 1].Length); + mono_gac_prefix = args[i + 1]; i += 2; } else if (args [i] == "--verbose") { verbose = true; @@ -221,65 +215,6 @@ public class TestRunner output_width = Math.Min (120, ti.test.Length); } - if (aot_build_flags != null) { - Console.WriteLine("AOT compiling tests"); - - object aot_monitor = new object (); - var aot_queue = new Queue (tests); - - List build_threads = new List (concurrency); - - for (int j = 0; j < concurrency; ++j) { - Thread thread = new Thread (() => { - while (true) { - String test_name; - - lock (aot_monitor) { - if (aot_queue.Count == 0) - break; - test_name = aot_queue.Dequeue (); - } - - string test_bitcode_output = test_name + "_bitcode_tmp"; - string test_bitcode_arg = ",temp-path=" + test_bitcode_output; - string aot_args = aot_build_flags + test_bitcode_arg + " " + test_name; - - Directory.CreateDirectory(test_bitcode_output); - - ProcessStartInfo job = new ProcessStartInfo (runtime, aot_args); - job.UseShellExecute = false; - job.EnvironmentVariables[ENV_TIMEOUT] = timeout.ToString(); - job.EnvironmentVariables[MONO_PATH] = mono_path; - Process compiler = new Process (); - compiler.StartInfo = job; - - compiler.Start (); - - if (!compiler.WaitForExit (timeout * 1000)) { - try { - compiler.Kill (); - } catch { - } - throw new Exception(String.Format("Timeout AOT compiling tests, output in {0}", test_bitcode_output)); - } else if (compiler.ExitCode != 0) { - throw new Exception(String.Format("Error AOT compiling tests, output in {0}", test_bitcode_output)); - } else { - Directory.Delete (test_bitcode_output, true); - } - } - }); - - thread.Start (); - - build_threads.Add (thread); - } - - for (int j = 0; j < build_threads.Count; ++j) - build_threads [j].Join (); - - Console.WriteLine("Done compiling"); - } - List threads = new List (concurrency); DateTime test_start_time = DateTime.UtcNow; @@ -306,19 +241,16 @@ public class TestRunner Console.Write ("."); } - string test_invoke; + /* Spawn a new process */ - if (aot_run_flags != null) - test_invoke = aot_run_flags + " " + test; - else - test_invoke = test; + string process_args = ""; - /* Spawn a new process */ - string process_args; - if (opt_set == null) - process_args = test_invoke; - else - process_args = "-O=" + opt_set + " " + test_invoke; + if (opt_set != null) + process_args += " -O=" + opt_set; + if (runtime_args != null) + process_args += " " + runtime_args; + + process_args += " " + test; ProcessStartInfo info = new ProcessStartInfo (runtime, process_args); info.UseShellExecute = false; @@ -329,6 +261,8 @@ public class TestRunner info.EnvironmentVariables["MONO_CONFIG"] = config; if (mono_path != null) info.EnvironmentVariables[MONO_PATH] = mono_path; + if (mono_gac_prefix != null) + info.EnvironmentVariables[MONO_GAC_PREFIX] = mono_gac_prefix; Process p = new Process (); p.StartInfo = info; @@ -346,14 +280,16 @@ public class TestRunner data.stderr = new StringBuilder (); p.OutputDataReceived += delegate (object sender, DataReceivedEventArgs e) { - if (e.Data != null) { - data.stdout.AppendLine (e.Data); + lock (data.stdoutLock) { + if (e.Data != null) + data.stdout.AppendLine (e.Data); } }; p.ErrorDataReceived += delegate (object sender, DataReceivedEventArgs e) { - if (e.Data != null) { - data.stderr.AppendLine (e.Data); + lock (data.stderrLock) { + if (e.Data != null) + data.stderr.AppendLine (e.Data); } }; @@ -369,14 +305,8 @@ public class TestRunner timedout.Add (data); } -#if !MOBILE_STATIC // Force the process to print a thread dump - try { - Syscall.kill (p.Id, Signum.SIGQUIT); - Thread.Sleep (1000); - } catch { - } -#endif + TryThreadDump (p.Id, data); if (verbose) { output.Write ($"timed out ({timeout}s)"); @@ -432,7 +362,9 @@ public class TestRunner XmlWriterSettings xmlWriterSettings = new XmlWriterSettings (); xmlWriterSettings.NewLineOnAttributes = true; xmlWriterSettings.Indent = true; - using (XmlWriter writer = XmlWriter.Create (String.Format ("TestResult-{0}.xml", testsuiteName), xmlWriterSettings)) { + + string xmlPath = String.Format ("TestResult-{0}.xml", testsuiteName); + using (XmlWriter writer = XmlWriter.Create (xmlPath, xmlWriterSettings)) { // writer.WriteStartDocument (); // @@ -549,6 +481,16 @@ public class TestRunner // writer.WriteEndElement (); writer.WriteEndDocument (); + + string babysitterXmlList = Environment.GetEnvironmentVariable("MONO_BABYSITTER_NUNIT_XML_LIST_FILE"); + if (!String.IsNullOrEmpty(babysitterXmlList)) { + try { + string fullXmlPath = Path.GetFullPath(xmlPath); + File.AppendAllText(babysitterXmlList, fullXmlPath + Environment.NewLine); + } catch (Exception e) { + Console.WriteLine("Attempted to record XML path to file {0} but failed.", babysitterXmlList); + } + } } if (verbose) { @@ -599,4 +541,119 @@ public class TestRunner // Char ::= #x9 | #xA | #xD | [#x20-#xD7FF] | [#xE000-#xFFFD] | [#x10000-#x10FFFF] /* any Unicode character, excluding the surrogate blocks, FFFE, and FFFF. */ return Regex.Replace (text, @"[^\x09\x0A\x0D\x20-\uD7FF\uE000-\uFFFD\u10000-\u10FFFF]", ""); } + + static void TryThreadDump (int pid, ProcessData data) + { + try { + TryGDB (pid, data); + return; + } catch { + } + +#if !FULL_AOT_DESKTOP && !MOBILE + /* LLDB cannot produce managed stacktraces for all the threads */ + try { + Syscall.kill (pid, Signum.SIGQUIT); + Thread.Sleep (1000); + } catch { + } +#endif + + try { + TryLLDB (pid, data); + return; + } catch { + } + } + + static void TryLLDB (int pid, ProcessData data) + { + string filename = Path.GetTempFileName (); + + using (StreamWriter sw = new StreamWriter (new FileStream (filename, FileMode.Open, FileAccess.Write))) + { + sw.WriteLine ("process attach --pid " + pid); + sw.WriteLine ("thread list"); + sw.WriteLine ("thread backtrace all"); + sw.WriteLine ("detach"); + sw.WriteLine ("quit"); + sw.Flush (); + + ProcessStartInfo psi = new ProcessStartInfo { + FileName = "lldb", + Arguments = "--batch --source \"" + filename + "\" --no-lldbinit", + UseShellExecute = false, + RedirectStandardError = true, + RedirectStandardOutput = true, + }; + + using (Process process = new Process { StartInfo = psi }) + { + process.OutputDataReceived += delegate (object sender, DataReceivedEventArgs e) { + lock (data.stdoutLock) { + if (e.Data != null) + data.stdout.AppendLine (e.Data); + } + }; + + process.ErrorDataReceived += delegate (object sender, DataReceivedEventArgs e) { + lock (data.stderrLock) { + if (e.Data != null) + data.stderr.AppendLine (e.Data); + } + }; + + process.Start (); + process.BeginOutputReadLine (); + process.BeginErrorReadLine (); + if (!process.WaitForExit (60 * 1000)) + process.Kill (); + } + } + } + + static void TryGDB (int pid, ProcessData data) + { + string filename = Path.GetTempFileName (); + + using (StreamWriter sw = new StreamWriter (new FileStream (filename, FileMode.Open, FileAccess.Write))) + { + sw.WriteLine ("attach " + pid); + sw.WriteLine ("info threads"); + sw.WriteLine ("thread apply all p mono_print_thread_dump(0)"); + sw.WriteLine ("thread apply all backtrace"); + sw.Flush (); + + ProcessStartInfo psi = new ProcessStartInfo { + FileName = "gdb", + Arguments = "-batch -x \"" + filename + "\" -nx", + UseShellExecute = false, + RedirectStandardError = true, + RedirectStandardOutput = true, + }; + + using (Process process = new Process { StartInfo = psi }) + { + process.OutputDataReceived += delegate (object sender, DataReceivedEventArgs e) { + lock (data.stdoutLock) { + if (e.Data != null) + data.stdout.AppendLine (e.Data); + } + }; + + process.ErrorDataReceived += delegate (object sender, DataReceivedEventArgs e) { + lock (data.stderrLock) { + if (e.Data != null) + data.stderr.AppendLine (e.Data); + } + }; + + process.Start (); + process.BeginOutputReadLine (); + process.BeginErrorReadLine (); + if (!process.WaitForExit (60 * 1000)) + process.Kill (); + } + } + } }