Nelze vybrat více než 25 témat Téma musí začínat písmenem nebo číslem, může obsahovat pomlčky („-“) a může být dlouhé až 35 znaků.

IrcClientTest.kt 7.0KB

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