Example #1
0
func StreamIdentifiersTestGroup(ctx *Context) *TestGroup {
	tg := NewTestGroup("5.1.1", "Stream Identifiers")

	tg.AddTestCase(NewTestCase(
		"Sends even-numbered stream identifier",
		"The endpoint MUST respond with a connection error of type PROTOCOL_ERROR.",
		func(ctx *Context) (expected []Result, actual Result) {
			http2Conn := CreateHttp2Conn(ctx, true)
			defer http2Conn.conn.Close()

			hdrs := commonHeaderFields(ctx)

			var hp http2.HeadersFrameParam
			hp.StreamID = 2
			hp.EndStream = true
			hp.EndHeaders = true
			hp.BlockFragment = http2Conn.EncodeHeader(hdrs)
			http2Conn.fr.WriteHeaders(hp)

			actualCodes := []http2.ErrCode{http2.ErrCodeProtocol}
			return TestConnectionError(ctx, http2Conn, actualCodes)
		},
	))

	if ctx.Strict {
		tg.AddTestCase(NewTestCase(
			"Sends stream identifier that is numerically smaller than previous",
			"The endpoint MUST respond with a connection error of type PROTOCOL_ERROR.",
			func(ctx *Context) (expected []Result, actual Result) {
				http2Conn := CreateHttp2Conn(ctx, true)
				defer http2Conn.conn.Close()

				hdrs := commonHeaderFields(ctx)

				var hp1 http2.HeadersFrameParam
				hp1.StreamID = 5
				hp1.EndStream = true
				hp1.EndHeaders = true
				hp1.BlockFragment = http2Conn.EncodeHeader(hdrs)
				http2Conn.fr.WriteHeaders(hp1)

				var hp2 http2.HeadersFrameParam
				hp2.StreamID = 3
				hp2.EndStream = true
				hp2.EndHeaders = true
				hp2.BlockFragment = http2Conn.EncodeHeader(hdrs)
				http2Conn.fr.WriteHeaders(hp2)

				actualCodes := []http2.ErrCode{http2.ErrCodeProtocol}
				return TestConnectionError(ctx, http2Conn, actualCodes)
			},
		))
	}

	return tg
}
Example #2
0
func PriorityTestGroup(ctx *Context) *TestGroup {
	tg := NewTestGroup("6.3", "PRIORITY")

	tg.AddTestCase(NewTestCase(
		"Sends a PRIORITY frame with 0x0 stream identifier",
		"The endpoint MUST respond with a connection error of type PROTOCOL_ERROR.",
		func(ctx *Context) (pass bool, expected []Result, actual Result) {
			http2Conn := CreateHttp2Conn(ctx, true)
			defer http2Conn.conn.Close()

			hdrs := commonHeaderFields(ctx)

			var hp http2.HeadersFrameParam
			hp.StreamID = 1
			hp.EndStream = false
			hp.EndHeaders = true
			hp.BlockFragment = http2Conn.EncodeHeader(hdrs)
			http2Conn.fr.WriteHeaders(hp)

			// PRIORITY Frame
			fmt.Fprintf(http2Conn.conn, "\x00\x00\x05\x02\x00\x00\x00\x00\x00")
			fmt.Fprintf(http2Conn.conn, "\x80\x00\x00\x01\x0a")

			actualCodes := []http2.ErrCode{http2.ErrCodeProtocol}
			return TestConnectionError(ctx, http2Conn, actualCodes)
		},
	))

	tg.AddTestCase(NewTestCase(
		"Sends a PRIORITY frame with a length other than 5 octets",
		"The endpoint MUST respond with a stream error of type FRAME_SIZE_ERROR.",
		func(ctx *Context) (pass bool, expected []Result, actual Result) {
			http2Conn := CreateHttp2Conn(ctx, true)
			defer http2Conn.conn.Close()

			hdrs := commonHeaderFields(ctx)

			var hp http2.HeadersFrameParam
			hp.StreamID = 1
			hp.EndStream = false
			hp.EndHeaders = true
			hp.BlockFragment = http2Conn.EncodeHeader(hdrs)
			http2Conn.fr.WriteHeaders(hp)

			// PRIORITY Frame
			fmt.Fprintf(http2Conn.conn, "\x00\x00\x04\x02\x00\x00\x00\x00\x01")
			fmt.Fprintf(http2Conn.conn, "\x80\x00\x00\x01")

			actualCodes := []http2.ErrCode{http2.ErrCodeFrameSize}
			return TestStreamError(ctx, http2Conn, actualCodes)
		},
	))

	return tg
}
Example #3
0
func MalformedRequestsAndResponsesTestGroup(ctx *Context) *TestGroup {
	tg := NewTestGroup("8.1.2.6", "Malformed Requests and Responses")

	tg.AddTestCase(NewTestCase(
		"Sends a HEADERS frame that contains the \"content-length\" header field which does not equal the sum of the DATA frame payload lengths",
		"The endpoint MUST respond with a stream error of type PROTOCOL_ERROR.",
		func(ctx *Context) (pass bool, expected []Result, actual Result) {
			http2Conn := CreateHttp2Conn(ctx, true)
			defer http2Conn.conn.Close()

			hdrs := commonHeaderFields(ctx)
			hdrs = append(hdrs, pair("content-length", "1"))
			hdrs[0].Value = "POST"

			var hp http2.HeadersFrameParam
			hp.StreamID = 1
			hp.EndStream = false
			hp.EndHeaders = true
			hp.BlockFragment = http2Conn.EncodeHeader(hdrs)
			http2Conn.fr.WriteHeaders(hp)
			http2Conn.fr.WriteData(1, true, []byte("test"))

			actualCodes := []http2.ErrCode{http2.ErrCodeProtocol}
			return TestStreamError(ctx, http2Conn, actualCodes)
		},
	))

	tg.AddTestCase(NewTestCase(
		"Sends a HEADERS frame that contains the \"content-length\" header field which does not equal the sum of the multiple DATA frame payload lengths",
		"The endpoint MUST respond with a stream error of type PROTOCOL_ERROR.",
		func(ctx *Context) (pass bool, expected []Result, actual Result) {
			http2Conn := CreateHttp2Conn(ctx, true)
			defer http2Conn.conn.Close()

			hdrs := commonHeaderFields(ctx)
			hdrs = append(hdrs, pair("content-length", "1"))
			hdrs[0].Value = "POST"

			var hp http2.HeadersFrameParam
			hp.StreamID = 1
			hp.EndStream = false
			hp.EndHeaders = true
			hp.BlockFragment = http2Conn.EncodeHeader(hdrs)
			http2Conn.fr.WriteHeaders(hp)
			http2Conn.fr.WriteData(1, false, []byte("test"))
			http2Conn.fr.WriteData(1, true, []byte("test"))

			actualCodes := []http2.ErrCode{http2.ErrCodeProtocol}
			return TestStreamError(ctx, http2Conn, actualCodes)
		},
	))

	return tg
}
Example #4
0
func RequestPseudoHeaderFieldsTestGroup(ctx *Context) *TestGroup {
	tg := NewTestGroup("8.1.2.3", "Request Pseudo-Header Fields")

	tg.AddTestCase(NewTestCase(
		"Sends a HEADERS frame that omits mandatory pseudo-header fields",
		"The endpoint MUST respond with a stream error of type PROTOCOL_ERROR.",
		func(ctx *Context) (pass bool, expected []Result, actual Result) {
			http2Conn := CreateHttp2Conn(ctx, true)
			defer http2Conn.conn.Close()

			hdrs := commonHeaderFields(ctx)
			tmp := hdrs[0:2]
			hdrs = append(tmp, hdrs[3])

			var hp http2.HeadersFrameParam
			hp.StreamID = 1
			hp.EndStream = true
			hp.EndHeaders = true
			hp.BlockFragment = http2Conn.EncodeHeader(hdrs)
			http2Conn.fr.WriteHeaders(hp)

			actualCodes := []http2.ErrCode{http2.ErrCodeProtocol}
			return TestStreamError(ctx, http2Conn, actualCodes)
		},
	))

	tg.AddTestCase(NewTestCase(
		"Sends a HEADERS frame containing more than one pseudo-header fields with the same name",
		"The endpoint MUST respond with a stream error of type PROTOCOL_ERROR.",
		func(ctx *Context) (pass bool, expected []Result, actual Result) {
			http2Conn := CreateHttp2Conn(ctx, true)
			defer http2Conn.conn.Close()

			hdrs1 := commonHeaderFields(ctx)
			hdrs2 := commonHeaderFields(ctx)
			hdrs := append(hdrs1, hdrs2...)

			var hp http2.HeadersFrameParam
			hp.StreamID = 1
			hp.EndStream = true
			hp.EndHeaders = true
			hp.BlockFragment = http2Conn.EncodeHeader(hdrs)
			http2Conn.fr.WriteHeaders(hp)

			actualCodes := []http2.ErrCode{http2.ErrCodeProtocol}
			return TestStreamError(ctx, http2Conn, actualCodes)
		},
	))

	return tg
}
Example #5
0
func ConnectionSpecificHeaderFieldsTestGroup(ctx *Context) *TestGroup {
	tg := NewTestGroup("8.1.2.2", "Connection-Specific Header Fields")

	tg.AddTestCase(NewTestCase(
		"Sends a HEADERS frame that contains the connection-specific header field",
		"The endpoint MUST respond with a stream error of type PROTOCOL_ERROR.",
		func(ctx *Context) (pass bool, expected []Result, actual Result) {
			http2Conn := CreateHttp2Conn(ctx, true)
			defer http2Conn.conn.Close()

			hdrs := commonHeaderFields(ctx)
			hdrs = append(hdrs, pair("connection", "keep-alive"))

			var hp http2.HeadersFrameParam
			hp.StreamID = 1
			hp.EndStream = true
			hp.EndHeaders = true
			hp.BlockFragment = http2Conn.EncodeHeader(hdrs)
			http2Conn.fr.WriteHeaders(hp)

			actualCodes := []http2.ErrCode{http2.ErrCodeProtocol}
			return TestStreamError(ctx, http2Conn, actualCodes)
		},
	))

	tg.AddTestCase(NewTestCase(
		"Sends a HEADERS frame that contains the TE header field that contain any value other than \"trailers\"",
		"The endpoint MUST respond with a stream error of type PROTOCOL_ERROR.",
		func(ctx *Context) (pass bool, expected []Result, actual Result) {
			http2Conn := CreateHttp2Conn(ctx, true)
			defer http2Conn.conn.Close()

			hdrs := commonHeaderFields(ctx)
			hdrs = append(hdrs, pair("trailers", "test"))
			hdrs = append(hdrs, pair("te", "trailers, deflate"))

			var hp http2.HeadersFrameParam
			hp.StreamID = 1
			hp.EndStream = true
			hp.EndHeaders = true
			hp.BlockFragment = http2Conn.EncodeHeader(hdrs)
			http2Conn.fr.WriteHeaders(hp)

			actualCodes := []http2.ErrCode{http2.ErrCodeProtocol}
			return TestStreamError(ctx, http2Conn, actualCodes)
		},
	))

	return tg
}
Example #6
0
func HttpHeaderFieldsTestGroup(ctx *Context) *TestGroup {
	tg := NewTestGroup("8.1.2", "HTTP Header Fields")

	tg.AddTestCase(NewTestCase(
		"Sends a HEADERS frame that contains the header field name in uppercase letters",
		"The endpoint MUST respond with a stream error of type PROTOCOL_ERROR.",
		func(ctx *Context) (pass bool, expected []Result, actual Result) {
			http2Conn := CreateHttp2Conn(ctx, true)
			defer http2Conn.conn.Close()

			hdrs := commonHeaderFields(ctx)
			hdrs = append(hdrs, pair("X-TEST", "test"))

			var hp http2.HeadersFrameParam
			hp.StreamID = 1
			hp.EndStream = true
			hp.EndHeaders = true
			hp.BlockFragment = http2Conn.EncodeHeader(hdrs)
			http2Conn.fr.WriteHeaders(hp)

			actualCodes := []http2.ErrCode{http2.ErrCodeProtocol}
			return TestStreamError(ctx, http2Conn, actualCodes)
		},
	))

	tg.AddTestGroup(PseudoHeaderFieldsTestGroup(ctx))
	tg.AddTestGroup(ConnectionSpecificHeaderFieldsTestGroup(ctx))
	tg.AddTestGroup(RequestPseudoHeaderFieldsTestGroup(ctx))
	tg.AddTestGroup(MalformedRequestsAndResponsesTestGroup(ctx))

	return tg
}
Example #7
0
func FrameSizeTestGroup(ctx *Context) *TestGroup {
	tg := NewTestGroup("4.2", "Frame Size")

	tg.AddTestCase(NewTestCase(
		"Sends large size frame that exceeds the SETTINGS_MAX_FRAME_SIZE",
		"The endpoint MUST send a FRAME_SIZE_ERROR error.",
		func(ctx *Context) (pass bool, expected []Result, actual Result) {
			http2Conn := CreateHttp2Conn(ctx, true)
			defer http2Conn.conn.Close()

			hdrs := commonHeaderFields(ctx)

			var hp http2.HeadersFrameParam
			hp.StreamID = 1
			hp.EndStream = false
			hp.EndHeaders = true
			hp.BlockFragment = http2Conn.EncodeHeader(hdrs)
			http2Conn.fr.WriteHeaders(hp)
			max_size, ok := http2Conn.Settings[http2.SettingMaxFrameSize]
			if !ok {
				max_size = 18384
			}

			http2Conn.fr.WriteData(1, true, []byte(dummyData(int(max_size)+1)))

			actualCodes := []http2.ErrCode{http2.ErrCodeFrameSize}
			return TestStreamError(ctx, http2Conn, actualCodes)
		},
	))

	return tg
}
Example #8
0
func TestHTTPHeaderFields(ctx *Context) {
	PrintHeader("8.1.2. HTTP Header Fields", 1)

	func(ctx *Context) {
		desc := "Sends a HEADERS frame that contains the header field name in uppercase letters"
		msg := "the endpoint MUST respond with a stream error of type PROTOCOL_ERROR."
		result := false

		http2Conn := CreateHttp2Conn(ctx, true)
		defer http2Conn.conn.Close()

		var buf bytes.Buffer
		hdrs := []hpack.HeaderField{
			pair(":method", "GET"),
			pair(":scheme", "http"),
			pair(":path", "/"),
			pair(":authority", ctx.Authority()),
			pair("X-TEST", "test"),
		}
		enc := hpack.NewEncoder(&buf)
		for _, hf := range hdrs {
			_ = enc.WriteField(hf)
		}

		var hp http2.HeadersFrameParam
		hp.StreamID = 1
		hp.EndStream = true
		hp.EndHeaders = true
		hp.BlockFragment = buf.Bytes()
		http2Conn.fr.WriteHeaders(hp)

		timeCh := time.After(3 * time.Second)

	loop:
		for {
			select {
			case f := <-http2Conn.dataCh:
				rf, ok := f.(*http2.RSTStreamFrame)
				if ok {
					if rf.ErrCode == http2.ErrCodeProtocol {
						result = true
						break loop
					}
				}
			case <-http2Conn.errCh:
				break loop
			case <-timeCh:
				break loop
			}
		}

		PrintResult(result, desc, msg, 1)
	}(ctx)

	TestPseudoHeaderFields(ctx)
	TestConnectionSpecificHeaderFields(ctx)
	TestRequestPseudoHeaderFields(ctx)
	TestMalformedRequestsAndResponses(ctx)
}
Example #9
0
func RstStreamTestGroup(ctx *Context) *TestGroup {
	tg := NewTestGroup("6.4", "RST_STREAM")

	tg.AddTestCase(NewTestCase(
		"Sends a RST_STREAM frame with 0x0 stream identifier",
		"The endpoint MUST respond with a connection error of type PROTOCOL_ERROR.",
		func(ctx *Context) (expected []Result, actual Result) {
			http2Conn := CreateHttp2Conn(ctx, true)
			defer http2Conn.conn.Close()

			http2Conn.fr.WriteRSTStream(0, http2.ErrCodeCancel)

			actualCodes := []http2.ErrCode{http2.ErrCodeProtocol}
			return TestConnectionError(ctx, http2Conn, actualCodes)
		},
	))

	tg.AddTestCase(NewTestCase(
		"Sends a RST_STREAM frame on a idle stream",
		"The endpoint MUST respond with a connection error of type PROTOCOL_ERROR.",
		func(ctx *Context) (expected []Result, actual Result) {
			http2Conn := CreateHttp2Conn(ctx, true)
			defer http2Conn.conn.Close()

			http2Conn.fr.WriteRSTStream(1, http2.ErrCodeCancel)

			actualCodes := []http2.ErrCode{http2.ErrCodeProtocol}
			return TestConnectionError(ctx, http2Conn, actualCodes)
		},
	))

	tg.AddTestCase(NewTestCase(
		"Sends a RST_STREAM frame with a length other than 4 octets",
		"The endpoint MUST respond with a connection error of type FRAME_SIZE_ERROR.",
		func(ctx *Context) (expected []Result, actual Result) {
			http2Conn := CreateHttp2Conn(ctx, true)
			defer http2Conn.conn.Close()

			hdrs := commonHeaderFields(ctx)

			var hp http2.HeadersFrameParam
			hp.StreamID = 1
			hp.EndStream = false
			hp.EndHeaders = true
			hp.BlockFragment = http2Conn.EncodeHeader(hdrs)
			http2Conn.fr.WriteHeaders(hp)

			// RST_STREAM Frame
			fmt.Fprintf(http2Conn.conn, "\x00\x00\x03\x03\x00\x00\x00\x00\x01")
			fmt.Fprintf(http2Conn.conn, "\x00\x00\x00")

			actualCodes := []http2.ErrCode{http2.ErrCodeFrameSize}
			return TestConnectionError(ctx, http2Conn, actualCodes)
		},
	))

	return tg
}
Example #10
0
func TestPriority(ctx *Context) {
	PrintHeader("6.3. PRIORITY", 0)

	func(ctx *Context) {
		desc := "Sends a PRIORITY frame with 0x0 stream identifier"
		msg := "The endpoint MUST respond with a connection error of type PROTOCOL_ERROR."
		result := false

		http2Conn := CreateHttp2Conn(ctx, true)
		defer http2Conn.conn.Close()

		var buf bytes.Buffer
		hdrs := []hpack.HeaderField{
			pair(":method", "GET"),
			pair(":scheme", "http"),
			pair(":path", "/"),
			pair(":authority", ctx.Authority()),
		}
		enc := hpack.NewEncoder(&buf)
		for _, hf := range hdrs {
			_ = enc.WriteField(hf)
		}

		var hp http2.HeadersFrameParam
		hp.StreamID = 1
		hp.EndStream = false
		hp.EndHeaders = true
		hp.BlockFragment = buf.Bytes()
		http2Conn.fr.WriteHeaders(hp)

		fmt.Fprintf(http2Conn.conn, "\x00\x00\x05\x02\x00\x00\x00\x00\x00")
		http2Conn.conn.Write(buf.Bytes())
		fmt.Fprintf(http2Conn.conn, "\x80\x00\x00\x01\x0a")

		timeCh := time.After(3 * time.Second)

	loop:
		for {
			select {
			case f := <-http2Conn.dataCh:
				gf, ok := f.(*http2.GoAwayFrame)
				if ok {
					if gf.ErrCode == http2.ErrCodeProtocol {
						result = true
					}
				}
			case <-http2Conn.errCh:
				break loop
			case <-timeCh:
				break loop
			}
		}

		PrintResult(result, desc, msg, 0)
	}(ctx)

	PrintFooter()
}
Example #11
0
func TestMalformedRequestsAndResponses(ctx *Context) {
	PrintHeader("8.1.2.6. Malformed Requests and Responses", 2)

	// 8.1.2.6. ボディを構成する DATA フレームペイロードの長さの合計が "content-length" ヘッダーフィールドの値と等しくない場合、リクエストやレスポンスは不正な形式になります。

	func(ctx *Context) {
		desc := "Sends a HEADERS frame that contains invalid \"content-length\" header field"
		msg := "the endpoint MUST respond with a stream error of type PROTOCOL_ERROR."
		result := false

		http2Conn := CreateHttp2Conn(ctx, true)
		defer http2Conn.conn.Close()

		var buf bytes.Buffer
		hdrs := []hpack.HeaderField{
			pair(":method", "POST"),
			pair(":scheme", "http"),
			pair(":path", "/"),
			pair(":authority", ctx.Authority()),
			pair("content-length", "1"),
		}
		enc := hpack.NewEncoder(&buf)
		for _, hf := range hdrs {
			_ = enc.WriteField(hf)
		}

		var hp http2.HeadersFrameParam
		hp.StreamID = 1
		hp.EndStream = false
		hp.EndHeaders = true
		hp.BlockFragment = buf.Bytes()
		http2Conn.fr.WriteHeaders(hp)
		http2Conn.fr.WriteData(1, true, []byte("test"))

		timeCh := time.After(3 * time.Second)

	loop:
		for {
			select {
			case f := <-http2Conn.dataCh:
				rf, ok := f.(*http2.RSTStreamFrame)
				if ok {
					if rf.ErrCode == http2.ErrCodeProtocol {
						result = true
						break loop
					}
				}
			case <-http2Conn.errCh:
				break loop
			case <-timeCh:
				break loop
			}
		}

		PrintResult(result, desc, msg, 2)
	}(ctx)
}
Example #12
0
File: 5_3.go Project: zeb209/h2spec
func StreamDependenciesTestGroup(ctx *Context) *TestGroup {
	tg := NewTestGroup("5.3.1", "Stream Dependencies")

	tg.AddTestCase(NewTestCase(
		"Sends HEADERS frame that depend on itself",
		"The endpoint MUST treat this as a stream error of type PROTOCOL_ERROR",
		func(ctx *Context) (pass bool, expected []Result, actual Result) {
			http2Conn := CreateHttp2Conn(ctx, true)
			defer http2Conn.conn.Close()

			hdrs := commonHeaderFields(ctx)

			var pp http2.PriorityParam
			pp.StreamDep = 3
			pp.Exclusive = false
			pp.Weight = 255

			var hp http2.HeadersFrameParam
			hp.StreamID = 3
			hp.EndStream = true
			hp.EndHeaders = true
			hp.Priority = pp
			hp.BlockFragment = http2Conn.EncodeHeader(hdrs)
			http2Conn.fr.WriteHeaders(hp)

			actualCodes := []http2.ErrCode{http2.ErrCodeProtocol}
			return TestStreamError(ctx, http2Conn, actualCodes)
		},
	))

	tg.AddTestCase(NewTestCase(
		"Sends PRIORITY frame that depend on itself",
		"The endpoint MUST treat this as a stream error of type PROTOCOL_ERROR",
		func(ctx *Context) (pass bool, expected []Result, actual Result) {
			http2Conn := CreateHttp2Conn(ctx, true)
			defer http2Conn.conn.Close()

			var pp http2.PriorityParam
			pp.StreamDep = 2
			pp.Exclusive = false
			pp.Weight = 255

			http2Conn.fr.WritePriority(2, pp)

			actualCodes := []http2.ErrCode{http2.ErrCodeProtocol}
			return TestStreamError(ctx, http2Conn, actualCodes)
		},
	))

	return tg
}
Example #13
0
func StreamConcurrencyTestGroup(ctx *Context) *TestGroup {
	tg := NewTestGroup("5.1.2", "Stream Concurrency")

	tg.AddTestCase(NewTestCase(
		"Sends HEADERS frames that causes their advertised concurrent stream limit to be exceeded",
		"The endpoint MUST treat this as a stream error (Section 5.4.2) of type PROTOCOL_ERROR or REFUSED_STREAM",
		func(ctx *Context) (expected []Result, actual Result) {
			http2Conn := CreateHttp2Conn(ctx, true)
			defer http2Conn.conn.Close()

			// Skip this test when SETTINGS_MAX_CONCURRENT_STREAMS is unlimited.
			_, ok := http2Conn.Settings[http2.SettingMaxConcurrentStreams]
			if !ok {
				actual = &ResultSkipped{"SETTINGS_MAX_CONCURRENT_STREAMS is unlimited."}
				return nil, actual
			}

			// Set INITIAL_WINDOW_SIZE to zero to prevent the peer from closing the stream
			settings := http2.Setting{http2.SettingInitialWindowSize, 0}
			http2Conn.fr.WriteSettings(settings)

			hdrs := commonHeaderFields(ctx)
			hbf := http2Conn.EncodeHeader(hdrs)

			var streamID uint32 = 1
			for i := 0; i <= int(http2Conn.Settings[http2.SettingMaxConcurrentStreams]); i++ {
				var hp http2.HeadersFrameParam
				hp.StreamID = streamID
				hp.EndStream = true
				hp.EndHeaders = true
				hp.BlockFragment = hbf
				http2Conn.fr.WriteHeaders(hp)
				streamID += 2
			}

			actualCodes := []http2.ErrCode{
				http2.ErrCodeProtocol,
				http2.ErrCodeRefusedStream,
			}
			return TestStreamError(ctx, http2Conn, actualCodes)
		},
	))

	return tg
}
Example #14
0
func StreamStatesTestGroup(ctx *Context) *TestGroup {
	tg := NewTestGroup("5.1", "Stream States")

	tg.AddTestCase(NewTestCase(
		"idle: Sends a DATA frame",
		"The endpoint MUST treat this as a connection error (Section 5.4.1) of type PROTOCOL_ERROR.",
		func(ctx *Context) (expected []Result, actual Result) {
			http2Conn := CreateHttp2Conn(ctx, true)
			defer http2Conn.conn.Close()

			http2Conn.fr.WriteData(1, true, []byte("test"))

			actualCodes := []http2.ErrCode{http2.ErrCodeProtocol}
			return TestConnectionError(ctx, http2Conn, actualCodes)
		},
	))

	tg.AddTestCase(NewTestCase(
		"idle: Sends a RST_STREAM frame",
		"The endpoint MUST treat this as a connection error (Section 5.4.1) of type PROTOCOL_ERROR.",
		func(ctx *Context) (expected []Result, actual Result) {
			http2Conn := CreateHttp2Conn(ctx, true)
			defer http2Conn.conn.Close()

			http2Conn.fr.WriteRSTStream(1, http2.ErrCodeCancel)

			actualCodes := []http2.ErrCode{http2.ErrCodeProtocol}
			return TestConnectionError(ctx, http2Conn, actualCodes)
		},
	))

	tg.AddTestCase(NewTestCase(
		"idle: Sends a WINDOW_UPDATE frame",
		"The endpoint MUST treat this as a connection error (Section 5.4.1) of type PROTOCOL_ERROR.",
		func(ctx *Context) (expected []Result, actual Result) {
			http2Conn := CreateHttp2Conn(ctx, true)
			defer http2Conn.conn.Close()

			http2Conn.fr.WriteWindowUpdate(1, 100)

			actualCodes := []http2.ErrCode{http2.ErrCodeProtocol}
			return TestConnectionError(ctx, http2Conn, actualCodes)
		},
	))

	tg.AddTestCase(NewTestCase(
		"idle: Sends a CONTINUATION frame",
		"The endpoint MUST treat this as a connection error (Section 5.4.1) of type PROTOCOL_ERROR.",
		func(ctx *Context) (expected []Result, actual Result) {
			http2Conn := CreateHttp2Conn(ctx, true)
			defer http2Conn.conn.Close()

			hdrs := commonHeaderFields(ctx)
			blockFragment := http2Conn.EncodeHeader(hdrs)

			http2Conn.fr.WriteContinuation(1, true, blockFragment)

			actualCodes := []http2.ErrCode{http2.ErrCodeProtocol}
			return TestConnectionError(ctx, http2Conn, actualCodes)
		},
	))

	tg.AddTestCase(NewTestCase(
		"half closed (remote): Sends a DATA frame",
		"The endpoint MUST respond with a stream error (Section 5.4.2) of type STREAM_CLOSED.",
		func(ctx *Context) (expected []Result, actual Result) {
			http2Conn := CreateHttp2Conn(ctx, true)
			defer http2Conn.conn.Close()

			hdrs := commonHeaderFields(ctx)
			blockFragment := http2Conn.EncodeHeader(hdrs)

			var hp http2.HeadersFrameParam
			hp.StreamID = 1
			hp.EndStream = true
			hp.EndHeaders = true
			hp.BlockFragment = blockFragment
			http2Conn.fr.WriteHeaders(hp)

			http2Conn.fr.WriteData(1, true, []byte("test"))

			actualCodes := []http2.ErrCode{http2.ErrCodeStreamClosed}
			return TestStreamError(ctx, http2Conn, actualCodes)
		},
	))

	tg.AddTestCase(NewTestCase(
		"half closed (remote): Sends a HEADERS frame",
		"The endpoint MUST respond with a stream error (Section 5.4.2) of type STREAM_CLOSED.",
		func(ctx *Context) (expected []Result, actual Result) {
			http2Conn := CreateHttp2Conn(ctx, true)
			defer http2Conn.conn.Close()

			hdrs := commonHeaderFields(ctx)
			blockFragment := http2Conn.EncodeHeader(hdrs)

			var hp1 http2.HeadersFrameParam
			hp1.StreamID = 1
			hp1.EndStream = true
			hp1.EndHeaders = true
			hp1.BlockFragment = blockFragment
			http2Conn.fr.WriteHeaders(hp1)

			var hp2 http2.HeadersFrameParam
			hp2.StreamID = 1
			hp2.EndStream = true
			hp2.EndHeaders = true
			hp2.BlockFragment = blockFragment
			http2Conn.fr.WriteHeaders(hp2)

			actualCodes := []http2.ErrCode{http2.ErrCodeStreamClosed}
			return TestStreamError(ctx, http2Conn, actualCodes)
		},
	))

	tg.AddTestCase(NewTestCase(
		"half closed (remote): Sends a CONTINUATION frame",
		"The endpoint MUST respond with a stream error (Section 5.4.2) of type STREAM_CLOSED.",
		func(ctx *Context) (expected []Result, actual Result) {
			http2Conn := CreateHttp2Conn(ctx, true)
			defer http2Conn.conn.Close()

			hdrs := commonHeaderFields(ctx)
			hdrs = append(hdrs, pair("x-dummy1", dummyData(10000)))
			hdrs = append(hdrs, pair("x-dummy2", dummyData(10000)))
			blockFragment := http2Conn.EncodeHeader(hdrs)

			var hp http2.HeadersFrameParam
			hp.StreamID = 1
			hp.EndStream = true
			hp.EndHeaders = true
			hp.BlockFragment = blockFragment[0:16384]
			http2Conn.fr.WriteHeaders(hp)

			http2Conn.fr.WriteContinuation(1, true, blockFragment[16384:])

			actualCodes := []http2.ErrCode{http2.ErrCodeStreamClosed}
			return TestStreamError(ctx, http2Conn, actualCodes)
		},
	))

	if ctx.Strict {
		tg.AddTestCase(NewTestCase(
			"closed: Sends a DATA frame",
			"The endpoint MUST treat this as a stream error (Section 5.4.2) of type STREAM_CLOSED.",
			func(ctx *Context) (expected []Result, actual Result) {
				http2Conn := CreateHttp2Conn(ctx, true)
				defer http2Conn.conn.Close()

				hdrs := commonHeaderFields(ctx)
				blockFragment := http2Conn.EncodeHeader(hdrs)

				var hp http2.HeadersFrameParam
				hp.StreamID = 1
				hp.EndStream = true
				hp.EndHeaders = true
				hp.BlockFragment = blockFragment
				http2Conn.fr.WriteHeaders(hp)

				expected, actual = TestStreamClose(ctx, http2Conn)
				if !EvaluateResult(expected, actual) {
					return expected, actual
				}

				http2Conn.fr.WriteData(1, true, []byte("test"))

				actualCodes := []http2.ErrCode{http2.ErrCodeStreamClosed}
				return TestStreamError(ctx, http2Conn, actualCodes)
			},
		))
	}

	if ctx.Strict {
		tg.AddTestCase(NewTestCase(
			"closed: Sends a HEADERS frame",
			"The endpoint MUST treat this as a stream error (Section 5.4.2) of type STREAM_CLOSED.",
			func(ctx *Context) (expected []Result, actual Result) {
				http2Conn := CreateHttp2Conn(ctx, true)
				defer http2Conn.conn.Close()

				hdrs := commonHeaderFields(ctx)
				blockFragment := http2Conn.EncodeHeader(hdrs)

				var hp http2.HeadersFrameParam
				hp.StreamID = 1
				hp.EndStream = true
				hp.EndHeaders = true
				hp.BlockFragment = blockFragment
				http2Conn.fr.WriteHeaders(hp)

				expected, actual = TestStreamClose(ctx, http2Conn)
				if !EvaluateResult(expected, actual) {
					return expected, actual
				}

				http2Conn.fr.WriteHeaders(hp)

				actualCodes := []http2.ErrCode{http2.ErrCodeStreamClosed}
				return TestStreamError(ctx, http2Conn, actualCodes)
			},
		))
	}

	tg.AddTestCase(NewTestCase(
		"closed: Sends a CONTINUATION frame",
		"The endpoint MUST treat this as a stream error (Section 5.4.2) of type STREAM_CLOSED.",
		func(ctx *Context) (expected []Result, actual Result) {
			http2Conn := CreateHttp2Conn(ctx, true)
			defer http2Conn.conn.Close()

			hdrs := commonHeaderFields(ctx)
			hdrs = append(hdrs, pair("x-dummy1", dummyData(10000)))
			hdrs = append(hdrs, pair("x-dummy2", dummyData(10000)))
			blockFragment := http2Conn.EncodeHeader(hdrs)

			var hp http2.HeadersFrameParam
			hp.StreamID = 1
			hp.EndStream = true
			hp.EndHeaders = false
			hp.BlockFragment = blockFragment[0:16384]
			http2Conn.fr.WriteHeaders(hp)

			http2Conn.fr.WriteContinuation(1, true, blockFragment[16384:])

			expected, actual = TestStreamClose(ctx, http2Conn)
			if !EvaluateResult(expected, actual) {
				return expected, actual
			}

			http2Conn.fr.WriteContinuation(1, true, blockFragment[16384:])

			actualCodes := []http2.ErrCode{http2.ErrCodeStreamClosed}
			return TestStreamError(ctx, http2Conn, actualCodes)
		},
	))

	tg.AddTestGroup(StreamIdentifiersTestGroup(ctx))
	tg.AddTestGroup(StreamConcurrencyTestGroup(ctx))

	return tg
}
Example #15
0
func ExtendingHttp2TestGroup(ctx *Context) *TestGroup {
	tg := NewTestGroup("5.5", "Extending HTTP/2")

	tg.AddTestCase(NewTestCase(
		"Sends an unknown extension frame",
		"The endpoint MUST discard frames that have unknown or unsupported types",
		func(ctx *Context) (pass bool, expected []Result, actual Result) {
			pass = false
			expected = []Result{
				&ResultFrame{LengthDefault, http2.FramePing, http2.FlagPingAck, ErrCodeDefault},
			}

			http2Conn := CreateHttp2Conn(ctx, true)
			defer http2Conn.conn.Close()

			// Write a frame of type 0xFF, which isn't yet defined
			// as an extension frame. This should be ignored; no GOAWAY,
			// RST_STREAM or closing the connection should occur
			http2Conn.fr.WriteRawFrame(0xFF, 0x00, 0, []byte("unknown"))

			// Now send a normal PING frame, and if this is processed
			// without error, then the preceeding unknown frame must have
			// been processed and ignored.
			data := [8]byte{'h', '2', 's', 'p', 'e', 'c'}
			http2Conn.fr.WritePing(false, data)

		loop:
			for {
				f, err := http2Conn.ReadFrame(ctx.Timeout)
				if err != nil {
					opErr, ok := err.(*net.OpError)
					if err == io.EOF || (ok && opErr.Err == syscall.ECONNRESET) {
						rf, ok := actual.(*ResultFrame)
						if actual == nil || (ok && rf.Type != http2.FrameGoAway) {
							actual = &ResultConnectionClose{}
						}
					} else if err == TIMEOUT {
						if actual == nil {
							actual = &ResultTestTimeout{}
						}
					} else {
						actual = &ResultError{err}
					}
					break loop
				}

				switch f := f.(type) {
				case *http2.PingFrame:
					actual = CreateResultFrame(f)
					if f.FrameHeader.Flags.Has(http2.FlagPingAck) {
						pass = true
						break loop
					}
				default:
					actual = CreateResultFrame(f)
				}
			}

			return pass, expected, actual
		},
	))

	tg.AddTestCase(NewTestCase(
		"Sends an unknown extension frame in the middle of a header block",
		"The endpoint MUST treat as a connection error of type PROTOCOL_ERROR.",
		func(ctx *Context) (pass bool, expected []Result, actual Result) {
			http2Conn := CreateHttp2Conn(ctx, true)
			defer http2Conn.conn.Close()

			hdrs := commonHeaderFields(ctx)
			hdrs = append(hdrs, pair("x-dummy1", dummyData(10000)))
			hdrs = append(hdrs, pair("x-dummy2", dummyData(10000)))
			blockFragment := http2Conn.EncodeHeader(hdrs)

			var hp http2.HeadersFrameParam
			hp.StreamID = 1
			hp.EndStream = true
			hp.EndHeaders = false
			hp.BlockFragment = blockFragment[0:16384]
			http2Conn.fr.WriteHeaders(hp)

			http2Conn.fr.WriteRawFrame(0xFF, 0x01, 0, []byte("unknown"))

			actualCodes := []http2.ErrCode{http2.ErrCodeProtocol}
			return TestConnectionError(ctx, http2Conn, actualCodes)
		},
	))

	return tg
}
Example #16
0
func TestHeaders(ctx *Context) {
	PrintHeader("6.2. HEADERS", 0)

	func(ctx *Context) {
		desc := "Sends a HEADERS frame followed by any frame other than CONTINUATION"
		msg := "The endpoint MUST treat the receipt of any other type of frame as a connection error of type PROTOCOL_ERROR."
		result := false

		http2Conn := CreateHttp2Conn(ctx, true)
		defer http2Conn.conn.Close()

		var buf bytes.Buffer
		hdrs := []hpack.HeaderField{
			pair(":method", "GET"),
			pair(":scheme", "http"),
			pair(":path", "/"),
			pair(":authority", ctx.Authority()),
		}
		enc := hpack.NewEncoder(&buf)
		for _, hf := range hdrs {
			_ = enc.WriteField(hf)
		}

		var hp http2.HeadersFrameParam
		hp.StreamID = 1
		hp.EndStream = false
		hp.EndHeaders = false
		hp.BlockFragment = buf.Bytes()
		http2Conn.fr.WriteHeaders(hp)
		http2Conn.fr.WriteData(1, true, []byte("test"))

		timeCh := time.After(3 * time.Second)

	loop:
		for {
			select {
			case f := <-http2Conn.dataCh:
				gf, ok := f.(*http2.GoAwayFrame)
				if ok {
					if gf.ErrCode == http2.ErrCodeProtocol {
						result = true
					}
				}
			case <-http2Conn.errCh:
				break loop
			case <-timeCh:
				break loop
			}
		}

		PrintResult(result, desc, msg, 0)
	}(ctx)

	func(ctx *Context) {
		desc := "Sends a HEADERS frame followed by a frame on a different stream"
		msg := "The endpoint MUST treat the receipt of a frame on a different stream as a connection error of type PROTOCOL_ERROR."
		result := false

		http2Conn := CreateHttp2Conn(ctx, true)
		defer http2Conn.conn.Close()

		var buf bytes.Buffer
		hdrs := []hpack.HeaderField{
			pair(":method", "GET"),
			pair(":scheme", "http"),
			pair(":path", "/"),
			pair(":authority", ctx.Authority()),
		}
		enc := hpack.NewEncoder(&buf)
		for _, hf := range hdrs {
			_ = enc.WriteField(hf)
		}

		var hp1 http2.HeadersFrameParam
		hp1.StreamID = 1
		hp1.EndStream = false
		hp1.EndHeaders = false
		hp1.BlockFragment = buf.Bytes()
		http2Conn.fr.WriteHeaders(hp1)

		var hp2 http2.HeadersFrameParam
		hp2.StreamID = 3
		hp2.EndStream = true
		hp2.EndHeaders = true
		hp2.BlockFragment = buf.Bytes()
		http2Conn.fr.WriteHeaders(hp2)

		timeCh := time.After(3 * time.Second)

	loop:
		for {
			select {
			case f := <-http2Conn.dataCh:
				gf, ok := f.(*http2.GoAwayFrame)
				if ok {
					if gf.ErrCode == http2.ErrCodeProtocol {
						result = true
					}
				}
			case <-http2Conn.errCh:
				break loop
			case <-timeCh:
				break loop
			}
		}

		PrintResult(result, desc, msg, 0)
	}(ctx)

	func(ctx *Context) {
		desc := "Sends a HEADERS frame with 0x0 stream identifier"
		msg := "The endpoint MUST respond with a connection error of type PROTOCOL_ERROR."
		result := false

		http2Conn := CreateHttp2Conn(ctx, true)
		defer http2Conn.conn.Close()

		var buf bytes.Buffer
		hdrs := []hpack.HeaderField{
			pair(":method", "GET"),
			pair(":scheme", "http"),
			pair(":path", "/"),
			pair(":authority", ctx.Authority()),
		}
		enc := hpack.NewEncoder(&buf)
		for _, hf := range hdrs {
			_ = enc.WriteField(hf)
		}

		var hp http2.HeadersFrameParam
		hp.StreamID = 0
		hp.EndStream = true
		hp.EndHeaders = true
		hp.BlockFragment = buf.Bytes()
		http2Conn.fr.WriteHeaders(hp)

		timeCh := time.After(3 * time.Second)

	loop:
		for {
			select {
			case f := <-http2Conn.dataCh:
				gf, ok := f.(*http2.GoAwayFrame)
				if ok {
					if gf.ErrCode == http2.ErrCodeProtocol {
						result = true
					}
				}
			case <-http2Conn.errCh:
				break loop
			case <-timeCh:
				break loop
			}
		}

		PrintResult(result, desc, msg, 0)
	}(ctx)

	func(ctx *Context) {
		desc := "Sends a HEADERS frame with invalid pad length"
		msg := "The endpoint MUST treat this as a connection error of type PROTOCOL_ERROR."
		result := false

		http2Conn := CreateHttp2Conn(ctx, true)
		defer http2Conn.conn.Close()

		var buf bytes.Buffer
		hdrs := []hpack.HeaderField{
			pair(":method", "GET"),
			pair(":scheme", "http"),
			pair(":path", "/"),
			pair(":authority", ctx.Authority()),
		}
		enc := hpack.NewEncoder(&buf)
		for _, hf := range hdrs {
			_ = enc.WriteField(hf)
		}

		fmt.Fprintf(http2Conn.conn, "\x00\x00\x0f\x01\x0c\x00\x00\x00\x01")
		http2Conn.conn.Write(buf.Bytes())
		fmt.Fprintf(http2Conn.conn, "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00")

		timeCh := time.After(3 * time.Second)

	loop:
		for {
			select {
			case f := <-http2Conn.dataCh:
				gf, ok := f.(*http2.GoAwayFrame)
				if ok {
					if gf.ErrCode == http2.ErrCodeProtocol {
						result = true
					}
				}
			case <-http2Conn.errCh:
				break loop
			case <-timeCh:
				break loop
			}
		}

		PrintResult(result, desc, msg, 0)
	}(ctx)

	PrintFooter()
}
Example #17
0
func TestPseudoHeaderFields(ctx *Context) {
	PrintHeader("8.1.2.1. Pseudo-Header Fields", 2)

	func(ctx *Context) {
		desc := "Sends a HEADERS frame that contains the pseudo-header field defined for response"
		msg := "the endpoint MUST respond with a stream error of type PROTOCOL_ERROR."
		result := false

		http2Conn := CreateHttp2Conn(ctx, true)
		defer http2Conn.conn.Close()

		var buf bytes.Buffer
		hdrs := []hpack.HeaderField{
			pair(":method", "GET"),
			pair(":scheme", "http"),
			pair(":path", "/"),
			pair(":authority", ctx.Authority()),
			pair(":status", "200"),
		}
		enc := hpack.NewEncoder(&buf)
		for _, hf := range hdrs {
			_ = enc.WriteField(hf)
		}

		var hp http2.HeadersFrameParam
		hp.StreamID = 1
		hp.EndStream = true
		hp.EndHeaders = true
		hp.BlockFragment = buf.Bytes()
		http2Conn.fr.WriteHeaders(hp)

		timeCh := time.After(3 * time.Second)

	loop:
		for {
			select {
			case f := <-http2Conn.dataCh:
				rf, ok := f.(*http2.RSTStreamFrame)
				if ok {
					if rf.ErrCode == http2.ErrCodeProtocol {
						result = true
						break loop
					}
				}
			case <-http2Conn.errCh:
				break loop
			case <-timeCh:
				break loop
			}
		}

		PrintResult(result, desc, msg, 2)
	}(ctx)

	func(ctx *Context) {
		desc := "Sends a HEADERS frame that contains the invalid pseudo-header field"
		msg := "the endpoint MUST respond with a stream error of type PROTOCOL_ERROR."
		result := false

		http2Conn := CreateHttp2Conn(ctx, true)
		defer http2Conn.conn.Close()

		var buf bytes.Buffer
		hdrs := []hpack.HeaderField{
			pair(":method", "GET"),
			pair(":scheme", "http"),
			pair(":path", "/"),
			pair(":authority", ctx.Authority()),
			pair(":test", "test"),
		}
		enc := hpack.NewEncoder(&buf)
		for _, hf := range hdrs {
			_ = enc.WriteField(hf)
		}

		var hp http2.HeadersFrameParam
		hp.StreamID = 1
		hp.EndStream = true
		hp.EndHeaders = true
		hp.BlockFragment = buf.Bytes()
		http2Conn.fr.WriteHeaders(hp)

		timeCh := time.After(3 * time.Second)

	loop:
		for {
			select {
			case f := <-http2Conn.dataCh:
				rf, ok := f.(*http2.RSTStreamFrame)
				if ok {
					if rf.ErrCode == http2.ErrCodeProtocol {
						result = true
						break loop
					}
				}
			case <-http2Conn.errCh:
				break loop
			case <-timeCh:
				break loop
			}
		}

		PrintResult(result, desc, msg, 2)
	}(ctx)

	func(ctx *Context) {
		desc := "Sends a HEADERS frame that contains a pseudo-header field that appears in a header block after a regular header field"
		msg := "the endpoint MUST respond with a stream error of type PROTOCOL_ERROR."
		result := false

		http2Conn := CreateHttp2Conn(ctx, true)
		defer http2Conn.conn.Close()

		var buf bytes.Buffer
		hdrs := []hpack.HeaderField{
			pair("x-test", "test"),
			pair(":method", "GET"),
			pair(":scheme", "http"),
			pair(":path", "/"),
			pair(":authority", ctx.Authority()),
		}
		enc := hpack.NewEncoder(&buf)
		for _, hf := range hdrs {
			_ = enc.WriteField(hf)
		}

		var hp http2.HeadersFrameParam
		hp.StreamID = 1
		hp.EndStream = true
		hp.EndHeaders = true
		hp.BlockFragment = buf.Bytes()
		http2Conn.fr.WriteHeaders(hp)

		timeCh := time.After(3 * time.Second)

	loop:
		for {
			select {
			case f := <-http2Conn.dataCh:
				rf, ok := f.(*http2.RSTStreamFrame)
				if ok {
					if rf.ErrCode == http2.ErrCodeProtocol {
						result = true
						break loop
					}
				}
			case <-http2Conn.errCh:
				break loop
			case <-timeCh:
				break loop
			}
		}

		PrintResult(result, desc, msg, 2)
	}(ctx)
}
Example #18
0
func TestConnectionSpecificHeaderFields(ctx *Context) {
	PrintHeader("8.1.2.2. Connection-Specific Header Fields", 2)

	// 8.1.2.3. CONNECT リクエスト (8.3節) である場合を除き、":method"、":scheme"、そして ":path" 擬似ヘッダーフィールドに有効な値を1つ含まなければなりません (MUST)。これらの擬似ヘッダーフィールドが省略された HTTP リクエストは不正な形式 (8.1.2.6節) です。
	// 8.1.2.6. ボディを構成する DATA フレームペイロードの長さの合計が "content-length" ヘッダーフィールドの値と等しくない場合、リクエストやレスポンスは不正な形式になります。

	func(ctx *Context) {
		desc := "Sends a HEADERS frame that contains the connection-specific header field"
		msg := "the endpoint MUST respond with a stream error of type PROTOCOL_ERROR."
		result := false

		http2Conn := CreateHttp2Conn(ctx, true)
		defer http2Conn.conn.Close()

		var buf bytes.Buffer
		hdrs := []hpack.HeaderField{
			pair(":method", "GET"),
			pair(":scheme", "http"),
			pair(":path", "/"),
			pair(":authority", ctx.Authority()),
			pair("connection", "keep-alive"),
		}
		enc := hpack.NewEncoder(&buf)
		for _, hf := range hdrs {
			_ = enc.WriteField(hf)
		}

		var hp http2.HeadersFrameParam
		hp.StreamID = 1
		hp.EndStream = true
		hp.EndHeaders = true
		hp.BlockFragment = buf.Bytes()
		http2Conn.fr.WriteHeaders(hp)

		timeCh := time.After(3 * time.Second)

	loop:
		for {
			select {
			case f := <-http2Conn.dataCh:
				rf, ok := f.(*http2.RSTStreamFrame)
				if ok {
					if rf.ErrCode == http2.ErrCodeProtocol {
						result = true
						break loop
					}
				}
			case <-http2Conn.errCh:
				break loop
			case <-timeCh:
				break loop
			}
		}

		PrintResult(result, desc, msg, 2)
	}(ctx)

	func(ctx *Context) {
		desc := "Sends a HEADERS frame that contains the TE header field that contain any value other than \"trailers\""
		msg := "the endpoint MUST respond with a stream error of type PROTOCOL_ERROR."
		result := false

		http2Conn := CreateHttp2Conn(ctx, true)
		defer http2Conn.conn.Close()

		var buf bytes.Buffer
		hdrs := []hpack.HeaderField{
			pair(":method", "GET"),
			pair(":scheme", "http"),
			pair(":path", "/"),
			pair(":authority", ctx.Authority()),
			pair("trailers", "test"),
			pair("te", "trailers, deflate"),
		}
		enc := hpack.NewEncoder(&buf)
		for _, hf := range hdrs {
			_ = enc.WriteField(hf)
		}

		var hp http2.HeadersFrameParam
		hp.StreamID = 1
		hp.EndStream = true
		hp.EndHeaders = true
		hp.BlockFragment = buf.Bytes()
		http2Conn.fr.WriteHeaders(hp)

		timeCh := time.After(3 * time.Second)

	loop:
		for {
			select {
			case f := <-http2Conn.dataCh:
				rf, ok := f.(*http2.RSTStreamFrame)
				if ok {
					if rf.ErrCode == http2.ErrCodeProtocol {
						result = true
						break loop
					}
				}
			case <-http2Conn.errCh:
				break loop
			case <-timeCh:
				break loop
			}
		}

		PrintResult(result, desc, msg, 2)
	}(ctx)
}
Example #19
0
func WindowUpdateTestGroup(ctx *Context) *TestGroup {
	tg := NewTestGroup("6.9", "WINDOW_UPDATE")

	tg.AddTestCase(NewTestCase(
		"Sends a WINDOW_UPDATE frame",
		"The endpoint is expected to send the DATA frame based on the window size.",
		func(ctx *Context) (expected []Result, actual Result) {
			expected = []Result{
				&ResultFrame{http2.FrameData, FlagDefault, ErrCodeDefault},
			}

			http2Conn := CreateHttp2Conn(ctx, true)
			defer http2Conn.conn.Close()

			settings := http2.Setting{http2.SettingInitialWindowSize, 1}
			http2Conn.fr.WriteSettings(settings)

			hdrs := commonHeaderFields(ctx)

			var hp http2.HeadersFrameParam
			hp.StreamID = 1
			hp.EndStream = true
			hp.EndHeaders = true
			hp.BlockFragment = http2Conn.EncodeHeader(hdrs)
			http2Conn.fr.WriteHeaders(hp)

			winUpdated := false

		loop:
			for {
				f, err := http2Conn.ReadFrame(ctx.Timeout)
				if err != nil {
					opErr, ok := err.(*net.OpError)
					if err == io.EOF || (ok && opErr.Err == syscall.ECONNRESET) {
						actual = &ResultConnectionClose{}
					} else if err == TIMEOUT {
						if actual == nil {
							actual = &ResultTestTimeout{}
						}
					} else {
						actual = &ResultError{err}
					}
					break loop
				}

				switch f := f.(type) {
				case *http2.DataFrame:

					if winUpdated {
						if f.FrameHeader.Length > 10 {
							err := errors.New("The length of DATA frame is invalid.")
							actual = &ResultError{err}
							break loop
						}

						actual = &ResultFrame{f.Header().Type, FlagDefault, ErrCodeDefault}
						break loop
					} else {
						if f.FrameHeader.Length != 1 {
							err := errors.New("The length of DATA frame is invalid.")
							actual = &ResultError{err}
							break loop
						}

						http2Conn.fr.WriteWindowUpdate(1, 10)
						winUpdated = true
					}
				default:
					actual = &ResultFrame{f.Header().Type, FlagDefault, ErrCodeDefault}
				}
			}

			return expected, actual
		},
	))

	tg.AddTestCase(NewTestCase(
		"Sends a WINDOW_UPDATE frame with an flow control window increment of 0",
		"The endpoint MUST respond with a connection error of type PROTOCOL_ERROR.",
		func(ctx *Context) (expected []Result, actual Result) {
			http2Conn := CreateHttp2Conn(ctx, true)
			defer http2Conn.conn.Close()

			http2Conn.fr.WriteWindowUpdate(0, 0)

			actualCodes := []http2.ErrCode{http2.ErrCodeProtocol}
			return TestConnectionError(ctx, http2Conn, actualCodes)
		},
	))

	tg.AddTestCase(NewTestCase(
		"Sends a WINDOW_UPDATE frame with an flow control window increment of 0 on a stream",
		"The endpoint MUST respond with a stream error of type PROTOCOL_ERROR.",
		func(ctx *Context) (expected []Result, actual Result) {
			http2Conn := CreateHttp2Conn(ctx, true)
			defer http2Conn.conn.Close()

			hdrs := commonHeaderFields(ctx)

			var hp http2.HeadersFrameParam
			hp.StreamID = 1
			hp.EndStream = false
			hp.EndHeaders = true
			hp.BlockFragment = http2Conn.EncodeHeader(hdrs)
			http2Conn.fr.WriteHeaders(hp)
			http2Conn.fr.WriteWindowUpdate(1, 0)

			actualCodes := []http2.ErrCode{http2.ErrCodeProtocol}
			return TestStreamError(ctx, http2Conn, actualCodes)
		},
	))

	tg.AddTestCase(NewTestCase(
		"Sends a WINDOW_UPDATE frame with a length other than a multiple of 4 octets",
		"The endpoint MUST respond with a connection error of type FRAME_SIZE_ERROR.",
		func(ctx *Context) (expected []Result, actual Result) {
			http2Conn := CreateHttp2Conn(ctx, true)
			defer http2Conn.conn.Close()

			fmt.Fprintf(http2Conn.conn, "\x00\x00\x03\x08\x00\x00\x00\x00\x00")
			fmt.Fprintf(http2Conn.conn, "\x00\x00\x01")

			actualCodes := []http2.ErrCode{http2.ErrCodeFrameSize}
			return TestConnectionError(ctx, http2Conn, actualCodes)
		},
	))

	tg.AddTestGroup(TheFlowControlWindowTestGroup(ctx))
	tg.AddTestGroup(InitialFlowControlWindowSizeTestGroup(ctx))

	return tg
}
Example #20
0
func PseudoHeaderFieldsTestGroup(ctx *Context) *TestGroup {
	tg := NewTestGroup("8.1.2.1", "Pseudo-Header Fields")

	tg.AddTestCase(NewTestCase(
		"Sends a HEADERS frame that contains the pseudo-header field defined for response",
		"The endpoint MUST respond with a stream error of type PROTOCOL_ERROR.",
		func(ctx *Context) (pass bool, expected []Result, actual Result) {
			http2Conn := CreateHttp2Conn(ctx, true)
			defer http2Conn.conn.Close()

			hdrs := commonHeaderFields(ctx)
			hdrs = append(hdrs, pair(":status", "200"))

			var hp http2.HeadersFrameParam
			hp.StreamID = 1
			hp.EndStream = true
			hp.EndHeaders = true
			hp.BlockFragment = http2Conn.EncodeHeader(hdrs)
			http2Conn.fr.WriteHeaders(hp)

			actualCodes := []http2.ErrCode{http2.ErrCodeProtocol}
			return TestStreamError(ctx, http2Conn, actualCodes)
		},
	))

	tg.AddTestCase(NewTestCase(
		"Sends a HEADERS frame that contains the invalid pseudo-header field",
		"The endpoint MUST respond with a stream error of type PROTOCOL_ERROR.",
		func(ctx *Context) (pass bool, expected []Result, actual Result) {
			http2Conn := CreateHttp2Conn(ctx, true)
			defer http2Conn.conn.Close()

			hdrs := commonHeaderFields(ctx)
			hdrs = append(hdrs, pair(":test", "test"))

			var hp http2.HeadersFrameParam
			hp.StreamID = 1
			hp.EndStream = true
			hp.EndHeaders = true
			hp.BlockFragment = http2Conn.EncodeHeader(hdrs)
			http2Conn.fr.WriteHeaders(hp)

			actualCodes := []http2.ErrCode{http2.ErrCodeProtocol}
			return TestStreamError(ctx, http2Conn, actualCodes)
		},
	))

	tg.AddTestCase(NewTestCase(
		"Sends a HEADERS frame that contains a pseudo-header field that appears in a header block after a regular header field",
		"The endpoint MUST respond with a stream error of type PROTOCOL_ERROR.",
		func(ctx *Context) (pass bool, expected []Result, actual Result) {
			http2Conn := CreateHttp2Conn(ctx, true)
			defer http2Conn.conn.Close()

			hdrs := commonHeaderFields(ctx)
			tmp := []hpack.HeaderField{
				pair("x-test", "test"),
			}
			hdrs = append(tmp, hdrs...)

			var hp http2.HeadersFrameParam
			hp.StreamID = 1
			hp.EndStream = true
			hp.EndHeaders = true
			hp.BlockFragment = http2Conn.EncodeHeader(hdrs)
			http2Conn.fr.WriteHeaders(hp)

			actualCodes := []http2.ErrCode{http2.ErrCodeProtocol}
			return TestStreamError(ctx, http2Conn, actualCodes)
		},
	))

	return tg
}
Example #21
0
func TheFlowControlWindowTestGroup(ctx *Context) *TestGroup {
	tg := NewTestGroup("6.9.1", "The Flow Control Window")

	tg.AddTestCase(NewTestCase(
		"Sends multiple WINDOW_UPDATE frames on a connection increasing the flow control window to above 2^31-1",
		"The endpoint MUST sends a GOAWAY frame with a FLOW_CONTROL_ERROR code.",
		func(ctx *Context) (expected []Result, actual Result) {
			expected = []Result{
				&ResultFrame{http2.FrameGoAway, FlagDefault, http2.ErrCodeFlowControl},
			}

			http2Conn := CreateHttp2Conn(ctx, true)
			defer http2Conn.conn.Close()

			http2Conn.fr.WriteWindowUpdate(0, 2147483647)
			http2Conn.fr.WriteWindowUpdate(0, 2147483647)

		loop:
			for {
				f, err := http2Conn.ReadFrame(ctx.Timeout)
				if err != nil {
					opErr, ok := err.(*net.OpError)
					if err == io.EOF || (ok && opErr.Err == syscall.ECONNRESET) {
						actual = &ResultConnectionClose{}
					} else if err == TIMEOUT {
						if actual == nil {
							actual = &ResultTestTimeout{}
						}
					} else {
						actual = &ResultError{err}
					}
					break loop
				}

				switch f := f.(type) {
				case *http2.GoAwayFrame:
					actual = &ResultFrame{f.Header().Type, FlagDefault, f.ErrCode}
					if f.ErrCode == http2.ErrCodeFlowControl {
						break loop
					}
				default:
					actual = &ResultFrame{f.Header().Type, FlagDefault, ErrCodeDefault}
				}
			}

			return expected, actual
		},
	))

	tg.AddTestCase(NewTestCase(
		"Sends multiple WINDOW_UPDATE frames on a stream increasing the flow control window to above 2^31-1",
		"The endpoint MUST sends a RST_STREAM with the error code of FLOW_CONTROL_ERROR code.",
		func(ctx *Context) (expected []Result, actual Result) {
			expected = []Result{
				&ResultFrame{http2.FrameRSTStream, FlagDefault, http2.ErrCodeFlowControl},
			}

			http2Conn := CreateHttp2Conn(ctx, true)
			defer http2Conn.conn.Close()

			hdrs := commonHeaderFields(ctx)

			var hp http2.HeadersFrameParam
			hp.StreamID = 1
			hp.EndStream = false
			hp.EndHeaders = true
			hp.BlockFragment = http2Conn.EncodeHeader(hdrs)
			http2Conn.fr.WriteHeaders(hp)

			http2Conn.fr.WriteWindowUpdate(1, 2147483647)
			http2Conn.fr.WriteWindowUpdate(1, 2147483647)

		loop:
			for {
				f, err := http2Conn.ReadFrame(ctx.Timeout)
				if err != nil {
					opErr, ok := err.(*net.OpError)
					if err == io.EOF || (ok && opErr.Err == syscall.ECONNRESET) {
						actual = &ResultConnectionClose{}
					} else if err == TIMEOUT {
						if actual == nil {
							actual = &ResultTestTimeout{}
						}
					} else {
						actual = &ResultError{err}
					}
					break loop
				}

				switch f := f.(type) {
				case *http2.RSTStreamFrame:
					actual = &ResultFrame{f.Header().Type, FlagDefault, f.ErrCode}
					if f.ErrCode == http2.ErrCodeFlowControl {
						break loop
					}
				default:
					actual = &ResultFrame{f.Header().Type, FlagDefault, ErrCodeDefault}
				}
			}

			return expected, actual
		},
	))

	return tg
}
Example #22
0
func HttpRequestResponseExchangeTestGroup(ctx *Context) *TestGroup {
	tg := NewTestGroup("8.1", "HTTP Request/Response Exchange")

	tg.AddTestCase(NewTestCase(
		"Sends a HEADERS frame as HEAD request",
		"The endpoint should respond with no DATA frame or empty DATA frame.",
		func(ctx *Context) (pass bool, expected []Result, actual Result) {
			pass = false
			expected = []Result{
				&ResultFrame{LengthDefault, http2.FrameHeaders, http2.FlagHeadersEndStream, ErrCodeDefault},
				&ResultFrame{0, http2.FrameData, http2.FlagDataEndStream, ErrCodeDefault},
			}

			http2Conn := CreateHttp2Conn(ctx, true)
			defer http2Conn.conn.Close()

			hdrs := commonHeaderFields(ctx)
			hdrs[0].Value = "HEAD"

			var hp http2.HeadersFrameParam
			hp.StreamID = 1
			hp.EndStream = true
			hp.EndHeaders = true
			hp.BlockFragment = http2Conn.EncodeHeader(hdrs)
			http2Conn.fr.WriteHeaders(hp)

		loop:
			for {
				f, err := http2Conn.ReadFrame(ctx.Timeout)
				if err != nil {
					opErr, ok := err.(*net.OpError)
					if err == io.EOF || (ok && opErr.Err == syscall.ECONNRESET) {
						rf, ok := actual.(*ResultFrame)
						if actual == nil || (ok && rf.Type != http2.FrameGoAway) {
							actual = &ResultConnectionClose{}
						}
					} else if err == TIMEOUT {
						if actual == nil {
							actual = &ResultTestTimeout{}
						}
					} else {
						actual = &ResultError{err}
					}
					break loop
				}

				switch f := f.(type) {
				case *http2.DataFrame:
					actual = CreateResultFrame(f)
					if f.FrameHeader.Flags.Has(http2.FlagDataEndStream) && f.Header().Length == 0 {
						pass = true
						break loop
					}
				case *http2.HeadersFrame:
					actual = CreateResultFrame(f)
					if f.FrameHeader.Flags.Has(http2.FlagHeadersEndStream) {
						pass = true
						break loop
					}
				}
				actual = CreateResultFrame(f)
			}

			return pass, expected, actual
		},
	))

	tg.AddTestCase(NewTestCase(
		"Sends a HEADERS frame containing trailer part",
		"The endpoint should respond with HEADERS frame.",
		func(ctx *Context) (pass bool, expected []Result, actual Result) {
			pass = false
			expected = []Result{
				&ResultFrame{LengthDefault, http2.FrameHeaders, http2.FlagHeadersEndStream, ErrCodeDefault},
			}

			http2Conn := CreateHttp2Conn(ctx, true)
			defer http2Conn.conn.Close()

			hdrs := commonHeaderFields(ctx)
			hdrs[0].Value = "POST"
			hdrs = append(hdrs, pair("content-length", "4"))
			hdrs = append(hdrs, pair("content-type", "text/plain"))
			hdrs = append(hdrs, pair("trailer", "x-test"))

			var hp1 http2.HeadersFrameParam
			hp1.StreamID = 1
			hp1.EndStream = false
			hp1.EndHeaders = true
			hp1.BlockFragment = http2Conn.EncodeHeader(hdrs)
			http2Conn.fr.WriteHeaders(hp1)

			http2Conn.fr.WriteData(1, false, []byte("test"))

			trailers := []hpack.HeaderField{
				pair("x-test", "ok"),
			}

			var hp2 http2.HeadersFrameParam
			hp2.StreamID = 1
			hp2.EndStream = true
			hp2.EndHeaders = true
			hp2.BlockFragment = http2Conn.EncodeHeader(trailers)
			http2Conn.fr.WriteHeaders(hp2)

		loop:
			for {
				f, err := http2Conn.ReadFrame(ctx.Timeout)
				if err != nil {
					opErr, ok := err.(*net.OpError)
					if err == io.EOF || (ok && opErr.Err == syscall.ECONNRESET) {
						rf, ok := actual.(*ResultFrame)
						if actual == nil || (ok && rf.Type != http2.FrameGoAway) {
							actual = &ResultConnectionClose{}
						}
					} else if err == TIMEOUT {
						if actual == nil {
							actual = &ResultTestTimeout{}
						}
					} else {
						actual = &ResultError{err}
					}
					break loop
				}

				switch f := f.(type) {
				case *http2.HeadersFrame:
					actual = CreateResultFrame(f)
					if f.FrameHeader.Flags.Has(http2.FlagHeadersEndHeaders) {
						pass = true
						break loop
					}
				}
				actual = CreateResultFrame(f)
			}

			return pass, expected, actual
		},
	))

	tg.AddTestGroup(HttpHeaderFieldsTestGroup(ctx))

	return tg
}
Example #23
0
func TestStreamIdentifiers(ctx *Context) {
	PrintHeader("5.1.1. Stream Identifiers", 1)
	msg := "The endpoint MUST respond with a connection error of type PROTOCOL_ERROR."

	func(ctx *Context) {
		desc := "Sends even-numbered stream identifier"
		result := false

		http2Conn := CreateHttp2Conn(ctx, true)
		defer http2Conn.conn.Close()

		var buf bytes.Buffer
		hdrs := []hpack.HeaderField{
			pair(":method", "GET"),
			pair(":scheme", "http"),
			pair(":path", "/"),
			pair(":authority", ctx.Authority()),
		}
		enc := hpack.NewEncoder(&buf)
		for _, hf := range hdrs {
			_ = enc.WriteField(hf)
		}

		var hp http2.HeadersFrameParam
		hp.StreamID = 2
		hp.EndStream = true
		hp.EndHeaders = true
		hp.BlockFragment = buf.Bytes()
		http2Conn.fr.WriteHeaders(hp)

		timeCh := time.After(3 * time.Second)

	loop:
		for {
			select {
			case f := <-http2Conn.dataCh:
				gf, ok := f.(*http2.GoAwayFrame)
				if ok {
					if gf.ErrCode == http2.ErrCodeProtocol {
						result = true
					}
				}
			case <-http2Conn.errCh:
				break loop
			case <-timeCh:
				break loop
			}
		}

		PrintResult(result, desc, msg, 1)
	}(ctx)

	func(ctx *Context) {
		desc := "Sends stream identifier that is numerically smaller than previous"
		result := false

		http2Conn := CreateHttp2Conn(ctx, true)
		defer http2Conn.conn.Close()

		var buf bytes.Buffer
		hdrs := []hpack.HeaderField{
			pair(":method", "GET"),
			pair(":scheme", "http"),
			pair(":path", "/"),
			pair(":authority", ctx.Authority()),
		}
		enc := hpack.NewEncoder(&buf)
		for _, hf := range hdrs {
			_ = enc.WriteField(hf)
		}

		var hp1 http2.HeadersFrameParam
		hp1.StreamID = 5
		hp1.EndStream = true
		hp1.EndHeaders = true
		hp1.BlockFragment = buf.Bytes()
		http2Conn.fr.WriteHeaders(hp1)

		var hp2 http2.HeadersFrameParam
		hp2.StreamID = 3
		hp2.EndStream = true
		hp2.EndHeaders = true
		hp2.BlockFragment = buf.Bytes()
		http2Conn.fr.WriteHeaders(hp2)

		timeCh := time.After(3 * time.Second)

	loop:
		for {
			select {
			case f := <-http2Conn.dataCh:
				gf, ok := f.(*http2.GoAwayFrame)
				if ok {
					if gf.ErrCode == http2.ErrCodeProtocol {
						result = true
					}
				}
			case <-http2Conn.errCh:
				break loop
			case <-timeCh:
				break loop
			}
		}

		PrintResult(result, desc, msg, 1)
	}(ctx)
}
Example #24
0
File: 4_3.go Project: zeb209/h2spec
func HeaderCompressionAndDecompressionTestGroup(ctx *Context) *TestGroup {
	tg := NewTestGroup("4.3", "Header Compression and Decompression")

	tg.AddTestCase(NewTestCase(
		"Sends invalid header block fragment",
		"The endpoint MUST terminate the connection with a connection error of type COMPRESSION_ERROR.",
		func(ctx *Context) (pass bool, expected []Result, actual Result) {
			http2Conn := CreateHttp2Conn(ctx, true)
			defer http2Conn.conn.Close()

			// Literal Header Field with Incremental Indexing without Length and String segment
			fmt.Fprintf(http2Conn.conn, "\x00\x00\x01\x01\x05\x00\x00\x00\x01\x40")

			actualCodes := []http2.ErrCode{http2.ErrCodeCompression}
			return TestConnectionError(ctx, http2Conn, actualCodes)
		},
	))

	tg.AddTestCase(NewTestCase(
		"Sends Dynamic Table Size Update (RFC 7541, 6.3)",
		"The endpoint must accept Dynamic Table Size Update",
		func(ctx *Context) (pass bool, expected []Result, actual Result) {
			http2Conn := CreateHttp2Conn(ctx, true)
			defer http2Conn.conn.Close()

			hdrs := commonHeaderFields(ctx)

			// 2 Dynamic Table Size Updates, 0 and 4096.
			blockFragment := []byte{0x20, 0x3f, 0xe1, 0x1f}
			blockFragment = append(blockFragment, http2Conn.EncodeHeader(hdrs)...)
			var hp http2.HeadersFrameParam
			hp.StreamID = 1
			hp.EndStream = true
			hp.EndHeaders = true
			hp.BlockFragment = blockFragment
			http2Conn.fr.WriteHeaders(hp)

			return TestStreamClose(ctx, http2Conn)
		},
	))

	tg.AddTestCase(NewTestCase(
		"Encodes Dynamic Table Size Update (RFC 7541, 6.3) after common header fields",
		"The endpoint MUST terminate the connection with a connection error of type COMPRESSION_ERROR.",
		func(ctx *Context) (pass bool, expected []Result, actual Result) {
			http2Conn := CreateHttp2Conn(ctx, true)
			defer http2Conn.conn.Close()

			hdrs := commonHeaderFields(ctx)

			blockFragment := http2Conn.EncodeHeader(hdrs)
			// append 2 Dynamic Table Size Updates, 0 and
			// 4096.  this is illegal, since RFC 7541,
			// section 4.2 says that dynamic table size
			// update MUST occur at the beginning of the
			// first header block following the changes to
			// the dynamic table size.
			blockFragment = append(blockFragment, 0x20, 0x3f, 0xe1, 0x1f)

			var hp http2.HeadersFrameParam
			hp.StreamID = 1
			hp.EndStream = true
			hp.EndHeaders = true
			hp.BlockFragment = blockFragment
			http2Conn.fr.WriteHeaders(hp)

			actualCodes := []http2.ErrCode{http2.ErrCodeCompression}
			return TestConnectionError(ctx, http2Conn, actualCodes)
		},
	))

	return tg
}
Example #25
0
func TestWindowUpdate(ctx *Context) {
	PrintHeader("6.9. WINDOW_UPDATE", 0)

	func(ctx *Context) {
		desc := "Sends a WINDOW_UPDATE frame with an flow control window increment of 0"
		msg := "the endpoint MUST respond with a connection error of type PROTOCOL_ERROR."
		result := false

		http2Conn := CreateHttp2Conn(ctx, true)
		defer http2Conn.conn.Close()

		http2Conn.fr.WriteWindowUpdate(0, 0)

		timeCh := time.After(3 * time.Second)

	loop:
		for {
			select {
			case f := <-http2Conn.dataCh:
				gf, ok := f.(*http2.GoAwayFrame)
				if ok {
					if gf.ErrCode == http2.ErrCodeProtocol {
						result = true
						break loop
					}
				}
			case <-http2Conn.errCh:
				break loop
			case <-timeCh:
				break loop
			}
		}

		PrintResult(result, desc, msg, 0)
	}(ctx)

	func(ctx *Context) {
		desc := "Sends a WINDOW_UPDATE frame with an flow control window increment of 0 on a stream"
		msg := "the endpoint MUST respond with a connection error of type PROTOCOL_ERROR."
		result := false

		http2Conn := CreateHttp2Conn(ctx, true)
		defer http2Conn.conn.Close()

		var buf bytes.Buffer
		hdrs := []hpack.HeaderField{
			pair(":method", "GET"),
			pair(":scheme", "http"),
			pair(":path", "/"),
			pair(":authority", ctx.Authority()),
		}
		enc := hpack.NewEncoder(&buf)
		for _, hf := range hdrs {
			_ = enc.WriteField(hf)
		}

		var hp http2.HeadersFrameParam
		hp.StreamID = 1
		hp.EndStream = false
		hp.EndHeaders = true
		hp.BlockFragment = buf.Bytes()
		http2Conn.fr.WriteHeaders(hp)
		http2Conn.fr.WriteWindowUpdate(1, 0)

		timeCh := time.After(3 * time.Second)

	loop:
		for {
			select {
			case f := <-http2Conn.dataCh:
				gf, ok := f.(*http2.GoAwayFrame)
				if ok {
					if gf.ErrCode == http2.ErrCodeProtocol {
						result = true
						break loop
					}
				}
			case <-http2Conn.errCh:
				break loop
			case <-timeCh:
				break loop
			}
		}

		PrintResult(result, desc, msg, 0)
	}(ctx)

	TestInitialFlowControlWindowSize(ctx)

	PrintFooter()
}
Example #26
0
func HeadersTestGroup(ctx *Context) *TestGroup {
	tg := NewTestGroup("6.2", "HEADERS")

	tg.AddTestCase(NewTestCase(
		"Sends a HEADERS frame followed by any frame other than CONTINUATION",
		"The endpoint MUST treat the receipt of any other type of frame as a connection error of type PROTOCOL_ERROR.",
		func(ctx *Context) (expected []Result, actual Result) {
			http2Conn := CreateHttp2Conn(ctx, true)
			defer http2Conn.conn.Close()

			hdrs := commonHeaderFields(ctx)

			var hp http2.HeadersFrameParam
			hp.StreamID = 1
			hp.EndStream = false
			hp.EndHeaders = false
			hp.BlockFragment = http2Conn.EncodeHeader(hdrs)
			http2Conn.fr.WriteHeaders(hp)
			http2Conn.fr.WriteData(1, true, []byte("test"))

			actualCodes := []http2.ErrCode{http2.ErrCodeProtocol}
			return TestConnectionError(ctx, http2Conn, actualCodes)
		},
	))

	tg.AddTestCase(NewTestCase(
		"Sends a HEADERS frame followed by a frame on a different stream",
		"The endpoint MUST treat the receipt of a frame on a different stream as a connection error of type PROTOCOL_ERROR.",
		func(ctx *Context) (expected []Result, actual Result) {
			http2Conn := CreateHttp2Conn(ctx, true)
			defer http2Conn.conn.Close()

			hdrs := commonHeaderFields(ctx)

			var hp1 http2.HeadersFrameParam
			hp1.StreamID = 1
			hp1.EndStream = false
			hp1.EndHeaders = false
			hp1.BlockFragment = http2Conn.EncodeHeader(hdrs)
			http2Conn.fr.WriteHeaders(hp1)

			var hp2 http2.HeadersFrameParam
			hp2.StreamID = 3
			hp2.EndStream = true
			hp2.EndHeaders = true
			hp2.BlockFragment = http2Conn.EncodeHeader(hdrs)
			http2Conn.fr.WriteHeaders(hp2)

			actualCodes := []http2.ErrCode{http2.ErrCodeProtocol}
			return TestConnectionError(ctx, http2Conn, actualCodes)
		},
	))

	tg.AddTestCase(NewTestCase(
		"Sends a HEADERS frame with 0x0 stream identifier",
		"The endpoint MUST respond with a connection error of type PROTOCOL_ERROR.",
		func(ctx *Context) (expected []Result, actual Result) {
			http2Conn := CreateHttp2Conn(ctx, true)
			defer http2Conn.conn.Close()

			hdrs := commonHeaderFields(ctx)

			var hp http2.HeadersFrameParam
			hp.StreamID = 0
			hp.EndStream = true
			hp.EndHeaders = true
			hp.BlockFragment = http2Conn.EncodeHeader(hdrs)
			http2Conn.fr.WriteHeaders(hp)

			actualCodes := []http2.ErrCode{http2.ErrCodeProtocol}
			return TestConnectionError(ctx, http2Conn, actualCodes)
		},
	))

	tg.AddTestCase(NewTestCase(
		"Sends a HEADERS frame with invalid pad length",
		"The endpoint MUST treat this as a connection error of type PROTOCOL_ERROR.",
		func(ctx *Context) (expected []Result, actual Result) {
			http2Conn := CreateHttp2Conn(ctx, true)
			defer http2Conn.conn.Close()

			var buf bytes.Buffer
			hdrs := commonHeaderFields(ctx)
			enc := hpack.NewEncoder(&buf)
			for _, hf := range hdrs {
				_ = enc.WriteField(hf)
			}

			fmt.Fprintf(http2Conn.conn, "\x00\x00\x0f\x01\x0c\x00\x00\x00\x01")
			http2Conn.conn.Write(buf.Bytes())
			fmt.Fprintf(http2Conn.conn, "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00")

			actualCodes := []http2.ErrCode{http2.ErrCodeProtocol}
			return TestConnectionError(ctx, http2Conn, actualCodes)
		},
	))

	return tg
}
Example #27
0
func TestContinuation(ctx *Context) {
	PrintHeader("6.10. CONTINUATION", 0)

	func(ctx *Context) {
		desc := "Sends a CONTINUATION frame"
		msg := "The endpoint must accept the frame."
		result := false

		http2Conn := CreateHttp2Conn(ctx, true)
		defer http2Conn.conn.Close()

		var buf bytes.Buffer
		hdrs := []hpack.HeaderField{
			pair(":method", "GET"),
			pair(":scheme", "http"),
			pair(":path", "/"),
			pair(":authority", ctx.Authority()),
			pair("x-dummy1", GetDummyData(10000)),
			pair("x-dummy2", GetDummyData(10000)),
		}
		enc := hpack.NewEncoder(&buf)
		for _, hf := range hdrs {
			_ = enc.WriteField(hf)
		}

		var blockFragment = buf.Bytes()

		var hp http2.HeadersFrameParam
		hp.StreamID = 1
		hp.EndStream = true
		hp.EndHeaders = false
		hp.BlockFragment = blockFragment[0:16384]
		http2Conn.fr.WriteHeaders(hp)

		http2Conn.fr.WriteContinuation(1, true, blockFragment[16384:])

		timeCh := time.After(3 * time.Second)

	loop:
		for {
			select {
			case f := <-http2Conn.dataCh:
				_, ok := f.(*http2.HeadersFrame)
				if ok {
					result = true
					break loop
				}
			case <-http2Conn.errCh:
				break loop
			case <-timeCh:
				break loop
			}
		}

		PrintResult(result, desc, msg, 0)
	}(ctx)

	func(ctx *Context) {
		desc := "Sends multiple CONTINUATION frames"
		msg := "The endpoint must accept the frames."
		result := false

		http2Conn := CreateHttp2Conn(ctx, true)
		defer http2Conn.conn.Close()

		var buf bytes.Buffer
		hdrs := []hpack.HeaderField{
			pair(":method", "GET"),
			pair(":scheme", "http"),
			pair(":path", "/"),
			pair(":authority", ctx.Authority()),
			pair("x-dummy1", GetDummyData(10000)),
			pair("x-dummy2", GetDummyData(10000)),
			pair("x-dummy3", GetDummyData(10000)),
			pair("x-dummy4", GetDummyData(10000)),
			pair("x-dummy5", GetDummyData(10000)),
		}
		enc := hpack.NewEncoder(&buf)
		for _, hf := range hdrs {
			_ = enc.WriteField(hf)
		}

		var blockFragment = buf.Bytes()

		var hp http2.HeadersFrameParam
		hp.StreamID = 1
		hp.EndStream = true
		hp.EndHeaders = false
		hp.BlockFragment = blockFragment[0:16384]
		http2Conn.fr.WriteHeaders(hp)

		http2Conn.fr.WriteContinuation(1, false, blockFragment[16384:32767])
		http2Conn.fr.WriteContinuation(1, true, blockFragment[32767:])

		timeCh := time.After(3 * time.Second)

	loop:
		for {
			select {
			case f := <-http2Conn.dataCh:
				_, ok := f.(*http2.HeadersFrame)
				if ok {
					result = true
					break loop
				}
			case <-http2Conn.errCh:
				break loop
			case <-timeCh:
				break loop
			}
		}

		PrintResult(result, desc, msg, 0)
	}(ctx)

	func(ctx *Context) {
		desc := "Sends a CONTINUATION frame followed by any frame other than CONTINUATION"
		msg := "The endpoint MUST treat as a connection error of type PROTOCOL_ERROR."
		result := false

		http2Conn := CreateHttp2Conn(ctx, true)
		defer http2Conn.conn.Close()

		var buf bytes.Buffer
		hdrs := []hpack.HeaderField{
			pair(":method", "GET"),
			pair(":scheme", "http"),
			pair(":path", "/"),
			pair(":authority", ctx.Authority()),
			pair("x-dummy1", GetDummyData(10000)),
			pair("x-dummy2", GetDummyData(10000)),
			pair("x-dummy3", GetDummyData(10000)),
			pair("x-dummy4", GetDummyData(10000)),
			pair("x-dummy5", GetDummyData(10000)),
		}
		enc := hpack.NewEncoder(&buf)
		for _, hf := range hdrs {
			_ = enc.WriteField(hf)
		}

		var blockFragment = buf.Bytes()

		var hp http2.HeadersFrameParam
		hp.StreamID = 1
		hp.EndStream = true
		hp.EndHeaders = false
		hp.BlockFragment = blockFragment[0:16384]
		http2Conn.fr.WriteHeaders(hp)

		http2Conn.fr.WriteContinuation(1, false, blockFragment[16384:32767])

		http2Conn.fr.WriteData(1, true, []byte("test"))

		timeCh := time.After(3 * time.Second)

	loop:
		for {
			select {
			case f := <-http2Conn.dataCh:
				gf, ok := f.(*http2.GoAwayFrame)
				if ok {
					if gf.ErrCode == http2.ErrCodeProtocol {
						result = true
						break loop
					}
				}
			case <-http2Conn.errCh:
				break loop
			case <-timeCh:
				break loop
			}
		}

		PrintResult(result, desc, msg, 0)
	}(ctx)

	func(ctx *Context) {
		desc := "Sends a CONTINUATION frame followed by a frame on a different stream"
		msg := "The endpoint MUST treat as a connection error of type PROTOCOL_ERROR."
		result := false

		http2Conn := CreateHttp2Conn(ctx, true)
		defer http2Conn.conn.Close()

		var buf bytes.Buffer
		hdrs := []hpack.HeaderField{
			pair(":method", "GET"),
			pair(":scheme", "http"),
			pair(":path", "/"),
			pair(":authority", ctx.Authority()),
			pair("x-dummy1", GetDummyData(10000)),
			pair("x-dummy2", GetDummyData(10000)),
			pair("x-dummy3", GetDummyData(10000)),
			pair("x-dummy4", GetDummyData(10000)),
			pair("x-dummy5", GetDummyData(10000)),
		}
		enc := hpack.NewEncoder(&buf)
		for _, hf := range hdrs {
			_ = enc.WriteField(hf)
		}

		var blockFragment = buf.Bytes()

		var hp http2.HeadersFrameParam
		hp.StreamID = 1
		hp.EndStream = true
		hp.EndHeaders = false
		hp.BlockFragment = blockFragment[0:16384]
		http2Conn.fr.WriteHeaders(hp)

		http2Conn.fr.WriteContinuation(1, false, blockFragment[16384:32767])
		http2Conn.fr.WriteContinuation(3, true, blockFragment[32767:])

		timeCh := time.After(3 * time.Second)

	loop:
		for {
			select {
			case f := <-http2Conn.dataCh:
				gf, ok := f.(*http2.GoAwayFrame)
				if ok {
					if gf.ErrCode == http2.ErrCodeProtocol {
						result = true
						break loop
					}
				}
			case <-http2Conn.errCh:
				break loop
			case <-timeCh:
				break loop
			}
		}

		PrintResult(result, desc, msg, 0)
	}(ctx)

	func(ctx *Context) {
		desc := "Sends a CONTINUATION frame with the stream identifier that is 0x0"
		msg := "The endpoint MUST treat as a connection error of type PROTOCOL_ERROR."
		result := false

		http2Conn := CreateHttp2Conn(ctx, true)
		defer http2Conn.conn.Close()

		var buf bytes.Buffer
		hdrs := []hpack.HeaderField{
			pair(":method", "GET"),
			pair(":scheme", "http"),
			pair(":path", "/"),
			pair(":authority", ctx.Authority()),
			pair("x-dummy1", GetDummyData(10000)),
			pair("x-dummy2", GetDummyData(10000)),
			pair("x-dummy3", GetDummyData(10000)),
			pair("x-dummy4", GetDummyData(10000)),
			pair("x-dummy5", GetDummyData(10000)),
		}
		enc := hpack.NewEncoder(&buf)
		for _, hf := range hdrs {
			_ = enc.WriteField(hf)
		}

		var blockFragment = buf.Bytes()

		var hp http2.HeadersFrameParam
		hp.StreamID = 1
		hp.EndStream = true
		hp.EndHeaders = false
		hp.BlockFragment = blockFragment[0:16384]
		http2Conn.fr.WriteHeaders(hp)

		http2Conn.fr.WriteContinuation(1, false, blockFragment[16384:32767])
		http2Conn.fr.WriteContinuation(0, true, blockFragment[32767:])

		timeCh := time.After(3 * time.Second)

	loop:
		for {
			select {
			case f := <-http2Conn.dataCh:
				gf, ok := f.(*http2.GoAwayFrame)
				if ok {
					if gf.ErrCode == http2.ErrCodeProtocol {
						result = true
						break loop
					}
				}
			case <-http2Conn.errCh:
				break loop
			case <-timeCh:
				break loop
			}
		}

		PrintResult(result, desc, msg, 0)
	}(ctx)

	func(ctx *Context) {
		desc := "Sends a CONTINUATION frame after the frame other than HEADERS, PUSH_PROMISE or CONTINUATION"
		msg := "The endpoint MUST treat as a connection error of type PROTOCOL_ERROR."
		result := false

		http2Conn := CreateHttp2Conn(ctx, true)
		defer http2Conn.conn.Close()

		var buf bytes.Buffer
		hdrs := []hpack.HeaderField{
			pair(":method", "GET"),
			pair(":scheme", "http"),
			pair(":path", "/"),
			pair(":authority", ctx.Authority()),
		}
		enc := hpack.NewEncoder(&buf)
		for _, hf := range hdrs {
			_ = enc.WriteField(hf)
		}

		var hp http2.HeadersFrameParam
		hp.StreamID = 1
		hp.EndStream = true
		hp.EndHeaders = true
		hp.BlockFragment = buf.Bytes()
		http2Conn.fr.WriteHeaders(hp)

		http2Conn.fr.WriteData(1, true, []byte("test"))

		http2Conn.fr.WriteContinuation(1, true, buf.Bytes())

		timeCh := time.After(3 * time.Second)

	loop:
		for {
			select {
			case f := <-http2Conn.dataCh:
				gf, ok := f.(*http2.GoAwayFrame)
				if ok {
					if gf.ErrCode == http2.ErrCodeProtocol {
						result = true
						break loop
					}
				}
			case <-http2Conn.errCh:
				break loop
			case <-timeCh:
				break loop
			}
		}

		PrintResult(result, desc, msg, 0)
	}(ctx)

	PrintFooter()
}
Example #28
0
func TestData(ctx *Context) {
	PrintHeader("6.1. DATA", 0)

	func(ctx *Context) {
		desc := "Sends a DATA frame with 0x0 stream identifier"
		msg := "The endpoint MUST respond with a connection error of type PROTOCOL_ERROR."
		result := false

		http2Conn := CreateHttp2Conn(ctx, true)
		defer http2Conn.conn.Close()

		http2Conn.fr.WriteData(0, true, []byte("test"))
		timeCh := time.After(3 * time.Second)

	loop:
		for {
			select {
			case f := <-http2Conn.dataCh:
				gf, ok := f.(*http2.GoAwayFrame)
				if ok {
					if gf.ErrCode == http2.ErrCodeProtocol {
						result = true
					}
				}
			case <-http2Conn.errCh:
				break loop
			case <-timeCh:
				break loop
			}
		}

		PrintResult(result, desc, msg, 0)
	}(ctx)

	func(ctx *Context) {
		desc := "Sends a DATA frame on the stream that is not opend"
		msg := "The endpoint MUST respond with a stream error of type STREAM_CLOSED."
		result := false

		http2Conn := CreateHttp2Conn(ctx, true)
		defer http2Conn.conn.Close()

		var buf bytes.Buffer
		hdrs := []hpack.HeaderField{
			pair(":method", "GET"),
			pair(":scheme", "http"),
			pair(":path", "/"),
			pair(":authority", ctx.Authority()),
		}
		enc := hpack.NewEncoder(&buf)
		for _, hf := range hdrs {
			_ = enc.WriteField(hf)
		}

		var hp http2.HeadersFrameParam
		hp.StreamID = 1
		hp.EndStream = true
		hp.EndHeaders = true
		hp.BlockFragment = buf.Bytes()
		http2Conn.fr.WriteHeaders(hp)
		http2Conn.fr.WriteData(1, true, []byte("test"))

		timeCh := time.After(3 * time.Second)

	loop:
		for {
			select {
			case f := <-http2Conn.dataCh:
				gf, ok := f.(*http2.GoAwayFrame)
				if ok {
					if gf.ErrCode == http2.ErrCodeStreamClosed {
						result = true
					}
				}
			case <-http2Conn.errCh:
				break loop
			case <-timeCh:
				break loop
			}
		}

		PrintResult(result, desc, msg, 0)
	}(ctx)

	// bradfitz/http2 does not support padding of DATA frame.
	/*
		func(ctx *Context) {
			desc := "Sends a DATA frame with invalid pad length"
			msg := "The endpoint MUST treat this as a connection error of type PROTOCOL_ERROR."
			result := false

			http2Conn := CreateHttp2Conn(ctx, true)
			defer http2Conn.conn.Close()

			var buf bytes.Buffer
			hdrs := []hpack.HeaderField{
				pair(":method", "GET"),
				pair(":scheme", "http"),
				pair(":path", "/"),
				pair(":authority", ctx.Authority()),
			}
			enc := hpack.NewEncoder(&buf)
			for _, hf := range hdrs {
				_ = enc.WriteField(hf)
			}

			var hp http2.HeadersFrameParam
			hp.StreamID = 1
			hp.EndStream = true
			hp.EndHeaders = true
			hp.BlockFragment = buf.Bytes()
			http2Conn.fr.WriteHeaders(hp)

			http2Conn.fr.WriteData(1, true, []byte("test"))

			timeCh := time.After(3 * time.Second)

		loop:
			for {
				select {
				case f := <-http2Conn.dataCh:
					gf, ok := f.(*http2.GoAwayFrame)
					if ok {
						if gf.ErrCode == http2.ErrCodeProtocol {
							result = true
						}
					}
				case <-http2Conn.errCh:
					break loop
				case <-timeCh:
					break loop
				}
			}

			PrintResult(result, desc, msg, 0)
		}(ctx)
	*/

	PrintFooter()
}
Example #29
0
func DataTestGroup(ctx *Context) *TestGroup {
	tg := NewTestGroup("6.1", "DATA")

	tg.AddTestCase(NewTestCase(
		"Sends a DATA frame with 0x0 stream identifier",
		"The endpoint MUST respond with a connection error of type PROTOCOL_ERROR.",
		func(ctx *Context) (pass bool, expected []Result, actual Result) {
			http2Conn := CreateHttp2Conn(ctx, true)
			defer http2Conn.conn.Close()

			http2Conn.fr.WriteData(0, true, []byte("test"))

			actualCodes := []http2.ErrCode{http2.ErrCodeProtocol}
			return TestConnectionError(ctx, http2Conn, actualCodes)
		},
	))

	tg.AddTestCase(NewTestCase(
		"Sends a DATA frame on the stream that is not opend",
		"The endpoint MUST respond with a stream error of type STREAM_CLOSED.",
		func(ctx *Context) (pass bool, expected []Result, actual Result) {
			http2Conn := CreateHttp2Conn(ctx, true)
			defer http2Conn.conn.Close()

			hdrs := commonHeaderFields(ctx)
			hdrs[0].Value = "POST"
			hdrs = append(hdrs, pair("content-type", "4"))

			var hp http2.HeadersFrameParam
			hp.StreamID = 1
			hp.EndStream = true
			hp.EndHeaders = true
			hp.BlockFragment = http2Conn.EncodeHeader(hdrs)
			http2Conn.fr.WriteHeaders(hp)
			http2Conn.fr.WriteData(1, true, []byte("test"))

			actualCodes := []http2.ErrCode{http2.ErrCodeStreamClosed}
			return TestStreamError(ctx, http2Conn, actualCodes)
		},
	))

	tg.AddTestCase(NewTestCase(
		"Sends a DATA frame with invalid pad length",
		"The endpoint MUST treat this as a connection error of type PROTOCOL_ERROR.",
		func(ctx *Context) (pass bool, expected []Result, actual Result) {
			http2Conn := CreateHttp2Conn(ctx, true)
			defer http2Conn.conn.Close()

			hdrs := commonHeaderFields(ctx)
			hdrs[0].Value = "POST"
			hdrs = append(hdrs, pair("content-type", "4"))

			var hp http2.HeadersFrameParam
			hp.StreamID = 1
			hp.EndStream = false
			hp.EndHeaders = true
			hp.BlockFragment = http2Conn.EncodeHeader(hdrs)
			http2Conn.fr.WriteHeaders(hp)

			// Data length: 5, Pad length: 6
			fmt.Fprintf(http2Conn.conn, "\x00\x00\x05\x00\x0b\x00\x00\x00\x01")
			fmt.Fprintf(http2Conn.conn, "\x06\x54\x65\x73\x74")

			actualCodes := []http2.ErrCode{http2.ErrCodeProtocol}
			return TestStreamError(ctx, http2Conn, actualCodes)
		},
	))

	return tg
}
Example #30
0
func ContinuationTestGroup(ctx *Context) *TestGroup {
	tg := NewTestGroup("6.10", "CONTINUATION")

	tg.AddTestCase(NewTestCase(
		"Sends a CONTINUATION frame",
		"The endpoint must accept the frame.",
		func(ctx *Context) (expected []Result, actual Result) {
			expected = []Result{
				&ResultFrame{http2.FrameHeaders, FlagDefault, ErrCodeDefault},
			}

			http2Conn := CreateHttp2Conn(ctx, true)
			defer http2Conn.conn.Close()

			hdrs := commonHeaderFields(ctx)
			hdrs = append(hdrs, pair("x-dummy1", dummyData(10000)))
			hdrs = append(hdrs, pair("x-dummy2", dummyData(10000)))
			blockFragment := http2Conn.EncodeHeader(hdrs)

			var hp http2.HeadersFrameParam
			hp.StreamID = 1
			hp.EndStream = true
			hp.EndHeaders = false
			hp.BlockFragment = blockFragment[0:16384]
			http2Conn.fr.WriteHeaders(hp)

			http2Conn.fr.WriteContinuation(1, true, blockFragment[16384:])

		loop:
			for {
				f, err := http2Conn.ReadFrame(ctx.Timeout)
				if err != nil {
					opErr, ok := err.(*net.OpError)
					if err == io.EOF || (ok && opErr.Err == syscall.ECONNRESET) {
						actual = &ResultConnectionClose{}
					} else if err == TIMEOUT {
						if actual == nil {
							actual = &ResultTestTimeout{}
						}
					} else {
						actual = &ResultError{err}
					}
					break loop
				}

				actual = &ResultFrame{f.Header().Type, FlagDefault, ErrCodeDefault}
				_, ok := f.(*http2.HeadersFrame)
				if ok {
					break loop
				}
			}

			return expected, actual
		},
	))

	tg.AddTestCase(NewTestCase(
		"Sends multiple CONTINUATION frames",
		"The endpoint must accept the frames.",
		func(ctx *Context) (expected []Result, actual Result) {
			expected = []Result{
				&ResultFrame{http2.FrameHeaders, FlagDefault, ErrCodeDefault},
			}

			http2Conn := CreateHttp2Conn(ctx, true)
			defer http2Conn.conn.Close()

			hdrs := commonHeaderFields(ctx)
			hdrs = append(hdrs, pair("x-dummy1", dummyData(10000)))
			hdrs = append(hdrs, pair("x-dummy2", dummyData(10000)))
			hdrs = append(hdrs, pair("x-dummy3", dummyData(10000)))
			hdrs = append(hdrs, pair("x-dummy4", dummyData(10000)))
			hdrs = append(hdrs, pair("x-dummy5", dummyData(10000)))

			blockFragment := http2Conn.EncodeHeader(hdrs)

			var hp http2.HeadersFrameParam
			hp.StreamID = 1
			hp.EndStream = true
			hp.EndHeaders = false
			hp.BlockFragment = blockFragment[0:16384]
			http2Conn.fr.WriteHeaders(hp)

			http2Conn.fr.WriteContinuation(1, false, blockFragment[16384:32767])
			http2Conn.fr.WriteContinuation(1, true, blockFragment[32767:])

		loop:
			for {
				f, err := http2Conn.ReadFrame(ctx.Timeout)
				if err != nil {
					opErr, ok := err.(*net.OpError)
					if err == io.EOF || (ok && opErr.Err == syscall.ECONNRESET) {
						actual = &ResultConnectionClose{}
					} else if err == TIMEOUT {
						if actual == nil {
							actual = &ResultTestTimeout{}
						}
					} else {
						actual = &ResultError{err}
					}
					break loop
				}

				actual = &ResultFrame{f.Header().Type, FlagDefault, ErrCodeDefault}
				_, ok := f.(*http2.HeadersFrame)
				if ok {
					break loop
				}
			}

			return expected, actual
		},
	))

	tg.AddTestCase(NewTestCase(
		"Sends a CONTINUATION frame followed by any frame other than CONTINUATION",
		"The endpoint MUST treat as a connection error of type PROTOCOL_ERROR.",
		func(ctx *Context) (expected []Result, actual Result) {
			http2Conn := CreateHttp2Conn(ctx, true)
			defer http2Conn.conn.Close()

			hdrs := commonHeaderFields(ctx)
			hdrs = append(hdrs, pair("x-dummy1", dummyData(10000)))
			hdrs = append(hdrs, pair("x-dummy2", dummyData(10000)))
			hdrs = append(hdrs, pair("x-dummy3", dummyData(10000)))
			hdrs = append(hdrs, pair("x-dummy4", dummyData(10000)))
			hdrs = append(hdrs, pair("x-dummy5", dummyData(10000)))

			blockFragment := http2Conn.EncodeHeader(hdrs)

			var hp http2.HeadersFrameParam
			hp.StreamID = 1
			hp.EndStream = true
			hp.EndHeaders = false
			hp.BlockFragment = blockFragment[0:16384]
			http2Conn.fr.WriteHeaders(hp)

			http2Conn.fr.WriteContinuation(1, false, blockFragment[16384:32767])
			http2Conn.fr.WriteData(1, true, []byte("test"))

			actualCodes := []http2.ErrCode{http2.ErrCodeProtocol}
			return TestConnectionError(ctx, http2Conn, actualCodes)
		},
	))

	tg.AddTestCase(NewTestCase(
		"Sends a CONTINUATION frame followed by a frame on a different stream",
		"The endpoint MUST treat as a connection error of type PROTOCOL_ERROR.",
		func(ctx *Context) (expected []Result, actual Result) {
			http2Conn := CreateHttp2Conn(ctx, true)
			defer http2Conn.conn.Close()

			hdrs := commonHeaderFields(ctx)
			hdrs = append(hdrs, pair("x-dummy1", dummyData(10000)))
			hdrs = append(hdrs, pair("x-dummy2", dummyData(10000)))
			hdrs = append(hdrs, pair("x-dummy3", dummyData(10000)))
			hdrs = append(hdrs, pair("x-dummy4", dummyData(10000)))
			hdrs = append(hdrs, pair("x-dummy5", dummyData(10000)))

			blockFragment := http2Conn.EncodeHeader(hdrs)

			var hp http2.HeadersFrameParam
			hp.StreamID = 1
			hp.EndStream = true
			hp.EndHeaders = false
			hp.BlockFragment = blockFragment[0:16384]
			http2Conn.fr.WriteHeaders(hp)

			http2Conn.fr.WriteContinuation(1, false, blockFragment[16384:32767])
			http2Conn.fr.WriteContinuation(3, true, blockFragment[32767:])

			actualCodes := []http2.ErrCode{http2.ErrCodeProtocol}
			return TestConnectionError(ctx, http2Conn, actualCodes)
		},
	))

	tg.AddTestCase(NewTestCase(
		"Sends a CONTINUATION frame with the stream identifier that is 0x0",
		"The endpoint MUST treat as a connection error of type PROTOCOL_ERROR.",
		func(ctx *Context) (expected []Result, actual Result) {
			http2Conn := CreateHttp2Conn(ctx, true)
			defer http2Conn.conn.Close()

			hdrs := commonHeaderFields(ctx)
			hdrs = append(hdrs, pair("x-dummy1", dummyData(10000)))
			hdrs = append(hdrs, pair("x-dummy2", dummyData(10000)))
			hdrs = append(hdrs, pair("x-dummy3", dummyData(10000)))
			hdrs = append(hdrs, pair("x-dummy4", dummyData(10000)))
			hdrs = append(hdrs, pair("x-dummy5", dummyData(10000)))

			blockFragment := http2Conn.EncodeHeader(hdrs)

			var hp http2.HeadersFrameParam
			hp.StreamID = 1
			hp.EndStream = true
			hp.EndHeaders = false
			hp.BlockFragment = blockFragment[0:16384]
			http2Conn.fr.WriteHeaders(hp)

			http2Conn.fr.WriteContinuation(1, false, blockFragment[16384:32767])
			http2Conn.fr.WriteContinuation(0, true, blockFragment[32767:])

			actualCodes := []http2.ErrCode{http2.ErrCodeProtocol}
			return TestConnectionError(ctx, http2Conn, actualCodes)
		},
	))

	tg.AddTestCase(NewTestCase(
		"Sends a CONTINUATION frame after the frame other than HEADERS, PUSH_PROMISE or CONTINUATION",
		"The endpoint MUST treat as a connection error of type PROTOCOL_ERROR.",
		func(ctx *Context) (expected []Result, actual Result) {
			http2Conn := CreateHttp2Conn(ctx, true)
			defer http2Conn.conn.Close()

			hdrs := commonHeaderFields(ctx)

			var hp http2.HeadersFrameParam
			hp.StreamID = 1
			hp.EndStream = false
			hp.EndHeaders = true
			hp.BlockFragment = http2Conn.EncodeHeader(hdrs)
			http2Conn.fr.WriteHeaders(hp)

			http2Conn.fr.WriteData(1, true, []byte("test"))
			http2Conn.fr.WriteContinuation(1, true, http2Conn.EncodeHeader(hdrs))

			actualCodes := []http2.ErrCode{http2.ErrCodeProtocol}
			return TestConnectionError(ctx, http2Conn, actualCodes)
		},
	))

	return tg
}