OSDN Git Service

0901cd485e91ae706e9ecd381845b6f19f430c6e
[trx-305dsp/dsp.git] / hirado / kernel / cfg / base / collection.cpp
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: collection.cpp,v 1.1 2009/01/31 05:27:37 suikan Exp $
37  */
38
39 // $Header: /cvsroot/toppersjsp4bf/jsp/cfg/base/collection.cpp,v 1.1 2009/01/31 05:27:37 suikan Exp $
40
41 #include "base/collection.h"
42
43
44 using namespace std;
45
46     //特に何もしないコンストラクタ
47 Collection::Collection(void) throw()
48 {}
49
50     //デストラクタ
51 Collection::~Collection(void) throw()
52 {
53         //念のために例外にふたをする
54     try { clear(); }
55     catch(...) {}
56 }
57
58     //インスタンスをコレクションに追加 (順序は登録順)
59 bool Collection::addInstance(Collectable * _instance, bool _destruction) throw()
60 {
61     bool result = false;
62
63     if(isValid() && _instance != 0) {
64
65             // 同じインスタンスを2回登録しないようにする
66         list<Element>::iterator scope;
67
68         scope = container.begin();
69         while(scope != container.end()) {
70             if(scope->instance == _instance)
71                 break;
72             ++ scope;
73         }
74
75         if(scope == container.end()) {
76                 // 末尾に要素を追加
77             struct Element element;
78             element.instance    = _instance;
79             element.destruction = _destruction;
80             container.push_back(element);
81         }
82         else {
83                 // 破棄指示は最新に直しておく
84             scope->destruction = _destruction;
85         }
86
87         result = true;
88     }
89
90     return result;
91 }
92
93     //指定されたCollectableインスタンスに相当する場所を指すイテレータの取得 (getInstance)
94 list<Collection::Element>::const_iterator Collection::_findInstance(const Collectable * predecessor) const throw()
95 {
96     list<Element>::const_iterator result;
97
98     result = container.begin();
99
100         //predecessorが指定されていた場合は探す
101     if(predecessor != 0) {
102         while(result != container.end()) {
103             if(result->instance == predecessor) {
104                 ++ result;   //検索はpredecessorの次から
105                 break;
106             }
107             ++ result;
108         }
109     }
110
111     return result;
112 }
113
114     //コレクションからインスタンスを取得
115 Collectable * Collection::getInstance(const type_info & type, const Collectable * predecessor) const throw()
116 {
117     Collectable * result;
118
119     result = 0;
120     if(isValid()) {
121
122         list<Element>::const_iterator scope;
123
124             // 先行するインスタンスの場所を探す
125         scope = _findInstance(predecessor);
126
127             // 指定された型を持つ次のインスタンスを探す
128         while(scope != container.end()) {
129             if(typeid(*scope->instance) == type) {
130                 result = scope->instance;
131                 break;
132             }
133             ++ scope;
134         }
135     }
136
137     return result;
138 }
139
140     //コレクションからインスタンスを除外 (破棄はしない)
141 bool Collection::removeInstance(const Collectable * instance) throw()
142 {
143     bool result = false;
144
145     if(isValid() && instance != 0) {
146         list<Element>::iterator scope;
147
148         scope = container.begin();
149         while(scope != container.end()) {
150             if(scope->instance == instance) {
151                     //要素の削除
152                 container.erase(scope);
153                 result = true;
154                 break;
155             }
156             ++ scope;
157         }
158     }
159
160     return result;
161 }
162
163     //全要素の破棄
164 void Collection::clear(void)
165 {
166     if(isValid()) {
167         list<Element>::iterator scope;
168         list<Element>::iterator next;
169
170             //破棄フラグがついているインスタンスを破棄
171         scope = container.begin();
172         while(scope != container.end()) {
173
174             next = scope;       //ROT系はdeleteすると自分を消しにかかるので、イテレータを保存するために先に次を取得しておく
175             ++ next;
176
177             if(scope->destruction)
178                 delete scope->instance;
179
180             scope = next;
181         }
182
183         container.clear();
184     }
185 }
186
187 /************************************************* テストスィート *************************************************/
188
189 #ifdef TESTSUITE
190 #include "coverage_undefs.h"
191
192 class TestCollectable : public Collectable
193 {};
194
195 class TestCollectable2 : public Collectable
196 {   public: ~TestCollectable2(void) throw() { TestSuite::check("TestCollectable2::~TestCollectable2"); }   };
197
198 #ifdef _MSC_VER
199 class TestCollectable3 : public Collectable
200 {   public: ~TestCollectable3(void) throw(int) { throw 0; }   };
201 #endif
202
203 class TestCollectable4 : public TestCollectable2
204 {   public: ~TestCollectable4(void) throw() { TestSuite::check("TestCollectable4::~TestCollectable4"); }   };
205
206 TESTSUITE(main, Collection)
207 {
208     BEGIN_CASE("addInstance","addInstance") {
209         BEGIN_CASE("1","インスタンスは正しく登録できる") {
210             Collection col;
211             TestCollectable test;
212             TestCollectable2 test2;
213
214             BEGIN_CASE("1","登録できTRUEが返る (1個目)") {
215                 if(!col.addInstance(&test,  false))
216                     TEST_FAIL;
217             } END_CASE;
218
219             BEGIN_CASE("2","登録できtrueが返る (2個目)") {
220                 if(!col.addInstance(&test2, false))
221                     TEST_FAIL;
222             } END_CASE;
223
224             BEGIN_CASE("3","個数が合ってる") {
225                 if(col.container.size() != 2)
226                     TEST_FAIL;
227             } END_CASE;
228
229             BEGIN_CASE("4","順番があってる") {
230             list<Element>::iterator scope;
231                 scope = col.container.begin();
232                 if(scope->instance != &test || scope->destruction != false)
233                     TEST_FAIL;
234                 ++ scope;
235                 if(scope->instance != &test2 || scope->destruction != false)
236                     TEST_FAIL;
237                 ++ scope;
238                 if(scope != col.container.end())
239                     TEST_FAIL;
240             } END_CASE;
241         } END_CASE;
242
243         BEGIN_CASE("2","NULLインスタンスは登録されない") {
244             Collection col;
245
246             BEGIN_CASE("1","NULLインスタンスを渡すとfalseが返る") {
247                 if(col.addInstance(0))
248                     TEST_FAIL;
249             } END_CASE;
250
251             BEGIN_CASE("2","何も登録されていない") {
252                 if(col.container.size() != 0)
253                     TEST_FAIL;
254             } END_CASE;
255         } END_CASE;
256
257         BEGIN_CASE("3","無効なインスタンスに対する操作でfalseが返る") {
258             Collection col;
259
260             if(col.addInstance(0))
261                 TEST_FAIL;
262         } END_CASE;
263
264         BEGIN_CASE("4","同一のインスタンスを2回登録しても1個だけしか登録されない") {
265             Collection col;
266             TestCollectable test;
267
268             TEST_CASE("0","[前提] 一回目は正しく成功する", col.addInstance(&test, false));
269
270             TEST_CASE("1","関数は正しく終了する", col.addInstance(&test, false));
271             TEST_CASE("2","インスタンス数は増えていない", col.container.size() == 1);
272
273         } END_CASE;
274
275     } END_CASE;
276
277     BEGIN_CASE("getInstance(type_info)","getInstance(type_info)") {
278         Collection col;
279         TestCollectable test;
280         TestCollectable test_2;
281         TestCollectable test_3;
282         TestCollectable2 test2;
283         TestCollectable2 test2_2;
284         TestCollectable2 test2_3;
285
286         col.addInstance(test);
287         col.addInstance(test2);
288         col.addInstance(test_2);
289         col.addInstance(test2_2);
290         col.addInstance(test_3);
291         col.addInstance(test2_3);
292
293         Collectable * instance = 0;
294
295         BEGIN_CASE("1","最初の要素を取得できる") {
296             instance = col.getInstance(typeid(TestCollectable));
297             if(instance != &test)
298                 TEST_FAIL;
299         } END_CASE;
300
301         BEGIN_CASE("2","次の要素を取得できる") {
302             instance = col.getInstance(typeid(TestCollectable), instance);
303             if(instance != &test_2)
304                 TEST_FAIL;
305         } END_CASE;
306
307         BEGIN_CASE("3","さらに次の要素を取得できる") {
308             instance = col.getInstance(typeid(TestCollectable), instance);
309             if(instance != &test_3)
310                 TEST_FAIL;
311         } END_CASE;
312
313         BEGIN_CASE("4","そのまた次の要素を取得したらNULLが返る") {
314             instance = col.getInstance(typeid(TestCollectable), instance);
315             if(instance != 0)
316                 TEST_FAIL;
317         } END_CASE;
318
319         BEGIN_CASE("5","最初の要素を取得できる") {
320             instance = col.getInstance(typeid(TestCollectable2));
321             if(instance != &test2)
322                 TEST_FAIL;
323         } END_CASE;
324
325         BEGIN_CASE("6","次の要素を取得できる") {
326             instance = col.getInstance(typeid(TestCollectable2), instance);
327             if(instance != &test2_2)
328                 TEST_FAIL;
329         } END_CASE;
330
331         BEGIN_CASE("7","さらに次の要素を取得できる") {
332             instance = col.getInstance(typeid(TestCollectable2), instance);
333             if(instance != &test2_3)
334                 TEST_FAIL;
335         } END_CASE;
336
337         BEGIN_CASE("8","そのまた次の要素を取得したらNULLが返る") {
338             instance = col.getInstance(typeid(TestCollectable), instance);
339             if(instance != 0)
340                 TEST_FAIL;
341         } END_CASE;
342
343         BEGIN_CASE("9","基底クラスではひっかからない") {
344             instance = col.getInstance(typeid(Collectable));
345             if(instance != 0)
346                 TEST_FAIL;
347         } END_CASE;
348
349         TEST_CASE("10","NULLに対して実行するとNULLが返る", ((Collection *)0)->getInstance(typeid(Collectable)) == 0);
350     } END_CASE;
351
352     BEGIN_CASE("getInstance<T>()","getInstance<T>()") {
353         Collection col;
354         TestCollectable test;
355         TestCollectable test_2;
356         TestCollectable test_3;
357         TestCollectable2 test2;
358         TestCollectable2 test2_2;
359         TestCollectable2 test2_3;
360
361         col.addInstance(test);
362         col.addInstance(test2);
363         col.addInstance(test_2);
364         col.addInstance(test2_2);
365         col.addInstance(test_3);
366         col.addInstance(test2_3);
367
368         Collectable * instance = 0;
369
370         BEGIN_CASE("1","最初の要素を取得できる") {
371             instance = col.getInstance<TestCollectable>();
372             if(instance != &test)
373                 TEST_FAIL;
374         } END_CASE;
375
376         BEGIN_CASE("2","次の要素を取得できる") {
377             instance = col.getInstance<TestCollectable>(instance);
378             if(instance != &test_2)
379                 TEST_FAIL;
380         } END_CASE;
381
382         BEGIN_CASE("3","さらに次の要素を取得できる") {
383             instance = col.getInstance<TestCollectable>(instance);
384             if(instance != &test_3)
385                 TEST_FAIL;
386         } END_CASE;
387
388         BEGIN_CASE("4","そのまた次の要素を取得したらNULLが返る") {
389             instance = col.getInstance<TestCollectable>(instance);
390             if(instance != 0)
391                 TEST_FAIL;
392         } END_CASE;
393
394         BEGIN_CASE("5","最初の要素を取得できる") {
395             instance = col.getInstance<TestCollectable2>();
396             if(instance != &test2)
397                 TEST_FAIL;
398         } END_CASE;
399
400         BEGIN_CASE("6","次の要素を取得できる") {
401             instance = col.getInstance<TestCollectable2>(instance);
402             if(instance != &test2_2)
403                 TEST_FAIL;
404         } END_CASE;
405
406         BEGIN_CASE("7","さらに次の要素を取得できる") {
407             instance = col.getInstance<TestCollectable2>(instance);
408             if(instance != &test2_3)
409                 TEST_FAIL;
410         } END_CASE;
411
412         BEGIN_CASE("8","そのまた次の要素を取得したらNULLが返る") {
413             instance = col.getInstance<TestCollectable2>(instance);
414             if(instance != 0)
415                 TEST_FAIL;
416         } END_CASE;
417
418         BEGIN_CASE("9","基底クラスで引っ掛ける その1") {
419             instance = col.getInstance<Collectable>();
420             if(instance != &test)
421                 TEST_FAIL;
422         } END_CASE;
423
424         BEGIN_CASE("10","基底クラスで引っ掛ける その2") {
425             instance = col.getInstance<Collectable>(instance);
426             if(instance != &test2)
427                 TEST_FAIL;
428         } END_CASE;
429
430         BEGIN_CASE("11","基底クラスで引っ掛ける その3") {
431             instance = col.getInstance<Collectable>(instance);
432             if(instance != &test_2)
433                 TEST_FAIL;
434         } END_CASE;
435
436         BEGIN_CASE("12","基底クラスで引っ掛ける その4") {
437             instance = col.getInstance<Collectable>(instance);
438             if(instance != &test2_2)
439                 TEST_FAIL;
440         } END_CASE;
441
442         BEGIN_CASE("13","基底クラスで引っ掛ける その5") {
443             instance = col.getInstance<Collectable>(instance);
444             if(instance != &test_3)
445                 TEST_FAIL;
446         } END_CASE;
447
448         BEGIN_CASE("14","基底クラスで引っ掛ける その6") {
449             instance = col.getInstance<Collectable>(instance);
450             if(instance != &test2_3)
451                 TEST_FAIL;
452         } END_CASE;
453
454         BEGIN_CASE("15","基底クラスで引っ掛ける その7") {
455             instance = col.getInstance<Collectable>(instance);
456             if(instance != 0)
457                 TEST_FAIL;
458         } END_CASE;
459
460         TEST_CASE("16","NULLに対して実行するとNULLが返る", ((Collection *)0)->getInstance<Collectable>() == 0);
461
462     } END_CASE;
463
464     BEGIN_CASE("removeInstance","removeInstance") {
465
466         BEGIN_CASE("1","正常に削除できる") {
467             Collection col;
468             TestCollectable test;
469             TestCollectable test2;
470
471             col.addInstance(test);
472             col.addInstance(test2);
473
474             BEGIN_CASE("1","存在する要素をremoveしたらtrue") {
475                 if(!col.removeInstance(&test))
476                     TEST_FAIL;
477             } END_CASE;
478
479             BEGIN_CASE("2","ちゃんと消えている") {
480                 if(col.container.size() != 1 || col.container.begin()->instance != &test2)
481                     TEST_FAIL;
482             } END_CASE;
483         } END_CASE;
484
485         BEGIN_CASE("2","NULLインスタンスに実行するとfalse") {
486             if(((Collection *)0)->removeInstance(0))
487                 TEST_FAIL;
488         } END_CASE;
489
490         BEGIN_CASE("3","登録していないインスタンスを指定すると失敗する") {
491             Collection col;
492             TestCollectable test;
493             TestCollectable test2;
494
495             col.addInstance(test);
496
497             if(col.removeInstance(&test2))
498                 TEST_FAIL;
499         } END_CASE;
500
501         BEGIN_CASE("4","NULLインスタンスを渡すと失敗する") {
502             Collection col;
503             TestCollectable test;
504             col.addInstance(test);
505
506             if(col.removeInstance(0))
507                 TEST_FAIL;
508         } END_CASE;
509     } END_CASE;
510
511     BEGIN_CASE("clear","clear") {
512         BEGIN_CASE("1","実体を登録してclear") {
513             Collection col;
514             TestCollectable2 test2;
515
516             TestSuite::clearCheckpoints();
517             col.addInstance(test2);
518             col.clear();
519
520             BEGIN_CASE("1","要素がなくなっている") {
521                 if(col.container.size() != 0)
522                     TEST_FAIL;
523             } END_CASE;
524
525             TEST_CASE("2","test2は破棄されない", !TestSuite::isReached("TestCollectable2::~TestCollectable2"));
526         } END_CASE;
527
528         BEGIN_CASE("2","ポインタを登録してclear") {
529             Collection col;
530             TestCollectable2 * test2 = new TestCollectable2;
531             
532             TestSuite::clearCheckpoints();
533             col.addInstance(test2);
534             col.clear();
535
536             BEGIN_CASE("1","要素がなくなっている") {
537                 if(col.container.size() != 0)
538                     TEST_FAIL;
539             } END_CASE;
540
541             TEST_CASE("2","test2は破棄される", TestSuite::isReached("TestCollectable2::~TestCollectable2"));
542         } END_CASE;
543
544         BEGIN_CASE("3","NULLオブジェクトに対して実行しても暴走しない") {
545             ((Collection *)0)->clear();
546         } END_CASE;
547
548 #ifdef _MSC_VER
549         BEGIN_CASE("4","例外が出るようなデストラクタをもつインスタンスを破棄すると例外が漏れる") {
550             Collection col;
551             bool result = false;
552             TestCollectable3 * test = new TestCollectable3;
553
554             col.addInstance(test);
555             try {
556                 col.clear();
557             }
558             catch(...) {
559                 result = true;
560             }
561
562
563             if(!result)
564                 TEST_FAIL;
565         } END_CASE;
566 #endif
567     } END_CASE;
568
569     BEGIN_CASE("destructor","destructor") {
570         BEGIN_CASE("1","実体を登録して破棄") {
571             Collection * col = new Collection;
572             TestCollectable2 test2;
573
574             TestSuite::clearCheckpoints();
575             col->addInstance(test2);
576             delete col;
577
578             TEST_CASE("1","test2は破棄されない", !TestSuite::isReached("TestCollectable2::~TestCollectable2"));
579         } END_CASE;
580
581         BEGIN_CASE("2","ポインタを登録してclear") {
582             Collection * col = new Collection;
583             TestCollectable2 * test2 = new TestCollectable2;
584
585             TestSuite::clearCheckpoints();
586             col->addInstance(test2);
587             delete col;
588
589             TEST_CASE("1","test2は破棄される", TestSuite::isReached("TestCollectable2::~TestCollectable2"));
590         } END_CASE;
591
592 #ifdef _MSC_VER
593         BEGIN_CASE("3","例外が出るようなデストラクタを持つインスタンスを破棄しても例外が漏れない") {
594             Collection * col = new Collection;
595             TestCollectable3 * test2 = new TestCollectable3;
596             bool result = true;
597             
598             TestSuite::clearCheckpoints();
599             col->addInstance(test2);
600
601             try {
602                 delete col;
603             }
604             catch(...) {
605                 result = false;
606             }
607
608             if(!result)
609                 TEST_FAIL;
610         } END_CASE;
611 #endif
612     } END_CASE;
613
614     BEGIN_CASE("deleteInstance","deleteInstance") {
615         BEGIN_CASE("1","インスタンスを削除できる") {
616             Collection col;
617             TestCollectable2 * test = new TestCollectable2;
618
619             TestSuite::clearCheckpoints();
620             col.addInstance(test);
621
622             TEST_CASE("0","[前提] ちゃんと登録されている", col.getInstance<TestCollectable2>() != 0);
623
624             col.deleteInstance<TestCollectable2>();
625             TEST_CASE("1","インスタンスが消えている", col.getInstance<TestCollectable2>() == 0);
626             TEST_CASE("2","デストラクタが実行されている", TestSuite::isReached("TestCollectable2::~TestCollectable2"));
627         }END_CASE;
628
629         BEGIN_CASE("2","関係ないクラスを指定したら削除されない") {
630             Collection col;
631             TestCollectable2 * test = new TestCollectable2;
632
633             TestSuite::clearCheckpoints();
634             col.addInstance(test);
635
636             TEST_CASE("0","[前提] ちゃんと登録されている", col.getInstance<TestCollectable2>() != 0);
637
638             col.deleteInstance<TestCollectable>();
639             TEST_CASE("1","インスタンスが消えていない", col.getInstance<TestCollectable2>() != 0);
640             TEST_CASE("2","デストラクタが実行されていない", !TestSuite::isReached("TestCollectable2::~TestCollectable2"));
641             delete test;
642         }END_CASE;
643
644         BEGIN_CASE("3","同じクラスだけでなく派生先も消える") {
645             Collection col;
646             TestCollectable2 * test = new TestCollectable2;
647             TestCollectable4 * test2 = new TestCollectable4;
648
649             TestSuite::clearCheckpoints();
650             col.addInstance(test);
651             col.addInstance(test2);
652
653             TEST_CASE("0","[前提] ちゃんと登録されている", col.getInstance(typeid(TestCollectable2)) != 0);
654             TEST_CASE("0","[前提] ちゃんと登録されている", col.getInstance(typeid(TestCollectable4)) != 0);
655
656             col.deleteInstance<TestCollectable2>();
657             TEST_CASE("1","インスタンスがすべて消えている", col.getInstance<TestCollectable2>() == 0);
658             TEST_CASE("2","TestCollectable2のデストラクタが実行されている", TestSuite::isReached("TestCollectable2::~TestCollectable2"));
659             TEST_CASE("3","TestCollectable4のデストラクタが実行されている", TestSuite::isReached("TestCollectable4::~TestCollectable4"));
660         }END_CASE;
661
662         BEGIN_CASE("4","実体は破棄対象にならない") {
663             Collection col;
664             TestCollectable2 test;
665
666             TestSuite::clearCheckpoints();
667             col.addInstance(test);
668
669             TEST_CASE("0","[前提] ちゃんと登録されている", col.getInstance<TestCollectable2>() != 0);
670
671             col.deleteInstance<TestCollectable2>();
672             TEST_CASE("1","インスタンスが消えている", col.getInstance<TestCollectable2>() == 0);
673             TEST_CASE("2","デストラクタが実行されていない", !TestSuite::isReached("TestCollectable2::~TestCollectable2"));
674         }END_CASE;
675
676         BEGIN_CASE("5","NULLオブジェクトに対して発行しても暴走しない") {
677             ((Collection *)0)->deleteInstance<TestCollectable>();
678         } END_CASE;
679
680     } END_CASE;
681
682     BEGIN_CASE("replaceInstance","replaceInstance") {
683         BEGIN_CASE("1","登録済みのインスタンスを入れ替える") {
684             Collection col;
685             TestCollectable2 test;
686             TestCollectable2 test2;
687
688             TestSuite::clearCheckpoints();
689             col.addInstance(test);
690
691             TEST_CASE("0","[前提] ちゃんと登録されている", col.getInstance(typeid(TestCollectable2)) != 0);
692             
693             TEST_CASE("1", "関数は成功する", col.replaceInstance<TestCollectable2>(test2));
694             TEST_CASE("2", "インスタンスは入れ替わっている", col.getInstance(typeid(TestCollectable2)) == &test2);
695             TEST_CASE("3", "test2以外にインスタンスはない", col.getInstance(typeid(TestCollectable2), &test2) == 0);
696             TEST_CASE("4", "デストラクタは実行されてない", !TestSuite::isReached("TestCollectable2::~TestCollectable2"));
697         } END_CASE;
698
699         BEGIN_CASE("2","登録済みのインスタンスを派生クラスのインスタンスで入れ替える") {
700             Collection col;
701             TestCollectable2 test;
702             TestCollectable4 test2;
703
704             TestSuite::clearCheckpoints();
705             col.addInstance(test);
706
707             TEST_CASE("0","[前提] ちゃんと登録されている", col.getInstance(typeid(TestCollectable2)) != 0);
708             
709             TEST_CASE("1", "関数は成功する", col.replaceInstance<TestCollectable2>(test2));
710             TEST_CASE("2", "インスタンスは入れ替わっている", col.getInstance<TestCollectable2>() == &test2);
711             TEST_CASE("3", "test2以外にインスタンスはない", col.getInstance(typeid(TestCollectable2)) == 0);
712             TEST_CASE("4", "デストラクタは実行されてない", !TestSuite::isReached("TestCollectable2::~TestCollectable2"));
713         } END_CASE;
714
715         BEGIN_CASE("3","無関係なクラスを指定して入れ替える") {
716             Collection col;
717             TestCollectable2 test;
718             TestCollectable4 test2;
719
720             TestSuite::clearCheckpoints();
721             col.addInstance(test);
722
723             TEST_CASE("0","[前提] ちゃんと登録されている", col.getInstance(typeid(TestCollectable2)) != 0);
724             
725             TEST_CASE("1", "関数は失敗する", !col.replaceInstance<TestCollectable>(test2));
726             TEST_CASE("2", "インスタンスは残っている", col.getInstance<TestCollectable2>() == &test);
727         } END_CASE;
728
729         BEGIN_CASE("4","登録済みのインスタンスを入れ替える (動的確保)") {
730             Collection col;
731             TestCollectable2 * test = new TestCollectable2;
732             TestCollectable2 test2;
733
734             TestSuite::clearCheckpoints();
735             col.addInstance(test);
736
737             TEST_CASE("0","[前提] ちゃんと登録されている", col.getInstance(typeid(TestCollectable2)) != 0);
738             
739             TEST_CASE("1", "関数は成功する", col.replaceInstance<TestCollectable2>(test2));
740             TEST_CASE("2", "インスタンスは入れ替わっている", col.getInstance(typeid(TestCollectable2)) == &test2);
741             TEST_CASE("3", "test2以外にインスタンスはない", col.getInstance(typeid(TestCollectable2), &test2) == 0);
742             TEST_CASE("4", "デストラクタは実行されてる", TestSuite::isReached("TestCollectable2::~TestCollectable2"));
743         } END_CASE;
744
745     } END_CASE;
746 }
747
748
749 class TestRuntimeObject : public RuntimeObject
750 {
751 public:
752     TestRuntimeObject(void) { CHECKPOINT("TestRuntimeObject::TestRuntimeObject"); }
753     ~TestRuntimeObject(void) { CHECKPOINT("TestRuntimeObject::~TestRuntimeObject"); }
754 };
755
756 class TestRuntimeObject2 : public RuntimeObject
757 {
758 public:
759     TestRuntimeObject2(void) : RuntimeObject(true) { CHECKPOINT("TestRuntimeObject2::TestRuntimeObject2"); }
760     ~TestRuntimeObject2(void) { CHECKPOINT("TestRuntimeObject2::~TestRuntimeObject2"); }
761 };
762
763 TESTSUITE(main, RuntimeObjectTable)
764 {
765     Singleton<RuntimeObjectTable>::Context context;
766     Singleton<RuntimeObjectTable>::saveContext(context);
767
768     BEGIN_CASE("getInstance","getInstance") {
769         BEGIN_CASE("1","getInstanceは正しく機能する") {
770             Singleton<RuntimeObjectTable>::renewInstance();
771             TestCollectable test;
772
773             Singleton<RuntimeObjectTable>::getInstance()->addInstance(test);
774
775             BEGIN_CASE("1","getInstance(typeid)") {
776                 if(RuntimeObjectTable::getInstance(typeid(TestCollectable)) != &test)
777                     TEST_FAIL;
778             } END_CASE;
779
780             BEGIN_CASE("2","getInstance<T>()") {
781                 if(RuntimeObjectTable::getInstance<TestCollectable>() != &test)
782                     TEST_FAIL;
783             } END_CASE;
784         } END_CASE;
785     } END_CASE;
786
787     BEGIN_CASE("RuntimeObject","RuntimeObject") {
788         BEGIN_CASE("1","生成すると登録され、破棄で消滅する") {
789             TestRuntimeObject * ro;
790
791             TestSuite::clearCheckpoints();
792
793             TEST_CASE("0","[前提] 登録されていない", RuntimeObjectTable::getInstance<TestRuntimeObject>() == 0);
794
795             ro = new TestRuntimeObject;
796
797             TEST_CASE("1","コンストラクタが実行されている", TestSuite::isReached("TestRuntimeObject::TestRuntimeObject"));
798             TEST_CASE("2","登録されている", RuntimeObjectTable::getInstance<TestRuntimeObject>() == ro);
799
800             delete ro;
801
802             TEST_CASE("3","デストラクタが実行されている", TestSuite::isReached("TestRuntimeObject::~TestRuntimeObject"));
803             TEST_CASE("4","登録が解除されている", RuntimeObjectTable::getInstance<TestRuntimeObject>() == 0);
804
805         } END_CASE;
806
807         BEGIN_CASE("2","自動破棄のチェック") {
808             TestRuntimeObject * ro;
809             TestRuntimeObject2 * ro2;
810
811             TestSuite::clearCheckpoints();
812
813             TEST_CASE("0","[前提] 登録されていない", RuntimeObjectTable::getInstance<TestRuntimeObject>() == 0);
814             TEST_CASE("0","[前提] 登録されていない", RuntimeObjectTable::getInstance<TestRuntimeObject2>() == 0);
815
816             ro = new TestRuntimeObject;
817             ro2 = new TestRuntimeObject2;
818
819             TEST_CASE("1","コンストラクタが実行されている(ro)", TestSuite::isReached("TestRuntimeObject::TestRuntimeObject"));
820             TEST_CASE("2","コンストラクタが実行されている(ro2)", TestSuite::isReached("TestRuntimeObject2::TestRuntimeObject2"));
821             TEST_CASE("3","登録されている(ro)", RuntimeObjectTable::getInstance<TestRuntimeObject>() == ro);
822             TEST_CASE("4","登録されている(ro2)", RuntimeObjectTable::getInstance<TestRuntimeObject2>() == ro2);
823
824             Singleton<RuntimeObjectTable>::getInstance()->clear();
825
826             TEST_CASE("5","デストラクタは実行されていない (ro)", !TestSuite::isReached("TestRuntimeObject::~TestRuntimeObject"));
827             TEST_CASE("6","デストラクタは実行されている (ro2)", TestSuite::isReached("TestRuntimeObject2::~TestRuntimeObject2"));
828             TEST_CASE("7","登録が解除されている", RuntimeObjectTable::getInstance<TestRuntimeObject>() == 0);
829             TEST_CASE("8","登録が解除されている", RuntimeObjectTable::getInstance<TestRuntimeObject2>() == 0);
830
831             delete ro;
832         } END_CASE;
833
834     } END_CASE;
835
836     Singleton<RuntimeObjectTable>::restoreContext(context);
837 }
838
839 #endif
840