Browse Source

Initial work on exposing async methods

Move message processors into their own package
Update ktor
tags/v0.10.1
Chris Smith 5 years ago
parent
commit
070d502463
51 changed files with 199 additions and 58 deletions
  1. 2
    0
      CHANGELOG
  2. 2
    2
      build.gradle.kts
  3. 42
    2
      src/main/kotlin/com/dmdirc/ktirc/IrcClient.kt
  4. 17
    8
      src/main/kotlin/com/dmdirc/ktirc/IrcClientImpl.kt
  5. 2
    1
      src/main/kotlin/com/dmdirc/ktirc/events/handlers/EventHandler.kt
  6. 18
    0
      src/main/kotlin/com/dmdirc/ktirc/events/handlers/LabelledResponseHandler.kt
  7. 1
    1
      src/main/kotlin/com/dmdirc/ktirc/events/mutators/BatchMutator.kt
  8. 1
    1
      src/main/kotlin/com/dmdirc/ktirc/io/MessageHandler.kt
  9. 1
    1
      src/main/kotlin/com/dmdirc/ktirc/messages/processors/AccountProcessor.kt
  10. 4
    1
      src/main/kotlin/com/dmdirc/ktirc/messages/processors/AuthenticationProcessor.kt
  11. 1
    1
      src/main/kotlin/com/dmdirc/ktirc/messages/processors/BatchProcessor.kt
  12. 1
    1
      src/main/kotlin/com/dmdirc/ktirc/messages/processors/CapabilityProcessor.kt
  13. 1
    1
      src/main/kotlin/com/dmdirc/ktirc/messages/processors/ChangeHostProcessor.kt
  14. 2
    1
      src/main/kotlin/com/dmdirc/ktirc/messages/processors/ISupportProcessor.kt
  15. 1
    1
      src/main/kotlin/com/dmdirc/ktirc/messages/processors/JoinProcessor.kt
  16. 1
    1
      src/main/kotlin/com/dmdirc/ktirc/messages/processors/KickProcessor.kt
  17. 1
    1
      src/main/kotlin/com/dmdirc/ktirc/messages/processors/MessageProcessor.kt
  18. 3
    1
      src/main/kotlin/com/dmdirc/ktirc/messages/processors/ModeProcessor.kt
  19. 5
    1
      src/main/kotlin/com/dmdirc/ktirc/messages/processors/MotdProcessor.kt
  20. 1
    1
      src/main/kotlin/com/dmdirc/ktirc/messages/processors/NamesProcessor.kt
  21. 1
    1
      src/main/kotlin/com/dmdirc/ktirc/messages/processors/NickProcessor.kt
  22. 2
    1
      src/main/kotlin/com/dmdirc/ktirc/messages/processors/NoticeProcessor.kt
  23. 1
    1
      src/main/kotlin/com/dmdirc/ktirc/messages/processors/PartProcessor.kt
  24. 2
    1
      src/main/kotlin/com/dmdirc/ktirc/messages/processors/PingProcessor.kt
  25. 2
    1
      src/main/kotlin/com/dmdirc/ktirc/messages/processors/PrivmsgProcessor.kt
  26. 1
    1
      src/main/kotlin/com/dmdirc/ktirc/messages/processors/QuitProcessor.kt
  27. 4
    1
      src/main/kotlin/com/dmdirc/ktirc/messages/processors/TopicProcessor.kt
  28. 2
    1
      src/main/kotlin/com/dmdirc/ktirc/messages/processors/WelcomeProcessor.kt
  29. 25
    1
      src/main/kotlin/com/dmdirc/ktirc/model/ServerState.kt
  30. 3
    3
      src/test/kotlin/com/dmdirc/ktirc/IrcClientImplTest.kt
  31. 13
    0
      src/test/kotlin/com/dmdirc/ktirc/events/mutators/BatchMutatorTest.kt
  32. 1
    1
      src/test/kotlin/com/dmdirc/ktirc/io/MessageHandlerTest.kt
  33. 1
    1
      src/test/kotlin/com/dmdirc/ktirc/messages/processors/AccountProcessorTest.kt
  34. 1
    1
      src/test/kotlin/com/dmdirc/ktirc/messages/processors/AuthenticationProcessorTest.kt
  35. 2
    1
      src/test/kotlin/com/dmdirc/ktirc/messages/processors/BatchProcessorTest.kt
  36. 1
    1
      src/test/kotlin/com/dmdirc/ktirc/messages/processors/CapabilityProcessorTest.kt
  37. 1
    1
      src/test/kotlin/com/dmdirc/ktirc/messages/processors/ChangeHostProcessorTest.kt
  38. 1
    1
      src/test/kotlin/com/dmdirc/ktirc/messages/processors/ISupportProcessorTest.kt
  39. 1
    1
      src/test/kotlin/com/dmdirc/ktirc/messages/processors/JoinProcessorTest.kt
  40. 1
    1
      src/test/kotlin/com/dmdirc/ktirc/messages/processors/KickProcessorTest.kt
  41. 1
    1
      src/test/kotlin/com/dmdirc/ktirc/messages/processors/ModeProcessorTest.kt
  42. 1
    1
      src/test/kotlin/com/dmdirc/ktirc/messages/processors/MotdProcessorTest.kt
  43. 1
    1
      src/test/kotlin/com/dmdirc/ktirc/messages/processors/NamesProcessorTest.kt
  44. 1
    1
      src/test/kotlin/com/dmdirc/ktirc/messages/processors/NickProcessorTest.kt
  45. 1
    1
      src/test/kotlin/com/dmdirc/ktirc/messages/processors/NoticeProcessorTest.kt
  46. 1
    1
      src/test/kotlin/com/dmdirc/ktirc/messages/processors/PartProcessorTest.kt
  47. 1
    1
      src/test/kotlin/com/dmdirc/ktirc/messages/processors/PrivmsgProcessorTest.kt
  48. 1
    1
      src/test/kotlin/com/dmdirc/ktirc/messages/processors/QuitProcessorTest.kt
  49. 1
    1
      src/test/kotlin/com/dmdirc/ktirc/messages/processors/TopicProcessorTest.kt
  50. 1
    1
      src/test/kotlin/com/dmdirc/ktirc/messages/processors/WelcomeProcessorTest.kt
  51. 16
    0
      src/test/kotlin/com/dmdirc/ktirc/model/ServerStateTest.kt

+ 2
- 0
CHANGELOG View File

1
 vNEXT (in development)
1
 vNEXT (in development)
2
 
2
 
3
+ * (Internal) Moved message processors into their own package
4
+
3
 v0.10.0
5
 v0.10.0
4
 
6
 
5
  * Batch start and end events are no longer included in BatchReceived events
7
  * Batch start and end events are no longer included in BatchReceived events

+ 2
- 2
build.gradle.kts View File

