1 ///////////////////////////////////////////////////////////////////////////////
2 // Name:        tests/longlong/longlong.cpp
3 // Purpose:     wxLongLong unit test
4 // Author:      Vadim Zeitlin, Wlodzimierz ABX Skiba
5 // Created:     2004-04-01
6 // Copyright:   (c) 2004 Vadim Zeitlin, Wlodzimierz Skiba
7 ///////////////////////////////////////////////////////////////////////////////
8 
9 // ----------------------------------------------------------------------------
10 // headers
11 // ----------------------------------------------------------------------------
12 
13 #include "testprec.h"
14 
15 
16 #ifndef WX_PRECOMP
17     #include "wx/wx.h"
18 #endif // WX_PRECOMP
19 
20 #include "wx/longlong.h"
21 #include "wx/timer.h"
22 
23 #if wxUSE_LONGLONG
24 
25 // ----------------------------------------------------------------------------
26 // helpers for testing
27 // ----------------------------------------------------------------------------
28 
29 // number of iterations in loops
30 #define ITEMS 1000
31 
32 // make a 64 bit number from 4 16 bit ones
33 #define MAKE_LL(x1, x2, x3, x4) wxLongLong((x1 << 16) | x2, (x3 << 16) | x3)
34 
35 // get a random 64 bit number
36 #define RAND_LL()   MAKE_LL(rand(), rand(), rand(), rand())
37 
38 static const long testLongs[] =
39 {
40     0,
41     1,
42     -1,
43     LONG_MAX,
44     LONG_MIN,
45     0x1234,
46     -0x1234
47 };
48 
49 // ----------------------------------------------------------------------------
50 // test class
51 // ----------------------------------------------------------------------------
52 
53 class LongLongTestCase : public CppUnit::TestCase
54 {
55 public:
56     LongLongTestCase();
57 
58 private:
59     CPPUNIT_TEST_SUITE( LongLongTestCase );
60         CPPUNIT_TEST( Conversion );
61         CPPUNIT_TEST( Comparison );
62         CPPUNIT_TEST( Addition );
63         CPPUNIT_TEST( Multiplication );
64         CPPUNIT_TEST( Division );
65         CPPUNIT_TEST( BitOperations );
66         CPPUNIT_TEST( ToString );
67         CPPUNIT_TEST( LoHi );
68         CPPUNIT_TEST( Limits );
69     CPPUNIT_TEST_SUITE_END();
70 
71     void Conversion();
72     void Comparison();
73     void Addition();
74     void Multiplication();
75     void Division();
76     void BitOperations();
77     void ToString();
78     void LoHi();
79     void Limits();
80 
81     wxDECLARE_NO_COPY_CLASS(LongLongTestCase);
82 };
83 
84 // register in the unnamed registry so that these tests are run by default
85 CPPUNIT_TEST_SUITE_REGISTRATION( LongLongTestCase );
86 
87 // also include in its own registry so that these tests can be run alone
88 CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( LongLongTestCase, "LongLongTestCase" );
89 
LongLongTestCase()90 LongLongTestCase::LongLongTestCase()
91 {
92     srand((unsigned)time(NULL));
93 }
94 
Conversion()95 void LongLongTestCase::Conversion()
96 {
97     for ( size_t n = 0; n < ITEMS; n++ )
98     {
99         wxLongLong a = RAND_LL();
100 
101         wxLongLong b(a.GetHi(), a.GetLo());
102         CPPUNIT_ASSERT( a == b );
103 
104 #if wxUSE_LONGLONG_WX
105         wxLongLongWx c(a.GetHi(), a.GetLo());
106         CPPUNIT_ASSERT( a == c );
107 #endif
108 
109 #if wxUSE_LONGLONG_NATIVE
110         wxLongLongNative d(a.GetHi(), a.GetLo());
111         CPPUNIT_ASSERT( a == d );
112 #endif
113     }
114 }
115 
Comparison()116 void LongLongTestCase::Comparison()
117 {
118     static const long ls[2] =
119     {
120         0x1234,
121        -0x1234,
122     };
123 
124     wxLongLong lls[2];
125     lls[0] = ls[0];
126     lls[1] = ls[1];
127 
128     for ( size_t n = 0; n < WXSIZEOF(testLongs); n++ )
129     {
130         for ( size_t m = 0; m < WXSIZEOF(lls); m++ )
131         {
132             CPPUNIT_ASSERT( (lls[m] < testLongs[n]) == (ls[m] < testLongs[n]) );
133             CPPUNIT_ASSERT( (lls[m] > testLongs[n]) == (ls[m] > testLongs[n]) );
134             CPPUNIT_ASSERT( (lls[m] <= testLongs[n]) == (ls[m] <= testLongs[n]) );
135             CPPUNIT_ASSERT( (lls[m] >= testLongs[n]) == (ls[m] >= testLongs[n]) );
136             CPPUNIT_ASSERT( (lls[m] != testLongs[n]) == (ls[m] != testLongs[n]) );
137             CPPUNIT_ASSERT( (lls[m] == testLongs[n]) == (ls[m] == testLongs[n]) );
138         }
139     }
140 }
141 
Addition()142 void LongLongTestCase::Addition()
143 {
144     for ( size_t n = 0; n < ITEMS; n++ )
145     {
146         wxLongLong a = RAND_LL();
147         wxLongLong b = RAND_LL();
148         wxLongLong c = a + b;
149 
150 #if wxUSE_LONGLONG_NATIVE
151         wxLongLongNative a1 = a;
152         wxLongLongNative b1 = b;
153         wxLongLongNative c1 = a1 + b1;
154         CPPUNIT_ASSERT( c == c1 );
155 #endif
156 
157 #if wxUSE_LONGLONG_WX
158         wxLongLongWx a2 = a;
159         wxLongLongWx b2 = b;
160         wxLongLongWx c2 = a2 + b2;
161         CPPUNIT_ASSERT( c == c2 );
162 #endif
163     }
164 }
165 
Multiplication()166 void LongLongTestCase::Multiplication()
167 {
168     for ( size_t n = 0; n < ITEMS; n++ )
169     {
170         wxLongLong a = RAND_LL();
171         wxLongLong b = RAND_LL();
172         wxLongLong c = a*b;
173 
174         wxLongLong a1(a.GetHi(), a.GetLo());
175         wxLongLong b1(b.GetHi(), b.GetLo());
176         wxLongLong c1 = a1*b1;
177         CPPUNIT_ASSERT( c1 == c );
178 
179 #if wxUSE_LONGLONG_WX
180         wxLongLongWx a2(a.GetHi(), a.GetLo());
181         wxLongLongWx b2(b.GetHi(), b.GetLo());
182         wxLongLongWx c2 = a2*b2;
183         CPPUNIT_ASSERT( c2 == c );
184 #endif
185 
186 #if wxUSE_LONGLONG_NATIVE
187         wxLongLongNative a3(a.GetHi(), a.GetLo());
188         wxLongLongNative b3(b.GetHi(), b.GetLo());
189         wxLongLongNative c3 = a3*b3;
190         CPPUNIT_ASSERT( c3 == c );
191 #endif
192     }
193 }
194 
Division()195 void LongLongTestCase::Division()
196 {
197     for ( size_t n = 0; n < ITEMS; n++ )
198     {
199         // get a random wxLongLong (shifting by 12 the MSB ensures that the
200         // multiplication will not overflow)
201         wxLongLong a = MAKE_LL((rand() >> 12), rand(), rand(), rand());
202 
203         // get a random (but non null) long (not wxLongLong for now) divider
204         long l;
205         do
206         {
207            l = rand();
208         }
209         while ( !l );
210 
211         wxLongLong q = a / l;
212         wxLongLong r = a % l;
213 
214         CPPUNIT_ASSERT( a == ( q * l + r ) );
215 
216 #if wxUSE_LONGLONG_WX
217         wxLongLongWx a1(a.GetHi(), a.GetLo());
218         wxLongLongWx q1 = a1 / l;
219         wxLongLongWx r1 = a1 % l;
220         CPPUNIT_ASSERT( q == q1 );
221         CPPUNIT_ASSERT( r == r1 );
222         CPPUNIT_ASSERT( a1 == ( q1 * l + r1 ) );
223 #endif
224 
225 #if wxUSE_LONGLONG_NATIVE
226         wxLongLongNative a2(a.GetHi(), a.GetLo());
227         wxLongLongNative q2 = a2 / l;
228         wxLongLongNative r2 = a2 % l;
229         CPPUNIT_ASSERT( q == q2 );
230         CPPUNIT_ASSERT( r == r2 );
231         CPPUNIT_ASSERT( a2 == ( q2 * l + r2 ) );
232 #endif
233     }
234 }
235 
BitOperations()236 void LongLongTestCase::BitOperations()
237 {
238     for ( size_t m = 0; m < ITEMS; m++ )
239     {
240         wxLongLong a = RAND_LL();
241 
242         for ( size_t n = 0; n < 33; n++ )
243         {
244             wxLongLong b(a.GetHi(), a.GetLo()), c, d = b, e;
245             d >>= n;
246             c = b >> n;
247             CPPUNIT_ASSERT( c == d );
248             d <<= n;
249             e = c << n;
250             CPPUNIT_ASSERT( d == e );
251 
252 #if wxUSE_LONGLONG_WX
253             wxLongLongWx b1(a.GetHi(), a.GetLo()), c1, d1 = b1, e1;
254             d1 >>= n;
255             c1 = b1 >> n;
256             CPPUNIT_ASSERT( c1 == d1 );
257             d1 <<= n;
258             e1 = c1 << n;
259             CPPUNIT_ASSERT( d1 == e1 );
260 #endif
261 
262 #if wxUSE_LONGLONG_NATIVE
263             wxLongLongNative b2(a.GetHi(), a.GetLo()), c2, d2 = b2, e2;
264             d2 >>= n;
265             c2 = b2 >> n;
266             CPPUNIT_ASSERT( c2 == d2 );
267             d2 <<= n;
268             e2 = c2 << n;
269             CPPUNIT_ASSERT( d2 == e2 );
270 #endif
271         }
272     }
273 }
274 
ToString()275 void LongLongTestCase::ToString()
276 {
277     wxString s1, s2;
278 
279     for ( size_t n = 0; n < WXSIZEOF(testLongs); n++ )
280     {
281         wxLongLong a = testLongs[n];
282         s1 = wxString::Format(wxT("%ld"), testLongs[n]);
283         s2 = a.ToString();
284         CPPUNIT_ASSERT( s1 == s2 );
285 
286         s2 = wxEmptyString;
287         s2 << a;
288         CPPUNIT_ASSERT( s1 == s2 );
289 
290 #if wxUSE_LONGLONG_WX
291         wxLongLongWx a1 = testLongs[n];
292         s2 = a1.ToString();
293         CPPUNIT_ASSERT( s1 == s2 );
294 #endif
295 
296 #if wxUSE_LONGLONG_NATIVE
297         wxLongLongNative a2 = testLongs[n];
298         s2 = a2.ToString();
299         CPPUNIT_ASSERT( s1 == s2 );
300 #endif
301     }
302 
303     wxLongLong a(0x12345678, 0x87654321);
304     CPPUNIT_ASSERT( a.ToString() == wxT("1311768467139281697") );
305     a.Negate();
306     CPPUNIT_ASSERT( a.ToString() == wxT("-1311768467139281697") );
307 
308     wxLongLong llMin(-2147483647L - 1L, 0);
309     CPPUNIT_ASSERT( llMin.ToString() == wxT("-9223372036854775808") );
310 
311 #if wxUSE_LONGLONG_WX
312     wxLongLongWx a1(a.GetHi(), a.GetLo());
313     CPPUNIT_ASSERT( a1.ToString() == wxT("-1311768467139281697") );
314     a1.Negate();
315     CPPUNIT_ASSERT( a1.ToString() == wxT("1311768467139281697") );
316 #endif
317 
318 #if wxUSE_LONGLONG_NATIVE
319     wxLongLongNative a2(a.GetHi(), a.GetLo());
320     CPPUNIT_ASSERT( a2.ToString() == wxT("-1311768467139281697") );
321     a2.Negate();
322     CPPUNIT_ASSERT( a2.ToString() == wxT("1311768467139281697") );
323 #endif
324 
325 }
326 
LoHi()327 void LongLongTestCase::LoHi()
328 {
329     wxLongLong ll(123, 456);
330     CPPUNIT_ASSERT_EQUAL( 456u, ll.GetLo() );
331     CPPUNIT_ASSERT_EQUAL( 123, ll.GetHi() );
332 
333     wxULongLong ull(987, 654);
334     CPPUNIT_ASSERT_EQUAL( 654u, ull.GetLo() );
335     CPPUNIT_ASSERT_EQUAL( 987u, ull.GetHi() );
336 }
337 
Limits()338 void LongLongTestCase::Limits()
339 {
340 #if wxUSE_LONGLONG_NATIVE
341     CPPUNIT_ASSERT( std::numeric_limits<wxLongLong>::is_specialized );
342     CPPUNIT_ASSERT( std::numeric_limits<wxULongLong>::is_specialized );
343 
344     wxULongLong maxval = std::numeric_limits<wxULongLong>::max();
345     CPPUNIT_ASSERT( maxval.ToDouble() > 0 );
346 #endif // wxUSE_LONGLONG_NATIVE
347 }
348 
349 #endif // wxUSE_LONGLONG
350