LUMIERA.clone/tests/gui/interact/ui-coord-test.cpp
Ichthyostega 42277c5760 UI-Coordinates: need to spell out all ctors explicitly
the usual drill...
once there is one additional non explicit conversion ctor,
lots of preferred conversion paths are opened under various conditions.

The only remedy is to define all ctors explicitly, instead of letting the
compiler infer them (from the imported base class ctors). Because this way
we're able to indicate a yet-more-preferred initialisation path and thus
prevent the compiler from going the conversion route.

In the actual case, the coordinate Builder is the culprit; obviously
we need smooth implicit conversion from builder expressions, and obviously
we also want to restrict Builder's ctors to be used from UICoord solely.

Unfortunately this misleads the compiler to do implement a simple copy construction
from non const reference by going through the prohibited Builder ctor, or to
instantiate the vararg-ctor inherited from PathArray.

Thus better be explicit and noisy...
2017-10-02 22:17:56 +02:00

378 lines
14 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
UICoord(Test) - properties of topological UI coordinate specifications
Copyright (C) Lumiera.org
2017, Hermann Vosseler <Ichthyostega@web.de>
This program 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.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
* *****************************************************/
/** @file ui-coord-test.cpp
** unit test \ref UICoord_test
*/
#include "lib/test/run.hpp"
#include "lib/test/test-helper.hpp"
#include "gui/interact/ui-coord.hpp"
#include "lib/format-cout.hpp"/////////////////////////TODO RLY?
#include "lib/format-util.hpp"
//#include "lib/idi/entry-id.hpp"
//#include "lib/diff/gen-node.hpp"
#include "lib/util.hpp"
#include <string>
using std::string;
//using lib::idi::EntryID;
//using lib::diff::GenNode;
//using util::isSameObject;
using lib::Symbol;
using util::isnil;
using util::join;
namespace gui {
namespace interact {
namespace test {
// using lumiera::error::LUMIERA_ERROR_WRONG_TYPE;
using lumiera::error::LUMIERA_ERROR_INDEX_BOUNDS;
using lumiera::error::LUMIERA_ERROR_LOGIC;
namespace { //Test fixture...
}//(End)Test fixture
/******************************************************************************//**
* @test verify the basic properties of topological UI coordinate specifications.
* - created as path-like sequence of components
* - provides a builder API for definition and mutation
* - Normalisation and handling of missing parts
* - access to UI coordinate components
* - string representation
* - comparisons
*
* @see ui-coord.hpp
* @see path-array.hpp
* @see PathArray_test
* @see UICoordResolver_test
* @see ViewSpecDSL_test
*/
class UICoord_test : public Test
{
virtual void
run (Arg)
{
verify_basics();
verify_builder();
verify_stringRepr();
verify_comparisons();
verify_localPredicates();
}
void
verify_basics()
{
UICoord undef;
CHECK (isnil (undef));
UICoord uic{"Γ","Δ","Θ","Ξ","Σ","Ψ","Φ","Ω"};
CHECK (not isnil (uic));
CHECK (8 == uic.size());
// path is iterable
CHECK ("Γ-Δ-Θ-Ξ-Σ-Ψ-Φ-Ω" == join(uic,"-"));
// indexed access
CHECK ("Γ" == uic[UIC_WINDOW]); // window spec to anchor the path
CHECK ("Δ" == uic[UIC_PERSP]); // the perspective used within that window
CHECK ("Θ" == uic[UIC_PANEL]); // the docking panel within the window
CHECK ("Ξ" == uic[UIC_VIEW]); // the view residing in the docking panel
CHECK ("Σ" == uic[UIC_TAB]); // the tab or element group within the view
CHECK ("Ψ" == uic[UIC_PATH]); // a path sequence...
CHECK ("Φ" == uic[UIC_PATH+1]); // ...descending through local widgets
CHECK ("Ω" == uic[UIC_PATH+2]);
// iteration of complete path matches index order
uint i=0;
for (UICoord::iterator ii = uic.begin(); ii; ++ii, ++i)
CHECK (uic[i] == *ii);
CHECK (8 == i);
VERIFY_ERROR (INDEX_BOUNDS, uic[8]);
// string representation
CHECK ("UI:Γ[Δ]-Θ.Ξ.Σ/Ψ/Φ/Ω" == string(uic));
CHECK ( "Γ[Δ]-Θ.Ξ.Σ" == uic.getComp());
CHECK ( "Ψ/Φ/Ω" == uic.getPath());
// new value can be assigned, but not altered in place
uic = UICoord{nullptr,nullptr,"Θ",nullptr,"Σ",nullptr,"Φ"};
CHECK (7 == uic.size());
// representation is trimmed and filled
CHECK ("UI:?-Θ.*.Σ/*/Φ" == string(uic));
CHECK (Symbol::EMPTY == uic[UIC_WINDOW]);
CHECK (Symbol::EMPTY == uic[UIC_PERSP]);
CHECK ("Θ" == uic[UIC_PANEL]);
CHECK ("*" == uic[UIC_VIEW]);
CHECK ("Σ" == uic[UIC_TAB]);
CHECK ("*" == uic[UIC_PATH]);
CHECK ("Φ" == uic[UIC_PATH+1]);
VERIFY_ERROR (INDEX_BOUNDS, uic[UIC_PATH+2]);
}
void
verify_builder()
{
UICoord uic1 = UICoord::window("window");
UICoord uic2 = uic1.view("view"); // Note: does not alter uic1
CHECK ("UI:window" == string(uic1));
CHECK ("UI:window[*]-*.view" == string(uic2));
CHECK (1 == uic1.size());
CHECK (4 == uic2.size());
// fault-tolerant accessors for the generic part
CHECK ("window" == uic1.getWindow());
CHECK ("window" == uic2.getWindow());
CHECK ("" == uic1.getPersp());
CHECK ("*" == uic2.getPersp());
CHECK ("" == uic1.getPanel());
CHECK ("*" == uic2.getPanel());
CHECK ("" == uic1.getView());
CHECK ("view" == uic2.getView());
CHECK ("" == uic1.getTab());
CHECK ("" == uic2.getTab());
CHECK ("" == uic1.getPath());
CHECK ("" == uic2.getPath());
CHECK ("window" == uic1.getComp());
CHECK ("window[*]-*.view" == uic2.getComp());
VERIFY_ERROR (INDEX_BOUNDS, uic1[UIC_PERSP]);
VERIFY_ERROR (INDEX_BOUNDS, uic2[UIC_TAB]);
// partial (incomplete) coordinate spec
UICoord uic3 = UICoord().view("view");
CHECK (4 == uic3.size());
CHECK ("UI:?.view" == string(uic3));
CHECK ("" == uic3.getWindow());
CHECK ("" == uic3.getPersp());
CHECK ("" == uic3.getPanel());
CHECK ("view" == uic3.getView());
UICoord uic4 = uic3.persp("perspective");
CHECK (4 == uic4.size());
CHECK ("UI:?[perspective]-*.view" == string(uic4));
uic4 = uic3.append("tab");
CHECK (5 == uic4.size());
CHECK ("UI:?.view.tab" == string(uic4));
uic4 = uic3.prepend("panel");
CHECK (4 == uic4.size());
CHECK ("UI:?-panel.view" == string(uic4));
uic4 = uic4.tab(555);
CHECK (5 == uic4.size());
CHECK ("UI:?-panel.view.#555" == string(uic4));
VERIFY_ERROR(LOGIC, uic1.prepend("root"));
}
void
verify_stringRepr()
{
UICoord uic;
CHECK ("UI:?" == string(uic));
CHECK ("" == uic.getComp());
CHECK ("" == uic.getPath());
uic = uic.path("ἁρχή");
CHECK ("UI:?/ἁρχή" == string(uic));
CHECK ("" == uic.getComp());
CHECK ("ἁρχή" == uic.getPath());
uic = uic.path("α/β/γ");
CHECK ("UI:?/α/β/γ" == string(uic));
CHECK ("" == uic.getComp());
CHECK ("α/β/γ" == uic.getPath());
uic = uic.append("δ");
CHECK ("UI:?/α/β/γ" == string(uic));
CHECK ("" == uic.getComp());
CHECK ("α/β/γ" == uic.getPath());
uic = uic.append("");
CHECK ("UI:?/α/β/γ" == string(uic));
CHECK ("" == uic.getComp());
CHECK ("α/β/γ" == uic.getPath());
uic = uic.append("ε/λ/ον");
CHECK ("UI:?/α/β/γ/δ/ε/λ/ον" == string(uic));
CHECK ("" == uic.getComp());
CHECK ("α/β/γ/δ/ε/λ/ον" == uic.getPath());
// note: we built a partially empty path array...
CHECK (12 == uic.size());
CHECK (Symbol::EMPTY == uic.getView());
CHECK (Symbol::EMPTY == uic.getTab());
CHECK (Symbol::EMPTY == uic[UIC_WINDOW]);
CHECK (Symbol::EMPTY == uic[UIC_PERSP]);
CHECK (Symbol::EMPTY == uic[UIC_PANEL]);
CHECK (Symbol::EMPTY == uic[UIC_VIEW]);
CHECK (Symbol::EMPTY == uic[UIC_TAB]);
CHECK ("α" == uic[UIC_PATH]);
CHECK ("β" == uic[UIC_PATH+1]);
CHECK ("γ" == uic[UIC_PATH+2]);
CHECK ("δ" == uic[UIC_PATH+3]);
CHECK ("ε" == uic[UIC_PATH+4]);
CHECK ("λ" == uic[UIC_PATH+5]);
CHECK ("ον" == uic[UIC_PATH+6]);
uic = uic.prepend("ειδος");
CHECK ("UI:?.ειδος/α/β/γ/δ/ε/λ/ον" == string(uic));
CHECK ("?.ειδος" == uic.getComp());
CHECK ("α/β/γ/δ/ε/λ/ον" == uic.getPath());
CHECK (12 == uic.size());
uic = uic.tab("");
CHECK ("UI:?/α/β/γ/δ/ε/λ/ον" == string(uic));
CHECK ("" == uic.getComp());
CHECK ("α/β/γ/δ/ε/λ/ον" == uic.getPath());
uic = uic.view("ειδος");
CHECK ("UI:?.ειδος.*/α/β/γ/δ/ε/λ/ον" == string(uic));
CHECK ("?.ειδος.*" == uic.getComp());
CHECK ("α/β/γ/δ/ε/λ/ον" == uic.getPath());
uic = uic.prepend("panel");
CHECK ("UI:?-panel.ειδος.*/α/β/γ/δ/ε/λ/ον" == string(uic));
CHECK ("?-panel.ειδος.*" == uic.getComp());
CHECK ("α/β/γ/δ/ε/λ/ον" == uic.getPath());
uic = uic.view(nullptr);
CHECK ("UI:?-panel.*.*/α/β/γ/δ/ε/λ/ον" == string(uic));
CHECK ("?-panel.*.*" == uic.getComp());
CHECK ("α/β/γ/δ/ε/λ/ον" == uic.getPath());
uic = uic.tab(8);
CHECK ("UI:?-panel.*.#8/α/β/γ/δ/ε/λ/ον" == string(uic));
CHECK ("?-panel.*.#8" == uic.getComp());
CHECK ("α/β/γ/δ/ε/λ/ον" == uic.getPath());
uic = uic.noTab();
CHECK ("UI:?-panel.*/α/β/γ/δ/ε/λ/ον" == string(uic));
CHECK ("?-panel.*" == uic.getComp());
CHECK ("α/β/γ/δ/ε/λ/ον" == uic.getPath());
uic = uic.tab(" ");
CHECK ("UI:?-panel.*. /α/β/γ/δ/ε/λ/ον" == string(uic));
CHECK ("?-panel.*. " == uic.getComp());
CHECK ("α/β/γ/δ/ε/λ/ον" == uic.getPath());
uic = uic.prepend("perspective");
CHECK ("UI:?[perspective]-panel.*. /α/β/γ/δ/ε/λ/ον" == string(uic));
CHECK ("?[perspective]-panel.*. " == uic.getComp());
CHECK ("α/β/γ/δ/ε/λ/ον" == uic.getPath());
uic = uic.prepend("win");
CHECK ("UI:win[perspective]-panel.*. /α/β/γ/δ/ε/λ/ον" == string(uic));
CHECK ("win[perspective]-panel.*. " == uic.getComp());
CHECK ("α/β/γ/δ/ε/λ/ον" == uic.getPath());
uic = uic.persp("");
CHECK ("UI:win[*]-panel.*. /α/β/γ/δ/ε/λ/ον" == string(uic));
CHECK ("win[*]-panel.*. " == uic.getComp());
CHECK ("α/β/γ/δ/ε/λ/ον" == uic.getPath());
CHECK (12 == uic.size());
uic = uic.path(" ");
CHECK ("UI:win[*]-panel.*. / " == string(uic));
CHECK ("win[*]-panel.*. " == uic.getComp());
CHECK (" " == uic.getPath());
CHECK (6 == uic.size());
CHECK (" " == uic[UIC_PATH]);
VERIFY_ERROR (INDEX_BOUNDS, uic[UIC_PATH+1]);
uic = uic.path(nullptr);
CHECK ("UI:win[*]-panel.*. " == string(uic));
CHECK ("win[*]-panel.*. " == uic.getComp());
CHECK ("" == uic.getPath());
CHECK (5 == uic.size());
VERIFY_ERROR (INDEX_BOUNDS, uic[UIC_PATH]);
uic = uic.append(nullptr);
CHECK ("UI:win[*]-panel.*. " == string(uic));
CHECK ("win[*]-panel.*. " == uic.getComp());
CHECK ("" == uic.getPath());
CHECK (5 == uic.size());
uic = uic.append("*");
CHECK ("UI:win[*]-panel.*. " == string(uic));
CHECK ("win[*]-panel.*. " == uic.getComp());
CHECK ("" == uic.getPath());
CHECK (5 == uic.size());
uic = uic.append("**");
CHECK ("UI:win[*]-panel.*. /**" == string(uic));
CHECK ("win[*]-panel.*. " == uic.getComp());
CHECK ("**" == uic.getPath());
CHECK ("**" == uic[UIC_PATH]);
CHECK (6 == uic.size());
uic = uic.tab("");
CHECK ("UI:win[*]-panel.*.*/**" == string(uic));
CHECK ("win[*]-panel.*.*" == uic.getComp());
CHECK ("**" == uic.getPath());
CHECK (6 == uic.size());
uic = uic.path("");
CHECK ("UI:win[*]-panel" == string(uic));
CHECK ("win[*]-panel" == uic.getComp());
CHECK ("" == uic.getPath());
CHECK (3 == uic.size());
}
void
verify_comparisons()
{
UICoord u1 {"Γ","Δ","Θ","Ξ","Σ","Ψ","Φ" };
UICoord u11{"Γ","Δ","Θ","Ξ","Σ","Ψ","Φ","Ω"};
UICoord u2 {"Γ","Δ","Θ","Σ","Ξ","Ψ","Φ","Ω"};
UICoord u1c{u1};
}
void
verify_localPredicates()
{
UNIMPLEMENTED ("predicates locally decidable based only on the coordinate data");
}
};
/** Register this test class... */
LAUNCHER (UICoord_test, "unit gui");
}}} // namespace gui::interact::test