/*
* tests/persist/cog/ValueSaveUTest.cxxtest
*
* Test of save and restore of generic values.
* Ported from tests/persist/sql/multi-driver/ValueSaveUTest.cxxtest
*
* Copyright (C) 2008, 2009, 2017, 2019 Linas Vepstas <linasvepstas@gmail.com>
*
* LICENSE:
* SPDX-License-Identifier: AGPL-3.0-or-later
*
* 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 <cstdio>
#include <opencog/atoms/base/Atom.h>
#include <opencog/atoms/base/Link.h>
#include <opencog/atoms/base/Node.h>
#include <opencog/atoms/atom_types/atom_types.h>
#include <opencog/persist/cog-types/atom_types.h>
#include <opencog/atomspace/AtomSpace.h>
#include <opencog/atoms/value/FloatValue.h>
#include <opencog/atoms/value/LinkValue.h>
#include <opencog/atoms/value/StringValue.h>
#include <opencog/atoms/value/VoidValue.h>
#include "../TestCogServer.h"
#include <opencog/persist/cog-storage/CogStorage.h>
#include <opencog/util/Logger.h>
using namespace opencog;
class ValueSaveUTest : public CxxTest::TestSuite
{
private:
std::string uri;
DECLARE_TEST_COGSERVER
public:
ValueSaveUTest(void)
{
logger().set_level(Logger::INFO);
// logger().set_level(Logger::DEBUG);
logger().set_print_to_stdout_flag(true);
// logger().set_sync_flag(true);
uri = "cog://localhost:16002";
INIT_TEST_COGSERVER(16002);
printf("Started CogServer\n");
}
~ValueSaveUTest()
{
STOP_TEST_COGSERVER
// 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_single_atom_save();
void test_save_restore(bool);
void check_one(ValuePtr, bool);
void test_load_by_type();
void test_link_by_type();
void test_link_by_type_quoted();
void test_incoming();
void test_load_by_key(bool);
};
/*
* This is called once before each test, for each test (!!)
*/
void ValueSaveUTest::setUp(void) {}
void ValueSaveUTest::tearDown(void) {}
// ============================================================
/**
* A simple test case that tests the saving of various values.
* Test passes if the save succeeds; the accuracy of the save
* is not tested (i.e. there's no restore; that's in the next test.
*/
void ValueSaveUTest::test_single_atom_save()
{
logger().info("BEGIN TEST: %s", __FUNCTION__);
AtomSpacePtr as = createAtomSpace();
Handle hsn = as->add_node(COG_STORAGE_NODE, std::string(uri));
StorageNodePtr store = StorageNodeCast(hsn);
store->setValue(as->add_node(PREDICATE_NODE, "*-open-*"), createVoidValue());
TS_ASSERT(store->connected())
Handle key = as->add_node(PREDICATE_NODE, "some pred key");
Handle atom = as->add_node(CONCEPT_NODE, "some node");
// Store the key and the atom, so as to avoid any UUID
// confusions.
store->store_atom(key);
store->store_atom(atom);
store->barrier();
// --------------------
// Now set some values
ValuePtr pvf = createFloatValue(
std::vector<double>({1.12345678901234567, 2.12345678901234567e35,
3.09876543210987654e200}));
atom->setValue(key, pvf);
store->store_atom(atom);
store->barrier();
// --------------------
ValuePtr pvs = createStringValue(
std::vector<std::string>({"aaa", "bb bb bb", "ccc ccc ccc"}));
atom->setValue(key, pvs);
store->store_atom(atom);
store->barrier();
// --------------------
ValuePtr pvl = createLinkValue(
std::vector<ValuePtr>({pvf, pvs}));
atom->setValue(key, pvl);
store->store_atom(atom);
store->barrier();
// --------------------
ValuePtr pvl2 = createLinkValue(
std::vector<ValuePtr>({pvl, pvl, pvf, pvs}));
atom->setValue(key, pvl2);
store->store_atom(atom);
store->barrier();
store->setValue(as->add_node(PREDICATE_NODE, "*-close-*"), createVoidValue());
as = nullptr;
logger().info("END TEST: %s", __FUNCTION__);
}
// ============================================================
/**
* Similar to above, but attempts to verify that the saved
* values are correct.
*/
void ValueSaveUTest::check_one(ValuePtr pap, bool fetchkey)
{
Handle bkey(createNode(PREDICATE_NODE, "some pred key"));
Handle batom(createNode(CONCEPT_NODE, "some node"));
// ------
// First, save the value
AtomSpacePtr as = createAtomSpace();
Handle hsn = as->add_node(COG_STORAGE_NODE, std::string(uri));
StorageNodePtr store = StorageNodeCast(hsn);
store->setValue(as->add_node(PREDICATE_NODE, "*-open-*"), createVoidValue());
TS_ASSERT(store->connected())
Handle key = store->fetch_atom(bkey);
Handle atom = store->fetch_atom(batom);
printf ("Setup atom %s\n", atom->to_string().c_str());
printf ("Vals %s\n", atom->valuesToString().c_str());
atom->setValue(key, pap);
store->store_atom(atom);
store->barrier();
printf ("Stored atom %s\n", atom->to_string().c_str());
printf ("Stored vals %s\n", atom->valuesToString().c_str());
as = nullptr;
// ---------------------------------
// Now, fetch the value and compare.
as = createAtomSpace();
hsn = as->add_node(COG_STORAGE_NODE, std::string(uri));
store = StorageNodeCast(hsn);
store->setValue(as->add_node(PREDICATE_NODE, "*-open-*"), createVoidValue());
TS_ASSERT(store->connected())
// Storage uses a different code path if the key is not yet
// known when the values are fetched. Test this code path.
if (fetchkey) key = store->fetch_atom(bkey);
atom = store->fetch_atom(batom);
printf("Got atom %s\n", atom->to_string().c_str());
printf("Got vals %s\n", atom->valuesToString().c_str());
ValuePtr fap = atom->getValue(key);
printf("Expecting %s\n", pap->to_string().c_str());
TS_ASSERT(*pap == *fap);
as = nullptr;
}
void ValueSaveUTest::test_save_restore(bool fkey)
{
logger().info("BEGIN TEST: %s", __FUNCTION__);
AtomSpacePtr as = createAtomSpace();
Handle hsn = as->add_node(COG_STORAGE_NODE, std::string(uri));
StorageNodePtr store = StorageNodeCast(hsn);
store->setValue(as->add_node(PREDICATE_NODE, "*-open-*"), createVoidValue());
TS_ASSERT(store->connected())
Handle key = as->add_node(PREDICATE_NODE, "some pred key");
Handle atom = as->add_node(CONCEPT_NODE, "some node");
// Store the key and the atom, so as to avoid any UUID
// confusions.
store->store_atom(key);
store->store_atom(atom);
store->barrier();
// --------------------
// Now set some values
ValuePtr pvf = createFloatValue(
std::vector<double>({1.6543210987654321, 2.67890123456789012e-35,
3.2109876543210987e-200}));
check_one(pvf, fkey);
// --------------------
ValuePtr pvs = createStringValue(
std::vector<std::string>({"aaa", "bb bb bb", "ccc ccc ccc"}));
check_one(pvs, fkey);
// --------------------
ValuePtr pvl = createLinkValue(
std::vector<ValuePtr>({pvf, pvs}));
check_one(pvl, fkey);
// --------------------
ValuePtr pvl2 = createLinkValue(
std::vector<ValuePtr>({pvl, pvl, pvf, pvs}));
check_one(pvl2, fkey);
::kill_data(store.get(), _test_asp.get());
as = nullptr;
logger().info("END TEST: %s", __FUNCTION__);
}
// ============================================================
// Test the fetch_all_atoms_of_type() method in the atomspace.
// The fetch should restore the truth values, and the other values,
// as well. This tests the fetching of nodes.
void ValueSaveUTest::test_load_by_type()
{
logger().info("BEGIN TEST: %s", __FUNCTION__);
AtomSpacePtr as = createAtomSpace();
Handle hsn = as->add_node(COG_STORAGE_NODE, std::string(uri));
StorageNodePtr store = StorageNodeCast(hsn);
store->setValue(as->add_node(PREDICATE_NODE, "*-open-*"), createVoidValue());
TS_ASSERT(store->connected())
// Clear out left-over junk, just in case.
::kill_data(store.get(), _test_asp.get());
Handle key = as->add_node(PREDICATE_NODE, "some pred key");
Handle af = as->add_node(CONCEPT_NODE, "float node");
Handle at = as->add_node(CONCEPT_NODE, "string node");
Handle al = as->add_node(CONCEPT_NODE, "link depth-1 node");
Handle av = as->add_node(CONCEPT_NODE, "link depth-2 node");
// --------------------
// Now set some values
ValuePtr pvf = createFloatValue(
std::vector<double>({1.1098765432109876, 2.1234567890123456e37,
3.2109876543210987e-250}));
af->setValue(key, pvf);
ValuePtr tf(createFloatValue(std::vector<double>({0.11, 100})));
af->setValue(truth_key(), tf);
// --------------------
ValuePtr pvt = createStringValue(
std::vector<std::string>({"aaa", "bb bb bb", "ccc ccc ccc"}));
at->setValue(key, pvt);
ValuePtr tt(createFloatValue(std::vector<double>({0.22, 200})));
at->setValue(truth_key(), tt);
// --------------------
ValuePtr pvl = createLinkValue(
std::vector<ValuePtr>({pvf, pvt}));
al->setValue(key, pvl);
ValuePtr tl(createFloatValue(std::vector<double>({0.33, 300})));
al->setValue(truth_key(), tl);
// --------------------
ValuePtr pvv = createLinkValue(
std::vector<ValuePtr>({pvl, pvl, pvf, pvt}));
av->setValue(key, pvv);
ValuePtr tv(createFloatValue(std::vector<double>({0.44, 400})));
av->setValue(truth_key(), tv);
// --------------------
// Save, and close things down.
store->store_atom(af);
store->store_atom(at);
store->store_atom(al);
store->store_atom(av);
store->barrier();
as = nullptr;
// --------------------
// Start it up again.
as = createAtomSpace();
hsn = as->add_node(COG_STORAGE_NODE, std::string(uri));
store = StorageNodeCast(hsn);
store->setValue(as->add_node(PREDICATE_NODE, "*-open-*"), createVoidValue());
TS_ASSERT(store->connected())
// --------------------
// Fetch by type. This is what we are testing.
store->fetch_all_atoms_of_type(CONCEPT_NODE);
store->barrier();
// Nine: 4 ConceptNodes, the PredicateNode "*-TruthValueKey-*",
// PredicateNode "some pred key", PredicateNode "*-IsKeyFlag-*",
// the CogStorageNode, and PredicateNode "*-open-*"
// -- the preds show up when the attached values are fetched.
printf ("fetched %lu atoms, expecting 9\n", as->get_size());
// printf("contents=%s\n", as->to_string().c_str());
TSM_ASSERT("Wrong number of Atoms fetched!", as->get_size() == 9);
Handle gkey = as->add_node(PREDICATE_NODE, "some pred key");
Handle gaf = as->add_node(CONCEPT_NODE, "float node");
Handle gat = as->add_node(CONCEPT_NODE, "string node");
Handle gal = as->add_node(CONCEPT_NODE, "link depth-1 node");
Handle gav = as->add_node(CONCEPT_NODE, "link depth-2 node");
TS_ASSERT(*gaf == *af);
TS_ASSERT(*gat == *at);
TS_ASSERT(*gal == *al);
TS_ASSERT(*gav == *av);
ValuePtr gtf = gaf->getValue(truth_key());
ValuePtr gtt = gat->getValue(truth_key());
ValuePtr gtl = gal->getValue(truth_key());
ValuePtr gtv = gav->getValue(truth_key());
printf("Wanted: %s\n", tf->to_string().c_str());
printf("Got: %s\n", gtf->to_string().c_str());
TS_ASSERT(*gtf == *tf);
TS_ASSERT(*gtt == *tt);
TS_ASSERT(*gtl == *tl);
TS_ASSERT(*gtv == *tv);
ValuePtr gpf = gaf->getValue(gkey);
ValuePtr gpt = gat->getValue(gkey);
ValuePtr gpl = gal->getValue(gkey);
ValuePtr gpv = gav->getValue(gkey);
TS_ASSERT(*gpf == *pvf);
TS_ASSERT(*gpt == *pvt);
TS_ASSERT(*gpl == *pvl);
TS_ASSERT(*gpv == *pvv);
// --------------------
as = nullptr;
logger().info("END TEST: %s", __FUNCTION__);
}
// ============================================================
// Test the fetch_all_atoms_of_type() method in the atomspace.
// The fetch should restore the truth values, and the other values,
// as well. This tests the fetching of links. This differs from
// the above, in that the values of the outgoing set should NOT
// be fetched.
void ValueSaveUTest::test_link_by_type()
{
logger().info("BEGIN TEST: %s", __FUNCTION__);
AtomSpacePtr as = createAtomSpace();
Handle hsn = as->add_node(COG_STORAGE_NODE, std::string(uri));
StorageNodePtr store = StorageNodeCast(hsn);
store->setValue(as->add_node(PREDICATE_NODE, "*-open-*"), createVoidValue());
TS_ASSERT(store->connected())
Handle key = as->add_node(PREDICATE_NODE, "some pred key");
Handle af = as->add_node(CONCEPT_NODE, "a float node");
Handle at = as->add_node(CONCEPT_NODE, "a string node");
Handle al = as->add_node(CONCEPT_NODE, "a depth-1 node");
Handle av = as->add_node(CONCEPT_NODE, "a depth-2 node");
Handle bf = as->add_node(CONCEPT_NODE, "b float node");
Handle bt = as->add_node(CONCEPT_NODE, "b string node");
Handle bl = as->add_node(CONCEPT_NODE, "b depth-1 node");
Handle bv = as->add_node(CONCEPT_NODE, "b depth-2 node");
Handle cf = as->add_link(LIST_LINK, {af, bf});
Handle ct = as->add_link(LIST_LINK, {at, bt});
Handle cl = as->add_link(LIST_LINK, {al, bl});
Handle cv = as->add_link(LIST_LINK, {av, bv});
// --------------------
// Now set some values
ValuePtr pvf = createFloatValue(
std::vector<double>({1.1098765432109876, 2.1234567890123456e37,
3.2109876543210987e-250}));
af->setValue(key, pvf);
bf->setValue(key, pvf);
cf->setValue(key, pvf);
ValuePtr tf(createFloatValue(std::vector<double>({0.11, 100})));
af->setValue(truth_key(), tf);
bf->setValue(truth_key(), tf);
cf->setValue(truth_key(), tf);
// --------------------
ValuePtr pvt = createStringValue(
std::vector<std::string>({"aaa", "bb bb bb", "ccc ccc ccc"}));
at->setValue(key, pvt);
bt->setValue(key, pvt);
ct->setValue(key, pvt);
ValuePtr tt(createFloatValue(std::vector<double>({0.22, 200})));
at->setValue(truth_key(), tt);
bt->setValue(truth_key(), tt);
ct->setValue(truth_key(), tt);
// --------------------
ValuePtr pvl = createLinkValue(
std::vector<ValuePtr>({pvf, pvt}));
al->setValue(key, pvl);
bl->setValue(key, pvl);
cl->setValue(key, pvl);
ValuePtr tl(createFloatValue(std::vector<double>({0.33, 300})));
al->setValue(truth_key(), tl);
bl->setValue(truth_key(), tl);
cl->setValue(truth_key(), tl);
// --------------------
ValuePtr pvv = createLinkValue(
std::vector<ValuePtr>({pvl, pvl, pvf, pvt}));
av->setValue(key, pvv);
bv->setValue(key, pvv);
cv->setValue(key, pvv);
ValuePtr tv(createFloatValue(std::vector<double>({0.44, 400})));
av->setValue(truth_key(), tv);
bv->setValue(truth_key(), tv);
cv->setValue(truth_key(), tv);
// --------------------
// Save, and close things down.
// Note that this store will also *recursively* store the
// values on the outgoing atoms, as well.
store->store_atom(cf);
store->store_atom(ct);
store->store_atom(cl);
store->store_atom(cv);
store->barrier();
as = nullptr;
// --------------------
// Start it up again.
as = createAtomSpace();
hsn = as->add_node(COG_STORAGE_NODE, std::string(uri));
store = StorageNodeCast(hsn);
store->setValue(as->add_node(PREDICATE_NODE, "*-open-*"), createVoidValue());
TS_ASSERT(store->connected())
// --------------------
// Fetch by type. This is what we are testing.
Handle gkey = as->add_node(PREDICATE_NODE, "some pred key");
Handle gaf = as->add_node(CONCEPT_NODE, "a float node");
Handle gat = as->add_node(CONCEPT_NODE, "a string node");
Handle gal = as->add_node(CONCEPT_NODE, "a depth-1 node");
Handle gav = as->add_node(CONCEPT_NODE, "a depth-2 node");
// Note that the A-nodes above are added *before* the fetch;
// The B-nodes are added after the fetch. In either case,
// there should not be any values fetched for either A or B;
// only the values on the C-links should be fetched.
// +1 for (PredicateNode "*-IsKeyFlag-*"), +1 for *-open-*
store->fetch_all_atoms_of_type(LIST_LINK);
store->barrier();
printf ("fetched %lu atoms, expecting 17\n", as->get_size());
// printf("contents=%s\n", as->to_string().c_str());
TSM_ASSERT("Wrong number of Atoms fetched!", as->get_size() == 17);
Handle gbf = as->add_node(CONCEPT_NODE, "b float node");
Handle gbt = as->add_node(CONCEPT_NODE, "b string node");
Handle gbl = as->add_node(CONCEPT_NODE, "b depth-1 node");
Handle gbv = as->add_node(CONCEPT_NODE, "b depth-2 node");
Handle gcf = as->add_link(LIST_LINK, {gaf, gbf});
Handle gct = as->add_link(LIST_LINK, {gat, gbt});
Handle gcl = as->add_link(LIST_LINK, {gal, gbl});
Handle gcv = as->add_link(LIST_LINK, {gav, gbv});
TS_ASSERT(*gcf == *cf);
TS_ASSERT(*gct == *ct);
TS_ASSERT(*gcl == *cl);
TS_ASSERT(*gcv == *cv);
ValuePtr gtf = gaf->getValue(truth_key());
ValuePtr gtt = gat->getValue(truth_key());
ValuePtr gtl = gal->getValue(truth_key());
ValuePtr gtv = gav->getValue(truth_key());
TS_ASSERT(gtf == nullptr);
TS_ASSERT(gtt == nullptr);
TS_ASSERT(gtl == nullptr);
TS_ASSERT(gtv == nullptr);
gtf = gbf->getValue(truth_key());
gtt = gbt->getValue(truth_key());
gtl = gbl->getValue(truth_key());
gtv = gbv->getValue(truth_key());
TS_ASSERT(gtf == nullptr);
TS_ASSERT(gtt == nullptr);
TS_ASSERT(gtl == nullptr);
TS_ASSERT(gtv == nullptr);
gtf = gcf->getValue(truth_key());
gtt = gct->getValue(truth_key());
gtl = gcl->getValue(truth_key());
gtv = gcv->getValue(truth_key());
TS_ASSERT(*gtf == *tf);
TS_ASSERT(*gtt == *tt);
TS_ASSERT(*gtl == *tl);
TS_ASSERT(*gtv == *tv);
// --------------------
ValuePtr gpf;
ValuePtr gpt;
ValuePtr gpl;
ValuePtr gpv;
try { gpf = gaf->getValue(gkey); } catch(const RuntimeException&) {}
try { gpt = gat->getValue(gkey); } catch(const RuntimeException&) {}
try { gpl = gal->getValue(gkey); } catch(const RuntimeException&) {}
try { gpv = gav->getValue(gkey); } catch(const RuntimeException&) {}
TS_ASSERT(gpf == nullptr);
TS_ASSERT(gpt == nullptr);
TS_ASSERT(gpl == nullptr);
TS_ASSERT(gpv == nullptr);
try { gpf = gbf->getValue(gkey); } catch(const RuntimeException&) {}
try { gpt = gbt->getValue(gkey); } catch(const RuntimeException&) {}
try { gpl = gbl->getValue(gkey); } catch(const RuntimeException&) {}
try { gpv = gbv->getValue(gkey); } catch(const RuntimeException&) {}
TS_ASSERT(gpf == nullptr);
TS_ASSERT(gpt == nullptr);
TS_ASSERT(gpl == nullptr);
TS_ASSERT(gpv == nullptr);
gpf = gcf->getValue(gkey);
gpt = gct->getValue(gkey);
gpl = gcl->getValue(gkey);
gpv = gcv->getValue(gkey);
TS_ASSERT(*gpf == *pvf);
TS_ASSERT(*gpt == *pvt);
TS_ASSERT(*gpl == *pvl);
TS_ASSERT(*gpv == *pvv);
// --------------------
as = nullptr;
logger().info("END TEST: %s", __FUNCTION__);
}
// ============================================================
// Same as test_link_by_type() except that the StringValue
// has some nasties intended to confuse parsing.
void ValueSaveUTest::test_link_by_type_quoted()
{
logger().info("BEGIN TEST: %s", __FUNCTION__);
AtomSpacePtr as = createAtomSpace();
Handle hsn = as->add_node(COG_STORAGE_NODE, std::string(uri));
StorageNodePtr store = StorageNodeCast(hsn);
store->setValue(as->add_node(PREDICATE_NODE, "*-open-*"), createVoidValue());
TS_ASSERT(store->connected())
Handle key = as->add_node(PREDICATE_NODE, "some (\"pred\"))) key");
Handle af = as->add_node(CONCEPT_NODE, "x \"float\" node");
Handle at = as->add_node(CONCEPT_NODE, "x \"string\" node");
Handle al = as->add_node(CONCEPT_NODE, "x \"depth-1\" node");
Handle av = as->add_node(CONCEPT_NODE, "x \"depth-2\" node");
Handle bf = as->add_node(CONCEPT_NODE, "b float node");
Handle bt = as->add_node(CONCEPT_NODE, "b string node");
Handle bl = as->add_node(CONCEPT_NODE, "b depth-1 node");
Handle bv = as->add_node(CONCEPT_NODE, "b depth-2 node");
Handle cf = as->add_link(LIST_LINK, {af, bf});
Handle ct = as->add_link(LIST_LINK, {at, bt});
Handle cl = as->add_link(LIST_LINK, {al, bl});
Handle cv = as->add_link(LIST_LINK, {av, bv});
// --------------------
// Now set some values
ValuePtr pvf = createFloatValue(
std::vector<double>({1.1098765432109876, 2.1234567890123456e37,
3.2109876543210987e-250}));
af->setValue(key, pvf);
bf->setValue(key, pvf);
cf->setValue(key, pvf);
ValuePtr tf(createFloatValue(std::vector<double>({0.11, 100})));
af->setValue(truth_key(), tf);
bf->setValue(truth_key(), tf);
cf->setValue(truth_key(), tf);
// --------------------
ValuePtr pvt = createStringValue(
std::vector<std::string>({"a\"a\"a", "bb) (bb) (bb", "ccc \")(\"ccc))\" ccc"}));
at->setValue(key, pvt);
bt->setValue(key, pvt);
ct->setValue(key, pvt);
ValuePtr tt(createFloatValue(std::vector<double>({0.22, 200})));
at->setValue(truth_key(), tt);
bt->setValue(truth_key(), tt);
ct->setValue(truth_key(), tt);
// --------------------
ValuePtr pvl = createLinkValue(
std::vector<ValuePtr>({pvf, pvt}));
al->setValue(key, pvl);
bl->setValue(key, pvl);
cl->setValue(key, pvl);
ValuePtr tl(createFloatValue(std::vector<double>({0.33, 300})));
al->setValue(truth_key(), tl);
bl->setValue(truth_key(), tl);
cl->setValue(truth_key(), tl);
// --------------------
ValuePtr pvv = createLinkValue(
std::vector<ValuePtr>({pvl, pvl, pvf, pvt}));
av->setValue(key, pvv);
bv->setValue(key, pvv);
cv->setValue(key, pvv);
ValuePtr tv(createFloatValue(std::vector<double>({0.44, 400})));
av->setValue(truth_key(), tv);
bv->setValue(truth_key(), tv);
cv->setValue(truth_key(), tv);
// --------------------
// Save, and close things down.
// Note that this store will also *recursively* store the
// values on the outgoing atoms, as well.
store->store_atom(cf);
store->store_atom(ct);
store->store_atom(cl);
store->store_atom(cv);
store->barrier();
as = nullptr;
// --------------------
// Start it up again.
as = createAtomSpace();
hsn = as->add_node(COG_STORAGE_NODE, std::string(uri));
store = StorageNodeCast(hsn);
store->setValue(as->add_node(PREDICATE_NODE, "*-open-*"), createVoidValue());
TS_ASSERT(store->connected())
// --------------------
// Fetch by type. This is what we are testing.
Handle gkey = as->add_node(PREDICATE_NODE, "some (\"pred\"))) key");
Handle gaf = as->add_node(CONCEPT_NODE, "x \"float\" node");
Handle gat = as->add_node(CONCEPT_NODE, "x \"string\" node");
Handle gal = as->add_node(CONCEPT_NODE, "x \"depth-1\" node");
Handle gav = as->add_node(CONCEPT_NODE, "x \"depth-2\" node");
// Note that the A-nodes above are added *before* the fetch;
// The B-nodes are added after the fetch. In either case,
// there should not be any values fetched for either A or B;
// only the values on the C-links should be fetched.
store->fetch_all_atoms_of_type(LIST_LINK);
store->barrier();
// We created 9 new atoms above, so expect 17 from before plus 9
// (+1 for *-IsKeyFlag-*, +1 for *-open-*)
printf ("fetched %lu atoms, expecting 26\n", as->get_size());
TSM_ASSERT("Wrong number of Atoms fetched!", as->get_size() == 26);
Handle gbf = as->add_node(CONCEPT_NODE, "b float node");
Handle gbt = as->add_node(CONCEPT_NODE, "b string node");
Handle gbl = as->add_node(CONCEPT_NODE, "b depth-1 node");
Handle gbv = as->add_node(CONCEPT_NODE, "b depth-2 node");
Handle gcf = as->add_link(LIST_LINK, {gaf, gbf});
Handle gct = as->add_link(LIST_LINK, {gat, gbt});
Handle gcl = as->add_link(LIST_LINK, {gal, gbl});
Handle gcv = as->add_link(LIST_LINK, {gav, gbv});
TS_ASSERT(*gcf == *cf);
TS_ASSERT(*gct == *ct);
TS_ASSERT(*gcl == *cl);
TS_ASSERT(*gcv == *cv);
ValuePtr gtf = gaf->getValue(truth_key());
ValuePtr gtt = gat->getValue(truth_key());
ValuePtr gtl = gal->getValue(truth_key());
ValuePtr gtv = gav->getValue(truth_key());
TS_ASSERT(gtf == nullptr);
TS_ASSERT(gtt == nullptr);
TS_ASSERT(gtl == nullptr);
TS_ASSERT(gtv == nullptr);
gtf = gbf->getValue(truth_key());
gtt = gbt->getValue(truth_key());
gtl = gbl->getValue(truth_key());
gtv = gbv->getValue(truth_key());
TS_ASSERT(gtf == nullptr);
TS_ASSERT(gtt == nullptr);
TS_ASSERT(gtl == nullptr);
TS_ASSERT(gtv == nullptr);
gtf = gcf->getValue(truth_key());
gtt = gct->getValue(truth_key());
gtl = gcl->getValue(truth_key());
gtv = gcv->getValue(truth_key());
printf("Expecting %s\n", tf->to_string().c_str());
printf("Got %s\n", gtf->to_string().c_str());
TS_ASSERT(*gtf == *tf);
TS_ASSERT(*gtt == *tt);
TS_ASSERT(*gtl == *tl);
TS_ASSERT(*gtv == *tv);
// --------------------
ValuePtr gpf;
ValuePtr gpt;
ValuePtr gpl;
ValuePtr gpv;
try { gpf = gaf->getValue(gkey); } catch(const RuntimeException&) {}
try { gpt = gat->getValue(gkey); } catch(const RuntimeException&) {}
try { gpl = gal->getValue(gkey); } catch(const RuntimeException&) {}
try { gpv = gav->getValue(gkey); } catch(const RuntimeException&) {}
TS_ASSERT(gpf == nullptr);
TS_ASSERT(gpt == nullptr);
TS_ASSERT(gpl == nullptr);
TS_ASSERT(gpv == nullptr);
try { gpf = gbf->getValue(gkey); } catch(const RuntimeException&) {}
try { gpt = gbt->getValue(gkey); } catch(const RuntimeException&) {}
try { gpl = gbl->getValue(gkey); } catch(const RuntimeException&) {}
try { gpv = gbv->getValue(gkey); } catch(const RuntimeException&) {}
TS_ASSERT(gpf == nullptr);
TS_ASSERT(gpt == nullptr);
TS_ASSERT(gpl == nullptr);
TS_ASSERT(gpv == nullptr);
gpf = gcf->getValue(gkey);
gpt = gct->getValue(gkey);
gpl = gcl->getValue(gkey);
gpv = gcv->getValue(gkey);
TS_ASSERT(*gpf == *pvf);
TS_ASSERT(*gpt == *pvt);
TS_ASSERT(*gpl == *pvl);
TS_ASSERT(*gpv == *pvv);
// --------------------
as = nullptr;
logger().info("END TEST: %s", __FUNCTION__);
}
// ============================================================
// Test the fetch_incoming_set() method in the atomspace.
// The fetch should restore the truth values, and the other values,
// as well, but only on the incoming set!
void ValueSaveUTest::test_incoming()
{
logger().info("BEGIN TEST: %s", __FUNCTION__);
AtomSpacePtr as = createAtomSpace();
Handle hsn = as->add_node(COG_STORAGE_NODE, std::string(uri));
StorageNodePtr store = StorageNodeCast(hsn);
store->setValue(as->add_node(PREDICATE_NODE, "*-open-*"), createVoidValue());
TS_ASSERT(store->connected())
Handle key = as->add_node(PREDICATE_NODE, "some pred key");
Handle af = as->add_node(CONCEPT_NODE, "a float node");
Handle at = as->add_node(CONCEPT_NODE, "a string node");
Handle al = as->add_node(CONCEPT_NODE, "a depth-1 node");
Handle av = as->add_node(CONCEPT_NODE, "a depth-2 node");
Handle bf = as->add_node(CONCEPT_NODE, "b float node");
Handle bt = as->add_node(CONCEPT_NODE, "b string node");
Handle bl = as->add_node(CONCEPT_NODE, "b depth-1 node");
Handle bv = as->add_node(CONCEPT_NODE, "b depth-2 node");
Handle cf = as->add_link(LIST_LINK, {af, bf});
Handle ct = as->add_link(LIST_LINK, {at, bt});
Handle cl = as->add_link(LIST_LINK, {al, bl});
Handle cv = as->add_link(LIST_LINK, {av, bv});
// --------------------
// Now set some values
ValuePtr pvf = createFloatValue(
std::vector<double>({1.1098765432109876, 2.1234567890123456e-37,
3.2109876543210987e250}));
af->setValue(key, pvf);
bf->setValue(key, pvf);
cf->setValue(key, pvf);
ValuePtr tf(createFloatValue(std::vector<double>({0.11, 100})));
af->setValue(truth_key(), tf);
bf->setValue(truth_key(), tf);
cf->setValue(truth_key(), tf);
// --------------------
ValuePtr pvt = createStringValue(
std::vector<std::string>({"aaa", "bb bb bb", "ccc ccc ccc"}));
at->setValue(key, pvt);
bt->setValue(key, pvt);
ct->setValue(key, pvt);
ValuePtr tt(createFloatValue(std::vector<double>({0.22, 200})));
at->setValue(truth_key(), tt);
bt->setValue(truth_key(), tt);
ct->setValue(truth_key(), tt);
// --------------------
ValuePtr pvl = createLinkValue(
std::vector<ValuePtr>({pvf, pvt}));
al->setValue(key, pvl);
bl->setValue(key, pvl);
cl->setValue(key, pvl);
ValuePtr tl(createFloatValue(std::vector<double>({0.33, 300})));
al->setValue(truth_key(), tl);
bl->setValue(truth_key(), tl);
cl->setValue(truth_key(), tl);
// --------------------
ValuePtr pvv = createLinkValue(
std::vector<ValuePtr>({pvl, pvl, pvf, pvt}));
av->setValue(key, pvv);
bv->setValue(key, pvv);
cv->setValue(key, pvv);
ValuePtr tv(createFloatValue(std::vector<double>({0.44, 400})));
av->setValue(truth_key(), tv);
bv->setValue(truth_key(), tv);
cv->setValue(truth_key(), tv);
// --------------------
// Save, and close things down.
// Note that this store will also *recursively* store the
// values on the outgoing atoms, as well.
store->store_atom(cf);
store->store_atom(ct);
store->store_atom(cl);
store->store_atom(cv);
store->barrier();
as = nullptr;
// --------------------
// Start it up again.
as = createAtomSpace();
hsn = as->add_node(COG_STORAGE_NODE, std::string(uri));
store = StorageNodeCast(hsn);
store->setValue(as->add_node(PREDICATE_NODE, "*-open-*"), createVoidValue());
TS_ASSERT(store->connected())
// --------------------
// Fetch incoming set. This is what we are testing.
Handle gkey = as->add_node(PREDICATE_NODE, "some pred key");
Handle gaf = as->add_node(CONCEPT_NODE, "a float node");
Handle gat = as->add_node(CONCEPT_NODE, "a string node");
Handle gal = as->add_node(CONCEPT_NODE, "a depth-1 node");
Handle gav = as->add_node(CONCEPT_NODE, "a depth-2 node");
// Note that the A-nodes above are added *before* the fetch;
// The B-nodes are added after the fetch. In either case,
// there should not be any values fetched for either A or B;
// only the values on the C-links should be fetched.
store->fetch_incoming_set(gaf, false);
store->fetch_incoming_set(gat, false);
store->fetch_incoming_set(gal, false);
store->fetch_incoming_set(gav, false);
store->barrier();
// +1 for *-IsKeyFlag-*, +1 for *-open-*
TSM_ASSERT("Wrong number of Atoms fetched!", as->get_size() == 17);
Handle gbf = as->add_node(CONCEPT_NODE, "b float node");
Handle gbt = as->add_node(CONCEPT_NODE, "b string node");
Handle gbl = as->add_node(CONCEPT_NODE, "b depth-1 node");
Handle gbv = as->add_node(CONCEPT_NODE, "b depth-2 node");
Handle gcf = as->add_link(LIST_LINK, {gaf, gbf});
Handle gct = as->add_link(LIST_LINK, {gat, gbt});
Handle gcl = as->add_link(LIST_LINK, {gal, gbl});
Handle gcv = as->add_link(LIST_LINK, {gav, gbv});
TS_ASSERT(*gcf == *cf);
TS_ASSERT(*gct == *ct);
TS_ASSERT(*gcl == *cl);
TS_ASSERT(*gcv == *cv);
ValuePtr gtf = gaf->getValue(truth_key());
ValuePtr gtt = gat->getValue(truth_key());
ValuePtr gtl = gal->getValue(truth_key());
ValuePtr gtv = gav->getValue(truth_key());
TS_ASSERT(gtf == nullptr);
TS_ASSERT(gtt == nullptr);
TS_ASSERT(gtl == nullptr);
TS_ASSERT(gtv == nullptr);
gtf = gbf->getValue(truth_key());
gtt = gbt->getValue(truth_key());
gtl = gbl->getValue(truth_key());
gtv = gbv->getValue(truth_key());
TS_ASSERT(gtf == nullptr);
TS_ASSERT(gtt == nullptr);
TS_ASSERT(gtl == nullptr);
TS_ASSERT(gtv == nullptr);
gtf = gcf->getValue(truth_key());
gtt = gct->getValue(truth_key());
gtl = gcl->getValue(truth_key());
gtv = gcv->getValue(truth_key());
TS_ASSERT(*gtf == *tf);
TS_ASSERT(*gtt == *tt);
TS_ASSERT(*gtl == *tl);
TS_ASSERT(*gtv == *tv);
// --------------------
ValuePtr gpf;
ValuePtr gpt;
ValuePtr gpl;
ValuePtr gpv;
try { gpf = gaf->getValue(gkey); } catch(const RuntimeException&) {}
try { gpt = gat->getValue(gkey); } catch(const RuntimeException&) {}
try { gpl = gal->getValue(gkey); } catch(const RuntimeException&) {}
try { gpv = gav->getValue(gkey); } catch(const RuntimeException&) {}
TS_ASSERT(gpf == nullptr);
TS_ASSERT(gpt == nullptr);
TS_ASSERT(gpl == nullptr);
TS_ASSERT(gpv == nullptr);
try { gpf = gbf->getValue(gkey); } catch(const RuntimeException&) {}
try { gpt = gbt->getValue(gkey); } catch(const RuntimeException&) {}
try { gpl = gbl->getValue(gkey); } catch(const RuntimeException&) {}
try { gpv = gbv->getValue(gkey); } catch(const RuntimeException&) {}
TS_ASSERT(gpf == nullptr);
TS_ASSERT(gpt == nullptr);
TS_ASSERT(gpl == nullptr);
TS_ASSERT(gpv == nullptr);
gpf = gcf->getValue(gkey);
gpt = gct->getValue(gkey);
gpl = gcl->getValue(gkey);
gpv = gcv->getValue(gkey);
TS_ASSERT(*gpf == *pvf);
TS_ASSERT(*gpt == *pvt);
TS_ASSERT(*gpl == *pvl);
TS_ASSERT(*gpv == *pvv);
// --------------------
as = nullptr;
logger().info("END TEST: %s", __FUNCTION__);
}
/* ============================= END OF FILE ================= */