A Generic ColdFusion Struct Visitor

Friday, July 10, 2009

Warning: No unit tests accompany this code.

Recently, I mentioned on Twitter that I wish CF had a regex version of StructFindValue, and this started a conversation between me, Ben Nadel, and Nathan Mische. Ben and Nathan, both of whom I swear are code factories, had code out there within hours to do what I was looking for. Bless their hearts. While I normally try to hold to the “Twitter is not a Chat” maxim, in this case, I ran with it and it yielded fruit.

During our conversation, what I came to realize was that I didn’t want just a reStructFindValue, what I wanted was a generic means of looping over structures and then “doing stuff” with each key that it encountered, as it walked recursively through a structure, no matter how deep/nested.

Some of you may recognize this as the Visitor pattern. I tweeted thusly:

@bennadel what ColdFusion really needs is a StructVisitor. With that, a man could do great things.

2:12 PM Jul 7th from TweetDeck in reply to bennadel

Inspired by our conversation, and by the quick contributions of these two fine gents, I decided to take a quick stab at a basic implementation of some code, which I’ll call “StructEach.cfc” (Nathan called his version StructEach, and I liked it). It should behave like so:

  • Take a Struct and a Visitor object as arguments to an “each()” function
  • Loop over all keys in the input Struct, recursing as it went
  • For all keys in the struct, pass the key and struct value into the “visit()” function of the Visitor object
  • The visit function of the Visitor must return a boolean indicating whether the code should continue looping over the struct
  • The visit function of the Visitor can do whatever the hell it wants to do.

Before showing the code for StructEach.cfc, let’s look at why you’d want to use something like this, and then how you would use it.

Why? What are the use cases for this?

  • Perhaps you’d like to take a structure and convert it to XML
  • Perhaps you’d like to do really weird or granular searching of the stuff inside the structure, even if the structure has arrays in it, queries, etc.
  • Perhaps you’d like to “dump” the values of a struct, but you want them in textareas b/c you need to see exactly what the strings look like, whitespace and all
  • Perhaps you’d like to do a deep comparison of two structures and report the differences in a way that’s easy to read

That last one, by the way, is my own personal use case for MXUnit.

What Kind of Structures should it take?

For me, I wanted this thing to be able to handle nastiness, not just simple structures. At the very least, it should take a struct that was this ugly:

startstruct

How do you use it?

First off, you’d write a CFC that implemented the “visit” function. Here’s a really simple visitor that just outputs anything passed into it, along with the full path to the value’s key in the structure

OutputVisitor.cfc


<cfcomponent hint="" output="false">
<cffunction name="visit" output="true" access="public" returntype="boolean" hint="">
<cfargument name="key" type="string" required="true"/>
<cfargument name="value" type="any" required="true"/>

<cfif isSimpleValue(value)>
<cfoutput>#key# = #value# <br></cfoutput>
<cfelse>
<cfdump var="#value#" label="#key#" expand="true">
</cfif>

<cfreturn true>
</cffunction>
</cfcomponent>


You’d then use this visitor like so:



<cfset outputVisitor = createObject("component","OutputVisitor")>
<cfset runner = createObject("component","StructEach")>
<cfset runner.each(struct,outputVisitor)>


In the case of the sample struct shown above, you’d get this output:



outputvisitor



Where it gets interesting



That’s not very useful, is it? But it demonstrates how you’d use it. What you can trust in your visitor is that for every key in the structure, your visit function will get called. That’s the sweetness of this approach… you’re free to do whatever you wish with the data coming in.



This gets interesting when you start to consider how this is all implemented: you’re passing an object into the StructEach… think about that. Objects can contain state. This means that you can “remember” things through the iterations of the struct, as your visit function is repeatedly hit.



Let’s look at an example that implements “regex find” functionality over a structure. My implementation will




  • provide an init() function for taking in searchString and scope arguments


  • return a struct containing keys “found”, “path”, and “value” as soon as it finds something that matches the regular expression, and it will return false so that the StructEach will stop searching. Consider this a findOneOf() >


  • return an array containing multiple structs if scope is set to “all”. Consider this a findAll() >



You’d call it like this:



<!--- a RegExFindVisitor that searches for 'even'; as soon as one is found, it'll stop searching --->
<cfset regexFindVisitor = createObject("component","RegExFindVisitor").init("even","one")>
<!--- a RegExFindVisitor that searches for 'even' or 'ix'; it will search every key in the struct --->
<cfset regexFindAllVisitor = createObject("component","RegExFindVisitor").init("even|ix","all")>

