-
Notifications
You must be signed in to change notification settings - Fork 151
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
2 changed files
with
133 additions
and
10 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -34,6 +34,7 @@ | |
|
||
/** | ||
* Test case for {@link Immutable} annotation and its implementation. | ||
* | ||
* @author Yegor Bugayenko ([email protected]) | ||
* @version $Id$ | ||
* @checkstyle ConstantUsageCheck (500 lines) | ||
|
@@ -69,6 +70,15 @@ public void catchedMutableTypesWithInterfaces() { | |
new MutableWithInterface(); | ||
} | ||
|
||
/** | ||
* Immutable can catch mutable classes with mutable implementation of | ||
* immutable interfaces. | ||
*/ | ||
@Test(expected = IllegalStateException.class) | ||
public void catchedMutableTypesWithImplementationOfImmutableInterface() { | ||
new MutableWithImmutableInterface(); | ||
} | ||
|
||
/** | ||
* Immutable can pass immutable classes. | ||
*/ | ||
|
@@ -77,6 +87,22 @@ public void passesImmutableObjects() { | |
new TruelyImmutable(); | ||
} | ||
|
||
/** | ||
* Immutable can pass immutable classes. | ||
*/ | ||
@Test | ||
public void passesImmutableObjectsWithNonPrivateFields() { | ||
new TruelyImmutableWithNonPrivateFields(); | ||
} | ||
|
||
/** | ||
* Immutable can catch mutable classes with interfaces. | ||
*/ | ||
@Test(expected = IllegalStateException.class) | ||
public void catchedTypesMutableByClassInheritance() { | ||
new MutableByInheritance(); | ||
} | ||
|
||
/** | ||
* Supposedly immutable class. | ||
*/ | ||
|
@@ -117,6 +143,47 @@ private static final class MutableWithInterface { | |
private final transient MutableInterface data = null; | ||
} | ||
|
||
/** | ||
* Other vague interface. | ||
*/ | ||
@Immutable | ||
private interface ImmutableInterface { | ||
/** | ||
* This function seems to be harmless. | ||
* @param input An input | ||
*/ | ||
void willBreakImmutability(int input); | ||
} | ||
|
||
/** | ||
* Mutable class implementing immutable interface. | ||
*/ | ||
@Immutable | ||
private static final class MutableWithImmutableInterface { | ||
/** | ||
* Supposedly immutable field that is not immutable after all. | ||
*/ | ||
private final ImmutableInterface impl = new ImmutableInterface() { | ||
private int state = 1; | ||
|
||
/** | ||
* This function breaks the immutability promised by the interface. | ||
*/ | ||
@Override | ||
public void willBreakImmutability(final int newstate) { | ||
this.state = newstate; | ||
} | ||
}; | ||
|
||
/** | ||
* Stupid getter. | ||
* @return A handle to mutate the object. Not good... | ||
*/ | ||
public ImmutableInterface getImpl() { | ||
return this.impl; | ||
} | ||
} | ||
|
||
/** | ||
* Truely immutable class. | ||
*/ | ||
|
@@ -125,11 +192,11 @@ private static final class TruelyImmutable { | |
/** | ||
* Something static final. | ||
*/ | ||
private static final Pattern PATTERN = Pattern.compile(".*"); | ||
private static final Pattern PATTERN = Pattern.compile(".?"); | ||
/** | ||
* Something just static. | ||
*/ | ||
private static Pattern ptrn = Pattern.compile(".+"); | ||
private static Pattern ptrn = Pattern.compile("\\d+"); | ||
/** | ||
* Immutable class member. | ||
*/ | ||
|
@@ -149,4 +216,61 @@ private static final class TruelyImmutable { | |
private final transient String[] texts = new String[] {"foo"}; | ||
} | ||
|
||
/** | ||
* Truely immutable class with non-private fields. | ||
* | ||
* @checkstyle VisibilityModifier (25 lines) | ||
*/ | ||
@Immutable | ||
private static final class TruelyImmutableWithNonPrivateFields { | ||
/** | ||
* Something static final. | ||
*/ | ||
private static final Pattern PATTERN = Pattern.compile(".*"); | ||
/** | ||
* Something just static. | ||
*/ | ||
private static Pattern ptrn = Pattern.compile(".+"); | ||
/** | ||
* Immutable class member. | ||
*/ | ||
private final transient String data = null; | ||
/** | ||
* Another immutable class member. | ||
*/ | ||
private final transient int number = 2; | ||
/** | ||
* Another immutable class member. | ||
*/ | ||
private final transient String text = "Hello!"; | ||
} | ||
|
||
/** | ||
* Almost immutable class. It can be inherited, because it is non-final; | ||
* thus methods in the child class can return nonsensical values (e.g. | ||
* getters that do no return the original value of their corresponding | ||
* fields). Moreover, immutability cannot be forced to a subclass. | ||
* See <a href= | ||
* "http://marxsoftware.blogspot.se/2009/09/ | ||
* is-java-immutable-class-always-final.html"> | ||
* Is java immutable class always final?</a> | ||
*/ | ||
@Immutable | ||
private static class MutableByInheritance { | ||
/** | ||
* Immutable class member. | ||
*/ | ||
private final transient String data = null; | ||
|
||
/** | ||
* Could be overloaded by a child of the class and then return | ||
* nonsensical value. | ||
* | ||
* @return A value that could differ from what is expected if returned by an overriding method | ||
*/ | ||
public String getData() { | ||
return this.data; | ||
} | ||
} | ||
|
||
} |