github.com/yandex/pandora@v0.5.32/components/providers/http/decoders/uri_test.go (about) 1 package decoders 2 3 import ( 4 "context" 5 "net/http" 6 "strings" 7 "testing" 8 "time" 9 10 "github.com/stretchr/testify/assert" 11 "github.com/stretchr/testify/require" 12 "github.com/yandex/pandora/components/providers/http/config" 13 "github.com/yandex/pandora/components/providers/http/decoders/ammo" 14 ) 15 16 func Test_uriDecoder_readLine(t *testing.T) { 17 var mustNewAmmo = func(t *testing.T, method string, url string, body []byte, header http.Header, tag string) *ammo.Ammo { 18 a := ammo.Ammo{} 19 err := a.Setup(method, url, body, header, tag) 20 require.NoError(t, err) 21 return &a 22 } 23 24 tests := []struct { 25 name string 26 data string 27 want *ammo.Ammo 28 wantErr bool 29 expectedCommonHeaders http.Header 30 }{ 31 { 32 name: "Header line", 33 data: "[Content-Type: application/json]", 34 want: nil, 35 wantErr: false, 36 expectedCommonHeaders: http.Header{ 37 "Content-Type": []string{"application/json"}, 38 "User-Agent": []string{"TestAgent"}, 39 }, 40 }, 41 { 42 name: "Valid URI", 43 data: "http://example.com/test", 44 want: mustNewAmmo(t, "GET", "http://example.com/test", nil, http.Header{ 45 "User-Agent": []string{"TestAgent"}, 46 "Authorization": []string{"Bearer xxx"}, 47 }, ""), 48 wantErr: false, 49 expectedCommonHeaders: http.Header{ 50 "User-Agent": []string{"TestAgent"}, 51 }, 52 }, 53 { 54 name: "URI with tag", 55 data: "http://example.com/test tag\n", 56 want: mustNewAmmo(t, "GET", "http://example.com/test", nil, http.Header{ 57 "User-Agent": []string{"TestAgent"}, 58 "Authorization": []string{"Bearer xxx"}, 59 }, "tag"), 60 wantErr: false, 61 expectedCommonHeaders: http.Header{ 62 "User-Agent": []string{"TestAgent"}, 63 }, 64 }, 65 { 66 name: "Invalid data", 67 data: "1http://foo.com tag", 68 want: nil, 69 wantErr: true, 70 }, 71 } 72 for _, tt := range tests { 73 t.Run(tt.name, func(t *testing.T) { 74 commonHeader := http.Header{"User-Agent": []string{"TestAgent"}} 75 decodedConfigHeaders := http.Header{"Authorization": []string{"Bearer xxx"}} 76 77 decoder := newURIDecoder(nil, config.Config{}, decodedConfigHeaders) 78 a, err := decoder.readLine(tt.data, commonHeader) 79 80 if tt.wantErr { 81 assert.Error(t, err) 82 return 83 } 84 if tt.want == nil { 85 assert.Nil(t, a) 86 } else { 87 assert.Equal(t, tt.want, a) 88 } 89 assert.Equal(t, tt.expectedCommonHeaders, commonHeader) 90 }) 91 } 92 } 93 94 const uriDecoderInput = ` /0 95 [A:b] 96 /1 97 [Host : example.com] 98 [ C : d ] 99 /2 100 [A:] 101 [Host : other.net] 102 103 /3 104 /4 some tag` 105 106 func getURIAmmoWants(t *testing.T) []DecodedAmmo { 107 var mustNewAmmo = func(t *testing.T, method string, url string, body []byte, header http.Header, tag string) *ammo.Ammo { 108 a := ammo.Ammo{} 109 err := a.Setup(method, url, body, header, tag) 110 require.NoError(t, err) 111 return &a 112 } 113 return []DecodedAmmo{ 114 mustNewAmmo(t, "GET", "/0", nil, http.Header{"Content-Type": []string{"application/json"}}, ""), 115 mustNewAmmo(t, "GET", "/1", nil, http.Header{"A": []string{"b"}, "Content-Type": []string{"application/json"}}, ""), 116 mustNewAmmo(t, "GET", "/2", nil, http.Header{"Host": []string{"example.com"}, "A": []string{"b"}, "C": []string{"d"}, "Content-Type": []string{"application/json"}}, ""), 117 mustNewAmmo(t, "GET", "/3", nil, http.Header{"Host": []string{"other.net"}, "A": []string{""}, "C": []string{"d"}, "Content-Type": []string{"application/json"}}, ""), 118 mustNewAmmo(t, "GET", "/4", nil, http.Header{"Host": []string{"other.net"}, "A": []string{""}, "C": []string{"d"}, "Content-Type": []string{"application/json"}}, "some tag"), 119 } 120 } 121 122 func Test_uriDecoder_Scan(t *testing.T) { 123 decoder := newURIDecoder(strings.NewReader(uriDecoderInput), config.Config{ 124 Limit: 10, 125 }, http.Header{"Content-Type": []string{"application/json"}}) 126 127 ctx, cancel := context.WithTimeout(context.Background(), time.Second) 128 defer cancel() 129 130 wants := getURIAmmoWants(t) 131 for j := 0; j < 2; j++ { 132 for i, want := range wants { 133 ammo, err := decoder.Scan(ctx) 134 assert.NoError(t, err, "iteration %d-%d", j, i) 135 assert.Equal(t, want, ammo, "iteration %d-%d", j, i) 136 } 137 } 138 139 _, err := decoder.Scan(ctx) 140 assert.Equal(t, err, ErrAmmoLimit) 141 assert.Equal(t, decoder.ammoNum, uint(len(wants)*2)) 142 assert.Equal(t, decoder.passNum, uint(1)) 143 } 144 145 func Test_uriDecoder_LoadAmmo(t *testing.T) { 146 decoder := newURIDecoder(strings.NewReader(uriDecoderInput), config.Config{ 147 Limit: 10, 148 }, http.Header{"Content-Type": []string{"application/json"}}) 149 150 ctx, cancel := context.WithTimeout(context.Background(), time.Second) 151 defer cancel() 152 153 wants := getURIAmmoWants(t) 154 155 ammos, err := decoder.LoadAmmo(ctx) 156 assert.NoError(t, err) 157 assert.Equal(t, wants, ammos) 158 assert.Equal(t, decoder.config.Limit, uint(10)) 159 assert.Equal(t, decoder.config.Passes, uint(0)) 160 } 161 162 func Benchmark_uriDecoder_Scan(b *testing.B) { 163 decoder := newURIDecoder( 164 strings.NewReader(uriDecoderInput), config.Config{}, 165 http.Header{"Content-Type": []string{"application/json"}}, 166 ) 167 ctx := context.Background() 168 169 b.ResetTimer() 170 for i := 0; i < b.N; i++ { 171 _, err := decoder.Scan(ctx) 172 require.NoError(b, err) 173 } 174 }