Tuesday, 15 December 2015
SLF4JLogging Testing
Every so often I need to test some logging. At the same time I prefer my tests to run concurrently.
The other log testing frameworks end up using singletons and horrors like the StaticLogBinder.
I got sick of writing similar log mocking code and providing examples of how to inject the logging impl using dependency injection rather than statics.
The up shot of this is that I wrote my own test utility implementation
https://github.com/portingle/slf4jtesting
Saturday, 13 August 2011
Immutable enforcement with AspectJ
Been messing around with AspectJ and out of curiosity I wondered if I could implement something to enforce immutability.
Came up with this.
If we label a type as @Immutable then the aspect verifies that the class really is immutable.
Primitive types are easy to check for immutability - just make sure they are "final".
However, fields that are objects are more tricky. The approach I've taken here is to allow object fields only if the field's class has also been marked as @Immutable.
There are a bunch of classes that we know to be immutable and we don't want to keep putting @Immutable on fields of this type (eg String). My approach here has been to put a set of trusted immutable types in the aspect. String and Float are the only ones in my example below.
package john.aspects.immutable;
public aspect ImmutableAspect {
pointcut field_is_marked_immutable_mutation() : set(@Immutable * *);
pointcut set_non_final_field() : set(!final * *);
/*
* add common known immutable classes here so you can use them without
* having to label field as Immutable too. worth doing this to avoid
* excessive use of Immutable at field level. too much local labelling of
* fields may lead to accidental labelling of a mutable type.
*/
pointcut known_immutable_type() : set(String *) || set(Float *);
pointcut is_safe_field_type() : known_immutable_type()
|| field_is_marked_immutable_mutation();
-
pointcut set_field_where_type_is_not_immutable() : set( (!@Immutable *) *);
pointcut set_field_type_is_mutable() : set_field_where_type_is_not_immutable()
&& !is_safe_field_type();
pointcut class_is_immutable() : @within(Immutable);
declare error : set_field_type_is_mutable()
&& class_is_immutable()
: "All fields on Immutable class must be also be Immutable";
declare error : set_non_final_field()
&& class_is_immutable()
: "Illegal mutation of field on Immutable class - field should be final";
} An example usage .. package john.aspects.immutable;import java.util.Date;
// turn on Immutability checks for this class
@Immutable
public class ImmutableTest {
// its ok to use an Immutable class as a field
final ImmutableTest ok = null;
// but not ok unless it's final
ImmutableTest bad_nonfinal = null;
// primitive finals work ok
final int ok_final_primitive_init = 0;
// but not ok unless final
int bad_NONFINAL_primitive_init = 0;
// a class without the immutable annotation isn't trusted.
final Integer bad_Integer_doesnt_have_annotation = null;
// however I can tell the Aspect that this instance is trusted
@Immutable
final Integer ok_Integer_can_be_overridden = null;
// however I can tell the Aspect that this instance is trusted
@Immutable
Integer bad_because_its_non_final = null;
// obviously Date is mutable so lying is a bad thing.
// if you do this then there's nothing the aspect can do to prevent you.
@Immutable
final Date ok_final_immutableoverride_class_ctorinit = null;
// We can add trusted types to the aspect and String is one of them.
// so I don't need to put Immutable here.
final String ok_final_immutable_init = "";
}
The annotation is trivial.
Can't use the JCIS Immutable annotation because it cannot be applied to a field. package john.aspects.immutable;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD, ElementType.TYPE})
public @interface Immutable { }
Still trying to work out how to extend the coverage to the superclass. I want to enforce that the superclass is either a type that also carries @Immutable or is Object.
Subscribe to:
Comments (Atom)
-
Clarity, Concurrency, Convenience I'm currently making some changes to Cucumber godog which is a behaviour driven development tool for...
-
Was looking into Java 8's functional programming features. I instantly came across a problem that functional programming in Java 8 ...
-
Visited Saturday April 13th 2019 The following timeline was what I achieved as a lone adult visiting KSC for the first time. I think if m...
Recommended Pattern for Shared State in GoDog
Clarity, Concurrency, Convenience I'm currently making some changes to Cucumber godog which is a behaviour driven development tool for...