Skip to content
This repository has been archived by the owner on Jan 10, 2025. It is now read-only.

Commit

Permalink
Add a HttpTextWriter that can send logs over http.
Browse files Browse the repository at this point in the history
There is no public API to create raw sockets with watchOS, so
we can't use Tcp directly, thus the need for using Http.
  • Loading branch information
rolfbjarne committed May 26, 2016
1 parent 1b5be08 commit ffe2a6d
Show file tree
Hide file tree
Showing 3 changed files with 142 additions and 7 deletions.
100 changes: 100 additions & 0 deletions NUnitLite/TouchRunner/HttpTextWriter.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
// HttpTextWriter.cs: Class to report test results using http requests
//
// Authors:
// Rolf Bjarne Kvinge <rolf@xamarin.com>
//
// Copyright 2016 Xamarin Inc.
//

using System;
using System.IO;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

#if __UNIFIED__
using Foundation;
#else
using MonoTouch.Foundation;
#endif

namespace MonoTouch.NUnit {
class HttpTextWriter : TextWriter
{
public string HostName;
public int Port;

TaskCompletionSource<bool> finished = new TaskCompletionSource<bool> ();
TaskCompletionSource<bool> closed = new TaskCompletionSource<bool> ();
StringBuilder log = new StringBuilder ();

public Task FinishedTask {
get {
return finished.Task;
}
}

public override Encoding Encoding {
get {
return Encoding.UTF8;
}
}

public override void Close ()
{
closed.SetResult (true);
Task.Run (async () =>
{
await finished.Task;
base.Close ();
});
}

Task SendData (string action, string uploadData)
{
var url = NSUrl.FromString ("http://" + HostName + ":" + Port + "/" + action);
var request = new NSMutableUrlRequest (url);
request.HttpMethod = "POST";
return NSUrlSession.SharedSession.CreateUploadTaskAsync (request, NSData.FromString (uploadData));
}

async void SendThread ()
{
try {
await SendData ("Start", "");
await closed.Task;
await SendData ("Finish", log.ToString ());
} catch (Exception ex) {
Console.WriteLine ("HttpTextWriter failed: {0}", ex);
} finally {
finished.SetResult (true);
}
}

public void Open ()
{
new Thread (SendThread)
{
IsBackground = true,
}.Start ();
}

public override void Write (char value)
{
Console.Out.Write (value);
log.Append (value);
}

public override void Write (char [] buffer)
{
Console.Out.Write (buffer);
log.Append (buffer);
}

public override void WriteLine (string value)
{
Console.Out.WriteLine (value);
log.AppendLine (value);
}
}
}
8 changes: 7 additions & 1 deletion NUnitLite/TouchRunner/TouchOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ public TouchOptions ()
EnableNetwork = defaults.BoolForKey ("network.enabled");
HostName = defaults.StringForKey ("network.host.name");
HostPort = (int)defaults.IntForKey ("network.host.port");
Transport = defaults.StringForKey ("network.transport");
SortNames = defaults.BoolForKey ("display.sort");

bool b;
Expand All @@ -64,13 +65,16 @@ public TouchOptions ()
HostPort = i;
if (bool.TryParse (Environment.GetEnvironmentVariable ("NUNIT_SORTNAMES"), out b))
SortNames = b;
if (!string.IsNullOrEmpty (Environment.GetEnvironmentVariable ("NUNIT_TRANSPORT")))
Transport = Environment.GetEnvironmentVariable ("NUNIT_TRANSPORT");

var os = new OptionSet () {
{ "autoexit", "If the app should exit once the test run has completed.", v => TerminateAfterExecution = true },
{ "autostart", "If the app should automatically start running the tests.", v => AutoStart = true },
{ "hostname=", "Comma-separated list of host names or IP address to (try to) connect to", v => HostName = v },
{ "hostport=", "TCP port to connect to.", v => HostPort = int.Parse (v) },
{ "hostport=", "HTTP/TCP port to connect to.", v => HostPort = int.Parse (v) },
{ "enablenetwork", "Enable the network reporter.", v => EnableNetwork = true },
{ "transport=", "Select transport method. Either TCP (default) or HTTP.", v => Transport = v },
};

try {
Expand All @@ -90,6 +94,8 @@ public TouchOptions ()

public bool TerminateAfterExecution { get; set; }

public string Transport { get; set; } = "TCP";

public bool ShowUseNetworkLogger {
get { return (EnableNetwork && !String.IsNullOrWhiteSpace (HostName) && (HostPort > 0)); }
}
Expand Down
41 changes: 35 additions & 6 deletions NUnitLite/TouchRunner/TouchRunner.cs
Original file line number Diff line number Diff line change
Expand Up @@ -127,8 +127,16 @@ public void AutoRun ()

// optionally end the process, e.g. click "Touch.Unit" -> log tests results, return to springboard...
// http://stackoverflow.com/questions/1978695/uiapplication-sharedapplication-terminatewithsuccess-is-not-there
if (TerminateAfterExecution)
TerminateWithSuccess ();
if (TerminateAfterExecution) {
if (WriterFinishedTask != null) {
Task.Run (async () => {
await WriterFinishedTask;
TerminateWithSuccess ();
});
} else {
TerminateWithSuccess ();
}
}
});
}

Expand All @@ -149,6 +157,8 @@ public void Run ()

public TextWriter Writer { get; set; }

Task WriterFinishedTask { get; set; }

static string SelectHostName (string[] names, int port)
{
if (names.Length == 0)
Expand Down Expand Up @@ -205,15 +215,34 @@ public bool OpenWriter (string message)
if (hostname != null) {
Console.WriteLine ("[{0}] Sending '{1}' results to {2}:{3}", now, message, hostname, options.HostPort);
try {
Writer = new TcpTextWriter (hostname, options.HostPort);
WriterFinishedTask = null;
switch (options.Transport) {
case "HTTP":
var w = new HttpTextWriter ()
{
HostName = hostname,
Port = options.HostPort,
};
w.Open ();
Writer = w;
WriterFinishedTask = w.FinishedTask;
break;
default:
Console.WriteLine ("Unknown transport '{0}': switching to default (TCP)", options.Transport);
goto case "TCP";
case "TCP":
Writer = new TcpTextWriter (hostname, options.HostPort);
break;
}
}
catch (SocketException) {
catch (Exception ex) {
#if __TVOS__ || __WATCHOS__
Console.WriteLine ("Network error: Cannot connect to {0}:{1}. Continuing on console.", hostname, options.HostPort);
Console.WriteLine ("Network error: Cannot connect to {0}:{1}: {2}. Continuing on console.", hostname, options.HostPort, ex);
Writer = Console.Out;
#else
Console.WriteLine ("Network error: Cannot connect to {0}:{1}: {2}.", hostname, options.HostPort, ex);
UIAlertView alert = new UIAlertView ("Network Error",
String.Format ("Cannot connect to {0}:{1}. Continue on console ?", hostname, options.HostPort),
String.Format ("Cannot connect to {0}:{1}: {2}. Continue on console ?", hostname, options.HostPort, ex.Message),
null, "Cancel", "Continue");
int button = -1;
alert.Clicked += delegate(object sender, UIButtonEventArgs e) {
Expand Down

0 comments on commit ffe2a6d

Please sign in to comment.