Browse Source

Event mutators

tags/v0.9.0
Chris Smith 5 years ago
parent
commit
0117d981a2
22 changed files with 435 additions and 264 deletions
  1. 4
    0
      CHANGELOG
  2. 5
    5
      src/main/kotlin/com/dmdirc/ktirc/IrcClientImpl.kt
  3. 2
    3
      src/main/kotlin/com/dmdirc/ktirc/events/handlers/CapabilitiesHandler.kt
  4. 11
    16
      src/main/kotlin/com/dmdirc/ktirc/events/handlers/ChannelStateHandler.kt
  5. 2
    2
      src/main/kotlin/com/dmdirc/ktirc/events/handlers/EventHandler.kt
  6. 2
    3
      src/main/kotlin/com/dmdirc/ktirc/events/handlers/PingHandler.kt
  7. 3
    20
      src/main/kotlin/com/dmdirc/ktirc/events/handlers/ServerStateHandler.kt
  8. 2
    3
      src/main/kotlin/com/dmdirc/ktirc/events/handlers/UserStateHandler.kt
  9. 36
    0
      src/main/kotlin/com/dmdirc/ktirc/events/mutators/ChannelFanOutMutator.kt
  10. 16
    0
      src/main/kotlin/com/dmdirc/ktirc/events/mutators/EventMutator.kt
  11. 36
    0
      src/main/kotlin/com/dmdirc/ktirc/events/mutators/ServerReadyMutator.kt
  12. 15
    9
      src/main/kotlin/com/dmdirc/ktirc/io/MessageHandler.kt
  13. 1
    1
      src/main/kotlin/com/dmdirc/ktirc/messages/MessageProcessor.kt
  14. 1
    1
      src/test/kotlin/com/dmdirc/ktirc/events/handlers/CapabilitiesHandlerTest.kt
  15. 6
    73
      src/test/kotlin/com/dmdirc/ktirc/events/handlers/ChannelStateHandlerTest.kt
  16. 1
    1
      src/test/kotlin/com/dmdirc/ktirc/events/handlers/PingHandlerTest.kt
  17. 79
    0
      src/test/kotlin/com/dmdirc/ktirc/events/handlers/ServerStateHandlerTest.kt
  18. 1
    1
      src/test/kotlin/com/dmdirc/ktirc/events/handlers/UserStateHandlerTest.kt
  19. 102
    0
      src/test/kotlin/com/dmdirc/ktirc/events/mutators/ChannelFanOutMutatorTest.kt
  20. 46
    0
      src/test/kotlin/com/dmdirc/ktirc/events/mutators/ServerReadyMutatorTest.kt
  21. 0
    109
      src/test/kotlin/com/dmdirc/ktirc/handlers/ServerStateHandlerTest.kt
  22. 64
    17
      src/test/kotlin/com/dmdirc/ktirc/io/MessageHandlerTest.kt

+ 4
- 0
CHANGELOG View File

4
    e.g. IrcClient { server("irc.example.com", 6667) }
4
    e.g. IrcClient { server("irc.example.com", 6667) }
5
  * Add behaviour options
5
  * Add behaviour options
6
    * requestModesOnJoin - automatically sends a MODE request when joining a channel
6
    * requestModesOnJoin - automatically sends a MODE request when joining a channel
7
+ * (Internal) Introduced event mutators
8
+   * Event mutators are now responsible for handling changing events in response to state
9
+     e.g. ChannelFanOutMutator creates Channel* events for global quits/nick changes/etc
10
+   * Event handlers now just handle events, and don't return anything
7
 
11
 
8
 v0.8.0
12
 v0.8.0
9
 
13
 

+ 5
- 5
src/main/kotlin/com/dmdirc/ktirc/IrcClientImpl.kt View File

1
 package com.dmdirc.ktirc
1
 package com.dmdirc.ktirc
2
 
2
 
3
 import com.dmdirc.ktirc.events.*
3
 import com.dmdirc.ktirc.events.*
4
-import com.dmdirc.ktirc.handlers.EventHandler
5
-import com.dmdirc.ktirc.handlers.eventHandlers
4
+import com.dmdirc.ktirc.events.handlers.EventHandler
5
+import com.dmdirc.ktirc.events.handlers.eventHandlers
6
+import com.dmdirc.ktirc.events.mutators.eventMutators
6
 import com.dmdirc.ktirc.io.KtorLineBufferedSocket
7
 import com.dmdirc.ktirc.io.KtorLineBufferedSocket
7
 import com.dmdirc.ktirc.io.LineBufferedSocket
8
 import com.dmdirc.ktirc.io.LineBufferedSocket
8
 import com.dmdirc.ktirc.io.MessageHandler
9
 import com.dmdirc.ktirc.io.MessageHandler
42
     override val channelState = ChannelStateMap { caseMapping }
43
     override val channelState = ChannelStateMap { caseMapping }
43
     override val userState = UserState { caseMapping }
44
     override val userState = UserState { caseMapping }
44
 
45
 
45
-    private val messageHandler = MessageHandler(messageProcessors.toList(), eventHandlers.toMutableList())
46
+    private val messageHandler = MessageHandler(messageProcessors, eventMutators, eventHandlers.toMutableList())
46
 
47
 
47
     private val parser = MessageParser()
48
     private val parser = MessageParser()
48
     private var socket: LineBufferedSocket? = null
49
     private var socket: LineBufferedSocket? = null
87
 
88
 
88
     override fun onEvent(handler: (IrcEvent) -> Unit) {
89
     override fun onEvent(handler: (IrcEvent) -> Unit) {
89
         messageHandler.handlers.add(object : EventHandler {
90
         messageHandler.handlers.add(object : EventHandler {
90
-            override fun processEvent(client: IrcClient, event: IrcEvent): List<IrcEvent> {
91
+            override fun processEvent(client: IrcClient, event: IrcEvent) {
91
                 handler(event)
92
                 handler(event)
92
-                return emptyList()
93
             }
93
             }
94
         })
94
         })
95
     }
95
     }

src/main/kotlin/com/dmdirc/ktirc/handlers/CapabilitiesHandler.kt → src/main/kotlin/com/dmdirc/ktirc/events/handlers/CapabilitiesHandler.kt View File

1
-package com.dmdirc.ktirc.handlers
1
+package com.dmdirc.ktirc.events.handlers
2
 
2
 
3
 import com.dmdirc.ktirc.IrcClient
3
 import com.dmdirc.ktirc.IrcClient
4
 import com.dmdirc.ktirc.events.*
4
 import com.dmdirc.ktirc.events.*
15
 
15
 
16
     private val log by logger()
16
     private val log by logger()
17
 
17
 
18
-    override fun processEvent(client: IrcClient, event: IrcEvent): List<IrcEvent> {
18
+    override fun processEvent(client: IrcClient, event: IrcEvent) {
19
         when (event) {
19
         when (event) {
20
             is ServerCapabilitiesReceived -> handleCapabilitiesReceived(client.serverState.capabilities, event.capabilities)
20
             is ServerCapabilitiesReceived -> handleCapabilitiesReceived(client.serverState.capabilities, event.capabilities)
21
             is ServerCapabilitiesFinished -> handleCapabilitiesFinished(client)
21
             is ServerCapabilitiesFinished -> handleCapabilitiesFinished(client)
24
             is SaslMechanismNotAvailableError -> handleSaslMechanismChange(client, event.mechanisms)
24
             is SaslMechanismNotAvailableError -> handleSaslMechanismChange(client, event.mechanisms)
25
             is SaslFinished -> handleSaslFinished(client)
25
             is SaslFinished -> handleSaslFinished(client)
26
         }
26
         }
27
-        return emptyList()
28
     }
27
     }
