Skip to content

Commit 0a2f4b7

Browse files
committed
Improve testing of generics.
An additional fix from Firestore for handling TypeVariables.
1 parent 182c821 commit 0a2f4b7

File tree

2 files changed

+42
-1
lines changed

2 files changed

+42
-1
lines changed

firebase-database/src/main/java/com/google/firebase/database/core/utilities/encoding/CustomClassMapper.java

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -187,8 +187,14 @@ private static <T> T deserializeToType(Object o, Type type) {
187187
// that this array always has at least one element, since the unbounded wildcard <?> always
188188
// has at least an upper bound of Object.
189189
Type[] upperBounds = ((WildcardType) type).getUpperBounds();
190-
hardAssert(upperBounds.length > 0, "Unexpected type bounds on wildcard " + type);
190+
hardAssert(upperBounds.length > 0, "Wildcard type " + type + " is not upper bounded.");
191191
return deserializeToType(o, upperBounds[0]);
192+
} else if (type instanceof TypeVariable) {
193+
// As above, TypeVariables always have at least one upper bound of Object.
194+
Type[] upperBounds = ((TypeVariable<?>) type).getBounds();
195+
hardAssert(upperBounds.length > 0, "Wildcard type " + type + " is not upper bounded.");
196+
return deserializeToType(o, upperBounds[0]);
197+
192198
} else if (type instanceof GenericArrayType) {
193199
throw new DatabaseException(
194200
"Generic Arrays are not supported, please use Lists " + "instead");

firebase-database/src/test/java/com/google/firebase/database/MapperTest.java

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121

2222
import androidx.annotation.Keep;
2323
import com.google.firebase.database.core.utilities.encoding.CustomClassMapper;
24+
import java.io.Serializable;
2425
import java.util.ArrayList;
2526
import java.util.Arrays;
2627
import java.util.Collection;
@@ -628,6 +629,22 @@ public String getValue() {
628629
}
629630
}
630631

632+
private static class MultiBoundedMapBean<T extends String & Serializable> {
633+
private Map<String, T> values;
634+
635+
public Map<String, T> getValues() {
636+
return values;
637+
}
638+
}
639+
640+
private static class MultiBoundedMapHolderBean {
641+
private MultiBoundedMapBean<String> map;
642+
643+
public MultiBoundedMapBean<String> getMap() {
644+
return map;
645+
}
646+
}
647+
631648
private static class StaticFieldBean {
632649
public static String value1 = "static-value";
633650
public String value2;
@@ -1772,6 +1789,24 @@ public void usingWildcardInGenericTypeIndicatorIsAllowed() {
17721789
fooMap, new GenericTypeIndicator<Map<String, ? extends String>>() {}));
17731790
}
17741791

1792+
@Test(expected = DatabaseException.class)
1793+
public void usingLowerBoundWildcardsIsForbidden() {
1794+
Map<String, String> fooMap = Collections.singletonMap("foo", "bar");
1795+
CustomClassMapper.convertToCustomClass(
1796+
fooMap, new GenericTypeIndicator<Map<String, ? super String>>() {});
1797+
}
1798+
1799+
@Test
1800+
public void multiBoundedWildcardsUsesTheFirst() {
1801+
Map<String, Object> source =
1802+
Collections.singletonMap(
1803+
"map", Collections.singletonMap("values", Collections.singletonMap("foo", "bar")));
1804+
MultiBoundedMapHolderBean bean =
1805+
CustomClassMapper.convertToCustomClass(source, MultiBoundedMapHolderBean.class);
1806+
Map<String, String> expected = Collections.singletonMap("foo", "bar");
1807+
assertEquals(expected, bean.map.values);
1808+
}
1809+
17751810
@Test(expected = DatabaseException.class)
17761811
public void unknownTypeParametersNotSupported() {
17771812
deserialize("{'value': 'foo'}", new GenericTypeIndicatorSubclass<GenericBean<?>>() {});

0 commit comments

Comments
 (0)