<cfset runner.each(struct,regexFindVisitor)>
<cfset runner.each(struct,regexFindAllVisitor)>

<cfdump var="#regexFindVisitor.getFound()#" label="regexFindVisitor">
<cfdump var="#regexFindAllVisitor.getFound()#" label="regexFindAllVisitor">


And here’s what you’d see:



regexfindvisitors



This is all made possible because the Visitor object can provide any other functions that it wants to… as long as it has a “visit()”, nothing else matters. In addition, the object can retain state. Thus, as visit is called, it can store stuff inside of itself for later computation and retrieval.



RegExFindVisitor.cfc



<cfcomponent hint="" output="false">	

<cffunction name="init" output="false" access="public" returntype="any" hint="">
<cfargument name="searchString" type="string" required="true"/>
<cfargument name="scope" type="string" required="false" default="one" hint="'one' or 'all'. If scope is 'all', returns an array; otherwise, returns a struct"/>
<cfset StructAppend(variables,arguments)>
<cfset variables.instance.found = []>
<cfreturn this>
</cffunction>

<cffunction name="visit" output="true" access="public" returntype="boolean" hint="">
<cfargument name="key" type="string" required="true"/>
<cfargument name="value" type="any" required="true"/>
<cfset var tmp = "">

<cfif isSimpleValue(value) && reFind(variables.searchString,value)>
<cfset tmp = {path=key,value=value,found="true"}>
<cfset ArrayAppend(variables.instance.found , tmp)>
<cfif variables.scope eq "one">
<cfset variables.instance.found = variables.instance.found[1]>
<cfreturn false>
</cfif>
</cfif>

<cfreturn true>
</cffunction>

<cffunction name="getFound" returntype="any">
<cfreturn variables.instance.found>
</cffunction>
</cfcomponent>


Note that our source structure contains keys that have arrays and queries in them, but we’re only concerned with the keys that have simple values (and any nested structs that have simple values). Consequently, I’ve wrapped the chunk of code that does the work in an “isSimpleValue()” check.



But imagine… what if you wanted to also search through the arrays or queries that are passed into this thing? You could do that by implementing some additional searches inside of here.



Here’s another one I whipped up: Imagine you had a big ugly struct with various and sundry data in it, and you wanted to get just the queries.



Here's how you'd call it:



<cfset queryHarvester = createObject("component","QueryHarvester")>
<cfset runner.each(struct,queryHarvester)>
<cfdump var="#queryHarvester.getQueries()#">


And here's its implementation:



QueryHarvester.cfc




<cfcomponent hint="" output="false">
<cfset queries = {}>
<cffunction name="visit" output="true" access="public" returntype="boolean" hint="">
<cfargument name="key" type="string" required="true"/>
<cfargument name="value" type="any" required="true"/>

<cfif isQuery(value)>
<cfset queries[key] = value>
</cfif>

<cfreturn true>
</cffunction>

<cffunction name="getQueries" returntype="struct">
<cfreturn queries>
</cffunction>

</cfcomponent>


And here’s what you’d get



queryharvestingvisitor



How does it work?



This is not sexy code, and it’s certainly not a) optimized or b) complete (for example, I’d like it to loop through arrays of structs as well). But it’s a start, and it’s very simple:



StructEach.cfc



<cfcomponent>
<cffunction name="each" output="true" access="public" returntype="any" hint="">
<cfargument name="struct" type="struct" required="true"/>
<cfargument name="visitor" type="any" required="true"/>
<cfargument name="path" type="string" required="false" default="" hint="don't touch this, suckers">
<cfscript>
var loopkey = "";
var thisPath = arguments.path;

for(loopkey in struct){
thisPath &= "[ ""#loopkey#"" ]";
if(isStruct(struct[loopkey])){
each(struct[loopkey],visitor,thisPath);
}else if(!visitor.visit(thisPath,struct[loopkey])){
return;
}
thisPath = arguments.path;
}
</cfscript>
</cffunction>
</cfcomponent>


Final Thoughts



