{"id":211,"date":"2013-12-09T13:00:04","date_gmt":"2013-12-09T13:00:04","guid":{"rendered":"http:\/\/writeasync.net\/?p=211"},"modified":"2014-03-05T03:14:48","modified_gmt":"2014-03-05T03:14:48","slug":"tdd-async-introducing-memorychannel","status":"publish","type":"post","link":"http:\/\/writeasync.net\/?p=211","title":{"rendered":"TDD + async: Introducing MemoryChannel"},"content":{"rendered":"<p>Can you use <a href=\"http:\/\/en.wikipedia.org\/wiki\/Test-driven_development\">test-driven development<\/a> and unit testing with asynchronous code? <strong>Yes<\/strong>, with a few caveats. Above all, unit tests should be <strong>deterministic<\/strong> and <strong>fast<\/strong>. This means you should stick to single-threaded workflows as much as possible and <em>never<\/em> sleep.<\/p>\n<p>To demonstrate these principles along with typical .NET 4.5 asynchronous patterns, I came up with a useful and complete example &#8212; <code>MemoryChannel<\/code>. <code>MemoryChannel<\/code> is a simple one-way communication channel which allows a sender to pass raw byte buffers to an asynchronous receiver. With some appropriate adapters, it could replace a named pipe or TCP socket (thus helping to eliminating external dependencies, for example, in a set of unit tests).<\/p>\n<p>Before writing the code, I sketched a crude <a title=\"Finite-state machine\" href=\"http:\/\/en.wikipedia.org\/wiki\/Finite-state_machine\">FSM diagram<\/a> on a piece of paper. Here is a much more refined version of that diagram (courtesy of <a title=\"Microsoft PowerPoint\" href=\"http:\/\/office.microsoft.com\/en-us\/powerpoint\/\">PowerPoint<\/a>, my diagramming tool of choice):<\/p>\n<p><a href=\"http:\/\/writeasync.net\/wp-content\/uploads\/2013\/12\/MemoryChannel-fsm.png\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-medium wp-image-251\" alt=\"MemoryChannel-fsm\" src=\"http:\/\/writeasync.net\/wp-content\/uploads\/2013\/12\/MemoryChannel-fsm-300x219.png\" width=\"300\" height=\"219\" srcset=\"http:\/\/writeasync.net\/wp-content\/uploads\/2013\/12\/MemoryChannel-fsm-300x219.png 300w, http:\/\/writeasync.net\/wp-content\/uploads\/2013\/12\/MemoryChannel-fsm.png 538w\" sizes=\"auto, (max-width: 300px) 100vw, 300px\" \/><\/a><\/p>\n<p>There are only four states (no data, data available, receive pending, and disposed) and three operations (send, receive, dispose). The only real complications here are the conditions relating to the sent and received data sizes. For example, if there is some data in the channel and a receiver requests more data than is available, the request should still complete but notify the receiver that only <code>S<\/code> bytes were transferred. However, if less data is requested (<code>R<\/code>), the excess (<code>S - R<\/code>) should remain available for later receive attempts.<\/p>\n<p>In true TDD style, I started with the minimum possible interface and decided to focus on the receive side of the state machine.<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\npublic class MemoryChannel\r\n{\r\n    public MemoryChannel()\r\n    {\r\n    }\r\n\r\n    public Task ReceiveAsync(byte&#x5B;] buffer)\r\n    {\r\n        throw new NotImplementedException();\r\n    }\r\n\r\n    public void Send(byte&#x5B;] buffer)\r\n    {\r\n        throw new NotImplementedException();\r\n    }\r\n}\r\n<\/pre>\n<p>Here is the first unit test, covering just the highlighted part of the state machine:<br \/>\n<a href=\"http:\/\/writeasync.net\/wp-content\/uploads\/2013\/12\/MemoryChannel-fsm-recv.png\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-medium wp-image-271\" alt=\"MemoryChannel-fsm-recv\" src=\"http:\/\/writeasync.net\/wp-content\/uploads\/2013\/12\/MemoryChannel-fsm-recv-300x131.png\" width=\"300\" height=\"131\" srcset=\"http:\/\/writeasync.net\/wp-content\/uploads\/2013\/12\/MemoryChannel-fsm-recv-300x131.png 300w, http:\/\/writeasync.net\/wp-content\/uploads\/2013\/12\/MemoryChannel-fsm-recv.png 544w\" sizes=\"auto, (max-width: 300px) 100vw, 300px\" \/><\/a><\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\npublic void Pending_receive_completes_after_send_with_same_data_size()\r\n{\r\n    MemoryChannel channel = new MemoryChannel();\r\n\r\n    byte&#x5B;] receiveBuffer = new byte&#x5B;3];\r\n    Task&lt;int&gt; receiveTask = channel.ReceiveAsync(receiveBuffer);\r\n\r\n    Assert.False(receiveTask.IsCompleted);\r\n    Assert.False(receiveTask.IsFaulted);\r\n\r\n    byte&#x5B;] sendBuffer = new byte&#x5B;] { 1, 2, 3 };\r\n    channel.Send(sendBuffer);\r\n\r\n    Assert.Equal(TaskStatus.RanToCompletion, receiveTask.Status);\r\n    Assert.Equal(3, receiveTask.Result);\r\n    Assert.Equal(new byte&#x5B;] { 1, 2, 3 }, receiveBuffer);\r\n}\r\n<\/pre>\n<p>To fulfill the conditions of this test, we need to return a <code>Task&lt;int&gt;<\/code> from <code>ReceiveAsync<\/code> which <em>has not yet completed<\/em> and only does so when a matching <code>Send<\/code> call is made. Additionally, to satisfy the unit testing principles above we need to do this without external threads. How can we do this?<\/p>\n<p>Enter <a href=\"http:\/\/blogs.msdn.com\/b\/pfxteam\/archive\/2009\/06\/02\/9685804.aspx\" title=\"The Nature of TaskCompletionSource&lt;TResult&gt;\">TaskCompletionSource<\/a> &#8212; one of the most useful library classes in the async .NET toolbox. Essentially, TCS lets us hand out a <code>Task<\/code> representing a custom asynchronous operation while giving us the ability to explicitly control the lifetime of this operation.<\/p>\n<p>To make the test above pass, we can use TCS to represent the pending receive operation like so, initializing it on start of receive and completing it (via <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/dd449202(v=vs.110).aspx\" title=\"TaskCompletionSource&lt;TResult&gt;.SetResult Method\">SetResult<\/a>) when <code>Send<\/code> is invoked:<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\npublic class MemoryChannel\r\n{\r\n    private TaskCompletionSource&lt;int&gt; pendingReceive;\r\n    private byte&#x5B;] pendingReceiveBuffer;\r\n\r\n    public MemoryChannel()\r\n    { \r\n    }\r\n\r\n    public Task&lt;int&gt; ReceiveAsync(byte&#x5B;] buffer)\r\n    {\r\n        this.pendingReceive = new TaskCompletionSource&lt;int&gt;();\r\n        this.pendingReceiveBuffer = buffer;\r\n        return this.pendingReceive.Task;\r\n    }\r\n \r\n    public void Send(byte&#x5B;] buffer)\r\n    {\r\n        buffer.CopyTo(this.pendingReceiveBuffer, 0);\r\n        this.pendingReceive.SetResult(buffer.Length);\r\n    }\r\n}\r\n<\/pre>\n<p>Note that <code>SetResult<\/code> will transition the task to a completed state as well <strong>run any synchronous continuations<\/strong>. This can be undesirable in some situations which I will get into in a later post.<\/p>\n<p>You can track the evolution of <code>MemoryChannel<\/code> into its full implementation in my <a href=\"https:\/\/github.com\/brian-dot-net\/writeasync\/tree\/master\/projects\/CommSample\" title=\"CommSample project\">CommSample project<\/a>. The <a href=\"https:\/\/github.com\/brian-dot-net\/writeasync\/commits\/master\/projects\/CommSample\" title=\"History for writeasync\/projects\/CommSample\">commit history<\/a> shows the changes following every new unit test or refactoring.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Can you use test-driven development and unit testing with asynchronous code? Yes, with a few caveats. Above all, unit tests should be deterministic and fast. This means you should stick to single-threaded workflows as much as possible and never sleep.&hellip; <\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[21,41],"tags":[],"class_list":["post-211","post","type-post","status-publish","format-standard","hentry","category-async","category-tdd"],"_links":{"self":[{"href":"http:\/\/writeasync.net\/index.php?rest_route=\/wp\/v2\/posts\/211","targetHints":{"allow":["GET"]}}],"collection":[{"href":"http:\/\/writeasync.net\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/writeasync.net\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/writeasync.net\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/writeasync.net\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=211"}],"version-history":[{"count":0,"href":"http:\/\/writeasync.net\/index.php?rest_route=\/wp\/v2\/posts\/211\/revisions"}],"wp:attachment":[{"href":"http:\/\/writeasync.net\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=211"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/writeasync.net\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=211"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/writeasync.net\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=211"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}