-
Notifications
You must be signed in to change notification settings - Fork 832
Remove invalid user EIDs and UIDs from bid request #3891
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
Changes from 1 commit
0f955e9
9352604
541cbed
22e6b21
db31c94
0f45f16
5514eae
74d9c26
5d56a61
5c45e53
4dcd6c9
675bd31
f6eea3c
ff59f36
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 |
---|---|---|
|
@@ -1296,8 +1296,14 @@ func (deps *endpointDeps) validateUser(req *openrtb_ext.RequestWrapper, aliases | |
// Check Universal User ID | ||
eids := userExt.GetEid() | ||
if eids != nil { | ||
eidsValue := *eids | ||
for eidIndex, eid := range eidsValue { | ||
|
||
validEids, eidErrors := validateEIDs(*eids) | ||
|
||
if len(eidErrors) > 0 { | ||
errL = append(errL, eidErrors...) | ||
} | ||
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. Likely fine to keep this logic here for now. We want to separate validation from fixing in the future. We can refactor this new logic along with the rest later. Thoughts @bsardo? |
||
|
||
for eidIndex, eid := range validEids { | ||
if eid.Source == "" { | ||
return append(errL, fmt.Errorf("request.user.ext.eids[%d] missing required field: \"source\"", eidIndex)) | ||
} | ||
|
@@ -1317,6 +1323,46 @@ func (deps *endpointDeps) validateUser(req *openrtb_ext.RequestWrapper, aliases | |
return errL | ||
} | ||
|
||
func validateEIDs(eids []openrtb2.EID) ([]openrtb2.EID, []error) { | ||
var errorsList []error | ||
validEIDs := make([]openrtb2.EID, 0, len(eids)) | ||
|
||
for _, eid := range eids { | ||
validUIDs, uidErrors := validateUIDs(eid.UIDs) | ||
errorsList = append(errorsList, uidErrors...) | ||
|
||
if len(validUIDs) > 0 { | ||
eid.UIDs = validUIDs | ||
validEIDs = append(validEIDs, eid) | ||
} else { | ||
errorsList = append(errorsList, &errortypes.Warning{ | ||
Message: fmt.Sprintf("Removed EID with empty UIDs (source: %s)", eid.Source), | ||
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. Please keep with the established error message format. Perhaps something like:
|
||
WarningCode: errortypes.InvalidUserEIDsWarningCode, | ||
}) | ||
} | ||
} | ||
|
||
return validEIDs, errorsList | ||
} | ||
|
||
func validateUIDs(uids []openrtb2.UID) ([]openrtb2.UID, []error) { | ||
var validUIDs []openrtb2.UID | ||
var uidErrors []error | ||
|
||
for _, uid := range uids { | ||
if uid.ID != "" { | ||
validUIDs = append(validUIDs, uid) | ||
} else { | ||
uidErrors = append(uidErrors, &errortypes.Warning{ | ||
Message: "Removed UID due to empty ID", | ||
WarningCode: errortypes.InvalidUserUIDsWarningCode, | ||
}) | ||
} | ||
} | ||
|
||
return validUIDs, uidErrors | ||
} | ||
|
||
func validateRegs(req *openrtb_ext.RequestWrapper, gpp gpplib.GppContainer) []error { | ||
var errL []error | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -5922,3 +5922,179 @@ func sortUserData(user *openrtb2.User) { | |
} | ||
} | ||
} | ||
func TestValidateEIDs(t *testing.T) { | ||
testCases := []struct { | ||
name string | ||
input []openrtb2.EID | ||
expected []openrtb2.EID | ||
numErrors int | ||
expectedErrorMessages []string | ||
}{ | ||
{ | ||
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. Please add the following test cases:
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. Added test cases for given scenarios |
||
name: "Valid EID with non-empty UID", | ||
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. Go test names cannot contain spaces so they are replaced with a dash character. This makes it hard to locate the failing test based on its name. Recommend using simpler test names like:
The parent test name is within scope so it's easy to locate in source. Please apply this guidance to other tests added in this PR. |
||
input: []openrtb2.EID{ | ||
{Source: "src1", UIDs: []openrtb2.UID{{ID: "id1"}}}, | ||
}, | ||
expected: []openrtb2.EID{ | ||
{Source: "src1", UIDs: []openrtb2.UID{{ID: "id1"}}}, | ||
}, | ||
numErrors: 0, | ||
expectedErrorMessages: nil, | ||
}, | ||
{ | ||
name: "EID with empty UID", | ||
input: []openrtb2.EID{ | ||
{Source: "src2", UIDs: []openrtb2.UID{{ID: ""}}}, | ||
}, | ||
expected: []openrtb2.EID{}, | ||
numErrors: 2, | ||
expectedErrorMessages: []string{ | ||
"Removed UID due to empty ID", | ||
"Removed EID with empty UIDs (source: src2)", | ||
}, | ||
}, | ||
{ | ||
name: "Multiple EIDs with some empty UIDs", | ||
input: []openrtb2.EID{ | ||
{Source: "src3", UIDs: []openrtb2.UID{{ID: "ID1"}, {ID: "ID2"}}}, | ||
{Source: "src4", UIDs: []openrtb2.UID{{ID: ""}, {ID: "ID1"}}}, | ||
{Source: "src5", UIDs: []openrtb2.UID{{ID: ""}, {ID: ""}}}, | ||
}, | ||
expected: []openrtb2.EID{ | ||
{Source: "src3", UIDs: []openrtb2.UID{{ID: "ID1"}, {ID: "ID2"}}}, | ||
{Source: "src4", UIDs: []openrtb2.UID{{ID: "ID1"}}}, | ||
}, | ||
numErrors: 4, | ||
expectedErrorMessages: []string{ | ||
"Removed UID due to empty ID", | ||
"Removed UID due to empty ID", | ||
"Removed UID due to empty ID", | ||
"Removed EID with empty UIDs (source: src5)", | ||
}, | ||
}, | ||
{ | ||
name: "All UIDs are empty", | ||
input: []openrtb2.EID{ | ||
{Source: "src6", UIDs: []openrtb2.UID{{ID: ""}, {ID: ""}}}, | ||
}, | ||
expected: []openrtb2.EID{}, | ||
numErrors: 3, | ||
expectedErrorMessages: []string{ | ||
"Removed UID due to empty ID", | ||
"Removed UID due to empty ID", | ||
"Removed EID with empty UIDs (source: src6)", | ||
}, | ||
}, | ||
} | ||
|
||
for _, tc := range testCases { | ||
t.Run(tc.name, func(t *testing.T) { | ||
validEIDs, errorsList := validateEIDs(tc.input) | ||
|
||
if len(validEIDs) != len(tc.expected) { | ||
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. Please use testify assert statements where possible. This can be written as follows which will compare the contents instead of just the array lengths, yielding more concrete tests.
|
||
t.Errorf("Expected %d valid EIDs, but got %d", len(tc.expected), len(validEIDs)) | ||
} | ||
|
||
if len(errorsList) != tc.numErrors { | ||
t.Errorf("Expected %d errors, but got %d", tc.numErrors, len(errorsList)) | ||
} | ||
|
||
// Assert error messages | ||
if tc.numErrors > 0 { | ||
var errorMessages []string | ||
for _, err := range errorsList { | ||
if warning, ok := err.(*errortypes.Warning); ok { | ||
errorMessages = append(errorMessages, warning.Message) | ||
} | ||
} | ||
|
||
for i, expectedMsg := range tc.expectedErrorMessages { | ||
if i >= len(errorMessages) { | ||
t.Errorf("Expected error message %q but got none", expectedMsg) | ||
} else if expectedMsg != errorMessages[i] { | ||
t.Errorf("Expected error message %q but got %q", expectedMsg, errorMessages[i]) | ||
} | ||
} | ||
} | ||
}) | ||
} | ||
} | ||
|
||
func TestValidateUIDs(t *testing.T) { | ||
testCases := []struct { | ||
name string | ||
input []openrtb2.UID | ||
expectedValidUIDs []openrtb2.UID | ||
expectedErrors []error | ||
}{ | ||
{ | ||
name: "All valid UIDs", | ||
input: []openrtb2.UID{ | ||
{ID: "id1"}, | ||
{ID: "id2"}, | ||
}, | ||
expectedValidUIDs: []openrtb2.UID{ | ||
{ID: "id1"}, | ||
{ID: "id2"}, | ||
}, | ||
expectedErrors: nil, | ||
}, | ||
{ | ||
name: "All empty UIDs", | ||
input: []openrtb2.UID{ | ||
{ID: ""}, | ||
{ID: ""}, | ||
}, | ||
expectedValidUIDs: nil, | ||
expectedErrors: []error{ | ||
&errortypes.Warning{ | ||
Message: "Removed UID due to empty ID", | ||
WarningCode: errortypes.InvalidUserUIDsWarningCode, | ||
}, | ||
&errortypes.Warning{ | ||
Message: "Removed UID due to empty ID", | ||
WarningCode: errortypes.InvalidUserUIDsWarningCode, | ||
}, | ||
}, | ||
}, | ||
{ | ||
name: "Mixed valid and empty UIDs", | ||
input: []openrtb2.UID{ | ||
{ID: "id1"}, | ||
{ID: ""}, | ||
{ID: "id2"}, | ||
{ID: ""}, | ||
}, | ||
expectedValidUIDs: []openrtb2.UID{ | ||
{ID: "id1"}, | ||
{ID: "id2"}, | ||
}, | ||
expectedErrors: []error{ | ||
&errortypes.Warning{ | ||
Message: "Removed UID due to empty ID", | ||
WarningCode: errortypes.InvalidUserUIDsWarningCode, | ||
}, | ||
&errortypes.Warning{ | ||
Message: "Removed UID due to empty ID", | ||
WarningCode: errortypes.InvalidUserUIDsWarningCode, | ||
}, | ||
}, | ||
}, | ||
{ | ||
name: "No UIDs", | ||
input: []openrtb2.UID{}, | ||
expectedValidUIDs: nil, | ||
expectedErrors: nil, | ||
}, | ||
} | ||
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. Please add a test case for a nil input. |
||
|
||
for _, tc := range testCases { | ||
t.Run(tc.name, func(t *testing.T) { | ||
validUIDs, errorsList := validateUIDs(tc.input) | ||
|
||
assert.ElementsMatch(t, tc.expectedValidUIDs, validUIDs, "Valid UIDs mismatch") | ||
|
||
assert.ElementsMatch(t, tc.expectedErrors, errorsList, "Errors mismatch") | ||
}) | ||
} | ||
} |
This file was deleted.
This file was deleted.
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -35,6 +35,8 @@ const ( | |
InvalidBidResponseDSAWarningCode | ||
SecCookieDeprecationLenWarningCode | ||
SecBrowsingTopicsWarningCode | ||
InvalidUserEIDsWarningCode | ||
InvalidUserUIDsWarningCode | ||
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. Do these new warning codes match with PBS-Java? We try to keep in sync. 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. Can you please help me to get those error codes. Do we have any document or PR to check new warning codes match with PBS-Java. 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. As per prebid-server-java/pull/3465, I understand that the same 999 warning code is being used when removing eids arrays. In the Prebid Server Go repository, 999 corresponds to UnknownErrorCode in the error codes reference. Are we intending to use UnknownErrorCode here as well? In this PR, I introduced InvalidUserEIDsWarningCode (10013) and InvalidUserUIDsWarningCode (10014). If we are okay with a generic error code, we could use UnknownErrorCode (999). However, please confirm whether we want separate error codes for InvalidUserEIDs and InvalidUserUIDs, or if using 999 would suffice. Kindly provide your input on this. 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. As discussed offline, it is ok to have these error codes. No change needed. |
||
) | ||
|
||
// Coder provides an error or warning code with severity. | ||
|
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.
Nitpick; Please remove the leading empty line.