From a3ef01f0968ed1847bf5368a2f6ef4060da2d66e Mon Sep 17 00:00:00 2001 From: Gaston Thea Date: Wed, 10 Dec 2025 11:51:47 -0300 Subject: [PATCH 1/3] Add updatesFlags metadata to split kill notification --- .../client/service/splits/SplitKillTask.java | 8 +++++++- .../client/service/SplitKillTaskTest.java | 16 +++++++++++++++- 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/main/src/main/java/io/split/android/client/service/splits/SplitKillTask.java b/main/src/main/java/io/split/android/client/service/splits/SplitKillTask.java index 0468af7d3..7754d1c0d 100644 --- a/main/src/main/java/io/split/android/client/service/splits/SplitKillTask.java +++ b/main/src/main/java/io/split/android/client/service/splits/SplitKillTask.java @@ -4,9 +4,13 @@ import androidx.annotation.NonNull; +import java.util.Collections; + +import io.split.android.client.api.EventMetadata; import io.split.android.client.dtos.Split; import io.split.android.client.events.ISplitEventsManager; import io.split.android.client.events.SplitInternalEvent; +import io.split.android.client.events.metadata.EventMetadataHelpers; import io.split.android.client.service.executor.SplitTask; import io.split.android.client.service.executor.SplitTaskExecutionInfo; import io.split.android.client.service.executor.SplitTaskType; @@ -53,7 +57,9 @@ public SplitTaskExecutionInfo execute() { splitToKill.changeNumber = mKilledSplit.changeNumber; mSplitsStorage.updateWithoutChecks(splitToKill); - mEventsManager.notifyInternalEvent(SplitInternalEvent.SPLIT_KILLED_NOTIFICATION); + EventMetadata metadata = EventMetadataHelpers.createUpdatedFlagsMetadata( + Collections.singletonList(mKilledSplit.name)); + mEventsManager.notifyInternalEvent(SplitInternalEvent.SPLIT_KILLED_NOTIFICATION, metadata); } catch (Exception e) { logError("Unknown error while updating killed feature flag: " + e.getLocalizedMessage()); return SplitTaskExecutionInfo.error(SplitTaskType.SPLIT_KILL); diff --git a/main/src/test/java/io/split/android/client/service/SplitKillTaskTest.java b/main/src/test/java/io/split/android/client/service/SplitKillTaskTest.java index 1545f6d5c..7f1c3de16 100644 --- a/main/src/test/java/io/split/android/client/service/SplitKillTaskTest.java +++ b/main/src/test/java/io/split/android/client/service/SplitKillTaskTest.java @@ -8,6 +8,9 @@ import org.mockito.Mock; import org.mockito.Mockito; +import java.util.List; + +import io.split.android.client.api.EventMetadata; import io.split.android.client.dtos.Split; import io.split.android.client.events.SplitEventsManager; import io.split.android.client.events.SplitInternalEvent; @@ -20,6 +23,7 @@ import io.split.android.helpers.FileHelper; import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.doThrow; import static org.mockito.Mockito.never; import static org.mockito.Mockito.reset; @@ -69,7 +73,17 @@ public void correctExecution() throws HttpFetcherException { Assert.assertEquals(split.defaultTreatment, splitCaptor.getValue().defaultTreatment); Assert.assertEquals(split.changeNumber, splitCaptor.getValue().changeNumber); Assert.assertEquals(true, splitCaptor.getValue().killed); - verify(mEventsManager, times(1)).notifyInternalEvent(SplitInternalEvent.SPLIT_KILLED_NOTIFICATION); + + ArgumentCaptor metadataCaptor = ArgumentCaptor.forClass(EventMetadata.class); + verify(mEventsManager, times(1)).notifyInternalEvent( + eq(SplitInternalEvent.SPLIT_KILLED_NOTIFICATION), metadataCaptor.capture()); + EventMetadata metadata = metadataCaptor.getValue(); + Assert.assertNotNull(metadata); + @SuppressWarnings("unchecked") + List updatedFlags = (List) metadata.get("updatedFlags"); + Assert.assertNotNull(updatedFlags); + Assert.assertEquals(1, updatedFlags.size()); + Assert.assertTrue(updatedFlags.contains("split1")); } @Test From db15d088158aebb4b056123bdab786b435a53a52 Mon Sep 17 00:00:00 2001 From: Gaston Thea Date: Wed, 10 Dec 2025 11:59:51 -0300 Subject: [PATCH 2/3] Integration test --- .../java/tests/service/EventsManagerTest.java | 42 +++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/main/src/androidTest/java/tests/service/EventsManagerTest.java b/main/src/androidTest/java/tests/service/EventsManagerTest.java index 0ff18385a..6dd1f0cbb 100644 --- a/main/src/androidTest/java/tests/service/EventsManagerTest.java +++ b/main/src/androidTest/java/tests/service/EventsManagerTest.java @@ -6,6 +6,7 @@ import org.junit.Test; import java.util.Arrays; +import java.util.Collections; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicBoolean; @@ -176,6 +177,47 @@ public void testKilledSplit() throws InterruptedException { Assert.assertTrue(updateTask.onExecutedCalled); } + @Test + public void testKilledSplitWithMetadata() throws InterruptedException { + SplitClientConfig cfg = SplitClientConfig.builder().build(); + SplitEventsManager eventManager = new SplitEventsManager(new SplitTaskExecutorImpl(), cfg.blockUntilReady()); + eventManager.setExecutionResources(new SplitEventExecutorResourcesMock()); + + CountDownLatch readyLatch = new CountDownLatch(1); + CountDownLatch updateLatch = new CountDownLatch(1); + AtomicReference receivedMetadata = new AtomicReference<>(); + + // Wait for SDK_READY first + eventManager.register(SplitEvent.SDK_READY, new SplitEventTask() { + @Override + public void onPostExecutionView(SplitClient client) { + readyLatch.countDown(); + } + }); + + // Register for SDK_UPDATE with metadata callback + eventManager.register(SplitEvent.SDK_UPDATE, new SplitEventTask() { + @Override + public void onPostExecution(SplitClient client, EventMetadata metadata) { + receivedMetadata.set(metadata); + updateLatch.countDown(); + } + }); + + // Make SDK_READY fire + eventManager.notifyInternalEvent(SplitInternalEvent.TARGETING_RULES_SYNC_COMPLETE); + eventManager.notifyInternalEvent(SplitInternalEvent.MEMBERSHIPS_SYNC_COMPLETE); + Assert.assertTrue("SDK_READY should fire", readyLatch.await(5, TimeUnit.SECONDS)); + + EventMetadata metadata = EventMetadataHelpers.createUpdatedFlagsMetadata( + Collections.singletonList("killed_flag")); + eventManager.notifyInternalEvent(SplitInternalEvent.SPLIT_KILLED_NOTIFICATION, metadata); + + Assert.assertTrue("SDK_UPDATE should fire", updateLatch.await(5, TimeUnit.SECONDS)); + Assert.assertNotNull("Metadata should not be null", receivedMetadata.get()); + Assert.assertTrue("Metadata should contain updatedFlags", receivedMetadata.get().containsKey("updatedFlags")); + } + @Test public void testKilledSplitBeforeReady() throws InterruptedException { From 04bc22847d604eca85ea43f15741b950c8904450 Mon Sep 17 00:00:00 2001 From: Gaston Thea Date: Wed, 10 Dec 2025 12:03:26 -0300 Subject: [PATCH 3/3] Extra check --- main/src/androidTest/java/tests/service/EventsManagerTest.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/main/src/androidTest/java/tests/service/EventsManagerTest.java b/main/src/androidTest/java/tests/service/EventsManagerTest.java index 6dd1f0cbb..a7080874c 100644 --- a/main/src/androidTest/java/tests/service/EventsManagerTest.java +++ b/main/src/androidTest/java/tests/service/EventsManagerTest.java @@ -7,6 +7,7 @@ import java.util.Arrays; import java.util.Collections; +import java.util.List; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicBoolean; @@ -216,6 +217,8 @@ public void onPostExecution(SplitClient client, EventMetadata metadata) { Assert.assertTrue("SDK_UPDATE should fire", updateLatch.await(5, TimeUnit.SECONDS)); Assert.assertNotNull("Metadata should not be null", receivedMetadata.get()); Assert.assertTrue("Metadata should contain updatedFlags", receivedMetadata.get().containsKey("updatedFlags")); + List metadataList = (List) receivedMetadata.get().get("updatedFlags"); + Assert.assertTrue("Metadata should contain only killed_flag", metadataList.size() == 1 && metadataList.contains("killed_flag")); } @Test