123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309 |
- package headers_test
- import (
- "testing"
- "github.com/google/go-cmp/cmp"
- "github.com/google/go-cmp/cmp/cmpopts"
- "github.com/stretchr/testify/assert"
- "github.com/stretchr/testify/require"
- "github.com/ydb-platform/ydb/library/go/httputil/headers"
- )
- // examples for tests taken from https://tools.ietf.org/html/rfc2616#section-14.3
- func TestParseAcceptEncoding(t *testing.T) {
- testCases := []struct {
- name string
- input string
- expected headers.AcceptableEncodings
- expectedErr error
- }{
- {
- "ietf_example_1",
- "compress, gzip",
- headers.AcceptableEncodings{
- {Encoding: headers.ContentEncoding("compress"), Weight: 1.0},
- {Encoding: headers.ContentEncoding("gzip"), Weight: 1.0},
- },
- nil,
- },
- {
- "ietf_example_2",
- "",
- nil,
- nil,
- },
- {
- "ietf_example_3",
- "*",
- headers.AcceptableEncodings{
- {Encoding: headers.ContentEncoding("*"), Weight: 1.0},
- },
- nil,
- },
- {
- "ietf_example_4",
- "compress;q=0.5, gzip;q=1.0",
- headers.AcceptableEncodings{
- {Encoding: headers.ContentEncoding("gzip"), Weight: 1.0},
- {Encoding: headers.ContentEncoding("compress"), Weight: 0.5},
- },
- nil,
- },
- {
- "ietf_example_5",
- "gzip;q=1.0, identity; q=0.5, *;q=0",
- headers.AcceptableEncodings{
- {Encoding: headers.ContentEncoding("gzip"), Weight: 1.0},
- {Encoding: headers.ContentEncoding("identity"), Weight: 0.5},
- {Encoding: headers.ContentEncoding("*"), Weight: 0},
- },
- nil,
- },
- {
- "solomon_headers",
- "zstd,lz4,gzip,deflate",
- headers.AcceptableEncodings{
- {Encoding: headers.ContentEncoding("zstd"), Weight: 1.0},
- {Encoding: headers.ContentEncoding("lz4"), Weight: 1.0},
- {Encoding: headers.ContentEncoding("gzip"), Weight: 1.0},
- {Encoding: headers.ContentEncoding("deflate"), Weight: 1.0},
- },
- nil,
- },
- }
- for _, tc := range testCases {
- t.Run(tc.name, func(t *testing.T) {
- acceptableEncodings, err := headers.ParseAcceptEncoding(tc.input)
- if tc.expectedErr != nil {
- assert.EqualError(t, err, tc.expectedErr.Error())
- } else {
- assert.NoError(t, err)
- }
- require.Len(t, acceptableEncodings, len(tc.expected))
- opt := cmpopts.IgnoreUnexported(headers.AcceptableEncoding{})
- assert.True(t, cmp.Equal(tc.expected, acceptableEncodings, opt), cmp.Diff(tc.expected, acceptableEncodings, opt))
- })
- }
- }
- func TestParseAccept(t *testing.T) {
- testCases := []struct {
- name string
- input string
- expected headers.AcceptableTypes
- expectedErr error
- }{
- {
- "empty_header",
- "",
- nil,
- nil,
- },
- {
- "accept_any",
- "*/*",
- headers.AcceptableTypes{
- {Type: headers.ContentTypeAny, Weight: 1.0},
- },
- nil,
- },
- {
- "accept_single",
- "application/json",
- headers.AcceptableTypes{
- {Type: headers.TypeApplicationJSON, Weight: 1.0},
- },
- nil,
- },
- {
- "accept_multiple",
- "application/json, application/protobuf",
- headers.AcceptableTypes{
- {Type: headers.TypeApplicationJSON, Weight: 1.0},
- {Type: headers.TypeApplicationProtobuf, Weight: 1.0},
- },
- nil,
- },
- {
- "accept_multiple_weighted",
- "application/json;q=0.8, application/protobuf",
- headers.AcceptableTypes{
- {Type: headers.TypeApplicationProtobuf, Weight: 1.0},
- {Type: headers.TypeApplicationJSON, Weight: 0.8},
- },
- nil,
- },
- {
- "accept_multiple_weighted_unsorted",
- "text/plain;q=0.5, application/protobuf, application/json;q=0.5",
- headers.AcceptableTypes{
- {Type: headers.TypeApplicationProtobuf, Weight: 1.0},
- {Type: headers.TypeTextPlain, Weight: 0.5},
- {Type: headers.TypeApplicationJSON, Weight: 0.5},
- },
- nil,
- },
- {
- "unknown_type",
- "custom/type, unknown/my_type;q=0.2",
- headers.AcceptableTypes{
- {Type: headers.ContentType("custom/type"), Weight: 1.0},
- {Type: headers.ContentType("unknown/my_type"), Weight: 0.2},
- },
- nil,
- },
- {
- "yabro_19.6.0",
- "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3",
- headers.AcceptableTypes{
- {Type: headers.ContentType("text/html"), Weight: 1.0},
- {Type: headers.ContentType("application/xhtml+xml"), Weight: 1.0},
- {Type: headers.ContentType("image/webp"), Weight: 1.0},
- {Type: headers.ContentType("image/apng"), Weight: 1.0},
- {Type: headers.ContentType("application/signed-exchange"), Weight: 1.0, Extension: map[string]string{"v": "b3"}},
- {Type: headers.ContentType("application/xml"), Weight: 0.9},
- {Type: headers.ContentType("*/*"), Weight: 0.8},
- },
- nil,
- },
- {
- "chrome_81.0.4044",
- "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9",
- headers.AcceptableTypes{
- {Type: headers.ContentType("text/html"), Weight: 1.0},
- {Type: headers.ContentType("application/xhtml+xml"), Weight: 1.0},
- {Type: headers.ContentType("image/webp"), Weight: 1.0},
- {Type: headers.ContentType("image/apng"), Weight: 1.0},
- {Type: headers.ContentType("application/xml"), Weight: 0.9},
- {Type: headers.ContentType("application/signed-exchange"), Weight: 0.9, Extension: map[string]string{"v": "b3"}},
- {Type: headers.ContentType("*/*"), Weight: 0.8},
- },
- nil,
- },
- {
- "firefox_77.0b3",
- "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8",
- headers.AcceptableTypes{
- {Type: headers.ContentType("text/html"), Weight: 1.0},
- {Type: headers.ContentType("application/xhtml+xml"), Weight: 1.0},
- {Type: headers.ContentType("image/webp"), Weight: 1.0},
- {Type: headers.ContentType("application/xml"), Weight: 0.9},
- {Type: headers.ContentType("*/*"), Weight: 0.8},
- },
- nil,
- },
- {
- "sort_by_most_specific",
- "text/*, text/html, */*, text/html;level=1",
- headers.AcceptableTypes{
- {Type: headers.ContentType("text/html"), Weight: 1.0, Extension: map[string]string{"level": "1"}},
- {Type: headers.ContentType("text/html"), Weight: 1.0},
- {Type: headers.ContentType("text/*"), Weight: 1.0},
- {Type: headers.ContentType("*/*"), Weight: 1.0},
- },
- nil,
- },
- }
- for _, tc := range testCases {
- t.Run(tc.name, func(t *testing.T) {
- at, err := headers.ParseAccept(tc.input)
- if tc.expectedErr != nil {
- assert.EqualError(t, err, tc.expectedErr.Error())
- } else {
- assert.NoError(t, err)
- }
- require.Len(t, at, len(tc.expected))
- opt := cmpopts.IgnoreUnexported(headers.AcceptableType{})
- assert.True(t, cmp.Equal(tc.expected, at, opt), cmp.Diff(tc.expected, at, opt))
- })
- }
- }
- func TestAcceptableTypesString(t *testing.T) {
- testCases := []struct {
- name string
- types headers.AcceptableTypes
- expected string
- }{
- {
- "empty",
- headers.AcceptableTypes{},
- "",
- },
- {
- "single",
- headers.AcceptableTypes{
- {Type: headers.TypeApplicationJSON},
- },
- "application/json",
- },
- {
- "single_weighted",
- headers.AcceptableTypes{
- {Type: headers.TypeApplicationJSON, Weight: 0.8},
- },
- "application/json;q=0.8",
- },
- {
- "multiple",
- headers.AcceptableTypes{
- {Type: headers.TypeApplicationJSON},
- {Type: headers.TypeApplicationProtobuf},
- },
- "application/json, application/protobuf",
- },
- {
- "multiple_weighted",
- headers.AcceptableTypes{
- {Type: headers.TypeApplicationProtobuf},
- {Type: headers.TypeApplicationJSON, Weight: 0.8},
- },
- "application/protobuf, application/json;q=0.8",
- },
- {
- "multiple_weighted_with_extension",
- headers.AcceptableTypes{
- {Type: headers.TypeApplicationProtobuf},
- {Type: headers.TypeApplicationJSON, Weight: 0.8},
- {Type: headers.TypeApplicationXML, Weight: 0.5, Extension: map[string]string{"label": "1"}},
- },
- "application/protobuf, application/json;q=0.8, application/xml;q=0.5;label=1",
- },
- }
- for _, tc := range testCases {
- t.Run(tc.name, func(t *testing.T) {
- assert.Equal(t, tc.expected, tc.types.String())
- })
- }
- }
- func BenchmarkParseAccept(b *testing.B) {
- benchCases := []string{
- "",
- "*/*",
- "application/json",
- "application/json, application/protobuf",
- "application/json;q=0.8, application/protobuf",
- "text/plain;q=0.5, application/protobuf, application/json;q=0.5",
- "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3",
- "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9",
- "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8",
- "text/*, text/html, */*, text/html;level=1",
- }
- b.ReportAllocs()
- b.ResetTimer()
- for i := 0; i < b.N; i++ {
- _, _ = headers.ParseAccept(benchCases[i%len(benchCases)])
- }
- }
|