/*
* tests/atoms/core/DefineLinkUTest.cxxtest
*
* Copyright (C) 2015 Nil Geisweiller
* 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/atoms/base/Atom.h>
#include <opencog/atomspace/AtomSpace.h>
#include <opencog/atoms/grant/DefineLink.h>
using namespace opencog;
// Test the DefineLink.
//
class DefineLinkUTest : public CxxTest::TestSuite
{
private:
AtomSpace _as;
public:
DefineLinkUTest()
{
logger().set_print_to_stdout_flag(true);
}
void setUp() {}
void tearDown() {}
void test_define_concept();
void test_define_in_child_space();
// void test_define_pattern();
// void test_define_function();
};
#define N _as.add_node
#define L _as.add_link
// Test DefineLink over a ConceptNode
void DefineLinkUTest::test_define_concept()
{
logger().info("BEGIN TEST: %s", __FUNCTION__);
// Create DefineLink over a concept node
Handle A = N(CONCEPT_NODE, "A");
Handle B = N(CONCEPT_NODE, "B");
Handle VA = N(VARIABLE_NODE, "$va");
Handle VB = N(VARIABLE_NODE, "$vb");
Handle aliasA = N(CONCEPT_NODE, "alias-of-A");
TS_ASSERT_THROWS_ANYTHING(L(DEFINE_LINK, aliasA, A));
aliasA = N(DEFINED_SCHEMA_NODE, "alias-of-A");
Handle def_concept = L(DEFINE_LINK, aliasA, A);
// Test that aliasA returns A as definition
Handle body = DefineLink::get_definition(aliasA);
TS_ASSERT_EQUALS(A, body);
// Reinserting the same definition doesn't raise an error
TS_ASSERT_THROWS_NOTHING(L(DEFINE_LINK, aliasA, A));
// But inserting another one with the same alias does raise an error
TS_ASSERT_THROWS_ANYTHING(L(DEFINE_LINK, aliasA, B));
TS_ASSERT_THROWS_ANYTHING(L(DEFINE_LINK, aliasA, VA));
TS_ASSERT_THROWS_ANYTHING(L(DEFINE_LINK, aliasA, VB));
body = DefineLink::get_definition(aliasA);
TS_ASSERT_EQUALS(A, body);
logger().info("END TEST: %s", __FUNCTION__);
}
// Test that DefineLink lookup works when the alias is localized
// (copied) to a child AtomSpace. This tests the AtomSpace::depth()
// function which must correctly find atoms in parent spaces.
void DefineLinkUTest::test_define_in_child_space()
{
logger().info("BEGIN TEST: %s", __FUNCTION__);
// Create a parent AtomSpace with a definition
AtomSpacePtr parent = createAtomSpace();
Handle body = parent->add_node(CONCEPT_NODE, "the-body");
Handle alias = parent->add_node(DEFINED_SCHEMA_NODE, "the-alias");
parent->add_link(DEFINE_LINK, alias, body);
// Verify lookup works in parent
Handle got = DefineLink::get_definition(alias, parent.get());
TS_ASSERT_EQUALS(body, got);
// Create a child AtomSpace
AtomSpacePtr child = createAtomSpace(parent);
// Localize (copy) the alias to the child space
Handle local_alias = child->localize(alias);
TS_ASSERT(local_alias != nullptr);
TS_ASSERT(local_alias->getAtomSpace() == child.get());
// Verify depth calculation: alias in parent should be at depth 1
int depth = child->depth(alias);
TS_ASSERT_EQUALS(1, depth);
// The key test: lookup should still work from the child space,
// even though the DefineLink is in the parent (depth 1).
got = DefineLink::get_definition(local_alias, child.get());
TS_ASSERT_EQUALS(body, got);
logger().info("END TEST: %s", __FUNCTION__);
}