diff --git a/events-domain/src/main/java/io/split/android/client/events/metadata/EventMetadataBuilder.java b/events-domain/src/main/java/io/split/android/client/events/metadata/EventMetadataBuilder.java
deleted file mode 100644
index 76cb30289..000000000
--- a/events-domain/src/main/java/io/split/android/client/events/metadata/EventMetadataBuilder.java
+++ /dev/null
@@ -1,103 +0,0 @@
-package io.split.android.client.events.metadata;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.VisibleForTesting;
-
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import io.split.android.client.api.EventMetadata;
-
-/**
- * Builder for creating {@link EventMetadata} instances.
- *
- * Values are validated during put operations. Only String, Number, Boolean,
- * and List<String> values are accepted. Invalid values will be silently ignored.
- */
-class EventMetadataBuilder {
-
- private static final MetadataValidator DEFAULT_VALIDATOR = new MetadataValidatorImpl();
-
- private final Map mData = new HashMap<>();
- private final MetadataValidator mValidator;
-
- EventMetadataBuilder() {
- this(DEFAULT_VALIDATOR);
- }
-
- @VisibleForTesting
- EventMetadataBuilder(@NonNull MetadataValidator validator) {
- mValidator = validator;
- }
-
- /**
- * Adds a String value to the metadata.
- *
- * @param key the key
- * @param value the String value
- * @return this builder
- */
- @NonNull
- public EventMetadataBuilder put(@NonNull String key, @NonNull String value) {
- if (mValidator.isValidValue(value)) {
- mData.put(key, value);
- }
- return this;
- }
-
- /**
- * Adds a Number value to the metadata.
- *
- * @param key the key
- * @param value the Number value (Integer, Long, Double, Float, etc.)
- * @return this builder
- */
- @NonNull
- public EventMetadataBuilder put(@NonNull String key, @NonNull Number value) {
- if (mValidator.isValidValue(value)) {
- mData.put(key, value);
- }
- return this;
- }
-
- /**
- * Adds a Boolean value to the metadata.
- *
- * @param key the key
- * @param value the Boolean value
- * @return this builder
- */
- @NonNull
- public EventMetadataBuilder put(@NonNull String key, boolean value) {
- if (mValidator.isValidValue(value)) {
- mData.put(key, value);
- }
- return this;
- }
-
- /**
- * Adds a List of Strings to the metadata.
- *
- * @param key the key
- * @param value the list of strings
- * @return this builder
- */
- @NonNull
- public EventMetadataBuilder put(@NonNull String key, @NonNull List value) {
- if (mValidator.isValidValue(value)) {
- mData.put(key, value);
- }
- return this;
- }
-
- /**
- * Builds the {@link EventMetadata} instance.
- *
- * @return a new immutable EventMetadata instance
- */
- @NonNull
- public EventMetadata build() {
- return new EventMetadataImpl(mData);
- }
-}
diff --git a/events-domain/src/main/java/io/split/android/client/events/metadata/EventMetadataHelpers.java b/events-domain/src/main/java/io/split/android/client/events/metadata/EventMetadataHelpers.java
index d7fc334a7..670a2b24b 100644
--- a/events-domain/src/main/java/io/split/android/client/events/metadata/EventMetadataHelpers.java
+++ b/events-domain/src/main/java/io/split/android/client/events/metadata/EventMetadataHelpers.java
@@ -3,6 +3,7 @@
import androidx.annotation.Nullable;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.HashSet;
import java.util.List;
@@ -11,39 +12,85 @@
/**
* Helper class for creating {@link EventMetadata} instances.
*
- * This keeps the metadata keys in a single place to avoid typos and inconsistencies.
+ * Use these factory methods to create metadata for different event types.
*/
public class EventMetadataHelpers {
- private static final String KEY_UPDATED_FLAGS = "updatedFlags";
- private static final String KEY_LAST_UPDATE_TIMESTAMP = "lastUpdateTimestamp";
- private static final String KEY_FRESH_INSTALL = "freshInstall";
-
private EventMetadataHelpers() {
// Utility class
}
- public static EventMetadata createUpdatedFlagsMetadata(List updatedSplitNames) {
- return new EventMetadataBuilder()
- .put(KEY_UPDATED_FLAGS, new ArrayList<>(new HashSet<>(updatedSplitNames)))
- .build();
+ /**
+ * Creates metadata for a FLAG_UPDATE event.
+ *
+ * Flag names are deduplicated automatically.
+ *
+ * @param flagNames the names of flags that were updated
+ * @param changeNumber the changeNumber associated with this update, or null if not available
+ * @return the event metadata
+ */
+ public static EventMetadata createFlagUpdateMetadata(
+ List flagNames,
+ @Nullable Long changeNumber) {
+ // Deduplicate flag names
+ List uniqueFlags = new ArrayList<>(new HashSet<>(flagNames));
+ return new EventMetadataImpl(
+ EventMetadata.Type.FLAG_UPDATE,
+ uniqueFlags,
+ changeNumber
+ );
}
/**
- * Creates metadata for the SDK_READY_FROM_CACHE event.
+ * Creates metadata for a SEGMENT_UPDATE event.
+ *
+ * Segment names are deduplicated automatically.
*
- * @param lastUpdateTimestamp the timestamp when the cache was last updated, or null if not available
- * @param freshInstall true if this is a fresh install (no prior cache), false if loaded from cache
+ * @param segmentNames the names of segments that were updated
+ * @param changeNumber the changeNumber associated with this update, or null if not available
* @return the event metadata
*/
- public static EventMetadata createCacheReadyMetadata(@Nullable Long lastUpdateTimestamp, boolean freshInstall) {
- EventMetadataBuilder builder = new EventMetadataBuilder()
- .put(KEY_FRESH_INSTALL, freshInstall);
+ public static EventMetadata createSegmentUpdateMetadata(
+ List segmentNames,
+ @Nullable Long changeNumber) {
+ // Deduplicate segment names
+ List uniqueSegments = new ArrayList<>(new HashSet<>(segmentNames));
+ return new EventMetadataImpl(
+ EventMetadata.Type.SEGMENT_UPDATE,
+ uniqueSegments,
+ changeNumber
+ );
+ }
- if (lastUpdateTimestamp != null) {
- builder.put(KEY_LAST_UPDATE_TIMESTAMP, lastUpdateTimestamp);
- }
+ /**
+ * Creates metadata for a FRESH_INSTALL event.
+ *
+ * This is used when SDK_READY_FROM_CACHE fires but there was no prior cache
+ * (fresh install scenario).
+ *
+ * @return the event metadata
+ */
+ public static EventMetadata createFreshInstallMetadata() {
+ return new EventMetadataImpl(
+ EventMetadata.Type.FRESH_INSTALL,
+ Collections.emptyList(),
+ null
+ );
+ }
- return builder.build();
+ /**
+ * Creates metadata for a FROM_CACHE event.
+ *
+ * This is used when SDK_READY_FROM_CACHE fires after loading from existing cache.
+ *
+ * @param lastUpdateTimestamp the timestamp when the cache was last updated
+ * @return the event metadata
+ */
+ public static EventMetadata createFromCacheMetadata(long lastUpdateTimestamp) {
+ return new EventMetadataImpl(
+ EventMetadata.Type.FROM_CACHE,
+ Collections.emptyList(),
+ lastUpdateTimestamp
+ );
}
}
diff --git a/events-domain/src/main/java/io/split/android/client/events/metadata/EventMetadataImpl.java b/events-domain/src/main/java/io/split/android/client/events/metadata/EventMetadataImpl.java
index 8c9b73ffa..248cb9f86 100644
--- a/events-domain/src/main/java/io/split/android/client/events/metadata/EventMetadataImpl.java
+++ b/events-domain/src/main/java/io/split/android/client/events/metadata/EventMetadataImpl.java
@@ -4,71 +4,53 @@
import androidx.annotation.Nullable;
import java.util.ArrayList;
-import java.util.Collection;
import java.util.Collections;
-import java.util.HashMap;
import java.util.List;
-import java.util.Map;
-import java.util.Set;
import io.split.android.client.api.EventMetadata;
/**
* Implementation of {@link EventMetadata}.
- * Use {@link EventMetadataBuilder} to create instances.
+ * Use {@link EventMetadataHelpers} factory methods to create instances.
*/
-class EventMetadataImpl implements EventMetadata {
+public class EventMetadataImpl implements EventMetadata {
- private final Map mData;
-
- EventMetadataImpl(@NonNull Map data) {
- Map copy = new HashMap<>();
- for (Map.Entry entry : data.entrySet()) {
- Object value = entry.getValue();
- if (value instanceof List) {
- copy.put(entry.getKey(), Collections.unmodifiableList(new ArrayList<>((List>) value)));
- } else {
- copy.put(entry.getKey(), value);
- }
- }
- mData = Collections.unmodifiableMap(copy);
+ @NonNull
+ private final Type mType;
+ @NonNull
+ private final List mValues;
+ @Nullable
+ private final Long mValue;
+
+ /**
+ * Creates a new EventMetadataImpl.
+ *
+ * @param type the type of metadata
+ * @param values the list of values (flag names, segment names, etc.)
+ * @param value the numeric value (changeNumber, timestamp, etc.)
+ */
+ public EventMetadataImpl(@NonNull Type type, @NonNull List values, @Nullable Long value) {
+ mType = type;
+ // Defensive copy to ensure immutability
+ mValues = Collections.unmodifiableList(new ArrayList<>(values));
+ mValue = value;
}
@NonNull
@Override
- public Set keys() {
- return mData.keySet();
+ public Type getType() {
+ return mType;
}
@NonNull
@Override
- public Collection values() {
- return mData.values();
+ public List getValues() {
+ return mValues;
}
@Nullable
@Override
- public Object get(@NonNull String key) {
- return mData.get(key);
- }
-
- @Override
- public boolean containsKey(@NonNull String key) {
- return mData.containsKey(key);
- }
-
- @NonNull
- @Override
- public Map toMap() {
- Map copy = new HashMap<>();
- for (Map.Entry entry : mData.entrySet()) {
- Object value = entry.getValue();
- if (value instanceof List) {
- copy.put(entry.getKey(), new ArrayList<>((List>) value));
- } else {
- copy.put(entry.getKey(), value);
- }
- }
- return copy;
+ public Long getValue() {
+ return mValue;
}
}
diff --git a/events-domain/src/main/java/io/split/android/client/events/metadata/MetadataValidator.java b/events-domain/src/main/java/io/split/android/client/events/metadata/MetadataValidator.java
deleted file mode 100644
index 3a25ff3ba..000000000
--- a/events-domain/src/main/java/io/split/android/client/events/metadata/MetadataValidator.java
+++ /dev/null
@@ -1,8 +0,0 @@
-package io.split.android.client.events.metadata;
-
-import androidx.annotation.Nullable;
-
-interface MetadataValidator {
-
- boolean isValidValue(@Nullable Object value);
-}
diff --git a/events-domain/src/main/java/io/split/android/client/events/metadata/MetadataValidatorImpl.java b/events-domain/src/main/java/io/split/android/client/events/metadata/MetadataValidatorImpl.java
deleted file mode 100644
index 64a579d53..000000000
--- a/events-domain/src/main/java/io/split/android/client/events/metadata/MetadataValidatorImpl.java
+++ /dev/null
@@ -1,31 +0,0 @@
-package io.split.android.client.events.metadata;
-
-import androidx.annotation.Nullable;
-
-import java.util.List;
-
-class MetadataValidatorImpl implements MetadataValidator {
-
- @Override
- public boolean isValidValue(@Nullable Object value) {
- if (value == null) {
- return false;
- }
-
- if (value instanceof String || value instanceof Number || value instanceof Boolean) {
- return true;
- }
-
- if (value instanceof List) {
- List> list = (List>) value;
- for (Object item : list) {
- if (!(item instanceof String)) {
- return false;
- }
- }
- return true;
- }
-
- return false;
- }
-}
diff --git a/events-domain/src/test/java/io/split/android/client/events/metadata/EventMetadataBuilderTest.java b/events-domain/src/test/java/io/split/android/client/events/metadata/EventMetadataBuilderTest.java
deleted file mode 100644
index 4652c1ba5..000000000
--- a/events-domain/src/test/java/io/split/android/client/events/metadata/EventMetadataBuilderTest.java
+++ /dev/null
@@ -1,201 +0,0 @@
-package io.split.android.client.events.metadata;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-
-import java.util.Arrays;
-import java.util.List;
-
-import io.split.android.client.api.EventMetadata;
-
-public class EventMetadataBuilderTest {
-
- @Mock
- private MetadataValidator mValidator;
-
- @Before
- public void setUp() {
- MockitoAnnotations.openMocks(this);
- }
-
- @Test
- public void putStringUsesValidator() {
- when(mValidator.isValidValue(any())).thenReturn(true);
-
- new EventMetadataBuilder(mValidator)
- .put("key", "value");
-
- verify(mValidator).isValidValue("value");
- }
-
- @Test
- public void putNumberUsesValidator() {
- when(mValidator.isValidValue(any())).thenReturn(true);
-
- new EventMetadataBuilder(mValidator)
- .put("key", 42);
-
- verify(mValidator).isValidValue(42);
- }
-
- @Test
- public void putBooleanUsesValidator() {
- when(mValidator.isValidValue(any())).thenReturn(true);
-
- new EventMetadataBuilder(mValidator)
- .put("key", true);
-
- verify(mValidator).isValidValue(true);
- }
-
- @Test
- public void putListUsesValidator() {
- when(mValidator.isValidValue(any())).thenReturn(true);
- List list = Arrays.asList("a", "b");
-
- new EventMetadataBuilder(mValidator)
- .put("key", list);
-
- verify(mValidator).isValidValue(list);
- }
-
- @Test
- public void putIgnoresValueWhenValidatorReturnsFalse() {
- when(mValidator.isValidValue(any())).thenReturn(false);
-
- EventMetadata metadata = new EventMetadataBuilder(mValidator)
- .put("key", "value")
- .build();
-
- assertFalse(metadata.containsKey("key"));
- }
-
- @Test
- public void putIncludesValueWhenValidatorReturnsTrue() {
- when(mValidator.isValidValue(any())).thenReturn(true);
-
- EventMetadata metadata = new EventMetadataBuilder(mValidator)
- .put("key", "value")
- .build();
-
- assertEquals("value", metadata.get("key"));
- }
-
- @Test
- public void buildCreatesEmptyMetadataWhenNothingAdded() {
- EventMetadata metadata = new EventMetadataBuilder().build();
-
- assertTrue(metadata.keys().isEmpty());
- }
-
- @Test
- public void putStringAddsValue() {
- EventMetadata metadata = new EventMetadataBuilder()
- .put("key", "value")
- .build();
-
- assertEquals("value", metadata.get("key"));
- }
-
- @Test
- public void putIntegerAddsValue() {
- EventMetadata metadata = new EventMetadataBuilder()
- .put("count", 42)
- .build();
-
- assertEquals(42, metadata.get("count"));
- }
-
- @Test
- public void putLongAddsValue() {
- EventMetadata metadata = new EventMetadataBuilder()
- .put("timestamp", 1234567890L)
- .build();
-
- assertEquals(1234567890L, metadata.get("timestamp"));
- }
-
- @Test
- public void putDoubleAddsValue() {
- EventMetadata metadata = new EventMetadataBuilder()
- .put("rate", 3.14)
- .build();
-
- assertEquals(3.14, metadata.get("rate"));
- }
-
- @Test
- public void putBooleanTrueAddsValue() {
- EventMetadata metadata = new EventMetadataBuilder()
- .put("enabled", true)
- .build();
-
- assertEquals(true, metadata.get("enabled"));
- }
-
- @Test
- public void putBooleanFalseAddsValue() {
- EventMetadata metadata = new EventMetadataBuilder()
- .put("disabled", false)
- .build();
-
- assertEquals(false, metadata.get("disabled"));
- }
-
- @Test
- public void putListOfStringsAddsValue() {
- List flags = Arrays.asList("flag_1", "flag_2", "flag_3");
-
- EventMetadata metadata = new EventMetadataBuilder()
- .put("updatedFlags", flags)
- .build();
-
- assertEquals(flags, metadata.get("updatedFlags"));
- }
-
- @Test
- public void chainingMultiplePutsWorks() {
- EventMetadata metadata = new EventMetadataBuilder()
- .put("string", "text")
- .put("number", 100)
- .put("flag", true)
- .put("list", Arrays.asList("a", "b"))
- .build();
-
- assertEquals(4, metadata.keys().size());
- assertEquals("text", metadata.get("string"));
- assertEquals(100, metadata.get("number"));
- assertEquals(true, metadata.get("flag"));
- assertEquals(Arrays.asList("a", "b"), metadata.get("list"));
- }
-
- @Test
- public void overwritingKeyUsesLastValue() {
- EventMetadata metadata = new EventMetadataBuilder()
- .put("key", "first")
- .put("key", "second")
- .build();
-
- assertEquals("second", metadata.get("key"));
- }
-
- @Test
- public void buildReturnsNewInstanceEachTime() {
- EventMetadataBuilder builder = new EventMetadataBuilder()
- .put("key", "value");
-
- EventMetadata metadata1 = builder.build();
- EventMetadata metadata2 = builder.build();
-
- assertEquals(metadata1.get("key"), metadata2.get("key"));
- }
-}
diff --git a/events-domain/src/test/java/io/split/android/client/events/metadata/EventMetadataHelpersTest.java b/events-domain/src/test/java/io/split/android/client/events/metadata/EventMetadataHelpersTest.java
index d21bc8d3f..747533fca 100644
--- a/events-domain/src/test/java/io/split/android/client/events/metadata/EventMetadataHelpersTest.java
+++ b/events-domain/src/test/java/io/split/android/client/events/metadata/EventMetadataHelpersTest.java
@@ -1,85 +1,160 @@
package io.split.android.client.events.metadata;
import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import org.junit.Test;
import java.util.Arrays;
+import java.util.Collections;
import java.util.List;
import io.split.android.client.api.EventMetadata;
+/**
+ * Tests for the {@link EventMetadataHelpers} factory methods.
+ */
public class EventMetadataHelpersTest {
- // Tests for createUpdatedFlagsMetadata (existing)
+ // Tests for createFlagUpdateMetadata
@Test
- public void createUpdatedFlagsMetadataContainsFlags() {
- List flags = Arrays.asList("flag1", "flag2", "flag3");
- EventMetadata metadata = EventMetadataHelpers.createUpdatedFlagsMetadata(flags);
-
- assertTrue(metadata.containsKey("updatedFlags"));
- @SuppressWarnings("unchecked")
- List result = (List) metadata.get("updatedFlags");
- assertEquals(3, result.size());
- assertTrue(result.contains("flag1"));
- assertTrue(result.contains("flag2"));
- assertTrue(result.contains("flag3"));
+ public void createFlagUpdateMetadataReturnsCorrectType() {
+ EventMetadata metadata = EventMetadataHelpers.createFlagUpdateMetadata(
+ Arrays.asList("flag1", "flag2"),
+ null
+ );
+
+ assertEquals(EventMetadata.Type.FLAG_UPDATE, metadata.getType());
+ }
+
+ @Test
+ public void createFlagUpdateMetadataReturnsCorrectFlagNames() {
+ List flagNames = Arrays.asList("flag1", "flag2", "flag3");
+ EventMetadata metadata = EventMetadataHelpers.createFlagUpdateMetadata(flagNames, null);
+
+ List values = metadata.getValues();
+ assertEquals(3, values.size());
+ assertTrue(values.contains("flag1"));
+ assertTrue(values.contains("flag2"));
+ assertTrue(values.contains("flag3"));
+ }
+
+ @Test
+ public void createFlagUpdateMetadataReturnsChangeNumber() {
+ Long changeNumber = 12345L;
+ EventMetadata metadata = EventMetadataHelpers.createFlagUpdateMetadata(
+ Arrays.asList("flag1"),
+ changeNumber
+ );
+
+ assertEquals(changeNumber, metadata.getValue());
+ }
+
+ @Test
+ public void createFlagUpdateMetadataWithNullChangeNumber() {
+ EventMetadata metadata = EventMetadataHelpers.createFlagUpdateMetadata(
+ Arrays.asList("flag1"),
+ null
+ );
+
+ assertNull(metadata.getValue());
+ }
+
+ @Test
+ public void createFlagUpdateMetadataDeduplicatesFlagNames() {
+ List flagNames = Arrays.asList("flag1", "flag2", "flag1", "flag3", "flag2");
+ EventMetadata metadata = EventMetadataHelpers.createFlagUpdateMetadata(flagNames, null);
+
+ List values = metadata.getValues();
+ // Should have deduplicated - only 3 unique flags
+ assertEquals(3, values.size());
+ }
+
+ // Tests for createSegmentUpdateMetadata
+ @Test
+ public void createSegmentUpdateMetadataReturnsCorrectType() {
+ EventMetadata metadata = EventMetadataHelpers.createSegmentUpdateMetadata(
+ Arrays.asList("segment1", "segment2"),
+ null
+ );
+
+ assertEquals(EventMetadata.Type.SEGMENT_UPDATE, metadata.getType());
+ }
+
+ @Test
+ public void createSegmentUpdateMetadataReturnsCorrectSegmentNames() {
+ List segmentNames = Arrays.asList("segment1", "segment2");
+ EventMetadata metadata = EventMetadataHelpers.createSegmentUpdateMetadata(segmentNames, null);
+
+ List values = metadata.getValues();
+ assertEquals(2, values.size());
+ assertTrue(values.contains("segment1"));
+ assertTrue(values.contains("segment2"));
+ }
+
+ @Test
+ public void createSegmentUpdateMetadataReturnsChangeNumber() {
+ Long changeNumber = 67890L;
+ EventMetadata metadata = EventMetadataHelpers.createSegmentUpdateMetadata(
+ Arrays.asList("segment1"),
+ changeNumber
+ );
+
+ assertEquals(changeNumber, metadata.getValue());
+ }
+
+ // Tests for createFreshInstallMetadata
+ @Test
+ public void createFreshInstallMetadataReturnsCorrectType() {
+ EventMetadata metadata = EventMetadataHelpers.createFreshInstallMetadata();
+
+ assertEquals(EventMetadata.Type.FRESH_INSTALL, metadata.getType());
}
- // Tests for createCacheReadyMetadata
@Test
- public void createCacheReadyMetadataWithTimestampAndFreshInstallFalse() {
- EventMetadata metadata = EventMetadataHelpers.createCacheReadyMetadata(1234567890L, false);
+ public void createFreshInstallMetadataReturnsEmptyValues() {
+ EventMetadata metadata = EventMetadataHelpers.createFreshInstallMetadata();
- assertEquals(1234567890L, metadata.get("lastUpdateTimestamp"));
- assertEquals(false, metadata.get("freshInstall"));
+ assertTrue(metadata.getValues().isEmpty());
}
@Test
- public void createCacheReadyMetadataWithNullTimestampAndFreshInstallTrue() {
- EventMetadata metadata = EventMetadataHelpers.createCacheReadyMetadata(null, true);
+ public void createFreshInstallMetadataReturnsNullValue() {
+ EventMetadata metadata = EventMetadataHelpers.createFreshInstallMetadata();
- assertNull(metadata.get("lastUpdateTimestamp"));
- assertEquals(true, metadata.get("freshInstall"));
+ assertNull(metadata.getValue());
}
+ // Tests for createFromCacheMetadata
@Test
- public void createCacheReadyMetadataKeysAreCorrect() {
- EventMetadata metadata = EventMetadataHelpers.createCacheReadyMetadata(123L, false);
+ public void createFromCacheMetadataReturnsCorrectType() {
+ EventMetadata metadata = EventMetadataHelpers.createFromCacheMetadata(1700000000000L);
- assertTrue(metadata.containsKey("lastUpdateTimestamp"));
- assertTrue(metadata.containsKey("freshInstall"));
- assertEquals(2, metadata.keys().size());
+ assertEquals(EventMetadata.Type.FROM_CACHE, metadata.getType());
}
@Test
- public void createCacheReadyMetadataWithZeroTimestamp() {
- EventMetadata metadata = EventMetadataHelpers.createCacheReadyMetadata(0L, false);
+ public void createFromCacheMetadataReturnsEmptyValues() {
+ EventMetadata metadata = EventMetadataHelpers.createFromCacheMetadata(1700000000000L);
- assertEquals(0L, metadata.get("lastUpdateTimestamp"));
- assertEquals(false, metadata.get("freshInstall"));
+ assertTrue(metadata.getValues().isEmpty());
}
@Test
- public void createCacheReadyMetadataForCachePath() {
- // Cache path: freshInstall=false, timestamp from storage
- long storedTimestamp = 1700000000000L;
- EventMetadata metadata = EventMetadataHelpers.createCacheReadyMetadata(storedTimestamp, false);
+ public void createFromCacheMetadataReturnsLastUpdateTimestamp() {
+ long timestamp = 1700000000000L;
+ EventMetadata metadata = EventMetadataHelpers.createFromCacheMetadata(timestamp);
- assertFalse((Boolean) metadata.get("freshInstall"));
- assertEquals(storedTimestamp, metadata.get("lastUpdateTimestamp"));
+ assertEquals(Long.valueOf(timestamp), metadata.getValue());
}
@Test
- public void createCacheReadyMetadataForSyncPath() {
- // Sync path: freshInstall=true, timestamp=null
- EventMetadata metadata = EventMetadataHelpers.createCacheReadyMetadata(null, true);
+ public void createFromCacheMetadataWithZeroTimestamp() {
+ EventMetadata metadata = EventMetadataHelpers.createFromCacheMetadata(0L);
- assertTrue((Boolean) metadata.get("freshInstall"));
- assertNull(metadata.get("lastUpdateTimestamp"));
+ assertEquals(Long.valueOf(0L), metadata.getValue());
}
}
diff --git a/events-domain/src/test/java/io/split/android/client/events/metadata/EventMetadataImplTest.java b/events-domain/src/test/java/io/split/android/client/events/metadata/EventMetadataImplTest.java
index 54059494e..f1c9e895f 100644
--- a/events-domain/src/test/java/io/split/android/client/events/metadata/EventMetadataImplTest.java
+++ b/events-domain/src/test/java/io/split/android/client/events/metadata/EventMetadataImplTest.java
@@ -1,7 +1,7 @@
package io.split.android.client.events.metadata;
import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
@@ -9,207 +9,216 @@
import java.util.ArrayList;
import java.util.Arrays;
-import java.util.Collection;
-import java.util.HashMap;
+import java.util.Collections;
import java.util.List;
-import java.util.Map;
-import java.util.Set;
+import io.split.android.client.api.EventMetadata;
+
+/**
+ * Tests for the unified {@link EventMetadataImpl}.
+ */
public class EventMetadataImplTest {
+ // Tests for FLAG_UPDATE type
@Test
- public void keysReturnsAllKeys() {
- Map data = new HashMap<>();
- data.put("key1", "value1");
- data.put("key2", 42);
- data.put("key3", true);
-
- EventMetadataImpl metadata = new EventMetadataImpl(data);
- Set keys = metadata.keys();
-
- assertEquals(3, keys.size());
- assertTrue(keys.contains("key1"));
- assertTrue(keys.contains("key2"));
- assertTrue(keys.contains("key3"));
+ public void flagUpdateMetadataReturnsCorrectType() {
+ List flagNames = Arrays.asList("flag1", "flag2");
+ EventMetadata metadata = new EventMetadataImpl(
+ EventMetadata.Type.FLAG_UPDATE,
+ flagNames,
+ 12345L
+ );
+
+ assertEquals(EventMetadata.Type.FLAG_UPDATE, metadata.getType());
}
@Test
- public void keysReturnsEmptySetForEmptyMetadata() {
- EventMetadataImpl metadata = new EventMetadataImpl(new HashMap<>());
-
- assertTrue(metadata.keys().isEmpty());
+ public void flagUpdateMetadataReturnsCorrectValues() {
+ List flagNames = Arrays.asList("flag1", "flag2", "flag3");
+ EventMetadata metadata = new EventMetadataImpl(
+ EventMetadata.Type.FLAG_UPDATE,
+ flagNames,
+ null
+ );
+
+ List values = metadata.getValues();
+ assertEquals(3, values.size());
+ assertTrue(values.contains("flag1"));
+ assertTrue(values.contains("flag2"));
+ assertTrue(values.contains("flag3"));
}
@Test
- public void valuesReturnsAllValues() {
- Map data = new HashMap<>();
- data.put("string", "value");
- data.put("number", 42);
-
- EventMetadataImpl metadata = new EventMetadataImpl(data);
- Collection values = metadata.values();
-
- assertEquals(2, values.size());
- assertTrue(values.contains("value"));
- assertTrue(values.contains(42));
+ public void flagUpdateMetadataReturnsChangeNumber() {
+ List flagNames = Arrays.asList("flag1");
+ Long changeNumber = 999L;
+ EventMetadata metadata = new EventMetadataImpl(
+ EventMetadata.Type.FLAG_UPDATE,
+ flagNames,
+ changeNumber
+ );
+
+ assertEquals(changeNumber, metadata.getValue());
}
@Test
- public void valuesReturnsEmptyCollectionForEmptyMetadata() {
- EventMetadataImpl metadata = new EventMetadataImpl(new HashMap<>());
-
- assertTrue(metadata.values().isEmpty());
+ public void flagUpdateMetadataWithNullChangeNumber() {
+ List flagNames = Arrays.asList("flag1");
+ EventMetadata metadata = new EventMetadataImpl(
+ EventMetadata.Type.FLAG_UPDATE,
+ flagNames,
+ null
+ );
+
+ assertNull(metadata.getValue());
}
+ // Tests for SEGMENT_UPDATE type
@Test
- public void getReturnsValueForExistingKey() {
- Map data = new HashMap<>();
- data.put("key", "value");
-
- EventMetadataImpl metadata = new EventMetadataImpl(data);
-
- assertEquals("value", metadata.get("key"));
+ public void segmentUpdateMetadataReturnsCorrectType() {
+ List segmentNames = Arrays.asList("segment1", "segment2");
+ EventMetadata metadata = new EventMetadataImpl(
+ EventMetadata.Type.SEGMENT_UPDATE,
+ segmentNames,
+ null
+ );
+
+ assertEquals(EventMetadata.Type.SEGMENT_UPDATE, metadata.getType());
}
@Test
- public void getReturnsNullForNonExistingKey() {
- Map data = new HashMap<>();
- data.put("key", "value");
-
- EventMetadataImpl metadata = new EventMetadataImpl(data);
-
- assertNull(metadata.get("nonExistingKey"));
+ public void segmentUpdateMetadataReturnsCorrectValues() {
+ List segmentNames = Arrays.asList("segment1", "segment2");
+ EventMetadata metadata = new EventMetadataImpl(
+ EventMetadata.Type.SEGMENT_UPDATE,
+ segmentNames,
+ null
+ );
+
+ List values = metadata.getValues();
+ assertEquals(2, values.size());
+ assertTrue(values.contains("segment1"));
+ assertTrue(values.contains("segment2"));
}
+ // Tests for FRESH_INSTALL type
@Test
- public void containsKeyReturnsTrueForExistingKey() {
- Map data = new HashMap<>();
- data.put("key", "value");
-
- EventMetadataImpl metadata = new EventMetadataImpl(data);
-
- assertTrue(metadata.containsKey("key"));
+ public void freshInstallMetadataReturnsCorrectType() {
+ EventMetadata metadata = new EventMetadataImpl(
+ EventMetadata.Type.FRESH_INSTALL,
+ Collections.emptyList(),
+ null
+ );
+
+ assertEquals(EventMetadata.Type.FRESH_INSTALL, metadata.getType());
}
@Test
- public void containsKeyReturnsFalseForNonExistingKey() {
- Map data = new HashMap<>();
- data.put("key", "value");
-
- EventMetadataImpl metadata = new EventMetadataImpl(data);
-
- assertFalse(metadata.containsKey("nonExistingKey"));
+ public void freshInstallMetadataReturnsEmptyValues() {
+ EventMetadata metadata = new EventMetadataImpl(
+ EventMetadata.Type.FRESH_INSTALL,
+ Collections.emptyList(),
+ null
+ );
+
+ assertTrue(metadata.getValues().isEmpty());
}
@Test
- public void toMapReturnsACopyOfTheData() {
- Map data = new HashMap<>();
- data.put("key", "value");
-
- EventMetadataImpl metadata = new EventMetadataImpl(data);
- Map copy = metadata.toMap();
-
- assertEquals(1, copy.size());
- assertEquals("value", copy.get("key"));
-
- // Verify it's a copy by modifying it
- copy.put("newKey", "newValue");
- assertFalse(metadata.containsKey("newKey"));
+ public void freshInstallMetadataReturnsNullValue() {
+ EventMetadata metadata = new EventMetadataImpl(
+ EventMetadata.Type.FRESH_INSTALL,
+ Collections.emptyList(),
+ null
+ );
+
+ assertNull(metadata.getValue());
}
+ // Tests for FROM_CACHE type
@Test
- public void toMapReturnsEmptyMapForEmptyMetadata() {
- EventMetadataImpl metadata = new EventMetadataImpl(new HashMap<>());
-
- assertTrue(metadata.toMap().isEmpty());
+ public void fromCacheMetadataReturnsCorrectType() {
+ EventMetadata metadata = new EventMetadataImpl(
+ EventMetadata.Type.FROM_CACHE,
+ Collections.emptyList(),
+ 1700000000000L
+ );
+
+ assertEquals(EventMetadata.Type.FROM_CACHE, metadata.getType());
}
@Test
- public void toMapReturnsModifiableCopyOfLists() {
- Map data = new HashMap<>();
- data.put("flags", Arrays.asList("flag_1", "flag_2"));
-
- EventMetadataImpl metadata = new EventMetadataImpl(data);
- Map copy = metadata.toMap();
-
- // Should be able to modify the list in the copy
- @SuppressWarnings("unchecked")
- List listInCopy = (List) copy.get("flags");
- listInCopy.add("flag_3");
-
- // Original metadata should not be affected
- @SuppressWarnings("unchecked")
- List originalList = (List) metadata.get("flags");
- assertEquals(2, originalList.size());
- assertEquals(Arrays.asList("flag_1", "flag_2"), originalList);
+ public void fromCacheMetadataReturnsEmptyValues() {
+ EventMetadata metadata = new EventMetadataImpl(
+ EventMetadata.Type.FROM_CACHE,
+ Collections.emptyList(),
+ 1700000000000L
+ );
+
+ assertTrue(metadata.getValues().isEmpty());
}
@Test
- public void toMapListsAreIndependentAcrossCalls() {
- Map data = new HashMap<>();
- data.put("flags", Arrays.asList("flag_1", "flag_2"));
-
- EventMetadataImpl metadata = new EventMetadataImpl(data);
-
- Map copy1 = metadata.toMap();
- Map copy2 = metadata.toMap();
-
- // Modify copy1's list
- @SuppressWarnings("unchecked")
- List list1 = (List) copy1.get("flags");
- list1.add("flag_3");
-
- // copy2's list should not be affected
- @SuppressWarnings("unchecked")
- List list2 = (List) copy2.get("flags");
- assertEquals(2, list2.size());
- assertEquals(Arrays.asList("flag_1", "flag_2"), list2);
+ public void fromCacheMetadataReturnsLastUpdateTimestamp() {
+ long timestamp = 1700000000000L;
+ EventMetadata metadata = new EventMetadataImpl(
+ EventMetadata.Type.FROM_CACHE,
+ Collections.emptyList(),
+ timestamp
+ );
+
+ assertEquals(Long.valueOf(timestamp), metadata.getValue());
}
+ // Immutability tests
@Test
- public void metadataIsImmutableAfterConstruction() {
- Map data = new HashMap<>();
- data.put("key", "value");
-
- EventMetadataImpl metadata = new EventMetadataImpl(data);
-
- // Modify original map
- data.put("newKey", "newValue");
-
- // Metadata should not be affected
- assertFalse(metadata.containsKey("newKey"));
- assertEquals(1, metadata.keys().size());
- }
-
- @Test
- public void listIsDefensivelyCopiedDuringConstruction() {
- List originalList = new ArrayList<>(Arrays.asList("flag_1", "flag_2"));
- Map data = new HashMap<>();
- data.put("flags", originalList);
-
- EventMetadataImpl metadata = new EventMetadataImpl(data);
+ public void valuesListIsImmutable() {
+ List original = new ArrayList<>(Arrays.asList("flag1", "flag2"));
+ EventMetadata metadata = new EventMetadataImpl(
+ EventMetadata.Type.FLAG_UPDATE,
+ original,
+ null
+ );
// Modify original list after construction
- originalList.add("flag_3");
+ original.add("flag3");
// Metadata should not be affected
- @SuppressWarnings("unchecked")
- List storedList = (List) metadata.get("flags");
- assertEquals(2, storedList.size());
- assertEquals(Arrays.asList("flag_1", "flag_2"), storedList);
+ assertEquals(2, metadata.getValues().size());
}
@Test(expected = UnsupportedOperationException.class)
- public void listReturnedByGetIsUnmodifiable() {
- Map data = new HashMap<>();
- data.put("flags", Arrays.asList("flag_1", "flag_2"));
+ public void valuesListReturnedIsUnmodifiable() {
+ EventMetadata metadata = new EventMetadataImpl(
+ EventMetadata.Type.FLAG_UPDATE,
+ Arrays.asList("flag1", "flag2"),
+ null
+ );
- EventMetadataImpl metadata = new EventMetadataImpl(data);
+ // This should throw UnsupportedOperationException
+ metadata.getValues().add("flag3");
+ }
- @SuppressWarnings("unchecked")
- List list = (List) metadata.get("flags");
+ @Test
+ public void getValuesNeverReturnsNull() {
+ EventMetadata metadata = new EventMetadataImpl(
+ EventMetadata.Type.FRESH_INSTALL,
+ Collections.emptyList(),
+ null
+ );
+
+ assertNotNull(metadata.getValues());
+ }
- // This should throw UnsupportedOperationException
- list.add("flag_3");
+ @Test
+ public void getTypeNeverReturnsNull() {
+ EventMetadata metadata = new EventMetadataImpl(
+ EventMetadata.Type.FLAG_UPDATE,
+ Collections.emptyList(),
+ null
+ );
+
+ assertNotNull(metadata.getType());
}
}
+
diff --git a/events-domain/src/test/java/io/split/android/client/events/metadata/MetadataValidatorImplTest.java b/events-domain/src/test/java/io/split/android/client/events/metadata/MetadataValidatorImplTest.java
deleted file mode 100644
index ad3098ef2..000000000
--- a/events-domain/src/test/java/io/split/android/client/events/metadata/MetadataValidatorImplTest.java
+++ /dev/null
@@ -1,132 +0,0 @@
-package io.split.android.client.events.metadata;
-
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
-
-import org.junit.Before;
-import org.junit.Test;
-
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-
-public class MetadataValidatorImplTest {
-
- private MetadataValidator mValidator;
-
- @Before
- public void setUp() {
- mValidator = new MetadataValidatorImpl();
- }
-
- @Test
- public void isValidValueReturnsTrueForString() {
- assertTrue(mValidator.isValidValue("value"));
- }
-
- @Test
- public void isValidValueReturnsTrueForEmptyString() {
- assertTrue(mValidator.isValidValue(""));
- }
-
- @Test
- public void isValidValueReturnsTrueForInteger() {
- assertTrue(mValidator.isValidValue(42));
- }
-
- @Test
- public void isValidValueReturnsTrueForLong() {
- assertTrue(mValidator.isValidValue(1234567890L));
- }
-
- @Test
- public void isValidValueReturnsTrueForDouble() {
- assertTrue(mValidator.isValidValue(3.14));
- }
-
- @Test
- public void isValidValueReturnsTrueForFloat() {
- assertTrue(mValidator.isValidValue(2.5f));
- }
-
- @Test
- public void isValidValueReturnsTrueForBooleanTrue() {
- assertTrue(mValidator.isValidValue(true));
- }
-
- @Test
- public void isValidValueReturnsTrueForBooleanFalse() {
- assertTrue(mValidator.isValidValue(false));
- }
-
- @Test
- public void isValidValueReturnsTrueForListOfStrings() {
- List list = Arrays.asList("flag_1", "flag_2", "flag_3");
- assertTrue(mValidator.isValidValue(list));
- }
-
- @Test
- public void isValidValueReturnsTrueForEmptyList() {
- assertTrue(mValidator.isValidValue(Collections.emptyList()));
- }
-
- @Test
- public void isValidValueReturnsTrueForSingleElementStringList() {
- assertTrue(mValidator.isValidValue(Collections.singletonList("single")));
- }
-
- @Test
- public void isValidValueReturnsFalseForNull() {
- assertFalse(mValidator.isValidValue(null));
- }
-
- @Test
- public void isValidValueReturnsFalseForListWithNullElement() {
- List list = Arrays.asList("valid", null, "also_valid");
- assertFalse(mValidator.isValidValue(list));
- }
-
- @Test
- public void isValidValueReturnsFalseForListWithMixedTypes() {
- List mixedList = Arrays.asList("string", 123, true);
- assertFalse(mValidator.isValidValue(mixedList));
- }
-
- @Test
- public void isValidValueReturnsFalseForListOfIntegers() {
- List intList = Arrays.asList(1, 2, 3);
- assertFalse(mValidator.isValidValue(intList));
- }
-
- @Test
- public void isValidValueReturnsFalseForListOfBooleans() {
- List boolList = Arrays.asList(true, false, true);
- assertFalse(mValidator.isValidValue(boolList));
- }
-
- @Test
- public void isValidValueReturnsFalseForPlainObject() {
- assertFalse(mValidator.isValidValue(new Object()));
- }
-
- @Test
- public void isValidValueReturnsFalseForMap() {
- assertFalse(mValidator.isValidValue(new HashMap()));
- }
-
- @Test
- public void isValidValueReturnsFalseForNestedList() {
- List> nestedList = Arrays.asList(
- Arrays.asList("a", "b"),
- Arrays.asList("c", "d")
- );
- assertFalse(mValidator.isValidValue(nestedList));
- }
-
- @Test
- public void isValidValueReturnsFalseForArray() {
- String[] array = {"a", "b", "c"};
- assertFalse(mValidator.isValidValue(array));
- }
-}