Skip to content

Commit

Permalink
Update iOS version parsing for LMT tracking to accept major.minor.pat…
Browse files Browse the repository at this point in the history
…ch format as well (prebid#1978)
  • Loading branch information
mansinahar authored Aug 26, 2021
1 parent aa89ced commit e3590c3
Show file tree
Hide file tree
Showing 5 changed files with 155 additions and 16 deletions.
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ require (
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b
github.com/influxdata/influxdb v1.6.1
github.com/julienschmidt/httprouter v1.1.0
github.com/k0kubun/colorstring v0.0.0-20150214042306-9440f1994b88 // indirect
github.com/lib/pq v1.0.0
github.com/magiconair/properties v1.8.5
github.com/mattn/go-colorable v0.1.2 // indirect
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,8 @@ github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
github.com/julienschmidt/httprouter v1.1.0 h1:7wLdtIiIpzOkC9u6sXOozpBauPdskj3ru4EI5MABq68=
github.com/julienschmidt/httprouter v1.1.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
github.com/k0kubun/colorstring v0.0.0-20150214042306-9440f1994b88 h1:uC1QfSlInpQF+M0ao65imhwqKnz3Q2z/d8PWZRMQvDM=
github.com/k0kubun/colorstring v0.0.0-20150214042306-9440f1994b88/go.mod h1:3w7q1U84EfirKl04SVQ/s7nPm1ZPhiXd34z40TNz36k=
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg=
Expand Down
48 changes: 48 additions & 0 deletions privacy/lmt/ios_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,54 @@ func TestModifyForIOS(t *testing.T) {
},
expectedLMT: openrtb2.Int8Ptr(1),
},
{
description: "14.1",
givenRequest: &openrtb2.BidRequest{
App: &openrtb2.App{},
Device: &openrtb2.Device{OS: "iOS", OSV: "14.1", IFA: "", Lmt: nil},
},
expectedLMT: openrtb2.Int8Ptr(1),
},
{
description: "14.1.3",
givenRequest: &openrtb2.BidRequest{
App: &openrtb2.App{},
Device: &openrtb2.Device{OS: "iOS", OSV: "14.1.3", IFA: "", Lmt: nil},
},
expectedLMT: openrtb2.Int8Ptr(1),
},
{
description: "14.2",
givenRequest: &openrtb2.BidRequest{
App: &openrtb2.App{},
Device: &openrtb2.Device{Ext: json.RawMessage(`{"atts":0}`), OS: "iOS", OSV: "14.2", IFA: "", Lmt: nil},
},
expectedLMT: openrtb2.Int8Ptr(0),
},
{
description: "14.2",
givenRequest: &openrtb2.BidRequest{
App: &openrtb2.App{},
Device: &openrtb2.Device{Ext: json.RawMessage(`{"atts":2}`), OS: "iOS", OSV: "14.2", IFA: "", Lmt: openrtb2.Int8Ptr(0)},
},
expectedLMT: openrtb2.Int8Ptr(1),
},
{
description: "14.2.7",
givenRequest: &openrtb2.BidRequest{
App: &openrtb2.App{},
Device: &openrtb2.Device{Ext: json.RawMessage(`{"atts":1}`), OS: "iOS", OSV: "14.2.7", IFA: "", Lmt: nil},
},
expectedLMT: openrtb2.Int8Ptr(1),
},
{
description: "14.2.7",
givenRequest: &openrtb2.BidRequest{
App: &openrtb2.App{},
Device: &openrtb2.Device{Ext: json.RawMessage(`{"atts":3}`), OS: "iOS", OSV: "14.2.7", IFA: "", Lmt: openrtb2.Int8Ptr(1)},
},
expectedLMT: openrtb2.Int8Ptr(0),
},
}

