/*
* Copyright (C) 2003, 2004, 2005 Joe Walnes.
* Copyright (C) 2006, 2007 XStream Committers.
* All rights reserved.
*
* The software in this package is published under the terms of the BSD
* style license a copy of which has been included with this distribution in
* the LICENSE.txt file.
*
* Created on 26. September 2003 by Joe Walnes
*/
package com.thoughtworks.acceptance;
import com.thoughtworks.acceptance.objects.Hardware;
import com.thoughtworks.acceptance.objects.Software;
import com.thoughtworks.acceptance.objects.StandardObject;
import com.thoughtworks.xstream.core.JVM;
import java.util.Collections;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.LinkedHashMap;
import java.util.Map;
public class MapTest extends AbstractAcceptanceTest {
public void testMapCanContainBasicObjects() {
Map map = new HashMap();
map.put("benny", "hill");
map.put("joe", "walnes");
String expected = "" +
"<map>\n" +
" <entry>\n" +
" <string>benny</string>\n" +
" <string>hill</string>\n" +
" </entry>\n" +
" <entry>\n" +
" <string>joe</string>\n" +
" <string>walnes</string>\n" +
" </entry>\n" +
"</map>";
assertBothWaysNormalized(map, expected, "map", "entry", "string[1]");
}
public void testMapCanContainCustomObjects() {
Map map = new HashMap();
map.put(new Software("microsoft", "windows"), new Hardware("x86", "p4"));
xstream.alias("software", Software.class);
xstream.alias("hardware", Hardware.class);
String expected = "" +
"<map>\n" +
" <entry>\n" +
" <software>\n" +
" <vendor>microsoft</vendor>\n" +
" <name>windows</name>\n" +
" </software>\n" +
" <hardware>\n" +
" <arch>x86</arch>\n" +
" <name>p4</name>\n" +
" </hardware>\n" +
" </entry>\n" +
"</map>";
assertBothWays(map, expected);
}
static class ThingWithMap extends StandardObject {
Map stuff = new HashMap();
}
public void testObjectCanContainMapAsField() {
ThingWithMap t = new ThingWithMap();
t.stuff.put("hi", "bye");
xstream.alias("thing-with-map", ThingWithMap.class);
String expected = "" +
"<thing-with-map>\n" +
" <stuff>\n" +
" <entry>\n" +
" <string>hi</string>\n" +
" <string>bye</string>\n" +
" </entry>\n" +
" </stuff>\n" +
"</thing-with-map>";
assertBothWays(t, expected);
}
public void testSupportsOldHashtables() {
Hashtable hashtable = new Hashtable();
hashtable.put("hello", "world");
String expected = "" +
"<hashtable>\n" +
" <entry>\n" +
" <string>hello</string>\n" +
" <string>world</string>\n" +
" </entry>\n" +
"</hashtable>";
assertBothWays(hashtable, expected);
}
static class ThingWithDifferentTypesOfMaps extends StandardObject {
private Map m1 = new HashMap();
private Map m2 = new Hashtable();
private HashMap m3 = new HashMap();
private Hashtable m4 = new Hashtable();
}
public void testObjectCanContainDifferentMapImplementations() {
xstream.alias("thing", ThingWithDifferentTypesOfMaps.class);
ThingWithDifferentTypesOfMaps thing = new ThingWithDifferentTypesOfMaps();
String expected = "" +
"<thing>\n" +
" <m1/>\n" +
" <m2 class=\"hashtable\"/>\n" +
" <m3/>\n" +
" <m4/>\n" +
"</thing>";
assertBothWays(thing, expected);
}
public void testLinkedHashMapRetainsOrdering() {
Map map = new LinkedHashMap();
map.put("Z", "a");
map.put("C", "c");
map.put("X", "b");
LinkedHashMap result = (LinkedHashMap) assertBothWays(map,
"<linked-hash-map>\n" +
" <entry>\n" +
" <string>Z</string>\n" +
" <string>a</string>\n" +
" </entry>\n" +
" <entry>\n" +
" <string>C</string>\n" +
" <string>c</string>\n" +
" </entry>\n" +
" <entry>\n" +
" <string>X</string>\n" +
" <string>b</string>\n" +
" </entry>\n" +
"</linked-hash-map>");
Object[] keys = result.keySet().toArray();
assertEquals("Z", keys[0]);
assertEquals("C", keys[1]);
assertEquals("X", keys[2]);
}
public void testAllowsEntryToBeAliasedToSomethingElse() {
Map map = new HashMap();
map.put("benny", "hill");
map.put("joe", "walnes");
String expected = "" +
"<map>\n" +
" <thing>\n" +
" <string>benny</string>\n" +
" <string>hill</string>\n" +
" </thing>\n" +
" <thing>\n" +
" <string>joe</string>\n" +
" <string>walnes</string>\n" +
" </thing>\n" +
"</map>";
xstream.alias("thing", Map.Entry.class);
assertBothWaysNormalized(map, expected, "map", "thing", "string[1]");
}
public static class MyMap extends HashMap {
}
public void testSubclassesOfMapAreHandled() {
MyMap myMap = new MyMap();
myMap.put("hehe", "hoho");
String xml = xstream.toXML(myMap);
MyMap myOtherMap = (MyMap) xstream.fromXML(xml);
assertEquals(myMap, myOtherMap);
}
public void testSynchronizedMap() {
final String expected;
if (JVM.is15()) {
expected = "" +
"<java.util.Collections_-SynchronizedMap serialization=\"custom\">\n" +
" <java.util.Collections_-SynchronizedMap>\n" +
" <default>\n" +
" <m/>\n" +
" <mutex class=\"java.util.Collections$SynchronizedMap\" reference=\"../../..\"/>\n" +
" </default>\n" +
" </java.util.Collections_-SynchronizedMap>\n" +
"</java.util.Collections_-SynchronizedMap>";
} else {
expected = "" +
"<java.util.Collections_-SynchronizedMap>\n" +
" <m/>\n" +
" <mutex class=\"java.util.Collections$SynchronizedMap\" reference=\"..\"/>\n" +
"</java.util.Collections_-SynchronizedMap>";
}
assertBothWays(Collections.synchronizedMap(new HashMap()), expected);
}
public void testUnmodifiableMap() {
String expected = "" +
"<java.util.Collections_-UnmodifiableMap>\n" +
" <m/>\n" +
"</java.util.Collections_-UnmodifiableMap>";
assertBothWays(Collections.unmodifiableMap(new HashMap()), expected);
}
public void testSingletonMap() {
String expected =""+
"<java.util.Collections_-SingletonMap>\n" +
" <k class=\"com.thoughtworks.acceptance.objects.Software\">\n" +
" <vendor>microsoft</vendor>\n" +
" <name>windows</name>\n" +
" </k>\n" +
" <v class=\"com.thoughtworks.acceptance.objects.Hardware\">\n" +
" <arch>x86</arch>\n" +
" <name>p4</name>\n" +
" </v>\n" +
"</java.util.Collections_-SingletonMap>";
assertBothWays(Collections.singletonMap(new Software("microsoft", "windows"), new Hardware("x86", "p4")), expected);
}
}