OverviewFilesCommitsIssuesDocsReleasesPeers

opencog-atomspace / tests / atoms / grant / DefineLinkUTest.cxxtest

127 lines · cxxtest ref:
/*
 * 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__);
}