This code, and even this approach, is purposely simple. There is nothing clever about it. I believe the value in an approach like this is in thinking about tasks in a more generic sense. Think of all the code out there in the world that does this: loops over keys in a structure recursively, and does stuff with the values it encounters. I imagine if you compared all of this code, it’d look remarkably similar in its recursion, but the details in the “else if” clause would be different.



Thus, in this approach, we’re extracting the common stuff into StructEach and providing hooks for implementations to get plugged into that “else if” part, in the form of a Visitor. Code gets much simpler and easier to understand; and code gets much easier to unit test because you’d be testing just your “visit” function, not the looping/recursion.



The downside is where you have recursion conditions that themselves require state external to the visitor; in this case, the StructEach approach wouldn’t work well, and there’s danger in trying to shoehorn an approach just to avoid a few lines of code. So, as with most things OO, you use this approach when it’s warranted, not just when it’s easy.



When you start thinking in more generic terms, you start to see opportunities for code reuse. For example, how much code is out there in the world, do you think, that loops over directories and "does stuff" to the directories and files in those directories? Imagine the dozen or so lines of boilerplate recursion code required to do the looping part, and the one line of code to delete the file. Multiply that by a gazillion. How much code in your own codebase does this looping, with the only difference being "what I do when I hit each file"?



If you think generically, you see there's a better way to do this: you create a DirectoryWalker type of deal that handles the looping, and then you provide a FileVisitor type of implementation that acts on each file it hits. So if you have code that deletes certain files in directories, or "touches" them to make them current, or archives certain files, or makes jpg thumbnails of pdfs that don’t already have thumbnails... you can separate that out into really small, easy-to-test Visitor implementations and just use DirectoryWalker to handle the boilerplate.



Consider the unit test for that last example, the one that generates thumbs. If you were to write a “generateThumbsForDirectory"()” function, that’s hard to test! Seriously… think about what would be required in a unit test to test it. You’re testing two things: 1) your recursion and 2) your thumbnail generation. But the recursion is boilerplate, and testing boilerplate sucks. What you really want to test is your thumb generation. So if you extract that out into a simple function that takes an existing File path, your job is simple: look for an existing thumb for that file, and if one doesn’t exist, create it. That’s a really small unit test comprising two functions: makeThumbnail_should_GenerateThumbnails_When_ThumbnailDoesNotExist() and makethumbnail_shouldNot_GenerateThumbnails_When_ThumbnailDoesExist(). You could write that in maybe 15 lines of code. You trust that the StructEach works because it’s been tested separately, and you can now trust your code because you’ve proven, with your tests, that your code works.



Fewer lines of code + easier-to-test functions = fewer bugs.

"Look, Ma. No Password!" - Secure Hashing in ColdFusion

Wednesday, June 24, 2009

I soaked up tons of great stuff at Frank Kim's recent Sansfire 2009 training
in Baltimore. As a matter of fact, it was the single best training event I have ever attended and I highly recommend it. After the module on
Java Cryptography Architecture (JCA) -- which was at the end of Day 3 and though my brain was fried -- I realized I had a big gap in my own knowledge in something that should be a fundamental skill for programmers today. Broadly and simply stated, that skill is to be able to protect data in your application. Now, if you're anything like me and you start hearing some terms like symmetric and asymmetric ciphers, MD5, SHA-1/2/3 message digest, cryptographically secure random number generation, etc., you might be inclined back away slowly (or quickly) and leave all that to someone else. Well, I'm here to say that implementing strong cryptography in ColdFusion is a lot easier than I expected. And knowing how do this and why will give you valuable skills that can only make your software safer and your programming stronger.

Let's start with a common web application task - storing credentials in a database. One appealing NIST recommendation is that you should not store the passwords at all. Rather, you should store a secure hash of the password instead. When authentication needs to take place, instead of reading the password from a database and comparing that to the password entered by the user, you retrieve the password hash from the database, hash the password entered in the form, then compare the hashes. If you understand why we do this and just want to see how, skip down to Secure Hashing. If you're mumbling to yourself "That sounds like a fucking waste of time," read the next two paragraphs.

The driver here is that passwords are secret and nobody should have access to a user's password other than the user. System administrators and support staff should have the ability to reset passwords but not to read them. You might ask, "But my sites don't contain any sensitive information, why should I care?". Though true, how much do you want to bet that users registered on your site are using the same set of credentials to log into other sites, even banks?
Does this possibly make your site a target for harvesting? Could this challenge customers' trust in you over time? Play that tape couple of times ...