29
 
28
 
30
     private fun handleCapabilitiesReceived(state: CapabilitiesState, capabilities: Map<Capability, String>) {
29
     private fun handleCapabilitiesReceived(state: CapabilitiesState, capabilities: Map<Capability, String>) {

src/main/kotlin/com/dmdirc/ktirc/handlers/ChannelStateHandler.kt → src/main/kotlin/com/dmdirc/ktirc/events/handlers/ChannelStateHandler.kt View File

1
-package com.dmdirc.ktirc.handlers
1
+package com.dmdirc.ktirc.events.handlers
2
 
2
 
3
 import com.dmdirc.ktirc.IrcClient
3
 import com.dmdirc.ktirc.IrcClient
4
 import com.dmdirc.ktirc.events.*
4
 import com.dmdirc.ktirc.events.*
12
 
12
 
13
     private val log by logger()
13
     private val log by logger()
14
 
14
 
15
-    override fun processEvent(client: IrcClient, event: IrcEvent): List<IrcEvent> {
15
+    override fun processEvent(client: IrcClient, event: IrcEvent) {
16
         when (event) {
16
         when (event) {
17
             is ChannelJoined -> handleJoin(client, event)
17
             is ChannelJoined -> handleJoin(client, event)
18
             is ChannelParted -> handlePart(client, event)
18
             is ChannelParted -> handlePart(client, event)
22
             is ChannelTopicDiscovered -> handleTopicDiscovered(client, event)
22
             is ChannelTopicDiscovered -> handleTopicDiscovered(client, event)
23
             is ChannelTopicMetadataDiscovered -> handleTopicMetadata(client, event)
23
             is ChannelTopicMetadataDiscovered -> handleTopicMetadata(client, event)
24
             is ChannelTopicChanged -> handleTopicChanged(client, event)
24
             is ChannelTopicChanged -> handleTopicChanged(client, event)
25
+            is ChannelQuit -> handleQuit(client, event)
26
+            is ChannelNickChanged -> handleNickChanged(client, event)
25
             is ModeChanged -> handleModeChanged(client, event)
27
             is ModeChanged -> handleModeChanged(client, event)
26
-            is UserQuit -> return handleQuit(client, event)
27
-            is UserNickChanged -> return handleNickChanged(client, event)
28
         }
28
         }
29
-        return emptyList()
30
     }
29
     }
31
 
30
 
32
     private fun handleJoin(client: IrcClient, event: ChannelJoined) {
31
     private fun handleJoin(client: IrcClient, event: ChannelJoined) {
158
         return 1
157
         return 1
159
     }
158
     }
160
 
159
 
161
-    private fun handleQuit(client: IrcClient, event: UserQuit) = sequence {
162
-        client.channelState.forEach {
163
-            if (it.users.contains(event.user.nickname)) {
164
-                it.users -= event.user.nickname
165
-                yield(ChannelQuit(event.time, event.user, it.name, event.reason))
166
-            }
160
+    private fun handleQuit(client: IrcClient, event: ChannelQuit) {
161
+        client.channelState[event.channel]?.let {
162
+            it.users -= event.user.nickname
167
         }
163
         }
168
-    }.toList()
164
+    }
169
 
165
 
170
-    private fun handleNickChanged(client: IrcClient, event: UserNickChanged) = sequence {
171
-        client.channelState.forEach {
166
+    private fun handleNickChanged(client: IrcClient, event: ChannelNickChanged) {
167
+        client.channelState[event.channel]?.let {
172
             it.users[event.user.nickname]?.let { chanUser ->
168
             it.users[event.user.nickname]?.let { chanUser ->
173
                 chanUser.nickname = event.newNick
169
                 chanUser.nickname = event.newNick
174
-                yield(ChannelNickChanged(event.time, event.user, it.name, event.newNick))
175
             }
170
             }
176
         }
171
         }
177
-    }.toList()
172
+    }
178
 
173
 
179
 }
174
 }

src/main/kotlin/com/dmdirc/ktirc/handlers/EventHandler.kt → src/main/kotlin/com/dmdirc/ktirc/events/handlers/EventHandler.kt View File

1
-package com.dmdirc.ktirc.handlers
1
+package com.dmdirc.ktirc.events.handlers
2
 
2
 
3
 import com.dmdirc.ktirc.IrcClient
3
 import com.dmdirc.ktirc.IrcClient
4
 import com.dmdirc.ktirc.events.IrcEvent
4
 import com.dmdirc.ktirc.events.IrcEvent
6
 @FunctionalInterface
6
 @FunctionalInterface
7
 internal interface EventHandler {
7
 internal interface EventHandler {
8
 
8
 
9
-    fun processEvent(client: IrcClient, event: IrcEvent): List<IrcEvent>
9
+    fun processEvent(client: IrcClient, event: IrcEvent)
10
 
10
 
11
 }
11
 }
12
 
12
 

src/main/kotlin/com/dmdirc/ktirc/handlers/PingHandler.kt → src/main/kotlin/com/dmdirc/ktirc/events/handlers/PingHandler.kt View File

1
-package com.dmdirc.ktirc.handlers
1
+package com.dmdirc.ktirc.events.handlers
2
 
2
 
3
 import com.dmdirc.ktirc.IrcClient
3
 import com.dmdirc.ktirc.IrcClient
4
 import com.dmdirc.ktirc.events.IrcEvent
4
 import com.dmdirc.ktirc.events.IrcEvent
7
 
7
 
8
 internal class PingHandler : EventHandler {
8
 internal class PingHandler : EventHandler {
9
 
9
 
10
-    override fun processEvent(client: IrcClient, event: IrcEvent): List<IrcEvent> {
10
+    override fun processEvent(client: IrcClient, event: IrcEvent) {
11
         when (event) {
11
         when (event) {
12
             is PingReceived -> client.sendPong(event.nonce)
12
             is PingReceived -> client.sendPong(event.nonce)
13
         }
13
         }
14
-        return emptyList()
15
     }
14
     }
16
 
15
 
17
 }
16
 }

src/main/kotlin/com/dmdirc/ktirc/handlers/ServerStateHandler.kt → src/main/kotlin/com/dmdirc/ktirc/events/handlers/ServerStateHandler.kt View File

1
-package com.dmdirc.ktirc.handlers
1
+package com.dmdirc.ktirc.events.handlers
2
 
2
 
3
 import com.dmdirc.ktirc.IrcClient
3
 import com.dmdirc.ktirc.IrcClient
4
 import com.dmdirc.ktirc.events.*
4
 import com.dmdirc.ktirc.events.*
5
 import com.dmdirc.ktirc.model.ServerState
5
 import com.dmdirc.ktirc.model.ServerState
6
 import com.dmdirc.ktirc.model.ServerStatus
6
 import com.dmdirc.ktirc.model.ServerStatus
7
-import java.time.LocalDateTime
8
 
7
 
