chat_test.go 7.0 KB

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