LUMIERA.clone/tests/lib/advice/advice-binding-pattern-test.cpp
2010-06-03 04:40:35 +02:00

216 lines
7.5 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/advice.hpp"
#include "lib/time.h"
#include <iostream>
using std::cout;
using std::endl;
namespace lib {
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()");
CHECK (b1 == b2);
b2.addPredicate("cat3(zzz)");
CHECK (b1 != b2);
b1.addTypeGuard<lumiera::Time>();
CHECK (b1 != b2);
b1.addPredicate(" cat3( zzz ) ");
CHECK (b1 != b2);
b2.addTypeGuard<lumiera::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 lib::advice::test