public TcpTestListener (IRemoteEventListener listener)
		{
			TcpListener = new TcpListener (new IPEndPoint (IPAddress.Loopback, 0));
			TcpListener.Start ();
			Task.Factory.StartNew (() => {
				try {
					using (var client = TcpListener.AcceptTcpClient ())
					using (var socketStream = client.GetStream ())
					using (var reader = new StreamReader (socketStream, Encoding.UTF8)) {

						string line = null;
						while ((line = reader.ReadLine ()) != null) {
							var element = XElement.Parse (line);

							Gtk.Application.Invoke (delegate {
								var testName = element.Attribute ("name").Value;
								if (element.Name.LocalName == "suite-started") {
									listener.SuiteStarted (testName);
								} else if (element.Name.LocalName == "test-started") {
									listener.TestStarted (testName);
								} else if (element.Name.LocalName == "test-finished") {
									listener.TestFinished (testName, CreateResult (element));
								} else if (element.Name.LocalName == "suite-finished") {
									listener.SuiteFinished (testName, CreateResult (element));
								}
							});
						}
					}
				} catch {

				} finally {
					TcpListener.Stop ();
				}
			});
		}
		public TcpTestListener (IRemoteEventListener listener, string suiteName)
		{
			this.testSuiteName = suiteName;
			this.listener = listener;
			bool rootSuiteStarted = false;

			TcpListener = new TcpListener (new IPEndPoint (IPAddress.Loopback, 0));
			TcpListener.Start ();
			Task.Factory.StartNew (() => {
				try {
					using (var client = TcpListener.AcceptTcpClient ())
					using (var socketStream = client.GetStream ())
					using (var reader = new StreamReader (socketStream, Encoding.UTF8)) {

						string line = null;
						while ((line = reader.ReadLine ()) != null) {
							var element = XElement.Parse (line);
							string testName = element.Attribute ("name").Value;
							var action = element.Name.LocalName;

							if (testSuiteName.Length == 0 && !rootSuiteStarted) {
								// Running the whole assembly
								rootTestName = testName;
								rootSuiteStarted = true;
								continue;
							}
							if (testSuiteName == testName && !rootSuiteStarted) {
								// Running a test suite
								rootTestName = testName;
								rootSuiteStarted = true;
								listener.SuiteStarted ("<root>");
								continue;
							}

							if (!rootSuiteStarted)
								continue;

							switch (action) {
							case "suite-started":
								UpdateTestSuiteStatus (testName, false); break;
							case "test-started":
								UpdateTestSuiteStatus (testName, true);
								listener.TestStarted (testName); break;
							case "test-finished":
								var res = CreateResult (element);
								AddTestResult (res);
								listener.TestFinished (testName, res); break;
							case "suite-finished":
								if (testName == rootTestName) {
									FinishSuites (0);
									listener.SuiteFinished ("<root>", CreateResult (element));
									rootSuiteStarted = false;
								}
								break;
							}
						}
					}
				} catch (Exception ex) {
					LoggingService.LogError ("Exception in test listener", ex);
				} finally {
					TcpListener.Stop ();
				}
			});
		}
		UnitTestResult ReportXmlResult (IRemoteEventListener listener, XElement elem, string testPrefix, bool macunitStyle)
		{
			UnitTestResult result = new UnitTestResult ();
			var time = (string)elem.Attribute ("time");
			if (time != null)
				result.Time = TimeSpan.FromSeconds (double.Parse (time, CultureInfo.InvariantCulture));
			result.TestDate = DateTime.Now;

			var reason = elem.Element ("reason");
			if (reason != null)
				result.Message = (string) reason;

			var failure = elem.Element ("failure");
			if (failure != null) {
				var msg = failure.Element ("message");
				if (msg != null)
					result.Message = (string)msg;
				var stack = failure.Element ("stack-trace");
				if (stack != null)
					result.StackTrace = (string)stack;
			}

			switch ((string)elem.Attribute ("result")) {
			case "Error":
			case "Failure":
				result.Status = ResultStatus.Failure;
				break;
			case "Success":
				result.Status = ResultStatus.Success;
				break;
			case "Ignored":
				result.Status = ResultStatus.Ignored;
				break;
			default:
				result.Status = ResultStatus.Inconclusive;
				break;
			}

			if (elem.Name == "test-suite") {
				// nunitlite does not emit <test-suite type="Namespace" elements so we need to fake
				// them by deconstructing the full type name and emitting the suite started events manually
				var names = new List<string> ();
				if (!macunitStyle || (string)elem.Attribute ("type") == "Assembly")
					names.Add ("<root>");
				else
					names.AddRange (elem.Attribute ("name").Value.Split ('.'));

				for (int i = 0; i < names.Count; i ++)
					listener.SuiteStarted (testPrefix + string.Join (".", names.Take (i + 1)));

				var name = (string)elem.Attribute ("type") == "Assembly" ? "<root>" : (string) elem.Attribute ("name");
				var cts = elem.Element ("results");
				if (cts != null) {
					foreach (var ct in cts.Elements ()) {
						var r = ReportXmlResult (listener, ct, name != "<root>" ? testPrefix + name + "." : "", macunitStyle);
						result.Add (r);
					}
				}
				for (int i = 0; i < names.Count; i ++)
					listener.SuiteFinished (testPrefix + string.Join (".", names.Take (i + 1)), result);
			} else {
				string name = (string)elem.Attribute ("name");
				switch (result.Status) {
				case ResultStatus.Success:
					result.Passed++;
					break;
				case ResultStatus.Failure:
					result.Failures++;
					break;
				case ResultStatus.Ignored:
					result.Ignored++;
					break;
				case ResultStatus.Inconclusive:
					result.Inconclusive++;
					break;
				}

				listener.TestStarted (name);
				listener.TestFinished (name, result);
			}
			return result;
		}
		UnitTestResult ReportXmlResult (IRemoteEventListener listener, XElement elem, string testPrefix)
		{
			UnitTestResult result = new UnitTestResult ();
			var time = (string)elem.Attribute ("time");
			if (time != null)
				result.Time = TimeSpan.FromSeconds (double.Parse (time, CultureInfo.InvariantCulture));
			result.TestDate = DateTime.Now;

			var reason = elem.Element ("reason");
			if (reason != null)
				result.Message = (string) reason;

			var failure = elem.Element ("failure");
			if (failure != null) {
				var msg = failure.Element ("message");
				if (msg != null)
					result.Message = (string)msg;
				var stack = failure.Element ("stack-trace");
				if (stack != null)
					result.StackTrace = (string)stack;
			}

			switch ((string)elem.Attribute ("result")) {
			case "Error":
			case "Failure":
				result.Status = ResultStatus.Failure;
				break;
			case "Success":
				result.Status = ResultStatus.Success;
				break;
			case "Ignored":
				result.Status = ResultStatus.Ignored;
				break;
			default:
				result.Status = ResultStatus.Inconclusive;
				break;
			}

			if (elem.Name == "test-suite") {
				var name = (string)elem.Attribute ("type") == "Assembly" ? "<root>" : (string) elem.Attribute ("name");
				listener.SuiteStarted (testPrefix + name);
				var cts = elem.Element ("results");
				if (cts != null) {
					foreach (var ct in cts.Elements ()) {
						var r = ReportXmlResult (listener, ct, name != "<root>" ? testPrefix + name + "." : "");
						result.Add (r);
					}
				}
				listener.SuiteFinished (testPrefix + name, result);
			} else {
				string name = (string)elem.Attribute ("name");
				switch (result.Status) {
				case ResultStatus.Success:
					result.Passed++;
					break;
				case ResultStatus.Failure:
					result.Failures++;
					break;
				case ResultStatus.Ignored:
					result.Ignored++;
					break;
				case ResultStatus.Inconclusive:
					result.Inconclusive++;
					break;
				}

				listener.TestStarted (name);
				listener.TestFinished (name, result);
			}
			return result;
		}
 public void TestStarted(TestName testCase)
 {
     wrapped.TestStarted(GetTestName(testCase));
     consoleOutput = new StringBuilder();
     consoleError  = new StringBuilder();
 }