wrote test: object smart pointer creation factory

This commit is contained in:
Fischlurch 2007-08-29 05:03:21 +02:00
parent d54b600382
commit 307945b629
7 changed files with 186 additions and 23 deletions

View file

@ -115,7 +115,7 @@ namespace cinelerra
CINELERRA_ERROR_DECLARE (LOGIC ); ///< contradiction to internal logic assumptions detected
CINELERRA_ERROR_DECLARE (FATAL ); ///< unable to cope with, internal logic floundered
CINELERRA_ERROR_DECLARE (CONFIG ); ///< execution aborted due to misconfiguration
CINELERRA_ERROR_DECLARE (STATE ); ///< unforseen internal state
CINELERRA_ERROR_DECLARE (STATE ); ///< unforeseen internal state
CINELERRA_ERROR_DECLARE (INVALID ); ///< invalid input or parameters encountered
CINELERRA_ERROR_DECLARE (EXTERNAL ); ///< failure in external service the application relies on
CINELERRA_ERROR_DECLARE (ASSERTION); ///< assertion failure

View file

@ -60,6 +60,8 @@ namespace cinelerra
* Note: non-virtual.
*/
SMP<T> operator() (){ return SMP<T> (new T ); };
typedef SMP<T> ptype;
private:
void operator= (const Factory&); // copy prohibited
@ -102,7 +104,7 @@ namespace cinelerra
*/
static void destroy (T* victim) { delete victim; };
public:
public:
shared_ptr<T> operator() () { return shared_ptr<T> (new T, &destroy ); }
};

View file

@ -33,20 +33,24 @@ namespace util
using std::string;
/** a family of util functions providing a "no value whatsoever" test */
inline bool isnil(const string& val)
/** a family of util functions providing a "no value whatsoever" test.
Works on strings and all STL containers, includes NULL test for pointers */
template <class CONT>
inline bool isnil(const CONT& container)
{
return 0 == val.length();
return container.empty();
}
inline bool isnil(const string* pval)
template <class CONT>
inline bool isnil(const CONT* pContainer)
{
return !pval || 0 == pval->length();
return !pContainer || pContainer->empty();
}
inline bool isnil(const char* pval)
template <>
inline bool isnil(const char* pCStr)
{
return !pval || 0 == std::strlen(pval);
return !pCStr || 0 == std::strlen(pCStr);
}

View file