9
 internal class ServerStateHandler : EventHandler {
8
 internal class ServerStateHandler : EventHandler {
10
 
9
 
11
-    override fun processEvent(client: IrcClient, event: IrcEvent): List<IrcEvent> {
10
+    override fun processEvent(client: IrcClient, event: IrcEvent) {
12
         when (event) {
11
         when (event) {
13
             is ServerConnecting -> client.serverState.status = ServerStatus.Connecting
12
             is ServerConnecting -> client.serverState.status = ServerStatus.Connecting
14
             is ServerConnected -> client.serverState.status = ServerStatus.Negotiating
13
             is ServerConnected -> client.serverState.status = ServerStatus.Negotiating
15
             is ServerDisconnected -> client.serverState.status = ServerStatus.Disconnected
14
             is ServerDisconnected -> client.serverState.status = ServerStatus.Disconnected
15
+            is ServerReady -> client.serverState.status = ServerStatus.Ready
16
             is ServerWelcome -> handleWelcome(client.serverState, event.server, event.localNick)
16
             is ServerWelcome -> handleWelcome(client.serverState, event.server, event.localNick)
17
             is ServerFeaturesUpdated -> client.serverState.features.setAll(event.serverFeatures)
17
             is ServerFeaturesUpdated -> client.serverState.features.setAll(event.serverFeatures)
18
-
19
-            // Events that won't trigger a server ready event
20
-            is PingReceived -> Unit
21
-            is ServerCapabilitiesReceived -> Unit
22
-            is ServerCapabilitiesAcknowledged -> Unit
23
-            is ServerCapabilitiesFinished -> Unit
24
-
25
-            else -> return checkReadyState(client, event.time)
26
         }
18
         }
27
-        return emptyList()
28
     }
19
     }
29
 
20
 
30
     private fun handleWelcome(serverState: ServerState, server: String, localNick: String) {
21
     private fun handleWelcome(serverState: ServerState, server: String, localNick: String) {
33
         serverState.localNickname = localNick
24
         serverState.localNickname = localNick
34
     }
25
     }
35
 
26
 
36
-    private fun checkReadyState(client: IrcClient, time: LocalDateTime): List<IrcEvent> {
37
-        if (client.serverState.receivedWelcome && client.serverState.status == ServerStatus.Negotiating) {
38
-            client.serverState.status = ServerStatus.Ready
39
-            return listOf(ServerReady(time))
40
-        }
41
-        return emptyList()
42
-    }
43
-
44
 }
27
 }

src/main/kotlin/com/dmdirc/ktirc/handlers/UserStateHandler.kt → src/main/kotlin/com/dmdirc/ktirc/events/handlers/UserStateHandler.kt View File

1
-package com.dmdirc.ktirc.handlers
1
+package com.dmdirc.ktirc.events.handlers
2
 
2
 
3
 import com.dmdirc.ktirc.IrcClient
3
 import com.dmdirc.ktirc.IrcClient
4
 import com.dmdirc.ktirc.events.*
4
 import com.dmdirc.ktirc.events.*
6
 
6
 
