• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2021 Google Inc. All rights reserved.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package com.google.flatbuffers.kotlin
17 
18 import kotlin.test.Test
19 import kotlin.test.assertEquals
20 import kotlin.test.assertTrue
21 
22 class JSONTest {
23 
24   @Test
parse2Testnull25   fun parse2Test() {
26     val dataStr = """
27       { "myKey" : [1, "yay"] }
28     """.trimIndent()
29     val data = dataStr.encodeToByteArray()
30     val buffer = ArrayReadWriteBuffer(data, writePosition = data.size)
31     val parser = JSONParser()
32     val root = parser.parse(buffer)
33     println(root.toJson())
34   }
35 
36   @Test
parseSamplenull37   fun parseSample() {
38     val dataStr = """
39       {
40         "ary" : [1, 2, 3],
41         "boolean_false": false,
42 "boolean_true": true, "double": 1.2E33,
43         "hello":"world"
44    ,"interesting": "value",
45 
46  "null_value":  null,
47 
48 
49   "object" : {
50     "field1": "hello"
51   }
52  }
53     """
54     val data = dataStr.encodeToByteArray()
55     val root = JSONParser().parse(ArrayReadWriteBuffer(data, writePosition = data.size))
56     println(root.toJson())
57     val map = root.toMap()
58 
59     assertEquals(8, map.size)
60     assertEquals("world", map["hello"].toString())
61     assertEquals("value", map["interesting"].toString())
62     assertEquals(12e32, map["double"].toDouble())
63     assertArrayEquals(intArrayOf(1, 2, 3), map["ary"].toIntArray())
64     assertEquals(true, map["boolean_true"].toBoolean())
65     assertEquals(false, map["boolean_false"].toBoolean())
66     assertEquals(true, map["null_value"].isNull)
67     assertEquals("hello", map["object"]["field1"].toString())
68 
69     val obj = map["object"]
70     assertEquals(true, obj.isMap)
71     assertEquals("{\"field1\":\"hello\"}", obj.toJson())
72     // TODO: Kotlin Double.toString() produce different strings dependending on the platform, so on JVM
73     // is 1.2E33, while on js is 1.2e+33. For now we are disabling this test.
74     //
75     // val minified = data.filterNot { it == ' '.toByte() || it == '\n'.toByte() }.toByteArray().decodeToString()
76     // assertEquals(minified, root.toJson())
77   }
78 
79   @Test
testDoublesnull80   fun testDoubles() {
81     val values = arrayOf(
82       "-0.0",
83       "1.0",
84       "1.7976931348613157",
85       "0.0",
86       "-0.5",
87       "3.141592653589793",
88       "2.718281828459045E-3",
89       "2.2250738585072014E-308",
90       "4.9E-15",
91     )
92     val parser = JSONParser()
93     assertEquals(-0.0, parser.parse(values[0]).toDouble())
94     assertEquals(1.0, parser.parse(values[1]).toDouble())
95     assertEquals(1.7976931348613157, parser.parse(values[2]).toDouble())
96     assertEquals(0.0, parser.parse(values[3]).toDouble())
97     assertEquals(-0.5, parser.parse(values[4]).toDouble())
98     assertEquals(3.141592653589793, parser.parse(values[5]).toDouble())
99     assertEquals(2.718281828459045e-3, parser.parse(values[6]).toDouble())
100     assertEquals(2.2250738585072014E-308, parser.parse(values[7]).toDouble())
101     assertEquals(4.9E-15, parser.parse(values[8]).toDouble())
102   }
103 
104   @Test
testIntsnull105   fun testInts() {
106     val values = arrayOf(
107       "-0",
108       "0",
109       "-1",
110       "${Int.MAX_VALUE}",
111       "${Int.MIN_VALUE}",
112       "${Long.MAX_VALUE}",
113       "${Long.MIN_VALUE}",
114     )
115     val parser = JSONParser()
116 
117     assertEquals(parser.parse(values[0]).toInt(), 0)
118     assertEquals(parser.parse(values[1]).toInt(), 0)
119     assertEquals(parser.parse(values[2]).toInt(), -1)
120     assertEquals(parser.parse(values[3]).toInt(), Int.MAX_VALUE)
121     assertEquals(parser.parse(values[4]).toInt(), Int.MIN_VALUE)
122     assertEquals(parser.parse(values[5]).toLong(), Long.MAX_VALUE)
123     assertEquals(parser.parse(values[6]).toLong(), Long.MIN_VALUE)
124   }
125 
126   @Test
testBooleansAndNullnull127   fun testBooleansAndNull() {
128     val values = arrayOf(
129       "true",
130       "false",
131       "null"
132     )
133     val parser = JSONParser()
134 
135     assertEquals(true, parser.parse(values[0]).toBoolean())
136     assertEquals(false, parser.parse(values[1]).toBoolean())
137     assertEquals(true, parser.parse(values[2]).isNull)
138   }
139 
140   @Test
testStringsnull141   fun testStrings() {
142     val values = arrayOf(
143       "\"\"",
144       "\"a\"",
145       "\"hello world\"",
146       "\"\\\"\\\\\\/\\b\\f\\n\\r\\t cool\"",
147       "\"\\u0000\"",
148       "\"\\u0021\"",
149       "\"hell\\u24AC\\n\\ro wor \\u0021 ld\"",
150       "\"\\/_\\\\_\\\"_\\uCAFE\\uBABE\\uAB98\\uFCDE\\ubcda\\uef4A\\b\\n\\r\\t`1~!@#\$%^&*()_+-=[]{}|;:',./<>?\"",
151     )
152     val parser = JSONParser()
153 
154     // empty
155     var ref = parser.parse(values[0])
156     assertEquals(true, ref.isString)
157     assertEquals("", ref.toString())
158     // a
159     ref = parser.parse(values[1])
160     assertEquals(true, ref.isString)
161     assertEquals("a", ref.toString())
162     // hello world
163     ref = parser.parse(values[2])
164     assertEquals(true, ref.isString)
165     assertEquals("hello world", ref.toString())
166     // "\\\"\\\\\\/\\b\\f\\n\\r\\t\""
167     ref = parser.parse(values[3])
168     assertEquals(true, ref.isString)
169     assertEquals("\"\\/\b${12.toChar()}\n\r\t cool", ref.toString())
170     // 0
171     ref = parser.parse(values[4])
172     assertEquals(true, ref.isString)
173     assertEquals(0.toChar().toString(), ref.toString())
174     // u0021
175     ref = parser.parse(values[5])
176     assertEquals(true, ref.isString)
177     assertEquals(0x21.toChar().toString(), ref.toString())
178     // "\"hell\\u24AC\\n\\ro wor \\u0021 ld\"",
179     ref = parser.parse(values[6])
180     assertEquals(true, ref.isString)
181     assertEquals("hell${0x24AC.toChar()}\n\ro wor ${0x21.toChar()} ld", ref.toString())
182 
183     ref = parser.parse(values[7])
184     println(ref.toJson())
185     assertEquals(true, ref.isString)
186     assertEquals("/_\\_\"_쫾몾ꮘﳞ볚\b\n\r\t`1~!@#$%^&*()_+-=[]{}|;:',./<>?", ref.toString())
187   }
188 
189   @Test
testUnicodenull190   fun testUnicode() {
191     // took from test/unicode_test.json
192     val data = """
193       {
194         "name": "unicode_test",
195         "testarrayofstring": [
196           "Цлїςσδε",
197           "フムアムカモケモ",
198           "フムヤムカモケモ",
199           "㊀㊁㊂㊃㊄",
200           "☳☶☲",
201           "����"
202         ],
203         "testarrayoftables": [
204           {
205             "name": "Цлїςσδε"
206           },
207           {
208             "name": "☳☶☲"
209           },
210           {
211             "name": "フムヤムカモケモ"
212           },
213           {
214             "name": "㊀㊁㊂㊃㊄"
215           },
216           {
217             "name": "フムアムカモケモ"
218           },
219           {
220             "name": "����"
221           }
222         ]
223       }
224     """.trimIndent()
225     val parser = JSONParser()
226     val ref = parser.parse(data)
227 
228     // name
229     assertEquals(3, ref.toMap().size)
230     assertEquals("unicode_test", ref["name"].toString())
231     // testarrayofstring
232     assertEquals(6, ref["testarrayofstring"].toVector().size)
233     assertEquals("Цлїςσδε", ref["testarrayofstring"][0].toString())
234     assertEquals("フムアムカモケモ", ref["testarrayofstring"][1].toString())
235     assertEquals("フムヤムカモケモ", ref["testarrayofstring"][2].toString())
236     assertEquals("㊀㊁㊂㊃㊄", ref["testarrayofstring"][3].toString())
237     assertEquals("☳☶☲", ref["testarrayofstring"][4].toString())
238     assertEquals("����", ref["testarrayofstring"][5].toString())
239     // testarrayoftables
240     assertEquals(6, ref["testarrayoftables"].toVector().size)
241     assertEquals("Цлїςσδε", ref["testarrayoftables"][0]["name"].toString())
242     assertEquals("☳☶☲", ref["testarrayoftables"][1]["name"].toString())
243     assertEquals("フムヤムカモケモ", ref["testarrayoftables"][2]["name"].toString())
244     assertEquals("㊀㊁㊂㊃㊄", ref["testarrayoftables"][3]["name"].toString())
245     assertEquals("フムアムカモケモ", ref["testarrayoftables"][4]["name"].toString())
246     assertEquals("����", ref["testarrayoftables"][5]["name"].toString())
247   }
248 
249   @Test
testArraysnull250   fun testArrays() {
251     val values = arrayOf(
252       "[]",
253       "[1]",
254       "[0,1, 2,3  , 4 ]",
255       "[1.0, 2.2250738585072014E-308,  4.9E-320]",
256       "[1.0, 2,  \"hello world\"]   ",
257       "[ 1.1, 2, [ \"hello\" ] ]",
258       "[[[1]]]"
259     )
260     val parser = JSONParser()
261 
262     // empty
263     var ref = parser.parse(values[0])
264     assertEquals(true, ref.isVector)
265     assertEquals(0, parser.parse(values[0]).toVector().size)
266     // single
267     ref = parser.parse(values[1])
268     assertEquals(true, ref.isTypedVector)
269     assertEquals(1, ref[0].toInt())
270     // ints
271     ref = parser.parse(values[2])
272     assertEquals(true, ref.isTypedVector)
273     assertEquals(T_VECTOR_INT, ref.type)
274     assertEquals(5, ref.toVector().size)
275     for (i in 0..4) {
276       assertEquals(i, ref[i].toInt())
277     }
278     // floats
279     ref = parser.parse(values[3])
280     assertEquals(true, ref.isTypedVector)
281     assertEquals(T_VECTOR_FLOAT, ref.type)
282     assertEquals(3, ref.toVector().size)
283     assertEquals(1.0, ref[0].toDouble())
284     assertEquals(2.2250738585072014E-308, ref[1].toDouble())
285     assertEquals(4.9E-320, ref[2].toDouble())
286     // mixed
287     ref = parser.parse(values[4])
288     assertEquals(false, ref.isTypedVector)
289     assertEquals(T_VECTOR, ref.type)
290     assertEquals(1.0, ref[0].toDouble())
291     assertEquals(2, ref[1].toInt())
292     assertEquals("hello world", ref[2].toString())
293     // nester array
294     ref = parser.parse(values[5])
295     assertEquals(false, ref.isTypedVector)
296     assertEquals(T_VECTOR, ref.type)
297     assertEquals(1.1, ref[0].toDouble())
298     assertEquals(2, ref[1].toInt())
299     assertEquals("hello", ref[2][0].toString())
300   }
301 
302   /**
303    * Several test cases provided by json.org
304    * For more details, see: http://json.org/JSON_checker/, with only
305    * one exception. Single strings are considered accepted, whereas on
306    * the test suit is should fail.
307    */
308   @Test
testParseMustFailnull309   fun testParseMustFail() {
310     val failList = listOf(
311       "[\"Unclosed array\"",
312       "{unquoted_key: \"keys must be quoted\"}",
313       "[\"extra comma\",]",
314       "[\"double extra comma\",,]",
315       "[   , \"<-- missing value\"]",
316       "[\"Comma after the close\"],",
317       "[\"Extra close\"]]",
318       "{\"Extra comma\": true,}",
319       "{\"Extra value after close\": true} \"misplaced quoted value\"",
320       "{\"Illegal expression\": 1 + 2}",
321       "{\"Illegal invocation\": alert()}",
322       "{\"Numbers cannot have leading zeroes\": 013}",
323       "{\"Numbers cannot be hex\": 0x14}",
324       "[\"Illegal backslash escape: \\x15\"]",
325       "[\\naked]",
326       "[\"Illegal backslash escape: \\017\"]",
327       "[[[[[[[[[[[[[[[[[[[[[[[\"Too deep\"]]]]]]]]]]]]]]]]]]]]]]]",
328       "{\"Missing colon\" null}",
329       "{\"Double colon\":: null}",
330       "{\"Comma instead of colon\", null}",
331       "[\"Colon instead of comma\": false]",
332       "[\"Bad value\", truth]",
333       "['single quote']",
334       "[\"\ttab\tcharacter\tin\tstring\t\"]",
335       "[\"tab\\   character\\   in\\  string\\  \"]",
336       "[\"line\nbreak\"]",
337       "[\"line\\\nbreak\"]",
338       "[0e]",
339       "[0e+]",
340       "[0e+-1]",
341       "{\"Comma instead if closing brace\": true,",
342       "[\"mismatch\"}"
343     )
344     for (data in failList) {
345       try {
346         JSONParser().parse(ArrayReadBuffer(data.encodeToByteArray()))
347         assertTrue(false, "SHOULD NOT PASS: $data")
348       } catch (e: IllegalStateException) {
349         println("FAIL $e")
350       }
351     }
352   }
353 
354   @Test
testParseMustPassnull355   fun testParseMustPass() {
356     val passList = listOf(
357       "[\n" +
358         "    \"JSON Test Pattern pass1\",\n" +
359         "    {\"object with 1 member\":[\"array with 1 element\"]},\n" +
360         "    {},\n" +
361         "    [],\n" +
362         "    -42,\n" +
363         "    true,\n" +
364         "    false,\n" +
365         "    null,\n" +
366         "    {\n" +
367         "        \"integer\": 1234567890,\n" +
368         "        \"real\": -9876.543210,\n" +
369         "        \"e\": 0.123456789e-12,\n" +
370         "        \"E\": 1.234567890E+34,\n" +
371         "        \"\":  23456789012E66,\n" +
372         "        \"zero\": 0,\n" +
373         "        \"one\": 1,\n" +
374         "        \"space\": \" \",\n" +
375         "        \"quote\": \"\\\"\",\n" +
376         "        \"backslash\": \"\\\\\",\n" +
377         "        \"controls\": \"\\b\\f\\n\\r\\t\",\n" +
378         "        \"slash\": \"/ & \\/\",\n" +
379         "        \"alpha\": \"abcdefghijklmnopqrstuvwyz\",\n" +
380         "        \"ALPHA\": \"ABCDEFGHIJKLMNOPQRSTUVWYZ\",\n" +
381         "        \"digit\": \"0123456789\",\n" +
382         "        \"0123456789\": \"digit\",\n" +
383         "        \"special\": \"`1~!@#\$%^&*()_+-={':[,]}|;.</>?\",\n" +
384         "        \"hex\": \"\\u0123\\u4567\\u89AB\\uCDEF\\uabcd\\uef4A\",\n" +
385         "        \"true\": true,\n" +
386         "        \"false\": false,\n" +
387         "        \"null\": null,\n" +
388         "        \"array\":[  ],\n" +
389         "        \"object\":{  },\n" +
390         "        \"address\": \"50 St. James Street\",\n" +
391         "        \"url\": \"http://www.JSON.org/\",\n" +
392         "        \"comment\": \"// /* <!-- --\",\n" +
393         "        \"# -- --> */\": \" \",\n" +
394         "        \" s p a c e d \" :[1,2 , 3\n" +
395         "\n" +
396         ",\n" +
397         "\n" +
398         "4 , 5        ,          6           ,7        ],\"compact\":[1,2,3,4,5,6,7],\n" +
399         "        \"jsontext\": \"{\\\"object with 1 member\\\":[\\\"array with 1 element\\\"]}\",\n" +
400         "        \"quotes\": \"&#34; \\u0022 %22 0x22 034 &#x22;\",\n" +
401         "        \"\\/\\\\\\\"\\uCAFE\\uBABE\\uAB98\\uFCDE\\ubcda\\uef4A\\b\\f\\n\\r\\t`1~!@#\$%^&*()_+-=[]{}|;:',./<>?\"\n" +
402         ": \"A key can be any string\"\n" +
403         "    },\n" +
404         "    0.5 ,98.6\n" +
405         ",\n" +
406         "99.44\n" +
407         ",\n" +
408         "\n" +
409         "1066,\n" +
410         "1e1,\n" +
411         "0.1e1,\n" +
412         "1e-1,\n" +
413         "1e00,2e+00,2e-00\n" +
414         ",\"rosebud\"]",
415       "{\n" +
416         "    \"JSON Test Pattern pass3\": {\n" +
417         "        \"The outermost value\": \"must be an object or array.\",\n" +
418         "        \"In this test\": \"It is an object.\"\n" +
419         "    }\n" +
420         "}",
421       "[[[[[[[[[[[[[[[[[[[\"Not too deep\"]]]]]]]]]]]]]]]]]]]",
422     )
423     for (data in passList) {
424       JSONParser().parse(ArrayReadBuffer(data.encodeToByteArray()))
425     }
426   }
427 }
428