OverviewFilesCommitsIssuesDocsReleasesPeers

opencog-atomspace / tests / query / ArcanaUTest.cxxtest

244 lines · cxxtest ref:
/*
 * tests/query/ArcanaUTest.cxxtest
 *
 * Copyright (C) 2015,2016 Linas Vepstas
 * 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/atoms/value/BoolValue.h>
#include <opencog/guile/SchemeEval.h>
#include <opencog/util/Logger.h>

using namespace opencog;

class ArcanaUTest: public CxxTest::TestSuite
{
private:
	AtomSpacePtr as;
	SchemeEval* eval;

public:
	ArcanaUTest(void)
	{
		logger().set_level(Logger::DEBUG);
		logger().set_print_to_stdout_flag(true);

		as = createAtomSpace();
		eval = SchemeEval::get_scheme_evaluator(as);
		eval->eval("(add-to-load-path \"" PROJECT_SOURCE_DIR "\")");

		eval->eval("(load-from-path \"tests/query/test_types.scm\")");
	}

	~ArcanaUTest()
	{
		// 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_repeats(void);
	void test_const(void);
	void test_dummy(void);
	void test_bigger_dummy(void);
	void xtest_numeric(void);
};

void ArcanaUTest::tearDown(void)
{
	as->clear();
}

void ArcanaUTest::setUp(void)
{
	as->clear();
}

#define getarity(hand) hand->get_arity()

/*
 * Miscellaneous Arcana
 * This one tests a repeated unit in a clause.
 */
void ArcanaUTest::test_repeats(void)
{
	logger().debug("BEGIN TEST: %s", __FUNCTION__);

	eval->eval("(load-from-path \"tests/query/arcana-repeat.scm\")");

	Handle same = eval->eval_h("(cog-execute! (CollectionOf (repeat-same)))");
	printf("same, num solutions=%zu\n", getarity(same));
	TS_ASSERT_EQUALS(1, getarity(same));

	Handle diff = eval->eval_h("(cog-execute! (CollectionOf (repeat-different)))");

	// Either one or two solutions are acceptable, as long as the
	// two are identical. One solution is preferred, but seems
	// not possible with the current algo.
	const HandleSeq& oset = diff->getOutgoingSet();
	size_t nsol = oset.size();
	bool pass = false;
	if (1 == nsol) pass = true;
	if (2 == nsol and oset[0] == oset[1]) pass = true;
	printf("diff, num solutions=%zu\n", nsol);
	if (1 <= nsol)
		printf("Solution 1:\n%s\n", oset[0]->to_short_string().c_str());
	if (2 == nsol)
		printf("Solution 2:\n%s\n", oset[0]->to_short_string().c_str());
	TS_ASSERT_EQUALS(true, pass);

	Handle d3d = eval->eval_h("(cog-execute! (CollectionOf (repeat-diff-thrice)))");
	printf("d3d, num solutions=%zu\n", getarity(d3d));
	TS_ASSERT(1 <= getarity(d3d));
	TS_ASSERT(getarity(d3d) <= 3);

	Handle thrice = eval->eval_h("(cog-execute! (CollectionOf (repeat-thrice)))");
	printf("thrice, num solutions=%zu\n", getarity(thrice));
	TS_ASSERT_EQUALS(1, getarity(thrice));

	Handle once = eval->eval_h("(cog-execute! (CollectionOf (repeat-once)))");
	printf("once, num solutions=%zu\n", getarity(once));
	TS_ASSERT_EQUALS(1, getarity(once));

	// ----
	logger().debug("END TEST: %s", __FUNCTION__);
}

/*
 * Miscellaneous Arcana
 * This one allows constant terms to trigger a match.
 */
