X-Git-Url: https://git.pterodactylus.net/?a=blobdiff_plain;f=src%2Ftest%2Fkotlin%2Fnet%2Fpterodactylus%2Fsone%2Fcore%2FUpdateCheckerTest.kt;fp=src%2Ftest%2Fkotlin%2Fnet%2Fpterodactylus%2Fsone%2Fcore%2FUpdateCheckerTest.kt;h=3bc8a9e63ef07298c3cd4abe2f7420e20d9d2f63;hb=a252a5d76e8ff8e89da3277a8e9472a499b3bc2b;hp=0000000000000000000000000000000000000000;hpb=135c25fa4317cbf607049935b183bfa71d532278;p=Sone.git diff --git a/src/test/kotlin/net/pterodactylus/sone/core/UpdateCheckerTest.kt b/src/test/kotlin/net/pterodactylus/sone/core/UpdateCheckerTest.kt new file mode 100644 index 0000000..3bc8a9e --- /dev/null +++ b/src/test/kotlin/net/pterodactylus/sone/core/UpdateCheckerTest.kt @@ -0,0 +1,237 @@ +package net.pterodactylus.sone.core + +import com.google.common.eventbus.* +import freenet.client.* +import freenet.keys.* +import freenet.support.io.* +import net.pterodactylus.sone.core.FreenetInterface.* +import net.pterodactylus.sone.core.event.* +import net.pterodactylus.sone.main.* +import net.pterodactylus.sone.test.* +import net.pterodactylus.util.version.Version +import org.hamcrest.MatcherAssert.* +import org.hamcrest.Matchers.equalTo +import org.hamcrest.Matchers.instanceOf +import org.junit.* +import org.mockito.ArgumentCaptor.* +import org.mockito.ArgumentMatchers.any +import org.mockito.Mockito.never +import org.mockito.Mockito.times +import org.mockito.Mockito.verify +import org.mockito.hamcrest.MockitoHamcrest.* +import java.io.* +import kotlin.Long.Companion.MAX_VALUE + +/** + * Unit test for [UpdateChecker]. + */ +class UpdateCheckerTest { + + private val eventBus = mock() + private val freenetInterface = mock() + private val currentVersion = Version(1, 0, 0) + private val pluginHomepage = PluginHomepage("KSK@homepage") + private val updateChecker = UpdateChecker(eventBus, freenetInterface, currentVersion, pluginHomepage) + + @Before + fun startUpdateChecker() { + updateChecker.start() + } + + @Test + fun `new update checker does not have a latest version`() { + assertThat(updateChecker.hasLatestVersion(), equalTo(false)) + assertThat(updateChecker.latestVersion, equalTo(currentVersion)) + } + + @Test + fun `starting an update checker register a usk`() { + verify(freenetInterface).registerUsk(any(FreenetURI::class.java), any(Callback::class.java)) + } + + @Test + fun `stopping an update checker unregisters a usk`() { + updateChecker.stop() + verify(freenetInterface).unregisterUsk(any(FreenetURI::class.java)) + } + + @Test + fun `callback does not download if new edition is not found`() { + setupCallbackWithEdition(MAX_VALUE, false) + verify(freenetInterface, never()).fetchUri(any(FreenetURI::class.java)) + verify(eventBus, never()).post(argThat(instanceOf(UpdateFoundEvent::class.java))) + } + + private fun setupCallbackWithEdition(edition: Long, newKnownGood: Boolean, newSlot: Boolean = false) { + val uri = forClass(FreenetURI::class.java) + val callback = forClass(Callback::class.java) + verify(freenetInterface).registerUsk(uri.capture(), callback.capture()) + callback.value.editionFound(uri.value, edition, newKnownGood, newSlot) + } + + @Test + fun `callback starts if new edition is found`() { + setupFetchResult(createFutureFetchResult()) + setupCallbackWithEdition(MAX_VALUE, true) + verifyAFreenetUriIsFetched() + verifyEventIsFired(Version(99, 0, 0), 11865368297000L, false) + verifyThatUpdateCheckerKnowsLatestVersion(Version(99, 0, 0), 11865368297000L) + } + + private fun createFutureFetchResult(): FetchResult { + val clientMetadata = ClientMetadata("application/xml") + val fetched = ArrayBucket(("# MapConfigurationBackendVersion=1\n" + + "CurrentVersion/Version: 99.0.0\n" + + "CurrentVersion/ReleaseTime: 11865368297000\n" + + "DisruptiveVersion/0.1.2: true").toByteArray()) + return FetchResult(clientMetadata, fetched) + } + + private fun verifyEventIsFired(version: Version, releaseTime: Long, disruptive: Boolean) { + val updateFoundEvent = forClass(UpdateFoundEvent::class.java) + verify(eventBus, times(1)).post(updateFoundEvent.capture()) + assertThat(updateFoundEvent.value.version, equalTo(version)) + assertThat(updateFoundEvent.value.releaseTime, equalTo(releaseTime)) + assertThat(updateFoundEvent.value.isDisruptive, equalTo(disruptive)) + } + + private fun verifyThatUpdateCheckerKnowsLatestVersion(version: Version, releaseTime: Long) { + assertThat(updateChecker.latestVersion, equalTo(version)) + assertThat(updateChecker.latestVersionDate, equalTo(releaseTime)) + assertThat(updateChecker.hasLatestVersion(), equalTo(true)) + } + + @Test + fun `callback does not start if no new edition is found`() { + setupFetchResult(createPastFetchResult()) + setupCallbackWithEdition(updateChecker.latestEdition, true) + verifyAFreenetUriIsFetched() + verifyNoUpdateFoundEventIsFired() + } + + private fun setupFetchResult(pastFetchResult: FetchResult) { + whenever(freenetInterface.fetchUri(any(FreenetURI::class.java))).thenAnswer { invocation -> + val freenetUri = invocation.arguments[0] as FreenetURI + Fetched(freenetUri, pastFetchResult) + } + } + + private fun createPastFetchResult(): FetchResult { + val clientMetadata = ClientMetadata("application/xml") + val fetched = ArrayBucket(("# MapConfigurationBackendVersion=1\n" + + "CurrentVersion/Version: 0.2\n" + + "CurrentVersion/ReleaseTime: 1289417883000").toByteArray()) + return FetchResult(clientMetadata, fetched) + } + + @Test + fun `invalid update file does not start callback`() { + setupFetchResult(createInvalidFetchResult()) + setupCallbackWithEdition(MAX_VALUE, true) + verifyAFreenetUriIsFetched() + verifyNoUpdateFoundEventIsFired() + } + + private fun createInvalidFetchResult(): FetchResult { + val clientMetadata = ClientMetadata("text/plain") + val fetched = ArrayBucket("Some other data.".toByteArray()) + return FetchResult(clientMetadata, fetched) + } + + @Test + fun `non existing properties will not cause update to be found`() { + setupCallbackWithEdition(MAX_VALUE, true) + verifyAFreenetUriIsFetched() + verifyNoUpdateFoundEventIsFired() + } + + private fun verifyNoUpdateFoundEventIsFired() { + verify(eventBus, never()).post(any(UpdateFoundEvent::class.java)) + } + + private fun verifyAFreenetUriIsFetched() { + verify(freenetInterface).fetchUri(any(FreenetURI::class.java)) + } + + @Test + fun `broken bucket does not cause update to be found`() { + setupFetchResult(createBrokenBucketFetchResult()) + setupCallbackWithEdition(MAX_VALUE, true) + verifyAFreenetUriIsFetched() + verifyNoUpdateFoundEventIsFired() + } + + private fun createBrokenBucketFetchResult(): FetchResult { + val clientMetadata = ClientMetadata("text/plain") + val fetched = object : ArrayBucket("Some other data.".toByteArray()) { + override fun getInputStream() = + whenever(mock().read()).thenThrow(IOException()).getMock() + } + return FetchResult(clientMetadata, fetched) + } + + @Test + fun `invalid time does not cause an update to be found`() { + setupFetchResult(createInvalidTimeFetchResult()) + setupCallbackWithEdition(MAX_VALUE, true) + verifyAFreenetUriIsFetched() + verifyNoUpdateFoundEventIsFired() + } + + private fun createInvalidTimeFetchResult(): FetchResult { + val clientMetadata = ClientMetadata("application/xml") + val fetched = ArrayBucket(("# MapConfigurationBackendVersion=1\n" + + "CurrentVersion/Version: 0.2\n" + + "CurrentVersion/ReleaseTime: invalid").toByteArray()) + return FetchResult(clientMetadata, fetched) + } + + @Test + fun `invalid properties does not cause an update to be found`() { + setupFetchResult(createMissingTimeFetchResult()) + setupCallbackWithEdition(MAX_VALUE, true) + verifyAFreenetUriIsFetched() + verifyNoUpdateFoundEventIsFired() + } + + private fun createMissingTimeFetchResult(): FetchResult { + val clientMetadata = ClientMetadata("application/xml") + val fetched = ArrayBucket(("# MapConfigurationBackendVersion=1\nCurrentVersion/Version: 0.2\n").toByteArray()) + return FetchResult(clientMetadata, fetched) + } + + @Test + fun `invalid version does not cause an update to be found`() { + setupFetchResult(createInvalidVersionFetchResult()) + setupCallbackWithEdition(MAX_VALUE, true) + verifyAFreenetUriIsFetched() + verifyNoUpdateFoundEventIsFired() + } + + private fun createInvalidVersionFetchResult(): FetchResult { + val clientMetadata = ClientMetadata("application/xml") + val fetched = ArrayBucket(("# MapConfigurationBackendVersion=1\n" + + "CurrentVersion/Version: foo\n" + + "CurrentVersion/ReleaseTime: 1289417883000").toByteArray()) + return FetchResult(clientMetadata, fetched) + } + + @Test + fun `disruptive version gets notification`() { + setupFetchResult(createDisruptiveVersionFetchResult()) + setupCallbackWithEdition(MAX_VALUE, true) + verifyAFreenetUriIsFetched() + verifyEventIsFired(Version(1, 2, 3), 1289417883000L, true) + verifyThatUpdateCheckerKnowsLatestVersion(Version(1, 2, 3), 1289417883000L) + } + + private fun createDisruptiveVersionFetchResult(): FetchResult { + val clientMetadata = ClientMetadata("application/xml") + val fetched = ArrayBucket(("# MapConfigurationBackendVersion=1\n" + + "CurrentVersion/Version: 1.2.3\n" + + "CurrentVersion/ReleaseTime: 1289417883000\n" + + "DisruptiveVersion/1.2.3: true").toByteArray()) + return FetchResult(clientMetadata, fetched) + } + +}