Skip to content

Commit cb2f8c9

Browse files
committed
Fix all JsonDocument tests
1 parent 65e5900 commit cb2f8c9

File tree

11 files changed

+176
-41
lines changed

11 files changed

+176
-41
lines changed

extras/tests/JsonDocument/ElementProxy.cpp

Lines changed: 32 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,44 +5,71 @@
55
#include <ArduinoJson.h>
66
#include <catch.hpp>
77

8+
#include "Allocators.hpp"
89
#include "Literals.hpp"
910

1011
using ElementProxy = ArduinoJson::detail::ElementProxy<JsonDocument&>;
1112

1213
TEST_CASE("ElementProxy::add()") {
13-
JsonDocument doc;
14+
SpyingAllocator spy;
15+
JsonDocument doc(&spy);
1416
doc.add<JsonVariant>();
1517
ElementProxy ep = doc[0];
1618

17-
SECTION("add(int)") {
19+
SECTION("integer") {
1820
ep.add(42);
1921

2022
REQUIRE(doc.as<std::string>() == "[[42]]");
23+
REQUIRE(spy.log() == AllocatorLog{
24+
Allocate(sizeofPool()),
25+
});
2126
}
2227

23-
SECTION("add(const char*)") {
28+
SECTION("string literal") {
2429
ep.add("world");
2530

2631
REQUIRE(doc.as<std::string>() == "[[\"world\"]]");
32+
REQUIRE(spy.log() == AllocatorLog{
33+
Allocate(sizeofPool()),
34+
});
35+
}
36+
37+
SECTION("const char*") {
38+
const char* s = "world";
39+
ep.add(s);
40+
41+
REQUIRE(doc.as<std::string>() == "[[\"world\"]]");
42+
REQUIRE(spy.log() == AllocatorLog{
43+
Allocate(sizeofPool()),
44+
Allocate(sizeofString("world")),
45+
});
2746
}
2847

29-
SECTION("add(char[])") {
48+
SECTION("char[]") {
3049
char s[] = "world";
3150
ep.add(s);
3251
strcpy(s, "!!!!!");
3352

3453
REQUIRE(doc.as<std::string>() == "[[\"world\"]]");
54+
REQUIRE(spy.log() == AllocatorLog{
55+
Allocate(sizeofPool()),
56+
Allocate(sizeofString("world")),
57+
});
3558
}
3659

3760
#ifdef HAS_VARIABLE_LENGTH_ARRAY
38-
SECTION("set(vla)") {
61+
SECTION("VLA") {
3962
size_t i = 8;
4063
char vla[i];
4164
strcpy(vla, "world");
4265

4366
ep.add(vla);
4467

4568
REQUIRE(doc.as<std::string>() == "[[\"world\"]]");
69+
REQUIRE(spy.log() == AllocatorLog{
70+
Allocate(sizeofPool()),
71+
Allocate(sizeofString("world")),
72+
});
4673
}
4774
#endif
4875
}

extras/tests/JsonDocument/MemberProxy.cpp

Lines changed: 47 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -14,41 +14,73 @@
1414
using ArduinoJson::detail::sizeofArray;
1515
using ArduinoJson::detail::sizeofObject;
1616

17-
using MemberProxy =
18-
ArduinoJson::detail::MemberProxy<JsonDocument&, const char*>;
19-
2017
TEST_CASE("MemberProxy::add()") {
21-
JsonDocument doc;
22-
MemberProxy mp = doc["hello"];
18+
SpyingAllocator spy;
19+
JsonDocument doc(&spy);
20+
auto mp = doc["hello"];
2321

24-
SECTION("add(int)") {
22+
SECTION("integer") {
2523
mp.add(42);
2624

2725
REQUIRE(doc.as<std::string>() == "{\"hello\":[42]}");
26+
REQUIRE(spy.log() == AllocatorLog{
27+
Allocate(sizeofPool()),
28+
});
2829
}
2930

30-
SECTION("add(const char*)") {
31+
SECTION("string literal") {
3132
mp.add("world");
3233

3334
REQUIRE(doc.as<std::string>() == "{\"hello\":[\"world\"]}");
35+
REQUIRE(spy.log() == AllocatorLog{
36+
Allocate(sizeofPool()),
37+
});
38+
}
39+
40+
SECTION("const char*") {
41+
const char* temp = "world";
42+
mp.add(temp);
43+
44+
REQUIRE(doc.as<std::string>() == "{\"hello\":[\"world\"]}");
45+
REQUIRE(spy.log() == AllocatorLog{
46+
Allocate(sizeofPool()),
47+
Allocate(sizeofString("world")),
48+
49+
});
50+
}
51+
52+
SECTION("char[]") {
53+
char temp[] = "world";
54+
mp.add(temp);
55+
56+
REQUIRE(doc.as<std::string>() == "{\"hello\":[\"world\"]}");
57+
REQUIRE(spy.log() == AllocatorLog{
58+
Allocate(sizeofPool()),
59+
Allocate(sizeofString("world")),
60+
61+
});
3462
}
3563

3664
#ifdef HAS_VARIABLE_LENGTH_ARRAY
37-
SECTION("add(vla)") {
65+
SECTION("VLA") {
3866
size_t i = 16;
3967
char vla[i];
4068
strcpy(vla, "world");
4169

4270
mp.add(vla);
4371

4472
REQUIRE(doc.as<std::string>() == "{\"hello\":[\"world\"]}");
73+
REQUIRE(spy.log() == AllocatorLog{
74+
Allocate(sizeofPool()),
75+
Allocate(sizeofString("world")),
76+
});
4577
}
4678
#endif
4779
}
4880

4981
TEST_CASE("MemberProxy::clear()") {
5082
JsonDocument doc;
51-
MemberProxy mp = doc["hello"];
83+
auto mp = doc["hello"];
5284

5385
SECTION("size goes back to zero") {
5486
mp.add(42);
@@ -139,7 +171,7 @@ TEST_CASE("MemberProxy::operator|()") {
139171

140172
TEST_CASE("MemberProxy::remove()") {
141173
JsonDocument doc;
142-
MemberProxy mp = doc["hello"];
174+
auto mp = doc["hello"];
143175

144176
SECTION("remove(int)") {
145177
mp.add(1);
@@ -186,7 +218,7 @@ TEST_CASE("MemberProxy::remove()") {
186218

187219
TEST_CASE("MemberProxy::set()") {
188220
JsonDocument doc;
189-
MemberProxy mp = doc["hello"];
221+
auto mp = doc["hello"];
190222

191223
SECTION("set(int)") {
192224
mp.set(42);
@@ -223,7 +255,7 @@ TEST_CASE("MemberProxy::set()") {
223255

224256
TEST_CASE("MemberProxy::size()") {
225257
JsonDocument doc;
226-
MemberProxy mp = doc["hello"];
258+
auto mp = doc["hello"];
227259

228260
SECTION("returns 0") {
229261
REQUIRE(mp.size() == 0);
@@ -246,7 +278,7 @@ TEST_CASE("MemberProxy::size()") {
246278

247279
TEST_CASE("MemberProxy::operator[]") {
248280
JsonDocument doc;
249-
MemberProxy mp = doc["hello"];
281+
auto mp = doc["hello"];
250282

251283
SECTION("set member") {
252284
mp["world"] = 42;
@@ -265,7 +297,7 @@ TEST_CASE("MemberProxy cast to JsonVariantConst") {
265297
JsonDocument doc;
266298
doc["hello"] = "world";
267299

268-
const MemberProxy mp = doc["hello"];
300+
const auto mp = doc["hello"];
269301

270302
JsonVariantConst var = mp;
271303

@@ -276,7 +308,7 @@ TEST_CASE("MemberProxy cast to JsonVariant") {
276308
JsonDocument doc;
277309
doc["hello"] = "world";
278310

279-
MemberProxy mp = doc["hello"];
311+
auto mp = doc["hello"];
280312

281313
JsonVariant var = mp;
282314

extras/tests/JsonDocument/add.cpp

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ TEST_CASE("JsonDocument::add(T)") {
2626
});
2727
}
2828

29-
SECTION("const char*") {
29+
SECTION("string literal") {
3030
doc.add("hello");
3131

3232
REQUIRE(doc.as<std::string>() == "[\"hello\"]");
@@ -35,6 +35,17 @@ TEST_CASE("JsonDocument::add(T)") {
3535
});
3636
}
3737

38+
SECTION("const char*") {
39+
const char* value = "hello";
40+
doc.add(value);
41+
42+
REQUIRE(doc.as<std::string>() == "[\"hello\"]");
43+
REQUIRE(spy.log() == AllocatorLog{
44+
Allocate(sizeofPool()),
45+
Allocate(sizeofString("hello")),
46+
});
47+
}
48+
3849
SECTION("std::string") {
3950
doc.add("example"_s);
4051
doc.add("example"_s);

extras/tests/JsonDocument/subscript.cpp

Lines changed: 64 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
#include <ArduinoJson.h>
66
#include <catch.hpp>
77

8+
#include "Allocators.hpp"
89
#include "Literals.hpp"
910

1011
TEST_CASE("JsonDocument::operator[]") {
@@ -14,7 +15,7 @@ TEST_CASE("JsonDocument::operator[]") {
1415
SECTION("object") {
1516
deserializeJson(doc, "{\"hello\":\"world\"}");
1617

17-
SECTION("const char*") {
18+
SECTION("string literal") {
1819
REQUIRE(doc["hello"] == "world");
1920
REQUIRE(cdoc["hello"] == "world");
2021
}
@@ -82,3 +83,65 @@ TEST_CASE("JsonDocument automatically promotes to array") {
8283

8384
REQUIRE(doc.as<std::string>() == "[null,null,2]");
8485
}
86+
87+
TEST_CASE("JsonDocument::operator[] key storage") {
88+
SpyingAllocator spy;
89+
JsonDocument doc(&spy);
90+
91+
SECTION("string literal") {
92+
doc["hello"] = 0;
93+
94+
REQUIRE(doc.as<std::string>() == "{\"hello\":0}");
95+
REQUIRE(spy.log() == AllocatorLog{
96+
Allocate(sizeofPool()),
97+
});
98+
}
99+
100+
SECTION("const char*") {
101+
const char* key = "hello";
102+
doc[key] = 0;
103+
104+
REQUIRE(doc.as<std::string>() == "{\"hello\":0}");
105+
REQUIRE(spy.log() == AllocatorLog{
106+
Allocate(sizeofPool()),
107+
Allocate(sizeofString("hello")),
108+
});
109+
}
110+
111+
SECTION("char[]") {
112+
char key[] = "hello";
113+
doc[key] = 0;
114+
115+
REQUIRE(doc.as<std::string>() == "{\"hello\":0}");
116+
REQUIRE(spy.log() == AllocatorLog{
117+
Allocate(sizeofPool()),
118+
Allocate(sizeofString("hello")),
119+
});
120+
}
121+
122+
SECTION("std::string") {
123+
doc["hello"_s] = 0;
124+
125+
REQUIRE(doc.as<std::string>() == "{\"hello\":0}");
126+
REQUIRE(spy.log() == AllocatorLog{
127+
Allocate(sizeofPool()),
128+
Allocate(sizeofString("hello")),
129+
});
130+
}
131+
#if defined(HAS_VARIABLE_LENGTH_ARRAY) && \
132+
!defined(SUBSCRIPT_CONFLICTS_WITH_BUILTIN_OPERATOR)
133+
SECTION("VLA") {
134+
size_t i = 16;
135+
char vla[i];
136+
strcpy(vla, "hello");
137+
138+
doc[vla] = 0;
139+
140+
REQUIRE(doc.as<std::string>() == "{\"hello\":0}");
141+
REQUIRE(spy.log() == AllocatorLog{
142+
Allocate(sizeofPool()),
143+
Allocate(sizeofString("hello")),
144+
});
145+
}
146+
#endif
147+
}

src/ArduinoJson/Array/JsonArray.hpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,8 @@ class JsonArray : public detail::VariantOperators<JsonArray> {
6666

6767
// Appends a value to the array.
6868
// https://arduinojson.org/v7/api/jsonarray/add/
69-
template <typename T>
69+
template <typename T,
70+
typename = detail::enable_if_t<!detail::is_const<T>::value>>
7071
bool add(T* value) const {
7172
return detail::ArrayData::addValue(data_, value, resources_);
7273
}

src/ArduinoJson/Document/JsonDocument.hpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -189,14 +189,15 @@ class JsonDocument : public detail::VariantOperators<const JsonDocument&> {
189189
template <typename TString>
190190
detail::enable_if_t<detail::IsString<TString>::value,
191191
detail::MemberProxy<JsonDocument&, TString>>
192-
operator[](const TString& key) {
193-
return {*this, key};
192+
operator[](TString&& key) {
193+
return {*this, detail::forward<TString>(key)};
194194
}
195195

196196
// Gets or sets a root object's member.
197197
// https://arduinojson.org/v7/api/jsondocument/subscript/
198198
template <typename TChar>
199-
detail::enable_if_t<detail::IsString<TChar*>::value,
199+
detail::enable_if_t<detail::IsString<TChar*>::value &&
200+
!detail::is_const<TChar>::value,
200201
detail::MemberProxy<JsonDocument&, TChar*>>
201202
operator[](TChar* key) {
202203
return {*this, key};

src/ArduinoJson/Object/JsonObject.hpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -104,14 +104,15 @@ class JsonObject : public detail::VariantOperators<JsonObject> {
104104
template <typename TString>
105105
detail::enable_if_t<detail::IsString<TString>::value,
106106
detail::MemberProxy<JsonObject, TString>>
107-
operator[](const TString& key) const {
108-
return {*this, key};
107+
operator[](TString&& key) const {
108+
return {*this, detail::forward<TString>(key)};
109109
}
110110

111111
// Gets or sets the member with specified key.
112112
// https://arduinojson.org/v7/api/jsonobject/subscript/
113113
template <typename TChar>
114-
detail::enable_if_t<detail::IsString<TChar*>::value,
114+
detail::enable_if_t<detail::IsString<TChar*>::value &&
115+
!detail::is_const<TChar>::value,
115116
detail::MemberProxy<JsonObject, TChar*>>
116117
operator[](TChar* key) const {
117118
return {*this, key};

src/ArduinoJson/Object/MemberProxy.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ class MemberProxy
3434
return *this;
3535
}
3636

37-
template <typename T>
37+
template <typename T, typename = enable_if_t<!is_const<T>::value>>
3838
MemberProxy& operator=(T* src) {
3939
this->set(src);
4040
return *this;

src/ArduinoJson/Strings/IsString.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ template <typename T, typename Enable = void>
1313
struct IsString : false_type {};
1414

1515
template <typename T>
16-
struct IsString<T, void_t<typename StringAdapter<T>::AdaptedString>>
16+
struct IsString<T, void_t<typename StringAdapterFor<T>::AdaptedString>>
1717
: true_type {};
1818

1919
ARDUINOJSON_END_PRIVATE_NAMESPACE

0 commit comments

Comments
 (0)