Skip to content

Commit ed83ef8

Browse files
authored
Merge pull request #106 from IABTechLab/aul-UID2-4666-v3-identity-map-e2e-test
V3 Identity Map test
2 parents 695c75b + 3bf54cc commit ed83ef8

File tree

10 files changed

+272
-99
lines changed

10 files changed

+272
-99
lines changed

pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@
9090
<dependency>
9191
<groupId>com.uid2</groupId>
9292
<artifactId>uid2-client</artifactId>
93-
<version>4.3.22</version>
93+
<version>4.8.0</version>
9494
</dependency>
9595
<dependency>
9696
<groupId>org.assertj</groupId>

src/test/java/app/component/Operator.java

Lines changed: 21 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -260,10 +260,28 @@ public DecryptionResponse v2TokenDecrypt(String token) throws UID2ClientExceptio
260260
return dspClient.decrypt(token);
261261
}
262262

263+
// Need to use the manual mapping for error cases - SDK won't allow creating input with bad emails or disable optout check
263264
public JsonNode v2IdentityMap(String payload) throws Exception {
264-
V2Envelope envelope = v2CreateEnvelope(payload, getClientApiSecret());
265-
String encryptedResponse = HttpClient.post(getBaseUrl() + "/v2/identity/map", envelope.envelope(), getClientApiKey());
266-
return v2DecryptEncryptedResponse(encryptedResponse, envelope.nonce(), getClientApiSecret());
265+
V2Envelope envelope = v2CreateEnvelope(payload, CLIENT_API_SECRET);
266+
String encryptedResponse = HttpClient.post(getBaseUrl() + "/v2/identity/map", envelope.envelope(), CLIENT_API_KEY);
267+
return v2DecryptEncryptedResponse(encryptedResponse, envelope.nonce(), CLIENT_API_SECRET);
268+
}
269+
270+
public IdentityMapResponse v2IdentityMap(IdentityMapInput input) {
271+
IdentityMapClient identityMapClient = new IdentityMapClient(getBaseUrl(), CLIENT_API_KEY, CLIENT_API_SECRET);
272+
return identityMapClient.generateIdentityMap(input);
273+
}
274+
275+
// Need to use the manual mapping for error cases - SDK won't allow creating input with bad emails
276+
public JsonNode v3IdentityMap(String payload) throws Exception {
277+
V2Envelope envelope = v2CreateEnvelope(payload, CLIENT_API_SECRET);
278+
String encryptedResponse = HttpClient.post(getBaseUrl() + "/v3/identity/map", envelope.envelope(), CLIENT_API_KEY);
279+
return v2DecryptEncryptedResponse(encryptedResponse, envelope.nonce(), CLIENT_API_SECRET);
280+
}
281+
282+
public IdentityMapV3Response v3IdentityMap(IdentityMapV3Input input) {
283+
IdentityMapV3Client identityMapV3Client = new IdentityMapV3Client(getBaseUrl(), CLIENT_API_KEY, CLIENT_API_SECRET);
284+
return identityMapV3Client.generateIdentityMap(input);
267285
}
268286

