Created
February 15, 2012 03:52
-
-
Save ronnieoverby/1833047 to your computer and use it in GitHub Desktop.
An interesting and bizarre unit test from my logging library
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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