-
Notifications
You must be signed in to change notification settings - Fork 16
/
gpp_parsed_consent_test.go
309 lines (284 loc) · 7.51 KB
/
gpp_parsed_consent_test.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
package iabconsent_test
import (
"encoding/base64"
"strings"
"github.com/go-check/check"
"github.com/pkg/errors"
"github.com/LiveRamp/iabconsent"
)
type GppParseSuite struct{}
var _ = check.Suite(&GppParseSuite{})
func (s *GppParseSuite) TestParseGppHeader(c *check.C) {
var tcs = []struct {
description string
header string
expected *iabconsent.GppHeader
}{
{
// Examples pulled from: https://github.com/InteractiveAdvertisingBureau/Global-Privacy-Platform/blob/main/Core/Consent%20String%20Specification.md#gpp-string-examples
description: "EU TCF v2 Section",
header: "DBABM",
expected: &iabconsent.GppHeader{
Type: 3,
Version: 1,
Sections: []int{2}},
},
{
description: "EU TCF v2 + USPrivacy String Sections",
header: "DBACNY",
expected: &iabconsent.GppHeader{
Type: 3,
Version: 1,
Sections: []int{2, 6}},
},
{
description: "Canadian TCF + USPrivacy String Sections",
header: "DBABjw",
expected: &iabconsent.GppHeader{
Type: 3,
Version: 1,
Sections: []int{5, 6}},
},
{
description: "US National MSPA (Multi-State Privacy Agreement)",
header: "DBABL",
expected: &iabconsent.GppHeader{
Type: 3,
Version: 1,
Sections: []int{7}},
},
{
description: "US Privacy and US National MSPA (Multi-State Privacy Agreement)",
header: "DBABzw",
expected: &iabconsent.GppHeader{
Type: 3,
Version: 1,
Sections: []int{6, 7}},
},
}
for _, tc := range tcs {
c.Log(tc)
var g, err = iabconsent.ParseGppHeader(tc.header)
c.Check(err, check.IsNil)
c.Check(g, check.DeepEquals, tc.expected)
}
}
func (s *GppParseSuite) TestParseGppHeaderError(c *check.C) {
var tcs = []struct {
description string
header string
expected error
}{
{
description: "GPP Header must be 3, as of Jan. 2023.",
// []byte{0b00000100, 0b00010000, 0b00000010, 0b00110101, 0b10000000}
header: "BBACNYA",
expected: errors.New("wrong gpp header type 1"),
},
{
description: "GPP Header must be 3, as of Jan. 2023, without trailing zero-padding.",
// Six bit groupings: 000001 000001 000000 000010 001101 011000
header: "BBACNY",
expected: errors.New("wrong gpp header type 1"),
},
{
description: "Only support GPP Version 1, as of Jan. 2023",
// []byte{0b00001100, 0b00100000, 0b00000010, 0b00110101, 0b10000000}
header: "DCACNYA",
expected: errors.New("unsupported gpp version 2"),
},
{
description: "Only support GPP Version 1, as of Jan. 2023, without trailing zero-padding.",
// Six bit groupings: 000011 000010 000000 000010 001101 011000
header: "DCACNY",
expected: errors.New("unsupported gpp version 2"),
}}
for _, tc := range tcs {
c.Log(tc)
var g, err = iabconsent.ParseGppHeader(tc.header)
c.Check(g, check.IsNil)
c.Check(err, check.NotNil)
c.Check(err.Error(), check.Equals, tc.expected.Error())
}
}
func (s *MspaSuite) TestMapGppSectionToParser(c *check.C) {
for gppString, expectedValues := range gppParsedConsentFixtures {
c.Log(gppString)
var gppSections, err = iabconsent.MapGppSectionToParser(gppString)
c.Check(err, check.IsNil)
// Instead of checking the parsing functions, run each of them to ensure the final values match.
c.Check(gppSections, check.HasLen, len(expectedValues))
for _, sect := range gppSections {
consent, err := sect.ParseConsent()
c.Check(err, check.IsNil)
c.Check(consent, check.DeepEquals, expectedValues[sect.GetSectionId()])
}
}
}
func (s *MspaSuite) TestMapGppSectionToParserErrors(c *check.C) {
tcs := []struct {
desc string
gpp string
expected error
}{
{
desc: "No sections.",
gpp: "DBABL",
expected: errors.New("not enough gpp segments"),
},
{
desc: "Mismatched # of sections, header expects 1.",
gpp: "DBABL~section1~section2",
expected: errors.New("mismatch number of sections"),
},
{
desc: "Bad header.",
gpp: "badheader~BVVqAAEABCA.QA",
expected: errors.New("read gpp header: wrong gpp header type 27"),
},
}
for _, t := range tcs {
c.Log(t.desc)
var p, err = iabconsent.MapGppSectionToParser(t.gpp)
c.Check(p, check.IsNil)
c.Check(err, check.ErrorMatches, t.expected.Error())
}
}
func (s *MspaSuite) TestParseGppConsent(c *check.C) {
for g, e := range gppParsedConsentFixtures {
c.Log(g)
var p, err = iabconsent.ParseGppConsent(g)
c.Check(err, check.IsNil)
c.Check(p, check.HasLen, len(e))
for i, expected := range e {
parsed, found := p[i]
c.Check(found, check.Equals, true)
c.Check(parsed, check.DeepEquals, expected)
}
}
}
func (s *MspaSuite) TestParseGppConsentError(c *check.C) {
tcs := []struct {
desc string
gpp string
}{
{
desc: "Empty Subsection.",
gpp: "DBABzw~1YNN~BVVqAAEABCA.",
},
{
desc: "Empty Subsection.",
gpp: "DBABAw~Bqqqqqqo.",
},
}
for _, tc := range tcs {
c.Log(tc.desc)
var p, err = iabconsent.ParseGppConsent(tc.gpp)
// Despite an error in the underlying parsing, we quietly do not add the bad value to the map.
c.Check(err, check.IsNil)
c.Check(p, check.HasLen, 0)
}
}
func (s *GppParseSuite) TestParseGppSubSections(c *check.C) {
var tcs = []struct {
description string
subsections string
expectedSubsection *iabconsent.GppSubSection
expectedError error
}{
{
description: "GPC Type, false value",
// 01000000
subsections: "QA",
expectedSubsection: &iabconsent.GppSubSection{
Gpc: false,
},
},
{
description: "GPC Type, true value.",
// 01100000
subsections: "YA",
expectedSubsection: &iabconsent.GppSubSection{
Gpc: true,
},
},
{
description: "No GPC Type.",
// 00000000
subsections: "AA",
expectedSubsection: &iabconsent.GppSubSection{
Gpc: false,
},
},
{
description: "GPC True, then GPC False, should remain True.",
// 01100000.01000000
subsections: "YA.QA",
expectedSubsection: &iabconsent.GppSubSection{
Gpc: true,
},
},
{
description: "GPC False, then GPC True, should remain True.",
// 01000000.01100000
subsections: "QA.YA",
expectedSubsection: &iabconsent.GppSubSection{
Gpc: true,
},
},
{
description: "GPC Error.",
// Blank value
subsections: "",
expectedSubsection: nil,
expectedError: errors.New("parse gpp subsection type: read int: read bits (index=0, length=2): bits: index out of range"),
},
}
for _, tc := range tcs {
c.Log(tc)
// There may be >1 subsections, and func expects them as an array, so split.
subsect := strings.Split(tc.subsections, ".")
var g, err = iabconsent.ParseGppSubSections(subsect)
if tc.expectedError == nil {
c.Check(err, check.IsNil)
} else {
c.Check(err.Error(), check.Equals, tc.expectedError.Error())
}
c.Check(g, check.DeepEquals, tc.expectedSubsection)
}
}
func (s *GppParseSuite) TestParseGpcSubSections(c *check.C) {
var tcs = []struct {
description string
subsection string
expected bool
}{
{
description: "All 0 bits.",
// 0000000
subsection: "AA",
expected: false,
},
{
description: "Second bit 1.",
// 01000000
subsection: "QA",
expected: false,
},
{
description: "First bit 1.",
// 1000000
subsection: "gA",
expected: true,
},
}
for _, tc := range tcs {
c.Log(tc)
b, err := base64.RawURLEncoding.DecodeString(tc.subsection)
c.Check(err, check.IsNil)
var cr = iabconsent.NewConsentReader(b)
g, err := iabconsent.ParseGpcSubsection(cr)
c.Check(err, check.IsNil)
c.Check(g, check.DeepEquals, tc.expected)
}
}