| 
									
										
										
										
											2021-03-29 17:14:01 +02:00
										 |  |  | // ArduinoJson - https://arduinojson.org
 | 
					
						
							| 
									
										
										
										
											2024-01-03 08:47:06 +01:00
										 |  |  | // Copyright © 2014-2024, Benoit BLANCHON
 | 
					
						
							| 
									
										
										
										
											2019-02-15 13:29:30 +01:00
										 |  |  | // MIT License
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define ARDUINOJSON_DECODE_UNICODE 1
 | 
					
						
							|  |  |  | #include <ArduinoJson.h>
 | 
					
						
							|  |  |  | #include <catch.hpp>
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-04-11 10:03:47 +02:00
										 |  |  | #include "Allocators.hpp"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-03-29 19:28:44 +02:00
										 |  |  | using ArduinoJson::detail::sizeofArray; | 
					
						
							| 
									
										
										
										
											2023-03-29 19:18:06 +02:00
										 |  |  | using ArduinoJson::detail::sizeofObject; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-02-15 13:29:30 +01:00
										 |  |  | TEST_CASE("Valid JSON strings value") { | 
					
						
							|  |  |  |   struct TestCase { | 
					
						
							|  |  |  |     const char* input; | 
					
						
							|  |  |  |     const char* expectedOutput; | 
					
						
							|  |  |  |   }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   TestCase testCases[] = { | 
					
						
							|  |  |  |       {"\"hello world\"", "hello world"}, | 
					
						
							|  |  |  |       {"\'hello world\'", "hello world"}, | 
					
						
							| 
									
										
										
										
											2020-02-17 09:15:34 +01:00
										 |  |  |       {"'\"'", "\""}, | 
					
						
							|  |  |  |       {"'\\\\'", "\\"}, | 
					
						
							|  |  |  |       {"'\\/'", "/"}, | 
					
						
							|  |  |  |       {"'\\b'", "\b"}, | 
					
						
							|  |  |  |       {"'\\f'", "\f"}, | 
					
						
							|  |  |  |       {"'\\n'", "\n"}, | 
					
						
							|  |  |  |       {"'\\r'", "\r"}, | 
					
						
							|  |  |  |       {"'\\t'", "\t"}, | 
					
						
							| 
									
										
										
										
											2019-02-15 13:29:30 +01:00
										 |  |  |       {"\"1\\\"2\\\\3\\/4\\b5\\f6\\n7\\r8\\t9\"", "1\"2\\3/4\b5\f6\n7\r8\t9"}, | 
					
						
							|  |  |  |       {"'\\u0041'", "A"}, | 
					
						
							| 
									
										
										
										
											2020-01-02 13:14:02 +01:00
										 |  |  |       {"'\\u00e4'", "\xc3\xa4"},                 // ä
 | 
					
						
							|  |  |  |       {"'\\u00E4'", "\xc3\xa4"},                 // ä
 | 
					
						
							|  |  |  |       {"'\\u3042'", "\xe3\x81\x82"},             // あ
 | 
					
						
							|  |  |  |       {"'\\ud83d\\udda4'", "\xf0\x9f\x96\xa4"},  // 🖤
 | 
					
						
							| 
									
										
										
										
											2020-01-27 12:10:10 +01:00
										 |  |  |       {"'\\uF053'", "\xef\x81\x93"},             // issue #1173
 | 
					
						
							|  |  |  |       {"'\\uF015'", "\xef\x80\x95"},             // issue #1173
 | 
					
						
							|  |  |  |       {"'\\uF054'", "\xef\x81\x94"},             // issue #1173
 | 
					
						
							| 
									
										
										
										
											2019-02-15 13:29:30 +01:00
										 |  |  |   }; | 
					
						
							|  |  |  |   const size_t testCount = sizeof(testCases) / sizeof(testCases[0]); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-07-17 18:15:13 +02:00
										 |  |  |   JsonDocument doc; | 
					
						
							| 
									
										
										
										
											2019-02-15 13:29:30 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |   for (size_t i = 0; i < testCount; i++) { | 
					
						
							|  |  |  |     const TestCase& testCase = testCases[i]; | 
					
						
							|  |  |  |     CAPTURE(testCase.input); | 
					
						
							|  |  |  |     DeserializationError err = deserializeJson(doc, testCase.input); | 
					
						
							| 
									
										
										
										
											2020-02-17 09:15:34 +01:00
										 |  |  |     CHECK(err == DeserializationError::Ok); | 
					
						
							|  |  |  |     CHECK(doc.as<std::string>() == testCase.expectedOutput); | 
					
						
							| 
									
										
										
										
											2019-02-15 13:29:30 +01:00
										 |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-08-31 13:58:27 +02:00
										 |  |  | TEST_CASE("\\u0000") { | 
					
						
							| 
									
										
										
										
											2023-07-17 18:15:13 +02:00
										 |  |  |   JsonDocument doc; | 
					
						
							| 
									
										
										
										
											2021-08-31 13:58:27 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |   DeserializationError err = deserializeJson(doc, "\"wx\\u0000yz\""); | 
					
						
							|  |  |  |   REQUIRE(err == DeserializationError::Ok); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   const char* result = doc.as<const char*>(); | 
					
						
							|  |  |  |   CHECK(result[0] == 'w'); | 
					
						
							|  |  |  |   CHECK(result[1] == 'x'); | 
					
						
							|  |  |  |   CHECK(result[2] == 0); | 
					
						
							|  |  |  |   CHECK(result[3] == 'y'); | 
					
						
							|  |  |  |   CHECK(result[4] == 'z'); | 
					
						
							|  |  |  |   CHECK(result[5] == 0); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-11-21 15:07:56 +01:00
										 |  |  |   CHECK(doc.as<JsonString>().size() == 5); | 
					
						
							|  |  |  |   CHECK(doc.as<std::string>().size() == 5); | 
					
						
							| 
									
										
										
										
											2021-08-31 13:58:27 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-02-15 13:29:30 +01:00
										 |  |  | TEST_CASE("Truncated JSON string") { | 
					
						
							|  |  |  |   const char* testCases[] = {"\"hello", "\'hello", "'\\u", "'\\u00", "'\\u000"}; | 
					
						
							|  |  |  |   const size_t testCount = sizeof(testCases) / sizeof(testCases[0]); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-07-17 18:15:13 +02:00
										 |  |  |   JsonDocument doc; | 
					
						
							| 
									
										
										
										
											2019-02-15 13:29:30 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |   for (size_t i = 0; i < testCount; i++) { | 
					
						
							|  |  |  |     const char* input = testCases[i]; | 
					
						
							|  |  |  |     CAPTURE(input); | 
					
						
							|  |  |  |     REQUIRE(deserializeJson(doc, input) == | 
					
						
							|  |  |  |             DeserializationError::IncompleteInput); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | TEST_CASE("Invalid JSON string") { | 
					
						
							|  |  |  |   const char* testCases[] = {"'\\u'",     "'\\u000g'", "'\\u000'", | 
					
						
							| 
									
										
										
										
											2020-02-17 09:15:34 +01:00
										 |  |  |                              "'\\u000G'", "'\\u000/'", "'\\x1234'"}; | 
					
						
							| 
									
										
										
										
											2019-02-15 13:29:30 +01:00
										 |  |  |   const size_t testCount = sizeof(testCases) / sizeof(testCases[0]); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-07-17 18:15:13 +02:00
										 |  |  |   JsonDocument doc; | 
					
						
							| 
									
										
										
										
											2019-02-15 13:29:30 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |   for (size_t i = 0; i < testCount; i++) { | 
					
						
							|  |  |  |     const char* input = testCases[i]; | 
					
						
							|  |  |  |     CAPTURE(input); | 
					
						
							|  |  |  |     REQUIRE(deserializeJson(doc, input) == DeserializationError::InvalidInput); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2019-02-18 16:04:51 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-04-11 10:03:47 +02:00
										 |  |  | TEST_CASE("Allocation of the key fails") { | 
					
						
							| 
									
										
										
										
											2023-07-25 14:53:54 +02:00
										 |  |  |   TimebombAllocator timebomb(0); | 
					
						
							|  |  |  |   SpyingAllocator spy(&timebomb); | 
					
						
							|  |  |  |   JsonDocument doc(&spy); | 
					
						
							| 
									
										
										
										
											2019-02-18 16:04:51 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-04-11 10:03:47 +02:00
										 |  |  |   SECTION("Quoted string, first member") { | 
					
						
							| 
									
										
										
										
											2021-10-23 18:50:53 +02:00
										 |  |  |     REQUIRE(deserializeJson(doc, "{\"example\":1}") == | 
					
						
							| 
									
										
										
										
											2020-02-17 09:15:34 +01:00
										 |  |  |             DeserializationError::NoMemory); | 
					
						
							| 
									
										
										
										
											2023-07-26 06:06:38 +02:00
										 |  |  |     REQUIRE(spy.log() == AllocatorLog{ | 
					
						
							|  |  |  |                              AllocateFail(sizeofStringBuffer()), | 
					
						
							|  |  |  |                          }); | 
					
						
							| 
									
										
										
										
											2023-04-11 10:03:47 +02:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   SECTION("Quoted string, second member") { | 
					
						
							| 
									
										
										
										
											2023-07-25 14:53:54 +02:00
										 |  |  |     timebomb.setCountdown(3); | 
					
						
							| 
									
										
										
										
											2021-10-23 18:50:53 +02:00
										 |  |  |     REQUIRE(deserializeJson(doc, "{\"hello\":1,\"world\"}") == | 
					
						
							| 
									
										
										
										
											2023-04-11 10:03:47 +02:00
										 |  |  |             DeserializationError::NoMemory); | 
					
						
							| 
									
										
										
										
											2023-07-26 06:06:38 +02:00
										 |  |  |     REQUIRE(spy.log() == | 
					
						
							|  |  |  |             AllocatorLog{ | 
					
						
							|  |  |  |                 Allocate(sizeofStringBuffer()), | 
					
						
							|  |  |  |                 Reallocate(sizeofStringBuffer(), sizeofString("hello")), | 
					
						
							|  |  |  |                 Allocate(sizeofPool()), | 
					
						
							|  |  |  |                 AllocateFail(sizeofStringBuffer()), | 
					
						
							| 
									
										
										
										
											2023-07-31 17:34:17 +02:00
										 |  |  |                 ReallocateFail(sizeofPool(), sizeofObject(1)), | 
					
						
							| 
									
										
										
										
											2023-07-26 06:06:38 +02:00
										 |  |  |             }); | 
					
						
							| 
									
										
										
										
											2020-02-17 09:15:34 +01:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-04-11 10:03:47 +02:00
										 |  |  |   SECTION("Non-Quoted string, first member") { | 
					
						
							|  |  |  |     REQUIRE(deserializeJson(doc, "{example:1}") == | 
					
						
							| 
									
										
										
										
											2020-02-17 09:15:34 +01:00
										 |  |  |             DeserializationError::NoMemory); | 
					
						
							| 
									
										
										
										
											2023-07-26 06:06:38 +02:00
										 |  |  |     REQUIRE(spy.log() == AllocatorLog{ | 
					
						
							|  |  |  |                              AllocateFail(sizeofStringBuffer()), | 
					
						
							|  |  |  |                          }); | 
					
						
							| 
									
										
										
										
											2023-04-11 10:03:47 +02:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   SECTION("Non-Quoted string, second member") { | 
					
						
							| 
									
										
										
										
											2023-07-25 14:53:54 +02:00
										 |  |  |     timebomb.setCountdown(3); | 
					
						
							| 
									
										
										
										
											2021-10-23 18:50:53 +02:00
										 |  |  |     REQUIRE(deserializeJson(doc, "{hello:1,world}") == | 
					
						
							| 
									
										
										
										
											2023-04-11 10:03:47 +02:00
										 |  |  |             DeserializationError::NoMemory); | 
					
						
							| 
									
										
										
										
											2023-07-26 06:06:38 +02:00
										 |  |  |     REQUIRE(spy.log() == | 
					
						
							|  |  |  |             AllocatorLog{ | 
					
						
							|  |  |  |                 Allocate(sizeofStringBuffer()), | 
					
						
							|  |  |  |                 Reallocate(sizeofStringBuffer(), sizeofString("hello")), | 
					
						
							|  |  |  |                 Allocate(sizeofPool()), | 
					
						
							|  |  |  |                 AllocateFail(sizeofStringBuffer()), | 
					
						
							| 
									
										
										
										
											2023-07-31 17:34:17 +02:00
										 |  |  |                 ReallocateFail(sizeofPool(), sizeofObject(1)), | 
					
						
							| 
									
										
										
										
											2023-07-26 06:06:38 +02:00
										 |  |  |             }); | 
					
						
							| 
									
										
										
										
											2020-02-17 09:15:34 +01:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2019-02-18 16:04:51 +01:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2021-11-20 20:29:09 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-04-11 10:03:47 +02:00
										 |  |  | TEST_CASE("String allocation fails") { | 
					
						
							| 
									
										
										
										
											2023-07-25 14:53:54 +02:00
										 |  |  |   SpyingAllocator spy(FailingAllocator::instance()); | 
					
						
							|  |  |  |   JsonDocument doc(&spy); | 
					
						
							| 
									
										
										
										
											2021-11-20 20:29:09 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |   SECTION("Input is const char*") { | 
					
						
							|  |  |  |     REQUIRE(deserializeJson(doc, "\"hello\"") == | 
					
						
							|  |  |  |             DeserializationError::NoMemory); | 
					
						
							| 
									
										
										
										
											2023-07-26 06:06:38 +02:00
										 |  |  |     REQUIRE(spy.log() == AllocatorLog{ | 
					
						
							|  |  |  |                              AllocateFail(sizeofStringBuffer()), | 
					
						
							|  |  |  |                          }); | 
					
						
							| 
									
										
										
										
											2021-11-20 20:29:09 +01:00
										 |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2023-03-29 19:28:44 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | TEST_CASE("Deduplicate values") { | 
					
						
							| 
									
										
										
										
											2023-07-25 14:53:54 +02:00
										 |  |  |   SpyingAllocator spy; | 
					
						
							|  |  |  |   JsonDocument doc(&spy); | 
					
						
							| 
									
										
										
										
											2023-03-29 19:28:44 +02:00
										 |  |  |   deserializeJson(doc, "[\"example\",\"example\"]"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   CHECK(doc[0].as<const char*>() == doc[1].as<const char*>()); | 
					
						
							| 
									
										
										
										
											2023-07-26 06:06:38 +02:00
										 |  |  |   REQUIRE(spy.log() == | 
					
						
							|  |  |  |           AllocatorLog{ | 
					
						
							|  |  |  |               Allocate(sizeofPool()), | 
					
						
							|  |  |  |               Allocate(sizeofStringBuffer()), | 
					
						
							|  |  |  |               Reallocate(sizeofStringBuffer(), sizeofString("example")), | 
					
						
							|  |  |  |               Allocate(sizeofStringBuffer()), | 
					
						
							|  |  |  |               Deallocate(sizeofStringBuffer()), | 
					
						
							| 
									
										
										
										
											2023-07-31 17:34:17 +02:00
										 |  |  |               Reallocate(sizeofPool(), sizeofArray(2)), | 
					
						
							| 
									
										
										
										
											2023-07-26 06:06:38 +02:00
										 |  |  |           }); | 
					
						
							| 
									
										
										
										
											2023-03-29 19:28:44 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | TEST_CASE("Deduplicate keys") { | 
					
						
							| 
									
										
										
										
											2023-07-25 14:53:54 +02:00
										 |  |  |   SpyingAllocator spy; | 
					
						
							|  |  |  |   JsonDocument doc(&spy); | 
					
						
							| 
									
										
										
										
											2023-03-29 19:28:44 +02:00
										 |  |  |   deserializeJson(doc, "[{\"example\":1},{\"example\":2}]"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   const char* key1 = doc[0].as<JsonObject>().begin()->key().c_str(); | 
					
						
							|  |  |  |   const char* key2 = doc[1].as<JsonObject>().begin()->key().c_str(); | 
					
						
							|  |  |  |   CHECK(key1 == key2); | 
					
						
							| 
									
										
										
										
											2023-07-24 17:21:25 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-07-26 06:06:38 +02:00
										 |  |  |   REQUIRE(spy.log() == | 
					
						
							|  |  |  |           AllocatorLog{ | 
					
						
							|  |  |  |               Allocate(sizeofPool()), | 
					
						
							|  |  |  |               Allocate(sizeofStringBuffer()), | 
					
						
							|  |  |  |               Reallocate(sizeofStringBuffer(), sizeofString("example")), | 
					
						
							|  |  |  |               Allocate(sizeofStringBuffer()), | 
					
						
							|  |  |  |               Deallocate(sizeofStringBuffer()), | 
					
						
							| 
									
										
										
										
											2023-07-31 17:34:17 +02:00
										 |  |  |               Reallocate(sizeofPool(), sizeofArray(2) + 2 * sizeofObject(1)), | 
					
						
							| 
									
										
										
										
											2023-07-26 06:06:38 +02:00
										 |  |  |           }); | 
					
						
							| 
									
										
										
										
											2023-03-29 19:28:44 +02:00
										 |  |  | } |