Files
ferretirc-client/src/test/kotlin/com/shr4pnel/ferretirc/IrcClientTest.kt
T

120 lines
4.6 KiB
Kotlin

package com.shr4pnel.ferretirc
import com.shr4pnel.ferretirc.net.messages.ServerMessage
import io.github.oshai.kotlinlogging.KotlinLogging
import kotlinx.coroutines.runBlocking
import org.junit.jupiter.api.AfterAll
import org.junit.jupiter.api.BeforeAll
import org.junit.jupiter.api.Test
import java.io.File
import java.lang.ProcessBuilder
import kotlin.test.assertEquals
import com.shr4pnel.ferretirc.net.messages.ClientMessage as Message
class IrcClientTest {
private val logger = KotlinLogging.logger {}
companion object {
lateinit var processes: MutableList<Process>
val client = IrcClient("localhost", 6667, enableLogging = true)
private val logger = KotlinLogging.logger {}
val guestUser = IrcClient("localhost", 6667)
@JvmStatic
@BeforeAll
fun setup(): Unit =
runBlocking {
val logFile = File("src/test/resources/logs/ngircd.log")
val ngircdConfigPath = javaClass.classLoader.getResource("ngircd.conf")!!.path
logFile.createNewFile()
processes =
ProcessBuilder.startPipeline(
listOf<ProcessBuilder>(
// Run IRC server in [-d] debug log mode, with [-n] no daemon, using config [-f] file at path
ProcessBuilder("ngircd", "-dnf", ngircdConfigPath).redirectErrorStream(true),
// Remove unhelpful default ngircd info [PID. relative time, GID?]
ProcessBuilder("sed", "-ue", "s/\\[[^][]*\\]//g"),
// Add relative timestamp
ProcessBuilder("ts", "-s", "%H:%M:%.S").redirectOutput(logFile),
),
)
client.connect()
client.register("shr4p", "Tyler Fullname", "password")
guestUser.connect()
guestUser.register("guest", "guest", "pass")
val default = client.server.fetchChannels().first()
client.join(default)
guestUser.join(default)
}
@JvmStatic
@AfterAll
fun shutdown() =
runBlocking {
logger.info { "Closing server." }
client.queueMessage(Message.Die())
client.waitForNext<ServerMessage.Notice>()
processes.forEach { it.destroy() }
}
}
@Test
fun pingGetsPong() =
runBlocking {
val token = "ACK"
val msg = Message.Ping(token)
val pong = client.queueMessageAndWaitForNext<ServerMessage.Pong>(msg)
assertEquals(token, pong.token, "Token in PING did not match PONG")
}
@Test
fun oper() =
runBlocking {
val mode = client.queueMessageAndWaitForNext<ServerMessage.Mode>(Message.Oper("shr4p", "password"))
assertEquals("shr4p", mode.operatorName, "Received incorrect operator name in MODE")
assertEquals("+o", mode.pMask, "Received unexpected mask in MODE")
logger.info { "Received MODE with mask ${mode.pMask}" }
}
@Test
fun listChannels() = runBlocking {
assert(
client.server.channels.value.isNotEmpty(),
)
}
@Test
fun messageLands() =
runBlocking {
val channels = client.server.channels.value
val message = Message.PrivMsg(channels.first(), "bring me to life")
val receivedMessage = client.waitForNextMessageAfterAction<ServerMessage.PrivMsg> {
guestUser.queueMessage(message)
}
logger.debug { "Message: $message, Received: $receivedMessage" }
assertEquals(message.message, receivedMessage.message)
assertEquals(message.target.chanName, receivedMessage.targets.first())
}
@Test
fun manyMessagesLand() =
runBlocking {
val channels = client.server.channels.value
val channel = channels.first()
val max = 100
val messages = mutableListOf<Message.PrivMsg>()
val receivedMessages = mutableListOf<ServerMessage.PrivMsg>()
for (i in 1..max) messages.add(Message.PrivMsg(channel, "$i: bring me to life"))
for (i in 0..<max) {
val msg = client.waitForNextMessageAfterAction<ServerMessage.PrivMsg> {
guestUser.queueMessage(messages[i])
}
receivedMessages.add(msg)
}
for (i in 0..<max) assertEquals(messages[i].message, receivedMessages[i].message)
}
}