Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[UID2-2022] Add tests for opt out status API #36

Merged
merged 4 commits into from
Jun 12, 2024
Merged
Show file tree
Hide file tree
Changes from 3 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
6 changes: 6 additions & 0 deletions src/test/java/app/component/Operator.java
Original file line number Diff line number Diff line change
Expand Up @@ -363,6 +363,12 @@ public JsonNode v2IdentityBuckets(String payload) throws Exception {
return v2DecryptEncryptedResponse(encryptedResponse, envelope.nonce(), CLIENT_API_SECRET);
}

public JsonNode v2OptOutStatus(String payload) throws Exception {
V2Envelope envelope = v2CreateEnvelope(payload, CLIENT_API_SECRET);
String encryptedResponse = HttpClient.post(getBaseUrl() + "/v2/optout/status", envelope.envelope(), CLIENT_API_KEY);
return v2DecryptEncryptedResponse(encryptedResponse, envelope.nonce(), CLIENT_API_SECRET);
}

public JsonNode v2KeySharing() throws Exception {
V2Envelope envelope = v2CreateEnvelope("", CLIENT_API_SECRET);
String encryptedResponse = HttpClient.post(getBaseUrl() + "/v2/key/sharing", envelope.envelope(), CLIENT_API_KEY);
Expand Down
73 changes: 69 additions & 4 deletions src/test/java/suite/optout/OptoutTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,15 @@
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;
import org.awaitility.Awaitility.*;

import java.time.Instant;
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.function.Function;

import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assumptions.assumeThat;
import static org.awaitility.Awaitility.await;
import static org.awaitility.Awaitility.with;

@SuppressWarnings("unused")
Expand All @@ -29,10 +28,12 @@ public class OptoutTest {
private static final int OPTOUT_WAIT_SECONDS = 300;

private static Set<Arguments> outputArgs;
private static Set<Arguments> outputAdvertisingIdArgs;

@BeforeAll
public static void setupAll() {
outputArgs = new HashSet<>();
outputAdvertisingIdArgs = new HashSet<>();
}

@ParameterizedTest(name = "/v2/token/logout with /v0/token/generate - {0} - {2}")
Expand Down Expand Up @@ -120,7 +121,26 @@ public void testV2LogoutWithV2TokenGenerateOldParticipant(String label, Operator
);
}

@ParameterizedTest(name = "/v2/token/logout with /v2/identity/map - {0} - {2}")
@MethodSource({
"suite.optout.TestData#identityMapEmailArgs",
"suite.optout.TestData#identityMapPhoneArgs"
})
@Order(5)
public void testV2LogoutWithV2IdentityMap(String label, Operator operator, String operatorName, String type, String emailOrPhone, boolean toOptOut) throws Exception {
JsonNode identityMapResponseNode = operator.v2IdentityMap("{\""+ type + "\":[\"" + emailOrPhone + "\"]}", false);
assertThat(identityMapResponseNode.at("/status").asText()).isEqualTo("success");
String rawUID = identityMapResponseNode.get("body").get("mapped").get(0).get(TestData.ADVERTISING_ID).asText();
long beforeOptOutTimestamp = Instant.now().toEpochMilli();
if (toOptOut) {
Thread.sleep(OPTOUT_DELAY_MS);
JsonNode logoutResponse = operator.v2TokenLogout(type, emailOrPhone);
assertThat(logoutResponse).isEqualTo(Mapper.OBJECT_MAPPER.readTree("{\"body\":{\"optout\":\"OK\"},\"status\":\"success\"}"));
}
outputAdvertisingIdArgs.add(Arguments.of(label, operator, operatorName, rawUID, toOptOut, beforeOptOutTimestamp));
}

@Order(6)
@ParameterizedTest(name = "/v0/token/refresh after {2} generate and {3} logout - {0} - {1}")
@MethodSource({
"afterOptoutTokenArgs"
Expand All @@ -130,7 +150,7 @@ public void testV0TokenRefreshAfterOptOut(String label, Operator operator, Strin
this.waitForOptOutResponse(operator::v0CheckedTokenRefresh, refreshToken, "{\"advertisement_token\":\"\",\"advertising_token\":\"\",\"refresh_token\":\"\"}");
}

@Order(6)
@Order(7)
@ParameterizedTest(name = "/v1/token/refresh after {2} generate and {3} logout - {0} - {1}")
@MethodSource({
"afterOptoutTokenArgs"
Expand All @@ -140,7 +160,7 @@ public void testV1TokenRefreshAfterOptOut(String label, Operator operator, Strin
this.waitForOptOutResponse(operator::v1CheckedTokenRefresh, refreshToken, "{\"status\":\"optout\"}");
}

@Order(7)
@Order(8)
@ParameterizedTest(name = "/v2/token/refresh after {2} generate and {3} logout - {0} - {1}")
@MethodSource({
"afterOptoutTokenArgs"
Expand All @@ -151,10 +171,55 @@ public void testV2TokenRefreshAfterOptOut(String label, Operator operator, Strin
with().pollInterval(5, TimeUnit.SECONDS).await("Get V2 Token Response").atMost(OPTOUT_WAIT_SECONDS, TimeUnit.SECONDS).until(() -> operator.v2TokenRefresh(refreshToken, refreshResponseKey).equals(Mapper.OBJECT_MAPPER.readTree("{\"status\":\"optout\"}")));
}

@Order(9)
@ParameterizedTest(name = "/v2/optout/status after v2/identity/map and v2/token/logout - DII {0} - expecting {4} - {2}")
Copy link
Collaborator

Choose a reason for hiding this comment

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

Maybe we can change the {0} in the other tests to DII {0} as well?

@MethodSource({"afterOptoutAdvertisingIdArgs"})
Copy link
Collaborator

Choose a reason for hiding this comment

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

To clarify: this is getting updated by running previous tests first - specifically testV2LogoutWithV2IdentityMap()

Can't the assertions here be applied to existing tests?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

are you suggesting I merge the two tests ? Yes I can merge them. Having separate tests has the advantage that the test needs to wait for less time for the opt out data to flow through, since there are other methods which run before it.
Do you see any benefit in merging them ?

Copy link
Collaborator

Choose a reason for hiding this comment

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

Nope that makes sense, thanks for the clarification

public void testV2OptOutStatus(String label, Operator operator, String operatorName, String rawUID,
boolean isOptedOut, long optedOutTimestamp) throws Exception {
String payload = "{\"advertising_ids\":[\"" + rawUID + "\"]}";
with().pollInterval(5, TimeUnit.SECONDS)
.await("Get Opt out status response")
.atMost(OPTOUT_WAIT_SECONDS, TimeUnit.SECONDS)
.until(() -> {
JsonNode response = operator.v2OptOutStatus(payload);
JsonNode body = response.get("body");
JsonNode optedOutJsonNode = body.get("opted_out");
if (isOptedOut) {
return optedOutJsonNode.size() == 1;

} else {
return optedOutJsonNode.isEmpty();
}
});
JsonNode response = operator.v2OptOutStatus(payload);
assertThat(response.at("/status").asText()).isEqualTo("success");
JsonNode body = response.get("body");
assertThat(body).isNotNull();
JsonNode optedOutJsonNode = body.get("opted_out");
assertThat(optedOutJsonNode).isNotNull();
if (isOptedOut) {
assertThat(optedOutJsonNode.size()).isEqualTo(1);
JsonNode optedOutRecord = optedOutJsonNode.get(0);
assertThat(optedOutRecord).isNotNull();
assertThat(optedOutRecord.has(TestData.ADVERTISING_ID)).isTrue();
String advertisingId = optedOutRecord.get(TestData.ADVERTISING_ID).asText();
assertThat(advertisingId).isEqualTo(rawUID);
assertThat(optedOutRecord.has(TestData.OPTED_OUT_SINCE)).isTrue();
long optedOutSinceMilliseconds = optedOutRecord.get(TestData.OPTED_OUT_SINCE).asLong();
assertThat(optedOutSinceMilliseconds).isGreaterThanOrEqualTo(optedOutTimestamp);
} else {
assertThat(optedOutJsonNode.size()).isEqualTo(0);
}
}

private static Set<Arguments> afterOptoutTokenArgs() {
return outputArgs;
}

private static Set<Arguments> afterOptoutAdvertisingIdArgs() {
return outputAdvertisingIdArgs;
}

private void addToken(String label, Operator operator, String tokenGenerateVersion, String tokenLogoutVersion, String refreshToken, String refreshResponseKey) {
outputArgs.add(Arguments.of(label, operator, tokenGenerateVersion, tokenLogoutVersion, refreshToken, refreshResponseKey));
}
Expand Down
73 changes: 58 additions & 15 deletions src/test/java/suite/optout/TestData.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
import java.util.stream.Collectors;

public final class TestData {
public static final String ADVERTISING_ID = "advertising_id";
public static final String OPTED_OUT_SINCE = "opted_out_since";
private static final boolean PHONE_SUPPORT = Boolean.parseBoolean(EnvUtil.getEnv("UID2_E2E_PHONE_SUPPORT"));

private TestData() {
Expand All @@ -34,12 +36,8 @@ public static Set<Arguments> tokenEmailArgs() {

public static Set<Arguments> optoutTokenEmailArgs() {
Set<Operator> operators = getPublicOperators();
Random random = new Random();
int number = random.nextInt(100000000);
String email = "test.email" + number + "@" + getRandomString(2, 10) + "." + getRandomString(2, 10);
Set<List<String>> inputs = Set.of(
List.of("good email", "email", email)
);

Set<List<String>> inputs = generateEmailSet(1);

Set<Arguments> args = new HashSet<>();
for (Operator operator : operators) {
Expand Down Expand Up @@ -69,15 +67,7 @@ public static Set<Arguments> tokenPhoneArgs() {

public static Set<Arguments> optoutTokenPhoneArgs() {
Set<Operator> operators = getPublicOperators();
Random random = new Random();
StringBuilder phone = new StringBuilder(String.valueOf(random.nextLong((10000000000L - 1000000000L) +1) + 1000000000L));
while (phone.length() < 10) {
phone.insert(0, "0");
}
phone.insert(0, "+0");
Set<List<String>> inputs = Set.of(
List.of("good phone", "phone", phone.toString())
);
Set<List<String>> inputs = generatePhoneSet(1);

Set<Arguments> args = new HashSet<>();
if (PHONE_SUPPORT) {
Expand All @@ -90,6 +80,59 @@ public static Set<Arguments> optoutTokenPhoneArgs() {
return args;
}

public static Set<Arguments> identityMapEmailArgs() {
Set<Operator> operators = getPublicOperators();
Set<List<String>> inputs = generateEmailSet(4);

Set<Arguments> args = new HashSet<>();
for (Operator operator : operators) {
for (List<String> input : inputs) {
args.add(Arguments.of(input.get(0), operator, operator.getName(), input.get(1), input.get(2), Boolean.parseBoolean(input.get(3))));
}
}
return args;
}

public static Set<Arguments> identityMapPhoneArgs() {
Set<Operator> operators = getPublicOperators();
Set<List<String>> inputs = generatePhoneSet(4);

Set<Arguments> args = new HashSet<>();
for (Operator operator : operators) {
for (List<String> input : inputs) {
args.add(Arguments.of(input.get(0), operator, operator.getName(), input.get(1), input.get(2), Boolean.parseBoolean(input.get(3))));
}
}
return args;
}

private static Set<List<String>> generateEmailSet(int count) {
Random random = new Random();
Set<List<String>> inputs = new HashSet<>(count);
for (int i = 0; i < count; ++i) {
int number = random.nextInt(100000000);
String email = "test.email" + number + "@" + getRandomString(2, 10) + "." + getRandomString(2, 10);
inputs.add(List.of("good email " + (i + 1), "email", email, i % 2 == 0 ? "true" : "false"));
}

return inputs;
}

private static Set<List<String>> generatePhoneSet(int count) {
Random random = new Random();
Set<List<String>> inputs = new HashSet<>();
final long bound = (10000000000L - 1000000000L) + 1;
for (int i = 0; i < count; ++i) {
StringBuilder phone = new StringBuilder(String.valueOf(random.nextLong(bound) + 1000000000L));
while (phone.length() < 10) {
phone.insert(0, "0");
}
phone.insert(0, "+0");
inputs.add(List.of("good phone " + (i + 1), "phone", phone.toString(), i % 2 == 0 ? "true" : "false"));
}
return inputs;
}

private static String getRandomString(int minLength, int maxLength) {
String alphabet = "abcdefghijklmnopqrstuvwxyz0123456789";
StringBuilder s = new StringBuilder();
Expand Down
Loading