OpenWalnut  1.3.1
WPropertyVariable_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 WPROPERTYVARIABLE_TEST_H
26 #define WPROPERTYVARIABLE_TEST_H
27 
28 #include <string>
29 
30 #include <cxxtest/TestSuite.h>
31 
32 #include "../WPropertyVariable.h"
33 #include "../constraints/WPropertyConstraintMin.h"
34 #include "../constraints/WPropertyConstraintMax.h"
35 
36 #include "../exceptions/WPropertyNotUnique.h"
37 #include "../exceptions/WPropertyUnknown.h"
38 #include "../exceptions/WPropertyNameMalformed.h"
39 
40 /**
41  * Test WPropertyVariable
42  */
43 class WPropertyVariableTest : public CxxTest::TestSuite
44 {
45 public:
46  /**
47  * A temporary holder for some value.
48  */
50 
51  /**
52  * A temporary holder for some value.
53  */
55 
56  /**
57  * Helper function which simply sets the value above to true. It is used to test some conditions here.
58  */
60  {
61  m_testTemporary1 = true;
62  }
63 
64  /**
65  * Helper function which simply sets the value above to true. It is used to test some conditions here.
66  */
68  {
69  m_testTemporary2 = true;
70  }
71 
72  /**
73  * Test instantiation, also test name and description and type (from WPropertyBase)
74  */
75  void testInstantiation( void )
76  {
77  boost::shared_ptr< WPropertyVariable< bool > > p;
78  TS_ASSERT_THROWS_NOTHING( p = boost::shared_ptr< WPropertyVariable< bool > >( new WPropertyVariable< bool >( "hey", "you", false ) ) );
79 
80  // test names
81  TS_ASSERT( p->getName() == "hey" );
82  TS_ASSERT( p->getDescription() == "you" );
83  TS_ASSERT( p->getType() == PV_BOOL );
84 
85  TS_ASSERT_THROWS_NOTHING( p.reset() );
86  }
87 
88  /**
89  * Tests that only properties with proper names can be created
90  */
91  void testNameConvention( void )
92  {
93  WException::disableBacktrace(); // in tests, turn of backtrace globally
94 
95  boost::shared_ptr< WPropertyVariable< bool > > p;
96  TS_ASSERT_THROWS( p = boost::shared_ptr< WPropertyVariable< bool > >( new WPropertyVariable< bool >( "hey/you", "you", false ) ),
98  }
99 
100  /**
101  * Tests the cloning functionality.
102  */
103  void testClone()
104  {
105  WException::disableBacktrace(); // in tests, turn of backtrace globally
106 
107  /////////////////////////
108  // Create an original
109 
110  // create an int property
111  boost::shared_ptr< WPropertyVariable< int > > p =
112  boost::shared_ptr< WPropertyVariable< int > >( new WPropertyVariable< int >( "hey", "you", false ) );
113  // add a min/max prop
116  p->set( 5 );
117 
118  /////////////////////////
119  // Clone it
120 
121  boost::shared_ptr< WPropertyVariable< int > > clone = p->clone()->toPropInt();
122 
123  // some rudimentary tests (from WPropertyBase)
124  TS_ASSERT( clone );
125  TS_ASSERT( clone->getType() == PV_INT );
126  TS_ASSERT( clone->getName() == p->getName() );
127  TS_ASSERT( clone->getDescription() == p->getDescription() );
128  TS_ASSERT( clone->getPurpose() == p->getPurpose() );
129 
130  // equal value?
131  TS_ASSERT( p->get() == clone->get() );
132 
133  // different conditions?
134  TS_ASSERT( p->getContraintsChangedCondition() != clone->getContraintsChangedCondition() );
135  TS_ASSERT( p->getUpdateCondition() != clone->getUpdateCondition() ); // this is from WPropertyBase
136 
137  // cloned constraints?
138  TS_ASSERT( p->getMin() != clone->getMin() ); // the constraints of course need to be cloned too
139  TS_ASSERT( p->getMax() != clone->getMax() ); // the constraints of course need to be cloned too
140 
141  TS_ASSERT( p->getMin()->getMin() == clone->getMin()->getMin() ); // but their values need to be the same. This somehow tests the clone
142  // feature of WPropertyConstrainMin and Max
143  TS_ASSERT( p->getMax()->getMax() == clone->getMax()->getMax() ); // but their values need to be the same. This somehow tests the clone
144  // feature of WPropertyConstrainMin and Max
145 
146  // check independence of both update conditions
147  p->getUpdateCondition()->subscribeSignal( boost::bind( &WPropertyVariableTest::setTemporary1, this ) );
148  clone->getUpdateCondition()->subscribeSignal( boost::bind( &WPropertyVariableTest::setTemporary2, this ) );
149 
150  // set the value of the clone -> fire condition of clone but not of original
151  m_testTemporary1 = false;
152  m_testTemporary2 = false;
153  clone->set( 4 );
154  TS_ASSERT( !m_testTemporary1 );
155  TS_ASSERT( m_testTemporary2 );
156 
157  // and test vice versa
158  m_testTemporary1 = false;
159  m_testTemporary2 = false;
160  p->set( 2 );
161  TS_ASSERT( m_testTemporary1 );
162  TS_ASSERT( !m_testTemporary2 );
163 
164  // do the same for constraints
165  m_testTemporary1 = false;
166  m_testTemporary2 = false;
167  clone->removeConstraint( PC_MIN );
168  TS_ASSERT( !m_testTemporary1 );
169  TS_ASSERT( m_testTemporary2 );
170 
171  // and vice versa
172  m_testTemporary1 = false;
173  m_testTemporary2 = false;
174  p->removeConstraint( PC_MIN );
175  TS_ASSERT( m_testTemporary1 );
176  TS_ASSERT( !m_testTemporary2 );
177  }
178 
179  /**
180  * Test min/max functionality, including tests for set(), accept() and ensureValidity.
181  */
183  {
184  WException::disableBacktrace(); // in tests, turn of backtrace globally
185 
186  // create an int property
187  boost::shared_ptr< WPropertyVariable< int > > p =
188  boost::shared_ptr< WPropertyVariable< int > >( new WPropertyVariable< int >( "hey", "you", false ) );
189 
190  // by default there should be no min/max property set. Only IF the property was created using a WProperties::addProperty.
193  TS_ASSERT( !cmin );
194  TS_ASSERT( !cmax );
195 
196  // does set() and accept work if no constraints are there?
197  TS_ASSERT( p->set( 123 ) );
198  TS_ASSERT( p->get() == 123 );
199  TS_ASSERT( p->accept( 12345 ) );
200 
201  // add a min prop
202  cmin = p->setMin( 10 );
203  cmax = p->setMax( 15 );
204  TS_ASSERT( cmin );
205  TS_ASSERT( cmax );
206 
207  // compare that getMin/max returns the correct ones
208  TS_ASSERT( cmin == p->getMin() );
209  TS_ASSERT( cmax == p->getMax() );
210 
211  // try to set a valid value
212  TS_ASSERT( p->set( 10 ) );
213  TS_ASSERT( p->get() == 10 );
214 
215  // try to set an invalid value
216  TS_ASSERT( !p->set( 9 ) );
217  TS_ASSERT( p->get() == 10 );
218  TS_ASSERT( !p->set( 16 ) );
219  TS_ASSERT( p->get() == 10 );
220 
221  // add another min value. Is the first one removed?
222  p->setMin( 5 );
223  p->setMax( 20 );
224  p->m_constraints->getReadTicket()->get().size();
225 
226  // try to set a valid value, which was invalid previously
227  TS_ASSERT( p->set( 9 ) );
228  TS_ASSERT( p->get() == 9 );
229  TS_ASSERT( p->set( 16 ) );
230  TS_ASSERT( p->get() == 16 );
231 
232  // finally, test ensureValidity
233  // this function helps to restore a property to a valid state after a constraint change
234 
235  // currently, the state of p is valid. So ensureValidity should do nothing
236  TS_ASSERT( p->ensureValidity( 10 ) );
237  TS_ASSERT( p->get() == 16 );
238 
239  // change the min constraint so that 16 gets invalid
240  TS_ASSERT( p->isValid() );
241  p->setMin( 17 );
242  TS_ASSERT( !p->isValid() );
243  TS_ASSERT( p->get() == 16 ); // setting a new constraint should NOT modify the current value
244 
245  // use ensureValidity
246  TS_ASSERT( p->ensureValidity( 18 ) );
247  TS_ASSERT( p->get() == 18 );
248  TS_ASSERT( p->isValid() );
249 
250  // what happens if the ensureValidity parameter itself is invalid? It should return false
251  p->setMin( 19 );
252  TS_ASSERT( !p->ensureValidity( 16 ) ); // 16 is invalid since minimum is 19
253  TS_ASSERT( !p->isValid() ); // the value should stay invalid
254  TS_ASSERT( p->get() == 18 );
255  }
256 
257  /**
258  * Tests constraint management. Especially add,replace,remove,count,getFirst.
259  */
261  {
262  WException::disableBacktrace(); // in tests, turn of backtrace globally
263 
264  // create an int property
265  boost::shared_ptr< WPropertyVariable< int > > p =
266  boost::shared_ptr< WPropertyVariable< int > >( new WPropertyVariable< int >( "hey", "you", false ) );
267 
268  // register a condition callback
269  p->getUpdateCondition()->subscribeSignal( boost::bind( &WPropertyVariableTest::setTemporary1, this ) );
270 
271  ////////////////////////////////////
272  // add
273 
274  // add a constraint
275  m_testTemporary1 = false;
277  boost::shared_ptr< WPropertyConstraintMin< int > >( new WPropertyConstraintMin< int >( 10 ) );
278  p->addConstraint( cmin );
279  TS_ASSERT( p->m_constraints->getReadTicket()->get().size() == 1 );
280  TS_ASSERT( m_testTemporary1 ); // the update condition has to be fired on constraint updates
281 
282  ////////////////////////////////////
283  // count, getFirst
284 
285  // count constraints
286  m_testTemporary1 = false;
287  TS_ASSERT( p->countConstraint( PC_MIN ) == 1 );
288  TS_ASSERT( p->countConstraint( PC_MAX ) == 0 );
289 
290  // get first constraint should return the first constraint of a specified type
291  TS_ASSERT( cmin == p->getFirstConstraint( PC_MIN ) );
292  TS_ASSERT( !p->getFirstConstraint( PC_MAX ) ); // there is no max constraint
293  TS_ASSERT( !m_testTemporary1 ); // these operations should not fire the condition
294 
295  ////////////////////////////////////
296  // replace
297 
298  // replace a constraint
299  m_testTemporary1 = false;
301  boost::shared_ptr< WPropertyConstraintMax< int > >( new WPropertyConstraintMax< int >( 15 ) );
302 
303  // replace non existent type
304  TS_ASSERT_THROWS_NOTHING( p->replaceConstraint( cmax, PC_MAX ) ); // since there is no max constraint, replace acts like addConstraint
305  TS_ASSERT( m_testTemporary1 );
306 
307  // replace existent type ( note: there is now a min and a max constraint )
308  m_testTemporary1 = false;
310  boost::shared_ptr< WPropertyConstraintMax< int > >( new WPropertyConstraintMax< int >( 20 ) );
311  p->replaceConstraint( cmax2, PC_MAX );
312  TS_ASSERT( m_testTemporary1 );
313  TS_ASSERT( cmax2 == p->getFirstConstraint( PC_MAX ) );
314 
315  ////////////////////////////////////
316  // remove
317 
318  // removeConstraints should not fire the condition if nothing is removed
319  m_testTemporary1 = false;
320  p->removeConstraint( PC_NOTEMPTY );
321  TS_ASSERT( !m_testTemporary1 );
322 
323  // remove max constraint
324  m_testTemporary1 = false;
325  TS_ASSERT( p->countConstraint( PC_MAX ) == 1 );
326  p->removeConstraint( PC_MAX );
327  TS_ASSERT( p->countConstraint( PC_MAX ) == 0 );
328  TS_ASSERT( m_testTemporary1 ); // should have fired
329 
330  // remove min constraint with pointer
331  m_testTemporary1 = false;
332  TS_ASSERT( p->countConstraint( PC_MIN ) == 1 );
333  p->removeConstraint( cmin );
334  TS_ASSERT( p->countConstraint( PC_MIN ) == 0 );
335  TS_ASSERT( m_testTemporary1 ); // should have fired
336  }
337 };
338 
339 #endif // WPROPERTYVARIABLE_TEST_H
340