OSDN Git Service

今日の作業はここまで
[gintenlib/gintenlib.git] / tests / clonable_ptr.cc
1 #include "../gintenlib/clonable_ptr.hpp"
2
3 // boost の単体テストフレームワーク
4 #include <boost/test/minimal.hpp>
5
6 // ポインタ自身のテスト
7 template<typename T>
8 void test_pointer( const gintenlib::clonable_ptr<T>& p )
9 {
10   // まず get() と get_pointer() のチェック
11   BOOST_CHECK( p.get() == get_pointer(p) );
12   
13   // NULL でない場合
14   if( p )
15   {
16     // operator! のチェック
17     BOOST_CHECK( !p == false );
18     
19     // operator*, operator-> のチェック
20     BOOST_CHECK( p.get() == &*p );
21     BOOST_CHECK( p.get() == p.operator->() );
22     
23     // use_count と unique のチェック
24     BOOST_CHECK( ( p.use_count() == 1 ) == p.unique() );
25   }
26   else
27   {
28     // get() は NULLか
29     BOOST_CHECK( p.get() == 0 );
30     // operator! のチェック
31     BOOST_CHECK( !p );
32     
33     // use_count は 0 か?
34     BOOST_CHECK( p.use_count() == 0 );
35     // !unique() か?
36     BOOST_CHECK( !p.unique() );
37     
38   }
39 }
40
41 // 基本的なチェック
42 template<typename T>
43 void test1( const gintenlib::clonable_ptr<T>& p0 )
44 {
45   using gintenlib::clonable_ptr;
46   
47   // まず p0 をテスト
48   test_pointer( p0 );
49   
50   // デフォルト構築
51   {
52     clonable_ptr<T> p1;
53     // NULL にセットされているか?
54     BOOST_CHECK( !p1 );
55     
56     // 他、もろもろはおk?
57     test_pointer( p1 );
58   }
59   
60   // コピー
61   {
62     // コピーに先立って参照カウントを調べる
63     int count = p0.use_count();
64     
65     // コピーする
66     clonable_ptr<T> p1 = p0;
67     // とりあえずテスト
68     test_pointer( p1 );
69     // アドレスと参照カウントの両面で等しいことを確認
70     BOOST_CHECK( p0 == p1 );
71     BOOST_CHECK( p0.use_count() == p1.use_count() );
72     
73     // また、コピーが出来た分、参照カウントは増えているはず
74     if( p0 )
75     {
76       BOOST_CHECK( p0.use_count() == count+1 );
77     }
78     else
79     {
80       // NULL の場合は参照カウントはゼロになる
81       BOOST_CHECK( count == 0 );
82       BOOST_CHECK( p0.use_count() == 0 );
83     }
84     
85     // リセットのテスト
86     p1.reset();
87     BOOST_CHECK( p1 == 0 );
88     // ふたたびテスト
89     test_pointer( p1 );
90     
91     // この時点で参照カウントは元に戻るはず
92     BOOST_CHECK( p0.use_count() == count );
93   }
94   
95   // 本題。clone のテスト
96   {
97     // まず参照カウントを調べる
98     int count = p0.use_count();
99     
100     // clone を作る
101     clonable_ptr<T> p1;
102     p1 = p0.clone();
103     // とりあえずテスト
104     test_pointer( p1 );
105     
106     // clone() しても参照カウントは変わらない
107     BOOST_CHECK( p0.use_count() == count );
108     
109     if( p0 )
110     {
111       // clone で作られたオブジェクトは unique
112       BOOST_CHECK( p1.unique() );
113       // clone したため、別のオブジェクトが格納されてるはず
114       BOOST_CHECK( p0 != p1 );
115     }
116     else
117     {
118       // NULL の場合は p1 もゼロのはず
119       BOOST_CHECK( !p1 );
120     }
121     
122     // 生ポインタで to_unique の確認
123     T* p_ = p1.get();
124     // これまでの過程で p1 は null か unique のはず
125     BOOST_CHECK( !p1 || p1.unique() );
126     // unique のときは to_unique() を呼んでも何もしないはず
127     p1.to_unique();
128     BOOST_CHECK( p_ == p1.get() );
129     // 念のためテスト
130     test_pointer( p1 );
131     
132     // 次に p1 にふたたび p0 の値を入れる
133     p1 = p0;
134     // 念のためテスト
135     test_pointer( p1 );
136     // 生ポインタの値を更新
137     p_ = p1.get();
138     // これにより、NULL であるかユニークじゃないかの状態になった
139     BOOST_CHECK( !p1 || !p1.unique() );
140     // unique を呼ぶと p0 は変化せず p1 が変化するはず
141     p1.to_unique();
142     BOOST_CHECK( p_ == p0.get() );
143     BOOST_CHECK( !p1 || p_ != p1.get() );
144     // またまたテスト
145     test_pointer( p1 );
146   }
147   
148   // おまけで to_shared
149   {
150     // 先に参照カウントを調べる
151     int count = p0.use_count();
152     
153     boost::shared_ptr<T> p1 = to_shared( p0 );
154     // アドレスは一緒
155     BOOST_CHECK( p0.get() == p1.get() );
156     // カウントは一つ増える
157     BOOST_CHECK( !p0 || p0.use_count() == count+1 );
158     
159     // shared_ptr がリセットされた場合、ちゃんと参照カウントは減る?
160     p1.reset();
161     BOOST_CHECK( p0.use_count() == count );
162   }
163   
164   // const 関連
165   {
166     // T から const T への変換
167     clonable_ptr<const T> p1 = p0;
168     // 念のためテスト
169     test_pointer( p1 );
170     // アドレスとカウントが等しいことを確認
171     BOOST_CHECK( p0 == p1 );
172     BOOST_CHECK( p0.use_count() == p1.use_count() );
173     
174     // const T 型のポインタで reset してみる
175     p1.reset( static_cast<const T*>( new T() ) );
176     // reset 後は当然 unique()
177     BOOST_CHECK( p1 && p1.unique() );
178     // 念のため更にテスト
179     test_pointer( p1 );
180     
181     // const T => T の変換( clone すれば可能 )
182     clonable_ptr<T> p2 = p1.clone();
183     // clone しないと無理
184     // clonable_ptr<T> p2 = p1;
185     
186     // 念には念を入れてテスト
187     test_pointer( p2 );
188     // clone() 後なので当然 unique
189     BOOST_CHECK( p2 && p2.unique() );
190     BOOST_CHECK( p1 != p2 );
191   }
192   
193   // おわり
194 }
195
196 int test_main( int argc, char* argv[] )
197 {
198   test1( gintenlib::clonable_ptr<int>( new int() ) );
199   test1( gintenlib::clonable_ptr<int>( static_cast<int*>(0) ) );
200     
201   return 0;
202 }