oservice_test.go 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501
  1. package handler
  2. import (
  3. "bytes"
  4. "context"
  5. "log/slog"
  6. "testing"
  7. "github.com/mk6i/retro-aim-server/server/oscar/middleware"
  8. "github.com/mk6i/retro-aim-server/state"
  9. "github.com/mk6i/retro-aim-server/wire"
  10. "github.com/stretchr/testify/assert"
  11. "github.com/stretchr/testify/mock"
  12. )
  13. func TestOServiceBOSHandler_ClientOnline(t *testing.T) {
  14. input := wire.SNACMessage{
  15. Frame: wire.SNACFrame{
  16. FoodGroup: wire.OService,
  17. SubGroup: wire.OServiceClientOnline,
  18. },
  19. Body: wire.SNAC_0x01_0x02_OServiceClientOnline{
  20. GroupVersions: []struct {
  21. FoodGroup uint16
  22. Version uint16
  23. ToolID uint16
  24. ToolVersion uint16
  25. }{
  26. {
  27. FoodGroup: 10,
  28. },
  29. },
  30. },
  31. }
  32. svc := newMockOServiceService(t)
  33. svc.EXPECT().
  34. ClientOnline(mock.Anything, input.Body, mock.Anything).
  35. Return(nil)
  36. h := NewOServiceHandler(slog.Default(), svc)
  37. responseWriter := newMockResponseWriter(t)
  38. buf := &bytes.Buffer{}
  39. assert.NoError(t, wire.MarshalBE(input.Body, buf))
  40. assert.NoError(t, h.ClientOnline(nil, nil, input.Frame, buf, responseWriter))
  41. }
  42. func TestOServiceBOSHandler_ServiceRequest(t *testing.T) {
  43. input := wire.SNACMessage{
  44. Frame: wire.SNACFrame{
  45. FoodGroup: wire.OService,
  46. SubGroup: wire.OServiceServiceRequest,
  47. },
  48. Body: wire.SNAC_0x01_0x04_OServiceServiceRequest{
  49. FoodGroup: wire.Chat,
  50. },
  51. }
  52. output := wire.SNACMessage{
  53. Frame: wire.SNACFrame{
  54. FoodGroup: wire.OService,
  55. SubGroup: wire.OServiceServiceResponse,
  56. },
  57. Body: wire.SNAC_0x01_0x05_OServiceServiceResponse{
  58. TLVRestBlock: wire.TLVRestBlock{
  59. TLVList: wire.TLVList{
  60. wire.NewTLVBE(0x01, uint16(1000)),
  61. },
  62. },
  63. },
  64. }
  65. svc := newMockOServiceService(t)
  66. svc.EXPECT().
  67. ServiceRequest(mock.Anything, mock.Anything, input.Frame, input.Body).
  68. Return(output, nil)
  69. h := NewOServiceHandler(slog.Default(), svc)
  70. responseWriter := newMockResponseWriter(t)
  71. responseWriter.EXPECT().
  72. SendSNAC(output.Frame, output.Body).
  73. Return(nil)
  74. buf := &bytes.Buffer{}
  75. assert.NoError(t, wire.MarshalBE(input.Body, buf))
  76. assert.NoError(t, h.ServiceRequest(nil, nil, input.Frame, buf, responseWriter))
  77. }
  78. func TestOServiceChatHandler_ClientOnline(t *testing.T) {
  79. input := wire.SNACMessage{
  80. Frame: wire.SNACFrame{
  81. FoodGroup: wire.OService,
  82. SubGroup: wire.OServiceClientOnline,
  83. },
  84. Body: wire.SNAC_0x01_0x02_OServiceClientOnline{
  85. GroupVersions: []struct {
  86. FoodGroup uint16
  87. Version uint16
  88. ToolID uint16
  89. ToolVersion uint16
  90. }{
  91. {
  92. FoodGroup: 10,
  93. },
  94. },
  95. },
  96. }
  97. svc := newMockOServiceService(t)
  98. svc.EXPECT().
  99. ClientOnline(mock.Anything, mock.Anything, mock.Anything).
  100. Return(nil)
  101. h := NewOServiceHandler(slog.Default(), svc)
  102. responseWriter := newMockResponseWriter(t)
  103. buf := &bytes.Buffer{}
  104. assert.NoError(t, wire.MarshalBE(input.Body, buf))
  105. assert.NoError(t, h.ClientOnline(nil, nil, input.Frame, buf, responseWriter))
  106. }
  107. func TestOServiceHandler_IdleNotification(t *testing.T) {
  108. input := wire.SNACMessage{
  109. Frame: wire.SNACFrame{
  110. FoodGroup: wire.OService,
  111. SubGroup: wire.OServiceIdleNotification,
  112. },
  113. Body: wire.SNAC_0x01_0x11_OServiceIdleNotification{
  114. IdleTime: 10,
  115. },
  116. }
  117. svc := newMockOServiceService(t)
  118. svc.EXPECT().
  119. IdleNotification(mock.Anything, mock.Anything, input.Body).
  120. Return(nil)
  121. h := OServiceHandler{
  122. OServiceService: svc,
  123. RouteLogger: middleware.RouteLogger{
  124. Logger: slog.Default(),
  125. },
  126. }
  127. responseWriter := newMockResponseWriter(t)
  128. buf := &bytes.Buffer{}
  129. assert.NoError(t, wire.MarshalBE(input.Body, buf))
  130. assert.NoError(t, h.IdleNotification(nil, nil, input.Frame, buf, responseWriter))
  131. }
  132. func TestOServiceHandler_ClientVersions(t *testing.T) {
  133. input := wire.SNACMessage{
  134. Frame: wire.SNACFrame{
  135. FoodGroup: wire.OService,
  136. SubGroup: wire.OServiceClientVersions,
  137. },
  138. Body: wire.SNAC_0x01_0x17_OServiceClientVersions{
  139. Versions: []uint16{
  140. 10,
  141. },
  142. },
  143. }
  144. output := wire.SNACMessage{
  145. Frame: wire.SNACFrame{
  146. FoodGroup: wire.OService,
  147. SubGroup: wire.OServiceHostVersions,
  148. },
  149. Body: wire.SNAC_0x01_0x18_OServiceHostVersions{
  150. Versions: []uint16{
  151. 10,
  152. },
  153. },
  154. }
  155. sess := state.NewSession()
  156. svc := newMockOServiceService(t)
  157. svc.EXPECT().
  158. ClientVersions(mock.Anything, sess, input.Frame, input.Body).
  159. Return(output)
  160. h := OServiceHandler{
  161. OServiceService: svc,
  162. RouteLogger: middleware.RouteLogger{
  163. Logger: slog.Default(),
  164. },
  165. }
  166. responseWriter := newMockResponseWriter(t)
  167. responseWriter.EXPECT().
  168. SendSNAC(output.Frame, output.Body).
  169. Return(nil)
  170. buf := &bytes.Buffer{}
  171. assert.NoError(t, wire.MarshalBE(input.Body, buf))
  172. assert.NoError(t, h.ClientVersions(context.Background(), sess, input.Frame, buf, responseWriter))
  173. }
  174. func TestOServiceHandler_RateParamsQuery(t *testing.T) {
  175. input := wire.SNACMessage{
  176. Frame: wire.SNACFrame{
  177. FoodGroup: wire.OService,
  178. SubGroup: wire.OServiceRateParamsQuery,
  179. },
  180. Body: struct{}{},
  181. }
  182. output := wire.SNACMessage{
  183. Frame: wire.SNACFrame{
  184. FoodGroup: wire.OService,
  185. SubGroup: wire.OServiceRateParamsReply,
  186. },
  187. Body: wire.SNAC_0x01_0x07_OServiceRateParamsReply{
  188. RateGroups: []struct {
  189. ID uint16
  190. Pairs []struct {
  191. FoodGroup uint16
  192. SubGroup uint16
  193. } `oscar:"count_prefix=uint16"`
  194. }{
  195. {
  196. ID: 1,
  197. },
  198. },
  199. },
  200. }
  201. svc := newMockOServiceService(t)
  202. svc.EXPECT().
  203. RateParamsQuery(mock.Anything, mock.Anything, input.Frame).
  204. Return(output)
  205. h := OServiceHandler{
  206. OServiceService: svc,
  207. RouteLogger: middleware.RouteLogger{
  208. Logger: slog.Default(),
  209. },
  210. }
  211. responseWriter := newMockResponseWriter(t)
  212. responseWriter.EXPECT().
  213. SendSNAC(output.Frame, output.Body).
  214. Return(nil)
  215. buf := &bytes.Buffer{}
  216. assert.NoError(t, wire.MarshalBE(input.Body, buf))
  217. assert.NoError(t, h.RateParamsQuery(nil, nil, input.Frame, buf, responseWriter))
  218. }
  219. func TestOServiceHandler_RateParamsSubAdd(t *testing.T) {
  220. input := wire.SNACMessage{
  221. Frame: wire.SNACFrame{
  222. FoodGroup: wire.OService,
  223. SubGroup: wire.OServiceRateParamsSubAdd,
  224. },
  225. Body: wire.SNAC_0x01_0x08_OServiceRateParamsSubAdd{
  226. ClassIDs: []uint16{1, 2, 3, 4},
  227. },
  228. }
  229. sess := state.NewSession()
  230. svc := newMockOServiceService(t)
  231. svc.EXPECT().
  232. RateParamsSubAdd(mock.Anything, sess, input.Body)
  233. h := OServiceHandler{
  234. OServiceService: svc,
  235. RouteLogger: middleware.RouteLogger{
  236. Logger: slog.Default(),
  237. },
  238. }
  239. buf := &bytes.Buffer{}
  240. assert.NoError(t, wire.MarshalBE(input.Body, buf))
  241. assert.NoError(t, h.RateParamsSubAdd(context.Background(), sess, input.Frame, buf, nil))
  242. }
  243. func TestOServiceHandler_SetUserInfoFields(t *testing.T) {
  244. input := wire.SNACMessage{
  245. Frame: wire.SNACFrame{
  246. FoodGroup: wire.OService,
  247. SubGroup: wire.OServiceSetUserInfoFields,
  248. },
  249. Body: wire.SNAC_0x01_0x1E_OServiceSetUserInfoFields{
  250. TLVRestBlock: wire.TLVRestBlock{
  251. TLVList: wire.TLVList{
  252. wire.NewTLVBE(0x01, []byte{1, 2, 3, 4}),
  253. },
  254. },
  255. },
  256. }
  257. output := wire.SNACMessage{
  258. Frame: wire.SNACFrame{
  259. FoodGroup: wire.OService,
  260. SubGroup: wire.OServiceUserInfoUpdate,
  261. },
  262. Body: wire.SNAC_0x01_0x0F_OServiceUserInfoUpdate{
  263. UserInfo: []wire.TLVUserInfo{
  264. {ScreenName: "screen-name"},
  265. {ScreenName: "screen-name"},
  266. },
  267. },
  268. }
  269. svc := newMockOServiceService(t)
  270. svc.EXPECT().
  271. SetUserInfoFields(mock.Anything, mock.Anything, input.Frame, input.Body).
  272. Return(output, nil)
  273. h := OServiceHandler{
  274. OServiceService: svc,
  275. RouteLogger: middleware.RouteLogger{
  276. Logger: slog.Default(),
  277. },
  278. }
  279. responseWriter := newMockResponseWriter(t)
  280. responseWriter.EXPECT().
  281. SendSNAC(output.Frame, output.Body).
  282. Return(nil)
  283. buf := &bytes.Buffer{}
  284. assert.NoError(t, wire.MarshalBE(input.Body, buf))
  285. assert.NoError(t, h.SetUserInfoFields(nil, nil, input.Frame, buf, responseWriter))
  286. }
  287. func TestOServiceHandler_UserInfoQuery(t *testing.T) {
  288. input := wire.SNACMessage{
  289. Frame: wire.SNACFrame{
  290. FoodGroup: wire.OService,
  291. SubGroup: wire.OServiceUserInfoQuery,
  292. },
  293. Body: struct{}{},
  294. }
  295. output := wire.SNACMessage{
  296. Frame: wire.SNACFrame{
  297. FoodGroup: wire.OService,
  298. SubGroup: wire.OServiceUserInfoUpdate,
  299. },
  300. Body: wire.SNAC_0x01_0x0F_OServiceUserInfoUpdate{
  301. UserInfo: []wire.TLVUserInfo{
  302. {ScreenName: "screen-name"},
  303. {ScreenName: "screen-name"},
  304. },
  305. },
  306. }
  307. svc := newMockOServiceService(t)
  308. svc.EXPECT().
  309. UserInfoQuery(mock.Anything, mock.Anything, input.Frame).
  310. Return(output)
  311. h := OServiceHandler{
  312. OServiceService: svc,
  313. RouteLogger: middleware.RouteLogger{
  314. Logger: slog.Default(),
  315. },
  316. }
  317. responseWriter := newMockResponseWriter(t)
  318. responseWriter.EXPECT().
  319. SendSNAC(output.Frame, output.Body).
  320. Return(nil)
  321. buf := &bytes.Buffer{}
  322. assert.NoError(t, wire.MarshalBE(input.Body, buf))
  323. assert.NoError(t, h.UserInfoQuery(nil, nil, input.Frame, buf, responseWriter))
  324. }
  325. func TestOServiceHandler_Noop(t *testing.T) {
  326. input := wire.SNACMessage{
  327. Frame: wire.SNACFrame{
  328. FoodGroup: wire.OService,
  329. SubGroup: wire.OServiceNoop,
  330. },
  331. Body: struct{}{},
  332. }
  333. h := OServiceHandler{
  334. RouteLogger: middleware.RouteLogger{
  335. Logger: slog.Default(),
  336. },
  337. }
  338. responseWriter := newMockResponseWriter(t)
  339. buf := &bytes.Buffer{}
  340. assert.NoError(t, wire.MarshalBE(input.Body, buf))
  341. assert.NoError(t, h.Noop(nil, nil, input.Frame, buf, responseWriter))
  342. }
  343. func TestOServiceHandler_SetPrivacyFlags(t *testing.T) {
  344. input := wire.SNACMessage{
  345. Frame: wire.SNACFrame{
  346. FoodGroup: wire.OService,
  347. SubGroup: wire.OServiceSetPrivacyFlags,
  348. },
  349. Body: wire.SNAC_0x01_0x14_OServiceSetPrivacyFlags{
  350. PrivacyFlags: wire.OServicePrivacyFlagMember,
  351. },
  352. }
  353. svc := newMockOServiceService(t)
  354. svc.EXPECT().
  355. SetPrivacyFlags(mock.Anything, input.Body)
  356. h := OServiceHandler{
  357. OServiceService: svc,
  358. RouteLogger: middleware.RouteLogger{
  359. Logger: slog.Default(),
  360. },
  361. }
  362. responseWriter := newMockResponseWriter(t)
  363. buf := &bytes.Buffer{}
  364. assert.NoError(t, wire.MarshalBE(input.Body, buf))
  365. assert.NoError(t, h.SetPrivacyFlags(nil, nil, input.Frame, buf, responseWriter))
  366. }
  367. func TestOServiceChatNavHandler_ClientOnline(t *testing.T) {
  368. input := wire.SNACMessage{
  369. Frame: wire.SNACFrame{
  370. FoodGroup: wire.OService,
  371. SubGroup: wire.OServiceClientOnline,
  372. },
  373. Body: wire.SNAC_0x01_0x02_OServiceClientOnline{
  374. GroupVersions: []struct {
  375. FoodGroup uint16
  376. Version uint16
  377. ToolID uint16
  378. ToolVersion uint16
  379. }{
  380. {
  381. FoodGroup: 10,
  382. },
  383. },
  384. },
  385. }
  386. svc := newMockOServiceService(t)
  387. svc.EXPECT().
  388. ClientOnline(mock.Anything, input.Body, mock.Anything).
  389. Return(nil)
  390. h := NewOServiceHandler(slog.Default(), svc)
  391. responseWriter := newMockResponseWriter(t)
  392. buf := &bytes.Buffer{}
  393. assert.NoError(t, wire.MarshalBE(input.Body, buf))
  394. assert.NoError(t, h.ClientOnline(nil, nil, input.Frame, buf, responseWriter))
  395. }
  396. func TestOServiceAlertHandler_ClientOnline(t *testing.T) {
  397. input := wire.SNACMessage{
  398. Frame: wire.SNACFrame{
  399. FoodGroup: wire.OService,
  400. SubGroup: wire.OServiceClientOnline,
  401. },
  402. Body: wire.SNAC_0x01_0x02_OServiceClientOnline{
  403. GroupVersions: []struct {
  404. FoodGroup uint16
  405. Version uint16
  406. ToolID uint16
  407. ToolVersion uint16
  408. }{
  409. {
  410. FoodGroup: 10,
  411. },
  412. },
  413. },
  414. }
  415. svc := newMockOServiceService(t)
  416. svc.EXPECT().
  417. ClientOnline(mock.Anything, input.Body, mock.Anything).
  418. Return(nil)
  419. h := NewOServiceHandler(slog.Default(), svc)
  420. responseWriter := newMockResponseWriter(t)
  421. buf := &bytes.Buffer{}
  422. assert.NoError(t, wire.MarshalBE(input.Body, buf))
  423. assert.NoError(t, h.ClientOnline(nil, nil, input.Frame, buf, responseWriter))
  424. }