37
 dependencies {
37
 dependencies {
38
     implementation(kotlin("stdlib-jdk8", "1.3.21"))
38
     implementation(kotlin("stdlib-jdk8", "1.3.21"))
39
     implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.1.1")
39
     implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.1.1")
40
-    implementation("io.ktor:ktor-network:1.1.2")
41
-    implementation("io.ktor:ktor-network-tls:1.1.2")
40
+    implementation("io.ktor:ktor-network:1.1.3")
41
+    implementation("io.ktor:ktor-network-tls:1.1.3")
42
 
42
 
43
     testImplementation("org.junit.jupiter:junit-jupiter-api:5.4.0")
43
     testImplementation("org.junit.jupiter:junit-jupiter-api:5.4.0")
44
     testImplementation("org.junit.jupiter:junit-jupiter-params:5.4.0")
44
     testImplementation("org.junit.jupiter:junit-jupiter-params:5.4.0")

+ 42
- 2
src/main/kotlin/com/dmdirc/ktirc/IrcClient.kt View File

5
 import com.dmdirc.ktirc.messages.sendJoin
5
 import com.dmdirc.ktirc.messages.sendJoin
6
 import com.dmdirc.ktirc.model.*
6
 import com.dmdirc.ktirc.model.*
7
 import com.dmdirc.ktirc.util.RemoveIn
7
 import com.dmdirc.ktirc.util.RemoveIn
8
+import kotlinx.coroutines.Deferred
8
 
9
 
9
 /**
10
 /**
10
  * Primary interface for interacting with KtIrc.
11
  * Primary interface for interacting with KtIrc.
65
      * This should only be needed to send raw/custom commands; standard messages can be sent using the
66
      * This should only be needed to send raw/custom commands; standard messages can be sent using the
66
      * extension methods in [com.dmdirc.ktirc.messages] such as [sendJoin].
67
      * extension methods in [com.dmdirc.ktirc.messages] such as [sendJoin].
67
      *
68
      *
69
+     * This method will return immediately; the message will be delivered by a coroutine. Messages
70
+     * are guaranteed to be delivered in order when this method is called multiple times.
71
+     *
68
      * @param tags The IRCv3 tags to prefix the message with, if any.
72
      * @param tags The IRCv3 tags to prefix the message with, if any.
69
-     * @param command The command to be sent
73
+     * @param command The command to be sent.
70
      * @param arguments The arguments to the command.
74
      * @param arguments The arguments to the command.
71
      */
75
      */
72
     fun send(tags: Map<MessageTag, String>, command: String, vararg arguments: String)
76
     fun send(tags: Map<MessageTag, String>, command: String, vararg arguments: String)
77
      * This should only be needed to send raw/custom commands; standard messages can be sent using the
81
      * This should only be needed to send raw/custom commands; standard messages can be sent using the
78
      * extension methods in [com.dmdirc.ktirc.messages] such as [sendJoin].
82
      * extension methods in [com.dmdirc.ktirc.messages] such as [sendJoin].
79
      *
83
      *
80
-     * @param command The command to be sent
84
+     * This method will return immediately; the message will be delivered by a coroutine. Messages
85
+     * are guaranteed to be delivered in order when this method is called multiple times.
86
+     *
87
+     * @param command The command to be sent.
81
      * @param arguments The arguments to the command.
88
      * @param arguments The arguments to the command.
82
      */
89
      */
83
     fun send(command: String, vararg arguments: String) = send(emptyMap(), command, *arguments)
90
     fun send(command: String, vararg arguments: String) = send(emptyMap(), command, *arguments)
84
 
91
 
92
+    /**
93
+     * Sends the given command to the IRC server, and waits for a response back.
94
+     *
95
+     * This should only be needed to send raw/custom commands; standard messages can be sent using the
96
+     * extension methods in [com.dmdirc.ktirc.messages] such as TODO: sendJoinAsync.
97
+     *
98
+     * This method will return immediately. If the server supports the labeled-responses capability,
99
+     * the returned [Deferred] will be eventually populated with the response from the server. If
100
+     * the server does not support the capability, or the response times out, `null` will be supplied.
101
+     *
102
+     * @param command The command to be sent.
103
+     * @param arguments The arguments to the command.
104
+     * @return A deferred [IrcEvent]? that contains the server's response to the command.
105
+     */
106
+    fun sendAsync(command: String, vararg arguments: String) = sendAsync(emptyMap(),  command, *arguments)
107
+
108
+    /**
109
+     * Sends the given command to the IRC server, and waits for a response back.
110
+     *
111
+     * This should only be needed to send raw/custom commands; standard messages can be sent using the
112
+     * extension methods in [com.dmdirc.ktirc.messages] such as TODO: sendJoinAsync.
113
+     *
114
+     * This method will return immediately. If the server supports the labeled-responses capability,
115
+     * the returned [Deferred] will be eventually populated with the response from the server. If
116
+     * the server does not support the capability, or the response times out, `null` will be supplied.
117
+     *
118
+     * @param tags The IRCv3 tags to prefix the message with, if any.
119
+     * @param command The command to be sent.
120
+     * @param arguments The arguments to the command.
121
+     * @return A deferred [IrcEvent]? that contains the server's response to the command.
122
+     */
123
+    fun sendAsync(tags: Map<MessageTag, String>, command: String, vararg arguments: String): Deferred<IrcEvent?>
124
+
85
     /**
125
     /**
86
      * Registers a new handler for all events on this connection.
126
      * Registers a new handler for all events on this connection.
87
      *
127
      *

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

8
 import com.dmdirc.ktirc.io.MessageHandler
8
 import com.dmdirc.ktirc.io.MessageHandler
9
 import com.dmdirc.ktirc.io.MessageParser
9
 import com.dmdirc.ktirc.io.MessageParser
10
 import com.dmdirc.ktirc.messages.*
10
 import com.dmdirc.ktirc.messages.*
11
+import com.dmdirc.ktirc.messages.processors.messageProcessors
11
 import com.dmdirc.ktirc.model.*
12
 import com.dmdirc.ktirc.model.*
12
 import com.dmdirc.ktirc.util.currentTimeProvider
13
 import com.dmdirc.ktirc.util.currentTimeProvider
13
 import com.dmdirc.ktirc.util.generateLabel
14
 import com.dmdirc.ktirc.util.generateLabel
14
 import com.dmdirc.ktirc.util.logger
15
 import com.dmdirc.ktirc.util.logger
15
 import io.ktor.util.KtorExperimentalAPI
16
 import io.ktor.util.KtorExperimentalAPI
16
 import kotlinx.coroutines.*
17
 import kotlinx.coroutines.*
18
+import kotlinx.coroutines.channels.Channel
17
 import kotlinx.coroutines.channels.map
19
 import kotlinx.coroutines.channels.map
20
+import kotlinx.coroutines.time.withTimeoutOrNull
21
+import java.time.Duration
18
 import java.util.concurrent.atomic.AtomicBoolean
22
 import java.util.concurrent.atomic.AtomicBoolean
23
+import java.util.logging.Level
19
 
24
 
20
 /**
25
 /**
21
  * Concrete implementation of an [IrcClient].
26
  * Concrete implementation of an [IrcClient].
33
     @KtorExperimentalAPI
38
     @KtorExperimentalAPI
34
     internal var socketFactory: (CoroutineScope, String, Int, Boolean) -> LineBufferedSocket = ::KtorLineBufferedSocket
39
     internal var socketFactory: (CoroutineScope, String, Int, Boolean) -> LineBufferedSocket = ::KtorLineBufferedSocket
35
 
40
 
41
+    internal var asyncTimeout = Duration.ofSeconds(20)
42
+
36
     override var behaviour = config.behaviour
43
     override var behaviour = config.behaviour
37
 
44
 
38
     override val serverState = ServerState(config.profile.nickname, config.server.host, config.sasl)
45
     override val serverState = ServerState(config.profile.nickname, config.server.host, config.sasl)
57
                 ?: log.warning { "No send channel for command: $command" }
64
                 ?: log.warning { "No send channel for command: $command" }
58
     }
65
     }
59
 
66
 
60
-    // TODO: This will become sendAsync and return a Deferred<IrcEvent>
61
-    internal fun sendWithLabel(tags: Map<MessageTag, String>, command: String, vararg arguments: String) {
62
-        maybeEchoMessage(command, arguments)
63
-        val tagseToSend = if (Capability.LabeledResponse in serverState.capabilities.enabledCapabilities) {
64
-            tags + (MessageTag.Label to generateLabel(this))
67
+    override fun sendAsync(tags: Map<MessageTag, String>, command: String, vararg arguments: String) = async {
68
+        if (serverState.supportsLabeledResponses) {
69
+            val label = generateLabel(this@IrcClientImpl)
70
+            val channel = Channel<IrcEvent>(1)
71
+            serverState.labelChannels[label] = channel
72
+            send(tags + (MessageTag.Label to label), command, *arguments)
73
+            withTimeoutOrNull(asyncTimeout) { channel.receive() }.also { serverState.labelChannels.remove(label) }
65
         } else {
74
         } else {
66
-            tags
75
+            send(tags, command, *arguments)
76
+            null
67
         }
77
         }
68
-        socket?.sendChannel?.offer(messageBuilder.build(tagseToSend, command, arguments))
69
-                ?: log.warning { "No send channel for command: $command" }
70
     }
78
     }
71
 
79
 
72
     override fun connect() {
80
     override fun connect() {
88
                     sendUser(config.profile.username, config.profile.realName)
96
                     sendUser(config.profile.username, config.profile.realName)
89
                     messageHandler.processMessages(this@IrcClientImpl, receiveChannel.map { parser.parse(it) })
97
                     messageHandler.processMessages(this@IrcClientImpl, receiveChannel.map { parser.parse(it) })
90
                 } catch (ex: Exception) {
98
                 } catch (ex: Exception) {
99
+                    log.log(Level.SEVERE, ex) { "Error connecting to ${config.server.host}:${config.server.port}" }
91
                     emitEvent(ServerConnectionError(EventMetadata(currentTimeProvider()), ex.toConnectionError(), ex.localizedMessage))
100
                     emitEvent(ServerConnectionError(EventMetadata(currentTimeProvider()), ex.toConnectionError(), ex.localizedMessage))
92
                 }
101
                 }
93
 
102
 

+ 2
- 1
src/main/kotlin/com/dmdirc/ktirc/events/handlers/EventHandler.kt View File

15
         ChannelStateHandler(),
15
         ChannelStateHandler(),
16
         PingHandler(),
16
         PingHandler(),
17
         ServerStateHandler(),
17
         ServerStateHandler(),
18
-        UserStateHandler()
18
+        UserStateHandler(),
19
+        LabelledResponseHandler()
19
 )
20
 )

+ 18
- 0
src/main/kotlin/com/dmdirc/ktirc/events/handlers/LabelledResponseHandler.kt View File

1
+package com.dmdirc.ktirc.events.handlers
2
+
3
+import com.dmdirc.ktirc.IrcClient
4
+import com.dmdirc.ktirc.events.IrcEvent
5
+import kotlinx.coroutines.GlobalScope
6
+import kotlinx.coroutines.launch
7
+
8
+class LabelledResponseHandler : EventHandler {
9
+
10
+    override fun processEvent(client: IrcClient, event: IrcEvent) {
11
+        event.metadata.label?.let {
12
+            GlobalScope.launch {
13
+                client.serverState.labelChannels[it]?.send(event)
14
+            }
15
+        }
16
+    }
17
+
18
+}

+ 1
- 1
src/main/kotlin/com/dmdirc/ktirc/events/mutators/BatchMutator.kt View File

27
 
27
 
28
     private fun finishBatch(client: IrcClient, event: BatchFinished): List<IrcEvent> {
28
     private fun finishBatch(client: IrcClient, event: BatchFinished): List<IrcEvent> {
29
         client.serverState.batches.remove(event.referenceId)?.let {
29
         client.serverState.batches.remove(event.referenceId)?.let {
30
-            val batch = BatchReceived(it.events[0].metadata, it.type, it.arguments.toTypedArray(), it.events)
30
+            val batch = BatchReceived(it.metadata, it.type, it.arguments.toTypedArray(), it.events)
31
             if (it.metadata.batchId == null) {
31
             if (it.metadata.batchId == null) {
32
                 return listOf(batch)
32
                 return listOf(batch)
33
             } else {
33
             } else {

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

4
 import com.dmdirc.ktirc.events.IrcEvent
4
 import com.dmdirc.ktirc.events.IrcEvent
5
 import com.dmdirc.ktirc.events.handlers.EventHandler
5
 import com.dmdirc.ktirc.events.handlers.EventHandler
6
 import com.dmdirc.ktirc.events.mutators.EventMutator
6
 import com.dmdirc.ktirc.events.mutators.EventMutator
7
-import com.dmdirc.ktirc.messages.MessageProcessor
7
+import com.dmdirc.ktirc.messages.processors.MessageProcessor
8
 import com.dmdirc.ktirc.model.IrcMessage
8
 import com.dmdirc.ktirc.model.IrcMessage
9
 import com.dmdirc.ktirc.util.logger
9
 import com.dmdirc.ktirc.util.logger
10
 import kotlinx.coroutines.channels.ReceiveChannel
10
 import kotlinx.coroutines.channels.ReceiveChannel

src/main/kotlin/com/dmdirc/ktirc/messages/AccountProcessor.kt → src/main/kotlin/com/dmdirc/ktirc/messages/processors/AccountProcessor.kt View File

1
-package com.dmdirc.ktirc.messages
1
+package com.dmdirc.ktirc.messages.processors
2
 
2
 
3
 import com.dmdirc.ktirc.events.UserAccountChanged
3
 import com.dmdirc.ktirc.events.UserAccountChanged
4
 import com.dmdirc.ktirc.model.IrcMessage
4
 import com.dmdirc.ktirc.model.IrcMessage

src/main/kotlin/com/dmdirc/ktirc/messages/AuthenticationProcessor.kt → src/main/kotlin/com/dmdirc/ktirc/messages/processors/AuthenticationProcessor.kt View File

1
-package com.dmdirc.ktirc.messages
1
+package com.dmdirc.ktirc.messages.processors
2
 
2
 
3
 import com.dmdirc.ktirc.events.AuthenticationMessage
3
 import com.dmdirc.ktirc.events.AuthenticationMessage
4
 import com.dmdirc.ktirc.events.SaslFinished
4
 import com.dmdirc.ktirc.events.SaslFinished
5
 import com.dmdirc.ktirc.events.SaslMechanismNotAvailableError
5
 import com.dmdirc.ktirc.events.SaslMechanismNotAvailableError
6
+import com.dmdirc.ktirc.messages.ERR_SASLFAIL
7
+import com.dmdirc.ktirc.messages.RPL_SASLMECHS
8
+import com.dmdirc.ktirc.messages.RPL_SASLSUCCESS
6
 import com.dmdirc.ktirc.model.IrcMessage
9
 import com.dmdirc.ktirc.model.IrcMessage
7
 
10
 
8
 internal class AuthenticationProcessor : MessageProcessor {
11
 internal class AuthenticationProcessor : MessageProcessor {

src/main/kotlin/com/dmdirc/ktirc/messages/BatchProcessor.kt → src/main/kotlin/com/dmdirc/ktirc/messages/processors/BatchProcessor.kt View File

1
-package com.dmdirc.ktirc.messages
1
+package com.dmdirc.ktirc.messages.processors
2
 
2
 
3
 import com.dmdirc.ktirc.events.BatchFinished
3
 import com.dmdirc.ktirc.events.BatchFinished
4
 import com.dmdirc.ktirc.events.BatchStarted
4
 import com.dmdirc.ktirc.events.BatchStarted

src/main/kotlin/com/dmdirc/ktirc/messages/CapabilityProcessor.kt → src/main/kotlin/com/dmdirc/ktirc/messages/processors/CapabilityProcessor.kt View File

1
-package com.dmdirc.ktirc.messages
1
+package com.dmdirc.ktirc.messages.processors
2
 
2
 
3
 import com.dmdirc.ktirc.events.EventMetadata
3
 import com.dmdirc.ktirc.events.EventMetadata
4
 import com.dmdirc.ktirc.events.ServerCapabilitiesAcknowledged
4
 import com.dmdirc.ktirc.events.ServerCapabilitiesAcknowledged

src/main/kotlin/com/dmdirc/ktirc/messages/ChangeHostProcessor.kt → src/main/kotlin/com/dmdirc/ktirc/messages/processors/ChangeHostProcessor.kt View File

1
-package com.dmdirc.ktirc.messages
1
+package com.dmdirc.ktirc.messages.processors
2
 
2
 
3
 import com.dmdirc.ktirc.events.UserHostChanged
3
 import com.dmdirc.ktirc.events.UserHostChanged
4
 import com.dmdirc.ktirc.model.IrcMessage
4
 import com.dmdirc.ktirc.model.IrcMessage

src/main/kotlin/com/dmdirc/ktirc/messages/ISupportProcessor.kt → src/main/kotlin/com/dmdirc/ktirc/messages/processors/ISupportProcessor.kt View File

1
-package com.dmdirc.ktirc.messages
1
+package com.dmdirc.ktirc.messages.processors
2
 
2
 
3
 import com.dmdirc.ktirc.events.ServerFeaturesUpdated
3
 import com.dmdirc.ktirc.events.ServerFeaturesUpdated
4
 import com.dmdirc.ktirc.io.CaseMapping
4
 import com.dmdirc.ktirc.io.CaseMapping
5
+import com.dmdirc.ktirc.messages.RPL_ISUPPORT
5
 import com.dmdirc.ktirc.model.IrcMessage
6
 import com.dmdirc.ktirc.model.IrcMessage
6
 import com.dmdirc.ktirc.model.ModePrefixMapping
7
 import com.dmdirc.ktirc.model.ModePrefixMapping
7
 import com.dmdirc.ktirc.model.ServerFeatureMap
8
 import com.dmdirc.ktirc.model.ServerFeatureMap

src/main/kotlin/com/dmdirc/ktirc/messages/JoinProcessor.kt → src/main/kotlin/com/dmdirc/ktirc/messages/processors/JoinProcessor.kt View File

1
-package com.dmdirc.ktirc.messages
1
+package com.dmdirc.ktirc.messages.processors
2
 
2
 
3
 import com.dmdirc.ktirc.events.ChannelJoined
3
 import com.dmdirc.ktirc.events.ChannelJoined
4
 import com.dmdirc.ktirc.model.IrcMessage
4
 import com.dmdirc.ktirc.model.IrcMessage

src/main/kotlin/com/dmdirc/ktirc/messages/KickProcessor.kt → src/main/kotlin/com/dmdirc/ktirc/messages/processors/KickProcessor.kt View File

1
-package com.dmdirc.ktirc.messages
1
+package com.dmdirc.ktirc.messages.processors
2
 
2
 
3
 import com.dmdirc.ktirc.events.ChannelUserKicked
3
 import com.dmdirc.ktirc.events.ChannelUserKicked
4
 import com.dmdirc.ktirc.model.IrcMessage
4
 import com.dmdirc.ktirc.model.IrcMessage

src/main/kotlin/com/dmdirc/ktirc/messages/MessageProcessor.kt → src/main/kotlin/com/dmdirc/ktirc/messages/processors/MessageProcessor.kt View File

1
-package com.dmdirc.ktirc.messages
1
+package com.dmdirc.ktirc.messages.processors
2
 
2
 
3
 import com.dmdirc.ktirc.events.IrcEvent
3
 import com.dmdirc.ktirc.events.IrcEvent
4
 import com.dmdirc.ktirc.model.IrcMessage
4
 import com.dmdirc.ktirc.model.IrcMessage

src/main/kotlin/com/dmdirc/ktirc/messages/ModeProcessor.kt → src/main/kotlin/com/dmdirc/ktirc/messages/processors/ModeProcessor.kt View File

1
-package com.dmdirc.ktirc.messages
1
+package com.dmdirc.ktirc.messages.processors
2
 
2
 
3
 import com.dmdirc.ktirc.events.ModeChanged
3
 import com.dmdirc.ktirc.events.ModeChanged
4
+import com.dmdirc.ktirc.messages.RPL_CHANNELMODEIS
5
+import com.dmdirc.ktirc.messages.RPL_UMODEIS
4
 import com.dmdirc.ktirc.model.IrcMessage
6
 import com.dmdirc.ktirc.model.IrcMessage
5
 
7
 
6
 internal class ModeProcessor : MessageProcessor {
8
 internal class ModeProcessor : MessageProcessor {

src/main/kotlin/com/dmdirc/ktirc/messages/MotdProcessor.kt → src/main/kotlin/com/dmdirc/ktirc/messages/processors/MotdProcessor.kt View File

1
-package com.dmdirc.ktirc.messages
1
+package com.dmdirc.ktirc.messages.processors
2
 
2
 
3
 import com.dmdirc.ktirc.events.MotdFinished
3
 import com.dmdirc.ktirc.events.MotdFinished
4
 import com.dmdirc.ktirc.events.MotdLineReceived
4
 import com.dmdirc.ktirc.events.MotdLineReceived
5
+import com.dmdirc.ktirc.messages.ERR_NOMOTD
6
+import com.dmdirc.ktirc.messages.RPL_ENDOFMOTD
7
+import com.dmdirc.ktirc.messages.RPL_MOTD
8
+import com.dmdirc.ktirc.messages.RPL_MOTDSTART
5
 import com.dmdirc.ktirc.model.IrcMessage
9
 import com.dmdirc.ktirc.model.IrcMessage
6
 
10
 
7
 internal class MotdProcessor : MessageProcessor {
11
 internal class MotdProcessor : MessageProcessor {

src/main/kotlin/com/dmdirc/ktirc/messages/NamesProcessor.kt → src/main/kotlin/com/dmdirc/ktirc/messages/processors/NamesProcessor.kt View File

1
-package com.dmdirc.ktirc.messages
1
+package com.dmdirc.ktirc.messages.processors
2
 
2
 
3
 import com.dmdirc.ktirc.events.ChannelNamesFinished
3
 import com.dmdirc.ktirc.events.ChannelNamesFinished
4
 import com.dmdirc.ktirc.events.ChannelNamesReceived
4
 import com.dmdirc.ktirc.events.ChannelNamesReceived

src/main/kotlin/com/dmdirc/ktirc/messages/NickProcessor.kt → src/main/kotlin/com/dmdirc/ktirc/messages/processors/NickProcessor.kt View File

1
-package com.dmdirc.ktirc.messages
1
+package com.dmdirc.ktirc.messages.processors
2
 
2
 
3
 import com.dmdirc.ktirc.events.UserNickChanged
3
 import com.dmdirc.ktirc.events.UserNickChanged
4
 import com.dmdirc.ktirc.model.IrcMessage
4
 import com.dmdirc.ktirc.model.IrcMessage

src/main/kotlin/com/dmdirc/ktirc/messages/NoticeProcessor.kt → src/main/kotlin/com/dmdirc/ktirc/messages/processors/NoticeProcessor.kt View File

1
-package com.dmdirc.ktirc.messages
1
+package com.dmdirc.ktirc.messages.processors
2
 
2
 
3
 import com.dmdirc.ktirc.events.CtcpReplyReceived
3
 import com.dmdirc.ktirc.events.CtcpReplyReceived
4
 import com.dmdirc.ktirc.events.IrcEvent
4
 import com.dmdirc.ktirc.events.IrcEvent
5
 import com.dmdirc.ktirc.events.NoticeReceived
5
 import com.dmdirc.ktirc.events.NoticeReceived
6
+import com.dmdirc.ktirc.messages.CTCP_BYTE
6
 import com.dmdirc.ktirc.model.IrcMessage
7
 import com.dmdirc.ktirc.model.IrcMessage
7
 import com.dmdirc.ktirc.model.User
8
 import com.dmdirc.ktirc.model.User
8
 
9
 

src/main/kotlin/com/dmdirc/ktirc/messages/PartProcessor.kt → src/main/kotlin/com/dmdirc/ktirc/messages/processors/PartProcessor.kt View File

1
-package com.dmdirc.ktirc.messages
1
+package com.dmdirc.ktirc.messages.processors
2
 
2
 
3
 import com.dmdirc.ktirc.events.ChannelParted
3
 import com.dmdirc.ktirc.events.ChannelParted
4
 import com.dmdirc.ktirc.model.IrcMessage
4
 import com.dmdirc.ktirc.model.IrcMessage

src/main/kotlin/com/dmdirc/ktirc/messages/PingProcessor.kt → src/main/kotlin/com/dmdirc/ktirc/messages/processors/PingProcessor.kt View File

1
-package com.dmdirc.ktirc.messages
1
+package com.dmdirc.ktirc.messages.processors
2
 
2
 
3
 import com.dmdirc.ktirc.events.PingReceived
3
 import com.dmdirc.ktirc.events.PingReceived
4
+import com.dmdirc.ktirc.messages.processors.MessageProcessor
4
 import com.dmdirc.ktirc.model.IrcMessage
5
 import com.dmdirc.ktirc.model.IrcMessage
5
 
6
 
6
 internal class PingProcessor : MessageProcessor {
7
 internal class PingProcessor : MessageProcessor {

src/main/kotlin/com/dmdirc/ktirc/messages/PrivmsgProcessor.kt → src/main/kotlin/com/dmdirc/ktirc/messages/processors/PrivmsgProcessor.kt View File

1
-package com.dmdirc.ktirc.messages
1
+package com.dmdirc.ktirc.messages.processors
2
 
2
 
3
 import com.dmdirc.ktirc.events.ActionReceived
3
 import com.dmdirc.ktirc.events.ActionReceived
4
 import com.dmdirc.ktirc.events.CtcpReceived
4
 import com.dmdirc.ktirc.events.CtcpReceived
5
 import com.dmdirc.ktirc.events.IrcEvent
5
 import com.dmdirc.ktirc.events.IrcEvent
6
 import com.dmdirc.ktirc.events.MessageReceived
6
 import com.dmdirc.ktirc.events.MessageReceived
7
+import com.dmdirc.ktirc.messages.CTCP_BYTE
7
 import com.dmdirc.ktirc.model.IrcMessage
8
 import com.dmdirc.ktirc.model.IrcMessage
8
 import com.dmdirc.ktirc.model.User
9
 import com.dmdirc.ktirc.model.User
9
 
10
 

src/main/kotlin/com/dmdirc/ktirc/messages/QuitProcessor.kt → src/main/kotlin/com/dmdirc/ktirc/messages/processors/QuitProcessor.kt View File

1
-package com.dmdirc.ktirc.messages
1
+package com.dmdirc.ktirc.messages.processors
2
 
2
 
3
 import com.dmdirc.ktirc.events.UserQuit
3
 import com.dmdirc.ktirc.events.UserQuit
4
 import com.dmdirc.ktirc.model.IrcMessage
4
 import com.dmdirc.ktirc.model.IrcMessage

src/main/kotlin/com/dmdirc/ktirc/messages/TopicProcessor.kt → src/main/kotlin/com/dmdirc/ktirc/messages/processors/TopicProcessor.kt View File

1
-package com.dmdirc.ktirc.messages
1
+package com.dmdirc.ktirc.messages.processors
2
 
2
 
3
 import com.dmdirc.ktirc.events.ChannelTopicChanged
3
 import com.dmdirc.ktirc.events.ChannelTopicChanged
4
 import com.dmdirc.ktirc.events.ChannelTopicDiscovered
4
 import com.dmdirc.ktirc.events.ChannelTopicDiscovered
5
 import com.dmdirc.ktirc.events.ChannelTopicMetadataDiscovered
5
 import com.dmdirc.ktirc.events.ChannelTopicMetadataDiscovered
6
+import com.dmdirc.ktirc.messages.RPL_NOTOPIC
7
+import com.dmdirc.ktirc.messages.RPL_TOPIC
8
+import com.dmdirc.ktirc.messages.RPL_TOPICWHOTIME
6
 import com.dmdirc.ktirc.model.IrcMessage
9
 import com.dmdirc.ktirc.model.IrcMessage
7
 import com.dmdirc.ktirc.model.asUser
10
 import com.dmdirc.ktirc.model.asUser
8
 import com.dmdirc.ktirc.util.currentTimeZoneProvider
11
 import com.dmdirc.ktirc.util.currentTimeZoneProvider

src/main/kotlin/com/dmdirc/ktirc/messages/WelcomeProcessor.kt → src/main/kotlin/com/dmdirc/ktirc/messages/processors/WelcomeProcessor.kt View File

1
-package com.dmdirc.ktirc.messages
1
+package com.dmdirc.ktirc.messages.processors
2
 
2
 
3
 import com.dmdirc.ktirc.events.ServerWelcome
3
 import com.dmdirc.ktirc.events.ServerWelcome
4
+import com.dmdirc.ktirc.messages.RPL_WELCOME
4
 import com.dmdirc.ktirc.model.IrcMessage
5
 import com.dmdirc.ktirc.model.IrcMessage
5
 
6
 
6
 internal class WelcomeProcessor : MessageProcessor {
7
 internal class WelcomeProcessor : MessageProcessor {

+ 25
- 1
src/main/kotlin/com/dmdirc/ktirc/model/ServerState.kt View File

5
 import com.dmdirc.ktirc.events.IrcEvent
5
 import com.dmdirc.ktirc.events.IrcEvent
6
 import com.dmdirc.ktirc.io.CaseMapping
6
 import com.dmdirc.ktirc.io.CaseMapping
7
 import com.dmdirc.ktirc.util.logger
7
 import com.dmdirc.ktirc.util.logger
8
+import kotlinx.coroutines.channels.SendChannel
8
 import java.util.concurrent.atomic.AtomicLong
9
 import java.util.concurrent.atomic.AtomicLong
9
 import kotlin.reflect.KClass
10
 import kotlin.reflect.KClass
10
 
11
 
76
      */
77
      */
77
     internal val labelCounter = AtomicLong(0)
78
     internal val labelCounter = AtomicLong(0)
78
 
79
 
80
+    /**
81
+     * Whether or not the server supports labeled responses.
82
+     */
83
+    internal val supportsLabeledResponses: Boolean
84
+        get() = Capability.LabeledResponse in capabilities.enabledCapabilities
85
+
86
+    /**
87
+     * Channels waiting for a label to be received.
88
+     */
89
+    internal val labelChannels = mutableMapOf<String, SendChannel<IrcEvent>>()
90
+
79
     /**
91
     /**
80
      * Determines if the given mode is one applied to a user of a channel, such as 'o' for operator.
92
      * Determines if the given mode is one applied to a user of a channel, such as 'o' for operator.
81
      */
93
      */
107
         sasl.reset()
119
         sasl.reset()
108
         batches.clear()
120
         batches.clear()
109
         labelCounter.set(0)
121
         labelCounter.set(0)
122
+        labelChannels.clear()
110
     }
123
     }