The good news is that password hashing is so simple I can see no real reason not to do it. I'm not claiming to make your site secure; I'm simply saying that if you securely store password hashes instead of passwords, you can mitigate a number of potential attacks; for example, the Rainbow Table attack [7]. Note that password hashing differs from storing passwords encrypted. Why is this important? Because anything encrypted needs to be unencrypted to be read. To unencrypt, there must be a key and frequently it will be one key that can be used to read all passwords. We don't ever want passwords to be read by anyone. Period. So, we want to create a strong, secure, one-way hash.

Secure Hashing

The technical term is Cryptographic Hash Function, and there are several algorithmic variations : most notably, Message Digest (MD5), Secure Hash Algorithm (SHA), and others. Essentially, a hash function generates a unique and fixed-sized representation of some data; aka a Fingerprint. A correct hash will always produce the same result for a given input; e.g., f(x)=y. For example, the string foo, when hashed with MD5 should always produce ACBD18DB4CC2F85CEDEF654FCCC4A4D8 in ColdFusion. If another algorithm is used, the output will be different than this, yet it still should always produce
consistent output.


Now, what if there are users with the same passwords? Won't the hashes be the same in the database? Right you are. What a Rainbow Table
[7] is, is essentially a large list of passwords that have been hashed using a number of algorithms. The attacker compares the hashes in your database with the ones in his Rainbow Table and then finds the matching password. The solution to this is to create unique hashes using salt and to repeatedly hash the hash. Salting is the process of inserting random data into the original data. Then, we repeat the hashing about 1000 times. This creates a unique and, if done correctly, a more secure hash.

Let's start with some usage. We use an example utility component ,Crypto , to perform the hashing. Full source code can be found here.


When run, this generates a password hash that looks something like 72C2CA24AD19EF7A8A9FC89184BA17BFA2D65CF3BE4FD2F0BBF3B460BD123550BC2D6BAB3AADF76EEAA4D8B5F6641A73365B21D17158779468049CACC32F0F2E and a base64 secure random salt value of 4OP5GFmp/z0YYgUUlprVoig4pkGWhNGgMl37Tn4sLPw=. When a user creates or changes their password, store only the hash and salt:


Now, to authenticate a user, you do something like this:


We're simply comparing the hashed value of the password entered by the user to the hashed value stored in the database. We do this by first retrieving the salt from the database and using that to generate the hashedFormPassword value. If you've read this far, I'm sure you want to look under the hood:


It doesn't get much easier for a complex topic, does it? computeHash() accepts 4 arguments: password, salt, iterations, and algorithm. The required ones are password and salt - salt should be a secure random base64 string. iterations is the number of times the hash will be rehashed. PKCS 5 recommends doing this "a modest" 1000 times[9]. This would be a performance concern if this operation were done frequently, but since it is done only when a user logs in or creates an account, it's considered acceptable. The last parameter, algorithm, is a specific message digest algorithm. It's specified here are SHA512, which is the strongest FIPS-140 approved secure hashing algorithm. Adobe has some very good documentation on available security providers and other related security best practices - this is required reading for ColdFusion developers! [5]

Salt Generation:


The core concept behind salt generation is to create a random set of bytes of N length. Since ColdFusion sits on Java, I chose the java.security.SecureRandom class.



Summary

Using the example Crypto component or your own variation will give you a viable option to storing passwords directly in the database and contribute to better security in your application. However, do not take my word alone for this. Please do some thorough research and learn for yourself. When it comes to protecting your customer's data and privacy (and your job) make sure you know what you are doing and why.

Test and be Happy!

References (Many are PDFs):
[1] OWASP Java Hashing - http://www.owasp.org/index.php/Hashing_Java
[2] NIST Secure Hash Standard - http://csrc.nist.gov/publications/fips/fips180-3/fips180-3_final.pdf
[3] FIPS-140-2 Draft (June,18,2009) - http://csrc.nist.gov/publications/fips/fips140-2/fips1402annexa.pdf

