UtilCollectionsTypesTest.java
package com.fasterxml.jackson.databind.deser.jdk;
import java.util.*;
import org.junit.jupiter.api.Test;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.json.JsonMapper;
import com.fasterxml.jackson.databind.testutil.NoCheckSubTypeValidator;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.fail;
// Unit tests for [databind#1868], [databind#1880], [databind#2265]
public class UtilCollectionsTypesTest
{
private final ObjectMapper DEFAULT_MAPPER = JsonMapper.builder()
.activateDefaultTyping(NoCheckSubTypeValidator.instance,
ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY)
.build();
/*
/**********************************************************
/* Unit tests, "empty" types
/**********************************************************
*/
@Test
public void testEmptyList() throws Exception {
_verifyCollection(Collections.emptyList());
}
@Test
public void testEmptySet() throws Exception {
_verifyCollection(Collections.emptySet());
}
@Test
public void testEmptyMap() throws Exception {
_verifyMap(Collections.emptyMap());
}
/*
/**********************************************************
/* Unit tests, "singleton" types
/**********************************************************
*/
@Test
public void testSingletonList() throws Exception {
_verifyCollection(Collections.singletonList("TheOne"));
}
@Test
public void testSingletonSet() throws Exception {
_verifyCollection(Collections.singleton("TheOne"));
}
@Test
public void testSingletonMap() throws Exception {
_verifyMap(Collections.singletonMap("foo", "bar"));
}
/*
/**********************************************************
/* Unit tests, "unmodifiable" types
/**********************************************************
*/
@Test
public void testUnmodifiableList() throws Exception {
_verifyCollection(Collections.unmodifiableList(Arrays.asList("first", "second")));
}
// [databind#2265]
@Test
public void testUnmodifiableListFromLinkedList() throws Exception {
final List<String> input = new LinkedList<>();
input.add("first");
input.add("second");
// Can't use simple "_verifyCollection" as type may change; instead use
// bit more flexible check:
Collection<?> act = _writeReadCollection(Collections.unmodifiableList(input));
assertEquals(input, act);
// and this check may be bit fragile (may need to revisit), but is good enough for now:
assertEquals(Collections.unmodifiableList(new ArrayList<>(input)).getClass(), act.getClass());
}
@Test
public void testUnmodifiableSet() throws Exception
{
Set<String> input = new LinkedHashSet<>(Arrays.asList("first", "second"));
_verifyCollection(Collections.unmodifiableSet(input));
}
@Test
public void testUnmodifiableMap() throws Exception
{
Map<String,String> input = new LinkedHashMap<>();
input.put("a", "b");
input.put("c", "d");
_verifyMap(Collections.unmodifiableMap(input));
}
/*
/**********************************************************
/* Unit tests, "synchronized" types, [databind#3009]
/**********************************************************
*/
// [databind#3009]
@Test
public void testSynchronizedCollection() throws Exception
{
// 07-Jan-2021, tatu: Some oddities, need to inline checking:
final Collection<?> input = Collections.synchronizedCollection(
Arrays.asList("first", "second"));
final Collection<?> output = _writeReadCollection(input);
final Class<?> actType = output.getClass();
if (!Collection.class.isAssignableFrom(actType)) {
fail("Should be subtype of java.util.Collection, is: "+actType.getName());
}
// And for some reason iteration order varies or something: direct equality
// check fails, so simply check contents:
assertEquals(input.size(), output.size());
assertEquals(new ArrayList<>(input),
new ArrayList<>(output));
}
// [databind#3009]
@Test
public void testSynchronizedSet() throws Exception {
Set<String> input = new LinkedHashSet<>(Arrays.asList("first", "second"));
_verifyCollection(Collections.synchronizedSet(input));
}
// [databind#3009]
@Test
public void testSynchronizedListRandomAccess() throws Exception {
_verifyCollection(Collections.synchronizedList(
Arrays.asList("first", "second")));
}
// [databind#3009]
@Test
public void testSynchronizedListLinked() throws Exception {
final List<String> linked = new LinkedList<>();
linked.add("first");
linked.add("second");
_verifyApproxCollection(Collections.synchronizedList(linked),
List.class);
}
// [databind#3009]
@Test
public void testSynchronizedMap() throws Exception {
Map<String,String> input = new LinkedHashMap<>();
input.put("a", "b");
input.put("c", "d");
_verifyMap(Collections.synchronizedMap(input));
}
/*
/**********************************************************
/* Unit tests, other
/**********************************************************
*/
@Test
public void testArraysAsList() throws Exception
{
// Here there are no semantics to preserve, so simply check that
// contents remain the same
List<String> input = Arrays.asList("a", "bc", "def");
String json = DEFAULT_MAPPER.writeValueAsString(input);
@SuppressWarnings("unchecked")
List<String> result = (List<String>) DEFAULT_MAPPER.readValue(json, List.class);
assertEquals(input, result);
// 21-Aug-2022, tatu: [databind#3565] should try to NOT make it
// unmodifiable
result.set(1, "b");
}
/*
/**********************************************************
/* Helper methods
/**********************************************************
*/
protected void _verifyCollection(Collection<?> exp) throws Exception {
Collection<?> act = _writeReadCollection(exp);
assertEquals(exp, act);
assertEquals(exp.getClass(), act.getClass());
}
protected void _verifyApproxCollection(Collection<?> exp,
Class<?> expType) throws Exception
{
Collection<?> act = _writeReadCollection(exp);
assertEquals(exp, act);
final Class<?> actType = act.getClass();
if (!expType.isAssignableFrom(actType)) {
fail("Should be subtype of "+expType.getName()+", is: "+actType.getName());
}
}
protected Collection<?> _writeReadCollection(Collection<?> input) throws Exception {
final String json = DEFAULT_MAPPER.writeValueAsString(input);
return DEFAULT_MAPPER.readValue(json, Collection.class);
}
protected void _verifyMap(Map<?,?> exp) throws Exception
{
String json = DEFAULT_MAPPER.writeValueAsString(exp);
Map<?,?> act = DEFAULT_MAPPER.readValue(json, Map.class);
assertEquals(exp, act);
assertEquals(exp.getClass(), act.getClass());
}
}