<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Talk Nerdy To Me - Java, C#, .Net</title>
	<atom:link href="http://www.gavaghan.org/blog/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.gavaghan.org/blog</link>
	<description>Mike Gavaghan blogs on Java, C#, .Net, and the software industry</description>
	<lastBuildDate>Mon, 22 Feb 2010 22:09:03 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>TCP/IP Parameter Tuning for Rapid Client Connections</title>
		<link>http://www.gavaghan.org/blog/2010/02/17/tcpip-parameter-tuning-for-rapid-client-connections/</link>
		<comments>http://www.gavaghan.org/blog/2010/02/17/tcpip-parameter-tuning-for-rapid-client-connections/#comments</comments>
		<pubDate>Wed, 17 Feb 2010 19:37:36 +0000</pubDate>
		<dc:creator>Mike Gavaghan</dc:creator>
				<category><![CDATA[CodeProject]]></category>
		<category><![CDATA[Software]]></category>

		<guid isPermaLink="false">http://www.gavaghan.org/blog/2010/02/17/tcpip-parameter-tuning-for-rapid-client-connections/</guid>
		<description><![CDATA[Applications that open and close a large number of client TCP/IP sockets run the risk of running out of available socket ports.  This can happen in a load and performance testing scenario using a tool like LISA Test from iTKO, or it could happen in a production environment if an active application simply needs to rapidly open and close a large number of outbound connections.

On the .NET platform, the exception raised reads "System.Net.Sockets.SocketException: Only one usage of each socket address (protocol/network address/port) is normally permitted <host>:<port>".

In Java, the exception is "java.net.BindException: Address already in use: connect".  

Both exceptions are misleading because they are generally associated with server socket conflicts – not outbound client socket connections.  However, a better understanding of the TCP state machine sheds some light on this behavior - and a solution.]]></description>
			<content:encoded><![CDATA[<p>Applications that open and close a large number of client TCP/IP sockets run the risk of running out of available socket ports.  This can happen in a load and performance testing scenario using a tool like <a target="_blank" href="http://www.itko.com/products/lisatest.jsp" title="LISA Test - QA Software for Composite Enterprise Applications and SOA">LISA Test</a> from <a target="_blank" href="http://www.itko.com/" title="LISA Virtualization and Validation Software for Modern Applications: SOA, Cloud, and BPM">iTKO</a>, or it could happen in a production environment if an active application simply needs to rapidly open and close a large number of outbound connections.</p>
<p>On the <strong>.NET</strong> platform, the exception raised reads &#8220;<code><a target="_blank" href="http://msdn.microsoft.com/en-us/library/system.net.sockets.socketexception.aspx" title="SocketException">System.Net.Sockets.SocketException</a>: Only one usage of each socket address (protocol/network address/port) is normally permitted &lt;host&gt;:&lt;port&gt;</code>&#8220;. </p>
<p><strong>In Java</strong>, the exception is &#8220;<code><a target="_blank" href="http://java.sun.com/javase/6/docs/api/java/net/BindException.html" title="Java BindException">java.net.BindException</a>: Address already in use: connect</code>&#8220;. </p>
<p>Both exceptions are misleading because they are generally associated with server socket conflicts – not outbound client socket connections.  However, a better understanding of the <a target="_blank" href="http://www.night-ray.com/TCPIP_State_Transition_Diagram.pdf" title="TCP Finite State Machine">TCP state machine</a> sheds some light on this behavior &#8211; and a solution.</p>
<p><span id="more-69"></span><strong>Common Port Conflict Exceptions</strong></p>
<p>Whenever TCP/IP encounters a port conflict, you can expect one of the two following exceptions to be thrown depending upon your environment:</p>
<p>In a C# environment, you&#8217;ll see this exception:</p>
<blockquote class="codeblock">
<blockquote class="codeline0"><p>System.Net.Sockets.SocketException: Only one usage of each socket address (protocol/network address/port) is normally permitted &lt;host&gt;:&lt;port&gt;</p></blockquote>
</blockquote>
<p>In Java, you&#8217;ll see this:</p>
<blockquote class="codeblock">
<blockquote class="codeline0"><p>java.net.BindException: Address already in use: connect</p></blockquote>
<blockquote class="codeline1"><p>at java.net.PlainSocketImpl.socketConnect(Native Method)</p></blockquote>
<blockquote class="codeline1"><p>at java.net.PlainSocketImpl.doConnect(PlainSocketImpl.java:333)</p></blockquote>
<blockquote class="codeline1"><p>at java.net.PlainSocketImpl.connectToAddress(PlainSocketImpl.java:195)</p></blockquote>
<blockquote class="codeline1"><p>at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:182)</p></blockquote>
<blockquote class="codeline1"><p>at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:366)</p></blockquote>
<blockquote class="codeline1"><p>at java.net.Socket.connect(Socket.java:519)</p></blockquote>
<blockquote class="codeline1"><p>at java.net.Socket.connect(Socket.java:469)</p></blockquote>
</blockquote>
<p>If you see these exceptions thrown when a <u>server</u> socket attempts to listen for incoming connections, the cause is obvious: the port you&#8217;re attempting to listen on is already in use.  For example, if you bring up a Web server, but another Web server is already running, an exception will be thrown because port 80 (or 8080) is already listening on behalf of another thread or application.</p>
<p>These exceptions are often confusing, however, when thrown setting up a <u>client</u> connection.  Client TCP connections are always assigned an OS-selected port on the local side, so why is the operating system selecting an active port?  The truth is the exception indicates <u><strong>no</strong></u> local port numbers are available to the client.  This misreporting of the error by the OS is half the confusion.</p>
<p><strong>Tuning Local Client Port Range</strong></p>
<p>The problem is two-fold.  First, Linux and Windows make only a certain number of ports available to client sockets – the default is in the range of 1024 to 5000.  Hence, you may have only 3,976 active client connections at a time.  For most systems, this is plenty.  However, in specific circumstances on systems requiring a large number of outbound connections, this limit can be exhausted.</p>
<p>This range, however, can be tuned.  On Windows,  the upper bound for client port assignments can be adjusted using the <a target="_blank" href="http://technet.microsoft.com/en-us/library/cc758002%28WS.10%29.aspx" title="MaxUserPort"><code>MaxUserPort</code></a> <code>DWORD</code> value on this registry key:</p>
<blockquote class="codeblock">
<blockquote class="codeline0"><p>HKLM\System\CurrentControlSet\Services\Tcpip\Parameters</p></blockquote>
</blockquote>
<p>Of course, rather than using the cumbersome <code>regedit</code>, you can <a target="_blank" href="http://www.gavaghan.org/blog/free-source-code/ip-tuner/" onclick="javascript:urchinTracker('/outgoing/free_source_code_iptuner');" title="Gavaghan TCP/IP Parameter Tuning for Windows">download IPTuner for free</a> to quickly optimize your Windows IP stack</p>
<p>On Linux, both the lower and upper bounds can be set using the following parameter:</p>
<blockquote class="codeblock">
<blockquote class="codeline0"><p>net.ipv4.ip_local_port_range = 32768 65536</p></blockquote>
</blockquote>
<p>How this parameter is set in Linux varies depending upon the flavor and version of Linux you&#8217;re using – and you&#8217;ll need to restart networking after you change it.</p>
<p><strong>Tuning TCP TIME_WAIT Timeout Value</strong></p>
<p>The second cause of these exceptions has to do with the <a target="_blank" href="http://www.night-ray.com/TCPIP_State_Transition_Diagram.pdf" title="TCP State Model">TCP state model</a> and the way sockets are closed.  Even after a socket has officially been &#8220;closed&#8221;, it hangs around in a <code>TIME_WAIT</code> state as a safety mechanism to deal with stray packets.  The default wait time on all operating systems, generally, is ridiculously long (240 seconds on Windows).  So, even if an application doesn’t require a lot of concurrent connections, it can still run out of available ports in a high load situation.  If even one connection is repeatedly opened and closed fast enough, you&#8217;ll soon have all available local sockets hanging around in a <code>TIME_WAIT</code> state and none available for new clients.</p>
<p>The <code>TIME_WAIT</code> state duration, however, is also tunable.</p>
<p>On Windows, using the same registry key, the <code><a target="_blank" href="http://technet.microsoft.com/en-us/library/cc938217.aspx" title="TcpTimedWaitDelay">TCPTimedWaitDelay</a></code> value can be used to adjust the <code>TIME_WAIT</code> duration from 30 to 300 seconds.  Of course, rather than using the cumbersome <code>regedit</code>, you can <a target="_blank" href="http://www.gavaghan.org/blog/free-source-code/ip-tuner/" onclick="javascript:urchinTracker('/outgoing/free_source_code_iptuner');" title="Gavaghan TCP/IP Parameter Tuning for Windows">download IPTuner for free</a> to quickly optimize your Windows IP stack.</p>
<p>On Linux, the wait delay is configured using the following parameter:</p>
<blockquote class="codeblock">
<blockquote class="codeline0"><p>net.ipv4.tcp_fin_timeout = 30</p></blockquote>
</blockquote>
<p>By decreasing the TCP wait delay, closed sockets spend less time in the <code>TIME_WAIT</code> state and get returned to the pool of available client ports faster. However, to avoid communication problems, do not lower this value below 30 seconds.</p>
<p><strong>Administrator Privileges Required</strong></p>
<p>On both Linux and Windows (even if using <strong>IP tuner</strong> or <code>regedit</code>), you&#8217;ll require administrator privileges to change these parameters.  However, anyone can view these settings to at least verify if they make sense.</p>
<ul class="download">
<li><strong><a href="http://www.gavaghan.org/blog/free-source-code/ip-tuner/" onclick="javascript:urchinTracker('/outgoing/free_source_code_iptuner');" title="Gavaghan TCP/IP Parameter Tuner for Windows">Download <strong>IPTuner</strong> for Windows here.</a></strong></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://www.gavaghan.org/blog/2010/02/17/tcpip-parameter-tuning-for-rapid-client-connections/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>The .NET Asynchronous I/O Design Pattern</title>
		<link>http://www.gavaghan.org/blog/2010/02/11/the-net-asynchronous-io-design-pattern/</link>
		<comments>http://www.gavaghan.org/blog/2010/02/11/the-net-asynchronous-io-design-pattern/#comments</comments>
		<pubDate>Thu, 11 Feb 2010 19:08:49 +0000</pubDate>
		<dc:creator>Mike Gavaghan</dc:creator>
				<category><![CDATA[CodeProject]]></category>
		<category><![CDATA[Software]]></category>

		<guid isPermaLink="false">http://www.gavaghan.org/blog/2010/02/11/the-net-asynchronous-io-design-pattern/</guid>
		<description><![CDATA[Asynchronous operations allow a program to perform time consuming tasks on a background thread while the main application continues to execute.  For example, consider when a program makes a request to a remote system.  In a single-threaded scenario, the call is made and the CPU goes idle as the caller waits on the server's processing time and the network latency.  If this waiting time can be delegated to a separate thread of execution, the program can complete other tasks until it receives notification the background work is complete.

However, managing multiple threads and cross-thread communication adds complexity to your code.  Fortunately, the .NET Framework has a useful design pattern applied to its I/O classes which easily enables asynchronous calls.  Let's take a look at an example.]]></description>
			<content:encoded><![CDATA[<p><a target="_blank" href="http://en.wikipedia.org/wiki/Asynchronous_I/O" title="Asynchronous I/O">Asynchronous operations</a> allow a program to perform time consuming tasks on a background thread while the main application continues to execute.  For example, consider when a program makes a request to a remote system.  In a single-threaded scenario, the call is made and the CPU goes idle as the caller waits on the server&#8217;s processing time and the network latency.  If this waiting time can be delegated to a separate thread of execution, the program can complete other tasks until it receives notification the background work is complete.</p>
<p>However, managing multiple threads and cross-thread communication adds complexity to your code.  Fortunately, the .NET Framework has a useful design pattern applied to its I/O classes which easily enables asynchronous calls.  Let&#8217;s take a look at an example.</p>
<p><span id="more-68"></span><strong>Async I/O for a DNS lookup</strong> </p>
<p>Suppose you need to lookup the IP address of a host.  The simplest way to do this is to use the <code><a target="_blank" href="http://msdn.microsoft.com/en-us/library/system.net.dns.aspx" title="System.Net.Dns">System.Net.Dns</a></code> class:</p>
<blockquote class="codeblock">
<blockquote class="codeline0"><p>IPAddress[] hostAddresses = Dns.GetHostAddresses(&#8220;www.gavaghan.org&#8221;);</p></blockquote>
</blockquote>
<p>A DNS lookup doesn&#8217;t take terribly long and, in most cases, the synchronous example above is fine.  DNS servers are highly efficient, and local DNS servers will cache authoritative data to optimize response times.</p>
<p>However, suppose you&#8217;re implementing a high performance mail server that detects spam by querying multiple <a target="_blank" href="http://www.gavaghan.org/blog/2008/06/11/kill-spam-with-real-time-dns-blacklists/" title="DNS Blacklist - DNSBL">real time DNS blacklists</a>.  For every incoming message, you must execute a dozen DNS operations:</p>
<blockquote class="codeblock">
<blockquote class="codeline0"><p>IPAddress[] spamcop = Dns.GetHostAddresses(&#8220;22.154.199.213.bl.spamcop.net&#8221;);</p></blockquote>
<blockquote class="codeline0"><p>IPAddress[] spamhaus = Dns.GetHostAddresses(&#8220;22.154.199.213.pbl.spamhaus.org&#8221;);</p></blockquote>
<blockquote class="codeline0"><p>IPAddress[] fiveten =</p></blockquote>
<blockquote class="codeline5"><p>Dns.GetHostAddresses(&#8220;22.154.199.213.blackholes.five-ten-sg.com&#8221;);</p></blockquote>
<blockquote class="codeline0"><p>//</p></blockquote>
<blockquote class="codeline0"><p>// . . . and a dozen others</p></blockquote>
<blockquote class="codeline0"><p>//</p></blockquote>
</blockquote>
<p>Each synchronous lookup blocks waiting for a response before moving on to the next lookup.  The cumulative effect of these delays will get costly.  Ideally, you&#8217;d want to perform each lookup on its own thread and let the requests run concurrently.</p>
<p>So, let&#8217;s implement a method that looks like this:</p>
<blockquote class="codeblock">
<blockquote class="codeline0"><p>public class AsyncDNSExample</p></blockquote>
<blockquote class="codeline0"><p>{</p></blockquote>
<blockquote class="codeline2"><p>public List&lt;IPAddress&gt; MultiHostLookup(List&lt;string&gt; hosts)</p></blockquote>
<blockquote class="codeline2"><p>{</p></blockquote>
</blockquote>
<p>This method will accept a list of host names, execute concurrent DNS lookups for all of them, and return with a list of resolved addresses.  Here&#8217;s how we might use this method:</p>
<blockquote class="codeblock">
<blockquote class="codeline0"><p>class Program</p></blockquote>
<blockquote class="codeline0"><p>{</p></blockquote>
<blockquote class="codeline2"><p>static void Main()</p></blockquote>
<blockquote class="codeline2"><p>{</p></blockquote>
<blockquote class="codeline4"><p>// build list of hosts to lookup</p></blockquote>
<blockquote class="codeline4"><p>List&lt;string&gt; hosts = new List&lt;string&gt;();</p></blockquote>
<blockquote class="codeline4"><p>hosts.Add(&#8220;www.gavaghan.org&#8221;);</p></blockquote>
<blockquote class="codeline4"><p>hosts.Add(&#8220;www.itko.com&#8221;);</p></blockquote>
<blockquote class="codeline4"><p>hosts.Add(&#8220;sombrita.com&#8221;);</p></blockquote>
<blockquote class="blankcodeline"></blockquote>
<blockquote class="codeline4"><p>// perform the concurrent lookup</p></blockquote>
<blockquote class="codeline4"><p>AsyncDNSExample lookup = new AsyncDNSExample();</p></blockquote>
<blockquote class="codeline4"><p>List&lt;IPAddress&gt; addressList = lookup.MultiHostLookup(hosts);</p></blockquote>
<blockquote class="blankcodeline"></blockquote>
<blockquote class="codeline4"><p>// write out the results</p></blockquote>
<blockquote class="codeline4"><p>foreach (IPAddress address in addressList)</p></blockquote>
<blockquote class="codeline4"><p>{</p></blockquote>
<blockquote class="codeline6"><p>Console.WriteLine(address);</p></blockquote>
<blockquote class="codeline4"><p>}</p></blockquote>
<blockquote class="codeline2"><p>}</p></blockquote>
<blockquote class="codeline0"><p>}</p></blockquote>
</blockquote>
<p><strong>Begin and End methods</strong></p>
<p>Many of .NET&#8217;s I/O classes have asynchronous versions of their synchronous methods.  For example, the <code>Read()</code> and <code>Write()</code> methods on <code><a target="_blank" href="http://msdn.microsoft.com/en-us/library/system.io.stream.aspx" title="System.IO.Strean">System.IO.Stream</a></code> have respective <code>BeginRead()</code> and <code>BeginWrite()</code> counterparts.  <code><a target="_blank" href="http://msdn.microsoft.com/en-us/library/system.net.sockets.socket.aspx" title="System.Net.Sockets.Socket">System.Net.Sockets.Socket</a></code> has <code>BeginAccept()</code> and <code>BeginConnect()</code>.  And, in benefit of this example, <code>Dns</code> has <code>BeginGetHostAddresses()</code>.</p>
<p>All of the <code>Begin*</code> methods cause the object&#8217;s work to execute on a worker thread in the .NET thread pool.  These methods take the same parameters as their synchronous counterparts plus two additional parameters supporting the async framework.</p>
<p>For example, here&#8217;s the signature for <code>BeginGetHostAddresses()</code>:</p>
<blockquote class="codeblock">
<blockquote class="codeline0"><p>public static IAsyncResult BeginGetHostAddresses(</p></blockquote>
<blockquote class="codeline5"><p>string hostNameOrAddress,</p></blockquote>
<blockquote class="codeline5"><p>AsyncCallback requestCallback,</p></blockquote>
<blockquote class="codeline5"><p>Object state</p></blockquote>
<blockquote class="codeline0"><p>)</p></blockquote>
</blockquote>
<p>One added parameter is an <code><a target="_blank" href="http://msdn.microsoft.com/en-us/library/system.asynccallback.aspx" title="AsyncCallback">AsyncCallback</a></code> delegate.  The delegate identifies the callback method .NET will invoke once asynchronous processing has completed.  The callback method takes a single parameter of type <code><a target="_blank" href="http://msdn.microsoft.com/en-us/library/system.iasyncresult.aspx" title="IAsyncResult">IAsyncResult</a></code>.  The <code>IAsyncResult</code> object must be used to access the result of the asynchronous call.</p>
<p>The second added parameter is an arbitrary state object (possibly null) that may be used to coordinate between the caller and the callback.  The state object is made available to the callback method through the <code>IAsyncResult</code> parameter.  An example is included a little later.</p>
<p>For each <code>Begin*</code> call, a corresponding <code>End*</code> call must be invoked to get the results of the method.  <code>End*</code> methods block synchronously until processing has been completed.  However, when called from within the callback method, <code>End*</code> methods return immediately because, at that point, the work is known to be done.</p>
<p>Let&#8217;s take a look at how our <code>MultiHostLookup()</code> method can be implemented using the asynchronous version of <code>GetHostAddresses()</code>:</p>
<blockquote class="codeblock">
<blockquote class="codeline0"><p>public class AsyncDNSExample</p></blockquote>
<blockquote class="codeline0"><p>{</p></blockquote>
<blockquote class="codeline2"><p>public List&lt;IPAddress&gt; MultiHostLookup(List&lt;string&gt; hosts)</p></blockquote>
<blockquote class="codeline2"><p>{</p></blockquote>
<blockquote class="codeline4"><p>// we&#8217;ll fill this list with the result of the DNS lookups</p></blockquote>
<blockquote class="codeline4"><p>List&lt;IPAddress&gt; addressList = new List&lt;IPAddress&gt;();</p></blockquote>
<blockquote class="blankcodeline"></blockquote>
<blockquote class="codeline4"><p>foreach (string host in hosts)</p></blockquote>
<blockquote class="codeline4"><p>{</p></blockquote>
<blockquote class="codeline6"><p>// begin an asynchronous lookup for each host</p></blockquote>
<blockquote class="codeline6"><p>Dns.BeginGetHostAddresses(</p></blockquote>
<blockquote class="codeline8"><p>host,</p></blockquote>
<blockquote class="codeline8"><p>GetHostAddressesCallback,</p></blockquote>
<blockquote class="codeline8"><p>addressList</p></blockquote>
<blockquote class="codeline6"><p>);</p></blockquote>
<blockquote class="codeline4"><p>}</p></blockquote>
<blockquote class="blankcodeline"></blockquote>
<blockquote class="codeline4"><p>//</p></blockquote>
<blockquote class="codeline4"><p>// we can do additional work here while the</p></blockquote>
<blockquote class="codeline4"><p>// DNS lookups continue in parallel</p></blockquote>
<blockquote class="codeline4"><p>//</p></blockquote>
<blockquote class="blankcodeline"></blockquote>
<blockquote class="codeline4"><p>lock (addressList)</p></blockquote>
<blockquote class="codeline4"><p>{</p></blockquote>
<blockquote class="codeline6"><p>// ensure all lookups have returned, otherwise wait</p></blockquote>
<blockquote class="codeline6"><p>while (addressList.Count != hosts.Count)</p></blockquote>
<blockquote class="codeline6"><p>{</p></blockquote>
<blockquote class="codeline8"><p>Monitor.Wait(addressList);</p></blockquote>
<blockquote class="codeline6"><p>}</p></blockquote>
<blockquote class="codeline4"><p>}</p></blockquote>
<blockquote class="blankcodeline"></blockquote>
<blockquote class="codeline4"><p>return addressList;</p></blockquote>
<blockquote class="codeline2"><p>}</p></blockquote>
<blockquote class="codeline0"><p>}</p></blockquote>
</blockquote>
<p>This method begins by allocating the <code>List&lt;IPAddress&gt;</code> object we&#8217;ll use to return our resolved addresses.  Then, we loop over each of the host names in the hosts <code>List&lt;string&gt;</code> and call <code>BeginGetHostAddresses()</code>.  Once this loop completes, all of the DNS queries are executing in parallel.</p>
<p>Notice the first parameter to <code>BeginGetHostAddresses()</code> is a host name &#8211; just like its synchronous counterpart.  For the second parameter, we pass a reference to our callback method, <code>GetHostAddressesCallback()</code>, which is defined below.  The third parameter is our result <code>List&lt;IPAddress&gt;</code>.  This will make the <code>List</code> available to the callback method.  When each DNS query completes, the callback method can update the list with each resolved address.</p>
<p>At this point, if we wanted to, we could code other logic to execute as we wait for the queries to complete.</p>
<p>Finally, we check the length of the list of resolved IP addresses to see if it&#8217;s the same length as the list of host names.  To do this, we must first lock the address list object (after all, we don&#8217;t want our address list modified on a callback thread at the same time we&#8217;re trying to inspect it).  If the list sizes are equal, we know all lookups have completed and we can return from the method.  Otherwise, we release the lock on the address list and block until receiving notification from the callback thread.</p>
<p>It&#8217;s all pretty simple.  Now, let&#8217;s see how to implement the callback method:</p>
<blockquote class="codeblock">
<blockquote class="codeline0"><p>public class AsyncDNSExample</p></blockquote>
<blockquote class="codeline0"><p>{</p></blockquote>
<blockquote class="codeline2"><p>private void GetHostAddressesCallback(IAsyncResult result)</p></blockquote>
<blockquote class="codeline2"><p>{</p></blockquote>
<blockquote class="codeline4"><p>// This method may fail with a SocketException, particularly</p></blockquote>
<blockquote class="codeline4"><p>// if the host is not found. A more robust solution would</p></blockquote>
<blockquote class="codeline4"><p>// handle such cases.</p></blockquote>
<blockquote class="codeline4"><p>IPAddress[] addresses = Dns.EndGetHostAddresses(result);</p></blockquote>
<blockquote class="blankcodeline"></blockquote>
<blockquote class="codeline4"><p>// for simplicity, we&#8217;ll take the first address</p></blockquote>
<blockquote class="codeline4"><p>IPAddress address = addresses[0];</p></blockquote>
<blockquote class="blankcodeline"></blockquote>
<blockquote class="codeline4"><p>// the address list we passed in is accessbile from AsyncState</p></blockquote>
<blockquote class="codeline4"><p>List&lt;IPAddress&gt; addressList = (List&lt;IPAddress&gt;)result.AsyncState;</p></blockquote>
<blockquote class="blankcodeline"></blockquote>
<blockquote class="codeline4"><p>// we need to ensure updates to the address list are threadsafe</p></blockquote>
<blockquote class="codeline4"><p>lock (addressList)</p></blockquote>
<blockquote class="codeline4"><p>{</p></blockquote>
<blockquote class="codeline6"><p>addressList.Add(address);</p></blockquote>
<blockquote class="blankcodeline"></blockquote>
<blockquote class="codeline6"><p>// notify listeners that another address has been added</p></blockquote>
<blockquote class="codeline6"><p>Monitor.PulseAll(addressList);</p></blockquote>
<blockquote class="codeline4"><p>}</p></blockquote>
<blockquote class="codeline2"><p>}</p></blockquote>
<blockquote class="blankcodeline"></blockquote>
<blockquote class="codeline2"><p>// this is our public method for performing multiple, concurrent</p></blockquote>
<blockquote class="codeline2"><p>// DNS requests</p></blockquote>
<blockquote class="codeline2"><p>public List&lt;IPAddress&gt; MultiHostLookup(List&lt;string&gt; hosts)</p></blockquote>
<blockquote class="codeline2"><p>{</p></blockquote>
<blockquote class="codeline4"><p>. . . .</p></blockquote>
<blockquote class="codeline2"><p>}</p></blockquote>
<blockquote class="codeline0"><p>}</p></blockquote>
</blockquote>
<p>The first thing that happens is the call to <code>EndGetHostAddresses()</code> with the <code>IAsyncResult</code> object passed in.  This call returns immediately with the result of the DNS query (it returns an array of IP addresses but, for simplicity, we&#8217;ll assume the first one is all we need).</p>
<p>Next, we get a reference to the <code>List&lt;IPAddress&gt;</code> object passed in by the <code>Begin*</code> call. This is where we&#8217;re going to save our resolved IP addresses.  However, for thread safety, we can only add our result from within a lock block.  We don&#8217;t want to be manipulating the list at the same time as another callback!</p>
<p>Finally, we pulse all threads listening on the result object.  This schedules the thread executing <code>MultiHostLookup()</code> to check if all of the results have been received.</p>
<p><strong>Conclusion</strong></p>
<p>Using asynchronous I/O can make your applications faster and your user interfaces more responsive &#8211; particularly when executing long running tasks and tasks that would otherwise leave the CPU idle. However, even with the .NET design pattern, multithreaded programming always adds to code complexity. So, only leverage this framework where performance optimization is required.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.gavaghan.org/blog/2010/02/11/the-net-asynchronous-io-design-pattern/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Understanding SSL – Part 1: Certificates and Keys</title>
		<link>http://www.gavaghan.org/blog/2009/10/14/understanding-ssl-%e2%80%93-part-1-certificates-and-keys/</link>
		<comments>http://www.gavaghan.org/blog/2009/10/14/understanding-ssl-%e2%80%93-part-1-certificates-and-keys/#comments</comments>
		<pubDate>Thu, 15 Oct 2009 01:35:00 +0000</pubDate>
		<dc:creator>Mike Gavaghan</dc:creator>
				<category><![CDATA[CodeProject]]></category>
		<category><![CDATA[Software]]></category>

		<guid isPermaLink="false">http://www.gavaghan.org/blog/2009/10/14/understanding-ssl-%e2%80%93-part-1-certificates-and-keys/</guid>
		<description><![CDATA[The technology behind Secure Sockets Layer (SSL) network connections is often perceived as a bit of &#8220;black magic&#8221; – smoke and mirrors securing our Internet connections from snooping.  When banking and shopping online, even a novice user understands their browser sets up an HTTPS connection (which is simply HTTP over SSL) to protect the transaction.  [...]]]></description>
			<content:encoded><![CDATA[<p>The technology behind <a target="_blank" href="http://en.wikipedia.org/wiki/Transport_Layer_Security" title="Transport Layer Security">Secure Sockets Layer (SSL)</a> network connections is often perceived as a bit of &#8220;black magic&#8221; – smoke and mirrors securing our Internet connections from snooping.  When banking and shopping online, even a novice user understands their browser sets up an <a target="_blank" href="http://en.wikipedia.org/wiki/Https" title="HTTP Secure">HTTPS</a> connection (which is simply HTTP over SSL) to protect the transaction.  It’s easy to simply surf to a secure URL and know that, somehow, SSL is magically keeping you safe.</p>
<p>Developing software that <em>uses </em>SSL is an entirely different matter.  The simplicity quickly fades, and the developer must confront the complexities of certificate management, trust stores, handshaking, and a host of other details that must be perfectly aligned to make the secure communication work.  In Part 1, we’ll cover a very high level of SSL concepts.  In subsequent posts, we’ll take a deeper dive into making these connections happen in both Java and C#.</p>
<p><span id="more-59"></span><strong>Understanding SSL</strong></p>
<p>SSL uses <a target="_blank" href="http://en.wikipedia.org/wiki/Public_key" title="Public-key cryptography">public key/private key cryptography</a> for three purposes. The most fundamental use is to encrypt data communication between the server and client.  However, it is also used to allow the server to prove its identity to the client and prevent <a target="_blank" href="http://en.wikipedia.org/wiki/Man-in-the-middle_attack" title="Man-in-the-middle attack">man-in-the-middle attacks</a> (where a malicious intermediary intercepts messages from the client and masquerades as the intended server).</p>
<p>A third use is for allowing the client to prove its identity to the server.  <a target="_blank" href="http://en.wikipedia.org/wiki/Mutual_authentication" title="Mutual Authentication">Mutual authentication</a> is an important and powerful feature of SSL, and it’s probably underused.  For now, we’ll just focus on the semantics of server authentication.  If you understand server authentication, you’ll be well on your way to understanding client authentication on your own.</p>
<p><strong>About Certificates</strong></p>
<p>Three fundamental components are involved in setting up an SSL connection between a server and client: a certificate, a public key, and a private key.</p>
<p><a target="_blank" href="http://en.wikipedia.org/wiki/Digital_certificate" title="Digital Certificate">Digital certificates</a> are used to identify an entity.  The entity could be a person (when used for secure email), or it could be a computer (when used for SSL).  There is quite a bit of information stored in a digital certificate, but the most important part is the name of the entity it is identifying.</p>
<p>The identity, also known as the “subject”, is specified as an <a target="_blank" href="http://en.wikipedia.org/wiki/Distinguished_Name" title="Distinguished Name">X.509 distinguished name</a>.  A distinguished name contains multiple components.  For example, the distinguished name on the certificate used to setup an HTTPS connection for Amazon.com’s shopping cart check-out looks like this:</p>
<blockquote class="codeblock">
<blockquote class="codeline0"><p>CN=www.amazon.com,</p></blockquote>
<blockquote class="codeline0"><p>O=Amazon.com Inc.,</p></blockquote>
<blockquote class="codeline0"><p>L=Seattle,</p></blockquote>
<blockquote class="codeline0"><p>S=Washington,</p></blockquote>
<blockquote class="codeline0"><p>C=US</p></blockquote>
</blockquote>
<p>How do we find this information?  From Internet Explorer, browse to any secure web page (one with an <code>https://</code> protocol in the URL).  Right-click on the page and select &#8220;Properties&#8221;.  From the properties page, click the &#8220;Certificates&#8221; button.  On the &#8220;Details&#8221; tab, we can see all of the information embedded in the certificate.  By selecting the &#8220;Subject&#8221; entry, we can see the entity the certificate identifies:</p>
<p><img src="http://www.gavaghan.org/blog/wp-content/uploads/2009/10/iecertificateview1.gif" alt="Certificate Viewer in Internet Explorer" /></p>
<p>For the purposes of establishing an SSL connection to a server, the only interesting part of the distinguished name is the “Common Name” specified by the “CN” component.  This is the name the server uses to identify the domain name of the host.</p>
<p>To establish a secure connection to Amazon.com, a client first resolves the domain name <code>www.amazon.com</code>.  After the SSL connection has been initiated, one of the first things the server will do is send its digital certificate.  The client will perform a number of validation steps before determining if it will continue with the connection.</p>
<p>Most importantly, the client will compare the domain name of the server it intended to connect to (in this case, <code>www.amazon.com</code>) with the common name (the “CN” field) found in the subject’s identity on the certificate.  If these names do not match, it means the client does not trust the identity of the server (and the client will likely choose to terminate the connection).</p>
<p>Although the server name may be correct, the client must still verify the integrity of the certificate to determine if it has been forged or tampered with.  The client does this by verifying the digital signature on the certificate.  We’ll talk more about digital signatures in a moment.</p>
<p>The client will also ensure the certificate is being used within a valid time frame.  All certificates contain an “issue date” and an “expiration date”.  A certificate is considered invalid outside of that date range.</p>
<p><strong>Public and Private Keys</strong></p>
<p>Public keys and private keys are number pairs with a special relationship.  Any data encrypted with one key can be decrypted with the other.  This is known as <a target="_blank" href="http://en.wikipedia.org/wiki/Asymmetric_encryption" title="Asymmetric encryption">asymmetric encryption</a>.  The security of asymmetric encryption lies in the difficulty of cracking encrypted data even when the key used for encryption is known.</p>
<p>The server’s public key is embedded within its certificate.  The public key is freely distributed so anyone wishing to establish an encrypted channel with the server may encrypt their data using the server’s public key.  The server will decrypt this message using its private key.  For this reason, private keys are closely guarded and kept secure.</p>
<p><strong>Digital Signatures</strong></p>
<p>Just as data may be encrypted with a public key and decrypted with a private key, the reverse is also true.  Data encrypted with a private key may be decrypted with the corresponding public key.</p>
<p>This property of keys is used to ensure the integrity of a digital certificate in a process called <a target="_blank" href="http://en.wikipedia.org/wiki/Digital_signature" title="Digital signature">digital signing</a>.</p>
<p>A <a target="_blank" href="http://en.wikipedia.org/wiki/Hashing_algorithm" title="Hashing algorithm">hashing algorithm</a> (such as <a target="_blank" href="http://en.wikipedia.org/wiki/Sha1" title="SHA1 Hashing">SHA1</a> or <a target="_blank" href="http://en.wikipedia.org/wiki/MD5" title="MD5 hashing">MD5</a>) is a means of processing all of the bytes of a message and producing a numeric “hash value”.  Hash values have long been used to ensure the integrity of messages that may become corrupted during transport.  A sender will transmit a message followed by the hash value it calculated for the message it intends to send.  The receiver calculates the hash value for the message it receives.  If the receiver calculates a different hash value than the one that was sent, the receiver concludes the message was corrupted during transit (and generally asks the sender to resend).</p>
<p>A hashing algorithm may also be used to determine if a message has been forged or tampered with.  Complicating this, however, is that a malicious third party could intercept a message, modify it, and simply recalculate the hash.  Asymmetric encryption technology solves this.</p>
<p>If a message sender wants to convince a recipient that his message is authentic and has not been tampered with, he will do two things.  First, the sender will calculate a hash value for the message.  This hash value will then be encrypted using the sender’s private key (a key which the sender, and only the sender, knows).  When the client receives the message, the client decrypts the hash value using the sender’s public key.  If the message has been tampered with, or if the message has been signed with anything other than the sender’s private key, the hash values will not agree and the client will not consider the message authentic.</p>
<p><strong>Certificate Signing</strong></p>
<p>When a certificate is created, it is digitally signed.  The digital signature is used to verify the authenticity of the certificate.  In an SSL connection, the client will attempt to verify the signature on the certificate presented by the server before deciding to continue establishing the connection.</p>
<p><strong>Self-signed certificates</strong></p>
<p>The simplest certificate is a <a target="_blank" href="http://en.wikipedia.org/wiki/Self-signed_certificate" title="Self-signed Certificates">self-signed certificate</a>.  The signature on a self-signed certificate is calculated using the same private key associated with the public key found on the certificate.  In a software development environment, self-signed certificates are an easy way to build testing environments that establish SSL connections without having to deal with the time and expense of obtaining a certificate through an establish certificate authority.</p>
<p><strong>Certificate Authority signed certificates</strong></p>
<p>Certificates may also be signed by a <a target="_blank" href="http://en.wikipedia.org/wiki/Certificate_authority" title="Certificate authority">certificate authority (CA)</a>.  A CA is a trusted third party that digitally signs certificates for entities that have gone through an established vetting process.  The CA, itself, also has a certificate that can be analyzed for authenticity – and the CA’s certificate might also be signed by yet another trusted third party (in this case, the CA is known as an intermediate CA).  All of these certificates, together, form a certificate chain.  At the top of the chain is a certificate authority called a <a target="_blank" href="http://en.wikipedia.org/wiki/Root_certificate" title="Root Certificate">Root CA</a> that uses a self-signed certificate.</p>
<p>Returning to the Amazon.com example, we can examine the server certificate and see that it is not a self signed certificate – it is signed by a CA with a distinguished named of:</p>
<blockquote class="codeblock">
<blockquote class="codeline0"><p>CN=VeriSign Class 3 Secure Server CA &#8211; G2,</p></blockquote>
<blockquote class="codeline0"><p>OU=Terms of use at https://www.verisign.com/rpa (c)09,</p></blockquote>
<blockquote class="codeline0"><p>OU=VeriSign Trust Network,</p></blockquote>
<blockquote class="codeline0"><p>O=VeriSign, Inc.,</p></blockquote>
<blockquote class="codeline0"><p>C=US</p></blockquote>
</blockquote>
<p>From the certificate details tab we looked at earlier, we can find the name of the certificate issuer by selecting the &#8220;Issuer&#8221; entry:</p>
<p><img src="http://www.gavaghan.org/blog/wp-content/uploads/2009/10/iecertificateview2.gif" alt="Certificate Viewer in Internet Explorer" /></p>
<p>VeriSign is a trusted third party that issues certificates for, among other things, eCommerce applications.</p>
<p>Why is it important to have a certificate signed by a trusted third party?  It’s important because new HTTPS-based Web applications are being deployed all of the time.  In terms of browser-based, retail eCommerce applications, it’s simply impractical for users to manage a list of all of the server certificates they have decided to &#8220;trust&#8221;.  Furthermore, reliably and securely obtaining a web site&#8217;s real server certificate would be too problematic.</p>
<p>Consider a new Amazon.com customer.  When the shopping cart checkout sends Amazon.com’s certificate identifying itself as <code>www.amazon.com</code>, how does the customer know to trust the certificate?  Although the certificate may have a valid name and signature on it, how does the customer decide to trust the certificate?  If it is self-signed, it could have been signed by <em>anyone</em> – including a malicious man-in-the-middle.  What the customer needs is a reliable means of receiving Amazon’s certificate that is protected from forgery.</p>
<p>To do this, Amazon chose not to use a self-signed certificate.  Instead, for a fee, it requested that VeriSign sign its online shopping certificate.  When the customer receives Amazon.com’s certificate, she says “I trust that I have a legitimate copy of VeriSign’s CA certificate, I trust VeriSign to only sign certificates of the real domain name owners, and I can see that Amazon.com’s certificate is signed by VeriSign.  Therefore, I believe the server responding at <code>www.amazon.com</code> is truly owned and managed by the same entity owning the <code>www.amazon.com</code> domain name.”</p>
<p><strong>Where Do Trusted CA’s Come From?</strong></p>
<p>Why does the customer believe she has a legitimate copy of VeriSign’s CA certificate?  She believes this because a set of &#8220;trusted&#8221; CAs came pre-installed with her Web browser software.  Internet Explorer, Firefox, and all other leading browser vendors pre-configure their browsers to trust well known CAs such as <a target="_blank" href="http://www.verisign.com/" title="Verisign">VeriSign</a>, <a target="_blank" href="http://www.thawte.com/" title="Thawte">Thawte</a>, and <a target="_blank" href="http://www.networksolutions.com/" title="Network Solutions">Network Solutions</a>.</p>
<p>C# programs will generally access the Windows <a target="_blank" href="http://en.wikipedia.org/wiki/Cryptographic_Service_Provider" title="Windows Cryptographic Service Provider">Cryptographic Service Provider</a> for trusted certificates.  The CSP is a shared OS resource usable by any program, and is also the same trust store consulted by Internet Explorer.</p>
<p>Similarly, the Java Runtime Environment comes with a pre-configure set of trusted certificate authorities.  The collection of trusted certificates can be found at <code>[JRE_HOME]/lib/security/cacerts</code>.  The <a target="_blank" href="http://java.sun.com/javase/6/docs/technotes/tools/windows/keytool.html" title="Java keytool"><code>keytool</code></a>, a command line utility found in the SDK, can be used to inspect and manipulate this file.  The default password for the <code>cacerts</code> keystore is “<code>changeit</code>”.</p>
<p><strong>Summary</strong></p>
<p>Public key cryptography is at the heart of SSL.  While most developers are aware this technology is used to encrypt a data channel, most are unfamiliar with its use of digital signing for identity authentication and message validation.  It is the lack of understanding of these other uses that generally stymie their efforts to implement SSL.</p>
<p>Stayed tuned for more posts on the lower level details of implementing SSL technology,</p>
]]></content:encoded>
			<wfw:commentRss>http://www.gavaghan.org/blog/2009/10/14/understanding-ssl-%e2%80%93-part-1-certificates-and-keys/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Liquid Cooling a PC: Gimmick or Necessity?</title>
		<link>http://www.gavaghan.org/blog/2009/10/06/liquid-cooling-a-pc-gimmick-or-necessity/</link>
		<comments>http://www.gavaghan.org/blog/2009/10/06/liquid-cooling-a-pc-gimmick-or-necessity/#comments</comments>
		<pubDate>Wed, 07 Oct 2009 02:54:03 +0000</pubDate>
		<dc:creator>Mike Gavaghan</dc:creator>
				<category><![CDATA[Hardware]]></category>

		<guid isPermaLink="false">http://www.gavaghan.org/blog/2009/10/06/liquid-cooling-a-pc-gimmick-or-necessity/</guid>
		<description><![CDATA[Early PCs seldom had more than a tiny, weak fan on the back of the case to push out excess heat generated by the internal electronics.  As transistors shrank and chips grew faster and more complex, CPUs began running hotter and reaching dangerous temperatures - so hot, in fact, that the little case fan couldn't protect the delicate electronics from burning out.

To address this, PC manufacturers began adding fans dedicated to cooling this nerve center of the motherboard.  Today, with high end gaming machines consuming up to 1000W or more, enormous heat is generated not just by the CPU, but by the memory, north and south bridges, and the graphics card.  To expel this heat from inside the case, larger and faster case fans are needed to keep everything running at a safe, relatively cool temperature.

For the past few years, PC accessory vendors have been marketing liquid cooling systems.  These products promise to cool more efficiently, and more quietly, than traditional fans - at the same time adding several hundred dollars to the total price tag of a new machine.  The question is: is this just a pricey gimmick, or is this the next logical step in the progression of ever more powerful machines?]]></description>
			<content:encoded><![CDATA[<p>Early PCs seldom had more than a tiny, weak fan on the back of the case to push out excess heat generated by the internal electronics.  As transistors shrank and chips grew faster and more complex, CPUs began running hotter and reaching dangerous temperatures - so hot, in fact, that the little case fan couldn&#8217;t protect the delicate electronics from burning out.</p>
<p>To address this, PC manufacturers began adding fans dedicated to cooling this nerve center of the motherboard.  Today, with high end gaming machines consuming up to 1000W or more, enormous heat is generated not just by the CPU, but by the memory, north and south bridges, and the graphics card.  To expel this heat from inside the case, larger and faster case fans are needed to keep everything running at a safe, relatively cool temperature.</p>
<p>For the past few years, PC accessory vendors have been marketing <a target="_blank" href="http://en.wikipedia.org/wiki/Water_cooling" title="Water Cooling">liquid cooling </a>systems.  These products promise to cool more efficiently, and more quietly, than traditional fans - at the same time adding several hundred dollars to the total price tag of a new machine.  The question is: is this just a pricey gimmick, or is this the next logical step in the progression of ever more powerful machines?</p>
<p><span id="more-62"></span><strong>What is liquid cooling?</strong></p>
<p><a target="_blank" href="http://en.wikipedia.org/wiki/Water_cooling" title="Water Cooling">Liquid cooling</a> your computer involves two separate components connected together by plastic PVC tubing filled with coolant.</p>
<p>The first component is the pump and radiator.  The pump is responsible for circulating coolant throughout your computer to absorb the heat generated by the various components.  The coolant is then pumped through a radiator, located outside of the case, which dissipates the heat outside.</p>
<p align="center"><a target="_blank" href="http://www.jdoqocy.com/click-3829051-10492042"><br />
<img border="0" width="468" src="http://www.awltovhc.com/image-3829051-10492042" alt="Once You Know, You Newegg" height="60" /></a></p>
<p align="left">The second component is the cooling blocks.  Cooling blocks are attached to one or more of your motherboard components.  The metal cooling blocks draw heat away from critical components on your motherboard, and coolant flowing through the blocks carries the heat to the radiator.</p>
<p>Fan cooling of components generally means drawing heat away from the electronics and filling the inside of the case with hot air &#8211; external case fans ultimately remove the heat from the case.  Liquid cooling <em>immediately</em> takes the heat out of the case.  Also, liquid coolant holds 4 times more heat than air, and transfers heat 30 times faster.</p>
<p><strong>When should you liquid cool?</strong></p>
<p>Simply put: most people do not need liquid cooling.  Desktop computers built to suit typical business applications - browsing, email, productivity applications, etc. - can easily get by on lower-end systems with minimal cooling requirements.  Even many gaming machines are well served by low to mid-range computers.</p>
<p>Higher end machines with top-of-the-line CPUs, however, are massive heat generators &#8211; and most CPU fans built for <a target="_blank" href="http://www.intel.com/Consumer/Learn/Desktop/corei7-detail.htm?cid=cim:ggl|core_us_ci7|f7A912|s" title="Intel Core i7">Intel&#8217;s latest line of Core i7 </a>processors are monstrous and louder than a NASCAR pit lane.  Added to the din of the other fans and components in the computer, these high RPM fans can be very distracting.  Liquid cooling the CPU can dramatically quiet the overall noise level coming from the box.</p>
<p>If you&#8217;re an overclocker, liquid cooling the CPU might be a necessity as there might not be any fan capable of keeping everything at a safe temperature.  You may also want to buy cooling blocks for your <a target="_blank" href="http://www.tomshardware.com/forum/258521-30-liquid-cooling-northbridge" title="Cooling North Bridge">north bridge</a>.</p>
<p><strong>When should you not liquid cool?</strong></p>
<p>If you have a low-end PC, noise and high temperatures are unlikely to be a problem.  You can save hundreds of dollars sticking to traditional fan cooling.</p>
<p>If you have a small case, you probably don&#8217;t have enough room to fit all of the cooling blocks and hoses necessary to install the cooling system.  For lqiuid cooling, plan on buying a full tower case in order to have plenty of room to work with.  A mid-tower case might work for simpler configurations, but it&#8217;d be a tight fit.</p>
<p>Finally, don&#8217;t liquid cool if you&#8217;re on a tight budget.  If you&#8217;re not overclocking, you can always buy traditional fans to keep your motherboard safely cool.  You may want to put some distance or baffling between you and your machine to minimize the noise, but you won&#8217;t have to worry about burning up your machine.</p>
<p><strong>What should you liquid cool?</strong></p>
<p><a target="_blank" href="http://www.kqzyfj.com/click-3829051-10442906" style="float: left; margin: 0px 15px 0pt 0pt"><img border="0" width="125" src="http://www.ftjcfx.com/image-3829051-10442906" alt="Once You Know, You Newegg" height="125" /></a>If you liquid cool nothing else, at least put a cooling block on the CPU.  In fact, it&#8217;s not unreasonable to have a system where <em>only</em> the CPU is liquid cooled.  This is the primary heat generating component inside your case.  Not only will the CPU quietly be kept to a safe temperature, the heat will be carried outside the case by the tubing &#8211; this reduces the load on the external case fans carry heat out from the inside.</p>
<p>Memory isn&#8217;t necessarily at risk of overheating (unless you&#8217;re overclocking), so it may not need special attention.  However, if you&#8217;ve filled up all of the DIMM slots, you might be pushing your luck.  The instructions to the <a href="http://asus.com/product.aspx?P_ID=QtpKQuERkuYw6trc" title="ASUS P6T">ASUS P6T </a>motherboard actually recommend adding additional RAM cooling when all six slots are used.</p>
<p>Think hard before liquid cooling memory.  Because the distance between DIMM slots is variable, RAM liquid coolers often involve sliding connectors.  These connectors are prone to leakage, and even the tiniest leak of electrically conductive coolant can ruin parts of your system.  If your memory is getting too hot, consider a <a target="_blank" href="http://www.newegg.com/Product/ProductList.aspx?Submit=ENE&amp;N=2010110572%201374126193&amp;name=Memory" title="Memory RAM Cooler">traditional fan cooler dedicated to RAM</a>.</p>
<p>High-end graphics cards might benefit from liquid cooling simply to reduce noise levels, but even that&#8217;s a stretch.  Many of the highest performing graphics cards on the market today still have reasonably quiet fans.  Also, liquid cooling these graphics cards means removing the fan over the GPU, thus invalidating your warranty.</p>
<p>The north bridge and south bridge sometimes need additional cooling in overclocking situations.</p>
<p>Finally, don&#8217;t bother cooling your hard drive or power supply.  Neither component is a substantial heat source.  In fact, hooking up too many cooling blocks in your loop will cause your pump to work harder and ultimately reduce the efficiency of your setup.  If you really feel you need to liquid cool every component in your box, consider adding a second loop.</p>
<p><strong>How to test</strong></p>
<p>Once you have your liquid cooling all set up, how do you load up your system to test its effectiveness?  For starters, I recommend installing a cooling system with temperature monitors.  You want to make sure your motherboard temperatures don&#8217;t enter a dangerous range while load testing your system.</p>
<p>To create a load, install <a target="_blank" href="http://boinc.berkeley.edu/" title="BOINC">BOINC</a>.  BOINC describes itself as using &#8220;the idle time on your computer to cure diseases, study global warming, discover pulsars, and do many other types of scientific research&#8221;.  Depending on the BOINC project you subscribe to, your computer will be assigned a small portion of a massive, mathematically intensive research problem.  By default, the computation will consume all available CPU cycles on your computer, and a goodly portion of your memory.</p>
<p>Keep a close eye on your system temperatures when you start this test.  I ran a BOINC test on my <a href="http://asus.com/product.aspx?P_ID=QtpKQuERkuYw6trc" title="ASUS P6T">ASUS P6T </a>motherboard with a <a target="_blank" href="http://www.intel.com/Consumer/Learn/Desktop/corei7-detail.htm?cid=cim:ggl|core_us_ci7|f7A912|s" title="Intel Core i7">Core i7 </a>processor and 12G of <a target="_blank" href="http://www.gskill.com/products.php?index=78" title="GSkill RAM">GSkill RAM</a>.  I was liquid cooling the CPU, but not memory.  In under 30 seconds, the CPU was running a cool 30C, but RAM was setting off the temperature alarm mat 55C!</p>
<p>Initially, my RAM had no dedicated cooling.  I removed the liquid cooling blocks because I couldn&#8217;t stop the leaking.  Based on this test, I added a dedicated, low-noise RAM cooler and now my box behaves beautifully.</p>
<p><strong>Final thoughts</strong></p>
<p>If you choose to liquid cool, my best advice is &#8220;be patient&#8221;.  Getting it right requires some experimentation.</p>
<p>Finally, select a brightly colored coolant like pink, bright blue, or fluorescent green.  This isn&#8217;t just about looking cool &#8211; these eye catching colors make spotting leaks on your motherboard a lot easier than a dull, colorless coolant.</p>
<p>My final thought?  Be cool, man, be  cool.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.gavaghan.org/blog/2009/10/06/liquid-cooling-a-pc-gimmick-or-necessity/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Kill Spam With Real-Time DNS Blacklists</title>
		<link>http://www.gavaghan.org/blog/2008/06/11/kill-spam-with-real-time-dns-blacklists/</link>
		<comments>http://www.gavaghan.org/blog/2008/06/11/kill-spam-with-real-time-dns-blacklists/#comments</comments>
		<pubDate>Wed, 11 Jun 2008 19:27:43 +0000</pubDate>
		<dc:creator>Mike Gavaghan</dc:creator>
				<category><![CDATA[Software]]></category>

		<guid isPermaLink="false">http://www.gavaghan.org/blog/2008/06/11/kill-spam-with-real-time-dns-blacklists/</guid>
		<description><![CDATA[A great Open Source project for gaining understanding about e-mail systems, including an in-depth look at SMTP and POP3, is the Java-based Apache JAMES Project.  Although JAMES has the unfortunate shortcoming of being built around the now defunct and unsupported Apache Avalon Framework, it’s still a fantastic learning tool for understanding email protocols, mail delivery, and spam filtering.  Not only that, it’s a fully functional, enterprise-ready mail server that can be up and running with minimal configuration.

One technology implemented by JAMES for spam filtering is real-time DNS blacklists.  DNSBLs identify the IP addresses of potential spam sources or machines known to be delivering spam (as determined by the sometimes controversial policies of the list owner).  Spam blacklists date back to 1996 with Paul Vixie’s Mail Abuse Prevention System, and are now used by ISPs and corporate mail systems around the world.  Countless organizations maintain blacklists, and Web sites like MX Toolbox permit ad hoc queries of IP addresses against dozens of published lists.]]></description>
			<content:encoded><![CDATA[<p>A great Open Source project for gaining understanding about e-mail systems, including an in-depth look at SMTP and POP3, is the Java-based <a target="_blank" href="http://james.apache.org/" title="Apache JAMES">Apache JAMES Project</a>.  Although JAMES has the unfortunate shortcoming of being built around the now defunct and unsupported <a target="_blank" href="http://avalon.apache.org/closed.html" title="Apache Avalon Project">Apache Avalon Framework</a>, it’s still a fantastic learning tool for understanding email protocols, mail delivery, and spam filtering.  Not only that, it’s a fully functional, enterprise-ready mail server that can be up and running with minimal configuration.</p>
<p>One technology implemented by JAMES for spam filtering is real-time DNS blacklists.  DNSBLs identify the IP addresses of potential spam sources and machines known to be delivering spam (as determined by the sometimes controversial policies of the list owner).  Spam blacklists date back to 1996 with Paul Vixie’s <a target="_blank" href="http://en.wikipedia.org/wiki/Mail_Abuse_Prevention_System" title="Mail Abuse Prevention System">Mail Abuse Prevention System</a>, and are now used by ISPs and corporate mail systems around the world.  Countless organizations maintain blacklists, and Web sites like <a target="_blank" href="http://www.mxtoolbox.com/" title="MX Toolbox">MX Toolbox</a> permit ad hoc queries of IP addresses against dozens of published lists.</p>
<p><span id="more-58"></span><strong>How It Works</strong></p>
<p>Built around the UDP-based DNS protocol, a DNSBL is an efficient and lightweight mechanism for checking the IP addresses of incoming messages against a list of email senders a mail server may wish to avoid.  This is much like the concept of today’s <a target="_blank" href="http://en.wikipedia.org/wiki/Service_oriented_architecture" title="Service Oriented Architecture">Service Oriented Architectures</a> – providing an uncoupled, standards-based interface consumed by arbitrary clients – except years ahead of its time when created.</p>
<p>Querying an IP address is as simple as reversing the octets of the address and appending the domain name of the list publisher.  Perform a DNS lookup of the <nobr>&#8220;A record&#8221;</nobr> for this string.  If a record is returned, the IP address is on the blacklist (some DNSBLs also return the reason for the listing in the TXT record).  If no record is found, the address isn’t listed.</p>
<p>Java, C#, and most other high level programming languages provide a means for performing a DNS lookup.  A simple way to try it out, however, is from a DOS prompt.  Suppose you want to check out the IP address <code>213.199.154.22</code> using the list maintained by <a target="_blank" href="http://www.five-ten-sg.com/" title="510 Software Group">510 Software Group</a> at <code>blackholes.five-ten-sg.com</code>.  You could use the <code>nslookup</code> command like this:</p>
<blockquote><p><code>nslookup 22.154.199.213.blackholes.five-ten-sg.com</code></p></blockquote>
<p>This should reply with “Non-existent domain”.  In other words, the address is “clean”.<br />
To lookup the same address on the <a target="_blank" href="http://www.spamcop.net/" title="SpamCop">SpamCop</a> blacklist at <code>bl.spamcop.net</code>, you would use this command:</p>
<blockquote><p><code>nslookup 22.154.199.213.bl.spamcop.net</code></p></blockquote>
<p>SpamCop also has a mechanism for simulating a positive response.  Technically, <code>127.0.0.2</code> is a local address.  But, SpamCop will provided a record for it:</p>
<blockquote><p><code>nslookup 2.0.0.127.bl.spamcop.net</code></p></blockquote>
<p>Try it out.  You’ll get back a valid “A record” indicating the address is listed – simulating the response you’d get for a blacklisted host.</p>
<p><strong>How Addresses Get Listed</strong></p>
<p>IP addresses get added to blacklists based on the policies selected by the list owners.  This is important to understand before blindly adding all available blacklists to your mail server.  Some lists are more aggressive than others, and the more aggressive a policy is the more likely you are to have legitimate email filtered out of your inbox.</p>
<p>Some spammers are identified by trusted sources forwarding spam messages to list managers.  The mail headers will identify the IP address of the sender.  Other spammers are identified when list owners plant <a target="_blank" href="http://en.wikipedia.org/wiki/Honeypot_%28computing%29" title="Honeypot (computing)">honeypots</a> – bogus email addresses posted online in order to identify spammers harvesting email address off of Web pages.</p>
<p>Some blacklists contain the IP addresses allocated to residential Internet subscribers regardless of whether they’ve been definitively identified as a spam source.  The rationale is that residential Internet users will use their ISP’s mail server to send and receive email.  Any email coming directly from a subscriber’s computer is either a deliberate spam campaign attempting to circumvent the ISP’s safeguards, or it’s a message generated by a <a target="_blank" href="http://en.wikipedia.org/wiki/Zombie_computer" title="Zombie computer">zombie</a> – a computer compromised by a virus and controlled by a hacker for the purpose of delivering spam.</p>
<p>Another category of blacklisted IP addresses belong to <a target="_blank" href="http://en.wikipedia.org/wiki/Open_relay" title="Open mail relay">open relays</a> – mail servers that don’t require authentication and thus provide a “hop” for spam messages to freely pass through.  Open relays allow spammers to hide the true origin of their messages (because the originating IP address might already be blacklisted).  This abuse of the open mail server often occurs without knowledge of the server owner.</p>
<p>All of these policies carry with them a bit of controversy.  A single spammer on a large network might cause thousands of innocent users on the same network to have their outbound email blocked.  Open relay owners are also regarded more as victims than active participants in spamming (although they should be summarily reprimanded for not applying the most basic of security measures to their mail exchange: <a target="_blank" href="http://en.wikipedia.org/wiki/SMTP-AUTH" title="SMTP-AUTH">SMTP authentication</a>).  Also, when blacklists are used by ISPs, customers might unknowingly fail to receive wanted messages that were filtered out based on someone else’s definition of spam.</p>
<p><strong>Available DNS Blacklists</strong></p>
<p>DNSBLs are intended for use by mail service providers – not individual email system users.  If you administer a mail server, a comparison of available blacklists you may consider configuring can be found at the <a target="_blank" href="http://stats.dnsbl.com/" title="DNSBL Resource">DNSBL Resource</a> Stats Center.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.gavaghan.org/blog/2008/06/11/kill-spam-with-real-time-dns-blacklists/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Got Requirements?  If Not, You&#8217;re Doomed</title>
		<link>http://www.gavaghan.org/blog/2008/03/31/got-requirements-if-not-youre-doomed/</link>
		<comments>http://www.gavaghan.org/blog/2008/03/31/got-requirements-if-not-youre-doomed/#comments</comments>
		<pubDate>Mon, 31 Mar 2008 11:31:07 +0000</pubDate>
		<dc:creator>Mike Gavaghan</dc:creator>
				<category><![CDATA[Commentary]]></category>

		<guid isPermaLink="false">http://www.gavaghan.org/blog/2008/03/31/got-requirements-if-not-youre-doomed/</guid>
		<description><![CDATA[Yet another software development disaster is headed for the digital trash heap of failed projects.  This time, the casualty is software funded by the U. S. Census Bureau.  The Associated Press reports failure to deliver usable software to census enumerators could add as much as $2 billion to the 2010 census. Worse, the AP reports "census officials are considering a return to using paper and pencil to count every man, woman and child in the nation."

This is a spectacular train wreck that had doom written all over it from Day One.  It’s a familiar, predictable pattern constantly repeated since the first clueless manager commanded "just make it user friendly".]]></description>
			<content:encoded><![CDATA[<p>Yet another software development disaster is headed for the digital trash heap of failed projects.  This time, the casualty is software funded by the <a href="http://www.census.gov/" title="U. S. Census Bureau" target="_blank">U. S. Census Bureau</a>.  <a href="http://www.cnn.com/2008/TECH/03/26/census.problems.ap/index.html" title=" Fancy computers spell trouble for 2010 census" target="_blank">The Associated Press reports</a> failure to deliver usable software to census enumerators could add as much as $2 billion to the 2010 <a href="http://en.wikipedia.org/wiki/Census#United_States" title="United States Census" target="_blank">census</a>. Worse, the AP reports &#8220;census officials are considering a return to using paper and pencil to count every man, woman and child in the nation.&#8221;</p>
<p>This is a spectacular train wreck that had doom written all over it from Day One.  It’s a familiar, predictable pattern constantly repeated since the first clueless manager commanded &#8220;just make it user friendly&#8221;.</p>
<p><span id="more-57"></span>The goal was simple enough: create handheld computers for census field workers to interview citizens and to electronically communicate with a central system.  What the Census Bureau got were expensive paperweights unable to transmit the large volumes of necessary data and too complex for census employees to comprehend during tests.</p>
<p>Census Director Steven Murdock blamed the failure on &#8220;communication problems&#8221; between the Census Bureau and the software contractor.  But, the AP learned, &#8220;interviews, congressional testimony, and government reports&#8221; soundly spell out the failure more precisely: &#8220;census officials are being blamed for a poor job spelling out technical requirements.&#8221;</p>
<p>Gee, doesn’t that sound familiar?  As <a href="http://workinghumor.com/quotes/yogi_berra.shtml" title="Yogi Berra Quotes" target="_blank">Yogi Berra so eloquently put it</a>: if you don&#8217;t know where you&#8217;re going, you might not get there.  The Census Bureau failed to spell out what they wanted, so they didn’t get it.</p>
<p><strong>Building software isn’t like shopping for it</strong></p>
<p>How can there be such viral stupidity in corporate leadership that this failure mode burns up capital and burns out developers with such regularity?</p>
<p>Here&#8217;s an analogy that works for me.  Many years ago, I bought a digital video camera.  To do anything meaningful with it, I needed editing software.  Several were available, so I browsed the stores and surfed the discussion groups to learn my options.  Each came with a unique set of functionality and corresponding price tag.</p>
<p>Many video editing products came with cool features I hadn’t even thought about. Suddenly, visions of green screen magic with pan-and-zoom, slow-motion effects did a fade transition to my Best Director acceptance speech at the Academy Awards!  When my decision was made, I plunked down my credit card and walked out of the store with a set of CDs rattling around inside a cardboard box.  I couldn’t wait to see what it could do!</p>
<p>We’re all familiar with this process of buying software.  Why is it so easy? Because <em>somebody else did the requirements analysis for us!</em>  Someone else spelled out the workflow of the user interface.  A subject matter expert carefully described what processes needed to be automated – and how.  The product was carefully prototyped, evaluated, refactored, and packaged into a polished work of technical elegance.  This process took months or years.  But, all we have to do as consumers is waltz into Best Buy on our lunch break.</p>
<p>But, what if no video editing software had ever been written before?  What if I was the first to identify the market and launch a little startup with the goal of making it big with the first video editing software targeting the consumer market?</p>
<p>Therein lies the greatest challenge in software development: building something that has never been built before, envisioning something never seen, describing an inspiration to someone else with sufficient clarity so they may bring it to reality.</p>
<p>Simply deciding on what features might be useful is hard enough.  Creating an interface and an intuitive workflow requires diligence, collaboration, and lots and lots of prototyping.</p>
<p><strong>Where the Census Bureau, and everyone else, gets it wrong</strong></p>
<p>At some point, the Census Bureau approached its contractor and described their needs.  I picture the conversation going something like this:</p>
<p><strong>Census Bureau:</strong> <em>Make us some software for our handheld computers.</em></p>
<p><strong>Contractor:</strong> <em>Okay.  What sort of work do your field workers do?  What are their most common tasks?  What kind of data will they be collecting?</em></p>
<p><strong>Census Bureau:</strong> <em>I don’t have time to go over that.  Just make sure it’s user friendly.</em></p>
<p>The Census Bureau thought they were strolling through Circuit City looking for “Intuit Census Taker 2010 Deluxe”.  They hadn’t stopped to think about what they really needed, they just figured they’d know it when they saw it.</p>
<p>In reality, they weren’t going to find their software on some store shelf.  After all, they needed software that had not been written before.  They needed careful analysis of their requirements.  They needed to identify <em>who</em> would use the software, <em>what</em> their users would be doing, and <em>how</em> they would be doing it.  Requirements analysis is hard.  It takes time.  It is tedious.</p>
<p>This is not work that can be passed on to the developers.  Developers are not the subject matter experts – they’re merely specialists in building dazzling creations meeting exacting specifications.  Leaving them to guess at requirements guarantees they’ll solve the wrong problem.</p>
<p><strong>How to fix it (and not fix it)</strong></p>
<p>Imagine buying a custom home and telling the builder &#8220;build me a home for $250,000…and make it pretty&#8221;.  Your builder can&#8217;t measure &#8220;pretty&#8221;.  How does he know when he’s done?  Requirements must be measurable and verifiable.</p>
<p>Your builder needs specific questions answered like “How many bedrooms?”, “One story or two?”  Failure to answer fundamental questions ensures you’ll blow 250K on a house you don’t want.  Answering these questions is your job – not the builder’s.  Software is no different.</p>
<p>Poor requirements analysis is the most common thread in all failed projects.  Who is responsible for providing requirements?  The primary stakeholders paying for the work.  Unfortunately, business process owners driving the software’s need see requirements definition as too burdensome – too much “busy work” – to task their own resources to address.  <em>Can’t the developers just write the software?  I’ll see if I like when they’re done.</em>  That’s a costly cycle to rely on.</p>
<p>When projects fail, developers take the heat.  Why?  They have no direct reports.  Everyone in the food chain has underlings to berate and scapegoat for their own failures.</p>
<p>So, an endless stream of passing fads gets hauled out to &#8220;correct&#8221; the waywardness of the development staff.  These fads are called &#8220;process&#8221; and go by important and trendy sounding names like <a href="http://en.wikipedia.org/wiki/RUP" title="IBM Rational Unified Process" target="_blank">RUP</a>, <a href="http://en.wikipedia.org/wiki/Extreme_programming" title="Extreme Programming" target="_blank">Extreme Programming</a>, and <a href="http://en.wikipedia.org/wiki/Agile_software_development" title="Agile Process" target="_blank">Agile</a>.  One process after another is ditched for &#8220;better&#8221; processes that theoretically correct the cause of the previous digital disaster.  When another failed product gets pitched into the bit bucket, the developers are erroneously accused of &#8220;not following the process.&#8221;</p>
<p>Don’t get me wrong.  I don’t mean to disparage the litany of software processes that have come and gone over the years.  But, doesn’t anybody wonder why we need so many?  Doesn’t anybody question why new processes continually come along claiming to &#8220;fix&#8221; the shortcomings of all before it?  <em>Why is a workable software process so hard to find?</em></p>
<p>They’re all workable – they simply fail to address the root cause of the problem.  The problem is leadership laziness.</p>
<p>When even halfway competent programmers are given a goal and sent on their way, you can expect them to deliver on all expectations.  Things like process, skill, and experience can influence the cost and maintainability of the code.  But, with clear requirements, you can always expect to get what you want.</p>
<p>So, business leaders, stop looking for the right “process”.  Instead, roll up your sleeves and do a little hard work.  Think about what you want.  Spell it out.  Be available for questions and clarifications.  Don’t make the developers guess.</p>
<p>It’s time well spent.  And, if your time is well spent, then so is your money.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.gavaghan.org/blog/2008/03/31/got-requirements-if-not-youre-doomed/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>JUnit Factory Part 3: Improving Code Coverage</title>
		<link>http://www.gavaghan.org/blog/2008/02/10/junit-factory-part-3-improving-code-coverage/</link>
		<comments>http://www.gavaghan.org/blog/2008/02/10/junit-factory-part-3-improving-code-coverage/#comments</comments>
		<pubDate>Mon, 11 Feb 2008 03:49:47 +0000</pubDate>
		<dc:creator>Mike Gavaghan</dc:creator>
				<category><![CDATA[Software]]></category>

		<guid isPermaLink="false">http://www.gavaghan.org/blog/2008/02/10/junit-factory-part-3-improving-code-coverage/</guid>
		<description><![CDATA[JUnit Factory is rather clever how it analyzes and executes your code to generate characterization tests. However, legacy Java code was generally not written with testability in mind. This sometimes makes it difficult for JUnit Factory to attain complete coverage of your code due to the need for objects to exist in a complex state or the need to interact with an external resource such as a database.

JUnit Factory is often able to generate mock instances automatically  for problematic classes. When automocking fails, the developer can improve coverage by either extracting behaviors into private methods or by providing hints to JUnit Factory in the form of test data helpers.]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.junitfactory.com" title="JUnit Factory" target="_blank">JUnit Factory</a> is rather clever how it analyzes and executes your code to generate characterization tests. However, legacy Java code was generally not written with testability in mind. This sometimes makes it difficult for JUnit Factory to attain complete coverage of your code due to the need for objects to exist in a complex state or the need to interact with an external resource such as a database.</p>
<p>JUnit Factory is often able to generate mock instances automatically  for problematic classes.  When automocking fails, the developer can improve coverage by either extracting behaviors into private methods or by providing hints to JUnit Factory in the form of test data helpers.</p>
<p><span id="more-54"></span>This post is part of a series:</p>
<p style="padding-left: 20px"> 1. <a href="http://www.gavaghan.org/blog/2008/01/04/characterization-tests-how-to-deal-with-legacy-java-code/" title="Characterization Tests: How To Deal With Legacy Java Code">Characterization Tests: How To Deal With Legacy Java Code</a><br />
2. <a href="http://www.gavaghan.org/blog/2008/01/15/junit-factory-part-1-generating-tests/" title="JUnit Factory Part 1: Generating Tests">JUnit Factory Part 1: Generating Tests</a><br />
3. <a href="http://www.gavaghan.org/blog/2008/01/24/junit-factory-part-2-finding-regressions/" title="JUnit Factory Part 2: Finding Regressions">JUnit Factory Part 2: Finding Regressions</a><br />
4. <strong>JUnit Factory Part 3: Improving Code Coverage</strong></p>
<p><strong>Handling External Resources</strong></p>
<p>A classic unit testing problem is testing business logic that depends on an external resource.  The external resource is usually a database, but it could also be a Web service, the file system, or a user interface.  This is challenging because a true unit test executes in the absence of external dependencies, but creating mocks is an expensive, laborious process for the developer.</p>
<p>JUnit Factory&#8217;s answer to this is the <a href="http://www.junitfactory.com/articles/mockingbird/" title="JUnit Factory Mockingbird" target="_blank">Mockingbird</a> framework.  When code to be tested must retrieve data from a database, JUnit Factory will repeatedly see some failure (like a <code>SQLException</code>) being thrown every time it tries to execute a database call.  To move beyond the database call, JUnit Factory will create a mock implementation of the failing method.</p>
<p>Let&#8217;s look at a modified version of the <code>makePurchase()</code> method we discussed earlier:</p>
<blockquote class="codeblock">
<blockquote class="codeline0"><p>public void makePurchase(Purchase purchase) throws CreditCardException</p></blockquote>
<blockquote class="codeline0"><p>{</p></blockquote>
<blockquote class="codeline1"><p>validateBalance(balance + purchase.getAmount());</p></blockquote>
<blockquote class="blankcodeline"></blockquote>
<blockquote class="codeline1"><p>CreditCardDAO dao = CreditCardDAO.getDAOImplementation();</p></blockquote>
<blockquote class="codeline1"><p>dao.recordPurchase(accountNumber, purchase);</p></blockquote>
<blockquote class="blankcodeline"></blockquote>
<blockquote class="codeline1"><p>balance = balance + purchase.getAmount();</p></blockquote>
<blockquote class="codeline0"><p>}</p></blockquote>
</blockquote>
<p>We&#8217;ve introduced a data access object called <code>CreditCardDAO</code> encapsulating our interface to an external system.  In this case, it&#8217;s probably a database.  There&#8217;s likely one or more subtypes of <code>CreditCardDAO</code>, such as <code>CreditCardOracleDAO</code> or <code>CreditCardMySqlDAO</code>, providing implementation-specific behaviors for the data storage system.</p>
<p>Notice there are no subtypes of <code>CreditCardDAO</code> in the <a href="http://www.gavaghan.org/blog/characterization-tests-sample-code/" title="Characterization Tests Sample Code">example Eclipse project archive</a>.  They wouldn&#8217;t be usable, anyway, since a properly written unit test should execute in the absence of a database.  A developer would need to create a mock instance of <code>CreditCardDAO</code> in order to write the test.</p>
<p>If we submit this class to JUnit Factory to autogenerate a characterization test, we can see how the call to <code>CreditCardDAO.recordPurchase()</code> gets mocked out using the Mockingbird framework:</p>
<blockquote class="codeblock">
<blockquote class="codeline0"><p>public void testMakePurchaseWithAggressiveMocks() throws Throwable</p></blockquote>
<blockquote class="codeline0"><p>{</p></blockquote>
<blockquote class="codeline1"><p>CreditCard creditCard =</p></blockquote>
<blockquote class="codeline4"><p>(CreditCard) Mockingbird.getProxyObject(CreditCard.class, true);</p></blockquote>
<blockquote class="blankcodeline"></blockquote>
<blockquote class="codeline1"><p>Purchase purchase =</p></blockquote>
<blockquote class="codeline4"><p>(Purchase) Mockingbird.getProxyObject(Purchase.class);</p></blockquote>
<blockquote class="blankcodeline"></blockquote>
<blockquote class="codeline1"><p>CreditCardDAO creditCardDAO = new CreditCardDAO();</p></blockquote>
<blockquote class="codeline1"><p>setPrivateField(creditCard, &#8220;creditLimit&#8221;, new Double(0.0));</p></blockquote>
<blockquote class="codeline1"><p>setPrivateField(creditCard, &#8220;accountNumber&#8221;, &#8220;&#8221;);</p></blockquote>
<blockquote class="codeline1"><p>setPrivateField(creditCard, &#8220;balance&#8221;, new Double(0.0));</p></blockquote>
<blockquote class="codeline1"><p>setPrivateField(purchase, &#8220;amount&#8221;, new Double(0.0));</p></blockquote>
<blockquote class="codeline1"><p>CreditCardDAO.setDAOImplementation(creditCardDAO);</p></blockquote>
<blockquote class="codeline1"><p>Mockingbird.enterRecordingMode();</p></blockquote>
<blockquote class="blankcodeline"></blockquote>
<blockquote class="codeline1"><p>Mockingbird.setReturnValue(false,</p></blockquote>
<blockquote class="codeline4"><p>creditCardDAO,</p></blockquote>
<blockquote class="codeline4"><p>&#8220;recordPurchase&#8221;,</p></blockquote>
<blockquote class="codeline4"><p>&#8220;(java.lang.String,example2.Purchase)void&#8221;,</p></blockquote>
<blockquote class="codeline4"><p>null,</p></blockquote>
<blockquote class="codeline4"><p>1</p></blockquote>
<blockquote class="codeline1"><p>);</p></blockquote>
<blockquote class="blankcodeline"></blockquote>
<blockquote class="codeline1"><p>Mockingbird.enterTestMode(CreditCard.class);</p></blockquote>
<blockquote class="codeline1"><p>creditCard.makePurchase(purchase);</p></blockquote>
<blockquote class="codeline1"><p>assertEquals(&#8220;creditCard.getBalance()&#8221;,</p></blockquote>
<blockquote class="codeline4"><p>0.0,</p></blockquote>
<blockquote class="codeline4"><p>creditCard.getBalance(),</p></blockquote>
<blockquote class="codeline4"><p>1.0E-6</p></blockquote>
<blockquote class="codeline1"><p>);</p></blockquote>
<blockquote class="codeline0"><p>}</p></blockquote>
<blockquote class="blankcodeline"></blockquote>
</blockquote>
<p>First, notice the suffix &#8220;WithAggressiveMocks&#8221; added to the end of the test method name.  This indicates JUnit Factory needed to create mocks for a few classes in order to create a test.  Aggressive mocks aren&#8217;t a problem, although they can make tests harder to read.  Later, we&#8217;ll discuss test data helpers which can sometimes be used to avoid aggressive mocking and create clearer test code.</p>
<p>The test method begins with Mockingbird creating a number of proxy instances to create a hook into the call to be mocked.  The actual insertion of the mock behavior occurs on the line that begins &#8220;<code>Mockingbird.setReturnValue</code>&#8220;.</p>
<p>Instead of instantiating a subtype of <code>CreditCardDAO</code>, JUnit Factory simply uses the base type.  However, the base implementation of <code>recordPurchase()</code> always throws a <code>RuntimeException</code> indicating it must be overridden by a subclass.  The &#8220;<code>setReturnValue()</code>&#8221; call adjusts the behavior of <code>recordPurchase()</code> to return normally instead.  This allows the rest of the <code>makePurchase()</code> method to execute and update the balance.</p>
<p><strong>These are unit tests &#8211; not integration tests</strong></p>
<p>You&#8217;ll see Mockingbird used in a number of scenarios, not just where calls to external resources would otherwise fail.  Mockingbird is applied anywhere JUnit Factory needs to control the return value of dependent types in order to continue executing a method.</p>
<p>This may seem a little disconcerting at first.  After all, how good are these tests if we&#8217;ve mocked the behavior of dependent classes?  This is okay.  Remember these are <a href="http://www.gavaghan.org/blog/2008/01/04/characterization-tests-how-to-deal-with-legacy-java-code/" title="Characterization Tests: How To Deal With Legacy Java Code"><em>characterization tests</em></a>.  This isn&#8217;t about asserting the correct behavior of our code.  We&#8217;re only trying to capture the behavior of legacy code so we can find regressions.</p>
<p><strong>Method extraction and test data helpers</strong></p>
<p>Next, let&#8217;s take a look at a method called <code>fraudCheck()</code>.  This implements an admittedly simplistic rule that flags account activity as suspicious if there are several small purchases (less than $10) that add up to over $100.</p>
<blockquote class="codeblock">
<blockquote class="codeline0"><p>public boolean fraudCheck()</p></blockquote>
<blockquote class="codeline0"><p>{</p></blockquote>
<blockquote class="codeline1"><p>CreditCardDAO dao = CreditCardDAO.getDAOImplementation();</p></blockquote>
<blockquote class="codeline1"><p>List purchases = dao.getRecentPurchases(accountNumber);</p></blockquote>
<blockquote class="blankcodeline"></blockquote>
<blockquote class="codeline1"><p>boolean isSuspicious;</p></blockquote>
<blockquote class="codeline1"><p>double purchaseTotal = 0;</p></blockquote>
<blockquote class="blankcodeline"></blockquote>
<blockquote class="codeline1"><p>for (Iterator iter = purchases.iterator(); iter.hasNext();)</p></blockquote>
<blockquote class="codeline1"><p>{</p></blockquote>
<blockquote class="codeline2"><p>Purchase purchase = (Purchase) iter.next();</p></blockquote>
<blockquote class="blankcodeline"></blockquote>
<blockquote class="codeline2"><p>if (purchase.getAmount() &lt; 10.00)</p></blockquote>
<blockquote class="codeline2"><p>{</p></blockquote>
<blockquote class="codeline3"><p>purchaseTotal += purchase.getAmount();</p></blockquote>
<blockquote class="codeline2"><p>}</p></blockquote>
<blockquote class="codeline1"><p>}</p></blockquote>
<blockquote class="blankcodeline"></blockquote>
<blockquote class="codeline1"><p>if (purchaseTotal &gt; 100.00)</p></blockquote>
<blockquote class="codeline1"><p>{</p></blockquote>
<blockquote class="codeline2"><p>isSuspicious = true;</p></blockquote>
<blockquote class="codeline1"><p>}</p></blockquote>
<blockquote class="codeline1"><p>else</p></blockquote>
<blockquote class="codeline1"><p>{</p></blockquote>
<blockquote class="codeline2"><p>isSuspicious = false;</p></blockquote>
<blockquote class="codeline1"><p>}</p></blockquote>
<blockquote class="blankcodeline"></blockquote>
<blockquote class="codeline1"><p>return isSuspicious;</p></blockquote>
<blockquote class="codeline0"><p>}</p></blockquote>
<blockquote class="blankcodeline"></blockquote>
</blockquote>
<p>When we execute <code>CreditCardAgitaTest</code>, we can look at the coverage information provided by the JUnit Factory plug-in on the left side of the editor window:</p>
<p><img src="http://www.gavaghan.org/blog/wp-content/uploads/2008/02/missingcoverage.gif" alt="Missing Coverage" border="1" /></p>
<p>Here, we see line 138 is never executed when we run the test.  For a series of purchases to be flagged as suspicious, we&#8217;d need at least 11 transactions of $9.99.  Although JUnit Factory can mock the return value of <code>getRecentPurchases()</code>, it was unable to discover the proper state of a purchase list that would result in the execution of this line. So, we&#8217;re not able to reach all branches of our code.</p>
<p><strong>Controlling preconditions</strong></p>
<p>We know how to create a list of purchases that satisfies the criteria for suspicious activity, but we need some way of inserting that list into a test.</p>
<p>A unit test involves creating a set of preconditions to a method (the parameters) and asserting a set of postconditions (the state manipulated by the method). Before we can control the list of purchases as a test precondition, we need to refactor our code to turn the list of purchases into a method parameter.</p>
<p>The safest way to do this is to use Eclipse&#8217;s refactoring tools.  Select the code in <code>fraudCheck()</code> from the first line <em>after</em> the call to <code>getRecentPurchases()</code> and on to the end of the method.  Right-click the highlighted code in the editor and select &#8220;Refactor -&gt; Extract Method&#8221;.  We&#8217;ll name the new method &#8220;<code>hasSuspiciousActivity()</code>&#8220;.</p>
<p><img src="http://www.gavaghan.org/blog/wp-content/uploads/2008/02/extractmethod.gif" alt="Extract Method" border="1" /></p>
<p>This is completely safe because extracting this code into its own method doesn&#8217;t actually change the behavior of the <code>fraudCheck()</code> method.  All we&#8217;ve done is make the <code>fraudCheck()</code> method <em>testable</em>.  The new code looks like this:</p>
<blockquote class="codeblock">
<blockquote class="codeline0"><p>public boolean fraudCheck()</p></blockquote>
<blockquote class="codeline0"><p>{</p></blockquote>
<blockquote class="codeline1"><p>CreditCardDAO dao = CreditCardDAO.getDAOImplementation();</p></blockquote>
<blockquote class="codeline1"><p>List purchases = dao.getRecentPurchases(accountNumber);</p></blockquote>
<blockquote class="blankcodeline"></blockquote>
<blockquote class="codeline1"><p>return hasSuspiciousActivity(purchases);</p></blockquote>
<blockquote class="codeline0"><p>}</p></blockquote>
<blockquote class="blankcodeline"></blockquote>
<blockquote class="codeline0"><p>private boolean hasSuspiciousActivity(List purchases)</p></blockquote>
<blockquote class="codeline0"><p>{</p></blockquote>
<blockquote class="codeline1"><p>boolean isSuspicious;</p></blockquote>
<blockquote class="codeline1"><p>double purchaseTotal = 0;</p></blockquote>
<blockquote class="blankcodeline"></blockquote>
<blockquote class="codeline1"><p>for (Iterator iter = purchases.iterator(); iter.hasNext();)</p></blockquote>
<blockquote class="codeline1"><p>{</p></blockquote>
<blockquote class="codeline2"><p>Purchase purchase = (Purchase) iter.next();</p></blockquote>
<blockquote class="blankcodeline"></blockquote>
<blockquote class="codeline2"><p>if (purchase.getAmount() &lt; 10.00)</p></blockquote>
<blockquote class="codeline2"><p>{</p></blockquote>
<blockquote class="codeline3"><p>purchaseTotal += purchase.getAmount();</p></blockquote>
<blockquote class="codeline2"><p>}</p></blockquote>
<blockquote class="codeline1"><p>}</p></blockquote>
<blockquote class="blankcodeline"></blockquote>
<blockquote class="codeline1"><p>if (purchaseTotal &gt; 100.00)</p></blockquote>
<blockquote class="codeline1"><p>{</p></blockquote>
<blockquote class="codeline2"><p>isSuspicious = true;</p></blockquote>
<blockquote class="codeline1"><p>}</p></blockquote>
<blockquote class="codeline1"><p>else</p></blockquote>
<blockquote class="codeline1"><p>{</p></blockquote>
<blockquote class="codeline2"><p>isSuspicious = false;</p></blockquote>
<blockquote class="codeline1"><p>}</p></blockquote>
<blockquote class="blankcodeline"></blockquote>
<blockquote class="codeline1"><p>return isSuspicious;</p></blockquote>
<blockquote class="codeline0"><p>}</p></blockquote>
</blockquote>
<p>What we&#8217;ve achieved is the creation of a method that takes a list of purchases as a parameter.  Now, we can give JUnit Factory a hint about how to create this parameter in such a way that <code>isSuspicious</code> will sometimes be set to &#8220;true&#8221;.</p>
<p><strong>Giving hints using test data helpers</strong></p>
<p>A test data helper is simply a class that creates objects JUnit Factory can pass as parameters to methods being tested.  Test data helper methods must 1) have a name that begins &#8220;create&#8221;, 2) take no parameters, and 3) return an instance of the target data type.  You may have as many test data helper methods on a test helper class as you want.</p>
<p>In the <a href="http://www.gavaghan.org/blog/characterization-tests-sample-code/" title="Characterization Tests Sample Code">sample Eclipse project archive</a>, look for a source folder named &#8220;testhelpers&#8221;.  In there you&#8217;ll find a class named <code>PurchaseListTestHelper</code>. This class implements <code>com.agitar.lib.TestHelper</code>, so JUnit Factory will recognize it as a global test helper (as opposed to the <code>ScopedTestHelper</code> interface which ties the helper methods to a particular type).   The class contains a single test data helper method named <code>createSuspiciousPurchaseList()</code>.  Here is the complete class definition:</p>
<blockquote class="codeblock">
<blockquote class="codeline0"><p>package example2;</p></blockquote>
<blockquote class="blankcodeline"></blockquote>
<blockquote class="codeline0"><p>import java.util.*;</p></blockquote>
<blockquote class="codeline0"><p>import com.agitar.lib.TestHelper;</p></blockquote>
<blockquote class="blankcodeline"></blockquote>
<blockquote class="codeline0"><p>public class PurchaseListTestHelper implements TestHelper</p></blockquote>
<blockquote class="codeline0"><p>{</p></blockquote>
<blockquote class="codeline1"><p>public static List createSuspiciousPurchaseList()</p></blockquote>
<blockquote class="codeline1"><p>{</p></blockquote>
<blockquote class="codeline2"><p>ArrayList purchaseList = new ArrayList();</p></blockquote>
<blockquote class="blankcodeline"></blockquote>
<blockquote class="codeline2"><p>try</p></blockquote>
<blockquote class="codeline2"><p>{</p></blockquote>
<blockquote class="codeline3"><p>for (int i = 0; i &lt; 11; i++)</p></blockquote>
<blockquote class="codeline3"><p>{</p></blockquote>
<blockquote class="codeline4"><p>Date purchaseDate = new Date(1000);</p></blockquote>
<blockquote class="codeline4"><p>double amount = 9.99;</p></blockquote>
<blockquote class="codeline4"><p>Purchase purchase = new Purchase( purchaseDate, amount );</p></blockquote>
<blockquote class="codeline4"><p>purchaseList.add(purchase);</p></blockquote>
<blockquote class="codeline3"><p>}</p></blockquote>
<blockquote class="codeline2"><p>}</p></blockquote>
<blockquote class="codeline2"><p>catch( CreditCardException exc )</p></blockquote>
<blockquote class="codeline2"><p>{</p></blockquote>
<blockquote class="codeline3"><p>throw new RuntimeException(&#8220;Failed to create purchase list&#8221;);</p></blockquote>
<blockquote class="codeline2"><p>}</p></blockquote>
<blockquote class="blankcodeline"></blockquote>
<blockquote class="codeline2"><p>return purchaseList;</p></blockquote>
<blockquote class="codeline1"><p>}</p></blockquote>
<blockquote class="codeline0"><p>}</p></blockquote>
</blockquote>
<p>This helper create a list of 11 purchases of $9.99 each.  If this object is passed to our <code>hasSuspiciousActivity()</code> method, we can expect it to execute the line setting <code>isSuspicious</code> to <code>true</code>.</p>
<p>Can we be sure JUnit Factory will use our test helper?  Not necessarily.  JUnit Factory prefers to use developer provided test data helpers whenever possible &#8211; as long as they provide unique code coverage or an interesting outcome.  If you have multiple test helpers, but they all provide the same test coverage, JUnit Factory will only use one of them.</p>
<p>If no test helper provides a desired execution flow,  JUnit Factory will create an instance of an object on its own by reflecting constructors off of the <code>Class</code> object.  It is only when this final strategy fails that JUnit Factory resorts to aggressive mocks and the Mockingbird framework.</p>
<p>Will JUnit Factory use the test data helper we just created?  We can generate tests for <code>CreditCard</code> again and find out.  JUnit Factory will search our entire Eclipse project for all available test data helpers.  There&#8217;s nothing to configure, because all classes implementing <code>TestHelper</code> or <code>ScopedTestHelper</code> will be used as candidates.</p>
<p>After regenerating tests for <code>CreditCard</code>, we can see the answer is &#8220;yes,&#8221; JUnit Factory found our test data helper and used it.  Some of the test cases for <code>hasSuspiciousActivity()</code> use <code>PurchaseListTestHelper </code> as shown in the generated test:</p>
<blockquote class="codeblock">
<blockquote class="codeline0"><p>public void testHasSuspiciousActivity() throws Throwable</p></blockquote>
<blockquote class="codeline0"><p>{</p></blockquote>
<blockquote class="codeline1"><p>CreditCard creditCard = new CreditCard(&#8220;3317 3013 6259 0300&#8243;, 100.0, 0.0);</p></blockquote>
<blockquote class="blankcodeline"></blockquote>
<blockquote class="codeline1"><p>List suspiciousPurchaseList =</p></blockquote>
<blockquote class="codeline5"><p>PurchaseListTestHelper.createSuspiciousPurchaseList();</p></blockquote>
<blockquote class="blankcodeline"></blockquote>
<blockquote class="codeline1"><p>boolean add =</p></blockquote>
<blockquote class="codeline5"><p>suspiciousPurchaseList.add(new Purchase(new Date(100L), 100.0));</p></blockquote>
<blockquote class="blankcodeline"></blockquote>
<blockquote class="codeline1"><p>boolean result = ((Boolean) callPrivateMethod( &#8220;example2.CreditCard&#8221;,</p></blockquote>
<blockquote class="codeline5"><p>&#8220;hasSuspiciousActivity&#8221;,</p></blockquote>
<blockquote class="codeline5"><p>new Class[] {List.class},</p></blockquote>
<blockquote class="codeline5"><p>creditCard,</p></blockquote>
<blockquote class="codeline5"><p>new Object[] {suspiciousPurchaseList})</p></blockquote>
<blockquote class="codeline1"><p>).booleanValue();</p></blockquote>
<blockquote class="blankcodeline"></blockquote>
<blockquote class="codeline1"><p>assertTrue(&#8220;result&#8221;, result);</p></blockquote>
<blockquote class="codeline0"><p>}</p></blockquote>
</blockquote>
<p>When we execute <code>CreditCardAgitarTest</code>, the code coverage bars in the editor window show JUnit Factory is now covering all of our business logic in <code>CreditCard</code>.  It has also created additional assertions in <code>CreditCardAgitarTest</code> to check the outcome when <code>isSuspicious</code> returns <code>true</code>.</p>
<p><strong>Test coverage strategy</strong></p>
<p>With so many tools at your your disposal, where do you begin?</p>
<p>First, don&#8217;t concern yourself with aggressive mocks.  Aggressive mocks happen automatically, and they&#8217;re okay.  They&#8217;re merely a sign your legacy code wasn&#8217;t written for testability.  Aggressive mocks give you the code coverage you need to detect changes in the behavior of your code.  If you have 100% code coverage already, the only reason you might look into one of the other two strategies is if you want to improve the readability of your tests.</p>
<p>If aggressive mocks don&#8217;t give you enough coverage, consider refactoring your code using the Eclipse tool to extract a method.  This allows you to create method parameters out of local variables that JUnit Factory couldn&#8217;t get into an appropriate state.  Often times, you won&#8217;t even need to create a test data helper after refactoring your code.  If the required state for a parameter is straightforward enough, JUnit Factory can figure out on its own how to create it properly.</p>
<p>Reach for test data helpers last.  They&#8217;re a powerful tool.  But, they require writing additional code &#8211; and that&#8217;s just more code you&#8217;ll need to maintain.  Use them only when refactoring doesn&#8217;t give you the coverage you need, or when team development policies preclude modifying existing code.</p>
<p>Lastly, always consider whether the missing coverage is worth solving.  You might be dealing with truly dead code that can never be reached.  You might also be dealing with one or two minor lines that simply aren&#8217;t worth the effort.  Aiming for 100% code coverage is a costly and, generally, foolish objective. Consider the cost against the benefit.</p>
<p>After all, if you&#8217;ve brought your test coverage from 0% up to 80% with the single click of a button, aren&#8217;t you profoundly better off than before?</p>
]]></content:encoded>
			<wfw:commentRss>http://www.gavaghan.org/blog/2008/02/10/junit-factory-part-3-improving-code-coverage/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>JUnit Factory Part 2: Finding Regressions</title>
		<link>http://www.gavaghan.org/blog/2008/01/24/junit-factory-part-2-finding-regressions/</link>
		<comments>http://www.gavaghan.org/blog/2008/01/24/junit-factory-part-2-finding-regressions/#comments</comments>
		<pubDate>Fri, 25 Jan 2008 02:59:34 +0000</pubDate>
		<dc:creator>Mike Gavaghan</dc:creator>
				<category><![CDATA[Software]]></category>

		<guid isPermaLink="false">http://www.gavaghan.org/blog/2008/01/24/junit-factory-part-2-finding-regressions/</guid>
		<description><![CDATA[Characterization tests provide a safety net for your legacy Java code by helping identify unintended changes in software behavior caused by code maintenance.  JUnit Factory (http://www.junitfactory.com) from Agitar Software (http://www.agitar.com) may be used to automatically generate these tests for you.  In this post, we’ll take a look at what happens to these characterization tests when a simple code change is made.]]></description>
			<content:encoded><![CDATA[<p>Characterization tests provide a safety net for your legacy Java code by helping identify unintended changes in software behavior caused by code maintenance.  <a href="http://www.junitfactory.com/" onclick="javascript:urchinTracker('/outgoing/junitfactory');" title="JUnit Factory" target="_blank">JUnit Factory</a> from <a href="http://www.agitar.com/" onclick="javascript:urchinTracker('/outgoing/agitar');" title="Agitar Software" target="_blank">Agitar Software</a> may be used to automatically generate these tests for you.  In this post, we’ll take a look at what happens to these characterization tests when a simple code change is made.</p>
<p><span id="more-52"></span>This post is part of a series:</p>
<p style="padding-left: 20px"> 1. <a href="http://www.gavaghan.org/blog/2008/01/04/characterization-tests-how-to-deal-with-legacy-java-code/" title="Characterization Tests: How To Deal With Legacy Java Code">Characterization Tests: How To Deal With Legacy Java Code</a><br />
2. <a href="http://www.gavaghan.org/blog/2008/01/15/junit-factory-part-1-generating-tests/" title="JUnit Factory Part 1: Generating Tests">JUnit Factory Part 1: Generating Tests</a><br />
<strong>3. JUnit Factory Part 2: Finding Regressions</strong><br />
4. <a href="http://www.gavaghan.org/blog/2008/02/10/junit-factory-part-3-improving-code-coverage/" title="JUnit Factory Part 3: Improving Code Coverage">JUnit Factory Part 3: Improving Code Coverage</a></p>
<p><strong>A simple requirements change</strong></p>
<p>Suppose we need to implement a simple requirements change to the <code>CreditCard</code> class we&#8217;ve already created.  Presently, the <code>validateBalance()</code> method disallows negative balances.  The business leadership of our company, however, has decided to allow customers to overpay their credit card balances.</p>
<p>Before writing any code, we must first verify that all of our current characterization tests still pass.  The fastest way to do this is to select the source folder containing our characterization tests in the Eclipse Package Explorer.  Right click on the folder and select &#8220;Run As / Agitar JUnit Test&#8221;.</p>
<p>If any tests fail, it means some other developer has already introduced a behavior change into the system without addressing how this affects tests.  If all of the tests pass, we know we have a safety net.  We may now move forward making changes confident any regressions will be detected before we commit our work to version control.</p>
<p>Credit card payments are recorded in the <code>makePayment()</code> method:</p>
<blockquote class="codeblock">
<blockquote class="codeline0"><p>public void makePayment( double amount )  throws CreditCardException</p></blockquote>
<blockquote class="codeline0"><p>{</p></blockquote>
<blockquote class="codeline1"><p>if (amount &lt;= 0)</p></blockquote>
<blockquote class="codeline1"><p>{</p></blockquote>
<blockquote class="codeline2"><p>throw new CreditCardException(&#8220;Payment amount must be positive&#8221;);</p></blockquote>
<blockquote class="codeline1"><p>}</p></blockquote>
<blockquote class="blankcodeline"></blockquote>
<blockquote class="codeline1"><p>validateBalance( balance &#8211; amount );</p></blockquote>
<blockquote class="codeline1"><p>balance = balance &#8211; amount;</p></blockquote>
<blockquote class="codeline0"><p>}</p></blockquote>
</blockquote>
<p>After ensuring a postive payment amount has been made, the method invokes <code>validateBalance()</code> on the proposed new balance to check if it&#8217;s legal.</p>
<p>Presently, <code>validateBalance()</code> disallows negative values, but we&#8217;ll comment out the section of the method that performs this check:</p>
<blockquote class="codeblock">
<blockquote class="codeline0"><p>private void validateBalance( double balance )  throws CreditCardException</p></blockquote>
<blockquote class="codeline0"><p>{</p></blockquote>
<blockquote class="codeline1"><p>//if (balance &lt; 0.00)</p></blockquote>
<blockquote class="codeline1"><p>//{</p></blockquote>
<blockquote class="codeline1"><p>// throw new CreditCardException(&#8220;Balance can&#8217;t go below minimum balance&#8221;);</p></blockquote>
<blockquote class="codeline1"><p>//}</p></blockquote>
<blockquote class="blankcodeline"></blockquote>
<blockquote class="codeline1"><p>if (balance &gt; creditLimit)</p></blockquote>
<blockquote class="codeline1"><p>{</p></blockquote>
<blockquote class="codeline2"><p>throw new CreditCardException(&#8220;Balance can&#8217;t exceed credit limit&#8221;);</p></blockquote>
<blockquote class="codeline1"><p>}</p></blockquote>
<blockquote class="codeline0"><p>}</p></blockquote>
</blockquote>
<p>The <code>makePurchase()</code> method now allows payments that exceed the outstanding balance on the credit card.</p>
<p><strong>Rerun the tests to find behavior changes</strong></p>
<p>When we rerun our characterization tests, we discover that three of the tests are now failing.  It shouldn&#8217;t come as any surprise, though, since changing the behavior of the class is what we intended to do.</p>
<p>So, we should just regenerate the <code>CreditCard</code> tests, right?  Absolutely not!  We must first analyze each of the test failures to determine if all of the failures reflect an expected change in behavior.</p>
<p>One failing test is for <code>validateBalance()</code>:</p>
<blockquote class="codeblock">
<blockquote class="codeline0"><p>public void testValidateBalanceThrowsCreditCardException() throws Throwable</p></blockquote>
<blockquote class="codeline0"><p>{</p></blockquote>
<blockquote class="codeline1"><p>CreditCard creditCard = new CreditCard(&#8220;2298 9812 4566 1184&#8243;, 100.0, 0.0);</p></blockquote>
<blockquote class="codeline1"><p>try</p></blockquote>
<blockquote class="codeline1"><p>{</p></blockquote>
<blockquote class="codeline2"><p>callPrivateMethod(&#8220;example1.CreditCard&#8221;,</p></blockquote>
<blockquote class="codeline5"><p>&#8220;validateBalance&#8221;,</p></blockquote>
<blockquote class="codeline5"><p>new Class[] {double.class},</p></blockquote>
<blockquote class="codeline5"><p>creditCard,</p></blockquote>
<blockquote class="codeline5"><p>new Object[] {new Double(-1.0)}</p></blockquote>
<blockquote class="codeline2"><p>);</p></blockquote>
<blockquote class="codeline2"><p>fail(&#8220;Expected CreditCardException to be thrown&#8221;);</p></blockquote>
<blockquote class="codeline1"><p>}</p></blockquote>
<blockquote class="codeline1"><p>catch (CreditCardException ex)</p></blockquote>
<blockquote class="codeline1"><p>{</p></blockquote>
<blockquote class="codeline2"><p>assertEquals(&#8220;ex.getMessage()&#8221;, &#8220;Balance can&#8217;t go below minimum balance&#8221;, ex.getMessage());</p></blockquote>
<blockquote class="codeline2"><p>assertThrownBy(CreditCard.class, ex);</p></blockquote>
<blockquote class="codeline1"><p>}</p></blockquote>
<blockquote class="codeline0"><p>}</p></blockquote>
</blockquote>
<p>This test passes -1.0 to <code>validateBalance()</code> and expects a <code>CreditCardException</code> to be thrown.  This test passed when run against the old code, but it fails now because an exception is no longer thrown for negative balances.  This is an <em>expected</em> test failure.  The failing test reflects an intended change of behavior.</p>
<p>As you might expect, there&#8217;s also a failing test for <code>makePayment()</code>:</p>
<blockquote class="codeblock">
<blockquote class="codeline0"><p>public void testMakePaymentThrowsCreditCardException() throws Throwable</p></blockquote>
<blockquote class="codeline0"><p>{</p></blockquote>
<blockquote class="codeline1"><p>CreditCard creditCard = new CreditCard(&#8220;2298 9812 4566 1184&#8243;, 1000.0, 100.0);</p></blockquote>
<blockquote class="codeline1"><p>creditCard.makePayment(0.10000000149011612);</p></blockquote>
<blockquote class="codeline1"><p>creditCard.makePurchase(new Purchase(new Date(0L), 1.4178674221038818));</p></blockquote>
<blockquote class="codeline1"><p>creditCard.makePurchase(new Purchase(new Date(100L), 100.0));</p></blockquote>
<blockquote class="codeline1"><p>creditCard.makePurchase(new Purchase(new Date(1000L), 3.9999998989515E-5));</p></blockquote>
<blockquote class="codeline1"><p>creditCard.makePurchase(new Purchase(new Date(1L), 1.0E-5));</p></blockquote>
<blockquote class="codeline1"><p>creditCard.makePurchase(new Purchase(new Date(-1L), 3.6909053325653076));</p></blockquote>
<blockquote class="codeline1"><p>creditCard.makePayment(100.0);</p></blockquote>
<blockquote class="codeline1"><p>creditCard.makePayment(5.630099296569824);</p></blockquote>
<blockquote class="codeline1"><p>creditCard.makePayment(1.8264453411102295);</p></blockquote>
<blockquote class="codeline1"><p>creditCard.makePayment(97.55227811549801);</p></blockquote>
<blockquote class="blankcodeline"></blockquote>
<blockquote class="codeline1"><p>try</p></blockquote>
<blockquote class="codeline1"><p>{</p></blockquote>
<blockquote class="codeline2"><p>creditCard.makePayment(0.0010);</p></blockquote>
<blockquote class="codeline2"><p>fail(&#8220;Expected CreditCardException to be thrown&#8221;);</p></blockquote>
<blockquote class="codeline1"><p>}</p></blockquote>
<blockquote class="codeline1"><p>catch (CreditCardException ex)</p></blockquote>
<blockquote class="codeline1"><p>{</p></blockquote>
<blockquote class="codeline2"><p>assertEquals(&#8220;ex.getMessage()&#8221;,</p></blockquote>
<blockquote class="codeline5"><p>&#8220;Balance can&#8217;t go below minimum balance&#8221;,</p></blockquote>
<blockquote class="codeline5"><p>ex.getMessage());</p></blockquote>
<blockquote class="codeline2"><p>assertThrownBy(CreditCard.class, ex);</p></blockquote>
<blockquote class="codeline2"><p>assertEquals(&#8220;creditCard.getBalance()&#8221;,</p></blockquote>
<blockquote class="codeline5"><p>0.0,</p></blockquote>
<blockquote class="codeline5"><p>creditCard.getBalance(),</p></blockquote>
<blockquote class="codeline5"><p>1.0E-6);</p></blockquote>
<blockquote class="codeline1"><p>}</p></blockquote>
<blockquote class="codeline0"><p>}</p></blockquote>
</blockquote>
<p>This is somewhat predictable since <code>makePayment()</code> depends on <code>validateBalance()</code>.  This tests performs a series of purchase and payment transactions and checks that a payment creating a negative balance throws an exception.  We no longer want such transactions to throw an exception, so this, too, is an expected test failure.</p>
<p>The third test failure, however, is cause for concern.  This test of the constructor fails:</p>
<blockquote class="codeblock">
<blockquote class="codeline0"><p>public void testConstructorThrowsCreditCardException1() throws Throwable</p></blockquote>
<blockquote class="codeline0"><p>{</p></blockquote>
<blockquote class="codeline1"><p>try</p></blockquote>
<blockquote class="codeline1"><p>{</p></blockquote>
<blockquote class="codeline2"><p>new CreditCard(&#8220;2298 9812 4566 1184&#8243;, 15000.0, -1.0);</p></blockquote>
<blockquote class="codeline2"><p>fail(&#8220;Expected CreditCardException to be thrown&#8221;);</p></blockquote>
<blockquote class="codeline1"><p>}</p></blockquote>
<blockquote class="codeline1"><p>catch (CreditCardException ex)</p></blockquote>
<blockquote class="codeline1"><p>{</p></blockquote>
<blockquote class="codeline2"><p>assertEquals(&#8220;ex.getMessage()&#8221;,</p></blockquote>
<blockquote class="codeline5"><p>&#8220;Balance can&#8217;t go below minimum balance&#8221;,</p></blockquote>
<blockquote class="codeline5"><p>ex.getMessage()</p></blockquote>
<blockquote class="codeline2"><p>);</p></blockquote>
<blockquote class="codeline2"><p>assertThrownBy(CreditCard.class, ex);</p></blockquote>
<blockquote class="codeline1"><p>}</p></blockquote>
<blockquote class="codeline0"><p>}</p></blockquote>
</blockquote>
<p>This test checks that an exception is thrown when <em>creating</em> a <code>CreditCard</code> with a negative opening balance.  Our requirements change permits a balance to go negative when making a payment, but not when opening a new account.  However, we inadvertently changed the behavior of the constructor because the constructor, just like the <code>makePayment()</code> method, is dependent on <code>validateBalance()</code>!</p>
<p><strong>Real regressions are usually far more obscure</strong></p>
<p>This is a rather simplistic example of where a change in one part our code creates a regression somewhere else.  In our <code>CreditCard</code> class, it would be trivial for a developer to grasp the entire behavior of the class and foresee the impact to the behavior of the constructor.</p>
<p>In real world applications, however, large legacy code bases contain complex relationships spanning hundreds of classes.  It&#8217;s simply not possible for a developer to approach unfamiliar code and understand all of the interdependencies.  Characterization tests will highlight behavior changes introduced by the developer, and allow the developer to analyzes those changes for correctness.</p>
<p>So, what shall we do about the regression we introduced in <code>CreditCard</code>?  One solution is to create a new method for validating the opening balance.  Invoke that method in the constructor instead of <code>validateBalance()</code>:</p>
<blockquote class="codeblock">
<blockquote class="codeline0"><p>public CreditCard( String accountNumber, double creditLimit,</p></blockquote>
<blockquote class="codeline5"><p>double balanceTransfer )  throws CreditCardException</p></blockquote>
<blockquote class="codeline0"><p>{</p></blockquote>
<blockquote class="codeline1"><p>// &#8230; validate and assign account number and credit limit</p></blockquote>
<blockquote class="blankcodeline"></blockquote>
<blockquote class="codeline1"><p>// validate the balance</p></blockquote>
<blockquote class="codeline1"><p>//validateBalance( balanceTransfer );</p></blockquote>
<blockquote class="codeline1"><p>validateOpeningBalance(balanceTransfer);</p></blockquote>
<blockquote class="blankcodeline"></blockquote>
<blockquote class="codeline1"><p>this.balance = balanceTransfer;</p></blockquote>
<blockquote class="codeline0"><p>}</p></blockquote>
<blockquote class="blankcodeline"></blockquote>
<blockquote class="codeline0"><p>private void validateOpeningBalance( double balance )</p></blockquote>
<blockquote class="codeline5"><p>throws CreditCardException</p></blockquote>
<blockquote class="codeline0"><p>{</p></blockquote>
<blockquote class="codeline1"><p>if (balance &lt; 0.00)</p></blockquote>
<blockquote class="codeline1"><p>{</p></blockquote>
<blockquote class="codeline2"><p>throw new CreditCardException(&#8220;Opening balance can&#8217;t be negative&#8221;);</p></blockquote>
<blockquote class="codeline1"><p>}</p></blockquote>
<blockquote class="blankcodeline"></blockquote>
<blockquote class="codeline1"><p>if (balance &gt; creditLimit)</p></blockquote>
<blockquote class="codeline1"><p>{</p></blockquote>
<blockquote class="codeline2"><p>throw new CreditCardException(&#8220;Balance can&#8217;t exceed credit limit&#8221;);</p></blockquote>
<blockquote class="codeline1"><p>}</p></blockquote>
<blockquote class="codeline0"><p>}</p></blockquote>
</blockquote>
<p>When we run our characterization tests now, the constructor test passes and the only failing tests are the expected failures.</p>
<p><strong>Regenerate tests </strong><strong>and commit changes </strong></p>
<p>Now that we&#8217;re convinced we haven&#8217;t introduced any behavior changes into the code except for the changes we meant to implement, we can commit the updated <code>CreditCard</code> class to version control.</p>
<p>At the same time, we also  should regenerate our <code>CreditCard</code> characterization tests and commit the new tests to version control.  The update characterization tests will reflect the new behavior, and they&#8217;ll be available the next time a requirements change is needed.</p>
<p>In my next post, we&#8217;ll start to look at code coverage issues.  Sometimes, JUnit Factory is unable to figure out how to execute all paths of your code.  This could be due to the need for objects to exist in a complex state, the need to interact with an external resource such as a database, or simply due to dead code.  Look for this post in the next few weeks.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.gavaghan.org/blog/2008/01/24/junit-factory-part-2-finding-regressions/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
