Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
137 changes: 79 additions & 58 deletions iabgpp-encoder/src/main/java/com/iab/gpp/encoder/section/TcfEuV2.java
Original file line number Diff line number Diff line change
@@ -1,18 +1,22 @@
package com.iab.gpp.encoder.section;

import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.util.ArrayList;
import java.util.List;
import com.iab.gpp.encoder.datatype.RangeEntry;
import com.iab.gpp.encoder.error.DecodingException;
import com.iab.gpp.encoder.error.EncodingException;
import com.iab.gpp.encoder.error.InvalidFieldException;
import com.iab.gpp.encoder.field.TcfEuV2Field;
import com.iab.gpp.encoder.segment.EncodableSegment;
import com.iab.gpp.encoder.segment.TcfEuV2CoreSegment;
import com.iab.gpp.encoder.segment.TcfEuV2PublisherPurposesSegment;
import com.iab.gpp.encoder.segment.TcfEuV2VendorsAllowedSegment;
import com.iab.gpp.encoder.segment.TcfEuV2VendorsDisclosedSegment;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.StringJoiner;

public class TcfEuV2 extends AbstractLazilyEncodableSection {

Expand Down Expand Up @@ -53,73 +57,90 @@ protected List<EncodableSegment> initializeSegments() {
segments.add(new TcfEuV2VendorsDisclosedSegment());
return segments;
}

@Override
public List<EncodableSegment> decodeSection(String encodedString) {
List<EncodableSegment> segments = initializeSegments();

if(encodedString != null && !encodedString.isEmpty()) {
String[] encodedSegments = encodedString.split("\\.");
for (int i = 0; i < encodedSegments.length; i++) {

/**
* The first 3 bits contain the segment id. Rather than decode the entire string, just check the first character.
*
* A-H = '000' = 0
* I-P = '001' = 1
* Q-X = '010' = 2
* Y-Z,a-f = '011' = 3
*
* Note that there is no segment id field for the core segment. Instead the first 6 bits are reserved
* for the encoding version which only coincidentally works here because the version value is less than 8.
*/

String encodedSegment = encodedSegments[i];
if(!encodedSegment.isEmpty()) {
char firstChar = encodedSegment.charAt(0);

// unfortunately, the segment ordering doesn't match the segment ids
if(firstChar >= 'A' && firstChar <= 'H') {
segments.get(0).decode(encodedSegments[i]);
} else if(firstChar >= 'I' && firstChar <= 'P') {
segments.get(3).decode(encodedSegments[i]);
} else if(firstChar >= 'Q' && firstChar <= 'X') {
segments.get(2).decode(encodedSegments[i]);
} else if((firstChar >= 'Y' && firstChar <= 'Z') || (firstChar >= 'a' && firstChar <= 'f')) {
segments.get(1).decode(encodedSegments[i]);
} else {
throw new DecodingException("Invalid segment '" + encodedSegment + "'");
}
}
public List<EncodableSegment> decodeSection(final String encodedString) {
final List<EncodableSegment> segments = initializeSegments();

if (encodedString == null || encodedString.isEmpty()) {
return segments;
}

final String[] encodedSegments = encodedString.split("\\.");

for (final String encodedSegment: encodedSegments) {
/**
* The first 3 bits contain the segment id. Rather than decode the entire string, just check the first character.
*
* A-H = '000' = 0
* I-P = '001' = 1
* Q-X = '010' = 2
* Y-Z,a-f = '011' = 3
*
* Note that there is no segment id field for the core segment. Instead the first 6 bits are reserved
* for the encoding version which only coincidentally works here because the version value is less than 8.
*/
if (encodedSegment.isEmpty()) {
continue;
}

final char firstChar = encodedSegment.charAt(0);

// unfortunately, the segment ordering doesn't match the segment ids
if(firstChar >= 'A' && firstChar <= 'H') {
segments.get(0).decode(encodedSegment);
} else if(firstChar >= 'I' && firstChar <= 'P') {
segments.get(3).decode(encodedSegment);
} else if(firstChar >= 'Q' && firstChar <= 'X') {
segments.get(2).decode(encodedSegment);
} else if((firstChar >= 'Y' && firstChar <= 'Z') || (firstChar >= 'a' && firstChar <= 'f')) {
segments.get(1).decode(encodedSegment);
} else {
throw new DecodingException("Invalid segment '" + encodedSegment + "'");
}
}

return segments;
}

@Override
public String encodeSection(List<EncodableSegment> segments) {
List<String> encodedSegments = new ArrayList<>();
if (segments.size() >= 1) {
encodedSegments.add(segments.get(0).encode());

Boolean isServiceSpecific = (Boolean) this.getFieldValue(TcfEuV2Field.IS_SERVICE_SPECIFIC);
if (isServiceSpecific) {
if (segments.size() >= 2) {
encodedSegments.add(segments.get(1).encode());
}
final StringJoiner encodedSegments = new StringJoiner(".");

/*
Only encode a non-core section if it doesn't have default values.
This is intended to match https://github.com/InteractiveAdvertisingBureau/iabtcf-java/blob/master/iabtcf-encoder/src/main/java/com/iabtcf/encoder/TCStringEncoder.java.
*/
for (final EncodableSegment segment: segments) {
final boolean encode;

if (
segment instanceof TcfEuV2CoreSegment
|| segment instanceof TcfEuV2VendorsDisclosedSegment
) {
/*
TcfEuV2VendorsDisclosedSegment is required in the TC string as of TCF 2.3.
https://iabeurope.eu/all-you-need-to-know-about-the-transition-to-tcf-v2-3/
*/
encode = true;
} else if (segment instanceof TcfEuV2PublisherPurposesSegment) {
final List<Boolean> publisherConsents = getPublisherConsents();
final List<Boolean> publisherLegitimateInterests = getPublisherLegitimateInterests();
encode = (publisherConsents != null && publisherConsents.contains(true))
|| (publisherLegitimateInterests != null && publisherLegitimateInterests.contains(true))
|| !Objects.equals(getNumCustomPurposes(), 0);
} else if (segment instanceof TcfEuV2VendorsAllowedSegment) {
encode = !Objects.equals(getVendorsAllowed(), Collections.emptyList());
} else {
if (segments.size() >= 2) {
encodedSegments.add(segments.get(2).encode());
throw new EncodingException(String.format("Unknown segment type '%s' for section %s.", segment.getClass().getName(), NAME));
}

if (segments.size() >= 3) {
encodedSegments.add(segments.get(3).encode());
}
}
if (encode) {
encodedSegments.add(segment.encode());
}
}

return String.join(".", encodedSegments);
return encodedSegments.toString();
}

@Override
Expand Down
28 changes: 14 additions & 14 deletions iabgpp-encoder/src/test/java/com/iab/gpp/encoder/GppModelTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ public void testEncodeDefaultAll() {

String gppString = gppModel.encode();
Assertions.assertEquals(
"DBACOYs~CPSG_8APSG_8AAAAAAENAACAAAAAAAAAAAAAAAAAAAAA.QAAA.IAAA~BPSG_8APSG_8AAAAAAENAACAAAAAAAAAAAAAAAAAAA.YAAAAAAAAAA~1---~BAAAAAAAAABA.QA~BAAAAABA.QA~BAAAABA~BAAAAEA.QA~BAAAAAQA~BAAAAAEA.QA~BAAAAABA~BAAAAABA.QA~BAAAAAABAA.QA~BAAAAAQA.QA~BAAAAAABAA.QA~BAAAAAQA.QA~BAAAAAQA.QA~BAAAAABA.QA~BAAAAAAAQA.QA~BAAAAAQA.QA~BAAAAAQA.QA",
"DBACOYs~CPSG_8APSG_8AAAAAAENAACAAAAAAAAAAAAAAAAAAAAA.IAAA~BPSG_8APSG_8AAAAAAENAACAAAAAAAAAAAAAAAAAAA.YAAAAAAAAAA~1---~BAAAAAAAAABA.QA~BAAAAABA.QA~BAAAABA~BAAAAEA.QA~BAAAAAQA~BAAAAAEA.QA~BAAAAABA~BAAAAABA.QA~BAAAAAABAA.QA~BAAAAAQA.QA~BAAAAAABAA.QA~BAAAAAQA.QA~BAAAAAQA.QA~BAAAAABA.QA~BAAAAAAAQA.QA~BAAAAAQA.QA~BAAAAAQA.QA",
gppString);
}

Expand Down Expand Up @@ -226,7 +226,7 @@ public void testEncodeTcfEuV2() {


String gppString = gppModel.encode();
Assertions.assertEquals("DBABMA~CPSG_8APSG_8ANwAAAENAwCAAAAAAAAAAAAAAAAAAAAA.QAAA.IAAA", gppString);
Assertions.assertEquals("DBABMA~CPSG_8APSG_8ANwAAAENAwCAAAAAAAAAAAAAAAAAAAAA.IAAA", gppString);

Assertions.assertEquals(2, gppString.split("~").length);

Expand Down Expand Up @@ -275,7 +275,7 @@ public void testEncodeUspV1AndTcfEuV2() {
Assertions.assertEquals(false, gppModel.hasSection(TcfCaV1.NAME));

String gppString = gppModel.encode();
Assertions.assertEquals("DBACNYA~CPSG_8APSG_8ANwAAAENAwCAAAAAAAAAAAAAAAAAAAAA.QAAA.IAAA~1YNN", gppString);
Assertions.assertEquals("DBACNYA~CPSG_8APSG_8ANwAAAENAwCAAAAAAAAAAAAAAAAAAAAA.IAAA~1YNN", gppString);

Assertions.assertEquals(3, gppString.split("~").length);

Expand Down Expand Up @@ -373,7 +373,7 @@ public void testEncodeUspV1AndTcfEuV2AndTcfCaV1() {

String gppString = gppModel.encode();
Assertions.assertEquals(
"DBACOeA~CPSG_8APSG_8ANwAAAENAwCAAAAAAAAAAAAAAAAAAAAA.QAAA.IAAA~BPSG_8APSG_8AAyACAENGdCgf_gfgAfgfgBgABABAAABAB4AACACAAA.fHHHA4444ao~1YNN",
"DBACOeA~CPSG_8APSG_8ANwAAAENAwCAAAAAAAAAAAAAAAAAAAAA.IAAA~BPSG_8APSG_8AAyACAENGdCgf_gfgAfgfgBgABABAAABAB4AACACAAA.fHHHA4444ao~1YNN",
gppString);

Assertions.assertEquals(4, gppString.split("~").length);
Expand Down Expand Up @@ -406,7 +406,7 @@ public void testDecodeDefaults() {
@Test
public void testDecodeDefaultsAll() {
String gppString =
"DBACOYs~CPSG_8APSG_8AAAAAAENAACAAAAAAAAAAAAAAAAAAAAA.QAAA.IAAA~BPSG_8APSG_8AAAAAAENAACAAAAAAAAAAAAAAAAAAA.YAAAAAAAAAA~1---~BAAAAAAAAABA.QA~BAAAAABA.QA~BAAAABA~BAAAAEA.QA~BAAAAAQA~BAAAAAEA.QA~BAAAAABA~BAAAAABA.QA~BAAAAAABAA.QA~BAAAAAQA.QA~BAAAAAABAA.QA~BAAAAAQA.QA~BAAAAAQA.QA~BAAAAABA.QA~BAAAAAAAQA.QA~BAAAAAQA.QA~BAAAAAABAA.QA";
"DBACOYs~CPSG_8APSG_8AAAAAAENAACAAAAAAAAAAAAAAAAAAAAA~BPSG_8APSG_8AAAAAAENAACAAAAAAAAAAAAAAAAAAA.YAAAAAAAAAA~1---~BAAAAAAAAABA.QA~BAAAAABA.QA~BAAAABA~BAAAAEA.QA~BAAAAAQA~BAAAAAEA.QA~BAAAAABA~BAAAAABA.QA~BAAAAAABAA.QA~BAAAAAQA.QA~BAAAAAABAA.QA~BAAAAAQA.QA~BAAAAAQA.QA~BAAAAABA.QA~BAAAAAAAQA.QA~BAAAAAQA.QA~BAAAAAABAA.QA";
GppModel gppModel = new GppModel(gppString);

Assertions.assertEquals(true, gppModel.hasSection(TcfEuV2.NAME));
Expand Down Expand Up @@ -456,7 +456,7 @@ public void testDecodeUspv1() {

@Test
public void testDecodeTcfEuV2() {
String gppString = "DBABMA~CPSG_8APSG_8ANwAAAENAwCAAAAAAAAAAAAAAAAAAAAA.QAAA.IAAA";
String gppString = "DBABMA~CPSG_8APSG_8ANwAAAENAwCAAAAAAAAAAAAAAAAAAAAA";
GppModel gppModel = new GppModel(gppString);

Assertions.assertEquals(Arrays.asList(2), gppModel.getSectionIds());
Expand Down Expand Up @@ -499,7 +499,7 @@ public void testDecodeTcfEuV2() {

@Test
public void testDecodeUspv1AndTcfEuV2() {
String gppString = "DBACNYA~CPSG_8APSG_8ANwAAAENAwCAAAAAAAAAAAAAAAAAAAAA.QAAA.IAAA~1YNN";
String gppString = "DBACNYA~CPSG_8APSG_8ANwAAAENAwCAAAAAAAAAAAAAAAAAAAAA~1YNN";
GppModel gppModel = new GppModel(gppString);

Assertions.assertEquals(Arrays.asList(2, 6), gppModel.getSectionIds());
Expand Down Expand Up @@ -564,7 +564,7 @@ public void testDecodeUspv1AndTcfEuV2() {
@Test
public void testDecodeUspv1AndTcfEuV2AndTcfCaV1() {
String gppString =
"DBACOeA~CPSG_8APSG_8ANwAAAENAwCAAAAAAAAAAAAAAAAAAAAA.QAAA.IAAA~BPSG_8APSG_8AAyACAENGdCgf_gfgAfgfgBgABABAAABAB4AACACAAA.fHHHA4444ao~1YNN";
"DBACOeA~CPSG_8APSG_8ANwAAAENAwCAAAAAAAAAAAAAAAAAAAAA~BPSG_8APSG_8AAyACAENGdCgf_gfgAfgfgBgABABAAABAB4AACACAAA.fHHHA4444ao~1YNN";
GppModel gppModel = new GppModel(gppString);

Assertions.assertEquals(Arrays.asList(2, 5, 6), gppModel.getSectionIds());
Expand Down Expand Up @@ -650,7 +650,7 @@ public void testEncode1() {
gppModel.setFieldValue(TcfEuV2.NAME, TcfEuV2Field.CREATED, utcDateTime);
gppModel.setFieldValue(TcfEuV2.NAME, TcfEuV2Field.LAST_UPDATED, utcDateTime);

Assertions.assertEquals("DBABMA~CPSG_8APSG_8AAAAAAENAACAAAAAAAAAAAAAAOAAAABAAAAA.QAAA.IAAA", gppModel.encode());
Assertions.assertEquals("DBABMA~CPSG_8APSG_8AAAAAAENAACAAAAAAAAAAAAAAOAAAABAAAAA.IAAA", gppModel.encode());
}

@Test
Expand All @@ -661,7 +661,7 @@ public void testEncode2() {
gppModel.setFieldValue(TcfEuV2.NAME, TcfEuV2Field.CREATED, utcDateTime);
gppModel.setFieldValue(TcfEuV2.NAME, TcfEuV2Field.LAST_UPDATED, utcDateTime);

Assertions.assertEquals("DBABMA~CPSG_8APSG_8AAAAAAENAACAAAAAAAAAAAAAAOwAQAOgAAAA.QAAA.IAAA", gppModel.encode());
Assertions.assertEquals("DBABMA~CPSG_8APSG_8AAAAAAENAACAAAAAAAAAAAAAAOwAQAOgAAAA.IAAA", gppModel.encode());
}

@Test
Expand All @@ -672,25 +672,25 @@ public void testEncode3() {
gppModel.setFieldValue(TcfEuV2.NAME, TcfEuV2Field.CREATED, utcDateTime);
gppModel.setFieldValue(TcfEuV2.NAME, TcfEuV2Field.LAST_UPDATED, utcDateTime);

Assertions.assertEquals("DBABMA~CPSG_8APSG_8AAAAAAENAACAAAAAAAAAAAAAFpQAwAAgCtAWkAAAAAAA.QAAA.IAAA",
Assertions.assertEquals("DBABMA~CPSG_8APSG_8AAAAAAENAACAAAAAAAAAAAAAFpQAwAAgCtAWkAAAAAAA.IAAA",
gppModel.encode());
}

@Test
public void testDecode1() {
GppModel gppModel = new GppModel("DBABMA~CPSG_8APSG_8AAAAAAENAACAAAAAAAAAAAAAAOAAAABAAAAA.QAAA.IAAA");
GppModel gppModel = new GppModel("DBABMA~CPSG_8APSG_8AAAAAAENAACAAAAAAAAAAAAAAOAAAABAAAAA.IAAA");
Assertions.assertEquals(Arrays.asList(28), gppModel.getFieldValue(TcfEuV2.NAME, TcfEuV2Field.VENDOR_CONSENTS));
}

@Test
public void testDecode2() {
GppModel gppModel = new GppModel("DBABMA~CPSG_8APSG_8AAAAAAENAACAAAAAAAAAAAAAAOwAQAOgAAAA.QAAA.IAAA");
GppModel gppModel = new GppModel("DBABMA~CPSG_8APSG_8AAAAAAENAACAAAAAAAAAAAAAAOwAQAOgAAAA.IAAA");
Assertions.assertEquals(Arrays.asList(29), gppModel.getFieldValue(TcfEuV2.NAME, TcfEuV2Field.VENDOR_CONSENTS));
}

@Test
public void testDecode3() {
GppModel gppModel = new GppModel("DBABMA~CPSG_8APSG_8AAAAAAENAACAAAAAAAAAAAAAFpQAwAAgCtAWkAAAAAAA.QAAA.IAAA");
GppModel gppModel = new GppModel("DBABMA~CPSG_8APSG_8AAAAAAENAACAAAAAAAAAAAAAFpQAwAAgCtAWkAAAAAAA");
Assertions.assertEquals(Arrays.asList(1, 173, 722),
gppModel.getFieldValue(TcfEuV2.NAME, TcfEuV2Field.VENDOR_CONSENTS));
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,23 +1,43 @@
package com.iab.gpp.encoder.section;

import com.iab.gpp.encoder.datatype.RangeEntry;
import com.iab.gpp.encoder.error.DecodingException;
import com.iab.gpp.encoder.field.TcfEuV2Field;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.util.Arrays;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import com.iab.gpp.encoder.datatype.RangeEntry;
import com.iab.gpp.encoder.error.DecodingException;
import com.iab.gpp.encoder.field.TcfEuV2Field;

public class TcfEuV2Test {

static final Set<String> FIELD_NAMES =
new TcfEuV2().initializeSegments().stream()
.flatMap(s -> s.getFieldNames().stream())
.collect(Collectors.toSet());

static void assertEqualFields(final TcfEuV2 expected, TcfEuV2 actual) {
for (String fieldName: FIELD_NAMES) {
Assertions.assertEquals(expected.getFieldValue(fieldName), actual.getFieldValue(fieldName));
}
}

@Test
public void testEncode1() {
TcfEuV2 tcfEuV2 = new TcfEuV2();
tcfEuV2.setFieldValue(TcfEuV2Field.CREATED, ZonedDateTime.of(2022, 1, 1, 0, 0, 0, 0, ZoneId.of("UTC")));
tcfEuV2.setFieldValue(TcfEuV2Field.LAST_UPDATED, ZonedDateTime.of(2022, 1, 1, 0, 0, 0, 0, ZoneId.of("UTC")));
Assertions.assertEquals("CPSG_8APSG_8AAAAAAENAACAAAAAAAAAAAAAAAAAAAAA.QAAA.IAAA", tcfEuV2.encode());
final ZonedDateTime time = ZonedDateTime.of(2022, 1, 1, 0, 0, 0, 0, ZoneId.of("UTC"));
tcfEuV2.setFieldValue(TcfEuV2Field.CREATED, time);
tcfEuV2.setFieldValue(TcfEuV2Field.LAST_UPDATED, time);

final String encoded = tcfEuV2.encode();
Assertions.assertEquals("CPSG_8APSG_8AAAAAAENAACAAAAAAAAAAAAAAAAAAAAA.IAAA", encoded);

final TcfEuV2 decoded = new TcfEuV2(encoded);

assertEqualFields(tcfEuV2, decoded);
}

@Test
Expand All @@ -40,12 +60,24 @@ public void testEncode2() {
Assertions.assertEquals(Arrays.asList(), tcfEuV2.getFieldValue(TcfEuV2Field.PUBLISHER_CUSTOM_CONSENTS));
Assertions.assertEquals(Arrays.asList(), tcfEuV2.getFieldValue(TcfEuV2Field.PUBLISHER_CUSTOM_LEGITIMATE_INTERESTS));

Assertions.assertEquals("CPSG_8APSG_8AAAAAAENAACgAAAAAAAAAAAAAAAAAAAA.YAAAAAAAAAAA", tcfEuV2.encode());
final String encoded = tcfEuV2.encode();
Assertions.assertEquals("CPSG_8APSG_8AAAAAAENAACgAAAAAAAAAAAAAAAAAAAA.IAAA", encoded);

final TcfEuV2 decoded = new TcfEuV2(encoded);

assertEqualFields(tcfEuV2, decoded);
}

@Test
public void testAlwaysEncodeCoreSegment() {
final TcfEuV2 tcfEuV2 = new TcfEuV2();
final char firstChar = tcfEuV2.encode().charAt(0);
Assertions.assertTrue(firstChar >= 'A' && firstChar <= 'H');
}

@Test
public void testDecode1() {
TcfEuV2 tcfEuV2 = new TcfEuV2("CAAAAAAAAAAAAAAAAAENAACAAAAAAAAAAAAAAAAAAAAA.QAAA.IAAA");
TcfEuV2 tcfEuV2 = new TcfEuV2("CAAAAAAAAAAAAAAAAAENAACAAAAAAAAAAAAAAAAAAAAA");

Assertions.assertEquals(2, tcfEuV2.getVersion());
Assertions.assertEquals(ZonedDateTime.of(1970, 1, 1, 0, 0, 0, 0, ZoneId.of("UTC")), tcfEuV2.getCreated());
Expand Down Expand Up @@ -98,7 +130,7 @@ public void testDecode1() {

@Test
public void testDecode2() {
TcfEuV2 tcfEuV2 = new TcfEuV2("CPSG_8APSG_8AAAAAAENAACgAAAAAAAAAAAAAAAAAAAA.YAAAAAAAAAAA");
TcfEuV2 tcfEuV2 = new TcfEuV2("CPSG_8APSG_8AAAAAAENAACgAAAAAAAAAAAAAAAAAAAA");

Assertions.assertEquals(2, tcfEuV2.getVersion());
Assertions.assertEquals(ZonedDateTime.of(2022, 1, 1, 0, 0, 0, 0, ZoneId.of("UTC")), tcfEuV2.getCreated());
Expand Down Expand Up @@ -153,7 +185,7 @@ public void testDecode2() {
@Test
public void testDecode3() {
TcfEuV2 tcfEuV2 = new TcfEuV2(
"CPcqBNJPcqBNJNwAAAENAwCAAAAAAAAAAAAAAAAAAAAA.YAAAAAAAAAA.QGLtV_T9fb2vj-_Z99_tkeYwf95y3p-wzhheMs-8NyZeH_B4Wv2MyvBX4JiQKGRgksjLBAQdtHGlcTQgBwIlViTLMYk2MjzNKJrJEilsbO2dYGD9Pn8HT3ZCY70-vv__7v3ff_3g.IGLtV_T9fb2vj-_Z99_tkeYwf95y3p-wzhheMs-8NyZeH_B4Wv2MyvBX4JiQKGRgksjLBAQdtHGlcTQgBwIlViTLMYk2MjzNKJrJEilsbO2dYGD9Pn8HT3ZCY70-vv__7v3ff_3g");
"CPcqBNJPcqBNJNwAAAENAwCAAAAAAAAAAAAAAAAAAAAA.QGLtV_T9fb2vj-_Z99_tkeYwf95y3p-wzhheMs-8NyZeH_B4Wv2MyvBX4JiQKGRgksjLBAQdtHGlcTQgBwIlViTLMYk2MjzNKJrJEilsbO2dYGD9Pn8HT3ZCY70-vv__7v3ff_3g.IGLtV_T9fb2vj-_Z99_tkeYwf95y3p-wzhheMs-8NyZeH_B4Wv2MyvBX4JiQKGRgksjLBAQdtHGlcTQgBwIlViTLMYk2MjzNKJrJEilsbO2dYGD9Pn8HT3ZCY70-vv__7v3ff_3g");


Assertions.assertEquals(2, tcfEuV2.getFieldValue("Version"));
Expand Down Expand Up @@ -328,7 +360,7 @@ public void testDecode5() {

@Test
public void testDecode6() {
TcfEuV2 tcfEuV2 = new TcfEuV2("COv_eg6Ov_eg6AOADBENAaCgAP_AAH_AACiQAVEUQQoAIQAqIoghAAQgAA.YAAAAAAAAAAAAAAAAAA");
TcfEuV2 tcfEuV2 = new TcfEuV2("COv_eg6Ov_eg6AOADBENAaCgAP_AAH_AACiQAVEUQQoAIQAqIoghAAQgAA");

Assertions.assertEquals(2, tcfEuV2.getFieldValue("Version"));
Assertions.assertEquals(14, tcfEuV2.getFieldValue("CmpId"));
Expand Down