From 6aab8bebea40f9ced7cd865046cd33c4e54941d7 Mon Sep 17 00:00:00 2001 From: Sylvia Liu Date: Fri, 16 Jun 2023 18:21:13 -0400 Subject: [PATCH] header padding, CA TCF support --- gpp_parsed_consent.go | 8 ++- gpp_parsed_consent_test.go | 24 +++++++ mspa_parsed_consent_fixture_test.go | 93 ++++++++++++++++--------- mspa_sections.go | 12 ++-- parse.go | 58 +++++++++++++++- v2_parsed_consent.go | 74 ++++++++++++++++++++ v2_parsed_consent_fixture_test.go | 103 ++++++++++++++++++++++++++++ v2_parsed_consent_test.go | 11 +++ 8 files changed, 340 insertions(+), 43 deletions(-) diff --git a/gpp_parsed_consent.go b/gpp_parsed_consent.go index 9932c59..cd93951 100644 --- a/gpp_parsed_consent.go +++ b/gpp_parsed_consent.go @@ -78,7 +78,13 @@ func ParseGppHeader(s string) (*GppHeader, error) { // IAB's base64 conversion means a 6 bit grouped value can be converted to 8 bit bytes. // Any leftover bits <8 would be skipped in normal base64 decoding. // Therefore, pad with 6 '0's w/ `A` to ensure that all bits are decoded into bytes. - var b, err = base64.RawURLEncoding.DecodeString(s + "A") + + gap := 3 - len(s)%4 + if gap != 0 { + s += strings.Repeat("A", gap) + } + + var b, err = base64.RawURLEncoding.DecodeString(s) if err != nil { return nil, errors.Wrap(err, "parse gpp header consent string") } diff --git a/gpp_parsed_consent_test.go b/gpp_parsed_consent_test.go index 18a4c26..cb8ed5f 100644 --- a/gpp_parsed_consent_test.go +++ b/gpp_parsed_consent_test.go @@ -69,6 +69,30 @@ func (s *GppParseSuite) TestParseGppHeader(c *check.C) { Version: 1, Sections: []int{8}}, }, + { + header: "DBABBgAA", + expected: &iabconsent.GppHeader{ + Type: 3, + Version: 1, + Sections: []int{8}, + }, + }, + { + header: "DBABzYA", + expected: &iabconsent.GppHeader{ + Type: 3, + Version: 1, + Sections: []int{6, 7, 8}, + }, + }, + { + header: "DBACOaw", + expected: &iabconsent.GppHeader{ + Type: 3, + Version: 1, + Sections: []int{2, 5, 6, 7, 8, 9, 10, 11, 12}, + }, + }, } for _, tc := range tcs { diff --git a/mspa_parsed_consent_fixture_test.go b/mspa_parsed_consent_fixture_test.go index c942835..08d66cc 100644 --- a/mspa_parsed_consent_fixture_test.go +++ b/mspa_parsed_consent_fixture_test.go @@ -172,11 +172,67 @@ var usVAConsentFixtures = map[string]*iabconsent.MspaParsedConsent{ } var usCAConsentFixtures = map[string]*iabconsent.MspaParsedConsent{ - "BVoAAACQ.QA": { + //"BVoAAACQ.QA": { + // Version: 1, + // SaleOptOutNotice: iabconsent.NoticeProvided, + // SharingOptOutNotice: iabconsent.NoticeProvided, + // SensitiveDataLimitUseNotice: iabconsent.NoticeProvided, + // SaleOptOut: iabconsent.NotOptedOut, + // SharingOptOut: iabconsent.NotOptedOut, + // SensitiveDataProcessing: map[int]iabconsent.MspaConsent{ + // 0: iabconsent.ConsentNotApplicable, + // 1: iabconsent.ConsentNotApplicable, + // 2: iabconsent.ConsentNotApplicable, + // 3: iabconsent.ConsentNotApplicable, + // 4: iabconsent.ConsentNotApplicable, + // 5: iabconsent.ConsentNotApplicable, + // 6: iabconsent.ConsentNotApplicable, + // 7: iabconsent.ConsentNotApplicable, + // 8: iabconsent.ConsentNotApplicable, + // }, + // KnownChildSensitiveDataConsents: map[int]iabconsent.MspaConsent{ + // 0: iabconsent.ConsentNotApplicable, + // 1: iabconsent.ConsentNotApplicable, + // }, + // PersonalDataConsents: iabconsent.ConsentNotApplicable, + // MspaCoveredTransaction: iabconsent.MspaNo, + // MspaOptOutOptionMode: iabconsent.MspaYes, + // MspaServiceProviderMode: iabconsent.MspaNotApplicable, + // + // Gpc: false, + //}, + //"BVoBAARQ.QA": { + // Version: 1, + // SaleOptOutNotice: iabconsent.NoticeProvided, + // SharingOptOutNotice: iabconsent.NoticeProvided, + // SensitiveDataLimitUseNotice: iabconsent.NoticeProvided, + // SaleOptOut: iabconsent.NotOptedOut, + // SharingOptOut: iabconsent.NotOptedOut, + // SensitiveDataProcessing: map[int]iabconsent.MspaConsent{ + // 0: iabconsent.ConsentNotApplicable, + // 1: iabconsent.ConsentNotApplicable, + // 2: iabconsent.ConsentNotApplicable, + // 3: iabconsent.NoConsent, + // 4: iabconsent.ConsentNotApplicable, + // 5: iabconsent.ConsentNotApplicable, + // 6: iabconsent.ConsentNotApplicable, + // 7: iabconsent.ConsentNotApplicable, + // 8: iabconsent.ConsentNotApplicable, + // }, + // KnownChildSensitiveDataConsents: map[int]iabconsent.MspaConsent{ + // 0: iabconsent.ConsentNotApplicable, + // 1: iabconsent.NoConsent, + // }, + // PersonalDataConsents: iabconsent.ConsentNotApplicable, + // MspaCoveredTransaction: iabconsent.MspaYes, + // MspaOptOutOptionMode: iabconsent.MspaYes, + // MspaServiceProviderMode: iabconsent.MspaNotApplicable, + //}, + "BUoAAAAA": { Version: 1, SaleOptOutNotice: iabconsent.NoticeProvided, SharingOptOutNotice: iabconsent.NoticeProvided, - SensitiveDataLimitUseNotice: iabconsent.NoticeProvided, + SensitiveDataLimitUseNotice: iabconsent.NoticeNotApplicable, SaleOptOut: iabconsent.NotOptedOut, SharingOptOut: iabconsent.NotOptedOut, SensitiveDataProcessing: map[int]iabconsent.MspaConsent{ @@ -195,37 +251,8 @@ var usCAConsentFixtures = map[string]*iabconsent.MspaParsedConsent{ 1: iabconsent.ConsentNotApplicable, }, PersonalDataConsents: iabconsent.ConsentNotApplicable, - MspaCoveredTransaction: iabconsent.MspaNo, - MspaOptOutOptionMode: iabconsent.MspaYes, - MspaServiceProviderMode: iabconsent.MspaNotApplicable, - - Gpc: false, - }, - "BVoBAARQ.QA": { - Version: 1, - SaleOptOutNotice: iabconsent.NoticeProvided, - SharingOptOutNotice: iabconsent.NoticeProvided, - SensitiveDataLimitUseNotice: iabconsent.NoticeProvided, - SaleOptOut: 2, - SharingOptOut: 2, - SensitiveDataProcessing: map[int]iabconsent.MspaConsent{ - 0: iabconsent.ConsentNotApplicable, - 1: iabconsent.ConsentNotApplicable, - 2: iabconsent.ConsentNotApplicable, - 3: iabconsent.NoConsent, - 4: iabconsent.ConsentNotApplicable, - 5: iabconsent.ConsentNotApplicable, - 6: iabconsent.ConsentNotApplicable, - 7: iabconsent.ConsentNotApplicable, - 8: iabconsent.ConsentNotApplicable, - }, - KnownChildSensitiveDataConsents: map[int]iabconsent.MspaConsent{ - 0: iabconsent.ConsentNotApplicable, - 1: iabconsent.NoConsent, - }, - PersonalDataConsents: iabconsent.ConsentNotApplicable, - MspaCoveredTransaction: iabconsent.MspaYes, - MspaOptOutOptionMode: iabconsent.MspaYes, + MspaCoveredTransaction: iabconsent.MspaNotApplicable, + MspaOptOutOptionMode: iabconsent.MspaNotApplicable, MspaServiceProviderMode: iabconsent.MspaNotApplicable, }, } diff --git a/mspa_sections.go b/mspa_sections.go index 7183815..33b9f54 100644 --- a/mspa_sections.go +++ b/mspa_sections.go @@ -97,12 +97,11 @@ func (t *TCFEU) ParseConsent() (GppParsedConsent, error) { } func (t *TCFCA) ParseConsent() (GppParsedConsent, error) { - return ParseV2(t.sectionValue) + return ParseCAV2(t.sectionValue) } func (u *USPV) ParseConsent() (GppParsedConsent, error) { return ParseCCPA(u.sectionValue) - } func (m *MspaUsNational) ParseConsent() (GppParsedConsent, error) { @@ -201,7 +200,7 @@ func (m *MspaUsCO) ParseConsent() (GppParsedConsent, error) { var b, err = base64.RawURLEncoding.DecodeString(segments[0]) if err != nil { - return nil, errors.Wrap(err, "parse usva consent string") + return nil, errors.Wrap(err, "parse usco consent string") } var r = NewConsentReader(b) @@ -241,7 +240,7 @@ func (m *MspaUsUT) ParseConsent() (GppParsedConsent, error) { var b, err = base64.RawURLEncoding.DecodeString(segments[0]) if err != nil { - return nil, errors.Wrap(err, "parse usva consent string") + return nil, errors.Wrap(err, "parse usut consent string") } var r = NewConsentReader(b) @@ -281,7 +280,7 @@ func (m *MspaUsCT) ParseConsent() (GppParsedConsent, error) { var b, err = base64.RawURLEncoding.DecodeString(segments[0]) if err != nil { - return nil, errors.Wrap(err, "parse usva consent string") + return nil, errors.Wrap(err, "parse usct consent string") } var r = NewConsentReader(b) @@ -321,8 +320,9 @@ func (m *MspaUsCA) ParseConsent() (GppParsedConsent, error) { var segments = strings.Split(m.sectionValue, ".") var b, err = base64.RawURLEncoding.DecodeString(segments[0]) + if err != nil { - return nil, errors.Wrap(err, "parse usva consent string") + return nil, errors.Wrap(err, "parse usca consent string") } var r = NewConsentReader(b) diff --git a/parse.go b/parse.go index 529e498..4acba1c 100644 --- a/parse.go +++ b/parse.go @@ -339,7 +339,7 @@ func (r *ConsentReader) ReadPublisherTCEntry() (*PublisherTCEntry, error) { // // Example Usage: // -// var pc, err = iabconsent.Parse("BONJ5bvONJ5bvAMAPyFRAL7AAAAMhuqKklS-gAAAAAAAAAAAAAAAAAAAAAAAAAA") +// var pc, err = iabconsent.Parse("BONJ5bvONJ5bvAMAPyFRAL7AAAAMhuqKklS-gAAAAAAAAAAAAAAAAAAAAAAAAAA") // // Deprecated: Use ParseV1 to parse V1 consent strings. func Parse(s string) (*ParsedConsent, error) { @@ -352,7 +352,7 @@ func Parse(s string) (*ParsedConsent, error) { // // Example Usage: // -// var pc, err = iabconsent.ParseV1("BONJ5bvONJ5bvAMAPyFRAL7AAAAMhuqKklS-gAAAAAAAAAAAAAAAAAAAAAAAAAA") +// var pc, err = iabconsent.ParseV1("BONJ5bvONJ5bvAMAPyFRAL7AAAAMhuqKklS-gAAAAAAAAAAAAAAAAAAAAAAAAAA") func ParseV1(s string) (*ParsedConsent, error) { var b, err = base64.RawURLEncoding.DecodeString(s) if err != nil { @@ -395,7 +395,7 @@ func ParseV1(s string) (*ParsedConsent, error) { // // Example Usage: // -// var pc, err = iabconsent.ParseV2("COvzTO5OvzTO5BRAAAENAPCoALIAADgAAAAAAewAwABAAlAB6ABBFAAA") +// var pc, err = iabconsent.ParseV2("COvzTO5OvzTO5BRAAAENAPCoALIAADgAAAAAAewAwABAAlAB6ABBFAAA") func ParseV2(s string) (*V2ParsedConsent, error) { var segments = strings.Split(s, ".") @@ -484,6 +484,58 @@ func ParseV2(s string) (*V2ParsedConsent, error) { return p, r.Err } +func ParseCAV2(s string) (*V2CAParsedConsent, error) { + var segments = strings.Split(s, ".") + + var b, err = base64.RawURLEncoding.DecodeString(segments[0]) + if err != nil { + return nil, errors.Wrap(err, "parse v2 consent string") + } + + var r = NewConsentReader(b) + + // This block of code directly describes the format of the payload. + // The spec for the consent string can be found here: + // https://github.com/InteractiveAdvertisingBureau/GDPR-Transparency-and-Consent-Framework/blob/47b45ab362515310183bb3572a367b8391ef4613/TCFv2/IAB%20Tech%20Lab%20-%20Consent%20string%20and%20vendor%20list%20formats%20v2.md#about-the-transparency--consent-string-tc-string + var p = &V2CAParsedConsent{} + p.Version, _ = r.ReadInt(6) + if p.Version != int(V2) { + return nil, errors.New("non-v2 string passed to v2 parse method") + } + p.Created, _ = r.ReadTime() + p.LastUpdated, _ = r.ReadTime() + p.CMPID, _ = r.ReadInt(12) + p.CMPVersion, _ = r.ReadInt(12) + p.ConsentScreen, _ = r.ReadInt(6) + p.ConsentLanguage, _ = r.ReadString(2) + p.VendorListVersion, _ = r.ReadInt(12) + p.TCFPolicyVersion, _ = r.ReadInt(6) + p.UseNonStandardStacks, _ = r.ReadBool() + p.SpecialFeatureExpressConsent, _ = r.ReadBitField(12) + p.PurposesExpressConsent, _ = r.ReadBitField(24) + p.PurposesImpliedConsent, _ = r.ReadBitField(24) + + p.MaxExpressConsentVendorID, _ = r.ReadInt(16) + p.IsExpressConsentRangeEncoding, _ = r.ReadBool() + if p.IsExpressConsentRangeEncoding { + p.NumExpressConsentEntries, _ = r.ReadInt(12) + p.VendorExpressConsent, _ = r.ReadRangeEntries(uint(p.NumExpressConsentEntries)) + } else { + p.ExpressConsentedVendors, _ = r.ReadBitField(uint(p.MaxExpressConsentVendorID)) + } + + p.MaxImpliedConsentVendorID, _ = r.ReadInt(16) + p.IsImpliedConsentRangeEncoding, _ = r.ReadBool() + if p.IsImpliedConsentRangeEncoding { + p.NumImpliedConsentEntries, _ = r.ReadInt(12) + p.VendorImpliedConsent, _ = r.ReadRangeEntries(uint(p.NumImpliedConsentEntries)) + } else { + p.ImpliedConsentedVendors, _ = r.ReadBitField(uint(p.MaxImpliedConsentVendorID)) + } + + return p, r.Err +} + // TCFVersion is an enum type used for easily identifying which version // a consent string is. type TCFVersion int diff --git a/v2_parsed_consent.go b/v2_parsed_consent.go index 17cca34..7b40a9f 100644 --- a/v2_parsed_consent.go +++ b/v2_parsed_consent.go @@ -122,6 +122,80 @@ type V2ParsedConsent struct { *PublisherTCEntry } +// V2CAParsedConsent represents data extracted from an v2 CA TCF Consent String. +type V2CAParsedConsent struct { + // Version number of the encoding format. + Version int + // Epoch deciseconds when this TC String was first created (should not be changed + // unless a new TCString is created from scratch). + Created time.Time + // Epoch deciseconds when TC String was last updated (Must be updated any time a + // value is changed). + LastUpdated time.Time + // Consent Management Platform ID that last updated the TC String. + // A unique ID will be assigned to each Consent Management Platform. + CMPID int + // Consent Management Platform version of the CMP that last updated this TC String. + // Each change to a CMP should increment their internally assigned version number as + // a record of which version the user gave consent and transparency was established. + CMPVersion int + // CMP Screen number at which consent was given for a user with the CMP that last + // updated this TC String. The number is a CMP internal designation and is CMPVersion + // specific. The number is used for identifying on which screen a user gave consent + // as a record. + ConsentScreen int + // Two-letter ISO 639-1 language code in which the CMP UI was presented. + ConsentLanguage string + // Number corresponds to the Global Vendor List (GVL) vendorListVersion. + VendorListVersion int + // Version of policy used within GVL. + TCFPolicyVersion int + // Setting this to 1 means that a publisher-run CMP – that is still IAB Europe + // registered – is using customized Stack descriptions and not the standard stack + // descriptions defined in the Policies. A CMP that services multiple publishers sets + // this value to 0. + UseNonStandardStacks bool + // The TCF Policies designates certain Features as “special” which means a CMP must + // afford the user a means to opt in to their use. These “Special Features” are + // published and numerically identified in the Global Vendor List separately from + // normal Features. + SpecialFeatureExpressConsent map[int]bool + // The user’s consent value for each Purpose established on the legal basis of consent. + // The Purposes are numerically identified and published in the Global Vendor List. + // From left to right, Purpose 1 maps to the 0th bit, purpose 24 maps to the bit at + // index 23. Special Purposes are a different ID space and not included in this field. + PurposesExpressConsent map[int]bool + // The Purpose’s transparency requirements are met for each Purpose on the legal basis + // of legitimate interest and the user has not exercised their “Right to Object” to that + // Purpose. By default or if the user has exercised their “Right to Object” to a Purpose, + // the corresponding bit for that Purpose is set to 0. From left to right, Purpose 1 maps + // to the 0th bit, purpose 24 maps to the bit at index 23. Special Purposes are a + // different ID space and not included in this field. + PurposesImpliedConsent map[int]bool + + MaxExpressConsentVendorID int + IsExpressConsentRangeEncoding bool + // The consent value for each Vendor ID. + ExpressConsentedVendors map[int]bool + // Number of RangeEntry sections to follow. + NumExpressConsentEntries int + // A single or range of Vendor ID(s) who have received consent. If a Vendor ID is not within + // the bounds of the ranges then the vendor is assumed to have “No Consent”. + VendorExpressConsent []*RangeEntry + + MaxImpliedConsentVendorID int + IsImpliedConsentRangeEncoding bool + // The consent value for each Vendor ID. + ImpliedConsentedVendors map[int]bool + // Number of RangeEntry sections to follow. + NumImpliedConsentEntries int + // A single or range of Vendor ID(s) who have received consent. If a Vendor ID is not within + // the bounds of the ranges then the vendor is assumed to have “No Consent”. + VendorImpliedConsent []*RangeEntry + + *PublisherTCEntry +} + // RestrictionType is an enum type of publisher restriction types. type RestrictionType int diff --git a/v2_parsed_consent_fixture_test.go b/v2_parsed_consent_fixture_test.go index 8fb81cb..81d6acf 100644 --- a/v2_parsed_consent_fixture_test.go +++ b/v2_parsed_consent_fixture_test.go @@ -410,3 +410,106 @@ var v2ConsentFixtures = map[string]*iabconsent.V2ParsedConsent{ PubRestrictionEntries: make([]*iabconsent.PubRestrictionEntry, 0), }, } + +var v2CAConsentFixtures = map[string]*iabconsent.V2CAParsedConsent{ + "CPb_z8APb_z8AEXahAENDDCgAf-AAP-AAAjhArgAUABcADQAOAArABcAGQAOAAgABIAC0AGgAOoAegB8AEWAJgAmgBQACkAFsAMIAaIBBgEIAI4AUoArQBbgDKAHaAPEAg4BJQCdgFNAKeAdQBAAC8wGDgMZAZYA00BrgDdwH1ARmAjgBpsB4ABYADgAKgAXAAyABwAEAAJAAaAA-ACKAEwAKQAaAA_ACEAEcAKUAW4AygCDgEWAKeAa8A6gCwgF5gMsAZeA00A.YAAAAAAAAAA": { + Version: 2, + Created: time.Date(2022, time.July, 12, 0, 0, 0, 0, time.UTC), + LastUpdated: time.Date(2022, time.July, 12, 0, 0, 0, 0, time.UTC), + CMPID: 279, + CMPVersion: 1697, + ConsentScreen: 0, + ConsentLanguage: "EN", + VendorListVersion: 195, + TCFPolicyVersion: 2, + UseNonStandardStacks: true, + SpecialFeatureExpressConsent: map[int]bool{}, + PurposesExpressConsent: map[int]bool{1: true, 2: true, 3: true, 4: true, 5: true, 6: true, 7: true, 8: true, 9: true, 10: true}, + PurposesImpliedConsent: map[int]bool{2: true, 3: true, 4: true, 5: true, 6: true, 7: true, 8: true, 9: true, 10: true}, + MaxExpressConsentVendorID: 1136, + IsExpressConsentRangeEncoding: true, + ExpressConsentedVendors: map[int]bool(nil), + NumExpressConsentEntries: 43, + VendorExpressConsent: []*iabconsent.RangeEntry{ + {StartVendorID: 10, EndVendorID: 11}, + {StartVendorID: 13, EndVendorID: 14}, + {StartVendorID: 21, EndVendorID: 21}, + {StartVendorID: 23, EndVendorID: 25}, + {StartVendorID: 28, EndVendorID: 28}, + {StartVendorID: 32, EndVendorID: 32}, + {StartVendorID: 36, EndVendorID: 36}, + {StartVendorID: 45, EndVendorID: 45}, + {StartVendorID: 52, EndVendorID: 52}, + {StartVendorID: 58, EndVendorID: 58}, + {StartVendorID: 61, EndVendorID: 62}, + {StartVendorID: 69, EndVendorID: 69}, + {StartVendorID: 76, EndVendorID: 77}, + {StartVendorID: 80, EndVendorID: 80}, + {StartVendorID: 82, EndVendorID: 82}, + {StartVendorID: 91, EndVendorID: 91}, + {StartVendorID: 97, EndVendorID: 97}, + {StartVendorID: 104, EndVendorID: 104}, + {StartVendorID: 131, EndVendorID: 132}, + {StartVendorID: 142, EndVendorID: 142}, + {StartVendorID: 165, EndVendorID: 165}, + {StartVendorID: 173, EndVendorID: 173}, + {StartVendorID: 183, EndVendorID: 183}, + {StartVendorID: 202, EndVendorID: 202}, + {StartVendorID: 237, EndVendorID: 237}, + {StartVendorID: 241, EndVendorID: 241}, + {StartVendorID: 263, EndVendorID: 263}, + {StartVendorID: 293, EndVendorID: 293}, + {StartVendorID: 315, EndVendorID: 315}, + {StartVendorID: 333, EndVendorID: 333}, + {StartVendorID: 335, EndVendorID: 335}, + {StartVendorID: 468, EndVendorID: 468}, + {StartVendorID: 512, EndVendorID: 512}, + {StartVendorID: 755, EndVendorID: 755}, + {StartVendorID: 775, EndVendorID: 775}, + {StartVendorID: 793, EndVendorID: 793}, + {StartVendorID: 812, EndVendorID: 812}, + {StartVendorID: 845, EndVendorID: 845}, + {StartVendorID: 860, EndVendorID: 860}, + {StartVendorID: 887, EndVendorID: 887}, + {StartVendorID: 1002, EndVendorID: 1002}, + {StartVendorID: 1126, EndVendorID: 1126}, + {StartVendorID: 1136, EndVendorID: 1136}, + }, + MaxImpliedConsentVendorID: 845, + IsImpliedConsentRangeEncoding: true, + ImpliedConsentedVendors: map[int]bool(nil), + NumImpliedConsentEntries: 30, + VendorImpliedConsent: []*iabconsent.RangeEntry{{StartVendorID: 11, EndVendorID: 11}, + {StartVendorID: 14, EndVendorID: 14}, + {StartVendorID: 21, EndVendorID: 21}, + {StartVendorID: 23, EndVendorID: 23}, + {StartVendorID: 25, EndVendorID: 25}, + {StartVendorID: 28, EndVendorID: 28}, + {StartVendorID: 32, EndVendorID: 32}, + {StartVendorID: 36, EndVendorID: 36}, + {StartVendorID: 52, EndVendorID: 52}, + {StartVendorID: 62, EndVendorID: 62}, + {StartVendorID: 69, EndVendorID: 69}, + {StartVendorID: 76, EndVendorID: 76}, + {StartVendorID: 82, EndVendorID: 82}, + {StartVendorID: 104, EndVendorID: 104}, + {StartVendorID: 126, EndVendorID: 126}, + {StartVendorID: 132, EndVendorID: 132}, + {StartVendorID: 142, EndVendorID: 142}, + {StartVendorID: 165, EndVendorID: 165}, + {StartVendorID: 183, EndVendorID: 183}, + {StartVendorID: 202, EndVendorID: 202}, + {StartVendorID: 263, EndVendorID: 263}, + {StartVendorID: 278, EndVendorID: 278}, + {StartVendorID: 335, EndVendorID: 335}, + {StartVendorID: 431, EndVendorID: 431}, + {StartVendorID: 468, EndVendorID: 468}, + {StartVendorID: 706, EndVendorID: 706}, + {StartVendorID: 755, EndVendorID: 755}, + {StartVendorID: 812, EndVendorID: 812}, + {StartVendorID: 815, EndVendorID: 815}, + {StartVendorID: 845, EndVendorID: 845}, + }, + PublisherTCEntry: (*iabconsent.PublisherTCEntry)(nil), + }, +} diff --git a/v2_parsed_consent_test.go b/v2_parsed_consent_test.go index 8d6a4cd..e7af2e4 100644 --- a/v2_parsed_consent_test.go +++ b/v2_parsed_consent_test.go @@ -411,4 +411,15 @@ func (v *V2ParsedConsentSuite) TestSuitableToProcess(c *check.C) { } } +func (v *V2ParsedConsentSuite) TestParseCAV2(c *check.C) { + for k, v := range v2CAConsentFixtures { + c.Log(k) + + var p, err = iabconsent.ParseCAV2(k) + + c.Check(err, check.IsNil) + c.Check(p, check.DeepEquals, v) + } +} + var _ = check.Suite(&V2ParsedConsentSuite{})