Skip to content

Commit d13645c

Browse files
Add documentation, update tests and improve code style.
1 parent 57587fd commit d13645c

File tree

6 files changed

+74
-82
lines changed

6 files changed

+74
-82
lines changed

firebase-config/src/main/java/com/google/firebase/remoteconfig/CustomSignals.java

Lines changed: 29 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,36 +20,60 @@
2020
import java.util.Map;
2121

2222
/**
23-
* Helper class which handles the storage and conversion to strings of key/value pairs with
24-
* heterogeneous value types for custom signals.
23+
* A container type to represent key/value pairs of heterogeneous types to be set as custom signals
24+
* in {@link FirebaseRemoteConfig#setCustomSignals}.
2525
*/
2626
public class CustomSignals {
27-
2827
final Map<String, String> customSignals;
2928

29+
/** Builder for constructing {@link CustomSignals} instances. */
3030
public static class Builder {
31-
// Holds the converted pairs of custom keys and values.
3231
private Map<String, String> customSignals = new HashMap<String, String>();
3332

34-
// Methods to accept keys and values and convert values to strings.
33+
/**
34+
* Adds a custom signal with a value that can be a string or null to the builder.
35+
*
36+
* @param key The key for the custom signal.
37+
* @param value The string value associated with the key. Can be null.
38+
* @return This Builder instance to allow chaining of method calls.
39+
*/
3540
@NonNull
3641
public Builder put(@NonNull String key, @Nullable String value) {
3742
customSignals.put(key, value);
3843
return this;
3944
}
4045

46+
/**
47+
* Adds a custom signal with a long value to the builder.
48+
*
49+
* @param key The key for the custom signal.
50+
* @param value The long value for the custom signal.
51+
* @return This Builder instance to allow chaining of method calls.
52+
*/
4153
@NonNull
4254
public Builder put(@NonNull String key, long value) {
4355
customSignals.put(key, Long.toString(value));
4456
return this;
4557
}
4658

59+
/**
60+
* Adds a custom signal with a double value to the builder.
61+
*
62+
* @param key The key for the custom signal.
63+
* @param value The double value for the custom signal.
64+
* @return This Builder instance to allow chaining of method calls.
65+
*/
4766
@NonNull
4867
public Builder put(@NonNull String key, double value) {
4968
customSignals.put(key, Double.toString(value));
5069
return this;
5170
}
5271

72+
/**
73+
* Creates a {@link CustomSignals} instance with the added custom signals.
74+
*
75+
* @return The constructed {@link CustomSignals} instance.
76+
*/
5377
@NonNull
5478
public CustomSignals build() {
5579
return new CustomSignals(this);

firebase-config/src/main/java/com/google/firebase/remoteconfig/FirebaseRemoteConfig.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -655,8 +655,10 @@ private Task<Void> setDefaultsWithStringsMapAsync(Map<String, String> defaultsSt
655655
/**
656656
* Asynchronously changes the custom signals for this {@link FirebaseRemoteConfig} instance.
657657
*
658-
* <p>The {@code customSignals} parameter should be an instance of {@link CustomSignals}, which
659-
* enforces the allowed types for custom signal values (String, Long or Double).
658+
* <p>The {@code customSignals} parameter should be an instance of {@link CustomSignals}.
659+
*
660+
* <p>Custom signals are subject to limits on the size of key/value pairs and the total
661+
* number of signals. Any calls that exceed these limits will be discarded.
660662
*
661663
* @param customSignals A dictionary of keys and the values of the custom signals to be set for
662664
* the app instance

firebase-config/src/main/java/com/google/firebase/remoteconfig/internal/ConfigSharedPrefsClient.java

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
import java.util.HashMap;
3838
import java.util.Iterator;
3939
import java.util.Map;
40+
import java.util.Objects;
4041
import org.json.JSONException;
4142
import org.json.JSONObject;
4243

@@ -272,6 +273,8 @@ public void setCustomSignals(Map<String, String> newCustomSignals) {
272273
synchronized (customSignalsLock) {
273274
// Retrieve existing custom signals
274275
Map<String, String> existingCustomSignals = getCustomSignals();
276+
// Tracks whether the custom signals have been modified.
277+
boolean modified = false;
275278

276279
for (Map.Entry<String, String> entry : newCustomSignals.entrySet()) {
277280
String key = entry.getKey();
@@ -291,14 +294,14 @@ public void setCustomSignals(Map<String, String> newCustomSignals) {
291294
// Merge new signals with existing ones, overwriting existing keys.
292295
// Also, remove entries where the new value is null.
293296
if (value != null) {
294-
existingCustomSignals.put(key, value);
297+
modified |= !Objects.equals(existingCustomSignals.put(key, value), value);
295298
} else {
296-
existingCustomSignals.remove(key);
299+
modified |= existingCustomSignals.remove(key) != null;
297300
}
298301
}
299302

300303
// Check if the map has actually changed and the size limit
301-
if (existingCustomSignals.equals(getCustomSignals())) {
304+
if (!modified) {
302305
return;
303306
}
304307
if (existingCustomSignals.size() > CUSTOM_SIGNALS_MAX_COUNT) {

firebase-config/src/test/java/com/google/firebase/remoteconfig/CustomSignalsTest.java

Lines changed: 30 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -14,69 +14,73 @@
1414

1515
package com.google.firebase.remoteconfig;
1616

17-
import static org.junit.Assert.assertEquals;
18-
import static org.junit.Assert.assertTrue;
17+
import static com.google.common.truth.Truth.assertThat;
1918

2019
import com.google.common.collect.ImmutableMap;
2120
import java.util.HashMap;
2221
import java.util.Map;
2322
import org.junit.Test;
24-
import org.junit.runner.RunWith;
25-
import org.robolectric.RobolectricTestRunner;
26-
import org.robolectric.annotation.Config;
2723

2824
/** Unit tests for the {@link CustomSignals}.*/
29-
@RunWith(RobolectricTestRunner.class)
30-
@Config(manifest = Config.NONE)
3125
public class CustomSignalsTest {
3226
@Test
3327
public void testCustomSignals_builderPutString() {
3428
CustomSignals customSignals =
3529
new CustomSignals.Builder().put("key1", "value1").put("key2", "value2").build();
3630
Map<String, String> expectedSignals = ImmutableMap.of("key1", "value1", "key2", "value2");
37-
assertEquals(expectedSignals, customSignals.customSignals);
31+
assertThat(customSignals.customSignals).isEqualTo(expectedSignals);
3832
}
3933

4034
@Test
4135
public void testCustomSignals_builderPutLong() {
4236
CustomSignals customSignals =
4337
new CustomSignals.Builder().put("key1", 123L).put("key2", 456L).build();
4438
Map<String, String> expectedSignals = ImmutableMap.of("key1", "123", "key2", "456");
45-
assertEquals(expectedSignals, customSignals.customSignals);
39+
assertThat(customSignals.customSignals).isEqualTo(expectedSignals);
4640
}
4741

4842
@Test
4943
public void testCustomSignals_builderPutDouble() {
5044
CustomSignals customSignals =
5145
new CustomSignals.Builder().put("key1", 12.34).put("key2", 56.78).build();
5246
Map<String, String> expectedSignals = ImmutableMap.of("key1", "12.34", "key2", "56.78");
53-
assertEquals(expectedSignals, customSignals.customSignals);
47+
assertThat(customSignals.customSignals).isEqualTo(expectedSignals);
5448
}
5549

5650
@Test
57-
public void testCustomSignals_builderPutMixedTypes() {
51+
public void testCustomSignals_builderPutNullValue() {
52+
CustomSignals customSignals = new CustomSignals.Builder().put("key1", null).build();
53+
Map<String, String> expectedSignals = new HashMap<>();
54+
expectedSignals.put("key1", null);
55+
assertThat(customSignals.customSignals).isEqualTo(expectedSignals);
56+
}
57+
58+
@Test
59+
public void testCustomSignals_builderPutDuplicateKeys() {
5860
CustomSignals customSignals =
5961
new CustomSignals.Builder()
6062
.put("key1", "value1")
61-
.put("key2", 123L)
62-
.put("key3", 45.67)
63+
.put("key1", "value2")
64+
.put("key1", "value3")
6365
.build();
64-
Map<String, String> expectedSignals =
65-
ImmutableMap.of("key1", "value1", "key2", "123", "key3", "45.67");
66-
assertEquals(expectedSignals, customSignals.customSignals);
66+
Map<String, String> expectedSignals = ImmutableMap.of("key1", "value3");
67+
assertThat(customSignals.customSignals).isEqualTo(expectedSignals);
6768
}
6869

6970
@Test
70-
public void testCustomSignals_builderPutNullValue() {
71-
CustomSignals customSignals = new CustomSignals.Builder().put("key1", null).build();
71+
public void testCustomSignals_builderPutMixedTypes() {
72+
CustomSignals customSignals =
73+
new CustomSignals.Builder()
74+
.put("key1", "value1")
75+
.put("key2", 123L)
76+
.put("key3", 45.67)
77+
.put("key4", null)
78+
.build();
7279
Map<String, String> expectedSignals = new HashMap<>();
73-
expectedSignals.put("key1", null);
74-
assertEquals(expectedSignals, customSignals.customSignals);
75-
}
76-
77-
@Test
78-
public void testCustomSignals_builderEmpty() {
79-
CustomSignals customSignals = new CustomSignals.Builder().build();
80-
assertTrue(customSignals.customSignals.isEmpty());
80+
expectedSignals.put("key1", "value1");
81+
expectedSignals.put("key2", "123");
82+
expectedSignals.put("key3", "45.67");
83+
expectedSignals.put("key4", null);
84+
assertThat(customSignals.customSignals).isEqualTo(expectedSignals);
8185
}
8286
}

firebase-config/src/test/java/com/google/firebase/remoteconfig/FirebaseRemoteConfigTest.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1667,6 +1667,7 @@ public void setCustomSignals_succeeds_and_calls_sharedPrefsClient() {
16671667
.put("key1", "value1")
16681668
.put("key2", 123L)
16691669
.put("key3", 12.34)
1670+
.put("key4", null)
16701671
.build();
16711672

16721673
Task<Void> setterTask = frc.setCustomSignals(customSignals);

firebase-config/src/test/java/com/google/firebase/remoteconfig/RemoteConfigTests.kt

Lines changed: 4 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@
1717
package com.google.firebase.remoteconfig
1818

1919
import androidx.test.core.app.ApplicationProvider
20-
import com.google.common.collect.ImmutableMap
2120
import com.google.common.truth.Truth.assertThat
2221
import com.google.common.util.concurrent.MoreExecutors
2322
import com.google.firebase.Firebase
@@ -150,58 +149,17 @@ class ConfigTests : BaseTestCase() {
150149
}
151150

152151
@Test
153-
fun `Custom Signals builder put string`() {
154-
val customSignals = customSignals {
155-
put("key1", "value1")
156-
put("key2", "value2")
157-
}
158-
val expectedSignals = ImmutableMap.of("key1", "value1", "key2", "value2")
159-
assertThat(customSignals.customSignals).isEqualTo(expectedSignals)
160-
}
161-
162-
@Test
163-
fun `Custom Signals builder put long`() {
164-
val customSignals = customSignals {
165-
put("key1", 123L)
166-
put("key2", 456L)
167-
}
168-
val expectedSignals = ImmutableMap.of("key1", "123", "key2", "456")
169-
assertThat(customSignals.customSignals).isEqualTo(expectedSignals)
170-
}
171-
172-
@Test
173-
fun `Custom Signals builder put double`() {
174-
val customSignals = customSignals {
175-
put("key1", 12.34)
176-
put("key2", 56.78)
177-
}
178-
val expectedSignals = ImmutableMap.of("key1", "12.34", "key2", "56.78")
179-
assertThat(customSignals.customSignals).isEqualTo(expectedSignals)
180-
}
181-
182-
@Test
183-
fun `Custom Signals builder put mixed types`() {
152+
fun `Custom Signals builder support multiple types`() {
184153
val customSignals = customSignals {
185154
put("key1", "value1")
186155
put("key2", 123L)
187156
put("key3", 45.67)
157+
put("key4", null)
188158
}
189-
val expectedSignals = ImmutableMap.of("key1", "value1", "key2", "123", "key3", "45.67")
159+
val expectedSignals =
160+
mapOf("key1" to "value1", "key2" to "123", "key3" to "45.67", "key4" to null)
190161
assertThat(customSignals.customSignals).isEqualTo(expectedSignals)
191162
}
192-
193-
@Test
194-
fun `Custom Signals builder put null value`() {
195-
val customSignals = customSignals { put("key1", null) }
196-
val expectedSignals = mapOf("key1" to null)
197-
assertThat(customSignals.customSignals).isEqualTo(expectedSignals)
198-
}
199-
200-
@Test
201-
fun `Custom Signals empty builder`() {
202-
val customSignals = customSignals {}
203-
assertThat(customSignals.customSignals).isEmpty()
204-
}
205163
}
206164

207165
@RunWith(RobolectricTestRunner::class)

0 commit comments

Comments
 (0)