aboutsummaryrefslogtreecommitdiffstats
path: root/extras/src/test/java/com/google/gson
diff options
context:
space:
mode:
Diffstat (limited to 'extras/src/test/java/com/google/gson')
-rw-r--r--extras/src/test/java/com/google/gson/graph/GraphAdapterBuilderTest.java197
-rw-r--r--extras/src/test/java/com/google/gson/interceptors/InterceptorTest.java171
-rw-r--r--extras/src/test/java/com/google/gson/typeadapters/RuntimeTypeAdapterFactoryTest.java211
-rw-r--r--extras/src/test/java/com/google/gson/typeadapters/UtcDateTypeAdapterTest.java79
4 files changed, 658 insertions, 0 deletions
diff --git a/extras/src/test/java/com/google/gson/graph/GraphAdapterBuilderTest.java b/extras/src/test/java/com/google/gson/graph/GraphAdapterBuilderTest.java
new file mode 100644
index 00000000..8a1d7cdb
--- /dev/null
+++ b/extras/src/test/java/com/google/gson/graph/GraphAdapterBuilderTest.java
@@ -0,0 +1,197 @@
+/*
+ * Copyright (C) 2011 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.gson.graph;
+
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+import com.google.gson.reflect.TypeToken;
+import java.lang.reflect.Type;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import junit.framework.TestCase;
+
+public final class GraphAdapterBuilderTest extends TestCase {
+ public void testSerialization() {
+ Roshambo rock = new Roshambo("ROCK");
+ Roshambo scissors = new Roshambo("SCISSORS");
+ Roshambo paper = new Roshambo("PAPER");
+ rock.beats = scissors;
+ scissors.beats = paper;
+ paper.beats = rock;
+
+ GsonBuilder gsonBuilder = new GsonBuilder();
+ new GraphAdapterBuilder()
+ .addType(Roshambo.class)
+ .registerOn(gsonBuilder);
+ Gson gson = gsonBuilder.create();
+
+ assertEquals("{'0x1':{'name':'ROCK','beats':'0x2'}," +
+ "'0x2':{'name':'SCISSORS','beats':'0x3'}," +
+ "'0x3':{'name':'PAPER','beats':'0x1'}}",
+ gson.toJson(rock).replace('"', '\''));
+ }
+
+ public void testDeserialization() {
+ String json = "{'0x1':{'name':'ROCK','beats':'0x2'}," +
+ "'0x2':{'name':'SCISSORS','beats':'0x3'}," +
+ "'0x3':{'name':'PAPER','beats':'0x1'}}";
+
+ GsonBuilder gsonBuilder = new GsonBuilder();
+ new GraphAdapterBuilder()
+ .addType(Roshambo.class)
+ .registerOn(gsonBuilder);
+ Gson gson = gsonBuilder.create();
+
+ Roshambo rock = gson.fromJson(json, Roshambo.class);
+ assertEquals("ROCK", rock.name);
+ Roshambo scissors = rock.beats;
+ assertEquals("SCISSORS", scissors.name);
+ Roshambo paper = scissors.beats;
+ assertEquals("PAPER", paper.name);
+ assertSame(rock, paper.beats);
+ }
+
+ public void testSerializationDirectSelfReference() {
+ Roshambo suicide = new Roshambo("SUICIDE");
+ suicide.beats = suicide;
+
+ GsonBuilder gsonBuilder = new GsonBuilder();
+ new GraphAdapterBuilder()
+ .addType(Roshambo.class)
+ .registerOn(gsonBuilder);
+ Gson gson = gsonBuilder.create();
+
+ assertEquals("{'0x1':{'name':'SUICIDE','beats':'0x1'}}",
+ gson.toJson(suicide).replace('"', '\''));
+ }
+
+ public void testDeserializationDirectSelfReference() {
+ String json = "{'0x1':{'name':'SUICIDE','beats':'0x1'}}";
+
+ GsonBuilder gsonBuilder = new GsonBuilder();
+ new GraphAdapterBuilder()
+ .addType(Roshambo.class)
+ .registerOn(gsonBuilder);
+ Gson gson = gsonBuilder.create();
+
+ Roshambo suicide = gson.fromJson(json, Roshambo.class);
+ assertEquals("SUICIDE", suicide.name);
+ assertSame(suicide, suicide.beats);
+ }
+
+ public void testSerializeListOfLists() {
+ Type listOfListsType = new TypeToken<List<List<?>>>() {}.getType();
+ Type listOfAnyType = new TypeToken<List<?>>() {}.getType();
+
+ List<List<?>> listOfLists = new ArrayList<List<?>>();
+ listOfLists.add(listOfLists);
+ listOfLists.add(new ArrayList<Object>());
+
+ GsonBuilder gsonBuilder = new GsonBuilder();
+ new GraphAdapterBuilder()
+ .addType(listOfListsType)
+ .addType(listOfAnyType)
+ .registerOn(gsonBuilder);
+ Gson gson = gsonBuilder.create();
+
+ String json = gson.toJson(listOfLists, listOfListsType);
+ assertEquals("{'0x1':['0x1','0x2'],'0x2':[]}", json.replace('"', '\''));
+ }
+
+ public void testDeserializeListOfLists() {
+ Type listOfAnyType = new TypeToken<List<?>>() {}.getType();
+ Type listOfListsType = new TypeToken<List<List<?>>>() {}.getType();
+
+ GsonBuilder gsonBuilder = new GsonBuilder();
+ new GraphAdapterBuilder()
+ .addType(listOfListsType)
+ .addType(listOfAnyType)
+ .registerOn(gsonBuilder);
+ Gson gson = gsonBuilder.create();
+
+ List<List<?>> listOfLists = gson.fromJson("{'0x1':['0x1','0x2'],'0x2':[]}", listOfListsType);
+ assertEquals(2, listOfLists.size());
+ assertSame(listOfLists, listOfLists.get(0));
+ assertEquals(Collections.emptyList(), listOfLists.get(1));
+ }
+
+ public void testSerializationWithMultipleTypes() {
+ Company google = new Company("Google");
+ new Employee("Jesse", google);
+ new Employee("Joel", google);
+
+ GsonBuilder gsonBuilder = new GsonBuilder();
+ new GraphAdapterBuilder()
+ .addType(Company.class)
+ .addType(Employee.class)
+ .registerOn(gsonBuilder);
+ Gson gson = gsonBuilder.create();
+
+ assertEquals("{'0x1':{'name':'Google','employees':['0x2','0x3']},"
+ + "'0x2':{'name':'Jesse','company':'0x1'},"
+ + "'0x3':{'name':'Joel','company':'0x1'}}",
+ gson.toJson(google).replace('"', '\''));
+ }
+
+ public void testDeserializationWithMultipleTypes() {
+ GsonBuilder gsonBuilder = new GsonBuilder();
+ new GraphAdapterBuilder()
+ .addType(Company.class)
+ .addType(Employee.class)
+ .registerOn(gsonBuilder);
+ Gson gson = gsonBuilder.create();
+
+ String json = "{'0x1':{'name':'Google','employees':['0x2','0x3']},"
+ + "'0x2':{'name':'Jesse','company':'0x1'},"
+ + "'0x3':{'name':'Joel','company':'0x1'}}";
+ Company company = gson.fromJson(json, Company.class);
+ assertEquals("Google", company.name);
+ Employee jesse = company.employees.get(0);
+ assertEquals("Jesse", jesse.name);
+ assertEquals(company, jesse.company);
+ Employee joel = company.employees.get(1);
+ assertEquals("Joel", joel.name);
+ assertEquals(company, joel.company);
+ }
+
+ static class Roshambo {
+ String name;
+ Roshambo beats;
+ Roshambo(String name) {
+ this.name = name;
+ }
+ }
+
+ static class Employee {
+ final String name;
+ final Company company;
+ Employee(String name, Company company) {
+ this.name = name;
+ this.company = company;
+ this.company.employees.add(this);
+ }
+ }
+
+ static class Company {
+ final String name;
+ final List<Employee> employees = new ArrayList<Employee>();
+ Company(String name) {
+ this.name = name;
+ }
+ }
+}
diff --git a/extras/src/test/java/com/google/gson/interceptors/InterceptorTest.java b/extras/src/test/java/com/google/gson/interceptors/InterceptorTest.java
new file mode 100644
index 00000000..0aab6598
--- /dev/null
+++ b/extras/src/test/java/com/google/gson/interceptors/InterceptorTest.java
@@ -0,0 +1,171 @@
+/*
+ * Copyright (C) 2012 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.google.gson.interceptors;
+
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+import com.google.gson.JsonParseException;
+import com.google.gson.JsonSyntaxException;
+import com.google.gson.TypeAdapter;
+import com.google.gson.reflect.TypeToken;
+import com.google.gson.stream.JsonReader;
+import com.google.gson.stream.JsonWriter;
+import java.io.IOException;
+import java.lang.reflect.Type;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import junit.framework.TestCase;
+
+/**
+ * Unit tests for {@link Intercept} and {@link JsonPostDeserializer}.
+ *
+ * @author Inderjeet Singh
+ */
+public final class InterceptorTest extends TestCase {
+
+ private Gson gson;
+
+ @Override
+ public void setUp() throws Exception {
+ super.setUp();
+ this.gson = new GsonBuilder()
+ .registerTypeAdapterFactory(new InterceptorFactory())
+ .enableComplexMapKeySerialization()
+ .create();
+ }
+
+ public void testExceptionsPropagated() {
+ try {
+ gson.fromJson("{}", User.class);
+ fail();
+ } catch (JsonParseException expected) {}
+ }
+
+ public void testTopLevelClass() {
+ User user = gson.fromJson("{name:'bob',password:'pwd'}", User.class);
+ assertEquals(User.DEFAULT_EMAIL, user.email);
+ }
+
+ public void testList() {
+ List<User> list = gson.fromJson("[{name:'bob',password:'pwd'}]", new TypeToken<List<User>>(){}.getType());
+ User user = list.get(0);
+ assertEquals(User.DEFAULT_EMAIL, user.email);
+ }
+
+ public void testCollection() {
+ Collection<User> list = gson.fromJson("[{name:'bob',password:'pwd'}]", new TypeToken<Collection<User>>(){}.getType());
+ User user = list.iterator().next();
+ assertEquals(User.DEFAULT_EMAIL, user.email);
+ }
+
+ public void testMapKeyAndValues() {
+ Type mapType = new TypeToken<Map<User, Address>>(){}.getType();
+ try {
+ gson.fromJson("[[{name:'bob',password:'pwd'},{}]]", mapType);
+ fail();
+ } catch (JsonSyntaxException expected) {}
+ Map<User, Address> map = gson.fromJson("[[{name:'bob',password:'pwd'},{city:'Mountain View',state:'CA',zip:'94043'}]]",
+ mapType);
+ Entry<User, Address> entry = map.entrySet().iterator().next();
+ assertEquals(User.DEFAULT_EMAIL, entry.getKey().email);
+ assertEquals(Address.DEFAULT_FIRST_LINE, entry.getValue().firstLine);
+ }
+
+ public void testField() {
+ UserGroup userGroup = gson.fromJson("{user:{name:'bob',password:'pwd'}}", UserGroup.class);
+ assertEquals(User.DEFAULT_EMAIL, userGroup.user.email);
+ }
+
+ public void testCustomTypeAdapter() {
+ Gson gson = new GsonBuilder()
+ .registerTypeAdapter(User.class, new TypeAdapter<User>() {
+ @Override public void write(JsonWriter out, User value) throws IOException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override public User read(JsonReader in) throws IOException {
+ in.beginObject();
+ in.nextName();
+ String name = in.nextString();
+ in.nextName();
+ String password = in.nextString();
+ in.endObject();
+ return new User(name, password);
+ }
+ })
+ .registerTypeAdapterFactory(new InterceptorFactory())
+ .create();
+ UserGroup userGroup = gson.fromJson("{user:{name:'bob',password:'pwd'}}", UserGroup.class);
+ assertEquals(User.DEFAULT_EMAIL, userGroup.user.email);
+ }
+
+ public void testDirectInvocationOfTypeAdapter() throws Exception {
+ TypeAdapter<UserGroup> adapter = gson.getAdapter(UserGroup.class);
+ UserGroup userGroup = adapter.fromJson("{\"user\":{\"name\":\"bob\",\"password\":\"pwd\"}}");
+ assertEquals(User.DEFAULT_EMAIL, userGroup.user.email);
+ }
+
+ @SuppressWarnings("unused")
+ private static final class UserGroup {
+ User user;
+ String city;
+ }
+
+ @Intercept(postDeserialize = UserValidator.class)
+ @SuppressWarnings("unused")
+ private static final class User {
+ static final String DEFAULT_EMAIL = "invalid@invalid.com";
+ String name;
+ String password;
+ String email;
+ Address address;
+ public User(String name, String password) {
+ this.name = name;
+ this.password = password;
+ }
+ }
+
+ public static final class UserValidator implements JsonPostDeserializer<User> {
+ public void postDeserialize(User user) {
+ if (user.name == null || user.password == null) {
+ throw new JsonSyntaxException("name and password are required fields.");
+ }
+ if (user.email == null) user.email = User.DEFAULT_EMAIL;
+ }
+ }
+
+ @Intercept(postDeserialize = AddressValidator.class)
+ @SuppressWarnings("unused")
+ private static final class Address {
+ static final String DEFAULT_FIRST_LINE = "unknown";
+ String firstLine;
+ String secondLine;
+ String city;
+ String state;
+ String zip;
+ }
+
+ public static final class AddressValidator implements JsonPostDeserializer<Address> {
+ public void postDeserialize(Address address) {
+ if (address.city == null || address.state == null || address.zip == null) {
+ throw new JsonSyntaxException("Address city, state and zip are required fields.");
+ }
+ if (address.firstLine == null) address.firstLine = Address.DEFAULT_FIRST_LINE;
+ }
+ }
+}
diff --git a/extras/src/test/java/com/google/gson/typeadapters/RuntimeTypeAdapterFactoryTest.java b/extras/src/test/java/com/google/gson/typeadapters/RuntimeTypeAdapterFactoryTest.java
new file mode 100644
index 00000000..8c62bef7
--- /dev/null
+++ b/extras/src/test/java/com/google/gson/typeadapters/RuntimeTypeAdapterFactoryTest.java
@@ -0,0 +1,211 @@
+/*
+ * Copyright (C) 2011 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.gson.typeadapters;
+
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+import com.google.gson.JsonParseException;
+import com.google.gson.TypeAdapterFactory;
+import junit.framework.TestCase;
+
+public final class RuntimeTypeAdapterFactoryTest extends TestCase {
+
+ public void testRuntimeTypeAdapter() {
+ RuntimeTypeAdapterFactory<BillingInstrument> rta = RuntimeTypeAdapterFactory.of(
+ BillingInstrument.class)
+ .registerSubtype(CreditCard.class);
+ Gson gson = new GsonBuilder()
+ .registerTypeAdapterFactory(rta)
+ .create();
+
+ CreditCard original = new CreditCard("Jesse", 234);
+ assertEquals("{\"type\":\"CreditCard\",\"cvv\":234,\"ownerName\":\"Jesse\"}",
+ gson.toJson(original, BillingInstrument.class));
+ BillingInstrument deserialized = gson.fromJson(
+ "{type:'CreditCard',cvv:234,ownerName:'Jesse'}", BillingInstrument.class);
+ assertEquals("Jesse", deserialized.ownerName);
+ assertTrue(deserialized instanceof CreditCard);
+ }
+
+ public void testRuntimeTypeIsBaseType() {
+ TypeAdapterFactory rta = RuntimeTypeAdapterFactory.of(
+ BillingInstrument.class)
+ .registerSubtype(BillingInstrument.class);
+ Gson gson = new GsonBuilder()
+ .registerTypeAdapterFactory(rta)
+ .create();
+
+ BillingInstrument original = new BillingInstrument("Jesse");
+ assertEquals("{\"type\":\"BillingInstrument\",\"ownerName\":\"Jesse\"}",
+ gson.toJson(original, BillingInstrument.class));
+ BillingInstrument deserialized = gson.fromJson(
+ "{type:'BillingInstrument',ownerName:'Jesse'}", BillingInstrument.class);
+ assertEquals("Jesse", deserialized.ownerName);
+ }
+
+ public void testNullBaseType() {
+ try {
+ RuntimeTypeAdapterFactory.of(null);
+ fail();
+ } catch (NullPointerException expected) {
+ }
+ }
+
+ public void testNullTypeFieldName() {
+ try {
+ RuntimeTypeAdapterFactory.of(BillingInstrument.class, null);
+ fail();
+ } catch (NullPointerException expected) {
+ }
+ }
+
+ public void testNullSubtype() {
+ RuntimeTypeAdapterFactory<BillingInstrument> rta = RuntimeTypeAdapterFactory.of(
+ BillingInstrument.class);
+ try {
+ rta.registerSubtype(null);
+ fail();
+ } catch (NullPointerException expected) {
+ }
+ }
+
+ public void testNullLabel() {
+ RuntimeTypeAdapterFactory<BillingInstrument> rta = RuntimeTypeAdapterFactory.of(
+ BillingInstrument.class);
+ try {
+ rta.registerSubtype(CreditCard.class, null);
+ fail();
+ } catch (NullPointerException expected) {
+ }
+ }
+
+ public void testDuplicateSubtype() {
+ RuntimeTypeAdapterFactory<BillingInstrument> rta = RuntimeTypeAdapterFactory.of(
+ BillingInstrument.class);
+ rta.registerSubtype(CreditCard.class, "CC");
+ try {
+ rta.registerSubtype(CreditCard.class, "Visa");
+ fail();
+ } catch (IllegalArgumentException expected) {
+ }
+ }
+
+ public void testDuplicateLabel() {
+ RuntimeTypeAdapterFactory<BillingInstrument> rta = RuntimeTypeAdapterFactory.of(
+ BillingInstrument.class);
+ rta.registerSubtype(CreditCard.class, "CC");
+ try {
+ rta.registerSubtype(BankTransfer.class, "CC");
+ fail();
+ } catch (IllegalArgumentException expected) {
+ }
+ }
+
+ public void testDeserializeMissingTypeField() {
+ TypeAdapterFactory billingAdapter = RuntimeTypeAdapterFactory.of(BillingInstrument.class)
+ .registerSubtype(CreditCard.class);
+ Gson gson = new GsonBuilder()
+ .registerTypeAdapterFactory(billingAdapter)
+ .create();
+ try {
+ gson.fromJson("{ownerName:'Jesse'}", BillingInstrument.class);
+ fail();
+ } catch (JsonParseException expected) {
+ }
+ }
+
+ public void testDeserializeMissingSubtype() {
+ TypeAdapterFactory billingAdapter = RuntimeTypeAdapterFactory.of(BillingInstrument.class)
+ .registerSubtype(BankTransfer.class);
+ Gson gson = new GsonBuilder()
+ .registerTypeAdapterFactory(billingAdapter)
+ .create();
+ try {
+ gson.fromJson("{type:'CreditCard',ownerName:'Jesse'}", BillingInstrument.class);
+ fail();
+ } catch (JsonParseException expected) {
+ }
+ }
+
+ public void testSerializeMissingSubtype() {
+ TypeAdapterFactory billingAdapter = RuntimeTypeAdapterFactory.of(BillingInstrument.class)
+ .registerSubtype(BankTransfer.class);
+ Gson gson = new GsonBuilder()
+ .registerTypeAdapterFactory(billingAdapter)
+ .create();
+ try {
+ gson.toJson(new CreditCard("Jesse", 456), BillingInstrument.class);
+ fail();
+ } catch (JsonParseException expected) {
+ }
+ }
+
+ public void testSerializeCollidingTypeFieldName() {
+ TypeAdapterFactory billingAdapter = RuntimeTypeAdapterFactory.of(BillingInstrument.class, "cvv")
+ .registerSubtype(CreditCard.class);
+ Gson gson = new GsonBuilder()
+ .registerTypeAdapterFactory(billingAdapter)
+ .create();
+ try {
+ gson.toJson(new CreditCard("Jesse", 456), BillingInstrument.class);
+ fail();
+ } catch (JsonParseException expected) {
+ }
+ }
+
+ public void testSerializeWrappedNullValue() {
+ TypeAdapterFactory billingAdapter = RuntimeTypeAdapterFactory.of(BillingInstrument.class)
+ .registerSubtype(CreditCard.class)
+ .registerSubtype(BankTransfer.class);
+ Gson gson = new GsonBuilder()
+ .registerTypeAdapterFactory(billingAdapter)
+ .create();
+ String serialized = gson.toJson(new BillingInstrumentWrapper(null), BillingInstrumentWrapper.class);
+ BillingInstrumentWrapper deserialized = gson.fromJson(serialized, BillingInstrumentWrapper.class);
+ assertNull(deserialized.instrument);
+ }
+
+ static class BillingInstrumentWrapper {
+ BillingInstrument instrument;
+ BillingInstrumentWrapper(BillingInstrument instrument) {
+ this.instrument = instrument;
+ }
+ }
+
+ static class BillingInstrument {
+ private final String ownerName;
+ BillingInstrument(String ownerName) {
+ this.ownerName = ownerName;
+ }
+ }
+
+ static class CreditCard extends BillingInstrument {
+ int cvv;
+ CreditCard(String ownerName, int cvv) {
+ super(ownerName);
+ this.cvv = cvv;
+ }
+ }
+
+ static class BankTransfer extends BillingInstrument {
+ int bankAccount;
+ BankTransfer(String ownerName, int bankAccount) {
+ super(ownerName);
+ this.bankAccount = bankAccount;
+ }
+ }
+}
diff --git a/extras/src/test/java/com/google/gson/typeadapters/UtcDateTypeAdapterTest.java b/extras/src/test/java/com/google/gson/typeadapters/UtcDateTypeAdapterTest.java
new file mode 100644
index 00000000..902dc477
--- /dev/null
+++ b/extras/src/test/java/com/google/gson/typeadapters/UtcDateTypeAdapterTest.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2011 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.gson.typeadapters;
+
+import java.text.SimpleDateFormat;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.Locale;
+import java.util.TimeZone;
+
+import junit.framework.TestCase;
+
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+
+public final class UtcDateTypeAdapterTest extends TestCase {
+ private final Gson gson = new GsonBuilder()
+ .registerTypeAdapter(Date.class, new UtcDateTypeAdapter())
+ .create();
+
+ public void testLocalTimeZone() {
+ Date expected = new Date();
+ String json = gson.toJson(expected);
+ Date actual = gson.fromJson(json, Date.class);
+ assertEquals(expected.getTime(), actual.getTime());
+ }
+
+ public void testDifferentTimeZones() {
+ for (String timeZone : TimeZone.getAvailableIDs()) {
+ Calendar cal = Calendar.getInstance(TimeZone.getTimeZone(timeZone));
+ Date expected = cal.getTime();
+ String json = gson.toJson(expected);
+ // System.out.println(json + ": " + timeZone);
+ Date actual = gson.fromJson(json, Date.class);
+ assertEquals(expected.getTime(), actual.getTime());
+ }
+ }
+
+ /**
+ * JDK 1.7 introduced support for XXX format to indicate UTC date. But Android is older JDK.
+ * We want to make sure that this date is parseable in Android.
+ */
+ public void testUtcDatesOnJdkBefore1_7() {
+ Gson gson = new GsonBuilder()
+ .registerTypeAdapter(Date.class, new UtcDateTypeAdapter())
+ .create();
+ gson.fromJson("'2014-12-05T04:00:00.000Z'", Date.class);
+ }
+
+ public void testUtcWithJdk7Default() {
+ Date expected = new Date();
+ SimpleDateFormat iso8601Format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSXXX", Locale.US);
+ iso8601Format.setTimeZone(TimeZone.getTimeZone("UTC"));
+ String expectedJson = "\"" + iso8601Format.format(expected) + "\"";
+ String actualJson = gson.toJson(expected);
+ assertEquals(expectedJson, actualJson);
+ Date actual = gson.fromJson(expectedJson, Date.class);
+ assertEquals(expected.getTime(), actual.getTime());
+ }
+
+ public void testNullDateSerialization() {
+ String json = gson.toJson(null, Date.class);
+ assertEquals("null", json);
+ }
+}