PropertyObject enhancements, unit-test for make check

This commit is contained in:
James Turner
2010-11-20 02:49:04 -08:00
parent 9d4f0f5824
commit ac535de2fa
5 changed files with 208 additions and 33 deletions

View File

@@ -1,2 +1,3 @@
props_test
propertyObject_test

View File

@@ -17,7 +17,8 @@ libsgprops_a_SOURCES = \
AtomicChangeListener.cxx \
propertyObject.cxx
check_PROGRAMS = props_test
check_PROGRAMS = props_test propertyObject_test
TESTS = propertyObject_test
props_test_SOURCES = props_test.cxx
props_test_LDADD = \
@@ -27,6 +28,15 @@ props_test_LDADD = \
$(top_builddir)/simgear/debug/libsgdebug.a \
$(top_builddir)/simgear/structure/libsgstructure.a
propertyObject_test_SOURCES = propertyObject_test.cxx
propertyObject_test_LDADD = \
libsgprops.a \
$(top_builddir)/simgear/xml/libsgxml.a \
$(top_builddir)/simgear/misc/libsgmisc.a \
$(top_builddir)/simgear/debug/libsgdebug.a \
$(top_builddir)/simgear/structure/libsgstructure.a
if HAVE_FRAMEWORK_OSG
props_test_LDFLAGS = $(openthreads_FRAMEWORK)
else

View File

@@ -31,6 +31,14 @@ void PropertyObjectBase::setDefaultRoot(SGPropertyNode* aRoot)
static_defaultRoot = aRoot;
}
PropertyObjectBase::PropertyObjectBase(const PropertyObjectBase& aOther) :
_base(aOther._base),
_path(aOther._path),
_prop(aOther._prop)
{
}
PropertyObjectBase::PropertyObjectBase(const char* aChild) :
_base(NULL),
_path(aChild),
@@ -62,30 +70,3 @@ SGPropertyNode* PropertyObjectBase::node(bool aCreate) const
} // of namespace simgear
void test()
{
SGPropObjDouble foo("/bar/foo");
SGPropertyNode* zoob;
SGPropObjDouble foo2 = SGPropObjDouble::create(zoob, "foo2", 42.0);
foo = 1123.0;
foo2 = 43;
std::string s("lalala");
foo = "lalal";
SGPropObjString sp(zoob);
sp = "fooo";
s = sp;
SGPropObjBool bp("/some nice big path");
bp = false;
bp = 456;
int i5 = bp;
}

View File

