1
2
3
4 package websocket
5
6 import (
7 "bufio"
8 "bytes"
9 "encoding/binary"
10 "math/bits"
11 "math/rand"
12 "strconv"
13 "testing"
14 "time"
15
16 "nhooyr.io/websocket/internal/test/assert"
17 )
18
19 func TestHeader(t *testing.T) {
20 t.Parallel()
21
22 t.Run("lengths", func(t *testing.T) {
23 t.Parallel()
24
25 lengths := []int{
26 124,
27 125,
28 126,
29 127,
30
31 65534,
32 65535,
33 65536,
34 65537,
35 }
36
37 for _, n := range lengths {
38 n := n
39 t.Run(strconv.Itoa(n), func(t *testing.T) {
40 t.Parallel()
41
42 testHeader(t, header{
43 payloadLength: int64(n),
44 })
45 })
46 }
47 })
48
49 t.Run("fuzz", func(t *testing.T) {
50 t.Parallel()
51
52 r := rand.New(rand.NewSource(time.Now().UnixNano()))
53 randBool := func() bool {
54 return r.Intn(2) == 0
55 }
56
57 for i := 0; i < 10000; i++ {
58 h := header{
59 fin: randBool(),
60 rsv1: randBool(),
61 rsv2: randBool(),
62 rsv3: randBool(),
63 opcode: opcode(r.Intn(16)),
64
65 masked: randBool(),
66 payloadLength: r.Int63(),
67 }
68 if h.masked {
69 h.maskKey = r.Uint32()
70 }
71
72 testHeader(t, h)
73 }
74 })
75 }
76
77 func testHeader(t *testing.T, h header) {
78 b := &bytes.Buffer{}
79 w := bufio.NewWriter(b)
80 r := bufio.NewReader(b)
81
82 err := writeFrameHeader(h, w, make([]byte, 8))
83 assert.Success(t, err)
84
85 err = w.Flush()
86 assert.Success(t, err)
87
88 h2, err := readFrameHeader(r, make([]byte, 8))
89 assert.Success(t, err)
90
91 assert.Equal(t, "read header", h, h2)
92 }
93
94 func Test_mask(t *testing.T) {
95 t.Parallel()
96
97 key := []byte{0xa, 0xb, 0xc, 0xff}
98 key32 := binary.LittleEndian.Uint32(key)
99 p := []byte{0xa, 0xb, 0xc, 0xf2, 0xc}
100 gotKey32 := mask(key32, p)
101
102 expP := []byte{0, 0, 0, 0x0d, 0x6}
103 assert.Equal(t, "p", expP, p)
104
105 expKey32 := bits.RotateLeft32(key32, -8)
106 assert.Equal(t, "key32", expKey32, gotKey32)
107 }
108
View as plain text