for _, test := range testCases {
Expand Down
28 changes: 17 additions & 11 deletions util/iosutil/iosutil.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ type Version struct {
func ParseVersion(v string) (Version, error) {
parts := strings.Split(v, ".")

if len(parts) != 2 {
return Version{}, errors.New("expected major.minor format")
if len(parts) < 2 || len(parts) > 3 {
return Version{}, errors.New("expected either major.minor or major.minor.patch format")
}

major, err := strconv.Atoi(parts[0])
Expand All @@ -37,6 +37,15 @@ func ParseVersion(v string) (Version, error) {
return version, nil
}

// Equal returns true if the iOS device version is equal to the desired major and minor version, using semantic versioning.
func (v Version) Equal(major, minor int) bool {
if v.Major == major {
return v.Minor == minor
}

return false
}

// EqualOrGreater returns true if the iOS device version is equal or greater to the desired version, using semantic versioning.
func (v Version) EqualOrGreater(major, minor int) bool {
if v.Major == major {
Expand All @@ -59,20 +68,17 @@ const (

// DetectVersionClassification detects the iOS version classification.
func DetectVersionClassification(v string) VersionClassification {
// exact comparisons first. no parsing required.
if v == "14.0" {
return Version140
}
if v == "14.1" {
return Version141
}

// semantic versioning comparison second. parsing required.
if iosVersion, err := ParseVersion(v); err == nil {
if iosVersion.Equal(14, 0) {
return Version140
}
if iosVersion.Equal(14, 1) {
return Version141
}
if iosVersion.EqualOrGreater(14, 2) {
return Version142OrGreater
}
}

return VersionUnknown
}
92 changes: 87 additions & 5 deletions util/iosutil/iosutil_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,24 +14,34 @@ func TestParseVersion(t *testing.T) {
expectedError string
}{
{
description: "Valid",
description: "Valid - major.minor format",
given: "14.2",
expectedVersion: Version{Major: 14, Minor: 2},
},
{
description: "Valid - major.minor.patch format",
given: "14.2.1",
expectedVersion: Version{Major: 14, Minor: 2},
},
{
description: "Invalid Parts - Empty",
given: "",
expectedError: "expected major.minor format",
expectedError: "expected either major.minor or major.minor.patch format",
},
{
description: "Invalid Parts - Too Few",
given: "14",
expectedError: "expected major.minor format",
expectedError: "expected either major.minor or major.minor.patch format",
},
{
description: "Invalid Parts - Too Many",
given: "14.2.1",
expectedError: "expected major.minor format",
given: "14.2.1.3",
expectedError: "expected either major.minor or major.minor.patch format",
},
{
description: "Invalid Parts - Too Few",
given: "14",
expectedError: "expected either major.minor or major.minor.patch format",
},
{
description: "Invalid Major",
Expand Down Expand Up @@ -110,6 +120,58 @@ func TestEqualOrGreater(t *testing.T) {
}
}

func TestEqual(t *testing.T) {
givenMajor := 14
givenMinor := 2

tests := []struct {
description string
givenVersion Version
expected bool
}{
{
description: "Less Than By Major + Minor",
givenVersion: Version{Major: 13, Minor: 1},
expected: false,
},
{
description: "Less Than By Major",
givenVersion: Version{Major: 13, Minor: 2},
expected: false,
},
{
description: "Less Than By Minor",
givenVersion: Version{Major: 14, Minor: 1},
expected: false,
},
{
description: "Equal",
givenVersion: Version{Major: 14, Minor: 2},
expected: true,
},
{
description: "Greater By Major + Minor",
givenVersion: Version{Major: 15, Minor: 3},
expected: false,
},
{
description: "Greater By Major",
givenVersion: Version{Major: 15, Minor: 2},
expected: false,
},
{
description: "Greater By Minor",
givenVersion: Version{Major: 14, Minor: 3},
expected: false,
},
}

for _, test := range tests {
result := test.givenVersion.Equal(givenMajor, givenMinor)
assert.Equal(t, test.expected, result, test.description)
}
}

func TestDetectVersionClassification(t *testing.T) {

tests := []struct {
Expand All @@ -124,22 +186,42 @@ func TestDetectVersionClassification(t *testing.T) {
given: "14.0",
expected: Version140,
},
{
given: "14.0.1",
expected: Version140,
},
{
given: "14.1",
expected: Version141,
},
{
given: "14.1.2",
expected: Version141,
},
{
given: "14.2",
expected: Version142OrGreater,
},
{
given: "14.2.3",
expected: Version142OrGreater,
},
{
given: "14.3",
expected: Version142OrGreater,
},
{
given: "14.3.2",
expected: Version142OrGreater,
},
{
given: "15.0",
expected: Version142OrGreater,
},
{
given: "15.0.1",
expected: Version142OrGreater,
},
}

for _, test := range tests {
Expand Down

0 comments on commit e3590c3

Please sign in to comment.