void ArcanaUTest::test_const(void)
{
	logger().debug("BEGIN TEST: %s", __FUNCTION__);

	eval->eval("(load-from-path \"tests/query/arcana-const.scm\")");

	// ----
	Handle marconi = eval->eval_h("marconi");

	Handle answer = eval->eval_h("(cog-execute! (CollectionOf who))");
	printf("radio=%s\n", answer->to_string().c_str());

	TS_ASSERT_EQUALS(1, getarity(answer));
	Handle devel = answer->getOutgoingAtom(0);

	TS_ASSERT_EQUALS(marconi, devel);

	// ----
	// Test DefinedSchemaNode as an answer.
	Handle defans = eval->eval_h("(cog-execute! (CollectionOf whodfn))");
	printf("defined radio=%s\n", defans->to_string().c_str());

	TS_ASSERT_EQUALS(1, getarity(defans));
	TS_ASSERT_EQUALS(defans, answer);

	// ----
	logger().debug("END TEST: %s", __FUNCTION__);
}

/*
 * Miscellaneous Arcana
 * This one tests addition of mandatory dummy terms.
 */
void ArcanaUTest::test_dummy(void)
{
	logger().debug("BEGIN TEST: %s", __FUNCTION__);

	eval->eval("(load-from-path \"tests/query/arcana-dummy.scm\")");

	// ----
	Handle answer = eval->eval_h("(cog-execute! (CollectionOf dummy))");
	printf("dummy=%s\n", answer->to_string().c_str());

	TS_ASSERT_EQUALS(SET_LINK, answer->get_type());
	TS_ASSERT_EQUALS(1, getarity(answer));
	Handle num = answer->getOutgoingAtom(0);

	Handle fourtwo = eval->eval_h("(Number 42)");
	TS_ASSERT_EQUALS(num, fourtwo);

	// ----
	logger().debug("END TEST: %s", __FUNCTION__);
}

/*
 * Miscellaneous Arcana
 * This one tests addition of complicated dummy terms.
 */
void ArcanaUTest::test_bigger_dummy(void)
{
	logger().debug("BEGIN TEST: %s", __FUNCTION__);

	eval->eval("(load-from-path \"tests/query/arcana-bigger-dummy.scm\")");

	// ----
	Handle answer = eval->eval_h("(cog-execute! (CollectionOf bigger-dummy))");
	printf("dummy=%s\n", answer->to_string().c_str());

	TS_ASSERT_EQUALS(SET_LINK, answer->get_type());
	TS_ASSERT_EQUALS(1, getarity(answer));

	Handle stfu = eval->eval_h("stfu");
	TS_ASSERT_EQUALS(answer, stfu);

	// ----
	logger().debug("END TEST: %s", __FUNCTION__);
}

/*
 * Miscellaneous Arcana
 * This one tests a "typical" behavior tree node.
 * XXX Disabled for now, because this used to depend on the Instantiator
 * to set the current time, and we don't want to use the Instantiator
 * any longer. So this needs some alternative implementatation. Since
 * StateLink is disused, we will let this lie fallow, for now.
 */
void ArcanaUTest::xtest_numeric(void)
{
	logger().debug("BEGIN TEST: %s", __FUNCTION__);

	eval->eval("(load-from-path \"tests/query/arcana-numeric.scm\")");

	// ----
	Handle sl = eval->eval_h("(StateLink"
	                         "   (SchemaNode \"start-interaction-timestamp\")"
	                         "   (LinkSignature (Type 'Number) (TimeLink)))");
	sl->execute(as.get());
  
	ValuePtr too_soon = eval->eval_v(
		"(cog-execute! (DefinedPredicateNode \"Time to change expression\"))");
	BoolValuePtr bvp_soon = BoolValueCast(too_soon);

	TS_ASSERT(not bvp_soon->get_bit(0));

	// The TV needs to change after 2 seconds.... sleep 4 to be safe.
	sleep(4);
	ValuePtr too_late = eval->eval_v(
		"(cog-execute! (DefinedPredicateNode \"Time to change expression\"))");
	BoolValuePtr bvp_late = BoolValueCast(too_late);
	TS_ASSERT(bvp_late->get_bit(0));

	// ----
	logger().debug("END TEST: %s", __FUNCTION__);
}