Implicitly duplicate String in the JsonBuffer (issue #84, #87)

This commit is contained in:
Benoit Blanchon
2015-07-25 15:38:12 +02:00
parent 92e687303d
commit c161f698fc
20 changed files with 762 additions and 253 deletions

View File

@ -7,103 +7,160 @@
#include <gtest/gtest.h>
#include <ArduinoJson.h>
TEST(ArduinoStringTests, JsonBuffer_ParseArray) {
DynamicJsonBuffer jsonBuffer;
String json("[1,2]");
JsonArray &array = jsonBuffer.parseArray(json);
class ArduinoStringTests : public ::testing::Test {
protected:
static void eraseString(String &str) {
char *p = const_cast<char *>(str.c_str());
while (*p) *p++ = '*';
}
DynamicJsonBuffer _jsonBuffer;
};
TEST_F(ArduinoStringTests, JsonBuffer_ParseArray) {
String json("[\"hello\"]");
JsonArray &array = _jsonBuffer.parseArray(json);
eraseString(json);
ASSERT_TRUE(array.success());
ASSERT_STREQ("hello", array[0]);
}
TEST(ArduinoStringTests, JsonBuffer_ParseObject) {
DynamicJsonBuffer jsonBuffer;
String json("{\"a\":1,\"b\":2}");
JsonObject &object = jsonBuffer.parseObject(json);
TEST_F(ArduinoStringTests, JsonBuffer_ParseObject) {
String json("{\"hello\":\"world\"}");
JsonObject &object = _jsonBuffer.parseObject(json);
eraseString(json);
ASSERT_TRUE(object.success());
ASSERT_STREQ("world", object["hello"]);
}
TEST(ArduinoStringTests, JsonVariant) {
String input = "Hello world!";
JsonVariant variant(input);
ASSERT_TRUE(variant.is<String>());
String output = variant.as<String>();
ASSERT_EQ(input, output);
}
TEST(ArduinoStringTests, JsonObject_Subscript) {
DynamicJsonBuffer jsonBuffer;
TEST_F(ArduinoStringTests, JsonObject_Subscript) {
char json[] = "{\"key\":\"value\"}";
JsonObject &object = jsonBuffer.parseObject(json);
JsonObject &object = _jsonBuffer.parseObject(json);
ASSERT_STREQ("value", object[String("key")]);
}
TEST(ArduinoStringTests, JsonObject_ConstSubscript) {
DynamicJsonBuffer jsonBuffer;
TEST_F(ArduinoStringTests, JsonObject_ConstSubscript) {
char json[] = "{\"key\":\"value\"}";
const JsonObject &object = jsonBuffer.parseObject(json);
const JsonObject &object = _jsonBuffer.parseObject(json);
ASSERT_STREQ("value", object[String("key")]);
}
TEST(ArduinoStringTests, JsonObject_Set) {
DynamicJsonBuffer jsonBuffer;
JsonObject &object = jsonBuffer.createObject();
String key = "key";
object.set(key, "value");
ASSERT_STREQ("value", object["key"]);
TEST_F(ArduinoStringTests, JsonObject_SetKey) {
JsonObject &object = _jsonBuffer.createObject();
String key("hello");
object.set(key, "world");
eraseString(key);
ASSERT_STREQ("world", object["hello"]);
}
TEST(ArduinoStringTests, JsonObject_Get) {
DynamicJsonBuffer jsonBuffer;
TEST_F(ArduinoStringTests, JsonObject_SetValue) {
JsonObject &object = _jsonBuffer.createObject();
String value("world");
object.set("hello", value);
eraseString(value);
ASSERT_STREQ("world", object["hello"]);
}
TEST_F(ArduinoStringTests, JsonObject_SetKeyValue) {
JsonObject &object = _jsonBuffer.createObject();
String key("hello");
String value("world");
object.set(key, value);
eraseString(key);
eraseString(value);
ASSERT_STREQ("world", object["hello"]);
}
TEST_F(ArduinoStringTests, JsonObject_Get) {
char json[] = "{\"key\":\"value\"}";
const JsonObject &object = jsonBuffer.parseObject(json);
const JsonObject &object = _jsonBuffer.parseObject(json);
ASSERT_STREQ("value", object.get(String("key")));
}
TEST(ArduinoStringTests, JsonObject_GetT) {
DynamicJsonBuffer jsonBuffer;
TEST_F(ArduinoStringTests, JsonObject_GetT) {
char json[] = "{\"key\":\"value\"}";
const JsonObject &object = jsonBuffer.parseObject(json);
const JsonObject &object = _jsonBuffer.parseObject(json);
ASSERT_STREQ("value", object.get<const char *>(String("key")));
}
TEST(ArduinoStringTests, JsonObject_IsT) {
DynamicJsonBuffer jsonBuffer;
TEST_F(ArduinoStringTests, JsonObject_IsT) {
char json[] = "{\"key\":\"value\"}";
const JsonObject &object = jsonBuffer.parseObject(json);
const JsonObject &object = _jsonBuffer.parseObject(json);
ASSERT_TRUE(object.is<const char *>(String("key")));
}
TEST(ArduinoStringTests, JsonObject_CreateNestedObject) {
DynamicJsonBuffer jsonBuffer;
TEST_F(ArduinoStringTests, JsonObject_CreateNestedObject) {
String key = "key";
char json[64];
JsonObject &object = jsonBuffer.createObject();
JsonObject &object = _jsonBuffer.createObject();
object.createNestedObject(key);
eraseString(key);
object.printTo(json, sizeof(json));
ASSERT_STREQ("{\"key\":{}}", json);
}
TEST(ArduinoStringTests, JsonObject_CreateNestedArray) {
DynamicJsonBuffer jsonBuffer;
TEST_F(ArduinoStringTests, JsonObject_CreateNestedArray) {
String key = "key";
char json[64];
JsonObject &object = jsonBuffer.createObject();
JsonObject &object = _jsonBuffer.createObject();
object.createNestedArray(key);
eraseString(key);
object.printTo(json, sizeof(json));
ASSERT_STREQ("{\"key\":[]}", json);
}
TEST(ArduinoStringTests, JsonObject_ContainsKey) {
DynamicJsonBuffer jsonBuffer;
TEST_F(ArduinoStringTests, JsonObject_ContainsKey) {
char json[] = "{\"key\":\"value\"}";
const JsonObject &object = jsonBuffer.parseObject(json);
const JsonObject &object = _jsonBuffer.parseObject(json);
ASSERT_TRUE(object.containsKey(String("key")));
}
TEST(ArduinoStringTests, JsonObject_Remove) {
DynamicJsonBuffer jsonBuffer;
TEST_F(ArduinoStringTests, JsonObject_Remove) {
char json[] = "{\"key\":\"value\"}";
JsonObject &object = jsonBuffer.parseObject(json);
JsonObject &object = _jsonBuffer.parseObject(json);
ASSERT_EQ(1, object.size());
object.remove(String("key"));
ASSERT_EQ(0, object.size());
}
}
TEST_F(ArduinoStringTests, JsonObjectSubscript_SetKey) {
JsonObject &object = _jsonBuffer.createObject();
String key("hello");
object[key] = "world";
eraseString(key);
ASSERT_STREQ("world", object["hello"]);
}
TEST_F(ArduinoStringTests, JsonObjectSubscript_SetValue) {
JsonObject &object = _jsonBuffer.createObject();
String value("world");
object["hello"] = value;
eraseString(value);
ASSERT_STREQ("world", object["hello"]);
}
TEST_F(ArduinoStringTests, JsonArray_Add) {
JsonArray &array = _jsonBuffer.createArray();
String value("hello");
array.add(value);
eraseString(value);
ASSERT_STREQ("hello", array[0]);
}
TEST_F(ArduinoStringTests, JsonArray_Set) {
JsonArray &array = _jsonBuffer.createArray();
String value("world");
array.add("hello");
array.set(0, value);
eraseString(value);
ASSERT_STREQ("world", array[0]);
}
TEST_F(ArduinoStringTests, JsonArraySubscript) {
JsonArray &array = _jsonBuffer.createArray();
String value("world");
array.add("hello");
array[0] = value;
eraseString(value);
ASSERT_STREQ("world", array[0]);
}

View File

@ -59,7 +59,7 @@ TEST_F(JsonObject_Container_Tests,
TEST_F(JsonObject_Container_Tests, CanStoreIntegers) {
_object["hello"] = 123;
_object["world"] = 456;
_object.set("world", 456);
EXPECT_EQ(123, _object["hello"].as<int>());
EXPECT_EQ(456, _object["world"].as<int>());
@ -67,7 +67,7 @@ TEST_F(JsonObject_Container_Tests, CanStoreIntegers) {
TEST_F(JsonObject_Container_Tests, CanStoreDoubles) {
_object["hello"] = 123.45;
_object["world"] = 456.78;
_object.set("world", 456.78);
EXPECT_EQ(123.45, _object["hello"].as<double>());
EXPECT_EQ(456.78, _object["world"].as<double>());
@ -75,7 +75,7 @@ TEST_F(JsonObject_Container_Tests, CanStoreDoubles) {
TEST_F(JsonObject_Container_Tests, CanStoreBooleans) {
_object["hello"] = true;
_object["world"] = false;
_object.set("world", false);
EXPECT_TRUE(_object["hello"].as<bool>());
EXPECT_FALSE(_object["world"].as<bool>());
@ -83,32 +83,32 @@ TEST_F(JsonObject_Container_Tests, CanStoreBooleans) {
TEST_F(JsonObject_Container_Tests, CanStoreStrings) {
_object["hello"] = "h3110";
_object["world"] = "w0r1d";
_object.set("world", "w0r1d");
EXPECT_STREQ("h3110", _object["hello"].as<const char*>());
EXPECT_STREQ("w0r1d", _object["world"].as<const char*>());
}
TEST_F(JsonObject_Container_Tests, CanStoreInnerArrays) {
JsonArray& innerarray1 = _jsonBuffer.createArray();
JsonArray& innerarray2 = _jsonBuffer.createArray();
TEST_F(JsonObject_Container_Tests, CanStoreArrays) {
JsonArray& array1 = _jsonBuffer.createArray();
JsonArray& array2 = _jsonBuffer.createArray();
_object["hello"] = innerarray1;
_object["world"] = innerarray2;
_object["hello"] = array1;
_object.set("world", array2);
EXPECT_EQ(&innerarray1, &_object["hello"].asArray());
EXPECT_EQ(&innerarray2, &_object["world"].asArray());
EXPECT_EQ(&array1, &_object["hello"].asArray());
EXPECT_EQ(&array2, &_object["world"].asArray());
}
TEST_F(JsonObject_Container_Tests, CanStoreInnerObjects) {
JsonObject& innerObject1 = _jsonBuffer.createObject();
JsonObject& innerObject2 = _jsonBuffer.createObject();
TEST_F(JsonObject_Container_Tests, CanStoreObjects) {
JsonObject& object1 = _jsonBuffer.createObject();
JsonObject& object2 = _jsonBuffer.createObject();
_object["hello"] = innerObject1;
_object["world"] = innerObject2;
_object["hello"] = object1;
_object.set("world", object2);
EXPECT_EQ(&innerObject1, &_object["hello"].asObject());
EXPECT_EQ(&innerObject2, &_object["world"].asObject());
EXPECT_EQ(&object1, &_object["hello"].asObject());
EXPECT_EQ(&object2, &_object["world"].asObject());
}
TEST_F(JsonObject_Container_Tests, ContainsKeyReturnsFalseForNonExistingKey) {

View File

@ -11,131 +11,105 @@ using namespace ArduinoJson::Internals;
class JsonObject_PrintTo_Tests : public testing::Test {
public:
JsonObject_PrintTo_Tests() : object(json.createObject()) {}
JsonObject_PrintTo_Tests() : _object(_jsonBuffer.createObject()) {}
protected:
void outputMustBe(const char *expected) {
char actual[256];
size_t actualLen = object.printTo(actual, sizeof(actual));
size_t measuredLen = object.measureLength();
size_t actualLen = _object.printTo(actual, sizeof(actual));
size_t measuredLen = _object.measureLength();
EXPECT_STREQ(expected, actual);
EXPECT_EQ(strlen(expected), actualLen);
EXPECT_EQ(strlen(expected), measuredLen);
}
StaticJsonBuffer<JSON_OBJECT_SIZE(2)> json;
JsonObject &object;
DynamicJsonBuffer _jsonBuffer;
JsonObject &_object;
};
TEST_F(JsonObject_PrintTo_Tests, EmptyObject) { outputMustBe("{}"); }
TEST_F(JsonObject_PrintTo_Tests, OneString) {
object["key"] = "value";
outputMustBe("{\"key\":\"value\"}");
}
TEST_F(JsonObject_PrintTo_Tests, TwoStrings) {
object["key1"] = "value1";
object["key2"] = "value2";
_object["key1"] = "value1";
_object.set("key2", "value2");
outputMustBe("{\"key1\":\"value1\",\"key2\":\"value2\"}");
}
TEST_F(JsonObject_PrintTo_Tests, RemoveFirst) {
object["key1"] = "value1";
object["key2"] = "value2";
object.remove("key1");
_object["key1"] = "value1";
_object["key2"] = "value2";
_object.remove("key1");
outputMustBe("{\"key2\":\"value2\"}");
}
TEST_F(JsonObject_PrintTo_Tests, RemoveLast) {
object["key1"] = "value1";
object["key2"] = "value2";
object.remove("key2");
_object["key1"] = "value1";
_object["key2"] = "value2";
_object.remove("key2");
outputMustBe("{\"key1\":\"value1\"}");
}
TEST_F(JsonObject_PrintTo_Tests, RemoveUnexistingKey) {
object["key1"] = "value1";
object["key2"] = "value2";
object.remove("key3");
_object["key1"] = "value1";
_object["key2"] = "value2";
_object.remove("key3");
outputMustBe("{\"key1\":\"value1\",\"key2\":\"value2\"}");
}
TEST_F(JsonObject_PrintTo_Tests, ReplaceExistingKey) {
object["key"] = "value1";
object["key"] = "value2";
_object["key"] = "value1";
_object["key"] = "value2";
outputMustBe("{\"key\":\"value2\"}");
}
TEST_F(JsonObject_PrintTo_Tests, OneStringOverCapacity) {
object["key1"] = "value1";
object["key2"] = "value2";
object["key3"] = "value3";
outputMustBe("{\"key1\":\"value1\",\"key2\":\"value2\"}");
TEST_F(JsonObject_PrintTo_Tests, TwoIntegers) {
_object["a"] = 1;
_object.set("b", 2);
outputMustBe("{\"a\":1,\"b\":2}");
}
TEST_F(JsonObject_PrintTo_Tests, OneInteger) {
object["key"] = 1;
outputMustBe("{\"key\":1}");
TEST_F(JsonObject_PrintTo_Tests, TwoDoublesFourDigits) {
_object["a"] = double_with_n_digits(3.14159265358979323846, 4);
_object.set("b", 2.71828182845904523536, 4);
outputMustBe("{\"a\":3.1416,\"b\":2.7183}");
}
TEST_F(JsonObject_PrintTo_Tests, OneDoubleFourDigits) {
object["key"] = double_with_n_digits(3.14159265358979323846, 4);
outputMustBe("{\"key\":3.1416}");
TEST_F(JsonObject_PrintTo_Tests, TwoDoubleDefaultDigits) {
_object["a"] = 3.14159265358979323846;
_object.set("b", 2.71828182845904523536);
outputMustBe("{\"a\":3.14,\"b\":2.72}");
}
TEST_F(JsonObject_PrintTo_Tests, OneDoubleDefaultDigits) {
object["key"] = 3.14159265358979323846;
outputMustBe("{\"key\":3.14}");
TEST_F(JsonObject_PrintTo_Tests, TwoNull) {
_object["a"] = static_cast<char *>(0);
_object.set("b", static_cast<char *>(0));
outputMustBe("{\"a\":null,\"b\":null}");
}
TEST_F(JsonObject_PrintTo_Tests, OneNull) {
object["key"] = static_cast<char *>(0);
outputMustBe("{\"key\":null}");
TEST_F(JsonObject_PrintTo_Tests, TwoBooleans) {
_object["a"] = true;
_object.set("b", false);
outputMustBe("{\"a\":true,\"b\":false}");
}
TEST_F(JsonObject_PrintTo_Tests, OneTrue) {
object["key"] = true;
outputMustBe("{\"key\":true}");
TEST_F(JsonObject_PrintTo_Tests, ThreeNestedArrays) {
_object.createNestedArray("a");
_object["b"] = _jsonBuffer.createArray();
_object.set("c", _jsonBuffer.createArray());
outputMustBe("{\"a\":[],\"b\":[],\"c\":[]}");
}
TEST_F(JsonObject_PrintTo_Tests, OneFalse) {
object["key"] = false;
outputMustBe("{\"key\":false}");
}
TEST_F(JsonObject_PrintTo_Tests, OneEmptyNestedArrayViaProxy) {
JsonArray &nestedArray = json.createArray();
object["key"] = nestedArray;
outputMustBe("{\"key\":[]}");
}
TEST_F(JsonObject_PrintTo_Tests, OneEmptyNestedObjectViaProxy) {
JsonObject &nestedArray = json.createObject();
object["key"] = nestedArray;
outputMustBe("{\"key\":{}}");
}
TEST_F(JsonObject_PrintTo_Tests, OneEmptyNestedObject) {
object.createNestedObject("key");
outputMustBe("{\"key\":{}}");
}
TEST_F(JsonObject_PrintTo_Tests, OneEmptyNestedArray) {
object.createNestedArray("key");
outputMustBe("{\"key\":[]}");
TEST_F(JsonObject_PrintTo_Tests, ThreeNestedObjects) {
_object.createNestedObject("a");
_object["b"] = _jsonBuffer.createObject();
_object.set("c", _jsonBuffer.createObject());
outputMustBe("{\"a\":{},\"b\":{},\"c\":{}}");
}

View File

@ -8,44 +8,49 @@
#include <ArduinoJson.h>
TEST(StaticJsonBuffer_CreateObject_Tests, GrowsWithObject) {
StaticJsonBuffer<JSON_OBJECT_SIZE(3)> json;
StaticJsonBuffer<JSON_OBJECT_SIZE(3)> buffer;
JsonObject &obj = json.createObject();
ASSERT_EQ(JSON_OBJECT_SIZE(0), json.size());
JsonObject &obj = buffer.createObject();
ASSERT_EQ(JSON_OBJECT_SIZE(0), buffer.size());
obj["hello"];
ASSERT_EQ(JSON_OBJECT_SIZE(0), json.size());
ASSERT_EQ(JSON_OBJECT_SIZE(0), buffer.size());
obj["hello"] = 1;
ASSERT_EQ(JSON_OBJECT_SIZE(1), json.size());
ASSERT_EQ(JSON_OBJECT_SIZE(1), buffer.size());
obj["world"] = 2;
ASSERT_EQ(JSON_OBJECT_SIZE(2), json.size());
ASSERT_EQ(JSON_OBJECT_SIZE(2), buffer.size());
obj["world"] = 3; // <- same key, should not grow
ASSERT_EQ(JSON_OBJECT_SIZE(2), json.size());
ASSERT_EQ(JSON_OBJECT_SIZE(2), buffer.size());
}
TEST(StaticJsonBuffer_CreateObject_Tests, SucceedWhenBigEnough) {
StaticJsonBuffer<JSON_OBJECT_SIZE(0)> json;
StaticJsonBuffer<JSON_OBJECT_SIZE(0)> buffer;
JsonObject &object = json.createObject();
JsonObject &object = buffer.createObject();
ASSERT_TRUE(object.success());
}
TEST(StaticJsonBuffer_CreateObject_Tests, FailsWhenTooSmall) {
StaticJsonBuffer<JSON_OBJECT_SIZE(0) - 1> json;
StaticJsonBuffer<JSON_OBJECT_SIZE(0) - 1> buffer;
JsonObject &object = json.createObject();
JsonObject &object = buffer.createObject();
ASSERT_FALSE(object.success());
}
TEST(StaticJsonBuffer_CreateObject_Tests, ObjectDoesntGrowWhenFull) {
StaticJsonBuffer<JSON_OBJECT_SIZE(1)> json;
StaticJsonBuffer<JSON_OBJECT_SIZE(1)> buffer;
JsonObject &obj = json.createObject();
JsonObject &obj = buffer.createObject();
obj["hello"] = 1;
obj["world"] = 2;
ASSERT_EQ(JSON_OBJECT_SIZE(1), json.size());
ASSERT_EQ(JSON_OBJECT_SIZE(1), buffer.size());
ASSERT_EQ(1, obj.size());
char json[64];
obj.printTo(json, sizeof(json));
ASSERT_STREQ("{\"hello\":1}", json);
}