package com.shr4pnel.ferretirc import com.shr4pnel.ferretirc.net.messages.ServerMessage import io.github.oshai.kotlinlogging.KotlinLogging import kotlinx.coroutines.runBlocking import kotlinx.coroutines.test.runTest 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 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( // 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") client.server } @JvmStatic @AfterAll fun shutdown() = runBlocking { logger.info { "Closing server." } client.queueMessage(Message.Die()) client.waitForNext() processes.forEach { it.destroy() } } } @Test fun pingGetsPong() = runTest { val token = "ACK" val msg = Message.Ping(token) val pong = client.queueAndWaitForNext(msg) assertEquals(token, pong.token, "Token in PING did not match PONG") } @Test fun oper() = runTest { client.queueMessage(Message.Oper("shr4p", "password")) val mode = client.waitForNext() 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() = runTest { val channels = client.server.fetchChannels() assert(channels.isNotEmpty()) client.queueMessage(Message.Join(channels.first())) } @Test fun messageLands() = runTest { val channels = client.server.fetchChannels() val message = Message.PrivMsg(channels.first(), "bring me to life") guestUser.queueMessage(message) val receivedMessage = client.waitForNext() logger.debug { "Message: $message, Received: $receivedMessage" } assertEquals(message.message, receivedMessage.message) assertEquals(message.target.chanName, receivedMessage.targets.first()) } }