Skip to content
Merged
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
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@
<dependency>
<groupId>com.uid2</groupId>
<artifactId>uid2-client</artifactId>
<version>4.3.22</version>
<version>4.8.0</version>
</dependency>
<dependency>
<groupId>org.assertj</groupId>
Expand Down
32 changes: 21 additions & 11 deletions src/test/java/app/component/Operator.java
Original file line number Diff line number Diff line change
Expand Up @@ -260,10 +260,28 @@ public DecryptionResponse v2TokenDecrypt(String token) throws UID2ClientExceptio
return dspClient.decrypt(token);
}

// Need to use the manual mapping for error cases - SDK won't allow creating input with bad emails or disable optout check
public JsonNode v2IdentityMap(String payload) throws Exception {
V2Envelope envelope = v2CreateEnvelope(payload, getClientApiSecret());
String encryptedResponse = HttpClient.post(getBaseUrl() + "/v2/identity/map", envelope.envelope(), getClientApiKey());
return v2DecryptEncryptedResponse(encryptedResponse, envelope.nonce(), getClientApiSecret());
V2Envelope envelope = v2CreateEnvelope(payload, CLIENT_API_SECRET);
String encryptedResponse = HttpClient.post(getBaseUrl() + "/v2/identity/map", envelope.envelope(), CLIENT_API_KEY);
return v2DecryptEncryptedResponse(encryptedResponse, envelope.nonce(), CLIENT_API_SECRET);
}

public IdentityMapResponse v2IdentityMap(IdentityMapInput input) {
IdentityMapClient identityMapClient = new IdentityMapClient(getBaseUrl(), CLIENT_API_KEY, CLIENT_API_SECRET);
return identityMapClient.generateIdentityMap(input);
}

// Need to use the manual mapping for error cases - SDK won't allow creating input with bad emails
public JsonNode v3IdentityMap(String payload) throws Exception {
V2Envelope envelope = v2CreateEnvelope(payload, CLIENT_API_SECRET);
String encryptedResponse = HttpClient.post(getBaseUrl() + "/v3/identity/map", envelope.envelope(), CLIENT_API_KEY);
return v2DecryptEncryptedResponse(encryptedResponse, envelope.nonce(), CLIENT_API_SECRET);
}

public IdentityMapV3Response v3IdentityMap(IdentityMapV3Input input) {
IdentityMapV3Client identityMapV3Client = new IdentityMapV3Client(getBaseUrl(), CLIENT_API_KEY, CLIENT_API_SECRET);
return identityMapV3Client.generateIdentityMap(input);
}

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

private String getClientApiKey() {
return CLIENT_API_KEY;
}

private String getClientApiSecret() {
return CLIENT_API_SECRET;
}

private V2Envelope v2CreateEnvelope(String payload, String secret) throws Exception {
// Unencrypted envelope payload = timestamp + nonce + raw payload
Instant timestamp = Instant.now();
Expand Down
7 changes: 0 additions & 7 deletions src/test/java/app/component/Validator.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@

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

Expand All @@ -20,12 +19,6 @@ public Validator(String host, Integer port, String name, String clientApiKey, St
.add("Authorization", "Bearer " + clientApiKey)
.add("X-UID2-Client-Version: java-e2e-test")
.build();

dspClient = new UID2Client(
this.getBaseUrl(),
clientApiKey,
clientSecret,
IdentityScope.UID2);
}

public Response triggerGenerateTokenFromEmail(String email) throws IOException {
Expand Down
6 changes: 3 additions & 3 deletions src/test/java/suite/E2ELocalFullTestSuite.java
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,9 @@
BasicTest.class,
CoreTest.class,
CoreRefreshTest.class,
V2ApiOperatorTest.class,
V2ApiOperatorPublicOnlyTest.class,
V2ApiOperatorLocalOnlyTest.class,
OperatorTest.class,
OperatorPublicOnlyTest.class,
OperatorLocalOnlyTest.class,
OptoutTest.class,
V2ApiValidatorTest.class
})
Expand Down
4 changes: 2 additions & 2 deletions src/test/java/suite/E2EPrivateOperatorTestSuite.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@
import org.junit.platform.suite.api.SelectClasses;
import org.junit.platform.suite.api.Suite;
import suite.basic.BasicTest;
import suite.operator.V2ApiOperatorTest;
import suite.operator.OperatorTest;

