From 3f4aadbaae13469bc66c7d9d06b8aec051d2c8bb Mon Sep 17 00:00:00 2001 From: Cody Constine Date: Fri, 11 Oct 2024 22:57:08 -0600 Subject: [PATCH 1/3] Started trying to add new tests --- pom.xml | 32 +++++ src/main/resources/localstack/init-aws.sh | 0 src/test/java/com/uid2/optout/TestUtils.java | 20 +++- .../uid2/optout/vertx/OptOutSenderTest.java | 109 ++++++++++++++++++ 4 files changed, 158 insertions(+), 3 deletions(-) mode change 100644 => 100755 src/main/resources/localstack/init-aws.sh create mode 100644 src/test/java/com/uid2/optout/vertx/OptOutSenderTest.java diff --git a/pom.xml b/pom.xml index 8a9110d..2e53e3a 100644 --- a/pom.xml +++ b/pom.xml @@ -18,6 +18,8 @@ 1.1.0 7.19.0 ${project.version} + 5.10.1 + 5.10.1 @@ -69,6 +71,36 @@ vertx-micrometer-metrics ${vertx.version} + + org.junit.jupiter + junit-jupiter-api + ${junit-jupiter.version} + test + + + org.junit.jupiter + junit-jupiter-engine + ${junit-jupiter.version} + test + + + org.junit.jupiter + junit-jupiter-params + ${junit-jupiter.version} + test + + + io.vertx + vertx-junit5 + ${vertx.version} + test + + + org.mockito + mockito-core + 5.10.0 + test + io.micrometer micrometer-registry-jmx diff --git a/src/main/resources/localstack/init-aws.sh b/src/main/resources/localstack/init-aws.sh old mode 100644 new mode 100755 diff --git a/src/test/java/com/uid2/optout/TestUtils.java b/src/test/java/com/uid2/optout/TestUtils.java index c52e5f4..1981bbf 100644 --- a/src/test/java/com/uid2/optout/TestUtils.java +++ b/src/test/java/com/uid2/optout/TestUtils.java @@ -64,12 +64,26 @@ public static String newDeltaFile(long... ids) { return newDeltaFile(TestUtils.toEntries(ids)); } + public static String newDeltaFile(Path path, long... ids) { + return newDeltaFile(TestUtils.toEntries(ids), path); + } + public static String newDeltaFile(OptOutEntry[] entries) { + Path tmpFile; + try { + tmpFile = Files.createTempFile(OptOutUtils.prefixDeltaFile, newSuffix()); + } catch (IOException e) { + e.printStackTrace(); + return null; + } + return newDeltaFile(entries, tmpFile); + } + + public static String newDeltaFile(OptOutEntry[] entries, Path path) { try { - Path tmpFile = Files.createTempFile(OptOutUtils.prefixDeltaFile, newSuffix()); OptOutCollection store = new OptOutCollection(entries); - Files.write(tmpFile, store.getStore(), StandardOpenOption.CREATE); - return tmpFile.toString(); + Files.write(path, store.getStore(), StandardOpenOption.CREATE); + return path.toString(); } catch (IOException e) { e.printStackTrace(); return null; diff --git a/src/test/java/com/uid2/optout/vertx/OptOutSenderTest.java b/src/test/java/com/uid2/optout/vertx/OptOutSenderTest.java new file mode 100644 index 0000000..2ff563b --- /dev/null +++ b/src/test/java/com/uid2/optout/vertx/OptOutSenderTest.java @@ -0,0 +1,109 @@ +package com.uid2.optout.vertx; + +import com.uid2.optout.Const; +import com.uid2.optout.TestUtils; +import com.uid2.optout.partner.IOptOutPartnerEndpoint; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Path; +import java.nio.file.Paths; +import io.micrometer.core.instrument.Metrics; +import io.micrometer.core.instrument.simple.SimpleMeterRegistry; +import io.vertx.core.Vertx; +import io.vertx.core.json.JsonObject; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.TestInfo; +import org.junit.jupiter.api.extension.ExtendWith; +import io.vertx.junit5.VertxExtension; +import io.vertx.junit5.VertxTestContext; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; + +import java.nio.file.Files; + +import static org.mockito.Mockito.when; + +@ExtendWith(VertxExtension.class) +public class OptOutSenderTest { + + private AutoCloseable mocks; + @Mock + private IOptOutPartnerEndpoint optOutPartnerEndpoint; + private final String partnerName = "testPartner"; + private final String filePath = "/tmp/uid2/optout"; + private final String eventBusName = "testEventBus"; + private OptOutSender optoutSender; + private final JsonObject config = new JsonObject(); + + private SimpleMeterRegistry registry; + + @BeforeEach + public void setup() { + new File(filePath + "/consumer/delta").mkdirs(); + } + + public void deployVerticle(Vertx vertx, VertxTestContext testContext) { + mocks = MockitoAnnotations.openMocks(this); + + setupConfig(); + setupMocks(); + + this.optoutSender = new OptOutSender(config, optOutPartnerEndpoint, eventBusName); + + vertx.deployVerticle(optoutSender, testContext.succeeding(id -> testContext.completeNow())); + + this.registry = new SimpleMeterRegistry(); + Metrics.globalRegistry.add(registry); + } + + private void setupMocks() { + when(optOutPartnerEndpoint.name()).thenReturn(partnerName); + } + + private void setupConfig() { + config.put(Const.Config.OptOutDataDirProp, filePath); + config.put(Const.Config.OptOutProducerReplicaIdProp, 1); + + config.put(Const.Config.OptOutSenderReplicaIdProp, 1); + config.put(Const.Config.OptOutProducerMaxReplicasProp, 1); + + config.put(Const.Config.OptOutDeltaRotateIntervalProp, 300); + } + + //@AfterEach + public void cleanup() throws IOException { + Files.walk(Paths.get(filePath)) + .map(Path::toFile) + .forEach(File::delete); + } + + private Path getDeltaPath() { + return Paths.get(filePath, "consumer/delta", "optout-delta-" + TestUtils.newSuffix()); + } + + + // Also tests ScanLocalForUnprocessedWithNoNewFiles + @Test + void verticleDeployed(Vertx vertx, VertxTestContext testContext) { + deployVerticle(vertx, testContext); + testContext.completeNow(); + } + + @Test + void testScanLocalForUnprocessedWithNewFile(Vertx vertx, VertxTestContext testContext) { + TestUtils.newDeltaFile(getDeltaPath(), 1, 2, 3); + deployVerticle(vertx, testContext); + testContext.completeNow(); + } + + @Test + void testRecieveMessage(Vertx vertx, VertxTestContext testContext) { + deployVerticle(vertx, testContext); + Path newFile = getDeltaPath(); + TestUtils.newDeltaFile(newFile, 1, 2, 3); + vertx.eventBus().publish(eventBusName, newFile.getFileName().toString()); + } +} From f503a4bf1de4e452d26faa812534b9a5c7208bcb Mon Sep 17 00:00:00 2001 From: Cody Constine Date: Mon, 21 Oct 2024 14:26:53 -0600 Subject: [PATCH 2/3] Got tests to work for sending the new deltas to partners --- .../uid2/optout/vertx/OptOutSenderTest.java | 29 ++++++++++++++----- 1 file changed, 22 insertions(+), 7 deletions(-) diff --git a/src/test/java/com/uid2/optout/vertx/OptOutSenderTest.java b/src/test/java/com/uid2/optout/vertx/OptOutSenderTest.java index 2ff563b..c46cbeb 100644 --- a/src/test/java/com/uid2/optout/vertx/OptOutSenderTest.java +++ b/src/test/java/com/uid2/optout/vertx/OptOutSenderTest.java @@ -10,12 +10,12 @@ import java.nio.file.Paths; import io.micrometer.core.instrument.Metrics; import io.micrometer.core.instrument.simple.SimpleMeterRegistry; +import io.vertx.core.Future; import io.vertx.core.Vertx; import io.vertx.core.json.JsonObject; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.TestInfo; import org.junit.jupiter.api.extension.ExtendWith; import io.vertx.junit5.VertxExtension; import io.vertx.junit5.VertxTestContext; @@ -23,8 +23,11 @@ import org.mockito.MockitoAnnotations; import java.nio.file.Files; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.TimeUnit; -import static org.mockito.Mockito.when; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.*; @ExtendWith(VertxExtension.class) public class OptOutSenderTest { @@ -35,6 +38,7 @@ public class OptOutSenderTest { private final String partnerName = "testPartner"; private final String filePath = "/tmp/uid2/optout"; private final String eventBusName = "testEventBus"; + private CompletableFuture test; private OptOutSender optoutSender; private final JsonObject config = new JsonObject(); @@ -49,7 +53,7 @@ public void deployVerticle(Vertx vertx, VertxTestContext testContext) { mocks = MockitoAnnotations.openMocks(this); setupConfig(); - setupMocks(); + setupMocks(vertx); this.optoutSender = new OptOutSender(config, optOutPartnerEndpoint, eventBusName); @@ -59,8 +63,13 @@ public void deployVerticle(Vertx vertx, VertxTestContext testContext) { Metrics.globalRegistry.add(registry); } - private void setupMocks() { + private void setupMocks(Vertx vertx) { when(optOutPartnerEndpoint.name()).thenReturn(partnerName); + test = new CompletableFuture(); + when(optOutPartnerEndpoint.send(any())).then((a) -> { + test.complete(null); + return Future.fromCompletionStage(test, vertx.getOrCreateContext()); + }); } private void setupConfig() { @@ -73,7 +82,7 @@ private void setupConfig() { config.put(Const.Config.OptOutDeltaRotateIntervalProp, 300); } - //@AfterEach + @AfterEach public void cleanup() throws IOException { Files.walk(Paths.get(filePath)) .map(Path::toFile) @@ -99,11 +108,17 @@ void testScanLocalForUnprocessedWithNewFile(Vertx vertx, VertxTestContext testCo testContext.completeNow(); } + // If this test hangs delete the /tmp/uid2/optout folder and run again. @Test - void testRecieveMessage(Vertx vertx, VertxTestContext testContext) { + void testRecieveMessage(Vertx vertx, VertxTestContext testContext) throws InterruptedException { deployVerticle(vertx, testContext); Path newFile = getDeltaPath(); TestUtils.newDeltaFile(newFile, 1, 2, 3); - vertx.eventBus().publish(eventBusName, newFile.getFileName().toString()); + vertx.eventBus().publish(eventBusName, newFile.toString()); + + while(!test.isDone()) { + Thread.sleep(100); + } + verify(optOutPartnerEndpoint, times(3)).send(any()); } } From f109230426bdc8ac9949ca05c1c4c01ca7892bff Mon Sep 17 00:00:00 2001 From: Cody Constine Date: Tue, 22 Oct 2024 11:32:22 -0600 Subject: [PATCH 3/3] Adding test for partner config --- .../uid2/optout/vertx/OptOutSenderTest.java | 5 +- .../vertx/PartnerConfigMonitorV2Test.java | 114 ++++++++++++++++++ 2 files changed, 118 insertions(+), 1 deletion(-) create mode 100644 src/test/java/com/uid2/optout/vertx/PartnerConfigMonitorV2Test.java diff --git a/src/test/java/com/uid2/optout/vertx/OptOutSenderTest.java b/src/test/java/com/uid2/optout/vertx/OptOutSenderTest.java index c46cbeb..79f2f32 100644 --- a/src/test/java/com/uid2/optout/vertx/OptOutSenderTest.java +++ b/src/test/java/com/uid2/optout/vertx/OptOutSenderTest.java @@ -8,6 +8,8 @@ import java.io.IOException; import java.nio.file.Path; import java.nio.file.Paths; + +import com.uid2.shared.optout.OptOutEntry; import io.micrometer.core.instrument.Metrics; import io.micrometer.core.instrument.simple.SimpleMeterRegistry; import io.vertx.core.Future; @@ -110,7 +112,7 @@ void testScanLocalForUnprocessedWithNewFile(Vertx vertx, VertxTestContext testCo // If this test hangs delete the /tmp/uid2/optout folder and run again. @Test - void testRecieveMessage(Vertx vertx, VertxTestContext testContext) throws InterruptedException { + void testRecieveMessageAndSendsIDs(Vertx vertx, VertxTestContext testContext) throws InterruptedException { deployVerticle(vertx, testContext); Path newFile = getDeltaPath(); TestUtils.newDeltaFile(newFile, 1, 2, 3); @@ -120,5 +122,6 @@ void testRecieveMessage(Vertx vertx, VertxTestContext testContext) throws Interr Thread.sleep(100); } verify(optOutPartnerEndpoint, times(3)).send(any()); + testContext.completeNow(); } } diff --git a/src/test/java/com/uid2/optout/vertx/PartnerConfigMonitorV2Test.java b/src/test/java/com/uid2/optout/vertx/PartnerConfigMonitorV2Test.java new file mode 100644 index 0000000..6e3ab08 --- /dev/null +++ b/src/test/java/com/uid2/optout/vertx/PartnerConfigMonitorV2Test.java @@ -0,0 +1,114 @@ +package com.uid2.optout.vertx; + +import com.uid2.optout.Const; +import com.uid2.shared.cloud.CloudStorageException; +import com.uid2.shared.cloud.DownloadCloudStorage; +import io.vertx.core.Vertx; +import io.vertx.core.json.JsonObject; +import io.vertx.junit5.VertxExtension; +import io.vertx.junit5.VertxTestContext; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import static org.junit.jupiter.api.Assertions.*; + +import java.io.ByteArrayInputStream; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.when; + +@ExtendWith(VertxExtension.class) +public class PartnerConfigMonitorV2Test { + private AutoCloseable mocks; + private final String filePath = "/tmp/uid2/optout"; + private final JsonObject config = new JsonObject(); + private final String eventBusName = "testEventBus"; + + @Mock + private DownloadCloudStorage metadataStorage; + @Mock + private DownloadCloudStorage contentStorage; + + private PartnerConfigMonitorV2 partnerConfigMonitorV2; + + @BeforeEach + public void deployVerticle(Vertx vertx, VertxTestContext testContext) { + mocks = MockitoAnnotations.openMocks(this); + + setupConfig(); + + partnerConfigMonitorV2 = new PartnerConfigMonitorV2(vertx, config, metadataStorage, contentStorage, eventBusName); + testContext.completeNow(); + } + + private void setupConfig() { + config.put(Const.Config.OptOutDataDirProp, filePath); + config.put(Const.Config.OptOutProducerReplicaIdProp, 1); + + config.put(Const.Config.OptOutSenderReplicaIdProp, 1); + config.put(Const.Config.OptOutProducerMaxReplicasProp, 1); + + config.put(Const.Config.OptOutDeltaRotateIntervalProp, 300); + + config.put(Const.Config.PartnersMetadataPathProp, "testPath"); + } + + @Test + void testConstructor(Vertx vertx, VertxTestContext testContext) { + testContext.completeNow(); + } + + @Test + void testLoadContent(Vertx vertx, VertxTestContext testContext) throws Exception { + JsonObject metadata = new JsonObject(); + JsonObject partner = new JsonObject(); + partner.put("location", "testLocation"); + metadata.put("partners", partner); + + String testString = """ + [ + { + "name": "test1", + "url": "https:/test.com/uid2/optout", + "method": "GET", + "query_params": [ + "action=dooptout", + "uid2=${ADVERTISING_ID}", + "timestamp=${OPTOUT_EPOCH}" + ], + "additional_headers": [ + "Authorization: Bearer some_bearer" + ], + "retry_count": 600, + "retry_backoff_ms": 6000 + }, + { + "name": "test2", + "url": "https:/example.com/optout", + "method": "POST", + "query_params": [ + "token=${ADVERTISING_ID}", + "timestamp=${OPTOUT_EPOCH}" + ], + "additional_headers": [ + "Authorization: Bearer bearer2" + ], + "retry_count": 60, + "retry_backoff_ms": 1000 + } + ] + """; + + when(contentStorage.download(any())).thenReturn(new ByteArrayInputStream(testString.getBytes())); + + long endpoints = partnerConfigMonitorV2.loadContent(metadata); + + //Two endpoints senders should be deployed + assertEquals(2, endpoints); + + + testContext.completeNow(); + } +}