PageRenderTime 680ms CodeModel.GetById 19ms RepoModel.GetById 1ms app.codeStats 0ms

/FakeDirectX/loki-lib/test/Checker/main.cpp

http://d3dgraphicspipeline.codeplex.com
C++ | 463 lines | 288 code | 95 blank | 80 comment | 18 complexity | ddd9703517c84dbbdee0b33bf1c0d03a MD5 | raw file
Possible License(s): LGPL-2.0, LGPL-2.1
  1. ////////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Test program for The Loki Library
  4. // Copyright (c) 2008 Richard Sposato
  5. // The copyright on this file is protected under the terms of the MIT license.
  6. //
  7. // Permission to use, copy, modify, distribute and sell this software for any
  8. // purpose is hereby granted without fee, provided that the above copyright
  9. // notice appear in all copies and that both that copyright notice and this
  10. // permission notice appear in supporting documentation.
  11. //
  12. // The author makes no representations about the suitability of this software
  13. // for any purpose. It is provided "as is" without express or implied warranty.
  14. //
  15. ////////////////////////////////////////////////////////////////////////////////
  16. // $Id$
  17. /// @file main.cpp This provides examples on how to use Loki's Checker facility.
  18. // ----------------------------------------------------------------------------
  19. #include "../../include/loki/Checker.h"
  20. #include <stdexcept>
  21. #include <iostream>
  22. #include <vector>
  23. #if !defined( nullptr )
  24. #define nullptr NULL
  25. #endif
  26. #if !defined( NULL )
  27. #define NULL 0
  28. #endif
  29. using namespace std;
  30. // ----------------------------------------------------------------------------
  31. /* This class has 2 invariants. The this pointer may never equal NULL, and the
  32. value may not equal zero.
  33. */
  34. class Thingy
  35. {
  36. public:
  37. static void ChangeThat( void );
  38. static unsigned int GetThat( void );
  39. explicit Thingy( unsigned int value );
  40. Thingy( const Thingy & that );
  41. Thingy & operator = ( const Thingy & that );
  42. ~Thingy( void );
  43. void Swap( Thingy & that );
  44. bool operator == ( const Thingy & that ) const;
  45. void DoSomethingEvil( void );
  46. unsigned int GetValue( void ) const;
  47. unsigned int DoSomething( bool doThrow ) const;
  48. void DoSomethingElse( void ) const;
  49. void AddCount( unsigned int count );
  50. unsigned int GetCount( unsigned int index ) const;
  51. void ClearCounts( void );
  52. private:
  53. /// This is a static validator.
  54. static bool StaticIsValid( void );
  55. /// This is a per-instance validator.
  56. bool IsValid( void ) const;
  57. /// This can be used to validate pre-conditions and post-conditions.
  58. bool IsValidEmpty( void ) const;
  59. /// This can be used to validate pre-conditions and post-conditions.
  60. bool IsValidFull( void ) const;
  61. // This shows how to declare checkers for non-static functions in a host class.
  62. typedef ::Loki::CheckFor< Thingy > CheckFor;
  63. // This shows how to declare checkers for static functions of a host class.
  64. typedef ::Loki::CheckStaticFor CheckStaticFor;
  65. typedef ::std::vector< unsigned int > IntBlock;
  66. static unsigned int s_value;
  67. unsigned int m_value;
  68. IntBlock m_counts;
  69. };
  70. unsigned int Thingy::s_value = 10;
  71. // ----------------------------------------------------------------------------
  72. // This example shows how static functions can use a no-throw checkers.
  73. void Thingy::ChangeThat( void )
  74. {
  75. CheckStaticFor::NoThrow checker( &Thingy::StaticIsValid );
  76. (void)checker;
  77. s_value--;
  78. }
  79. // ----------------------------------------------------------------------------
  80. // This example shows how static functions can use an invariant checker.
  81. unsigned int Thingy::GetThat( void )
  82. {
  83. CheckStaticFor::Invariants checker( &Thingy::StaticIsValid );
  84. (void)checker;
  85. return s_value;
  86. }
  87. // ----------------------------------------------------------------------------
  88. // This example shows how ctors can use an invariant checker.
  89. Thingy::Thingy( unsigned int value ) :
  90. m_value( value ),
  91. m_counts()
  92. {
  93. CheckFor::Invariants checker( this, &Thingy::IsValid );
  94. (void)checker;
  95. }
  96. // ----------------------------------------------------------------------------
  97. Thingy::Thingy( const Thingy & that ) :
  98. m_value( that.m_value ),
  99. m_counts( that.m_counts )
  100. {
  101. CheckFor::Invariants checker( this, &Thingy::IsValid );
  102. (void)checker;
  103. }
  104. // ----------------------------------------------------------------------------
  105. Thingy & Thingy::operator = ( const Thingy & that )
  106. {
  107. CheckFor::Invariants checker( this, &Thingy::IsValid );
  108. (void)checker;
  109. if ( &that != this )
  110. {
  111. Thingy temp( that );
  112. temp.Swap( *this );
  113. }
  114. return *this;
  115. }
  116. // ----------------------------------------------------------------------------
  117. // A destructor really doesn't need a checker, but does need to confirm
  118. // the object is valid at the start of the destructor.
  119. Thingy::~Thingy( void )
  120. {
  121. assert( IsValid() );
  122. }
  123. // ----------------------------------------------------------------------------
  124. // A swap function gets 2 checkers - one for this, and another for that.
  125. void Thingy::Swap( Thingy & that )
  126. {
  127. CheckFor::Invariants checker1( this, &Thingy::IsValid );
  128. (void)checker1;
  129. CheckFor::Invariants checker2( &that, &Thingy::IsValid );
  130. (void)checker2;
  131. const IntBlock counts( m_counts );
  132. m_counts = that.m_counts;
  133. that.m_counts = counts;
  134. const unsigned int value = m_value;
  135. m_value = that.m_value;
  136. that.m_value = value;
  137. }
  138. // ----------------------------------------------------------------------------
  139. bool Thingy::operator == ( const Thingy & that ) const
  140. {
  141. return ( m_value == that.m_value );
  142. }
  143. // ----------------------------------------------------------------------------
  144. void Thingy::DoSomethingEvil( void )
  145. {
  146. m_value = 0;
  147. }
  148. // ----------------------------------------------------------------------------
  149. // This example shows how to use the no-throw checker.
  150. unsigned int Thingy::GetValue( void ) const
  151. {
  152. CheckFor::NoThrow checker( this, &Thingy::IsValid );
  153. (void)checker;
  154. return m_value;
  155. }
  156. // ----------------------------------------------------------------------------
  157. // This example shows how to use the equality checker.
  158. unsigned int Thingy::DoSomething( bool doThrow ) const
  159. {
  160. CheckFor::Equality checker( this, &Thingy::IsValid );
  161. (void)checker;
  162. if ( doThrow )
  163. throw ::std::logic_error( "Test Exception." );
  164. return m_value;
  165. }
  166. // ----------------------------------------------------------------------------
  167. // This example shows how to use the no-change checker.
  168. void Thingy::DoSomethingElse( void ) const
  169. {
  170. CheckFor::NoChange checker( this, &Thingy::IsValid );
  171. (void)checker;
  172. }
  173. // ----------------------------------------------------------------------------
  174. void Thingy::AddCount( unsigned int count )
  175. {
  176. // This function's checker cares about class invariants and post-conditions,
  177. // but does not need to check pre-conditions, so it passes in a nullptr for
  178. // the pre-condition validator. Ths post-condition validator just makes sure
  179. // the container has at least 1 element.
  180. CheckFor::Invariants checker( this, &Thingy::IsValid, nullptr, &Thingy::IsValidFull );
  181. m_counts.push_back( count );
  182. }
  183. // ----------------------------------------------------------------------------
  184. unsigned int Thingy::GetCount( unsigned int index ) const
  185. {
  186. // This function's checker cares about class invariants and both the pre- and
  187. // post-conditions, so it passes in pointers for all 3 validators. The pre-
  188. // and post-conditions are both about making sure the container is not empty.
  189. CheckFor::NoChangeOrThrow checker( this, &Thingy::IsValid, &Thingy::IsValidFull, &Thingy::IsValidFull );
  190. if ( m_counts.size() <= index )
  191. return 0;
  192. const unsigned int count = m_counts[ index ];
  193. return count;
  194. }
  195. // ----------------------------------------------------------------------------
  196. void Thingy::ClearCounts( void )
  197. {
  198. // This function's checker cares about class invariants and post-conditions,
  199. // but does not need to check pre-conditions, so it passes in a nullptr for
  200. // the pre-condition validator. Ths post-condition validator just makes sure
  201. // the container has no elements.
  202. CheckFor::NoThrow checker( this, &Thingy::IsValid, nullptr, &Thingy::IsValidEmpty );
  203. m_counts.clear();
  204. }
  205. // ----------------------------------------------------------------------------
  206. // This is a static validator.
  207. bool Thingy::StaticIsValid( void )
  208. {
  209. assert( s_value != 0 );
  210. return true;
  211. }
  212. // ----------------------------------------------------------------------------
  213. // This is a per-instance validator.
  214. bool Thingy::IsValid( void ) const
  215. {
  216. assert( nullptr != this );
  217. assert( m_value != 0 );
  218. return true;
  219. }
  220. // ----------------------------------------------------------------------------
  221. bool Thingy::IsValidEmpty( void ) const
  222. {
  223. assert( nullptr != this );
  224. assert( m_counts.size() == 0 );
  225. return true;
  226. }
  227. // ----------------------------------------------------------------------------
  228. bool Thingy::IsValidFull( void ) const
  229. {
  230. assert( nullptr != this );
  231. assert( m_counts.size() != 0 );
  232. return true;
  233. }
  234. // ----------------------------------------------------------------------------
  235. // This is a validator function called by checkers inside standalone functions.
  236. bool AllIsValid( void )
  237. {
  238. assert( Thingy::GetThat() != 0 );
  239. return true;
  240. }
  241. // ----------------------------------------------------------------------------
  242. void DoSomething( void )
  243. {
  244. // This example shows how to use a checker in a stand-alone function.
  245. ::Loki::CheckStaticFor::NoThrow checker( &AllIsValid );
  246. (void)checker;
  247. Thingy::ChangeThat();
  248. }
  249. // ----------------------------------------------------------------------------
  250. void ThrowTest( void )
  251. {
  252. Thingy thingy( 10 );
  253. throw ::std::logic_error( "Will Thingy assert during an exception?" );
  254. }
  255. // ----------------------------------------------------------------------------
  256. int main( unsigned int argc, const char * const argv[] )
  257. {
  258. (void)argc;
  259. (void)argv;
  260. try
  261. {
  262. cout << "Just before call to ThrowTest." << endl;
  263. ThrowTest();
  264. cout << "Just after call to ThrowTest." << endl;
  265. }
  266. catch ( const ::std::logic_error & ex )
  267. {
  268. cout << "Caught an exception! " << ex.what() << endl;
  269. }
  270. catch ( const ::std::exception & ex )
  271. {
  272. cout << "Caught an exception! " << ex.what() << endl;
  273. }
  274. catch ( ... )
  275. {
  276. cout << "Caught an exception!" << endl;
  277. }
  278. unsigned int count = 0;
  279. try
  280. {
  281. cout << "Running basic tests with Thingy." << endl;
  282. // First do some tests on class member functions.
  283. Thingy t1( 1 );
  284. t1.DoSomething( false );
  285. Thingy t2( 2 );
  286. t2.DoSomething( true );
  287. cout << "Done with basic tests with Thingy." << endl;
  288. }
  289. catch ( const ::std::logic_error & ex )
  290. {
  291. cout << "Caught an exception! " << ex.what() << endl;
  292. }
  293. catch ( const ::std::exception & ex )
  294. {
  295. cout << "Caught an exception! " << ex.what() << endl;
  296. }
  297. catch ( ... )
  298. {
  299. cout << "Caught an exception!" << endl;
  300. }
  301. try
  302. {
  303. Thingy t1( 1 );
  304. cout << "Now running tests with Thingy counts." << endl;
  305. // These lines will exercise the functions with pre- and post-conditions.
  306. t1.AddCount( 11 );
  307. t1.AddCount( 13 );
  308. t1.AddCount( 17 );
  309. t1.AddCount( 19 );
  310. count = t1.GetCount( 3 );
  311. assert( count == 19 );
  312. count = t1.GetCount( 0 );
  313. assert( count == 11 );
  314. t1.ClearCounts();
  315. cout << "Done with tests with Thingy counts." << endl;
  316. }
  317. catch ( const ::std::logic_error & ex )
  318. {
  319. cout << "Caught an exception! " << ex.what() << endl;
  320. }
  321. catch ( const ::std::exception & ex )
  322. {
  323. cout << "Caught an exception! " << ex.what() << endl;
  324. }
  325. catch ( ... )
  326. {
  327. cout << "Caught an exception!" << endl;
  328. }
  329. try
  330. {
  331. cout << "Now run tests on static member functions" << endl;
  332. // Next do some tests with static member functions.
  333. Thingy::ChangeThat();
  334. const unsigned int value = Thingy::GetThat();
  335. assert( value != 0 );
  336. cout << "Done with tests on static member functions" << endl;
  337. }
  338. catch ( const ::std::logic_error & ex )
  339. {
  340. cout << "Caught an exception! " << ex.what() << endl;
  341. }
  342. catch ( const ::std::exception & ex )
  343. {
  344. cout << "Caught an exception! " << ex.what() << endl;
  345. }
  346. catch ( ... )
  347. {
  348. cout << "Caught an exception!" << endl;
  349. }
  350. try
  351. {
  352. cout << "Now run test on a standalone function." << endl;
  353. // Then do a test with a standalone function.
  354. DoSomething();
  355. cout << "Done with test on a standalone function." << endl;
  356. }
  357. catch ( const ::std::exception & ex )
  358. {
  359. cout << "Caught an exception! " << ex.what() << endl;
  360. }
  361. catch ( ... )
  362. {
  363. cout << "Caught an exception!" << endl;
  364. }
  365. cout << "All done!" << endl;
  366. return 0;
  367. }
  368. // ----------------------------------------------------------------------------