From: David ‘Bombe’ Roden Date: Tue, 18 Oct 2016 20:08:13 +0000 (+0200) Subject: Add fallback query X-Git-Tag: v2~110 X-Git-Url: https://git.pterodactylus.net/?a=commitdiff_plain;h=0f320a24b3212b30584b8eb6eb364dba04e41c81;p=rhynodge.git Add fallback query --- 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() + } + +}