summaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
authorPeter Wu <peter@lekensteyn.nl>2014-05-09 01:09:51 +0200
committerPeter Wu <peter@lekensteyn.nl>2014-05-09 01:09:51 +0200
commita197179a1b78850e1273943611487b331b546af4 (patch)
treecdcdd9a4344c274214762a413697bddcce947c0a /test
parent8ab0f11e97de813d04e14b881149ea5b6fcc6782 (diff)
downloadDatafiller-a197179a1b78850e1273943611487b331b546af4.tar.gz
Add ValidatingJsonDeserializerTest (JUnit)
Diffstat (limited to 'test')
-rw-r--r--test/data/ValidatingJsonDeserializerTest.java438
1 files changed, 438 insertions, 0 deletions
diff --git a/test/data/ValidatingJsonDeserializerTest.java b/test/data/ValidatingJsonDeserializerTest.java
new file mode 100644
index 0000000..ef19cd3
--- /dev/null
+++ b/test/data/ValidatingJsonDeserializerTest.java
@@ -0,0 +1,438 @@
+package data;
+
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+import com.google.gson.JsonArray;
+import com.google.gson.JsonNull;
+import com.google.gson.JsonObject;
+import com.google.gson.JsonParseException;
+import org.junit.Test;
+import static org.junit.Assert.*;
+
+/**
+ * Tests whether the ValidatingJsonDeserializer class properly rejects
+ * incomplete or malformed Tweet or User objects.
+ *
+ * @author Peter Wu
+ */
+public class ValidatingJsonDeserializerTest {
+
+ private final static String exampleTweet = "{"
+ + " \"retweeted\": false,"
+ + " \"in_reply_to_screen_name\": null,"
+ + " \"possibly_sensitive\": false,"
+ + " \"truncated\": false,"
+ + " \"lang\": \"en\","
+ + " \"in_reply_to_status_id_str\": null,"
+ + " \"id\": 461441338630619136,"
+ + " \"in_reply_to_user_id_str\": null,"
+ + " \"in_reply_to_status_id\": null,"
+ + " \"created_at\": \"Wed Apr 30 09:46:02 +0000 2014\","
+ + " \"favorite_count\": 0,"
+ + " \"place\": null,"
+ + " \"coordinates\": null,"
+ + " \"metadata\": {"
+ + " \"result_type\": \"recent\","
+ + " \"iso_language_code\": \"en\""
+ + " },"
+ + " \"text\": \"RT @verge: Samsung's Galaxy K zoom is a high-end smartphone and an incredible selfie machine http://t.co/I5WmnHV9HM http://t.co/V8Pm2bxzcH\","
+ + " \"contributors\": null,"
+ + " \"retweeted_status\": {"
+ + " \"contributors\": null,"
+ + " \"text\": \"Samsung's Galaxy K zoom is a high-end smartphone and an incredible selfie machine http://t.co/I5WmnHV9HM http://t.co/V8Pm2bxzcH\","
+ + " \"geo\": null,"
+ + " \"retweeted\": false,"
+ + " \"in_reply_to_screen_name\": null,"
+ + " \"possibly_sensitive\": false,"
+ + " \"truncated\": false,"
+ + " \"lang\": \"en\","
+ + " \"entities\": {"
+ + " \"symbols\": [],"
+ + " \"urls\": [{"
+ + " \"expanded_url\": \"http://vrge.co/1ivZTla\","
+ + " \"indices\": [82, 104],"
+ + " \"display_url\": \"vrge.co/1ivZTla\","
+ + " \"url\": \"http://t.co/I5WmnHV9HM\""
+ + " }],"
+ + " \"hashtags\": [],"
+ + " \"media\": [{"
+ + " \"sizes\": {"
+ + " \"small\": {"
+ + " \"w\": 340,"
+ + " \"resize\": \"fit\","
+ + " \"h\": 225"
+ + " },"
+ + " \"thumb\": {"
+ + " \"w\": 150,"
+ + " \"resize\": \"crop\","
+ + " \"h\": 150"
+ + " },"
+ + " \"large\": {"
+ + " \"w\": 1020,"
+ + " \"resize\": \"fit\","
+ + " \"h\": 675"
+ + " },"
+ + " \"medium\": {"
+ + " \"w\": 599,"
+ + " \"resize\": \"fit\","
+ + " \"h\": 397"
+ + " }"
+ + " },"
+ + " \"id\": 461125128559263744,"
+ + " \"media_url_https\": \"https://pbs.twimg.com/media/BmY-3HzIAAAR1d6.jpg\","
+ + " \"media_url\": \"http://pbs.twimg.com/media/BmY-3HzIAAAR1d6.jpg\","
+ + " \"expanded_url\": \"http://twitter.com/verge/status/461125128710262784/photo/1\","
+ + " \"indices\": [105, 127],"
+ + " \"id_str\": \"461125128559263744\","
+ + " \"type\": \"photo\","
+ + " \"display_url\": \"pic.twitter.com/V8Pm2bxzcH\","
+ + " \"url\": \"http://t.co/V8Pm2bxzcH\""
+ + " }],"
+ + " \"user_mentions\": []"
+ + " },"
+ + " \"in_reply_to_status_id_str\": null,"
+ + " \"id\": 461125128710262784,"
+ + " \"source\": \"<a href=\\\"http://itunes.apple.com/us/app/twitter/id409789998?mt=12\\\" rel=\\\"nofollow\\\">Twitter for Mac<\\/a>\","
+ + " \"in_reply_to_user_id_str\": null,"
+ + " \"favorited\": false,"
+ + " \"in_reply_to_status_id\": null,"
+ + " \"retweet_count\": 113,"
+ + " \"created_at\": \"Tue Apr 29 12:49:32 +0000 2014\","
+ + " \"in_reply_to_user_id\": null,"
+ + " \"favorite_count\": 79,"
+ + " \"id_str\": \"461125128710262784\","
+ + " \"place\": null,"
+ + " \"user\": {"
+ + " \"location\": \"The Universe\","
+ + " \"default_profile\": false,"
+ + " \"profile_background_tile\": false,"
+ + " \"statuses_count\": 45365,"
+ + " \"lang\": \"en\","
+ + " \"profile_link_color\": \"FA4D2A\","
+ + " \"profile_banner_url\": \"https://pbs.twimg.com/profile_banners/275686563/1348153919\","
+ + " \"id\": 275686563,"
+ + " \"following\": null,"
+ + " \"protected\": false,"
+ + " \"favourites_count\": 679,"
+ + " \"profile_text_color\": \"333333\","
+ + " \"description\": \"The culture of now. We tell stories at the intersection of science, technology, art, and the humanities.\","
+ + " \"verified\": true,"
+ + " \"contributors_enabled\": false,"
+ + " \"profile_sidebar_border_color\": \"FFFFFF\","
+ + " \"name\": \"The Verge\","
+ + " \"profile_background_color\": \"FFFFFF\","
+ + " \"created_at\": \"Fri Apr 01 19:54:22 +0000 2011\","
+ + " \"is_translation_enabled\": true,"
+ + " \"default_profile_image\": false,"
+ + " \"followers_count\": 442637,"
+ + " \"profile_image_url_https\": \"https://pbs.twimg.com/profile_images/1450127603/TheVerge_Badge_Color1_normal.png\","
+ + " \"geo_enabled\": false,"
+ + " \"profile_background_image_url\": \"http://pbs.twimg.com/profile_background_images/378800000021313532/66906cdb8cdbfe2de5ac7ada880ca029.png\","
+ + " \"profile_background_image_url_https\": \"https://pbs.twimg.com/profile_background_images/378800000021313532/66906cdb8cdbfe2de5ac7ada880ca029.png\","
+ + " \"follow_request_sent\": null,"
+ + " \"entities\": {"
+ + " \"description\": {"
+ + " \"urls\": []"
+ + " },"
+ + " \"url\": {"
+ + " \"urls\": [{"
+ + " \"expanded_url\": \"http://www.theverge.com\","
+ + " \"indices\": [0, 22],"
+ + " \"display_url\": \"theverge.com\","
+ + " \"url\": \"http://t.co/W2SFxIGhA4\""
+ + " }]"
+ + " }"
+ + " },"
+ + " \"url\": \"http://t.co/W2SFxIGhA4\","
+ + " \"utc_offset\": -14400,"
+ + " \"time_zone\": \"Eastern Time (US & Canada)\","
+ + " \"notifications\": null,"
+ + " \"profile_use_background_image\": true,"
+ + " \"friends_count\": 112,"
+ + " \"profile_sidebar_fill_color\": \"EFEFEF\","
+ + " \"screen_name\": \"verge\","
+ + " \"id_str\": \"275686563\","
+ + " \"profile_image_url\": \"http://pbs.twimg.com/profile_images/1450127603/TheVerge_Badge_Color1_normal.png\","
+ + " \"listed_count\": 17450,"
+ + " \"is_translator\": false"
+ + " },"
+ + " \"coordinates\": null,"
+ + " \"metadata\": {"
+ + " \"result_type\": \"recent\","
+ + " \"iso_language_code\": \"en\""
+ + " }"
+ + " },"
+ + " \"geo\": null,"
+ + " \"entities\": {"
+ + " \"symbols\": [],"
+ + " \"urls\": [{"
+ + " \"expanded_url\": \"http://vrge.co/1ivZTla\","
+ + " \"indices\": [93, 115],"
+ + " \"display_url\": \"vrge.co/1ivZTla\","
+ + " \"url\": \"http://t.co/I5WmnHV9HM\""
+ + " }],"
+ + " \"hashtags\": [],"
+ + " \"media\": [{"
+ + " \"sizes\": {"
+ + " \"small\": {"
+ + " \"w\": 340,"
+ + " \"resize\": \"fit\","
+ + " \"h\": 225"
+ + " },"
+ + " \"thumb\": {"
+ + " \"w\": 150,"
+ + " \"resize\": \"crop\","
+ + " \"h\": 150"
+ + " },"
+ + " \"large\": {"
+ + " \"w\": 1020,"
+ + " \"resize\": \"fit\","
+ + " \"h\": 675"
+ + " },"
+ + " \"medium\": {"
+ + " \"w\": 599,"
+ + " \"resize\": \"fit\","
+ + " \"h\": 397"
+ + " }"
+ + " },"
+ + " \"id\": 461125128559263744,"
+ + " \"media_url_https\": \"https://pbs.twimg.com/media/BmY-3HzIAAAR1d6.jpg\","
+ + " \"media_url\": \"http://pbs.twimg.com/media/BmY-3HzIAAAR1d6.jpg\","
+ + " \"expanded_url\": \"http://twitter.com/verge/status/461125128710262784/photo/1\","
+ + " \"indices\": [116, 138],"
+ + " \"id_str\": \"461125128559263744\","
+ + " \"type\": \"photo\","
+ + " \"display_url\": \"pic.twitter.com/V8Pm2bxzcH\","
+ + " \"url\": \"http://t.co/V8Pm2bxzcH\""
+ + " }],"
+ + " \"user_mentions\": [{"
+ + " \"id\": 275686563,"
+ + " \"name\": \"The Verge\","
+ + " \"indices\": [3, 9],"
+ + " \"screen_name\": \"verge\","
+ + " \"id_str\": \"275686563\""
+ + " }]"
+ + " },"
+ + " \"source\": \"<a href=\\\"https://twitter.com/download/android\\\" rel=\\\"nofollow\\\">Twitter for Android Tablets<\\/a>\","
+ + " \"favorited\": false,"
+ + " \"in_reply_to_user_id\": null,"
+ + " \"retweet_count\": 113,"
+ + " \"id_str\": \"461441338630619136\","
+ + " \"user\": {"
+ + " \"location\": \"GURGAON\","
+ + " \"default_profile\": false,"
+ + " \"profile_background_tile\": true,"
+ + " \"statuses_count\": 2208,"
+ + " \"lang\": \"en\","
+ + " \"profile_link_color\": \"2FC2EF\","
+ + " \"profile_banner_url\": \"https://pbs.twimg.com/profile_banners/106707648/1398635609\","
+ + " \"id\": 106707648,"
+ + " \"following\": null,"
+ + " \"protected\": false,"
+ + " \"favourites_count\": 547,"
+ + " \"profile_text_color\": \"666666\","
+ + " \"description\": \"A WANNABE WRITER.....\","
+ + " \"verified\": false,"
+ + " \"contributors_enabled\": false,"
+ + " \"profile_sidebar_border_color\": \"FFFFFF\","
+ + " \"name\": \"MANGO PEOPLE\","
+ + " \"profile_background_color\": \"1A1B1F\","
+ + " \"created_at\": \"Wed Jan 20 12:59:53 +0000 2010\","
+ + " \"is_translation_enabled\": false,"
+ + " \"default_profile_image\": false,"
+ + " \"followers_count\": 573,"
+ + " \"profile_image_url_https\": \"https://pbs.twimg.com/profile_images/461180974823272448/RpSM6o2f_normal.jpeg\","
+ + " \"geo_enabled\": true,"
+ + " \"profile_background_image_url\": \"http://pbs.twimg.com/profile_background_images/378800000157705856/1unyAtzk.jpeg\","
+ + " \"profile_background_image_url_https\": \"https://pbs.twimg.com/profile_background_images/378800000157705856/1unyAtzk.jpeg\","
+ + " \"follow_request_sent\": null,"
+ + " \"entities\": {"
+ + " \"description\": {"
+ + " \"urls\": []"
+ + " },"
+ + " \"url\": {"
+ + " \"urls\": [{"
+ + " \"expanded_url\": \"http://FACEBOOK.COM/BENXROCKS\","
+ + " \"indices\": [0, 22],"
+ + " \"display_url\": \"FACEBOOK.COM/BENXROCKS\","
+ + " \"url\": \"http://t.co/Uwbbg0oN3T\""
+ + " }]"
+ + " }"
+ + " },"
+ + " \"url\": \"http://t.co/Uwbbg0oN3T\","
+ + " \"utc_offset\": 19800,"
+ + " \"time_zone\": \"New Delhi\","
+ + " \"notifications\": null,"
+ + " \"profile_use_background_image\": true,"
+ + " \"friends_count\": 1719,"
+ + " \"profile_sidebar_fill_color\": \"252429\","
+ + " \"screen_name\": \"BH4NUKALRA\","
+ + " \"id_str\": \"106707648\","
+ + " \"profile_image_url\": \"http://pbs.twimg.com/profile_images/461180974823272448/RpSM6o2f_normal.jpeg\","
+ + " \"listed_count\": 2,"
+ + " \"is_translator\": false"
+ + " }"
+ + "}";
+
+ private Object deserializeJson(String json, Class cls) {
+ Gson gson = new GsonBuilder()
+ .registerTypeAdapter(cls, new ValidatingJsonDeserializer<>())
+ .create();
+ return gson.fromJson(json, cls);
+ }
+
+ @Test
+ public void testUserEmpty() {
+ try {
+ deserializeJson("{}", User.class);
+ fail("Empty object literal should be rejected.");
+ } catch (JsonParseException ex) {
+ // assume id to be the first field
+ assertEquals("Missing field: id", ex.getMessage());
+ }
+ }
+
+ @Test
+ public void testTweetEmpty() {
+ try {
+ deserializeJson("{}", Tweet.class);
+ fail("Empty object literal should be rejected.");
+ } catch (JsonParseException ex) {
+ // assume id to be the first field
+ assertEquals("Missing field: id", ex.getMessage());
+ }
+ }
+
+ /**
+ * Test of deserialize method, of class ValidatingJsonDeserializer.
+ */
+ @Test
+ public void testDeserializeTweet() {
+ Tweet tweet = (Tweet) deserializeJson(exampleTweet, Tweet.class);
+ Gson gson = new GsonBuilder().setPrettyPrinting().create();
+ //System.out.println(gson.toJson(tweet));
+ assertEquals(461441338630619136L, tweet.id);
+ assertNotNull(tweet.retweeted_status);
+ assertEquals("Wed Apr 30 09:46:02 +0000 2014", tweet.created_at);
+
+ assertNotNull(tweet.user);
+ assertEquals("GURGAON", tweet.user.location);
+ assertNotNull(tweet.user.entities);
+ assertNotNull(tweet.user.entities.url);
+ assertEquals(1, tweet.user.entities.url.urls.length);
+ assertEquals("http://FACEBOOK.COM/BENXROCKS",
+ tweet.user.entities.url.urls[0].expanded_url);
+
+ assertEquals("en", tweet.retweeted_status.user.lang);
+ assertEquals(1, tweet.entities.user_mentions.length);
+ assertEquals(275686563, tweet.entities.user_mentions[0].id);
+ assertEquals(0, tweet.entities.hashtags.length);
+ assertEquals(1, tweet.entities.urls.length);
+ assertEquals("http://vrge.co/1ivZTla", tweet.entities.urls[0].expanded_url);
+ }
+
+ private JsonObject buildMinimalUser() {
+ JsonObject user = new JsonObject();
+ user.addProperty("id", 4);
+ user.addProperty("name", "X");
+ user.addProperty("time_zone", "X");
+ user.addProperty("statuses_count", 4);
+ user.addProperty("followers_count", 4);
+ user.addProperty("friends_count", 4);
+ user.addProperty("location", "X");
+ user.addProperty("screen_name", "X");
+ user.addProperty("created_at", "X");
+ JsonObject entities = new JsonObject();
+ JsonObject urlEntity = new JsonObject();
+ urlEntity.add("urls", new JsonArray());
+ entities.add("url", urlEntity);
+ user.add("entities", entities);
+ user.addProperty("lang", "X");
+ return user;
+ }
+
+ private JsonObject buildMinimalTweet(JsonObject user) {
+ JsonObject tweet = new JsonObject();
+ tweet.addProperty("id", 4);
+ tweet.addProperty("lang", "X");
+ tweet.addProperty("in_reply_to_user_id", 4);
+ tweet.addProperty("created_at", "X");
+ tweet.addProperty("favorite_count", 4);
+ tweet.addProperty("place", "X");
+ tweet.addProperty("coordinates", "X");
+ tweet.addProperty("text", "X");
+ tweet.add("retweeted_status", JsonNull.INSTANCE); // Tweet object
+ JsonObject entities = new JsonObject();
+ entities.add("hashtags", new JsonArray());
+ entities.add("urls", new JsonArray());
+ entities.add("user_mentions", new JsonArray());
+ tweet.add("entities", entities);
+ tweet.addProperty("retweet_count", 4);
+ tweet.add("user", user);
+ return tweet;
+ }
+
+ private void removeProperty(JsonObject obj, String... names) {
+ String prop;
+ for (int i = 0; i < names.length - 1; i++) {
+ prop = names[i];
+ assert obj.has(prop) : "Missing object property: " + prop;
+ obj = obj.getAsJsonObject(prop);
+ }
+ prop = names[names.length - 1];
+ assert obj.has(prop) : "Cannot remove missing property: " + prop;
+ obj.remove(prop);
+ }
+
+ private void checkImpairedTweet(String... names) {
+ JsonObject tweet = buildMinimalTweet(buildMinimalUser());
+ removeProperty(tweet, names);
+ String prop = names[names.length - 1];
+ checkTweetFail(tweet, "Missing field: " + prop);
+ }
+
+ private void checkTweetFail(JsonObject tweet, String exp) {
+ Gson gson = new Gson();
+ System.out.println("Checking for failure: " + exp);
+ String json = gson.toJson(tweet);
+ try {
+ deserializeJson(json, Tweet.class);
+ System.out.println("JSON that should have failed: " + json);
+ fail("Expected: " + exp);
+ } catch (JsonParseException ex) {
+ System.out.println("Failure message: " + ex.getMessage());
+ assertEquals(exp, ex.getMessage());
+ }
+ }
+
+ private Tweet checkTweetPass(JsonObject tweet) {
+ Gson gson = new Gson();
+ String json = gson.toJson(tweet);
+ return (Tweet) deserializeJson(json, Tweet.class);
+ }
+
+ @Test
+ public void testMinimal() {
+ checkTweetPass(buildMinimalTweet(buildMinimalUser()));
+ checkTweetFail(buildMinimalTweet(null), "Missing field: user");
+ }
+
+ @Test
+ public void testTweet() {
+ checkImpairedTweet("text");
+ }
+
+ @Test
+ public void testTweetEntities() {
+ checkImpairedTweet("entities");
+ checkImpairedTweet("entities", "hashtags");
+ checkImpairedTweet("entities", "urls");
+ }
+
+ @Test
+ public void testUserEntities() {
+ checkImpairedTweet("user", "entities");
+ checkImpairedTweet("user", "entities", "url");
+ checkImpairedTweet("user", "entities", "url", "urls");
+ }
+}