OpenWalnut  1.3.1
WProperties_test.h
1 //---------------------------------------------------------------------------
2 //
3 // Project: OpenWalnut ( http://www.openwalnut.org )
4 //
5 // Copyright 2009 OpenWalnut Community, BSV@Uni-Leipzig and CNCF@MPI-CBS
6 // For more information see http://www.openwalnut.org/copying
7 //
8 // This file is part of OpenWalnut.
9 //
10 // OpenWalnut is free software: you can redistribute it and/or modify
11 // it under the terms of the GNU Lesser General Public License as published by
12 // the Free Software Foundation, either version 3 of the License, or
13 // (at your option) any later version.
14 //
15 // OpenWalnut is distributed in the hope that it will be useful,
16 // but WITHOUT ANY WARRANTY; without even the implied warranty of
17 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 // GNU Lesser General Public License for more details.
19 //
20 // You should have received a copy of the GNU Lesser General Public License
21 // along with OpenWalnut. If not, see <http://www.gnu.org/licenses/>.
22 //
23 //---------------------------------------------------------------------------
24 
25 #ifndef WPROPERTIES_TEST_H
26 #define WPROPERTIES_TEST_H
27 
28 #include <string>
29 
30 #include <cxxtest/TestSuite.h>
31 
32 #include "../WProperties.h"
33 #include "../exceptions/WPropertyNotUnique.h"
34 #include "../exceptions/WPropertyUnknown.h"
35 #include "../exceptions/WPropertyNameMalformed.h"
36 
37 /**
38  * Test WProperties
39  */
40 class WPropertiesTest : public CxxTest::TestSuite
41 {
42 public:
43  /**
44  * A temporary holder for some value.
45  */
47 
48  /**
49  * A temporary holder for some value.
50  */
52 
53  /**
54  * Helper function which simply sets the value above to true. It is used to test some conditions here.
55  */
57  {
58  m_testTemporary1 = true;
59  }
60 
61  /**
62  * Helper function which simply sets the value above to true. It is used to test some conditions here.
63  */
65  {
66  m_testTemporary2 = true;
67  }
68 
69  /**
70  * Test instantiation, also test name and description and type (from WPropertyBase)
71  */
72  void testInstantiation( void )
73  {
74  boost::shared_ptr< WProperties > p;
75  TS_ASSERT_THROWS_NOTHING( p = boost::shared_ptr< WProperties >( new WProperties( "hey", "you" ) ) );
76 
77  // test names
78  TS_ASSERT( p->getName() == "hey" );
79  TS_ASSERT( p->getDescription() == "you" );
80  TS_ASSERT( p->getType() == PV_GROUP );
81 
82  TS_ASSERT_THROWS_NOTHING( p.reset() );
83  }
84 
85  /**
86  * Test the add features, also tests the type of properties added
87  */
88  void testAdd( void )
89  {
90  WException::disableBacktrace(); // in tests, turn of backtrace globally
91 
92  boost::shared_ptr< WProperties > p = boost::shared_ptr< WProperties >( new WProperties( "hey", "you" ) );
93 
94  // add some new properties
95  boost::shared_ptr< WPropertyBase > p1 = p->addProperty( "1", "test1", true );
96  boost::shared_ptr< WPropertyBase > p2 = p->addProperty( "2", "test2", 1 );
97  boost::shared_ptr< WPropertyBase > p3 = p->addProperty( "3", "test3", 1.0 );
98 
99  // add a malformed (name) property
100  // The name is malformed since the "/" is used as group separator
101  TS_ASSERT_THROWS( p->addProperty( "4/5", "test4", 1.0 ), WPropertyNameMalformed );
102 
103  // this should have created 3 props
104  TS_ASSERT( p->m_properties.getReadTicket()->get().size() == 3 );
105 
106  // ensure that it has created the correct types:
107  TS_ASSERT( p1->getType() == PV_BOOL );
108  TS_ASSERT( p2->getType() == PV_INT );
109  TS_ASSERT( p3->getType() == PV_DOUBLE );
110 
111  // try to add another property with the same name ( regardless of actual type )
112  TS_ASSERT_THROWS( p->addProperty( "1", "test1", 1.0 ), WPropertyNotUnique );
113  }
114 
115  /**
116  * Test the clear() method
117  */
118  void testClear( void )
119  {
120  WException::disableBacktrace(); // in tests, turn of backtrace globally
121 
122  boost::shared_ptr< WProperties > p = boost::shared_ptr< WProperties >( new WProperties( "hey", "you" ) );
123 
124  // add some new properties
125  boost::shared_ptr< WPropertyBase > p1 = p->addProperty( "1", "test1", true );
126  boost::shared_ptr< WPropertyBase > p2 = p->addProperty( "2", "test2", 1 );
127  boost::shared_ptr< WPropertyBase > p3 = p->addProperty( "3", "test3", 1.0 );
128 
129  // this should have created 3 props
130  TS_ASSERT( p->m_properties.getReadTicket()->get().size() == 3 );
131 
132  // clear
133  TS_ASSERT_THROWS_NOTHING( p->clear() );
134  TS_ASSERT( p->m_properties.getReadTicket()->get().size() == 0 );
135 
136  // multiple clear should not cause any error
137  TS_ASSERT_THROWS_NOTHING( p->clear() );
138  }
139 
140  /**
141  * Test the removeProperty() method
142  */
143  void testRemove( void )
144  {
145  WException::disableBacktrace(); // in tests, turn of backtrace globally
146 
147  boost::shared_ptr< WProperties > p = boost::shared_ptr< WProperties >( new WProperties( "hey", "you" ) );
148 
149  // add some new properties
150  boost::shared_ptr< WPropertyBase > p1 = p->addProperty( "1", "test1", true );
151  boost::shared_ptr< WPropertyBase > p2 = p->addProperty( "2", "test2", 1 );
152  boost::shared_ptr< WPropertyBase > p3 = p->addProperty( "3", "test3", 1.0 );
153 
154  // this should have created 3 props
155  TS_ASSERT( p->m_properties.getReadTicket()->get().size() == 3 );
156 
157  // remove a property
158  TS_ASSERT_THROWS_NOTHING( p->removeProperty( p2 ) );
159  TS_ASSERT( p->m_properties.getReadTicket()->get().size() == 2 );
160 
161  // remove a prop which is not in the list
162  TS_ASSERT_THROWS_NOTHING( p->removeProperty( p2 ) );
163  TS_ASSERT( p->m_properties.getReadTicket()->get().size() == 2 );
164  }
165 
166  /**
167  * Tests whether the properties children can be set by the WProperties::set call using a other WProperties instance
168  */
170  {
171  WException::disableBacktrace(); // in tests, turn of backtrace globally
172 
173  // some props we can use as target
174  boost::shared_ptr< WProperties > t = boost::shared_ptr< WProperties >( new WProperties( "hey", "you" ) );
175 
176  // add some new properties
177  WPropBool tp1 = t->addProperty( "p1", "", true );
178  WPropInt tp2 = t->addProperty( "p2", "", 1 );
179  WPropGroup tg1 = t->addPropertyGroup( "g1", "" );
180  WPropDouble tp3 = tg1->addProperty( "p3", "", 1.0 );
181  WPropDouble tp4 = t->addProperty( "p4", "", 10.0 );
182 
183  // create a group we can use as source
184  boost::shared_ptr< WProperties > s = boost::shared_ptr< WProperties >( new WProperties( "hey", "you" ) );
185 
186  // add some new properties
187  WPropBool sp1 = s->addProperty( "p1", "", false );
188  WPropInt sp2 = s->addProperty( "p2__", "", 10 ); // NOTE: the name is different
189  WPropGroup sg1 = s->addPropertyGroup( "g1", "" );
190  WPropDouble sp3 = sg1->addProperty( "p3", "", 2.0 );
191  WPropInt sp4 = s->addProperty( "p4", "", 2 );
192 
193  // let us set t using the values in s
194  t->set( s );
195 
196  // lets check the values:
197  // tp1 should be set to the value of sp1
198  TS_ASSERT( tp1->get() == sp1->get() );
199  // tp2 should be untouched as no corresponding property exists in s
200  TS_ASSERT( tp2->get() == 1 );
201  // the child of the group g1 should be set to sp3
202  TS_ASSERT( tp3->get() == sp3->get() );
203  // tp4 must not be sp4 even if the names match. The type is a mismatch
204  TS_ASSERT( tp4->get() == 10.0 );
205  }
206 
207  /**
208  * Test the features to find and get properties.
209  */
211  {
212  WException::disableBacktrace(); // in tests, turn of backtrace globally
213 
214  boost::shared_ptr< WProperties > p = boost::shared_ptr< WProperties >( new WProperties( "hey", "you" ) );
215 
216  // add some new properties
217  boost::shared_ptr< WPropertyBase > p1 = p->addProperty( "1", "test1", true );
218  boost::shared_ptr< WPropertyBase > p2 = p->addProperty( "2", "test2", 1 );
219  boost::shared_ptr< WPropertyBase > p3 = p->addProperty( "3", "test3", 1.0 );
220 
221  /////////////
222  // exists
223 
224  // now, try to check whether a property exists:
225  TS_ASSERT( p->existsProperty( "1" ) );
226  TS_ASSERT( !p->existsProperty( "shouldNotBeInTheList" ) );
227 
228  /////////////
229  // find
230 
231  // same for find. Find does not throw an exception if the property does not exist! It simply returns it or NULL
232  boost::shared_ptr< WPropertyBase > someProp;
233  TS_ASSERT_THROWS_NOTHING( someProp = p->findProperty( "1" ) );
234  // The property exists -> return value is not NULL
235  TS_ASSERT( someProp );
236 
237  // now for an unexisting one
238  TS_ASSERT_THROWS_NOTHING( someProp = p->findProperty( "shouldNotBeInTheList" ) );
239  // The property exists -> return value is not NULL
240  TS_ASSERT( !someProp );
241 
242  /////////////
243  // get
244 
245  // the getProperty method throws an exception if the property has not been found.
246 
247  // this one exists -> no exception
248  TS_ASSERT_THROWS_NOTHING( someProp = p->getProperty( "1" ) );
249  TS_ASSERT( someProp );
250 
251  // this one does not exist
252  TS_ASSERT_THROWS( someProp = p->getProperty( "shouldNotBeInTheList" ), WPropertyUnknown );
253  }
254 
255  /**
256  * Test the recursive search mechanism.
257  */
259  {
260  boost::shared_ptr< WProperties > p = boost::shared_ptr< WProperties >( new WProperties( "hey", "you" ) );
261  boost::shared_ptr< WProperties > psub = p->addPropertyGroup( "heySub", "you" );
262 
263  // add some new properties
264  boost::shared_ptr< WPropertyBase > p1 = p->addProperty( "1", "test1", true );
265  boost::shared_ptr< WPropertyBase > p2 = p->addProperty( "2", "test2", 1 );
266  boost::shared_ptr< WPropertyBase > p3 = psub->addProperty( "3", "test3", 1.0 );
267  boost::shared_ptr< WPropertyBase > p4 = psub->addProperty( "4", "test4", std::string( "hello" ) );
268 
269  // insert a prop with the same name as a sub property
270  TS_ASSERT_THROWS( p->addProperty( "heySub", "test1", true ), WPropertyNotUnique );
271 
272  /////////////
273  // exists
274 
275  // try to find a property of a group in the parent: should fail
276  TS_ASSERT( !p->existsProperty( "3" ) );
277  TS_ASSERT( !p->existsProperty( "4" ) );
278  TS_ASSERT( psub->existsProperty( "3" ) );
279  TS_ASSERT( psub->existsProperty( "4" ) );
280  TS_ASSERT( !psub->existsProperty( "1" ) );
281  TS_ASSERT( !psub->existsProperty( "2" ) );
282 
283  // search it with the proper name:
284  TS_ASSERT( p->existsProperty( "heySub/3" ) );
285  TS_ASSERT( !p->existsProperty( "heySub/1" ) );
286 
287  /////////////
288  // find
289 
290  // search it with the proper name:
291  TS_ASSERT( p3 == p->findProperty( "heySub/3" ) );
292  TS_ASSERT( p4 == p->findProperty( "heySub/4" ) );
293 
294  // ensure nothing is found if wrong name is specified
295  TS_ASSERT( boost::shared_ptr< WPropertyBase >() == p->findProperty( "heySub/1" ) );
296 
297  /////////////
298  // get
299 
300  TS_ASSERT_THROWS_NOTHING( p->getProperty( "heySub/3" ) );
301  TS_ASSERT_THROWS_NOTHING( p->getProperty( "heySub/4" ) );
302 
303  // ensure nothing is found if wrong name is specified
304  TS_ASSERT_THROWS( p->getProperty( "heySub/1" ), WPropertyUnknown );
305  }
306 
307  /**
308  * Tests the cloning functionality.
309  */
310  void testClone()
311  {
312  /////////////////////
313  // Clone
314 
315  boost::shared_ptr< WProperties > orig = boost::shared_ptr< WProperties >( new WProperties( "hey", "you" ) );
316  boost::shared_ptr< WProperties > clone = orig->clone()->toPropGroup();
317 
318  // test that toPropGroup worked and both are different
319  TS_ASSERT( clone.get() );
320  TS_ASSERT( orig != clone );
321 
322  /////////////////////
323  // Conditions
324 
325  // is there a new condition? This has to be the case, this mainly situated in WPropertyBase
326  TS_ASSERT( orig->getUpdateCondition() != clone->getUpdateCondition() );
327 
328  // update of property list does not modify the original
329  clone->addProperty( "1", "test1", 1.0 );
330  TS_ASSERT( clone->m_properties.getReadTicket()->get().size() == 1 );
331  TS_ASSERT( orig->m_properties.getReadTicket()->get().size() == 0 );
332 
333  // does the condition fire on add?
334  // first, register some callbacks to test it
335  m_testTemporary1 = false;
336  m_testTemporary2 = false;
337  orig->getUpdateCondition()->subscribeSignal( boost::bind( &WPropertiesTest::setTemporary1, this ) );
338  clone->getUpdateCondition()->subscribeSignal( boost::bind( &WPropertiesTest::setTemporary2, this ) );
339 
340  // add a bool property -> conditions fired?
341  clone->addProperty( "2", "test2", false );
342 
343  // the first should not fire, but the condition of the clone
344  TS_ASSERT( m_testTemporary1 == false );
345  TS_ASSERT( m_testTemporary2 == true );
346 
347  // the same thing but vice versa
348  m_testTemporary1 = false;
349  m_testTemporary2 = false;
350  orig->addProperty( "1", "test1", false );
351  // this time, the first should fire but not the second
352  TS_ASSERT( m_testTemporary2 == false );
353  TS_ASSERT( m_testTemporary1 == true );
354 
355  /////////////////////
356  // cloned list
357 
358  // the clone now contains some properties -> clone it again and check the list of contained properties
359  boost::shared_ptr< WProperties > cloneClone = clone->clone()->toPropGroup();
360 
361  // same size?
362  TS_ASSERT( clone->m_properties.getReadTicket()->get().size() == 2 );
363  TS_ASSERT( cloneClone->m_properties.getReadTicket()->get().size() == 2 );
364 
365  WProperties::PropertySharedContainerType::ReadTicket t = clone->getProperties();
366 
367  // iterate the original and check that there exists a cloned property in the cloned one
368  for( WProperties::PropertyConstIterator iter = t->get().begin(); iter != t->get().end(); ++iter )
369  {
370  // ensure there is a corresponding property in cloneClone
371  boost::shared_ptr< WPropertyBase > p = cloneClone->findProperty( ( *iter )->getName() );
372  TS_ASSERT( p ); // found?
373  TS_ASSERT( p != ( *iter ) ); // is it really a clone? (the cloning functionality of WPropertyVariable is tested separately
374  }
375  }
376 };
377 
378 #endif // WPROPERTIES_TEST_H
379 
380