test_json_native.h 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228
  1. /**************************************************************************/
  2. /* test_json_native.h */
  3. /**************************************************************************/
  4. /* This file is part of: */
  5. /* GODOT ENGINE */
  6. /* https://godotengine.org */
  7. /**************************************************************************/
  8. /* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
  9. /* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
  10. /* */
  11. /* Permission is hereby granted, free of charge, to any person obtaining */
  12. /* a copy of this software and associated documentation files (the */
  13. /* "Software"), to deal in the Software without restriction, including */
  14. /* without limitation the rights to use, copy, modify, merge, publish, */
  15. /* distribute, sublicense, and/or sell copies of the Software, and to */
  16. /* permit persons to whom the Software is furnished to do so, subject to */
  17. /* the following conditions: */
  18. /* */
  19. /* The above copyright notice and this permission notice shall be */
  20. /* included in all copies or substantial portions of the Software. */
  21. /* */
  22. /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
  23. /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
  24. /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
  25. /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
  26. /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
  27. /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
  28. /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
  29. /**************************************************************************/
  30. #ifndef TEST_JSON_NATIVE_H
  31. #define TEST_JSON_NATIVE_H
  32. #include "core/io/json.h"
  33. #include "core/variant/typed_array.h"
  34. #include "core/variant/typed_dictionary.h"
  35. #include "tests/test_macros.h"
  36. namespace TestJSONNative {
  37. String encode(const Variant &p_variant, bool p_full_objects = false) {
  38. return JSON::stringify(JSON::from_native(p_variant, p_full_objects), "", false);
  39. }
  40. Variant decode(const String &p_string, bool p_allow_objects = false) {
  41. return JSON::to_native(JSON::parse_string(p_string), p_allow_objects);
  42. }
  43. void test(const Variant &p_variant, const String &p_string, bool p_with_objects = false) {
  44. CHECK(encode(p_variant, p_with_objects) == p_string);
  45. CHECK(decode(p_string, p_with_objects).get_construct_string() == p_variant.get_construct_string());
  46. }
  47. TEST_CASE("[JSON][Native] Conversion between native and JSON formats") {
  48. // `Nil` and `bool` (represented as JSON keyword literals).
  49. test(Variant(), "null");
  50. test(false, "false");
  51. test(true, "true");
  52. // Numbers and strings (represented as JSON strings).
  53. test(1, R"("i:1")");
  54. test(1.0, R"("f:1.0")");
  55. test(String("abc"), R"("s:abc")");
  56. test(StringName("abc"), R"("sn:abc")");
  57. test(NodePath("abc"), R"("np:abc")");
  58. // Non-serializable types (always empty after deserialization).
  59. test(RID(), R"({"type":"RID"})");
  60. test(Callable(), R"({"type":"Callable"})");
  61. test(Signal(), R"({"type":"Signal"})");
  62. // Math types.
  63. test(Vector2(1, 2), R"({"type":"Vector2","args":[1.0,2.0]})");
  64. test(Vector2i(1, 2), R"({"type":"Vector2i","args":[1,2]})");
  65. test(Rect2(1, 2, 3, 4), R"({"type":"Rect2","args":[1.0,2.0,3.0,4.0]})");
  66. test(Rect2i(1, 2, 3, 4), R"({"type":"Rect2i","args":[1,2,3,4]})");
  67. test(Vector3(1, 2, 3), R"({"type":"Vector3","args":[1.0,2.0,3.0]})");
  68. test(Vector3i(1, 2, 3), R"({"type":"Vector3i","args":[1,2,3]})");
  69. test(Transform2D(1, 2, 3, 4, 5, 6), R"({"type":"Transform2D","args":[1.0,2.0,3.0,4.0,5.0,6.0]})");
  70. test(Vector4(1, 2, 3, 4), R"({"type":"Vector4","args":[1.0,2.0,3.0,4.0]})");
  71. test(Vector4i(1, 2, 3, 4), R"({"type":"Vector4i","args":[1,2,3,4]})");
  72. test(Plane(1, 2, 3, 4), R"({"type":"Plane","args":[1.0,2.0,3.0,4.0]})");
  73. test(Quaternion(1, 2, 3, 4), R"({"type":"Quaternion","args":[1.0,2.0,3.0,4.0]})");
  74. test(AABB(Vector3(1, 2, 3), Vector3(4, 5, 6)), R"({"type":"AABB","args":[1.0,2.0,3.0,4.0,5.0,6.0]})");
  75. const Basis b(Vector3(1, 2, 3), Vector3(4, 5, 6), Vector3(7, 8, 9));
  76. test(b, R"({"type":"Basis","args":[1.0,2.0,3.0,4.0,5.0,6.0,7.0,8.0,9.0]})");
  77. const Transform3D tr3d(Vector3(1, 2, 3), Vector3(4, 5, 6), Vector3(7, 8, 9), Vector3(10, 11, 12));
  78. test(tr3d, R"({"type":"Transform3D","args":[1.0,2.0,3.0,4.0,5.0,6.0,7.0,8.0,9.0,10.0,11.0,12.0]})");
  79. const Projection p(Vector4(1, 2, 3, 4), Vector4(5, 6, 7, 8), Vector4(9, 10, 11, 12), Vector4(13, 14, 15, 16));
  80. test(p, R"({"type":"Projection","args":[1.0,2.0,3.0,4.0,5.0,6.0,7.0,8.0,9.0,10.0,11.0,12.0,13.0,14.0,15.0,16.0]})");
  81. test(Color(1, 2, 3, 4), R"({"type":"Color","args":[1.0,2.0,3.0,4.0]})");
  82. // `Object`.
  83. Ref<Resource> res;
  84. res.instantiate();
  85. // The properties are stored in an array because the order in which they are assigned may be important during initialization.
  86. const String res_repr = R"({"type":"Resource","props":["resource_local_to_scene",false,"resource_name","s:","script",null]})";
  87. test(res, res_repr, true);
  88. ERR_PRINT_OFF;
  89. CHECK(encode(res) == "null");
  90. CHECK(decode(res_repr).get_type() == Variant::NIL);
  91. ERR_PRINT_ON;
  92. // `Dictionary`.
  93. Dictionary dict;
  94. dict[false] = true;
  95. dict[0] = 1;
  96. dict[0.0] = 1.0;
  97. // Godot dictionaries preserve insertion order, so an array is used for keys/values.
  98. test(dict, R"({"type":"Dictionary","args":[false,true,"i:0","i:1","f:0.0","f:1.0"]})");
  99. TypedDictionary<int64_t, int64_t> int_int_dict;
  100. int_int_dict[1] = 2;
  101. int_int_dict[3] = 4;
  102. test(int_int_dict, R"({"type":"Dictionary","key_type":"int","value_type":"int","args":["i:1","i:2","i:3","i:4"]})");
  103. TypedDictionary<int64_t, Variant> int_var_dict;
  104. int_var_dict[1] = "2";
  105. int_var_dict[3] = "4";
  106. test(int_var_dict, R"({"type":"Dictionary","key_type":"int","args":["i:1","s:2","i:3","s:4"]})");
  107. TypedDictionary<Variant, int64_t> var_int_dict;
  108. var_int_dict["1"] = 2;
  109. var_int_dict["3"] = 4;
  110. test(var_int_dict, R"({"type":"Dictionary","value_type":"int","args":["s:1","i:2","s:3","i:4"]})");
  111. Dictionary dict2;
  112. dict2["x"] = res;
  113. const String dict2_repr = vformat(R"({"type":"Dictionary","args":["s:x",%s]})", res_repr);
  114. test(dict2, dict2_repr, true);
  115. ERR_PRINT_OFF;
  116. CHECK(encode(dict2) == R"({"type":"Dictionary","args":["s:x",null]})");
  117. CHECK(decode(dict2_repr).get_construct_string() == "{\n\"x\": null\n}");
  118. ERR_PRINT_ON;
  119. TypedDictionary<String, Resource> res_dict;
  120. res_dict["x"] = res;
  121. const String res_dict_repr = vformat(R"({"type":"Dictionary","key_type":"String","value_type":"Resource","args":["s:x",%s]})", res_repr);
  122. test(res_dict, res_dict_repr, true);
  123. ERR_PRINT_OFF;
  124. CHECK(encode(res_dict) == "null");
  125. CHECK(decode(res_dict_repr).get_type() == Variant::NIL);
  126. ERR_PRINT_ON;
  127. // `Array`.
  128. Array arr;
  129. arr.push_back(true);
  130. arr.push_back(1);
  131. arr.push_back("abc");
  132. test(arr, R"([true,"i:1","s:abc"])");
  133. TypedArray<int64_t> int_arr;
  134. int_arr.push_back(1);
  135. int_arr.push_back(2);
  136. int_arr.push_back(3);
  137. test(int_arr, R"({"type":"Array","elem_type":"int","args":["i:1","i:2","i:3"]})");
  138. Array arr2;
  139. arr2.push_back(1);
  140. arr2.push_back(res);
  141. arr2.push_back(9);
  142. const String arr2_repr = vformat(R"(["i:1",%s,"i:9"])", res_repr);
  143. test(arr2, arr2_repr, true);
  144. ERR_PRINT_OFF;
  145. CHECK(encode(arr2) == R"(["i:1",null,"i:9"])");
  146. CHECK(decode(arr2_repr).get_construct_string() == "[1, null, 9]");
  147. ERR_PRINT_ON;
  148. TypedArray<Resource> res_arr;
  149. res_arr.push_back(res);
  150. const String res_arr_repr = vformat(R"({"type":"Array","elem_type":"Resource","args":[%s]})", res_repr);
  151. test(res_arr, res_arr_repr, true);
  152. ERR_PRINT_OFF;
  153. CHECK(encode(res_arr) == "null");
  154. CHECK(decode(res_arr_repr).get_type() == Variant::NIL);
  155. ERR_PRINT_ON;
  156. // Packed arrays.
  157. test(PackedByteArray({ 1, 2, 3 }), R"({"type":"PackedByteArray","args":[1,2,3]})");
  158. test(PackedInt32Array({ 1, 2, 3 }), R"({"type":"PackedInt32Array","args":[1,2,3]})");
  159. test(PackedInt64Array({ 1, 2, 3 }), R"({"type":"PackedInt64Array","args":[1,2,3]})");
  160. test(PackedFloat32Array({ 1, 2, 3 }), R"({"type":"PackedFloat32Array","args":[1.0,2.0,3.0]})");
  161. test(PackedFloat64Array({ 1, 2, 3 }), R"({"type":"PackedFloat64Array","args":[1.0,2.0,3.0]})");
  162. test(PackedStringArray({ "a", "b", "c" }), R"({"type":"PackedStringArray","args":["a","b","c"]})");
  163. const PackedVector2Array pv2arr({ Vector2(1, 2), Vector2(3, 4), Vector2(5, 6) });
  164. test(pv2arr, R"({"type":"PackedVector2Array","args":[1.0,2.0,3.0,4.0,5.0,6.0]})");
  165. const PackedVector3Array pv3arr({ Vector3(1, 2, 3), Vector3(4, 5, 6), Vector3(7, 8, 9) });
  166. test(pv3arr, R"({"type":"PackedVector3Array","args":[1.0,2.0,3.0,4.0,5.0,6.0,7.0,8.0,9.0]})");
  167. const PackedColorArray pcolarr({ Color(1, 2, 3, 4), Color(5, 6, 7, 8), Color(9, 10, 11, 12) });
  168. test(pcolarr, R"({"type":"PackedColorArray","args":[1.0,2.0,3.0,4.0,5.0,6.0,7.0,8.0,9.0,10.0,11.0,12.0]})");
  169. const PackedVector4Array pv4arr({ Vector4(1, 2, 3, 4), Vector4(5, 6, 7, 8), Vector4(9, 10, 11, 12) });
  170. test(pv4arr, R"({"type":"PackedVector4Array","args":[1.0,2.0,3.0,4.0,5.0,6.0,7.0,8.0,9.0,10.0,11.0,12.0]})");
  171. }
  172. } // namespace TestJSONNative
  173. #endif // TEST_JSON_NATIVE_H