[4] Guide to Enterprise Password Management (Draft) - http://csrc.nist.gov/publications/drafts/800-118/draft-sp800-118.pdf
[5] ColdFusion 8 developer security guidelines - http://www.adobe.com/devnet/coldfusion/articles/dev_security/coldfusion_security_cf8.pdf
[6] Java Cryptography Architecture (JCA) - http://java.sun.com/javase/6/docs/technotes/guides/security/crypto/CryptoSpec.html
[7] Rainbow table - http://en.wikipedia.org/wiki/Rainbow_table
[8] NIST Advanced Encryption Standard Algorithm Validation List - http://csrc.nist.gov/groups/STM/cavp/documents/aes/aesval.html
[9] PKCS #5 v2.1: Password-Based Cryptography Standard - ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-5v2/pkcs5v2_1.pdf

IntelliJ IDEA Plugin for CFML

Saturday, June 13, 2009

As ColdFusion developers, unlike many other languages, the one thing we simply don't have is code insight or object & method resolution for 3rd party Java or ColdFusion products. I understand that this is difficult to achieve for dynamic languages, but, just because it's "hard" is not an excuse, imo.

I'm a big fan of IntelliJ IDEA and it's the best tool for Java and Groovy development I've used - these guys know what an IDE should do and they also support open source projects. IDEA also gives you the ability to create Flex and Air projects. Recently, developer Valeria Nikolaenko, has built a CFML plugin for IDEA and has consistently been releasing updates. The most recent one fits especially nicely with any project that uses ColdFusion and Java together. Specifically, if you use Mark Mandel's JavaLoader you'll find this feature of particular interest. Basically, it allows you to get Java method resolution inside of CFML for classes loaded with JavaLoader. Check it out:




So, what we've done here is create a JavaLoader instance using createObject(...) and then we create a Java class, esapi, in the editor. When you type esapi. then hit Ctrl+Space, Voila!, all the methods and their signatures for the ESAPI class are presented in the editor. You do have to perform a few project set up tasks in order to make this happen in IDEA, assuming you've installed the CFML plugin already:
  1. Add your 3rd party jars to your project's class path
  2. Add the ColdFusion facet to your project and tell it where your webroot and subdirectory are located
  3. In your source code, tell the CFML plugin about your JavaLoader variable and jar locations:
    <!---@javaloader name="loader" jarPath="/home/webapps/cfesapi/lib/" --->
If you've ever done Java development without code insight, you know what the typical process is - you need to constantly go back and forth between the Javadoc APIs, copy and paste, or you dump out the object's metadata and try to figure out how to call it. The configuration above steps seem like minimal effort compared to the typical manual process required to work with Java inside of ColdFusion. It's not the end-all-be-all solution, but it's big step in the right direction. Ideally, if all the configuration could be done at the project level, that would even be better.

Now, if we could just have an MXUnit plugin for IDEA, it could be a seriously dangerous all-around IDE for $249 US.

Continuous Integration with Hudson, CF, and MXUnit: Setting up Notifications

Thursday, June 4, 2009

In previous entries, I wrote about configuring a project in Hudson and setting up your project to run your MXUnit tests and report results. Before we talk about setting up email and IM communication, let’s briefly look at what you should now have, in pictures, if you’ve set up a project. I’m using MXUnit as the example project here.

First, an entry in the project list, indicating the build’s health

hudson_mxunitbuildhealth

Next, when you drill into the project, you’ll see your recent build results on the left, along with your test trends on the right

mxunit_projectstatus

On the left side, with your list of previous builds, you can click the “trends” link and see a time trend graph

hudson_timetrend

You can click on a link for your last build and see more details about it. When you click on the Test Results link, you get this view

mxunit_passedbuild

From there, you can drill down into the reports for more information, should you need it

If a build fails, it’ll show you something like this:

hudsonbuildfailure

Communicating This Information

All of this information is lovely; however, we’re not interested in monitoring the Hudson interface every time a build runs. Instead, we want to get notified when things change. That’s it: when build status changes. For me, continuous integration is as much about communicating results as it is about providing an easy, scheduled mechanism for running your tests (we don’t care about compiling and linking in CF applications, so that core benefit of CI doesn’t apply to us either).

Ideally, only interested parties would be notified on a change in build status. For example, let’s say a build runs at 8:00 AM, and all tests pass. It runs again at 8:15 AM, and tests fail. What I want to happen is:

  1. Hudson looks at source control for the users who have committed code since the last build
  2. Hudson notifies *just* those people that the build is now failing.
  3. Hudson does this either via email, instant message (SMS), or both.

Fortunately, this is all possible. Let’s set it up.

Configuring Email Settings