111
 
124
 
112
 }
125
 }
122
      * Gets the value, or the default value, of the given feature.
135
      * Gets the value, or the default value, of the given feature.
123
      */
136
      */
124
     @Suppress("UNCHECKED_CAST")
137
     @Suppress("UNCHECKED_CAST")
125
-    operator fun <T : Any> get(feature: ServerFeature<T>) = features.getOrDefault(feature, feature.default) as? T? ?: feature.default
138
+    operator fun <T : Any> get(feature: ServerFeature<T>) = features.getOrDefault(feature, feature.default) as? T?
139
+            ?: feature.default
126
 
140
 
127
     internal operator fun set(feature: ServerFeature<*>, value: Any) {
141
     internal operator fun set(feature: ServerFeature<*>, value: Any) {
128
         require(feature.type.isInstance(value)) {
142
         require(feature.type.isInstance(value)) {
146
 
160
 
147
     /** Determines whether the given character is a mode prefix (e.g. "@", "+"). */
161
     /** Determines whether the given character is a mode prefix (e.g. "@", "+"). */
148
     fun isPrefix(char: Char) = prefixes.contains(char)
162
     fun isPrefix(char: Char) = prefixes.contains(char)
163
+
149
     /** Determines whether the given character is a channel user mode (e.g. "o", "v"). */
164
     /** Determines whether the given character is a channel user mode (e.g. "o", "v"). */
150
     fun isMode(char: Char) = modes.contains(char)
165
     fun isMode(char: Char) = modes.contains(char)
166
+
151
     /** Gets the mode corresponding to the given prefix (e.g. "@" -> "o"). */
167
     /** Gets the mode corresponding to the given prefix (e.g. "@" -> "o"). */
152
     fun getMode(prefix: Char) = modes[prefixes.indexOf(prefix)]
168
     fun getMode(prefix: Char) = modes[prefixes.indexOf(prefix)]
169
+
153
     /** Gets the modes corresponding to the given prefixes (e.g. "@+" -> "ov"). */
170
     /** Gets the modes corresponding to the given prefixes (e.g. "@+" -> "ov"). */
154
     fun getModes(prefixes: String) = String(prefixes.map(this::getMode).toCharArray())
171
     fun getModes(prefixes: String) = String(prefixes.map(this::getMode).toCharArray())
155
 
172
 
161
 sealed class ServerFeature<T : Any>(val name: String, val type: KClass<T>, val default: T? = null) {
178
 sealed class ServerFeature<T : Any>(val name: String, val type: KClass<T>, val default: T? = null) {
162
     /** The network the server says it belongs to. */
179
     /** The network the server says it belongs to. */
163
     object Network : ServerFeature<String>("NETWORK", String::class)
180
     object Network : ServerFeature<String>("NETWORK", String::class)
181
+
164
     /** The case mapping the server uses, defaulting to RFC. */
182
     /** The case mapping the server uses, defaulting to RFC. */
165
     object ServerCaseMapping : ServerFeature<CaseMapping>("CASEMAPPING", CaseMapping::class, CaseMapping.Rfc)
183
     object ServerCaseMapping : ServerFeature<CaseMapping>("CASEMAPPING", CaseMapping::class, CaseMapping.Rfc)
184
+
166
     /** The mode prefixes the server uses, defaulting to ov/@+. */
185
     /** The mode prefixes the server uses, defaulting to ov/@+. */
167
     object ModePrefixes : ServerFeature<ModePrefixMapping>("PREFIX", ModePrefixMapping::class, ModePrefixMapping("ov", "@+"))
186
     object ModePrefixes : ServerFeature<ModePrefixMapping>("PREFIX", ModePrefixMapping::class, ModePrefixMapping("ov", "@+"))
187
+
168
     /** The maximum number of channels a client may join. */
188
     /** The maximum number of channels a client may join. */
169
     object MaximumChannels : ServerFeature<Int>("MAXCHANNELS", Int::class) // TODO: CHANLIMIT also exists
189
     object MaximumChannels : ServerFeature<Int>("MAXCHANNELS", Int::class) // TODO: CHANLIMIT also exists
190
+
170
     /** The modes supported in channels. */
191
     /** The modes supported in channels. */
171
     object ChannelModes : ServerFeature<Array<String>>("CHANMODES", Array<String>::class)
192
     object ChannelModes : ServerFeature<Array<String>>("CHANMODES", Array<String>::class)
193
+
172
     /** The types of channels supported. */
194
     /** The types of channels supported. */
173
     object ChannelTypes : ServerFeature<String>("CHANTYPES", String::class, "#&")
195
     object ChannelTypes : ServerFeature<String>("CHANTYPES", String::class, "#&")
196
+
174
     /** The maximum length of a channel name, defaulting to 200. */
197
     /** The maximum length of a channel name, defaulting to 200. */
175
     object MaximumChannelNameLength : ServerFeature<Int>("CHANNELLEN", Int::class, 200)
198
     object MaximumChannelNameLength : ServerFeature<Int>("CHANNELLEN", Int::class, 200)
199
+
176
     /** Whether or not the server supports extended who. */
200
     /** Whether or not the server supports extended who. */
177
     object WhoxSupport : ServerFeature<Boolean>("WHOX", Boolean::class, false)
201
     object WhoxSupport : ServerFeature<Boolean>("WHOX", Boolean::class, false)
178
 }
202
 }

+ 3
- 3
src/test/kotlin/com/dmdirc/ktirc/IrcClientImplTest.kt View File

294
         client.socketFactory = mockSocketFactory
294
         client.socketFactory = mockSocketFactory
295
         client.connect()
295
         client.connect()
296
 
296
 
297
-        client.sendWithLabel(tagMap(), "testing", "123")
297
+        client.sendAsync(tagMap(), "testing", "123")
298
 
298
 
299
         assertLineReceived("testing 123")
299
         assertLineReceived("testing 123")
300
     }
300
     }
307
         client.serverState.capabilities.enabledCapabilities[Capability.LabeledResponse] = ""
307
         client.serverState.capabilities.enabledCapabilities[Capability.LabeledResponse] = ""
308
         client.connect()
308
         client.connect()
309
 
309
 
310
-        client.sendWithLabel(tagMap(), "testing", "123")
310
+        client.sendAsync(tagMap(), "testing", "123")
311
 
311
 
312
         assertLineReceived("@draft/label=abc123 testing 123")
312
         assertLineReceived("@draft/label=abc123 testing 123")
313
     }
313
     }
