From 3f936ae4f345a960bf55f44786f91f2010dc9fca Mon Sep 17 00:00:00 2001 From: =?utf8?q?David=20=E2=80=98Bombe=E2=80=99=20Roden?= Date: Sat, 29 Apr 2023 21:29:08 +0200 Subject: [PATCH] =?utf8?q?=E2=9C=85=20Add=20equals=20for=20AbstractState?= MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit --- .../rhynodge/states/AbstractState.java | 61 ++++++++++++++-- .../rhynodge/states/AbstractStateTest.kt | 83 ++++++++++++++++++++++ 2 files changed, 140 insertions(+), 4 deletions(-) create mode 100644 src/test/kotlin/net/pterodactylus/rhynodge/states/AbstractStateTest.kt diff --git a/src/main/java/net/pterodactylus/rhynodge/states/AbstractState.java b/src/main/java/net/pterodactylus/rhynodge/states/AbstractState.java index 081fbcc..8828fe4 100644 --- a/src/main/java/net/pterodactylus/rhynodge/states/AbstractState.java +++ b/src/main/java/net/pterodactylus/rhynodge/states/AbstractState.java @@ -17,6 +17,8 @@ package net.pterodactylus.rhynodge.states; +import java.time.Clock; +import java.util.Objects; import javax.annotation.Nonnull; import javax.annotation.Nullable; @@ -69,11 +71,26 @@ public abstract class AbstractState implements State { * otherwise */ protected AbstractState(boolean success) { - this(success, true, null); + this(Clock.systemUTC(), success); + } + + /** + * Creates a new state. + * + * @param clock The clock for generating {@link #time} + * @param success {@code true} if the state is successful, {@code false} + * otherwise + */ + protected AbstractState(Clock clock, boolean success) { + this(clock, success, true, null); } protected AbstractState(boolean success, boolean empty) { - this(success, empty, null); + this(Clock.systemUTC(), success, empty); + } + + protected AbstractState(Clock clock, boolean success, boolean empty) { + this(clock, success, empty, null); } /** @@ -83,7 +100,17 @@ public abstract class AbstractState implements State { * The exception that occured while retrieving the state */ protected AbstractState(Throwable exception) { - this(false, true, exception); + this(Clock.systemUTC(), exception); + } + + /** + * Creates a new non-successful state with the given exception. + * + * @param clock The clock for generating {@link #time} + * @param exception The exception that occured while retrieving the state + */ + protected AbstractState(Clock clock, Throwable exception) { + this(clock, false, true, exception); } /** @@ -96,7 +123,19 @@ public abstract class AbstractState implements State { * The exception that occured while retrieving the state */ protected AbstractState(boolean success, boolean empty, Throwable exception) { - this.time = System.currentTimeMillis(); + this(Clock.systemUTC(), success, empty, exception); + } + + /** + * Creates a new state. + * + * @param clock The clock for generating {@link #time} + * @param success {@code true} if the state is successful, {@code false} + * otherwise + * @param exception The exception that occured while retrieving the state + */ + protected AbstractState(Clock clock, boolean success, boolean empty, Throwable exception) { + this.time = clock.millis(); this.success = success; this.empty = empty; this.exception = exception; @@ -176,4 +215,18 @@ public abstract class AbstractState implements State { @SuppressWarnings("UnstableApiUsage") private static final Escaper htmlEscaper = HtmlEscapers.htmlEscaper(); + @Override + public int hashCode() { + return Objects.hash(success, empty, time, failCount, exception); + } + + @Override + public boolean equals(Object object) { + if (!(object instanceof AbstractState)) { + return false; + } + AbstractState abstractState = (AbstractState) object; + return (success == abstractState.success) && (empty == abstractState.empty) && (time == abstractState.time) && (failCount == abstractState.failCount) && Objects.equals(exception, abstractState.exception); + } + } diff --git a/src/test/kotlin/net/pterodactylus/rhynodge/states/AbstractStateTest.kt b/src/test/kotlin/net/pterodactylus/rhynodge/states/AbstractStateTest.kt new file mode 100644 index 0000000..29d7386 --- /dev/null +++ b/src/test/kotlin/net/pterodactylus/rhynodge/states/AbstractStateTest.kt @@ -0,0 +1,83 @@ +package net.pterodactylus.rhynodge.states + +import org.hamcrest.MatcherAssert.assertThat +import org.hamcrest.Matchers.equalTo +import org.junit.Test +import java.time.Clock +import java.time.Instant.now +import java.time.ZoneOffset.UTC + +/** + * Unit test for [AbstractState]. + */ +class AbstractStateTest { + + @Test + fun `equals returns true when everything is the same`() { + val first = object : AbstractState(testClock, false) { + override fun plainText() = "foo" + } + val second = object : AbstractState(testClock, false) { + override fun plainText() = "foo" + } + assertThat(first.equals(second), equalTo(true)) + } + + @Test + fun `equals returns false for when success is different`() { + val first = object : AbstractState(testClock, false) { + override fun plainText() = "foo" + } + val second = object : AbstractState(testClock, true) { + override fun plainText() = "foo" + } + assertThat(first.equals(second), equalTo(false)) + } + + @Test + fun `equals return false when empty is different`() { + val first = object : AbstractState(testClock, false, false) { + override fun plainText() = "foo" + } + val second = object : AbstractState(testClock, false, true) { + override fun plainText() = "foo" + } + assertThat(first.equals(second), equalTo(false)) + } + + @Test + fun `equals returns false when time is different`() { + val first = object : AbstractState(testClock, false) { + override fun plainText() = "foo" + } + val second = object : AbstractState(Clock.fixed(now().plusSeconds(1), UTC), false) { + override fun plainText() = "foo" + } + assertThat(first.equals(second), equalTo(false)) + } + + @Test + fun `equals returns false when failCount is different`() { + val first = object : AbstractState(testClock, false) { + override fun plainText() = "foo" + }.apply { setFailCount(12) } + val second = object : AbstractState(testClock, false) { + override fun plainText() = "foo" + }.apply { setFailCount(23) } + assertThat(first.equals(second), equalTo(false)) + } + + @Test + fun `equals returns false when exception is different`() { + val first = object : AbstractState(testClock, RuntimeException()) { + override fun plainText() = "foo" + } + val second = object : AbstractState(testClock, IllegalArgumentException()) { + override fun plainText() = "foo" + } + assertThat(first.equals(second), equalTo(false)) + } + +} + +private val testClock = Clock.fixed(now(), UTC) -- 2.7.4