Skip to content

Commit

Permalink
Clean-up SimpleListeners and fix invalid XML header (#93)
Browse files Browse the repository at this point in the history
As mentioned here: #91 (comment), we include some garbage in the results XML
  • Loading branch information
premun authored Apr 27, 2020
1 parent 08b0461 commit 98cd85e
Show file tree
Hide file tree
Showing 8 changed files with 133 additions and 156 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,7 @@
"profiles": {
"XHarness": {
"commandName": "Project",
"commandLineArgs": "",
"environmentVariables": {
}
"commandLineArgs": "ios package --name=DummyTestProject --assembly=\"D:\\github\\xharness\\artifacts\\bin\\DummyTestProject\\Debug\\net5.0\\DummyTestProject.dll\" --working-directory=workdir --output-directory=outdir --testing-framework=xUnit --template=Managed --platform=iPhoneSimulator"
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,35 +11,37 @@ namespace Microsoft.DotNet.XHarness.iOS.Shared.Listeners
{
public class SimpleFileListener : SimpleListener
{
Thread processor_thread;
bool cancel;
private readonly bool _xmlOutput;
private Thread _processorThread;
private bool _cancel;

public string Path { get; private set; }

public SimpleFileListener(string path, ILog log, ILog testLog, bool xmlOutput)
: base(log, testLog, xmlOutput)
public SimpleFileListener(string path, ILog log, ILog testLog, bool xmlOutput) : base(log, testLog)
{
Path = path ?? throw new ArgumentNullException(nameof(path));
_xmlOutput = xmlOutput;
}

protected override void Stop()
{
cancel = true;
processor_thread.Join();
processor_thread = null;
_cancel = true;
_processorThread.Join();
_processorThread = null;
Finished(true);
}

public override void Initialize()
{
processor_thread = new Thread(Processing);
_processorThread = new Thread(Processing);
}

protected override void Start()
{
processor_thread.Start();
_processorThread.Start();
}

void Processing()
private void Processing()
{
Connected("N/A");
using (var fs = new BlockingFileStream(Path) { Listener = this })
Expand All @@ -49,18 +51,18 @@ void Processing()
string line;
while ((line = reader.ReadLine()) != null)
{
OutputWriter.WriteLine(line);
TestLog.WriteLine(line);
if (line.StartsWith("[Runner executing:", StringComparison.Ordinal))
{
Log.WriteLine("Tests have started executing");
}
else if (!XmlOutput && line.StartsWith("Tests run: ", StringComparison.Ordinal))
else if (!_xmlOutput && line.StartsWith("Tests run: ", StringComparison.Ordinal))
{
Log.WriteLine("Tests have finished executing");
Finished();
return;
}
else if (XmlOutput && line == "<!-- the end -->")
else if (_xmlOutput && line == "<!-- the end -->")
{
Log.WriteLine("Tests have finished executing");
Finished();
Expand All @@ -71,11 +73,10 @@ void Processing()
}
}

class BlockingFileStream : FileStream
private class BlockingFileStream : FileStream
{
public SimpleFileListener Listener;

long last_position;
private long _lastPosition;

public BlockingFileStream(string path)
: base(path, FileMode.OpenOrCreate, FileAccess.Read, FileShare.ReadWrite)
Expand All @@ -84,10 +85,13 @@ public BlockingFileStream(string path)

public override int Read(byte[] array, int offset, int count)
{
while (last_position == base.Length && !Listener.cancel)
while (_lastPosition == base.Length && !Listener._cancel)
{
Thread.Sleep(25);
}

var rv = base.Read(array, offset, count);
last_position += rv;
_lastPosition += rv;
return rv;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,34 +12,35 @@ namespace Microsoft.DotNet.XHarness.iOS.Shared.Listeners
{
public class SimpleHttpListener : SimpleListener
{
readonly bool autoExit;
HttpListener server;
bool connected_once;
private readonly bool _autoExit;
private HttpListener _server;
private bool _connected_once;

public SimpleHttpListener(ILog log, ILog testLog, bool autoExit, bool xmlOutput)
: base(log, testLog, xmlOutput)
public SimpleHttpListener(ILog log, ILog testLog, bool autoExit) : base(log, testLog)
{
this.autoExit = autoExit;
_autoExit = autoExit;
}

public override void Initialize()
{
server = new HttpListener();
_server = new HttpListener();

if (Port != 0)
{
throw new NotImplementedException();
}

// Try and find an unused port
int attemptsLeft = 50;
Random r = new Random((int)DateTime.Now.Ticks);
while (attemptsLeft-- > 0)
{
var newPort = r.Next(49152, 65535); // The suggested range for dynamic ports is 49152-65535 (IANA)
server.Prefixes.Clear();
server.Prefixes.Add("http://*:" + newPort + "/");
_server.Prefixes.Clear();
_server.Prefixes.Add("http://*:" + newPort + "/");
try
{
server.Start();
_server.Start();
Port = newPort;
break;
}
Expand All @@ -52,7 +53,7 @@ public override void Initialize()

protected override void Stop()
{
server.Stop();
_server.Stop();
}

protected override void Start()
Expand All @@ -64,21 +65,23 @@ protected override void Start()
Log.WriteLine("Test log server listening on: {0}:{1}", Address, Port);
do
{
var context = server.GetContext();
var context = _server.GetContext();
processed = Processing(context);
} while (!autoExit || !processed);
} while (!_autoExit || !processed);
}
catch (Exception e)
{
var se = e as SocketException;
if (se == null || se.SocketErrorCode != SocketError.Interrupted)
{
Console.WriteLine("[{0}] : {1}", DateTime.Now, e);
}
}
finally
{
try
{
server.Stop();
_server.Stop();
}
finally
{
Expand All @@ -87,7 +90,7 @@ protected override void Start()
}
}

bool Processing(HttpListenerContext context)
private bool Processing(HttpListenerContext context)
{
var finished = false;

Expand All @@ -97,23 +100,26 @@ bool Processing(HttpListenerContext context)
var stream = request.InputStream;
var data = string.Empty;
using (var reader = new StreamReader(stream))
{
data = reader.ReadToEnd();
}

stream.Close();

switch (request.RawUrl)
{
case "/Start":
if (!connected_once)
if (!_connected_once)
{
connected_once = true;
_connected_once = true;
Connected(request.RemoteEndPoint.ToString());
}
break;
case "/Finish":
if (!finished)
{
OutputWriter.Write(data);
OutputWriter.Flush();
TestLog.Write(data);
TestLog.Flush();
finished = true;
}
break;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,74 +10,49 @@

namespace Microsoft.DotNet.XHarness.iOS.Shared.Listeners
{
public interface ISimpleListener
public interface ISimpleListener : IDisposable
{
Task CompletionTask { get; }
Task ConnectedTask { get; }
int Port { get; }
ILog TestLog { get; }

void Cancel();
void Dispose();
void Initialize();
void StartAsync();
}

public abstract class SimpleListener : ISimpleListener, IDisposable
public abstract class SimpleListener : ISimpleListener
{
readonly TaskCompletionSource<bool> stopped = new TaskCompletionSource<bool>();
readonly TaskCompletionSource<bool> connected = new TaskCompletionSource<bool>();
public ILog TestLog { get; private set; }
private readonly TaskCompletionSource<bool> _stopped = new TaskCompletionSource<bool>();
private readonly TaskCompletionSource<bool> _connected = new TaskCompletionSource<bool>();

// TODO: This can be removed as it's commented out below
string xml_data;
public ILog TestLog { get; private set; }

protected readonly IPAddress Address = IPAddress.Any;
protected ILog Log { get; }
protected bool XmlOutput { get; }
protected ILog OutputWriter { get; private set; }
protected abstract void Start();
protected abstract void Stop();

public Task ConnectedTask => connected.Task;
public Task ConnectedTask => _connected.Task;
public int Port { get; protected set; }
public abstract void Initialize();

protected SimpleListener(ILog log, ILog testLog, bool xmlOutput)
protected SimpleListener(ILog log, ILog testLog)
{
Log = log ?? throw new ArgumentNullException(nameof(log));
TestLog = testLog ?? throw new ArgumentNullException(nameof(testLog));
XmlOutput = xmlOutput;
}

protected void Connected(string remote)
{
Log.WriteLine("Connection from {0} saving logs to {1}", remote, TestLog.FullPath);
connected.TrySetResult(true);

if (OutputWriter == null)
{
OutputWriter = TestLog;
// a few extra bits of data only available from this side
var local_data =
$@"[Local Date/Time: {DateTime.Now}]
[Remote Address: {remote}]";
if (XmlOutput)
{
// This can end up creating invalid xml randomly:
// https://github.com/xamarin/maccore/issues/827
//xml_data = local_data;
}
else
{
OutputWriter.WriteLine(local_data);
}
}
_connected.TrySetResult(true);
}

protected void Finished(bool early_termination = false)
{
if (stopped.TrySetResult(early_termination))
if (_stopped.TrySetResult(early_termination))
{
if (early_termination)
{
Expand All @@ -87,16 +62,9 @@ protected void Finished(bool early_termination = false)
{
Log.WriteLine("Tests have finished executing");
}
if (xml_data != null)
{
OutputWriter.WriteLine($"<!-- \n{xml_data}\n -->");
OutputWriter.Flush();
xml_data = null;
}
}
}


public void StartAsync()
{
var t = new Thread(() =>
Expand All @@ -107,7 +75,7 @@ public void StartAsync()
}
catch (Exception e)
{
Console.WriteLine($"{GetType().Name}: an exception occurred in processing thread: {e}");
Log.WriteLine($"{GetType().Name}: an exception occurred in processing thread: {e}");
}
})
{
Expand All @@ -118,24 +86,18 @@ public void StartAsync()

public bool WaitForCompletion(TimeSpan ts)
{
return stopped.Task.Wait(ts);
return _stopped.Task.Wait(ts);
}

public Task CompletionTask
{
get
{
return stopped.Task;
}
}
public Task CompletionTask => _stopped.Task;

public void Cancel()
{
connected.TrySetCanceled();
_connected.TrySetCanceled();
try
{
// wait a second just in case more data arrives.
if (!stopped.Task.Wait(TimeSpan.FromSeconds(1)))
if (!_stopped.Task.Wait(TimeSpan.FromSeconds(1)))
Stop();
}
catch
Expand All @@ -144,19 +106,10 @@ public void Cancel()
}
}

#region IDisposable Support
protected virtual void Dispose(bool disposing)
public virtual void Dispose()
{
if (OutputWriter != null)
OutputWriter.Dispose();
TestLog.Dispose();
}

public void Dispose()
{
Dispose(true);
}
#endregion

}
}

Loading

0 comments on commit 98cd85e

Please sign in to comment.