You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

ircconn_test.go 2.5KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  1. // Copyright (c) 2020 Shivaram Lingamneni <slingamn@cs.stanford.edu>
  2. // released under the MIT license
  3. package irc
  4. import (
  5. "io"
  6. "math/rand"
  7. "net"
  8. "reflect"
  9. "testing"
  10. "time"
  11. "github.com/oragono/oragono/irc/utils"
  12. )
  13. // mockConn is a fake net.Conn / io.Reader that yields len(counts) lines,
  14. // each consisting of counts[i] 'a' characters and a terminating '\n'
  15. type mockConn struct {
  16. counts []int
  17. }
  18. func min(i, j int) (m int) {
  19. if i < j {
  20. return i
  21. } else {
  22. return j
  23. }
  24. }
  25. func (c *mockConn) Read(b []byte) (n int, err error) {
  26. for len(b) > 0 {
  27. if len(c.counts) == 0 {
  28. return n, io.EOF
  29. }
  30. if c.counts[0] == 0 {
  31. b[0] = '\n'
  32. c.counts = c.counts[1:]
  33. b = b[1:]
  34. n += 1
  35. continue
  36. }
  37. size := min(c.counts[0], len(b))
  38. for i := 0; i < size; i++ {
  39. b[i] = 'a'
  40. }
  41. c.counts[0] -= size
  42. b = b[size:]
  43. n += size
  44. }
  45. return n, nil
  46. }
  47. func (c *mockConn) Write(b []byte) (n int, err error) {
  48. return
  49. }
  50. func (c *mockConn) Close() error {
  51. c.counts = nil
  52. return nil
  53. }
  54. func (c *mockConn) LocalAddr() net.Addr {
  55. return nil
  56. }
  57. func (c *mockConn) RemoteAddr() net.Addr {
  58. return nil
  59. }
  60. func (c *mockConn) SetDeadline(t time.Time) error {
  61. return nil
  62. }
  63. func (c *mockConn) SetReadDeadline(t time.Time) error {
  64. return nil
  65. }
  66. func (c *mockConn) SetWriteDeadline(t time.Time) error {
  67. return nil
  68. }
  69. func newMockConn(counts []int) *utils.WrappedConn {
  70. cpCounts := make([]int, len(counts))
  71. copy(cpCounts, counts)
  72. c := &mockConn{
  73. counts: cpCounts,
  74. }
  75. return &utils.WrappedConn{
  76. Conn: c,
  77. }
  78. }
  79. // construct a mock reader with some number of \n-terminated lines,
  80. // verify that IRCStreamConn can read and split them as expected
  81. func doLineReaderTest(counts []int, t *testing.T) {
  82. c := newMockConn(counts)
  83. r := NewIRCStreamConn(c)
  84. var readCounts []int
  85. for {
  86. line, err := r.ReadLine()
  87. if err == nil {
  88. readCounts = append(readCounts, len(line))
  89. } else if err == io.EOF {
  90. break
  91. } else {
  92. panic(err)
  93. }
  94. }
  95. if !reflect.DeepEqual(counts, readCounts) {
  96. t.Errorf("expected %#v, got %#v", counts, readCounts)
  97. }
  98. }
  99. const (
  100. maxMockReaderLen = 100
  101. maxMockReaderLineLen = 4096 + 511
  102. )
  103. func TestLineReader(t *testing.T) {
  104. counts := []int{44, 428, 3, 0, 200, 2000, 0, 4044, 33, 3, 2, 1, 0, 1, 2, 3, 48, 555}
  105. doLineReaderTest(counts, t)
  106. // fuzz
  107. r := rand.New(rand.NewSource(time.Now().UnixNano()))
  108. for i := 0; i < 1000; i++ {
  109. countsLen := r.Intn(maxMockReaderLen) + 1
  110. counts := make([]int, countsLen)
  111. for i := 0; i < countsLen; i++ {
  112. counts[i] = r.Intn(maxMockReaderLineLen)
  113. }
  114. doLineReaderTest(counts, t)
  115. }
  116. }