1 /*
2 * This file is part of HexEditor plugin for Code::Blocks studio
3 * Copyright (C) 2009 Bartlomiej Swiecki
4 *
5 * HexEditor plugin is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 3 of the License, or
8 * (at your option) any later version.
9 *
10 * HexEditor plugin is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with HexEditor plugin. If not, see <http://www.gnu.org/licenses/>.
17 *
18 * $Revision: 8350 $
19 * $Id: TestCasesHelper.h 8350 2012-09-04 08:05:13Z jenslody $
20 * $HeadURL: svn://svn.code.sf.net/p/codeblocks/code/branches/release-20.xx/src/plugins/contrib/HexEditor/TestCasesHelper.h $
21 */
22 
23 #ifndef TESTCASESHELPER_H
24 #define TESTCASESHELPER_H
25 
26 #include "TestCasesBase.h"
27 
28 template< typename T, int maxTests > class TestCasesHelper;
29 
30 namespace Detail
31 {
32     struct RunHelperBase
33     {
34         template< typename T, int maxTests, int testNo >
CallRunnerRunHelperBase35         inline int CallRunner( TestCasesHelper< T, maxTests >& hlpr, int prevTest )
36         {
37             return hlpr. template Runner< testNo >( prevTest );
38         }
39     };
40 
41     /** \brief Extra structure needed because of lack of partial function template specialization */
42     template< typename T, int maxTests, int testNo >
RunRunHelper43     struct RunHelper: public RunHelperBase { public: inline int Run( TestCasesHelper< T, maxTests >& hlpr )
44     {
45         return CallRunner< T, maxTests, testNo >( hlpr, RunHelper< T, maxTests, testNo-1 >().Run( hlpr ) );
46     }};
47 
48     template< typename T, int maxTests >
49     struct RunHelper<T, maxTests, 0 > { public: inline int Run( TestCasesHelper< T, maxTests >& ) { return 0; } };
50 }
51 
52 /** \brief Helper for automated test cases */
53 template< typename T, int maxTests = 50 >
54 class TestCasesHelper: public T, public TestCasesBase
55 {
56     public:
57 
58         /** \brief Run the tests */
59         virtual bool PerformTests()
60         {
61             return RunTests();
62         }
63 
64         /** \brief Main function performing the test,
65          *         Implementations are made by partial instantiation
66          */
67         template< int i >
68         void Test()
69         {
70             m_NoSuchTest = true;
71         }
72 
73         /** \brief Test condition */
74         void Ensure( bool condition, const wxString& failMsg )
75         {
76             if ( !condition )
77             {
78                 TestError err;
79                 err.m_Msg = failMsg;
80                 throw err;
81             }
82         }
83 
84     private:
85 
86         /** \brief Run all the tests */
87         inline bool RunTests()
88         {
89             m_FailCnt = 0;
90             m_PassCnt = 0;
91             m_SkipCnt = 0;
92 
93             Detail::RunHelper< T, maxTests, maxTests > ().Run( *this );
94 
95             AddLog( wxString::Format( _T("===============================") ) );
96             AddLog( wxString::Format( _T("Summary:") ) );
97             AddLog( wxString::Format( _T(" Passed: %d"), m_PassCnt ) );
98             AddLog( wxString::Format( _T(" Failed: %d"), m_FailCnt ) );
99             AddLog( wxString::Format( _T("  Total: %d"), m_PassCnt + m_FailCnt ) );
100 
101             return m_FailCnt == 0;
102         }
103 
104         /** \brief Run all test from 0 to testNo
105          *  \return No of last available test
106          */
107         template< int testNo >
108         inline int Runner( int prevTest )
109         {
110             // Check if someone has requested tests to stop
111             if ( StopTest() )
112             {
113                 return testNo;
114             }
115 
116             wxString result;
117             bool pass = true;
118             m_NoSuchTest = false;
119 
120             // Call our own test
121             try
122             {
123                 Test< testNo >();
124             }
125             catch ( const TestError& err )
126             {
127                 // Display test's info
128                 pass = false;
129                 result = wxString::Format( _T("Test %d FAILED: %s"), testNo, err.m_Msg.wx_str() );
130             }
131 
132             if ( m_NoSuchTest )
133             {
134                 // There was no such test
135                 m_SkipCnt++;
136                 return prevTest;
137             }
138 
139             // Enumerate skipped tests
140             for ( int i = prevTest+1; i<testNo; i++ )
141             {
142                 AddLog( wxString::Format( _T("Test %d skipped: not defined"), i)  );
143             }
144 
145             // Log our results
146             AddLog( pass ? wxString::Format( _T("Test %d passed"), testNo ) : result );
147 
148             ( pass ? m_PassCnt : m_FailCnt ) ++;
149 
150             return testNo;
151         }
152 
153         /** \brief error report */
154         struct TestError { wxString m_Msg; };
155 
156         int m_FailCnt;
157         int m_PassCnt;
158         int m_SkipCnt;
159         bool m_NoSuchTest;
160 
161         friend class Detail::RunHelperBase;
162 };
163 
164 
165 
166 #endif
167