@Suite
@SelectClasses({
BasicTest.class,
V2ApiOperatorTest.class
OperatorTest.class
})
public class E2EPrivateOperatorTestSuite {
}
6 changes: 3 additions & 3 deletions src/test/java/suite/E2EPublicOperatorTestSuite.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,9 @@
BasicTest.class,
CoreTest.class,
CoreRefreshTest.class,
V2ApiOperatorTest.class,
V2ApiOperatorPublicOnlyTest.class,
V2ApiOperatorLocalOnlyTest.class,
OperatorTest.class,
OperatorPublicOnlyTest.class,
OperatorLocalOnlyTest.class,
OptoutTest.class
})
public class E2EPublicOperatorTestSuite {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,6 @@
import app.component.App;
import app.component.Operator;
import com.uid2.client.*;
import common.Const;
import common.EnvUtil;
import org.junit.jupiter.api.condition.EnabledIf;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.MethodSource;
Expand All @@ -18,7 +16,7 @@
import static org.junit.jupiter.api.Assertions.assertTrue;

@EnabledIf("common.EnabledCondition#isLocal")
public class V2ApiOperatorLocalOnlyTest {
public class OperatorLocalOnlyTest {
@ParameterizedTest(name = "{index} ==> Sender {0} encrypts with {1}, recipient {2} decrypts with {3}, expected result is {4}")
@MethodSource({
"suite.operator.TestData#sharingArgs",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,13 @@
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.MethodSource;

import java.util.List;

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

@SuppressWarnings("unused")
public class V2ApiOperatorPublicOnlyTest {
public class OperatorPublicOnlyTest {
private static final String EMAIL_OPTOUT_ID = "optout@unifiedid.com";
private static final String PHONE_OPTOUT_ID = "+00000000001";

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

@ParameterizedTest(name = "/v3/identity/map - OPTOUT EMAIL, NO OPTOUT PARAM - {0} - {2} - Old Participant: {5}")
@MethodSource({
"suite.operator.TestData#tokenEmailArgsSpecialOptout",
"suite.operator.TestData#tokenPhoneArgsSpecialOptout"
})
public void testV3IdentityMapSpecialOptout(String label, Operator operator, String operatorName, String type, String identity) throws Exception {
if (isPrivateOperator(operator)) {
return;
}

String payload = "{\"" + type + "\": [\"" + identity + "\"]}";
JsonNode response = operator.v3IdentityMap(payload);

assertThat(response.get("body").get(type).get(0).get("e").asText()).isEqualTo("optout");
}

@EnabledIf("common.EnabledCondition#isLocal")
@ParameterizedTest(name = "/v2/token/client-generate - {0} - {2}")
@MethodSource({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,14 @@
import org.junit.jupiter.params.provider.MethodSource;

import java.time.Duration;
import java.time.Instant;
import java.util.List;

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

@SuppressWarnings("unused")
public class V2ApiOperatorTest {
public class OperatorTest {
/*
TODO:
/v2/token/generate - Add failure case
Expand All @@ -31,6 +32,7 @@ public class V2ApiOperatorTest {

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

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

@ParameterizedTest(name = "/v2/identity/map - {0} - {2}")
@MethodSource({
"suite.operator.TestData#identityMapBatchEmailArgs",
"suite.operator.TestData#identityMapBatchPhoneArgs",
"suite.operator.TestData#identityMapBatchBadEmailArgs",
"suite.operator.TestData#identityMapBatchBadPhoneArgs"
})
public void testV2IdentityMap(String label, Operator operator, String operatorName, String payload) throws Exception {
public void testV2IdentityMapUnmapped(String label, Operator operator, String operatorName, String payload) throws Exception {
JsonNode response = operator.v2IdentityMap(payload);

// TODO: Assert the value
assertThat(response.at("/status").asText()).isEqualTo("success");
assertThat(response.at("/body/unmapped/0/reason").asText()).isEqualTo("invalid identifier");
}

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

assertThat(response.at("/status").asText()).isEqualTo("success");
// TODO: Assert the value
assertThat(response.at("/status").asText()).isEqualTo("success");
}

var mapped = response.at("/body/mapped");
assertThat(mapped.size()).isEqualTo(10_000);
@ParameterizedTest(name = "/v2/identity/map - {0} - {2}")
@MethodSource({"suite.operator.TestData#identityMapArgs"})
public void testV2IdentityMap(
String label,
Operator operator,
String operatorName,
IdentityMapInput input,
List<String> diis
) {
assertTimeoutPreemptively(Duration.ofSeconds(5), () -> { // Validate we didn't make mapping too slow.
var response = operator.v2IdentityMap(input);

assertThat(response.isSuccess()).isTrue();

assertThat(response.getUnmappedIdentities()).isEmpty();

var allMappedDiis = response.getMappedIdentities();
assertThat(allMappedDiis.size()).isEqualTo(10_000);

for (var dii : diis) {
var mappedDii = allMappedDiis.get(dii);
assertThat(mappedDii).isNotNull();
assertThat(mappedDii.getRawUid().length()).isEqualTo(RAW_UID_SIZE);
assertThat(mappedDii.getBucketId()).isNotBlank();
}
});
}

for (int i = 0; i < 10_000; i++) {
assertThat(mapped.get(i).get("identifier").asText()).isEqualTo(diis.get(i));
assertThat(mapped.get(i).get("advertising_id").asText()).isNotNull().isNotEmpty();
assertThat(mapped.get(i).get("bucket_id").asText()).isNotNull().isNotEmpty();
@ParameterizedTest(name = "/v3/identity/map - {0} - {2}")
@MethodSource({"suite.operator.TestData#identityMapV3Args"})
public void testV3IdentityMapLargeBatch(
String label,
Operator operator,
String operatorName,
IdentityMapV3Input input,
List<String> diis
) {
assertTimeoutPreemptively(Duration.ofSeconds(5), () -> { // Validate we didn't make mapping too slow.
var response = operator.v3IdentityMap(input);

assertThat(response.isSuccess()).isTrue();

assertThat(response.getUnmappedIdentities()).isEmpty();

var allMappedDiis = response.getMappedIdentities();
assertThat(allMappedDiis.size()).isEqualTo(10_000);

for (var dii : diis) {
var mappedDii = allMappedDiis.get(dii);
assertThat(mappedDii).isNotNull();

// Current UID should always be there and should have correct length
assertThat(mappedDii.getCurrentRawUid().length()).isEqualTo(RAW_UID_SIZE);

// Previous UID is there for 90 days after rotation only, then it's null.
// If it's there, it should have the correct size
assertThat(mappedDii.getPreviousRawUid()).satisfiesAnyOf(
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We don't want to do an assertion based on the dii's last updated?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We don't expose that to clients so can't get it in e2e test and I don't want to start going to S3 and parsing salt files from e2e tests.

uid -> assertThat(uid).isNull(),
uid -> assertThat(uid).hasSize(RAW_UID_SIZE)
);

// Sanity check that refresh from is a date not too far in the past.
// If it is, either there is an Operator issue or salt rotation hasn't been running for a long time.
assertThat(mappedDii.getRefreshFrom()).isAfter(Instant.now().minus(Duration.ofHours(1)));
}
});
}

@ParameterizedTest(name = "/v3/identity/map - {0} - {2}")
@MethodSource({
"suite.operator.TestData#identityMapV3BatchBadEmailArgs",
"suite.operator.TestData#identityMapV3BatchBadPhoneArgs"
})
public void testV3IdentityMapUnmapped(String label, Operator operator, String operatorName, String payload, String identityType) throws Exception {
JsonNode response = operator.v3IdentityMap(payload);

assertThat(response.at("/status").asText()).isEqualTo("success");
assertThat(response.at("/body/" + identityType + "/0/e").asText()).isEqualTo("invalid identifier");
}


@ParameterizedTest(name = "/v2/identity/map - VALIDATE EMAIL - {0} - {2}")
@MethodSource({
Expand Down
Loading