fixed wxVector<T> to work with non-POD types again; added optimization to keep using...
[wxWidgets.git] / tests / vectors / vectors.cpp
1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: tests/vectors/vectors.cpp
3 // Purpose: wxVector<T> unit test
4 // Author: Vaclav Slavik
5 // Created: 2007-07-07
6 // RCS-ID: $Id$
7 // Copyright: (c) 2007 Vaclav Slavik
8 ///////////////////////////////////////////////////////////////////////////////
9
10 // ----------------------------------------------------------------------------
11 // headers
12 // ----------------------------------------------------------------------------
13
14 #include "testprec.h"
15
16 #ifdef __BORLANDC__
17 #pragma hdrstop
18 #endif
19
20 #ifndef WX_PRECOMP
21 #include "wx/wx.h"
22 #endif // WX_PRECOMP
23
24 #include "wx/vector.h"
25
26 // ----------------------------------------------------------------------------
27 // simple class capable of detecting leaks of its objects
28 // ----------------------------------------------------------------------------
29
30 class CountedObject
31 {
32 public:
33 CountedObject(int n = 0) : m_n(n) { ms_count++; }
34 CountedObject(const CountedObject& co) : m_n(co.m_n) { ms_count++; }
35 ~CountedObject() { ms_count--; }
36
37 int GetValue() const { return m_n; }
38
39 static int GetCount() { return ms_count; }
40
41 private:
42 static int ms_count;
43
44 int m_n;
45 };
46
47 int CountedObject::ms_count = 0;
48
49 // ----------------------------------------------------------------------------
50 // simple class capable of checking it's this pointer validity
51 // ----------------------------------------------------------------------------
52
53 class SelfPointingObject
54 {
55 public:
56 SelfPointingObject() { m_self = this; }
57 SelfPointingObject(const SelfPointingObject&) { m_self = this; }
58 ~SelfPointingObject() { CPPUNIT_ASSERT( this == m_self ); }
59
60 private:
61 SelfPointingObject *m_self;
62 };
63
64 // ----------------------------------------------------------------------------
65 // test class
66 // ----------------------------------------------------------------------------
67
68 class VectorsTestCase : public CppUnit::TestCase
69 {
70 public:
71 VectorsTestCase() {}
72
73 private:
74 CPPUNIT_TEST_SUITE( VectorsTestCase );
75 CPPUNIT_TEST( PushPopTest );
76 CPPUNIT_TEST( Insert );
77 CPPUNIT_TEST( Erase );
78 CPPUNIT_TEST( Iterators );
79 CPPUNIT_TEST( Objects );
80 CPPUNIT_TEST( NonPODs );
81 CPPUNIT_TEST_SUITE_END();
82
83 void PushPopTest();
84 void Insert();
85 void Erase();
86 void Iterators();
87 void Objects();
88 void NonPODs();
89
90 DECLARE_NO_COPY_CLASS(VectorsTestCase)
91 };
92
93 // register in the unnamed registry so that these tests are run by default
94 CPPUNIT_TEST_SUITE_REGISTRATION( VectorsTestCase );
95
96 // also include in it's own registry so that these tests can be run alone
97 CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( VectorsTestCase, "VectorsTestCase" );
98
99 void VectorsTestCase::PushPopTest()
100 {
101 wxVector<int> v;
102
103 CPPUNIT_ASSERT( v.size() == 0 );
104 v.push_back(1);
105 CPPUNIT_ASSERT( v.size() == 1 );
106 v.push_back(2);
107 CPPUNIT_ASSERT( v.size() == 2 );
108 v.push_back(42);
109 CPPUNIT_ASSERT( v.size() == 3 );
110
111 CPPUNIT_ASSERT( v[0] == 1 );
112 CPPUNIT_ASSERT( v[1] == 2 );
113 CPPUNIT_ASSERT( v[2] == 42 );
114
115 v.pop_back();
116 CPPUNIT_ASSERT( v.size() == 2 );
117 CPPUNIT_ASSERT( v[0] == 1 );
118 CPPUNIT_ASSERT( v[1] == 2 );
119
120 v.pop_back();
121 CPPUNIT_ASSERT( v.size() == 1 );
122 CPPUNIT_ASSERT( v[0] == 1 );
123
124 v.pop_back();
125 CPPUNIT_ASSERT( v.size() == 0 );
126 CPPUNIT_ASSERT( v.empty() );
127
128 wxVector<char> vEmpty;
129 }
130
131 void VectorsTestCase::Insert()
132 {
133 wxVector<char> v;
134
135 v.insert(v.end(), 'a');
136 CPPUNIT_ASSERT( v.size() == 1 );
137 CPPUNIT_ASSERT( v[0] == 'a' );
138
139 v.insert(v.end(), 'b');
140 CPPUNIT_ASSERT( v.size() == 2 );
141 CPPUNIT_ASSERT( v[0] == 'a' );
142 CPPUNIT_ASSERT( v[1] == 'b' );
143
144 v.insert(v.begin(), '0');
145 CPPUNIT_ASSERT( v.size() == 3 );
146 CPPUNIT_ASSERT( v[0] == '0' );
147 CPPUNIT_ASSERT( v[1] == 'a' );
148 CPPUNIT_ASSERT( v[2] == 'b' );
149
150 v.insert(v.begin() + 2, 'X');
151 CPPUNIT_ASSERT( v.size() == 4 );
152 CPPUNIT_ASSERT( v[0] == '0' );
153 CPPUNIT_ASSERT( v[1] == 'a' );
154 CPPUNIT_ASSERT( v[2] == 'X' );
155 CPPUNIT_ASSERT( v[3] == 'b' );
156 }
157
158 void VectorsTestCase::Erase()
159 {
160 wxVector<int> v;
161
162 v.push_back(1);
163 v.push_back(2);
164 v.push_back(3);
165 v.push_back(4);
166 CPPUNIT_ASSERT( v.size() == 4 );
167
168 v.erase(v.begin(), v.end()-1);
169 CPPUNIT_ASSERT( v.size() == 1 );
170 CPPUNIT_ASSERT( v[0] == 4 );
171
172 v.clear();
173 v.push_back(1);
174 v.push_back(2);
175 v.push_back(3);
176 v.push_back(4);
177 CPPUNIT_ASSERT( v.size() == 4 );
178
179 v.erase(v.begin());
180 CPPUNIT_ASSERT( v.size() == 3 );
181 CPPUNIT_ASSERT( v[0] == 2 );
182 CPPUNIT_ASSERT( v[1] == 3 );
183 CPPUNIT_ASSERT( v[2] == 4 );
184 }
185
186 void VectorsTestCase::Iterators()
187 {
188 wxVector<int> v;
189 v.push_back(1);
190 v.push_back(2);
191 v.push_back(3);
192 v.push_back(4);
193
194 int value = 1;
195 for ( wxVector<int>::iterator i = v.begin(); i != v.end(); ++i, ++value )
196 {
197 CPPUNIT_ASSERT_EQUAL( value, *i );
198 }
199 }
200
201 void VectorsTestCase::Objects()
202 {
203 wxVector<CountedObject> v;
204 v.push_back(CountedObject(1));
205 v.push_back(CountedObject(2));
206 v.push_back(CountedObject(3));
207
208 v.erase(v.begin());
209 WX_ASSERT_SIZET_EQUAL( 2, v.size() );
210 CPPUNIT_ASSERT_EQUAL( 2, CountedObject::GetCount() );
211
212 v.clear();
213 CPPUNIT_ASSERT_EQUAL( 0, CountedObject::GetCount() );
214 }
215
216 void VectorsTestCase::NonPODs()
217 {
218 wxVector<SelfPointingObject> v;
219 v.push_back(SelfPointingObject());
220 v.push_back(SelfPointingObject());
221 v.push_back(SelfPointingObject());
222
223 v.erase(v.begin());
224 v.clear();
225
226 // try the same with wxString, which is not POD, but is implemented in
227 // a movable way (this won't assert, but would crash or show some memory
228 // problems under Valgrind if wxString couldn't be safely moved with
229 // memmove()):
230 wxVector<wxString> vs;
231 vs.push_back("one");
232 vs.push_back("two");
233 vs.push_back("three");
234
235 vs.erase(vs.begin());
236 vs.clear();
237 }