]> git.mxchange.org Git - simgear.git/blob - simgear/props/propertyObject_test.cxx
scenery: Really, most people don't care for the noise.
[simgear.git] / simgear / props / propertyObject_test.cxx
1 #ifdef HAVE_CONFIG_H
2 #  include <simgear_config.h>
3 #endif
4
5 #ifdef NDEBUG
6 // Always enable DEBUG mode in test application, otherwise "assert" test
7 // statements have no effect and don't actually test anything (catch 17 ;-) ).
8 #undef NDEBUG
9 #endif
10
11 #include <simgear/compiler.h>
12
13 #include <iostream>
14 #include <cassert>
15 #include <cstring>
16
17 // working around MSVC weirdness with props.hxx and SGMathFwd
18 #include <simgear/math/SGMath.hxx>
19
20 #include "propertyObject.hxx"
21
22 #include <simgear/structure/exception.hxx>
23
24 using std::cout;
25 using std::cerr;
26 using std::endl;
27
28 using namespace simgear;
29
30
31 SGPropertyNode* testRoot = NULL;
32
33 bool testBasic()
34 {
35   PropertyObject<int> aBar("a/bar");
36   assert(aBar == 1234);
37
38
39   PropertyObject<int> aWib("a/wib"); // doesn't exist
40   aWib = 999; // create + set
41   assert(aWib == 999); // read back
42   assert(testRoot->getIntValue("a/wib") == 999);
43
44   assert(aWib < 1000);
45   assert(998 < aWib);
46
47   PropertyObject<double> aFoo("a/foo");
48   assert(aFoo == 12.0);
49
50   double ff(aFoo);
51   assert(ff == 12.0); // comparison with literal
52   if (ff != 12.0) cout << "Error: a/foo != 12!" << endl;
53   
54   const float fff(12.0f);
55   assert(fff == aFoo); // comparion with float value
56   if (fff != aFoo) cout << "Error: 12 != a/foo" << endl;
57
58   return true;
59 }
60
61 void testRelative()
62 {
63   SGPropertyNode* n = testRoot->getNode("a");
64   assert(n);
65
66   PropertyObject<int> a1(n, "bar");
67   assert(a1 == 1234);
68
69   PropertyObject<int> a5(n, "some/child/path");
70   a5 = 4321;
71   assert(n->getIntValue("some/child/path") == 4321);
72
73   SGPropertyNode* m = testRoot->getNode("a/alice");
74   PropertyObject<std::string> a4(m);
75   assert(a4 == "aaaa");
76 }
77
78 void testString()
79 {
80   PropertyObject<std::string> sp("a/alice");
81   assert(sp == "aaaa"); // read
82
83   sp = "xxxx"; // assignment from char* literal
84   assert(!strcmp(testRoot->getStringValue("a/alice"), "xxxx"));
85
86   std::string d = "yyyy";
87   sp = d; // assignment from std::string
88   assert(sp == d);  // comaprisom with std::string
89
90   std::string e(sp), f; // check construction-conversion
91   assert(e == "yyyy");
92   f = sp; // assignment conversion
93   assert(f == "yyyy");
94 }
95
96 void testAssignment()
97 {
98   PropertyObject<int> a1("a/bar");
99   PropertyObject<int> a2("b/blah/foo[1]");
100
101  // ensure assignment between property objects copies values, *not*
102  // copies the property reference
103   a2 = a1 = 88; // a2 should *not* point to a/bar after this!
104   assert(testRoot->getIntValue("b/blah/foo[1]") == 88);
105   assert(a2.node() == testRoot->getNode("b/blah/foo[1]"));
106   a2 = 99;
107   assert(a2 == 99);
108   assert(a1 == 88);
109
110   PropertyObject<int> a3(a1);
111   assert(a1.node() == a3.node());
112   a3 = 44;
113   assert(a1 == 44);
114
115 }
116
117 void testSTLContainer()
118 {
119   std::vector<PropertyObject<int> > vec;
120 // enlarging the vec causes the copy-constructor to be called,
121 // when the storage is re-sized
122   vec.push_back(PropertyObject<int>("a/thing[0]")); 
123   vec.push_back(PropertyObject<int>("a/thing[1]")); 
124   vec.push_back(PropertyObject<int>("a/thing[2]")); 
125   vec.push_back(PropertyObject<int>("a/thing[3]")); 
126
127   vec[0] = 1234;
128   vec[1] = 2345;
129   vec[2] = 6789;
130   vec[3] = -11;
131
132   assert(testRoot->getIntValue("a/thing[2]") == 6789);
133   assert(testRoot->getIntValue("a/thing[3]") == -11);
134   assert(testRoot->getIntValue("a/thing[0]") == 1234);
135
136   for (int i=0; i<100; ++i) {
137     char path[128];
138     ::snprintf(path, 128, "d/foo[%d]", i);
139     vec.push_back(PropertyObject<int>(path));
140     testRoot->setIntValue(path, i * 4);
141   }
142
143   assert(vec[0] == 1234);
144   assert(vec[3] == -11);
145 }
146
147 void testReadMissing()
148 {
149   PropertyObject<bool> b("not/found/honest");
150
151   try {
152     bool v = b;
153     assert(false && "read of missing property didn't throw");
154     (void) v; // don't warn about unused variable
155   } catch (sg_exception& e) {
156     // expected
157   }
158
159   PropertyObject<std::string> s("also/missing");
160   try {
161     std::string s2 = s;
162   } catch (sg_exception& e) {
163     // expected
164   }
165 }
166
167 void testCreate()
168 {
169   PropertyObject<bool> a = PropertyObject<bool>::create("a/lemon", true);
170   assert(a == true);
171   assert(testRoot->getBoolValue("a/lemon") == true);
172   
173
174   PropertyObject<int> b(PropertyObject<int>::create("a/pear", 3142));
175   assert(b == 3142);
176   
177   PropertyObject<std::string> c(PropertyObject<std::string>::create("a/lime", "fofofo"));
178   assert(c == "fofofo");
179
180 // check overloads for string version
181   SGPropertyNode* n = testRoot->getNode("b", true);
182   PropertyObject<std::string> d(PropertyObject<std::string>::create(n, "grape", "xyz"));
183   assert(!strcmp(testRoot->getStringValue("b/grape"), "xyz"));
184   
185   
186 }
187
188 int main(int argc, char* argv[])
189 {
190         testRoot = new SGPropertyNode();
191         simgear::PropertyObjectBase::setDefaultRoot(testRoot);
192
193 // create some properties 'manually'
194         testRoot->setDoubleValue("a/foo", 12.0);
195         testRoot->setIntValue("a/bar", 1234);
196         testRoot->setBoolValue("a/flags[3]", true);
197   testRoot->setStringValue("a/alice", "aaaa");
198
199 // basic reading / setting
200         if (!testBasic()) {
201                 return EXIT_FAILURE;            
202         }
203
204   testRelative();
205   testReadMissing();
206   testString();
207   testAssignment();
208   testSTLContainer();
209   testCreate();
210
211   return EXIT_SUCCESS;
212 }
213