320
         client.serverState.capabilities.enabledCapabilities[Capability.LabeledResponse] = ""
320
         client.serverState.capabilities.enabledCapabilities[Capability.LabeledResponse] = ""
321
         client.connect()
321
         client.connect()
322
 
322
 
323
-        client.sendWithLabel(tagMap(MessageTag.AccountName to "x"), "testing", "123")
323
+        client.sendAsync(tagMap(MessageTag.AccountName to "x"), "testing", "123")
324
 
324
 
325
         assertLineReceived("@account=x;draft/label=abc123 testing 123")
325
         assertLineReceived("@account=x;draft/label=abc123 testing 123")
326
     }
326
     }

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

94
         assertTrue(event.events[0] is ServerConnected)
94
         assertTrue(event.events[0] is ServerConnected)
95
     }
95
     }
96
 
96
 
97
+    @Test
98
+    fun `sends finished batch with correct metadata`() {
99
+        val metadata = EventMetadata(TestConstants.time, label = "1234")
100
+        fakeServerState.batches["abcdef"] = Batch("netsplit", listOf("p1", "p2"), metadata, events = mutableListOf(ServerConnected(EventMetadata(TestConstants.time, "abcdef"))))
101
+
102
+        val events = mutator.mutateEvent(ircClient, messageEmitter, BatchFinished(EventMetadata(TestConstants.time), "abcdef"))
103
+
104
+        assertEquals(1, events.size)
105
+        assertTrue(events[0] is BatchReceived)
106
+        val event = events[0] as BatchReceived
107
+        assertSame(metadata, event.metadata)
108
+    }
109
+
97
     @Test
