github.com/prebid/prebid-server@v0.275.0/prebid_cache_client/client_test.go (about) 1 package prebid_cache_client 2 3 import ( 4 "bytes" 5 "context" 6 "encoding/json" 7 "fmt" 8 "net/http" 9 "net/http/httptest" 10 "strconv" 11 "testing" 12 13 "github.com/prebid/prebid-server/config" 14 "github.com/prebid/prebid-server/metrics" 15 metricsConf "github.com/prebid/prebid-server/metrics/config" 16 17 "github.com/stretchr/testify/assert" 18 "github.com/stretchr/testify/mock" 19 ) 20 21 func TestEmptyPut(t *testing.T) { 22 handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 23 t.Errorf("The server should not be called.") 24 }) 25 server := httptest.NewServer(handler) 26 defer server.Close() 27 28 metricsMock := &metrics.MetricsEngineMock{} 29 30 client := &clientImpl{ 31 httpClient: server.Client(), 32 putUrl: server.URL, 33 metrics: metricsMock, 34 } 35 ids, _ := client.PutJson(context.Background(), nil) 36 assertIntEqual(t, len(ids), 0) 37 ids, _ = client.PutJson(context.Background(), []Cacheable{}) 38 assertIntEqual(t, len(ids), 0) 39 40 metricsMock.AssertNotCalled(t, "RecordPrebidCacheRequestTime") 41 } 42 43 func TestBadResponse(t *testing.T) { 44 handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 45 w.WriteHeader(500) 46 }) 47 server := httptest.NewServer(handler) 48 defer server.Close() 49 50 metricsMock := &metrics.MetricsEngineMock{} 51 metricsMock.On("RecordPrebidCacheRequestTime", true, mock.Anything).Once() 52 53 client := &clientImpl{ 54 httpClient: server.Client(), 55 putUrl: server.URL, 56 metrics: metricsMock, 57 } 58 ids, _ := client.PutJson(context.Background(), []Cacheable{ 59 { 60 Type: TypeJSON, 61 Data: json.RawMessage("true"), 62 }, { 63 Type: TypeJSON, 64 Data: json.RawMessage("false"), 65 }, 66 }) 67 assertIntEqual(t, len(ids), 2) 68 assertStringEqual(t, ids[0], "") 69 assertStringEqual(t, ids[1], "") 70 71 metricsMock.AssertExpectations(t) 72 } 73 74 func TestCancelledContext(t *testing.T) { 75 testCases := []struct { 76 description string 77 cacheable []Cacheable 78 expectedItems int 79 expectedPayloadSize int 80 }{ 81 { 82 description: "1 Item", 83 cacheable: []Cacheable{ 84 { 85 Type: TypeJSON, 86 Data: json.RawMessage("true"), 87 }, 88 }, 89 expectedItems: 1, 90 expectedPayloadSize: 39, 91 }, 92 { 93 description: "2 Items", 94 cacheable: []Cacheable{ 95 { 96 Type: TypeJSON, 97 Data: json.RawMessage("true"), 98 }, 99 { 100 Type: TypeJSON, 101 Data: json.RawMessage("false"), 102 }, 103 }, 104 expectedItems: 2, 105 expectedPayloadSize: 69, 106 }, 107 } 108 109 // Initialize Stub Server 110 stubHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 111 w.WriteHeader(200) 112 }) 113 stubServer := httptest.NewServer(stubHandler) 114 defer stubServer.Close() 115 116 // Run Tests 117 for _, testCase := range testCases { 118 metricsMock := &metrics.MetricsEngineMock{} 119 metricsMock.On("RecordPrebidCacheRequestTime", false, mock.Anything).Once() 120 121 client := &clientImpl{ 122 httpClient: stubServer.Client(), 123 putUrl: stubServer.URL, 124 metrics: metricsMock, 125 } 126 127 ctx, cancel := context.WithCancel(context.Background()) 128 cancel() 129 ids, errs := client.PutJson(ctx, testCase.cacheable) 130 131 expectedErrorMessage := fmt.Sprintf("Items=%v, Payload Size=%v", testCase.expectedItems, testCase.expectedPayloadSize) 132 133 assert.Equal(t, testCase.expectedItems, len(ids), testCase.description+":ids") 134 assert.Len(t, errs, 1) 135 assert.Contains(t, errs[0].Error(), "Error sending the request to Prebid Cache: context canceled", testCase.description+":error") 136 assert.Contains(t, errs[0].Error(), expectedErrorMessage, testCase.description+":error_dimensions") 137 metricsMock.AssertExpectations(t) 138 } 139 } 140 141 func TestSuccessfulPut(t *testing.T) { 142 server := httptest.NewServer(newHandler(2)) 143 defer server.Close() 144 145 metricsMock := &metrics.MetricsEngineMock{} 146 metricsMock.On("RecordPrebidCacheRequestTime", true, mock.Anything).Once() 147 148 client := &clientImpl{ 149 httpClient: server.Client(), 150 putUrl: server.URL, 151 metrics: metricsMock, 152 } 153 154 ids, _ := client.PutJson(context.Background(), []Cacheable{ 155 { 156 Type: TypeJSON, 157 Data: json.RawMessage("true"), 158 TTLSeconds: 300, 159 }, { 160 Type: TypeJSON, 161 Data: json.RawMessage("false"), 162 }, 163 }) 164 assertIntEqual(t, len(ids), 2) 165 assertStringEqual(t, ids[0], "0") 166 assertStringEqual(t, ids[1], "1") 167 168 metricsMock.AssertExpectations(t) 169 } 170 171 func TestEncodeValueToBuffer(t *testing.T) { 172 buf := new(bytes.Buffer) 173 testCache := Cacheable{ 174 Type: TypeJSON, 175 Data: json.RawMessage(`{}`), 176 TTLSeconds: 300, 177 BidID: "bid", 178 Bidder: "bdr", 179 Timestamp: 123456789, 180 } 181 expected := string(`{"type":"json","ttlseconds":300,"value":{},"bidid":"bid","bidder":"bdr","timestamp":123456789}`) 182 _ = encodeValueToBuffer(testCache, false, buf) 183 actual := buf.String() 184 assertStringEqual(t, expected, actual) 185 } 186 187 // The following test asserts that the cache client's GetExtCacheData() implementation is able to pull return the exact Path and Host that were 188 // specified in Prebid-Server's configuration, no substitutions nor default values. 189 func TestStripCacheHostAndPath(t *testing.T) { 190 inCacheURL := config.Cache{ExpectedTimeMillis: 10} 191 type aTest struct { 192 inExtCacheURL config.ExternalCache 193 expectedScheme string 194 expectedHost string 195 expectedPath string 196 } 197 testInput := []aTest{ 198 { 199 inExtCacheURL: config.ExternalCache{ 200 Scheme: "", 201 Host: "prebid-server.prebid.org", 202 Path: "/pbcache/endpoint", 203 }, 204 expectedScheme: "", 205 expectedHost: "prebid-server.prebid.org", 206 expectedPath: "/pbcache/endpoint", 207 }, 208 { 209 inExtCacheURL: config.ExternalCache{ 210 Scheme: "https", 211 Host: "prebid-server.prebid.org", 212 Path: "/pbcache/endpoint", 213 }, 214 expectedScheme: "https", 215 expectedHost: "prebid-server.prebid.org", 216 expectedPath: "/pbcache/endpoint", 217 }, 218 { 219 inExtCacheURL: config.ExternalCache{ 220 Scheme: "", 221 Host: "prebidcache.net", 222 Path: "", 223 }, 224 expectedScheme: "", 225 expectedHost: "prebidcache.net", 226 expectedPath: "", 227 }, 228 { 229 inExtCacheURL: config.ExternalCache{ 230 Scheme: "", 231 Host: "", 232 Path: "", 233 }, 234 expectedScheme: "", 235 expectedHost: "", 236 expectedPath: "", 237 }, 238 { 239 inExtCacheURL: config.ExternalCache{ 240 Scheme: "", 241 Host: "prebid-server.prebid.org", 242 Path: "pbcache/endpoint", 243 }, 244 expectedScheme: "", 245 expectedHost: "prebid-server.prebid.org", 246 expectedPath: "/pbcache/endpoint", 247 }, 248 { 249 inExtCacheURL: config.ExternalCache{ 250 Scheme: "", 251 Host: "prebidcache.net", 252 Path: "/", 253 }, 254 expectedScheme: "", 255 expectedHost: "prebidcache.net", 256 expectedPath: "", 257 }, 258 } 259 for _, test := range testInput { 260 cacheClient := NewClient(&http.Client{}, &inCacheURL, &test.inExtCacheURL, &metricsConf.NilMetricsEngine{}) 261 scheme, host, path := cacheClient.GetExtCacheData() 262 263 assert.Equal(t, test.expectedScheme, scheme) 264 assert.Equal(t, test.expectedHost, host) 265 assert.Equal(t, test.expectedPath, path) 266 } 267 } 268 269 func assertIntEqual(t *testing.T, expected, actual int) { 270 t.Helper() 271 if expected != actual { 272 t.Errorf("Expected %d, got %d", expected, actual) 273 } 274 } 275 276 func assertStringEqual(t *testing.T, expected, actual string) { 277 t.Helper() 278 if expected != actual { 279 t.Errorf(`Expected "%s", got "%s"`, expected, actual) 280 } 281 } 282 283 type handlerResponseObject struct { 284 UUID string `json:"uuid"` 285 } 286 287 type handlerResponse struct { 288 Responses []handlerResponseObject `json:"responses"` 289 } 290 291 func newHandler(numResponses int) http.HandlerFunc { 292 return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 293 resp := handlerResponse{ 294 Responses: make([]handlerResponseObject, numResponses), 295 } 296 for i := 0; i < numResponses; i++ { 297 resp.Responses[i].UUID = strconv.Itoa(i) 298 } 299 300 respBytes, _ := json.Marshal(resp) 301 w.Write(respBytes) 302 }) 303 }