您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

IrcClientTest.kt 6.4KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184
  1. package com.dmdirc.ktirc
  2. import com.dmdirc.ktirc.events.EventHandler
  3. import com.dmdirc.ktirc.events.ServerWelcome
  4. import com.dmdirc.ktirc.io.CaseMapping
  5. import com.dmdirc.ktirc.io.LineBufferedSocket
  6. import com.dmdirc.ktirc.model.Profile
  7. import com.dmdirc.ktirc.model.Server
  8. import com.dmdirc.ktirc.model.ServerFeature
  9. import com.dmdirc.ktirc.model.User
  10. import com.nhaarman.mockitokotlin2.*
  11. import kotlinx.coroutines.channels.Channel
  12. import kotlinx.coroutines.launch
  13. import kotlinx.coroutines.runBlocking
  14. import org.junit.jupiter.api.Assertions.*
  15. import org.junit.jupiter.api.Test
  16. import org.junit.jupiter.api.assertThrows
  17. internal class IrcClientImplTest {
  18. companion object {
  19. private const val HOST = "thegibson.com"
  20. private const val PORT = 12345
  21. private const val NICK = "AcidBurn"
  22. private const val REAL_NAME = "Kate Libby"
  23. private const val USER_NAME = "acidb"
  24. private const val PASSWORD = "HackThePlanet"
  25. }
  26. private val readLineChannel = Channel<ByteArray>(10)
  27. private val mockSocket = mock<LineBufferedSocket> {
  28. on { readLines(any()) } doReturn readLineChannel
  29. }
  30. private val mockSocketFactory = mock<(String, Int) -> LineBufferedSocket> {
  31. on { invoke(HOST, PORT) } doReturn mockSocket
  32. }
  33. private val mockEventHandler = mock<EventHandler>()
  34. @Test
  35. fun `IrcClientImpl uses socket factory to create a new socket on connect`() {
  36. runBlocking {
  37. val client = IrcClientImpl(Server(HOST, PORT), Profile(NICK, REAL_NAME, USER_NAME))
  38. client.socketFactory = mockSocketFactory
  39. readLineChannel.close()
  40. client.connect()
  41. verify(mockSocketFactory).invoke(HOST, PORT)
  42. }
  43. }
  44. @Test
  45. fun `IrcClientImpl throws if socket already exists`() {
  46. runBlocking {
  47. val client = IrcClientImpl(Server(HOST, PORT), Profile(NICK, REAL_NAME, USER_NAME))
  48. client.socketFactory = mockSocketFactory
  49. readLineChannel.close()
  50. client.connect()
  51. assertThrows<IllegalStateException> {
  52. runBlocking {
  53. client.connect()
  54. }
  55. }
  56. }
  57. }
  58. @Test
  59. fun `IrcClientImpl sends basic connection strings`() {
  60. runBlocking {
  61. val client = IrcClientImpl(Server(HOST, PORT), Profile(NICK, REAL_NAME, USER_NAME))
  62. client.socketFactory = mockSocketFactory
  63. readLineChannel.close()
  64. client.connect()
  65. with(inOrder(mockSocket).verify(mockSocket)) {
  66. sendLine("NICK :$NICK")
  67. sendLine("USER $USER_NAME localhost $HOST :$REAL_NAME")
  68. }
  69. }
  70. }
  71. @Test
  72. fun `IrcClientImpl sends password first, when present`() {
  73. runBlocking {
  74. val client = IrcClientImpl(Server(HOST, PORT, password = PASSWORD), Profile(NICK, REAL_NAME, USER_NAME))
  75. client.socketFactory = mockSocketFactory
  76. readLineChannel.close()
  77. client.connect()
  78. with(inOrder(mockSocket).verify(mockSocket)) {
  79. sendLine("PASS :$PASSWORD")
  80. sendLine("NICK :$NICK")
  81. }
  82. }
  83. }
  84. @Test
  85. fun `IrcClientImpl sends events to provided event handler`() {
  86. runBlocking {
  87. val client = IrcClientImpl(Server(HOST, PORT, password = PASSWORD), Profile(NICK, REAL_NAME, USER_NAME))
  88. client.socketFactory = mockSocketFactory
  89. client.eventHandler = mockEventHandler
  90. launch {
  91. readLineChannel.send(":the.gibson 001 acidBurn :Welcome to the IRC!".toByteArray())
  92. readLineChannel.close()
  93. }
  94. client.connect()
  95. verify(mockEventHandler).processEvent(client, ServerWelcome("acidBurn"))
  96. }
  97. }
  98. @Test
  99. fun `IrcClientImpl removes old event handlers when new one is added`() {
  100. runBlocking {
  101. val client = IrcClientImpl(Server(HOST, PORT, password = PASSWORD), Profile(NICK, REAL_NAME, USER_NAME))
  102. client.socketFactory = mockSocketFactory
  103. client.eventHandler = mockEventHandler
  104. client.eventHandler = mock()
  105. launch {
  106. readLineChannel.send(":the.gibson 001 acidBurn :Welcome to the IRC!".toByteArray())
  107. readLineChannel.close()
  108. }
  109. client.connect()
  110. verify(mockEventHandler, never()).processEvent(client, ServerWelcome("acidBurn"))
  111. }
  112. }
  113. @Test
  114. fun `IrcClientImpl removes old event handlers when it is set to null`() {
  115. runBlocking {
  116. val client = IrcClientImpl(Server(HOST, PORT, password = PASSWORD), Profile(NICK, REAL_NAME, USER_NAME))
  117. client.socketFactory = mockSocketFactory
  118. client.eventHandler = mockEventHandler
  119. client.eventHandler = null
  120. launch {
  121. readLineChannel.send(":the.gibson 001 acidBurn :Welcome to the IRC!".toByteArray())
  122. readLineChannel.close()
  123. }
  124. client.connect()
  125. verify(mockEventHandler, never()).processEvent(client, ServerWelcome("acidBurn"))
  126. }
  127. }
  128. @Test
  129. fun `IrcClient gets case mapping from server features`() {
  130. val client = IrcClientImpl(Server(HOST, PORT), Profile(NICK, REAL_NAME, USER_NAME))
  131. client.serverState.features[ServerFeature.ServerCaseMapping] = CaseMapping.RfcStrict
  132. assertEquals(CaseMapping.RfcStrict, client.caseMapping)
  133. }
  134. @Test
  135. fun `IrcClient indicates if user is local user or not`() {
  136. val client = IrcClientImpl(Server(HOST, PORT), Profile(NICK, REAL_NAME, USER_NAME))
  137. client.serverState.localNickname = "[acidBurn]"
  138. assertTrue(client.isLocalUser(User("{acidBurn}", "libby", "root.localhost")))
  139. assertFalse(client.isLocalUser(User("acid-Burn", "libby", "root.localhost")))
  140. }
  141. @Test
  142. fun `IrcClient uses current case mapping to check local user`() {
  143. val client = IrcClientImpl(Server(HOST, PORT), Profile(NICK, REAL_NAME, USER_NAME))
  144. client.serverState.localNickname = "[acidBurn]"
  145. client.serverState.features[ServerFeature.ServerCaseMapping] = CaseMapping.Ascii
  146. assertFalse(client.isLocalUser(User("{acidBurn}", "libby", "root.localhost")))
  147. }
  148. }