From f1157310719cdd0ad987709dcc217c99c9d87665 Mon Sep 17 00:00:00 2001 From: Preben Ingvaldsen Date: Mon, 16 Mar 2015 15:35:10 -0700 Subject: [PATCH] Add ConfigDocumentParser JSON tests Add tests to ensure that the ConfigDocumentParser can parse valid JSON, and that it throws the proper errors when parsing invalid JSON. --- .../config/impl/ConfigDocumentParser.java | 3 +- .../impl/ConfigDocumentParserTest.scala | 66 ++++++++++++++++++- 2 files changed, 67 insertions(+), 2 deletions(-) diff --git a/config/src/main/java/com/typesafe/config/impl/ConfigDocumentParser.java b/config/src/main/java/com/typesafe/config/impl/ConfigDocumentParser.java index 341dd333..f1f967f2 100644 --- a/config/src/main/java/com/typesafe/config/impl/ConfigDocumentParser.java +++ b/config/src/main/java/com/typesafe/config/impl/ConfigDocumentParser.java @@ -56,7 +56,7 @@ final class ConfigDocumentParser { private Token nextToken() { Token t = popToken(); if (flavor == ConfigSyntax.JSON) { - if (Tokens.isUnquotedText(t)) { + if (Tokens.isUnquotedText(t) && !isUnquotedWhitespace(t)) { throw parseError(addKeyName("Token not allowed in valid JSON: '" + Tokens.getUnquotedText(t) + "'")); } else if (Tokens.isSubstitution(t)) { @@ -91,6 +91,7 @@ final class ConfigDocumentParser { if (flavor == ConfigSyntax.JSON) { Token t = nextTokenIgnoringWhitespace(nodes); if (t == Tokens.COMMA) { + nodes.add(new ConfigNodeSingleToken(t)); return true; } else { putBack(t); diff --git a/config/src/test/scala/com/typesafe/config/impl/ConfigDocumentParserTest.scala b/config/src/test/scala/com/typesafe/config/impl/ConfigDocumentParserTest.scala index 97e6ec73..560d39e1 100644 --- a/config/src/test/scala/com/typesafe/config/impl/ConfigDocumentParserTest.scala +++ b/config/src/test/scala/com/typesafe/config/impl/ConfigDocumentParserTest.scala @@ -1,15 +1,29 @@ package com.typesafe.config.impl +import com.typesafe.config.{ConfigException, ConfigSyntax, ConfigParseOptions} import org.junit.Assert._ import org.junit.Test -class ConfigDocumentParserTest extends TestUtils{ +class ConfigDocumentParserTest extends TestUtils { private def parseTest(origText: String) { val node = ConfigDocumentParser.parse(tokenize(origText)) assertEquals(origText, node.render()) } + private def parseJSONFailuresTest(origText: String, containsMessage: String) { + var exceptionThrown = false + try { + ConfigDocumentParser.parse(tokenize(origText), ConfigParseOptions.defaults().setSyntax(ConfigSyntax.JSON)) + } catch { + case e: Exception => + exceptionThrown = true + assertTrue(e.isInstanceOf[ConfigException]) + assertTrue(e.getMessage.contains(containsMessage)) + } + assertTrue(exceptionThrown) + } + @Test def parseSuccess { parseTest("foo:bar") @@ -122,5 +136,55 @@ class ConfigDocumentParserTest extends TestUtils{ } // Did I cover everything? }""") + + // Can correctly parse a JSON string + val origText = + """{ + "foo": "bar", + "baz": 123, + "qux": true, + "array": [ + {"a": true, + "c": false}, + 12 + ] + } + """ + val node = ConfigDocumentParser.parse(tokenize(origText), ConfigParseOptions.defaults().setSyntax(ConfigSyntax.JSON)) + assertEquals(origText, node.render()) + } + + @Test + def parseJSONFailures() { + // JSON does not support concatenations + parseJSONFailuresTest("""{ "foo": 123 456 789 } """, "Expecting close brace } or a comma") + + // JSON must begin with { or [ + parseJSONFailuresTest(""""a": 123, "b": 456"""", "Document must have an object or array at root") + + // JSON does not support unquoted text + parseJSONFailuresTest("""{"foo": unquotedtext}""", "Token not allowed in valid JSON") + + // JSON does not support substitutions + parseJSONFailuresTest("""{"foo": ${"a.b"}}""", "Substitutions (${} syntax) not allowed in JSON") + + // JSON does not support multi-element paths + parseJSONFailuresTest("""{"foo"."bar": 123}""", "Token not allowed in valid JSON") + + // JSON does not support = + parseJSONFailuresTest("""{"foo"=123}""", """Key '"foo"' may not be followed by token: '='""") + + // JSON does not support += + parseJSONFailuresTest("""{"foo" += "bar"}""", """Key '"foo"' may not be followed by token: '+='""") + + // JSON does not support duplicate keys + parseJSONFailuresTest("""{"foo" : 123, "foo": 456}""", "JSON does not allow duplicate fields") + + // JSON does not support trailing commas + parseJSONFailuresTest("""{"foo" : 123,}""", "expecting a field name after a comma, got a close brace } instead") + + // JSON does not support empty documents + parseJSONFailuresTest("", "Empty document") + } }