-
Notifications
You must be signed in to change notification settings - Fork 762
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Timeout fix #1390
Timeout fix #1390
Changes from 7 commits
3a06124
4c8af73
f60311a
1d6ee61
7ffe372
0a07154
160b03f
18c8061
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,7 @@ | ||
package exchange | ||
|
||
import ( | ||
"bytes" | ||
"context" | ||
"encoding/json" | ||
"errors" | ||
|
@@ -10,6 +11,7 @@ import ( | |
"testing" | ||
"time" | ||
|
||
"github.com/golang/glog" | ||
"github.com/mxmCherry/openrtb" | ||
"github.com/prebid/prebid-server/adapters" | ||
"github.com/prebid/prebid-server/config" | ||
|
@@ -1254,15 +1256,28 @@ func TestTimeoutNotificationOff(t *testing.T) { | |
if tb, ok := bidder.Bidder.(adapters.TimeoutBidder); !ok { | ||
t.Error("Failed to cast bidder to a TimeoutBidder") | ||
} else { | ||
bidder.doTimeoutNotification(tb, &adapters.RequestData{}) | ||
bidder.doTimeoutNotification(tb, &adapters.RequestData{}, glog.Warningf) | ||
} | ||
} | ||
|
||
func TestTimeoutNotificationOn(t *testing.T) { | ||
ctx, cancelFunc := context.WithDeadline(context.Background(), time.Now().Add(-7*time.Hour)) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Does the time matter since we're cancelling the context immediately? If so, consider using just |
||
cancelFunc() | ||
respBody := "{\"bid\":false}" | ||
respStatus := 200 | ||
server := httptest.NewServer(mockHandler(respStatus, "getBody", respBody)) | ||
server := httptest.NewServer(mockSlowHandler(respStatus, "getBody", respBody)) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The slow handler waits 500ms. I think that's too long for a unit test. Ideally we'd inject a mock context to the timeout caller, but since we can't I think using smaller timeouts is a good compromise. Let's use 201ms or 205ms since the method is hardcoded for 200ms. |
||
defer server.Close() | ||
bidRequest := adapters.RequestData{ | ||
Method: "POST", | ||
Uri: server.URL, | ||
Body: []byte("{\"id\":\"this-id\",\"app\":{\"publisher\":{\"id\":\"pub-id\"}}}"), | ||
} | ||
|
||
var buf bytes.Buffer | ||
|
||
mylogger := func(msg string, args ...interface{}) { | ||
buf.WriteString(fmt.Sprintf(fmt.Sprintln(msg), args...)) | ||
} | ||
|
||
bidderImpl := ¬ifingBidder{ | ||
notiRequest: adapters.RequestData{ | ||
|
@@ -1272,21 +1287,40 @@ func TestTimeoutNotificationOn(t *testing.T) { | |
Headers: http.Header{}, | ||
}, | ||
} | ||
// bidderImpl := audienceNetwork.NewFacebookBidder("test-platform-id", "test-app-secret") | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Consider removing the comment. |
||
bidderInfo := adapters.BidderInfo{ | ||
Status: adapters.StatusActive, | ||
Capabilities: &adapters.CapabilitiesInfo{ | ||
App: &adapters.PlatformInfo{ | ||
MediaTypes: []openrtb_ext.BidType{openrtb_ext.BidTypeBanner}, | ||
}, | ||
}, | ||
} | ||
ibidder := adapters.EnforceBidderInfo(bidderImpl, bidderInfo) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. IMO it would be nice to bundle this along with the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
bidder := &bidderAdapter{ | ||
Bidder: bidderImpl, | ||
Bidder: ibidder, | ||
Client: server.Client(), | ||
DebugConfig: config.Debug{ | ||
TimeoutNotification: config.TimeoutNotification{ | ||
Log: true, | ||
Log: true, | ||
SamplingRate: 1.0, | ||
}, | ||
}, | ||
me: &metricsConfig.DummyMetricsEngine{}, | ||
} | ||
if tb, ok := bidder.Bidder.(adapters.TimeoutBidder); !ok { | ||
t.Error("Failed to cast bidder to a TimeoutBidder") | ||
var corebidder adapters.Bidder = bidder.Bidder | ||
if b, ok := corebidder.(*adapters.InfoAwareBidder); ok { | ||
corebidder = b.Bidder | ||
} | ||
if _, ok := corebidder.(adapters.TimeoutBidder); !ok { | ||
t.Fatal("Failed to cast bidder to a TimeoutBidder") | ||
SyntaxNode marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} else { | ||
bidder.doTimeoutNotification(tb, &adapters.RequestData{}) | ||
bidder.doRequestImpl(ctx, &bidRequest, mylogger) | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What if the logic inside There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It would not. The entire auction core is in our sights for a refactor soon. |
||
time.Sleep(300 * time.Millisecond) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We can probably lower this to around 210ms. |
||
expected := "TimeoutNotification: error:(context deadline exceeded) body:\n" | ||
actual := buf.String() | ||
assert.EqualValues(t, expected, actual) | ||
} | ||
|
||
type goodSingleBidder struct { | ||
|
@@ -1364,11 +1398,12 @@ func (bidder *bidRejector) MakeBids(internalRequest *openrtb.BidRequest, externa | |
} | ||
|
||
type notifingBidder struct { | ||
requests []*adapters.RequestData | ||
notiRequest adapters.RequestData | ||
} | ||
|
||
func (bidder *notifingBidder) MakeRequests(request *openrtb.BidRequest, reqInfo *adapters.ExtraRequestInfo) ([]*adapters.RequestData, []error) { | ||
return nil, nil | ||
return bidder.requests, nil | ||
} | ||
|
||
func (bidder *notifingBidder) MakeBids(internalRequest *openrtb.BidRequest, externalRequest *adapters.RequestData, response *adapters.ResponseData) (*adapters.BidderResponse, []error) { | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -1830,6 +1830,18 @@ func mockHandler(statusCode int, getBody string, postBody string) http.Handler { | |
}) | ||
} | ||
|
||
func mockSlowHandler(statusCode int, getBody string, postBody string) http.Handler { | ||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { | ||
time.Sleep(500 * time.Millisecond) | ||
w.WriteHeader(statusCode) | ||
if r.Method == "GET" { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't think the method type is important for the test. Consider accepting a single |
||
w.Write([]byte(getBody)) | ||
} else { | ||
w.Write([]byte(postBody)) | ||
} | ||
}) | ||
} | ||
|
||
type wellBehavedCache struct{} | ||
|
||
func (c *wellBehavedCache) GetExtCacheData() (string, string) { | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we need this extra function?
doRequest
is not part of the interface methods and its signature can be modified.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes. The purpose of
doRequest
is to inject the logger. There's cleaner ways of doing this, but it requires larger refactoring which we're punting on for this PR.