Repository: grpc/grpc-go
File: internal/transport/transport_test.go (Go)

Code before:
				Fields: []hpack.HeaderField{
					{Name: "content-type", Value: "application/grpc"},
					{Name: ":status", Value: "504"},
				},
			},
			wantStatus:          status.New(codes.OK, ""),
			wantStatusEndStream: status.New(codes.Internal, ""),
		},
		{
			name: "trailer only grpc timeout ignores http status",
			metaHeaderFrame: &http2.MetaHeadersFrame{
				Fields: []hpack.HeaderField{
					{Name: "content-type", Value: "application/grpc"},
					{Name: "grpc-status", Value: "4"},
					{Name: "grpc-message", Value: "Request timed out: Internal error"},
					{Name: ":status", Value: "200"},
				},
			},
			wantStatusEndStream: status.New(codes.DeadlineExceeded, "Request timed out: Internal error"),
		},
	} {

		t.Run(test.name, func(t *testing.T) {
			if test.wantStatus == nil {
				t.Skip()
			}
			ts := testStream()
			s := testClient(ts)

			test.metaHeaderFrame.HeadersFrame = &http2.HeadersFrame{
				FrameHeader: http2.FrameHeader{
					StreamID: 0,
				},
			}

			s.operateHeaders(test.metaHeaderFrame)
			got := ts.status
			want := test.wantStatus
			if got.Code() != want.Code() || got.Message() != want.Message() {
				t.Fatalf("operateHeaders(%v); status = \ngot: %s\nwant: %s", test.metaHeaderFrame, got, want)
			}
		})
		t.Run(fmt.Sprintf("%s-end_stream", test.name), func(t *testing.T) {
			ts := testStream()
			s := testClient(ts)

			test.metaHeaderFrame.HeadersFrame = &http2.HeadersFrame{
				FrameHeader: http2.FrameHeader{
					StreamID: 0,
					Flags:    http2.FlagHeadersEndStream,
				},

Review comment (suggestion):
Instead of skipping the test, can we assert the expected behaviour of parsing such header frames?

Ideally, we should not be running two different tests on the same set of test cases and instead have two test functions.

Code after:

	for _, tc := range tests {
		t.Run(tc.name, func(t *testing.T) {
			cs := newTestClientStream()
			s := newTestHTTP2Client(cs)

			tc.metaHeaderFrame.HeadersFrame = &http2.HeadersFrame{
				FrameHeader: http2.FrameHeader{
					StreamID: 1,
				},
			}

			s.operateHeaders(tc.metaHeaderFrame)
			got := cs.status
			want := tc.wantStatus
			if got.Code() != want.Code() || got.Message() != want.Message() {
				t.Errorf("operateHeaders(%v) got status %q, want %q", tc.metaHeaderFrame, got, want)
			}
		})
	}
}

// TestClientDecodeTrailer validates the handling of trailer frames, which may
// or may not also be the initial header frame (header-only response).
func (s) TestClientDecodeTrailer(t *testing.T) {
	tests := []struct {
		name                string
		metaHeaderFrame     *http2.MetaHeadersFrame
		wantEndStreamStatus *status.Status
	}{
		{
			name: "valid_trailer",
			metaHeaderFrame: &http2.MetaHeadersFrame{
				Fields: []hpack.HeaderField{
					{Name: "content-type", Value: "application/grpc"},
					{Name: "grpc-status", Value: "0"},
					{Name: ":status", Value: "200"},
				},
			},
			wantEndStreamStatus: status.New(codes.OK, ""),
		},
		{
			name: "missing_content_type_in_grpc_mode",
			metaHeaderFrame: &http2.MetaHeadersFrame{
				Fields: []hpack.HeaderField{
					{Name: "grpc-status", Value: "0"},
					{Name: ":status", Value: "200"},
				},
			},
			wantEndStreamStatus: status.New(codes.OK, ""),
		},