Library: finish coverage of element handling limits and failures
...including the interesting cases where objects are relocated and the element spread is changed. With the help of the checksum feature built into the test-dummy objects, the properly balanced invocation of constructors can be demonstrated PS: for historical context... Last week the "Big F**cking Rocket" successfully performed the test flight 4; both booster and Starship made it back to the water surface and performed a soft splash-down after decelerating to speed zero. The Starship was even able to maintain control in spite of quite some heat damage on the steering flaps. Yes ... all techies around the world are thrilled...
This commit is contained in:
parent
00287360be
commit
fd1ed7e78f
2 changed files with 139 additions and 26 deletions
|
|
@ -120,7 +120,11 @@ namespace test{
|
|||
struct ShortBlocker
|
||||
: util::NonCopyable
|
||||
{
|
||||
int16_t val{short(1 + (rand() % 1'000))};
|
||||
int16_t val;
|
||||
|
||||
ShortBlocker (short r = 1 + (rand() % 1'000))
|
||||
: val(r)
|
||||
{ };
|
||||
};
|
||||
|
||||
} // (END) test types
|
||||
|
|
@ -239,7 +243,7 @@ namespace test{
|
|||
}
|
||||
|
||||
|
||||
/** @test TODO proper handling of exceptions during population
|
||||
/** @test proper handling of exceptions during population
|
||||
* - when the container is filled with arbitrary subclasses
|
||||
* of a base interface with virtual destructor, the first element is used
|
||||
* to accommodate the storage spread; larger elements or elements of a completely
|
||||
|
|
@ -250,11 +254,25 @@ namespace test{
|
|||
* can be expanded by move-relocation. Yet totally unrelated elements can not be
|
||||
* accepted (due to unknown destructor); and when accepting another unspecific
|
||||
* subclass instance, the ability to grow by move-relocation is lost.
|
||||
* - a container defined for trivial data elements (trivially movable and destructible)
|
||||
* can grow dynamically just by moving data around with `memmove`. Only in this case
|
||||
* the _element spread_ can easily be adjusted after the fact, since a trivial element
|
||||
* can be relocated to accommodate an increased spread. It is possible to add various
|
||||
* different data elements into such a container, yet all will be accessed through an
|
||||
* unchecked hard cast to the base element (`uint8_t` in this case). However, once we
|
||||
* add a _non-copyable_ element, this capability for arbitrarily moving elements around
|
||||
* is lost — we can not adapt the spread any more and the container can no longer
|
||||
* grow dynamically.
|
||||
* - all these failure conditions are handled properly, including exceptions emanating
|
||||
* from element constructors; the container remains sane and no memory is leaked.
|
||||
* @todo WIP 6/24 🔁 define ⟶ ✔ implement
|
||||
*/
|
||||
void
|
||||
check_ErrorHandling()
|
||||
{
|
||||
// prepare to verify proper invocation of all constructors / destructors
|
||||
Dummy::checksum() = 0;
|
||||
|
||||
{ // Scenario-1 : Baseclass and arbitrary subclass elements
|
||||
SeveralBuilder<Dummy> builder;
|
||||
|
||||
|
|
@ -292,6 +310,10 @@ namespace test{
|
|||
, builder.fillElm (20) );
|
||||
CHECK (10 == builder.size());
|
||||
}
|
||||
// in spite of all the provoked failures,
|
||||
// all element destructors were invoked
|
||||
CHECK (0 == Dummy::checksum());
|
||||
|
||||
|
||||
{ // Scenario-2 : Baseclass and elements of a single fixed subclass
|
||||
SeveralBuilder<Dummy, Num<5>> builder;
|
||||
|
|
@ -338,23 +360,107 @@ namespace test{
|
|||
CHECK (elms[i].calc(i) == 5 + i + (5+5+5+5+5));
|
||||
CHECK (elms.back().calc(0) == 1 + 0 + (1));
|
||||
}
|
||||
CHECK (0 == Dummy::checksum());
|
||||
|
||||
|
||||
{ // Scenario-3 : arbitrary elements of trivial type
|
||||
SeveralBuilder<uint8_t> builder;
|
||||
|
||||
string BFR{"starship is cool"};
|
||||
builder.appendAll (BFR);
|
||||
CHECK (16 == builder.size());
|
||||
CHECK ( 4 == builder.capReserve());
|
||||
builder.reserve(16);
|
||||
CHECK ( 0 == builder.size());
|
||||
CHECK (16 == builder.capacity());
|
||||
CHECK (16 == builder.capReserve());
|
||||
|
||||
builder.append(int64_t(33));
|
||||
CHECK (17 == builder.size());
|
||||
CHECK ( 3 == builder.capReserve());
|
||||
string BFR{"starship is"};
|
||||
builder.appendAll (BFR);
|
||||
CHECK (11 == builder.size());
|
||||
CHECK (16 == builder.capacity());
|
||||
CHECK ( 5 == builder.capReserve());
|
||||
|
||||
// append element that is much larger than a char
|
||||
// => since elements are trivial, they can be moved to accommodate
|
||||
builder.append (int64_t(32));
|
||||
CHECK (12 == builder.size());
|
||||
CHECK (16 == builder.capacity()); // note: capacity remained nominally the same
|
||||
CHECK ( 4 == builder.capReserve()); // while in fact the spread and thus the buffer were increased
|
||||
|
||||
// emplace a completely unrelated object type,
|
||||
// which is also trivially destructible, but non-copyable
|
||||
builder.emplace<ShortBlocker> ('c');
|
||||
|
||||
// can emplace further trivial objects, since there is still capacity left
|
||||
builder.append (int('o'), long('o'));
|
||||
CHECK (15 == builder.size());
|
||||
CHECK ( 1 == builder.capReserve());
|
||||
|
||||
VERIFY_FAIL ("Unable to place element of type Num<5u>"
|
||||
, builder.append (Num<5>{}) );
|
||||
CHECK (sizeof(Num<5>) > sizeof(int64_t));
|
||||
// not surprising: this one was too large,
|
||||
// and due to the non-copyable element we can not adapt anymore
|
||||
|
||||
class NonTrivial
|
||||
{
|
||||
public:
|
||||
~NonTrivial() { }
|
||||
};
|
||||
|
||||
// adding data of a non-trivial type is rejected,
|
||||
// since the container does not capture individual element types
|
||||
// and thus does not know how to delete it
|
||||
CHECK (sizeof(NonTrivial) <= sizeof(int64_t));
|
||||
VERIFY_FAIL ("Unsupported kind of destructor for element type SeveralBuilder_test::check_ErrorHandling()::NonTrivial"
|
||||
, builder.append (NonTrivial{}) );
|
||||
CHECK ( 1 == builder.capReserve());
|
||||
|
||||
// space for a single one left...
|
||||
builder.append ('l');
|
||||
CHECK (16 == builder.size());
|
||||
CHECK ( 0 == builder.capReserve());
|
||||
|
||||
// and now we've run out of space, and due to the non-copyable object, move-relocation is rejected
|
||||
VERIFY_FAIL ("Several-container is unable to accommodate further element of type char; "
|
||||
"storage reserve (128 bytes ≙ 16 elms) exhausted and unable to move "
|
||||
"elements of mixed unknown detail type, which are not trivially movable."
|
||||
, builder.append ('!') );
|
||||
|
||||
// yet the container is still fine....
|
||||
auto elms = builder.build();
|
||||
CHECK (16 == elms.size());
|
||||
CHECK (join(elms, "·") == "s·t·a·r·s·h·i·p· ·i·s· ·c·o·o·l"_expect);
|
||||
}
|
||||
CHECK (0 == Dummy::checksum());
|
||||
|
||||
{ // Scenario-4 : exception from element constructor
|
||||
SeveralBuilder<Dummy> builder;
|
||||
|
||||
builder.emplace<Num<3>>(42);
|
||||
CHECK (1 == builder.size());
|
||||
|
||||
Dummy::activateCtorFailure(true);
|
||||
try {
|
||||
builder.emplace<Num<3>>(23);
|
||||
NOTREACHED ("did not throw");
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
// Exception emanated from Dummy(baseclass) ctor;
|
||||
// at that point, the local val was set to the seed (≙23).
|
||||
// When a constructor fails in C++, the destructor is not called,
|
||||
// thus we have to compensate here to balance the checksum
|
||||
Dummy::checksum() -= 23;
|
||||
}
|
||||
CHECK (1 == builder.size());
|
||||
Dummy::activateCtorFailure(false);
|
||||
builder.emplace<Num<3>>(23);
|
||||
|
||||
auto elms = builder.build();
|
||||
SHOW_EXPR(elms.size())
|
||||
SHOW_EXPR(join(elms, "·"))
|
||||
CHECK (2 == elms.size());
|
||||
CHECK (elms.front().calc(1) == 3 + 1 + (42+42+42));
|
||||
CHECK (elms.back().calc(5) == 3 + 5 + (23+23+23));
|
||||
}
|
||||
// all other destructors properly invoked...
|
||||
CHECK (0 == Dummy::checksum());
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -83380,25 +83380,25 @@ Date:   Thu Apr 20 18:53:17 2023 +0200<br/>
|
|||
</node>
|
||||
</node>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1717806899733" ID="ID_1104689236" MODIFIED="1717806906392" TEXT="Fall-5-Behandlung">
|
||||
<icon BUILTIN="flag-yellow"/>
|
||||
<node COLOR="#338800" CREATED="1717806899733" ID="ID_1104689236" MODIFIED="1718219695888" TEXT="Fall-5-Behandlung">
|
||||
<icon BUILTIN="button_ok"/>
|
||||
<node CREATED="1717806920506" ID="ID_200574355" MODIFIED="1717806935142" TEXT="⟹ setzen der wild-move-Flag"/>
|
||||
<node BACKGROUND_COLOR="#f8f1cb" COLOR="#a50125" CREATED="1717806977490" ID="ID_901373417" MODIFIED="1717807004591" TEXT="aber nur falls der Typ tatsächlich akzeptiert wird">
|
||||
<node BACKGROUND_COLOR="#e0ceaa" COLOR="#690f14" CREATED="1717806977490" ID="ID_901373417" MODIFIED="1718219698071" TEXT="aber nur falls der Typ tatsächlich akzeptiert wird">
|
||||
<icon BUILTIN="messagebox_warning"/>
|
||||
<node BACKGROUND_COLOR="#f0d5c5" COLOR="#990033" CREATED="1717807023866" ID="ID_1721210839" MODIFIED="1717807027244" TEXT="relevant?">
|
||||
<node BACKGROUND_COLOR="#caa188" COLOR="#990033" CREATED="1717807023866" ID="ID_1721210839" MODIFIED="1718219718022" TEXT="relevant?">
|
||||
<icon BUILTIN="help"/>
|
||||
<node CREATED="1717807029327" ID="ID_1277661282" MODIFIED="1717807037454" TEXT="ist wohl eine Tautologie"/>
|
||||
<node CREATED="1717807038066" ID="ID_530732635" MODIFIED="1717807078709" TEXT="nicht akzeptiert ⟹ ↯ ⟹ ��"/>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1717807152128" ID="ID_1054193038" MODIFIED="1717810946694" TEXT="Aber: reiner Fall-5 muß erkannt werden">
|
||||
<node COLOR="#435e98" CREATED="1717807152128" ID="ID_1054193038" MODIFIED="1718219680753" TEXT="Aber: reiner Fall-5 muß erkannt werden">
|
||||
<arrowlink COLOR="#712925" DESTINATION="ID_1786086824" ENDARROW="Default" ENDINCLINATION="-23;57;" ID="Arrow_ID_1218222484" STARTARROW="None" STARTINCLINATION="-323;21;"/>
|
||||
<icon BUILTIN="messagebox_warning"/>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1715625082614" ID="ID_1575150785" MODIFIED="1715625089779" TEXT="SeveralBuilder_test">
|
||||
<icon BUILTIN="flag-yellow"/>
|
||||
<node BACKGROUND_COLOR="#eef0c5" COLOR="#990000" CREATED="1715625082614" ID="ID_1575150785" MODIFIED="1718219667879" TEXT="SeveralBuilder_test">
|
||||
<icon BUILTIN="pencil"/>
|
||||
<node COLOR="#338800" CREATED="1716857382440" ID="ID_46730448" MODIFIED="1718073046966" TEXT="simpleUsage">
|
||||
<icon BUILTIN="button_ok"/>
|
||||
<node COLOR="#338800" CREATED="1717980996623" ID="ID_644007892" MODIFIED="1718037983007" TEXT="Several mit sieben Fibonacci-Zahlen">
|
||||
|
|
@ -83494,8 +83494,8 @@ Date:   Thu Apr 20 18:53:17 2023 +0200<br/>
|
|||
<icon BUILTIN="button_ok"/>
|
||||
</node>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1716857382441" ID="ID_610081580" MODIFIED="1716857402102" TEXT="check_ErrorHandling">
|
||||
<icon BUILTIN="flag-yellow"/>
|
||||
<node COLOR="#338800" CREATED="1716857382441" ID="ID_610081580" MODIFIED="1718221655801" TEXT="check_ErrorHandling">
|
||||
<icon BUILTIN="button_ok"/>
|
||||
<node COLOR="#338800" CREATED="1718121991093" ID="ID_70431031" MODIFIED="1718153132386" TEXT="Base + beliebiger Typ">
|
||||
<icon BUILTIN="button_ok"/>
|
||||
<node COLOR="#435e98" CREATED="1718121998540" ID="ID_160009328" MODIFIED="1718153130346" STYLE="fork" TEXT="Typ zu groß"/>
|
||||
|
|
@ -83627,8 +83627,8 @@ Date:   Thu Apr 20 18:53:17 2023 +0200<br/>
|
|||
</node>
|
||||
<node COLOR="#435e98" CREATED="1718201899221" ID="ID_1719848161" MODIFIED="1718207782278" TEXT="wenn man eine Subklasse platziert, wird die Möglichkeit für Wachstum beschnitten"/>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#eef0c5" COLOR="#990000" CREATED="1718122252659" ID="ID_616405505" MODIFIED="1718208089182" TEXT="Triviale Typen">
|
||||
<icon BUILTIN="pencil"/>
|
||||
<node COLOR="#338800" CREATED="1718122252659" ID="ID_616405505" MODIFIED="1718219069975" TEXT="Triviale Typen">
|
||||
<icon BUILTIN="button_ok"/>
|
||||
<node COLOR="#435e98" CREATED="1718122293022" ID="ID_697520417" MODIFIED="1718209949804" TEXT="kann wachsen"/>
|
||||
<node COLOR="#435e98" CREATED="1718122302932" ID="ID_293207594" MODIFIED="1718209952087" TEXT="kann spread ändern">
|
||||
<node COLOR="#435e98" CREATED="1718211785014" ID="ID_185961323" MODIFIED="1718211802523" TEXT="explizit im Debugger beobachtet">
|
||||
|
|
@ -83636,17 +83636,24 @@ Date:   Thu Apr 20 18:53:17 2023 +0200<br/>
|
|||
<icon BUILTIN="idea"/>
|
||||
</node>
|
||||
</node>
|
||||
<node CREATED="1718153752253" ID="ID_1509145683" MODIFIED="1718153763392" TEXT="kann aber keinen nicht-trivialen Typ platzieren"/>
|
||||
<node COLOR="#435e98" CREATED="1718219051026" ID="ID_714747490" MODIFIED="1718219068199" TEXT="kann dann beliebige weitere triviale Objekte einfügen"/>
|
||||
<node COLOR="#435e98" CREATED="1718153752253" ID="ID_1509145683" MODIFIED="1718219045074" TEXT="kann aber keinen nicht-trivialen Typ platzieren"/>
|
||||
</node>
|
||||
<node CREATED="1718202490965" ID="ID_247674037" MODIFIED="1718206085439" TEXT="Handhabung von non-copyable-Objekten">
|
||||
<linktarget COLOR="#638ad5" DESTINATION="ID_247674037" ENDARROW="Default" ENDINCLINATION="-777;-16;" ID="Arrow_ID_10606647" SOURCE="ID_1146034926" STARTARROW="None" STARTINCLINATION="-438;67;"/>
|
||||
<node COLOR="#338800" CREATED="1718219075565" ID="ID_433297246" MODIFIED="1718221628518" TEXT="Fehler im Element-Konstruktor">
|
||||
<icon BUILTIN="button_ok"/>
|
||||
</node>
|
||||
<node COLOR="#338800" CREATED="1718221630271" ID="ID_1168231088" MODIFIED="1718221654795" TEXT="Dummy-Checksumme prüfen ⟹ alle Destruktoren korrekt aufgerufen">
|
||||
<icon BUILTIN="button_ok"/>
|
||||
</node>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1716857382441" ID="ID_1397767362" MODIFIED="1716857402102" TEXT="check_ElementAccess">
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1716857382441" ID="ID_1397767362" MODIFIED="1718219037095" TEXT="check_ElementStorage">
|
||||
<icon BUILTIN="flag-yellow"/>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1718067224015" ID="ID_1830672111" MODIFIED="1718067235928" TEXT="Alignment-Behandlung verifizieren">
|
||||
<icon BUILTIN="flag-yellow"/>
|
||||
</node>
|
||||
<node CREATED="1718202490965" ID="ID_247674037" MODIFIED="1718206085439" TEXT="Handhabung von non-copyable-Objekten">
|
||||
<linktarget COLOR="#638ad5" DESTINATION="ID_247674037" ENDARROW="Default" ENDINCLINATION="-777;-16;" ID="Arrow_ID_10606647" SOURCE="ID_1146034926" STARTARROW="None" STARTINCLINATION="-438;67;"/>
|
||||
</node>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1716857382442" ID="ID_28139752" MODIFIED="1716857402101" TEXT="check_CustomAllocator">
|
||||
<icon BUILTIN="flag-yellow"/>
|
||||
|
|
|
|||
Loading…
Reference in a new issue