2010-03-23 04:52:50 +01:00
|
|
|
/*
|
|
|
|
|
EntryID(Test) - proof-of-concept test for a combined hash+symbolic ID
|
2010-12-17 23:28:49 +01:00
|
|
|
|
2010-03-23 04:52:50 +01:00
|
|
|
Copyright (C) Lumiera.org
|
|
|
|
|
2010, Hermann Vosseler <Ichthyostega@web.de>
|
2010-12-17 23:28:49 +01:00
|
|
|
|
2010-03-23 04:52:50 +01:00
|
|
|
This program is free software; you can redistribute it and/or
|
|
|
|
|
modify it under the terms of the GNU General Public License as
|
2010-12-17 23:28:49 +01:00
|
|
|
published by the Free Software Foundation; either version 2 of
|
|
|
|
|
the License, or (at your option) any later version.
|
|
|
|
|
|
2010-03-23 04:52:50 +01:00
|
|
|
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.
|
2010-12-17 23:28:49 +01:00
|
|
|
|
2010-03-23 04:52:50 +01:00
|
|
|
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.
|
2010-12-17 23:28:49 +01:00
|
|
|
|
2010-03-23 04:52:50 +01:00
|
|
|
* *****************************************************/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#include "lib/test/run.hpp"
|
|
|
|
|
#include "lib/test/test-helper.hpp"
|
|
|
|
|
|
2015-07-02 19:24:44 +02:00
|
|
|
#include "lib/idi/entry-id.hpp"
|
2015-06-30 03:06:17 +02:00
|
|
|
#include "proc/asset/struct-scheme.hpp"
|
2010-03-28 05:14:57 +02:00
|
|
|
#include "proc/mobject/session/clip.hpp"
|
2015-05-30 22:09:26 +02:00
|
|
|
#include "proc/mobject/session/fork.hpp"
|
2010-03-29 06:56:42 +02:00
|
|
|
#include "lib/meta/trait-special.hpp"
|
2010-03-23 04:52:50 +01:00
|
|
|
#include "lib/util-foreach.hpp"
|
|
|
|
|
#include "lib/symbol.hpp"
|
|
|
|
|
|
2014-04-03 22:42:48 +02:00
|
|
|
#include <unordered_map>
|
2010-03-23 04:52:50 +01:00
|
|
|
#include <iostream>
|
|
|
|
|
#include <string>
|
|
|
|
|
|
2010-03-29 03:27:47 +02:00
|
|
|
using lib::test::showSizeof;
|
2010-03-23 04:52:50 +01:00
|
|
|
using lib::test::randStr;
|
|
|
|
|
using util::isSameObject;
|
2011-12-03 03:18:03 +01:00
|
|
|
using util::contains;
|
2010-03-29 06:56:42 +02:00
|
|
|
using util::and_all;
|
2010-03-23 04:52:50 +01:00
|
|
|
using lib::Literal;
|
|
|
|
|
using std::string;
|
|
|
|
|
using std::cout;
|
|
|
|
|
using std::endl;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2015-07-02 19:13:50 +02:00
|
|
|
namespace lib {
|
|
|
|
|
namespace idi {
|
|
|
|
|
namespace test{
|
2010-03-23 04:52:50 +01:00
|
|
|
|
2011-12-02 17:50:44 +01:00
|
|
|
using lumiera::error::LUMIERA_ERROR_WRONG_TYPE;
|
|
|
|
|
|
2010-03-24 05:00:06 +01:00
|
|
|
namespace { // Test definitions...
|
2010-03-23 04:52:50 +01:00
|
|
|
|
|
|
|
|
struct Dummy { };
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
2015-07-02 19:13:50 +02:00
|
|
|
using DummyID = EntryID<Dummy>;
|
|
|
|
|
using ForkID = EntryID<proc::mobject::session::Fork>;
|
|
|
|
|
using ClipID = EntryID<proc::mobject::session::Clip>;
|
2010-03-23 04:52:50 +01:00
|
|
|
|
2010-03-29 06:56:42 +02:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2013-10-24 23:06:36 +02:00
|
|
|
/***********************************************************************//**
|
2010-03-23 04:52:50 +01:00
|
|
|
* @test proof-of-concept test for a combined symbolic and hash based ID.
|
|
|
|
|
* - create some symbolic IDs
|
|
|
|
|
* - check default assignment works properly
|
|
|
|
|
* - check comparisons
|
|
|
|
|
* - check hashing
|
|
|
|
|
* - use the embedded hash ID (LUID) as hashtable key
|
2010-03-29 06:56:42 +02:00
|
|
|
*
|
2010-03-23 04:52:50 +01:00
|
|
|
* @see lib::HashIndexed::Id
|
|
|
|
|
* @see mobject::Placement real world usage example
|
|
|
|
|
*/
|
|
|
|
|
class EntryID_test : public Test
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
virtual void
|
|
|
|
|
run (Arg)
|
|
|
|
|
{
|
|
|
|
|
checkCreation();
|
|
|
|
|
checkBasicProperties();
|
|
|
|
|
checkComparisions();
|
|
|
|
|
checkErasure();
|
|
|
|
|
buildHashtable();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
checkCreation ()
|
|
|
|
|
{
|
|
|
|
|
DummyID dID1;
|
|
|
|
|
DummyID dID2("strange");
|
|
|
|
|
DummyID dID3;
|
2010-03-24 05:00:06 +01:00
|
|
|
CHECK (dID1.isValid());
|
|
|
|
|
CHECK (dID2.isValid());
|
|
|
|
|
CHECK (dID3.isValid());
|
2010-03-23 04:52:50 +01:00
|
|
|
CHECK (dID1 != dID2); CHECK (dID2 != dID1);
|
|
|
|
|
CHECK (dID2 != dID3); CHECK (dID3 != dID2);
|
|
|
|
|
CHECK (dID1 != dID3); CHECK (dID3 != dID1);
|
|
|
|
|
|
2015-05-31 02:03:24 +02:00
|
|
|
ForkID tID1;
|
|
|
|
|
ForkID tID2;
|
|
|
|
|
ForkID tID3("special");
|
2010-03-24 05:00:06 +01:00
|
|
|
CHECK (tID1.isValid());
|
|
|
|
|
CHECK (tID2.isValid());
|
|
|
|
|
CHECK (tID3.isValid());
|
2010-03-23 04:52:50 +01:00
|
|
|
CHECK (tID1 != tID2); CHECK (tID2 != tID1);
|
|
|
|
|
CHECK (tID2 != tID3); CHECK (tID3 != tID2);
|
|
|
|
|
CHECK (tID1 != tID3); CHECK (tID3 != tID1);
|
|
|
|
|
|
2010-03-29 03:27:47 +02:00
|
|
|
cout << dID1 << endl;
|
|
|
|
|
cout << dID2 << endl;
|
|
|
|
|
cout << dID3 << endl;
|
|
|
|
|
|
|
|
|
|
cout << tID1 << endl;
|
|
|
|
|
cout << tID2 << endl;
|
|
|
|
|
cout << tID3 << endl;
|
|
|
|
|
|
2010-03-23 04:52:50 +01:00
|
|
|
DummyID x (dID2); // copy ctor
|
|
|
|
|
CHECK (x == dID2);
|
|
|
|
|
CHECK (!isSameObject (x, dID2));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
checkBasicProperties ()
|
|
|
|
|
{
|
2015-07-02 19:13:50 +02:00
|
|
|
using proc::asset::Asset;
|
|
|
|
|
using proc::asset::STRUCT;
|
|
|
|
|
using proc::asset::Category;
|
|
|
|
|
using proc::asset::idi::getAssetIdent;
|
|
|
|
|
|
2015-05-31 02:03:24 +02:00
|
|
|
ForkID tID(" test ⚡ ☠ ☭ ⚡ track ");
|
2015-07-02 19:13:50 +02:00
|
|
|
CHECK (getAssetIdent(tID) == Asset::Ident("test_track", Category(STRUCT,"forks"), "lumi", 0));
|
2010-03-23 04:52:50 +01:00
|
|
|
|
2015-05-31 02:03:24 +02:00
|
|
|
CHECK (tID.getHash() == ForkID("☢ test ☢ track ☢").getHash());
|
2010-03-23 04:52:50 +01:00
|
|
|
|
2015-07-02 19:13:50 +02:00
|
|
|
CHECK (tID.getSym() == getAssetIdent(tID).name);
|
|
|
|
|
CHECK (getAssetIdent(ForkID()).category == Category (STRUCT,"forks"));
|
|
|
|
|
CHECK (getAssetIdent(ClipID()).category == Category (STRUCT,"clips"));
|
2010-03-23 04:52:50 +01:00
|
|
|
|
2010-03-29 06:56:42 +02:00
|
|
|
ClipID cID2,cID3;
|
|
|
|
|
CHECK (cID2.getSym() < cID3.getSym());
|
2010-03-23 04:52:50 +01:00
|
|
|
CHECK (ClipID("x").getSym() == ClipID(" x ").getSym());
|
|
|
|
|
|
2010-03-29 06:56:42 +02:00
|
|
|
for (uint i=0; i<10000; ++i)
|
2010-03-23 04:52:50 +01:00
|
|
|
{
|
2015-05-31 02:03:24 +02:00
|
|
|
ForkID arbitrary(randStr(30));
|
2010-03-23 04:52:50 +01:00
|
|
|
CHECK (0 < arbitrary.getHash());
|
|
|
|
|
CHECK (tID.getHash() != arbitrary.getHash());
|
|
|
|
|
tID = arbitrary;
|
|
|
|
|
CHECK (tID.getHash() == arbitrary.getHash());
|
|
|
|
|
CHECK (tID.getSym() == arbitrary.getSym());
|
2015-07-02 19:13:50 +02:00
|
|
|
CHECK (getAssetIdent(tID)== getAssetIdent(arbitrary));
|
2010-03-23 04:52:50 +01:00
|
|
|
}
|
|
|
|
|
|
2015-05-31 02:03:24 +02:00
|
|
|
cout << showSizeof<ForkID>() << endl;
|
2010-03-29 06:56:42 +02:00
|
|
|
cout << showSizeof<BareEntryID>() << endl;
|
2015-05-31 02:03:24 +02:00
|
|
|
CHECK (sizeof(ForkID) == sizeof(BareEntryID));
|
|
|
|
|
CHECK (sizeof(ForkID) == sizeof(lumiera_uid) + sizeof(void*));
|
2010-03-23 04:52:50 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
checkComparisions ()
|
|
|
|
|
{
|
2015-05-31 02:03:24 +02:00
|
|
|
ForkID tID1("a1");
|
|
|
|
|
ForkID tID2("a1");
|
|
|
|
|
ForkID tID3("a2");
|
|
|
|
|
ForkID tID4("b");
|
2010-03-23 04:52:50 +01:00
|
|
|
CHECK (tID1 == tID2);
|
|
|
|
|
|
|
|
|
|
CHECK (tID2 < tID3);
|
|
|
|
|
CHECK (tID2 <= tID3);
|
|
|
|
|
CHECK (tID3 >= tID2);
|
|
|
|
|
CHECK (tID3 > tID2);
|
|
|
|
|
|
|
|
|
|
CHECK (tID3 < tID4);
|
|
|
|
|
CHECK (tID3 <= tID4);
|
|
|
|
|
CHECK (tID4 >= tID3);
|
|
|
|
|
CHECK (tID4 > tID3);
|
|
|
|
|
|
2015-05-31 02:03:24 +02:00
|
|
|
ForkID trackID1, trackID2;
|
2010-03-29 06:56:42 +02:00
|
|
|
CHECK (trackID1 < trackID2); // auto generated IDs are prefix + running counter
|
2010-03-23 04:52:50 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2010-03-29 06:56:42 +02:00
|
|
|
|
|
|
|
|
/** @test handling of EntryIDs through their common base class,
|
|
|
|
|
* which means erasing the specific type information.
|
|
|
|
|
* While this type information can't be recovered
|
|
|
|
|
* after erasure, we can try to upcast back
|
|
|
|
|
* to a known type; this upcast is safe,
|
|
|
|
|
* because the embedded hash-ID
|
|
|
|
|
* is based on the type info.
|
|
|
|
|
*/
|
2010-03-23 04:52:50 +01:00
|
|
|
void
|
|
|
|
|
checkErasure ()
|
|
|
|
|
{
|
2015-07-03 00:33:02 +02:00
|
|
|
ForkID fID("suspicious");
|
2015-05-31 02:03:24 +02:00
|
|
|
ClipID cID("suspicious");
|
2010-03-23 04:52:50 +01:00
|
|
|
|
2015-07-03 00:33:02 +02:00
|
|
|
CHECK (fID.getHash() != cID.getHash());
|
|
|
|
|
CHECK (fID.getSym() == cID.getSym());
|
2010-03-23 04:52:50 +01:00
|
|
|
|
2015-07-03 00:33:02 +02:00
|
|
|
BareEntryID bIDf (fID);
|
2010-03-23 04:52:50 +01:00
|
|
|
BareEntryID bIDc (cID);
|
|
|
|
|
|
2015-07-03 00:33:02 +02:00
|
|
|
CHECK (bIDf != bIDc);
|
|
|
|
|
CHECK (bIDf.getHash() != bIDc.getHash());
|
|
|
|
|
CHECK (bIDf.getSym() == bIDc.getSym());
|
2010-03-23 04:52:50 +01:00
|
|
|
CHECK ("suspicious" == bIDc.getSym());
|
|
|
|
|
|
2015-07-02 19:13:50 +02:00
|
|
|
using proc::mobject::session::Fork;
|
|
|
|
|
using proc::mobject::session::Clip;
|
2015-07-03 00:33:02 +02:00
|
|
|
ForkID tIDnew = bIDf.recast<Fork>();
|
2015-05-31 02:03:24 +02:00
|
|
|
ClipID cIDnew = bIDc.recast<Clip>();
|
2015-07-03 00:33:02 +02:00
|
|
|
CHECK (tIDnew == fID);
|
2010-03-23 04:52:50 +01:00
|
|
|
CHECK (cIDnew == cID);
|
|
|
|
|
|
2015-07-03 00:33:02 +02:00
|
|
|
VERIFY_ERROR (WRONG_TYPE, bIDf.recast<Clip>());
|
2015-05-31 02:03:24 +02:00
|
|
|
VERIFY_ERROR (WRONG_TYPE, bIDc.recast<Fork>());
|
2010-03-23 04:52:50 +01:00
|
|
|
VERIFY_ERROR (WRONG_TYPE, bIDc.recast<Dummy>());
|
2015-07-03 00:33:02 +02:00
|
|
|
VERIFY_ERROR (WRONG_TYPE, bIDf.recast<Dummy>());
|
2010-03-29 06:56:42 +02:00
|
|
|
|
2015-07-03 00:33:02 +02:00
|
|
|
CHECK (fID == ForkID::recast (bIDf)); // equivalent static API on typed subclass
|
2015-05-31 02:03:24 +02:00
|
|
|
VERIFY_ERROR (WRONG_TYPE, ForkID::recast(bIDc));
|
2015-07-03 00:33:02 +02:00
|
|
|
VERIFY_ERROR (WRONG_TYPE, ClipID::recast(bIDf));
|
2010-03-29 06:56:42 +02:00
|
|
|
VERIFY_ERROR (WRONG_TYPE, DummyID::recast(bIDc));
|
2015-07-03 00:33:02 +02:00
|
|
|
VERIFY_ERROR (WRONG_TYPE, DummyID::recast(bIDf));
|
2010-03-23 04:52:50 +01:00
|
|
|
|
2010-03-29 06:56:42 +02:00
|
|
|
// mixed equality comparisons (based on the hash)
|
2015-07-03 00:33:02 +02:00
|
|
|
BareEntryID bIDt_copy (bIDf);
|
|
|
|
|
CHECK (bIDf == bIDt_copy);
|
|
|
|
|
CHECK (!isSameObject (bIDf, bIDt_copy));
|
2010-03-23 04:52:50 +01:00
|
|
|
|
2015-07-03 00:33:02 +02:00
|
|
|
CHECK (fID != bIDc);
|
2010-03-29 06:56:42 +02:00
|
|
|
CHECK (cID != bIDt_copy);
|
2015-07-03 00:33:02 +02:00
|
|
|
CHECK (fID == bIDt_copy);
|
2010-03-23 04:52:50 +01:00
|
|
|
|
2015-07-03 00:33:02 +02:00
|
|
|
CHECK (bIDf == ForkID ("suspicious"));
|
|
|
|
|
CHECK (bIDf != ClipID ("suspicious"));
|
2010-03-29 06:56:42 +02:00
|
|
|
CHECK (bIDc == ClipID ("suspicious"));
|
2015-05-31 02:03:24 +02:00
|
|
|
CHECK (ForkID ("suspicious") != ClipID ("suspicious"));
|
2010-03-23 04:52:50 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2010-03-29 06:56:42 +02:00
|
|
|
|
2015-01-06 14:37:26 +01:00
|
|
|
//---key--+-value-+-hash-function---
|
2014-04-03 22:42:48 +02:00
|
|
|
typedef std::unordered_map<DummyID, string, DummyID::UseEmbeddedHash> Hashtable;
|
2010-03-29 06:56:42 +02:00
|
|
|
|
|
|
|
|
/** @test build a hashtable, using EntryID as key,
|
2015-08-15 05:31:50 +02:00
|
|
|
* thereby using the embedded hash-ID
|
|
|
|
|
* @note there is a known weakness of the boost::hash
|
|
|
|
|
* when used on IDs with a running number suffix. /////TICKET #587
|
|
|
|
|
* We use a trick to spread the numbers better.
|
|
|
|
|
* @see HashGenerator_test#verify_Knuth_workaround
|
|
|
|
|
*/
|
2010-03-23 04:52:50 +01:00
|
|
|
void
|
|
|
|
|
buildHashtable ()
|
2010-03-29 06:56:42 +02:00
|
|
|
{
|
2010-03-23 04:52:50 +01:00
|
|
|
Hashtable tab;
|
|
|
|
|
|
2015-08-15 05:31:50 +02:00
|
|
|
for (uint i=0; i<100000; ++i)
|
2010-03-23 04:52:50 +01:00
|
|
|
{
|
|
|
|
|
DummyID dummy;
|
|
|
|
|
tab[dummy] = string(dummy);
|
|
|
|
|
}
|
|
|
|
|
|
2010-03-29 06:56:42 +02:00
|
|
|
CHECK (and_all (tab, verifyEntry));
|
2015-08-15 05:31:50 +02:00
|
|
|
CHECK (100000 == tab.size());
|
2010-03-23 04:52:50 +01:00
|
|
|
}
|
2010-03-29 06:56:42 +02:00
|
|
|
|
|
|
|
|
|
|
|
|
|
static bool
|
|
|
|
|
verifyEntry (Hashtable::value_type entry)
|
|
|
|
|
{
|
2011-12-03 03:18:03 +01:00
|
|
|
return checkForHashCollision(string(entry.first), entry.second);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static bool
|
|
|
|
|
checkForHashCollision(string const& key, string const& val)
|
|
|
|
|
{
|
|
|
|
|
if (key != val) cout << "Hash collision: "<<key<<" != "<<val<< endl;
|
|
|
|
|
return key == val;
|
2010-03-29 06:56:42 +02:00
|
|
|
}
|
|
|
|
|
|
2010-03-23 04:52:50 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** Register this test class... */
|
2015-07-02 19:24:44 +02:00
|
|
|
LAUNCHER (EntryID_test, "unit common");
|
2010-03-23 04:52:50 +01:00
|
|
|
|
|
|
|
|
|
2015-07-02 19:13:50 +02:00
|
|
|
}}} // namespace lib::idi::test
|