293 lines
8.6 KiB
C++
293 lines
8.6 KiB
C++
|
|
/*
|
||
|
|
DefsRegistryImpl(Test) - verifying correct behaviour of the defaults registry
|
||
|
|
|
||
|
|
Copyright (C) Lumiera.org
|
||
|
|
2008, Hermann Vosseler <Ichthyostega@web.de>
|
||
|
|
|
||
|
|
This program is free software; you can redistribute it and/or
|
||
|
|
modify it under the terms of the GNU General Public License as
|
||
|
|
published by the Free Software Foundation; either version 2 of
|
||
|
|
the License, or (at your option) any later version.
|
||
|
|
|
||
|
|
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 General Public License
|
||
|
|
along with this program; if not, write to the Free Software
|
||
|
|
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||
|
|
|
||
|
|
* *****************************************************/
|
||
|
|
|
||
|
|
|
||
|
|
#include "lib/test/run.hpp"
|
||
|
|
#include "lib/util.hpp"
|
||
|
|
|
||
|
|
#include "proc/mobject/session/defs-registry.hpp"
|
||
|
|
#include "lib/factory.hpp"
|
||
|
|
#include "lib/query.hpp"
|
||
|
|
#include "lib/p.hpp"
|
||
|
|
|
||
|
|
#include "../lib/query/querydiagnostics.hpp"
|
||
|
|
|
||
|
|
#include <boost/scoped_ptr.hpp>
|
||
|
|
#include <boost/format.hpp>
|
||
|
|
#include <map>
|
||
|
|
|
||
|
|
using lumiera::P;
|
||
|
|
using lumiera::Query;
|
||
|
|
using lumiera::query::test::garbage_query;
|
||
|
|
using util::isnil;
|
||
|
|
|
||
|
|
using boost::scoped_ptr;
|
||
|
|
using boost::format;
|
||
|
|
using std::string;
|
||
|
|
using std::rand;
|
||
|
|
using std::map;
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
namespace mobject {
|
||
|
|
namespace session {
|
||
|
|
namespace test {
|
||
|
|
|
||
|
|
format typePatt ("Dummy<%2i>");
|
||
|
|
format instancePatt ("obj_%s_%i");
|
||
|
|
format predicatePatt ("%s_%2i( %s )");
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
/** create a random new ID */
|
||
|
|
string
|
||
|
|
newID (string prefix)
|
||
|
|
{
|
||
|
|
return str (instancePatt % prefix % rand());
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
/** template for generating some different test types */
|
||
|
|
template<int I>
|
||
|
|
struct Dummy
|
||
|
|
{
|
||
|
|
static string name;
|
||
|
|
string instanceID;
|
||
|
|
operator string () const { return instanceID; }
|
||
|
|
bool operator== (const Dummy& odu) const { return this == &odu; }
|
||
|
|
|
||
|
|
|
||
|
|
Dummy () : instanceID (newID (name)) {}
|
||
|
|
};
|
||
|
|
|
||
|
|
template<int I>
|
||
|
|
string Dummy<I>::name = str (typePatt % I);
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
/************************************************************************
|
||
|
|
* @test build an registry table (just for this test) configured for
|
||
|
|
* some artificial test Types. Register some entries and verify
|
||
|
|
* the intended behaviour of the storage structure.
|
||
|
|
* @see DefsManagerImpl_test for checking the implementation details
|
||
|
|
* in the actual context used in Lumiera.
|
||
|
|
*/
|
||
|
|
class DefsRegistryImpl_test : public Test
|
||
|
|
{
|
||
|
|
scoped_ptr<DefsRegistry> reg_;
|
||
|
|
|
||
|
|
typedef lumiera::P<Dummy<13> > O;
|
||
|
|
typedef lumiera::P<Dummy<23> > P;
|
||
|
|
|
||
|
|
typedef Query<Dummy<13> > Q13;
|
||
|
|
typedef Query<Dummy<23> > Q23;
|
||
|
|
|
||
|
|
typedef DefsRegistry::Iter<Dummy<13> > Iter13;
|
||
|
|
typedef DefsRegistry::Iter<Dummy<23> > Iter23;
|
||
|
|
|
||
|
|
|
||
|
|
// fabricating Objects wrapped into smart-ptrs
|
||
|
|
lib::factory::RefcountFac<Dummy<13> > oFac;
|
||
|
|
lib::factory::RefcountFac<Dummy<23> > pFac;
|
||
|
|
|
||
|
|
O o1, o2, o3;
|
||
|
|
Q13 q1, q2, q3, q4, q5;
|
||
|
|
map<Q23, P> ps;
|
||
|
|
|
||
|
|
public:
|
||
|
|
DefsRegistryImpl_test ()
|
||
|
|
: o1 (oFac()), o2 (oFac()), o3 (oFac()),
|
||
|
|
q1 (garbage_query (1)),
|
||
|
|
q2 (garbage_query (2)),
|
||
|
|
q3 (garbage_query (3)),
|
||
|
|
q4 (garbage_query (4)),
|
||
|
|
q5 (garbage_query (5))
|
||
|
|
{ }
|
||
|
|
|
||
|
|
|
||
|
|
virtual void
|
||
|
|
run (Arg)
|
||
|
|
{
|
||
|
|
this->reg_.reset (new DefsRegistry);
|
||
|
|
|
||
|
|
fill_table ();
|
||
|
|
check_query ();
|
||
|
|
check_remove ();
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
void
|
||
|
|
fill_table ()
|
||
|
|
{
|
||
|
|
// at start the registry is indeed empty
|
||
|
|
// thus a query doesn't yield any results....
|
||
|
|
CHECK ( ! *(reg_->candidates(Q13 ("something"))) );
|
||
|
|
|
||
|
|
reg_->put (o1, q5);
|
||
|
|
reg_->put (o2, q4);
|
||
|
|
reg_->put (o3, q3);
|
||
|
|
reg_->put (o3, q2);
|
||
|
|
reg_->put (o2, q1);
|
||
|
|
reg_->put (o1, Q13()); // the empty query
|
||
|
|
|
||
|
|
ps.clear();
|
||
|
|
for (int i=0; i<100; ++i)
|
||
|
|
{
|
||
|
|
P px (pFac());
|
||
|
|
Q23 qx (garbage_query());
|
||
|
|
ps[qx] = px;
|
||
|
|
reg_->put (px, qx);
|
||
|
|
px->instanceID = qx;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
void
|
||
|
|
check_query ()
|
||
|
|
{
|
||
|
|
Iter13 i (reg_->candidates(Q13 ("irrelevant query")));
|
||
|
|
CHECK ( i.hasNext());
|
||
|
|
CHECK ( *i++ == o1); // ordered according to the degree of the queries
|
||
|
|
CHECK ( *i++ == o2);
|
||
|
|
CHECK ( *i++ == o3);
|
||
|
|
CHECK ( *i++ == o3);
|
||
|
|
CHECK ( *i++ == o2);
|
||
|
|
CHECK ( *i == o1);
|
||
|
|
CHECK (!i.hasNext());
|
||
|
|
CHECK (! *++i ); // null after end
|
||
|
|
|
||
|
|
i = reg_->candidates(q3);
|
||
|
|
CHECK ( *i++ == o3); // found by direct match
|
||
|
|
CHECK ( *i++ == o1); // followed by the ordered enumeration
|
||
|
|
CHECK ( *i++ == o2);
|
||
|
|
CHECK ( *i++ == o3);
|
||
|
|
CHECK ( *i++ == o3);
|
||
|
|
CHECK ( *i++ == o2);
|
||
|
|
CHECK ( *i++ == o1);
|
||
|
|
CHECK (!i.hasNext());
|
||
|
|
|
||
|
|
i = reg_->candidates(Q13());
|
||
|
|
CHECK ( *i++ == o1); // found by direct match to the empty query
|
||
|
|
CHECK ( *i++ == o1);
|
||
|
|
CHECK ( *i++ == o2);
|
||
|
|
CHECK ( *i++ == o3);
|
||
|
|
CHECK ( *i++ == o3);
|
||
|
|
CHECK ( *i++ == o2);
|
||
|
|
CHECK ( *i++ == o1);
|
||
|
|
CHECK (!i.hasNext());
|
||
|
|
|
||
|
|
uint d=0;
|
||
|
|
uint d_prev=0;
|
||
|
|
Iter23 j = reg_->candidates(Q23 ("some crap"));
|
||
|
|
for ( ; *j ; ++j )
|
||
|
|
{
|
||
|
|
CHECK ( *j );
|
||
|
|
Q23 qx ((*j)->instanceID);
|
||
|
|
CHECK ( ps[qx] == (*j));
|
||
|
|
d = lumiera::query::countPred (qx);
|
||
|
|
CHECK ( d_prev <= d );
|
||
|
|
d_prev = d;
|
||
|
|
}
|
||
|
|
CHECK (!j.hasNext());
|
||
|
|
|
||
|
|
// calling with an arbitrary (registered) query
|
||
|
|
// yields the corresponding object at start of the enumeration
|
||
|
|
j = reg_->candidates(ps.begin()->first);
|
||
|
|
CHECK ( *j == ps.begin()->second);
|
||
|
|
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
void
|
||
|
|
check_remove ()
|
||
|
|
{
|
||
|
|
reg_->forget (o2);
|
||
|
|
|
||
|
|
Iter13 i (reg_->candidates(q4));
|
||
|
|
CHECK ( i.hasNext());
|
||
|
|
CHECK ( *i++ == o1); // ordered according to the degree of the queries
|
||
|
|
// but the o2 entries are missing
|
||
|
|
CHECK ( *i++ == o3);
|
||
|
|
CHECK ( *i++ == o3);
|
||
|
|
// missing
|
||
|
|
CHECK ( *i == o1);
|
||
|
|
CHECK (!i.hasNext());
|
||
|
|
|
||
|
|
o3.reset(); // killing the only reference....
|
||
|
|
// expires the weak ref in the registry
|
||
|
|
|
||
|
|
i = reg_->candidates(Q13 ("something"));
|
||
|
|
CHECK ( i.hasNext());
|
||
|
|
CHECK ( *i++ == o1); // ordered according to the degree of the queries
|
||
|
|
// but now also the o3 entries are missing...
|
||
|
|
CHECK ( *i == o1);
|
||
|
|
CHECK (!i.hasNext());
|
||
|
|
|
||
|
|
CHECK ( reg_->put (o1, q5)); // trying to register the same object at the same place
|
||
|
|
// doesn't change anything (but counts as "success")
|
||
|
|
i = reg_->candidates(q5);
|
||
|
|
CHECK ( *i++ == o1); // direct match
|
||
|
|
CHECK ( *i++ == o1);
|
||
|
|
CHECK ( *i++ == o1);
|
||
|
|
CHECK (!i.hasNext());
|
||
|
|
|
||
|
|
CHECK (!reg_->put (o2, q5)); // trying to (re)register o2 with a existing query
|
||
|
|
// counts as failure (nothing changes)
|
||
|
|
i = reg_->candidates(q5);
|
||
|
|
CHECK ( *i++ == o1); // direct match
|
||
|
|
CHECK ( *i++ == o1);
|
||
|
|
CHECK ( *i++ == o1);
|
||
|
|
CHECK (!i.hasNext());
|
||
|
|
|
||
|
|
CHECK ( reg_->put (o2, q2)); // trying to (re)register o2 with another query succeeds
|
||
|
|
i = reg_->candidates(q2);
|
||
|
|
CHECK ( *i++ == o2); // direct match
|
||
|
|
CHECK ( *i++ == o1);
|
||
|
|
CHECK ( *i++ == o2); // inserted here in the dataset
|
||
|
|
CHECK ( *i++ == o1);
|
||
|
|
CHECK (!i.hasNext());
|
||
|
|
|
||
|
|
CHECK ( reg_->forget (o1));
|
||
|
|
CHECK (!reg_->forget (o1)); // failure, because it's already removed
|
||
|
|
CHECK ( reg_->forget (o2));
|
||
|
|
|
||
|
|
o3 = oFac(); // another object is another object (it's irrelevant...)
|
||
|
|
|
||
|
|
i = reg_->candidates(q2);
|
||
|
|
CHECK (! (*i)); // empty
|
||
|
|
}
|
||
|
|
|
||
|
|
};
|
||
|
|
|
||
|
|
|
||
|
|
/** Register this test class... */
|
||
|
|
LAUNCHER (DefsRegistryImpl_test, "function session");
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
}}} // namespace mobject::session::test
|