chat_nav_test.go 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  1. package oscar
  2. import (
  3. "bytes"
  4. "context"
  5. "io"
  6. "log/slog"
  7. "testing"
  8. "github.com/stretchr/testify/assert"
  9. "github.com/stretchr/testify/mock"
  10. "github.com/mk6i/retro-aim-server/state"
  11. "github.com/mk6i/retro-aim-server/wire"
  12. )
  13. func TestChatNavServer_handleNewConnection(t *testing.T) {
  14. sess := state.NewSession()
  15. sess.SetID("login-cookie-1234")
  16. clientReader, serverWriter := io.Pipe()
  17. serverReader, clientWriter := io.Pipe()
  18. go func() {
  19. // < receive FLAPSignonFrame
  20. flap := wire.FLAPFrame{}
  21. assert.NoError(t, wire.Unmarshal(&flap, serverReader))
  22. buf, err := flap.ReadBody(serverReader)
  23. assert.NoError(t, err)
  24. flapSignonFrame := wire.FLAPSignonFrame{}
  25. assert.NoError(t, wire.Unmarshal(&flapSignonFrame, buf))
  26. // > send FLAPSignonFrame
  27. flapSignonFrame = wire.FLAPSignonFrame{
  28. FLAPVersion: 1,
  29. }
  30. flapSignonFrame.Append(wire.NewTLV(wire.OServiceTLVTagsLoginCookie, []byte(sess.ID())))
  31. buf = &bytes.Buffer{}
  32. assert.NoError(t, wire.Marshal(flapSignonFrame, buf))
  33. flap = wire.FLAPFrame{
  34. StartMarker: 42,
  35. FrameType: wire.FLAPFrameSignon,
  36. PayloadLength: uint16(buf.Len()),
  37. }
  38. assert.NoError(t, wire.Marshal(flap, serverWriter))
  39. _, err = serverWriter.Write(buf.Bytes())
  40. assert.NoError(t, err)
  41. // < receive SNAC_0x01_0x03_OServiceHostOnline
  42. flap = wire.FLAPFrame{}
  43. assert.NoError(t, wire.Unmarshal(&flap, serverReader))
  44. buf, err = flap.ReadBody(serverReader)
  45. assert.NoError(t, err)
  46. frame := wire.SNACFrame{}
  47. assert.NoError(t, wire.Unmarshal(&frame, buf))
  48. body := wire.SNAC_0x01_0x03_OServiceHostOnline{}
  49. assert.NoError(t, wire.Unmarshal(&body, buf))
  50. // send the first request that should get relayed to Handler
  51. flapc := flapClient{
  52. w: serverWriter,
  53. }
  54. frame = wire.SNACFrame{
  55. FoodGroup: wire.OService,
  56. SubGroup: wire.OServiceClientOnline,
  57. }
  58. assert.NoError(t, flapc.SendSNAC(frame, struct{}{}))
  59. assert.NoError(t, serverWriter.Close())
  60. }()
  61. authService := newMockAuthService(t)
  62. authService.EXPECT().
  63. RetrieveBOSSession(sess.ID()).
  64. Return(sess, nil)
  65. onlineNotifier := newMockOnlineNotifier(t)
  66. onlineNotifier.EXPECT().
  67. HostOnline().
  68. Return(wire.SNACMessage{
  69. Frame: wire.SNACFrame{
  70. FoodGroup: wire.OService,
  71. SubGroup: wire.OServiceHostOnline,
  72. },
  73. Body: wire.SNAC_0x01_0x03_OServiceHostOnline{},
  74. })
  75. // we can't assert that the same sess instance created above is passed as a
  76. // parameter to Handle because the session instance is copied
  77. router := newMockHandler(t)
  78. router.EXPECT().
  79. Handle(mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).
  80. Run(func(ctx context.Context, sess *state.Session, inFrame wire.SNACFrame, r io.Reader, rw ResponseWriter) {
  81. assert.Equal(t, wire.SNACFrame{
  82. FoodGroup: wire.OService,
  83. SubGroup: wire.OServiceClientOnline,
  84. }, inFrame)
  85. }).Return(nil)
  86. rt := ChatNavServer{
  87. AuthService: authService,
  88. Handler: router,
  89. Logger: slog.Default(),
  90. OnlineNotifier: onlineNotifier,
  91. }
  92. rwc := pipeRWC{
  93. PipeReader: clientReader,
  94. PipeWriter: clientWriter,
  95. }
  96. assert.NoError(t, rt.handleNewConnection(context.Background(), rwc))
  97. }