tests: test the tolerance of the JSON deserializer on custom JSON code
[nit.git] / tests / test_json_deserialization_plain.nit
diff --git a/tests/test_json_deserialization_plain.nit b/tests/test_json_deserialization_plain.nit
new file mode 100644 (file)
index 0000000..e577eda
--- /dev/null
@@ -0,0 +1,82 @@
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# 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.
+
+import json::serialization
+import json::static
+
+class MyClass
+       serialize
+
+       var i: Int
+       var s: String
+       var f: Float
+       var a: Array[String]
+       var o: nullable MyClass
+
+       redef fun to_s do return "<MyClass i:{i} s:{s} f:{f} a:[{a.join(", ")}] o:{o or else "<null>"}>"
+end
+
+redef class JsonObject
+       redef fun to_s do return "<JsonObject "+join(", ", ":")+">"
+end
+
+var tests = new Array[String]
+
+# Complete object, as would it be generated by serialization services
+tests.add """
+{"__kind": "obj", "__id": 0, "__class": "MyClass", "i": 123, "s": "hello", "f": 123.456, "a": ["one", "two"], "o": null}"""
+
+# Skipping the `__kind` and `__id` is allowed
+tests.add """
+{"__class": "MyClass", "i": 123, "s": "hello", "f": 123.456, "a": ["one", "two"], "o": null}"""
+
+# The attributes can be in any order
+tests.add """
+{"s": "hello", "o": null, "i": 123, "f": 123.456, "__class": "MyClass", "a": ["one", "two"]}"""
+
+# Extra attributes are ignored
+tests.add """
+{"__class": "MyClass", "i": 123, "s": "hello", "f": 123.456, "o": null, "a": ["one", "two"], "Some random attribute": 777}"""
+
+# Skipping `o` will cause an error but the attribute will be set to `null`
+tests.add """
+{"__class": "MyClass", "i": 123, "s": "hello", "f": 123.456, "a": ["one", "two"]}"""
+
+# Nest different classes
+tests.add """
+{"__class": "MyClass", "i": 123, "s": "hello", "f": 123.456, "a": ["one", "two"], "o":
+       {"__class": "MyClass", "i": 456, "s": "world", "f": 654.321, "a": ["1", "2"], "o": null}}"""
+
+# No `__class` is not advised and will raise an error, but it will be received as a `JsonObject`
+tests.add """
+{"i": 123, "s": "hello", "f": 123.456, "a": ["one", "two"], "o": null}"""
+
+# Invalid type on `o`
+tests.add """
+{"__class": "MyClass", "i": 123, "s": "hello", "f": 123.456, "a": ["one", "two"], "o": "Not the right type"}"""
+
+# Deserializing an invalid JSON string will raise an error
+tests.add "not valid json"
+
+# Missing attributes will raise errors and will crash on access
+#alt2#tests = ["""{"__class": "MyClass", "i": 123, "o": null}"""]
+
+for o in tests do
+       var deserializer = new JsonDeserializer(o)
+       var deserialized = deserializer.deserialize
+
+       print "# JSON: {o}"
+       if deserializer.errors.not_empty then print "# Errors: '{deserializer.errors.join("', '")}'"
+       print "# Nit: {deserialized or else "null"}\n"
+end