Files
simgear/simgear/props/propertyObject_test.cxx
T
ThorstenB 44db6d9e44 Move vector property templates to separate header file.
Fixes the "weirdness" with MSVC complaining about incomplete class specs,
since forward declarations (SGMathFwd.hxx) are used in props.hxx only.
Only the few extended (vector) property templates require including the
full SGMath.hxx (with MSVC) - and these are used in few places.
2012-05-05 00:07:07 +02:00

212 lines
4.9 KiB
C++

#ifdef HAVE_CONFIG_H
# include <simgear_config.h>
#endif
#ifdef NDEBUG
// Always enable DEBUG mode in test application, otherwise "assert" test
// statements have no effect and don't actually test anything (catch 17 ;-) ).
#undef NDEBUG
#endif
#include <simgear/compiler.h>
#include <iostream>
#include <cassert>
#include <cstdlib>
#include <cstring>
#include "propertyObject.hxx"
#include <simgear/structure/exception.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
if (ff != 12.0) cout << "Error: a/foo != 12!" << endl;
const float fff(12.0f);
assert(fff == aFoo); // comparion with float value
if (fff != aFoo) cout << "Error: 12 != a/foo" << endl;
return true;
}
void testRelative()
{
SGPropertyNode* n = testRoot->getNode("a");
assert(n);
PropertyObject<int> a1(n, "bar");
assert(a1 == 1234);
PropertyObject<int> a5(n, "some/child/path");
a5 = 4321;
assert(n->getIntValue("some/child/path") == 4321);
SGPropertyNode* m = testRoot->getNode("a/alice");
PropertyObject<std::string> a4(m);
assert(a4 == "aaaa");
}
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");
(void) v; // don't warn about unused variable
} catch (sg_exception& e) {
// expected
}
PropertyObject<std::string> s("also/missing");
try {
std::string s2 = s;
} catch (sg_exception& e) {
// expected
}
}
void testCreate()
{
PropertyObject<bool> a = PropertyObject<bool>::create("a/lemon", true);
assert(a == true);
assert(testRoot->getBoolValue("a/lemon") == true);
PropertyObject<int> b(PropertyObject<int>::create("a/pear", 3142));
assert(b == 3142);
PropertyObject<std::string> c(PropertyObject<std::string>::create("a/lime", "fofofo"));
assert(c == "fofofo");
// check overloads for string version
SGPropertyNode* n = testRoot->getNode("b", true);
PropertyObject<std::string> d(PropertyObject<std::string>::create(n, "grape", "xyz"));
assert(!strcmp(testRoot->getStringValue("b/grape"), "xyz"));
}
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;
}
testRelative();
testReadMissing();
testString();
testAssignment();
testSTLContainer();
testCreate();
return EXIT_SUCCESS;
}