StringBuilder and my Biggest Pet Peeve
What You Should Know About Strings
In both Java and .NET (and other languages) String objects are immutable. They don’t change. Period. If you “change” a String, it creates a new String. That includes String concatenation using a +
// One string created "foo" String foo = "foo"; // foo exists, "bar" is created and the combination of foo and "bar" is a third string String bar = foo + " bar";
Ok, if you don’t know this, fine. But if you don’t know this, why would you EVER use a StringBuilder?
Why Does StringBuilder Exist?
We know that Strings are immutable. If you need to do a bunch of string modification, concatenation, replacement – you will create a bunch of strings. Ok, great…why do I care? We care because we are told that creating a lot of Objects (and then later having to Garbage Collect them) is inefficient. To start with, I will guarantee right now that concatenating strings WILL NOT be the thing that prevents your application from performing. Guaranteed. Period.
Ok fine, it’s not going to be a problem. But you want to be a responsible coder and not do things that are intentionally inefficient if you can help it.
So you use a StringBuilder. StringBuilder is implemented internally as an array of characters. The code manages the allocation and copying of data to new arrays if the buffer gets filled. It sometimes over allocates the new buffer so that it has to perform allocations less often. You sacrifice a bit of memory overhead to avoid some Object creation and Garbage Collection later.
My Biggest Pet Peeve
Your use of StringBuilder is a premature optimization but probably a forgivable one.
So, WHY, OH WHY do you do this:
// One string created "foo" StringBuilder sb = new StringBuilder(); sb.append("Foo: " + fooValue + " \n"); sb.append("Bar: " + barValue + "\n");
It makes me have violent thoughts. Please stop.
Update:
For some of the reasons why Strings are immutable, see this post on immutability and its positive qualities.
MSBuild Task for PartCover
<![Rant[
I continue to lament the dearth of option for Test Coverage in the .NET world.
In the Java world you have open source tools like Emma and Cobertura that are widely used and supported (and many more) as well as proprietary tools like Clover available.
.NET we have an open source NCover SF that requires you to do odd code instrumentation and is essentially dead it seams, another NCover which is proprietary and costs money and PartCover which is open source, but doesn't seem real active.
Don't get me wrong, NCover.org is a good option if you are willing to spend the money for it. But with a team of 30+ and a CI server, I'm not sure if I want to drop $10k on it. (NCover up until version 1.5.8 was Free Software (GPL) before it was closed. Who has the source and why haven't you forked it yet?)
]]>
If you’re not willing to pay that basically leaves PartCover. But of course you want to integrate your code coverage with your automated build. There was no support for MSBuild out of the box, so I decided to build it.
Creating an MSBuild Task
I need to do 2 things to run PartCover:
- Register the native PartCover.CorDriver.dll
- Execute the PartCover.exe with the proper options
Register Native DLL
To see the details on how to register a native DLL using .NET code so my earlier post Register and Unregister COM DLL from .NET Code.
Execute PartCover
The MSBuild framework provides a ToolTask base class whose whole purpose is for executing external command line tools. I used this as the base of the task.
1. ToolName
First you override the ToolName property to return the name of the EXE to run. Nothing special here, it’s just the executable name.
protected override string ToolName { get { return "PartCover.exe"; } }
2. Properties
Next to start build the task you go about defining all of the settings that a user will need to set to execute the task. You then create those as Properties on the class and they will be set by MSBuild. Start with the simple things that someone will need to pass to get the tool to execute properly. You can build from there for other properties. If possible give the properties sane defaults so that people don’t have to override them in their build file.
// ... /// <summary> /// The application to execute to get the coverage results. /// Generally this will be your unit testing exe. /// </summary> public string Target { get { return _target; } set { _target = value; } } /// <summary> /// The arguments to pass to the <see cref="Target"/> executable /// </summary> public string TargetArgs { get { return _targetArgs; } set { _targetArgs = value; } } public string WorkingDirectory { get { return _workingDirectory; } set { _workingDirectory = value; } } // ...
3. Command Arguments
Then you need to override string GenerateCommandLineCommands() method. The whole purpose of this method is to construct any command line parameters that need to be passed to the ToolName command using the Properties defined in the task.
protected override string GenerateCommandLineCommands() { StringBuilder builder = new StringBuilder(); AppendIfPresent(builder, "--target", Target); AppendIfPresent(builder, "--target-work-dir", WorkingDirectory); AppendIfPresent(builder, "--target-args", QuoteIfNeeded(TargetArgs)); AppendIfPresent(builder, "--output", Output); AppendMultipleItemsTo(builder, "--include", Include); AppendMultipleItemsTo(builder, "--exclude", Exclude); Log.LogCommandLine(builder.ToString()); return builder.ToString(); }
5. Execute
Finally, if you have anything special to do, you can override the Execute(). In this case, I wanted to handle the registering and de-registering of the Core.dll. Make sure that you call the base.Execute() method so that the TaskTarget can do the work that it needs to do.
public override bool Execute() { string corDriverPath = Path.Combine(ToolPath, CorDriverName); Log.LogMessage("CoreDriver: {0}", corDriverPath); using (Registrar registrar = new Registrar(corDriverPath)) { registrar.RegisterComDLL(); return base.Execute(); } }
To see the whole thing, download the files at the bottom of this post.
How to Use PartCover with MSBuild
Now that you have a Custom task you need to create a Target in your MSBuild file to execute the task.
<!-- Register the PartCover.MSBuild.dll so the PartCover task is available --> <UsingTask TaskName="PartCover.MSBuild.PartCover" AssemblyFile="$(LibDirectory)/PartCover/PartCover.MSBuild.dll" /> <!-- Setup a property so you can use it in your task --> <ItemGroup> <TestAssemblies Include="src/ZorchedProj/bin/$(Configuration)/ZorchedProj.Tests.dll" /> </ItemGroup> <!-- Create a Target to call the PartCover task --> <Target Name="Test" DependsOnTargets="CoreBuild"> <!-- Configure the task to execute --> <PartCover ToolPath="$(LibDirectory)/PartCover" Target="$(LibDirectory)NUnitnunit-console.exe" TargetArgs="%(TestAssemblies.FullPath) /xml=%(TestAssemblies.Filename).xml /labels /nologo /noshadow" WorkingDirectory="$(MSBuildProjectDirectory)" Output="partcover.xml" Include="[Zorched.*]*" Exclude="[*.Test]*" /> </Target>
Download the code:
PartCover MSbuild.zip
Good luck and I hope someone else finds this useful.
Tracking Project Metrics
How do you track the health of your software projects? Ideally you could come up with few, easy to collect metrics and have your Continuous Integration system generate the information and maybe even graph it over time. What we track is going to be based on a set of beliefs and assumptions, so I think we should make that clear.
My Software Metrics Beliefs and Assumptions
- The simplest code that solves the problem is the best. Simple does not mean rote or repetitive. It means well designed, well abstracted, well factored.
- Unit Testing improves the quality of code.
- Overly complex code, code that is not well factored, “big” code is hard to unit test.
- The metrics need to be easy to interpret and easy to gather or I won’t do it.
Based on those beliefs and assumptions we have defined the kinds of things we care about. We want simple, small classes and methods. We want classes that fit the Single Responsibility Principle. We want unit test coverage. And we want to know when we deviate from those things.
Inevitably this won’t tell you the whole picture of a project. Some deviation is inevitable as well (we’re not perfect). But this is giving us a picture into a project that would let us look at “hot spots” and determine if they are things we want to deal with. It will never tell you if the system does what a user really wants. It will never fully tell you if a project will be successful.
The Metrics I Came Up With
- Unit Test Coverage – How many code paths are being exercised in our tests.
- Cyclomatic Complexity – Number of methods over 10, 20, 40
- Lines of Code – General size information
- Methods over a certain size – Number of methods over 15, 30, 45 lines
- Classes over a certain size – Number of classes over 150, 300, 600 lines
- Afferent/Efferent Coupling – Dead code and code that does too much
Tools
I’m currently thinking mostly about .NET projects because at work we do a lot of small to mid-size projects using .NET. Many of the tools already exist and are Open Source in the Java world and many Java Continuous Integration servers support calculating some of those metrics for you already. So you’re probably in pretty good shape if you’re doing Java development.
FxCop
Out-of-the-box FxCop doesn’t really give you many of these things. But it does provide you a way that you can fairly easily your own rules using their API.
For Example to calculate Cyclomatic Complexity you can implement a class that extends BaseIntrospectionRule and overrides the VistBranch and VisitSwitchInstruction.
public override void VisitBranch(Branch branch) { if (branch.Condition != null) { Level ++; } base.VisitBranch(branch); } public override void VisitSwitchInstruction(SwitchInstruction switchInstruction) { Level += switchInstruction.Targets.Count; base.VisitSwitchInstruction(switchInstruction); }
Coverage
PartCover is an open source code coverage tool for .NET. It does the job but does not have what I’d call any “wow” factor.
NCover is a proprietary coverage tool. High on wow factor, but expensive. NCover was once free and open source and gained a good following, but they switched and closed it and made the decision to charge $150 – $300 a license for it depending on the version.
(I lament the state of the .NET ecosystem with regard to tooling. Either an OK open source version or an expensive commercial version is not a real choice. There are so many good options in the Unit Testing space, but not in the coverage space.)
NDepend Mini-Review
Disclosure: I received a free copy of NDepend from the creator. I would like to think that didn’t influence this at all, but wanted to make that known.
One of the tools that I’ve been looking at for .NET projects is NDepend. It seems to cover all of the cases that I mentioned above except for the Code Coverage case (although it integrates with NCover, but I haven’t looked at that). It has a really cool query languages, that looks a lot like SQL, that lets you customize any of the existing metrics that it tracks or write your own (it comes with so many that it seems like I just customize). It comes with so many metrics that in practice it can be seem quite overwhelming. I think the right thing to do for most projects is to pick the handful that you care about and limit it to that.
NDepend comes with NAnt and MSBuild tasks that will let you integrate it into your build automation. It also comes with an XSL stylesheet to integrate the NDepend output into CruiseControl.NET for reporting purposes.
Some things you might run into:
- C# support is the primary language (e.g. No support for code level Cyclomatic Complexity for non-C# language, but still supports IL level CC). Only a problem if you are forced to do VB.NET of course, or use another CLR language.
- A single license is $400 and 20 licenses or more are over $200 each. So price could be a concern to many people. I’m thinking it might make the most sense to run this on a CI server, so in that case you would probably only need a small number of licenses.
- It integrates with code coverage tools, but currently only NCover. See the previous comments about the cost of NCover combined with the cost of NDepend if price is an issue.
What Else?
What does everyone else think? What do you care about and what are the right metrics for keeping track of the health of a software project?
Background
The command regsvr32 is used to register a native, unmanaged code DLL so that it is available via COM. With a registered DLL you can use COM Interop to call that code from .NET Managed code.
Regsvr32 is unmanaged code and as such makes use of some existing functions that are defined in the kernel32.dll. Fortunately .NET makes available a pretty easy to use foreign function interface (FFI) in the form of P/Invoke.
In general to call an unmanaged function you just need to use the DllImport annotation on an extern function to tell the CLR how to access the function.
e.g.:
[DllImport("shell32.dll")] static extern int DllGetVersion(ref DLLVERSIONINFO pdvi);
Registering an Unmanaged DLL with C# Code
regsvr32 actually calls functions defined within the DLL itself in what is known as a self-registering DLL. So assuming your DLL is self-registering then you should be able to use this approach as well. The only thing we need to do is figure out what functions to call.
It ends up there are 2 basic functions: LoadLibrary and GetProcAddress.
LoadLibrary
LoadLibrary returns a handle the module (a pointer to a structure).
After you are done with you library you can clean up by calling FreeLibrary passing it the handle that was returned from LoadLibrary.
GetProcAddress
GetProcAddress finds a function defined in a module and returns a pointer to that function. A function pointer allows you to call a method in a dynamic way. It is functionally equivalent to a delegate in managed code.
In C e.g.:
(*some_func)();
Put it All Together
Now we have a basic algorithm to register a DLL:
- LoadLibrary to get a handle to the library
- GetProcAddress to get a function pointer to the proper function to register the DLL
- Call the function returned from GetProcAddress
- Cleanup
Mix that in with some error checking code and I got the following:
public class Registrar : IDisposable { private IntPtr hLib; [DllImport("kernel32.dll", CharSet = CharSet.Ansi, ExactSpelling = true, SetLastError = true)] internal static extern IntPtr GetProcAddress(IntPtr hModule, string procName); [DllImport("kernel32.dll", SetLastError = true)] internal static extern IntPtr LoadLibrary(string lpFileName); [DllImport("kernel32.dll", SetLastError = true)] internal static extern bool FreeLibrary(IntPtr hModule); internal delegate int PointerToMethodInvoker(); public Registrar(string filePath) { hLib = LoadLibrary(filePath); if (IntPtr.Zero == hLib) { int errno = Marshal.GetLastWin32Error(); throw new Win32Exception(errno, "Failed to load library."); } } public void RegisterComDLL() { CallPointerMethod("DllRegisterServer"); } public void UnRegisterComDLL() { CallPointerMethod("DllUnregisterServer"); } private void CallPointerMethod(string methodName) { IntPtr dllEntryPoint = GetProcAddress(hLib, methodName); if (IntPtr.Zero == dllEntryPoint) { throw new Win32Exception(Marshal.GetLastWin32Error()); } PointerToMethodInvoker drs = (PointerToMethodInvoker) Marshal.GetDelegateForFunctionPointer(dllEntryPoint, typeof(PointerToMethodInvoker)); drs(); } public void Dispose() { if (IntPtr.Zero != hLib) { UnRegisterComDLL(); FreeLibrary(hLib); hLib = IntPtr.Zero; } } }
Note:
The requirement I was dealing with was a build script so I wanted to register the unmanaged DLL, use it, and then unregister it so the computer would be in its previous state. If you want to leave the DLL registered, such as for an install program, you would need to modify the above example.
To call this code you just need to pass it a path to the dll that needs to be registered.
using (Registrar registrar = new Registrar("path\\to\\com.dll")) { registrar.RegisterComDLL(); return base.Execute(); }
Resources:
Check out pinvoke.net for a lot of good documentation and example of how to call native methods from managed code.
Windows Subversion Maintenance Scripts
Previously I wrote about the Subversion Maintenance Scripts that I use for doing things like backups and upgrades. They were bash shell scripts that automated dealing with multiple Subversion repositories. The secret was that those guys were being run using Cygwin on Windows. Recently we got a new, more powerful server to run our Virtuals on. I decided to rewrite the scripts using native Windows Batch files so that I wouldn’t have to install Cygwin again. Hopefully someone else will find this useful too.
Windows Batch Script for Creating a Default Repository Structure
I work for a custom software development consulting firm so we have a lot of different clients. We don’t want to mix different clients’ code so we create a repository per client. We often get multiple projects per client though (yeah, they like us) so we go ahead and create a project under the client. We also like to use the trunk, tags and branches directories by default.
With all of these rules: Automate!
create_repo.bat
@echo off REM Check command line args to make sure a customer and project name were passed IF (%1)==() GOTO CMDLINE IF (%2)==() GOTO CMDLINE REM If svnadmin is not in your path, uncomment the following REM PATH=%PATH%;"D:\Program Files\Subversion\bin" REM Set up variables with the directories SET CUSTOMER=%1 SET PROJECT=%2 SET CUR_DIR=%~dp0 SET CUR_DIR=%CUR_DIR:\=/% SET SVN_DIR=%CUR_DIR%/repos/%CUSTOMER% SET PROJ_DIR=file:///%SVN_DIR%/%PROJECT% echo Creating directory in %SVN_DIR% svnadmin create "%SVN_DIR%" svn -m "Create default structure." mkdir %PROJ_DIR% %PROJ_DIR%/trunk %PROJ_DIR%/tags %PROJ_DIR%/branches GOTO END :CMDLINE echo Usage: %0 ^<customer^> ^<project^> :END echo Done
Some of the interesting pieces:
%~dp0 gives you the directory that the current script lives in.
%CUR_DIR:\=/% replaces the backslash (\) with forward slashes (/) so that the SVN file:// URL will work correctly.
Windows Batch Script to Dump Your Subversion Repositories
The next thing you might want to do is to dump all of your repositories so that you can back them up or upgrade SVN or move to a new server. With just one repository it’s easy to do by hand. With 20+ repositories it’s much nicer to run a script and then go do something else.
dump_all.bat
@echo off SET DUMP_DIR=dumps SET REPOS_DIR=repos IF NOT EXIST %DUMP_DIR% ( echo Creating directory %DUMP_DIR% md %DUMP_DIR% ) echo Dumping... FOR /f %%i IN ('dir /B /A:D %REPOS_DIR%\*') DO ( echo Dumping %REPOS_DIR%\%%i to %DUMP_DIR%\%%i.dump svnadmin dump %REPOS_DIR%\%%i > %DUMP_DIR%\%%i.dump )
Some of the interesting pieces:
FOR /f %%i IN (‘dir /B /A:D %REPOS_DIR%\*’) DO is the part that finds each directory (in this case an SVN repository). Then for each repository you run the svnadmin dump command and send the dump file to a different directory.
Windows Batch Script to Load Your Subversion Repositories
After you’ve dumped all of your repositories and you need to restore them, because you’ve upgraded or moved them to a new server we need to do the reverse of the dump script.
restore_all.bat
@echo off SET DUMP_DIR=dumps SET REPOS_DIR=repos echo Restoring.... REM %%~ni becomes the dump name without .dump FOR /f %%i IN ('dir /B %DUMP_DIR%\*.dump') DO ( echo Restoring %DUMP_DIR%\%%i to %REPOS_DIR%\%%~ni svnadmin create %REPOS_DIR%\%%~ni svnadmin load %REPOS_DIR%\%%~ni < %DUMP_DIR%\%%i )
Some of the interesting pieces:
FOR in this case is the same as the dump, except it’s looking for all the dump files.
%%i holds the name of the dump file (e.g. repo.dump). %%~ni strips off the extension to give you just the name of the file (e.g. repo).
Now you can manage your repositories with ease if you’re stuck on a Windows machine.
Swapping Values Without a Temp Variable
It’s been a long time since I’ve done any C programming (the only C I ever really did was in school 10+ years ago) and I’ve never done it outside of school. I figure since I look at and study languages that are pretty esoteric, it’s only fair to throw in a language that is really widely used. It should make my Objective-C better (which probably isn’t saying much). It also gives me a chance to go “a little closer to the metal” I guess. Hey look, a Bus Error!
Anyway, one of the things that I love/hate about C are the little tricks that people often use. Sometimes they’re really fun but often they take a bit of thinking to understand if you’re not familiar with them. One of those that I ran across again was swapping values without a temp variable.
How Normal People Swap Values
The simplest way of swapping two values is ususally accomplished using a temp variable to hold one of the values for a moment.
int a = 2; int b = 5; int temp = 0; temp = a; a = b; b = temp;
And Another Way
But you can accomplish the same thing using an Exclusive Or (XOR) operation.
To review bitwise operations:
& AND 0101 (5) 1100 (12) ---- & 0100 (4) | OR 0101 (5) 1100 (12) ---- | 1101 (13) ^ XOR 0101 (5) 1100 (12) ---- | 1001 (9)
The ^= just combines the XOR with an Assignment.
int a = 2; int b = 5; a ^= b; b ^= a; a ^= b;
Now isn’t that totally intuitive? Yeah, not to me either. Technically once you know this piece of trivia, you don’t really need to think about it. You’ll just recognize the pattern and understand what’s going on. But understanding why it works is probably a good thing.
So, I just came up with an example that shows what’s happening:
int a = 2; // 0010 int b = 5; // 0101 a ^= b; // 0111 = 0010 ^ 0101 b ^= a; // 0010 = 0101 ^ 0111 a ^= b; // 0101 = 0111 ^ 0010
What are some of the principles in why this works?:
a ^ b == b ^ a
XOR is a reversible binary operation.
a = a ^ b // now a is some other value b = a ^ b // now b is the original value of a a = a ^ b // now a is the original value of b
This isn’t a proof of any sort, but hopefully it will help you understand why it actually works. If you want even more of an explanation, and a proof, check out the article on Wikipedia: XOR Swap Algorithm
Scheme/HtDP Unit Testing Functions
How to Design Programs (HtDP) provides a series of unit testing functions that allow you to test the output of any kind of function. The current version talks about testing your code, but doesn’t offer a lot of guidance into how to do that. Everything you need is there though, so in case you are doing this on your own and don’t have a teacher to tell you to do this, here’s some explanation that I hope helps.
check-expect
check-expect takes the results of a function and the expected value. This is the simplest of the testing constructs which answers the question “Does the expected result of a function call equal the result returned by the function?”. It handles all of the details about types of values returned, so it can work with a simple value like a number, a complex value like a structure or a list, or even a picture.
;; add: number number -> number ;; add two numbers together (define (add n m) (+ n m)) ;; Tests (check-expect (add 1 1) 2)
check-within
check-within is similar to check-expect, but it allows for a third argument to tell wether or not the result is within a certain difference of the actual answer. This is good for certain functions that might produce random results, but the most common case is when dealing with floating point numbers. Floating point numbers are not always represented precisely, so there needs to be some “room for error” so to speak.
(define PI 3.14) (check-within (/ 22 7) PI .003) (check-within (random 10) 0 9)
check-error
Finally, you can use check-error to test cases where your function throws an error. Those error conditions are an important part of a function contract, so testing them should be done just like any other possible conditions.
One of the things that threw me at first was what to use as the expected value of a check-error test.
An error is HtDP is “throw” by a function like:
(error 'function-name "some message")
After a bit of trial and error, I found out the expected result is a string like:
; "function-name: some message" (check-error (error 'list-pick "list too short") "list-pick: list too short")
More Realistic Example
;; list-pick : list-of-symbols N[>= 0] -> symbol ;; to determine the nth symbol from alos, counting from 0; ;; signals an error if there is no nth item (define (list-pick alos n) (cond [(empty? alos) (error 'list-pick "list too short")] [(= n 0) (first alos)] [(> n 0) (list-pick (rest alos) (sub1 n))])) ;; Tests (check-error (list-pick empty 1) "list-pick: list too short") (check-expect (list-pick (list 'a 'b 'c 'd) 3) 'd) (check-error (list-pick (list 'a 'b 'c 'd) 4) "list-pick: list too short")
Studying HtDP
I haven’t posted in a while, but I’ve recently been studying How to Design Programs (HtDP). It’s really a book about teaching beginners how to program by following a series of recipes that tell you how to identify and solve different classes of problems. The techniques are taught in a very basic subset of Scheme. (There are actually multiple learning languages that slowly build up the available functionality.) You don’t have to know any Scheme to get started though.
Basic Scheme
I’m sure you can figure out what the following does without knowing any scheme:
(+ 1 3) (* 10 10)
They explain a bit about equality and conditionals:
(= 1 1) ; true (and true true) ; true (or true false) ; false (and (>= 1 1) (= 2 2)) ; true
Then building on basic arithmetic and boolean logic, they add a bit of algebra to teach how to define your own methods:
(define (add1 n) (+ n 1)) (define (sqr n) (* n n)) ;; Tests (= (add1 2) 3) (= (sqr 10) 100)
It grows from those simple constructs into how to build structured and list data and how to process those kinds of data.
Why Might You Care?
It’s very hard for me to judge what it would be like to learn to program using this book. I personally have 10 years of programming experience myself and learned first with BASIC, then really with Pascal and C/C++. Professionally I first programmed in Java, then C#. From there I really got interested in dynamic languages like Python then Ruby and looked a bit at Objective-C in there. By and large these are all Imperative Programming Languages. I’m sure my experience isn’t unique for those of us who didn’t go to MIT. So, if like me, you are new to Functional Programming then it is an interesting book because it teaches you how to think in terms of functional decomposition.
Multi-core processing is the future and functional programming, due to the ability to much more easily create side-effect free programs, is well suited for parallelization. Understanding functional programming is going to be very important for programmers in the future. We might never go to all functional programming, but we might go to more mixed-mode languages that allow us to easily write parallelized code for portions of a program that need it.
Grails Testing Acegi Security
Almost every web application I create needs some form of user authentication and authorization. Grails provides a great plugin system that allows you to extend the base framework to provide these kinds of features. My current favorite security plugin for Grails is the Acegi Security Plugin. It’s built using the Spring Security framework and the robust and widely used Acegi framework. I like the fact that it is built on top of existing, well-known frameworks which is the philosophy of Grails itself. It is also a flexible plugin that has a good default object model.
One of the situations that inevitably arises is how to unit test code that depends on your security framework. Either you will want to test that basic authorization is working, or you might have code that makes decisions based upon who is logged in or what roles they might have. To run those test you have to setup your test cases so that the code that works when the system is running normally is tested.
Unit Testing Setup for Testing Acegi Security Code
This situation arose for me the other day and so I thought I would share the solution that I came up with.
import org.springframework.security.context.SecurityContextHolder as SCH import org.springframework.security.providers.TestingAuthenticationToken import org.springframework.security.GrantedAuthority import org.springframework.security.Authentication import org.springframework.security.GrantedAuthorityImpl class AuthenticationBaseTests extends GroovyTestCase { def setUp() { def user = User.get(1) // or create a new one if one doesn't exist authenticate(user, "abc123", [new GrantedAuthorityImpl('ROLE_ADMIN')]) } protected Authentication authenticate(user, credentials, authorities) { def principal = new Expando() principal.domainClass = user Authentication authentication = new TestingAuthenticationToken(principal, null, authorities as GrantedAuthority[]) authentication.authenticated = true SCH.context.authentication = authentication return authentication } }
setUp()
The setUp() method will get executed prior to your tests being run. So if you want to do different things for each test you would want to move this code to a more appropriate place. In the setup method we are creating our Principle class, in this case, the User. Next we pass the user along with all of the roles we want the user to have for the given test case.
authenticate(user, credentials, authorities)
The real setup work is done in the authenticate() method. This method does the real work of setting up the Authentication Token and setting it in the static context, which is a thread local variable I think, that is used by the framework to determine who is making the request and what rights they have.
The fun thing about this message is the use of the Expando class. Expando allows you to create a class on the fly. This is a really interesting way to do a Mock object on-the-fly in Groovy. In this case we’re creating a Mock authentication principle. We know, by looking at the Acegi Security code, that the security framework expects an object that will call domainClass to get the underlying implementation of the User (or Principle) implemented in the application. That will return us the User object that we are setting.
This simple method can be added to a base class and then inherited from any tests that need user authentication to run successfully.
Grails has a rich set of tools for performing validations of your domain objects. There are quite a few built in validations that you can use. These mainly resolve around validating single properties within a single domain object. It also supports things like validating the sizes of dependent collections.
Sometimes you need to know about the properties of one instance to validate another dependent instance. The property of that dependent instance might be used to determine the valid values of or might provide a limit for a property.
This is more easily explained with an example.
Problem Statement
I’ll use voting for members of the Board of a public company as an example.
A ShareHolder owns N number of shares of stock in a company. When the ShareHolder votes on a Board member of the company, the ShareHolder can assign 1 to N shares to that Candidate. The top 5 Candidates that receive the most Shares (not individual votes) win the election.
We might create a series of Domain classes like this:
class ShareHolder { static hasMany = [votes:Vote] String name Double shares } class Candidate { static hasMany = [votes:Vote] String name } class Vote { static belongsTo = [shareHolder: ShareHolder, candidate: Candidate] Double voteShares }
A ShareHolder can vote multiple times, so it has many Votes. A Candidate can be voted for many times, so it has many Votes. A given Vote can be assigned 1 or more shares. But the shares for a given vote must be less than or equal to the number of shares that the voter (the ShareHolder) owns.
Validation
The natural place to perform this validation is on the Vote domain object itself. The problem is that the limit is really the shares value from the ShareHolder domain object. To solve this we can not use a built in validation. Instead we need to create our own.
To do this we can utilize the validator validation. This is no different than any other custom validation that we might need to create. Since we must have the ShareHolder and the Candidate set for this to be a valid object, we can assume that they are available. Because of this we should be able to access their properties to validate our Vote domain object.
Add a custom validator constraint:
class Vote { static belongsTo = [shareHolder: ShareHolder, candidate: Candidate] Double voteShares static constraints = { voteShares(min: 0D, validator: { val, obj -> val <= obj.shareHolder?.shares }) } }
As you can see, the obj that gets passed in is the instance that is being validated. The val is the value of the property being validated, in this case the voteShares property. All that has to be done is to compare the value of the obj.shareHolder?.shares too the voteShares property. The obj.shareHolder?. should protect us against a null reference in case the shareHolder isn’t set. Then the validation will just fail on not having the ShareHolder.
Nothing really tricky here, just something interesting I ran into recently.