OSDN Git Service

700ce7d3aa550b073d373e2a2e7ece87c79f3ce7
[trx-305dsp/dsp.git] / hirado / kernel / cfg / base / testsuite.h
1 /*
2  *  TOPPERS/JSP Kernel
3  *      Toyohashi Open Platform for Embedded Real-Time Systems/
4  *      Just Standard Profile Kernel
5  * 
6  *  Copyright (C) 2003 by Embedded and Real-Time Systems Laboratory
7  *                              Toyohashi Univ. of Technology, JAPAN
8  * 
9  *  上記著作権者は,以下の (1)〜(4) の条件か,Free Software Foundation 
10  *  によって公表されている GNU General Public License の Version 2 に記
11  *  述されている条件を満たす場合に限り,本ソフトウェア(本ソフトウェア
12  *  を改変したものを含む.以下同じ)を使用・複製・改変・再配布(以下,
13  *  利用と呼ぶ)することを無償で許諾する.
14  *  (1) 本ソフトウェアをソースコードの形で利用する場合には,上記の著作
15  *      権表示,この利用条件および下記の無保証規定が,そのままの形でソー
16  *      スコード中に含まれていること.
17  *  (2) 本ソフトウェアを,ライブラリ形式など,他のソフトウェア開発に使
18  *      用できる形で再配布する場合には,再配布に伴うドキュメント(利用
19  *      者マニュアルなど)に,上記の著作権表示,この利用条件および下記
20  *      の無保証規定を掲載すること.
21  *  (3) 本ソフトウェアを,機器に組み込むなど,他のソフトウェア開発に使
22  *      用できない形で再配布する場合には,次のいずれかの条件を満たすこ
23  *      と.
24  *    (a) 再配布に伴うドキュメント(利用者マニュアルなど)に,上記の著
25  *        作権表示,この利用条件および下記の無保証規定を掲載すること.
26  *    (b) 再配布の形態を,別に定める方法によって,TOPPERSプロジェクトに
27  *        報告すること.
28  *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
29  *      害からも,上記著作権者およびTOPPERSプロジェクトを免責すること.
30  * 
31  *  本ソフトウェアは,無保証で提供されているものである.上記著作権者お
32  *  よびTOPPERSプロジェクトは,本ソフトウェアに関して,その適用可能性も
33  *  含めて,いかなる保証も行わない.また,本ソフトウェアの利用により直
34  *  接的または間接的に生じたいかなる損害に関しても,その責任を負わない.
35  * 
36  *  @(#) $Id: testsuite.h,v 1.1 2009/01/31 05:27:37 suikan Exp $
37  */
38
39 /*
40  *   テストスィート実行補助 クラス/マクロライブラリ
41  */
42
43 // $Header: /cvsroot/toppersjsp4bf/jsp/cfg/base/testsuite.h,v 1.1 2009/01/31 05:27:37 suikan Exp $
44
45
46 #ifdef TESTSUITE
47
48     //シナリオ終端マクロ(Exceptionクラスの有無によって中身を替えたいのでここにおく)
49 #  undef END_CASE
50 #  ifdef EXCEPT_H
51 #    define END_CASE }catch(TestSuite::Fail & x) { _suite_control.fail_in_suite(x.getMessage()); } catch(Exception & exc) { _suite_control.fail_in_suite(string("不明な例外 : ") + exc.getDetails()); } catch(...) { _suite_control.fail_in_suite("テスト実行中に不明な例外を受け取ったため中断された"); } _suite_control.leave_case(); }
52 #  else
53 #    define END_CASE }catch(TestSuite::Fail & x) { _suite_control.fail_in_suite(x.getMessage()); } catch(...) { _suite_control.fail_in_suite("テスト実行中に不明な例外を受け取ったため中断された"); } _suite_control.leave_case(); }
54 #  endif
55
56 #endif
57
58
59 #ifndef TESTSUITE_H
60 #define TESTSUITE_H
61
62     //テストスィートをかけるかどうか
63 //#define TESTSUITE
64
65
66 #if defined(TESTSUITE) //&& defined(_DEBUG)
67
68     //ストリームの内容をテストで使いたいので入れ替える
69 #include <iostream>
70 #define cin  _cin
71 #define cout _cout
72 #define cerr _cerr
73
74 #include <sstream>
75
76 namespace std {
77     extern stringstream _cin;
78     extern stringstream _cout;
79     extern stringstream _cerr;
80 }
81
82 #include <string>
83 #include <list>
84 #include <set>
85 #include <map>
86
87
88     //標準のテストスィート関数のプロトタイプ宣言用マクロ
89 #define TESTSUITE_PROTOTYPE(suite) \
90     public: \
91         static void test_suite_##suite(TestSuiteControl & _suite_control);
92
93
94     //標準のテストスィート関数の定義用マクロ (わざとスィート実行の条件コンパイル用の定義名と同じ名前にする)
95 #undef TESTSUITE
96 #define TESTSUITE(suite,cls) \
97     TestSuite TestSuite_##cls##_##suite(#cls "(" #suite ")", cls::test_suite_##suite); \
98     void cls::test_suite_##suite(TestSuiteControl & _suite_control)
99
100 #define TESTSUITE_(suite,cls,spr) \
101     TestSuite TestSuite_##spr##_##cls##_##suite(#spr "::" #cls "(" #suite ")", spr::cls::test_suite_##suite); \
102     void spr::cls::test_suite_##suite(TestSuiteControl & _suite_control)
103
104     //多重実行防止用マクロ
105 #define PROCEED_ONCE static bool _proceed_once_flag_ = false; if(_proceed_once_flag_) return; else _proceed_once_flag_ = true;
106
107     //シナリオ開始マクロ
108 #define BEGIN_CASE(x,y) if(_suite_control.enter_case(x,y,__FILE__,__LINE__)) { try {
109
110     //シナリオ失敗マクロ
111 #define TEST_FAIL     throw TestSuite::Fail();
112 #define TEST_FAIL_(x) throw TestSuite::Fail(x);
113
114     //短いシナリオ用マクロ
115 #define TEST_CASE(x,y,z)   BEGIN_CASE(x,y) { if(!(z)) TEST_FAIL;    } END_CASE
116 #define TEST_CASE_(x,y,z,u) BEGIN_CASE(x,y) { if(!(z)) TEST_FAIL_(u); } END_CASE
117
118     //到達判定マクロ
119 #define CHECKPOINT(x) TestSuite::check(x);
120
121     //シングルトン退避
122 #define SINGLETON(x)    Singleton<x>::Context context;     Singleton<x>::saveContext(context);
123 #define SINGLETON_(x,y) Singleton<x>::Context context_##y; Singleton<x>::saveContext(context_##y);
124
125 /*
126  *  テストスィートの実行制御クラス
127  */
128 class TestSuiteControl {
129 protected:
130     std::list<std::string> session;         //現在のセッション名スタック
131
132     std::string    target_session;          //処理対象セッション名
133     std::string    current_session;         //現在のスィートシナリオ名
134     std::string    current_description;     //現在のスィートシナリオの説明
135     std::ostream * out;                     //説明の出力先
136     bool           fail;                    //失敗したシナリオがあったかどうか
137     bool           verbose;                 //冗長出力するか否か
138
139     unsigned int   case_count;              //ケースの総数
140     unsigned int   fail_count;              //失敗したケースの数
141
142         //シナリオ名の取得
143     std::string get_suitename(const char * name = "") const;
144
145
146 public:
147         //コンストラクタ
148     TestSuiteControl(std::ostream & _out, const char * _pattern = "");
149
150         //テストシナリオの表題設定 (返却値 : 実行する必要があるかどうか)
151     bool        _enter_case(const char * session, const char * description, const char * filename = "", long lineno = -1);
152     inline void leave_case(void) { leave_session(); }
153
154         //シングルステップ実行時に中に飛び込まないためのラッパ
155     inline bool enter_case(const char * session, const char * description, const char * filename = "", long lineno = -1)
156     {   return _enter_case(session, description, filename, lineno);   }
157
158         //テストセッション名 (シナリオプレフィクス) の設定/解除
159     void enter_session(const std::string & session);
160     void leave_session(void);
161
162         //テストシナリオの失敗報告
163     void fail_in_suite(std::string msg="");                                           
164
165         //失敗したシナリオの有無の確認
166     inline bool is_failed(void) const
167     {   return fail;   }
168
169         //冗長出力の設定
170     inline void set_verbose(bool _verbose = true)
171     {   verbose = _verbose;   }
172
173         //実行したテストケースの数
174     inline unsigned int countCases(void) const
175     {   return case_count;   }
176
177         //失敗したテストケースの数
178     inline unsigned int countFails(void) const
179     {   return fail_count;   }
180 };
181
182     //シングルトンのテストスィートのためにここでインクルード
183 #include "base/singleton.h"
184
185 /*
186  *  テストスィート実行クラス
187  */
188 class TestSuite {
189 public:
190     class Fail  //テストケース失敗通知に用いる例外用クラス
191     {
192     protected:
193         std::string msg;
194
195     public:
196             //コンストラクタ
197         Fail(std::string src = "") throw() : msg(src) {}
198
199             //コピーコンストラクタ
200         Fail(const Fail & src) throw() : msg(src.msg) {}
201         
202             //メッセージを取得
203         inline const std::string & getMessage(void) const throw()
204         {   return msg;   }
205     };
206
207     typedef void (*SuiteFunction)(TestSuiteControl &);
208
209         /* クラス毎のテストスィートに関する情報を保持するクラス */
210     class SuiteContainerNode
211     {
212     protected:
213         std::string   session;
214         SuiteFunction suite;
215     
216     public:
217             //スィート情報コンストラクタ
218         SuiteContainerNode(const char * session, SuiteFunction suite);
219         SuiteContainerNode(const SuiteContainerNode & src);
220
221             //スィートの実行
222         bool invoke(TestSuiteControl & suite_control);
223
224             //スィート名の取得
225         inline const std::string & getName(void) const throw()
226         {   return session;   }
227     };
228
229         //実行すべきテストスィートを持つインスタンスのリストの型
230     class SuiteContainer : public std::list<SuiteContainerNode>
231     {   public: SINGLETON_CONSTRUCTOR(SuiteContainer) {}   };
232
233         /* 実行オプション */
234     enum tagPerformOption {
235         THROUGH = 1,    //すべて通しで実行する (いちいち止めない)
236         VERBOSE = 2,    //冗長出力
237
238         DEFAULT = THROUGH
239     };
240
241         /* チェックポイントを格納するクラス */
242     class Checkpoint : public std::set<std::string>
243     { public: SINGLETON_CONSTRUCTOR(Checkpoint) throw() {} };
244
245 protected:
246     bool            fail;       //最後に実行したスィートが失敗したがどうかを保持する変数
247     static bool     starvated;  //newに失敗するかどうか
248
249 public:
250         //コンストラクタ
251     TestSuite(const char * session, SuiteFunction suite);
252
253         //デストラクタ
254     ~TestSuite(void);
255
256         //テストスィートの実行  (返却値:スィートが正しく実行されたかどうか)
257     static bool performTestSuite(int flags = THROUGH, const char * pattern = "");
258
259         //テストスィートの実行 (引数変換)
260     inline static bool performTestSuite(const char * pattern)
261     {   return performTestSuite(THROUGH, pattern);   }
262
263         //登録されているトップレベルスィートの一覧表示
264     static void listTestSuite(void);
265
266         /*
267          *   チェックポイント用関数
268          */
269
270         //通過したことを報告
271     inline static void check(std::string checkname)
272     {   Singleton<Checkpoint>::getInstance()->insert(checkname);   }
273
274         //これまでに受けた報告を削除
275     inline static void clearCheckpoints(void)
276     {   Singleton<Checkpoint>::getInstance()->clear();   }
277
278         //その位置に来たか
279     static bool isReached(std::string checkname);
280
281         /*
282          *   テスト用作業関数
283          */
284
285         //ファイルの中身を開いてチェックする
286     static bool compareFileContents(const char * filename, const char * filecontents, bool remove = true);
287 };
288
289 /*
290  *  スィート実行用main関数
291  */
292 extern int main(int argc, char ** argv);
293
294 #define main pseudo_main    //通常のmainを差し換え
295
296     //簡易ソフトウェアトレース機能のインクルード
297 #include "base/coverage_defs.h"
298
299 #else
300
301 /*********************************************************************************************/
302 /*
303  *  テストを実行しないときのクラス定義
304  */
305
306 #define TESTABLEOBJECT(x)
307 #define TESTABLEOBJECT_(x,y)
308 #define TESTSUITE_PROTOTYPE(x)
309 #define TESTSUITE_(x,y)
310 #define PROCEED_ONCE
311
312 #define BEGIN_CASE(x,y)
313 #define END_CASE
314 #define TEST_FAIL
315
316 #define CHECKPOINT(x)
317
318 /*
319     *  テストスィート実行クラス
320     */
321 class TestSuite {
322 public:
323         //テストスィートの実行  (返却値:スィートを正しく実行したかどうか)
324     inline static bool performTestSuite(void) { return true; };
325 };
326
327 #endif
328
329 #endif /* TESTSUITE_H */
330