110
     @Test
98
     fun `adds a batch to its parent when it finishes`() {
111
     fun `adds a batch to its parent when it finishes`() {
99
         fakeServerState.batches["12345"] = Batch("history", emptyList(), EventMetadata(TestConstants.time))
112
         fakeServerState.batches["12345"] = Batch("history", emptyList(), EventMetadata(TestConstants.time))

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

5
 import com.dmdirc.ktirc.events.*
5
 import com.dmdirc.ktirc.events.*
6
 import com.dmdirc.ktirc.events.handlers.EventHandler
6
 import com.dmdirc.ktirc.events.handlers.EventHandler
7
 import com.dmdirc.ktirc.events.mutators.EventMutator
7
 import com.dmdirc.ktirc.events.mutators.EventMutator
8
-import com.dmdirc.ktirc.messages.MessageProcessor
8
+import com.dmdirc.ktirc.messages.processors.MessageProcessor
9
 import com.dmdirc.ktirc.model.IrcMessage
9
 import com.dmdirc.ktirc.model.IrcMessage
10
 import io.mockk.*
10
 import io.mockk.*
11
 import kotlinx.coroutines.channels.Channel
11
 import kotlinx.coroutines.channels.Channel

src/test/kotlin/com/dmdirc/ktirc/messages/AccountProcessorTest.kt → src/test/kotlin/com/dmdirc/ktirc/messages/processors/AccountProcessorTest.kt View File

1
-package com.dmdirc.ktirc.messages
1
+package com.dmdirc.ktirc.messages.processors
2
 
2
 
3
 import com.dmdirc.ktirc.TestConstants
3
 import com.dmdirc.ktirc.TestConstants
4
 import com.dmdirc.ktirc.model.IrcMessage
4
 import com.dmdirc.ktirc.model.IrcMessage

src/test/kotlin/com/dmdirc/ktirc/messages/AuthenticationProcessorTest.kt → src/test/kotlin/com/dmdirc/ktirc/messages/processors/AuthenticationProcessorTest.kt View File

1
-package com.dmdirc.ktirc.messages
1
+package com.dmdirc.ktirc.messages.processors
2
 
2
 
3
 import com.dmdirc.ktirc.TestConstants
3
 import com.dmdirc.ktirc.TestConstants
4
 import com.dmdirc.ktirc.events.AuthenticationMessage
4
 import com.dmdirc.ktirc.events.AuthenticationMessage

src/test/kotlin/com/dmdirc/ktirc/messages/BatchProcessorTest.kt → src/test/kotlin/com/dmdirc/ktirc/messages/processors/BatchProcessorTest.kt View File

1
-package com.dmdirc.ktirc.messages
1
+package com.dmdirc.ktirc.messages.processors
2
 
2
 
3
 import com.dmdirc.ktirc.TestConstants
3
 import com.dmdirc.ktirc.TestConstants
4
 import com.dmdirc.ktirc.events.BatchFinished
4
 import com.dmdirc.ktirc.events.BatchFinished
5
 import com.dmdirc.ktirc.events.BatchStarted
5
 import com.dmdirc.ktirc.events.BatchStarted
6
+import com.dmdirc.ktirc.messages.processors.BatchProcessor
6
 import com.dmdirc.ktirc.model.IrcMessage
7
 import com.dmdirc.ktirc.model.IrcMessage
7
 import com.dmdirc.ktirc.params
8
 import com.dmdirc.ktirc.params
8
 import com.dmdirc.ktirc.util.currentTimeProvider
9
 import com.dmdirc.ktirc.util.currentTimeProvider

src/test/kotlin/com/dmdirc/ktirc/messages/CapabilityProcessorTest.kt → src/test/kotlin/com/dmdirc/ktirc/messages/processors/CapabilityProcessorTest.kt View File

1
-package com.dmdirc.ktirc.messages
1
+package com.dmdirc.ktirc.messages.processors
2
 
2
 
3
 import com.dmdirc.ktirc.events.ServerCapabilitiesAcknowledged
3
 import com.dmdirc.ktirc.events.ServerCapabilitiesAcknowledged
4
 import com.dmdirc.ktirc.events.ServerCapabilitiesFinished
4
 import com.dmdirc.ktirc.events.ServerCapabilitiesFinished

src/test/kotlin/com/dmdirc/ktirc/messages/ChangeHostProcessorTest.kt → src/test/kotlin/com/dmdirc/ktirc/messages/processors/ChangeHostProcessorTest.kt View File

1
-package com.dmdirc.ktirc.messages
1
+package com.dmdirc.ktirc.messages.processors
2
 
2
 
3
 import com.dmdirc.ktirc.model.IrcMessage
3
 import com.dmdirc.ktirc.model.IrcMessage
4
 import com.dmdirc.ktirc.model.User
4
 import com.dmdirc.ktirc.model.User

src/test/kotlin/com/dmdirc/ktirc/messages/ISupportProcessorTest.kt → src/test/kotlin/com/dmdirc/ktirc/messages/processors/ISupportProcessorTest.kt View File

1
-package com.dmdirc.ktirc.messages
1
+package com.dmdirc.ktirc.messages.processors
2
 
2
 
3
 import com.dmdirc.ktirc.io.CaseMapping
3
 import com.dmdirc.ktirc.io.CaseMapping
4
 import com.dmdirc.ktirc.model.IrcMessage
4
 import com.dmdirc.ktirc.model.IrcMessage

src/test/kotlin/com/dmdirc/ktirc/messages/JoinProcessorTest.kt → src/test/kotlin/com/dmdirc/ktirc/messages/processors/JoinProcessorTest.kt View File

1
-package com.dmdirc.ktirc.messages
1
+package com.dmdirc.ktirc.messages.processors
2
 
2
 
3
 import com.dmdirc.ktirc.TestConstants
3
 import com.dmdirc.ktirc.TestConstants
4
 import com.dmdirc.ktirc.model.IrcMessage
4
 import com.dmdirc.ktirc.model.IrcMessage

src/test/kotlin/com/dmdirc/ktirc/messages/KickProcessorTest.kt → src/test/kotlin/com/dmdirc/ktirc/messages/processors/KickProcessorTest.kt View File

1
-package com.dmdirc.ktirc.messages
1
+package com.dmdirc.ktirc.messages.processors
2
 
2
 
3
 import com.dmdirc.ktirc.TestConstants
3
 import com.dmdirc.ktirc.TestConstants
4
 import com.dmdirc.ktirc.model.IrcMessage
4
 import com.dmdirc.ktirc.model.IrcMessage

src/test/kotlin/com/dmdirc/ktirc/messages/ModeProcessorTest.kt → src/test/kotlin/com/dmdirc/ktirc/messages/processors/ModeProcessorTest.kt View File

1
-package com.dmdirc.ktirc.messages
1
+package com.dmdirc.ktirc.messages.processors
2
 
2
 
3
 import com.dmdirc.ktirc.TestConstants
3
 import com.dmdirc.ktirc.TestConstants
4
 import com.dmdirc.ktirc.model.IrcMessage
4
 import com.dmdirc.ktirc.model.IrcMessage

src/test/kotlin/com/dmdirc/ktirc/messages/MotdProcessorTest.kt → src/test/kotlin/com/dmdirc/ktirc/messages/processors/MotdProcessorTest.kt View File

1
-package com.dmdirc.ktirc.messages
1
+package com.dmdirc.ktirc.messages.processors
2
 
2
 
3
 import com.dmdirc.ktirc.TestConstants
3
 import com.dmdirc.ktirc.TestConstants
4
 import com.dmdirc.ktirc.events.MotdFinished
4
 import com.dmdirc.ktirc.events.MotdFinished

src/test/kotlin/com/dmdirc/ktirc/messages/NamesProcessorTest.kt → src/test/kotlin/com/dmdirc/ktirc/messages/processors/NamesProcessorTest.kt View File

1
-package com.dmdirc.ktirc.messages
1
+package com.dmdirc.ktirc.messages.processors
2
 
2
 
3
 import com.dmdirc.ktirc.events.ChannelNamesFinished
3
 import com.dmdirc.ktirc.events.ChannelNamesFinished
4
 import com.dmdirc.ktirc.events.ChannelNamesReceived
4
 import com.dmdirc.ktirc.events.ChannelNamesReceived

src/test/kotlin/com/dmdirc/ktirc/messages/NickProcessorTest.kt → src/test/kotlin/com/dmdirc/ktirc/messages/processors/NickProcessorTest.kt View File

1
-package com.dmdirc.ktirc.messages
1
+package com.dmdirc.ktirc.messages.processors
2
 
2
 
3
 import com.dmdirc.ktirc.model.IrcMessage
3
 import com.dmdirc.ktirc.model.IrcMessage
4
 import com.dmdirc.ktirc.params
4
 import com.dmdirc.ktirc.params

src/test/kotlin/com/dmdirc/ktirc/messages/NoticeProcessorTest.kt → src/test/kotlin/com/dmdirc/ktirc/messages/processors/NoticeProcessorTest.kt View File

1
-package com.dmdirc.ktirc.messages
1
+package com.dmdirc.ktirc.messages.processors
2
 
2
 
3
 import com.dmdirc.ktirc.TestConstants
3
 import com.dmdirc.ktirc.TestConstants
4
 import com.dmdirc.ktirc.events.CtcpReplyReceived
4
 import com.dmdirc.ktirc.events.CtcpReplyReceived

src/test/kotlin/com/dmdirc/ktirc/messages/PartProcessorTest.kt → src/test/kotlin/com/dmdirc/ktirc/messages/processors/PartProcessorTest.kt View File

1
-package com.dmdirc.ktirc.messages
1
+package com.dmdirc.ktirc.messages.processors
2
 
2
 
3
 import com.dmdirc.ktirc.TestConstants
3
 import com.dmdirc.ktirc.TestConstants
4
 import com.dmdirc.ktirc.model.IrcMessage
4
 import com.dmdirc.ktirc.model.IrcMessage

src/test/kotlin/com/dmdirc/ktirc/messages/PrivmsgProcessorTest.kt → src/test/kotlin/com/dmdirc/ktirc/messages/processors/PrivmsgProcessorTest.kt View File

1
-package com.dmdirc.ktirc.messages
1
+package com.dmdirc.ktirc.messages.processors
2
 
2
 
3
 import com.dmdirc.ktirc.TestConstants
3
 import com.dmdirc.ktirc.TestConstants
4
 import com.dmdirc.ktirc.events.ActionReceived
4
 import com.dmdirc.ktirc.events.ActionReceived

src/test/kotlin/com/dmdirc/ktirc/messages/QuitProcessorTest.kt → src/test/kotlin/com/dmdirc/ktirc/messages/processors/QuitProcessorTest.kt View File

1
-package com.dmdirc.ktirc.messages
1
+package com.dmdirc.ktirc.messages.processors
2
 
2
 
3
 import com.dmdirc.ktirc.TestConstants
3
 import com.dmdirc.ktirc.TestConstants
4
 import com.dmdirc.ktirc.model.IrcMessage
4
 import com.dmdirc.ktirc.model.IrcMessage

src/test/kotlin/com/dmdirc/ktirc/messages/TopicProcessorTest.kt → src/test/kotlin/com/dmdirc/ktirc/messages/processors/TopicProcessorTest.kt View File

1
-package com.dmdirc.ktirc.messages
1
+package com.dmdirc.ktirc.messages.processors
2
 
2
 
3
 import com.dmdirc.ktirc.TestConstants
3
 import com.dmdirc.ktirc.TestConstants
4
 import com.dmdirc.ktirc.events.ChannelTopicChanged
4
 import com.dmdirc.ktirc.events.ChannelTopicChanged

src/test/kotlin/com/dmdirc/ktirc/messages/WelcomeProcessorTest.kt → src/test/kotlin/com/dmdirc/ktirc/messages/processors/WelcomeProcessorTest.kt View File

1
-package com.dmdirc.ktirc.messages
1
+package com.dmdirc.ktirc.messages.processors
2
 
2
 
3
 import com.dmdirc.ktirc.TestConstants
3
 import com.dmdirc.ktirc.TestConstants
4
 import com.dmdirc.ktirc.model.IrcMessage
4
 import com.dmdirc.ktirc.model.IrcMessage

+ 16
- 0
src/test/kotlin/com/dmdirc/ktirc/model/ServerStateTest.kt View File

2
 
2
 
3
 import com.dmdirc.ktirc.TestConstants
3
 import com.dmdirc.ktirc.TestConstants
4
 import com.dmdirc.ktirc.events.EventMetadata
4
 import com.dmdirc.ktirc.events.EventMetadata
5
+import kotlinx.coroutines.channels.Channel
5
 import org.junit.jupiter.api.Assertions.*
6
 import org.junit.jupiter.api.Assertions.*
6
 import org.junit.jupiter.api.Test
7
 import org.junit.jupiter.api.Test
7
 
8
 
60
         assertEquals(ChannelModeType.NoParameter, serverState.channelModeType('b'))
61
         assertEquals(ChannelModeType.NoParameter, serverState.channelModeType('b'))
61
     }
62
     }
