Lumiera  0.pre.03
»edit your freedom«
entry-id-test.cpp
Go to the documentation of this file.
1 /*
2  EntryID(Test) - proof-of-concept test for a combined hash+symbolic ID
3 
4  Copyright (C) Lumiera.org
5  2010, Hermann Vosseler <Ichthyostega@web.de>
6 
7  This program is free software; you can redistribute it and/or
8  modify it under the terms of the GNU General Public License as
9  published by the Free Software Foundation; either version 2 of
10  the License, or (at your option) any later version.
11 
12  This program is distributed in the hope that it will be useful,
13  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  GNU General Public License for more details.
16 
17  You should have received a copy of the GNU General Public License
18  along with this program; if not, write to the Free Software
19  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 
21 * *****************************************************/
22 
28 #include "lib/test/run.hpp"
29 #include "lib/test/test-helper.hpp"
30 
31 #include "lib/idi/entry-id.hpp"
36 #include "lib/util-foreach.hpp"
37 #include "lib/format-cout.hpp"
38 #include "lib/symbol.hpp"
39 
40 #include <unordered_map>
41 #include <string>
42 
43 using lib::test::showSizeof;
44 using lib::test::randStr;
45 using util::isSameObject;
46 using util::contains;
47 using util::and_all;
48 using lib::Literal;
49 using std::string;
50 
51 
52 
53 namespace lib {
54 namespace idi {
55 namespace test{
56 
57  using LERR_(WRONG_TYPE);
58 
59  namespace { // Test definitions...
60 
61  struct Dummy { };
62 
63  }
64 
65  using DummyID = EntryID<Dummy>;
68 
69 
70 
71 
72  /***********************************************************************/
83  class EntryID_test : public Test
84  {
85 
86  virtual void
87  run (Arg)
88  {
89  checkCreation();
90  checkBasicProperties();
91  checkComparisions();
92  checkErasure();
93  buildHashtable();
94  }
95 
96 
97 
98  void
99  checkCreation ()
100  {
101  DummyID dID1;
102  DummyID dID2("strange");
103  DummyID dID3;
104  CHECK (dID1.isValid());
105  CHECK (dID2.isValid());
106  CHECK (dID3.isValid());
107  CHECK (dID1 != dID2); CHECK (dID2 != dID1);
108  CHECK (dID2 != dID3); CHECK (dID3 != dID2);
109  CHECK (dID1 != dID3); CHECK (dID3 != dID1);
110 
111  ForkID tID1;
112  ForkID tID2;
113  ForkID tID3("special");
114  CHECK (tID1.isValid());
115  CHECK (tID2.isValid());
116  CHECK (tID3.isValid());
117  CHECK (tID1 != tID2); CHECK (tID2 != tID1);
118  CHECK (tID2 != tID3); CHECK (tID3 != tID2);
119  CHECK (tID1 != tID3); CHECK (tID3 != tID1);
120 
121  cout << dID1 << endl;
122  cout << dID2 << endl;
123  cout << dID3 << endl;
124 
125  cout << tID1 << endl;
126  cout << tID2 << endl;
127  cout << tID3 << endl;
128 
129  DummyID x (dID2); // copy ctor
130  CHECK (x == dID2);
131  CHECK (!isSameObject (x, dID2));
132  }
133 
134 
135  void
136  checkBasicProperties ()
137  {
138  using steam::asset::Asset;
139  using steam::asset::STRUCT;
141  using steam::asset::idi::getAssetIdent;
142 
143  ForkID tID(" test ⚡ ☠ ☭ ⚡ track ");
144 
145  // Symbol-ID will be "sanitised"
146  CHECK ("test_track" == tID.getSym());
147  CHECK (tID == ForkID("☢ test ☢ track ☢"));
148  CHECK (tID == ForkID(string{"☢ test ☢ track ☢"}));
149 
150  // but: there is a pass-through for internal symbols
151  CHECK (tID != ForkID(Symbol{"☢ test ☢ track ☢"}));
152 
153  CHECK (tID.getHash() == ForkID("☢ test ☢ track ☢").getHash());
154 
155  CHECK (getAssetIdent(tID) == Asset::Ident("test_track", Category(STRUCT,"forks"), "lumi", 0));
156 
157  CHECK (tID.getSym() == getAssetIdent(tID).name);
158  CHECK (getAssetIdent(ForkID()).category == Category (STRUCT,"forks"));
159  CHECK (getAssetIdent(ClipID()).category == Category (STRUCT,"clips"));
160 
161  ClipID cID2,cID3;
162  CHECK (cID2.getSym() < cID3.getSym());
163  CHECK (ClipID("x").getSym() == ClipID(" x ").getSym());
164 
165  for (uint i=0; i<10000; ++i)
166  {
167  ForkID arbitrary(randStr(30));
168  CHECK (0 < arbitrary.getHash());
169  CHECK (tID.getHash() != arbitrary.getHash());
170  tID = arbitrary;
171  CHECK (tID.getHash() == arbitrary.getHash());
172  CHECK (tID.getSym() == arbitrary.getSym());
173  CHECK (getAssetIdent(tID)== getAssetIdent(arbitrary));
174  }
175 
176  cout << showSizeof<ForkID>() << endl;
177  cout << showSizeof<BareEntryID>() << endl;
178  cout << showSizeof<lumiera_uid>() << endl;
179  cout << showSizeof<string>() << endl;
180  cout << showSizeof<void*>() << endl;
181  CHECK (sizeof(ForkID) == sizeof(BareEntryID));
182  CHECK (sizeof(ForkID) == sizeof(lumiera_uid) + sizeof(string));
183  }
184 
185 
186  void
187  checkComparisions ()
188  {
189  ForkID tID1("a1");
190  ForkID tID2("a1");
191  ForkID tID3("a2");
192  ForkID tID4("b");
193  CHECK (tID1 == tID2);
194 
195  CHECK (tID2 < tID3);
196  CHECK (tID2 <= tID3);
197  CHECK (tID3 >= tID2);
198  CHECK (tID3 > tID2);
199 
200  CHECK (tID3 < tID4);
201  CHECK (tID3 <= tID4);
202  CHECK (tID4 >= tID3);
203  CHECK (tID4 > tID3);
204 
205  ForkID trackID1, trackID2;
206  CHECK (trackID1 < trackID2); // auto generated IDs are prefix + running counter
207  }
208 
209 
210 
219  void
221  {
222  ForkID fID("suspicious");
223  ClipID cID("suspicious");
224 
225  CHECK (fID.getHash() != cID.getHash());
226  CHECK (fID.getSym() == cID.getSym());
227 
228  BareEntryID bIDf (fID);
229  BareEntryID bIDc (cID);
230 
231  CHECK (bIDf != bIDc);
232  CHECK (bIDf.getHash() != bIDc.getHash());
233  CHECK (bIDf.getSym() == bIDc.getSym());
234  CHECK ("suspicious" == bIDc.getSym());
235 
238  ForkID tIDnew = bIDf.recast<Fork>();
239  ClipID cIDnew = bIDc.recast<Clip>();
240  CHECK (tIDnew == fID);
241  CHECK (cIDnew == cID);
242 
243  VERIFY_ERROR (WRONG_TYPE, bIDf.recast<Clip>());
244  VERIFY_ERROR (WRONG_TYPE, bIDc.recast<Fork>());
245  VERIFY_ERROR (WRONG_TYPE, bIDc.recast<Dummy>());
246  VERIFY_ERROR (WRONG_TYPE, bIDf.recast<Dummy>());
247 
248  CHECK (fID == ForkID::recast (bIDf)); // equivalent static API on typed subclass
249  VERIFY_ERROR (WRONG_TYPE, ForkID::recast(bIDc));
250  VERIFY_ERROR (WRONG_TYPE, ClipID::recast(bIDf));
251  VERIFY_ERROR (WRONG_TYPE, DummyID::recast(bIDc));
252  VERIFY_ERROR (WRONG_TYPE, DummyID::recast(bIDf));
253 
254  // mixed equality comparisons (based on the hash)
255  BareEntryID bIDt_copy (bIDf);
256  CHECK (bIDf == bIDt_copy);
257  CHECK (!isSameObject (bIDf, bIDt_copy));
258 
259  CHECK (fID != bIDc);
260  CHECK (cID != bIDt_copy);
261  CHECK (fID == bIDt_copy);
262 
263  CHECK (bIDf == ForkID ("suspicious"));
264  CHECK (bIDf != ClipID ("suspicious"));
265  CHECK (bIDc == ClipID ("suspicious"));
266  CHECK (ForkID ("suspicious") != ClipID ("suspicious"));
267  }
268 
269 
270 
271  //---key--+-value-+-hash-function---
272  typedef std::unordered_map<DummyID, string, DummyID::UseEmbeddedHash> Hashtable;
273 
281  void
283  {
284  Hashtable tab;
285 
286  for (uint i=0; i<100000; ++i)
287  {
288  DummyID dummy;
289  tab[dummy] = string(dummy);
290  }
291 
292  CHECK (and_all (tab, verifyEntry));
293  CHECK (100000 == tab.size());
294  }
295 
296 
297  static bool
298  verifyEntry (Hashtable::value_type entry)
299  {
300  return checkForHashCollision(string(entry.first), entry.second);
301  }
302 
303  static bool
304  checkForHashCollision(string const& key, string const& val)
305  {
306  if (key != val) cout << "Hash collision: "<<key<<" != "<<val<< endl;
307  return key == val;
308  }
309 
310  };
311 
312 
313 
315  LAUNCHER (EntryID_test, "unit common");
316 
317 
318 }}} // namespace lib::idi::test
type erased baseclass for building a combined hash and symbolic ID.
Definition: entry-id.hpp:142
string name
element ID, comprehensible but sanitised.
Definition: asset.hpp:164
Automatically use custom string conversion in C++ stream output.
Tree like classification of Assets.
Definition: category.hpp:75
AnyPair entry(Query< TY > const &query, typename WrapReturn< TY >::Wrapper &obj)
helper to simplify creating mock table entries, wrapped correctly
Definition: run.hpp:49
inline string literal This is a marker type to indicate that
Definition: symbol.hpp:85
MObject in the Session to represent a clip on the timeline.
typed symbolic and hash ID for asset-like position accounting.
Definition: entry-id.hpp:135
#define VERIFY_ERROR(ERROR_ID, ERRONEOUS_STATEMENT)
Macro to verify that a statement indeed raises an exception.
bool and_all(CON const &elements, FUN function, P1 &&bind1, ARGS &&...args)
Accept binding for arbitrary function arguments.
A user visible/editable Clip is a reference to a contiguous sequence of media data loaded as Asset in...
Organisational grouping device within the Session model ("Track" / "Media Bin").
Implementation namespace for support and library code.
string randStr(size_t len)
create garbage string of given length
Definition: test-helper.cpp:69
Token or Atom with distinct identity.
Definition: symbol.hpp:126
EntryID< TAR > const & recast() const
try to upcast this BareEntryID to a fully typed EntryID.
Definition: entry-id.hpp:331
Marker types to indicate a literal string and a Symbol.
Simple test class runner.
Superinterface describing especially bookkeeping properties.
Definition: asset.hpp:148
A collection of frequently used helper functions to support unit testing.
Rarely used specialisations of otherwise heavily used generic code.
A Fork serves as grouping device within the Session.
Definition: fork.hpp:103
Bare symbolic and hash ID used for accounting of asset like entries.
unsigned char lumiera_uid[16]
storage for a Lumiera unique ID, based on a 128bit random number
Definition: hash-value.h:45
Perform operations "for each element" of a collection.
Naming and labelling scheme for structural assets.
bool contains(SEQ const &cont, typename SEQ::const_reference val)
shortcut for brute-force containment test in any sequential container
Definition: util.hpp:255
bool isSameObject(A const &a, B const &b)
compare plain object identity, bypassing any custom comparison operators.
Definition: util.hpp:372