Skip to content

Commit

Permalink
Issue: #29
Browse files Browse the repository at this point in the history
Added unit tests to test issue #29
  • Loading branch information
xforever1313 committed Feb 3, 2019
1 parent fd9c24a commit 78cbc44
Show file tree
Hide file tree
Showing 2 changed files with 107 additions and 1 deletion.
7 changes: 7 additions & 0 deletions Chaskis/ChaskisCore/IrcConnection.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,12 @@ public class IrcConnection : IDisposable, IConnection, IChaskisEventScheduler, I
/// </summary>
public event Action<string> ReadEvent;

/// <summary>
/// Internal event called when the reader thread exits.
/// Mainly here for unit testing reasons.
/// </summary>
internal event Action OnReaderThreadExit;

// Rationale for maximum length:
// Per this site: http://www.networksorcery.com/enp/protocol/irc.htm
// The command MUST either be a valid IRC command or a three digit
Expand Down Expand Up @@ -747,6 +753,7 @@ private void ReaderThread()
finally
{
StaticLogger.Log.WriteLine( "ReaderThread Exiting" );
this.OnReaderThreadExit?.Invoke();
}
}

Expand Down
101 changes: 100 additions & 1 deletion Chaskis/UnitTests/CoreTests/IrcConnectionTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,12 @@
//

using System;
using System.IO;
using System.Net.Sockets;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using Chaskis.Core;
using Chaskis.UnitTests.Common;
using Moq;
using NUnit.Framework;

Expand Down Expand Up @@ -439,8 +442,104 @@ public void SendPongTest()
this.mac.VerifyAll();
}

/// <summary>
/// Ensures the reader thread will exit correctly when a <see cref="SocketException"/> happens.
/// </summary>
[Test]
public void ReaderThreadSocketException()
{
this.DoReaderThreadFailureTest( new SocketException() );
}

/// <summary>
/// Ensures the reader thread will exit correctly when a <see cref="IOException"/> happens.
/// </summary>
[Test]
public void ReaderThreadIoException()
{
this.DoReaderThreadFailureTest( new IOException() );
}

/// <summary>
/// Ensures the reader thread will exit correctly when an <see cref="ObjectDisposedException"/> happens.
/// </summary>
[Test]
public void ReaderThreadObjectDisposedException()
{
this.DoReaderThreadFailureTest( new ObjectDisposedException( "someobject" ) );
}

/// <summary>
/// Ensures the reader thread will exit correctly when an <see cref="AggregateException"/> happens.
/// </summary>
[Test]
public void ReaderThreadAggregateException()
{
this.DoReaderThreadFailureTest( new AggregateException() );
}

/// <summary>
/// Ensures the reader thread will exit correctly when any <see cref="Exception"/> happens.
/// </summary>
[Test]
public void ReaderThreadException()
{
this.DoReaderThreadFailureTest( new Exception( "lol" ) );
}

// ---------------- Test Helpers ----------------

/// <summary>
/// This test tests issue that caused issue #29.
/// If we catch an Exception we weren't expecting, the reader thread would
/// blow up and consistently throw exceptions.
///
/// Now if we get any Exception, we gracefully exit the reader thread and wait
/// for the watchdog to reconnect us. This test case simply tests that the
/// reader thread terminates.
/// </summary>
private void DoReaderThreadFailureTest<T>( T e ) where T : Exception
{
const string line1 = "Line 1";

this.mac.SetupSequence(
m => m.ReadLine()
)
.Returns( line1 )
.Throws( e );

StringBuilder messages = new StringBuilder();
using( ManualResetEvent readerThreadExitedEvent = new ManualResetEvent( false ) )
{
using( IrcConnection connection = new IrcConnection( this.defaultConfig, this.parsingQueue.Object, this.mac.Object ) )
{
void threadExitedAction() { readerThreadExitedEvent.Set(); }
void onReadLineAction( string s ) { messages.AppendLine( s ); }

try
{
connection.OnReaderThreadExit += threadExitedAction;
connection.ReadEvent += onReadLineAction;

this.DoConnect( connection );

Assert.IsTrue( readerThreadExitedEvent.WaitOne( 5000 ) );

this.DoDisconnect( connection );
}
finally
{
connection.OnReaderThreadExit -= threadExitedAction;
connection.ReadEvent -= onReadLineAction;
}
}
}

// Ensure our line gets called *somewhere*.
Assert.IsTrue( Regex.IsMatch( messages.ToString(), @"\s*" + line1 + @"\s*" ) );
this.mac.VerifyAll();
}

private void SetupConnection()
{
this.mac.Setup(
Expand Down

0 comments on commit 78cbc44

Please sign in to comment.