2009-12-20 04:33:24 +01:00
|
|
|
/*
|
|
|
|
|
ItemWrapper(Test) - wrapping and holding arbitrary values, pointers and references
|
2010-12-10 02:55:40 +01:00
|
|
|
|
2009-12-20 04:33:24 +01:00
|
|
|
Copyright (C) Lumiera.org
|
|
|
|
|
2009, Hermann Vosseler <Ichthyostega@web.de>
|
2010-12-10 02:55:40 +01:00
|
|
|
|
2009-12-20 04:33:24 +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
|
|
|
|
|
published by the Free Software Foundation; either version 2 of the
|
|
|
|
|
License, or (at your option) any later version.
|
2010-12-10 02:55:40 +01:00
|
|
|
|
2009-12-20 04:33:24 +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-10 02:55:40 +01:00
|
|
|
|
2009-12-20 04:33:24 +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-10 02:55:40 +01:00
|
|
|
|
2009-12-20 04:33:24 +01:00
|
|
|
* *****************************************************/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#include "lib/test/run.hpp"
|
|
|
|
|
#include "lib/test/test-helper.hpp"
|
|
|
|
|
#include "lib/util.hpp"
|
|
|
|
|
|
|
|
|
|
#include "lib/wrapper.hpp"
|
|
|
|
|
|
2009-12-23 01:36:11 +01:00
|
|
|
#include <tr1/functional>
|
2009-12-21 07:52:58 +01:00
|
|
|
#include <iostream>
|
2009-12-20 04:33:24 +01:00
|
|
|
#include <cstdlib>
|
|
|
|
|
#include <string>
|
2009-12-23 01:36:11 +01:00
|
|
|
#include <vector>
|
2009-12-20 04:33:24 +01:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
namespace lib {
|
2009-12-21 05:44:29 +01:00
|
|
|
namespace wrapper {
|
2009-12-20 04:33:24 +01:00
|
|
|
namespace test{
|
2010-12-10 02:55:40 +01:00
|
|
|
|
2009-12-20 04:33:24 +01:00
|
|
|
using ::Test;
|
2009-12-23 04:46:09 +01:00
|
|
|
using lib::test::randStr;
|
|
|
|
|
using lib::test::showSizeof;
|
2009-12-20 04:33:24 +01:00
|
|
|
using util::isSameObject;
|
2010-12-10 02:55:40 +01:00
|
|
|
|
2009-12-23 04:46:09 +01:00
|
|
|
using std::tr1::placeholders::_1;
|
|
|
|
|
using std::tr1::ref;
|
2009-12-23 01:36:11 +01:00
|
|
|
using std::vector;
|
2009-12-20 04:33:24 +01:00
|
|
|
using std::string;
|
2009-12-25 05:24:49 +01:00
|
|
|
using std::rand;
|
2009-12-21 07:52:58 +01:00
|
|
|
using std::cout;
|
|
|
|
|
using std::endl;
|
2010-12-10 02:55:40 +01:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2009-12-21 07:52:58 +01:00
|
|
|
namespace { // Test helper: yet another ctor/dtor counting class
|
2010-12-10 02:55:40 +01:00
|
|
|
|
2009-12-21 07:52:58 +01:00
|
|
|
long cntTracker = 0;
|
2010-12-10 02:55:40 +01:00
|
|
|
|
2009-12-21 07:52:58 +01:00
|
|
|
struct Tracker
|
|
|
|
|
{
|
|
|
|
|
uint i_;
|
2010-12-10 02:55:40 +01:00
|
|
|
|
2009-12-21 07:52:58 +01:00
|
|
|
Tracker() : i_(rand() % 500) { ++cntTracker; }
|
|
|
|
|
Tracker(Tracker const& ot) : i_(ot.i_) { ++cntTracker; }
|
|
|
|
|
~Tracker() { --cntTracker; }
|
|
|
|
|
};
|
2010-12-10 02:55:40 +01:00
|
|
|
|
2009-12-21 07:52:58 +01:00
|
|
|
bool operator== (Tracker const& t1, Tracker const& t2) { return t1.i_ == t2.i_; }
|
|
|
|
|
bool operator!= (Tracker const& t1, Tracker const& t2) { return t1.i_ != t2.i_; }
|
2010-12-10 02:55:40 +01:00
|
|
|
|
|
|
|
|
|
2009-12-23 04:46:09 +01:00
|
|
|
/// to be bound as test function....
|
|
|
|
|
int&
|
|
|
|
|
pickElement (vector<int>& vec, size_t idx)
|
|
|
|
|
{
|
|
|
|
|
return vec[idx];
|
|
|
|
|
}
|
2010-12-10 02:55:40 +01:00
|
|
|
|
2009-12-23 04:46:09 +01:00
|
|
|
function<int&(size_t)>
|
|
|
|
|
pickElement_ofVector (vector<int>& vec)
|
|
|
|
|
{
|
|
|
|
|
return std::tr1::bind (pickElement, ref(vec), _1 );
|
|
|
|
|
}
|
2010-12-10 02:55:40 +01:00
|
|
|
|
|
|
|
|
|
2009-12-23 04:46:09 +01:00
|
|
|
} // (END) Test helpers
|
2010-12-10 02:55:40 +01:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2009-12-20 04:33:24 +01:00
|
|
|
/*******************************************************************************
|
2009-12-23 04:46:09 +01:00
|
|
|
* @test use the ItemWrapper to define inline-storage holding values,
|
|
|
|
|
* pointers and references. Verify correct behaviour in each case,
|
|
|
|
|
* including (self)assignment, empty check, invalid dereferentiation.
|
2010-12-10 02:55:40 +01:00
|
|
|
*
|
2009-12-23 04:46:09 +01:00
|
|
|
* @see wrapper.hpp
|
2009-12-20 04:33:24 +01:00
|
|
|
*/
|
|
|
|
|
class ItemWrapper_test : public Test
|
|
|
|
|
{
|
2010-12-10 02:55:40 +01:00
|
|
|
|
|
|
|
|
|
2009-12-20 04:33:24 +01:00
|
|
|
virtual void
|
|
|
|
|
run (Arg)
|
|
|
|
|
{
|
2009-12-21 06:19:56 +01:00
|
|
|
ulong l1 (rand() % 1000);
|
|
|
|
|
ulong l2 (rand() % 1000);
|
|
|
|
|
string s1 (randStr(50));
|
|
|
|
|
string s2 (randStr(50));
|
|
|
|
|
const char* cp (s1.c_str());
|
2010-12-10 02:55:40 +01:00
|
|
|
|
2009-12-21 06:19:56 +01:00
|
|
|
verifyWrapper<ulong> (l1, l2);
|
|
|
|
|
verifyWrapper<ulong&> (l1, l2);
|
|
|
|
|
verifyWrapper<ulong*> (&l1, &l2);
|
|
|
|
|
verifyWrapper<ulong*> ((0), &l2);
|
|
|
|
|
verifyWrapper<ulong*> (&l1, (0));
|
|
|
|
|
verifyWrapper<ulong const&> (l1, l2);
|
2010-12-10 02:55:40 +01:00
|
|
|
|
2009-12-21 06:19:56 +01:00
|
|
|
verifyWrapper<string> (s1, s2);
|
|
|
|
|
verifyWrapper<string&> (s1, s2);
|
|
|
|
|
verifyWrapper<string*> (&s1, &s2);
|
2010-12-10 02:55:40 +01:00
|
|
|
|
2009-12-21 06:19:56 +01:00
|
|
|
verifyWrapper<const char*> (cp, "Lumiera");
|
2010-12-10 02:55:40 +01:00
|
|
|
|
|
|
|
|
|
2009-12-21 07:52:58 +01:00
|
|
|
verifySaneInstanceHandling();
|
2009-12-20 04:33:24 +01:00
|
|
|
verifyWrappedRef ();
|
2010-12-10 02:55:40 +01:00
|
|
|
|
2009-12-23 01:36:11 +01:00
|
|
|
verifyFunctionResult ();
|
2009-12-25 05:24:49 +01:00
|
|
|
verifyFunctionRefResult ();
|
2009-12-20 04:33:24 +01:00
|
|
|
}
|
2010-12-10 02:55:40 +01:00
|
|
|
|
|
|
|
|
|
2009-12-20 04:33:24 +01:00
|
|
|
template<typename X>
|
|
|
|
|
void
|
2009-12-21 06:19:56 +01:00
|
|
|
verifyWrapper (X val, X otherVal)
|
2009-12-20 04:33:24 +01:00
|
|
|
{
|
2009-12-21 06:19:56 +01:00
|
|
|
const ItemWrapper<X> wrap(val);
|
2010-12-10 02:55:40 +01:00
|
|
|
CHECK (wrap);
|
|
|
|
|
|
2009-12-21 07:52:58 +01:00
|
|
|
cout << "ItemWrapper: " << showSizeof(wrap) << endl;
|
2010-12-10 02:55:40 +01:00
|
|
|
|
2009-12-20 04:33:24 +01:00
|
|
|
ItemWrapper<X> copy1 (wrap);
|
|
|
|
|
ItemWrapper<X> copy2;
|
|
|
|
|
ItemWrapper<X> empty;
|
2010-12-10 02:55:40 +01:00
|
|
|
|
|
|
|
|
CHECK (copy1);
|
|
|
|
|
CHECK (!copy2);
|
|
|
|
|
CHECK (false == bool(empty));
|
|
|
|
|
|
|
|
|
|
CHECK (wrap == copy1);
|
|
|
|
|
CHECK (wrap != copy2);
|
|
|
|
|
CHECK (wrap != empty);
|
|
|
|
|
|
2009-12-20 04:33:24 +01:00
|
|
|
copy2 = copy1;
|
2010-12-10 02:55:40 +01:00
|
|
|
CHECK (copy2);
|
|
|
|
|
CHECK (wrap == copy2);
|
|
|
|
|
CHECK (wrap != empty);
|
|
|
|
|
|
2009-12-20 04:33:24 +01:00
|
|
|
copy2 = otherVal;
|
2010-12-10 02:55:40 +01:00
|
|
|
CHECK (copy2);
|
|
|
|
|
CHECK (wrap != copy2);
|
|
|
|
|
CHECK (wrap != empty);
|
|
|
|
|
|
|
|
|
|
CHECK (val == *wrap);
|
|
|
|
|
CHECK (val == *copy1);
|
|
|
|
|
CHECK (val != *copy2);
|
2009-12-20 04:33:24 +01:00
|
|
|
VERIFY_ERROR (BOTTOM_VALUE, *empty );
|
2010-12-10 02:55:40 +01:00
|
|
|
|
|
|
|
|
CHECK (otherVal == *copy2);
|
2009-12-20 04:33:24 +01:00
|
|
|
copy1 = copy2;
|
2010-12-10 02:55:40 +01:00
|
|
|
CHECK (otherVal == *copy1);
|
|
|
|
|
CHECK (otherVal == *copy2);
|
|
|
|
|
CHECK (wrap != copy1);
|
|
|
|
|
CHECK (wrap != copy2);
|
|
|
|
|
|
2009-12-21 07:52:58 +01:00
|
|
|
copy1 = empty; // assign empty to discard value
|
2009-12-23 04:46:09 +01:00
|
|
|
copy1 = copy1; // self-assign empty value
|
2010-12-10 02:55:40 +01:00
|
|
|
CHECK (!copy1);
|
|
|
|
|
|
2009-12-21 07:52:58 +01:00
|
|
|
copy1 = copy2;
|
2010-12-10 02:55:40 +01:00
|
|
|
CHECK (otherVal == *copy1);
|
2009-12-21 07:52:58 +01:00
|
|
|
copy1 = copy1; // self-assign (will be suppressed)
|
2010-12-10 02:55:40 +01:00
|
|
|
CHECK (otherVal == *copy1);
|
2009-12-23 04:46:09 +01:00
|
|
|
copy1 = *copy1; // self-assign also detected in this case
|
2010-12-10 02:55:40 +01:00
|
|
|
CHECK (otherVal == *copy2);
|
|
|
|
|
|
|
|
|
|
CHECK (copy1);
|
2009-12-21 05:44:29 +01:00
|
|
|
copy1.reset();
|
2010-12-10 02:55:40 +01:00
|
|
|
CHECK (!copy1);
|
|
|
|
|
CHECK (empty == copy1);
|
|
|
|
|
CHECK (copy2 != copy1);
|
2009-12-20 04:33:24 +01:00
|
|
|
VERIFY_ERROR (BOTTOM_VALUE, *copy1 );
|
|
|
|
|
};
|
2010-12-10 02:55:40 +01:00
|
|
|
|
|
|
|
|
|
2009-12-21 07:52:58 +01:00
|
|
|
/** @test verify that ctor and dtor calls are balanced,
|
|
|
|
|
* even when assigning and self-assigning.
|
|
|
|
|
*/
|
|
|
|
|
void
|
|
|
|
|
verifySaneInstanceHandling()
|
|
|
|
|
{
|
|
|
|
|
cntTracker = 0;
|
|
|
|
|
{
|
|
|
|
|
Tracker t1;
|
|
|
|
|
Tracker t2;
|
2010-12-10 02:55:40 +01:00
|
|
|
|
2009-12-21 07:52:58 +01:00
|
|
|
verifyWrapper<Tracker> (t1, t2);
|
|
|
|
|
verifyWrapper<Tracker&> (t1, t2);
|
|
|
|
|
verifyWrapper<Tracker*> (&t1, &t2);
|
2010-12-10 02:55:40 +01:00
|
|
|
|
2009-12-21 07:52:58 +01:00
|
|
|
}
|
2010-12-10 02:55:40 +01:00
|
|
|
CHECK (0 == cntTracker);
|
2009-12-21 07:52:58 +01:00
|
|
|
}
|
2010-12-10 02:55:40 +01:00
|
|
|
|
|
|
|
|
|
2009-12-21 07:52:58 +01:00
|
|
|
/** @test verify especially that we can wrap and handle
|
|
|
|
|
* a reference "value" in a pointer-like manner
|
|
|
|
|
*/
|
2009-12-20 04:33:24 +01:00
|
|
|
void
|
|
|
|
|
verifyWrappedRef ()
|
|
|
|
|
{
|
|
|
|
|
int x = 5;
|
|
|
|
|
ItemWrapper<int&> refWrap;
|
2010-12-10 02:55:40 +01:00
|
|
|
CHECK (!refWrap);
|
|
|
|
|
|
2009-12-20 04:33:24 +01:00
|
|
|
refWrap = x;
|
2010-12-10 02:55:40 +01:00
|
|
|
CHECK (refWrap);
|
|
|
|
|
CHECK (5 == *refWrap);
|
|
|
|
|
CHECK (x == *refWrap);
|
|
|
|
|
|
2009-12-20 04:33:24 +01:00
|
|
|
*refWrap += 5;
|
2010-12-10 02:55:40 +01:00
|
|
|
CHECK (x == 10);
|
|
|
|
|
|
2009-12-20 04:33:24 +01:00
|
|
|
ItemWrapper<int*> ptrWrap (& *refWrap);
|
2010-12-10 02:55:40 +01:00
|
|
|
CHECK ( isSameObject (**ptrWrap, x));
|
|
|
|
|
CHECK (!isSameObject ( *ptrWrap, &x));
|
2009-12-20 04:33:24 +01:00
|
|
|
**ptrWrap += 13;
|
2010-12-10 02:55:40 +01:00
|
|
|
CHECK (x == 23);
|
2009-12-20 04:33:24 +01:00
|
|
|
}
|
2010-12-10 02:55:40 +01:00
|
|
|
|
|
|
|
|
|
2009-12-23 01:36:11 +01:00
|
|
|
/** @test verify an extension built on top of the ItemWrapper:
|
2009-12-25 05:24:49 +01:00
|
|
|
* a function which remembers the last result. As a simple test,
|
|
|
|
|
* we bind the \c rand() standard lib function and remember the
|
|
|
|
|
* last returned random value.
|
|
|
|
|
*/
|
|
|
|
|
void
|
|
|
|
|
verifyFunctionResult()
|
|
|
|
|
{
|
|
|
|
|
FunctionResult<int(void)> randomVal (std::rand);
|
2010-12-10 02:55:40 +01:00
|
|
|
|
2009-12-25 05:24:49 +01:00
|
|
|
// function was never invoked, thus the remembered result is NIL
|
2010-12-10 02:55:40 +01:00
|
|
|
CHECK (!randomVal);
|
2009-12-25 05:24:49 +01:00
|
|
|
VERIFY_ERROR (BOTTOM_VALUE, *randomVal );
|
2010-12-10 02:55:40 +01:00
|
|
|
|
2009-12-25 05:24:49 +01:00
|
|
|
int v1 = randomVal();
|
2010-12-10 02:55:40 +01:00
|
|
|
CHECK (v1 == *randomVal);
|
|
|
|
|
CHECK (v1 == *randomVal);
|
|
|
|
|
CHECK (v1 == *randomVal);
|
|
|
|
|
CHECK (randomVal);
|
|
|
|
|
|
2009-12-25 05:24:49 +01:00
|
|
|
int v2;
|
|
|
|
|
do v2 = randomVal();
|
|
|
|
|
while (v1 == v2);
|
2010-12-10 02:55:40 +01:00
|
|
|
CHECK (v2 == *randomVal);
|
|
|
|
|
CHECK (v2 == *randomVal);
|
|
|
|
|
CHECK (v1 != *randomVal);
|
2009-12-25 05:24:49 +01:00
|
|
|
}
|
2010-12-10 02:55:40 +01:00
|
|
|
|
|
|
|
|
|
2009-12-25 05:24:49 +01:00
|
|
|
/** @test verify an extension built on top of the ItemWrapper:
|
|
|
|
|
* a function which remembers the last result. Here we use
|
|
|
|
|
* a test function, which picks a member of an vector and
|
2009-12-23 04:46:09 +01:00
|
|
|
* returns a \em reference to it. Thus the cached "result"
|
|
|
|
|
* can be used to access and change the values within the
|
|
|
|
|
* original vector. In a real world usage scenario, such a
|
|
|
|
|
* function could be an (expensive) data structure access.
|
|
|
|
|
*/
|
2009-12-23 01:36:11 +01:00
|
|
|
void
|
2009-12-25 05:24:49 +01:00
|
|
|
verifyFunctionRefResult()
|
2009-12-23 01:36:11 +01:00
|
|
|
{
|
|
|
|
|
vector<int> testVec;
|
|
|
|
|
for (uint i=0; i<10; ++i)
|
|
|
|
|
testVec.push_back(i);
|
2010-12-10 02:55:40 +01:00
|
|
|
|
2009-12-23 04:46:09 +01:00
|
|
|
FunctionResult<int&(size_t)> funRes (pickElement_ofVector(testVec));
|
2010-12-10 02:55:40 +01:00
|
|
|
|
2009-12-23 01:36:11 +01:00
|
|
|
// function was never invoked, thus the remembered result is NIL
|
2010-12-10 02:55:40 +01:00
|
|
|
CHECK (!funRes);
|
2009-12-23 01:36:11 +01:00
|
|
|
VERIFY_ERROR (BOTTOM_VALUE, *funRes );
|
2010-12-10 02:55:40 +01:00
|
|
|
|
2009-12-23 01:36:11 +01:00
|
|
|
int& r5 = funRes (5);
|
2010-12-10 02:55:40 +01:00
|
|
|
CHECK (funRes); // indicates existence of cached result
|
|
|
|
|
|
|
|
|
|
CHECK (5 == r5);
|
|
|
|
|
CHECK (isSameObject (r5, testVec[5]));
|
|
|
|
|
|
2009-12-23 04:46:09 +01:00
|
|
|
int& r5x = *funRes;
|
2010-12-10 02:55:40 +01:00
|
|
|
CHECK (isSameObject (r5, r5x));
|
|
|
|
|
|
|
|
|
|
CHECK ( isSameObject (r5, *funRes));
|
2009-12-23 04:46:09 +01:00
|
|
|
int& r7 = funRes (7);
|
2010-12-10 02:55:40 +01:00
|
|
|
CHECK (!isSameObject (r5, *funRes));
|
|
|
|
|
CHECK ( isSameObject (r7, *funRes));
|
|
|
|
|
|
2009-12-23 01:36:11 +01:00
|
|
|
-- r5x;
|
|
|
|
|
++ *funRes;
|
2010-12-10 02:55:40 +01:00
|
|
|
CHECK (5-1 == testVec[5]);
|
|
|
|
|
CHECK (7+1 == testVec[7]);
|
|
|
|
|
CHECK (7+1 == r7);
|
2009-12-23 01:36:11 +01:00
|
|
|
}
|
2009-12-20 04:33:24 +01:00
|
|
|
};
|
2010-12-10 02:55:40 +01:00
|
|
|
|
2009-12-20 04:33:24 +01:00
|
|
|
LAUNCHER (ItemWrapper_test, "unit common");
|
2010-12-10 02:55:40 +01:00
|
|
|
|
|
|
|
|
|
2009-12-21 05:44:29 +01:00
|
|
|
}}} // namespace lib::wrapper::test
|
2009-12-20 04:33:24 +01:00
|
|
|
|