269287
public JsonNode v2IdentityBuckets(String payload) throws Exception {
@@ -284,14 +302,6 @@ public JsonNode v2KeySharing() throws Exception {
284302
return v2DecryptEncryptedResponse(encryptedResponse, envelope.nonce(), CLIENT_API_SECRET);
285303
}
286304

287-
private String getClientApiKey() {
288-
return CLIENT_API_KEY;
289-
}
290-
291-
private String getClientApiSecret() {
292-
return CLIENT_API_SECRET;
293-
}
294-
295305
private V2Envelope v2CreateEnvelope(String payload, String secret) throws Exception {
296306
// Unencrypted envelope payload = timestamp + nonce + raw payload
297307
Instant timestamp = Instant.now();

src/test/java/app/component/Validator.java

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88

99
public class Validator extends App {
1010
private final PublisherUid2Helper publisherHelper;
11-
private final UID2Client dspClient;
1211
private final Headers standardHeaders;
1312
private final MediaType FORM = MediaType.get("application/x-www-form-urlencoded");;
1413

@@ -20,12 +19,6 @@ public Validator(String host, Integer port, String name, String clientApiKey, St
2019
.add("Authorization", "Bearer " + clientApiKey)
2120
.add("X-UID2-Client-Version: java-e2e-test")
2221
.build();
23-
24-
dspClient = new UID2Client(
25-
this.getBaseUrl(),
26-
clientApiKey,
27-
clientSecret,
28-
IdentityScope.UID2);
2922
}
3023

3124
public Response triggerGenerateTokenFromEmail(String email) throws IOException {

src/test/java/suite/E2ELocalFullTestSuite.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,9 @@
1414
BasicTest.class,
1515
CoreTest.class,
1616
CoreRefreshTest.class,
17-
V2ApiOperatorTest.class,
18-
V2ApiOperatorPublicOnlyTest.class,
19-
V2ApiOperatorLocalOnlyTest.class,
17+
OperatorTest.class,
18+
OperatorPublicOnlyTest.class,
19+
OperatorLocalOnlyTest.class,
2020
OptoutTest.class,
2121
V2ApiValidatorTest.class
2222
})

src/test/java/suite/E2EPrivateOperatorTestSuite.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,12 @@
33
import org.junit.platform.suite.api.SelectClasses;
44
import org.junit.platform.suite.api.Suite;
55
import suite.basic.BasicTest;
6-
import suite.operator.V2ApiOperatorTest;
6+
import suite.operator.OperatorTest;
77

88
@Suite
99
@SelectClasses({
1010
BasicTest.class,
11-
V2ApiOperatorTest.class
11+
OperatorTest.class
1212
})
1313
public class E2EPrivateOperatorTestSuite {
1414
}

src/test/java/suite/E2EPublicOperatorTestSuite.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,9 @@
1313
BasicTest.class,
1414
CoreTest.class,
1515
CoreRefreshTest.class,
16-
V2ApiOperatorTest.class,
17-
V2ApiOperatorPublicOnlyTest.class,
18-
V2ApiOperatorLocalOnlyTest.class,
16+
OperatorTest.class,
17+
OperatorPublicOnlyTest.class,
18+
OperatorLocalOnlyTest.class,
1919
OptoutTest.class
2020
})
2121
public class E2EPublicOperatorTestSuite {

src/test/java/suite/operator/V2ApiOperatorLocalOnlyTest.java renamed to src/test/java/suite/operator/OperatorLocalOnlyTest.java

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,6 @@
33
import app.component.App;
44
import app.component.Operator;
55
import com.uid2.client.*;
6-
import common.Const;
7-
import common.EnvUtil;
86
import org.junit.jupiter.api.condition.EnabledIf;
97
import org.junit.jupiter.params.ParameterizedTest;
108
import org.junit.jupiter.params.provider.MethodSource;
@@ -18,7 +16,7 @@
1816
import static org.junit.jupiter.api.Assertions.assertTrue;
1917

2018
@EnabledIf("common.EnabledCondition#isLocal")
21-
public class V2ApiOperatorLocalOnlyTest {
19+
public class OperatorLocalOnlyTest {
2220
@ParameterizedTest(name = "{index} ==> Sender {0} encrypts with {1}, recipient {2} decrypts with {3}, expected result is {4}")
2321
@MethodSource({
2422
"suite.operator.TestData#sharingArgs",

src/test/java/suite/operator/V2ApiOperatorPublicOnlyTest.java renamed to src/test/java/suite/operator/OperatorPublicOnlyTest.java

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,13 @@
99
import org.junit.jupiter.params.ParameterizedTest;
1010
import org.junit.jupiter.params.provider.MethodSource;
1111

12+
import java.util.List;
13+
1214
import static org.assertj.core.api.Assertions.assertThat;
1315
import static org.junit.jupiter.api.Assertions.*;
1416

1517
@SuppressWarnings("unused")
16-
public class V2ApiOperatorPublicOnlyTest {
18+
public class OperatorPublicOnlyTest {
1719
private static final String EMAIL_OPTOUT_ID = "[email protected]";
1820
private static final String PHONE_OPTOUT_ID = "+00000000001";
1921

@@ -81,6 +83,22 @@ public void testV2IdentityMapSpecialOptoutNoParam(String label, Operator operato
8183
assertThat(response.get("body").get("unmapped").get(0).get("reason").asText()).isEqualTo("optout");
8284
}
8385

86+
@ParameterizedTest(name = "/v3/identity/map - OPTOUT EMAIL, NO OPTOUT PARAM - {0} - {2} - Old Participant: {5}")
87+
@MethodSource({
88+
"suite.operator.TestData#tokenEmailArgsSpecialOptout",
89+
"suite.operator.TestData#tokenPhoneArgsSpecialOptout"
90+
})
91+
public void testV3IdentityMapSpecialOptout(String label, Operator operator, String operatorName, String type, String identity) throws Exception {
92+
if (isPrivateOperator(operator)) {
93+
return;
94+
}
95+
96+
String payload = "{\"" + type + "\": [\"" + identity + "\"]}";
97+
JsonNode response = operator.v3IdentityMap(payload);
98+
99+
assertThat(response.get("body").get(type).get(0).get("e").asText()).isEqualTo("optout");
100+
}
101+
84102
@EnabledIf("common.EnabledCondition#isLocal")
85103
@ParameterizedTest(name = "/v2/token/client-generate - {0} - {2}")
86104
@MethodSource({

src/test/java/suite/operator/V2ApiOperatorTest.java renamed to src/test/java/suite/operator/OperatorTest.java

Lines changed: 87 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,14 @@
1111
import org.junit.jupiter.params.provider.MethodSource;
1212

1313
import java.time.Duration;
14+
import java.time.Instant;
1415
import java.util.List;
1516

1617
import static org.assertj.core.api.Assertions.assertThat;
1718
import static org.junit.jupiter.api.Assertions.*;
1819

1920
@SuppressWarnings("unused")
20-
public class V2ApiOperatorTest {
21+
public class OperatorTest {
2122
/*
2223
TODO:
2324
/v2/token/generate - Add failure case
@@ -31,6 +32,7 @@ public class V2ApiOperatorTest {
3132

3233
private static final ObjectMapper OBJECT_MAPPER = Mapper.getInstance();
3334
private static final String CLIENT_SITE_ID = EnvUtil.getEnv(Const.Config.Operator.CLIENT_SITE_ID);
35+
private static final int RAW_UID_SIZE = 44;
3436

3537
@ParameterizedTest(name = "/v2/token/generate - {0} - {2}")
3638
@MethodSource({
@@ -96,39 +98,108 @@ public void testV2TokenValidate(String label, Operator operator, String operator
9698

9799
@ParameterizedTest(name = "/v2/identity/map - {0} - {2}")
98100
@MethodSource({
99-
"suite.operator.TestData#identityMapBatchEmailArgs",
100-
"suite.operator.TestData#identityMapBatchPhoneArgs",
101101
"suite.operator.TestData#identityMapBatchBadEmailArgs",
102102
"suite.operator.TestData#identityMapBatchBadPhoneArgs"
103103
})
104-
public void testV2IdentityMap(String label, Operator operator, String operatorName, String payload) throws Exception {
104+
public void testV2IdentityMapUnmapped(String label, Operator operator, String operatorName, String payload) throws Exception {
105105
JsonNode response = operator.v2IdentityMap(payload);
106106

107-
// TODO: Assert the value
108107
assertThat(response.at("/status").asText()).isEqualTo("success");
108+
assertThat(response.at("/body/unmapped/0/reason").asText()).isEqualTo("invalid identifier");
109109
}
110110

111111
@ParameterizedTest(name = "/v2/identity/map - {0} - {2}")
112112
@MethodSource({
113-
"suite.operator.TestData#identityMapBigBatchArgs"
113+
"suite.operator.TestData#identityMapBatchEmailArgs",
114+
"suite.operator.TestData#identityMapBatchPhoneArgs",
114115
})
115-
public void testV2IdentityMapLargeBatch(String label, Operator operator, String operatorName, String payload, List<String> diis) {
116-
assertTimeoutPreemptively(Duration.ofSeconds(5), () -> { // Validate we didn't make mapping too slow.
117-
JsonNode response = operator.v2IdentityMap(payload);
116+
public void testV2IdentityMapMapped(String label, Operator operator, String operatorName, String payload) throws Exception {
117+
JsonNode response = operator.v2IdentityMap(payload);
118118

119-
assertThat(response.at("/status").asText()).isEqualTo("success");
119+
// TODO: Assert the value
120+
assertThat(response.at("/status").asText()).isEqualTo("success");
121+
}
120122

121-
var mapped = response.at("/body/mapped");
122-
assertThat(mapped.size()).isEqualTo(10_000);
123+
@ParameterizedTest(name = "/v2/identity/map - {0} - {2}")
124+
@MethodSource({"suite.operator.TestData#identityMapArgs"})
125+
public void testV2IdentityMap(
126+
String label,
127+
Operator operator,
128+
String operatorName,
129+
IdentityMapInput input,
130+
List<String> diis
131+
) {
132+
assertTimeoutPreemptively(Duration.ofSeconds(5), () -> { // Validate we didn't make mapping too slow.
133+
var response = operator.v2IdentityMap(input);
134+
135+
assertThat(response.isSuccess()).isTrue();
136+
137+
assertThat(response.getUnmappedIdentities()).isEmpty();
138+
139+
var allMappedDiis = response.getMappedIdentities();
140+
assertThat(allMappedDiis.size()).isEqualTo(10_000);
141+
142+
for (var dii : diis) {
143+
var mappedDii = allMappedDiis.get(dii);
144+
assertThat(mappedDii).isNotNull();
145+
assertThat(mappedDii.getRawUid().length()).isEqualTo(RAW_UID_SIZE);
146+
assertThat(mappedDii.getBucketId()).isNotBlank();
147+
}
148+
});
149+
}
123150

124-
for (int i = 0; i < 10_000; i++) {
125-
assertThat(mapped.get(i).get("identifier").asText()).isEqualTo(diis.get(i));
126-
assertThat(mapped.get(i).get("advertising_id").asText()).isNotNull().isNotEmpty();
127-
assertThat(mapped.get(i).get("bucket_id").asText()).isNotNull().isNotEmpty();
151+
@ParameterizedTest(name = "/v3/identity/map - {0} - {2}")
152+
@MethodSource({"suite.operator.TestData#identityMapV3Args"})
153+
public void testV3IdentityMapLargeBatch(
154+
String label,
155+
Operator operator,
156+
String operatorName,
157+
IdentityMapV3Input input,
158+
List<String> diis
159+
) {
160+
assertTimeoutPreemptively(Duration.ofSeconds(5), () -> { // Validate we didn't make mapping too slow.
161+
var response = operator.v3IdentityMap(input);
162+
163+
assertThat(response.isSuccess()).isTrue();
164+
165+
assertThat(response.getUnmappedIdentities()).isEmpty();
166+
167+
var allMappedDiis = response.getMappedIdentities();
168+
assertThat(allMappedDiis.size()).isEqualTo(10_000);
169+
170+
for (var dii : diis) {
171+
var mappedDii = allMappedDiis.get(dii);
172+
assertThat(mappedDii).isNotNull();
173+
174+
// Current UID should always be there and should have correct length
175+
assertThat(mappedDii.getCurrentRawUid().length()).isEqualTo(RAW_UID_SIZE);
176+
177+
// Previous UID is there for 90 days after rotation only, then it's null.
178+
// If it's there, it should have the correct size
179+
assertThat(mappedDii.getPreviousRawUid()).satisfiesAnyOf(
180+
uid -> assertThat(uid).isNull(),
181+
uid -> assertThat(uid).hasSize(RAW_UID_SIZE)
182+
);
183+
184+
// Sanity check that refresh from is a date not too far in the past.
185+
// If it is, either there is an Operator issue or salt rotation hasn't been running for a long time.
186+
assertThat(mappedDii.getRefreshFrom()).isAfter(Instant.now().minus(Duration.ofHours(1)));
128187
}
129188
});
130189
}
131190

191+
@ParameterizedTest(name = "/v3/identity/map - {0} - {2}")
192+
@MethodSource({
193+
"suite.operator.TestData#identityMapV3BatchBadEmailArgs",
194+
"suite.operator.TestData#identityMapV3BatchBadPhoneArgs"
195+
})
196+
public void testV3IdentityMapUnmapped(String label, Operator operator, String operatorName, String payload, String identityType) throws Exception {
197+
JsonNode response = operator.v3IdentityMap(payload);
198+
199+
assertThat(response.at("/status").asText()).isEqualTo("success");
200+
assertThat(response.at("/body/" + identityType + "/0/e").asText()).isEqualTo("invalid identifier");
201+
}
202+
132203

133204
@ParameterizedTest(name = "/v2/identity/map - VALIDATE EMAIL - {0} - {2}")
134205
@MethodSource({

0 commit comments

Comments
 (0)