//
// Copyright (C) 2008 Novell, Inc (http://www.novell.com)
//
-// Permission is hereby granted, free of charge, to any person obtaining
-// a copy of this software and associated documentation files (the
-// "Software"), to deal in the Software without restriction, including
-// without limitation the rights to use, copy, modify, merge, publish,
-// distribute, sublicense, and/or sell copies of the Software, and to
-// permit persons to whom the Software is furnished to do so, subject to
-// the following conditions:
-//
-// The above copyright notice and this permission notice shall be
-// included in all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
-// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
//
using System;
using System.IO;
using System.Globalization;
using System.Xml;
using System.Text.RegularExpressions;
+using Mono.Unix.Native;
//
// This is a simple test runner with support for parallel execution
public class TestRunner
{
+ const string TEST_TIME_FORMAT = "mm\\:ss\\.fff";
+ const string ENV_TIMEOUT = "TEST_DRIVER_TIMEOUT_SEC";
+
class ProcessData {
public string test;
public StreamWriter stdout, stderr;
string testsuiteName = null;
string inputFile = null;
- DateTime test_start_time = DateTime.UtcNow;
-
// FIXME: Add support for runtime arguments + env variables
string disabled_tests = null;
object monitor = new object ();
- if (concurrency != 1)
- Console.WriteLine ("Running tests: ");
+ Console.WriteLine ("Running tests: ");
var test_info = new Queue<TestInfo> ();
if (opt_sets.Count == 0) {
foreach (string s in tests)
test_info.Enqueue (new TestInfo { test = s, opt_set = opt });
}
- }
+ }
+
+ /* compute the max length of test names, to have an optimal output width */
+ int output_width = -1;
+ foreach (TestInfo ti in test_info) {
+ if (ti.test.Length > output_width)
+ output_width = Math.Min (120, ti.test.Length);
+ }
List<Thread> threads = new List<Thread> (concurrency);
+ DateTime test_start_time = DateTime.UtcNow;
+
for (int j = 0; j < concurrency; ++j) {
Thread thread = new Thread (() => {
while (true) {
ti = test_info.Dequeue ();
}
+ var output = new StringWriter ();
+
string test = ti.test;
string opt_set = ti.opt_set;
- if (concurrency == 1)
- Console.Write ("Testing " + test + "... ");
+ output.Write (String.Format ("{{0,-{0}}} ", output_width), test);
/* Spawn a new process */
string process_args;
info.UseShellExecute = false;
info.RedirectStandardOutput = true;
info.RedirectStandardError = true;
+ info.EnvironmentVariables[ENV_TIMEOUT] = timeout.ToString();
Process p = new Process ();
p.StartInfo = info;
}
};
+ var start = DateTime.UtcNow;
+
p.Start ();
p.BeginOutputReadLine ();
timedout.Add (data);
}
- if (concurrency == 1)
- Console.WriteLine ("timed out.");
- else
- Console.Write (".");
+ // Force the process to print a thread dump
+ try {
+ Syscall.kill (p.Id, Signum.SIGQUIT);
+ Thread.Sleep (1000);
+ } catch {
+ }
+
+ output.Write ("timed out");
p.Kill ();
} else if (p.ExitCode != expectedExitCode) {
+ var end = DateTime.UtcNow;
+
lock (monitor) {
failed.Add (data);
}
- if (concurrency == 1)
- Console.WriteLine ("failed.");
- else
- Console.Write (".");
+ output.Write ("failed, time: {0}, exit code: {1}", (end - start).ToString (TEST_TIME_FORMAT), p.ExitCode);
} else {
+ var end = DateTime.UtcNow;
+
lock (monitor) {
passed.Add (data);
}
- if (concurrency == 1)
- Console.WriteLine ("passed.");
- else
- Console.Write (".");
+ output.Write ("passed, time: {0}", (end - start).ToString (TEST_TIME_FORMAT));
}
p.Close ();
+
+ lock (monitor) {
+ Console.WriteLine (output.ToString ());
+ }
}
});
for (int j = 0; j < threads.Count; ++j)
threads [j].Join ();
+ TimeSpan test_time = DateTime.UtcNow - test_start_time;
+
int npassed = passed.Count;
int nfailed = failed.Count;
int ntimedout = timedout.Count;
- TimeSpan test_time = DateTime.UtcNow - test_start_time;
XmlWriterSettings xmlWriterSettings = new XmlWriterSettings ();
xmlWriterSettings.NewLineOnAttributes = true;
xmlWriterSettings.Indent = true;
- using (XmlWriter writer = XmlWriter.Create (String.Format ("TestResults_{0}.xml", testsuiteName), xmlWriterSettings)) {
+ using (XmlWriter writer = XmlWriter.Create (String.Format ("TestResult-{0}.xml", testsuiteName), xmlWriterSettings)) {
// <?xml version="1.0" encoding="utf-8" standalone="no"?>
writer.WriteStartDocument ();
// <!--This file represents the results of running a test suite-->
writer.WriteEndDocument ();
}
+ Console.WriteLine ();
+ Console.WriteLine ("Time: {0}", test_time.ToString (TEST_TIME_FORMAT));
Console.WriteLine ();
Console.WriteLine ("{0,4} test(s) passed", npassed);
Console.WriteLine ("{0,4} test(s) failed", nfailed);