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