/*
* 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__);
}