]> git.saurik.com Git - wxWidgets.git/blame - samples/console/console.cpp
Some more bug reports
[wxWidgets.git] / samples / console / console.cpp
CommitLineData
37667812
VZ
1/////////////////////////////////////////////////////////////////////////////
2// Name: samples/console/console.cpp
3// Purpose: a sample console (as opposed to GUI) progam using wxWindows
4// Author: Vadim Zeitlin
5// Modified by:
6// Created: 04.10.99
7// RCS-ID: $Id$
8// Copyright: (c) 1999 Vadim Zeitlin <zeitlin@dptmaths.ens-cachan.fr>
9// Licence: wxWindows license
10/////////////////////////////////////////////////////////////////////////////
11
e87271f3
VZ
12// ============================================================================
13// declarations
14// ============================================================================
15
16// ----------------------------------------------------------------------------
17// headers
18// ----------------------------------------------------------------------------
19
37667812
VZ
20#include <stdio.h>
21
22#include <wx/string.h>
bbfa0322 23#include <wx/file.h>
37667812 24#include <wx/app.h>
e87271f3
VZ
25
26// ----------------------------------------------------------------------------
27// conditional compilation
28// ----------------------------------------------------------------------------
29
30// what to test?
378b05f7
VZ
31
32//#define TEST_ARRAYS
2a310492 33//#define TEST_CMDLINE
211c2250 34//#define TEST_DIR
b568d04f 35//#define TEST_LOG
5e6a0e83 36//#define TEST_LONGLONG
1944c6bd 37//#define TEST_MIME
9fc3ad34 38//#define TEST_STRINGS
d34bce84 39//#define TEST_THREADS
2a310492 40#define TEST_TIME
e87271f3
VZ
41
42// ============================================================================
43// implementation
44// ============================================================================
45
d34bce84
VZ
46#ifdef TEST_CMDLINE
47
48// ----------------------------------------------------------------------------
49// wxCmdLineParser
50// ----------------------------------------------------------------------------
51
52#include <wx/cmdline.h>
53#include <wx/datetime.h>
54
55static void ShowCmdLine(const wxCmdLineParser& parser)
56{
57 wxString s = "Input files: ";
58
59 size_t count = parser.GetParamCount();
60 for ( size_t param = 0; param < count; param++ )
61 {
62 s << parser.GetParam(param) << ' ';
63 }
64
65 s << '\n'
66 << "Verbose:\t" << (parser.Found("v") ? "yes" : "no") << '\n'
67 << "Quiet:\t" << (parser.Found("q") ? "yes" : "no") << '\n';
68
69 wxString strVal;
70 long lVal;
71 wxDateTime dt;
72 if ( parser.Found("o", &strVal) )
73 s << "Output file:\t" << strVal << '\n';
74 if ( parser.Found("i", &strVal) )
75 s << "Input dir:\t" << strVal << '\n';
76 if ( parser.Found("s", &lVal) )
77 s << "Size:\t" << lVal << '\n';
78 if ( parser.Found("d", &dt) )
79 s << "Date:\t" << dt.FormatISODate() << '\n';
80
81 wxLogMessage(s);
82}
83
84#endif // TEST_CMDLINE
85
1944c6bd
VZ
86// ----------------------------------------------------------------------------
87// wxDir
88// ----------------------------------------------------------------------------
89
90#ifdef TEST_DIR
91
92#include <wx/dir.h>
93
94static void TestDirEnumHelper(wxDir& dir,
95 int flags = wxDIR_DEFAULT,
96 const wxString& filespec = wxEmptyString)
97{
98 wxString filename;
99
100 if ( !dir.IsOpened() )
101 return;
102
103 bool cont = dir.GetFirst(&filename, filespec, flags);
104 while ( cont )
105 {
106 printf("\t%s\n", filename.c_str());
107
108 cont = dir.GetNext(&filename);
109 }
110
111 puts("");
112}
113
114static void TestDirEnum()
115{
116 wxDir dir(wxGetCwd());
117
118 puts("Enumerating everything in current directory:");
119 TestDirEnumHelper(dir);
120
121 puts("Enumerating really everything in current directory:");
122 TestDirEnumHelper(dir, wxDIR_DEFAULT | wxDIR_DOTDOT);
123
124 puts("Enumerating object files in current directory:");
125 TestDirEnumHelper(dir, wxDIR_DEFAULT, "*.o");
126
127 puts("Enumerating directories in current directory:");
128 TestDirEnumHelper(dir, wxDIR_DIRS);
129
130 puts("Enumerating files in current directory:");
131 TestDirEnumHelper(dir, wxDIR_FILES);
132
133 puts("Enumerating files including hidden in current directory:");
134 TestDirEnumHelper(dir, wxDIR_FILES | wxDIR_HIDDEN);
135
136#ifdef __UNIX__
137 dir.Open("/");
138#elif defined(__WXMSW__)
139 dir.Open("c:\\");
140#else
141 #error "don't know where the root directory is"
142#endif
143
144 puts("Enumerating everything in root directory:");
145 TestDirEnumHelper(dir, wxDIR_DEFAULT);
146
147 puts("Enumerating directories in root directory:");
148 TestDirEnumHelper(dir, wxDIR_DIRS);
149
150 puts("Enumerating files in root directory:");
151 TestDirEnumHelper(dir, wxDIR_FILES);
152
153 puts("Enumerating files including hidden in root directory:");
154 TestDirEnumHelper(dir, wxDIR_FILES | wxDIR_HIDDEN);
155
156 puts("Enumerating files in non existing directory:");
157 wxDir dirNo("nosuchdir");
158 TestDirEnumHelper(dirNo);
159}
160
161#endif // TEST_DIR
162
696e1ea0
VZ
163// ----------------------------------------------------------------------------
164// MIME types
165// ----------------------------------------------------------------------------
166
167#ifdef TEST_MIME
168
169#include <wx/mimetype.h>
170
171static void TestMimeEnum()
172{
173 wxMimeTypesManager mimeTM;
174 wxArrayString mimetypes;
175
176 size_t count = mimeTM.EnumAllFileTypes(mimetypes);
177
178 printf("*** All %u known filetypes: ***\n", count);
179
180 wxArrayString exts;
181 wxString desc;
182
183 for ( size_t n = 0; n < count; n++ )
184 {
185 wxFileType *filetype = mimeTM.GetFileTypeFromMimeType(mimetypes[n]);
186 if ( !filetype )
c61f4f6d 187 {
97e0ceea
VZ
188 printf("nothing known about the filetype '%s'!\n",
189 mimetypes[n].c_str());
696e1ea0 190 continue;
c61f4f6d
VZ
191 }
192
696e1ea0
VZ
193 filetype->GetDescription(&desc);
194 filetype->GetExtensions(exts);
195
299fcbfe
VZ
196 filetype->GetIcon(NULL);
197
696e1ea0
VZ
198 wxString extsAll;
199 for ( size_t e = 0; e < exts.GetCount(); e++ )
200 {
201 if ( e > 0 )
202 extsAll << _T(", ");
203 extsAll += exts[e];
204 }
205
54acce90
VZ
206 printf("\t%s: %s (%s)\n",
207 mimetypes[n].c_str(), desc.c_str(), extsAll.c_str());
696e1ea0
VZ
208 }
209}
210
211#endif // TEST_MIME
212
b76b015e
VZ
213// ----------------------------------------------------------------------------
214// long long
215// ----------------------------------------------------------------------------
216
217#ifdef TEST_LONGLONG
218
219#include <wx/longlong.h>
220#include <wx/timer.h>
221
2a310492
VZ
222// make a 64 bit number from 4 16 bit ones
223#define MAKE_LL(x1, x2, x3, x4) wxLongLong((x1 << 16) | x2, (x3 << 16) | x3)
224
225// get a random 64 bit number
226#define RAND_LL() MAKE_LL(rand(), rand(), rand(), rand())
227
228#if wxUSE_LONGLONG_NATIVE
229inline bool operator==(const wxLongLongWx& a, const wxLongLongNative& b)
230 { return a.GetHi() == b.GetHi() && a.GetLo() == b.GetLo(); }
231inline bool operator==(const wxLongLongNative& a, const wxLongLongWx& b)
232 { return a.GetHi() == b.GetHi() && a.GetLo() == b.GetLo(); }
233#endif // wxUSE_LONGLONG_NATIVE
234
b76b015e
VZ
235static void TestSpeed()
236{
237 static const long max = 100000000;
238 long n;
9fc3ad34 239
b76b015e
VZ
240 {
241 wxStopWatch sw;
242
243 long l = 0;
244 for ( n = 0; n < max; n++ )
245 {
246 l += n;
247 }
248
249 printf("Summing longs took %ld milliseconds.\n", sw.Time());
250 }
251
2ea24d9f 252#if wxUSE_LONGLONG_NATIVE
b76b015e
VZ
253 {
254 wxStopWatch sw;
255
2ea24d9f 256 wxLongLong_t l = 0;
b76b015e
VZ
257 for ( n = 0; n < max; n++ )
258 {
259 l += n;
260 }
261
2ea24d9f 262 printf("Summing wxLongLong_t took %ld milliseconds.\n", sw.Time());
b76b015e 263 }
2ea24d9f 264#endif // wxUSE_LONGLONG_NATIVE
b76b015e
VZ
265
266 {
267 wxStopWatch sw;
268
269 wxLongLong l;
270 for ( n = 0; n < max; n++ )
271 {
272 l += n;
273 }
274
275 printf("Summing wxLongLongs took %ld milliseconds.\n", sw.Time());
276 }
277}
278
2a310492 279static void TestLongLongConversion()
b76b015e 280{
2a310492
VZ
281 puts("*** Testing wxLongLong conversions ***\n");
282
283 wxLongLong a;
284 size_t nTested = 0;
285 for ( size_t n = 0; n < 100000; n++ )
286 {
287 a = RAND_LL();
288
289#if wxUSE_LONGLONG_NATIVE
290 wxLongLongNative b(a.GetHi(), a.GetLo());
5e6a0e83 291
2a310492
VZ
292 wxASSERT_MSG( a == b, "conversions failure" );
293#else
294 puts("Can't do it without native long long type, test skipped.");
b76b015e 295
2a310492
VZ
296 return;
297#endif // wxUSE_LONGLONG_NATIVE
298
299 if ( !(nTested % 1000) )
300 {
301 putchar('.');
302 fflush(stdout);
303 }
304
305 nTested++;
306 }
307
308 puts(" done!");
309}
310
311static void TestMultiplication()
312{
313 puts("*** Testing wxLongLong multiplication ***\n");
314
315 wxLongLong a, b;
316 size_t nTested = 0;
317 for ( size_t n = 0; n < 100000; n++ )
318 {
319 a = RAND_LL();
320 b = RAND_LL();
321
322#if wxUSE_LONGLONG_NATIVE
323 wxLongLongNative aa(a.GetHi(), a.GetLo());
324 wxLongLongNative bb(b.GetHi(), b.GetLo());
325
326 wxASSERT_MSG( a*b == aa*bb, "multiplication failure" );
327#else // !wxUSE_LONGLONG_NATIVE
328 puts("Can't do it without native long long type, test skipped.");
329
330 return;
331#endif // wxUSE_LONGLONG_NATIVE
332
333 if ( !(nTested % 1000) )
334 {
335 putchar('.');
336 fflush(stdout);
337 }
338
339 nTested++;
340 }
341
342 puts(" done!");
343}
344
345static void TestDivision()
346{
347 puts("*** Testing wxLongLong division ***\n");
2f02cb89 348
2ea24d9f 349 wxLongLong q, r;
2f02cb89 350 size_t nTested = 0;
5e6a0e83 351 for ( size_t n = 0; n < 100000; n++ )
2f02cb89
VZ
352 {
353 // get a random wxLongLong (shifting by 12 the MSB ensures that the
354 // multiplication will not overflow)
355 wxLongLong ll = MAKE_LL((rand() >> 12), rand(), rand(), rand());
356
2ea24d9f
VZ
357 // get a random long (not wxLongLong for now) to divide it with
358 long l = rand();
359 q = ll / l;
360 r = ll % l;
361
2a310492
VZ
362#if wxUSE_LONGLONG_NATIVE
363 wxLongLongNative m(ll.GetHi(), ll.GetLo());
364
365 wxLongLongNative p = m / l, s = m % l;
366 wxASSERT_MSG( q == p && r == s, "division failure" );
367#else // !wxUSE_LONGLONG_NATIVE
5e6a0e83 368 // verify the result
2ea24d9f 369 wxASSERT_MSG( ll == q*l + r, "division failure" );
2a310492 370#endif // wxUSE_LONGLONG_NATIVE
2f02cb89 371
5e6a0e83
VZ
372 if ( !(nTested % 1000) )
373 {
374 putchar('.');
375 fflush(stdout);
376 }
377
2f02cb89
VZ
378 nTested++;
379 }
380
5e6a0e83 381 puts(" done!");
2a310492 382}
2f02cb89 383
2a310492
VZ
384static void TestAddition()
385{
386 puts("*** Testing wxLongLong addition ***\n");
387
388 wxLongLong a, b, c;
389 size_t nTested = 0;
390 for ( size_t n = 0; n < 100000; n++ )
391 {
392 a = RAND_LL();
393 b = RAND_LL();
394 c = a + b;
395
396#if wxUSE_LONGLONG_NATIVE
397 wxASSERT_MSG( c == wxLongLongNative(a.GetHi(), a.GetLo()) +
398 wxLongLongNative(b.GetHi(), b.GetLo()),
399 "addition failure" );
400#else // !wxUSE_LONGLONG_NATIVE
401 wxASSERT_MSG( c - b == a, "addition failure" );
402#endif // wxUSE_LONGLONG_NATIVE
403
404 if ( !(nTested % 1000) )
405 {
406 putchar('.');
407 fflush(stdout);
408 }
409
410 nTested++;
411 }
412
413 puts(" done!");
b76b015e
VZ
414}
415
2a310492
VZ
416static void TestBitOperations()
417{
418 puts("*** Testing wxLongLong bit operation ***\n");
419
420 wxLongLong a, c;
421 size_t nTested = 0;
422 for ( size_t n = 0; n < 100000; n++ )
423 {
424 a = RAND_LL();
425
426#if wxUSE_LONGLONG_NATIVE
427 for ( size_t n = 0; n < 33; n++ )
428 {
429 wxLongLongNative b(a.GetHi(), a.GetLo());
430
431 b >>= n;
432 c = a >> n;
433
434 wxASSERT_MSG( b == c, "bit shift failure" );
435
436 b = wxLongLongNative(a.GetHi(), a.GetLo()) << n;
437 c = a << n;
438
439 wxASSERT_MSG( b == c, "bit shift failure" );
440 }
441
442#else // !wxUSE_LONGLONG_NATIVE
443 puts("Can't do it without native long long type, test skipped.");
444
445 return;
446#endif // wxUSE_LONGLONG_NATIVE
447
448 if ( !(nTested % 1000) )
449 {
450 putchar('.');
451 fflush(stdout);
452 }
453
454 nTested++;
455 }
456
457 puts(" done!");
458}
459
460#undef MAKE_LL
461#undef RAND_LL
462
b76b015e
VZ
463#endif // TEST_LONGLONG
464
465// ----------------------------------------------------------------------------
466// date time
467// ----------------------------------------------------------------------------
468
469#ifdef TEST_TIME
470
97e0ceea
VZ
471#include <wx/date.h>
472
b76b015e
VZ
473#include <wx/datetime.h>
474
299fcbfe
VZ
475// the test data
476struct Date
477{
478 wxDateTime::wxDateTime_t day;
479 wxDateTime::Month month;
480 int year;
481 wxDateTime::wxDateTime_t hour, min, sec;
482 double jdn;
211c2250 483 wxDateTime::WeekDay wday;
299fcbfe
VZ
484 time_t gmticks, ticks;
485
486 void Init(const wxDateTime::Tm& tm)
487 {
488 day = tm.mday;
489 month = tm.mon;
490 year = tm.year;
491 hour = tm.hour;
492 min = tm.min;
493 sec = tm.sec;
494 jdn = 0.0;
495 gmticks = ticks = -1;
496 }
497
498 wxDateTime DT() const
499 { return wxDateTime(day, month, year, hour, min, sec); }
500
239446b4
VZ
501 bool SameDay(const wxDateTime::Tm& tm) const
502 {
503 return day == tm.mday && month == tm.mon && year == tm.year;
504 }
505
299fcbfe
VZ
506 wxString Format() const
507 {
508 wxString s;
509 s.Printf("%02d:%02d:%02d %10s %02d, %4d%s",
510 hour, min, sec,
511 wxDateTime::GetMonthName(month).c_str(),
512 day,
513 abs(wxDateTime::ConvertYearToBC(year)),
514 year > 0 ? "AD" : "BC");
515 return s;
516 }
239446b4
VZ
517
518 wxString FormatDate() const
519 {
520 wxString s;
521 s.Printf("%02d-%s-%4d%s",
522 day,
f0f951fa 523 wxDateTime::GetMonthName(month, wxDateTime::Name_Abbr).c_str(),
239446b4
VZ
524 abs(wxDateTime::ConvertYearToBC(year)),
525 year > 0 ? "AD" : "BC");
526 return s;
527 }
299fcbfe
VZ
528};
529
530static const Date testDates[] =
531{
211c2250
VZ
532 { 1, wxDateTime::Jan, 1970, 00, 00, 00, 2440587.5, wxDateTime::Thu, 0, -3600 },
533 { 21, wxDateTime::Jan, 2222, 00, 00, 00, 2532648.5, wxDateTime::Mon, -1, -1 },
534 { 29, wxDateTime::May, 1976, 12, 00, 00, 2442928.0, wxDateTime::Sat, 202219200, 202212000 },
535 { 29, wxDateTime::Feb, 1976, 00, 00, 00, 2442837.5, wxDateTime::Sun, 194400000, 194396400 },
536 { 1, wxDateTime::Jan, 1900, 12, 00, 00, 2415021.0, wxDateTime::Mon, -1, -1 },
537 { 1, wxDateTime::Jan, 1900, 00, 00, 00, 2415020.5, wxDateTime::Mon, -1, -1 },
538 { 15, wxDateTime::Oct, 1582, 00, 00, 00, 2299160.5, wxDateTime::Fri, -1, -1 },
539 { 4, wxDateTime::Oct, 1582, 00, 00, 00, 2299149.5, wxDateTime::Mon, -1, -1 },
540 { 1, wxDateTime::Mar, 1, 00, 00, 00, 1721484.5, wxDateTime::Thu, -1, -1 },
541 { 1, wxDateTime::Jan, 1, 00, 00, 00, 1721425.5, wxDateTime::Mon, -1, -1 },
239446b4
VZ
542 { 31, wxDateTime::Dec, 0, 00, 00, 00, 1721424.5, wxDateTime::Sun, -1, -1 },
543 { 1, wxDateTime::Jan, 0, 00, 00, 00, 1721059.5, wxDateTime::Sat, -1, -1 },
544 { 12, wxDateTime::Aug, -1234, 00, 00, 00, 1270573.5, wxDateTime::Fri, -1, -1 },
545 { 12, wxDateTime::Aug, -4000, 00, 00, 00, 260313.5, wxDateTime::Sat, -1, -1 },
211c2250 546 { 24, wxDateTime::Nov, -4713, 00, 00, 00, -0.5, wxDateTime::Mon, -1, -1 },
299fcbfe
VZ
547};
548
2f02cb89
VZ
549// this test miscellaneous static wxDateTime functions
550static void TestTimeStatic()
551{
552 puts("\n*** wxDateTime static methods test ***");
553
554 // some info about the current date
555 int year = wxDateTime::GetCurrentYear();
556 printf("Current year %d is %sa leap one and has %d days.\n",
557 year,
558 wxDateTime::IsLeapYear(year) ? "" : "not ",
559 wxDateTime::GetNumberOfDays(year));
560
561 wxDateTime::Month month = wxDateTime::GetCurrentMonth();
562 printf("Current month is '%s' ('%s') and it has %d days\n",
f0f951fa 563 wxDateTime::GetMonthName(month, wxDateTime::Name_Abbr).c_str(),
2f02cb89
VZ
564 wxDateTime::GetMonthName(month).c_str(),
565 wxDateTime::GetNumberOfDays(month));
566
567 // leap year logic
fcc3d7cb
VZ
568 static const size_t nYears = 5;
569 static const size_t years[2][nYears] =
2f02cb89
VZ
570 {
571 // first line: the years to test
572 { 1990, 1976, 2000, 2030, 1984, },
573
574 // second line: TRUE if leap, FALSE otherwise
575 { FALSE, TRUE, TRUE, FALSE, TRUE }
576 };
577
578 for ( size_t n = 0; n < nYears; n++ )
579 {
580 int year = years[0][n];
239446b4
VZ
581 bool should = years[1][n] != 0,
582 is = wxDateTime::IsLeapYear(year);
2f02cb89 583
239446b4 584 printf("Year %d is %sa leap year (%s)\n",
2f02cb89 585 year,
239446b4
VZ
586 is ? "" : "not ",
587 should == is ? "ok" : "ERROR");
2f02cb89
VZ
588
589 wxASSERT( should == wxDateTime::IsLeapYear(year) );
590 }
591}
592
593// test constructing wxDateTime objects
594static void TestTimeSet()
595{
596 puts("\n*** wxDateTime construction test ***");
597
299fcbfe
VZ
598 for ( size_t n = 0; n < WXSIZEOF(testDates); n++ )
599 {
600 const Date& d1 = testDates[n];
601 wxDateTime dt = d1.DT();
602
603 Date d2;
604 d2.Init(dt.GetTm());
605
606 wxString s1 = d1.Format(),
607 s2 = d2.Format();
608
609 printf("Date: %s == %s (%s)\n",
610 s1.c_str(), s2.c_str(),
611 s1 == s2 ? "ok" : "ERROR");
612 }
2f02cb89
VZ
613}
614
fcc3d7cb
VZ
615// test time zones stuff
616static void TestTimeZones()
617{
618 puts("\n*** wxDateTime timezone test ***");
619
620 wxDateTime now = wxDateTime::Now();
621
299fcbfe
VZ
622 printf("Current GMT time:\t%s\n", now.Format("%c", wxDateTime::GMT0).c_str());
623 printf("Unix epoch (GMT):\t%s\n", wxDateTime((time_t)0).Format("%c", wxDateTime::GMT0).c_str());
624 printf("Unix epoch (EST):\t%s\n", wxDateTime((time_t)0).Format("%c", wxDateTime::EST).c_str());
625 printf("Current time in Paris:\t%s\n", now.Format("%c", wxDateTime::CET).c_str());
626 printf(" Moscow:\t%s\n", now.Format("%c", wxDateTime::MSK).c_str());
627 printf(" New York:\t%s\n", now.Format("%c", wxDateTime::EST).c_str());
9d9b7755
VZ
628
629 wxDateTime::Tm tm = now.GetTm();
630 if ( wxDateTime(tm) != now )
631 {
632 printf("ERROR: got %s instead of %s\n",
633 wxDateTime(tm).Format().c_str(), now.Format().c_str());
634 }
fcc3d7cb
VZ
635}
636
e6ec579c
VZ
637// test some minimal support for the dates outside the standard range
638static void TestTimeRange()
639{
640 puts("\n*** wxDateTime out-of-standard-range dates test ***");
641
211c2250
VZ
642 static const char *fmt = "%d-%b-%Y %H:%M:%S";
643
1ef54dcf 644 printf("Unix epoch:\t%s\n",
211c2250 645 wxDateTime(2440587.5).Format(fmt).c_str());
1ef54dcf 646 printf("Feb 29, 0: \t%s\n",
211c2250 647 wxDateTime(29, wxDateTime::Feb, 0).Format(fmt).c_str());
e6ec579c 648 printf("JDN 0: \t%s\n",
211c2250 649 wxDateTime(0.0).Format(fmt).c_str());
e6ec579c 650 printf("Jan 1, 1AD:\t%s\n",
211c2250 651 wxDateTime(1, wxDateTime::Jan, 1).Format(fmt).c_str());
e6ec579c 652 printf("May 29, 2099:\t%s\n",
211c2250 653 wxDateTime(29, wxDateTime::May, 2099).Format(fmt).c_str());
e6ec579c
VZ
654}
655
299fcbfe 656static void TestTimeTicks()
e6ec579c 657{
299fcbfe 658 puts("\n*** wxDateTime ticks test ***");
e6ec579c 659
299fcbfe 660 for ( size_t n = 0; n < WXSIZEOF(testDates); n++ )
1ef54dcf 661 {
299fcbfe
VZ
662 const Date& d = testDates[n];
663 if ( d.ticks == -1 )
664 continue;
1ef54dcf 665
299fcbfe
VZ
666 wxDateTime dt = d.DT();
667 long ticks = (dt.GetValue() / 1000).ToLong();
668 printf("Ticks of %s:\t% 10ld", d.Format().c_str(), ticks);
669 if ( ticks == d.ticks )
670 {
671 puts(" (ok)");
672 }
673 else
674 {
675 printf(" (ERROR: should be %ld, delta = %ld)\n",
676 d.ticks, ticks - d.ticks);
677 }
678
679 dt = d.DT().ToTimezone(wxDateTime::GMT0);
680 ticks = (dt.GetValue() / 1000).ToLong();
681 printf("GMtks of %s:\t% 10ld", d.Format().c_str(), ticks);
682 if ( ticks == d.gmticks )
683 {
684 puts(" (ok)");
685 }
686 else
687 {
688 printf(" (ERROR: should be %ld, delta = %ld)\n",
689 d.gmticks, ticks - d.gmticks);
690 }
691 }
692
693 puts("");
694}
695
696// test conversions to JDN &c
697static void TestTimeJDN()
698{
699 puts("\n*** wxDateTime to JDN test ***");
1ef54dcf
VZ
700
701 for ( size_t n = 0; n < WXSIZEOF(testDates); n++ )
702 {
703 const Date& d = testDates[n];
299fcbfe 704 wxDateTime dt(d.day, d.month, d.year, d.hour, d.min, d.sec);
1ef54dcf
VZ
705 double jdn = dt.GetJulianDayNumber();
706
299fcbfe 707 printf("JDN of %s is:\t% 15.6f", d.Format().c_str(), jdn);
1ef54dcf
VZ
708 if ( jdn == d.jdn )
709 {
710 puts(" (ok)");
711 }
712 else
713 {
714 printf(" (ERROR: should be %f, delta = %f)\n",
715 d.jdn, jdn - d.jdn);
716 }
717 }
e6ec579c
VZ
718}
719
211c2250
VZ
720// test week days computation
721static void TestTimeWDays()
722{
723 puts("\n*** wxDateTime weekday test ***");
724
239446b4
VZ
725 // test GetWeekDay()
726 size_t n;
727 for ( n = 0; n < WXSIZEOF(testDates); n++ )
211c2250
VZ
728 {
729 const Date& d = testDates[n];
730 wxDateTime dt(d.day, d.month, d.year, d.hour, d.min, d.sec);
731
732 wxDateTime::WeekDay wday = dt.GetWeekDay();
733 printf("%s is: %s",
734 d.Format().c_str(),
239446b4 735 wxDateTime::GetWeekDayName(wday).c_str());
211c2250
VZ
736 if ( wday == d.wday )
737 {
738 puts(" (ok)");
739 }
740 else
741 {
742 printf(" (ERROR: should be %s)\n",
239446b4
VZ
743 wxDateTime::GetWeekDayName(d.wday).c_str());
744 }
745 }
746
747 puts("");
748
749 // test SetToWeekDay()
750 struct WeekDateTestData
751 {
752 Date date; // the real date (precomputed)
753 int nWeek; // its week index in the month
754 wxDateTime::WeekDay wday; // the weekday
755 wxDateTime::Month month; // the month
756 int year; // and the year
757
758 wxString Format() const
759 {
760 wxString s, which;
761 switch ( nWeek < -1 ? -nWeek : nWeek )
762 {
763 case 1: which = "first"; break;
764 case 2: which = "second"; break;
765 case 3: which = "third"; break;
766 case 4: which = "fourth"; break;
767 case 5: which = "fifth"; break;
768
769 case -1: which = "last"; break;
770 }
771
772 if ( nWeek < -1 )
773 {
774 which += " from end";
775 }
776
777 s.Printf("The %s %s of %s in %d",
778 which.c_str(),
779 wxDateTime::GetWeekDayName(wday).c_str(),
780 wxDateTime::GetMonthName(month).c_str(),
781 year);
782
783 return s;
784 }
785 };
786
787 // the array data was generated by the following python program
788 /*
789from DateTime import *
790from whrandom import *
791from string import *
792
793monthNames = [ 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec' ]
794wdayNames = [ 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun' ]
795
796week = DateTimeDelta(7)
797
798for n in range(20):
799 year = randint(1900, 2100)
800 month = randint(1, 12)
801 day = randint(1, 28)
802 dt = DateTime(year, month, day)
803 wday = dt.day_of_week
804
805 countFromEnd = choice([-1, 1])
806 weekNum = 0;
807
808 while dt.month is month:
809 dt = dt - countFromEnd * week
810 weekNum = weekNum + countFromEnd
811
812 data = { 'day': rjust(`day`, 2), 'month': monthNames[month - 1], 'year': year, 'weekNum': rjust(`weekNum`, 2), 'wday': wdayNames[wday] }
97e0ceea 813
239446b4
VZ
814 print "{ { %(day)s, wxDateTime::%(month)s, %(year)d }, %(weekNum)d, "\
815 "wxDateTime::%(wday)s, wxDateTime::%(month)s, %(year)d }," % data
97e0ceea 816 */
239446b4
VZ
817
818 static const WeekDateTestData weekDatesTestData[] =
819 {
820 { { 20, wxDateTime::Mar, 2045 }, 3, wxDateTime::Mon, wxDateTime::Mar, 2045 },
821 { { 5, wxDateTime::Jun, 1985 }, -4, wxDateTime::Wed, wxDateTime::Jun, 1985 },
822 { { 12, wxDateTime::Nov, 1961 }, -3, wxDateTime::Sun, wxDateTime::Nov, 1961 },
823 { { 27, wxDateTime::Feb, 2093 }, -1, wxDateTime::Fri, wxDateTime::Feb, 2093 },
824 { { 4, wxDateTime::Jul, 2070 }, -4, wxDateTime::Fri, wxDateTime::Jul, 2070 },
825 { { 2, wxDateTime::Apr, 1906 }, -5, wxDateTime::Mon, wxDateTime::Apr, 1906 },
826 { { 19, wxDateTime::Jul, 2023 }, -2, wxDateTime::Wed, wxDateTime::Jul, 2023 },
827 { { 5, wxDateTime::May, 1958 }, -4, wxDateTime::Mon, wxDateTime::May, 1958 },
828 { { 11, wxDateTime::Aug, 1900 }, 2, wxDateTime::Sat, wxDateTime::Aug, 1900 },
829 { { 14, wxDateTime::Feb, 1945 }, 2, wxDateTime::Wed, wxDateTime::Feb, 1945 },
830 { { 25, wxDateTime::Jul, 1967 }, -1, wxDateTime::Tue, wxDateTime::Jul, 1967 },
831 { { 9, wxDateTime::May, 1916 }, -4, wxDateTime::Tue, wxDateTime::May, 1916 },
832 { { 20, wxDateTime::Jun, 1927 }, 3, wxDateTime::Mon, wxDateTime::Jun, 1927 },
833 { { 2, wxDateTime::Aug, 2000 }, 1, wxDateTime::Wed, wxDateTime::Aug, 2000 },
834 { { 20, wxDateTime::Apr, 2044 }, 3, wxDateTime::Wed, wxDateTime::Apr, 2044 },
835 { { 20, wxDateTime::Feb, 1932 }, -2, wxDateTime::Sat, wxDateTime::Feb, 1932 },
836 { { 25, wxDateTime::Jul, 2069 }, 4, wxDateTime::Thu, wxDateTime::Jul, 2069 },
837 { { 3, wxDateTime::Apr, 1925 }, 1, wxDateTime::Fri, wxDateTime::Apr, 1925 },
838 { { 21, wxDateTime::Mar, 2093 }, 3, wxDateTime::Sat, wxDateTime::Mar, 2093 },
839 { { 3, wxDateTime::Dec, 2074 }, -5, wxDateTime::Mon, wxDateTime::Dec, 2074 },
840 };
841
842 static const char *fmt = "%d-%b-%Y";
843
844 wxDateTime dt;
845 for ( n = 0; n < WXSIZEOF(weekDatesTestData); n++ )
846 {
847 const WeekDateTestData& wd = weekDatesTestData[n];
848
849 dt.SetToWeekDay(wd.wday, wd.nWeek, wd.month, wd.year);
850
851 printf("%s is %s", wd.Format().c_str(), dt.Format(fmt).c_str());
852
853 const Date& d = wd.date;
854 if ( d.SameDay(dt.GetTm()) )
855 {
856 puts(" (ok)");
857 }
858 else
859 {
860 dt.Set(d.day, d.month, d.year);
861
862 printf(" (ERROR: should be %s)\n", dt.Format(fmt).c_str());
211c2250
VZ
863 }
864 }
865}
866
239446b4
VZ
867// test the computation of (ISO) week numbers
868static void TestTimeWNumber()
869{
870 puts("\n*** wxDateTime week number test ***");
871
872 struct WeekNumberTestData
873 {
874 Date date; // the date
9d9b7755
VZ
875 wxDateTime::wxDateTime_t week; // the week number in the year
876 wxDateTime::wxDateTime_t wmon; // the week number in the month
877 wxDateTime::wxDateTime_t wmon2; // same but week starts with Sun
239446b4
VZ
878 wxDateTime::wxDateTime_t dnum; // day number in the year
879 };
880
881 // data generated with the following python script:
882 /*
883from DateTime import *
884from whrandom import *
885from string import *
886
887monthNames = [ 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec' ]
888wdayNames = [ 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun' ]
889
9d9b7755
VZ
890def GetMonthWeek(dt):
891 weekNumMonth = dt.iso_week[1] - DateTime(dt.year, dt.month, 1).iso_week[1] + 1
892 if weekNumMonth < 0:
893 weekNumMonth = weekNumMonth + 53
894 return weekNumMonth
895
896def GetLastSundayBefore(dt):
897 if dt.iso_week[2] == 7:
898 return dt
899 else:
900 return dt - DateTimeDelta(dt.iso_week[2])
901
239446b4
VZ
902for n in range(20):
903 year = randint(1900, 2100)
904 month = randint(1, 12)
905 day = randint(1, 28)
906 dt = DateTime(year, month, day)
907 dayNum = dt.day_of_year
908 weekNum = dt.iso_week[1]
9d9b7755
VZ
909 weekNumMonth = GetMonthWeek(dt)
910
911 weekNumMonth2 = 0
912 dtSunday = GetLastSundayBefore(dt)
913
914 while dtSunday >= GetLastSundayBefore(DateTime(dt.year, dt.month, 1)):
915 weekNumMonth2 = weekNumMonth2 + 1
916 dtSunday = dtSunday - DateTimeDelta(7)
917
918 data = { 'day': rjust(`day`, 2), \
919 'month': monthNames[month - 1], \
920 'year': year, \
921 'weekNum': rjust(`weekNum`, 2), \
922 'weekNumMonth': weekNumMonth, \
923 'weekNumMonth2': weekNumMonth2, \
924 'dayNum': rjust(`dayNum`, 3) }
925
926 print " { { %(day)s, "\
927 "wxDateTime::%(month)s, "\
928 "%(year)d }, "\
929 "%(weekNum)s, "\
930 "%(weekNumMonth)s, "\
931 "%(weekNumMonth2)s, "\
239446b4 932 "%(dayNum)s }," % data
9d9b7755 933
239446b4
VZ
934 */
935 static const WeekNumberTestData weekNumberTestDates[] =
936 {
9d9b7755
VZ
937 { { 27, wxDateTime::Dec, 1966 }, 52, 5, 5, 361 },
938 { { 22, wxDateTime::Jul, 1926 }, 29, 4, 4, 203 },
939 { { 22, wxDateTime::Oct, 2076 }, 43, 4, 4, 296 },
940 { { 1, wxDateTime::Jul, 1967 }, 26, 1, 1, 182 },
941 { { 8, wxDateTime::Nov, 2004 }, 46, 2, 2, 313 },
942 { { 21, wxDateTime::Mar, 1920 }, 12, 3, 4, 81 },
943 { { 7, wxDateTime::Jan, 1965 }, 1, 2, 2, 7 },
944 { { 19, wxDateTime::Oct, 1999 }, 42, 4, 4, 292 },
945 { { 13, wxDateTime::Aug, 1955 }, 32, 2, 2, 225 },
946 { { 18, wxDateTime::Jul, 2087 }, 29, 3, 3, 199 },
947 { { 2, wxDateTime::Sep, 2028 }, 35, 1, 1, 246 },
948 { { 28, wxDateTime::Jul, 1945 }, 30, 5, 4, 209 },
949 { { 15, wxDateTime::Jun, 1901 }, 24, 3, 3, 166 },
950 { { 10, wxDateTime::Oct, 1939 }, 41, 3, 2, 283 },
951 { { 3, wxDateTime::Dec, 1965 }, 48, 1, 1, 337 },
952 { { 23, wxDateTime::Feb, 1940 }, 8, 4, 4, 54 },
953 { { 2, wxDateTime::Jan, 1987 }, 1, 1, 1, 2 },
954 { { 11, wxDateTime::Aug, 2079 }, 32, 2, 2, 223 },
955 { { 2, wxDateTime::Feb, 2063 }, 5, 1, 1, 33 },
956 { { 16, wxDateTime::Oct, 1942 }, 42, 3, 3, 289 },
239446b4
VZ
957 };
958
959 for ( size_t n = 0; n < WXSIZEOF(weekNumberTestDates); n++ )
960 {
961 const WeekNumberTestData& wn = weekNumberTestDates[n];
962 const Date& d = wn.date;
963
964 wxDateTime dt = d.DT();
965
9d9b7755
VZ
966 wxDateTime::wxDateTime_t
967 week = dt.GetWeekOfYear(wxDateTime::Monday_First),
968 wmon = dt.GetWeekOfMonth(wxDateTime::Monday_First),
969 wmon2 = dt.GetWeekOfMonth(wxDateTime::Sunday_First),
970 dnum = dt.GetDayOfYear();
239446b4
VZ
971
972 printf("%s: the day number is %d",
973 d.FormatDate().c_str(), dnum);
974 if ( dnum == wn.dnum )
975 {
976 printf(" (ok)");
977 }
978 else
979 {
980 printf(" (ERROR: should be %d)", wn.dnum);
981 }
982
9d9b7755
VZ
983 printf(", week in month is %d", wmon);
984 if ( wmon == wn.wmon )
985 {
986 printf(" (ok)");
987 }
988 else
989 {
990 printf(" (ERROR: should be %d)", wn.wmon);
991 }
992
993 printf(" or %d", wmon2);
994 if ( wmon2 == wn.wmon2 )
995 {
996 printf(" (ok)");
997 }
998 else
999 {
1000 printf(" (ERROR: should be %d)", wn.wmon2);
1001 }
1002
1003 printf(", week in year is %d", week);
239446b4
VZ
1004 if ( week == wn.week )
1005 {
1006 puts(" (ok)");
1007 }
1008 else
1009 {
1010 printf(" (ERROR: should be %d)\n", wn.week);
1011 }
1012 }
1013}
1014
1015// test DST calculations
1016static void TestTimeDST()
1017{
1018 puts("\n*** wxDateTime DST test ***");
1019
1020 printf("DST is%s in effect now.\n\n",
1021 wxDateTime::Now().IsDST() ? "" : " not");
1022
1023 // taken from http://www.energy.ca.gov/daylightsaving.html
1024 static const Date datesDST[2][2004 - 1900 + 1] =
1025 {
1026 {
1027 { 1, wxDateTime::Apr, 1990 },
1028 { 7, wxDateTime::Apr, 1991 },
1029 { 5, wxDateTime::Apr, 1992 },
1030 { 4, wxDateTime::Apr, 1993 },
1031 { 3, wxDateTime::Apr, 1994 },
1032 { 2, wxDateTime::Apr, 1995 },
1033 { 7, wxDateTime::Apr, 1996 },
1034 { 6, wxDateTime::Apr, 1997 },
1035 { 5, wxDateTime::Apr, 1998 },
1036 { 4, wxDateTime::Apr, 1999 },
1037 { 2, wxDateTime::Apr, 2000 },
1038 { 1, wxDateTime::Apr, 2001 },
1039 { 7, wxDateTime::Apr, 2002 },
1040 { 6, wxDateTime::Apr, 2003 },
1041 { 4, wxDateTime::Apr, 2004 },
1042 },
1043 {
1044 { 28, wxDateTime::Oct, 1990 },
1045 { 27, wxDateTime::Oct, 1991 },
1046 { 25, wxDateTime::Oct, 1992 },
1047 { 31, wxDateTime::Oct, 1993 },
1048 { 30, wxDateTime::Oct, 1994 },
1049 { 29, wxDateTime::Oct, 1995 },
1050 { 27, wxDateTime::Oct, 1996 },
1051 { 26, wxDateTime::Oct, 1997 },
1052 { 25, wxDateTime::Oct, 1998 },
1053 { 31, wxDateTime::Oct, 1999 },
1054 { 29, wxDateTime::Oct, 2000 },
1055 { 28, wxDateTime::Oct, 2001 },
1056 { 27, wxDateTime::Oct, 2002 },
1057 { 26, wxDateTime::Oct, 2003 },
1058 { 31, wxDateTime::Oct, 2004 },
1059 }
1060 };
1061
1062 int year;
1063 for ( year = 1990; year < 2005; year++ )
1064 {
1065 wxDateTime dtBegin = wxDateTime::GetBeginDST(year, wxDateTime::USA),
1066 dtEnd = wxDateTime::GetEndDST(year, wxDateTime::USA);
1067
1068 printf("DST period in the US for year %d: from %s to %s",
1069 year, dtBegin.Format().c_str(), dtEnd.Format().c_str());
1070
1071 size_t n = year - 1990;
1072 const Date& dBegin = datesDST[0][n];
1073 const Date& dEnd = datesDST[1][n];
97e0ceea 1074
239446b4
VZ
1075 if ( dBegin.SameDay(dtBegin.GetTm()) && dEnd.SameDay(dtEnd.GetTm()) )
1076 {
1077 puts(" (ok)");
1078 }
1079 else
1080 {
1081 printf(" (ERROR: should be %s %d to %s %d)\n",
1082 wxDateTime::GetMonthName(dBegin.month).c_str(), dBegin.day,
1083 wxDateTime::GetMonthName(dEnd.month).c_str(), dEnd.day);
1084 }
1085 }
1086
1087 puts("");
1088
1089 for ( year = 1990; year < 2005; year++ )
1090 {
1091 printf("DST period in Europe for year %d: from %s to %s\n",
1092 year,
1093 wxDateTime::GetBeginDST(year, wxDateTime::Country_EEC).Format().c_str(),
1094 wxDateTime::GetEndDST(year, wxDateTime::Country_EEC).Format().c_str());
1095 }
1096}
1097
68ee7c47
VZ
1098// test wxDateTime -> text conversion
1099static void TestTimeFormat()
1100{
1101 puts("\n*** wxDateTime formatting test ***");
1102
b38e2f7d
VZ
1103 // some information may be lost during conversion, so store what kind
1104 // of info should we recover after a round trip
1105 enum CompareKind
68ee7c47 1106 {
b38e2f7d
VZ
1107 CompareNone, // don't try comparing
1108 CompareBoth, // dates and times should be identical
1109 CompareDate, // dates only
1110 CompareTime // time only
1111 };
1112
1113 static const struct
1114 {
1115 CompareKind compareKind;
1116 const char *format;
1117 } formatTestFormats[] =
1118 {
1119 { CompareBoth, "---> %c" },
1120 { CompareDate, "Date is %A, %d of %B, in year %Y" },
1121 { CompareBoth, "Date is %x, time is %X" },
1122 { CompareTime, "Time is %H:%M:%S or %I:%M:%S %p" },
1123 { CompareNone, "The day of year: %j, the week of year: %W" },
68ee7c47
VZ
1124 };
1125
1126 static const Date formatTestDates[] =
1127 {
68ee7c47
VZ
1128 { 29, wxDateTime::May, 1976, 18, 30, 00 },
1129 { 31, wxDateTime::Dec, 1999, 23, 30, 00 },
b38e2f7d
VZ
1130#if 0
1131 // this test can't work for other centuries because it uses two digit
1132 // years in formats, so don't even try it
68ee7c47
VZ
1133 { 29, wxDateTime::May, 2076, 18, 30, 00 },
1134 { 29, wxDateTime::Feb, 2400, 02, 15, 25 },
1135 { 01, wxDateTime::Jan, -52, 03, 16, 47 },
b38e2f7d 1136#endif
68ee7c47
VZ
1137 };
1138
1139 // an extra test (as it doesn't depend on date, don't do it in the loop)
1140 printf("%s\n", wxDateTime::Now().Format("Our timezone is %Z").c_str());
1141
b38e2f7d 1142 for ( size_t d = 0; d < WXSIZEOF(formatTestDates) + 1; d++ )
68ee7c47
VZ
1143 {
1144 puts("");
1145
b38e2f7d 1146 wxDateTime dt = d == 0 ? wxDateTime::Now() : formatTestDates[d - 1].DT();
68ee7c47
VZ
1147 for ( size_t n = 0; n < WXSIZEOF(formatTestFormats); n++ )
1148 {
b38e2f7d 1149 wxString s = dt.Format(formatTestFormats[n].format);
f0f951fa
VZ
1150 printf("%s", s.c_str());
1151
b38e2f7d
VZ
1152 // what can we recover?
1153 int kind = formatTestFormats[n].compareKind;
1154
f0f951fa
VZ
1155 // convert back
1156 wxDateTime dt2;
b38e2f7d 1157 const wxChar *result = dt2.ParseFormat(s, formatTestFormats[n].format);
f0f951fa
VZ
1158 if ( !result )
1159 {
b38e2f7d
VZ
1160 // converion failed - should it have?
1161 if ( kind == CompareNone )
1162 puts(" (ok)");
1163 else
1164 puts(" (ERROR: conversion back failed)");
f0f951fa
VZ
1165 }
1166 else if ( *result )
1167 {
1168 // should have parsed the entire string
1169 puts(" (ERROR: conversion back stopped too soon)");
1170 }
f0f951fa
VZ
1171 else
1172 {
b38e2f7d
VZ
1173 bool equal = FALSE; // suppress compilaer warning
1174 switch ( kind )
1175 {
1176 case CompareBoth:
1177 equal = dt2 == dt;
1178 break;
1179
1180 case CompareDate:
1181 equal = dt.IsSameDate(dt2);
1182 break;
1183
1184 case CompareTime:
1185 equal = dt.IsSameTime(dt2);
1186 break;
1187 }
1188
1189 if ( !equal )
1190 {
1191 printf(" (ERROR: got back '%s' instead of '%s')\n",
1192 dt2.Format().c_str(), dt.Format().c_str());
1193 }
1194 else
1195 {
1196 puts(" (ok)");
1197 }
f0f951fa 1198 }
68ee7c47
VZ
1199 }
1200 }
1201}
1202
97e0ceea
VZ
1203// test text -> wxDateTime conversion
1204static void TestTimeParse()
1205{
1206 puts("\n*** wxDateTime parse test ***");
1207
1208 struct ParseTestData
1209 {
1210 const char *format;
1211 Date date;
1212 bool good;
1213 };
1214
1215 static const ParseTestData parseTestDates[] =
1216 {
68ee7c47
VZ
1217 { "Sat, 18 Dec 1999 00:46:40 +0100", { 18, wxDateTime::Dec, 1999, 00, 46, 40 }, TRUE },
1218 { "Wed, 1 Dec 1999 05:17:20 +0300", { 1, wxDateTime::Dec, 1999, 03, 17, 20 }, TRUE },
97e0ceea
VZ
1219 };
1220
1221 for ( size_t n = 0; n < WXSIZEOF(parseTestDates); n++ )
1222 {
1223 const char *format = parseTestDates[n].format;
1224
1225 printf("%s => ", format);
1226
1227 wxDateTime dt;
1228 if ( dt.ParseRfc822Date(format) )
1229 {
1230 printf("%s ", dt.Format().c_str());
1231
1232 if ( parseTestDates[n].good )
1233 {
1234 wxDateTime dtReal = parseTestDates[n].date.DT();
1235 if ( dt == dtReal )
1236 {
1237 puts("(ok)");
1238 }
1239 else
1240 {
1241 printf("(ERROR: should be %s)\n", dtReal.Format().c_str());
1242 }
1243 }
1244 else
1245 {
1246 puts("(ERROR: bad format)");
1247 }
1248 }
1249 else
1250 {
1251 printf("bad format (%s)\n",
1252 parseTestDates[n].good ? "ERROR" : "ok");
1253 }
1254 }
1255}
1256
9d9b7755
VZ
1257static void TestInteractive()
1258{
1259 puts("\n*** interactive wxDateTime tests ***");
1260
1261 char buf[128];
1262
1263 for ( ;; )
1264 {
1265 printf("Enter a date: ");
1266 if ( !fgets(buf, WXSIZEOF(buf), stdin) )
1267 break;
1268
1269 wxDateTime dt;
1270 if ( !dt.ParseDate(buf) )
1271 {
1272 puts("failed to parse the date");
1273
1274 continue;
1275 }
1276
1277 printf("%s: day %u, week of month %u/%u, week of year %u\n",
1278 dt.FormatISODate().c_str(),
1279 dt.GetDayOfYear(),
1280 dt.GetWeekOfMonth(wxDateTime::Monday_First),
1281 dt.GetWeekOfMonth(wxDateTime::Sunday_First),
1282 dt.GetWeekOfYear(wxDateTime::Monday_First));
1283 }
1284
1285 puts("\n*** done ***");
1286}
1287
1288static void TestTimeArithmetics()
1289{
1290 puts("\n*** testing arithmetic operations on wxDateTime ***");
1291
1292 static const struct
1293 {
1294 wxDateSpan span;
1295 const char *name;
1296 } testArithmData[] =
1297 {
1298 { wxDateSpan::Day(), "day" },
1299 { wxDateSpan::Week(), "week" },
1300 { wxDateSpan::Month(), "month" },
1301 { wxDateSpan::Year(), "year" },
1302 { wxDateSpan(1, 2, 3, 4), "year, 2 months, 3 weeks, 4 days" },
1303 };
1304
1305 wxDateTime dt(29, wxDateTime::Dec, 1999), dt1, dt2;
1306
1307 for ( size_t n = 0; n < WXSIZEOF(testArithmData); n++ )
1308 {
1309 wxDateSpan span = testArithmData[n].span;
1310 dt1 = dt + span;
1311 dt2 = dt - span;
1312
1313 const char *name = testArithmData[n].name;
1314 printf("%s + %s = %s, %s - %s = %s\n",
1315 dt.FormatISODate().c_str(), name, dt1.FormatISODate().c_str(),
1316 dt.FormatISODate().c_str(), name, dt2.FormatISODate().c_str());
1317
1318 printf("Going back: %s", (dt1 - span).FormatISODate().c_str());
1319 if ( dt1 - span == dt )
1320 {
1321 puts(" (ok)");
1322 }
1323 else
1324 {
1325 printf(" (ERROR: should be %s)\n", dt.FormatISODate().c_str());
1326 }
1327
1328 printf("Going forward: %s", (dt2 + span).FormatISODate().c_str());
1329 if ( dt2 + span == dt )
1330 {
1331 puts(" (ok)");
1332 }
1333 else
1334 {
1335 printf(" (ERROR: should be %s)\n", dt.FormatISODate().c_str());
1336 }
1337
1338 printf("Double increment: %s", (dt2 + 2*span).FormatISODate().c_str());
1339 if ( dt2 + 2*span == dt1 )
1340 {
1341 puts(" (ok)");
1342 }
1343 else
1344 {
1345 printf(" (ERROR: should be %s)\n", dt2.FormatISODate().c_str());
1346 }
1347
1348 puts("");
1349 }
1350}
1351
0de868d9
VZ
1352static void TestTimeHolidays()
1353{
1354 puts("\n*** testing wxDateTimeHolidayAuthority ***\n");
1355
1356 wxDateTime::Tm tm = wxDateTime(29, wxDateTime::May, 2000).GetTm();
1357 wxDateTime dtStart(1, tm.mon, tm.year),
1358 dtEnd = dtStart.GetLastMonthDay();
1359
1360 wxDateTimeArray hol;
1361 wxDateTimeHolidayAuthority::GetHolidaysInRange(dtStart, dtEnd, hol);
1362
1363 const wxChar *format = "%d-%b-%Y (%a)";
1364
1365 printf("All holidays between %s and %s:\n",
1366 dtStart.Format(format).c_str(), dtEnd.Format(format).c_str());
1367
1368 size_t count = hol.GetCount();
1369 for ( size_t n = 0; n < count; n++ )
1370 {
1371 printf("\t%s\n", hol[n].Format(format).c_str());
1372 }
1373
1374 puts("");
1375}
1376
68ee7c47
VZ
1377#if 0
1378
97e0ceea
VZ
1379// test compatibility with the old wxDate/wxTime classes
1380static void TestTimeCompatibility()
1381{
1382 puts("\n*** wxDateTime compatibility test ***");
1383
1384 printf("wxDate for JDN 0: %s\n", wxDate(0l).FormatDate().c_str());
1385 printf("wxDate for MJD 0: %s\n", wxDate(2400000).FormatDate().c_str());
1386
1387 double jdnNow = wxDateTime::Now().GetJDN();
1388 long jdnMidnight = (long)(jdnNow - 0.5);
1389 printf("wxDate for today: %s\n", wxDate(jdnMidnight).FormatDate().c_str());
1390
1391 jdnMidnight = wxDate().Set().GetJulianDate();
1392 printf("wxDateTime for today: %s\n",
1393 wxDateTime((double)(jdnMidnight + 0.5)).Format("%c", wxDateTime::GMT0).c_str());
1394
1395 int flags = wxEUROPEAN;//wxFULL;
1396 wxDate date;
1397 date.Set();
1398 printf("Today is %s\n", date.FormatDate(flags).c_str());
1399 for ( int n = 0; n < 7; n++ )
1400 {
1401 printf("Previous %s is %s\n",
1402 wxDateTime::GetWeekDayName((wxDateTime::WeekDay)n),
1403 date.Previous(n + 1).FormatDate(flags).c_str());
1404 }
1405}
1406
68ee7c47
VZ
1407#endif // 0
1408
b76b015e
VZ
1409#endif // TEST_TIME
1410
e87271f3
VZ
1411// ----------------------------------------------------------------------------
1412// threads
1413// ----------------------------------------------------------------------------
1414
1415#ifdef TEST_THREADS
1416
bbfa0322 1417#include <wx/thread.h>
37667812 1418
bbfa0322
VZ
1419static size_t gs_counter = (size_t)-1;
1420static wxCriticalSection gs_critsect;
b568d04f 1421static wxCondition gs_cond;
bbfa0322 1422
b568d04f 1423class MyJoinableThread : public wxThread
bbfa0322
VZ
1424{
1425public:
b568d04f
VZ
1426 MyJoinableThread(size_t n) : wxThread(wxTHREAD_JOINABLE)
1427 { m_n = n; Create(); }
bbfa0322
VZ
1428
1429 // thread execution starts here
b568d04f 1430 virtual ExitCode Entry();
bbfa0322 1431
b568d04f
VZ
1432private:
1433 size_t m_n;
bbfa0322
VZ
1434};
1435
b568d04f 1436wxThread::ExitCode MyJoinableThread::Entry()
bbfa0322 1437{
b568d04f
VZ
1438 unsigned long res = 1;
1439 for ( size_t n = 1; n < m_n; n++ )
1440 {
1441 res *= n;
1442
1443 // it's a loooong calculation :-)
1444 Sleep(100);
1445 }
bbfa0322 1446
b568d04f 1447 return (ExitCode)res;
bbfa0322
VZ
1448}
1449
b568d04f
VZ
1450class MyDetachedThread : public wxThread
1451{
1452public:
fcc3d7cb
VZ
1453 MyDetachedThread(size_t n, char ch)
1454 {
1455 m_n = n;
1456 m_ch = ch;
1457 m_cancelled = FALSE;
1458
1459 Create();
1460 }
b568d04f
VZ
1461
1462 // thread execution starts here
1463 virtual ExitCode Entry();
1464
1465 // and stops here
1466 virtual void OnExit();
1467
1468private:
9fc3ad34
VZ
1469 size_t m_n; // number of characters to write
1470 char m_ch; // character to write
fcc3d7cb
VZ
1471
1472 bool m_cancelled; // FALSE if we exit normally
b568d04f
VZ
1473};
1474
1475wxThread::ExitCode MyDetachedThread::Entry()
bbfa0322
VZ
1476{
1477 {
1478 wxCriticalSectionLocker lock(gs_critsect);
1479 if ( gs_counter == (size_t)-1 )
1480 gs_counter = 1;
1481 else
1482 gs_counter++;
1483 }
1484
9fc3ad34 1485 for ( size_t n = 0; n < m_n; n++ )
bbfa0322
VZ
1486 {
1487 if ( TestDestroy() )
fcc3d7cb
VZ
1488 {
1489 m_cancelled = TRUE;
1490
bbfa0322 1491 break;
fcc3d7cb 1492 }
bbfa0322
VZ
1493
1494 putchar(m_ch);
1495 fflush(stdout);
1496
1497 wxThread::Sleep(100);
1498 }
1499
b568d04f 1500 return 0;
bbfa0322
VZ
1501}
1502
b568d04f 1503void MyDetachedThread::OnExit()
bbfa0322 1504{
9fc3ad34
VZ
1505 wxLogTrace("thread", "Thread %ld is in OnExit", GetId());
1506
bbfa0322 1507 wxCriticalSectionLocker lock(gs_critsect);
fcc3d7cb 1508 if ( !--gs_counter && !m_cancelled )
b568d04f 1509 gs_cond.Signal();
bbfa0322
VZ
1510}
1511
9fc3ad34
VZ
1512void TestDetachedThreads()
1513{
2f02cb89 1514 puts("\n*** Testing detached threads ***");
9fc3ad34
VZ
1515
1516 static const size_t nThreads = 3;
1517 MyDetachedThread *threads[nThreads];
1518 size_t n;
1519 for ( n = 0; n < nThreads; n++ )
1520 {
1521 threads[n] = new MyDetachedThread(10, 'A' + n);
1522 }
1523
1524 threads[0]->SetPriority(WXTHREAD_MIN_PRIORITY);
1525 threads[1]->SetPriority(WXTHREAD_MAX_PRIORITY);
1526
1527 for ( n = 0; n < nThreads; n++ )
1528 {
1529 threads[n]->Run();
1530 }
1531
1532 // wait until all threads terminate
1533 gs_cond.Wait();
1534
1535 puts("");
1536}
1537
1538void TestJoinableThreads()
1539{
2f02cb89 1540 puts("\n*** Testing a joinable thread (a loooong calculation...) ***");
9fc3ad34
VZ
1541
1542 // calc 10! in the background
1543 MyJoinableThread thread(10);
1544 thread.Run();
1545
1546 printf("\nThread terminated with exit code %lu.\n",
1547 (unsigned long)thread.Wait());
1548}
1549
1550void TestThreadSuspend()
1551{
2f02cb89
VZ
1552 puts("\n*** Testing thread suspend/resume functions ***");
1553
1554 MyDetachedThread *thread = new MyDetachedThread(15, 'X');
9fc3ad34
VZ
1555
1556 thread->Run();
1557
1558 // this is for this demo only, in a real life program we'd use another
1559 // condition variable which would be signaled from wxThread::Entry() to
1560 // tell us that the thread really started running - but here just wait a
1561 // bit and hope that it will be enough (the problem is, of course, that
1562 // the thread might still not run when we call Pause() which will result
1563 // in an error)
1564 wxThread::Sleep(300);
1565
1566 for ( size_t n = 0; n < 3; n++ )
1567 {
1568 thread->Pause();
1569
1570 puts("\nThread suspended");
1571 if ( n > 0 )
1572 {
1573 // don't sleep but resume immediately the first time
1574 wxThread::Sleep(300);
1575 }
1576 puts("Going to resume the thread");
1577
1578 thread->Resume();
1579 }
1580
4c460b34
VZ
1581 puts("Waiting until it terminates now");
1582
9fc3ad34
VZ
1583 // wait until the thread terminates
1584 gs_cond.Wait();
1585
1586 puts("");
1587}
1588
2f02cb89
VZ
1589void TestThreadDelete()
1590{
1591 // As above, using Sleep() is only for testing here - we must use some
1592 // synchronisation object instead to ensure that the thread is still
1593 // running when we delete it - deleting a detached thread which already
1594 // terminated will lead to a crash!
1595
1596 puts("\n*** Testing thread delete function ***");
1597
4c460b34
VZ
1598 MyDetachedThread *thread0 = new MyDetachedThread(30, 'W');
1599
1600 thread0->Delete();
1601
1602 puts("\nDeleted a thread which didn't start to run yet.");
1603
2f02cb89
VZ
1604 MyDetachedThread *thread1 = new MyDetachedThread(30, 'Y');
1605
1606 thread1->Run();
1607
1608 wxThread::Sleep(300);
1609
1610 thread1->Delete();
1611
1612 puts("\nDeleted a running thread.");
1613
1614 MyDetachedThread *thread2 = new MyDetachedThread(30, 'Z');
1615
1616 thread2->Run();
1617
1618 wxThread::Sleep(300);
1619
1620 thread2->Pause();
1621
1622 thread2->Delete();
1623
1624 puts("\nDeleted a sleeping thread.");
1625
4c460b34
VZ
1626 MyJoinableThread thread3(20);
1627 thread3.Run();
2f02cb89 1628
4c460b34 1629 thread3.Delete();
2f02cb89
VZ
1630
1631 puts("\nDeleted a joinable thread.");
1632
4c460b34
VZ
1633 MyJoinableThread thread4(2);
1634 thread4.Run();
2f02cb89
VZ
1635
1636 wxThread::Sleep(300);
1637
4c460b34 1638 thread4.Delete();
2f02cb89
VZ
1639
1640 puts("\nDeleted a joinable thread which already terminated.");
1641
1642 puts("");
1643}
1644
e87271f3
VZ
1645#endif // TEST_THREADS
1646
1647// ----------------------------------------------------------------------------
1648// arrays
1649// ----------------------------------------------------------------------------
1650
1651#ifdef TEST_ARRAYS
1652
1653void PrintArray(const char* name, const wxArrayString& array)
1654{
1655 printf("Dump of the array '%s'\n", name);
1656
1657 size_t nCount = array.GetCount();
1658 for ( size_t n = 0; n < nCount; n++ )
1659 {
1660 printf("\t%s[%u] = '%s'\n", name, n, array[n].c_str());
1661 }
1662}
1663
1664#endif // TEST_ARRAYS
1665
9fc3ad34
VZ
1666// ----------------------------------------------------------------------------
1667// strings
1668// ----------------------------------------------------------------------------
1669
1670#ifdef TEST_STRINGS
1671
1672#include "wx/timer.h"
1673
299fcbfe 1674static void TestString()
9fc3ad34
VZ
1675{
1676 wxStopWatch sw;
1677
1678 wxString a, b, c;
1679
1680 a.reserve (128);
1681 b.reserve (128);
1682 c.reserve (128);
1683
1684 for (int i = 0; i < 1000000; ++i)
1685 {
1686 a = "Hello";
1687 b = " world";
1688 c = "! How'ya doin'?";
1689 a += b;
1690 a += c;
1691 c = "Hello world! What's up?";
1692 if (c != a)
1693 c = "Doh!";
1694 }
1695
1696 printf ("TestString elapsed time: %ld\n", sw.Time());
1697}
1698
299fcbfe 1699static void TestPChar()
9fc3ad34
VZ
1700{
1701 wxStopWatch sw;
1702
1703 char a [128];
1704 char b [128];
1705 char c [128];
1706
1707 for (int i = 0; i < 1000000; ++i)
1708 {
1709 strcpy (a, "Hello");
1710 strcpy (b, " world");
1711 strcpy (c, "! How'ya doin'?");
1712 strcat (a, b);
1713 strcat (a, c);
1714 strcpy (c, "Hello world! What's up?");
1715 if (strcmp (c, a) == 0)
1716 strcpy (c, "Doh!");
1717 }
1718
1719 printf ("TestPChar elapsed time: %ld\n", sw.Time());
1720}
1721
299fcbfe
VZ
1722static void TestStringSub()
1723{
1724 wxString s("Hello, world!");
1725
1726 puts("*** Testing wxString substring extraction ***");
1727
1728 printf("String = '%s'\n", s.c_str());
1729 printf("Left(5) = '%s'\n", s.Left(5).c_str());
1730 printf("Right(6) = '%s'\n", s.Right(6).c_str());
1731 printf("Mid(3, 5) = '%s'\n", s(3, 5).c_str());
1732 printf("Mid(3) = '%s'\n", s.Mid(3).c_str());
1733 printf("substr(3, 5) = '%s'\n", s.substr(3, 5).c_str());
1734 printf("substr(3) = '%s'\n", s.substr(3).c_str());
1735
1736 puts("");
1737}
1738
f0f951fa
VZ
1739static void TestStringFormat()
1740{
1741 puts("*** Testing wxString formatting ***");
1742
1743 wxString s;
1744 s.Printf("%03d", 18);
1745
1746 printf("Number 18: %s\n", wxString::Format("%03d", 18).c_str());
1747 printf("Number 18: %s\n", s.c_str());
1748
1749 puts("");
1750}
1751
9fc3ad34
VZ
1752#endif // TEST_STRINGS
1753
e87271f3
VZ
1754// ----------------------------------------------------------------------------
1755// entry point
1756// ----------------------------------------------------------------------------
1757
bbfa0322 1758int main(int argc, char **argv)
37667812
VZ
1759{
1760 if ( !wxInitialize() )
1761 {
1762 fprintf(stderr, "Failed to initialize the wxWindows library, aborting.");
1763 }
1764
0de868d9
VZ
1765#ifdef TEST_USLEEP
1766 puts("Sleeping for 3 seconds... z-z-z-z-z...");
1767 wxUsleep(3000);
1768#endif // TEST_USLEEP
1769
d34bce84
VZ
1770#ifdef TEST_CMDLINE
1771 static const wxCmdLineEntryDesc cmdLineDesc[] =
1772 {
1773 { wxCMD_LINE_SWITCH, "v", "verbose", "be verbose" },
1774 { wxCMD_LINE_SWITCH, "q", "quiet", "be quiet" },
1775
1776 { wxCMD_LINE_OPTION, "o", "output", "output file" },
1777 { wxCMD_LINE_OPTION, "i", "input", "input dir" },
1778 { wxCMD_LINE_OPTION, "s", "size", "output block size", wxCMD_LINE_VAL_NUMBER },
1e245dc2 1779 { wxCMD_LINE_OPTION, "d", "date", "output file date", wxCMD_LINE_VAL_DATE },
d34bce84
VZ
1780
1781 { wxCMD_LINE_PARAM, NULL, NULL, "input file",
1782 wxCMD_LINE_VAL_STRING, wxCMD_LINE_PARAM_MULTIPLE },
1783
1784 { wxCMD_LINE_NONE }
1785 };
1786
1787 wxCmdLineParser parser(cmdLineDesc, argc, argv);
1788
1789 switch ( parser.Parse() )
1790 {
1791 case -1:
1792 wxLogMessage("Help was given, terminating.");
1793 break;
1794
1795 case 0:
1796 ShowCmdLine(parser);
1797 break;
1798
1799 default:
1800 wxLogMessage("Syntax error detected, aborting.");
1801 break;
1802 }
1803#endif // TEST_CMDLINE
1804
9fc3ad34 1805#ifdef TEST_STRINGS
299fcbfe
VZ
1806 if ( 0 )
1807 {
1808 TestPChar();
1809 TestString();
1810 }
f0f951fa
VZ
1811 if ( 0 )
1812 {
1813 TestStringSub();
1814 }
1815 TestStringFormat();
9fc3ad34
VZ
1816#endif // TEST_STRINGS
1817
e87271f3
VZ
1818#ifdef TEST_ARRAYS
1819 wxArrayString a1;
1820 a1.Add("tiger");
1821 a1.Add("cat");
1822 a1.Add("lion");
1823 a1.Add("dog");
1824 a1.Add("human");
1825 a1.Add("ape");
1826
1827 puts("*** Initially:");
1828
1829 PrintArray("a1", a1);
1830
1831 wxArrayString a2(a1);
1832 PrintArray("a2", a2);
1833
1834 wxSortedArrayString a3(a1);
1835 PrintArray("a3", a3);
1836
1837 puts("*** After deleting a string from a1");
1838 a1.Remove(2);
1839
1840 PrintArray("a1", a1);
1841 PrintArray("a2", a2);
1842 PrintArray("a3", a3);
1843
1844 puts("*** After reassigning a1 to a2 and a3");
1845 a3 = a2 = a1;
1846 PrintArray("a2", a2);
1847 PrintArray("a3", a3);
1848#endif // TEST_ARRAYS
1849
1944c6bd
VZ
1850#ifdef TEST_DIR
1851 TestDirEnum();
1852#endif // TEST_DIR
1853
378b05f7
VZ
1854#ifdef TEST_LOG
1855 wxString s;
1856 for ( size_t n = 0; n < 8000; n++ )
1857 {
1858 s << (char)('A' + (n % 26));
1859 }
1860
1861 wxString msg;
1862 msg.Printf("A very very long message: '%s', the end!\n", s.c_str());
1863
1864 // this one shouldn't be truncated
1865 printf(msg);
1866
1867 // but this one will because log functions use fixed size buffer
b568d04f
VZ
1868 // (note that it doesn't need '\n' at the end neither - will be added
1869 // by wxLog anyhow)
1870 wxLogMessage("A very very long message 2: '%s', the end!", s.c_str());
378b05f7
VZ
1871#endif // TEST_LOG
1872
e87271f3 1873#ifdef TEST_THREADS
696e1ea0
VZ
1874 int nCPUs = wxThread::GetCPUCount();
1875 printf("This system has %d CPUs\n", nCPUs);
1876 if ( nCPUs != -1 )
1877 wxThread::SetConcurrency(nCPUs);
ef8d96c2 1878
9fc3ad34
VZ
1879 if ( argc > 1 && argv[1][0] == 't' )
1880 wxLog::AddTraceMask("thread");
b568d04f 1881
4c460b34 1882 if ( 1 )
2f02cb89 1883 TestDetachedThreads();
4c460b34 1884 if ( 1 )
2f02cb89 1885 TestJoinableThreads();
4c460b34 1886 if ( 1 )
2f02cb89
VZ
1887 TestThreadSuspend();
1888 if ( 1 )
1889 TestThreadDelete();
1890
e87271f3 1891#endif // TEST_THREADS
37667812 1892
b76b015e 1893#ifdef TEST_LONGLONG
2a310492
VZ
1894 // seed pseudo random generator
1895 srand((unsigned)time(NULL));
1896
b76b015e 1897 if ( 0 )
2a310492 1898 {
b76b015e 1899 TestSpeed();
2a310492
VZ
1900 }
1901 TestMultiplication();
1902 if ( 0 )
1903 {
b76b015e 1904 TestDivision();
2a310492
VZ
1905 TestAddition();
1906 TestLongLongConversion();
1907 TestBitOperations();
1908 }
b76b015e
VZ
1909#endif // TEST_LONGLONG
1910
696e1ea0
VZ
1911#ifdef TEST_MIME
1912 TestMimeEnum();
1913#endif // TEST_MIME
1914
b76b015e 1915#ifdef TEST_TIME
0de868d9 1916 if ( 0 )
299fcbfe 1917 {
9d9b7755
VZ
1918 TestTimeSet();
1919 TestTimeStatic();
1920 TestTimeRange();
1921 TestTimeZones();
1922 TestTimeTicks();
1923 TestTimeJDN();
1924 TestTimeDST();
1925 TestTimeWDays();
1926 TestTimeWNumber();
1927 TestTimeParse();
1928 TestTimeFormat();
1929 TestTimeArithmetics();
41acf5c0 1930 }
0de868d9 1931 TestTimeHolidays();
9d9b7755
VZ
1932 if ( 0 )
1933 TestInteractive();
b76b015e
VZ
1934#endif // TEST_TIME
1935
37667812
VZ
1936 wxUninitialize();
1937
1938 return 0;
1939}