7
 internal class UserStateHandler : EventHandler {
7
 internal class UserStateHandler : EventHandler {
8
 
8
 
9
-    override fun processEvent(client: IrcClient, event: IrcEvent): List<IrcEvent> {
9
+    override fun processEvent(client: IrcClient, event: IrcEvent) {
10
         when (event) {
10
         when (event) {
11
             is ChannelJoined -> handleJoin(client.userState, event)
11
             is ChannelJoined -> handleJoin(client.userState, event)
12
             is ChannelParted -> handlePart(client, event)
12
             is ChannelParted -> handlePart(client, event)
16
             is UserNickChanged -> handleNickChanged(client, event)
16
             is UserNickChanged -> handleNickChanged(client, event)
17
             is UserQuit -> handleQuit(client.userState, event)
17
             is UserQuit -> handleQuit(client.userState, event)
18
         }
18
         }
19
-        return emptyList()
20
     }
19
     }
21
 
20
 
22
     private fun handleJoin(state: UserState, event: ChannelJoined) {
21
     private fun handleJoin(state: UserState, event: ChannelJoined) {

+ 36
- 0
src/main/kotlin/com/dmdirc/ktirc/events/mutators/ChannelFanOutMutator.kt View File

1
+package com.dmdirc.ktirc.events.mutators
2
+
3
+import com.dmdirc.ktirc.IrcClient
4
+import com.dmdirc.ktirc.events.*
5
+
6
+/**
7
+ * "Fans out" global events such as quits and nick changes to each channel a user is in.
8
+ */
9
+internal class ChannelFanOutMutator : EventMutator {
10
+
11
+    override fun mutateEvent(client: IrcClient, event: IrcEvent) = sequence<IrcEvent> {
12
+        yield(event)
13
+        when (event) {
14
+            is UserQuit -> handleQuit(client, event)
15
+            is UserNickChanged -> handleNickChanged(client, event)
16
+        }
17
+    }.toList()
18
+
19
+    private suspend fun SequenceScope<IrcEvent>.handleQuit(client: IrcClient, event: UserQuit) {
20
+        client.channelState.forEach {
21
+            if (it.users.contains(event.user.nickname)) {
22
+                yield(ChannelQuit(event.time, event.user, it.name, event.reason))
23
+            }
24
+        }
25
+    }
26
+
27
+    private suspend fun SequenceScope<IrcEvent>.handleNickChanged(client: IrcClient, event: UserNickChanged) {
28
+        client.channelState.forEach {
29
+            it.users[event.user.nickname]?.let { chanUser ->
30
+                chanUser.nickname = event.newNick
31
+                yield(ChannelNickChanged(event.time, event.user, it.name, event.newNick))
32
+            }
33
+        }
34
+    }
35
+
36
+}

+ 16
- 0
src/main/kotlin/com/dmdirc/ktirc/events/mutators/EventMutator.kt View File

1
+package com.dmdirc.ktirc.events.mutators
2
+
3
+import com.dmdirc.ktirc.IrcClient
4
+import com.dmdirc.ktirc.events.IrcEvent
5
+
6
+@FunctionalInterface
7
+internal interface EventMutator {
8
+
9
+    fun mutateEvent(client: IrcClient, event: IrcEvent): List<IrcEvent>
10
+
11
+}
12
+
13
+internal val eventMutators = listOf(
14
+        ServerReadyMutator(),
15
+        ChannelFanOutMutator()
16
+)

+ 36
- 0
src/main/kotlin/com/dmdirc/ktirc/events/mutators/ServerReadyMutator.kt View File

1
+package com.dmdirc.ktirc.events.mutators
2
+
3
+import com.dmdirc.ktirc.IrcClient
4
+import com.dmdirc.ktirc.events.*
5
+import com.dmdirc.ktirc.model.ServerStatus
6
+
7
+/**
8
+ * Sends a [ServerReady] event once the first line has been received post 001/005/etc.
9
+ */
10
+internal class ServerReadyMutator : EventMutator {
11
+
12
+    /** Events that won't trigger a 'server ready' event to be sent. */
13
+    private val excludedEvents = listOf(
14
+            ServerConnecting::class,
15
+            ServerConnected::class,
16
+            ServerDisconnected::class,
17
+            ServerWelcome::class,
18
+            ServerReady::class,
19
+            ServerFeaturesUpdated::class,
20
+
21
+            PingReceived::class,
22
+            ServerCapabilitiesReceived::class,
23
+            ServerCapabilitiesAcknowledged::class,
24
+            ServerCapabilitiesFinished::class
25
+    )
26
+
27
+    override fun mutateEvent(client: IrcClient, event: IrcEvent): List<IrcEvent> = sequence {
28
+        if (client.serverState.receivedWelcome
29
+                && client.serverState.status == ServerStatus.Negotiating
30
+                && event::class !in excludedEvents) {
31
+            yield(ServerReady(event.time))
32
+        }
33
+        yield(event)
34
+    }.toList()
35
+
36
+}

+ 15
- 9
src/main/kotlin/com/dmdirc/ktirc/io/MessageHandler.kt View File

1
 package com.dmdirc.ktirc.io
1
 package com.dmdirc.ktirc.io
2
 
2
 
3
 import com.dmdirc.ktirc.IrcClient
3
 import com.dmdirc.ktirc.IrcClient
4
-import com.dmdirc.ktirc.handlers.EventHandler
5
 import com.dmdirc.ktirc.events.IrcEvent
4
 import com.dmdirc.ktirc.events.IrcEvent
5
+import com.dmdirc.ktirc.events.handlers.EventHandler
6
+import com.dmdirc.ktirc.events.mutators.EventMutator
6
 import com.dmdirc.ktirc.messages.MessageProcessor
7
 import com.dmdirc.ktirc.messages.MessageProcessor
7
 import com.dmdirc.ktirc.model.IrcMessage
8
 import com.dmdirc.ktirc.model.IrcMessage
8
 import com.dmdirc.ktirc.util.logger
9
 import com.dmdirc.ktirc.util.logger
9
 import kotlinx.coroutines.channels.ReceiveChannel
10
 import kotlinx.coroutines.channels.ReceiveChannel
10
 
11
 
11
-internal class MessageHandler(private val processors: List<MessageProcessor>, val handlers: MutableList<EventHandler>) {
12
+internal class MessageHandler(
13
+        private val processors: List<MessageProcessor>,
14
+        private val mutators: List<EventMutator>,
15
+        val handlers: MutableList<EventHandler>) {
12
 
16
 
13
     private val log by logger()
17
     private val log by logger()
14
 
18
 
15
     suspend fun processMessages(ircClient: IrcClient, messages: ReceiveChannel<IrcMessage>) {
19
     suspend fun processMessages(ircClient: IrcClient, messages: ReceiveChannel<IrcMessage>) {
16
         for (message in messages) {
20
         for (message in messages) {
17
-            message.toEvents().forEach { event -> emitEvent(ircClient, event) }
21
+            emitEvents(ircClient, message.toEvents())
18
         }
22
         }
19
     }
23
     }
20
 
24
 
21
-    fun emitEvent(ircClient: IrcClient, ircEvent: IrcEvent) {
22
-        log.fine { "Dispatching event of type ${ircEvent::class}" }
23
-        handlers.forEach { handler ->
24
-            handler.processEvent(ircClient, ircEvent).forEach {
25
-                emitEvent(ircClient, it)
26
-            }
25
+    fun emitEvent(ircClient: IrcClient, ircEvent: IrcEvent) = emitEvents(ircClient, listOf(ircEvent))
26
+
27
+    fun emitEvents(ircClient: IrcClient, ircEvents: List<IrcEvent>) {
28
+        mutators.fold(ircEvents) { events, mutator ->
29
+            events.flatMap { mutator.mutateEvent(ircClient, it) }
30
+        }.forEach { event ->
31
+            log.fine { "Dispatching event of type ${event::class}" }
32
+            handlers.forEach { it.processEvent(ircClient, event) }
27
         }
33
         }
28
     }
34
     }
29
 
35
 

+ 1
- 1
src/main/kotlin/com/dmdirc/ktirc/messages/MessageProcessor.kt View File

17
 
17
 
18
 }
18
 }
19
 
19
 
20
-internal val messageProcessors = setOf(
20
+internal val messageProcessors = listOf(
21
         AccountProcessor(),
21
         AccountProcessor(),
22
         AuthenticationProcessor(),
22
         AuthenticationProcessor(),
23
         CapabilityProcessor(),
23
         CapabilityProcessor(),

src/test/kotlin/com/dmdirc/ktirc/handlers/CapabilitiesHandlerTest.kt → src/test/kotlin/com/dmdirc/ktirc/events/handlers/CapabilitiesHandlerTest.kt View File

1
-package com.dmdirc.ktirc.handlers
1
+package com.dmdirc.ktirc.events.handlers
2
 
2
 
3
 import com.dmdirc.ktirc.IrcClient
3
 import com.dmdirc.ktirc.IrcClient
4
 import com.dmdirc.ktirc.TestConstants
4
 import com.dmdirc.ktirc.TestConstants

src/test/kotlin/com/dmdirc/ktirc/handlers/ChannelStateHandlerTest.kt → src/test/kotlin/com/dmdirc/ktirc/events/handlers/ChannelStateHandlerTest.kt View File

1
-package com.dmdirc.ktirc.handlers
1
+package com.dmdirc.ktirc.events.handlers
2
 
2
 
3
 import com.dmdirc.ktirc.BehaviourConfig
3
 import com.dmdirc.ktirc.BehaviourConfig
4
 import com.dmdirc.ktirc.IrcClient
4
 import com.dmdirc.ktirc.IrcClient
216
     }
216
     }
217
 
217
 
218
     @Test
218
     @Test
219
-    fun `removes user from all channel member lists for quits`() {
219
+    fun `removes user from channel member lists for quits`() {
220
         with (ChannelState("#thegibson") { CaseMapping.Rfc }) {
220
         with (ChannelState("#thegibson") { CaseMapping.Rfc }) {
221
             users += ChannelUser("ZeroCool")
221
             users += ChannelUser("ZeroCool")
222
             channelStateMap += this
222
             channelStateMap += this
232
             channelStateMap += this
232
             channelStateMap += this
233
         }
233
         }
234
 
234
 
235
-        handler.processEvent(ircClient, UserQuit(TestConstants.time, User("zerocool", "dade", "root.localhost")))
235
+        handler.processEvent(ircClient, ChannelQuit(TestConstants.time, User("zerocool", "dade", "root.localhost"), "#thegibson"))
236
+        handler.processEvent(ircClient, ChannelQuit(TestConstants.time, User("zerocool", "dade", "root.localhost"), "#dumpsterdiving"))
236
 
237
 
237
         assertFalse("zerocool" in channelStateMap["#thegibson"]!!.users)
238
         assertFalse("zerocool" in channelStateMap["#thegibson"]!!.users)
238
         assertFalse("zerocool" in channelStateMap["#dumpsterdiving"]!!.users)
239
         assertFalse("zerocool" in channelStateMap["#dumpsterdiving"]!!.users)
240
         assertTrue("acidburn" in channelStateMap["#chat"]!!.users)
241
         assertTrue("acidburn" in channelStateMap["#chat"]!!.users)
241
     }
242
     }
242
 
243
 
243
-
244
-    @Test
245
-    fun `raises ChannelQuit event for each channel a user quits from`() {
246
-        with (ChannelState("#thegibson") { CaseMapping.Rfc }) {
247
-            users += ChannelUser("ZeroCool")
248
-            channelStateMap += this
249
-        }
250
-
251
-        with (ChannelState("#dumpsterdiving") { CaseMapping.Rfc }) {
252
-            users += ChannelUser("ZeroCool")
253
-            channelStateMap += this
254
-        }
255
-
256
-        with (ChannelState("#chat") { CaseMapping.Rfc }) {
257
-            users += ChannelUser("AcidBurn")
258
-            channelStateMap += this
259
-        }
260
-
261
-        val events = handler.processEvent(ircClient, UserQuit(TestConstants.time, User("zerocool", "dade", "root.localhost"), "Hack the planet!"))
262
-
263
-        val names = mutableListOf<String>()
264
-        assertEquals(2, events.size)
265
-        events.forEach { event ->
266
-            (event as ChannelQuit).let {
267
-                assertEquals(TestConstants.time, it.time)
268
-                assertEquals("zerocool", it.user.nickname)
269
-                assertEquals("Hack the planet!", it.reason)
270
-                names.add(it.channel)
271
-            }
272
-        }
273
-
274
-        assertTrue("#thegibson" in names)
275
-        assertTrue("#dumpsterdiving" in names)
276
-    }
277
-
278
     @Test
244
     @Test
279
     fun `renames user in channel member list for nick changes`() {
245
     fun `renames user in channel member list for nick changes`() {
280
         val channel = ChannelState("#thegibson") { CaseMapping.Rfc }
246
         val channel = ChannelState("#thegibson") { CaseMapping.Rfc }
281
         channel.users += ChannelUser("acidBurn")
247
         channel.users += ChannelUser("acidBurn")
282
         channelStateMap += channel
248
         channelStateMap += channel
283
 
249
 
284
-        handler.processEvent(ircClient, UserNickChanged(TestConstants.time, User("acidburn", "libby", "root.localhost"), "acidB"))
250
+        handler.processEvent(ircClient, ChannelNickChanged(TestConstants.time, User("acidburn", "libby", "root.localhost"), "#thegibson", "acidB"))
251
+        handler.processEvent(ircClient, ChannelNickChanged(TestConstants.time, User("acidburn", "libby", "root.localhost"), "#dumpsterdiving", "acidB"))
285
 
252
 
286
         assertFalse("acidBurn" in channel.users)
253
         assertFalse("acidBurn" in channel.users)
287
         assertTrue("acidB" in channel.users)
254
         assertTrue("acidB" in channel.users)
288
         assertEquals("acidB", channel.users["acidB"]?.nickname)
255
         assertEquals("acidB", channel.users["acidB"]?.nickname)
289
     }
256
     }
290
 
257
 
291
-    @Test
292
-    fun `raises ChannelNickChanged event for each channel a user changes nicks in`() {
293
-        with (ChannelState("#thegibson") { CaseMapping.Rfc }) {
294
-            users += ChannelUser("ZeroCool")
295
-            channelStateMap += this
296
-        }
297
-
298
-        with (ChannelState("#dumpsterdiving") { CaseMapping.Rfc }) {
299
-            users += ChannelUser("ZeroCool")
300
-            channelStateMap += this
301
-        }
302
-
303
-        with (ChannelState("#chat") { CaseMapping.Rfc }) {
304
-            users += ChannelUser("AcidBurn")
305
-            channelStateMap += this
306
-        }
307
-
308
-        val events = handler.processEvent(ircClient, UserNickChanged(TestConstants.time, User("zerocool", "dade", "root.localhost"), "zer0c00l"))
309
-
310
-        val names = mutableListOf<String>()
311
-        assertEquals(2, events.size)
312
-        events.forEach { event ->
313
-            (event as ChannelNickChanged).let {
314
-                assertEquals(TestConstants.time, it.time)
315
-                assertEquals("zerocool", it.user.nickname)
316
-                assertEquals("zer0c00l", it.newNick)
317
-                names.add(it.channel)
318
-            }
319
-        }
320
-
321
-        assertTrue("#thegibson" in names)
322
-        assertTrue("#dumpsterdiving" in names)
323
-    }
324
-
325
     @Test
258
     @Test
326
     fun `sets mode discovered flag when discovered mode event received`() {
259
     fun `sets mode discovered flag when discovered mode event received`() {
327
         val channel = ChannelState("#thegibson") { CaseMapping.Rfc }
260
         val channel = ChannelState("#thegibson") { CaseMapping.Rfc }

src/test/kotlin/com/dmdirc/ktirc/handlers/PingHandlerTest.kt → src/test/kotlin/com/dmdirc/ktirc/events/handlers/PingHandlerTest.kt View File

1
-package com.dmdirc.ktirc.handlers
1
+package com.dmdirc.ktirc.events.handlers
2
 
2
 
3
 import com.dmdirc.ktirc.IrcClient
3
 import com.dmdirc.ktirc.IrcClient
4
 import com.dmdirc.ktirc.TestConstants
4
 import com.dmdirc.ktirc.TestConstants

+ 79
- 0
src/test/kotlin/com/dmdirc/ktirc/events/handlers/ServerStateHandlerTest.kt View File

1
+package com.dmdirc.ktirc.events.handlers
2
+
3
+import com.dmdirc.ktirc.IrcClient
4
+import com.dmdirc.ktirc.TestConstants
5
+import com.dmdirc.ktirc.events.*
6
+import com.dmdirc.ktirc.model.ServerFeature
7
+import com.dmdirc.ktirc.model.ServerFeatureMap
8
+import com.dmdirc.ktirc.model.ServerState
9
+import com.dmdirc.ktirc.model.ServerStatus
10
+import com.nhaarman.mockitokotlin2.doReturn
11
+import com.nhaarman.mockitokotlin2.mock
12
+import org.junit.jupiter.api.Assertions.*
13
+import org.junit.jupiter.api.Test
14
+
15
+internal class ServerStateHandlerTest {
16
+
17
+    private val serverState = ServerState("", "")
18
+    private val ircClient = mock<IrcClient> {
19
+        on { serverState } doReturn serverState
20
+    }
21
+
22
+    private val handler = ServerStateHandler()
23
+
24
+    @Test
25
+    fun `sets local nickname on welcome event`() {
26
+        handler.processEvent(ircClient, ServerWelcome(TestConstants.time, "the.gibson", "acidBurn"))
27
+        assertEquals("acidBurn", serverState.localNickname)
28
+    }
29
+
30
+    @Test
31
+    fun `sets server name on welcome event`() {
32
+        handler.processEvent(ircClient, ServerWelcome(TestConstants.time, "the.gibson", "acidBurn"))
33
+        assertEquals("the.gibson", serverState.serverName)
34
+    }
35
+
36
+    @Test
37
+    fun `sets receivedWelcome on welcome event`() {
38
+        handler.processEvent(ircClient, ServerWelcome(TestConstants.time, "the.gibson", "acidBurn"))
39
+        assertTrue(serverState.receivedWelcome)
40
+    }
41
+
42
+    @Test
43
+    fun `sets state to connecting on event`() {
44
+        handler.processEvent(ircClient, ServerConnecting(TestConstants.time))
45
+        assertEquals(ServerStatus.Connecting, serverState.status)
46
+    }
47
+
48
+    @Test
49
+    fun `sets state to disconnected on event`() {
50
+        serverState.status = ServerStatus.Ready
51
+        handler.processEvent(ircClient, ServerDisconnected(TestConstants.time))
52
+        assertEquals(ServerStatus.Disconnected, serverState.status)
53
+    }
54
+
55
+    @Test
56
+    fun `sets state to negotiating on connected`() {
57
+        handler.processEvent(ircClient, ServerConnected(TestConstants.time))
58
+        assertEquals(ServerStatus.Negotiating, serverState.status)
59
+    }
60
+
61
+    @Test
62
+    fun `sets state to ready on ServerReady`() {
63
+        handler.processEvent(ircClient, ServerReady(TestConstants.time))
64
+        assertEquals(ServerStatus.Ready, serverState.status)
65
+    }
66
+
67
+    @Test
68
+    fun `updates features on features event`() {
69
+        val features = ServerFeatureMap()
70
+        features[ServerFeature.ChannelModes] = arrayOf("abc", "def")
71
+        features[ServerFeature.WhoxSupport] = true
72
+
73
+        handler.processEvent(ircClient, ServerFeaturesUpdated(TestConstants.time, features))
74
+
75
+        assertArrayEquals(arrayOf("abc", "def"), serverState.features[ServerFeature.ChannelModes])
76
+        assertEquals(true, serverState.features[ServerFeature.WhoxSupport])
77
+    }
78
+
79
+}

src/test/kotlin/com/dmdirc/ktirc/handlers/UserStateHandlerTest.kt → src/test/kotlin/com/dmdirc/ktirc/events/handlers/UserStateHandlerTest.kt View File

1
-package com.dmdirc.ktirc.handlers
1
+package com.dmdirc.ktirc.events.handlers
2
 
2
 
3
 import com.dmdirc.ktirc.IrcClient
3
 import com.dmdirc.ktirc.IrcClient
4
 import com.dmdirc.ktirc.TestConstants
4
 import com.dmdirc.ktirc.TestConstants

+ 102
- 0
src/test/kotlin/com/dmdirc/ktirc/events/mutators/ChannelFanOutMutatorTest.kt View File

1
+package com.dmdirc.ktirc.events.mutators
2
+
3
+import com.dmdirc.ktirc.BehaviourConfig
4
+import com.dmdirc.ktirc.IrcClient
5
+import com.dmdirc.ktirc.TestConstants
6
+import com.dmdirc.ktirc.events.ChannelNickChanged
7
+import com.dmdirc.ktirc.events.ChannelQuit
8
+import com.dmdirc.ktirc.events.UserNickChanged
9
+import com.dmdirc.ktirc.events.UserQuit
10
+import com.dmdirc.ktirc.io.CaseMapping
11
+import com.dmdirc.ktirc.model.*
12
+import com.nhaarman.mockitokotlin2.doReturn
13
+import com.nhaarman.mockitokotlin2.mock
14
+import org.junit.jupiter.api.Assertions
15
+import org.junit.jupiter.api.Test
16
+
17
+internal class ChannelFanOutMutatorTest {
18
+
19
+    private val mutator = ChannelFanOutMutator()
20
+    private val channelStateMap = ChannelStateMap { CaseMapping.Rfc }
21
+    private val serverState = ServerState("", "")
22
+    private val behaviour = BehaviourConfig()
23
+    private val ircClient = mock<IrcClient> {
24
+        on { serverState } doReturn serverState
25
+        on { channelState } doReturn channelStateMap
26
+        on { behaviour } doReturn behaviour
27
+        on { isLocalUser(User("acidburn", "libby", "root.localhost")) } doReturn true
28
+        on { isLocalUser("acidburn") } doReturn  true
29
+    }
30
+
31
+    @Test
32
+    fun `raises ChannelQuit event for each channel a user quits from`() {
33
+        with (ChannelState("#thegibson") { CaseMapping.Rfc }) {
34
+            users += ChannelUser("ZeroCool")
35
+            channelStateMap += this
36
+        }
37
+
38
+        with (ChannelState("#dumpsterdiving") { CaseMapping.Rfc }) {
39
+            users += ChannelUser("ZeroCool")
40
+            channelStateMap += this
41
+        }
42
+
43
+        with (ChannelState("#chat") { CaseMapping.Rfc }) {
44
+            users += ChannelUser("AcidBurn")
45
+            channelStateMap += this
46
+        }
47
+
48
+        val quitEvent = UserQuit(TestConstants.time, User("zerocool", "dade", "root.localhost"), "Hack the planet!")
49
+        val events = mutator.mutateEvent(ircClient, quitEvent)
50
+
51
+        val names = mutableListOf<String>()
52
+        Assertions.assertEquals(3, events.size)
53
+        Assertions.assertSame(quitEvent, events[0])
54
+        events.subList(1, events.size).forEach { event ->
55
+            (event as ChannelQuit).let {
56
+                Assertions.assertEquals(TestConstants.time, it.time)
57
+                Assertions.assertEquals("zerocool", it.user.nickname)
58
+                Assertions.assertEquals("Hack the planet!", it.reason)
59
+                names.add(it.channel)
60
+            }
61
+        }
62
+
63
+        Assertions.assertTrue("#thegibson" in names)
64
+        Assertions.assertTrue("#dumpsterdiving" in names)
65
+    }
66
+
67
+    @Test
68
+    fun `raises ChannelNickChanged event for each channel a user changes nicks in`() {
69
+        with (ChannelState("#thegibson") { CaseMapping.Rfc }) {
70
+            users += ChannelUser("ZeroCool")
71
+            channelStateMap += this
72
+        }
73
+
74
+        with (ChannelState("#dumpsterdiving") { CaseMapping.Rfc }) {
75
+            users += ChannelUser("ZeroCool")
76
+            channelStateMap += this
77
+        }
78
+
79
+        with (ChannelState("#chat") { CaseMapping.Rfc }) {
80
+            users += ChannelUser("AcidBurn")
81
+            channelStateMap += this
82
+        }
83
+
84
+        val nickEvent = UserNickChanged(TestConstants.time, User("zerocool", "dade", "root.localhost"), "zer0c00l")
85
+        val events = mutator.mutateEvent(ircClient, nickEvent)
86
+
87
+        val names = mutableListOf<String>()
88
+        Assertions.assertEquals(3, events.size)
89
+        Assertions.assertSame(nickEvent, events[0])
90
+        events.subList(1, events.size).forEach { event ->
91
+            (event as ChannelNickChanged).let {
92
+                Assertions.assertEquals(TestConstants.time, it.time)
93
+                Assertions.assertEquals("zerocool", it.user.nickname)
94
+                Assertions.assertEquals("zer0c00l", it.newNick)
95
+                names.add(it.channel)
96
+            }
97
+        }
98
+
99
+        Assertions.assertTrue("#thegibson" in names)
100
+        Assertions.assertTrue("#dumpsterdiving" in names)
101
+    }
102
+}

+ 46
- 0
src/test/kotlin/com/dmdirc/ktirc/events/mutators/ServerReadyMutatorTest.kt View File

1
+package com.dmdirc.ktirc.events.mutators
2
+
3
+import com.dmdirc.ktirc.IrcClient
4
+import com.dmdirc.ktirc.TestConstants
5
+import com.dmdirc.ktirc.events.*
6
+import com.dmdirc.ktirc.model.ServerState
7
+import com.dmdirc.ktirc.model.ServerStatus
8
+import com.dmdirc.ktirc.model.User
9
+import com.nhaarman.mockitokotlin2.doReturn
10
+import com.nhaarman.mockitokotlin2.mock
11
+import org.junit.jupiter.api.Assertions.*
12
+import org.junit.jupiter.api.Test
13
+
14
+internal class ServerReadyMutatorTest {
15
+
16
+    private val serverState = ServerState("", "")
17
+    private val ircClient = mock<IrcClient> {
18
+        on { serverState } doReturn serverState
19
+    }
20
+
21
+    private val mutator = ServerReadyMutator()
22
+
23
+
24
+    @Test
25
+    fun `emits event on receiving post-005 line`() {
26
+        ircClient.serverState.receivedWelcome = true
27
+        ircClient.serverState.status = ServerStatus.Negotiating
28
+
29
+        listOf(
30
+                ServerWelcome(TestConstants.time, "the.gibson", "acidBurn"),
31
+                PingReceived(TestConstants.time, "1234".toByteArray()),
32
+                ServerCapabilitiesReceived(TestConstants.time, emptyMap()),
33
+                ServerCapabilitiesAcknowledged(TestConstants.time, emptyMap()),
34
+                ServerCapabilitiesFinished(TestConstants.time)
35
+        ).forEach {
36
+            assertEquals(1, mutator.mutateEvent(ircClient, it).size)
37
+        }
38
+
39
+        val event = MessageReceived(TestConstants.time, User("zeroCool"), "acidBurn", "Welcome!")
40
+        val events = mutator.mutateEvent(ircClient, event)
41
+        assertEquals(2, events.size)
42
+        assertSame(event, events[1])
43
+        assertTrue(events[0] is ServerReady)
44
+    }
45
+
46
+}

+ 0
- 109
src/test/kotlin/com/dmdirc/ktirc/handlers/ServerStateHandlerTest.kt View File

1
-package com.dmdirc.ktirc.handlers
2
-
3
-import com.dmdirc.ktirc.IrcClient
4
-import com.dmdirc.ktirc.TestConstants
5
-import com.dmdirc.ktirc.events.*
6
-import com.dmdirc.ktirc.model.*
7
-import com.nhaarman.mockitokotlin2.doReturn
8
-import com.nhaarman.mockitokotlin2.mock
9
-import kotlinx.coroutines.runBlocking
10
-import org.junit.jupiter.api.Assertions.*
11
-import org.junit.jupiter.api.Test
12
-
13
-internal class ServerStateHandlerTest {
14
-
15
-    private val serverState = ServerState("", "")
16
-    private val ircClient = mock<IrcClient> {
17
-        on { serverState } doReturn serverState
18
-    }
19
-
20
-    private val handler = ServerStateHandler()
21
-
22
-    @Test
23
-    fun `ServerStateHandler sets local nickname on welcome event`() = runBlocking {
24
-        handler.processEvent(ircClient, ServerWelcome(TestConstants.time, "the.gibson", "acidBurn"))
25
-        assertEquals("acidBurn", serverState.localNickname)
26
-    }
27
-
28
-    @Test
29
-    fun `ServerStateHandler sets server name on welcome event`() = runBlocking {
30
-        handler.processEvent(ircClient, ServerWelcome(TestConstants.time, "the.gibson", "acidBurn"))
31
-        assertEquals("the.gibson", serverState.serverName)
32
-    }
33
-
34
-    @Test
35
-    fun `ServerStateHandler sets receivedWelcome on welcome event`() = runBlocking {
36
-        handler.processEvent(ircClient, ServerWelcome(TestConstants.time, "the.gibson", "acidBurn"))
37
-        assertTrue(serverState.receivedWelcome)
38
-    }
39
-
40
-    @Test
41
-    fun `ServerStateHandler sets state to connecting on event`() = runBlocking {
42
-        handler.processEvent(ircClient, ServerConnecting(TestConstants.time))
43
-        assertEquals(ServerStatus.Connecting, serverState.status)
44
-    }
45
-
46
-    @Test
47
-    fun `ServerStateHandler sets state to disconnected on event`() = runBlocking {
48
-        serverState.status = ServerStatus.Ready
49
-        handler.processEvent(ircClient, ServerDisconnected(TestConstants.time))
50
-        assertEquals(ServerStatus.Disconnected, serverState.status)
51
-    }
52
-
53
-    @Test
54
-    fun `ServerStateHandler sets state to negotiating on connected`() = runBlocking {
55
-        handler.processEvent(ircClient, ServerConnected(TestConstants.time))
56
-        assertEquals(ServerStatus.Negotiating, serverState.status)
57
-    }
58
-
59
-    @Test
60
-    fun `ServerStateHandler sets server state to ready on receiving post-005 line`() = runBlocking {
61
-        ircClient.serverState.status = ServerStatus.Negotiating
62
-
63
-        listOf(
64
-                ServerWelcome(TestConstants.time, "the.gibson", "acidBurn"),
65
-                PingReceived(TestConstants.time, "1234".toByteArray()),
66
-                ServerCapabilitiesReceived(TestConstants.time, emptyMap()),
67
-                ServerCapabilitiesAcknowledged(TestConstants.time, emptyMap()),
68
-                ServerCapabilitiesFinished(TestConstants.time),
69
-                MessageReceived(TestConstants.time, User("zeroCool"), "acidBurn", "Welcome!")
70
-        ).forEach {
71
-            assertEquals(ServerStatus.Negotiating, serverState.status)
72
-            handler.processEvent(ircClient, it)
73
-        }
74
-
75
-        assertEquals(ServerStatus.Ready, serverState.status)
76
-    }
77
-
78
-    @Test
79
-    fun `ServerStateHandler emits event on receiving post-005 line`() = runBlocking {
80
-        ircClient.serverState.status = ServerStatus.Negotiating
81
-
82
-        listOf(
83
-                ServerWelcome(TestConstants.time, "the.gibson", "acidBurn"),
84
-                PingReceived(TestConstants.time, "1234".toByteArray()),
85
-                ServerCapabilitiesReceived(TestConstants.time, emptyMap()),
86
-                ServerCapabilitiesAcknowledged(TestConstants.time, emptyMap()),
87
-                ServerCapabilitiesFinished(TestConstants.time)
88
-        ).forEach {
89
-            assertTrue(handler.processEvent(ircClient, it).isEmpty())
90
-        }
91
-
92
-        val events = handler.processEvent(ircClient, MessageReceived(TestConstants.time, User("zeroCool"), "acidBurn", "Welcome!"))
93
-        assertEquals(1, events.size)
94
-        assertTrue(events[0] is ServerReady)
95
-    }
96
-
97
-    @Test
98
-    fun `ServerStateHandler updates features on features event`() = runBlocking {
99
-        val features = ServerFeatureMap()
100
-        features[ServerFeature.ChannelModes] = arrayOf("abc", "def")
101
-        features[ServerFeature.WhoxSupport] = true
102
-
103
-        handler.processEvent(ircClient, ServerFeaturesUpdated(TestConstants.time, features))
104
-
105
-        assertArrayEquals(arrayOf("abc", "def"), serverState.features[ServerFeature.ChannelModes])
106
-        assertEquals(true, serverState.features[ServerFeature.WhoxSupport])
107
-    }
108
-
109
-}

+ 64
- 17
src/test/kotlin/com/dmdirc/ktirc/io/MessageHandlerTest.kt View File

2
 
2
 
3
 import com.dmdirc.ktirc.IrcClient
3
 import com.dmdirc.ktirc.IrcClient
4
 import com.dmdirc.ktirc.TestConstants
4
 import com.dmdirc.ktirc.TestConstants
5
-import com.dmdirc.ktirc.handlers.EventHandler
6
 import com.dmdirc.ktirc.events.ServerConnected
5
 import com.dmdirc.ktirc.events.ServerConnected
7
 import com.dmdirc.ktirc.events.ServerReady
6
 import com.dmdirc.ktirc.events.ServerReady
8
 import com.dmdirc.ktirc.events.ServerWelcome
7
 import com.dmdirc.ktirc.events.ServerWelcome
8
+import com.dmdirc.ktirc.events.handlers.EventHandler
9
+import com.dmdirc.ktirc.events.mutators.EventMutator
9
 import com.dmdirc.ktirc.messages.MessageProcessor
10
 import com.dmdirc.ktirc.messages.MessageProcessor
10
 import com.dmdirc.ktirc.model.IrcMessage
11
 import com.dmdirc.ktirc.model.IrcMessage
11
 import com.nhaarman.mockitokotlin2.*
12
 import com.nhaarman.mockitokotlin2.*
26
     }
27
     }
27
 
28
 
28
     @Test
29
     @Test
29
-    fun `MessageHandler passes message on to correct processor`() = runBlocking<Unit> {
30
-        val handler = MessageHandler(listOf(joinProcessor, nickProcessor), mutableListOf())
30
+    fun `passes message on to correct processor`() = runBlocking<Unit> {
31
+        val handler = MessageHandler(listOf(joinProcessor, nickProcessor), emptyList(), mutableListOf())
31
         val message = IrcMessage(emptyMap(), null, "JOIN", emptyList())
32
         val message = IrcMessage(emptyMap(), null, "JOIN", emptyList())
32
 
33
 
33
         with(Channel<IrcMessage>(1)) {
34
         with(Channel<IrcMessage>(1)) {
40
     }
41
     }
41
 
42
 
42
     @Test
43
     @Test
43
-    fun `MessageHandler reads multiple messages`() = runBlocking<Unit> {
44
-        val handler = MessageHandler(listOf(joinProcessor, nickProcessor), mutableListOf())
44
+    fun `reads multiple messages`() = runBlocking<Unit> {
45
+        val handler = MessageHandler(listOf(joinProcessor, nickProcessor), emptyList(), mutableListOf())
45
         val joinMessage = IrcMessage(emptyMap(), null, "JOIN", emptyList())
46
         val joinMessage = IrcMessage(emptyMap(), null, "JOIN", emptyList())
46
         val nickMessage = IrcMessage(emptyMap(), null, "NICK", emptyList())
47
         val nickMessage = IrcMessage(emptyMap(), null, "NICK", emptyList())
47
         val otherMessage = IrcMessage(emptyMap(), null, "OTHER", emptyList())
48
         val otherMessage = IrcMessage(emptyMap(), null, "OTHER", emptyList())
61
     }
62
     }
62
 
63
 
63
     @Test
64
     @Test
64
-    fun `MessageHandler invokes all event handler with all returned events`() = runBlocking<Unit> {
65
+    fun `invokes all event handler with all returned events`() = runBlocking {
65
         val eventHandler1 = mock<EventHandler>()
66
         val eventHandler1 = mock<EventHandler>()
66
         val eventHandler2 = mock<EventHandler>()
67
         val eventHandler2 = mock<EventHandler>()
67
-        val handler = MessageHandler(listOf(joinProcessor, nickProcessor), mutableListOf(eventHandler1, eventHandler2))
68
+        val handler = MessageHandler(listOf(joinProcessor, nickProcessor), emptyList(), mutableListOf(eventHandler1, eventHandler2))
68
         val joinMessage = IrcMessage(emptyMap(), null, "JOIN", emptyList())
69
         val joinMessage = IrcMessage(emptyMap(), null, "JOIN", emptyList())
69
         whenever(joinProcessor.process(any())).thenReturn(listOf(ServerConnected(TestConstants.time), ServerWelcome(TestConstants.time, "the.gibson", "acidBurn")))
70
         whenever(joinProcessor.process(any())).thenReturn(listOf(ServerConnected(TestConstants.time), ServerWelcome(TestConstants.time, "the.gibson", "acidBurn")))
70
 
71
 
81
     }
82
     }
82
 
83
 
83
     @Test
84
     @Test
84
-    fun `MessageHandler emits custom events to all handlers`() = runBlocking<Unit> {
85
+    fun `emits custom events to all handlers`() {
85
         val eventHandler1 = mock<EventHandler>()
86
         val eventHandler1 = mock<EventHandler>()
86
         val eventHandler2 = mock<EventHandler>()
87
         val eventHandler2 = mock<EventHandler>()
87
-        val handler = MessageHandler(emptyList(), mutableListOf(eventHandler1, eventHandler2))
88
+        val handler = MessageHandler(emptyList(), emptyList(), mutableListOf(eventHandler1, eventHandler2))
88
         handler.emitEvent(ircClient, ServerWelcome(TestConstants.time, "the.gibson", "acidBurn"))
89
         handler.emitEvent(ircClient, ServerWelcome(TestConstants.time, "the.gibson", "acidBurn"))
89
 
90
 
90
         verify(eventHandler1).processEvent(same(ircClient), isA<ServerWelcome>())
91
         verify(eventHandler1).processEvent(same(ircClient), isA<ServerWelcome>())
92
     }
93
     }
93
 
94
 
94
     @Test
95
     @Test
95
-    fun `MessageHandler emits events returned from handler`() = runBlocking<Unit> {
96
-        val eventHandler1 = mock<EventHandler> {
97
-            on { processEvent(any(), isA<ServerWelcome>()) } doReturn listOf(ServerReady(TestConstants.time))
96
+    fun `mutates events in order`() {
97
+        val eventMutator1 = mock<EventMutator> {
98
+            on { mutateEvent(any(), isA<ServerWelcome>()) } doReturn listOf(ServerReady(TestConstants.time))
98
         }
99
         }
99
-        val eventHandler2 = mock<EventHandler>()
100
-        val handler = MessageHandler(emptyList(), mutableListOf(eventHandler1, eventHandler2))
100
+        val eventMutator2 = mock<EventMutator> {
101
+            on { mutateEvent(any(), isA<ServerReady>()) } doReturn listOf(ServerConnected(TestConstants.time))
102
+        }
103
+        val eventHandler = mock<EventHandler>()
104
+
105
+        val handler = MessageHandler(emptyList(), listOf(eventMutator1, eventMutator2), mutableListOf(eventHandler))
106
+        handler.emitEvent(ircClient, ServerWelcome(TestConstants.time, "the.gibson", "acidBurn"))
107
+
108
+        verify(eventMutator1).mutateEvent(same(ircClient), isA<ServerWelcome>())
109
+        verify(eventMutator2).mutateEvent(same(ircClient), isA<ServerReady>())
110
+        verify(eventHandler).processEvent(same(ircClient), isA<ServerConnected>())
111
+        verifyNoMoreInteractions(eventHandler)
112
+    }
113
+
114
+    @Test
115
+    fun `allows mutators to fan out events`() {
116
+        val eventMutator1 = mock<EventMutator> {
117
+            on { mutateEvent(any(), isA<ServerWelcome>()) } doReturn listOf(
118
+                    ServerReady(TestConstants.time),
119
+                    ServerConnected(TestConstants.time)
120
+            )
121
+        }
122
+        val eventMutator2 = mock<EventMutator> {
123
+            on { mutateEvent(any(), isA<ServerReady>()) } doReturn listOf(ServerReady(TestConstants.time))
124
+            on { mutateEvent(any(), isA<ServerConnected>()) } doReturn listOf(ServerConnected(TestConstants.time))
125
+        }
126
+        val eventHandler = mock<EventHandler>()
127
+
128
+        val handler = MessageHandler(emptyList(), listOf(eventMutator1, eventMutator2), mutableListOf(eventHandler))
129
+        handler.emitEvent(ircClient, ServerWelcome(TestConstants.time, "the.gibson", "acidBurn"))
130
+
131
+        with (inOrder(eventMutator2, eventHandler)) {
132
+            verify(eventMutator2).mutateEvent(same(ircClient), isA<ServerReady>())
133
+            verify(eventMutator2).mutateEvent(same(ircClient), isA<ServerConnected>())
134
+            verify(eventHandler).processEvent(same(ircClient), isA<ServerReady>())
135
+            verify(eventHandler).processEvent(same(ircClient), isA<ServerConnected>())
136
+        }
137
+    }
138
+
139
+    @Test
140
+    fun `allows mutators to suppress events`() {
141
+        val eventMutator1 = mock<EventMutator> {
142
+            on { mutateEvent(any(), isA<ServerWelcome>()) } doReturn emptyList()
143
+        }
144
+        val eventMutator2 = mock<EventMutator>()
145
+        val eventHandler = mock<EventHandler>()
146
+
147
+        val handler = MessageHandler(emptyList(), listOf(eventMutator1, eventMutator2), mutableListOf(eventHandler))
101
         handler.emitEvent(ircClient, ServerWelcome(TestConstants.time, "the.gibson", "acidBurn"))
148
         handler.emitEvent(ircClient, ServerWelcome(TestConstants.time, "the.gibson", "acidBurn"))
102
 
149
 
103
-        verify(eventHandler1).processEvent(same(ircClient), isA<ServerReady>())
104
-        verify(eventHandler2).processEvent(same(ircClient), isA<ServerReady>())
150
+        verify(eventMutator2, never()).mutateEvent(any(), any())
151
+        verify(eventHandler, never()).processEvent(any(), any())
105
     }
152
     }
106
 
153
 
107
-}
154
+}

Loading…
Cancel
Save