Highly-opinionated (ex-bullshit-free) MTPROTO proxy for Telegram. If you use v1.0 or upgrade broke you proxy, please read the chapter Version 2
Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.

conn_test.go 3.2KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163
  1. package doppel
  2. import (
  3. "bytes"
  4. "context"
  5. "encoding/binary"
  6. "errors"
  7. "io"
  8. "sync"
  9. "testing"
  10. "time"
  11. "github.com/9seconds/mtg/v2/internal/testlib"
  12. "github.com/9seconds/mtg/v2/mtglib/internal/tls"
  13. "github.com/stretchr/testify/mock"
  14. "github.com/stretchr/testify/suite"
  15. )
  16. type ConnMock struct {
  17. testlib.EssentialsConnMock
  18. mu sync.Mutex
  19. writeBuffer bytes.Buffer
  20. }
  21. func (m *ConnMock) Write(p []byte) (int, error) {
  22. args := m.Called(p)
  23. if err := args.Error(1); err != nil {
  24. return args.Int(0), err
  25. }
  26. m.mu.Lock()
  27. defer m.mu.Unlock()
  28. return m.writeBuffer.Write(p)
  29. }
  30. func (m *ConnMock) Written() []byte {
  31. m.mu.Lock()
  32. defer m.mu.Unlock()
  33. return bytes.Clone(m.writeBuffer.Bytes())
  34. }
  35. type ConnTestSuite struct {
  36. suite.Suite
  37. connMock *ConnMock
  38. ctx context.Context
  39. ctxCancel context.CancelFunc
  40. }
  41. func (suite *ConnTestSuite) SetupTest() {
  42. ctx, cancel := context.WithCancel(context.Background())
  43. suite.ctx = ctx
  44. suite.ctxCancel = cancel
  45. suite.connMock = &ConnMock{}
  46. }
  47. func (suite *ConnTestSuite) TearDownTest() {
  48. suite.ctxCancel()
  49. suite.connMock.AssertExpectations(suite.T())
  50. }
  51. func (suite *ConnTestSuite) makeConn() Conn {
  52. return NewConn(suite.ctx, suite.connMock, &Stats{
  53. k: 2.0,
  54. lambda: 0.01,
  55. })
  56. }
  57. func (suite *ConnTestSuite) TestWriteBuffersData() {
  58. suite.connMock.
  59. On("Write", mock.AnythingOfType("[]uint8")).
  60. Return(0, nil).
  61. Maybe()
  62. c := suite.makeConn()
  63. defer c.Stop()
  64. n, err := c.Write([]byte{1, 2, 3})
  65. suite.NoError(err)
  66. suite.Equal(3, n)
  67. }
  68. func (suite *ConnTestSuite) TestWriteOutputsTLSRecords() {
  69. suite.connMock.
  70. On("Write", mock.AnythingOfType("[]uint8")).
  71. Return(0, nil).
  72. Maybe()
  73. c := suite.makeConn()
  74. payload := []byte("hello doppelganger")
  75. _, err := c.Write(payload)
  76. suite.NoError(err)
  77. suite.Eventually(func() bool {
  78. return len(suite.connMock.Written()) > 0
  79. }, 2*time.Second, time.Millisecond)
  80. c.Stop()
  81. assembled := &bytes.Buffer{}
  82. reader := bytes.NewReader(suite.connMock.Written())
  83. for {
  84. header := make([]byte, tls.SizeHeader)
  85. if _, err := io.ReadFull(reader, header); err != nil {
  86. break
  87. }
  88. suite.Equal(byte(tls.TypeApplicationData), header[0])
  89. suite.Equal(tls.TLSVersion[:], header[tls.SizeRecordType:tls.SizeRecordType+tls.SizeVersion])
  90. length := binary.BigEndian.Uint16(header[tls.SizeRecordType+tls.SizeVersion:])
  91. suite.Greater(length, uint16(0))
  92. rec := make([]byte, length)
  93. _, err := io.ReadFull(reader, rec)
  94. suite.NoError(err)
  95. assembled.Write(rec)
  96. }
  97. suite.Equal(payload, assembled.Bytes())
  98. }
  99. func (suite *ConnTestSuite) TestWriteReturnsErrorAfterStop() {
  100. suite.connMock.
  101. On("Write", mock.AnythingOfType("[]uint8")).
  102. Return(0, nil).
  103. Maybe()
  104. c := suite.makeConn()
  105. c.Stop()
  106. time.Sleep(10 * time.Millisecond)
  107. _, err := c.Write([]byte{1})
  108. suite.Error(err)
  109. }
  110. func (suite *ConnTestSuite) TestStopOnUnderlyingWriteError() {
  111. suite.connMock.
  112. On("Write", mock.AnythingOfType("[]uint8")).
  113. Return(0, errors.New("connection reset")).
  114. Maybe()
  115. c := suite.makeConn()
  116. _, _ = c.Write([]byte("data"))
  117. suite.Eventually(func() bool {
  118. _, err := c.Write([]byte{1})
  119. return err != nil
  120. }, 2*time.Second, time.Millisecond)
  121. }
  122. func TestConn(t *testing.T) {
  123. t.Parallel()
  124. suite.Run(t, &ConnTestSuite{})
  125. }