From 0f320a24b3212b30584b8eb6eb364dba04e41c81 Mon Sep 17 00:00:00 2001 From: =?utf8?q?David=20=E2=80=98Bombe=E2=80=99=20Roden?= Date: Tue, 18 Oct 2016 22:08:13 +0200 Subject: [PATCH] Add fallback query --- .../rhynodge/queries/FallbackQuery.kt | 26 ++++++ .../rhynodge/queries/FallbackQueryTest.kt | 101 +++++++++++++++++++++ 2 files changed, 127 insertions(+) create mode 100644 src/main/java/net/pterodactylus/rhynodge/queries/FallbackQuery.kt create mode 100644 src/test/kotlin/net/pterodactylus/rhynodge/queries/FallbackQueryTest.kt diff --git a/src/main/java/net/pterodactylus/rhynodge/queries/FallbackQuery.kt b/src/main/java/net/pterodactylus/rhynodge/queries/FallbackQuery.kt new file mode 100644 index 0000000..6e5fbd1 --- /dev/null +++ b/src/main/java/net/pterodactylus/rhynodge/queries/FallbackQuery.kt @@ -0,0 +1,26 @@ +package net.pterodactylus.rhynodge.queries + +import net.pterodactylus.rhynodge.Query +import net.pterodactylus.rhynodge.State +import net.pterodactylus.rhynodge.states.FailedState + +/** + * [Query] that can run a number of other [Query]s, returning the first successful [State] that is encountered. + * + * @author [David ‘Bombe’ Roden](mailto:bombe@pterodactylus.net) + */ +class FallbackQuery(private vararg val queries: Query) : Query { + + init { + if (queries.isEmpty()) { + throw IllegalArgumentException("queries must not be empty") + } + } + + override fun state(): State { + var lastFailedState: State = FailedState() + queries.asSequence().map(Query::state).forEach { lastFailedState = it; if (it.success()) return it } + return lastFailedState + } + +} diff --git a/src/test/kotlin/net/pterodactylus/rhynodge/queries/FallbackQueryTest.kt b/src/test/kotlin/net/pterodactylus/rhynodge/queries/FallbackQueryTest.kt new file mode 100644 index 0000000..209454d --- /dev/null +++ b/src/test/kotlin/net/pterodactylus/rhynodge/queries/FallbackQueryTest.kt @@ -0,0 +1,101 @@ +package net.pterodactylus.rhynodge.queries + +import net.pterodactylus.rhynodge.Query +import net.pterodactylus.rhynodge.State +import net.pterodactylus.rhynodge.states.AbstractState +import net.pterodactylus.rhynodge.states.FailedState +import org.hamcrest.MatcherAssert.assertThat +import org.hamcrest.Matchers.`is` +import org.hamcrest.Matchers.sameInstance +import org.junit.Rule +import org.junit.Test +import org.junit.rules.ExpectedException +import org.mockito.Mockito.`when` +import org.mockito.Mockito.mock +import org.mockito.Mockito.never +import org.mockito.Mockito.verify + +/** + * Unit test for [FallbackQuery]. + * + * @author [David ‘Bombe’ Roden](mailto:bombe@pterodactylus.net) + */ +class FallbackQueryTest { + + @JvmField @Rule val expectedException = ExpectedException.none()!! + + private val firstQuery = mock(Query::class.java) + private val secondQuery = mock(Query::class.java) + private val thirdQuery = mock(Query::class.java) + private val query = FallbackQuery(firstQuery, secondQuery, thirdQuery) + + private fun setupQueries(firstState: State = FailedState(), secondState: State = FailedState(), thirdState: State = FailedState()) { + `when`(firstQuery.state()).thenReturn(firstState) + `when`(secondQuery.state()).thenReturn(secondState) + `when`(thirdQuery.state()).thenReturn(thirdState) + } + + @Test + fun `fallback query returns state of third query`() { + val successState: AbstractState = object : AbstractState() {} + setupQueries(thirdState = successState) + assertThat(query.state(), sameInstance(successState)) + } + + @Test + fun `fallback query calls all three queries`() { + val successState: AbstractState = object : AbstractState() {} + setupQueries(thirdState = successState) + query.state() + verify(firstQuery).state() + verify(secondQuery).state() + verify(thirdQuery).state() + } + + @Test + fun `fallback query returns second state`() { + val successState: AbstractState = object : AbstractState() {} + setupQueries(secondState = successState) + assertThat(query.state(), sameInstance(successState)) + } + + @Test + fun `fallback query does not query third query`() { + val successState: AbstractState = object : AbstractState() {} + setupQueries(secondState = successState) + query.state() + verify(firstQuery).state() + verify(secondQuery).state() + verify(thirdQuery, never()).state() + } + + @Test + fun `fallback query returns first state`() { + val successState: AbstractState = object : AbstractState() {} + setupQueries(firstState = successState) + assertThat(query.state(), sameInstance(successState)) + } + + @Test + fun `fallback query does not query second and third query`() { + val successState: AbstractState = object : AbstractState() {} + setupQueries(firstState = successState) + query.state() + verify(firstQuery).state() + verify(secondQuery, never()).state() + verify(thirdQuery, never()).state() + } + + @Test + fun `fallback query returns failed state if no query succeeds`() { + setupQueries() + assertThat(query.state().success(), `is`(false)) + } + + @Test + fun `fallback query can not be created without queries`() { + expectedException.expect(IllegalArgumentException::class.java) + FallbackQuery() + } + +} -- 2.7.4