@ -3,7 +3,9 @@ TESTING "Component Test Suite: ALL" ./test-components
TEST "Hello test" HelloWorld_test <<END
TEST "Hello test" HelloWorld_test 3 <<END
out: This is how the world ends...
out: This is how the world ends...
out: This is how the world ends...
return: 0
END
@ -45,6 +47,30 @@ out: Standard Cmdlineformat:one two
END
TEST "ExceptionError_test" ExceptionError_test <<END
out: caught: CINELERRA_ERROR_LIFE_AND_UNIVERSE:and everything? (don't panic)...the answer is: 42
out: caught cinelerra::Error: CINELERRA_ERROR_DERIVED:convoluted exception
out: caught error::Logic: CINELERRA_ERROR_FATAL:floundered (test-2).
out: caught error::Invalid: CINELERRA_ERROR_INVALID:invalid input or parameters (test-3).
out: caught cinelerra::Error: CINELERRA_ERROR_EXTERNAL:failure in external service (test-4).
out: caught std::runtime_error: test-5
out: caught std::exception: St9exception
out: intermediate handler caught: CINELERRA_ERROR_EXTERNAL:failure in external service (test-7).....will rethrow as error::State
out: caught cinelerra::Error: CINELERRA_ERROR_STATE:unforseen state -- caused by: CINELERRA_ERROR_EXTERNAL:failure in external service (test-7).
out: intermediate handler caught: CINELERRA_ERROR_EXTERNAL:failure in external service (test-8).....will rethrow as error::State
out: 2nd intermediate handler caught: CINELERRA_ERROR_STATE:unforseen state -- caused by: CINELERRA_ERROR_EXTERNAL:failure in external service (test-8).....will rethrow as error::Config
out: caught cinelerra::Error: CINELERRA_ERROR_CONFIG:misconfiguration -- caused by: CINELERRA_ERROR_EXTERNAL:failure in external service (test-8).
END
TEST "Factory_test" Factory_test 5 <<END
out: ctor TargetObj(5) successfull
out: now the smart-ptr has refcount=3
out: .....TargetObj(5): data="*****", array[5]={0,1,2,3,4,}
out: dtor ~TargetObj(5) successfull
END
TEST "TestOption_test" TestOption_test <<END
out: Testing invocation with cmdline: ...
out: --> Testgroup=ALL
@ -79,7 +105,3 @@ out: --> Testgroup=TestGroupID
out: --> Test-ID =SingleTestID
out: --> remaining=SingleTestID spam --eggs
END
TEST "Factory_test" Factory_test <<END
END

View file

@ -22,6 +22,20 @@
#include "common/test/run.hpp"
#include "common/factory.hpp"
#include "common/util.hpp"
#include <boost/algorithm/string.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/format.hpp>
#include <iostream>
using boost::algorithm::join;
using boost::lexical_cast;
using boost::format;
using util::isnil;
using std::string;
using std::cout;
namespace cinelerra
@ -29,28 +43,122 @@ namespace cinelerra
namespace test
{
class ObjFactory;
/**
* Target object to be created by the Test-Factory
* Target object to be created by the Test-Factory.
* Allocates a variable amount of additional heap memory
* and prints diagnostic messages.
*/
class TargetObj
{
uint cnt_;
string* heapData_;
string* heapArray_;
TargetObj(uint num)
: cnt_ (num),
heapData_ (new string(num,'*')),
heapArray_ (new string[num])
{
for (uint i=0; i<cnt_; ++i)
heapArray_[i] = lexical_cast<string>(i);
cout << format("ctor TargetObj(%i) successfull\n") % cnt_;
}
~TargetObj() throw()
{
delete heapData_;
delete[] heapArray_;
cout << format("dtor ~TargetObj(%i) successfull\n") % cnt_;
}
friend class ObjFactory;
public:
static ObjFactory create;
operator string () const
{
string array_contents = "{";
for (uint i=0; i<cnt_; ++i)
array_contents += heapArray_[i]+",";
array_contents+="}";
return str (format(".....TargetObj(%1%): data=\"%2%\", array[%1%]=%3%")
% cnt_
% *heapData_
% array_contents
);
}
};
/**********************************************************
* @test the various object creation factories
/** Test-Factory specialized to create TargetObj instances
* using the 1-argument constructor TargetObj::TargetObj(int).
* It will create boost::shared_ptr instances, because
* factory::RefcountPtr was parametrized with this smart pointer type.
* @note ObjFactory can use the private constructor because it's a friend.
*/
class ObjFactory : public factory::RefcountPtr<TargetObj>
{
static void destroy (TargetObj* victim) { delete victim; };
public:
/** specialized Factory method for creating TargetObj instances.
* Here, we invoke a special constructor, but basically we could
* do everything we want, creating instances of sub classes,
* registering objects etc. Further, we could have used a
* custom allocator or a special deleter function.
*/
ptype operator() (uint param){ return ptype (new TargetObj (param), &destroy); };
};
/** shorthand for the created smart-pointer class,
* here it's a (refcounting) boost::shared_ptr
*/
typedef ObjFactory::ptype pTarget;
ObjFactory TargetObj::create;
/*******************************************************************
* @test the basic object creation Factory behaviour: We declared
* a static field TargetObj::create to be a ObjFactory. So,
* by invoking this functor, we get a boost::shared_ptr
* wrapping a new TargetObj instance. From this we copy
* further shared-ptrs, invoke a member function and
* finally, when leaving the scope, our TargetObj
* will be destroyed automatically.
* @see cinelerra::Factory
* @todo still to be written...
*/
class Factory_test : public Test
{
virtual void run(Arg arg)
{
uint num= isnil(arg)? 1 : lexical_cast<uint>(arg[1]);
pTarget p1 (TargetObj::create (num));
pTarget p2 (p1);
pTarget p3 = p2;
cout << "now the smart-ptr has refcount=" << p1.use_count() << "\n"
<< string (*p3) << "\n";
}
};
/** Register this test class to be invoked in some test groups (suites) */
Launch<Factory_test> run_Factory_test("Factory_test","unit common");
/** Register this test class... */
LAUNCHER (Factory_test, "unit common");

View file

@ -24,6 +24,12 @@
#include <iostream>
#include "common/test/run.hpp"
#include "common/util.hpp"
using util::isnil;
#include <boost/lexical_cast.hpp>
using boost::lexical_cast;
namespace cinelerra
{
@ -38,7 +44,10 @@ namespace cinelerra
{
virtual void run(Arg arg)
{
greeting();
int num= isnil(arg)? 1 : lexical_cast<int> (arg[1]);
for ( ; 0 < num-- ; )
greeting();
}
void greeting()

View file

@ -707,7 +707,7 @@ The next point is allocation failures. These are possible by C/C++ standard but
</pre>
</div>
<div title="ErrorHandling-Cpp" modifier="Ichthyostega" created="200708140640" changecount="1">
<div title="ErrorHandling-Cpp" modifier="Ichthyostega" modified="200708290301" created="200708140640" changecount="3">
<pre>Basically, the C++ error handling techniques are layered on top of the [[C solution|ErrorHandling-C]].
!Proposal:
We use a common base class for all our application specific exceptions. These exceptions can be thought of as a classification of error situations, thus the hierarchical approach. The purpose of throwing such a //classified exception// is
@ -716,8 +716,26 @@ We use a common base class for all our application specific exceptions. These ex
!!Requirements for the Exception Interface
* a means for capturing and transporting detail informations
* the possibility to link to the ''root cause'' of an exception, even after having passed several subsystem barriers.
* the possibility to get at the ''root cause'' of an exception, even after having passed several subsystem barriers.
* getting standardized error messages automatically
!!provided features
The C++ errorhandling Classes and functions can be found in {{{common/error.hpp}}} (not to be confused with the elementary C errorhandling of the cinelerra support lib {{{lib/error.h}}}. See also the &quot;exceptionerrortest.cpp&quot;
* the constructor of the Exception base class will set the C-style error flag as well. Obviously, when an exception gets caught and handled, this error-flag should be reset (and this is the responsibility of the handler).
* we add a __unknown()__ handler which will print additional diagnostics.
* the Exception class has a diagnostic message intended for developers and a friendly message for the user. It is encouraged to write a detailed description of each error situation right into a string constant passed to the exception object ctor. This will serve the purpose of documenting the error situation in the source code and at the same time help diagnosis.
* there is a variant of the constructor taking a reference to an std::exception. This is intended for //chained exceptions//. Whenever an handler catches an exception, but then decides to rethrow it with different classification, the original exception object should be passed on by using this constructor, so it's {{{what()}}} message can be preserved and will be included in the final log entry. While this may look like overkill in a small example, it is a very helpful facility in a larger layered application, where it is often difficult to spot the original cause of an exception encountered.
* for each mayor category of Exception subclasses, we define a C-style error constant. The client code is free to define further detailed error constants and Exception subclasses.
* to help defining Exception subclasses, a macro {{{CINELERRA_EXCEPTION_DECLARE}}} is provided.
!!!basic Exception categories
|!category|!description|
|error::Logic| contradiction to internal logic assumptions detected|
|error::Fatal| special subclass of Logic: situation can't be handled, internal logic floundered |
|error::Config| execution aborted due to misconfiguration |
|error::State| unforeseen internal state |
|error::Invalid| invalid input or parameters encountered |
|error::External| failure in external service the application relies on |
</pre>
</div>
<div title="FullScreenPlugin" modifier="CehTeh" modified="200706110313" created="200607241016" tags="systemConfig lewcidExtension" server.type="file" server.host="file:///home/ct/.homepage/home.html" server.page.revision="200706110313">