2025-01-20 23:55:42 +01:00
|
|
|
|
/*
|
|
|
|
|
|
BranchCase(Test) - verify parsing textual specifications
|
|
|
|
|
|
|
|
|
|
|
|
Copyright (C)
|
|
|
|
|
|
2024, Hermann Vosseler <Ichthyostega@web.de>
|
|
|
|
|
|
|
|
|
|
|
|
**Lumiera** is free software; you can redistribute it and/or modify it
|
|
|
|
|
|
under the terms of the GNU General Public License as published by the
|
|
|
|
|
|
Free Software Foundation; either version 2 of the License, or (at your
|
|
|
|
|
|
option) any later version. See the file COPYING for further details.
|
|
|
|
|
|
|
|
|
|
|
|
* *****************************************************************/
|
|
|
|
|
|
|
|
|
|
|
|
/** @file branch-case-test.cpp
|
|
|
|
|
|
** unit test \ref BranchCase_test
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#include "lib/test/run.hpp"
|
2025-01-21 03:53:29 +01:00
|
|
|
|
//#include "lib/test/test-helper.hpp"
|
|
|
|
|
|
#include "lib/test/tracking-dummy.hpp"
|
2025-01-20 23:55:42 +01:00
|
|
|
|
#include "lib/branch-case.hpp"
|
2025-01-21 03:53:29 +01:00
|
|
|
|
#include "lib/format-obj.hpp"
|
2025-01-20 23:55:42 +01:00
|
|
|
|
#include "lib/test/diagnostic-output.hpp"//////////////////TODO
|
|
|
|
|
|
|
|
|
|
|
|
|
2025-01-21 03:53:29 +01:00
|
|
|
|
namespace lib {
|
|
|
|
|
|
namespace test{
|
2025-01-20 23:55:42 +01:00
|
|
|
|
|
|
|
|
|
|
|
2025-01-21 03:53:29 +01:00
|
|
|
|
/********************************************************//**
|
|
|
|
|
|
* @test verify a _Sum Type_ to hold alternative model types
|
|
|
|
|
|
* for several result branches of an evaluation.
|
|
|
|
|
|
* @see parse.hpp "usage example"
|
2025-01-20 23:55:42 +01:00
|
|
|
|
*/
|
|
|
|
|
|
class BranchCase_test : public Test
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
|
|
virtual void
|
|
|
|
|
|
run (Arg)
|
|
|
|
|
|
{
|
2025-01-21 03:53:29 +01:00
|
|
|
|
simpleUsage();
|
|
|
|
|
|
demonstrateStorage();
|
|
|
|
|
|
verifyCopyAssignment();
|
2025-01-20 23:55:42 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2025-01-21 03:53:29 +01:00
|
|
|
|
/** @test create one alternative and access embedded model value. */
|
2025-01-20 23:55:42 +01:00
|
|
|
|
void
|
2025-01-21 03:53:29 +01:00
|
|
|
|
simpleUsage()
|
2025-01-20 23:55:42 +01:00
|
|
|
|
{
|
2025-01-21 03:53:29 +01:00
|
|
|
|
using Branch = BranchCase<char,ushort>;
|
|
|
|
|
|
Branch branch{1, 42}; // construct for second branch (#1) to hold ushort(42)
|
|
|
|
|
|
CHECK (1 == branch.selected());
|
|
|
|
|
|
CHECK (42 == branch.get<1>()); // direct access with known branch-nr
|
|
|
|
|
|
CHECK ('*' == branch.get<0>()); // Warning: no protection against accessing the wrong branch
|
|
|
|
|
|
|
|
|
|
|
|
int val{-5};
|
|
|
|
|
|
auto visitor = [&](auto& it){ val = it;};
|
|
|
|
|
|
branch.accept (visitor);
|
|
|
|
|
|
CHECK (42 == val);
|
2025-01-20 23:55:42 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-01-21 03:53:29 +01:00
|
|
|
|
|
|
|
|
|
|
/** @test demonstrate expected storage layout...
|
|
|
|
|
|
* - the selector field always coincides with the object itself
|
|
|
|
|
|
* - the storage buffer starts after the `size_t` selector
|
|
|
|
|
|
*/
|
2025-01-20 23:55:42 +01:00
|
|
|
|
void
|
2025-01-21 03:53:29 +01:00
|
|
|
|
demonstrateStorage()
|
2025-01-20 23:55:42 +01:00
|
|
|
|
{
|
2025-01-21 03:53:29 +01:00
|
|
|
|
using Branch = BranchCase<ushort,double>;
|
|
|
|
|
|
CHECK (sizeof(double)+sizeof(size_t) <= sizeof(Branch));
|
|
|
|
|
|
CHECK (sizeof(double) == Branch::SIZ);
|
2025-01-20 23:55:42 +01:00
|
|
|
|
|
2025-01-21 03:53:29 +01:00
|
|
|
|
double phi{(1+sqrt(5))/2};
|
|
|
|
|
|
Branch b1{1,phi};
|
|
|
|
|
|
CHECK (1 == b1.selected());
|
|
|
|
|
|
CHECK (phi == b1.get<1>());
|
2025-01-20 23:55:42 +01:00
|
|
|
|
|
2025-01-21 03:53:29 +01:00
|
|
|
|
auto p = reinterpret_cast<size_t*> (&b1);
|
|
|
|
|
|
CHECK (1 == *p);
|
|
|
|
|
|
CHECK (phi == * reinterpret_cast<double*>(p+1));
|
2025-01-20 23:55:42 +01:00
|
|
|
|
|
2025-01-21 03:53:29 +01:00
|
|
|
|
// force-place a differently constructed object at the same location
|
|
|
|
|
|
new(p) Branch{0,42};
|
|
|
|
|
|
CHECK (0 == b1.selected());
|
|
|
|
|
|
CHECK (42 == b1.get<0>());
|
|
|
|
|
|
CHECK (0 == *p);
|
|
|
|
|
|
CHECK (42 == * reinterpret_cast<ushort*>(p+1));
|
2025-01-20 23:55:42 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2025-01-21 03:53:29 +01:00
|
|
|
|
|
|
|
|
|
|
/** @test verify selector and payload instances
|
|
|
|
|
|
* are properly handled on copy, clone, assignment and swap.
|
|
|
|
|
|
*/
|
2025-01-20 23:55:42 +01:00
|
|
|
|
void
|
2025-01-21 03:53:29 +01:00
|
|
|
|
verifyCopyAssignment()
|
2025-01-20 23:55:42 +01:00
|
|
|
|
{
|
2025-01-21 03:53:29 +01:00
|
|
|
|
using Branch = BranchCase<char,string>;
|
|
|
|
|
|
CHECK (sizeof(string)+sizeof(size_t) <= sizeof(Branch));
|
2025-01-20 23:55:42 +01:00
|
|
|
|
|
2025-01-21 03:53:29 +01:00
|
|
|
|
// use generic to-String visitor to display contents
|
|
|
|
|
|
auto render = [](auto const& it) -> string { return util::toString(it); };
|
2025-01-20 23:55:42 +01:00
|
|
|
|
|
2025-01-21 03:53:29 +01:00
|
|
|
|
Branch b1{1, "evil"};
|
|
|
|
|
|
CHECK ( 1 == b1.TOP );
|
|
|
|
|
|
CHECK ( 1 == b1.selected());
|
|
|
|
|
|
CHECK ("evil" == b1.get<1>());
|
|
|
|
|
|
CHECK ("evil" == b1.accept(render));
|
2025-01-20 23:55:42 +01:00
|
|
|
|
|
2025-01-21 03:53:29 +01:00
|
|
|
|
Branch b2{0,42};
|
|
|
|
|
|
CHECK ( 0 == b2.selected());
|
|
|
|
|
|
CHECK ('*' == b2.get<0>());
|
|
|
|
|
|
CHECK ("*" == b2.accept(render));
|
2025-01-20 23:55:42 +01:00
|
|
|
|
|
2025-01-21 03:53:29 +01:00
|
|
|
|
Branch b3{b1};
|
|
|
|
|
|
CHECK (1 == b3.selected());
|
|
|
|
|
|
CHECK ("evil" == b3.accept(render));
|
2025-01-20 23:55:42 +01:00
|
|
|
|
|
2025-01-21 03:53:29 +01:00
|
|
|
|
b3 = b2;
|
|
|
|
|
|
CHECK ( 0 == b3.selected());
|
|
|
|
|
|
CHECK ("*" == b3.accept(render));
|
|
|
|
|
|
CHECK ("*" == b2.accept(render));
|
|
|
|
|
|
CHECK ("evil" == b1.accept(render));
|
2025-01-20 23:55:42 +01:00
|
|
|
|
|
2025-01-21 03:53:29 +01:00
|
|
|
|
b3 = move(b1);
|
|
|
|
|
|
CHECK ( 1 == b3.selected() );
|
|
|
|
|
|
CHECK ( 0 == b2.selected() );
|
|
|
|
|
|
CHECK ("evil" == b3.accept(render));
|
|
|
|
|
|
CHECK ("*" == b2.accept(render));
|
|
|
|
|
|
CHECK ("" == b1.accept(render)); // ◁——————————— warning: moved-away string is "implementation defined"
|
2025-01-20 23:55:42 +01:00
|
|
|
|
|
2025-01-21 03:53:29 +01:00
|
|
|
|
swap (b3,b2);
|
|
|
|
|
|
CHECK ( 0 == b3.selected());
|
|
|
|
|
|
CHECK ( 1 == b2.selected());
|
|
|
|
|
|
CHECK ("*" == b3.accept(render));
|
|
|
|
|
|
CHECK ("evil" == b2.accept(render));
|
|
|
|
|
|
CHECK ("" == b1.accept(render));
|
2025-01-20 23:55:42 +01:00
|
|
|
|
|
2025-01-21 03:53:29 +01:00
|
|
|
|
//_______________________________
|
|
|
|
|
|
// verify proper payload lifecycle
|
|
|
|
|
|
seedRand();
|
|
|
|
|
|
Dummy::checksum() = 0;
|
|
|
|
|
|
{ // track instances by checksum...
|
|
|
|
|
|
Dummy dummy;
|
|
|
|
|
|
auto rr = dummy.getVal();
|
|
|
|
|
|
CHECK (rr == Dummy::checksum());
|
|
|
|
|
|
CHECK (rr > 0);
|
|
|
|
|
|
|
|
|
|
|
|
using BB = BranchCase<string,Dummy>;
|
|
|
|
|
|
BB bb1{1, dummy};
|
|
|
|
|
|
CHECK (bb1.get<1>().getVal() == rr);
|
|
|
|
|
|
CHECK (2*rr == Dummy::checksum()); // got two instances due to copy-init
|
|
|
|
|
|
|
|
|
|
|
|
BB bb2{0, "dummy"};
|
|
|
|
|
|
CHECK (2*rr == Dummy::checksum());
|
|
|
|
|
|
|
|
|
|
|
|
swap (bb1,bb2);
|
|
|
|
|
|
CHECK (bb1.get<0>() == "dummy");
|
|
|
|
|
|
CHECK (bb2.get<1>().getVal() == rr);
|
|
|
|
|
|
CHECK (2*rr == Dummy::checksum());
|
|
|
|
|
|
|
|
|
|
|
|
bb1 = bb2;
|
|
|
|
|
|
CHECK (bb1.get<1>().getVal() == rr);
|
|
|
|
|
|
CHECK (3*rr == Dummy::checksum()); // assignment by copy
|
|
|
|
|
|
|
|
|
|
|
|
bb2 = move(bb1); // move-assignment
|
|
|
|
|
|
CHECK (2*rr == Dummy::checksum()); // existing instance destroyed properly
|
|
|
|
|
|
CHECK (bb2.get<1>().getVal() == rr);
|
|
|
|
|
|
CHECK (bb1.get<1>().getVal() == Dummy::DEFUNCT);
|
|
|
|
|
|
|
|
|
|
|
|
bb2 = BB{1,Dummy()}; // wipes out the other copy
|
|
|
|
|
|
auto rr2 = bb2.get<1>().getVal(); // but implants a different one
|
|
|
|
|
|
CHECK (rr+rr2 == Dummy::checksum());
|
|
|
|
|
|
CHECK (rr == dummy.getVal());
|
|
|
|
|
|
}// leave scope: invoke dtors here
|
|
|
|
|
|
|
|
|
|
|
|
CHECK (0 == Dummy::checksum());
|
2025-01-20 23:55:42 +01:00
|
|
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
LAUNCHER (BranchCase_test, "unit common");
|
|
|
|
|
|
|
|
|
|
|
|
|
2025-01-21 03:53:29 +01:00
|
|
|
|
}} // namespace lib::test
|
2025-01-20 23:55:42 +01:00
|
|
|
|
|