Skip to content

Commit

Permalink
Preallocate pool list
Browse files Browse the repository at this point in the history
  • Loading branch information
bblanchon committed Jul 21, 2023
1 parent e57e629 commit 01f02f3
Show file tree
Hide file tree
Showing 19 changed files with 183 additions and 143 deletions.
46 changes: 34 additions & 12 deletions extras/tests/Helpers/Allocators.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,38 +32,60 @@ struct FailingAllocator : ArduinoJson::Allocator {

class AllocatorLog {
public:
static std::string Allocate(size_t s) {
class Entry {
public:
Entry(std::string s, size_t n = 1) : str_(s), count_(n) {}

const std::string& str() const {
return str_;
}

size_t count() const {
return count_;
}

Entry operator*(size_t n) const {
return Entry(str_, n);
}

private:
std::string str_;
size_t count_;
};

static Entry Allocate(size_t s) {
char buffer[32];
sprintf(buffer, "allocate(%zu)", s);
return buffer;
return Entry(buffer);
}

static std::string AllocateFail(size_t s) {
static Entry AllocateFail(size_t s) {
char buffer[32];
sprintf(buffer, "allocate(%zu) -> nullptr", s);
return buffer;
return Entry(buffer);
}

static std::string Reallocate(size_t s1, size_t s2) {
static Entry Reallocate(size_t s1, size_t s2) {
char buffer[32];
sprintf(buffer, "reallocate(%zu, %zu)", s1, s2);
return buffer;
return Entry(buffer);
};

static std::string ReallocateFail(size_t s1, size_t s2) {
static Entry ReallocateFail(size_t s1, size_t s2) {
char buffer[32];
sprintf(buffer, "reallocate(%zu, %zu) -> nullptr", s1, s2);
return buffer;
return Entry(buffer);
};

static std::string Deallocate(size_t s) {
static Entry Deallocate(size_t s) {
char buffer[32];
sprintf(buffer, "deallocate(%zu)", s);
return buffer;
return Entry(buffer);
};

AllocatorLog& operator<<(const std::string& s) {
log_ << s << "\n";
AllocatorLog& operator<<(const Entry& entry) {
for (size_t i = 0; i < entry.count(); i++)
log_ << entry.str() << "\n";
return *this;
}

Expand Down
7 changes: 2 additions & 5 deletions extras/tests/JsonArray/clear.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,10 +39,7 @@ TEST_CASE("JsonArray::clear()") {
for (int i = 0; i < ARDUINOJSON_POOL_CAPACITY; i++)
array.add(i);

REQUIRE(
allocator.log() ==
AllocatorLog() << AllocatorLog::Allocate(sizeofPoolList())
<< AllocatorLog::Allocate(sizeofPool()) // only one pool
);
REQUIRE(allocator.log() == AllocatorLog()
<< AllocatorLog::Allocate(sizeofPool()));
}
}
6 changes: 2 additions & 4 deletions extras/tests/JsonArray/remove.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -105,9 +105,7 @@ TEST_CASE("Removed elements are recycled") {
// add one element; it should use the free slot
array.add(42);

REQUIRE(
allocator.log() ==
AllocatorLog() << AllocatorLog::Allocate(sizeofPoolList())
<< AllocatorLog::Allocate(sizeofPool()) // only one pool
REQUIRE(allocator.log() == AllocatorLog() << AllocatorLog::Allocate(
sizeofPool()) // only one pool
);
}
4 changes: 2 additions & 2 deletions extras/tests/JsonDeserializer/array.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -281,7 +281,7 @@ TEST_CASE("deserialize JSON array under memory constraints") {
}

SECTION("allocation of pool fails") {
allocator.setCountdown(1);
allocator.setCountdown(0);
char input[] = "[1]";

DeserializationError err = deserializeJson(doc, input);
Expand All @@ -291,7 +291,7 @@ TEST_CASE("deserialize JSON array under memory constraints") {
}

SECTION("allocation of string fails in array") {
allocator.setCountdown(2);
allocator.setCountdown(1);
char input[] = "[0,\"hi!\"]";

DeserializationError err = deserializeJson(doc, input);
Expand Down
14 changes: 2 additions & 12 deletions extras/tests/JsonDeserializer/object.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -344,18 +344,8 @@ TEST_CASE("deserialize JSON object under memory constraints") {
REQUIRE(doc.as<std::string>() == "{}");
}

SECTION("pool list allocation fails") {
allocator.setCountdown(2);
char input[] = "{\"a\":1}";

DeserializationError err = deserializeJson(doc, input);

REQUIRE(err == DeserializationError::NoMemory);
REQUIRE(doc.as<std::string>() == "{}");
}

SECTION("pool allocation fails") {
allocator.setCountdown(3);
allocator.setCountdown(2);
char input[] = "{\"a\":1}";

DeserializationError err = deserializeJson(doc, input);
Expand All @@ -365,7 +355,7 @@ TEST_CASE("deserialize JSON object under memory constraints") {
}

SECTION("string allocation fails") {
allocator.setCountdown(4);
allocator.setCountdown(3);
char input[] = "{\"a\":\"b\"}";

DeserializationError err = deserializeJson(doc, input);
Expand Down
6 changes: 2 additions & 4 deletions extras/tests/JsonDeserializer/string.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -111,14 +111,13 @@ TEST_CASE("Allocation of the key fails") {
}

SECTION("Quoted string, second member") {
timebombAllocator.setCountdown(4);
timebombAllocator.setCountdown(3);
REQUIRE(deserializeJson(doc, "{\"hello\":1,\"world\"}") ==
DeserializationError::NoMemory);
REQUIRE(spyingAllocator.log() ==
AllocatorLog() << AllocatorLog::Allocate(sizeofString(31))
<< AllocatorLog::Reallocate(sizeofString(31),
sizeofString(5))
<< AllocatorLog::Allocate(sizeofPoolList())
<< AllocatorLog::Allocate(sizeofPool())
<< AllocatorLog::AllocateFail(sizeofString(31)));
}
Expand All @@ -131,14 +130,13 @@ TEST_CASE("Allocation of the key fails") {
}

SECTION("Non-Quoted string, second member") {
timebombAllocator.setCountdown(4);
timebombAllocator.setCountdown(3);
REQUIRE(deserializeJson(doc, "{hello:1,world}") ==
DeserializationError::NoMemory);
REQUIRE(spyingAllocator.log() ==
AllocatorLog() << AllocatorLog::Allocate(sizeofString(31))
<< AllocatorLog::Reallocate(sizeofString(31),
sizeofString(5))
<< AllocatorLog::Allocate(sizeofPoolList())
<< AllocatorLog::Allocate(sizeofPool())
<< AllocatorLog::AllocateFail(sizeofString(31)));
}
Expand Down
9 changes: 2 additions & 7 deletions extras/tests/JsonDocument/assignment.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ TEST_CASE("JsonDocument assignment") {

REQUIRE(spyingAllocator.log() ==
AllocatorLog() << AllocatorLog::Allocate(sizeofString(5)) // hello
<< AllocatorLog::Allocate(sizeofPoolList())
<< AllocatorLog::Allocate(sizeofPool())
<< AllocatorLog::Allocate(sizeofString(5)) // world
);
Expand All @@ -40,8 +39,7 @@ TEST_CASE("JsonDocument assignment") {

REQUIRE(doc2.as<std::string>() == "[{\"hello\":\"world\"}]");
REQUIRE(spyingAllocator.log() ==
AllocatorLog() << AllocatorLog::Allocate(sizeofPoolList())
<< AllocatorLog::Allocate(sizeofPool())
AllocatorLog() << AllocatorLog::Allocate(sizeofPool())
<< AllocatorLog::Allocate(sizeofString(5)) // hello
<< AllocatorLog::Allocate(sizeofString(5)) // world
);
Expand All @@ -58,7 +56,6 @@ TEST_CASE("JsonDocument assignment") {
REQUIRE(doc2.as<std::string>() == "{\"hello\":\"world\"}");
REQUIRE(spyingAllocator.log() ==
AllocatorLog() << AllocatorLog::Allocate(sizeofString(5)) // hello
<< AllocatorLog::Allocate(sizeofPoolList())
<< AllocatorLog::Allocate(sizeofPool())
<< AllocatorLog::Allocate(sizeofString(5)) // world
);
Expand All @@ -78,13 +75,11 @@ TEST_CASE("JsonDocument assignment") {
REQUIRE(
spyingAllocator.log() ==
AllocatorLog() << AllocatorLog::Allocate(sizeofString(5)) // hello
<< AllocatorLog::Allocate(sizeofPoolList())
<< AllocatorLog::Allocate(sizeofPool())
<< AllocatorLog::Allocate(sizeofString(5)) // world
<< AllocatorLog::Deallocate(sizeofString(5)) // hello
<< AllocatorLog::Deallocate(sizeofString(5)) // world
<< AllocatorLog::Deallocate(sizeofPool())
<< AllocatorLog::Deallocate(sizeofPoolList()));
<< AllocatorLog::Deallocate(sizeofPool()));
}

SECTION("Assign from JsonObject") {
Expand Down
6 changes: 2 additions & 4 deletions extras/tests/JsonDocument/constructor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,7 @@ TEST_CASE("JsonDocument constructor") {

REQUIRE(doc2.as<std::string>() == "{\"hello\":\"world\"}");
REQUIRE(spyingAllocator.log() ==
AllocatorLog() << AllocatorLog::Allocate(sizeofPoolList())
<< AllocatorLog::Allocate(sizeofPool()));
AllocatorLog() << AllocatorLog::Allocate(sizeofPool()));
}

SECTION("Construct from JsonArray") {
Expand All @@ -72,8 +71,7 @@ TEST_CASE("JsonDocument constructor") {

REQUIRE(doc2.as<std::string>() == "[\"hello\"]");
REQUIRE(spyingAllocator.log() ==
AllocatorLog() << AllocatorLog::Allocate(sizeofPoolList())
<< AllocatorLog::Allocate(sizeofPool()));
AllocatorLog() << AllocatorLog::Allocate(sizeofPool()));
}

SECTION("Construct from JsonVariant") {
Expand Down
4 changes: 1 addition & 3 deletions extras/tests/JsonDocument/garbageCollect.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,9 @@ TEST_CASE("JsonDocument::garbageCollect()") {
REQUIRE(doc.as<std::string>() == "{\"dancing\":2}");
REQUIRE(spyingAllocator.log() ==
AllocatorLog() << AllocatorLog::Allocate(sizeofString(7))
<< AllocatorLog::Allocate(sizeofPoolList())
<< AllocatorLog::Allocate(sizeofPool())
<< AllocatorLog::Deallocate(sizeofString(7))
<< AllocatorLog::Deallocate(sizeofPool())
<< AllocatorLog::Deallocate(sizeofPoolList()));
<< AllocatorLog::Deallocate(sizeofPool()));
}

SECTION("when allocation fails") {
Expand Down
4 changes: 2 additions & 2 deletions extras/tests/JsonDocument/overflowed.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,13 +47,13 @@ TEST_CASE("JsonDocument::overflowed()") {
}

SECTION("returns true after a failed deserialization") {
allocator.setCountdown(1);
allocator.setCountdown(0);
deserializeJson(doc, "[1, 2]");
CHECK(doc.overflowed() == true);
}

SECTION("returns false after a successful deserialization") {
allocator.setCountdown(4);
allocator.setCountdown(3);
deserializeJson(doc, "[\"example\"]");
CHECK(doc.overflowed() == false);
}
Expand Down
64 changes: 23 additions & 41 deletions extras/tests/JsonDocument/shrinkToFit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -105,13 +105,10 @@ TEST_CASE("JsonDocument::shrinkToFit()") {
doc.shrinkToFit();

REQUIRE(doc.as<std::string>() == "{\"key\":42}");
REQUIRE(spyingAllocator.log() ==
AllocatorLog() << AllocatorLog::Allocate(sizeofPoolList())
<< AllocatorLog::Allocate(sizeofPool())
<< AllocatorLog::Reallocate(sizeofPool(),
sizeofObject(1))
<< AllocatorLog::Reallocate(sizeofPoolList(),
sizeofPoolList(1)));
REQUIRE(spyingAllocator.log() == AllocatorLog()
<< AllocatorLog::Allocate(sizeofPool())
<< AllocatorLog::Reallocate(
sizeofPool(), sizeofObject(1)));
}

SECTION("owned key") {
Expand All @@ -122,12 +119,9 @@ TEST_CASE("JsonDocument::shrinkToFit()") {
REQUIRE(doc.as<std::string>() == "{\"abcdefg\":42}");
REQUIRE(spyingAllocator.log() ==
AllocatorLog() << AllocatorLog::Allocate(sizeofString(7))
<< AllocatorLog::Allocate(sizeofPoolList())
<< AllocatorLog::Allocate(sizeofPool())
<< AllocatorLog::Reallocate(sizeofPool(),
sizeofObject(1))
<< AllocatorLog::Reallocate(sizeofPoolList(),
sizeofPoolList(1)));
sizeofObject(1)));
}

SECTION("linked string in array") {
Expand All @@ -136,13 +130,10 @@ TEST_CASE("JsonDocument::shrinkToFit()") {
doc.shrinkToFit();

REQUIRE(doc.as<std::string>() == "[\"hello\"]");
REQUIRE(
spyingAllocator.log() ==
AllocatorLog() << AllocatorLog::Allocate(sizeofPoolList())
<< AllocatorLog::Allocate(sizeofPool())
<< AllocatorLog::Reallocate(sizeofPool(), sizeofArray(1))
<< AllocatorLog::Reallocate(sizeofPoolList(),
sizeofPoolList(1)));
REQUIRE(spyingAllocator.log() == AllocatorLog()
<< AllocatorLog::Allocate(sizeofPool())
<< AllocatorLog::Reallocate(
sizeofPool(), sizeofArray(1)));
}

SECTION("owned string in array") {
Expand All @@ -151,14 +142,11 @@ TEST_CASE("JsonDocument::shrinkToFit()") {
doc.shrinkToFit();

REQUIRE(doc.as<std::string>() == "[\"abcdefg\"]");
REQUIRE(
spyingAllocator.log() ==
AllocatorLog() << AllocatorLog::Allocate(sizeofPoolList())
<< AllocatorLog::Allocate(sizeofPool())
<< AllocatorLog::Allocate(sizeofString(7))
<< AllocatorLog::Reallocate(sizeofPool(), sizeofArray(1))
<< AllocatorLog::Reallocate(sizeofPoolList(),
sizeofPoolList(1)));
REQUIRE(spyingAllocator.log() ==
AllocatorLog() << AllocatorLog::Allocate(sizeofPool())
<< AllocatorLog::Allocate(sizeofString(7))
<< AllocatorLog::Reallocate(sizeofPool(),
sizeofArray(1)));
}

SECTION("linked string in object") {
Expand All @@ -167,13 +155,10 @@ TEST_CASE("JsonDocument::shrinkToFit()") {
doc.shrinkToFit();

REQUIRE(doc.as<std::string>() == "{\"key\":\"hello\"}");
REQUIRE(spyingAllocator.log() ==
AllocatorLog() << AllocatorLog::Allocate(sizeofPoolList())
<< AllocatorLog::Allocate(sizeofPool())
<< AllocatorLog::Reallocate(sizeofPool(),
sizeofObject(1))
<< AllocatorLog::Reallocate(sizeofPoolList(),
sizeofPoolList(1)));
REQUIRE(spyingAllocator.log() == AllocatorLog()
<< AllocatorLog::Allocate(sizeofPool())
<< AllocatorLog::Reallocate(
sizeofPool(), sizeofObject(1)));
}

SECTION("owned string in object") {
Expand All @@ -182,13 +167,10 @@ TEST_CASE("JsonDocument::shrinkToFit()") {
doc.shrinkToFit();

REQUIRE(doc.as<std::string>() == "{\"key\":\"abcdefg\"}");
REQUIRE(
spyingAllocator.log() ==
AllocatorLog() << AllocatorLog::Allocate(sizeofPoolList())
<< AllocatorLog::Allocate(sizeofPool())
<< AllocatorLog::Allocate(sizeofString(7))
<< AllocatorLog::Reallocate(sizeofPool(), sizeofPool(1))
<< AllocatorLog::Reallocate(sizeofPoolList(),
sizeofPoolList(1)));
REQUIRE(spyingAllocator.log() ==
AllocatorLog() << AllocatorLog::Allocate(sizeofPool())
<< AllocatorLog::Allocate(sizeofString(7))
<< AllocatorLog::Reallocate(sizeofPool(),
sizeofPool(1)));
}
}
4 changes: 2 additions & 2 deletions extras/tests/JsonObject/copy.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ TEST_CASE("JsonObject::set()") {
}

SECTION("copy fails in the middle of an object") {
TimebombAllocator allocator(3);
TimebombAllocator allocator(2);
JsonDocument doc3(&allocator);
JsonObject obj3 = doc3.to<JsonObject>();

Expand All @@ -88,7 +88,7 @@ TEST_CASE("JsonObject::set()") {
}

SECTION("copy fails in the middle of an array") {
TimebombAllocator allocator(2);
TimebombAllocator allocator(1);
JsonDocument doc3(&allocator);
JsonObject obj3 = doc3.to<JsonObject>();

Expand Down
Loading

0 comments on commit 01f02f3

Please sign in to comment.