lumiera_/tests/library/advice/advice-binding-pattern-test.cpp
Ichthyostega ada5cefaaf re-arrange tests according to layer structure
the buildsystem will now pick up and link
all test cases according to the layer, e.g.
backend tests will automatically be linked
against the backend + library solely.
2013-01-07 05:43:01 +01:00

218 lines
7.6 KiB
C++

/*
AdviceBindingPattern(Test) - cover pattern matching used to dispatch Advice
Copyright (C) Lumiera.org
2010, 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.
* *****************************************************/
#include "lib/test/run.hpp"
#include "lib/test/test-helper.hpp"
#include "lib/time/timevalue.hpp"
#include "common/advice.hpp"
#include <iostream>
using lib::time::Time;
using std::cout;
using std::endl;
namespace lumiera {
namespace advice {
namespace test {
namespace {
class DummyAdvice { };
}
/*******************************************************************************
* @test the pattern matching machinery used to find an Advice solution.
* Each advice::Provision and advice::Request specifies a binding, used
* to discern various pieces of advice. Whenever patterns on the two sides
* match, an Advice channel is created, causing the advice provision to
* get visible to the advised entity.
*
* This test creates various patterns and verifies matching behaves
* as specified and documented.
*
* @todo partially unimplemented and thus commented out ////////////////////TICKET #605
*
* @see advice.hpp
* @see AdviceBasics_test
* @see AdviceMultiplicity_test
* @see AdviceIndex_test implementation test
*/
class AdviceBindingPattern_test : public Test
{
virtual void
run (Arg)
{
verifyPatternSyntax();
verifyPatternNormalisation();
verifyStaticMatch();
verifyPreparedMatch();
verifyDynamicMatch();
}
void
verifyPatternSyntax()
{
#define _PARSE_AND_SHOW(_STR_) \
cout << _STR_ << "\t--->" << Binding(_STR_) << endl;
_PARSE_AND_SHOW ("");
_PARSE_AND_SHOW ("aSymbol");
_PARSE_AND_SHOW ("a.compound_Symbol-with-various.parts");
_PARSE_AND_SHOW ("trailing Garbage allowed. ☢☢ eat ☠☠☠ atomic ☠☠☠ waste ☢☢");
_PARSE_AND_SHOW ("a, list , of ,symbols.");
_PARSE_AND_SHOW ("nullary().");
_PARSE_AND_SHOW ("nullary( )");
_PARSE_AND_SHOW ("nullary .");
_PARSE_AND_SHOW ("predicate( with-argument )");
VERIFY_ERROR (BINDING_PATTERN_SYNTAX, Binding("no (valid definition here)"));
VERIFY_ERROR (BINDING_PATTERN_SYNTAX, Binding("predicate(with ☠☠☠ Garbage ☠☠☠"));
VERIFY_ERROR (BINDING_PATTERN_SYNTAX, Binding("§&Ω%€GΩ%€ar☠☠☠baäääääge"));
Binding testBinding;
testBinding.addTypeGuard<DummyAdvice>();
testBinding.addPredicate("one two(), three( four ).");
cout << testBinding << endl;
}
void
verifyPatternNormalisation()
{
Binding b0, b00;
Binding b1 ("cat1(), cat2().");
Binding b2 (" cat2 cat1 ....");
cout << "b0==" << b0 << endl;
cout << "b1==" << b1 << endl;
cout << "b2==" << b2 << endl;
CHECK (b0 == b00); CHECK (b00 == b0);
CHECK (b1 == b2); CHECK (b2 == b1);
CHECK (b0 != b1); CHECK (b1 != b0);
CHECK (b0 != b2); CHECK (b2 != b0);
b2.addPredicate("cat1()"); // adding the same predicate multiple times has no effect
b2.addPredicate(" cat1 ");
CHECK (b1 == b2);
b2.addPredicate("cat3(zzz)");
CHECK (b1 != b2);
b1.addTypeGuard<Time>();
CHECK (b1 != b2);
b1.addPredicate(" cat3( zzz ) ");
CHECK (b1 != b2);
b2.addTypeGuard<Time>();
CHECK (b1 == b2);
cout << "b2==" << b2 << endl;
}
void
verifyStaticMatch()
{
CHECK ( matches (Binding(), Binding()));
CHECK ( matches (Binding("pred()"), Binding("pred( ) ")));
CHECK ( matches (Binding("pred(x)"), Binding("pred(x)")));
CHECK (!matches (Binding("pred()"), Binding("pred(x)")));
CHECK (!matches (Binding("pred(x)"), Binding("pred(y)")));
CHECK ( matches (Binding("pred(x), pred(y)"), Binding("pred(y), pred(x)")));
CHECK (!matches (Binding("pred(x), pred(y)"), Binding("pred(y), pred(y)")));
}
void
verifyPreparedMatch()
{
Binding b1 ("pred()");
Binding b2 ("pred");
Binding b3 ("pred, pred(x)");
Binding b4 ("pred( x ) , pred().");
CHECK ( matches (b1,b2));
CHECK ( matches (b3,b4));
Binding::Matcher bm1 (b1.buildMatcher());
Binding::Matcher bm2 (b2.buildMatcher());
Binding::Matcher bm3 (b3.buildMatcher());
Binding::Matcher bm4 (b4.buildMatcher());
CHECK (hash_value(b1) == hash_value(bm1));
CHECK (hash_value(b2) == hash_value(bm2));
CHECK (hash_value(b3) == hash_value(bm3));
CHECK (hash_value(b4) == hash_value(bm4));
CHECK (hash_value(b1) != hash_value(b3));
CHECK ( matches (bm1,bm2));
CHECK ( matches (bm3,bm4));
CHECK (!matches (bm1,bm3));
CHECK (!matches (bm2,bm4));
}
/** @test match against patterns containing variables,
* verify the created solution arguments
* @todo this is a future extension and its not clear
* if we need it and what the exact semantics
* could be ///////////////////////////////TICKET #615
*/
void
verifyDynamicMatch()
{
#if false /////////////////////////////////////////////////////////////////////////////////////////////////////////////UNIMPLEMENTED :: TICKET #615
CHECK ( matches (Binding("pred(u)"), Binding("pred(X)")));
CHECK ( matches (Binding("pred(f(u))"), Binding("pred(f(X))")));
CHECK ( matches (Binding("pred(f(u,Y))"), Binding("pred(f(X,v))")));
CHECK ( matches (Binding("pred(f(u,X))"), Binding("pred(f(X,v))"))); // the so called "standardisation apart"
CHECK (!matches (Binding("pred(u,v)"), Binding("pred(X)")));
CHECK (!matches (Binding("pred(f(u))"), Binding("pred(f(v))")));
CHECK (!matches (Binding("pred(f(u))"), Binding("pred(g(X))")));
CHECK (!matches (Binding("pred(f(u,v))"), Binding("pred(f(X,X))")));
//////TODO should also cover the difference between equality and match, which gets tangible only in conjunction with variables
#endif /////////////////////////////////////////////////////////////////////////////////////////////////////////////UNIMPLEMENTED :: TICKET #615
}
};
/** Register this test class... */
LAUNCHER (AdviceBindingPattern_test, "unit common");
}}} // namespace lumiera::advice::test