Skip to content

Instantly share code, notes, and snippets.

@ronnieoverby
Created February 15, 2012 03:52
Show Gist options
  • Save ronnieoverby/1833047 to your computer and use it in GitHub Desktop.
Save ronnieoverby/1833047 to your computer and use it in GitHub Desktop.
An interesting and bizarre unit test from my logging library
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using NUnit.Framework;
using Overby.Logger;
namespace Overby.Logging.Tests
{
[TestFixture]
public class MultiThreadingTests
{
class ThreadUnsafeLogger : Logger.Logger
{
Guid ctrl;
Guid test;
public ThreadUnsafeLogger()
{
test = ctrl = Guid.NewGuid();
}
protected override void PerformLogging(LogEntry entry)
{
Control();
}
public void Control()
{
// it doesn't get any more thread dangerous than this!!!
if (test != ctrl)
throw new ThreadSafetyException();
// now you see it
test = Guid.NewGuid();
// now you don't
test = ctrl;
}
}
ThreadUnsafeLogger logger;
[TestFixtureSetUp]
public void TestFixtureSetUp()
{
logger = new ThreadUnsafeLogger { IsAsynchronous = false };
ExceptionHandler.LoggerExceptionUnhandled += new EventHandler<LoggerExceptionEventArgs>(ExceptionHandler_LoggerExceptionUnhandled);
}
void ExceptionHandler_LoggerExceptionUnhandled(object sender, LoggerExceptionEventArgs e)
{
throw new AssertionException("this shouldn't happen!", e.Exception);
}
[SetUp]
public void TestSetup()
{
}
[Test]
public void logger_operations_are_thread_safe_even_if_logger_is_not()
{
// this test hasn't failed after many invokations and always completes in twice the set duration
// looks like a passing test :)
var duration = TimeSpan.FromSeconds(5);
Console.WriteLine("verify Control() doesnt throw in sequence");
Assert.DoesNotThrow(() =>
{
foreach (var x in Until(duration))
logger.Control();
});
Console.WriteLine("verify Control() throws in parallel ");
try
{
Parallel.ForEach(WhileTrue(), x => logger.Control());
Assert.Fail("DID NOT THROW!");
}
catch (AggregateException aggex)
{
foreach (var ex in aggex.Flatten().InnerExceptions)
{
Assert.IsInstanceOf<ThreadSafetyException>(ex);
}
}
Console.WriteLine("verify Control() called via logging operation does not throw in parallel (is thread safe)");
Assert.DoesNotThrow(() =>
Parallel.ForEach(Until(duration), x => logger.LogInfo("test")));
}
IEnumerable<ulong> Until(TimeSpan duration)
{
var until = DateTime.Now.Add(duration);
ulong i = 0;
while (DateTime.Now < until)
{
yield return i++;
}
}
IEnumerable<ulong> WhileTrue()
{
ulong i = 0;
while (true)
{
yield return i++;
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment