chat_test.go 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257
  1. package server
  2. import (
  3. "bytes"
  4. "context"
  5. "github.com/stretchr/testify/mock"
  6. "testing"
  7. "github.com/mkaminski/goaim/oscar"
  8. "github.com/stretchr/testify/assert"
  9. )
  10. func TestSendAndReceiveChatChannelMsgToHost(t *testing.T) {
  11. cases := []struct {
  12. // name is the unit test name
  13. name string
  14. // userSession is the session of the user sending the chat message
  15. userSession *Session
  16. // inputSNAC is the SNAC sent by the sender client
  17. inputSNAC oscar.SNAC_0x0E_0x05_ChatChannelMsgToHost
  18. // expectSNACToParticipants is the message the server broadcast to chat
  19. // room participants (except the sender)
  20. expectSNACToParticipants oscar.XMessage
  21. expectOutput *oscar.XMessage
  22. }{
  23. {
  24. name: "send chat room message, expect acknowledgement to sender client",
  25. userSession: newTestSession("user_sending_chat_msg", sessOptCannedSignonTime),
  26. inputSNAC: oscar.SNAC_0x0E_0x05_ChatChannelMsgToHost{
  27. Cookie: 1234,
  28. Channel: 14,
  29. TLVRestBlock: oscar.TLVRestBlock{
  30. TLVList: oscar.TLVList{
  31. {
  32. TType: oscar.ChatTLVPublicWhisperFlag,
  33. Val: []byte{},
  34. },
  35. {
  36. TType: oscar.ChatTLVEnableReflectionFlag,
  37. Val: []byte{},
  38. },
  39. },
  40. },
  41. },
  42. expectSNACToParticipants: oscar.XMessage{
  43. SnacFrame: oscar.SnacFrame{
  44. FoodGroup: oscar.CHAT,
  45. SubGroup: oscar.ChatChannelMsgToClient,
  46. },
  47. SnacOut: oscar.SNAC_0x0E_0x06_ChatChannelMsgToClient{
  48. Cookie: 1234,
  49. Channel: 14,
  50. TLVRestBlock: oscar.TLVRestBlock{
  51. TLVList: oscar.TLVList{
  52. oscar.NewTLV(oscar.ChatTLVPublicWhisperFlag, []byte{}),
  53. oscar.NewTLV(oscar.ChatTLVEnableReflectionFlag, []byte{}),
  54. oscar.NewTLV(oscar.ChatTLVSenderInformation,
  55. newTestSession("user_sending_chat_msg", sessOptCannedSignonTime).TLVUserInfo()),
  56. },
  57. },
  58. },
  59. },
  60. expectOutput: &oscar.XMessage{
  61. SnacFrame: oscar.SnacFrame{
  62. FoodGroup: oscar.CHAT,
  63. SubGroup: oscar.ChatChannelMsgToClient,
  64. },
  65. SnacOut: oscar.SNAC_0x0E_0x06_ChatChannelMsgToClient{
  66. Cookie: 1234,
  67. Channel: 14,
  68. TLVRestBlock: oscar.TLVRestBlock{
  69. TLVList: oscar.TLVList{
  70. oscar.NewTLV(oscar.ChatTLVPublicWhisperFlag, []byte{}),
  71. oscar.NewTLV(oscar.ChatTLVEnableReflectionFlag, []byte{}),
  72. oscar.NewTLV(oscar.ChatTLVSenderInformation, newTestSession("user_sending_chat_msg", sessOptCannedSignonTime).TLVUserInfo()),
  73. },
  74. },
  75. },
  76. },
  77. },
  78. {
  79. name: "send chat room message, don't expect acknowledgement to sender client",
  80. userSession: newTestSession("user_sending_chat_msg", sessOptCannedSignonTime),
  81. inputSNAC: oscar.SNAC_0x0E_0x05_ChatChannelMsgToHost{
  82. Cookie: 1234,
  83. Channel: 14,
  84. TLVRestBlock: oscar.TLVRestBlock{
  85. TLVList: oscar.TLVList{
  86. {
  87. TType: oscar.ChatTLVPublicWhisperFlag,
  88. Val: []byte{},
  89. },
  90. },
  91. },
  92. },
  93. expectSNACToParticipants: oscar.XMessage{
  94. SnacFrame: oscar.SnacFrame{
  95. FoodGroup: oscar.CHAT,
  96. SubGroup: oscar.ChatChannelMsgToClient,
  97. },
  98. SnacOut: oscar.SNAC_0x0E_0x06_ChatChannelMsgToClient{
  99. Cookie: 1234,
  100. Channel: 14,
  101. TLVRestBlock: oscar.TLVRestBlock{
  102. TLVList: oscar.TLVList{
  103. oscar.NewTLV(oscar.ChatTLVPublicWhisperFlag, []byte{}),
  104. oscar.NewTLV(oscar.ChatTLVSenderInformation,
  105. newTestSession("user_sending_chat_msg", sessOptCannedSignonTime).TLVUserInfo()),
  106. },
  107. },
  108. },
  109. },
  110. expectOutput: &oscar.XMessage{},
  111. },
  112. }
  113. for _, tc := range cases {
  114. t.Run(tc.name, func(t *testing.T) {
  115. //
  116. // initialize dependencies
  117. //
  118. crm := NewMockChatSessionManager(t)
  119. crm.EXPECT().
  120. BroadcastExcept(mock.Anything, tc.userSession, tc.expectSNACToParticipants)
  121. //
  122. // send input SNAC
  123. //
  124. svc := ChatService{}
  125. outputSNAC, err := svc.ChannelMsgToHostHandler(context.Background(), tc.userSession, crm, tc.inputSNAC)
  126. assert.NoError(t, err)
  127. if tc.expectOutput.SnacFrame == (oscar.SnacFrame{}) {
  128. return // handler doesn't return response
  129. }
  130. assert.Equal(t, tc.expectOutput, outputSNAC)
  131. })
  132. }
  133. }
  134. func TestChatRouter_RouteChat(t *testing.T) {
  135. cases := []struct {
  136. // name is the unit test name
  137. name string
  138. // input is the request payload
  139. input oscar.XMessage
  140. // output is the response payload
  141. output *oscar.XMessage
  142. // handlerErr is the mocked handler error response
  143. handlerErr error
  144. // expectErr is the expected error returned by the router
  145. expectErr error
  146. }{
  147. {
  148. name: "receive ChatChannelMsgToHost, return ChatChannelMsgToClient",
  149. input: oscar.XMessage{
  150. SnacFrame: oscar.SnacFrame{
  151. FoodGroup: oscar.CHAT,
  152. SubGroup: oscar.ChatChannelMsgToHost,
  153. },
  154. SnacOut: oscar.SNAC_0x0E_0x05_ChatChannelMsgToHost{
  155. Channel: 4,
  156. },
  157. },
  158. output: &oscar.XMessage{
  159. SnacFrame: oscar.SnacFrame{
  160. FoodGroup: oscar.CHAT,
  161. SubGroup: oscar.ChatChannelMsgToClient,
  162. },
  163. SnacOut: oscar.SNAC_0x0E_0x06_ChatChannelMsgToClient{
  164. Channel: 4,
  165. },
  166. },
  167. },
  168. {
  169. name: "receive ChatChannelMsgToHost, return no response",
  170. input: oscar.XMessage{
  171. SnacFrame: oscar.SnacFrame{
  172. FoodGroup: oscar.CHAT,
  173. SubGroup: oscar.ChatChannelMsgToHost,
  174. },
  175. SnacOut: oscar.SNAC_0x0E_0x05_ChatChannelMsgToHost{
  176. Channel: 4,
  177. },
  178. },
  179. output: nil,
  180. },
  181. {
  182. name: "receive ChatRowListInfo, return ErrUnsupportedSubGroup",
  183. input: oscar.XMessage{
  184. SnacFrame: oscar.SnacFrame{
  185. FoodGroup: oscar.CHAT,
  186. SubGroup: oscar.ChatRowListInfo,
  187. },
  188. SnacOut: struct{}{},
  189. },
  190. output: nil,
  191. expectErr: ErrUnsupportedSubGroup,
  192. },
  193. }
  194. for _, tc := range cases {
  195. t.Run(tc.name, func(t *testing.T) {
  196. svc := NewMockChatHandler(t)
  197. svc.EXPECT().
  198. ChannelMsgToHostHandler(mock.Anything, mock.Anything, mock.Anything, tc.input.SnacOut).
  199. Return(tc.output, tc.handlerErr).
  200. Maybe()
  201. router := ChatRouter{
  202. ChatHandler: svc,
  203. RouteLogger: RouteLogger{
  204. Logger: NewLogger(Config{}),
  205. },
  206. }
  207. bufIn := &bytes.Buffer{}
  208. assert.NoError(t, oscar.Marshal(tc.input.SnacOut, bufIn))
  209. bufOut := &bytes.Buffer{}
  210. seq := uint32(0)
  211. err := router.RouteChat(nil, nil, nil, tc.input.SnacFrame, bufIn, bufOut, &seq)
  212. assert.ErrorIs(t, err, tc.expectErr)
  213. if tc.expectErr != nil {
  214. return
  215. }
  216. if tc.output == nil {
  217. // make sure no response was sent
  218. assert.Empty(t, bufOut.Bytes())
  219. return
  220. }
  221. // verify the FLAP frame
  222. flap := oscar.FlapFrame{}
  223. assert.NoError(t, oscar.Unmarshal(&flap, bufOut))
  224. // make sure the sequence increments
  225. assert.Equal(t, seq, uint32(1))
  226. assert.Equal(t, flap.Sequence, uint16(0))
  227. flapBuf, err := flap.SNACBuffer(bufOut)
  228. assert.NoError(t, err)
  229. // verify the SNAC frame
  230. snacFrame := oscar.SnacFrame{}
  231. assert.NoError(t, oscar.Unmarshal(&snacFrame, flapBuf))
  232. assert.Equal(t, tc.output.SnacFrame, snacFrame)
  233. // verify the SNAC message
  234. snacBuf := &bytes.Buffer{}
  235. assert.NoError(t, oscar.Marshal(tc.output.SnacOut, snacBuf))
  236. assert.Equal(t, snacBuf.Bytes(), flapBuf.Bytes())
  237. })
  238. }
  239. }