http_test.go 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644
  1. package toc
  2. import (
  3. "encoding/base64"
  4. "io"
  5. "log/slog"
  6. "net/http"
  7. "net/http/httptest"
  8. "testing"
  9. "github.com/stretchr/testify/assert"
  10. "github.com/stretchr/testify/mock"
  11. "github.com/mk6i/retro-aim-server/state"
  12. "github.com/mk6i/retro-aim-server/wire"
  13. )
  14. func TestOSCARProxy_NewServeMux(t *testing.T) {
  15. cookieBaker, err := state.NewHMACCookieBaker()
  16. assert.NoError(t, err)
  17. p := OSCARProxy{
  18. CookieBaker: cookieBaker,
  19. Logger: slog.Default(),
  20. }
  21. cookie, err := p.newHTTPAuthToken(state.NewIdentScreenName("me"))
  22. assert.NoError(t, err)
  23. cases := []struct {
  24. // name is the unit test name
  25. name string
  26. // path is the HTTP request path
  27. path string
  28. // expectedStatus is the expected HTTP response code
  29. expectedStatus int
  30. // expectedBody is the expected body payload
  31. expectedBody string
  32. // mockParams is the list of params sent to mocks that satisfy this
  33. // method's dependencies
  34. mockParams mockParams
  35. }{
  36. {
  37. name: "Successfully retrieve HTML profile",
  38. path: "/info?from=me&user=them&cookie=" + cookie,
  39. expectedStatus: http.StatusOK,
  40. expectedBody: `<font lang="0"><a href="aim:GoChat?RoomName=General&amp;Exchange=4">Let's chat</font></a><br><br><font color="#ff0000" lang="0">colorfg</font><font color="#000000"> </font><font back="#00ff00">colorbg</font><font> </font><font size="4">big</font><font size="3"> <b></font><font>bold</b></font><font> <i></font><font>italic</i></font><font> <u></font><font>underline</u></font><font> 8-)</font><hr><s>strike</s><sub>sub</sub><sup>sup</sup>`,
  41. mockParams: mockParams{
  42. locateParams: locateParams{
  43. userInfoQueryParams: userInfoQueryParams{
  44. {
  45. me: state.NewIdentScreenName("me"),
  46. inBody: wire.SNAC_0x02_0x05_LocateUserInfoQuery{
  47. Type: uint16(wire.LocateTypeSig),
  48. ScreenName: "them",
  49. },
  50. msg: wire.SNACMessage{
  51. Frame: wire.SNACFrame{
  52. FoodGroup: wire.Locate,
  53. SubGroup: wire.LocateUserInfoReply,
  54. },
  55. Body: wire.SNAC_0x02_0x06_LocateUserInfoReply{
  56. TLVUserInfo: newTestSession("them").TLVUserInfo(),
  57. LocateInfo: wire.TLVRestBlock{
  58. TLVList: wire.TLVList{
  59. wire.NewTLVBE(wire.LocateTLVTagsInfoSigData, `"<HTML><BODY BGCOLOR="#ffffff"><FONT LANG="0"><A HREF="aim:GoChat?RoomName=General&Exchange=4">Let's chat</FONT></A><BR><BR><FONT COLOR="#ff0000" LANG="0">colorfg</FONT><FONT COLOR="#000000"> </FONT><FONT BACK="#00ff00">colorbg</FONT><FONT> </FONT><FONT SIZE=4>big</FONT><FONT SIZE=3> <B></FONT><FONT>bold</B></FONT><FONT> <I></FONT><FONT>italic</I></FONT><FONT> <U></FONT><FONT>underline</U></FONT><FONT> 8-)</FONT><HR><S>strike</S><SUB>sub</SUB><SUP>sup</SUP></BODY></HTML>"`),
  60. },
  61. },
  62. },
  63. },
  64. },
  65. },
  66. },
  67. },
  68. },
  69. {
  70. name: "Successfully retrieve plaintext profile",
  71. path: "/info?from=me&user=them&cookie=" + cookie,
  72. expectedStatus: http.StatusOK,
  73. expectedBody: "My profile!",
  74. mockParams: mockParams{
  75. locateParams: locateParams{
  76. userInfoQueryParams: userInfoQueryParams{
  77. {
  78. me: state.NewIdentScreenName("me"),
  79. inBody: wire.SNAC_0x02_0x05_LocateUserInfoQuery{
  80. Type: uint16(wire.LocateTypeSig),
  81. ScreenName: "them",
  82. },
  83. msg: wire.SNACMessage{
  84. Frame: wire.SNACFrame{
  85. FoodGroup: wire.Locate,
  86. SubGroup: wire.LocateUserInfoReply,
  87. },
  88. Body: wire.SNAC_0x02_0x06_LocateUserInfoReply{
  89. TLVUserInfo: newTestSession("them").TLVUserInfo(),
  90. LocateInfo: wire.TLVRestBlock{
  91. TLVList: wire.TLVList{
  92. wire.NewTLVBE(wire.LocateTLVTagsInfoSigData, "My profile!"),
  93. },
  94. },
  95. },
  96. },
  97. },
  98. },
  99. },
  100. },
  101. },
  102. {
  103. name: "Retrieve profile with missing `from` query param",
  104. path: "/info?user=them&cookie=" + cookie,
  105. expectedStatus: http.StatusBadRequest,
  106. expectedBody: "required `from` param is missing",
  107. },
  108. {
  109. name: "Retrieve profile with missing `from` query param",
  110. path: "/info?from=me&cookie=" + cookie,
  111. expectedStatus: http.StatusBadRequest,
  112. expectedBody: "required `user` param is missing",
  113. },
  114. {
  115. name: "Retrieve profile with missing `cookie` query param",
  116. path: "/info?from=me&user=them",
  117. expectedStatus: http.StatusBadRequest,
  118. expectedBody: "required `cookie` param is missing",
  119. },
  120. {
  121. name: "Retrieve profile with invalid auth cookie",
  122. path: func() string {
  123. return "/info?from=me&user=them&cookie=" + base64.URLEncoding.EncodeToString([]byte("blahblah"))
  124. }(),
  125. expectedStatus: http.StatusForbidden,
  126. expectedBody: "invalid auth cookie",
  127. },
  128. {
  129. name: "Retrieve profile, receive error from locate svc",
  130. path: "/info?from=me&user=them&cookie=" + cookie,
  131. expectedStatus: http.StatusInternalServerError,
  132. expectedBody: "internal server error",
  133. mockParams: mockParams{
  134. locateParams: locateParams{
  135. userInfoQueryParams: userInfoQueryParams{
  136. {
  137. me: state.NewIdentScreenName("me"),
  138. inBody: wire.SNAC_0x02_0x05_LocateUserInfoQuery{
  139. Type: uint16(wire.LocateTypeSig),
  140. ScreenName: "them",
  141. },
  142. msg: wire.SNACMessage{
  143. Frame: wire.SNACFrame{
  144. FoodGroup: wire.Locate,
  145. SubGroup: wire.LocateUserInfoReply,
  146. },
  147. Body: wire.SNAC_0x02_0x06_LocateUserInfoReply{
  148. TLVUserInfo: newTestSession("them").TLVUserInfo(),
  149. LocateInfo: wire.TLVRestBlock{
  150. TLVList: wire.TLVList{
  151. wire.NewTLVBE(wire.LocateTLVTagsInfoSigData, "<HTML><BODY>My profile!</BODY></HTML>"),
  152. },
  153. },
  154. },
  155. },
  156. err: io.EOF,
  157. },
  158. },
  159. },
  160. },
  161. },
  162. {
  163. name: "Retrieve profile, receive unknown response from locate svc",
  164. path: "/info?from=me&user=them&cookie=" + cookie,
  165. expectedStatus: http.StatusInternalServerError,
  166. expectedBody: "internal server error",
  167. mockParams: mockParams{
  168. locateParams: locateParams{
  169. userInfoQueryParams: userInfoQueryParams{
  170. {
  171. me: state.NewIdentScreenName("me"),
  172. inBody: wire.SNAC_0x02_0x05_LocateUserInfoQuery{
  173. Type: uint16(wire.LocateTypeSig),
  174. ScreenName: "them",
  175. },
  176. msg: wire.SNACMessage{
  177. Frame: wire.SNACFrame{
  178. FoodGroup: wire.Locate,
  179. SubGroup: wire.LocateUserInfoReply,
  180. },
  181. Body: wire.SNAC_0x04_0x09_ICBMEvilReply{},
  182. },
  183. },
  184. },
  185. },
  186. },
  187. },
  188. {
  189. name: "Retrieve profile, user offline",
  190. path: "/info?from=me&user=them&cookie=" + cookie,
  191. expectedStatus: http.StatusNotFound,
  192. expectedBody: "user is unavailable",
  193. mockParams: mockParams{
  194. locateParams: locateParams{
  195. userInfoQueryParams: userInfoQueryParams{
  196. {
  197. me: state.NewIdentScreenName("me"),
  198. inBody: wire.SNAC_0x02_0x05_LocateUserInfoQuery{
  199. Type: uint16(wire.LocateTypeSig),
  200. ScreenName: "them",
  201. },
  202. msg: wire.SNACMessage{
  203. Frame: wire.SNACFrame{
  204. FoodGroup: wire.Locate,
  205. SubGroup: wire.LocateUserInfoReply,
  206. },
  207. Body: wire.SNACError{
  208. Code: wire.ErrorCodeNotLoggedOn,
  209. },
  210. },
  211. },
  212. },
  213. },
  214. },
  215. },
  216. {
  217. name: "Retrieve profile, receive error code from locate svc",
  218. path: "/info?from=me&user=them&cookie=" + cookie,
  219. expectedStatus: http.StatusInternalServerError,
  220. expectedBody: "internal server error",
  221. mockParams: mockParams{
  222. locateParams: locateParams{
  223. userInfoQueryParams: userInfoQueryParams{
  224. {
  225. me: state.NewIdentScreenName("me"),
  226. inBody: wire.SNAC_0x02_0x05_LocateUserInfoQuery{
  227. Type: uint16(wire.LocateTypeSig),
  228. ScreenName: "them",
  229. },
  230. msg: wire.SNACMessage{
  231. Frame: wire.SNACFrame{
  232. FoodGroup: wire.Locate,
  233. SubGroup: wire.LocateUserInfoReply,
  234. },
  235. Body: wire.SNACError{
  236. Code: wire.ErrorCodeInvalidSnac,
  237. },
  238. },
  239. },
  240. },
  241. },
  242. },
  243. },
  244. {
  245. name: "Successfully retrieve directory info",
  246. path: "/dir_info?user=them&cookie=" + cookie,
  247. expectedStatus: http.StatusOK,
  248. expectedBody: "their_first_name",
  249. mockParams: mockParams{
  250. locateParams: locateParams{
  251. dirInfoParams: dirInfoParams{
  252. {
  253. body: wire.SNAC_0x02_0x0B_LocateGetDirInfo{
  254. ScreenName: "them",
  255. },
  256. msg: wire.SNACMessage{
  257. Body: wire.SNAC_0x02_0x0C_LocateGetDirReply{
  258. Status: wire.LocateGetDirReplyOK,
  259. TLVBlock: wire.TLVBlock{
  260. TLVList: wire.TLVList{
  261. wire.NewTLVBE(wire.ODirTLVFirstName, "their_first_name"),
  262. },
  263. },
  264. },
  265. },
  266. },
  267. },
  268. },
  269. },
  270. },
  271. {
  272. name: "Retrieve directory info, no results found",
  273. path: "/dir_info?user=them&cookie=" + cookie,
  274. expectedStatus: http.StatusNotFound,
  275. expectedBody: "no user directory info found",
  276. mockParams: mockParams{
  277. locateParams: locateParams{
  278. dirInfoParams: dirInfoParams{
  279. {
  280. body: wire.SNAC_0x02_0x0B_LocateGetDirInfo{
  281. ScreenName: "them",
  282. },
  283. msg: wire.SNACMessage{
  284. Body: wire.SNAC_0x02_0x0C_LocateGetDirReply{
  285. Status: wire.LocateGetDirReplyOK,
  286. TLVBlock: wire.TLVBlock{
  287. TLVList: wire.TLVList{},
  288. },
  289. },
  290. },
  291. },
  292. },
  293. },
  294. },
  295. },
  296. {
  297. name: "Retrieve directory info, unexpected response from locate svc",
  298. path: "/dir_info?user=them&cookie=" + cookie,
  299. expectedStatus: http.StatusInternalServerError,
  300. expectedBody: "internal server error",
  301. mockParams: mockParams{
  302. locateParams: locateParams{
  303. dirInfoParams: dirInfoParams{
  304. {
  305. body: wire.SNAC_0x02_0x0B_LocateGetDirInfo{
  306. ScreenName: "them",
  307. },
  308. msg: wire.SNACMessage{
  309. Body: wire.SNACError{},
  310. },
  311. },
  312. },
  313. },
  314. },
  315. },
  316. {
  317. name: "Search directory with missing `user` query param",
  318. path: "/dir_info?cookie=" + cookie,
  319. expectedStatus: http.StatusBadRequest,
  320. expectedBody: "required `user` param is missing",
  321. },
  322. {
  323. name: "Retrieve directory info, receive err from locate svc",
  324. path: "/dir_info?user=them&cookie=" + cookie,
  325. expectedStatus: http.StatusInternalServerError,
  326. expectedBody: "internal server error",
  327. mockParams: mockParams{
  328. locateParams: locateParams{
  329. dirInfoParams: dirInfoParams{
  330. {
  331. body: wire.SNAC_0x02_0x0B_LocateGetDirInfo{
  332. ScreenName: "them",
  333. },
  334. msg: wire.SNACMessage{
  335. Body: wire.SNAC_0x02_0x0C_LocateGetDirReply{
  336. Status: wire.LocateGetDirReplyOK,
  337. TLVBlock: wire.TLVBlock{
  338. TLVList: wire.TLVList{
  339. wire.NewTLVBE(wire.ODirTLVFirstName, "their_first_name"),
  340. },
  341. },
  342. },
  343. },
  344. err: io.EOF,
  345. },
  346. },
  347. },
  348. },
  349. },
  350. {
  351. name: "Successfully search directory by name and address",
  352. path: "/dir_search?first_name=their_first_name" +
  353. "&middle_name=their_middle_name" +
  354. "&last_name=their_last_name" +
  355. "&maiden_name=their_maiden_name" +
  356. "&city=their_city" +
  357. "&state=their_state" +
  358. "&country=their_country" +
  359. "&cookie=" + cookie,
  360. expectedStatus: http.StatusOK,
  361. expectedBody: "their_first_name",
  362. mockParams: mockParams{
  363. dirSearchParams: dirSearchParams{
  364. infoQueryParams: infoQueryParams{
  365. {
  366. inBody: wire.SNAC_0x0F_0x02_InfoQuery{
  367. TLVRestBlock: wire.TLVRestBlock{
  368. TLVList: wire.TLVList{
  369. wire.NewTLVBE(wire.ODirTLVFirstName, "their_first_name"),
  370. wire.NewTLVBE(wire.ODirTLVMiddleName, "their_middle_name"),
  371. wire.NewTLVBE(wire.ODirTLVLastName, "their_last_name"),
  372. wire.NewTLVBE(wire.ODirTLVMaidenName, "their_maiden_name"),
  373. wire.NewTLVBE(wire.ODirTLVCity, "their_city"),
  374. wire.NewTLVBE(wire.ODirTLVState, "their_state"),
  375. wire.NewTLVBE(wire.ODirTLVCountry, "their_country"),
  376. },
  377. },
  378. },
  379. msg: wire.SNACMessage{
  380. Body: wire.SNAC_0x0F_0x03_InfoReply{
  381. Status: wire.ODirSearchResponseOK,
  382. Results: struct {
  383. List []wire.TLVBlock `oscar:"count_prefix=uint16"`
  384. }{
  385. List: []wire.TLVBlock{
  386. {
  387. TLVList: wire.TLVList{
  388. wire.NewTLVBE(wire.ODirTLVFirstName, "their_first_name"),
  389. },
  390. },
  391. },
  392. },
  393. },
  394. },
  395. },
  396. },
  397. },
  398. },
  399. },
  400. {
  401. name: "Successfully search directory by email",
  402. path: "/dir_search?email=their_email@aol.com&cookie=" + cookie,
  403. expectedStatus: http.StatusOK,
  404. expectedBody: "their_first_name",
  405. mockParams: mockParams{
  406. dirSearchParams: dirSearchParams{
  407. infoQueryParams: infoQueryParams{
  408. {
  409. inBody: wire.SNAC_0x0F_0x02_InfoQuery{
  410. TLVRestBlock: wire.TLVRestBlock{
  411. TLVList: wire.TLVList{
  412. wire.NewTLVBE(wire.ODirTLVEmailAddress, "their_email@aol.com"),
  413. },
  414. },
  415. },
  416. msg: wire.SNACMessage{
  417. Body: wire.SNAC_0x0F_0x03_InfoReply{
  418. Status: wire.ODirSearchResponseOK,
  419. Results: struct {
  420. List []wire.TLVBlock `oscar:"count_prefix=uint16"`
  421. }{
  422. List: []wire.TLVBlock{
  423. {
  424. TLVList: wire.TLVList{
  425. wire.NewTLVBE(wire.ODirTLVFirstName, "their_first_name"),
  426. },
  427. },
  428. },
  429. },
  430. },
  431. },
  432. },
  433. },
  434. },
  435. },
  436. },
  437. {
  438. name: "Successfully search directory by keyword",
  439. path: "/dir_search?keyword=their_keyword&cookie=" + cookie,
  440. expectedStatus: http.StatusOK,
  441. expectedBody: "their_first_name",
  442. mockParams: mockParams{
  443. dirSearchParams: dirSearchParams{
  444. infoQueryParams: infoQueryParams{
  445. {
  446. inBody: wire.SNAC_0x0F_0x02_InfoQuery{
  447. TLVRestBlock: wire.TLVRestBlock{
  448. TLVList: wire.TLVList{
  449. wire.NewTLVBE(wire.ODirTLVInterest, "their_keyword"),
  450. },
  451. },
  452. },
  453. msg: wire.SNACMessage{
  454. Body: wire.SNAC_0x0F_0x03_InfoReply{
  455. Status: wire.ODirSearchResponseOK,
  456. Results: struct {
  457. List []wire.TLVBlock `oscar:"count_prefix=uint16"`
  458. }{
  459. List: []wire.TLVBlock{
  460. {
  461. TLVList: wire.TLVList{
  462. wire.NewTLVBE(wire.ODirTLVFirstName, "their_first_name"),
  463. },
  464. },
  465. },
  466. },
  467. },
  468. },
  469. },
  470. },
  471. },
  472. },
  473. },
  474. {
  475. name: "Search directory by email, receive err from dir search svc",
  476. path: "/dir_search?email=their_email@aol.com&cookie=" + cookie,
  477. expectedStatus: http.StatusInternalServerError,
  478. expectedBody: "internal server error",
  479. mockParams: mockParams{
  480. dirSearchParams: dirSearchParams{
  481. infoQueryParams: infoQueryParams{
  482. {
  483. inBody: wire.SNAC_0x0F_0x02_InfoQuery{
  484. TLVRestBlock: wire.TLVRestBlock{
  485. TLVList: wire.TLVList{
  486. wire.NewTLVBE(wire.ODirTLVEmailAddress, "their_email@aol.com"),
  487. },
  488. },
  489. },
  490. msg: wire.SNACMessage{
  491. Body: wire.SNAC_0x0F_0x03_InfoReply{
  492. Status: wire.ODirSearchResponseOK,
  493. Results: struct {
  494. List []wire.TLVBlock `oscar:"count_prefix=uint16"`
  495. }{
  496. List: []wire.TLVBlock{
  497. {
  498. TLVList: wire.TLVList{
  499. wire.NewTLVBE(wire.ODirTLVFirstName, "their_first_name"),
  500. },
  501. },
  502. },
  503. },
  504. },
  505. },
  506. err: io.EOF,
  507. },
  508. },
  509. },
  510. },
  511. },
  512. {
  513. name: "Search directory by email, receive unknown response from dir search svc",
  514. path: "/dir_search?email=their_email@aol.com&cookie=" + cookie,
  515. expectedStatus: http.StatusInternalServerError,
  516. expectedBody: "internal server error",
  517. mockParams: mockParams{
  518. dirSearchParams: dirSearchParams{
  519. infoQueryParams: infoQueryParams{
  520. {
  521. inBody: wire.SNAC_0x0F_0x02_InfoQuery{
  522. TLVRestBlock: wire.TLVRestBlock{
  523. TLVList: wire.TLVList{
  524. wire.NewTLVBE(wire.ODirTLVEmailAddress, "their_email@aol.com"),
  525. },
  526. },
  527. },
  528. msg: wire.SNACMessage{
  529. Body: wire.SNACError{},
  530. },
  531. },
  532. },
  533. },
  534. },
  535. },
  536. {
  537. name: "Search directory without any correct search parameters",
  538. path: "/dir_search?cookie=" + cookie,
  539. expectedStatus: http.StatusBadRequest,
  540. expectedBody: "missing search parameters",
  541. mockParams: mockParams{
  542. dirSearchParams: dirSearchParams{
  543. infoQueryParams: infoQueryParams{
  544. {
  545. inBody: wire.SNAC_0x0F_0x02_InfoQuery{},
  546. msg: wire.SNACMessage{
  547. Body: wire.SNAC_0x0F_0x03_InfoReply{
  548. Status: wire.ODirSearchResponseNameMissing,
  549. },
  550. },
  551. },
  552. },
  553. },
  554. },
  555. },
  556. {
  557. name: "Search directory, receive error code from search dir svc",
  558. path: "/dir_search?cookie=" + cookie,
  559. expectedStatus: http.StatusInternalServerError,
  560. expectedBody: "internal server error",
  561. mockParams: mockParams{
  562. dirSearchParams: dirSearchParams{
  563. infoQueryParams: infoQueryParams{
  564. {
  565. inBody: wire.SNAC_0x0F_0x02_InfoQuery{},
  566. msg: wire.SNACMessage{
  567. Body: wire.SNAC_0x0F_0x03_InfoReply{
  568. Status: wire.ODirSearchResponseUnavailable1,
  569. },
  570. },
  571. },
  572. },
  573. },
  574. },
  575. },
  576. {
  577. name: "Search directory, receive unknown response from search dir svc",
  578. path: "/dir_search?cookie=" + cookie,
  579. expectedStatus: http.StatusInternalServerError,
  580. expectedBody: "internal server error",
  581. mockParams: mockParams{
  582. dirSearchParams: dirSearchParams{
  583. infoQueryParams: infoQueryParams{
  584. {
  585. inBody: wire.SNAC_0x0F_0x02_InfoQuery{},
  586. msg: wire.SNACMessage{
  587. Body: wire.SNAC_0x0F_0x03_InfoReply{
  588. Status: wire.ODirSearchResponseUnavailable1,
  589. },
  590. },
  591. },
  592. },
  593. },
  594. },
  595. },
  596. }
  597. for _, tc := range cases {
  598. t.Run(tc.name, func(t *testing.T) {
  599. locateSvc := newMockLocateService(t)
  600. for _, params := range tc.mockParams.userInfoQueryParams {
  601. locateSvc.EXPECT().
  602. UserInfoQuery(mock.Anything, matchSession(params.me), wire.SNACFrame{}, params.inBody).
  603. Return(params.msg, params.err)
  604. }
  605. for _, params := range tc.mockParams.dirInfoParams {
  606. locateSvc.EXPECT().
  607. DirInfo(mock.Anything, wire.SNACFrame{}, params.body).
  608. Return(params.msg, params.err)
  609. }
  610. dirSearchSvc := newMockDirSearchService(t)
  611. for _, params := range tc.mockParams.infoQueryParams {
  612. dirSearchSvc.EXPECT().
  613. InfoQuery(mock.Anything, wire.SNACFrame{}, params.inBody).
  614. Return(params.msg, params.err)
  615. }
  616. svc := OSCARProxy{
  617. CookieBaker: cookieBaker,
  618. DirSearchService: dirSearchSvc,
  619. LocateService: locateSvc,
  620. Logger: slog.Default(),
  621. }
  622. req, err := http.NewRequest(http.MethodGet, tc.path, nil)
  623. if err != nil {
  624. t.Fatalf("Failed to create request: %v", err)
  625. }
  626. rr := httptest.NewRecorder()
  627. svc.NewServeMux().ServeHTTP(rr, req)
  628. assert.Equal(t, tc.expectedStatus, rr.Code)
  629. assert.Contains(t, rr.Body.String(), tc.expectedBody)
  630. })
  631. }
  632. }