From 368a304c940e5379935aa828f3f30d17d7a29fbb Mon Sep 17 00:00:00 2001
From: Carl Mastrangelo <notcarl@google.com>
Date: Tue, 1 Dec 2015 16:19:23 -0800
Subject: [PATCH] Add http2 test for small http max frame size

---
 tools/http2_interop/http2interop.go |  1 +
 tools/http2_interop/s6.5.go         | 33 +++++++++++++++++++++++++++++
 tools/http2_interop/s6.5_test.go    | 14 ++++++++++++
 tools/http2_interop/settings.go     | 17 +++++++--------
 4 files changed, 56 insertions(+), 9 deletions(-)
 create mode 100644 tools/http2_interop/s6.5.go
 create mode 100644 tools/http2_interop/s6.5_test.go

diff --git a/tools/http2_interop/http2interop.go b/tools/http2_interop/http2interop.go
index abd7d4cf7d..1276a71afc 100644
--- a/tools/http2_interop/http2interop.go
+++ b/tools/http2_interop/http2interop.go
@@ -330,6 +330,7 @@ func http2Connect(c net.Conn, sf *SettingsFrame) error {
 	if _, err := c.Write([]byte(Preface)); err != nil {
 		return err
 	}
+
 	if sf == nil {
 		sf = &SettingsFrame{}
 	}
diff --git a/tools/http2_interop/s6.5.go b/tools/http2_interop/s6.5.go
new file mode 100644
index 0000000000..8145b6e031
--- /dev/null
+++ b/tools/http2_interop/s6.5.go
@@ -0,0 +1,33 @@
+package http2interop
+
+import (
+	"time"
+)
+
+// Section 6.5 says the minimum SETTINGS_MAX_FRAME_SIZE is 16,384
+func testSmallMaxFrameSize(ctx *HTTP2InteropCtx) error {
+	conn, err := connect(ctx)
+	if err != nil {
+		return err
+	}
+	defer conn.Close()
+	conn.Log = ctx.T.Log
+	conn.SetDeadline(time.Now().Add(defaultTimeout))
+
+	sf := &SettingsFrame{
+		Params: []SettingsParameter{{
+			Identifier: SettingsMaxFrameSize,
+			Value:      1<<14 - 1, // 1 less than the smallest maximum
+		}},
+	}
+
+	if err := http2Connect(conn, sf); err != nil {
+		return err
+	}
+
+	if _, err := expectGoAwaySoon(conn); err != nil {
+		return err
+	}
+
+	return nil
+}
diff --git a/tools/http2_interop/s6.5_test.go b/tools/http2_interop/s6.5_test.go
new file mode 100644
index 0000000000..48e8ced576
--- /dev/null
+++ b/tools/http2_interop/s6.5_test.go
@@ -0,0 +1,14 @@
+package http2interop
+
+import (
+	"testing"
+)
+
+func TestSmallMaxFrameSize(t *testing.T) {
+	if *testCase != "experimental" {
+		t.SkipNow()
+	}
+	ctx := InteropCtx(t)
+	err := testSmallMaxFrameSize(ctx)
+	matchError(t, err, "Got goaway frame")
+}
diff --git a/tools/http2_interop/settings.go b/tools/http2_interop/settings.go
index 5a2b1ada65..97914d960f 100644
--- a/tools/http2_interop/settings.go
+++ b/tools/http2_interop/settings.go
@@ -29,19 +29,19 @@ const (
 func (si SettingsIdentifier) String() string {
 	switch si {
 	case SettingsHeaderTableSize:
-		return "HEADER_TABLE_SIZE"
+		return "SETTINGS_HEADER_TABLE_SIZE"
 	case SettingsEnablePush:
-		return "ENABLE_PUSH"
+		return "SETTINGS_ENABLE_PUSH"
 	case SettingsMaxConcurrentStreams:
-		return "MAX_CONCURRENT_STREAMS"
+		return "SETTINGS_MAX_CONCURRENT_STREAMS"
 	case SettingsInitialWindowSize:
-		return "INITIAL_WINDOW_SIZE"
+		return "SETTINGS_INITIAL_WINDOW_SIZE"
 	case SettingsMaxFrameSize:
-		return "MAX_FRAME_SIZE"
+		return "SETTINGS_MAX_FRAME_SIZE"
 	case SettingsMaxHeaderListSize:
-		return "MAX_HEADER_LIST_SIZE"
+		return "SETTINGS_MAX_HEADER_LIST_SIZE"
 	default:
-		return fmt.Sprintf("UNKNOWN(%d)", uint16(si))
+		return fmt.Sprintf("SETTINGS_UNKNOWN(%d)", uint16(si))
 	}
 }
 
@@ -82,7 +82,7 @@ func (f *SettingsFrame) UnmarshalPayload(raw []byte) error {
 }
 
 func (f *SettingsFrame) MarshalPayload() ([]byte, error) {
-	raw := make([]byte, 0, len(f.Params)*6)
+	raw := make([]byte, len(f.Params)*6)
 	for i, p := range f.Params {
 		binary.BigEndian.PutUint16(raw[i*6:i*6+2], uint16(p.Identifier))
 		binary.BigEndian.PutUint32(raw[i*6+2:i*6+6], p.Value)
@@ -102,7 +102,6 @@ func (f *SettingsFrame) MarshalBinary() ([]byte, error) {
 	if err != nil {
 		return nil, err
 	}
-
 	header = append(header, payload...)
 
 	return header, nil
-- 
GitLab