@@ -29,6 +29,8 @@ class PropertyObjectBase
public:
static void setDefaultRoot(SGPropertyNode* aRoot);
PropertyObjectBase(const PropertyObjectBase& aOther);
PropertyObjectBase(const char* aChild);
PropertyObjectBase(SGPropertyNode* aNode, const char* aChild = NULL);
@@ -61,6 +63,12 @@ public:
}
// copy-constructor
PropertyObject(const PropertyObject<T>& aOther) :
PropertyObjectBase(aOther)
{
}
// create() form creates the property immediately
static PropertyObject<T> create(const char* aPath, T aValue)
{
@@ -86,7 +94,7 @@ public:
// conversion operators
operator T () const
{
SGPropertyNode* n = node(false);
SGPropertyNode* n = node();
if (!n) {
throw sg_exception("read of undefined property:", _path);
}
@@ -96,7 +104,7 @@ public:
T operator=(const T& aValue)
{
SGPropertyNode* n = node(true);
SGPropertyNode* n = PropertyObjectBase::node(true);
if (!n) {
return aValue;
}
@@ -105,6 +113,10 @@ public:
return aValue;
}
SGPropertyNode* node() const
{
return PropertyObjectBase::node(false);
}
}; // of template PropertyObject
@@ -130,7 +142,7 @@ public:
operator std::string () const
{
SGPropertyNode* n = node(false);
SGPropertyNode* n = node();
if (!n) {
throw sg_exception("read of undefined property:", _path);
}
@@ -140,7 +152,7 @@ public:
const char* operator=(const char* aValue)
{
SGPropertyNode* n = node(true);
SGPropertyNode* n = PropertyObjectBase::node(true);
if (!n) {
return aValue;
}
@@ -151,7 +163,7 @@ public:
std::string operator=(const std::string& aValue)
{
SGPropertyNode* n = node(true);
SGPropertyNode* n = PropertyObjectBase::node(true);
if (!n) {
return aValue;
}
@@ -160,6 +172,22 @@ public:
return aValue;
}
bool operator==(const char* value) const
{
std::string s(*this);
return (s == value);
}
bool operator==(const std::string& value) const
{
std::string s(*this);
return (s == value);
}
SGPropertyNode* node() const
{
return PropertyObjectBase::node(false);
}
private:
};

View File

@@ -0,0 +1,155 @@
#include <simgear/compiler.h>
#include <iostream>
#include <cassert>
#include <cstring>
#include "propertyObject.hxx"
using std::cout;
using std::cerr;
using std::endl;
using namespace simgear;
SGPropertyNode* testRoot = NULL;
bool testBasic()
{
PropertyObject<int> aBar("a/bar");
assert(aBar == 1234);
PropertyObject<int> aWib("a/wib"); // doesn't exist
aWib = 999; // create + set
assert(aWib == 999); // read back
assert(testRoot->getIntValue("a/wib") == 999);
assert(aWib < 1000);
assert(998 < aWib);
PropertyObject<double> aFoo("a/foo");
assert(aFoo == 12.0);
double ff(aFoo);
assert(ff == 12.0); // comparison with literal
const float fff(12.0f);
assert(fff == aFoo); // comparion with float value
return true;
}
void testString()
{
PropertyObject<std::string> sp("a/alice");
assert(sp == "aaaa"); // read
sp = "xxxx"; // assignment from char* literal
assert(!strcmp(testRoot->getStringValue("a/alice"), "xxxx"));
std::string d = "yyyy";
sp = d; // assignment from std::string
assert(sp == d); // comaprisom with std::string
std::string e(sp), f; // check construction-conversion
assert(e == "yyyy");
f = sp; // assignment conversion
assert(f == "yyyy");
}
void testAssignment()
{
PropertyObject<int> a1("a/bar");
PropertyObject<int> a2("b/blah/foo[1]");
// ensure assignment between property objects copies values, *not*
// copies the property reference
a2 = a1 = 88; // a2 should *not* point to a/bar after this!
assert(testRoot->getIntValue("b/blah/foo[1]") == 88);
assert(a2.node() == testRoot->getNode("b/blah/foo[1]"));
a2 = 99;
assert(a2 == 99);
assert(a1 == 88);
PropertyObject<int> a3(a1);
assert(a1.node() == a3.node());
a3 = 44;
assert(a1 == 44);
}
void testSTLContainer()
{
std::vector<PropertyObject<int> > vec;
// enlarging the vec causes the copy-constructor to be called,
// when the storage is re-sized
vec.push_back(PropertyObject<int>("a/thing[0]"));
vec.push_back(PropertyObject<int>("a/thing[1]"));
vec.push_back(PropertyObject<int>("a/thing[2]"));
vec.push_back(PropertyObject<int>("a/thing[3]"));
vec[0] = 1234;
vec[1] = 2345;
vec[2] = 6789;
vec[3] = -11;
assert(testRoot->getIntValue("a/thing[2]") == 6789);
assert(testRoot->getIntValue("a/thing[3]") == -11);
assert(testRoot->getIntValue("a/thing[0]") == 1234);
for (int i=0; i<100; ++i) {
char path[128];
::snprintf(path, 128, "d/foo[%d]", i);
vec.push_back(PropertyObject<int>(path));
testRoot->setIntValue(path, i * 4);
}
assert(vec[0] == 1234);
assert(vec[3] == -11);
}
void testReadMissing()
{
PropertyObject<bool> b("not/found/honest");
try {
bool v = b;
assert(false && "read of missing property didn't throw");
} catch (sg_exception& e) {
// expected
}
PropertyObject<std::string> s("also/missing");
try {
std::string s2 = s;
} catch (sg_exception& e) {
// expected
}
}
int main(int argc, char* argv[])
{
testRoot = new SGPropertyNode();
simgear::PropertyObjectBase::setDefaultRoot(testRoot);
// create some properties 'manually'
testRoot->setDoubleValue("a/foo", 12.0);
testRoot->setIntValue("a/bar", 1234);
testRoot->setBoolValue("a/flags[3]", true);
testRoot->setStringValue("a/alice", "aaaa");
// basic reading / setting
if (!testBasic()) {
return EXIT_FAILURE;
}
testReadMissing();
testString();
testAssignment();
testSTLContainer();
return EXIT_SUCCESS;
}