diff --git a/src/test/java/suite/operator/TestData.java b/src/test/java/suite/operator/TestData.java index 38a6df8..bee844e 100644 --- a/src/test/java/suite/operator/TestData.java +++ b/src/test/java/suite/operator/TestData.java @@ -3,13 +3,12 @@ import app.AppsMap; import app.component.App; import app.component.Operator; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; import com.uid2.client.DecryptionStatus; import org.junit.jupiter.params.provider.Arguments; -import java.util.HashSet; -import java.util.List; -import java.util.Optional; -import java.util.Set; +import java.util.*; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -17,6 +16,7 @@ public final class TestData { public static final int RAW_UID2_LENGTH = 44; + private static final Random RANDOM = new Random(); private TestData() { } @@ -326,6 +326,57 @@ public static Set identityMapBatchEmailArgs() { return args; } + public static Set identityMapBigBatchArgs() throws JsonProcessingException { + ObjectMapper mapper = new ObjectMapper(); + Set operators = AppsMap.getApps(Operator.class); + + List emails = new ArrayList<>(); + List phones = new ArrayList<>(); + List emailHashes = new ArrayList<>(); + List phoneHashes = new ArrayList<>(); + for (int i = 0; i < 10_000; i++) { + emails.add(randomEmail()); + phones.add(randomPhoneNumber()); + emailHashes.add(randomHash()); + phoneHashes.add(randomHash()); + } + + var emailsPayload = identityMapPayload(mapper, "email", emails); + var phonesPayload = identityMapPayload(mapper, "phone", phones); + var emailHashesPayload = identityMapPayload(mapper, "email_hash", emailHashes); + var phoneHashesPayload = identityMapPayload(mapper, "phone_hash", phoneHashes); + + Set args = new HashSet<>(); + for (Operator operator : operators) { + args.add(Arguments.of("10k emails", operator, operator.getName(), emailsPayload, emails)); + args.add(Arguments.of("10k phones", operator, operator.getName(), phonesPayload, phones)); + args.add(Arguments.of("10k email hashes", operator, operator.getName(), emailHashesPayload, emailHashes)); + args.add(Arguments.of("10k phone hashes", operator, operator.getName(), phoneHashesPayload, phoneHashes)); + } + return args; + } + + private static String identityMapPayload(ObjectMapper mapper, String field, List diis) throws JsonProcessingException { + var json = mapper.createObjectNode().putPOJO(field, diis).put("policy", 1); + return mapper.writeValueAsString(json); + } + + private static String randomEmail() { + return "email_" + Math.abs(RANDOM.nextLong()) + "@example.com"; + } + + private static String randomPhoneNumber() { + // Phone numbers with 15 digits are technically valid but are not used in any country + return "+" + String.format("%015d", Math.abs(RANDOM.nextLong() % 1_000_000_000_000_000L)); + } + + private static String randomHash() { + // This isn't really a hashed DII but looks like one ot UID2 + byte[] randomBytes = new byte[32]; + RANDOM.nextBytes(randomBytes); + return Base64.getEncoder().encodeToString(randomBytes); + } + public static Set identityMapBatchEmailArgsBadPolicy() { Set operators = getPublicOperators(); Set> inputs = Set.of( diff --git a/src/test/java/suite/operator/V2ApiOperatorTest.java b/src/test/java/suite/operator/V2ApiOperatorTest.java index 1a5430d..3800af1 100644 --- a/src/test/java/suite/operator/V2ApiOperatorTest.java +++ b/src/test/java/suite/operator/V2ApiOperatorTest.java @@ -10,6 +10,9 @@ import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.MethodSource; +import java.time.Duration; +import java.util.List; + import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.*; @@ -105,6 +108,28 @@ public void testV2IdentityMap(String label, Operator operator, String operatorNa assertThat(response.at("/status").asText()).isEqualTo("success"); } + @ParameterizedTest(name = "/v2/identity/map - {0} - {2}") + @MethodSource({ + "suite.operator.TestData#identityMapBigBatchArgs" + }) + public void testV2IdentityMapLargeBatch(String label, Operator operator, String operatorName, String payload, List diis) { + assertTimeoutPreemptively(Duration.ofSeconds(5), () -> { // Validate we didn't make mapping too slow. + JsonNode response = operator.v2IdentityMap(payload); + + assertThat(response.at("/status").asText()).isEqualTo("success"); + + var mapped = response.at("/body/mapped"); + assertThat(mapped.size()).isEqualTo(10_000); + + 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 = "/v2/identity/map - VALIDATE EMAIL - {0} - {2}") @MethodSource({ "suite.operator.TestData#tokenValidateEmailArgs",