]> git.saurik.com Git - wxWidgets.git/blame - samples/console/console.cpp
no message
[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 25
d31b7b68
VZ
26// without this pragma, the stupid compiler precompiles #defines below so that
27// changing them doesn't "take place" later!
28#ifdef __VISUALC__
29 #pragma hdrstop
30#endif
31
e87271f3
VZ
32// ----------------------------------------------------------------------------
33// conditional compilation
34// ----------------------------------------------------------------------------
35
d31b7b68 36// what to test (in alphabetic order)?
378b05f7 37
bbf8fc53
VZ
38//#define TEST_ARRAYS
39//#define TEST_CMDLINE
d31b7b68 40//#define TEST_DATETIME
bbf8fc53 41//#define TEST_DIR
d31b7b68 42//#define TEST_EXECUTE
2c8e4738
VZ
43//#define TEST_FILECONF
44//#define TEST_HASH
bbf8fc53
VZ
45//#define TEST_LOG
46//#define TEST_LONGLONG
47//#define TEST_MIME
2c8e4738 48//#define TEST_SOCKETS
ee6e1b1d 49//#define TEST_STRINGS
bbf8fc53 50//#define TEST_THREADS
d31b7b68 51#define TEST_TIMER
e87271f3
VZ
52
53// ============================================================================
54// implementation
55// ============================================================================
56
d34bce84
VZ
57// ----------------------------------------------------------------------------
58// wxCmdLineParser
59// ----------------------------------------------------------------------------
60
d31b7b68
VZ
61#ifdef TEST_CMDLINE
62
d34bce84
VZ
63#include <wx/cmdline.h>
64#include <wx/datetime.h>
65
66static void ShowCmdLine(const wxCmdLineParser& parser)
67{
68 wxString s = "Input files: ";
69
70 size_t count = parser.GetParamCount();
71 for ( size_t param = 0; param < count; param++ )
72 {
73 s << parser.GetParam(param) << ' ';
74 }
75
76 s << '\n'
77 << "Verbose:\t" << (parser.Found("v") ? "yes" : "no") << '\n'
78 << "Quiet:\t" << (parser.Found("q") ? "yes" : "no") << '\n';
79
80 wxString strVal;
81 long lVal;
82 wxDateTime dt;
83 if ( parser.Found("o", &strVal) )
84 s << "Output file:\t" << strVal << '\n';
85 if ( parser.Found("i", &strVal) )
86 s << "Input dir:\t" << strVal << '\n';
87 if ( parser.Found("s", &lVal) )
88 s << "Size:\t" << lVal << '\n';
89 if ( parser.Found("d", &dt) )
90 s << "Date:\t" << dt.FormatISODate() << '\n';
91
92 wxLogMessage(s);
93}
94
95#endif // TEST_CMDLINE
96
1944c6bd
VZ
97// ----------------------------------------------------------------------------
98// wxDir
99// ----------------------------------------------------------------------------
100
101#ifdef TEST_DIR
102
103#include <wx/dir.h>
104
105static void TestDirEnumHelper(wxDir& dir,
106 int flags = wxDIR_DEFAULT,
107 const wxString& filespec = wxEmptyString)
108{
109 wxString filename;
110
111 if ( !dir.IsOpened() )
112 return;
113
114 bool cont = dir.GetFirst(&filename, filespec, flags);
115 while ( cont )
116 {
117 printf("\t%s\n", filename.c_str());
118
119 cont = dir.GetNext(&filename);
120 }
121
122 puts("");
123}
124
125static void TestDirEnum()
126{
127 wxDir dir(wxGetCwd());
128
129 puts("Enumerating everything in current directory:");
130 TestDirEnumHelper(dir);
131
132 puts("Enumerating really everything in current directory:");
133 TestDirEnumHelper(dir, wxDIR_DEFAULT | wxDIR_DOTDOT);
134
135 puts("Enumerating object files in current directory:");
136 TestDirEnumHelper(dir, wxDIR_DEFAULT, "*.o");
137
138 puts("Enumerating directories in current directory:");
139 TestDirEnumHelper(dir, wxDIR_DIRS);
140
141 puts("Enumerating files in current directory:");
142 TestDirEnumHelper(dir, wxDIR_FILES);
143
144 puts("Enumerating files including hidden in current directory:");
145 TestDirEnumHelper(dir, wxDIR_FILES | wxDIR_HIDDEN);
146
147#ifdef __UNIX__
148 dir.Open("/");
149#elif defined(__WXMSW__)
150 dir.Open("c:\\");
151#else
152 #error "don't know where the root directory is"
153#endif
154
155 puts("Enumerating everything in root directory:");
156 TestDirEnumHelper(dir, wxDIR_DEFAULT);
157
158 puts("Enumerating directories in root directory:");
159 TestDirEnumHelper(dir, wxDIR_DIRS);
160
161 puts("Enumerating files in root directory:");
162 TestDirEnumHelper(dir, wxDIR_FILES);
163
164 puts("Enumerating files including hidden in root directory:");
165 TestDirEnumHelper(dir, wxDIR_FILES | wxDIR_HIDDEN);
166
167 puts("Enumerating files in non existing directory:");
168 wxDir dirNo("nosuchdir");
169 TestDirEnumHelper(dirNo);
170}
171
172#endif // TEST_DIR
173
d93c719a
VZ
174// ----------------------------------------------------------------------------
175// wxExecute
176// ----------------------------------------------------------------------------
177
178#ifdef TEST_EXECUTE
179
180#include <wx/utils.h>
181
182static void TestExecute()
183{
184 puts("*** testing wxExecute ***");
185
186#ifdef __UNIX__
187 #define COMMAND "echo hi"
2c8e4738
VZ
188 #define SHELL_COMMAND "echo hi from shell"
189 #define REDIRECT_COMMAND "date"
d93c719a
VZ
190#elif defined(__WXMSW__)
191 #define COMMAND "command.com -c 'echo hi'"
2c8e4738
VZ
192 #define SHELL_COMMAND "echo hi"
193 #define REDIRECT_COMMAND COMMAND
d93c719a
VZ
194#else
195 #error "no command to exec"
196#endif // OS
197
2c8e4738
VZ
198 printf("Testing wxShell: ");
199 fflush(stdout);
200 if ( wxShell(SHELL_COMMAND) )
201 puts("Ok.");
d93c719a 202 else
2c8e4738
VZ
203 puts("ERROR.");
204
205 printf("Testing wxExecute: ");
206 fflush(stdout);
207 if ( wxExecute(COMMAND, TRUE /* sync */) == 0 )
208 puts("Ok.");
209 else
210 puts("ERROR.");
211
212#if 0 // no, it doesn't work (yet?)
213 printf("Testing async wxExecute: ");
214 fflush(stdout);
215 if ( wxExecute(COMMAND) != 0 )
216 puts("Ok (command launched).");
217 else
218 puts("ERROR.");
219#endif // 0
220
221 printf("Testing wxExecute with redirection:\n");
222 wxArrayString output;
223 if ( wxExecute(REDIRECT_COMMAND, output) != 0 )
224 {
225 puts("ERROR.");
226 }
227 else
228 {
229 size_t count = output.GetCount();
230 for ( size_t n = 0; n < count; n++ )
231 {
232 printf("\t%s\n", output[n].c_str());
233 }
234
235 puts("Ok.");
236 }
d93c719a
VZ
237}
238
239#endif // TEST_EXECUTE
240
ee6e1b1d
VZ
241// ----------------------------------------------------------------------------
242// wxFileConfig
243// ----------------------------------------------------------------------------
244
245#ifdef TEST_FILECONF
246
247#include <wx/confbase.h>
248#include <wx/fileconf.h>
249
250static const struct FileConfTestData
251{
252 const wxChar *name; // value name
253 const wxChar *value; // the value from the file
254} fcTestData[] =
255{
256 { _T("value1"), _T("one") },
257 { _T("value2"), _T("two") },
258 { _T("novalue"), _T("default") },
259};
260
261static void TestFileConfRead()
262{
263 puts("*** testing wxFileConfig loading/reading ***");
264
265 wxFileConfig fileconf(_T("test"), wxEmptyString,
266 _T("testdata.fc"), wxEmptyString,
267 wxCONFIG_USE_RELATIVE_PATH);
268
269 // test simple reading
270 puts("\nReading config file:");
271 wxString defValue(_T("default")), value;
272 for ( size_t n = 0; n < WXSIZEOF(fcTestData); n++ )
273 {
274 const FileConfTestData& data = fcTestData[n];
275 value = fileconf.Read(data.name, defValue);
276 printf("\t%s = %s ", data.name, value.c_str());
277 if ( value == data.value )
278 {
279 puts("(ok)");
280 }
281 else
282 {
283 printf("(ERROR: should be %s)\n", data.value);
284 }
285 }
286
287 // test enumerating the entries
288 puts("\nEnumerating all root entries:");
289 long dummy;
290 wxString name;
291 bool cont = fileconf.GetFirstEntry(name, dummy);
292 while ( cont )
293 {
294 printf("\t%s = %s\n",
295 name.c_str(),
296 fileconf.Read(name.c_str(), _T("ERROR")).c_str());
297
298 cont = fileconf.GetNextEntry(name, dummy);
299 }
300}
301
302#endif // TEST_FILECONF
303
2c8e4738
VZ
304// ----------------------------------------------------------------------------
305// wxHashTable
306// ----------------------------------------------------------------------------
307
308#ifdef TEST_HASH
309
310#include <wx/hash.h>
311
312struct Foo
313{
314 Foo(int n_) { n = n_; count++; }
315 ~Foo() { count--; }
316
317 int n;
318
319 static size_t count;
320};
321
322size_t Foo::count = 0;
323
324WX_DECLARE_LIST(Foo, wxListFoos);
325WX_DECLARE_HASH(Foo, wxListFoos, wxHashFoos);
326
327#include <wx/listimpl.cpp>
328
329WX_DEFINE_LIST(wxListFoos);
330
331static void TestHash()
332{
333 puts("*** Testing wxHashTable ***\n");
334
335 {
336 wxHashFoos hash;
337 hash.DeleteContents(TRUE);
338
339 printf("Hash created: %u foos in hash, %u foos totally\n",
340 hash.GetCount(), Foo::count);
341
342 static const int hashTestData[] =
343 {
344 0, 1, 17, -2, 2, 4, -4, 345, 3, 3, 2, 1,
345 };
346
347 size_t n;
348 for ( n = 0; n < WXSIZEOF(hashTestData); n++ )
349 {
350 hash.Put(hashTestData[n], n, new Foo(n));
351 }
352
353 printf("Hash filled: %u foos in hash, %u foos totally\n",
354 hash.GetCount(), Foo::count);
355
356 puts("Hash access test:");
357 for ( n = 0; n < WXSIZEOF(hashTestData); n++ )
358 {
359 printf("\tGetting element with key %d, value %d: ",
360 hashTestData[n], n);
361 Foo *foo = hash.Get(hashTestData[n], n);
362 if ( !foo )
363 {
364 printf("ERROR, not found.\n");
365 }
366 else
367 {
368 printf("%d (%s)\n", foo->n,
369 (size_t)foo->n == n ? "ok" : "ERROR");
370 }
371 }
372
373 printf("\nTrying to get an element not in hash: ");
374
375 if ( hash.Get(1234) || hash.Get(1, 0) )
376 {
377 puts("ERROR: found!");
378 }
379 else
380 {
381 puts("ok (not found)");
382 }
383 }
384
385 printf("Hash destroyed: %u foos left\n", Foo::count);
386}
387
388#endif // TEST_HASH
389
696e1ea0
VZ
390// ----------------------------------------------------------------------------
391// MIME types
392// ----------------------------------------------------------------------------
393
394#ifdef TEST_MIME
395
396#include <wx/mimetype.h>
397
398static void TestMimeEnum()
399{
400 wxMimeTypesManager mimeTM;
401 wxArrayString mimetypes;
402
403 size_t count = mimeTM.EnumAllFileTypes(mimetypes);
404
405 printf("*** All %u known filetypes: ***\n", count);
406
407 wxArrayString exts;
408 wxString desc;
409
410 for ( size_t n = 0; n < count; n++ )
411 {
412 wxFileType *filetype = mimeTM.GetFileTypeFromMimeType(mimetypes[n]);
413 if ( !filetype )
c61f4f6d 414 {
97e0ceea
VZ
415 printf("nothing known about the filetype '%s'!\n",
416 mimetypes[n].c_str());
696e1ea0 417 continue;
c61f4f6d
VZ
418 }
419
696e1ea0
VZ
420 filetype->GetDescription(&desc);
421 filetype->GetExtensions(exts);
422
299fcbfe
VZ
423 filetype->GetIcon(NULL);
424
696e1ea0
VZ
425 wxString extsAll;
426 for ( size_t e = 0; e < exts.GetCount(); e++ )
427 {
428 if ( e > 0 )
429 extsAll << _T(", ");
430 extsAll += exts[e];
431 }
432
54acce90
VZ
433 printf("\t%s: %s (%s)\n",
434 mimetypes[n].c_str(), desc.c_str(), extsAll.c_str());
696e1ea0
VZ
435 }
436}
437
438#endif // TEST_MIME
439
b76b015e
VZ
440// ----------------------------------------------------------------------------
441// long long
442// ----------------------------------------------------------------------------
443
444#ifdef TEST_LONGLONG
445
446#include <wx/longlong.h>
447#include <wx/timer.h>
448
2a310492
VZ
449// make a 64 bit number from 4 16 bit ones
450#define MAKE_LL(x1, x2, x3, x4) wxLongLong((x1 << 16) | x2, (x3 << 16) | x3)
451
452// get a random 64 bit number
453#define RAND_LL() MAKE_LL(rand(), rand(), rand(), rand())
454
7d0bb74d 455#if wxUSE_LONGLONG_WX
2a310492
VZ
456inline bool operator==(const wxLongLongWx& a, const wxLongLongNative& b)
457 { return a.GetHi() == b.GetHi() && a.GetLo() == b.GetLo(); }
458inline bool operator==(const wxLongLongNative& a, const wxLongLongWx& b)
459 { return a.GetHi() == b.GetHi() && a.GetLo() == b.GetLo(); }
7d0bb74d 460#endif // wxUSE_LONGLONG_WX
2a310492 461
b76b015e
VZ
462static void TestSpeed()
463{
464 static const long max = 100000000;
465 long n;
9fc3ad34 466
b76b015e
VZ
467 {
468 wxStopWatch sw;
469
470 long l = 0;
471 for ( n = 0; n < max; n++ )
472 {
473 l += n;
474 }
475
476 printf("Summing longs took %ld milliseconds.\n", sw.Time());
477 }
478
2ea24d9f 479#if wxUSE_LONGLONG_NATIVE
b76b015e
VZ
480 {
481 wxStopWatch sw;
482
2ea24d9f 483 wxLongLong_t l = 0;
b76b015e
VZ
484 for ( n = 0; n < max; n++ )
485 {
486 l += n;
487 }
488
2ea24d9f 489 printf("Summing wxLongLong_t took %ld milliseconds.\n", sw.Time());
b76b015e 490 }
2ea24d9f 491#endif // wxUSE_LONGLONG_NATIVE
b76b015e
VZ
492
493 {
494 wxStopWatch sw;
495
496 wxLongLong l;
497 for ( n = 0; n < max; n++ )
498 {
499 l += n;
500 }
501
502 printf("Summing wxLongLongs took %ld milliseconds.\n", sw.Time());
503 }
504}
505
2a310492 506static void TestLongLongConversion()
b76b015e 507{
2a310492
VZ
508 puts("*** Testing wxLongLong conversions ***\n");
509
510 wxLongLong a;
511 size_t nTested = 0;
512 for ( size_t n = 0; n < 100000; n++ )
513 {
514 a = RAND_LL();
515
516#if wxUSE_LONGLONG_NATIVE
517 wxLongLongNative b(a.GetHi(), a.GetLo());
5e6a0e83 518
2a310492
VZ
519 wxASSERT_MSG( a == b, "conversions failure" );
520#else
521 puts("Can't do it without native long long type, test skipped.");
b76b015e 522
2a310492
VZ
523 return;
524#endif // wxUSE_LONGLONG_NATIVE
525
526 if ( !(nTested % 1000) )
527 {
528 putchar('.');
529 fflush(stdout);
530 }
531
532 nTested++;
533 }
534
535 puts(" done!");
536}
537
538static void TestMultiplication()
539{
540 puts("*** Testing wxLongLong multiplication ***\n");
541
542 wxLongLong a, b;
543 size_t nTested = 0;
544 for ( size_t n = 0; n < 100000; n++ )
545 {
546 a = RAND_LL();
547 b = RAND_LL();
548
549#if wxUSE_LONGLONG_NATIVE
550 wxLongLongNative aa(a.GetHi(), a.GetLo());
551 wxLongLongNative bb(b.GetHi(), b.GetLo());
552
553 wxASSERT_MSG( a*b == aa*bb, "multiplication failure" );
554#else // !wxUSE_LONGLONG_NATIVE
555 puts("Can't do it without native long long type, test skipped.");
556
557 return;
558#endif // wxUSE_LONGLONG_NATIVE
559
560 if ( !(nTested % 1000) )
561 {
562 putchar('.');
563 fflush(stdout);
564 }
565
566 nTested++;
567 }
568
569 puts(" done!");
570}
571
572static void TestDivision()
573{
574 puts("*** Testing wxLongLong division ***\n");
2f02cb89 575
2ea24d9f 576 wxLongLong q, r;
2f02cb89 577 size_t nTested = 0;
5e6a0e83 578 for ( size_t n = 0; n < 100000; n++ )
2f02cb89
VZ
579 {
580 // get a random wxLongLong (shifting by 12 the MSB ensures that the
581 // multiplication will not overflow)
582 wxLongLong ll = MAKE_LL((rand() >> 12), rand(), rand(), rand());
583
2ea24d9f
VZ
584 // get a random long (not wxLongLong for now) to divide it with
585 long l = rand();
586 q = ll / l;
587 r = ll % l;
588
2a310492
VZ
589#if wxUSE_LONGLONG_NATIVE
590 wxLongLongNative m(ll.GetHi(), ll.GetLo());
591
592 wxLongLongNative p = m / l, s = m % l;
593 wxASSERT_MSG( q == p && r == s, "division failure" );
594#else // !wxUSE_LONGLONG_NATIVE
5e6a0e83 595 // verify the result
2ea24d9f 596 wxASSERT_MSG( ll == q*l + r, "division failure" );
2a310492 597#endif // wxUSE_LONGLONG_NATIVE
2f02cb89 598
5e6a0e83
VZ
599 if ( !(nTested % 1000) )
600 {
601 putchar('.');
602 fflush(stdout);
603 }
604
2f02cb89
VZ
605 nTested++;
606 }
607
5e6a0e83 608 puts(" done!");
2a310492 609}
2f02cb89 610
2a310492
VZ
611static void TestAddition()
612{
613 puts("*** Testing wxLongLong addition ***\n");
614
615 wxLongLong a, b, c;
616 size_t nTested = 0;
617 for ( size_t n = 0; n < 100000; n++ )
618 {
619 a = RAND_LL();
620 b = RAND_LL();
621 c = a + b;
622
623#if wxUSE_LONGLONG_NATIVE
624 wxASSERT_MSG( c == wxLongLongNative(a.GetHi(), a.GetLo()) +
625 wxLongLongNative(b.GetHi(), b.GetLo()),
7c968cee 626 "addition failure" );
2a310492
VZ
627#else // !wxUSE_LONGLONG_NATIVE
628 wxASSERT_MSG( c - b == a, "addition failure" );
629#endif // wxUSE_LONGLONG_NATIVE
630
631 if ( !(nTested % 1000) )
632 {
633 putchar('.');
634 fflush(stdout);
635 }
636
637 nTested++;
638 }
639
640 puts(" done!");
b76b015e
VZ
641}
642
2a310492
VZ
643static void TestBitOperations()
644{
645 puts("*** Testing wxLongLong bit operation ***\n");
646
647 wxLongLong a, c;
648 size_t nTested = 0;
649 for ( size_t n = 0; n < 100000; n++ )
650 {
651 a = RAND_LL();
652
653#if wxUSE_LONGLONG_NATIVE
654 for ( size_t n = 0; n < 33; n++ )
655 {
656 wxLongLongNative b(a.GetHi(), a.GetLo());
657
658 b >>= n;
659 c = a >> n;
660
661 wxASSERT_MSG( b == c, "bit shift failure" );
662
663 b = wxLongLongNative(a.GetHi(), a.GetLo()) << n;
664 c = a << n;
665
666 wxASSERT_MSG( b == c, "bit shift failure" );
667 }
668
669#else // !wxUSE_LONGLONG_NATIVE
670 puts("Can't do it without native long long type, test skipped.");
671
672 return;
673#endif // wxUSE_LONGLONG_NATIVE
674
675 if ( !(nTested % 1000) )
676 {
677 putchar('.');
678 fflush(stdout);
679 }
680
681 nTested++;
682 }
683
684 puts(" done!");
685}
686
687#undef MAKE_LL
688#undef RAND_LL
689
b76b015e
VZ
690#endif // TEST_LONGLONG
691
2c8e4738
VZ
692// ----------------------------------------------------------------------------
693// sockets
694// ----------------------------------------------------------------------------
695
696#ifdef TEST_SOCKETS
697
698#include <wx/socket.h>
699
700static void TestSocketClient()
701{
702 puts("*** Testing wxSocketClient ***\n");
703
704 wxIPV4address addrDst;
705 addrDst.Hostname("www.wxwindows.org");
706 addrDst.Service(80);
707
708 wxSocketClient client;
709 if ( !client.Connect(addrDst) )
710 {
711 printf("ERROR: failed to connect to %s\n", addrDst.Hostname().c_str());
712 }
713 else
714 {
715 char buf[8192];
716
717 client.Write("get /front.htm\n", 17);
718 client.Read(buf, WXSIZEOF(buf));
719 printf("Server replied:\n%s", buf);
720 }
721}
722
723#endif // TEST_SOCKETS
724
d31b7b68
VZ
725// ----------------------------------------------------------------------------
726// timers
727// ----------------------------------------------------------------------------
728
729#ifdef TEST_TIMER
730
731#include <wx/timer.h>
732#include <wx/utils.h>
733
734static void TestStopWatch()
735{
736 puts("*** Testing wxStopWatch ***\n");
737
738 wxStopWatch sw;
739 printf("Sleeping 3 seconds...");
740 wxSleep(3);
87798c00 741 printf("\telapsed time: %ldms\n", sw.Time());
d31b7b68
VZ
742
743 sw.Pause();
744 printf("Sleeping 2 more seconds...");
745 wxSleep(2);
87798c00 746 printf("\telapsed time: %ldms\n", sw.Time());
d31b7b68
VZ
747
748 sw.Resume();
749 printf("And 3 more seconds...");
750 wxSleep(3);
87798c00
VZ
751 printf("\telapsed time: %ldms\n", sw.Time());
752
753 wxStopWatch sw2;
754 puts("\nChecking for 'backwards clock' bug...");
755 for ( size_t n = 0; n < 70; n++ )
756 {
757 sw2.Start();
89e6463c
GRG
758
759 for ( size_t m = 0; m < 100000; m++ )
87798c00 760 {
89e6463c
GRG
761 if ( sw.Time() < 0 || sw2.Time() < 0 )
762 {
763 puts("\ntime is negative - ERROR!");
764 }
87798c00
VZ
765 }
766
767 putchar('.');
768 }
769
770 puts(", ok.");
d31b7b68
VZ
771}
772
773#endif // TEST_TIMER
774
b76b015e
VZ
775// ----------------------------------------------------------------------------
776// date time
777// ----------------------------------------------------------------------------
778
d31b7b68 779#ifdef TEST_DATETIME
b76b015e 780
97e0ceea
VZ
781#include <wx/date.h>
782
b76b015e
VZ
783#include <wx/datetime.h>
784
299fcbfe
VZ
785// the test data
786struct Date
787{
788 wxDateTime::wxDateTime_t day;
789 wxDateTime::Month month;
790 int year;
791 wxDateTime::wxDateTime_t hour, min, sec;
792 double jdn;
211c2250 793 wxDateTime::WeekDay wday;
299fcbfe
VZ
794 time_t gmticks, ticks;
795
796 void Init(const wxDateTime::Tm& tm)
797 {
798 day = tm.mday;
799 month = tm.mon;
800 year = tm.year;
801 hour = tm.hour;
802 min = tm.min;
803 sec = tm.sec;
804 jdn = 0.0;
805 gmticks = ticks = -1;
806 }
807
808 wxDateTime DT() const
809 { return wxDateTime(day, month, year, hour, min, sec); }
810
239446b4
VZ
811 bool SameDay(const wxDateTime::Tm& tm) const
812 {
813 return day == tm.mday && month == tm.mon && year == tm.year;
814 }
815
299fcbfe
VZ
816 wxString Format() const
817 {
818 wxString s;
819 s.Printf("%02d:%02d:%02d %10s %02d, %4d%s",
820 hour, min, sec,
821 wxDateTime::GetMonthName(month).c_str(),
822 day,
823 abs(wxDateTime::ConvertYearToBC(year)),
824 year > 0 ? "AD" : "BC");
825 return s;
826 }
239446b4
VZ
827
828 wxString FormatDate() const
829 {
830 wxString s;
831 s.Printf("%02d-%s-%4d%s",
832 day,
f0f951fa 833 wxDateTime::GetMonthName(month, wxDateTime::Name_Abbr).c_str(),
239446b4
VZ
834 abs(wxDateTime::ConvertYearToBC(year)),
835 year > 0 ? "AD" : "BC");
836 return s;
837 }
299fcbfe
VZ
838};
839
840static const Date testDates[] =
841{
211c2250
VZ
842 { 1, wxDateTime::Jan, 1970, 00, 00, 00, 2440587.5, wxDateTime::Thu, 0, -3600 },
843 { 21, wxDateTime::Jan, 2222, 00, 00, 00, 2532648.5, wxDateTime::Mon, -1, -1 },
844 { 29, wxDateTime::May, 1976, 12, 00, 00, 2442928.0, wxDateTime::Sat, 202219200, 202212000 },
845 { 29, wxDateTime::Feb, 1976, 00, 00, 00, 2442837.5, wxDateTime::Sun, 194400000, 194396400 },
846 { 1, wxDateTime::Jan, 1900, 12, 00, 00, 2415021.0, wxDateTime::Mon, -1, -1 },
847 { 1, wxDateTime::Jan, 1900, 00, 00, 00, 2415020.5, wxDateTime::Mon, -1, -1 },
848 { 15, wxDateTime::Oct, 1582, 00, 00, 00, 2299160.5, wxDateTime::Fri, -1, -1 },
849 { 4, wxDateTime::Oct, 1582, 00, 00, 00, 2299149.5, wxDateTime::Mon, -1, -1 },
850 { 1, wxDateTime::Mar, 1, 00, 00, 00, 1721484.5, wxDateTime::Thu, -1, -1 },
851 { 1, wxDateTime::Jan, 1, 00, 00, 00, 1721425.5, wxDateTime::Mon, -1, -1 },
239446b4
VZ
852 { 31, wxDateTime::Dec, 0, 00, 00, 00, 1721424.5, wxDateTime::Sun, -1, -1 },
853 { 1, wxDateTime::Jan, 0, 00, 00, 00, 1721059.5, wxDateTime::Sat, -1, -1 },
854 { 12, wxDateTime::Aug, -1234, 00, 00, 00, 1270573.5, wxDateTime::Fri, -1, -1 },
855 { 12, wxDateTime::Aug, -4000, 00, 00, 00, 260313.5, wxDateTime::Sat, -1, -1 },
211c2250 856 { 24, wxDateTime::Nov, -4713, 00, 00, 00, -0.5, wxDateTime::Mon, -1, -1 },
299fcbfe
VZ
857};
858
2f02cb89
VZ
859// this test miscellaneous static wxDateTime functions
860static void TestTimeStatic()
861{
862 puts("\n*** wxDateTime static methods test ***");
863
864 // some info about the current date
865 int year = wxDateTime::GetCurrentYear();
866 printf("Current year %d is %sa leap one and has %d days.\n",
867 year,
868 wxDateTime::IsLeapYear(year) ? "" : "not ",
869 wxDateTime::GetNumberOfDays(year));
870
871 wxDateTime::Month month = wxDateTime::GetCurrentMonth();
872 printf("Current month is '%s' ('%s') and it has %d days\n",
f0f951fa 873 wxDateTime::GetMonthName(month, wxDateTime::Name_Abbr).c_str(),
2f02cb89
VZ
874 wxDateTime::GetMonthName(month).c_str(),
875 wxDateTime::GetNumberOfDays(month));
876
877 // leap year logic
fcc3d7cb
VZ
878 static const size_t nYears = 5;
879 static const size_t years[2][nYears] =
2f02cb89
VZ
880 {
881 // first line: the years to test
882 { 1990, 1976, 2000, 2030, 1984, },
883
884 // second line: TRUE if leap, FALSE otherwise
885 { FALSE, TRUE, TRUE, FALSE, TRUE }
886 };
887
888 for ( size_t n = 0; n < nYears; n++ )
889 {
890 int year = years[0][n];
239446b4
VZ
891 bool should = years[1][n] != 0,
892 is = wxDateTime::IsLeapYear(year);
2f02cb89 893
239446b4 894 printf("Year %d is %sa leap year (%s)\n",
2f02cb89 895 year,
239446b4
VZ
896 is ? "" : "not ",
897 should == is ? "ok" : "ERROR");
2f02cb89
VZ
898
899 wxASSERT( should == wxDateTime::IsLeapYear(year) );
900 }
901}
902
903// test constructing wxDateTime objects
904static void TestTimeSet()
905{
906 puts("\n*** wxDateTime construction test ***");
907
299fcbfe
VZ
908 for ( size_t n = 0; n < WXSIZEOF(testDates); n++ )
909 {
910 const Date& d1 = testDates[n];
911 wxDateTime dt = d1.DT();
912
913 Date d2;
914 d2.Init(dt.GetTm());
915
916 wxString s1 = d1.Format(),
917 s2 = d2.Format();
918
919 printf("Date: %s == %s (%s)\n",
920 s1.c_str(), s2.c_str(),
921 s1 == s2 ? "ok" : "ERROR");
922 }
2f02cb89
VZ
923}
924
fcc3d7cb
VZ
925// test time zones stuff
926static void TestTimeZones()
927{
928 puts("\n*** wxDateTime timezone test ***");
929
930 wxDateTime now = wxDateTime::Now();
931
299fcbfe
VZ
932 printf("Current GMT time:\t%s\n", now.Format("%c", wxDateTime::GMT0).c_str());
933 printf("Unix epoch (GMT):\t%s\n", wxDateTime((time_t)0).Format("%c", wxDateTime::GMT0).c_str());
934 printf("Unix epoch (EST):\t%s\n", wxDateTime((time_t)0).Format("%c", wxDateTime::EST).c_str());
935 printf("Current time in Paris:\t%s\n", now.Format("%c", wxDateTime::CET).c_str());
936 printf(" Moscow:\t%s\n", now.Format("%c", wxDateTime::MSK).c_str());
937 printf(" New York:\t%s\n", now.Format("%c", wxDateTime::EST).c_str());
9d9b7755
VZ
938
939 wxDateTime::Tm tm = now.GetTm();
940 if ( wxDateTime(tm) != now )
941 {
942 printf("ERROR: got %s instead of %s\n",
943 wxDateTime(tm).Format().c_str(), now.Format().c_str());
944 }
fcc3d7cb
VZ
945}
946
e6ec579c
VZ
947// test some minimal support for the dates outside the standard range
948static void TestTimeRange()
949{
950 puts("\n*** wxDateTime out-of-standard-range dates test ***");
951
211c2250
VZ
952 static const char *fmt = "%d-%b-%Y %H:%M:%S";
953
1ef54dcf 954 printf("Unix epoch:\t%s\n",
211c2250 955 wxDateTime(2440587.5).Format(fmt).c_str());
1ef54dcf 956 printf("Feb 29, 0: \t%s\n",
211c2250 957 wxDateTime(29, wxDateTime::Feb, 0).Format(fmt).c_str());
e6ec579c 958 printf("JDN 0: \t%s\n",
211c2250 959 wxDateTime(0.0).Format(fmt).c_str());
e6ec579c 960 printf("Jan 1, 1AD:\t%s\n",
211c2250 961 wxDateTime(1, wxDateTime::Jan, 1).Format(fmt).c_str());
e6ec579c 962 printf("May 29, 2099:\t%s\n",
211c2250 963 wxDateTime(29, wxDateTime::May, 2099).Format(fmt).c_str());
e6ec579c
VZ
964}
965
299fcbfe 966static void TestTimeTicks()
e6ec579c 967{
299fcbfe 968 puts("\n*** wxDateTime ticks test ***");
e6ec579c 969
299fcbfe 970 for ( size_t n = 0; n < WXSIZEOF(testDates); n++ )
1ef54dcf 971 {
299fcbfe
VZ
972 const Date& d = testDates[n];
973 if ( d.ticks == -1 )
974 continue;
1ef54dcf 975
299fcbfe
VZ
976 wxDateTime dt = d.DT();
977 long ticks = (dt.GetValue() / 1000).ToLong();
978 printf("Ticks of %s:\t% 10ld", d.Format().c_str(), ticks);
979 if ( ticks == d.ticks )
980 {
981 puts(" (ok)");
982 }
983 else
984 {
985 printf(" (ERROR: should be %ld, delta = %ld)\n",
986 d.ticks, ticks - d.ticks);
987 }
988
989 dt = d.DT().ToTimezone(wxDateTime::GMT0);
990 ticks = (dt.GetValue() / 1000).ToLong();
991 printf("GMtks of %s:\t% 10ld", d.Format().c_str(), ticks);
992 if ( ticks == d.gmticks )
993 {
994 puts(" (ok)");
995 }
996 else
997 {
998 printf(" (ERROR: should be %ld, delta = %ld)\n",
999 d.gmticks, ticks - d.gmticks);
1000 }
1001 }
1002
1003 puts("");
1004}
1005
1006// test conversions to JDN &c
1007static void TestTimeJDN()
1008{
1009 puts("\n*** wxDateTime to JDN test ***");
1ef54dcf
VZ
1010
1011 for ( size_t n = 0; n < WXSIZEOF(testDates); n++ )
1012 {
1013 const Date& d = testDates[n];
299fcbfe 1014 wxDateTime dt(d.day, d.month, d.year, d.hour, d.min, d.sec);
1ef54dcf
VZ
1015 double jdn = dt.GetJulianDayNumber();
1016
299fcbfe 1017 printf("JDN of %s is:\t% 15.6f", d.Format().c_str(), jdn);
1ef54dcf
VZ
1018 if ( jdn == d.jdn )
1019 {
1020 puts(" (ok)");
1021 }
1022 else
1023 {
1024 printf(" (ERROR: should be %f, delta = %f)\n",
1025 d.jdn, jdn - d.jdn);
1026 }
1027 }
e6ec579c
VZ
1028}
1029
211c2250
VZ
1030// test week days computation
1031static void TestTimeWDays()
1032{
1033 puts("\n*** wxDateTime weekday test ***");
1034
239446b4
VZ
1035 // test GetWeekDay()
1036 size_t n;
1037 for ( n = 0; n < WXSIZEOF(testDates); n++ )
211c2250
VZ
1038 {
1039 const Date& d = testDates[n];
1040 wxDateTime dt(d.day, d.month, d.year, d.hour, d.min, d.sec);
1041
1042 wxDateTime::WeekDay wday = dt.GetWeekDay();
1043 printf("%s is: %s",
1044 d.Format().c_str(),
239446b4 1045 wxDateTime::GetWeekDayName(wday).c_str());
211c2250
VZ
1046 if ( wday == d.wday )
1047 {
1048 puts(" (ok)");
1049 }
1050 else
1051 {
1052 printf(" (ERROR: should be %s)\n",
239446b4
VZ
1053 wxDateTime::GetWeekDayName(d.wday).c_str());
1054 }
1055 }
1056
1057 puts("");
1058
1059 // test SetToWeekDay()
1060 struct WeekDateTestData
1061 {
1062 Date date; // the real date (precomputed)
1063 int nWeek; // its week index in the month
1064 wxDateTime::WeekDay wday; // the weekday
1065 wxDateTime::Month month; // the month
1066 int year; // and the year
1067
1068 wxString Format() const
1069 {
1070 wxString s, which;
1071 switch ( nWeek < -1 ? -nWeek : nWeek )
1072 {
1073 case 1: which = "first"; break;
1074 case 2: which = "second"; break;
1075 case 3: which = "third"; break;
1076 case 4: which = "fourth"; break;
1077 case 5: which = "fifth"; break;
1078
1079 case -1: which = "last"; break;
1080 }
1081
1082 if ( nWeek < -1 )
1083 {
1084 which += " from end";
1085 }
1086
1087 s.Printf("The %s %s of %s in %d",
1088 which.c_str(),
1089 wxDateTime::GetWeekDayName(wday).c_str(),
1090 wxDateTime::GetMonthName(month).c_str(),
1091 year);
1092
1093 return s;
1094 }
1095 };
1096
1097 // the array data was generated by the following python program
1098 /*
1099from DateTime import *
1100from whrandom import *
1101from string import *
1102
1103monthNames = [ 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec' ]
1104wdayNames = [ 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun' ]
1105
1106week = DateTimeDelta(7)
1107
1108for n in range(20):
1109 year = randint(1900, 2100)
1110 month = randint(1, 12)
1111 day = randint(1, 28)
1112 dt = DateTime(year, month, day)
1113 wday = dt.day_of_week
1114
1115 countFromEnd = choice([-1, 1])
1116 weekNum = 0;
1117
1118 while dt.month is month:
1119 dt = dt - countFromEnd * week
1120 weekNum = weekNum + countFromEnd
1121
1122 data = { 'day': rjust(`day`, 2), 'month': monthNames[month - 1], 'year': year, 'weekNum': rjust(`weekNum`, 2), 'wday': wdayNames[wday] }
97e0ceea 1123
239446b4
VZ
1124 print "{ { %(day)s, wxDateTime::%(month)s, %(year)d }, %(weekNum)d, "\
1125 "wxDateTime::%(wday)s, wxDateTime::%(month)s, %(year)d }," % data
97e0ceea 1126 */
239446b4
VZ
1127
1128 static const WeekDateTestData weekDatesTestData[] =
1129 {
1130 { { 20, wxDateTime::Mar, 2045 }, 3, wxDateTime::Mon, wxDateTime::Mar, 2045 },
1131 { { 5, wxDateTime::Jun, 1985 }, -4, wxDateTime::Wed, wxDateTime::Jun, 1985 },
1132 { { 12, wxDateTime::Nov, 1961 }, -3, wxDateTime::Sun, wxDateTime::Nov, 1961 },
1133 { { 27, wxDateTime::Feb, 2093 }, -1, wxDateTime::Fri, wxDateTime::Feb, 2093 },
1134 { { 4, wxDateTime::Jul, 2070 }, -4, wxDateTime::Fri, wxDateTime::Jul, 2070 },
1135 { { 2, wxDateTime::Apr, 1906 }, -5, wxDateTime::Mon, wxDateTime::Apr, 1906 },
1136 { { 19, wxDateTime::Jul, 2023 }, -2, wxDateTime::Wed, wxDateTime::Jul, 2023 },
1137 { { 5, wxDateTime::May, 1958 }, -4, wxDateTime::Mon, wxDateTime::May, 1958 },
1138 { { 11, wxDateTime::Aug, 1900 }, 2, wxDateTime::Sat, wxDateTime::Aug, 1900 },
1139 { { 14, wxDateTime::Feb, 1945 }, 2, wxDateTime::Wed, wxDateTime::Feb, 1945 },
1140 { { 25, wxDateTime::Jul, 1967 }, -1, wxDateTime::Tue, wxDateTime::Jul, 1967 },
1141 { { 9, wxDateTime::May, 1916 }, -4, wxDateTime::Tue, wxDateTime::May, 1916 },
1142 { { 20, wxDateTime::Jun, 1927 }, 3, wxDateTime::Mon, wxDateTime::Jun, 1927 },
1143 { { 2, wxDateTime::Aug, 2000 }, 1, wxDateTime::Wed, wxDateTime::Aug, 2000 },
1144 { { 20, wxDateTime::Apr, 2044 }, 3, wxDateTime::Wed, wxDateTime::Apr, 2044 },
1145 { { 20, wxDateTime::Feb, 1932 }, -2, wxDateTime::Sat, wxDateTime::Feb, 1932 },
1146 { { 25, wxDateTime::Jul, 2069 }, 4, wxDateTime::Thu, wxDateTime::Jul, 2069 },
1147 { { 3, wxDateTime::Apr, 1925 }, 1, wxDateTime::Fri, wxDateTime::Apr, 1925 },
1148 { { 21, wxDateTime::Mar, 2093 }, 3, wxDateTime::Sat, wxDateTime::Mar, 2093 },
1149 { { 3, wxDateTime::Dec, 2074 }, -5, wxDateTime::Mon, wxDateTime::Dec, 2074 },
1150 };
1151
1152 static const char *fmt = "%d-%b-%Y";
1153
1154 wxDateTime dt;
1155 for ( n = 0; n < WXSIZEOF(weekDatesTestData); n++ )
1156 {
1157 const WeekDateTestData& wd = weekDatesTestData[n];
1158
1159 dt.SetToWeekDay(wd.wday, wd.nWeek, wd.month, wd.year);
1160
1161 printf("%s is %s", wd.Format().c_str(), dt.Format(fmt).c_str());
1162
1163 const Date& d = wd.date;
1164 if ( d.SameDay(dt.GetTm()) )
1165 {
1166 puts(" (ok)");
1167 }
1168 else
1169 {
1170 dt.Set(d.day, d.month, d.year);
1171
1172 printf(" (ERROR: should be %s)\n", dt.Format(fmt).c_str());
211c2250
VZ
1173 }
1174 }
1175}
1176
239446b4
VZ
1177// test the computation of (ISO) week numbers
1178static void TestTimeWNumber()
1179{
1180 puts("\n*** wxDateTime week number test ***");
1181
1182 struct WeekNumberTestData
1183 {
1184 Date date; // the date
9d9b7755
VZ
1185 wxDateTime::wxDateTime_t week; // the week number in the year
1186 wxDateTime::wxDateTime_t wmon; // the week number in the month
1187 wxDateTime::wxDateTime_t wmon2; // same but week starts with Sun
239446b4
VZ
1188 wxDateTime::wxDateTime_t dnum; // day number in the year
1189 };
1190
1191 // data generated with the following python script:
1192 /*
1193from DateTime import *
1194from whrandom import *
1195from string import *
1196
1197monthNames = [ 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec' ]
1198wdayNames = [ 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun' ]
1199
9d9b7755
VZ
1200def GetMonthWeek(dt):
1201 weekNumMonth = dt.iso_week[1] - DateTime(dt.year, dt.month, 1).iso_week[1] + 1
1202 if weekNumMonth < 0:
1203 weekNumMonth = weekNumMonth + 53
1204 return weekNumMonth
7c968cee 1205
9d9b7755
VZ
1206def GetLastSundayBefore(dt):
1207 if dt.iso_week[2] == 7:
1208 return dt
1209 else:
1210 return dt - DateTimeDelta(dt.iso_week[2])
1211
239446b4
VZ
1212for n in range(20):
1213 year = randint(1900, 2100)
1214 month = randint(1, 12)
1215 day = randint(1, 28)
1216 dt = DateTime(year, month, day)
1217 dayNum = dt.day_of_year
1218 weekNum = dt.iso_week[1]
9d9b7755
VZ
1219 weekNumMonth = GetMonthWeek(dt)
1220
1221 weekNumMonth2 = 0
1222 dtSunday = GetLastSundayBefore(dt)
1223
1224 while dtSunday >= GetLastSundayBefore(DateTime(dt.year, dt.month, 1)):
1225 weekNumMonth2 = weekNumMonth2 + 1
1226 dtSunday = dtSunday - DateTimeDelta(7)
1227
1228 data = { 'day': rjust(`day`, 2), \
1229 'month': monthNames[month - 1], \
1230 'year': year, \
1231 'weekNum': rjust(`weekNum`, 2), \
1232 'weekNumMonth': weekNumMonth, \
1233 'weekNumMonth2': weekNumMonth2, \
1234 'dayNum': rjust(`dayNum`, 3) }
1235
1236 print " { { %(day)s, "\
1237 "wxDateTime::%(month)s, "\
1238 "%(year)d }, "\
1239 "%(weekNum)s, "\
1240 "%(weekNumMonth)s, "\
1241 "%(weekNumMonth2)s, "\
239446b4 1242 "%(dayNum)s }," % data
9d9b7755 1243
239446b4
VZ
1244 */
1245 static const WeekNumberTestData weekNumberTestDates[] =
1246 {
9d9b7755
VZ
1247 { { 27, wxDateTime::Dec, 1966 }, 52, 5, 5, 361 },
1248 { { 22, wxDateTime::Jul, 1926 }, 29, 4, 4, 203 },
1249 { { 22, wxDateTime::Oct, 2076 }, 43, 4, 4, 296 },
1250 { { 1, wxDateTime::Jul, 1967 }, 26, 1, 1, 182 },
1251 { { 8, wxDateTime::Nov, 2004 }, 46, 2, 2, 313 },
1252 { { 21, wxDateTime::Mar, 1920 }, 12, 3, 4, 81 },
1253 { { 7, wxDateTime::Jan, 1965 }, 1, 2, 2, 7 },
1254 { { 19, wxDateTime::Oct, 1999 }, 42, 4, 4, 292 },
1255 { { 13, wxDateTime::Aug, 1955 }, 32, 2, 2, 225 },
1256 { { 18, wxDateTime::Jul, 2087 }, 29, 3, 3, 199 },
1257 { { 2, wxDateTime::Sep, 2028 }, 35, 1, 1, 246 },
1258 { { 28, wxDateTime::Jul, 1945 }, 30, 5, 4, 209 },
1259 { { 15, wxDateTime::Jun, 1901 }, 24, 3, 3, 166 },
1260 { { 10, wxDateTime::Oct, 1939 }, 41, 3, 2, 283 },
1261 { { 3, wxDateTime::Dec, 1965 }, 48, 1, 1, 337 },
1262 { { 23, wxDateTime::Feb, 1940 }, 8, 4, 4, 54 },
1263 { { 2, wxDateTime::Jan, 1987 }, 1, 1, 1, 2 },
1264 { { 11, wxDateTime::Aug, 2079 }, 32, 2, 2, 223 },
1265 { { 2, wxDateTime::Feb, 2063 }, 5, 1, 1, 33 },
1266 { { 16, wxDateTime::Oct, 1942 }, 42, 3, 3, 289 },
239446b4
VZ
1267 };
1268
1269 for ( size_t n = 0; n < WXSIZEOF(weekNumberTestDates); n++ )
1270 {
1271 const WeekNumberTestData& wn = weekNumberTestDates[n];
1272 const Date& d = wn.date;
1273
1274 wxDateTime dt = d.DT();
1275
9d9b7755
VZ
1276 wxDateTime::wxDateTime_t
1277 week = dt.GetWeekOfYear(wxDateTime::Monday_First),
1278 wmon = dt.GetWeekOfMonth(wxDateTime::Monday_First),
1279 wmon2 = dt.GetWeekOfMonth(wxDateTime::Sunday_First),
1280 dnum = dt.GetDayOfYear();
239446b4
VZ
1281
1282 printf("%s: the day number is %d",
1283 d.FormatDate().c_str(), dnum);
1284 if ( dnum == wn.dnum )
1285 {
1286 printf(" (ok)");
1287 }
1288 else
1289 {
1290 printf(" (ERROR: should be %d)", wn.dnum);
1291 }
1292
9d9b7755
VZ
1293 printf(", week in month is %d", wmon);
1294 if ( wmon == wn.wmon )
1295 {
1296 printf(" (ok)");
1297 }
1298 else
1299 {
1300 printf(" (ERROR: should be %d)", wn.wmon);
1301 }
1302
1303 printf(" or %d", wmon2);
1304 if ( wmon2 == wn.wmon2 )
1305 {
1306 printf(" (ok)");
1307 }
1308 else
1309 {
1310 printf(" (ERROR: should be %d)", wn.wmon2);
1311 }
1312
1313 printf(", week in year is %d", week);
239446b4
VZ
1314 if ( week == wn.week )
1315 {
1316 puts(" (ok)");
1317 }
1318 else
1319 {
1320 printf(" (ERROR: should be %d)\n", wn.week);
1321 }
1322 }
1323}
1324
1325// test DST calculations
1326static void TestTimeDST()
1327{
1328 puts("\n*** wxDateTime DST test ***");
1329
1330 printf("DST is%s in effect now.\n\n",
1331 wxDateTime::Now().IsDST() ? "" : " not");
1332
1333 // taken from http://www.energy.ca.gov/daylightsaving.html
1334 static const Date datesDST[2][2004 - 1900 + 1] =
1335 {
1336 {
1337 { 1, wxDateTime::Apr, 1990 },
1338 { 7, wxDateTime::Apr, 1991 },
1339 { 5, wxDateTime::Apr, 1992 },
1340 { 4, wxDateTime::Apr, 1993 },
1341 { 3, wxDateTime::Apr, 1994 },
1342 { 2, wxDateTime::Apr, 1995 },
1343 { 7, wxDateTime::Apr, 1996 },
1344 { 6, wxDateTime::Apr, 1997 },
1345 { 5, wxDateTime::Apr, 1998 },
1346 { 4, wxDateTime::Apr, 1999 },
1347 { 2, wxDateTime::Apr, 2000 },
1348 { 1, wxDateTime::Apr, 2001 },
1349 { 7, wxDateTime::Apr, 2002 },
1350 { 6, wxDateTime::Apr, 2003 },
1351 { 4, wxDateTime::Apr, 2004 },
1352 },
1353 {
1354 { 28, wxDateTime::Oct, 1990 },
1355 { 27, wxDateTime::Oct, 1991 },
1356 { 25, wxDateTime::Oct, 1992 },
1357 { 31, wxDateTime::Oct, 1993 },
1358 { 30, wxDateTime::Oct, 1994 },
1359 { 29, wxDateTime::Oct, 1995 },
1360 { 27, wxDateTime::Oct, 1996 },
1361 { 26, wxDateTime::Oct, 1997 },
1362 { 25, wxDateTime::Oct, 1998 },
1363 { 31, wxDateTime::Oct, 1999 },
1364 { 29, wxDateTime::Oct, 2000 },
1365 { 28, wxDateTime::Oct, 2001 },
1366 { 27, wxDateTime::Oct, 2002 },
1367 { 26, wxDateTime::Oct, 2003 },
1368 { 31, wxDateTime::Oct, 2004 },
1369 }
1370 };
1371
1372 int year;
1373 for ( year = 1990; year < 2005; year++ )
1374 {
1375 wxDateTime dtBegin = wxDateTime::GetBeginDST(year, wxDateTime::USA),
1376 dtEnd = wxDateTime::GetEndDST(year, wxDateTime::USA);
1377
1378 printf("DST period in the US for year %d: from %s to %s",
1379 year, dtBegin.Format().c_str(), dtEnd.Format().c_str());
1380
1381 size_t n = year - 1990;
1382 const Date& dBegin = datesDST[0][n];
1383 const Date& dEnd = datesDST[1][n];
97e0ceea 1384
239446b4
VZ
1385 if ( dBegin.SameDay(dtBegin.GetTm()) && dEnd.SameDay(dtEnd.GetTm()) )
1386 {
1387 puts(" (ok)");
1388 }
1389 else
1390 {
1391 printf(" (ERROR: should be %s %d to %s %d)\n",
1392 wxDateTime::GetMonthName(dBegin.month).c_str(), dBegin.day,
1393 wxDateTime::GetMonthName(dEnd.month).c_str(), dEnd.day);
1394 }
1395 }
1396
1397 puts("");
1398
1399 for ( year = 1990; year < 2005; year++ )
1400 {
1401 printf("DST period in Europe for year %d: from %s to %s\n",
1402 year,
1403 wxDateTime::GetBeginDST(year, wxDateTime::Country_EEC).Format().c_str(),
1404 wxDateTime::GetEndDST(year, wxDateTime::Country_EEC).Format().c_str());
1405 }
1406}
1407
68ee7c47
VZ
1408// test wxDateTime -> text conversion
1409static void TestTimeFormat()
1410{
1411 puts("\n*** wxDateTime formatting test ***");
1412
b38e2f7d
VZ
1413 // some information may be lost during conversion, so store what kind
1414 // of info should we recover after a round trip
1415 enum CompareKind
68ee7c47 1416 {
b38e2f7d
VZ
1417 CompareNone, // don't try comparing
1418 CompareBoth, // dates and times should be identical
1419 CompareDate, // dates only
1420 CompareTime // time only
1421 };
1422
1423 static const struct
1424 {
1425 CompareKind compareKind;
1426 const char *format;
1427 } formatTestFormats[] =
1428 {
1429 { CompareBoth, "---> %c" },
1430 { CompareDate, "Date is %A, %d of %B, in year %Y" },
1431 { CompareBoth, "Date is %x, time is %X" },
1432 { CompareTime, "Time is %H:%M:%S or %I:%M:%S %p" },
1433 { CompareNone, "The day of year: %j, the week of year: %W" },
68ee7c47
VZ
1434 };
1435
1436 static const Date formatTestDates[] =
1437 {
68ee7c47
VZ
1438 { 29, wxDateTime::May, 1976, 18, 30, 00 },
1439 { 31, wxDateTime::Dec, 1999, 23, 30, 00 },
b38e2f7d
VZ
1440#if 0
1441 // this test can't work for other centuries because it uses two digit
1442 // years in formats, so don't even try it
68ee7c47
VZ
1443 { 29, wxDateTime::May, 2076, 18, 30, 00 },
1444 { 29, wxDateTime::Feb, 2400, 02, 15, 25 },
1445 { 01, wxDateTime::Jan, -52, 03, 16, 47 },
b38e2f7d 1446#endif
68ee7c47
VZ
1447 };
1448
1449 // an extra test (as it doesn't depend on date, don't do it in the loop)
1450 printf("%s\n", wxDateTime::Now().Format("Our timezone is %Z").c_str());
1451
b38e2f7d 1452 for ( size_t d = 0; d < WXSIZEOF(formatTestDates) + 1; d++ )
68ee7c47
VZ
1453 {
1454 puts("");
1455
b38e2f7d 1456 wxDateTime dt = d == 0 ? wxDateTime::Now() : formatTestDates[d - 1].DT();
68ee7c47
VZ
1457 for ( size_t n = 0; n < WXSIZEOF(formatTestFormats); n++ )
1458 {
b38e2f7d 1459 wxString s = dt.Format(formatTestFormats[n].format);
f0f951fa
VZ
1460 printf("%s", s.c_str());
1461
b38e2f7d
VZ
1462 // what can we recover?
1463 int kind = formatTestFormats[n].compareKind;
1464
f0f951fa
VZ
1465 // convert back
1466 wxDateTime dt2;
b38e2f7d 1467 const wxChar *result = dt2.ParseFormat(s, formatTestFormats[n].format);
f0f951fa
VZ
1468 if ( !result )
1469 {
b38e2f7d
VZ
1470 // converion failed - should it have?
1471 if ( kind == CompareNone )
1472 puts(" (ok)");
1473 else
1474 puts(" (ERROR: conversion back failed)");
f0f951fa
VZ
1475 }
1476 else if ( *result )
1477 {
1478 // should have parsed the entire string
1479 puts(" (ERROR: conversion back stopped too soon)");
1480 }
f0f951fa
VZ
1481 else
1482 {
b38e2f7d
VZ
1483 bool equal = FALSE; // suppress compilaer warning
1484 switch ( kind )
1485 {
1486 case CompareBoth:
1487 equal = dt2 == dt;
1488 break;
1489
1490 case CompareDate:
1491 equal = dt.IsSameDate(dt2);
1492 break;
1493
1494 case CompareTime:
1495 equal = dt.IsSameTime(dt2);
1496 break;
1497 }
1498
1499 if ( !equal )
1500 {
1501 printf(" (ERROR: got back '%s' instead of '%s')\n",
1502 dt2.Format().c_str(), dt.Format().c_str());
1503 }
1504 else
1505 {
1506 puts(" (ok)");
1507 }
f0f951fa 1508 }
68ee7c47
VZ
1509 }
1510 }
1511}
1512
97e0ceea
VZ
1513// test text -> wxDateTime conversion
1514static void TestTimeParse()
1515{
1516 puts("\n*** wxDateTime parse test ***");
1517
1518 struct ParseTestData
1519 {
1520 const char *format;
1521 Date date;
1522 bool good;
1523 };
1524
1525 static const ParseTestData parseTestDates[] =
1526 {
68ee7c47
VZ
1527 { "Sat, 18 Dec 1999 00:46:40 +0100", { 18, wxDateTime::Dec, 1999, 00, 46, 40 }, TRUE },
1528 { "Wed, 1 Dec 1999 05:17:20 +0300", { 1, wxDateTime::Dec, 1999, 03, 17, 20 }, TRUE },
97e0ceea
VZ
1529 };
1530
1531 for ( size_t n = 0; n < WXSIZEOF(parseTestDates); n++ )
1532 {
1533 const char *format = parseTestDates[n].format;
1534
1535 printf("%s => ", format);
1536
1537 wxDateTime dt;
1538 if ( dt.ParseRfc822Date(format) )
1539 {
1540 printf("%s ", dt.Format().c_str());
1541
1542 if ( parseTestDates[n].good )
1543 {
1544 wxDateTime dtReal = parseTestDates[n].date.DT();
1545 if ( dt == dtReal )
1546 {
1547 puts("(ok)");
1548 }
1549 else
1550 {
1551 printf("(ERROR: should be %s)\n", dtReal.Format().c_str());
1552 }
1553 }
1554 else
1555 {
1556 puts("(ERROR: bad format)");
1557 }
1558 }
1559 else
1560 {
1561 printf("bad format (%s)\n",
1562 parseTestDates[n].good ? "ERROR" : "ok");
1563 }
1564 }
1565}
1566
9d9b7755
VZ
1567static void TestInteractive()
1568{
1569 puts("\n*** interactive wxDateTime tests ***");
1570
1571 char buf[128];
1572
1573 for ( ;; )
1574 {
1575 printf("Enter a date: ");
1576 if ( !fgets(buf, WXSIZEOF(buf), stdin) )
1577 break;
1578
1579 wxDateTime dt;
1580 if ( !dt.ParseDate(buf) )
1581 {
1582 puts("failed to parse the date");
1583
1584 continue;
1585 }
1586
1587 printf("%s: day %u, week of month %u/%u, week of year %u\n",
1588 dt.FormatISODate().c_str(),
1589 dt.GetDayOfYear(),
1590 dt.GetWeekOfMonth(wxDateTime::Monday_First),
1591 dt.GetWeekOfMonth(wxDateTime::Sunday_First),
1592 dt.GetWeekOfYear(wxDateTime::Monday_First));
1593 }
1594
1595 puts("\n*** done ***");
1596}
1597
1598static void TestTimeArithmetics()
1599{
1600 puts("\n*** testing arithmetic operations on wxDateTime ***");
1601
1602 static const struct
1603 {
1604 wxDateSpan span;
1605 const char *name;
7c968cee 1606 } testArithmData[] =
9d9b7755
VZ
1607 {
1608 { wxDateSpan::Day(), "day" },
1609 { wxDateSpan::Week(), "week" },
1610 { wxDateSpan::Month(), "month" },
1611 { wxDateSpan::Year(), "year" },
1612 { wxDateSpan(1, 2, 3, 4), "year, 2 months, 3 weeks, 4 days" },
1613 };
7c968cee 1614
9d9b7755
VZ
1615 wxDateTime dt(29, wxDateTime::Dec, 1999), dt1, dt2;
1616
1617 for ( size_t n = 0; n < WXSIZEOF(testArithmData); n++ )
1618 {
1619 wxDateSpan span = testArithmData[n].span;
1620 dt1 = dt + span;
1621 dt2 = dt - span;
1622
1623 const char *name = testArithmData[n].name;
1624 printf("%s + %s = %s, %s - %s = %s\n",
1625 dt.FormatISODate().c_str(), name, dt1.FormatISODate().c_str(),
1626 dt.FormatISODate().c_str(), name, dt2.FormatISODate().c_str());
1627
1628 printf("Going back: %s", (dt1 - span).FormatISODate().c_str());
1629 if ( dt1 - span == dt )
1630 {
1631 puts(" (ok)");
1632 }
1633 else
1634 {
1635 printf(" (ERROR: should be %s)\n", dt.FormatISODate().c_str());
1636 }
1637
1638 printf("Going forward: %s", (dt2 + span).FormatISODate().c_str());
1639 if ( dt2 + span == dt )
1640 {
1641 puts(" (ok)");
1642 }
1643 else
1644 {
1645 printf(" (ERROR: should be %s)\n", dt.FormatISODate().c_str());
1646 }
1647
1648 printf("Double increment: %s", (dt2 + 2*span).FormatISODate().c_str());
1649 if ( dt2 + 2*span == dt1 )
1650 {
1651 puts(" (ok)");
1652 }
1653 else
1654 {
1655 printf(" (ERROR: should be %s)\n", dt2.FormatISODate().c_str());
1656 }
1657
1658 puts("");
1659 }
1660}
1661
0de868d9
VZ
1662static void TestTimeHolidays()
1663{
1664 puts("\n*** testing wxDateTimeHolidayAuthority ***\n");
1665
1666 wxDateTime::Tm tm = wxDateTime(29, wxDateTime::May, 2000).GetTm();
1667 wxDateTime dtStart(1, tm.mon, tm.year),
1668 dtEnd = dtStart.GetLastMonthDay();
1669
1670 wxDateTimeArray hol;
1671 wxDateTimeHolidayAuthority::GetHolidaysInRange(dtStart, dtEnd, hol);
1672
1673 const wxChar *format = "%d-%b-%Y (%a)";
1674
1675 printf("All holidays between %s and %s:\n",
1676 dtStart.Format(format).c_str(), dtEnd.Format(format).c_str());
1677
1678 size_t count = hol.GetCount();
1679 for ( size_t n = 0; n < count; n++ )
1680 {
1681 printf("\t%s\n", hol[n].Format(format).c_str());
1682 }
1683
1684 puts("");
1685}
1686
68ee7c47
VZ
1687#if 0
1688
97e0ceea
VZ
1689// test compatibility with the old wxDate/wxTime classes
1690static void TestTimeCompatibility()
1691{
1692 puts("\n*** wxDateTime compatibility test ***");
1693
1694 printf("wxDate for JDN 0: %s\n", wxDate(0l).FormatDate().c_str());
1695 printf("wxDate for MJD 0: %s\n", wxDate(2400000).FormatDate().c_str());
1696
1697 double jdnNow = wxDateTime::Now().GetJDN();
1698 long jdnMidnight = (long)(jdnNow - 0.5);
1699 printf("wxDate for today: %s\n", wxDate(jdnMidnight).FormatDate().c_str());
1700
1701 jdnMidnight = wxDate().Set().GetJulianDate();
1702 printf("wxDateTime for today: %s\n",
1703 wxDateTime((double)(jdnMidnight + 0.5)).Format("%c", wxDateTime::GMT0).c_str());
1704
1705 int flags = wxEUROPEAN;//wxFULL;
1706 wxDate date;
1707 date.Set();
1708 printf("Today is %s\n", date.FormatDate(flags).c_str());
1709 for ( int n = 0; n < 7; n++ )
1710 {
1711 printf("Previous %s is %s\n",
1712 wxDateTime::GetWeekDayName((wxDateTime::WeekDay)n),
1713 date.Previous(n + 1).FormatDate(flags).c_str());
1714 }
1715}
1716
68ee7c47
VZ
1717#endif // 0
1718
d31b7b68 1719#endif // TEST_DATETIME
b76b015e 1720
e87271f3
VZ
1721// ----------------------------------------------------------------------------
1722// threads
1723// ----------------------------------------------------------------------------
1724
1725#ifdef TEST_THREADS
1726
bbfa0322 1727#include <wx/thread.h>
37667812 1728
bbfa0322
VZ
1729static size_t gs_counter = (size_t)-1;
1730static wxCriticalSection gs_critsect;
b568d04f 1731static wxCondition gs_cond;
bbfa0322 1732
b568d04f 1733class MyJoinableThread : public wxThread
bbfa0322
VZ
1734{
1735public:
b568d04f
VZ
1736 MyJoinableThread(size_t n) : wxThread(wxTHREAD_JOINABLE)
1737 { m_n = n; Create(); }
bbfa0322
VZ
1738
1739 // thread execution starts here
b568d04f 1740 virtual ExitCode Entry();
bbfa0322 1741
b568d04f
VZ
1742private:
1743 size_t m_n;
bbfa0322
VZ
1744};
1745
b568d04f 1746wxThread::ExitCode MyJoinableThread::Entry()
bbfa0322 1747{
b568d04f
VZ
1748 unsigned long res = 1;
1749 for ( size_t n = 1; n < m_n; n++ )
1750 {
1751 res *= n;
1752
1753 // it's a loooong calculation :-)
1754 Sleep(100);
1755 }
bbfa0322 1756
b568d04f 1757 return (ExitCode)res;
bbfa0322
VZ
1758}
1759
b568d04f
VZ
1760class MyDetachedThread : public wxThread
1761{
1762public:
fcc3d7cb
VZ
1763 MyDetachedThread(size_t n, char ch)
1764 {
1765 m_n = n;
1766 m_ch = ch;
1767 m_cancelled = FALSE;
1768
1769 Create();
1770 }
b568d04f
VZ
1771
1772 // thread execution starts here
1773 virtual ExitCode Entry();
1774
1775 // and stops here
1776 virtual void OnExit();
1777
1778private:
9fc3ad34
VZ
1779 size_t m_n; // number of characters to write
1780 char m_ch; // character to write
fcc3d7cb
VZ
1781
1782 bool m_cancelled; // FALSE if we exit normally
b568d04f
VZ
1783};
1784
1785wxThread::ExitCode MyDetachedThread::Entry()
bbfa0322
VZ
1786{
1787 {
1788 wxCriticalSectionLocker lock(gs_critsect);
1789 if ( gs_counter == (size_t)-1 )
1790 gs_counter = 1;
1791 else
1792 gs_counter++;
1793 }
1794
9fc3ad34 1795 for ( size_t n = 0; n < m_n; n++ )
bbfa0322
VZ
1796 {
1797 if ( TestDestroy() )
fcc3d7cb
VZ
1798 {
1799 m_cancelled = TRUE;
1800
bbfa0322 1801 break;
fcc3d7cb 1802 }
bbfa0322
VZ
1803
1804 putchar(m_ch);
1805 fflush(stdout);
1806
1807 wxThread::Sleep(100);
1808 }
1809
b568d04f 1810 return 0;
bbfa0322
VZ
1811}
1812
b568d04f 1813void MyDetachedThread::OnExit()
bbfa0322 1814{
9fc3ad34
VZ
1815 wxLogTrace("thread", "Thread %ld is in OnExit", GetId());
1816
bbfa0322 1817 wxCriticalSectionLocker lock(gs_critsect);
fcc3d7cb 1818 if ( !--gs_counter && !m_cancelled )
b568d04f 1819 gs_cond.Signal();
bbfa0322
VZ
1820}
1821
9fc3ad34
VZ
1822void TestDetachedThreads()
1823{
2f02cb89 1824 puts("\n*** Testing detached threads ***");
9fc3ad34
VZ
1825
1826 static const size_t nThreads = 3;
1827 MyDetachedThread *threads[nThreads];
1828 size_t n;
1829 for ( n = 0; n < nThreads; n++ )
1830 {
1831 threads[n] = new MyDetachedThread(10, 'A' + n);
1832 }
1833
1834 threads[0]->SetPriority(WXTHREAD_MIN_PRIORITY);
1835 threads[1]->SetPriority(WXTHREAD_MAX_PRIORITY);
1836
1837 for ( n = 0; n < nThreads; n++ )
1838 {
1839 threads[n]->Run();
1840 }
1841
1842 // wait until all threads terminate
1843 gs_cond.Wait();
1844
1845 puts("");
1846}
1847
1848void TestJoinableThreads()
1849{
2f02cb89 1850 puts("\n*** Testing a joinable thread (a loooong calculation...) ***");
9fc3ad34
VZ
1851
1852 // calc 10! in the background
1853 MyJoinableThread thread(10);
1854 thread.Run();
1855
1856 printf("\nThread terminated with exit code %lu.\n",
1857 (unsigned long)thread.Wait());
1858}
1859
1860void TestThreadSuspend()
1861{
2f02cb89
VZ
1862 puts("\n*** Testing thread suspend/resume functions ***");
1863
1864 MyDetachedThread *thread = new MyDetachedThread(15, 'X');
9fc3ad34
VZ
1865
1866 thread->Run();
1867
1868 // this is for this demo only, in a real life program we'd use another
1869 // condition variable which would be signaled from wxThread::Entry() to
1870 // tell us that the thread really started running - but here just wait a
1871 // bit and hope that it will be enough (the problem is, of course, that
1872 // the thread might still not run when we call Pause() which will result
1873 // in an error)
1874 wxThread::Sleep(300);
1875
1876 for ( size_t n = 0; n < 3; n++ )
1877 {
1878 thread->Pause();
1879
1880 puts("\nThread suspended");
1881 if ( n > 0 )
1882 {
1883 // don't sleep but resume immediately the first time
1884 wxThread::Sleep(300);
1885 }
1886 puts("Going to resume the thread");
1887
1888 thread->Resume();
1889 }
1890
4c460b34
VZ
1891 puts("Waiting until it terminates now");
1892
9fc3ad34
VZ
1893 // wait until the thread terminates
1894 gs_cond.Wait();
1895
1896 puts("");
1897}
1898
2f02cb89
VZ
1899void TestThreadDelete()
1900{
1901 // As above, using Sleep() is only for testing here - we must use some
1902 // synchronisation object instead to ensure that the thread is still
1903 // running when we delete it - deleting a detached thread which already
1904 // terminated will lead to a crash!
1905
1906 puts("\n*** Testing thread delete function ***");
1907
4c460b34
VZ
1908 MyDetachedThread *thread0 = new MyDetachedThread(30, 'W');
1909
1910 thread0->Delete();
1911
1912 puts("\nDeleted a thread which didn't start to run yet.");
1913
2f02cb89
VZ
1914 MyDetachedThread *thread1 = new MyDetachedThread(30, 'Y');
1915
1916 thread1->Run();
1917
1918 wxThread::Sleep(300);
1919
1920 thread1->Delete();
1921
1922 puts("\nDeleted a running thread.");
1923
1924 MyDetachedThread *thread2 = new MyDetachedThread(30, 'Z');
1925
1926 thread2->Run();
1927
1928 wxThread::Sleep(300);
1929
1930 thread2->Pause();
1931
1932 thread2->Delete();
1933
1934 puts("\nDeleted a sleeping thread.");
1935
4c460b34
VZ
1936 MyJoinableThread thread3(20);
1937 thread3.Run();
2f02cb89 1938
4c460b34 1939 thread3.Delete();
2f02cb89
VZ
1940
1941 puts("\nDeleted a joinable thread.");
1942
4c460b34
VZ
1943 MyJoinableThread thread4(2);
1944 thread4.Run();
2f02cb89
VZ
1945
1946 wxThread::Sleep(300);
1947
4c460b34 1948 thread4.Delete();
2f02cb89
VZ
1949
1950 puts("\nDeleted a joinable thread which already terminated.");
1951
1952 puts("");
1953}
1954
e87271f3
VZ
1955#endif // TEST_THREADS
1956
1957// ----------------------------------------------------------------------------
1958// arrays
1959// ----------------------------------------------------------------------------
1960
1961#ifdef TEST_ARRAYS
1962
1963void PrintArray(const char* name, const wxArrayString& array)
1964{
1965 printf("Dump of the array '%s'\n", name);
1966
1967 size_t nCount = array.GetCount();
1968 for ( size_t n = 0; n < nCount; n++ )
1969 {
1970 printf("\t%s[%u] = '%s'\n", name, n, array[n].c_str());
1971 }
1972}
1973
1974#endif // TEST_ARRAYS
1975
9fc3ad34
VZ
1976// ----------------------------------------------------------------------------
1977// strings
1978// ----------------------------------------------------------------------------
1979
1980#ifdef TEST_STRINGS
1981
1982#include "wx/timer.h"
bbf8fc53 1983#include "wx/tokenzr.h"
9fc3ad34 1984
7c968cee
VZ
1985static void TestStringConstruction()
1986{
1987 puts("*** Testing wxString constructores ***");
1988
1989 #define TEST_CTOR(args, res) \
1990 { \
1991 wxString s args ; \
1992 printf("wxString%s = %s ", #args, s.c_str()); \
1993 if ( s == res ) \
1994 { \
1995 puts("(ok)"); \
1996 } \
1997 else \
1998 { \
1999 printf("(ERROR: should be %s)\n", res); \
2000 } \
2001 }
2002
2003 TEST_CTOR((_T('Z'), 4), _T("ZZZZ"));
2004 TEST_CTOR((_T("Hello"), 4), _T("Hell"));
2005 TEST_CTOR((_T("Hello"), 5), _T("Hello"));
2006 // TEST_CTOR((_T("Hello"), 6), _T("Hello")); -- should give assert failure
2007
2008 static const wxChar *s = _T("?really!");
2009 const wxChar *start = wxStrchr(s, _T('r'));
2010 const wxChar *end = wxStrchr(s, _T('!'));
2011 TEST_CTOR((start, end), _T("really"));
2012
2013 puts("");
2014}
2015
299fcbfe 2016static void TestString()
9fc3ad34
VZ
2017{
2018 wxStopWatch sw;
2019
2020 wxString a, b, c;
2021
2022 a.reserve (128);
2023 b.reserve (128);
2024 c.reserve (128);
2025
2026 for (int i = 0; i < 1000000; ++i)
2027 {
2028 a = "Hello";
2029 b = " world";
2030 c = "! How'ya doin'?";
2031 a += b;
2032 a += c;
2033 c = "Hello world! What's up?";
2034 if (c != a)
2035 c = "Doh!";
2036 }
2037
2038 printf ("TestString elapsed time: %ld\n", sw.Time());
2039}
2040
299fcbfe 2041static void TestPChar()
9fc3ad34
VZ
2042{
2043 wxStopWatch sw;
2044
2045 char a [128];
2046 char b [128];
2047 char c [128];
2048
2049 for (int i = 0; i < 1000000; ++i)
2050 {
2051 strcpy (a, "Hello");
2052 strcpy (b, " world");
2053 strcpy (c, "! How'ya doin'?");
2054 strcat (a, b);
2055 strcat (a, c);
2056 strcpy (c, "Hello world! What's up?");
2057 if (strcmp (c, a) == 0)
2058 strcpy (c, "Doh!");
2059 }
2060
2061 printf ("TestPChar elapsed time: %ld\n", sw.Time());
2062}
2063
299fcbfe
VZ
2064static void TestStringSub()
2065{
2066 wxString s("Hello, world!");
2067
2068 puts("*** Testing wxString substring extraction ***");
2069
2070 printf("String = '%s'\n", s.c_str());
2071 printf("Left(5) = '%s'\n", s.Left(5).c_str());
2072 printf("Right(6) = '%s'\n", s.Right(6).c_str());
2073 printf("Mid(3, 5) = '%s'\n", s(3, 5).c_str());
2074 printf("Mid(3) = '%s'\n", s.Mid(3).c_str());
2075 printf("substr(3, 5) = '%s'\n", s.substr(3, 5).c_str());
2076 printf("substr(3) = '%s'\n", s.substr(3).c_str());
2077
2078 puts("");
2079}
2080
f0f951fa
VZ
2081static void TestStringFormat()
2082{
2083 puts("*** Testing wxString formatting ***");
2084
2085 wxString s;
2086 s.Printf("%03d", 18);
2087
2088 printf("Number 18: %s\n", wxString::Format("%03d", 18).c_str());
2089 printf("Number 18: %s\n", s.c_str());
2090
2091 puts("");
2092}
2093
d71fa6fb
VZ
2094// returns "not found" for npos, value for all others
2095static wxString PosToString(size_t res)
2096{
2097 wxString s = res == wxString::npos ? wxString(_T("not found"))
2098 : wxString::Format(_T("%u"), res);
2099 return s;
2100}
2101
2102static void TestStringFind()
2103{
2104 puts("*** Testing wxString find() functions ***");
2105
2106 static const wxChar *strToFind = _T("ell");
2107 static const struct StringFindTest
2108 {
2109 const wxChar *str;
2110 size_t start,
2111 result; // of searching "ell" in str
2112 } findTestData[] =
2113 {
2114 { _T("Well, hello world"), 0, 1 },
2115 { _T("Well, hello world"), 6, 7 },
2116 { _T("Well, hello world"), 9, wxString::npos },
2117 };
2118
2119 for ( size_t n = 0; n < WXSIZEOF(findTestData); n++ )
2120 {
2121 const StringFindTest& ft = findTestData[n];
2122 size_t res = wxString(ft.str).find(strToFind, ft.start);
2123
2124 printf(_T("Index of '%s' in '%s' starting from %u is %s "),
2125 strToFind, ft.str, ft.start, PosToString(res).c_str());
2126
2127 size_t resTrue = ft.result;
2128 if ( res == resTrue )
2129 {
2130 puts(_T("(ok)"));
2131 }
2132 else
2133 {
2134 printf(_T("(ERROR: should be %s)\n"),
2135 PosToString(resTrue).c_str());
2136 }
2137 }
2138
2139 puts("");
2140}
2141
bbf8fc53
VZ
2142// replace TABs with \t and CRs with \n
2143static wxString MakePrintable(const wxChar *s)
2144{
2145 wxString str(s);
2146 (void)str.Replace(_T("\t"), _T("\\t"));
2147 (void)str.Replace(_T("\n"), _T("\\n"));
2148 (void)str.Replace(_T("\r"), _T("\\r"));
2149
2150 return str;
2151}
2152
2153static void TestStringTokenizer()
2154{
2155 puts("*** Testing wxStringTokenizer ***");
2156
7c968cee
VZ
2157 static const wxChar *modeNames[] =
2158 {
2159 _T("default"),
2160 _T("return empty"),
2161 _T("return all empty"),
2162 _T("with delims"),
2163 _T("like strtok"),
2164 };
2165
bbf8fc53
VZ
2166 static const struct StringTokenizerTest
2167 {
7c968cee
VZ
2168 const wxChar *str; // string to tokenize
2169 const wxChar *delims; // delimiters to use
2170 size_t count; // count of token
2171 wxStringTokenizerMode mode; // how should we tokenize it
2172 } tokenizerTestData[] =
2173 {
2174 { _T(""), _T(" "), 0 },
2175 { _T("Hello, world"), _T(" "), 2 },
2176 { _T("Hello, world "), _T(" "), 2 },
2177 { _T("Hello, world"), _T(","), 2 },
2178 { _T("Hello, world!"), _T(",!"), 2 },
2179 { _T("Hello,, world!"), _T(",!"), 3 },
2180 { _T("Hello, world!"), _T(",!"), 3, wxTOKEN_RET_EMPTY_ALL },
2181 { _T("username:password:uid:gid:gecos:home:shell"), _T(":"), 7 },
2182 { _T("1 \t3\t4 6 "), wxDEFAULT_DELIMITERS, 4 },
2183 { _T("1 \t3\t4 6 "), wxDEFAULT_DELIMITERS, 6, wxTOKEN_RET_EMPTY },
2184 { _T("1 \t3\t4 6 "), wxDEFAULT_DELIMITERS, 9, wxTOKEN_RET_EMPTY_ALL },
2185 { _T("01/02/99"), _T("/-"), 3 },
2186 { _T("01-02/99"), _T("/-"), 3, wxTOKEN_RET_DELIMS },
bbf8fc53
VZ
2187 };
2188
2189 for ( size_t n = 0; n < WXSIZEOF(tokenizerTestData); n++ )
2190 {
2191 const StringTokenizerTest& tt = tokenizerTestData[n];
7c968cee 2192 wxStringTokenizer tkz(tt.str, tt.delims, tt.mode);
bbf8fc53
VZ
2193
2194 size_t count = tkz.CountTokens();
7c968cee
VZ
2195 printf(_T("String '%s' has %u tokens delimited by '%s' (mode = %s) "),
2196 MakePrintable(tt.str).c_str(),
bbf8fc53 2197 count,
7c968cee
VZ
2198 MakePrintable(tt.delims).c_str(),
2199 modeNames[tkz.GetMode()]);
bbf8fc53
VZ
2200 if ( count == tt.count )
2201 {
2202 puts(_T("(ok)"));
2203 }
2204 else
2205 {
2206 printf(_T("(ERROR: should be %u)\n"), tt.count);
2207
2208 continue;
2209 }
2210
7c968cee
VZ
2211 // if we emulate strtok(), check that we do it correctly
2212 wxChar *buf, *s, *last;
2213
2214 if ( tkz.GetMode() == wxTOKEN_STRTOK )
2215 {
2216 buf = new wxChar[wxStrlen(tt.str) + 1];
2217 wxStrcpy(buf, tt.str);
2218
2219 s = wxStrtok(buf, tt.delims, &last);
2220 }
2221 else
2222 {
2223 buf = NULL;
2224 }
2225
bbf8fc53
VZ
2226 // now show the tokens themselves
2227 size_t count2 = 0;
2228 while ( tkz.HasMoreTokens() )
2229 {
7c968cee
VZ
2230 wxString token = tkz.GetNextToken();
2231
2232 printf(_T("\ttoken %u: '%s'"),
bbf8fc53 2233 ++count2,
7c968cee
VZ
2234 MakePrintable(token).c_str());
2235
2236 if ( buf )
2237 {
2238 if ( token == s )
2239 {
2240 puts(" (ok)");
2241 }
2242 else
2243 {
2244 printf(" (ERROR: should be %s)\n", s);
2245 }
2246
2247 s = wxStrtok(NULL, tt.delims, &last);
2248 }
2249 else
2250 {
2251 // nothing to compare with
2252 puts("");
2253 }
bbf8fc53
VZ
2254 }
2255
2256 if ( count2 != count )
2257 {
7c968cee 2258 puts(_T("\tERROR: token count mismatch"));
bbf8fc53 2259 }
7c968cee
VZ
2260
2261 delete [] buf;
bbf8fc53
VZ
2262 }
2263
2264 puts("");
2265}
2266
9fc3ad34
VZ
2267#endif // TEST_STRINGS
2268
e87271f3
VZ
2269// ----------------------------------------------------------------------------
2270// entry point
2271// ----------------------------------------------------------------------------
2272
bbfa0322 2273int main(int argc, char **argv)
37667812
VZ
2274{
2275 if ( !wxInitialize() )
2276 {
2277 fprintf(stderr, "Failed to initialize the wxWindows library, aborting.");
2278 }
2279
0de868d9
VZ
2280#ifdef TEST_USLEEP
2281 puts("Sleeping for 3 seconds... z-z-z-z-z...");
2282 wxUsleep(3000);
2283#endif // TEST_USLEEP
2284
d34bce84
VZ
2285#ifdef TEST_CMDLINE
2286 static const wxCmdLineEntryDesc cmdLineDesc[] =
2287 {
2288 { wxCMD_LINE_SWITCH, "v", "verbose", "be verbose" },
2289 { wxCMD_LINE_SWITCH, "q", "quiet", "be quiet" },
2290
2291 { wxCMD_LINE_OPTION, "o", "output", "output file" },
2292 { wxCMD_LINE_OPTION, "i", "input", "input dir" },
2293 { wxCMD_LINE_OPTION, "s", "size", "output block size", wxCMD_LINE_VAL_NUMBER },
1e245dc2 2294 { wxCMD_LINE_OPTION, "d", "date", "output file date", wxCMD_LINE_VAL_DATE },
d34bce84
VZ
2295
2296 { wxCMD_LINE_PARAM, NULL, NULL, "input file",
2297 wxCMD_LINE_VAL_STRING, wxCMD_LINE_PARAM_MULTIPLE },
2298
2299 { wxCMD_LINE_NONE }
2300 };
2301
2302 wxCmdLineParser parser(cmdLineDesc, argc, argv);
2303
2304 switch ( parser.Parse() )
2305 {
2306 case -1:
2307 wxLogMessage("Help was given, terminating.");
2308 break;
2309
2310 case 0:
2311 ShowCmdLine(parser);
2312 break;
2313
2314 default:
2315 wxLogMessage("Syntax error detected, aborting.");
2316 break;
2317 }
2318#endif // TEST_CMDLINE
2319
9fc3ad34 2320#ifdef TEST_STRINGS
299fcbfe
VZ
2321 if ( 0 )
2322 {
2323 TestPChar();
2324 TestString();
2325 }
f0f951fa
VZ
2326 if ( 0 )
2327 {
7c968cee 2328 TestStringConstruction();
f0f951fa 2329 TestStringSub();
d71fa6fb 2330 TestStringFormat();
bbf8fc53 2331 TestStringFind();
7c968cee 2332 TestStringTokenizer();
ee6e1b1d 2333 }
9fc3ad34
VZ
2334#endif // TEST_STRINGS
2335
e87271f3
VZ
2336#ifdef TEST_ARRAYS
2337 wxArrayString a1;
2338 a1.Add("tiger");
2339 a1.Add("cat");
2340 a1.Add("lion");
2341 a1.Add("dog");
2342 a1.Add("human");
2343 a1.Add("ape");
2344
2345 puts("*** Initially:");
2346
2347 PrintArray("a1", a1);
2348
2349 wxArrayString a2(a1);
2350 PrintArray("a2", a2);
2351
2352 wxSortedArrayString a3(a1);
2353 PrintArray("a3", a3);
2354
2355 puts("*** After deleting a string from a1");
2356 a1.Remove(2);
2357
2358 PrintArray("a1", a1);
2359 PrintArray("a2", a2);
2360 PrintArray("a3", a3);
2361
2362 puts("*** After reassigning a1 to a2 and a3");
2363 a3 = a2 = a1;
2364 PrintArray("a2", a2);
2365 PrintArray("a3", a3);
2366#endif // TEST_ARRAYS
2367
1944c6bd
VZ
2368#ifdef TEST_DIR
2369 TestDirEnum();
2370#endif // TEST_DIR
2371
d93c719a
VZ
2372#ifdef TEST_EXECUTE
2373 TestExecute();
2374#endif // TEST_EXECUTE
2375
ee6e1b1d
VZ
2376#ifdef TEST_FILECONF
2377 TestFileConfRead();
2378#endif // TEST_FILECONF
2379
378b05f7
VZ
2380#ifdef TEST_LOG
2381 wxString s;
2382 for ( size_t n = 0; n < 8000; n++ )
2383 {
2384 s << (char)('A' + (n % 26));
2385 }
2386
2387 wxString msg;
2388 msg.Printf("A very very long message: '%s', the end!\n", s.c_str());
2389
2390 // this one shouldn't be truncated
2391 printf(msg);
2392
2393 // but this one will because log functions use fixed size buffer
b568d04f
VZ
2394 // (note that it doesn't need '\n' at the end neither - will be added
2395 // by wxLog anyhow)
2396 wxLogMessage("A very very long message 2: '%s', the end!", s.c_str());
378b05f7
VZ
2397#endif // TEST_LOG
2398
e87271f3 2399#ifdef TEST_THREADS
696e1ea0
VZ
2400 int nCPUs = wxThread::GetCPUCount();
2401 printf("This system has %d CPUs\n", nCPUs);
2402 if ( nCPUs != -1 )
2403 wxThread::SetConcurrency(nCPUs);
ef8d96c2 2404
9fc3ad34
VZ
2405 if ( argc > 1 && argv[1][0] == 't' )
2406 wxLog::AddTraceMask("thread");
b568d04f 2407
4c460b34 2408 if ( 1 )
2f02cb89 2409 TestDetachedThreads();
4c460b34 2410 if ( 1 )
2f02cb89 2411 TestJoinableThreads();
4c460b34 2412 if ( 1 )
2f02cb89
VZ
2413 TestThreadSuspend();
2414 if ( 1 )
2415 TestThreadDelete();
2416
e87271f3 2417#endif // TEST_THREADS
37667812 2418
b76b015e 2419#ifdef TEST_LONGLONG
2a310492
VZ
2420 // seed pseudo random generator
2421 srand((unsigned)time(NULL));
2422
b76b015e 2423 if ( 0 )
2a310492 2424 {
b76b015e 2425 TestSpeed();
2a310492
VZ
2426 }
2427 TestMultiplication();
2428 if ( 0 )
2429 {
b76b015e 2430 TestDivision();
2a310492
VZ
2431 TestAddition();
2432 TestLongLongConversion();
2433 TestBitOperations();
2434 }
b76b015e
VZ
2435#endif // TEST_LONGLONG
2436
2c8e4738
VZ
2437#ifdef TEST_HASH
2438 TestHash();
2439#endif // TEST_HASH
2440
696e1ea0
VZ
2441#ifdef TEST_MIME
2442 TestMimeEnum();
2443#endif // TEST_MIME
2444
2c8e4738
VZ
2445#ifdef TEST_SOCKETS
2446 TestSocketClient();
2447#endif // TEST_SOCKETS
2448
d31b7b68
VZ
2449#ifdef TEST_TIMER
2450 TestStopWatch();
2451#endif // TEST_TIMER
2452
2453#ifdef TEST_DATETIME
0de868d9 2454 if ( 0 )
299fcbfe 2455 {
9d9b7755
VZ
2456 TestTimeSet();
2457 TestTimeStatic();
2458 TestTimeRange();
2459 TestTimeZones();
2460 TestTimeTicks();
2461 TestTimeJDN();
2462 TestTimeDST();
2463 TestTimeWDays();
2464 TestTimeWNumber();
2465 TestTimeParse();
2466 TestTimeFormat();
2467 TestTimeArithmetics();
41acf5c0 2468 }
0de868d9 2469 TestTimeHolidays();
9d9b7755
VZ
2470 if ( 0 )
2471 TestInteractive();
d31b7b68 2472#endif // TEST_DATETIME
b76b015e 2473
37667812
VZ
2474 wxUninitialize();
2475
2476 return 0;
2477}