2014-12-02 17:57:48 +03:00
|
|
|
package h2spec
|
|
|
|
|
|
|
|
import (
|
2015-02-15 17:32:50 +03:00
|
|
|
"errors"
|
2015-01-18 17:16:19 +03:00
|
|
|
"fmt"
|
2014-12-02 17:57:48 +03:00
|
|
|
"github.com/bradfitz/http2"
|
|
|
|
"io"
|
2015-02-19 16:48:03 +03:00
|
|
|
"net"
|
|
|
|
"syscall"
|
2014-12-02 17:57:48 +03:00
|
|
|
)
|
|
|
|
|
2015-02-15 17:32:50 +03:00
|
|
|
func ErrorHandlingTestGroup() *TestGroup {
|
|
|
|
tg := NewTestGroup("5.4", "Error Handling")
|
2015-01-20 17:49:47 +03:00
|
|
|
|
2015-02-15 17:32:50 +03:00
|
|
|
tg.AddTestGroup(ConnectionErrorHandlingTestGroup())
|
|
|
|
|
|
|
|
return tg
|
2014-12-02 17:57:48 +03:00
|
|
|
}
|
|
|
|
|
2015-02-15 17:32:50 +03:00
|
|
|
func ConnectionErrorHandlingTestGroup() *TestGroup {
|
|
|
|
tg := NewTestGroup("5.4.1", "Connection Error Handling")
|
2014-12-02 17:57:48 +03:00
|
|
|
|
2015-02-15 17:32:50 +03:00
|
|
|
tg.AddTestCase(NewTestCase(
|
|
|
|
"Receives a GOAWAY frame",
|
|
|
|
"After sending the GOAWAY frame, the endpoint MUST close the TCP connection.",
|
|
|
|
func(ctx *Context) (expected []Result, actual Result) {
|
|
|
|
expected = []Result{
|
|
|
|
&ResultConnectionClose{},
|
|
|
|
}
|
|
|
|
goaway := false
|
|
|
|
closed := false
|
2014-12-02 17:57:48 +03:00
|
|
|
|
2015-02-15 17:32:50 +03:00
|
|
|
http2Conn := CreateHttp2Conn(ctx, true)
|
|
|
|
defer http2Conn.conn.Close()
|
2014-12-02 17:57:48 +03:00
|
|
|
|
2015-02-15 17:32:50 +03:00
|
|
|
// PING frame with invalid stream ID
|
|
|
|
fmt.Fprintf(http2Conn.conn, "\x00\x00\x08\x06\x00\x00\x00\x00\x03")
|
|
|
|
fmt.Fprintf(http2Conn.conn, "\x00\x00\x00\x00\x00\x00\x00\x00")
|
2015-01-18 17:16:19 +03:00
|
|
|
|
2015-02-15 17:32:50 +03:00
|
|
|
loop:
|
|
|
|
for {
|
|
|
|
f, err := http2Conn.ReadFrame(ctx.Timeout)
|
|
|
|
if err != nil {
|
2015-02-19 16:48:03 +03:00
|
|
|
opErr, ok := err.(*net.OpError)
|
|
|
|
if err == io.EOF || (ok && opErr.Err == syscall.ECONNRESET) {
|
2015-02-15 17:32:50 +03:00
|
|
|
closed = true
|
|
|
|
} else if err == TIMEOUT {
|
|
|
|
if actual == nil {
|
|
|
|
actual = &ResultTestTimeout{}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
actual = &ResultError{err}
|
|
|
|
}
|
|
|
|
break loop
|
|
|
|
}
|
|
|
|
switch f := f.(type) {
|
|
|
|
case *http2.GoAwayFrame:
|
|
|
|
if f.ErrCode == http2.ErrCodeProtocol {
|
|
|
|
goaway = true
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
actual = &ResultFrame{f.Header().Type, FlagDefault, ErrCodeDefault}
|
2014-12-02 17:57:48 +03:00
|
|
|
}
|
2015-01-18 19:26:26 +03:00
|
|
|
}
|
2015-02-15 17:32:50 +03:00
|
|
|
|
|
|
|
if goaway && closed && actual == nil {
|
|
|
|
actual = &ResultConnectionClose{}
|
|
|
|
} else {
|
|
|
|
actual = &ResultError{
|
|
|
|
errors.New("Connection closed, but did not receive a GOAWAY Frame."),
|
2015-01-18 19:26:26 +03:00
|
|
|
}
|
2014-12-02 17:57:48 +03:00
|
|
|
}
|
|
|
|
|
2015-02-15 17:32:50 +03:00
|
|
|
return expected, actual
|
|
|
|
},
|
|
|
|
))
|
|
|
|
|
|
|
|
return tg
|
2014-12-02 17:57:48 +03:00
|
|
|
}
|