Being Cellfish

Stuff I wished I've found in some blog (and sometimes did)

December, 2009

Change of Address
This blog has moved to blog.cellfish.se.
Posts
  • Being Cellfish

    2009 Advent Calendar December 24th

    • 0 Comments

    As I mentioned yesterday we now don't have any tests for the MutexWrapper which is a thin wrapper for the Mutex implementation in .Net. I don't think it is necessary to always have tests for these thin wrappers but sometimes it is a good idea to add a few tests just to verify that you've understood how the API works. These tests should not be run all the time as all your other unit tests but should be part of your acceptance test suite or something similar. Keep them and run them from time to time. This is how it might look for the MutexWrapper:

    1: public class MutexWrapper 2: { 3: private readonly Mutex _lock = new Mutex(); 4:   5: public virtual void WaitOne() 6: { 7: _lock.WaitOne(); 8: } 9:   10: public virtual void ReleaseMutex() 11: { 12: _lock.ReleaseMutex(); 13: } 14: } 15:   16: public class Given_an_unlocked_MutexWrapper 17: { 18: private MutexWrapper _lock = new MutexWrapper(); 19:   20: [Fact(Timeout = 1000)] 21: void It_should_be_possible_to_WaitOne() 22: { 23: _lock.WaitOne(); 24: } 25: } 26:   27: public class Given_a_locked_MutexWrapper : IDisposable 28: { 29: private MutexWrapper _lock = new MutexWrapper(); 30: private Thread _thread; 31: private bool _gotLock = false; 32:   33: public Given_a_locked_MutexWrapper() 34: { 35: _thread = new Thread(() => 36: { 37: _lock.WaitOne(); 38: _gotLock = true; 39: _lock.ReleaseMutex(); 40: }); 41: } 42:   43: public void Dispose() 44: { 45: if (_thread != null) 46: { 47: _thread.Abort(); 48: } 49: } 50:   51: private void CompleteSetup() 52: { 53: _lock.WaitOne(); 54: _thread.Start(); 55: Assert.False(_thread.Join(250)); 56: } 57:   58: [Fact(Timeout = 1000)] 59: void It_should_block_on_WaitOne() 60: { 61: CompleteSetup(); 62: Assert.False(_gotLock); 63: } 64:   65: [Fact(Timeout = 1000)] 66: void It_should_complete_WaitOne_once_released() 67: { 68: CompleteSetup(); 69: _lock.ReleaseMutex(); 70: Assert.True(_thread.Join(500)); 71: Assert.True(_gotLock); 72: } 73: } 74:   75: public class Given_an_abandoned_MutexWrapper : IDisposable 76: { 77: private MutexWrapper _lock = new MutexWrapper(); 78: private EventWaitHandle _threadStarted = new EventWaitHandle(false, EventResetMode.ManualReset); 79: private EventWaitHandle _threadStop = new EventWaitHandle(false, EventResetMode.ManualReset); 80: private Thread _thread; 81:   82: public Given_an_abandoned_MutexWrapper() 83: { 84: _thread = new Thread(() => 85: { 86: _lock.WaitOne(); 87: _threadStarted.Set(); 88: _threadStop.WaitOne(); 89: }); 90: _thread.Start(); 91: } 92:   93: public void Dispose() 94: { 95: if (_thread != null) 96: { 97: _thread.Abort(); 98: } 99: } 100:   101: [Fact(Timeout = 1000)] 102: void It_should_throw_exception_when_waited_for() 103: { 104: _threadStarted.WaitOne(); 105: _threadStop.Set(); 106: Assert.Throws<AbandonedMutexException>(() => { _lock.WaitOne(); }); 107: } 108: }
  • Being Cellfish

    2009 Advent Calendar December 1st

    • 0 Comments

    One way of adding tests for thread safety is to let the important object handle the locking through two protected members:

    1: public class ImportantObject 2: { 3: private Mutex _lock = new Mutex(); 4:   5: public void ImportantMethod() 6: { 7: Lock(); 8: // Do things. 9: Unlock(); 10: } 11:   12: protected virtual void Lock() 13: { 14: _lock.WaitOne(); 15: } 16:   17: protected virtual void Unlock() 18: { 19: _lock.ReleaseMutex(); 20: } 21: }

    Now we can write a specification that looks like this:

    1: public class Given_an_ImportantObject 2: { 3: class TestableImportantObject : ImportantObject 4: { 5: public int NumberOfLocks { get; private set; } 6: 7: public TestableImportantObject() 8: { 9: NumberOfLocks = 0; 10: } 11:   12: protected override void Lock() 13: { 14: ++NumberOfLocks; 15: } 16:   17: protected override void Unlock() 18: { 19: 20: } 21: } 22:   23: private TestableImportantObject _importantObject = new TestableImportantObject(); 24:   25: [Fact] 26: void It_should_take_lock_when_ImportantMethod_is_called() 27: { 28: _importantObject.ImportantMethod(); 29: Assert.Equal(1, _importantObject.NumberOfLocks); 30: } 31: }

    Now we have a test/specification for thread safety! or do we? 

  • Being Cellfish

    2009 Advent Calendar December 2nd

    • 0 Comments

    Adding virtual methods to handle locks as we did yesterday is really not a good solution. The lock should be a separate object and in order to be able to fake the lock I'll make it an interface:

    1: public interface Lock 2: { 3: void Lock(); 4: void Unlock(); 5: } 6:   7: public class MutexLock : Lock 8: { 9: private readonly Mutex _lock = new Mutex(); 10:   11: public void Lock() 12: { 13: _lock.WaitOne(); 14: } 15:   16: public void Unlock() 17: { 18: _lock.ReleaseMutex(); 19: } 20: }

    Considering that it would be pretty neat to inject the lock dependency to the important object using generics:

    1: public class ImportantObject<Tlock> where Tlock : Lock,new() 2: { 3: private readonly Tlock _lock = new Tlock(); 4:   5: public void ImportantMethod() 6: { 7: _lock.Lock(); 8: // Do things. 9: _lock.Unlock(); 10: } 11: }

    Then thread safety can be tested like this:

    1: public class Given_an_ImportantObject 2: { 3: class FakeLock : Lock 4: { 5: public static int NumberOfLocks { get; private set; } 6:   7: public FakeLock() 8: { 9: NumberOfLocks = 0; 10: } 11:   12: public void Lock() 13: { 14: ++NumberOfLocks; 15: } 16:   17: public void Unlock() 18: { 19:   20: } 21: } 22:   23: private ImportantObject<FakeLock> _importantObject = new ImportantObject<FakeLock>(); 24:   25: [Fact] 26: void It_should_take_lock_when_ImportantMethod_is_called() 27: { 28: _importantObject.ImportantMethod(); 29: Assert.Equal(1, FakeLock.NumberOfLocks); 30: } 31: }

    However since generics are used we need a static spy in the faked lock which might be a problem if several tests run concurrently. Not typical for unit test runners but not impossible. We'll have to address that later.

  • Being Cellfish

    2009 Advent Calendar December 20th

    • 0 Comments

    But wait! What happened yesterday? We added some significant functionality; hiding the fact that AbandonedMutexException might be thrown. Because of this I want to break out the Mutex implementation into a separate, thin wrapper for the Mutex object:

    1: public class MutexWrapper 2: { 3: private readonly Mutex _lock = new Mutex(); 4:   5: public void WaitOne() 6: { 7: _lock.WaitOne(); 8: } 9:   10: public void ReleaseMutex() 11: { 12: _lock.ReleaseMutex(); 13: } 14: }

    Given that I use generics to inject the dependency:

    1: public class MutexLock<T> : Lock where T : MutexWrapper, new() 2: { 3: private readonly T _lock = new T(); 4:   5: public void Lock() 6: { 7: try 8: { 9: _lock.WaitOne(); 10: } 11: catch (AbandonedMutexException) { } 12: } 13:   14: public void Unlock() 15: { 16: _lock.ReleaseMutex(); 17: } 18: }

    I'll spare you the changes needed to make the tests compile for now since the use of MutexWrapper makes it possible to remove all those helper threads and slow tests for the MutexLock class.

  • Being Cellfish

    2009 Advent Calendar December 19th

    • 2 Comments

    So far so good but there is one more thing I want the MutexLock to do. The Mutex object may throw an exception (AbandonedMutexException) when being waited for if the current owning thread terminates without releasing the mutex. I want to hide that fact in my MutexLock so I don't need to handle that exception everywhere in my code:

    1: public class Given_an_abandoned_lock : IDisposable 2: { 3: private MutexLock _lock = new MutexLock(); 4: private EventWaitHandle _threadStarted = new EventWaitHandle(false, EventResetMode.ManualReset); 5: private EventWaitHandle _threadStop = new EventWaitHandle(false, EventResetMode.ManualReset); 6: private Thread _thread; 7:   8: public Given_an_abandoned_lock() 9: { 10: _thread = new Thread(() => 11: { 12: _lock.Lock(); 13: _threadStarted.Set(); 14: _threadStop.WaitOne(); 15: }); 16: _thread.Start(); 17: } 18:   19: public void Dispose() 20: { 21: if (_thread != null) 22: { 23: _thread.Abort(); 24: } 25: } 26:   27: [Fact(Timeout=1000)] 28: void It_should_be_possible_to_take_lock_when_thread_dies() 29: { 30: _threadStarted.WaitOne(); 31: _threadStop.Set(); 32: Assert.DoesNotThrow(() => { _lock.Lock(); }); 33: } 34: }

    And that test leads to the following implementation:

    1: public class MutexLock : Lock 2: { 3: private readonly Mutex _lock = new Mutex(); 4:   5: public void Lock() 6: { 7: try 8: { 9: _lock.WaitOne(); 10: } 11: catch (AbandonedMutexException) {} 12: } 13:   14: public void Unlock() 15: { 16: _lock.ReleaseMutex(); 17: } 18: }
  • Being Cellfish

    The 2009 Advent Calendar Wrap Up

    • 0 Comments

    So I hope I showed you a way to BDD/TDD a thread safe solution without slow pesky tests that needs a number of helper threads to verify thread safety. Also, you're not guaranteed that your code is thread safe just because of your tests when you use threads to try and break your code. You can use something like Chess to find such bugs but having tests that consistently verifies thread safety is much better IMHO.

    And did we create better code this way (because BDD/TDD is about writing better code, right)? I think the separation of concerns between the ImportantObject, ImportantProvider and the Transaction are pretty neat. The introduction of MutexWrapper might be questionable for some people but it illustrates how different concerns should be separated and by doing so you can test more things in a simple way.

    For your convenience here is a summary of all links and the final version of the code.

  • Being Cellfish

    2009 Advent Calendar December 12th

    • 0 Comments

    So now we need to fix the broken ImportantProvider making sure it uses one lock:

    1: public class Given_two_transactions_from_the_same_ImportantProvider 2: { 3: private FakeLock _lock; 4: private ImportantProvider _importantProvider; 5: private Transaction _transaction1; 6: private Transaction _transaction2; 7:   8: public Given_two_transactions_from_the_same_ImportantProvider() 9: { 10: _lock = new FakeLock(); 11: _importantProvider = new ImportantProvider(new DummyObject(), _lock); 12: _transaction1 = _importantProvider.Transaction; 13: _transaction2 = _importantProvider.Transaction; 14: } 15:   16: [Fact] 17: void It_should_be_two_different_transactions() 18: { 19: Assert.NotSame(_transaction1, _transaction2); 20: } 21:   22: [Fact] 23: void It_should_be_the_same_ImportantObject_returned_by_both_transactions() 24: { 25: Assert.Same(_transaction1.ImportantObject, _transaction2.ImportantObject); 26: } 27:   28: [Fact] 29: void It_should_take_lock_once_for_each_transaction() 30: { 31: Assert.Equal(2, _lock.NumberOfLocks); 32: } 33: }

    As you can see in the test I've chosen constructor injection for the lock in this case:

    1: public class ImportantProvider 2: { 3: private ImportantInterface _importantObject; 4: private Lock _lock; 5:   6: public ImportantProvider(ImportantInterface importantObject, Lock aLock) 7: { 8: _lock = aLock; 9: _importantObject = importantObject; 10: } 11:   12: public Transaction Transaction 13: { 14: get 15: { 16: return new Transaction(_importantObject, _lock); 17: } 18: } 19: }
  • Being Cellfish

    2009 Advent Calendar December 14th

    • 0 Comments

    But if we're using generics; why not do it for the lock too:

    1: public class ImportantProvider<T,L> where T : ImportantInterface, new() where L : Lock,new() 2: { 3: private T _importantObject = new T(); 4: private L _lock = new L(); 5:   6: public Transaction Transaction 7: { 8: get 9: { 10: return new Transaction(_importantObject, _lock); 11: } 12: } 13: }

    But that leads to test code with static fields for verification. And I didn't like that before either... So it is a good idea to back that change out event though the ImportantProvider looks very neat with it IMHO.

  • Being Cellfish

    2009 Advent Calendar December 3rd

    • 0 Comments

    Let's continue with the same lock interface and MutexLock implementation as yesterday. In order to switch from dependency injection using generics to a classical constructor injection we have to change the important object to something like this:

    1: public class ImportantObject 2: { 3: private readonly Lock _lock; 4:   5: public ImportantObject() : this(new MutexLock()) 6: { 7: 8: } 9:   10: public ImportantObject(Lock aLock) 11: { 12: _lock = aLock; 13: } 14:   15: public void ImportantMethod() 16: { 17: _lock.Lock(); 18: // Do things. 19: _lock.Unlock(); 20: } 21: }

    Which can be tested like this:

    1: public class Given_an_ImportantObject 2: { 3: class FakeLock : Lock 4: { 5: public int NumberOfLocks { get; private set; } 6:   7: public FakeLock() 8: { 9: NumberOfLocks = 0; 10: } 11:   12: public void Lock() 13: { 14: ++NumberOfLocks; 15: } 16:   17: public void Unlock() 18: { 19:   20: } 21: } 22:   23: private ImportantObject _importantObject; 24: private FakeLock _lock; 25:   26: public Given_an_ImportantObject() 27: { 28: _lock = new FakeLock(); 29: _importantObject = new ImportantObject(_lock); 30: } 31:   32: [Fact] 33: void It_should_take_lock_when_ImportantMethod_is_called() 34: { 35: _importantObject.ImportantMethod(); 36: Assert.Equal(1, _lock.NumberOfLocks); 37: } 38: }

    However there is still one big problem with this solution. I'll tell you tomorrow.

  • Being Cellfish

    2009 Advent Calendar December 6th

    • 0 Comments

    Since I want the transaction we're creating to take the lock when created I also want to release the lock when the transaction is disposed:

    1: public class When_using_a_transaction 2: { 3: class FakeLock : Lock 4: { 5: public bool IsLocked { get; private set; } 6:   7: public FakeLock() 8: { 9: IsLocked = false; 10: } 11:   12: public void Lock() 13: { 14: IsLocked = true; 15: } 16:   17: public void Unlock() 18: { 19: IsLocked = false; 20: } 21: } 22:   23: private FakeLock _lock; 24:   25: public When_using_a_transaction() 26: { 27: _lock = new FakeLock(); 28: } 29:   30: [Fact] 31: void It_should_take_lock_when_created() 32: { 33: Assert.False(_lock.IsLocked); 34: using (Transaction transaction = new Transaction(_lock)) 35: { 36: Assert.True(_lock.IsLocked); 37: } 38: } 39:   40: [Fact] 41: void It_should_release_lock_when_leaving_scope() 42: { 43: using (Transaction transaction = new Transaction(_lock)) 44: { 45: Assert.True(_lock.IsLocked); 46: } 47: Assert.False(_lock.IsLocked); 48: } 49: }

    And the transaction implementation:

    1: public class Transaction : IDisposable 2: { 3: private readonly Lock _lock; 4:   5: public Transaction() 6: : this(new MutexLock()) 7: { 8:   9: } 10:   11: public Transaction(Lock aLock) 12: { 13: _lock = aLock; 14: _lock.Lock(); 15: } 16:   17: public void Dispose() 18: { 19: _lock.Unlock(); 20: } 21: }
Page 1 of 3 (25 items) 123