From the main Hudson screen, type “configure” in the search box

Scroll down to the bottom and find the E-mail notification section.

I’m using gmail in this case, so I plugged in my gmail credentials, using “smtp.gmail.com” as the server. I’m keeping “default email suffix” blank since this can’t be computed (this would be more for corporate email accounts where you can trust that the email would end up as “firstname” + “lastname” + default email suffix, for example).

In the Advanced settings, I checked “use smtp authentication”, entered my email address into the username field, added my password, checked “use ssl”, and specified the port as 465

 

Configuring SMS (Jabber) via GTalk

From the “manage Hudson” screen, click on Manage Plugins

go to “Available Plugins”, and find the “Hudson Jabber notifier plugin”. Click things and install it. Restart if necessary.

Now, back in your Manage Hudson screen, you’ll have a new section, right above the Email section, for Jabber.

I entered my gmail address and password, and “talk.google.com” as the server. That’s it!

For the visually inclined, here’s what all of this looks like:

hudsonnotificationsetup

Noise Control

At the project level, you can also configure how noisy you want this communication to be. Here’s what that looks like:

hudson_notificationconfig

From that image, you’ll see that I can configure when I want to be notified… every build, just on change, etc. Thus, to substantially reduce the noise from your scheduled builds, go into the project and configure it to only notify via IM on status change. This, in my humble opinion, is gold.

Configuring Users

Now that the communication mechanisms are set up, we have to associate email addresses with the subversion users. Quite possibly there’s an easier way to do this via some batch process, but as I’m just getting started with my Hudson investigation, I haven’t looked into it. So please don’t take this as “the only way” or “best practice”, because I do not know that to be true.

For my setup for MXUnit, I linked it to SVN and when it updated and there were changes, it created new a new user for any user that was associated with a change. So, I committed some code to MXUnit, ran a Hudson build, and Hudson added me as a user, silently.

