mirror of
https://github.com/aler9/gortsplib
synced 2025-10-25 00:00:30 +08:00
base: improve negative tests
This commit is contained in:
@@ -36,6 +36,7 @@ type Header map[string]HeaderValue
|
|||||||
|
|
||||||
func (h *Header) read(rb *bufio.Reader) error {
|
func (h *Header) read(rb *bufio.Reader) error {
|
||||||
*h = make(Header)
|
*h = make(Header)
|
||||||
|
count := 0
|
||||||
|
|
||||||
for {
|
for {
|
||||||
byt, err := rb.ReadByte()
|
byt, err := rb.ReadByte()
|
||||||
@@ -52,15 +53,14 @@ func (h *Header) read(rb *bufio.Reader) error {
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(*h) >= headerMaxEntryCount {
|
if count >= headerMaxEntryCount {
|
||||||
return fmt.Errorf("headers count exceeds %d (it's %d)",
|
return fmt.Errorf("headers count exceeds %d", headerMaxEntryCount)
|
||||||
headerMaxEntryCount, len(*h))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
key := string([]byte{byt})
|
key := string([]byte{byt})
|
||||||
byts, err := readBytesLimited(rb, ':', headerMaxKeyLength-1)
|
byts, err := readBytesLimited(rb, ':', headerMaxKeyLength-1)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return fmt.Errorf("value is missing")
|
||||||
}
|
}
|
||||||
key += string(byts[:len(byts)-1])
|
key += string(byts[:len(byts)-1])
|
||||||
key = headerKeyNormalize(key)
|
key = headerKeyNormalize(key)
|
||||||
@@ -85,16 +85,13 @@ func (h *Header) read(rb *bufio.Reader) error {
|
|||||||
}
|
}
|
||||||
val := string(byts[:len(byts)-1])
|
val := string(byts[:len(byts)-1])
|
||||||
|
|
||||||
if len(val) == 0 {
|
|
||||||
return fmt.Errorf("empty header value")
|
|
||||||
}
|
|
||||||
|
|
||||||
err = readByteEqual(rb, '\n')
|
err = readByteEqual(rb, '\n')
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
(*h)[key] = append((*h)[key], val)
|
(*h)[key] = append((*h)[key], val)
|
||||||
|
count++
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
|||||||
@@ -42,6 +42,16 @@ var casesHeader = []struct {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"empty",
|
||||||
|
[]byte("Testing:\r\n" +
|
||||||
|
"\r\n"),
|
||||||
|
[]byte("Testing: \r\n" +
|
||||||
|
"\r\n"),
|
||||||
|
Header{
|
||||||
|
"Testing": HeaderValue{""},
|
||||||
|
},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"without space",
|
"without space",
|
||||||
[]byte("CSeq:2\r\n" +
|
[]byte("CSeq:2\r\n" +
|
||||||
@@ -116,3 +126,50 @@ func TestHeaderWrite(t *testing.T) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestHeaderReadErrors(t *testing.T) {
|
||||||
|
for _, ca := range []struct {
|
||||||
|
name string
|
||||||
|
dec []byte
|
||||||
|
err string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
"empty",
|
||||||
|
[]byte{},
|
||||||
|
"EOF",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"r without n",
|
||||||
|
[]byte("Testing: val\rTesting: val\r\n"),
|
||||||
|
"expected '\n', got 'T'",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"final r without n",
|
||||||
|
[]byte("Testing: val\r\nTesting: val\r\n\r"),
|
||||||
|
"EOF",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"missing value",
|
||||||
|
[]byte("Testing\r\n"),
|
||||||
|
"value is missing",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"too many entries",
|
||||||
|
func() []byte {
|
||||||
|
var ret []byte
|
||||||
|
for i := 0; i < headerMaxEntryCount+2; i++ {
|
||||||
|
ret = append(ret, []byte("Testing: val\r\n")...)
|
||||||
|
}
|
||||||
|
ret = append(ret, []byte("\r\n")...)
|
||||||
|
return ret
|
||||||
|
}(),
|
||||||
|
"headers count exceeds 255",
|
||||||
|
},
|
||||||
|
} {
|
||||||
|
t.Run(ca.name, func(t *testing.T) {
|
||||||
|
h := make(Header)
|
||||||
|
err := h.read(bufio.NewReader(bytes.NewBuffer(ca.dec)))
|
||||||
|
require.Equal(t, ca.err, err.Error())
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -71,7 +71,7 @@ func (req *Request) Read(rb *bufio.Reader) error {
|
|||||||
|
|
||||||
ur, err := ParseURL(rawURL)
|
ur, err := ParseURL(rawURL)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("unable to parse url (%v)", rawURL)
|
return fmt.Errorf("invalid URL (%v)", rawURL)
|
||||||
}
|
}
|
||||||
req.URL = ur
|
req.URL = ur
|
||||||
|
|
||||||
|
|||||||
@@ -160,48 +160,73 @@ func TestRequestReadErrors(t *testing.T) {
|
|||||||
for _, ca := range []struct {
|
for _, ca := range []struct {
|
||||||
name string
|
name string
|
||||||
byts []byte
|
byts []byte
|
||||||
|
err string
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
"empty",
|
"empty",
|
||||||
[]byte{},
|
[]byte{},
|
||||||
|
"EOF",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"missing url, protocol, eol",
|
"missing url, protocol, eol",
|
||||||
[]byte("GET"),
|
[]byte("GET"),
|
||||||
|
"EOF",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"missing protocol, eol",
|
"missing protocol, eol",
|
||||||
[]byte("GET rtsp://testing123/test"),
|
[]byte("GET rtsp://testing123/test"),
|
||||||
|
"EOF",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"missing eol",
|
"missing eol",
|
||||||
[]byte("GET rtsp://testing123/test RTSP/1.0"),
|
[]byte("GET rtsp://testing123/test RTSP/1.0"),
|
||||||
|
"EOF",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"empty method",
|
"empty method",
|
||||||
[]byte(" rtsp://testing123 RTSP/1.0\r\n"),
|
[]byte(" rtsp://testing123 RTSP/1.0\r\n"),
|
||||||
|
"empty method",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"empty URL",
|
"empty URL",
|
||||||
[]byte("GET RTSP/1.0\r\n"),
|
[]byte("GET RTSP/1.0\r\n"),
|
||||||
|
"invalid URL ()",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"empty protocol",
|
"empty protocol",
|
||||||
[]byte("GET http://testing123 \r\n"),
|
[]byte("GET rtsp://testing123 \r\n"),
|
||||||
|
"expected 'RTSP/1.0', got ''",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"invalid URL",
|
"invalid URL",
|
||||||
[]byte("GET http://testing123 RTSP/1.0\r\n"),
|
[]byte("GET http://testing123 RTSP/1.0\r\n"),
|
||||||
|
"invalid URL (http://testing123)",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"invalid protocol",
|
"invalid protocol",
|
||||||
[]byte("GET rtsp://testing123 RTSP/2.0\r\n"),
|
[]byte("GET rtsp://testing123 RTSP/2.0\r\n"),
|
||||||
|
"expected 'RTSP/1.0', got 'RTSP/2.0'",
|
||||||
},
|
},
|
||||||
} {
|
} {
|
||||||
t.Run(ca.name, func(t *testing.T) {
|
t.Run(ca.name, func(t *testing.T) {
|
||||||
var req Request
|
var req Request
|
||||||
err := req.Read(bufio.NewReader(bytes.NewBuffer(ca.byts)))
|
err := req.Read(bufio.NewReader(bytes.NewBuffer(ca.byts)))
|
||||||
require.Error(t, err)
|
require.Equal(t, ca.err, err.Error())
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestRequestReadIgnoreFrames(t *testing.T) {
|
||||||
|
byts := []byte{0x24, 0x6, 0x0, 0x4, 0x1, 0x2, 0x3, 0x4}
|
||||||
|
byts = append(byts, []byte("OPTIONS rtsp://example.com/media.mp4 RTSP/1.0\r\n"+
|
||||||
|
"CSeq: 1\r\n"+
|
||||||
|
"Proxy-Require: gzipped-messages\r\n"+
|
||||||
|
"Require: implicit-play\r\n"+
|
||||||
|
"\r\n")...)
|
||||||
|
|
||||||
|
rb := bufio.NewReader(bytes.NewBuffer(byts))
|
||||||
|
buf := make([]byte, 10)
|
||||||
|
var req Request
|
||||||
|
err := req.ReadIgnoreFrames(rb, buf)
|
||||||
|
require.NoError(t, err)
|
||||||
|
}
|
||||||
|
|||||||
@@ -164,7 +164,7 @@ func (res *Response) Read(rb *bufio.Reader) error {
|
|||||||
res.StatusMessage = string(byts[:len(byts)-1])
|
res.StatusMessage = string(byts[:len(byts)-1])
|
||||||
|
|
||||||
if len(res.StatusMessage) == 0 {
|
if len(res.StatusMessage) == 0 {
|
||||||
return fmt.Errorf("empty status")
|
return fmt.Errorf("empty status message")
|
||||||
}
|
}
|
||||||
|
|
||||||
err = readByteEqual(rb, '\n')
|
err = readByteEqual(rb, '\n')
|
||||||
|
|||||||
@@ -122,44 +122,58 @@ func TestResponseReadErrors(t *testing.T) {
|
|||||||
for _, ca := range []struct {
|
for _, ca := range []struct {
|
||||||
name string
|
name string
|
||||||
byts []byte
|
byts []byte
|
||||||
|
err string
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
"empty",
|
"empty",
|
||||||
[]byte{},
|
[]byte{},
|
||||||
|
"EOF",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"missing code, message, eol",
|
"missing code, message, eol",
|
||||||
[]byte("RTSP/1.0"),
|
[]byte("RTSP/1.0"),
|
||||||
|
"EOF",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"missing message, eol",
|
"missing message, eol",
|
||||||
[]byte("RTSP/1.0 200"),
|
[]byte("RTSP/1.0 200"),
|
||||||
|
"EOF",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"missing eol",
|
"missing eol",
|
||||||
[]byte("RTSP/1.0 200 OK"),
|
[]byte("RTSP/1.0 200 OK"),
|
||||||
|
"EOF",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"missing eol 2",
|
"missing eol 2",
|
||||||
[]byte("RTSP/1.0 200 OK\r"),
|
[]byte("RTSP/1.0 200 OK\r"),
|
||||||
|
"EOF",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"invalid protocol",
|
"invalid protocol",
|
||||||
[]byte("RTSP/2.0 200 OK\r\n"),
|
[]byte("RTSP/2.0 200 OK\r\n"),
|
||||||
|
"expected 'RTSP/1.0', got 'RTSP/2.0'",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code too long",
|
||||||
|
[]byte("RTSP/1.0 1234 OK\r\n"),
|
||||||
|
"buffer length exceeds 4",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"invalid code",
|
"invalid code",
|
||||||
[]byte("RTSP/2.0 string OK\r\n"),
|
[]byte("RTSP/1.0 str OK\r\n"),
|
||||||
|
"unable to parse status code",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"empty message",
|
"empty message",
|
||||||
[]byte("RTSP/2.0 string \r\n"),
|
[]byte("RTSP/1.0 200 \r\n"),
|
||||||
|
"empty status message",
|
||||||
},
|
},
|
||||||
} {
|
} {
|
||||||
t.Run(ca.name, func(t *testing.T) {
|
t.Run(ca.name, func(t *testing.T) {
|
||||||
var res Response
|
var res Response
|
||||||
err := res.Read(bufio.NewReader(bytes.NewBuffer(ca.byts)))
|
err := res.Read(bufio.NewReader(bytes.NewBuffer(ca.byts)))
|
||||||
require.Error(t, err)
|
require.Equal(t, ca.err, err.Error())
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -193,7 +207,7 @@ func TestResponseWriteAutoFillStatus(t *testing.T) {
|
|||||||
require.Equal(t, byts, buf.Bytes())
|
require.Equal(t, byts, buf.Bytes())
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestReadIgnoreFrames(t *testing.T) {
|
func TestResponseReadIgnoreFrames(t *testing.T) {
|
||||||
byts := []byte{0x24, 0x6, 0x0, 0x4, 0x1, 0x2, 0x3, 0x4}
|
byts := []byte{0x24, 0x6, 0x0, 0x4, 0x1, 0x2, 0x3, 0x4}
|
||||||
byts = append(byts, []byte("RTSP/1.0 200 OK\r\n"+
|
byts = append(byts, []byte("RTSP/1.0 200 OK\r\n"+
|
||||||
"CSeq: 1\r\n"+
|
"CSeq: 1\r\n"+
|
||||||
|
|||||||
Reference in New Issue
Block a user