As part of my work at Witsbits during the summer, I wrote some C code for processing firewall configuration requests. The set up was straightforward; an URI based request sent to a server was handled by a system written purely in C which forwarded the requests to an appropriate handler function. Legal rules where accepted, translated into netfilter rules and stored in an SQL data base.
The customer would be able to add (I) and delete (II) firewall rules; the add (I) rules had several possible call structures which mixed groups, single ip's and other firewalls. Delete (II) calls could remove rules (if present). Since the add (I) calls had several different possible (legal) combinations, the code naturally became case-testing with a lot of "if(...)".. "switch(..)" etc. As a Haskell:er I wanted several ways of reassuring myself that the code I wrote behaved itself nicely and didn't mess things up. With this in mind, I started early by writing the foundation of a haskell program in parallel to the code I was writing in C. This proved to be quite helpful since it forced me to think extra carefully about what calls where legal and how I would check that a call was legal in an efficient way.
As the project progressed, I soon had a full fledged working haskell program using QuickCheck, Network libraries (HTTP,TCP,URI) and Codec.Binary.Base64.String with yet other minor auxiliary libraries. The haskell program identified itself to the firewall server, and generated valid and invalid packets on the fly, sending them across the network and recording the replies. The server, which handled the requests and replied with 200, 201 or 404 if something went wrong, also output a lot of debug info.
So, the haskell program was running controlled randomized test cases against a server! And voila, I was swatting bugs in my C code with minimal effort.
The greatest effort was put into learning to use the Network libraries properly; but besides that I must say this worked as a charm. Next time I'm faced with writing C code for a web based system, I'll start equally early on the Haskell program that will be testing it.
QuickCheck just made it quicker to find the bugs.