OpenWalnut  1.4.0
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( 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( 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( 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( 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( 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( 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( 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( 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 
static void disableBacktrace()
Function disables backtraces.
Definition: WException.cpp:200
void testAdd(void)
Test the add features, also tests the type of properties added.
void testGetAndExistsAndFindRecursive(void)
Test the recursive search mechanism.
void testClone()
Tests the cloning functionality.
Indicates invalid property name.
WPropertyGroupBase::PropertyConstIterator PropertyConstIterator
The const iterator type of the container.
void testGetAndExistsAndFind(void)
Test the features to find and get properties.
void testRemove(void)
Test the removeProperty() method.
Class to manage properties of an object and to provide convenience methods for easy access and manipu...
Test WProperties.
void setTemporary1()
Helper function which simply sets the value above to true.
void setTemporary2()
Helper function which simply sets the value above to true.
Indicates that a given property is not unique in a group of properties.
void testClear(void)
Test the clear() method.
bool m_testTemporary2
A temporary holder for some value.
void testInstantiation(void)
Test instantiation, also test name and description and type (from WPropertyBase)
bool m_testTemporary1
A temporary holder for some value.
void testRecursiveSetByProperty(void)
Tests whether the properties children can be set by the WProperties::set call using a other WProperti...
boost::shared_ptr< WSharedObjectTicketRead< PropertyContainerType > > ReadTicket
Type for read tickets.
Definition: WSharedObject.h:64
Indicates invalid element access of a container.