package com.dmdirc.ktirc.io import com.dmdirc.ktirc.IrcClient import com.dmdirc.ktirc.TestConstants import com.dmdirc.ktirc.events.* import com.dmdirc.ktirc.events.handlers.EventHandler import com.dmdirc.ktirc.events.mutators.EventMutator import com.dmdirc.ktirc.messages.MessageProcessor import com.dmdirc.ktirc.model.IrcMessage import com.nhaarman.mockitokotlin2.* import kotlinx.coroutines.channels.Channel import kotlinx.coroutines.runBlocking import org.junit.jupiter.api.Test internal class MessageHandlerTest { private val ircClient = mock() private val nickProcessor = mock { on { commands } doReturn arrayOf("FOO", "NICK") } private val joinProcessor = mock { on { commands } doReturn arrayOf("BAR", "JOIN") } @Test fun `passes message on to correct processor`() = runBlocking { val handler = MessageHandler(listOf(joinProcessor, nickProcessor), emptyList(), mutableListOf()) val message = IrcMessage(emptyMap(), null, "JOIN", emptyList()) with(Channel(1)) { send(message) close() handler.processMessages(ircClient, this) } verify(joinProcessor).process(message) } @Test fun `reads multiple messages`() = runBlocking { val handler = MessageHandler(listOf(joinProcessor, nickProcessor), emptyList(), mutableListOf()) val joinMessage = IrcMessage(emptyMap(), null, "JOIN", emptyList()) val nickMessage = IrcMessage(emptyMap(), null, "NICK", emptyList()) val otherMessage = IrcMessage(emptyMap(), null, "OTHER", emptyList()) with(Channel(3)) { send(joinMessage) send(nickMessage) send(otherMessage) close() handler.processMessages(ircClient, this) } with(inOrder(joinProcessor, nickProcessor)) { verify(joinProcessor).process(joinMessage) verify(nickProcessor).process(nickMessage) } } @Test fun `invokes all event handler with all returned events`() = runBlocking { val eventHandler1 = mock() val eventHandler2 = mock() val handler = MessageHandler(listOf(joinProcessor, nickProcessor), emptyList(), mutableListOf(eventHandler1, eventHandler2)) val joinMessage = IrcMessage(emptyMap(), null, "JOIN", emptyList()) whenever(joinProcessor.process(any())).thenReturn(listOf(ServerConnected(EventMetadata(TestConstants.time)), ServerWelcome(EventMetadata(TestConstants.time), "the.gibson", "acidBurn"))) with(Channel(1)) { send(joinMessage) close() handler.processMessages(ircClient, this) } verify(eventHandler1).processEvent(same(ircClient), isA()) verify(eventHandler1).processEvent(same(ircClient), isA()) verify(eventHandler2).processEvent(same(ircClient), isA()) verify(eventHandler2).processEvent(same(ircClient), isA()) } @Test fun `sends custom events to all handlers`() { val eventHandler1 = mock() val eventHandler2 = mock() val handler = MessageHandler(emptyList(), emptyList(), mutableListOf(eventHandler1, eventHandler2)) handler.handleEvent(ircClient, ServerWelcome(EventMetadata(TestConstants.time), "the.gibson", "acidBurn")) verify(eventHandler1).processEvent(same(ircClient), isA()) verify(eventHandler2).processEvent(same(ircClient), isA()) } @Test fun `sends custom events to all emitters`() { val handler = MessageHandler(emptyList(), emptyList(), emptyList()) val emitter1 = mock<(IrcEvent) -> Unit>() val emitter2 = mock<(IrcEvent) -> Unit>() handler.addEmitter(emitter1) handler.addEmitter(emitter2) handler.handleEvent(ircClient, ServerWelcome(EventMetadata(TestConstants.time), "the.gibson", "acidBurn")) verify(emitter1).invoke(isA()) verify(emitter2).invoke(isA()) } @Test fun `sends events to handlers but not mutators or emitters if process only is true`() { val mutator = mock() val eventHandler1 = mock() val eventHandler2 = mock() val handler = MessageHandler(emptyList(), listOf(mutator), listOf(eventHandler1, eventHandler2)) val emitter = mock<(IrcEvent) -> Unit>() handler.addEmitter(emitter) handler.handleEvent(ircClient, ServerWelcome(EventMetadata(TestConstants.time), "the.gibson", "acidBurn"), true) verify(eventHandler1).processEvent(same(ircClient), isA()) verify(eventHandler2).processEvent(same(ircClient), isA()) verify(emitter, never()).invoke(any()) verify(mutator, never()).mutateEvent(any(), any(), any()) } @Test fun `mutates events in order`() { val eventMutator1 = mock { on { mutateEvent(any(), any(), isA()) } doReturn listOf(ServerReady(EventMetadata(TestConstants.time))) } val eventMutator2 = mock { on { mutateEvent(any(), any(), isA()) } doReturn listOf(ServerConnected(EventMetadata(TestConstants.time))) } val eventHandler = mock() val handler = MessageHandler(emptyList(), listOf(eventMutator1, eventMutator2), mutableListOf(eventHandler)) handler.handleEvent(ircClient, ServerWelcome(EventMetadata(TestConstants.time), "the.gibson", "acidBurn")) verify(eventMutator1).mutateEvent(same(ircClient), same(handler), isA()) verify(eventMutator2).mutateEvent(same(ircClient), same(handler), isA()) verify(eventHandler).processEvent(same(ircClient), isA()) verifyNoMoreInteractions(eventHandler) } @Test fun `allows mutators to fan out events`() { val eventMutator1 = mock { on { mutateEvent(any(), any(), isA()) } doReturn listOf( ServerReady(EventMetadata(TestConstants.time)), ServerConnected(EventMetadata(TestConstants.time)) ) } val eventMutator2 = mock { on { mutateEvent(any(), any(), isA()) } doReturn listOf(ServerReady(EventMetadata(TestConstants.time))) on { mutateEvent(any(), any(), isA()) } doReturn listOf(ServerConnected(EventMetadata(TestConstants.time))) } val eventHandler = mock() val handler = MessageHandler(emptyList(), listOf(eventMutator1, eventMutator2), mutableListOf(eventHandler)) handler.handleEvent(ircClient, ServerWelcome(EventMetadata(TestConstants.time), "the.gibson", "acidBurn")) with(inOrder(eventMutator2, eventHandler)) { verify(eventMutator2).mutateEvent(same(ircClient), same(handler), isA()) verify(eventMutator2).mutateEvent(same(ircClient), same(handler), isA()) verify(eventHandler).processEvent(same(ircClient), isA()) verify(eventHandler).processEvent(same(ircClient), isA()) } } @Test fun `allows mutators to suppress events`() { val eventMutator1 = mock { on { mutateEvent(any(), any(), isA()) } doReturn emptyList() } val eventMutator2 = mock() val eventHandler = mock() val handler = MessageHandler(emptyList(), listOf(eventMutator1, eventMutator2), mutableListOf(eventHandler)) handler.handleEvent(ircClient, ServerWelcome(EventMetadata(TestConstants.time), "the.gibson", "acidBurn")) verify(eventMutator2, never()).mutateEvent(any(), same(handler), any()) verify(eventHandler, never()).processEvent(any(), any()) } }