Writing a JUnit test for a security permission object. That's got to be easy, right? Well it took me a while to figure out a solution so I thought I'd share.
Joda-Time has a security permission class, JodaTimePermission, that controls whether you have the rights to do things such as alter the current time. But writing a test was a pain, and what I have doesn't work on JDK1.3 or earlier.
The problem is to be able to change the security policy without manually stopping and starting the JVM and changing the policy file.
My solution was to create two classes that represented 'yes' and 'no':
private static final Policy RESTRICT; private static final Policy ALLOW; static { // don't call Policy.getPolicy() RESTRICT = new Policy() { public PermissionCollection getPermissions(CodeSource codesource) { Permissions p = new Permissions(); p.add(new AllPermission()); // enable everything return p; } public void refresh() { } public boolean implies(ProtectionDomain domain, Permission permission) { if (permission instanceof JodaTimePermission) { return false; } return true; } }; ALLOW = new Policy() { public PermissionCollection getPermissions(CodeSource codesource) { Permissions p = new Permissions(); p.add(new AllPermission()); // enable everything return p; } public void refresh() { } }; }
These could then be used in the actual test method:
public void testChangeCurrentTime() { try { Policy.setPolicy(RESTRICT); System.setSecurityManager(new SecurityManager()); DateTimeUtils.setsetCurrentMillisFixed(0L); // disallowed by security fail(); } catch (SecurityException ex) { // ok } finally { System.setSecurityManager(null); Policy.setPolicy(ALLOW); } }
I have to say that it all feels like a hack to me. So, has anyone else come up with a better solution for testing security permissions?
Great post! I wish more OSS tools would use the standard java security model. Joda just moved from maybe-i'll-bookmark-this to i-should-definitely-check-this-out status.
ReplyDeleteTo your question; unfortunately, I have run into the exact same problem in the past (twice) and I've yet to find anything better than what you have here. The only other option I considered was wrapping the static AccessController calls in a delegating application-coded instance that was pluggable by interface. While this would work (i.e. you could check that the access controller was called without needing to munge the Policy), it smacks of over-engineering :(