From 2b5b8fb4c5fdb46bf542736c316dd4e5ec06f167 Mon Sep 17 00:00:00 2001 From: Benoit Blanchon Date: Fri, 31 Oct 2014 16:30:10 +0100 Subject: [PATCH 1/8] Removed empty files --- src/Internals/CompactJsonWriter.cpp | 7 ------- src/Internals/PrettyJsonWriter.cpp | 7 ------- 2 files changed, 14 deletions(-) delete mode 100644 src/Internals/CompactJsonWriter.cpp delete mode 100644 src/Internals/PrettyJsonWriter.cpp diff --git a/src/Internals/CompactJsonWriter.cpp b/src/Internals/CompactJsonWriter.cpp deleted file mode 100644 index 587496b3..00000000 --- a/src/Internals/CompactJsonWriter.cpp +++ /dev/null @@ -1,7 +0,0 @@ -// Copyright Benoit Blanchon 2014 -// MIT License -// -// Arduino JSON library -// https://github.com/bblanchon/ArduinoJson - -#include "ArduinoJson/Internals/CompactJsonWriter.hpp" diff --git a/src/Internals/PrettyJsonWriter.cpp b/src/Internals/PrettyJsonWriter.cpp deleted file mode 100644 index b6a03812..00000000 --- a/src/Internals/PrettyJsonWriter.cpp +++ /dev/null @@ -1,7 +0,0 @@ -// Copyright Benoit Blanchon 2014 -// MIT License -// -// Arduino JSON library -// https://github.com/bblanchon/ArduinoJson - -#include "ArduinoJson/Internals/PrettyJsonWriter.hpp" From 74b45445603151532b3fa2db524578337a736b87 Mon Sep 17 00:00:00 2001 From: Benoit Blanchon Date: Fri, 31 Oct 2014 16:50:21 +0100 Subject: [PATCH 2/8] Fixed parsing when opening brace/bracket is missing --- src/Internals/JsonParser.cpp | 6 +++--- test/JsonParser_Array_Tests.cpp | 6 +++++- test/JsonParser_Object_Tests.cpp | 8 +++++--- 3 files changed, 13 insertions(+), 7 deletions(-) diff --git a/src/Internals/JsonParser.cpp b/src/Internals/JsonParser.cpp index 70c5f98d..de736c02 100644 --- a/src/Internals/JsonParser.cpp +++ b/src/Internals/JsonParser.cpp @@ -74,9 +74,9 @@ void JsonParser::parseAnythingTo(JsonValue &destination) { } JsonArray &JsonParser::parseArray() { - skip('['); + if (!skip('[')) return JsonArray::invalid(); // missing opening bracket - if (isEnd()) return JsonArray::invalid(); + if (isEnd()) return JsonArray::invalid(); // end of stream JsonArray &array = _buffer->createArray(); if (skip(']')) return array; // empty array @@ -127,7 +127,7 @@ void JsonParser::parseNullTo(JsonValue &destination) { } JsonObject &JsonParser::parseObject() { - skip('{'); + if (!skip('{')) return JsonObject::invalid(); // missing opening brace if (isEnd()) return JsonObject::invalid(); // premature ending diff --git a/test/JsonParser_Array_Tests.cpp b/test/JsonParser_Array_Tests.cpp index db3ef8a2..c4ba4922 100644 --- a/test/JsonParser_Array_Tests.cpp +++ b/test/JsonParser_Array_Tests.cpp @@ -58,9 +58,13 @@ TEST_F(JsonParser_Array_Tests, EmptyArray) { sizeMustBe(0); } +TEST_F(JsonParser_Array_Tests, MissingOpeningBracket) { + whenInputIs("]"); + parseMustFail(); +} + TEST_F(JsonParser_Array_Tests, ArrayWithNoEnd) { whenInputIs("["); - parseMustFail(); } diff --git a/test/JsonParser_Object_Tests.cpp b/test/JsonParser_Object_Tests.cpp index 95403610..5d25c536 100644 --- a/test/JsonParser_Object_Tests.cpp +++ b/test/JsonParser_Object_Tests.cpp @@ -45,22 +45,24 @@ TEST_F(JsonParser_Object_Test, EmptyObject) { sizeMustBe(0); } +TEST_F(JsonParser_Object_Test, MissingOpeningBrace) { + whenInputIs("}"); + parseMustFail(); +} + TEST_F(JsonParser_Object_Test, MissingClosingBrace) { whenInputIs("{"); parseMustFail(); - sizeMustBe(0); } TEST_F(JsonParser_Object_Test, MissingColonAndValue) { whenInputIs("{\"key\"}"); parseMustFail(); - sizeMustBe(0); } TEST_F(JsonParser_Object_Test, MissingQuotesAndColonAndValue) { whenInputIs("{key}"); parseMustFail(); - sizeMustBe(0); } TEST_F(JsonParser_Object_Test, OneString) { From 98463ea168085863aec69745278f6a14acc6f4d3 Mon Sep 17 00:00:00 2001 From: Benoit Blanchon Date: Fri, 31 Oct 2014 18:41:34 +0100 Subject: [PATCH 3/8] Added a script to run tests continuously --- scripts/run-tests.sh | 44 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100644 scripts/run-tests.sh diff --git a/scripts/run-tests.sh b/scripts/run-tests.sh new file mode 100644 index 00000000..a41e83a8 --- /dev/null +++ b/scripts/run-tests.sh @@ -0,0 +1,44 @@ +#!/bin/bash + +FILE=../bin/ArduinoJsonTests.exe +MD5="" + +file_changed() { + [[ ! -f "$FILE" ]] && return 1 + NEW_MD5=$(md5sum $FILE) + [[ "$MD5" == "$NEW_MD5" ]] && return 1 + MD5=$NEW_MD5 + return 0 +} + +test_succeed() { + echo -en "\007"{,} +} + +test_failed() { + echo -en "\007"{,,,,,,,,,,,} +} + +run_tests() { + $FILE + case $? in + 0) + test_succeed + ;; + 1) + test_failed + ;; + esac +} + +while true +do + if file_changed + then + run_tests + else + sleep 2 + fi +done + + From fead9b50b1f9ae3a9487cb67724f69e4dd7323a9 Mon Sep 17 00:00:00 2001 From: Benoit Blanchon Date: Fri, 31 Oct 2014 21:08:04 +0100 Subject: [PATCH 4/8] Fixed bug in parser when "null", "true" or "false" is mispelled --- include/ArduinoJson/Internals/JsonParser.hpp | 1 + src/Internals/JsonParser.cpp | 27 ++++++++++++-------- test/JsonParser_Array_Tests.cpp | 15 +++++++++++ 3 files changed, 33 insertions(+), 10 deletions(-) diff --git a/include/ArduinoJson/Internals/JsonParser.hpp b/include/ArduinoJson/Internals/JsonParser.hpp index b423978a..be21b385 100644 --- a/include/ArduinoJson/Internals/JsonParser.hpp +++ b/include/ArduinoJson/Internals/JsonParser.hpp @@ -22,6 +22,7 @@ class JsonParser { bool isEnd() { return *_ptr == '\0'; } bool skip(char charToSkip); + bool skip(const char *wordToSkip); void skipSpaces(); void parseAnythingTo(JsonValue &destination); diff --git a/src/Internals/JsonParser.cpp b/src/Internals/JsonParser.cpp index de736c02..d7fe1fb0 100644 --- a/src/Internals/JsonParser.cpp +++ b/src/Internals/JsonParser.cpp @@ -30,6 +30,15 @@ bool JsonParser::skip(char charToSkip) { return true; } +bool JsonParser::skip(const char *wordToSkip) { + const char *charToSkip = wordToSkip; + while (*charToSkip && *_ptr == *charToSkip) { + charToSkip++; + _ptr++; + } + return *charToSkip == '\0'; +} + void JsonParser::parseAnythingTo(JsonValue &destination) { skipSpaces(); @@ -96,13 +105,10 @@ JsonArray &JsonParser::parseArray() { void JsonParser::parseBooleanTo(JsonValue &destination) { bool value = *_ptr == 't'; - // TODO: bug if string ends here !!! - - _ptr += value ? 4 : 5; - // 4 = strlen("true") - // 5 = strlen("false"); - - destination = value; + if (skip(value ? "true" : "false")) + destination = value; + else + destination = JsonValue::invalid(); } void JsonParser::parseNumberTo(JsonValue &destination) { @@ -121,9 +127,10 @@ void JsonParser::parseNumberTo(JsonValue &destination) { } void JsonParser::parseNullTo(JsonValue &destination) { - _ptr += 4; // strlen("null") - - destination = static_cast(NULL); + if (skip("null")) + destination = static_cast(NULL); + else + destination = JsonValue::invalid(); } JsonObject &JsonParser::parseObject() { diff --git a/test/JsonParser_Array_Tests.cpp b/test/JsonParser_Array_Tests.cpp index c4ba4922..64f8b889 100644 --- a/test/JsonParser_Array_Tests.cpp +++ b/test/JsonParser_Array_Tests.cpp @@ -143,6 +143,21 @@ TEST_F(JsonParser_Array_Tests, TwoNulls) { secondElementMustBe(nullCharPtr); } +TEST_F(JsonParser_Array_Tests, IncompleteNull) { + whenInputIs("[nul!]"); + parseMustFail(); +} + +TEST_F(JsonParser_Array_Tests, IncompleteTrue) { + whenInputIs("[tru!]"); + parseMustFail(); +} + +TEST_F(JsonParser_Array_Tests, IncompleteFalse) { + whenInputIs("[fals!]"); + parseMustFail(); +} + TEST_F(JsonParser_Array_Tests, TwoStrings) { whenInputIs("[\"hello\",\"world\"]"); From 825ab0357eb2046d99e9ab1249b72956f62f7c24 Mon Sep 17 00:00:00 2001 From: Benoit Blanchon Date: Sat, 1 Nov 2014 09:09:58 +0100 Subject: [PATCH 5/8] Added integration test with a JSON sample from OpenWeatherMap --- test/IntegrationTests.cpp | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 test/IntegrationTests.cpp diff --git a/test/IntegrationTests.cpp b/test/IntegrationTests.cpp new file mode 100644 index 00000000..c2c6a02a --- /dev/null +++ b/test/IntegrationTests.cpp @@ -0,0 +1,37 @@ +// Copyright Benoit Blanchon 2014 +// MIT License +// +// Arduino JSON library +// https://github.com/bblanchon/ArduinoJson + +#include +#include +#include +#include + +using namespace ArduinoJson; + +TEST(IntegrationTests, OpenWeatherMap) { + StaticJsonBuffer<2048> json; + const char* input = + "{\"coord\":{\"lon\":-0.13,\"lat\":51.51},\"sys\":{\"type\":1,\"id\":" + "5093,\"message\":0.1177,\"country\":\"GB\",\"sunrise\":1414824893," + "\"sunset\":1414859596},\"weather\":[{\"id\":802,\"main\":\"Clouds\"," + "\"description\":\"scattered clouds\",\"icon\":\"03d\"}],\"base\":\"cmc " + "stations\",\"main\":{\"temp\":288.62,\"pressure\":1015,\"humidity\":87," + "\"temp_min\":287.15,\"temp_max\":290.15},\"wind\":{\"speed\":4.6," + "\"deg\":240},\"clouds\":{\"all\":40},\"dt\":1414825810,\"id\":2643743," + "\"name\":\"London\",\"cod\":200}"; + + char inputBuffer[1024]; + + strcpy(inputBuffer, input); + + JsonObject& o1 = json.parseObject(inputBuffer); + + char outputBuffer[1024]; + + o1.printTo(outputBuffer, sizeof(outputBuffer)); + + ASSERT_STREQ(input, outputBuffer); +} \ No newline at end of file From 9da7dce3101b29e4e28c085fbc9395f8bfdc1ec8 Mon Sep 17 00:00:00 2001 From: Benoit Blanchon Date: Sat, 1 Nov 2014 13:30:37 +0100 Subject: [PATCH 6/8] Fixed double formatting issue --- src/Arduino/Print.cpp | 2 +- src/Internals/JsonParser.cpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Arduino/Print.cpp b/src/Arduino/Print.cpp index 877447d7..6525f04a 100644 --- a/src/Arduino/Print.cpp +++ b/src/Arduino/Print.cpp @@ -19,7 +19,7 @@ size_t Print::print(const char s[]) { size_t Print::print(double value, int digits) { char tmp[32]; - sprintf(tmp, "%.*g", digits + 1, value); + sprintf(tmp, "%.*f", digits, value); return print(tmp); } diff --git a/src/Internals/JsonParser.cpp b/src/Internals/JsonParser.cpp index d7fe1fb0..1df73876 100644 --- a/src/Internals/JsonParser.cpp +++ b/src/Internals/JsonParser.cpp @@ -117,9 +117,9 @@ void JsonParser::parseNumberTo(JsonValue &destination) { if (*endOfLong == '.') { // stopped on a decimal separator - double douleValue = strtod(_ptr, &_ptr); + double doubleValue = strtod(_ptr, &_ptr); int decimals = _ptr - endOfLong - 1; - destination.set(douleValue, decimals); + destination.set(doubleValue, decimals); } else { _ptr = endOfLong; destination = longValue; From cd773e3f37651fa3cd598ef5458bb4824642bcf8 Mon Sep 17 00:00:00 2001 From: Benoit Blanchon Date: Sat, 1 Nov 2014 13:45:07 +0100 Subject: [PATCH 7/8] Added an integration test that uses prettyPrintTo() --- test/IntegrationTests.cpp | 55 +++++++++++++++++++++++++-------------- 1 file changed, 35 insertions(+), 20 deletions(-) diff --git a/test/IntegrationTests.cpp b/test/IntegrationTests.cpp index c2c6a02a..730f8073 100644 --- a/test/IntegrationTests.cpp +++ b/test/IntegrationTests.cpp @@ -11,27 +11,42 @@ using namespace ArduinoJson; -TEST(IntegrationTests, OpenWeatherMap) { +class IntegrationTests : public testing::TestWithParam { + protected: + virtual void SetUp() { + _input = GetParam(); + strcpy(inputBuffer, _input); + } + + const char* _input; + char inputBuffer[2048]; + char outputBuffer[2048]; + char intermediateBuffer[2048]; StaticJsonBuffer<2048> json; - const char* input = - "{\"coord\":{\"lon\":-0.13,\"lat\":51.51},\"sys\":{\"type\":1,\"id\":" - "5093,\"message\":0.1177,\"country\":\"GB\",\"sunrise\":1414824893," - "\"sunset\":1414859596},\"weather\":[{\"id\":802,\"main\":\"Clouds\"," - "\"description\":\"scattered clouds\",\"icon\":\"03d\"}],\"base\":\"cmc " - "stations\",\"main\":{\"temp\":288.62,\"pressure\":1015,\"humidity\":87," - "\"temp_min\":287.15,\"temp_max\":290.15},\"wind\":{\"speed\":4.6," - "\"deg\":240},\"clouds\":{\"all\":40},\"dt\":1414825810,\"id\":2643743," - "\"name\":\"London\",\"cod\":200}"; +}; - char inputBuffer[1024]; +TEST_P(IntegrationTests, ParseThenPrint) { + json.parseObject(inputBuffer).printTo(outputBuffer, sizeof(outputBuffer)); + ASSERT_STREQ(_input, outputBuffer); +} - strcpy(inputBuffer, input); +TEST_P(IntegrationTests, ParseThenPrettyPrintThenParseThenPrint) { + json.parseObject(inputBuffer) + .prettyPrintTo(intermediateBuffer, sizeof(intermediateBuffer)); + json.parseObject(intermediateBuffer) + .printTo(outputBuffer, sizeof(outputBuffer)); + ASSERT_STREQ(_input, outputBuffer); +} - JsonObject& o1 = json.parseObject(inputBuffer); - - char outputBuffer[1024]; - - o1.printTo(outputBuffer, sizeof(outputBuffer)); - - ASSERT_STREQ(input, outputBuffer); -} \ No newline at end of file +INSTANTIATE_TEST_CASE_P( + OpenWeatherMap, IntegrationTests, + testing::Values( + "{\"coord\":{\"lon\":-0.13,\"lat\":51.51},\"sys\":{\"type\":1,\"id\":" + "5093,\"message\":0.1177,\"country\":\"GB\",\"sunrise\":1414824893," + "\"sunset\":1414859596},\"weather\":[{\"id\":802,\"main\":\"Clouds\"," + "\"description\":\"scattered " + "clouds\",\"icon\":\"03d\"}],\"base\":\"cmc " + "stations\",\"main\":{\"temp\":288.62,\"pressure\":1015,\"humidity\":" + "87,\"temp_min\":287.15,\"temp_max\":290.15},\"wind\":{\"speed\":4.6," + "\"deg\":240},\"clouds\":{\"all\":40},\"dt\":1414825810,\"id\":2643743," + "\"name\":\"London\",\"cod\":200}")); \ No newline at end of file From ad83820257dc8270d2ce617a90989613ecd6e39a Mon Sep 17 00:00:00 2001 From: Benoit Blanchon Date: Sat, 1 Nov 2014 16:39:51 +0100 Subject: [PATCH 8/8] Added integration test with YQL data --- test/IntegrationTests.cpp | 74 ++++++++++++++++++++++++++++++++------- 1 file changed, 61 insertions(+), 13 deletions(-) diff --git a/test/IntegrationTests.cpp b/test/IntegrationTests.cpp index 730f8073..d0dd793d 100644 --- a/test/IntegrationTests.cpp +++ b/test/IntegrationTests.cpp @@ -19,10 +19,10 @@ class IntegrationTests : public testing::TestWithParam { } const char* _input; - char inputBuffer[2048]; - char outputBuffer[2048]; - char intermediateBuffer[2048]; - StaticJsonBuffer<2048> json; + char inputBuffer[10000]; + char outputBuffer[10000]; + char intermediateBuffer[10000]; + StaticJsonBuffer<10000> json; }; TEST_P(IntegrationTests, ParseThenPrint) { @@ -33,6 +33,7 @@ TEST_P(IntegrationTests, ParseThenPrint) { TEST_P(IntegrationTests, ParseThenPrettyPrintThenParseThenPrint) { json.parseObject(inputBuffer) .prettyPrintTo(intermediateBuffer, sizeof(intermediateBuffer)); + json.clear(); json.parseObject(intermediateBuffer) .printTo(outputBuffer, sizeof(outputBuffer)); ASSERT_STREQ(_input, outputBuffer); @@ -41,12 +42,59 @@ TEST_P(IntegrationTests, ParseThenPrettyPrintThenParseThenPrint) { INSTANTIATE_TEST_CASE_P( OpenWeatherMap, IntegrationTests, testing::Values( - "{\"coord\":{\"lon\":-0.13,\"lat\":51.51},\"sys\":{\"type\":1,\"id\":" - "5093,\"message\":0.1177,\"country\":\"GB\",\"sunrise\":1414824893," - "\"sunset\":1414859596},\"weather\":[{\"id\":802,\"main\":\"Clouds\"," - "\"description\":\"scattered " - "clouds\",\"icon\":\"03d\"}],\"base\":\"cmc " - "stations\",\"main\":{\"temp\":288.62,\"pressure\":1015,\"humidity\":" - "87,\"temp_min\":287.15,\"temp_max\":290.15},\"wind\":{\"speed\":4.6," - "\"deg\":240},\"clouds\":{\"all\":40},\"dt\":1414825810,\"id\":2643743," - "\"name\":\"London\",\"cod\":200}")); \ No newline at end of file + "{\"coord\":{\"lon\":145.77,\"lat\":-16.92},\"sys\":{\"type\":1,\"id\":" + "8166,\"message\":0.1222,\"country\":\"AU\",\"sunrise\":1414784325," + "\"sunset\":1414830137},\"weather\":[{\"id\":801,\"main\":\"Clouds\"," + "\"description\":\"few clouds\",\"icon\":\"02n\"}],\"base\":\"cmc " + "stations\",\"main\":{\"temp\":296.15,\"pressure\":1014,\"humidity\":" + "83,\"temp_min\":296.15,\"temp_max\":296.15},\"wind\":{\"speed\":2.22," + "\"deg\":114.501},\"clouds\":{\"all\":20},\"dt\":1414846800,\"id\":" + "2172797,\"name\":\"Cairns\",\"cod\":200}")); + +INSTANTIATE_TEST_CASE_P( + YahooQueryLanguage, IntegrationTests, + testing::Values( + "{\"query\":{\"count\":40,\"created\":\"2014-11-01T14:16:49Z\"," + "\"lang\":\"fr-FR\",\"results\":{\"item\":[{\"title\":\"Burkina army " + "backs Zida as interim leader\"},{\"title\":\"British jets intercept " + "Russian bombers\"},{\"title\":\"Doubts chip away at nation's most " + "trusted agencies\"},{\"title\":\"Cruise ship stuck off Norway, no " + "damage\"},{\"title\":\"U.S. military launches 10 air strikes in " + "Syria, Iraq\"},{\"title\":\"Blackout hits Bangladesh as line from " + "India fails\"},{\"title\":\"Burkina Faso president in Ivory Coast " + "after ouster\"},{\"title\":\"Kurds in Turkey rally to back city " + "besieged by IS\"},{\"title\":\"A majority of Scots would vote for " + "independence now:poll\"},{\"title\":\"Tunisia elections possible " + "model for region\"},{\"title\":\"Islamic State kills 85 more members " + "of Iraqi tribe\"},{\"title\":\"Iraqi officials:IS extremists line " + "up, kill 50\"},{\"title\":\"Burkina Faso army backs presidential " + "guard official to lead transition\"},{\"title\":\"Kurdish peshmerga " + "arrive with weapons in Syria's Kobani\"},{\"title\":\"Driver sought " + "in crash that killed 3 on Halloween\"},{\"title\":\"Ex-Marine arrives " + "in US after release from Mexico jail\"},{\"title\":\"UN panel " + "scrambling to finish climate report\"},{\"title\":\"Investigators, " + "Branson go to spacecraft crash site\"},{\"title\":\"Soldiers vie for " + "power after Burkina Faso president quits\"},{\"title\":\"For a man " + "without a party, turnout is big test\"},{\"title\":\"'We just had a " + "hunch':US marshals nab Eric Frein\"},{\"title\":\"Boko Haram leader " + "threatens to kill German hostage\"},{\"title\":\"Nurse free to move " + "about as restrictions eased\"},{\"title\":\"Former Burkina president " + "Compaore arrives in Ivory Coast:sources\"},{\"title\":\"Libyan port " + "rebel leader refuses to hand over oil ports to rival " + "group\"},{\"title\":\"Iraqi peshmerga fighters prepare for Syria " + "battle\"},{\"title\":\"1 Dem Senate candidate welcoming Obama's " + "help\"},{\"title\":\"Bikers cancel party after police recover " + "bar\"},{\"title\":\"New question in Texas:Can Davis survive " + "defeat?\"},{\"title\":\"Ukraine rebels to hold election, despite " + "criticism\"},{\"title\":\"Iraqi officials say Islamic State group " + "lines up, kills 50 tribesmen, women in Anbar " + "province\"},{\"title\":\"James rebounds, leads Cavaliers past " + "Bulls\"},{\"title\":\"UK warns travelers they could be terror " + "targets\"},{\"title\":\"Hello Kitty celebrates 40th " + "birthday\"},{\"title\":\"A look at people killed during space " + "missions\"},{\"title\":\"Nigeria's purported Boko Haram leader says " + "has 'married off' girls:AFP\"},{\"title\":\"Mexico orders immediate " + "release of Marine veteran\"},{\"title\":\"As election closes in, " + "Obama on center stage\"},{\"title\":\"Body of Zambian president " + "arrives home\"},{\"title\":\"South Africa arrests 2 Vietnamese for " + "poaching\"}]}}}"));