62
 
63
 
64
+    @Test
65
+    fun `indicates labels are enabled when cap is present`() {
66
+        val serverState = ServerState("acidBurn", "")
67
+        serverState.capabilities.enabledCapabilities[Capability.LabeledResponse] = ""
68
+        assertTrue(serverState.supportsLabeledResponses)
69
+    }
70
+
71
+    @Test
72
+    fun `indicates labels are not enabled when cap is absent`() {
73
+        val serverState = ServerState("acidBurn", "")
74
+        assertFalse(serverState.supportsLabeledResponses)
75
+    }
76
+
63
     @Test
77
     @Test
64
     fun `reset clears all state`() = with(ServerState("acidBurn", "")) {
78
     fun `reset clears all state`() = with(ServerState("acidBurn", "")) {
65
         receivedWelcome = true
79
         receivedWelcome = true
71
         sasl.saslBuffer = "in progress"
85
         sasl.saslBuffer = "in progress"
72
         batches["batch"] = Batch("type", emptyList(), EventMetadata(TestConstants.time))
86
         batches["batch"] = Batch("type", emptyList(), EventMetadata(TestConstants.time))
73
         labelCounter.set(100)
87
         labelCounter.set(100)
88
+        labelChannels["#thegibson"] = Channel(1)
74
 
89
 
75
         reset()
90
         reset()
76
 
91
 
83
         assertEquals("", sasl.saslBuffer)
98
         assertEquals("", sasl.saslBuffer)
84
         assertTrue(batches.isEmpty())
99
         assertTrue(batches.isEmpty())
85
         assertEquals(0, labelCounter.get())
100
         assertEquals(0, labelCounter.get())
101
+        assertTrue(labelChannels.isEmpty())
86
     }
102
     }
87
 
103
 
88
 }
104
 }

Loading…
Cancel
Save