OverviewFilesCommitsIssuesDocsReleasesPeers

opencog-atomspace / tests / query / FiniteStateMachineUTest.cxxtest

155 lines · cxxtest ref:
/*
 * tests/query/FiniteStateMachineUTest.cxxtest
 *
 * Copyright (C) 2015 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/guile/SchemeEval.h>
#include <opencog/atomspace/AtomSpace.h>
#include <opencog/util/Logger.h>

using namespace opencog;

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

public:
	FiniteStateMachineUTest(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 "\")");

	}

	~FiniteStateMachineUTest()
	{
		// 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);

	Handle get_state(Handle);
	void do_test_basic(void);
	void test_basic_rw(void);
	void test_basic_overlay(void);
};

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

void FiniteStateMachineUTest::setUp(void)
{
	as->clear();
	eval->eval("(load-from-path \"tests/query/finite-state-machine.scm\")");
}

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

Handle FiniteStateMachineUTest::get_state(Handle set_link)
{
	Handle and_link = set_link->getOutgoingAtom(0);
	Handle list_link = and_link->getOutgoingAtom(0);
	return list_link->getOutgoingAtom(1);
}

/*
 * FiniteStateMachine most basic unit test.
 */
void FiniteStateMachineUTest::do_test_basic(void)
{
	// We expect the incoming set to have an arity of 3: once for the
	// real, actual state, and once for each of the two VariableNodes.
	Handle istate = eval->eval_h("(AnchorNode \"Current State\")");
	TS_ASSERT_EQUALS(3, istate->getIncomingSetSize());

	// Set up the three possible state handles.
	// (Excluding the initial state).
	HandleSeq states;
	Handle green = eval->eval_h("(ConceptNode \"green\")");
	states.push_back(green);
	Handle yellow = eval->eval_h("(ConceptNode \"yellow\")");
	states.push_back(yellow);
	Handle red = eval->eval_h("(ConceptNode \"red\")");
	states.push_back(red);

	// Take one step of the finite state machine.
	printf("Going to take one step\n");
	Handle first = eval->eval_h("(cog-execute! (CollectionOf take-one-step))");
	printf("First state found:\n%s\n", first->to_short_string().c_str());
	TS_ASSERT_EQUALS(1, getarity(first));

	// After the first step, we expect a green light.
	TS_ASSERT_EQUALS(green, get_state(first));

	// We expect the incoming set to have an arity of 3: once for the
	// real, actual state, and once for each of the two VariableNodes.
	Handle state = eval->eval_h("(AnchorNode \"Current State\")");
	TS_ASSERT_EQUALS(3, state->getIncomingSetSize());

	for (int i=1; i<21; i++)
	{
		printf("Going to take one step; %d\n", i);
		Handle next = eval->eval_h("(cog-execute! (CollectionOf take-one-step))");
		TS_ASSERT_EQUALS(1, getarity(next));
		TS_ASSERT_EQUALS(states[i%3], get_state(next));
	}
}

void FiniteStateMachineUTest::test_basic_rw(void)
{
	logger().debug("BEGIN TEST: %s", __FUNCTION__);
	do_test_basic();
	logger().debug("END TEST: %s", __FUNCTION__);
}

void FiniteStateMachineUTest::test_basic_overlay(void)
{
	logger().debug("BEGIN TEST: %s", __FUNCTION__);

	// Mark base-space as readonly; create a read-write overlay.
	as->set_read_only();
	AtomSpacePtr save = as;
	as = createAtomSpace(as);
	SchemeEval* seval = eval;
	eval = SchemeEval::get_scheme_evaluator(as);

	// Testing is performed in a write-through mode.
	as->clear_copy_on_write();

	do_test_basic();

	eval = seval;
	as = save;
	as->set_read_write();

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