package de.vksi.c4j.systemtest.contractclassmagic; import static de.vksi.c4j.Condition.postCondition; import static org.hamcrest.Matchers.containsString; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; import de.vksi.c4j.ContractReference; import de.vksi.c4j.Pure; import de.vksi.c4j.Target; import de.vksi.c4j.systemtest.TransformerAwareRule; public class RecursiveSystemTest { @Rule public TransformerAwareRule transformerAware = new TransformerAwareRule(); @Rule public ExpectedException expectedException = ExpectedException.none(); @Test public void testCorrectEquals() { new TargetClassWithCorrectEquals().equals(new TargetClassWithCorrectEquals()); } @ContractReference(ContractClassWithCorrectEquals.class) private static class TargetClassWithCorrectEquals { @Pure @Override public boolean equals(Object obj) { return this == obj; } } private static class ContractClassWithCorrectEquals extends TargetClassWithCorrectEquals { @Target private TargetClassWithCorrectEquals target; @Override public boolean equals(Object obj) { if (postCondition()) { assert target.equals(target) : "is reflexive"; assert target.equals(obj) == obj.equals(target) : "is symmetric"; } return false; } } @Test public void testUnreflexiveEquals() { TargetClassWithUnreflexiveEquals target = new TargetClassWithUnreflexiveEquals(); expectedException.expect(AssertionError.class); expectedException.expectMessage(containsString("is reflexive")); target.equals(target); } @ContractReference(ContractClassWithUnreflexiveEquals.class) private static class TargetClassWithUnreflexiveEquals { @Override public boolean equals(Object obj) { return this != obj; } } private static class ContractClassWithUnreflexiveEquals extends TargetClassWithUnreflexiveEquals { @Target private TargetClassWithUnreflexiveEquals target; @Override public boolean equals(Object obj) { if (postCondition()) { assert target.equals(target) : "is reflexive"; assert target.equals(obj) == obj.equals(target) : "is symmetric"; } return false; } } @Test public void testUnsymmetricEquals() { expectedException.expect(AssertionError.class); expectedException.expectMessage(containsString("is symmetric")); new TargetClassWithUnsymmetricEquals(3).equals(new TargetClassWithUnsymmetricEquals(4)); } @ContractReference(ContractClassWithUnsymmetricEquals.class) private static class TargetClassWithUnsymmetricEquals { private int value; public TargetClassWithUnsymmetricEquals(int value) { this.value = value; } @Override public boolean equals(Object obj) { if (!(obj instanceof TargetClassWithUnsymmetricEquals)) { return false; } return this.value >= ((TargetClassWithUnsymmetricEquals) obj).value; } } private static class ContractClassWithUnsymmetricEquals extends TargetClassWithUnsymmetricEquals { @Target private TargetClassWithUnsymmetricEquals target; public ContractClassWithUnsymmetricEquals() { super(0); } @Override public boolean equals(Object obj) { if (postCondition()) { assert target.equals(target) : "is reflexive"; assert target.equals(obj) == obj.equals(target) : "is symmetric"; } return false; } } }