To give the “marc.esher” user notification details:

  1. from the main Hudson screen I clicked on “people” then on “marc.esher”. (You can also get here if you know the username you want to configure by typing that username in the "Search” box at the top of the screen)
  2. click Configure
  3. enter my email address
  4. since I installed the Jabber plugin, it also has a space for jabber credentials. I entered my gmail address again.

So what’s all this get me?

After this configuration was finished, here’s what I get:

Emails on build failure that look like this:

hudsonbuildfailure_email

GTalk notifications on build failure that look like this:

hudsonbuildfailure_gtalk

And corresponding messages for when things go back to normal.

Importantly, what I don’t get: noise. I don’t get notified on every build via email. I don’t have to constantly go to a website to check the build status. I get notifications when I care about them: when things go bad, and when things go from bad back to good.

Summary

Continuous Integration is about communication. It’s about noise control. And so far I’m discovering that Hudson is performing admirably. You can configure different methods of communication, all hooked into source control, with different “strategies” (on every build, on every change, etc). I appreciate this level of configurability. In addition, I was able to get all of this going without reading a single page of documentation. I think that speaks to Hudson’s ease of use.

7 Totally Stupid Useless Ways to Invoke ColdFusion Components

Sunday, May 31, 2009







Warning:
The content contained herein contains utterly useless, potentially offensive, and very juvenile language. This is not suited for just about everyone.


There are many levels of stupidity - I believe in, and have worked very hard at, exploring many such levels in theory and in practice. Though some individuals are gifted with natural stupidity, I believe to be a true and utter mooncalf demands rigorous discipline and hours of practice. To support this process, you can explore other distinct facets of stupidity ranging from the simple-moron to the mullet-sporting-crank-snorting-utter-fucking-bonehead. To be more than a mere journeyman dolt, however, demands discipline and, above all, dedication.




In this small and inane piece, I will attempt to demonstrate how a programmer can proceed from a state of being simply moronic to a high level random-self-inflicted-headwound-fuckhead. The key lies is in using what little brain power you might have towards something of little or no utility whatsoever. Remember this and I truly believe you will go nowhere but backwards.




7 Totally Stupid Useless Ways to Invoke ColdFusion Components


Full stupid source code available here
(click the Download button for a zip/tar file)



This is the stupid component under test we will invoke in 7 truly dumb ass ways.




All these examples are written as MXUnit tests, which, by doing so, has arguably decreased my own stupidity rating. Note also that these are written in <cfscript>. This reduces the number of keystrokes required in order to write useless piss-ant code.




Here's the setUp():



#7 (Simply Moronic)



#6 (Approaching Idiocy)



#5 (The Java Loser)



#4 (Douche Bag)


#3 (Turd Mongrol)



#2 (Dumbass Pissant)



#1 (Asshat Monkey Shit Hurler)



Stupid source code here




Feel free to post stupid code or links to such. Using Gists might be cool, though they're not stupid.




CI with Hudson, CF, and MXUnit: Configuring ANT and Running Tests

Friday, May 29, 2009

If you’re already running your MXUnit tests with ANT, then this should go quickly. If not, then you’ll need to read this first. Create your ANT build file (build.xml), create your “runTests” target (or whatever you want to call it), and get your test runs working from within Eclipse or at the command line. Only after you get those working should you try integrating with Hudson… one thing at a time.

Configuring ANT within Hudson

Hudson needs to know where your ANT install lives. If you haven’t downloaded ANT, do so now, unzip it, and put it somewhere. Then, copy the path to that location.

From your main Hudson screen, click on “Manage Hudson”, then “Configure System”. More quickly, type “configure” into the search box and it’ll take you to the same place. Go down to the “ANT” section, click “Add”, and paste that path to your ANT install. Note, this is NOT the “bin” directory… just the ANT root. Give it a name, like “ANT 1.7” or whatever. Click Save

Hudson will not treat this ANT location as the default location. You must (at least, I did) have to explicitly choose this ANT instance for every project setup. Just so you know. This tripped me up at first.

Sample ANT build file



<?xml version="1.0" encoding="ISO-8859-1"?>

<project name="Sample" basedir="." default="main">

<target name="init">

<property name="testroot" location="../tests/framework" />
<property name="componentPath" value="mxunit.tests.framework" />
<property name="server" value="localhost" />
<property name="port" value="80" />

<!-- wherever the mxunit-ant.jar lives -->
<property name="mxunitant" location="../ant" />
<property name="mxunitjar" location="${mxunitant}/lib/mxunit-ant.jar" />
<property name="mxunitxsl" location="${mxunitant}/xsl" />

<!-- this is where the xml and html will live -->
<mkdir dir="testresults" />
</target>

<target name="runtests" description="Make output directories and run the MXUnit task" depends="init">
<taskdef name="mxunittask" classname="org.mxunit.ant.MXUnitAntTask" classpath="${mxunitjar}" />
<mxunittask server="${server}" port="${port}" outputdir="testresults" verbose="true">
<directory path="${testroot}" recurse="false" packageName="${componentPath}" componentPath="${componentPath}" />
</mxunittask>

<mkdir dir="junithtml" />
<junitreport todir="junithtml">
<fileset dir="testresults">
<include name="*.xml" />
</fileset>
<report format="frames" todir="junithtml" styledir="${mxunitxsl}" />
</junitreport>
</target>


</project>


Configuring your project’s test runner step



Navigate to your project, then click “Configure”. More quickly, you can search for your project by name, then search for “configure”, and you’ll get to the same screen.



Find the "Build" section. click "Add build step". Select "Invoke ANT". Select the ANT instance from the dropdown list of installed ANTs. In the "target" field, type the name of the target in your ANT build file that you use to run tests. For example, "runTests"



This might be all you need. so you could save this and try to do a build now, and see what happens.



Test Runner Step Configuration, Part 2: Properties



Now’s a good time to talk about the weirdo nature of ColdFusion projects with respect to CI. Remember, you checked out your project from Subversion into Hudson’s workspace, but that’s not the code you care about… your code already lives on a DEV server and is updated by some other means. However, there is one file that gets checked out that you do care about: Your ANT build file.



When Hudson runs your ANT file, it’ll be running the one from its workspace. And then that build file will be executing its tests against the components you specify on your DEV server. Got it? Good. Confused? I know.



It’s possible that your build file’s runTests target might need some properties that are possibly set in a properties file that you don’t keep in SVN or which otherwise you need to override. For example, for MXUnit itself, our build file looks at a file named “unames.properties” to get some configuration information such as server name, port, usernames/passwords, webroot location, and some other things. This is NOT kept in SVN b/c it’s unique for each MXUnit contributor. When MXUnit’s runTests is run, it tries to read that properties file and then set the server, port, and webroot properties. But since that file isn’t checked out from SVN, it’s not visible in Hudson’s workspace and thus those properties never get set. It’s super easy to get around this though!



In your ANT step’s “Advanced” tab, you’ll see a “properties” box. In here, you can type in any properties in name=value format, linebreak-delimited, and poof, properties problem solved. For example, here’s what I put into the properties box for the MXUnit job:



server=localhost

port=80


webroot=c:/inetpub/wwwroot



Configuring your project’s JUnit XML Output



In that sample ANT build file above, you saw how easy it was for MXUnit to spit out JUnit-compliant XML. Basically, no matter where your tests actually run (http://blah/whatever/HttpAntRunner.cfc), your JUnit XML files will go in a directory relative to the build file that is running. Got that? That means that, as discussed above, your JUnit xml files will go in your Hudson workspace somewhere. This is perfect, because that’s where Hudson wants them to be.



For example, with the MXUnit build, the build file is at mxunit/build.xml. It specifies a location for the JUnit xml output as something that evaluates to tests/testresults/tmp/. So in the Hudson configuration for the MXUnit job, I specify the JUnit XML location as:



tests/testresults/tmp/*.xml



That’s it. So wherever your xml files go relative to your workspace root, simply go to the “Post Build Action” section of your job configuration, check the “Publish JUnit XML” checkbox, and enter in the path to your xml files, with *.xml, as I did above. Click save



Re-saving ant.bat



After I got the MXUnit project all set up, I ran the build; it executed the tests; Hudson read the JUnit XML (all tests passed). And then…. Failed. Failed?! WTF? WTF was failing? The Hudson console output (thank you, Hudson!) read: “The system cannot find the batch label specified”.



This wasn’t a Hudson problem. It wasn’t an MXUnit problem. Turns out, it was the ant.bat file giving me grief. That’s right… the ant.bat that ships with the eclipse ANT install. Perhaps had I been using a “proper” install, this wouldn’t have been the case. Nonetheless, I wasn’t. So, how to fix it? Simple



Open up ant.bat in Textpad. Notice that it’s in Unix format. Change the format to “PC”. Click Save.



Rerun the Hudson build. Oh Joy. Oh Rapture. A fully functioning test run with test results. Let the CI begin.



What’s Next?



Next up, configuring notifications.

Continuous Integration with ColdFusion, Hudson, and MXUnit: Getting Started

Thursday, May 28, 2009

This series will demonstrate how to set up a continuous integration (CI) environment for ColdFusion projects using Hudson CI and MXUnit. We’ll cover Hudson setup, MXUnit test runs and JUnit XML output, and a few notification mechanisms (email, IM).

Installing Hudson

This will cover the super-duper simple way to run Hudson, which you'd do for testing this stuff out. DO NOT RUN YOUR REAL CONTINUOUS INTEGRATION ENVIRONMENT IN THIS MANNER. If you already have Tomcat set up, then you know how to install war files so follow that procedure instead (i.e. drop the war where you put your war files, or use the admin to deploy the war. It's that simple)

  1. Download the Hudson war file and put it somewhere
  2. Open a command line and navigate to the war file location
  3. type “java –jar hudson.war”
  4. This will launch Hudson. You can navigate to http://localhost:8080 and from there, you’re ready to start

Pulling your project from Subversion (SVN)

  1. Click "create a new job"
  2. Give your job a name, and then select Freestyle Software Project
  3. Under Source Code Management, select SVN, and then plug in your project’s SVN location, eg http://svn.myproject/whatever/trunk
  4. From here, you can click “Save” and then perform a build by clicking “Build”. This will check out your code into the Hudson workspace for your project

But this code isn’t where I need the code to be! Good point. As I get started with this, I’m going to just keep doing it this way until I figure out a better approach. At least where I work, we have DEV servers where code is automatically updated from SVN anyways, and our unit tests all run against the DEV server. I’m not setting up a CI environment in order to set up yet another server; instead, I’m setting it up so that I can get better reporting and notifications while still executing the same tests against the same code.

Hudson does allow you to choose a “custom workspace”, but I’m not going to get into that right here as I’m not sure yet whether it’s relevant for ColdFusion projects. I can see people being tempted to set the Hudson workspace to an existing project location on a Dev server, for example. Time will tell if this proves to be a good idea

What’s Next?

See how easy that was? Next up, configuring ANT, running your tests, and recording results