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