github.com/prebid/prebid-server/v2@v2.18.0/privacy/lmt/ios_test.go (about) 1 package lmt 2 3 import ( 4 "encoding/json" 5 "testing" 6 7 "github.com/prebid/openrtb/v20/openrtb2" 8 "github.com/prebid/prebid-server/v2/util/iosutil" 9 "github.com/stretchr/testify/assert" 10 ) 11 12 // TestModifyForIOS is a simple spot check end-to-end test for the integration of all functional components. 13 func TestModifyForIOS(t *testing.T) { 14 testCases := []struct { 15 description string 16 givenRequest *openrtb2.BidRequest 17 expectedLMT *int8 18 }{ 19 { 20 description: "13.0", 21 givenRequest: &openrtb2.BidRequest{ 22 App: &openrtb2.App{}, 23 Device: &openrtb2.Device{OS: "iOS", OSV: "13.0", IFA: "", Lmt: nil}, 24 }, 25 expectedLMT: nil, 26 }, 27 { 28 description: "14.0", 29 givenRequest: &openrtb2.BidRequest{ 30 App: &openrtb2.App{}, 31 Device: &openrtb2.Device{OS: "iOS", OSV: "14.0", IFA: "", Lmt: nil}, 32 }, 33 expectedLMT: openrtb2.Int8Ptr(1), 34 }, 35 { 36 description: "14.1", 37 givenRequest: &openrtb2.BidRequest{ 38 App: &openrtb2.App{}, 39 Device: &openrtb2.Device{OS: "iOS", OSV: "14.1", IFA: "", Lmt: nil}, 40 }, 41 expectedLMT: openrtb2.Int8Ptr(1), 42 }, 43 { 44 description: "14.1.3", 45 givenRequest: &openrtb2.BidRequest{ 46 App: &openrtb2.App{}, 47 Device: &openrtb2.Device{OS: "iOS", OSV: "14.1.3", IFA: "", Lmt: nil}, 48 }, 49 expectedLMT: openrtb2.Int8Ptr(1), 50 }, 51 { 52 description: "14.2", 53 givenRequest: &openrtb2.BidRequest{ 54 App: &openrtb2.App{}, 55 Device: &openrtb2.Device{Ext: json.RawMessage(`{"atts":0}`), OS: "iOS", OSV: "14.2", IFA: "", Lmt: nil}, 56 }, 57 expectedLMT: openrtb2.Int8Ptr(1), 58 }, 59 { 60 description: "14.2", 61 givenRequest: &openrtb2.BidRequest{ 62 App: &openrtb2.App{}, 63 Device: &openrtb2.Device{Ext: json.RawMessage(`{"atts":2}`), OS: "iOS", OSV: "14.2", IFA: "", Lmt: openrtb2.Int8Ptr(0)}, 64 }, 65 expectedLMT: openrtb2.Int8Ptr(1), 66 }, 67 { 68 description: "14.2.7", 69 givenRequest: &openrtb2.BidRequest{ 70 App: &openrtb2.App{}, 71 Device: &openrtb2.Device{Ext: json.RawMessage(`{"atts":1}`), OS: "iOS", OSV: "14.2.7", IFA: "", Lmt: nil}, 72 }, 73 expectedLMT: openrtb2.Int8Ptr(1), 74 }, 75 { 76 description: "14.2.7", 77 givenRequest: &openrtb2.BidRequest{ 78 App: &openrtb2.App{}, 79 Device: &openrtb2.Device{Ext: json.RawMessage(`{"atts":3}`), OS: "iOS", OSV: "14.2.7", IFA: "", Lmt: openrtb2.Int8Ptr(1)}, 80 }, 81 expectedLMT: openrtb2.Int8Ptr(0), 82 }, 83 } 84 85 for _, test := range testCases { 86 ModifyForIOS(test.givenRequest) 87 assert.Equal(t, test.expectedLMT, test.givenRequest.Device.Lmt, test.description) 88 } 89 } 90 91 func TestModifyForIOSHelper(t *testing.T) { 92 testCases := []struct { 93 description string 94 givenRequest *openrtb2.BidRequest 95 expectedModifier140Called bool 96 expectedModifier142Called bool 97 }{ 98 { 99 description: "Valid 14.0", 100 givenRequest: &openrtb2.BidRequest{ 101 App: &openrtb2.App{}, 102 Device: &openrtb2.Device{OS: "iOS", OSV: "14.0"}, 103 }, 104 expectedModifier140Called: true, 105 expectedModifier142Called: false, 106 }, 107 { 108 description: "Valid 14.2 Or Greater", 109 givenRequest: &openrtb2.BidRequest{ 110 App: &openrtb2.App{}, 111 Device: &openrtb2.Device{OS: "iOS", OSV: "14.2"}, 112 }, 113 expectedModifier140Called: false, 114 expectedModifier142Called: true, 115 }, 116 { 117 description: "Invalid Version", 118 givenRequest: &openrtb2.BidRequest{ 119 App: &openrtb2.App{}, 120 Device: &openrtb2.Device{OS: "iOS", OSV: "invalid"}, 121 }, 122 expectedModifier140Called: false, 123 expectedModifier142Called: false, 124 }, 125 { 126 description: "Invalid OS", 127 givenRequest: &openrtb2.BidRequest{ 128 App: &openrtb2.App{}, 129 Device: &openrtb2.Device{OS: "invalid", OSV: "14.0"}, 130 }, 131 expectedModifier140Called: false, 132 expectedModifier142Called: false, 133 }, 134 { 135 description: "Invalid Nil Device", 136 givenRequest: &openrtb2.BidRequest{ 137 App: &openrtb2.App{}, 138 Device: nil, 139 }, 140 expectedModifier140Called: false, 141 expectedModifier142Called: false, 142 }, 143 } 144 145 for _, test := range testCases { 146 modifierIOS140Called := false 147 modifierIOS140 := func(req *openrtb2.BidRequest) { modifierIOS140Called = true } 148 149 modifierIOS142Called := false 150 modifierIOS142 := func(req *openrtb2.BidRequest) { modifierIOS142Called = true } 151 152 modifiers := map[iosutil.VersionClassification]modifier{ 153 iosutil.Version140: modifierIOS140, 154 iosutil.Version142OrGreater: modifierIOS142, 155 } 156 157 modifyForIOS(test.givenRequest, modifiers) 158 159 assert.Equal(t, test.expectedModifier140Called, modifierIOS140Called, test.description) 160 assert.Equal(t, test.expectedModifier142Called, modifierIOS142Called, test.description) 161 } 162 } 163 164 func TestIsRequestForIOS(t *testing.T) { 165 testCases := []struct { 166 description string 167 givenRequest *openrtb2.BidRequest 168 expected bool 169 }{ 170 { 171 description: "Valid", 172 givenRequest: &openrtb2.BidRequest{ 173 App: &openrtb2.App{}, 174 Device: &openrtb2.Device{OS: "iOS"}, 175 }, 176 expected: true, 177 }, 178 { 179 description: "Valid - OS Case Insensitive", 180 givenRequest: &openrtb2.BidRequest{ 181 App: &openrtb2.App{}, 182 Device: &openrtb2.Device{OS: "IOS"}, 183 }, 184 expected: true, 185 }, 186 { 187 description: "Invalid - Nil Request", 188 givenRequest: nil, 189 expected: false, 190 }, 191 { 192 description: "Invalid - Nil App", 193 givenRequest: &openrtb2.BidRequest{ 194 App: nil, 195 Device: &openrtb2.Device{OS: "iOS"}, 196 }, 197 expected: false, 198 }, 199 { 200 description: "Invalid - Nil Device", 201 givenRequest: &openrtb2.BidRequest{ 202 App: &openrtb2.App{}, 203 Device: nil, 204 }, 205 expected: false, 206 }, 207 { 208 description: "Invalid - Empty OS", 209 givenRequest: &openrtb2.BidRequest{ 210 App: &openrtb2.App{}, 211 Device: &openrtb2.Device{OS: ""}, 212 }, 213 expected: false, 214 }, 215 { 216 description: "Invalid - Wrong OS", 217 givenRequest: &openrtb2.BidRequest{ 218 App: &openrtb2.App{}, 219 Device: &openrtb2.Device{OS: "Android"}, 220 }, 221 expected: false, 222 }, 223 } 224 225 for _, test := range testCases { 226 result := isRequestForIOS(test.givenRequest) 227 assert.Equal(t, test.expected, result, test.description) 228 } 229 } 230 231 func TestModifyForIOS14X(t *testing.T) { 232 testCases := []struct { 233 description string 234 givenDevice openrtb2.Device 235 expectedLMT *int8 236 }{ 237 { 238 description: "IFA Empty", 239 givenDevice: openrtb2.Device{IFA: "", Lmt: nil}, 240 expectedLMT: openrtb2.Int8Ptr(1), 241 }, 242 { 243 description: "IFA Zero UUID", 244 givenDevice: openrtb2.Device{IFA: "00000000-0000-0000-0000-000000000000", Lmt: nil}, 245 expectedLMT: openrtb2.Int8Ptr(1), 246 }, 247 { 248 description: "IFA Populated", 249 givenDevice: openrtb2.Device{IFA: "any-real-value", Lmt: nil}, 250 expectedLMT: openrtb2.Int8Ptr(0), 251 }, 252 { 253 description: "Overwrites Existing", 254 givenDevice: openrtb2.Device{IFA: "", Lmt: openrtb2.Int8Ptr(0)}, 255 expectedLMT: openrtb2.Int8Ptr(1), 256 }, 257 } 258 259 for _, test := range testCases { 260 request := &openrtb2.BidRequest{Device: &test.givenDevice} 261 modifyForIOS14X(request) 262 assert.Equal(t, test.expectedLMT, request.Device.Lmt, test.description) 263 } 264 } 265 266 func TestModifyForIOS142OrGreater(t *testing.T) { 267 testCases := []struct { 268 description string 269 givenDevice openrtb2.Device 270 expectedLMT *int8 271 }{ 272 { 273 description: "Not Determined", 274 givenDevice: openrtb2.Device{Ext: json.RawMessage(`{"atts":0}`), Lmt: nil}, 275 expectedLMT: openrtb2.Int8Ptr(1), 276 }, 277 { 278 description: "Restricted", 279 givenDevice: openrtb2.Device{Ext: json.RawMessage(`{"atts":1}`), Lmt: nil}, 280 expectedLMT: openrtb2.Int8Ptr(1), 281 }, 282 { 283 description: "Denied", 284 givenDevice: openrtb2.Device{Ext: json.RawMessage(`{"atts":2}`), Lmt: nil}, 285 expectedLMT: openrtb2.Int8Ptr(1), 286 }, 287 { 288 description: "Authorized", 289 givenDevice: openrtb2.Device{Ext: json.RawMessage(`{"atts":3}`), Lmt: nil}, 290 expectedLMT: openrtb2.Int8Ptr(0), 291 }, 292 { 293 description: "Overwrites Existing", 294 givenDevice: openrtb2.Device{Ext: json.RawMessage(`{"atts":3}`), Lmt: openrtb2.Int8Ptr(1)}, 295 expectedLMT: openrtb2.Int8Ptr(0), 296 }, 297 { 298 description: "Invalid Value - Unknown", 299 givenDevice: openrtb2.Device{Ext: json.RawMessage(`{"atts":4}`), Lmt: nil}, 300 expectedLMT: nil, 301 }, 302 { 303 description: "Invalid Value - Unknown - Does Not Overwrite Existing", 304 givenDevice: openrtb2.Device{Ext: json.RawMessage(`{"atts":4}`), Lmt: openrtb2.Int8Ptr(1)}, 305 expectedLMT: openrtb2.Int8Ptr(1), 306 }, 307 { 308 description: "Invalid Value - Missing", 309 givenDevice: openrtb2.Device{Ext: json.RawMessage(`{}`), Lmt: nil}, 310 expectedLMT: nil, 311 }, 312 { 313 description: "Invalid Value - Wrong Type", 314 givenDevice: openrtb2.Device{Ext: json.RawMessage(`{"atts":"wrong type"}`), Lmt: nil}, 315 expectedLMT: nil, 316 }, 317 } 318 319 for _, test := range testCases { 320 request := &openrtb2.BidRequest{Device: &test.givenDevice} 321 modifyForIOS142OrGreater(request) 322 assert.Equal(t, test.expectedLMT, request.Device.Lmt, test.description) 323 } 324 }