/*
* tests/query/LoopPatternUTest.cxxtest
*
* Copyright (C) 2009 Linas Vepstas <linasvepstas@gmail.com>
* All Rights Reserved
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License v3 as
* published by the Free Software Foundation and including the exceptions
* at http://opencog.org/wiki/Licenses
*
* 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 Affero General Public License
* along with this program; if not, write to:
* Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include <opencog/atomspace/AtomSpace.h>
#include <opencog/util/Logger.h>
#include "imply.h"
#undef DEBUG
using namespace opencog;
class LoopPatternUTest : public CxxTest::TestSuite
{
private:
AtomSpacePtr as;
Handle clauses, implicand;
Handle hone, htwo, hthree;
public:
LoopPatternUTest(void)
{
logger().set_level(Logger::DEBUG);
logger().set_print_to_stdout_flag(true);
}
~LoopPatternUTest()
{
// erase the log file if no assertions failed
if (!CxxTest::TestTracker::tracker().suiteFailed())
std::remove(logger().get_filename().c_str());
}
void setUp(void);
void tearDown(void);
void test_prep(void);
void verify(Handle);
void cycle(Handle, Handle, Handle);
};
/*
* This function sets up the following structures:
*/
#define an as->add_node
#define al as->add_link
#define getarity(hand) hand->get_arity()
#define getlink(hand,pos) hand->getOutgoingAtom(pos)
void LoopPatternUTest::tearDown(void)
{
}
void LoopPatternUTest::setUp(void)
{
as = createAtomSpace();
// Create an implication link that will be tested.
clauses =
al(AND_LINK,
al(LIST_LINK,
an(VARIABLE_NODE, "$var0"),
an(VARIABLE_NODE, "$var1")
),
al(LIST_LINK,
an(VARIABLE_NODE, "$var1"),
an(VARIABLE_NODE, "$var2")
),
al(LIST_LINK,
an(VARIABLE_NODE, "$var2"),
an(VARIABLE_NODE, "$var0")
)
);
implicand =
al(ORDERED_LINK,
an(VARIABLE_NODE, "$var0"),
an(VARIABLE_NODE, "$var1"),
an(VARIABLE_NODE, "$var2")
);
// Create data on which the above pattern should match
al(LIST_LINK,
hone = an(CONCEPT_NODE, "one"),
htwo = an(CONCEPT_NODE, "two")
);
al(LIST_LINK,
htwo = an(CONCEPT_NODE, "two"),
hthree = an(CONCEPT_NODE, "three")
);
al(LIST_LINK,
hthree = an(CONCEPT_NODE, "three"),
hone = an(CONCEPT_NODE, "one")
);
}
/*
* Circular loop
*
* Expect to get the following result, given the above data:
*
* OrderedLink
* ConceptNode "one"
* ConceptNode "two"
* ConceptNode "three"
*/
void LoopPatternUTest::cycle(Handle va, Handle vb, Handle vc)
{
if (va == hone)
{
TSM_ASSERT_EQUALS("incorrect vb", htwo, vb);
TSM_ASSERT_EQUALS("incorrect vc", hthree, vc);
}
else
if (va == htwo)
{
TSM_ASSERT_EQUALS("incorrect vb", hthree, vb);
TSM_ASSERT_EQUALS("incorrect vc", hone, vc);
}
else
if (va == hthree)
{
TSM_ASSERT_EQUALS("incorrect vb", hone, vb);
TSM_ASSERT_EQUALS("incorrect vc", htwo, vc);
}
else
TSM_ASSERT_EQUALS("invalid va", 0, 1);
}
void LoopPatternUTest::verify(Handle soln)
{
Handle va = getlink(soln, 0);
Handle vb = getlink(soln, 1);
Handle vc = getlink(soln, 2);
cycle (va, vb, vc);
}
void LoopPatternUTest::test_prep(void)
{
logger().debug("BEGIN TEST: %s", __FUNCTION__);
// Result should be a ListLink
Handle result = imply(as, clauses, implicand);
#define NO_SELF_GROUNDING 1
#ifdef NO_SELF_GROUNDING
// Expect three answers.
TSM_ASSERT_EQUALS("incorrect arity", getarity(result), 3);
#else
// Expect five answers.
TSM_ASSERT_EQUALS("incorrect arity", getarity(result), 5);
#endif
// Check that each answer gives the loop in cyclic order.
verify (getlink(result, 0));
verify (getlink(result, 1));
verify (getlink(result, 2));
Handle va = getlink(getlink(result, 0), 0);
Handle vb = getlink(getlink(result, 1), 0);
Handle vc = getlink(getlink(result, 2), 0);
bool found_one = false, found_two = false, found_three = false;
if (va == hone) found_one = true;
if (va == htwo) found_two = true;
if (va == hthree) found_three = true;
if (vb == hone) found_one = true;
if (vb == htwo) found_two = true;
if (vb == hthree) found_three = true;
if (vc == hone) found_one = true;
if (vc == htwo) found_two = true;
if (vc == hthree) found_three = true;
if (!(found_one && found_two && found_three))
TSM_ASSERT_EQUALS("not all solutions enumerated", 0, 1);
logger().debug("END TEST: %s", __FUNCTION__);
}