]> git.saurik.com Git - wxWidgets.git/blob - samples/console/console.cpp
oops, forgot to fix wxHtmlTag dtor
[wxWidgets.git] / samples / console / console.cpp
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
12 // ============================================================================
13 // declarations
14 // ============================================================================
15
16 // ----------------------------------------------------------------------------
17 // headers
18 // ----------------------------------------------------------------------------
19
20 #include <wx/defs.h>
21
22 #if wxUSE_GUI
23 #error "This sample can't be compiled in GUI mode."
24 #endif // wxUSE_GUI
25
26 #include <stdio.h>
27
28 #include <wx/string.h>
29 #include <wx/file.h>
30 #include <wx/app.h>
31
32 // without this pragma, the stupid compiler precompiles #defines below so that
33 // changing them doesn't "take place" later!
34 #ifdef __VISUALC__
35 #pragma hdrstop
36 #endif
37
38 // ----------------------------------------------------------------------------
39 // conditional compilation
40 // ----------------------------------------------------------------------------
41
42 // what to test (in alphabetic order)?
43
44 //#define TEST_ARRAYS
45 //#define TEST_CHARSET
46 //#define TEST_CMDLINE
47 //#define TEST_DATETIME
48 //#define TEST_DIR
49 //#define TEST_DLLLOADER
50 //#define TEST_ENVIRON
51 //#define TEST_EXECUTE
52 //#define TEST_FILE
53 //#define TEST_FILECONF
54 //#define TEST_FILENAME
55 //#define TEST_FTP
56 //#define TEST_HASH
57 //#define TEST_INFO_FUNCTIONS
58 //#define TEST_LIST
59 //#define TEST_LOCALE
60 //#define TEST_LOG
61 //#define TEST_LONGLONG
62 //#define TEST_MIME
63 //#define TEST_PATHLIST
64 //#define TEST_REGCONF
65 #define TEST_REGEX
66 //#define TEST_REGISTRY
67 //#define TEST_SNGLINST
68 //#define TEST_SOCKETS
69 //#define TEST_STREAMS
70 //#define TEST_STRINGS
71 //#define TEST_THREADS
72 //#define TEST_TIMER
73 //#define TEST_VCARD -- don't enable this (VZ)
74 //#define TEST_WCHAR
75 //#define TEST_ZIP
76 //#define TEST_ZLIB
77
78 #ifdef TEST_SNGLINST
79 #include <wx/snglinst.h>
80 #endif // TEST_SNGLINST
81
82 // ----------------------------------------------------------------------------
83 // test class for container objects
84 // ----------------------------------------------------------------------------
85
86 #if defined(TEST_ARRAYS) || defined(TEST_LIST)
87
88 class Bar // Foo is already taken in the hash test
89 {
90 public:
91 Bar(const wxString& name) : m_name(name) { ms_bars++; }
92 ~Bar() { ms_bars--; }
93
94 static size_t GetNumber() { return ms_bars; }
95
96 const char *GetName() const { return m_name; }
97
98 private:
99 wxString m_name;
100
101 static size_t ms_bars;
102 };
103
104 size_t Bar::ms_bars = 0;
105
106 #endif // defined(TEST_ARRAYS) || defined(TEST_LIST)
107
108 // ============================================================================
109 // implementation
110 // ============================================================================
111
112 // ----------------------------------------------------------------------------
113 // helper functions
114 // ----------------------------------------------------------------------------
115
116 #if defined(TEST_STRINGS) || defined(TEST_SOCKETS)
117
118 // replace TABs with \t and CRs with \n
119 static wxString MakePrintable(const wxChar *s)
120 {
121 wxString str(s);
122 (void)str.Replace(_T("\t"), _T("\\t"));
123 (void)str.Replace(_T("\n"), _T("\\n"));
124 (void)str.Replace(_T("\r"), _T("\\r"));
125
126 return str;
127 }
128
129 #endif // MakePrintable() is used
130
131 // ----------------------------------------------------------------------------
132 // wxFontMapper::CharsetToEncoding
133 // ----------------------------------------------------------------------------
134
135 #ifdef TEST_CHARSET
136
137 #include <wx/fontmap.h>
138
139 static void TestCharset()
140 {
141 static const wxChar *charsets[] =
142 {
143 // some vali charsets
144 _T("us-ascii "),
145 _T("iso8859-1 "),
146 _T("iso-8859-12 "),
147 _T("koi8-r "),
148 _T("utf-7 "),
149 _T("cp1250 "),
150 _T("windows-1252"),
151
152 // and now some bogus ones
153 _T(" "),
154 _T("cp1249 "),
155 _T("iso--8859-1 "),
156 _T("iso-8859-19 "),
157 };
158
159 for ( size_t n = 0; n < WXSIZEOF(charsets); n++ )
160 {
161 wxFontEncoding enc = wxTheFontMapper->CharsetToEncoding(charsets[n]);
162 wxPrintf(_T("Charset: %s\tEncoding: %s (%s)\n"),
163 charsets[n],
164 wxTheFontMapper->GetEncodingName(enc).c_str(),
165 wxTheFontMapper->GetEncodingDescription(enc).c_str());
166 }
167 }
168
169 #endif // TEST_CHARSET
170
171 // ----------------------------------------------------------------------------
172 // wxCmdLineParser
173 // ----------------------------------------------------------------------------
174
175 #ifdef TEST_CMDLINE
176
177 #include <wx/cmdline.h>
178 #include <wx/datetime.h>
179
180 static void ShowCmdLine(const wxCmdLineParser& parser)
181 {
182 wxString s = "Input files: ";
183
184 size_t count = parser.GetParamCount();
185 for ( size_t param = 0; param < count; param++ )
186 {
187 s << parser.GetParam(param) << ' ';
188 }
189
190 s << '\n'
191 << "Verbose:\t" << (parser.Found("v") ? "yes" : "no") << '\n'
192 << "Quiet:\t" << (parser.Found("q") ? "yes" : "no") << '\n';
193
194 wxString strVal;
195 long lVal;
196 wxDateTime dt;
197 if ( parser.Found("o", &strVal) )
198 s << "Output file:\t" << strVal << '\n';
199 if ( parser.Found("i", &strVal) )
200 s << "Input dir:\t" << strVal << '\n';
201 if ( parser.Found("s", &lVal) )
202 s << "Size:\t" << lVal << '\n';
203 if ( parser.Found("d", &dt) )
204 s << "Date:\t" << dt.FormatISODate() << '\n';
205 if ( parser.Found("project_name", &strVal) )
206 s << "Project:\t" << strVal << '\n';
207
208 wxLogMessage(s);
209 }
210
211 #endif // TEST_CMDLINE
212
213 // ----------------------------------------------------------------------------
214 // wxDir
215 // ----------------------------------------------------------------------------
216
217 #ifdef TEST_DIR
218
219 #include <wx/dir.h>
220
221 #ifdef __UNIX__
222 static const wxChar *ROOTDIR = _T("/");
223 static const wxChar *TESTDIR = _T("/usr");
224 #elif defined(__WXMSW__)
225 static const wxChar *ROOTDIR = _T("c:\\");
226 static const wxChar *TESTDIR = _T("d:\\");
227 #else
228 #error "don't know where the root directory is"
229 #endif
230
231 static void TestDirEnumHelper(wxDir& dir,
232 int flags = wxDIR_DEFAULT,
233 const wxString& filespec = wxEmptyString)
234 {
235 wxString filename;
236
237 if ( !dir.IsOpened() )
238 return;
239
240 bool cont = dir.GetFirst(&filename, filespec, flags);
241 while ( cont )
242 {
243 printf("\t%s\n", filename.c_str());
244
245 cont = dir.GetNext(&filename);
246 }
247
248 puts("");
249 }
250
251 static void TestDirEnum()
252 {
253 puts("*** Testing wxDir::GetFirst/GetNext ***");
254
255 wxDir dir(wxGetCwd());
256
257 puts("Enumerating everything in current directory:");
258 TestDirEnumHelper(dir);
259
260 puts("Enumerating really everything in current directory:");
261 TestDirEnumHelper(dir, wxDIR_DEFAULT | wxDIR_DOTDOT);
262
263 puts("Enumerating object files in current directory:");
264 TestDirEnumHelper(dir, wxDIR_DEFAULT, "*.o");
265
266 puts("Enumerating directories in current directory:");
267 TestDirEnumHelper(dir, wxDIR_DIRS);
268
269 puts("Enumerating files in current directory:");
270 TestDirEnumHelper(dir, wxDIR_FILES);
271
272 puts("Enumerating files including hidden in current directory:");
273 TestDirEnumHelper(dir, wxDIR_FILES | wxDIR_HIDDEN);
274
275 dir.Open(ROOTDIR);
276
277 puts("Enumerating everything in root directory:");
278 TestDirEnumHelper(dir, wxDIR_DEFAULT);
279
280 puts("Enumerating directories in root directory:");
281 TestDirEnumHelper(dir, wxDIR_DIRS);
282
283 puts("Enumerating files in root directory:");
284 TestDirEnumHelper(dir, wxDIR_FILES);
285
286 puts("Enumerating files including hidden in root directory:");
287 TestDirEnumHelper(dir, wxDIR_FILES | wxDIR_HIDDEN);
288
289 puts("Enumerating files in non existing directory:");
290 wxDir dirNo("nosuchdir");
291 TestDirEnumHelper(dirNo);
292 }
293
294 class DirPrintTraverser : public wxDirTraverser
295 {
296 public:
297 virtual wxDirTraverseResult OnFile(const wxString& filename)
298 {
299 return wxDIR_CONTINUE;
300 }
301
302 virtual wxDirTraverseResult OnDir(const wxString& dirname)
303 {
304 wxString path, name, ext;
305 wxSplitPath(dirname, &path, &name, &ext);
306
307 if ( !ext.empty() )
308 name << _T('.') << ext;
309
310 wxString indent;
311 for ( const wxChar *p = path.c_str(); *p; p++ )
312 {
313 if ( wxIsPathSeparator(*p) )
314 indent += _T(" ");
315 }
316
317 printf("%s%s\n", indent.c_str(), name.c_str());
318
319 return wxDIR_CONTINUE;
320 }
321 };
322
323 static void TestDirTraverse()
324 {
325 puts("*** Testing wxDir::Traverse() ***");
326
327 // enum all files
328 wxArrayString files;
329 size_t n = wxDir::GetAllFiles(TESTDIR, &files);
330 printf("There are %u files under '%s'\n", n, TESTDIR);
331 if ( n > 1 )
332 {
333 printf("First one is '%s'\n", files[0u].c_str());
334 printf(" last one is '%s'\n", files[n - 1].c_str());
335 }
336
337 // enum again with custom traverser
338 wxDir dir(TESTDIR);
339 DirPrintTraverser traverser;
340 dir.Traverse(traverser, _T(""), wxDIR_DIRS | wxDIR_HIDDEN);
341 }
342
343 #endif // TEST_DIR
344
345 // ----------------------------------------------------------------------------
346 // wxDllLoader
347 // ----------------------------------------------------------------------------
348
349 #ifdef TEST_DLLLOADER
350
351 #include <wx/dynlib.h>
352
353 static void TestDllLoad()
354 {
355 #if defined(__WXMSW__)
356 static const wxChar *LIB_NAME = _T("kernel32.dll");
357 static const wxChar *FUNC_NAME = _T("lstrlenA");
358 #elif defined(__UNIX__)
359 // weird: using just libc.so does *not* work!
360 static const wxChar *LIB_NAME = _T("/lib/libc-2.0.7.so");
361 static const wxChar *FUNC_NAME = _T("strlen");
362 #else
363 #error "don't know how to test wxDllLoader on this platform"
364 #endif
365
366 puts("*** testing wxDllLoader ***\n");
367
368 wxDllType dllHandle = wxDllLoader::LoadLibrary(LIB_NAME);
369 if ( !dllHandle )
370 {
371 wxPrintf(_T("ERROR: failed to load '%s'.\n"), LIB_NAME);
372 }
373 else
374 {
375 typedef int (*strlenType)(char *);
376 strlenType pfnStrlen = (strlenType)wxDllLoader::GetSymbol(dllHandle, FUNC_NAME);
377 if ( !pfnStrlen )
378 {
379 wxPrintf(_T("ERROR: function '%s' wasn't found in '%s'.\n"),
380 FUNC_NAME, LIB_NAME);
381 }
382 else
383 {
384 if ( pfnStrlen("foo") != 3 )
385 {
386 wxPrintf(_T("ERROR: loaded function is not strlen()!\n"));
387 }
388 else
389 {
390 puts("... ok");
391 }
392 }
393
394 wxDllLoader::UnloadLibrary(dllHandle);
395 }
396 }
397
398 #endif // TEST_DLLLOADER
399
400 // ----------------------------------------------------------------------------
401 // wxGet/SetEnv
402 // ----------------------------------------------------------------------------
403
404 #ifdef TEST_ENVIRON
405
406 #include <wx/utils.h>
407
408 static wxString MyGetEnv(const wxString& var)
409 {
410 wxString val;
411 if ( !wxGetEnv(var, &val) )
412 val = _T("<empty>");
413 else
414 val = wxString(_T('\'')) + val + _T('\'');
415
416 return val;
417 }
418
419 static void TestEnvironment()
420 {
421 const wxChar *var = _T("wxTestVar");
422
423 puts("*** testing environment access functions ***");
424
425 printf("Initially getenv(%s) = %s\n", var, MyGetEnv(var).c_str());
426 wxSetEnv(var, _T("value for wxTestVar"));
427 printf("After wxSetEnv: getenv(%s) = %s\n", var, MyGetEnv(var).c_str());
428 wxSetEnv(var, _T("another value"));
429 printf("After 2nd wxSetEnv: getenv(%s) = %s\n", var, MyGetEnv(var).c_str());
430 wxUnsetEnv(var);
431 printf("After wxUnsetEnv: getenv(%s) = %s\n", var, MyGetEnv(var).c_str());
432 printf("PATH = %s\n", MyGetEnv(_T("PATH")).c_str());
433 }
434
435 #endif // TEST_ENVIRON
436
437 // ----------------------------------------------------------------------------
438 // wxExecute
439 // ----------------------------------------------------------------------------
440
441 #ifdef TEST_EXECUTE
442
443 #include <wx/utils.h>
444
445 static void TestExecute()
446 {
447 puts("*** testing wxExecute ***");
448
449 #ifdef __UNIX__
450 #define COMMAND "cat -n ../../Makefile" // "echo hi"
451 #define SHELL_COMMAND "echo hi from shell"
452 #define REDIRECT_COMMAND COMMAND // "date"
453 #elif defined(__WXMSW__)
454 #define COMMAND "command.com -c 'echo hi'"
455 #define SHELL_COMMAND "echo hi"
456 #define REDIRECT_COMMAND COMMAND
457 #else
458 #error "no command to exec"
459 #endif // OS
460
461 printf("Testing wxShell: ");
462 fflush(stdout);
463 if ( wxShell(SHELL_COMMAND) )
464 puts("Ok.");
465 else
466 puts("ERROR.");
467
468 printf("Testing wxExecute: ");
469 fflush(stdout);
470 if ( wxExecute(COMMAND, TRUE /* sync */) == 0 )
471 puts("Ok.");
472 else
473 puts("ERROR.");
474
475 #if 0 // no, it doesn't work (yet?)
476 printf("Testing async wxExecute: ");
477 fflush(stdout);
478 if ( wxExecute(COMMAND) != 0 )
479 puts("Ok (command launched).");
480 else
481 puts("ERROR.");
482 #endif // 0
483
484 printf("Testing wxExecute with redirection:\n");
485 wxArrayString output;
486 if ( wxExecute(REDIRECT_COMMAND, output) != 0 )
487 {
488 puts("ERROR.");
489 }
490 else
491 {
492 size_t count = output.GetCount();
493 for ( size_t n = 0; n < count; n++ )
494 {
495 printf("\t%s\n", output[n].c_str());
496 }
497
498 puts("Ok.");
499 }
500 }
501
502 #endif // TEST_EXECUTE
503
504 // ----------------------------------------------------------------------------
505 // file
506 // ----------------------------------------------------------------------------
507
508 #ifdef TEST_FILE
509
510 #include <wx/file.h>
511 #include <wx/ffile.h>
512 #include <wx/textfile.h>
513
514 static void TestFileRead()
515 {
516 puts("*** wxFile read test ***");
517
518 wxFile file(_T("testdata.fc"));
519 if ( file.IsOpened() )
520 {
521 printf("File length: %lu\n", file.Length());
522
523 puts("File dump:\n----------");
524
525 static const off_t len = 1024;
526 char buf[len];
527 for ( ;; )
528 {
529 off_t nRead = file.Read(buf, len);
530 if ( nRead == wxInvalidOffset )
531 {
532 printf("Failed to read the file.");
533 break;
534 }
535
536 fwrite(buf, nRead, 1, stdout);
537
538 if ( nRead < len )
539 break;
540 }
541
542 puts("----------");
543 }
544 else
545 {
546 printf("ERROR: can't open test file.\n");
547 }
548
549 puts("");
550 }
551
552 static void TestTextFileRead()
553 {
554 puts("*** wxTextFile read test ***");
555
556 wxTextFile file(_T("testdata.fc"));
557 if ( file.Open() )
558 {
559 printf("Number of lines: %u\n", file.GetLineCount());
560 printf("Last line: '%s'\n", file.GetLastLine().c_str());
561
562 wxString s;
563
564 puts("\nDumping the entire file:");
565 for ( s = file.GetFirstLine(); !file.Eof(); s = file.GetNextLine() )
566 {
567 printf("%6u: %s\n", file.GetCurrentLine() + 1, s.c_str());
568 }
569 printf("%6u: %s\n", file.GetCurrentLine() + 1, s.c_str());
570
571 puts("\nAnd now backwards:");
572 for ( s = file.GetLastLine();
573 file.GetCurrentLine() != 0;
574 s = file.GetPrevLine() )
575 {
576 printf("%6u: %s\n", file.GetCurrentLine() + 1, s.c_str());
577 }
578 printf("%6u: %s\n", file.GetCurrentLine() + 1, s.c_str());
579 }
580 else
581 {
582 printf("ERROR: can't open '%s'\n", file.GetName());
583 }
584
585 puts("");
586 }
587
588 static void TestFileCopy()
589 {
590 puts("*** Testing wxCopyFile ***");
591
592 static const wxChar *filename1 = _T("testdata.fc");
593 static const wxChar *filename2 = _T("test2");
594 if ( !wxCopyFile(filename1, filename2) )
595 {
596 puts("ERROR: failed to copy file");
597 }
598 else
599 {
600 wxFFile f1(filename1, "rb"),
601 f2(filename2, "rb");
602
603 if ( !f1.IsOpened() || !f2.IsOpened() )
604 {
605 puts("ERROR: failed to open file(s)");
606 }
607 else
608 {
609 wxString s1, s2;
610 if ( !f1.ReadAll(&s1) || !f2.ReadAll(&s2) )
611 {
612 puts("ERROR: failed to read file(s)");
613 }
614 else
615 {
616 if ( (s1.length() != s2.length()) ||
617 (memcmp(s1.c_str(), s2.c_str(), s1.length()) != 0) )
618 {
619 puts("ERROR: copy error!");
620 }
621 else
622 {
623 puts("File was copied ok.");
624 }
625 }
626 }
627 }
628
629 if ( !wxRemoveFile(filename2) )
630 {
631 puts("ERROR: failed to remove the file");
632 }
633
634 puts("");
635 }
636
637 #endif // TEST_FILE
638
639 // ----------------------------------------------------------------------------
640 // wxFileConfig
641 // ----------------------------------------------------------------------------
642
643 #ifdef TEST_FILECONF
644
645 #include <wx/confbase.h>
646 #include <wx/fileconf.h>
647
648 static const struct FileConfTestData
649 {
650 const wxChar *name; // value name
651 const wxChar *value; // the value from the file
652 } fcTestData[] =
653 {
654 { _T("value1"), _T("one") },
655 { _T("value2"), _T("two") },
656 { _T("novalue"), _T("default") },
657 };
658
659 static void TestFileConfRead()
660 {
661 puts("*** testing wxFileConfig loading/reading ***");
662
663 wxFileConfig fileconf(_T("test"), wxEmptyString,
664 _T("testdata.fc"), wxEmptyString,
665 wxCONFIG_USE_RELATIVE_PATH);
666
667 // test simple reading
668 puts("\nReading config file:");
669 wxString defValue(_T("default")), value;
670 for ( size_t n = 0; n < WXSIZEOF(fcTestData); n++ )
671 {
672 const FileConfTestData& data = fcTestData[n];
673 value = fileconf.Read(data.name, defValue);
674 printf("\t%s = %s ", data.name, value.c_str());
675 if ( value == data.value )
676 {
677 puts("(ok)");
678 }
679 else
680 {
681 printf("(ERROR: should be %s)\n", data.value);
682 }
683 }
684
685 // test enumerating the entries
686 puts("\nEnumerating all root entries:");
687 long dummy;
688 wxString name;
689 bool cont = fileconf.GetFirstEntry(name, dummy);
690 while ( cont )
691 {
692 printf("\t%s = %s\n",
693 name.c_str(),
694 fileconf.Read(name.c_str(), _T("ERROR")).c_str());
695
696 cont = fileconf.GetNextEntry(name, dummy);
697 }
698 }
699
700 #endif // TEST_FILECONF
701
702 // ----------------------------------------------------------------------------
703 // wxFileName
704 // ----------------------------------------------------------------------------
705
706 #ifdef TEST_FILENAME
707
708 #include <wx/filename.h>
709
710 static struct FileNameInfo
711 {
712 const wxChar *fullname;
713 const wxChar *path;
714 const wxChar *name;
715 const wxChar *ext;
716 } filenames[] =
717 {
718 { _T("/usr/bin/ls"), _T("/usr/bin"), _T("ls"), _T("") },
719 { _T("/usr/bin/"), _T("/usr/bin"), _T(""), _T("") },
720 { _T("~/.zshrc"), _T("~"), _T(".zshrc"), _T("") },
721 { _T("../../foo"), _T("../.."), _T("foo"), _T("") },
722 { _T("foo.bar"), _T(""), _T("foo"), _T("bar") },
723 { _T("~/foo.bar"), _T("~"), _T("foo"), _T("bar") },
724 { _T("Mahogany-0.60/foo.bar"), _T("Mahogany-0.60"), _T("foo"), _T("bar") },
725 { _T("/tmp/wxwin.tar.bz"), _T("/tmp"), _T("wxwin.tar"), _T("bz") },
726 };
727
728 static void TestFileNameConstruction()
729 {
730 puts("*** testing wxFileName construction ***");
731
732 for ( size_t n = 0; n < WXSIZEOF(filenames); n++ )
733 {
734 wxFileName fn(filenames[n].fullname, wxPATH_UNIX);
735
736 printf("Filename: '%s'\t", fn.GetFullPath().c_str());
737 if ( !fn.Normalize(wxPATH_NORM_ALL, _T(""), wxPATH_UNIX) )
738 {
739 puts("ERROR (couldn't be normalized)");
740 }
741 else
742 {
743 printf("normalized: '%s'\n", fn.GetFullPath().c_str());
744 }
745 }
746
747 puts("");
748 }
749
750 static void TestFileNameSplit()
751 {
752 puts("*** testing wxFileName splitting ***");
753
754 for ( size_t n = 0; n < WXSIZEOF(filenames); n++ )
755 {
756 const FileNameInfo &fni = filenames[n];
757 wxString path, name, ext;
758 wxFileName::SplitPath(fni.fullname, &path, &name, &ext);
759
760 printf("%s -> path = '%s', name = '%s', ext = '%s'",
761 fni.fullname, path.c_str(), name.c_str(), ext.c_str());
762 if ( path != fni.path )
763 printf(" (ERROR: path = '%s')", fni.path);
764 if ( name != fni.name )
765 printf(" (ERROR: name = '%s')", fni.name);
766 if ( ext != fni.ext )
767 printf(" (ERROR: ext = '%s')", fni.ext);
768 puts("");
769 }
770
771 puts("");
772 }
773
774 static void TestFileNameComparison()
775 {
776 // TODO!
777 }
778
779 static void TestFileNameOperations()
780 {
781 // TODO!
782 }
783
784 static void TestFileNameCwd()
785 {
786 // TODO!
787 }
788
789 #endif // TEST_FILENAME
790
791 // ----------------------------------------------------------------------------
792 // wxHashTable
793 // ----------------------------------------------------------------------------
794
795 #ifdef TEST_HASH
796
797 #include <wx/hash.h>
798
799 struct Foo
800 {
801 Foo(int n_) { n = n_; count++; }
802 ~Foo() { count--; }
803
804 int n;
805
806 static size_t count;
807 };
808
809 size_t Foo::count = 0;
810
811 WX_DECLARE_LIST(Foo, wxListFoos);
812 WX_DECLARE_HASH(Foo, wxListFoos, wxHashFoos);
813
814 #include <wx/listimpl.cpp>
815
816 WX_DEFINE_LIST(wxListFoos);
817
818 static void TestHash()
819 {
820 puts("*** Testing wxHashTable ***\n");
821
822 {
823 wxHashFoos hash;
824 hash.DeleteContents(TRUE);
825
826 printf("Hash created: %u foos in hash, %u foos totally\n",
827 hash.GetCount(), Foo::count);
828
829 static const int hashTestData[] =
830 {
831 0, 1, 17, -2, 2, 4, -4, 345, 3, 3, 2, 1,
832 };
833
834 size_t n;
835 for ( n = 0; n < WXSIZEOF(hashTestData); n++ )
836 {
837 hash.Put(hashTestData[n], n, new Foo(n));
838 }
839
840 printf("Hash filled: %u foos in hash, %u foos totally\n",
841 hash.GetCount(), Foo::count);
842
843 puts("Hash access test:");
844 for ( n = 0; n < WXSIZEOF(hashTestData); n++ )
845 {
846 printf("\tGetting element with key %d, value %d: ",
847 hashTestData[n], n);
848 Foo *foo = hash.Get(hashTestData[n], n);
849 if ( !foo )
850 {
851 printf("ERROR, not found.\n");
852 }
853 else
854 {
855 printf("%d (%s)\n", foo->n,
856 (size_t)foo->n == n ? "ok" : "ERROR");
857 }
858 }
859
860 printf("\nTrying to get an element not in hash: ");
861
862 if ( hash.Get(1234) || hash.Get(1, 0) )
863 {
864 puts("ERROR: found!");
865 }
866 else
867 {
868 puts("ok (not found)");
869 }
870 }
871
872 printf("Hash destroyed: %u foos left\n", Foo::count);
873 }
874
875 #endif // TEST_HASH
876
877 // ----------------------------------------------------------------------------
878 // wxList
879 // ----------------------------------------------------------------------------
880
881 #ifdef TEST_LIST
882
883 #include <wx/list.h>
884
885 WX_DECLARE_LIST(Bar, wxListBars);
886 #include <wx/listimpl.cpp>
887 WX_DEFINE_LIST(wxListBars);
888
889 static void TestListCtor()
890 {
891 puts("*** Testing wxList construction ***\n");
892
893 {
894 wxListBars list1;
895 list1.Append(new Bar(_T("first")));
896 list1.Append(new Bar(_T("second")));
897
898 printf("After 1st list creation: %u objects in the list, %u objects total.\n",
899 list1.GetCount(), Bar::GetNumber());
900
901 wxListBars list2;
902 list2 = list1;
903
904 printf("After 2nd list creation: %u and %u objects in the lists, %u objects total.\n",
905 list1.GetCount(), list2.GetCount(), Bar::GetNumber());
906
907 list1.DeleteContents(TRUE);
908 }
909
910 printf("After list destruction: %u objects left.\n", Bar::GetNumber());
911 }
912
913 #endif // TEST_LIST
914
915 // ----------------------------------------------------------------------------
916 // wxLocale
917 // ----------------------------------------------------------------------------
918
919 #ifdef TEST_LOCALE
920
921 #include "wx/intl.h"
922 #include "wx/utils.h" // for wxSetEnv
923
924 static wxLocale gs_localeDefault(wxLANGUAGE_ENGLISH);
925
926 // find the name of the language from its value
927 static const char *GetLangName(int lang)
928 {
929 static const char *languageNames[] =
930 {
931 "DEFAULT",
932 "UNKNOWN",
933 "ABKHAZIAN",
934 "AFAR",
935 "AFRIKAANS",
936 "ALBANIAN",
937 "AMHARIC",
938 "ARABIC",
939 "ARABIC_ALGERIA",
940 "ARABIC_BAHRAIN",
941 "ARABIC_EGYPT",
942 "ARABIC_IRAQ",
943 "ARABIC_JORDAN",
944 "ARABIC_KUWAIT",
945 "ARABIC_LEBANON",
946 "ARABIC_LIBYA",
947 "ARABIC_MOROCCO",
948 "ARABIC_OMAN",
949 "ARABIC_QATAR",
950 "ARABIC_SAUDI_ARABIA",
951 "ARABIC_SUDAN",
952 "ARABIC_SYRIA",
953 "ARABIC_TUNISIA",
954 "ARABIC_UAE",
955 "ARABIC_YEMEN",
956 "ARMENIAN",
957 "ASSAMESE",
958 "AYMARA",
959 "AZERI",
960 "AZERI_CYRILLIC",
961 "AZERI_LATIN",
962 "BASHKIR",
963 "BASQUE",
964 "BELARUSIAN",
965 "BENGALI",
966 "BHUTANI",
967 "BIHARI",
968 "BISLAMA",
969 "BRETON",
970 "BULGARIAN",
971 "BURMESE",
972 "CAMBODIAN",
973 "CATALAN",
974 "CHINESE",
975 "CHINESE_SIMPLIFIED",
976 "CHINESE_TRADITIONAL",
977 "CHINESE_HONGKONG",
978 "CHINESE_MACAU",
979 "CHINESE_SINGAPORE",
980 "CHINESE_TAIWAN",
981 "CORSICAN",
982 "CROATIAN",
983 "CZECH",
984 "DANISH",
985 "DUTCH",
986 "DUTCH_BELGIAN",
987 "ENGLISH",
988 "ENGLISH_UK",
989 "ENGLISH_US",
990 "ENGLISH_AUSTRALIA",
991 "ENGLISH_BELIZE",
992 "ENGLISH_BOTSWANA",
993 "ENGLISH_CANADA",
994 "ENGLISH_CARIBBEAN",
995 "ENGLISH_DENMARK",
996 "ENGLISH_EIRE",
997 "ENGLISH_JAMAICA",
998 "ENGLISH_NEW_ZEALAND",
999 "ENGLISH_PHILIPPINES",
1000 "ENGLISH_SOUTH_AFRICA",
1001 "ENGLISH_TRINIDAD",
1002 "ENGLISH_ZIMBABWE",
1003 "ESPERANTO",
1004 "ESTONIAN",
1005 "FAEROESE",
1006 "FARSI",
1007 "FIJI",
1008 "FINNISH",
1009 "FRENCH",
1010 "FRENCH_BELGIAN",
1011 "FRENCH_CANADIAN",
1012 "FRENCH_LUXEMBOURG",
1013 "FRENCH_MONACO",
1014 "FRENCH_SWISS",
1015 "FRISIAN",
1016 "GALICIAN",
1017 "GEORGIAN",
1018 "GERMAN",
1019 "GERMAN_AUSTRIAN",
1020 "GERMAN_BELGIUM",
1021 "GERMAN_LIECHTENSTEIN",
1022 "GERMAN_LUXEMBOURG",
1023 "GERMAN_SWISS",
1024 "GREEK",
1025 "GREENLANDIC",
1026 "GUARANI",
1027 "GUJARATI",
1028 "HAUSA",
1029 "HEBREW",
1030 "HINDI",
1031 "HUNGARIAN",
1032 "ICELANDIC",
1033 "INDONESIAN",
1034 "INTERLINGUA",
1035 "INTERLINGUE",
1036 "INUKTITUT",
1037 "INUPIAK",
1038 "IRISH",
1039 "ITALIAN",
1040 "ITALIAN_SWISS",
1041 "JAPANESE",
1042 "JAVANESE",
1043 "KANNADA",
1044 "KASHMIRI",
1045 "KASHMIRI_INDIA",
1046 "KAZAKH",
1047 "KERNEWEK",
1048 "KINYARWANDA",
1049 "KIRGHIZ",
1050 "KIRUNDI",
1051 "KONKANI",
1052 "KOREAN",
1053 "KURDISH",
1054 "LAOTHIAN",
1055 "LATIN",
1056 "LATVIAN",
1057 "LINGALA",
1058 "LITHUANIAN",
1059 "MACEDONIAN",
1060 "MALAGASY",
1061 "MALAY",
1062 "MALAYALAM",
1063 "MALAY_BRUNEI_DARUSSALAM",
1064 "MALAY_MALAYSIA",
1065 "MALTESE",
1066 "MANIPURI",
1067 "MAORI",
1068 "MARATHI",
1069 "MOLDAVIAN",
1070 "MONGOLIAN",
1071 "NAURU",
1072 "NEPALI",
1073 "NEPALI_INDIA",
1074 "NORWEGIAN_BOKMAL",
1075 "NORWEGIAN_NYNORSK",
1076 "OCCITAN",
1077 "ORIYA",
1078 "OROMO",
1079 "PASHTO",
1080 "POLISH",
1081 "PORTUGUESE",
1082 "PORTUGUESE_BRAZILIAN",
1083 "PUNJABI",
1084 "QUECHUA",
1085 "RHAETO_ROMANCE",
1086 "ROMANIAN",
1087 "RUSSIAN",
1088 "RUSSIAN_UKRAINE",
1089 "SAMOAN",
1090 "SANGHO",
1091 "SANSKRIT",
1092 "SCOTS_GAELIC",
1093 "SERBIAN",
1094 "SERBIAN_CYRILLIC",
1095 "SERBIAN_LATIN",
1096 "SERBO_CROATIAN",
1097 "SESOTHO",
1098 "SETSWANA",
1099 "SHONA",
1100 "SINDHI",
1101 "SINHALESE",
1102 "SISWATI",
1103 "SLOVAK",
1104 "SLOVENIAN",
1105 "SOMALI",
1106 "SPANISH",
1107 "SPANISH_ARGENTINA",
1108 "SPANISH_BOLIVIA",
1109 "SPANISH_CHILE",
1110 "SPANISH_COLOMBIA",
1111 "SPANISH_COSTA_RICA",
1112 "SPANISH_DOMINICAN_REPUBLIC",
1113 "SPANISH_ECUADOR",
1114 "SPANISH_EL_SALVADOR",
1115 "SPANISH_GUATEMALA",
1116 "SPANISH_HONDURAS",
1117 "SPANISH_MEXICAN",
1118 "SPANISH_MODERN",
1119 "SPANISH_NICARAGUA",
1120 "SPANISH_PANAMA",
1121 "SPANISH_PARAGUAY",
1122 "SPANISH_PERU",
1123 "SPANISH_PUERTO_RICO",
1124 "SPANISH_URUGUAY",
1125 "SPANISH_US",
1126 "SPANISH_VENEZUELA",
1127 "SUNDANESE",
1128 "SWAHILI",
1129 "SWEDISH",
1130 "SWEDISH_FINLAND",
1131 "TAGALOG",
1132 "TAJIK",
1133 "TAMIL",
1134 "TATAR",
1135 "TELUGU",
1136 "THAI",
1137 "TIBETAN",
1138 "TIGRINYA",
1139 "TONGA",
1140 "TSONGA",
1141 "TURKISH",
1142 "TURKMEN",
1143 "TWI",
1144 "UIGHUR",
1145 "UKRAINIAN",
1146 "URDU",
1147 "URDU_INDIA",
1148 "URDU_PAKISTAN",
1149 "UZBEK",
1150 "UZBEK_CYRILLIC",
1151 "UZBEK_LATIN",
1152 "VIETNAMESE",
1153 "VOLAPUK",
1154 "WELSH",
1155 "WOLOF",
1156 "XHOSA",
1157 "YIDDISH",
1158 "YORUBA",
1159 "ZHUANG",
1160 "ZULU",
1161 };
1162
1163 if ( (size_t)lang < WXSIZEOF(languageNames) )
1164 return languageNames[lang];
1165 else
1166 return "INVALID";
1167 }
1168
1169 static void TestDefaultLang()
1170 {
1171 puts("*** Testing wxLocale::GetSystemLanguage ***");
1172
1173 static const wxChar *langStrings[] =
1174 {
1175 NULL, // system default
1176 _T("C"),
1177 _T("fr"),
1178 _T("fr_FR"),
1179 _T("en"),
1180 _T("en_GB"),
1181 _T("en_US"),
1182 _T("de_DE.iso88591"),
1183 _T("german"),
1184 _T("?"), // invalid lang spec
1185 _T("klingonese"), // I bet on some systems it does exist...
1186 };
1187
1188 wxPrintf(_T("The default system encoding is %s (%d)\n"),
1189 wxLocale::GetSystemEncodingName().c_str(),
1190 wxLocale::GetSystemEncoding());
1191
1192 for ( size_t n = 0; n < WXSIZEOF(langStrings); n++ )
1193 {
1194 const char *langStr = langStrings[n];
1195 if ( langStr )
1196 {
1197 // FIXME: this doesn't do anything at all under Windows, we need
1198 // to create a new wxLocale!
1199 wxSetEnv(_T("LC_ALL"), langStr);
1200 }
1201
1202 int lang = gs_localeDefault.GetSystemLanguage();
1203 printf("Locale for '%s' is %s.\n",
1204 langStr ? langStr : "system default", GetLangName(lang));
1205 }
1206 }
1207
1208 #endif // TEST_LOCALE
1209
1210 // ----------------------------------------------------------------------------
1211 // MIME types
1212 // ----------------------------------------------------------------------------
1213
1214 #ifdef TEST_MIME
1215
1216 #include <wx/mimetype.h>
1217
1218 static void TestMimeEnum()
1219 {
1220 wxPuts(_T("*** Testing wxMimeTypesManager::EnumAllFileTypes() ***\n"));
1221
1222 wxArrayString mimetypes;
1223
1224 size_t count = wxTheMimeTypesManager->EnumAllFileTypes(mimetypes);
1225
1226 printf("*** All %u known filetypes: ***\n", count);
1227
1228 wxArrayString exts;
1229 wxString desc;
1230
1231 for ( size_t n = 0; n < count; n++ )
1232 {
1233 wxFileType *filetype =
1234 wxTheMimeTypesManager->GetFileTypeFromMimeType(mimetypes[n]);
1235 if ( !filetype )
1236 {
1237 printf("nothing known about the filetype '%s'!\n",
1238 mimetypes[n].c_str());
1239 continue;
1240 }
1241
1242 filetype->GetDescription(&desc);
1243 filetype->GetExtensions(exts);
1244
1245 filetype->GetIcon(NULL);
1246
1247 wxString extsAll;
1248 for ( size_t e = 0; e < exts.GetCount(); e++ )
1249 {
1250 if ( e > 0 )
1251 extsAll << _T(", ");
1252 extsAll += exts[e];
1253 }
1254
1255 printf("\t%s: %s (%s)\n",
1256 mimetypes[n].c_str(), desc.c_str(), extsAll.c_str());
1257 }
1258
1259 puts("");
1260 }
1261
1262 static void TestMimeOverride()
1263 {
1264 wxPuts(_T("*** Testing wxMimeTypesManager additional files loading ***\n"));
1265
1266 static const wxChar *mailcap = _T("/tmp/mailcap");
1267 static const wxChar *mimetypes = _T("/tmp/mime.types");
1268
1269 if ( wxFile::Exists(mailcap) )
1270 wxPrintf(_T("Loading mailcap from '%s': %s\n"),
1271 mailcap,
1272 wxTheMimeTypesManager->ReadMailcap(mailcap) ? _T("ok") : _T("ERROR"));
1273 else
1274 wxPrintf(_T("WARN: mailcap file '%s' doesn't exist, not loaded.\n"),
1275 mailcap);
1276
1277 if ( wxFile::Exists(mimetypes) )
1278 wxPrintf(_T("Loading mime.types from '%s': %s\n"),
1279 mimetypes,
1280 wxTheMimeTypesManager->ReadMimeTypes(mimetypes) ? _T("ok") : _T("ERROR"));
1281 else
1282 wxPrintf(_T("WARN: mime.types file '%s' doesn't exist, not loaded.\n"),
1283 mimetypes);
1284
1285 puts("");
1286 }
1287
1288 static void TestMimeFilename()
1289 {
1290 wxPuts(_T("*** Testing MIME type from filename query ***\n"));
1291
1292 static const wxChar *filenames[] =
1293 {
1294 _T("readme.txt"),
1295 _T("document.pdf"),
1296 _T("image.gif"),
1297 };
1298
1299 for ( size_t n = 0; n < WXSIZEOF(filenames); n++ )
1300 {
1301 const wxString fname = filenames[n];
1302 wxString ext = fname.AfterLast(_T('.'));
1303 wxFileType *ft = wxTheMimeTypesManager->GetFileTypeFromExtension(ext);
1304 if ( !ft )
1305 {
1306 wxPrintf(_T("WARNING: extension '%s' is unknown.\n"), ext.c_str());
1307 }
1308 else
1309 {
1310 wxString desc;
1311 if ( !ft->GetDescription(&desc) )
1312 desc = _T("<no description>");
1313
1314 wxString cmd;
1315 if ( !ft->GetOpenCommand(&cmd,
1316 wxFileType::MessageParameters(fname, _T(""))) )
1317 cmd = _T("<no command available>");
1318
1319 wxPrintf(_T("To open %s (%s) do '%s'.\n"),
1320 fname.c_str(), desc.c_str(), cmd.c_str());
1321
1322 delete ft;
1323 }
1324 }
1325
1326 puts("");
1327 }
1328
1329 static void TestMimeAssociate()
1330 {
1331 wxPuts(_T("*** Testing creation of filetype association ***\n"));
1332
1333 wxFileTypeInfo ftInfo(
1334 _T("application/x-xyz"),
1335 _T("xyzview '%s'"), // open cmd
1336 _T(""), // print cmd
1337 _T("XYZ File") // description
1338 _T(".xyz"), // extensions
1339 NULL // end of extensions
1340 );
1341 ftInfo.SetShortDesc(_T("XYZFile")); // used under Win32 only
1342
1343 wxFileType *ft = wxTheMimeTypesManager->Associate(ftInfo);
1344 if ( !ft )
1345 {
1346 wxPuts(_T("ERROR: failed to create association!"));
1347 }
1348 else
1349 {
1350 // TODO: read it back
1351 delete ft;
1352 }
1353
1354 puts("");
1355 }
1356
1357 #endif // TEST_MIME
1358
1359 // ----------------------------------------------------------------------------
1360 // misc information functions
1361 // ----------------------------------------------------------------------------
1362
1363 #ifdef TEST_INFO_FUNCTIONS
1364
1365 #include <wx/utils.h>
1366
1367 static void TestOsInfo()
1368 {
1369 puts("*** Testing OS info functions ***\n");
1370
1371 int major, minor;
1372 wxGetOsVersion(&major, &minor);
1373 printf("Running under: %s, version %d.%d\n",
1374 wxGetOsDescription().c_str(), major, minor);
1375
1376 printf("%ld free bytes of memory left.\n", wxGetFreeMemory());
1377
1378 printf("Host name is %s (%s).\n",
1379 wxGetHostName().c_str(), wxGetFullHostName().c_str());
1380
1381 puts("");
1382 }
1383
1384 static void TestUserInfo()
1385 {
1386 puts("*** Testing user info functions ***\n");
1387
1388 printf("User id is:\t%s\n", wxGetUserId().c_str());
1389 printf("User name is:\t%s\n", wxGetUserName().c_str());
1390 printf("Home dir is:\t%s\n", wxGetHomeDir().c_str());
1391 printf("Email address:\t%s\n", wxGetEmailAddress().c_str());
1392
1393 puts("");
1394 }
1395
1396 #endif // TEST_INFO_FUNCTIONS
1397
1398 // ----------------------------------------------------------------------------
1399 // long long
1400 // ----------------------------------------------------------------------------
1401
1402 #ifdef TEST_LONGLONG
1403
1404 #include <wx/longlong.h>
1405 #include <wx/timer.h>
1406
1407 // make a 64 bit number from 4 16 bit ones
1408 #define MAKE_LL(x1, x2, x3, x4) wxLongLong((x1 << 16) | x2, (x3 << 16) | x3)
1409
1410 // get a random 64 bit number
1411 #define RAND_LL() MAKE_LL(rand(), rand(), rand(), rand())
1412
1413 #if wxUSE_LONGLONG_WX
1414 inline bool operator==(const wxLongLongWx& a, const wxLongLongNative& b)
1415 { return a.GetHi() == b.GetHi() && a.GetLo() == b.GetLo(); }
1416 inline bool operator==(const wxLongLongNative& a, const wxLongLongWx& b)
1417 { return a.GetHi() == b.GetHi() && a.GetLo() == b.GetLo(); }
1418 #endif // wxUSE_LONGLONG_WX
1419
1420 static void TestSpeed()
1421 {
1422 static const long max = 100000000;
1423 long n;
1424
1425 {
1426 wxStopWatch sw;
1427
1428 long l = 0;
1429 for ( n = 0; n < max; n++ )
1430 {
1431 l += n;
1432 }
1433
1434 printf("Summing longs took %ld milliseconds.\n", sw.Time());
1435 }
1436
1437 #if wxUSE_LONGLONG_NATIVE
1438 {
1439 wxStopWatch sw;
1440
1441 wxLongLong_t l = 0;
1442 for ( n = 0; n < max; n++ )
1443 {
1444 l += n;
1445 }
1446
1447 printf("Summing wxLongLong_t took %ld milliseconds.\n", sw.Time());
1448 }
1449 #endif // wxUSE_LONGLONG_NATIVE
1450
1451 {
1452 wxStopWatch sw;
1453
1454 wxLongLong l;
1455 for ( n = 0; n < max; n++ )
1456 {
1457 l += n;
1458 }
1459
1460 printf("Summing wxLongLongs took %ld milliseconds.\n", sw.Time());
1461 }
1462 }
1463
1464 static void TestLongLongConversion()
1465 {
1466 puts("*** Testing wxLongLong conversions ***\n");
1467
1468 wxLongLong a;
1469 size_t nTested = 0;
1470 for ( size_t n = 0; n < 100000; n++ )
1471 {
1472 a = RAND_LL();
1473
1474 #if wxUSE_LONGLONG_NATIVE
1475 wxLongLongNative b(a.GetHi(), a.GetLo());
1476
1477 wxASSERT_MSG( a == b, "conversions failure" );
1478 #else
1479 puts("Can't do it without native long long type, test skipped.");
1480
1481 return;
1482 #endif // wxUSE_LONGLONG_NATIVE
1483
1484 if ( !(nTested % 1000) )
1485 {
1486 putchar('.');
1487 fflush(stdout);
1488 }
1489
1490 nTested++;
1491 }
1492
1493 puts(" done!");
1494 }
1495
1496 static void TestMultiplication()
1497 {
1498 puts("*** Testing wxLongLong multiplication ***\n");
1499
1500 wxLongLong a, b;
1501 size_t nTested = 0;
1502 for ( size_t n = 0; n < 100000; n++ )
1503 {
1504 a = RAND_LL();
1505 b = RAND_LL();
1506
1507 #if wxUSE_LONGLONG_NATIVE
1508 wxLongLongNative aa(a.GetHi(), a.GetLo());
1509 wxLongLongNative bb(b.GetHi(), b.GetLo());
1510
1511 wxASSERT_MSG( a*b == aa*bb, "multiplication failure" );
1512 #else // !wxUSE_LONGLONG_NATIVE
1513 puts("Can't do it without native long long type, test skipped.");
1514
1515 return;
1516 #endif // wxUSE_LONGLONG_NATIVE
1517
1518 if ( !(nTested % 1000) )
1519 {
1520 putchar('.');
1521 fflush(stdout);
1522 }
1523
1524 nTested++;
1525 }
1526
1527 puts(" done!");
1528 }
1529
1530 static void TestDivision()
1531 {
1532 puts("*** Testing wxLongLong division ***\n");
1533
1534 wxLongLong q, r;
1535 size_t nTested = 0;
1536 for ( size_t n = 0; n < 100000; n++ )
1537 {
1538 // get a random wxLongLong (shifting by 12 the MSB ensures that the
1539 // multiplication will not overflow)
1540 wxLongLong ll = MAKE_LL((rand() >> 12), rand(), rand(), rand());
1541
1542 // get a random long (not wxLongLong for now) to divide it with
1543 long l = rand();
1544 q = ll / l;
1545 r = ll % l;
1546
1547 #if wxUSE_LONGLONG_NATIVE
1548 wxLongLongNative m(ll.GetHi(), ll.GetLo());
1549
1550 wxLongLongNative p = m / l, s = m % l;
1551 wxASSERT_MSG( q == p && r == s, "division failure" );
1552 #else // !wxUSE_LONGLONG_NATIVE
1553 // verify the result
1554 wxASSERT_MSG( ll == q*l + r, "division failure" );
1555 #endif // wxUSE_LONGLONG_NATIVE
1556
1557 if ( !(nTested % 1000) )
1558 {
1559 putchar('.');
1560 fflush(stdout);
1561 }
1562
1563 nTested++;
1564 }
1565
1566 puts(" done!");
1567 }
1568
1569 static void TestAddition()
1570 {
1571 puts("*** Testing wxLongLong addition ***\n");
1572
1573 wxLongLong a, b, c;
1574 size_t nTested = 0;
1575 for ( size_t n = 0; n < 100000; n++ )
1576 {
1577 a = RAND_LL();
1578 b = RAND_LL();
1579 c = a + b;
1580
1581 #if wxUSE_LONGLONG_NATIVE
1582 wxASSERT_MSG( c == wxLongLongNative(a.GetHi(), a.GetLo()) +
1583 wxLongLongNative(b.GetHi(), b.GetLo()),
1584 "addition failure" );
1585 #else // !wxUSE_LONGLONG_NATIVE
1586 wxASSERT_MSG( c - b == a, "addition failure" );
1587 #endif // wxUSE_LONGLONG_NATIVE
1588
1589 if ( !(nTested % 1000) )
1590 {
1591 putchar('.');
1592 fflush(stdout);
1593 }
1594
1595 nTested++;
1596 }
1597
1598 puts(" done!");
1599 }
1600
1601 static void TestBitOperations()
1602 {
1603 puts("*** Testing wxLongLong bit operation ***\n");
1604
1605 wxLongLong ll;
1606 size_t nTested = 0;
1607 for ( size_t n = 0; n < 100000; n++ )
1608 {
1609 ll = RAND_LL();
1610
1611 #if wxUSE_LONGLONG_NATIVE
1612 for ( size_t n = 0; n < 33; n++ )
1613 {
1614 }
1615 #else // !wxUSE_LONGLONG_NATIVE
1616 puts("Can't do it without native long long type, test skipped.");
1617
1618 return;
1619 #endif // wxUSE_LONGLONG_NATIVE
1620
1621 if ( !(nTested % 1000) )
1622 {
1623 putchar('.');
1624 fflush(stdout);
1625 }
1626
1627 nTested++;
1628 }
1629
1630 puts(" done!");
1631 }
1632
1633 static void TestLongLongComparison()
1634 {
1635 #if wxUSE_LONGLONG_WX
1636 puts("*** Testing wxLongLong comparison ***\n");
1637
1638 static const long testLongs[] =
1639 {
1640 0,
1641 1,
1642 -1,
1643 LONG_MAX,
1644 LONG_MIN,
1645 0x1234,
1646 -0x1234
1647 };
1648
1649 static const long ls[2] =
1650 {
1651 0x1234,
1652 -0x1234,
1653 };
1654
1655 wxLongLongWx lls[2];
1656 lls[0] = ls[0];
1657 lls[1] = ls[1];
1658
1659 for ( size_t n = 0; n < WXSIZEOF(testLongs); n++ )
1660 {
1661 bool res;
1662
1663 for ( size_t m = 0; m < WXSIZEOF(lls); m++ )
1664 {
1665 res = lls[m] > testLongs[n];
1666 printf("0x%lx > 0x%lx is %s (%s)\n",
1667 ls[m], testLongs[n], res ? "true" : "false",
1668 res == (ls[m] > testLongs[n]) ? "ok" : "ERROR");
1669
1670 res = lls[m] < testLongs[n];
1671 printf("0x%lx < 0x%lx is %s (%s)\n",
1672 ls[m], testLongs[n], res ? "true" : "false",
1673 res == (ls[m] < testLongs[n]) ? "ok" : "ERROR");
1674
1675 res = lls[m] == testLongs[n];
1676 printf("0x%lx == 0x%lx is %s (%s)\n",
1677 ls[m], testLongs[n], res ? "true" : "false",
1678 res == (ls[m] == testLongs[n]) ? "ok" : "ERROR");
1679 }
1680 }
1681 #endif // wxUSE_LONGLONG_WX
1682 }
1683
1684 #undef MAKE_LL
1685 #undef RAND_LL
1686
1687 #endif // TEST_LONGLONG
1688
1689 // ----------------------------------------------------------------------------
1690 // path list
1691 // ----------------------------------------------------------------------------
1692
1693 #ifdef TEST_PATHLIST
1694
1695 static void TestPathList()
1696 {
1697 puts("*** Testing wxPathList ***\n");
1698
1699 wxPathList pathlist;
1700 pathlist.AddEnvList("PATH");
1701 wxString path = pathlist.FindValidPath("ls");
1702 if ( path.empty() )
1703 {
1704 printf("ERROR: command not found in the path.\n");
1705 }
1706 else
1707 {
1708 printf("Command found in the path as '%s'.\n", path.c_str());
1709 }
1710 }
1711
1712 #endif // TEST_PATHLIST
1713
1714 // ----------------------------------------------------------------------------
1715 // regular expressions
1716 // ----------------------------------------------------------------------------
1717
1718 #ifdef TEST_REGEX
1719
1720 #include <wx/regex.h>
1721
1722 static void TestRegExCompile()
1723 {
1724 wxPuts(_T("*** Testing RE compilation ***\n"));
1725
1726 static struct RegExCompTestData
1727 {
1728 const wxChar *pattern;
1729 bool correct;
1730 } regExCompTestData[] =
1731 {
1732 { _T("foo"), TRUE },
1733 { _T("foo("), FALSE },
1734 { _T("foo(bar"), FALSE },
1735 { _T("foo(bar)"), TRUE },
1736 { _T("foo["), FALSE },
1737 { _T("foo[bar"), FALSE },
1738 { _T("foo[bar]"), TRUE },
1739 { _T("foo{"), TRUE },
1740 { _T("foo{1"), FALSE },
1741 { _T("foo{bar"), TRUE },
1742 { _T("foo{1}"), TRUE },
1743 { _T("foo{1,2}"), TRUE },
1744 { _T("foo{bar}"), TRUE },
1745 { _T("foo*"), TRUE },
1746 { _T("foo**"), FALSE },
1747 { _T("foo+"), TRUE },
1748 { _T("foo++"), FALSE },
1749 { _T("foo?"), TRUE },
1750 { _T("foo??"), FALSE },
1751 { _T("foo?+"), FALSE },
1752 };
1753
1754 wxRegEx re;
1755 for ( size_t n = 0; n < WXSIZEOF(regExCompTestData); n++ )
1756 {
1757 const RegExCompTestData& data = regExCompTestData[n];
1758 bool ok = re.Compile(data.pattern);
1759
1760 wxPrintf(_T("'%s' is %sa valid RE (%s)\n"),
1761 data.pattern,
1762 ok ? _T("") : _T("not "),
1763 ok == data.correct ? _T("ok") : _T("ERROR"));
1764 }
1765 }
1766
1767 static void TestRegExMatch()
1768 {
1769 wxPuts(_T("*** Testing RE matching ***\n"));
1770
1771 static struct RegExMatchTestData
1772 {
1773 const wxChar *pattern;
1774 const wxChar *text;
1775 bool correct;
1776 } regExMatchTestData[] =
1777 {
1778 { _T("foo"), _T("bar"), FALSE },
1779 { _T("foo"), _T("foobar"), TRUE },
1780 { _T("^foo"), _T("foobar"), TRUE },
1781 { _T("^foo"), _T("barfoo"), FALSE },
1782 { _T("bar$"), _T("barbar"), TRUE },
1783 { _T("bar$"), _T("barbar "), FALSE },
1784 };
1785
1786 for ( size_t n = 0; n < WXSIZEOF(regExMatchTestData); n++ )
1787 {
1788 const RegExMatchTestData& data = regExMatchTestData[n];
1789
1790 wxRegEx re(data.pattern);
1791 bool ok = re.Matches(data.text);
1792
1793 wxPrintf(_T("'%s' %s %s (%s)\n"),
1794 data.pattern,
1795 ok ? _T("matches") : _T("doesn't match"),
1796 data.text,
1797 ok == data.correct ? _T("ok") : _T("ERROR"));
1798 }
1799 }
1800
1801 static void TestRegExSubmatch()
1802 {
1803 wxPuts(_T("*** Testing RE subexpressions ***\n"));
1804
1805 wxRegEx re(_T("([[:alpha:]]+) ([[:alpha:]]+) ([[:digit:]]+).*([[:digit:]]+)$"));
1806 if ( !re.IsValid() )
1807 {
1808 wxPuts(_T("ERROR: compilation failed."));
1809 return;
1810 }
1811
1812 wxString text = _T("Fri Jul 13 18:37:52 CEST 2001");
1813
1814 if ( !re.Matches(text) )
1815 {
1816 wxPuts(_T("ERROR: match expected."));
1817 }
1818 else
1819 {
1820 wxPrintf(_T("Entire match: %s\n"), re.GetMatch(text).c_str());
1821
1822 wxPrintf(_T("Date: %s/%s/%s, wday: %s\n"),
1823 re.GetMatch(text, 3).c_str(),
1824 re.GetMatch(text, 2).c_str(),
1825 re.GetMatch(text, 4).c_str(),
1826 re.GetMatch(text, 1).c_str());
1827 }
1828 }
1829
1830 static void TestRegExReplacement()
1831 {
1832 wxPuts(_T("*** Testing RE replacement ***"));
1833
1834 static struct RegExReplTestData
1835 {
1836 const wxChar *text;
1837 const wxChar *repl;
1838 const wxChar *result;
1839 size_t count;
1840 } regExReplTestData[] =
1841 {
1842 { _T("foo123"), _T("bar"), _T("bar"), 1 },
1843 { _T("foo123"), _T("\\2\\1"), _T("123foo"), 1 },
1844 { _T("foo_123"), _T("\\2\\1"), _T("123foo"), 1 },
1845 { _T("123foo"), _T("bar"), _T("123foo"), 0 },
1846 { _T("123foo456foo"), _T("&&"), _T("123foo456foo456foo"), 1 },
1847 { _T("foo123foo123"), _T("bar"), _T("barbar"), 2 },
1848 { _T("foo123_foo456_foo789"), _T("bar"), _T("bar_bar_bar"), 3 },
1849 };
1850
1851 const wxChar *pattern = _T("([a-z]+)[^0-9]*([0-9]+)");
1852 wxRegEx re = pattern;
1853
1854 wxPrintf(_T("Using pattern '%s' for replacement.\n"), pattern);
1855
1856 for ( size_t n = 0; n < WXSIZEOF(regExReplTestData); n++ )
1857 {
1858 const RegExReplTestData& data = regExReplTestData[n];
1859
1860 wxString text = data.text;
1861 size_t nRepl = re.Replace(&text, data.repl);
1862
1863 wxPrintf(_T("%s =~ s/RE/%s/g: %u match%s, result = '%s' ("),
1864 data.text, data.repl,
1865 nRepl, nRepl == 1 ? _T("") : _T("es"),
1866 text.c_str());
1867 if ( text == data.result && nRepl == data.count )
1868 {
1869 wxPuts(_T("ok)"));
1870 }
1871 else
1872 {
1873 wxPrintf(_T("ERROR: should be %u and '%s')\n"),
1874 data.count, data.result);
1875 }
1876 }
1877 }
1878
1879 static void TestRegExInteractive()
1880 {
1881 wxPuts(_T("*** Testing RE interactively ***"));
1882
1883 for ( ;; )
1884 {
1885 char pattern[128];
1886 printf("\nEnter a pattern: ");
1887 if ( !fgets(pattern, WXSIZEOF(pattern), stdin) )
1888 break;
1889
1890 // kill the last '\n'
1891 pattern[strlen(pattern) - 1] = 0;
1892
1893 wxRegEx re;
1894 if ( !re.Compile(pattern) )
1895 {
1896 continue;
1897 }
1898
1899 char text[128];
1900 for ( ;; )
1901 {
1902 printf("Enter text to match: ");
1903 if ( !fgets(text, WXSIZEOF(text), stdin) )
1904 break;
1905
1906 // kill the last '\n'
1907 text[strlen(text) - 1] = 0;
1908
1909 if ( !re.Matches(text) )
1910 {
1911 printf("No match.\n");
1912 }
1913 else
1914 {
1915 printf("Pattern matches at '%s'\n", re.GetMatch(text).c_str());
1916
1917 size_t start, len;
1918 for ( size_t n = 1; ; n++ )
1919 {
1920 if ( !re.GetMatch(&start, &len, n) )
1921 {
1922 break;
1923 }
1924
1925 printf("Subexpr %u matched '%s'\n",
1926 n, wxString(text + start, len).c_str());
1927 }
1928 }
1929 }
1930 }
1931 }
1932
1933 #endif // TEST_REGEX
1934
1935 // ----------------------------------------------------------------------------
1936 // registry and related stuff
1937 // ----------------------------------------------------------------------------
1938
1939 // this is for MSW only
1940 #ifndef __WXMSW__
1941 #undef TEST_REGCONF
1942 #undef TEST_REGISTRY
1943 #endif
1944
1945 #ifdef TEST_REGCONF
1946
1947 #include <wx/confbase.h>
1948 #include <wx/msw/regconf.h>
1949
1950 static void TestRegConfWrite()
1951 {
1952 wxRegConfig regconf(_T("console"), _T("wxwindows"));
1953 regconf.Write(_T("Hello"), wxString(_T("world")));
1954 }
1955
1956 #endif // TEST_REGCONF
1957
1958 #ifdef TEST_REGISTRY
1959
1960 #include <wx/msw/registry.h>
1961
1962 // I chose this one because I liked its name, but it probably only exists under
1963 // NT
1964 static const wxChar *TESTKEY =
1965 _T("HKEY_LOCAL_MACHINE\\SYSTEM\\ControlSet001\\Control\\CrashControl");
1966
1967 static void TestRegistryRead()
1968 {
1969 puts("*** testing registry reading ***");
1970
1971 wxRegKey key(TESTKEY);
1972 printf("The test key name is '%s'.\n", key.GetName().c_str());
1973 if ( !key.Open() )
1974 {
1975 puts("ERROR: test key can't be opened, aborting test.");
1976
1977 return;
1978 }
1979
1980 size_t nSubKeys, nValues;
1981 if ( key.GetKeyInfo(&nSubKeys, NULL, &nValues, NULL) )
1982 {
1983 printf("It has %u subkeys and %u values.\n", nSubKeys, nValues);
1984 }
1985
1986 printf("Enumerating values:\n");
1987
1988 long dummy;
1989 wxString value;
1990 bool cont = key.GetFirstValue(value, dummy);
1991 while ( cont )
1992 {
1993 printf("Value '%s': type ", value.c_str());
1994 switch ( key.GetValueType(value) )
1995 {
1996 case wxRegKey::Type_None: printf("ERROR (none)"); break;
1997 case wxRegKey::Type_String: printf("SZ"); break;
1998 case wxRegKey::Type_Expand_String: printf("EXPAND_SZ"); break;
1999 case wxRegKey::Type_Binary: printf("BINARY"); break;
2000 case wxRegKey::Type_Dword: printf("DWORD"); break;
2001 case wxRegKey::Type_Multi_String: printf("MULTI_SZ"); break;
2002 default: printf("other (unknown)"); break;
2003 }
2004
2005 printf(", value = ");
2006 if ( key.IsNumericValue(value) )
2007 {
2008 long val;
2009 key.QueryValue(value, &val);
2010 printf("%ld", val);
2011 }
2012 else // string
2013 {
2014 wxString val;
2015 key.QueryValue(value, val);
2016 printf("'%s'", val.c_str());
2017
2018 key.QueryRawValue(value, val);
2019 printf(" (raw value '%s')", val.c_str());
2020 }
2021
2022 putchar('\n');
2023
2024 cont = key.GetNextValue(value, dummy);
2025 }
2026 }
2027
2028 static void TestRegistryAssociation()
2029 {
2030 /*
2031 The second call to deleteself genertaes an error message, with a
2032 messagebox saying .flo is crucial to system operation, while the .ddf
2033 call also fails, but with no error message
2034 */
2035
2036 wxRegKey key;
2037
2038 key.SetName("HKEY_CLASSES_ROOT\\.ddf" );
2039 key.Create();
2040 key = "ddxf_auto_file" ;
2041 key.SetName("HKEY_CLASSES_ROOT\\.flo" );
2042 key.Create();
2043 key = "ddxf_auto_file" ;
2044 key.SetName("HKEY_CLASSES_ROOT\\ddxf_auto_file\\DefaultIcon");
2045 key.Create();
2046 key = "program,0" ;
2047 key.SetName("HKEY_CLASSES_ROOT\\ddxf_auto_file\\shell\\open\\command");
2048 key.Create();
2049 key = "program \"%1\"" ;
2050
2051 key.SetName("HKEY_CLASSES_ROOT\\.ddf" );
2052 key.DeleteSelf();
2053 key.SetName("HKEY_CLASSES_ROOT\\.flo" );
2054 key.DeleteSelf();
2055 key.SetName("HKEY_CLASSES_ROOT\\ddxf_auto_file\\DefaultIcon");
2056 key.DeleteSelf();
2057 key.SetName("HKEY_CLASSES_ROOT\\ddxf_auto_file\\shell\\open\\command");
2058 key.DeleteSelf();
2059 }
2060
2061 #endif // TEST_REGISTRY
2062
2063 // ----------------------------------------------------------------------------
2064 // sockets
2065 // ----------------------------------------------------------------------------
2066
2067 #ifdef TEST_SOCKETS
2068
2069 #include <wx/socket.h>
2070 #include <wx/protocol/protocol.h>
2071 #include <wx/protocol/http.h>
2072
2073 static void TestSocketServer()
2074 {
2075 puts("*** Testing wxSocketServer ***\n");
2076
2077 static const int PORT = 3000;
2078
2079 wxIPV4address addr;
2080 addr.Service(PORT);
2081
2082 wxSocketServer *server = new wxSocketServer(addr);
2083 if ( !server->Ok() )
2084 {
2085 puts("ERROR: failed to bind");
2086
2087 return;
2088 }
2089
2090 for ( ;; )
2091 {
2092 printf("Server: waiting for connection on port %d...\n", PORT);
2093
2094 wxSocketBase *socket = server->Accept();
2095 if ( !socket )
2096 {
2097 puts("ERROR: wxSocketServer::Accept() failed.");
2098 break;
2099 }
2100
2101 puts("Server: got a client.");
2102
2103 server->SetTimeout(60); // 1 min
2104
2105 while ( socket->IsConnected() )
2106 {
2107 wxString s;
2108 char ch = '\0';
2109 for ( ;; )
2110 {
2111 if ( socket->Read(&ch, sizeof(ch)).Error() )
2112 {
2113 // don't log error if the client just close the connection
2114 if ( socket->IsConnected() )
2115 {
2116 puts("ERROR: in wxSocket::Read.");
2117 }
2118
2119 break;
2120 }
2121
2122 if ( ch == '\r' )
2123 continue;
2124
2125 if ( ch == '\n' )
2126 break;
2127
2128 s += ch;
2129 }
2130
2131 if ( ch != '\n' )
2132 {
2133 break;
2134 }
2135
2136 printf("Server: got '%s'.\n", s.c_str());
2137 if ( s == _T("bye") )
2138 {
2139 delete socket;
2140
2141 break;
2142 }
2143
2144 socket->Write(s.MakeUpper().c_str(), s.length());
2145 socket->Write("\r\n", 2);
2146 printf("Server: wrote '%s'.\n", s.c_str());
2147 }
2148
2149 puts("Server: lost a client.");
2150
2151 socket->Destroy();
2152 }
2153
2154 // same as "delete server" but is consistent with GUI programs
2155 server->Destroy();
2156 }
2157
2158 static void TestSocketClient()
2159 {
2160 puts("*** Testing wxSocketClient ***\n");
2161
2162 static const char *hostname = "www.wxwindows.org";
2163
2164 wxIPV4address addr;
2165 addr.Hostname(hostname);
2166 addr.Service(80);
2167
2168 printf("--- Attempting to connect to %s:80...\n", hostname);
2169
2170 wxSocketClient client;
2171 if ( !client.Connect(addr) )
2172 {
2173 printf("ERROR: failed to connect to %s\n", hostname);
2174 }
2175 else
2176 {
2177 printf("--- Connected to %s:%u...\n",
2178 addr.Hostname().c_str(), addr.Service());
2179
2180 char buf[8192];
2181
2182 // could use simply "GET" here I suppose
2183 wxString cmdGet =
2184 wxString::Format("GET http://%s/\r\n", hostname);
2185 client.Write(cmdGet, cmdGet.length());
2186 printf("--- Sent command '%s' to the server\n",
2187 MakePrintable(cmdGet).c_str());
2188 client.Read(buf, WXSIZEOF(buf));
2189 printf("--- Server replied:\n%s", buf);
2190 }
2191 }
2192
2193 #endif // TEST_SOCKETS
2194
2195 // ----------------------------------------------------------------------------
2196 // FTP
2197 // ----------------------------------------------------------------------------
2198
2199 #ifdef TEST_FTP
2200
2201 #include <wx/protocol/ftp.h>
2202
2203 static wxFTP ftp;
2204
2205 #define FTP_ANONYMOUS
2206
2207 #ifdef FTP_ANONYMOUS
2208 static const char *directory = "/pub";
2209 static const char *filename = "welcome.msg";
2210 #else
2211 static const char *directory = "/etc";
2212 static const char *filename = "issue";
2213 #endif
2214
2215 static bool TestFtpConnect()
2216 {
2217 puts("*** Testing FTP connect ***");
2218
2219 #ifdef FTP_ANONYMOUS
2220 static const char *hostname = "ftp.wxwindows.org";
2221
2222 printf("--- Attempting to connect to %s:21 anonymously...\n", hostname);
2223 #else // !FTP_ANONYMOUS
2224 static const char *hostname = "localhost";
2225
2226 char user[256];
2227 fgets(user, WXSIZEOF(user), stdin);
2228 user[strlen(user) - 1] = '\0'; // chop off '\n'
2229 ftp.SetUser(user);
2230
2231 char password[256];
2232 printf("Password for %s: ", password);
2233 fgets(password, WXSIZEOF(password), stdin);
2234 password[strlen(password) - 1] = '\0'; // chop off '\n'
2235 ftp.SetPassword(password);
2236
2237 printf("--- Attempting to connect to %s:21 as %s...\n", hostname, user);
2238 #endif // FTP_ANONYMOUS/!FTP_ANONYMOUS
2239
2240 if ( !ftp.Connect(hostname) )
2241 {
2242 printf("ERROR: failed to connect to %s\n", hostname);
2243
2244 return FALSE;
2245 }
2246 else
2247 {
2248 printf("--- Connected to %s, current directory is '%s'\n",
2249 hostname, ftp.Pwd().c_str());
2250 }
2251
2252 return TRUE;
2253 }
2254
2255 // test (fixed?) wxFTP bug with wu-ftpd >= 2.6.0?
2256 static void TestFtpWuFtpd()
2257 {
2258 wxFTP ftp;
2259 static const char *hostname = "ftp.eudora.com";
2260 if ( !ftp.Connect(hostname) )
2261 {
2262 printf("ERROR: failed to connect to %s\n", hostname);
2263 }
2264 else
2265 {
2266 static const char *filename = "eudora/pubs/draft-gellens-submit-09.txt";
2267 wxInputStream *in = ftp.GetInputStream(filename);
2268 if ( !in )
2269 {
2270 printf("ERROR: couldn't get input stream for %s\n", filename);
2271 }
2272 else
2273 {
2274 size_t size = in->StreamSize();
2275 printf("Reading file %s (%u bytes)...", filename, size);
2276
2277 char *data = new char[size];
2278 if ( !in->Read(data, size) )
2279 {
2280 puts("ERROR: read error");
2281 }
2282 else
2283 {
2284 printf("Successfully retrieved the file.\n");
2285 }
2286
2287 delete [] data;
2288 delete in;
2289 }
2290 }
2291 }
2292
2293 static void TestFtpList()
2294 {
2295 puts("*** Testing wxFTP file listing ***\n");
2296
2297 // test CWD
2298 if ( !ftp.ChDir(directory) )
2299 {
2300 printf("ERROR: failed to cd to %s\n", directory);
2301 }
2302
2303 printf("Current directory is '%s'\n", ftp.Pwd().c_str());
2304
2305 // test NLIST and LIST
2306 wxArrayString files;
2307 if ( !ftp.GetFilesList(files) )
2308 {
2309 puts("ERROR: failed to get NLIST of files");
2310 }
2311 else
2312 {
2313 printf("Brief list of files under '%s':\n", ftp.Pwd().c_str());
2314 size_t count = files.GetCount();
2315 for ( size_t n = 0; n < count; n++ )
2316 {
2317 printf("\t%s\n", files[n].c_str());
2318 }
2319 puts("End of the file list");
2320 }
2321
2322 if ( !ftp.GetDirList(files) )
2323 {
2324 puts("ERROR: failed to get LIST of files");
2325 }
2326 else
2327 {
2328 printf("Detailed list of files under '%s':\n", ftp.Pwd().c_str());
2329 size_t count = files.GetCount();
2330 for ( size_t n = 0; n < count; n++ )
2331 {
2332 printf("\t%s\n", files[n].c_str());
2333 }
2334 puts("End of the file list");
2335 }
2336
2337 if ( !ftp.ChDir(_T("..")) )
2338 {
2339 puts("ERROR: failed to cd to ..");
2340 }
2341
2342 printf("Current directory is '%s'\n", ftp.Pwd().c_str());
2343 }
2344
2345 static void TestFtpDownload()
2346 {
2347 puts("*** Testing wxFTP download ***\n");
2348
2349 // test RETR
2350 wxInputStream *in = ftp.GetInputStream(filename);
2351 if ( !in )
2352 {
2353 printf("ERROR: couldn't get input stream for %s\n", filename);
2354 }
2355 else
2356 {
2357 size_t size = in->StreamSize();
2358 printf("Reading file %s (%u bytes)...", filename, size);
2359 fflush(stdout);
2360
2361 char *data = new char[size];
2362 if ( !in->Read(data, size) )
2363 {
2364 puts("ERROR: read error");
2365 }
2366 else
2367 {
2368 printf("\nContents of %s:\n%s\n", filename, data);
2369 }
2370
2371 delete [] data;
2372 delete in;
2373 }
2374 }
2375
2376 static void TestFtpFileSize()
2377 {
2378 puts("*** Testing FTP SIZE command ***");
2379
2380 if ( !ftp.ChDir(directory) )
2381 {
2382 printf("ERROR: failed to cd to %s\n", directory);
2383 }
2384
2385 printf("Current directory is '%s'\n", ftp.Pwd().c_str());
2386
2387 if ( ftp.FileExists(filename) )
2388 {
2389 int size = ftp.GetFileSize(filename);
2390 if ( size == -1 )
2391 printf("ERROR: couldn't get size of '%s'\n", filename);
2392 else
2393 printf("Size of '%s' is %d bytes.\n", filename, size);
2394 }
2395 else
2396 {
2397 printf("ERROR: '%s' doesn't exist\n", filename);
2398 }
2399 }
2400
2401 static void TestFtpMisc()
2402 {
2403 puts("*** Testing miscellaneous wxFTP functions ***");
2404
2405 if ( ftp.SendCommand("STAT") != '2' )
2406 {
2407 puts("ERROR: STAT failed");
2408 }
2409 else
2410 {
2411 printf("STAT returned:\n\n%s\n", ftp.GetLastResult().c_str());
2412 }
2413
2414 if ( ftp.SendCommand("HELP SITE") != '2' )
2415 {
2416 puts("ERROR: HELP SITE failed");
2417 }
2418 else
2419 {
2420 printf("The list of site-specific commands:\n\n%s\n",
2421 ftp.GetLastResult().c_str());
2422 }
2423 }
2424
2425 static void TestFtpInteractive()
2426 {
2427 puts("\n*** Interactive wxFTP test ***");
2428
2429 char buf[128];
2430
2431 for ( ;; )
2432 {
2433 printf("Enter FTP command: ");
2434 if ( !fgets(buf, WXSIZEOF(buf), stdin) )
2435 break;
2436
2437 // kill the last '\n'
2438 buf[strlen(buf) - 1] = 0;
2439
2440 // special handling of LIST and NLST as they require data connection
2441 wxString start(buf, 4);
2442 start.MakeUpper();
2443 if ( start == "LIST" || start == "NLST" )
2444 {
2445 wxString wildcard;
2446 if ( strlen(buf) > 4 )
2447 wildcard = buf + 5;
2448
2449 wxArrayString files;
2450 if ( !ftp.GetList(files, wildcard, start == "LIST") )
2451 {
2452 printf("ERROR: failed to get %s of files\n", start.c_str());
2453 }
2454 else
2455 {
2456 printf("--- %s of '%s' under '%s':\n",
2457 start.c_str(), wildcard.c_str(), ftp.Pwd().c_str());
2458 size_t count = files.GetCount();
2459 for ( size_t n = 0; n < count; n++ )
2460 {
2461 printf("\t%s\n", files[n].c_str());
2462 }
2463 puts("--- End of the file list");
2464 }
2465 }
2466 else // !list
2467 {
2468 char ch = ftp.SendCommand(buf);
2469 printf("Command %s", ch ? "succeeded" : "failed");
2470 if ( ch )
2471 {
2472 printf(" (return code %c)", ch);
2473 }
2474
2475 printf(", server reply:\n%s\n\n", ftp.GetLastResult().c_str());
2476 }
2477 }
2478
2479 puts("\n*** done ***");
2480 }
2481
2482 static void TestFtpUpload()
2483 {
2484 puts("*** Testing wxFTP uploading ***\n");
2485
2486 // upload a file
2487 static const char *file1 = "test1";
2488 static const char *file2 = "test2";
2489 wxOutputStream *out = ftp.GetOutputStream(file1);
2490 if ( out )
2491 {
2492 printf("--- Uploading to %s ---\n", file1);
2493 out->Write("First hello", 11);
2494 delete out;
2495 }
2496
2497 // send a command to check the remote file
2498 if ( ftp.SendCommand(wxString("STAT ") + file1) != '2' )
2499 {
2500 printf("ERROR: STAT %s failed\n", file1);
2501 }
2502 else
2503 {
2504 printf("STAT %s returned:\n\n%s\n",
2505 file1, ftp.GetLastResult().c_str());
2506 }
2507
2508 out = ftp.GetOutputStream(file2);
2509 if ( out )
2510 {
2511 printf("--- Uploading to %s ---\n", file1);
2512 out->Write("Second hello", 12);
2513 delete out;
2514 }
2515 }
2516
2517 #endif // TEST_FTP
2518
2519 // ----------------------------------------------------------------------------
2520 // streams
2521 // ----------------------------------------------------------------------------
2522
2523 #ifdef TEST_STREAMS
2524
2525 #include <wx/wfstream.h>
2526 #include <wx/mstream.h>
2527
2528 static void TestFileStream()
2529 {
2530 puts("*** Testing wxFileInputStream ***");
2531
2532 static const wxChar *filename = _T("testdata.fs");
2533 {
2534 wxFileOutputStream fsOut(filename);
2535 fsOut.Write("foo", 3);
2536 }
2537
2538 wxFileInputStream fsIn(filename);
2539 printf("File stream size: %u\n", fsIn.GetSize());
2540 while ( !fsIn.Eof() )
2541 {
2542 putchar(fsIn.GetC());
2543 }
2544
2545 if ( !wxRemoveFile(filename) )
2546 {
2547 printf("ERROR: failed to remove the file '%s'.\n", filename);
2548 }
2549
2550 puts("\n*** wxFileInputStream test done ***");
2551 }
2552
2553 static void TestMemoryStream()
2554 {
2555 puts("*** Testing wxMemoryInputStream ***");
2556
2557 wxChar buf[1024];
2558 wxStrncpy(buf, _T("Hello, stream!"), WXSIZEOF(buf));
2559
2560 wxMemoryInputStream memInpStream(buf, wxStrlen(buf));
2561 printf(_T("Memory stream size: %u\n"), memInpStream.GetSize());
2562 while ( !memInpStream.Eof() )
2563 {
2564 putchar(memInpStream.GetC());
2565 }
2566
2567 puts("\n*** wxMemoryInputStream test done ***");
2568 }
2569
2570 #endif // TEST_STREAMS
2571
2572 // ----------------------------------------------------------------------------
2573 // timers
2574 // ----------------------------------------------------------------------------
2575
2576 #ifdef TEST_TIMER
2577
2578 #include <wx/timer.h>
2579 #include <wx/utils.h>
2580
2581 static void TestStopWatch()
2582 {
2583 puts("*** Testing wxStopWatch ***\n");
2584
2585 wxStopWatch sw;
2586 printf("Sleeping 3 seconds...");
2587 wxSleep(3);
2588 printf("\telapsed time: %ldms\n", sw.Time());
2589
2590 sw.Pause();
2591 printf("Sleeping 2 more seconds...");
2592 wxSleep(2);
2593 printf("\telapsed time: %ldms\n", sw.Time());
2594
2595 sw.Resume();
2596 printf("And 3 more seconds...");
2597 wxSleep(3);
2598 printf("\telapsed time: %ldms\n", sw.Time());
2599
2600 wxStopWatch sw2;
2601 puts("\nChecking for 'backwards clock' bug...");
2602 for ( size_t n = 0; n < 70; n++ )
2603 {
2604 sw2.Start();
2605
2606 for ( size_t m = 0; m < 100000; m++ )
2607 {
2608 if ( sw.Time() < 0 || sw2.Time() < 0 )
2609 {
2610 puts("\ntime is negative - ERROR!");
2611 }
2612 }
2613
2614 putchar('.');
2615 }
2616
2617 puts(", ok.");
2618 }
2619
2620 #endif // TEST_TIMER
2621
2622 // ----------------------------------------------------------------------------
2623 // vCard support
2624 // ----------------------------------------------------------------------------
2625
2626 #ifdef TEST_VCARD
2627
2628 #include <wx/vcard.h>
2629
2630 static void DumpVObject(size_t level, const wxVCardObject& vcard)
2631 {
2632 void *cookie;
2633 wxVCardObject *vcObj = vcard.GetFirstProp(&cookie);
2634 while ( vcObj )
2635 {
2636 printf("%s%s",
2637 wxString(_T('\t'), level).c_str(),
2638 vcObj->GetName().c_str());
2639
2640 wxString value;
2641 switch ( vcObj->GetType() )
2642 {
2643 case wxVCardObject::String:
2644 case wxVCardObject::UString:
2645 {
2646 wxString val;
2647 vcObj->GetValue(&val);
2648 value << _T('"') << val << _T('"');
2649 }
2650 break;
2651
2652 case wxVCardObject::Int:
2653 {
2654 unsigned int i;
2655 vcObj->GetValue(&i);
2656 value.Printf(_T("%u"), i);
2657 }
2658 break;
2659
2660 case wxVCardObject::Long:
2661 {
2662 unsigned long l;
2663 vcObj->GetValue(&l);
2664 value.Printf(_T("%lu"), l);
2665 }
2666 break;
2667
2668 case wxVCardObject::None:
2669 break;
2670
2671 case wxVCardObject::Object:
2672 value = _T("<node>");
2673 break;
2674
2675 default:
2676 value = _T("<unknown value type>");
2677 }
2678
2679 if ( !!value )
2680 printf(" = %s", value.c_str());
2681 putchar('\n');
2682
2683 DumpVObject(level + 1, *vcObj);
2684
2685 delete vcObj;
2686 vcObj = vcard.GetNextProp(&cookie);
2687 }
2688 }
2689
2690 static void DumpVCardAddresses(const wxVCard& vcard)
2691 {
2692 puts("\nShowing all addresses from vCard:\n");
2693
2694 size_t nAdr = 0;
2695 void *cookie;
2696 wxVCardAddress *addr = vcard.GetFirstAddress(&cookie);
2697 while ( addr )
2698 {
2699 wxString flagsStr;
2700 int flags = addr->GetFlags();
2701 if ( flags & wxVCardAddress::Domestic )
2702 {
2703 flagsStr << _T("domestic ");
2704 }
2705 if ( flags & wxVCardAddress::Intl )
2706 {
2707 flagsStr << _T("international ");
2708 }
2709 if ( flags & wxVCardAddress::Postal )
2710 {
2711 flagsStr << _T("postal ");
2712 }
2713 if ( flags & wxVCardAddress::Parcel )
2714 {
2715 flagsStr << _T("parcel ");
2716 }
2717 if ( flags & wxVCardAddress::Home )
2718 {
2719 flagsStr << _T("home ");
2720 }
2721 if ( flags & wxVCardAddress::Work )
2722 {
2723 flagsStr << _T("work ");
2724 }
2725
2726 printf("Address %u:\n"
2727 "\tflags = %s\n"
2728 "\tvalue = %s;%s;%s;%s;%s;%s;%s\n",
2729 ++nAdr,
2730 flagsStr.c_str(),
2731 addr->GetPostOffice().c_str(),
2732 addr->GetExtAddress().c_str(),
2733 addr->GetStreet().c_str(),
2734 addr->GetLocality().c_str(),
2735 addr->GetRegion().c_str(),
2736 addr->GetPostalCode().c_str(),
2737 addr->GetCountry().c_str()
2738 );
2739
2740 delete addr;
2741 addr = vcard.GetNextAddress(&cookie);
2742 }
2743 }
2744
2745 static void DumpVCardPhoneNumbers(const wxVCard& vcard)
2746 {
2747 puts("\nShowing all phone numbers from vCard:\n");
2748
2749 size_t nPhone = 0;
2750 void *cookie;
2751 wxVCardPhoneNumber *phone = vcard.GetFirstPhoneNumber(&cookie);
2752 while ( phone )
2753 {
2754 wxString flagsStr;
2755 int flags = phone->GetFlags();
2756 if ( flags & wxVCardPhoneNumber::Voice )
2757 {
2758 flagsStr << _T("voice ");
2759 }
2760 if ( flags & wxVCardPhoneNumber::Fax )
2761 {
2762 flagsStr << _T("fax ");
2763 }
2764 if ( flags & wxVCardPhoneNumber::Cellular )
2765 {
2766 flagsStr << _T("cellular ");
2767 }
2768 if ( flags & wxVCardPhoneNumber::Modem )
2769 {
2770 flagsStr << _T("modem ");
2771 }
2772 if ( flags & wxVCardPhoneNumber::Home )
2773 {
2774 flagsStr << _T("home ");
2775 }
2776 if ( flags & wxVCardPhoneNumber::Work )
2777 {
2778 flagsStr << _T("work ");
2779 }
2780
2781 printf("Phone number %u:\n"
2782 "\tflags = %s\n"
2783 "\tvalue = %s\n",
2784 ++nPhone,
2785 flagsStr.c_str(),
2786 phone->GetNumber().c_str()
2787 );
2788
2789 delete phone;
2790 phone = vcard.GetNextPhoneNumber(&cookie);
2791 }
2792 }
2793
2794 static void TestVCardRead()
2795 {
2796 puts("*** Testing wxVCard reading ***\n");
2797
2798 wxVCard vcard(_T("vcard.vcf"));
2799 if ( !vcard.IsOk() )
2800 {
2801 puts("ERROR: couldn't load vCard.");
2802 }
2803 else
2804 {
2805 // read individual vCard properties
2806 wxVCardObject *vcObj = vcard.GetProperty("FN");
2807 wxString value;
2808 if ( vcObj )
2809 {
2810 vcObj->GetValue(&value);
2811 delete vcObj;
2812 }
2813 else
2814 {
2815 value = _T("<none>");
2816 }
2817
2818 printf("Full name retrieved directly: %s\n", value.c_str());
2819
2820
2821 if ( !vcard.GetFullName(&value) )
2822 {
2823 value = _T("<none>");
2824 }
2825
2826 printf("Full name from wxVCard API: %s\n", value.c_str());
2827
2828 // now show how to deal with multiply occuring properties
2829 DumpVCardAddresses(vcard);
2830 DumpVCardPhoneNumbers(vcard);
2831
2832 // and finally show all
2833 puts("\nNow dumping the entire vCard:\n"
2834 "-----------------------------\n");
2835
2836 DumpVObject(0, vcard);
2837 }
2838 }
2839
2840 static void TestVCardWrite()
2841 {
2842 puts("*** Testing wxVCard writing ***\n");
2843
2844 wxVCard vcard;
2845 if ( !vcard.IsOk() )
2846 {
2847 puts("ERROR: couldn't create vCard.");
2848 }
2849 else
2850 {
2851 // set some fields
2852 vcard.SetName("Zeitlin", "Vadim");
2853 vcard.SetFullName("Vadim Zeitlin");
2854 vcard.SetOrganization("wxWindows", "R&D");
2855
2856 // just dump the vCard back
2857 puts("Entire vCard follows:\n");
2858 puts(vcard.Write());
2859 }
2860 }
2861
2862 #endif // TEST_VCARD
2863
2864 // ----------------------------------------------------------------------------
2865 // wide char (Unicode) support
2866 // ----------------------------------------------------------------------------
2867
2868 #ifdef TEST_WCHAR
2869
2870 #include <wx/strconv.h>
2871 #include <wx/fontenc.h>
2872 #include <wx/encconv.h>
2873 #include <wx/buffer.h>
2874
2875 static void TestUtf8()
2876 {
2877 puts("*** Testing UTF8 support ***\n");
2878
2879 static const char textInUtf8[] =
2880 {
2881 208, 157, 208, 181, 209, 129, 208, 186, 208, 176, 208, 183, 208, 176,
2882 208, 189, 208, 189, 208, 190, 32, 208, 191, 208, 190, 209, 128, 208,
2883 176, 208, 180, 208, 190, 208, 178, 208, 176, 208, 187, 32, 208, 188,
2884 208, 181, 208, 189, 209, 143, 32, 209, 129, 208, 178, 208, 190, 208,
2885 181, 208, 185, 32, 208, 186, 209, 128, 209, 131, 209, 130, 208, 181,
2886 208, 185, 209, 136, 208, 181, 208, 185, 32, 208, 189, 208, 190, 208,
2887 178, 208, 190, 209, 129, 209, 130, 209, 140, 209, 142, 0
2888 };
2889
2890 char buf[1024];
2891 wchar_t wbuf[1024];
2892 if ( wxConvUTF8.MB2WC(wbuf, textInUtf8, WXSIZEOF(textInUtf8)) <= 0 )
2893 {
2894 puts("ERROR: UTF-8 decoding failed.");
2895 }
2896 else
2897 {
2898 // using wxEncodingConverter
2899 #if 0
2900 wxEncodingConverter ec;
2901 ec.Init(wxFONTENCODING_UNICODE, wxFONTENCODING_KOI8);
2902 ec.Convert(wbuf, buf);
2903 #else // using wxCSConv
2904 wxCSConv conv(_T("koi8-r"));
2905 if ( conv.WC2MB(buf, wbuf, 0 /* not needed wcslen(wbuf) */) <= 0 )
2906 {
2907 puts("ERROR: conversion to KOI8-R failed.");
2908 }
2909 else
2910 #endif
2911
2912 printf("The resulting string (in koi8-r): %s\n", buf);
2913 }
2914 }
2915
2916 #endif // TEST_WCHAR
2917
2918 // ----------------------------------------------------------------------------
2919 // ZIP stream
2920 // ----------------------------------------------------------------------------
2921
2922 #ifdef TEST_ZIP
2923
2924 #include "wx/filesys.h"
2925 #include "wx/fs_zip.h"
2926 #include "wx/zipstrm.h"
2927
2928 static const wxChar *TESTFILE_ZIP = _T("testdata.zip");
2929
2930 static void TestZipStreamRead()
2931 {
2932 puts("*** Testing ZIP reading ***\n");
2933
2934 static const wxChar *filename = _T("foo");
2935 wxZipInputStream istr(TESTFILE_ZIP, filename);
2936 printf("Archive size: %u\n", istr.GetSize());
2937
2938 printf("Dumping the file '%s':\n", filename);
2939 while ( !istr.Eof() )
2940 {
2941 putchar(istr.GetC());
2942 fflush(stdout);
2943 }
2944
2945 puts("\n----- done ------");
2946 }
2947
2948 static void DumpZipDirectory(wxFileSystem& fs,
2949 const wxString& dir,
2950 const wxString& indent)
2951 {
2952 wxString prefix = wxString::Format(_T("%s#zip:%s"),
2953 TESTFILE_ZIP, dir.c_str());
2954 wxString wildcard = prefix + _T("/*");
2955
2956 wxString dirname = fs.FindFirst(wildcard, wxDIR);
2957 while ( !dirname.empty() )
2958 {
2959 if ( !dirname.StartsWith(prefix + _T('/'), &dirname) )
2960 {
2961 wxPrintf(_T("ERROR: unexpected wxFileSystem::FindNext result\n"));
2962
2963 break;
2964 }
2965
2966 wxPrintf(_T("%s%s\n"), indent.c_str(), dirname.c_str());
2967
2968 DumpZipDirectory(fs, dirname,
2969 indent + wxString(_T(' '), 4));
2970
2971 dirname = fs.FindNext();
2972 }
2973
2974 wxString filename = fs.FindFirst(wildcard, wxFILE);
2975 while ( !filename.empty() )
2976 {
2977 if ( !filename.StartsWith(prefix, &filename) )
2978 {
2979 wxPrintf(_T("ERROR: unexpected wxFileSystem::FindNext result\n"));
2980
2981 break;
2982 }
2983
2984 wxPrintf(_T("%s%s\n"), indent.c_str(), filename.c_str());
2985
2986 filename = fs.FindNext();
2987 }
2988 }
2989
2990 static void TestZipFileSystem()
2991 {
2992 puts("*** Testing ZIP file system ***\n");
2993
2994 wxFileSystem::AddHandler(new wxZipFSHandler);
2995 wxFileSystem fs;
2996 wxPrintf(_T("Dumping all files in the archive %s:\n"), TESTFILE_ZIP);
2997
2998 DumpZipDirectory(fs, _T(""), wxString(_T(' '), 4));
2999 }
3000
3001 #endif // TEST_ZIP
3002
3003 // ----------------------------------------------------------------------------
3004 // ZLIB stream
3005 // ----------------------------------------------------------------------------
3006
3007 #ifdef TEST_ZLIB
3008
3009 #include <wx/zstream.h>
3010 #include <wx/wfstream.h>
3011
3012 static const wxChar *FILENAME_GZ = _T("test.gz");
3013 static const char *TEST_DATA = "hello and hello again";
3014
3015 static void TestZlibStreamWrite()
3016 {
3017 puts("*** Testing Zlib stream reading ***\n");
3018
3019 wxFileOutputStream fileOutStream(FILENAME_GZ);
3020 wxZlibOutputStream ostr(fileOutStream, 0);
3021 printf("Compressing the test string... ");
3022 ostr.Write(TEST_DATA, sizeof(TEST_DATA));
3023 if ( !ostr )
3024 {
3025 puts("(ERROR: failed)");
3026 }
3027 else
3028 {
3029 puts("(ok)");
3030 }
3031
3032 puts("\n----- done ------");
3033 }
3034
3035 static void TestZlibStreamRead()
3036 {
3037 puts("*** Testing Zlib stream reading ***\n");
3038
3039 wxFileInputStream fileInStream(FILENAME_GZ);
3040 wxZlibInputStream istr(fileInStream);
3041 printf("Archive size: %u\n", istr.GetSize());
3042
3043 puts("Dumping the file:");
3044 while ( !istr.Eof() )
3045 {
3046 putchar(istr.GetC());
3047 fflush(stdout);
3048 }
3049
3050 puts("\n----- done ------");
3051 }
3052
3053 #endif // TEST_ZLIB
3054
3055 // ----------------------------------------------------------------------------
3056 // date time
3057 // ----------------------------------------------------------------------------
3058
3059 #ifdef TEST_DATETIME
3060
3061 #include <math.h>
3062
3063 #include <wx/date.h>
3064
3065 #include <wx/datetime.h>
3066
3067 // the test data
3068 struct Date
3069 {
3070 wxDateTime::wxDateTime_t day;
3071 wxDateTime::Month month;
3072 int year;
3073 wxDateTime::wxDateTime_t hour, min, sec;
3074 double jdn;
3075 wxDateTime::WeekDay wday;
3076 time_t gmticks, ticks;
3077
3078 void Init(const wxDateTime::Tm& tm)
3079 {
3080 day = tm.mday;
3081 month = tm.mon;
3082 year = tm.year;
3083 hour = tm.hour;
3084 min = tm.min;
3085 sec = tm.sec;
3086 jdn = 0.0;
3087 gmticks = ticks = -1;
3088 }
3089
3090 wxDateTime DT() const
3091 { return wxDateTime(day, month, year, hour, min, sec); }
3092
3093 bool SameDay(const wxDateTime::Tm& tm) const
3094 {
3095 return day == tm.mday && month == tm.mon && year == tm.year;
3096 }
3097
3098 wxString Format() const
3099 {
3100 wxString s;
3101 s.Printf("%02d:%02d:%02d %10s %02d, %4d%s",
3102 hour, min, sec,
3103 wxDateTime::GetMonthName(month).c_str(),
3104 day,
3105 abs(wxDateTime::ConvertYearToBC(year)),
3106 year > 0 ? "AD" : "BC");
3107 return s;
3108 }
3109
3110 wxString FormatDate() const
3111 {
3112 wxString s;
3113 s.Printf("%02d-%s-%4d%s",
3114 day,
3115 wxDateTime::GetMonthName(month, wxDateTime::Name_Abbr).c_str(),
3116 abs(wxDateTime::ConvertYearToBC(year)),
3117 year > 0 ? "AD" : "BC");
3118 return s;
3119 }
3120 };
3121
3122 static const Date testDates[] =
3123 {
3124 { 1, wxDateTime::Jan, 1970, 00, 00, 00, 2440587.5, wxDateTime::Thu, 0, -3600 },
3125 { 21, wxDateTime::Jan, 2222, 00, 00, 00, 2532648.5, wxDateTime::Mon, -1, -1 },
3126 { 29, wxDateTime::May, 1976, 12, 00, 00, 2442928.0, wxDateTime::Sat, 202219200, 202212000 },
3127 { 29, wxDateTime::Feb, 1976, 00, 00, 00, 2442837.5, wxDateTime::Sun, 194400000, 194396400 },
3128 { 1, wxDateTime::Jan, 1900, 12, 00, 00, 2415021.0, wxDateTime::Mon, -1, -1 },
3129 { 1, wxDateTime::Jan, 1900, 00, 00, 00, 2415020.5, wxDateTime::Mon, -1, -1 },
3130 { 15, wxDateTime::Oct, 1582, 00, 00, 00, 2299160.5, wxDateTime::Fri, -1, -1 },
3131 { 4, wxDateTime::Oct, 1582, 00, 00, 00, 2299149.5, wxDateTime::Mon, -1, -1 },
3132 { 1, wxDateTime::Mar, 1, 00, 00, 00, 1721484.5, wxDateTime::Thu, -1, -1 },
3133 { 1, wxDateTime::Jan, 1, 00, 00, 00, 1721425.5, wxDateTime::Mon, -1, -1 },
3134 { 31, wxDateTime::Dec, 0, 00, 00, 00, 1721424.5, wxDateTime::Sun, -1, -1 },
3135 { 1, wxDateTime::Jan, 0, 00, 00, 00, 1721059.5, wxDateTime::Sat, -1, -1 },
3136 { 12, wxDateTime::Aug, -1234, 00, 00, 00, 1270573.5, wxDateTime::Fri, -1, -1 },
3137 { 12, wxDateTime::Aug, -4000, 00, 00, 00, 260313.5, wxDateTime::Sat, -1, -1 },
3138 { 24, wxDateTime::Nov, -4713, 00, 00, 00, -0.5, wxDateTime::Mon, -1, -1 },
3139 };
3140
3141 // this test miscellaneous static wxDateTime functions
3142 static void TestTimeStatic()
3143 {
3144 puts("\n*** wxDateTime static methods test ***");
3145
3146 // some info about the current date
3147 int year = wxDateTime::GetCurrentYear();
3148 printf("Current year %d is %sa leap one and has %d days.\n",
3149 year,
3150 wxDateTime::IsLeapYear(year) ? "" : "not ",
3151 wxDateTime::GetNumberOfDays(year));
3152
3153 wxDateTime::Month month = wxDateTime::GetCurrentMonth();
3154 printf("Current month is '%s' ('%s') and it has %d days\n",
3155 wxDateTime::GetMonthName(month, wxDateTime::Name_Abbr).c_str(),
3156 wxDateTime::GetMonthName(month).c_str(),
3157 wxDateTime::GetNumberOfDays(month));
3158
3159 // leap year logic
3160 static const size_t nYears = 5;
3161 static const size_t years[2][nYears] =
3162 {
3163 // first line: the years to test
3164 { 1990, 1976, 2000, 2030, 1984, },
3165
3166 // second line: TRUE if leap, FALSE otherwise
3167 { FALSE, TRUE, TRUE, FALSE, TRUE }
3168 };
3169
3170 for ( size_t n = 0; n < nYears; n++ )
3171 {
3172 int year = years[0][n];
3173 bool should = years[1][n] != 0,
3174 is = wxDateTime::IsLeapYear(year);
3175
3176 printf("Year %d is %sa leap year (%s)\n",
3177 year,
3178 is ? "" : "not ",
3179 should == is ? "ok" : "ERROR");
3180
3181 wxASSERT( should == wxDateTime::IsLeapYear(year) );
3182 }
3183 }
3184
3185 // test constructing wxDateTime objects
3186 static void TestTimeSet()
3187 {
3188 puts("\n*** wxDateTime construction test ***");
3189
3190 for ( size_t n = 0; n < WXSIZEOF(testDates); n++ )
3191 {
3192 const Date& d1 = testDates[n];
3193 wxDateTime dt = d1.DT();
3194
3195 Date d2;
3196 d2.Init(dt.GetTm());
3197
3198 wxString s1 = d1.Format(),
3199 s2 = d2.Format();
3200
3201 printf("Date: %s == %s (%s)\n",
3202 s1.c_str(), s2.c_str(),
3203 s1 == s2 ? "ok" : "ERROR");
3204 }
3205 }
3206
3207 // test time zones stuff
3208 static void TestTimeZones()
3209 {
3210 puts("\n*** wxDateTime timezone test ***");
3211
3212 wxDateTime now = wxDateTime::Now();
3213
3214 printf("Current GMT time:\t%s\n", now.Format("%c", wxDateTime::GMT0).c_str());
3215 printf("Unix epoch (GMT):\t%s\n", wxDateTime((time_t)0).Format("%c", wxDateTime::GMT0).c_str());
3216 printf("Unix epoch (EST):\t%s\n", wxDateTime((time_t)0).Format("%c", wxDateTime::EST).c_str());
3217 printf("Current time in Paris:\t%s\n", now.Format("%c", wxDateTime::CET).c_str());
3218 printf(" Moscow:\t%s\n", now.Format("%c", wxDateTime::MSK).c_str());
3219 printf(" New York:\t%s\n", now.Format("%c", wxDateTime::EST).c_str());
3220
3221 wxDateTime::Tm tm = now.GetTm();
3222 if ( wxDateTime(tm) != now )
3223 {
3224 printf("ERROR: got %s instead of %s\n",
3225 wxDateTime(tm).Format().c_str(), now.Format().c_str());
3226 }
3227 }
3228
3229 // test some minimal support for the dates outside the standard range
3230 static void TestTimeRange()
3231 {
3232 puts("\n*** wxDateTime out-of-standard-range dates test ***");
3233
3234 static const char *fmt = "%d-%b-%Y %H:%M:%S";
3235
3236 printf("Unix epoch:\t%s\n",
3237 wxDateTime(2440587.5).Format(fmt).c_str());
3238 printf("Feb 29, 0: \t%s\n",
3239 wxDateTime(29, wxDateTime::Feb, 0).Format(fmt).c_str());
3240 printf("JDN 0: \t%s\n",
3241 wxDateTime(0.0).Format(fmt).c_str());
3242 printf("Jan 1, 1AD:\t%s\n",
3243 wxDateTime(1, wxDateTime::Jan, 1).Format(fmt).c_str());
3244 printf("May 29, 2099:\t%s\n",
3245 wxDateTime(29, wxDateTime::May, 2099).Format(fmt).c_str());
3246 }
3247
3248 static void TestTimeTicks()
3249 {
3250 puts("\n*** wxDateTime ticks test ***");
3251
3252 for ( size_t n = 0; n < WXSIZEOF(testDates); n++ )
3253 {
3254 const Date& d = testDates[n];
3255 if ( d.ticks == -1 )
3256 continue;
3257
3258 wxDateTime dt = d.DT();
3259 long ticks = (dt.GetValue() / 1000).ToLong();
3260 printf("Ticks of %s:\t% 10ld", d.Format().c_str(), ticks);
3261 if ( ticks == d.ticks )
3262 {
3263 puts(" (ok)");
3264 }
3265 else
3266 {
3267 printf(" (ERROR: should be %ld, delta = %ld)\n",
3268 d.ticks, ticks - d.ticks);
3269 }
3270
3271 dt = d.DT().ToTimezone(wxDateTime::GMT0);
3272 ticks = (dt.GetValue() / 1000).ToLong();
3273 printf("GMtks of %s:\t% 10ld", d.Format().c_str(), ticks);
3274 if ( ticks == d.gmticks )
3275 {
3276 puts(" (ok)");
3277 }
3278 else
3279 {
3280 printf(" (ERROR: should be %ld, delta = %ld)\n",
3281 d.gmticks, ticks - d.gmticks);
3282 }
3283 }
3284
3285 puts("");
3286 }
3287
3288 // test conversions to JDN &c
3289 static void TestTimeJDN()
3290 {
3291 puts("\n*** wxDateTime to JDN test ***");
3292
3293 for ( size_t n = 0; n < WXSIZEOF(testDates); n++ )
3294 {
3295 const Date& d = testDates[n];
3296 wxDateTime dt(d.day, d.month, d.year, d.hour, d.min, d.sec);
3297 double jdn = dt.GetJulianDayNumber();
3298
3299 printf("JDN of %s is:\t% 15.6f", d.Format().c_str(), jdn);
3300 if ( jdn == d.jdn )
3301 {
3302 puts(" (ok)");
3303 }
3304 else
3305 {
3306 printf(" (ERROR: should be %f, delta = %f)\n",
3307 d.jdn, jdn - d.jdn);
3308 }
3309 }
3310 }
3311
3312 // test week days computation
3313 static void TestTimeWDays()
3314 {
3315 puts("\n*** wxDateTime weekday test ***");
3316
3317 // test GetWeekDay()
3318 size_t n;
3319 for ( n = 0; n < WXSIZEOF(testDates); n++ )
3320 {
3321 const Date& d = testDates[n];
3322 wxDateTime dt(d.day, d.month, d.year, d.hour, d.min, d.sec);
3323
3324 wxDateTime::WeekDay wday = dt.GetWeekDay();
3325 printf("%s is: %s",
3326 d.Format().c_str(),
3327 wxDateTime::GetWeekDayName(wday).c_str());
3328 if ( wday == d.wday )
3329 {
3330 puts(" (ok)");
3331 }
3332 else
3333 {
3334 printf(" (ERROR: should be %s)\n",
3335 wxDateTime::GetWeekDayName(d.wday).c_str());
3336 }
3337 }
3338
3339 puts("");
3340
3341 // test SetToWeekDay()
3342 struct WeekDateTestData
3343 {
3344 Date date; // the real date (precomputed)
3345 int nWeek; // its week index in the month
3346 wxDateTime::WeekDay wday; // the weekday
3347 wxDateTime::Month month; // the month
3348 int year; // and the year
3349
3350 wxString Format() const
3351 {
3352 wxString s, which;
3353 switch ( nWeek < -1 ? -nWeek : nWeek )
3354 {
3355 case 1: which = "first"; break;
3356 case 2: which = "second"; break;
3357 case 3: which = "third"; break;
3358 case 4: which = "fourth"; break;
3359 case 5: which = "fifth"; break;
3360
3361 case -1: which = "last"; break;
3362 }
3363
3364 if ( nWeek < -1 )
3365 {
3366 which += " from end";
3367 }
3368
3369 s.Printf("The %s %s of %s in %d",
3370 which.c_str(),
3371 wxDateTime::GetWeekDayName(wday).c_str(),
3372 wxDateTime::GetMonthName(month).c_str(),
3373 year);
3374
3375 return s;
3376 }
3377 };
3378
3379 // the array data was generated by the following python program
3380 /*
3381 from DateTime import *
3382 from whrandom import *
3383 from string import *
3384
3385 monthNames = [ 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec' ]
3386 wdayNames = [ 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun' ]
3387
3388 week = DateTimeDelta(7)
3389
3390 for n in range(20):
3391 year = randint(1900, 2100)
3392 month = randint(1, 12)
3393 day = randint(1, 28)
3394 dt = DateTime(year, month, day)
3395 wday = dt.day_of_week
3396
3397 countFromEnd = choice([-1, 1])
3398 weekNum = 0;
3399
3400 while dt.month is month:
3401 dt = dt - countFromEnd * week
3402 weekNum = weekNum + countFromEnd
3403
3404 data = { 'day': rjust(`day`, 2), 'month': monthNames[month - 1], 'year': year, 'weekNum': rjust(`weekNum`, 2), 'wday': wdayNames[wday] }
3405
3406 print "{ { %(day)s, wxDateTime::%(month)s, %(year)d }, %(weekNum)d, "\
3407 "wxDateTime::%(wday)s, wxDateTime::%(month)s, %(year)d }," % data
3408 */
3409
3410 static const WeekDateTestData weekDatesTestData[] =
3411 {
3412 { { 20, wxDateTime::Mar, 2045 }, 3, wxDateTime::Mon, wxDateTime::Mar, 2045 },
3413 { { 5, wxDateTime::Jun, 1985 }, -4, wxDateTime::Wed, wxDateTime::Jun, 1985 },
3414 { { 12, wxDateTime::Nov, 1961 }, -3, wxDateTime::Sun, wxDateTime::Nov, 1961 },
3415 { { 27, wxDateTime::Feb, 2093 }, -1, wxDateTime::Fri, wxDateTime::Feb, 2093 },
3416 { { 4, wxDateTime::Jul, 2070 }, -4, wxDateTime::Fri, wxDateTime::Jul, 2070 },
3417 { { 2, wxDateTime::Apr, 1906 }, -5, wxDateTime::Mon, wxDateTime::Apr, 1906 },
3418 { { 19, wxDateTime::Jul, 2023 }, -2, wxDateTime::Wed, wxDateTime::Jul, 2023 },
3419 { { 5, wxDateTime::May, 1958 }, -4, wxDateTime::Mon, wxDateTime::May, 1958 },
3420 { { 11, wxDateTime::Aug, 1900 }, 2, wxDateTime::Sat, wxDateTime::Aug, 1900 },
3421 { { 14, wxDateTime::Feb, 1945 }, 2, wxDateTime::Wed, wxDateTime::Feb, 1945 },
3422 { { 25, wxDateTime::Jul, 1967 }, -1, wxDateTime::Tue, wxDateTime::Jul, 1967 },
3423 { { 9, wxDateTime::May, 1916 }, -4, wxDateTime::Tue, wxDateTime::May, 1916 },
3424 { { 20, wxDateTime::Jun, 1927 }, 3, wxDateTime::Mon, wxDateTime::Jun, 1927 },
3425 { { 2, wxDateTime::Aug, 2000 }, 1, wxDateTime::Wed, wxDateTime::Aug, 2000 },
3426 { { 20, wxDateTime::Apr, 2044 }, 3, wxDateTime::Wed, wxDateTime::Apr, 2044 },
3427 { { 20, wxDateTime::Feb, 1932 }, -2, wxDateTime::Sat, wxDateTime::Feb, 1932 },
3428 { { 25, wxDateTime::Jul, 2069 }, 4, wxDateTime::Thu, wxDateTime::Jul, 2069 },
3429 { { 3, wxDateTime::Apr, 1925 }, 1, wxDateTime::Fri, wxDateTime::Apr, 1925 },
3430 { { 21, wxDateTime::Mar, 2093 }, 3, wxDateTime::Sat, wxDateTime::Mar, 2093 },
3431 { { 3, wxDateTime::Dec, 2074 }, -5, wxDateTime::Mon, wxDateTime::Dec, 2074 },
3432 };
3433
3434 static const char *fmt = "%d-%b-%Y";
3435
3436 wxDateTime dt;
3437 for ( n = 0; n < WXSIZEOF(weekDatesTestData); n++ )
3438 {
3439 const WeekDateTestData& wd = weekDatesTestData[n];
3440
3441 dt.SetToWeekDay(wd.wday, wd.nWeek, wd.month, wd.year);
3442
3443 printf("%s is %s", wd.Format().c_str(), dt.Format(fmt).c_str());
3444
3445 const Date& d = wd.date;
3446 if ( d.SameDay(dt.GetTm()) )
3447 {
3448 puts(" (ok)");
3449 }
3450 else
3451 {
3452 dt.Set(d.day, d.month, d.year);
3453
3454 printf(" (ERROR: should be %s)\n", dt.Format(fmt).c_str());
3455 }
3456 }
3457 }
3458
3459 // test the computation of (ISO) week numbers
3460 static void TestTimeWNumber()
3461 {
3462 puts("\n*** wxDateTime week number test ***");
3463
3464 struct WeekNumberTestData
3465 {
3466 Date date; // the date
3467 wxDateTime::wxDateTime_t week; // the week number in the year
3468 wxDateTime::wxDateTime_t wmon; // the week number in the month
3469 wxDateTime::wxDateTime_t wmon2; // same but week starts with Sun
3470 wxDateTime::wxDateTime_t dnum; // day number in the year
3471 };
3472
3473 // data generated with the following python script:
3474 /*
3475 from DateTime import *
3476 from whrandom import *
3477 from string import *
3478
3479 monthNames = [ 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec' ]
3480 wdayNames = [ 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun' ]
3481
3482 def GetMonthWeek(dt):
3483 weekNumMonth = dt.iso_week[1] - DateTime(dt.year, dt.month, 1).iso_week[1] + 1
3484 if weekNumMonth < 0:
3485 weekNumMonth = weekNumMonth + 53
3486 return weekNumMonth
3487
3488 def GetLastSundayBefore(dt):
3489 if dt.iso_week[2] == 7:
3490 return dt
3491 else:
3492 return dt - DateTimeDelta(dt.iso_week[2])
3493
3494 for n in range(20):
3495 year = randint(1900, 2100)
3496 month = randint(1, 12)
3497 day = randint(1, 28)
3498 dt = DateTime(year, month, day)
3499 dayNum = dt.day_of_year
3500 weekNum = dt.iso_week[1]
3501 weekNumMonth = GetMonthWeek(dt)
3502
3503 weekNumMonth2 = 0
3504 dtSunday = GetLastSundayBefore(dt)
3505
3506 while dtSunday >= GetLastSundayBefore(DateTime(dt.year, dt.month, 1)):
3507 weekNumMonth2 = weekNumMonth2 + 1
3508 dtSunday = dtSunday - DateTimeDelta(7)
3509
3510 data = { 'day': rjust(`day`, 2), \
3511 'month': monthNames[month - 1], \
3512 'year': year, \
3513 'weekNum': rjust(`weekNum`, 2), \
3514 'weekNumMonth': weekNumMonth, \
3515 'weekNumMonth2': weekNumMonth2, \
3516 'dayNum': rjust(`dayNum`, 3) }
3517
3518 print " { { %(day)s, "\
3519 "wxDateTime::%(month)s, "\
3520 "%(year)d }, "\
3521 "%(weekNum)s, "\
3522 "%(weekNumMonth)s, "\
3523 "%(weekNumMonth2)s, "\
3524 "%(dayNum)s }," % data
3525
3526 */
3527 static const WeekNumberTestData weekNumberTestDates[] =
3528 {
3529 { { 27, wxDateTime::Dec, 1966 }, 52, 5, 5, 361 },
3530 { { 22, wxDateTime::Jul, 1926 }, 29, 4, 4, 203 },
3531 { { 22, wxDateTime::Oct, 2076 }, 43, 4, 4, 296 },
3532 { { 1, wxDateTime::Jul, 1967 }, 26, 1, 1, 182 },
3533 { { 8, wxDateTime::Nov, 2004 }, 46, 2, 2, 313 },
3534 { { 21, wxDateTime::Mar, 1920 }, 12, 3, 4, 81 },
3535 { { 7, wxDateTime::Jan, 1965 }, 1, 2, 2, 7 },
3536 { { 19, wxDateTime::Oct, 1999 }, 42, 4, 4, 292 },
3537 { { 13, wxDateTime::Aug, 1955 }, 32, 2, 2, 225 },
3538 { { 18, wxDateTime::Jul, 2087 }, 29, 3, 3, 199 },
3539 { { 2, wxDateTime::Sep, 2028 }, 35, 1, 1, 246 },
3540 { { 28, wxDateTime::Jul, 1945 }, 30, 5, 4, 209 },
3541 { { 15, wxDateTime::Jun, 1901 }, 24, 3, 3, 166 },
3542 { { 10, wxDateTime::Oct, 1939 }, 41, 3, 2, 283 },
3543 { { 3, wxDateTime::Dec, 1965 }, 48, 1, 1, 337 },
3544 { { 23, wxDateTime::Feb, 1940 }, 8, 4, 4, 54 },
3545 { { 2, wxDateTime::Jan, 1987 }, 1, 1, 1, 2 },
3546 { { 11, wxDateTime::Aug, 2079 }, 32, 2, 2, 223 },
3547 { { 2, wxDateTime::Feb, 2063 }, 5, 1, 1, 33 },
3548 { { 16, wxDateTime::Oct, 1942 }, 42, 3, 3, 289 },
3549 };
3550
3551 for ( size_t n = 0; n < WXSIZEOF(weekNumberTestDates); n++ )
3552 {
3553 const WeekNumberTestData& wn = weekNumberTestDates[n];
3554 const Date& d = wn.date;
3555
3556 wxDateTime dt = d.DT();
3557
3558 wxDateTime::wxDateTime_t
3559 week = dt.GetWeekOfYear(wxDateTime::Monday_First),
3560 wmon = dt.GetWeekOfMonth(wxDateTime::Monday_First),
3561 wmon2 = dt.GetWeekOfMonth(wxDateTime::Sunday_First),
3562 dnum = dt.GetDayOfYear();
3563
3564 printf("%s: the day number is %d",
3565 d.FormatDate().c_str(), dnum);
3566 if ( dnum == wn.dnum )
3567 {
3568 printf(" (ok)");
3569 }
3570 else
3571 {
3572 printf(" (ERROR: should be %d)", wn.dnum);
3573 }
3574
3575 printf(", week in month is %d", wmon);
3576 if ( wmon == wn.wmon )
3577 {
3578 printf(" (ok)");
3579 }
3580 else
3581 {
3582 printf(" (ERROR: should be %d)", wn.wmon);
3583 }
3584
3585 printf(" or %d", wmon2);
3586 if ( wmon2 == wn.wmon2 )
3587 {
3588 printf(" (ok)");
3589 }
3590 else
3591 {
3592 printf(" (ERROR: should be %d)", wn.wmon2);
3593 }
3594
3595 printf(", week in year is %d", week);
3596 if ( week == wn.week )
3597 {
3598 puts(" (ok)");
3599 }
3600 else
3601 {
3602 printf(" (ERROR: should be %d)\n", wn.week);
3603 }
3604 }
3605 }
3606
3607 // test DST calculations
3608 static void TestTimeDST()
3609 {
3610 puts("\n*** wxDateTime DST test ***");
3611
3612 printf("DST is%s in effect now.\n\n",
3613 wxDateTime::Now().IsDST() ? "" : " not");
3614
3615 // taken from http://www.energy.ca.gov/daylightsaving.html
3616 static const Date datesDST[2][2004 - 1900 + 1] =
3617 {
3618 {
3619 { 1, wxDateTime::Apr, 1990 },
3620 { 7, wxDateTime::Apr, 1991 },
3621 { 5, wxDateTime::Apr, 1992 },
3622 { 4, wxDateTime::Apr, 1993 },
3623 { 3, wxDateTime::Apr, 1994 },
3624 { 2, wxDateTime::Apr, 1995 },
3625 { 7, wxDateTime::Apr, 1996 },
3626 { 6, wxDateTime::Apr, 1997 },
3627 { 5, wxDateTime::Apr, 1998 },
3628 { 4, wxDateTime::Apr, 1999 },
3629 { 2, wxDateTime::Apr, 2000 },
3630 { 1, wxDateTime::Apr, 2001 },
3631 { 7, wxDateTime::Apr, 2002 },
3632 { 6, wxDateTime::Apr, 2003 },
3633 { 4, wxDateTime::Apr, 2004 },
3634 },
3635 {
3636 { 28, wxDateTime::Oct, 1990 },
3637 { 27, wxDateTime::Oct, 1991 },
3638 { 25, wxDateTime::Oct, 1992 },
3639 { 31, wxDateTime::Oct, 1993 },
3640 { 30, wxDateTime::Oct, 1994 },
3641 { 29, wxDateTime::Oct, 1995 },
3642 { 27, wxDateTime::Oct, 1996 },
3643 { 26, wxDateTime::Oct, 1997 },
3644 { 25, wxDateTime::Oct, 1998 },
3645 { 31, wxDateTime::Oct, 1999 },
3646 { 29, wxDateTime::Oct, 2000 },
3647 { 28, wxDateTime::Oct, 2001 },
3648 { 27, wxDateTime::Oct, 2002 },
3649 { 26, wxDateTime::Oct, 2003 },
3650 { 31, wxDateTime::Oct, 2004 },
3651 }
3652 };
3653
3654 int year;
3655 for ( year = 1990; year < 2005; year++ )
3656 {
3657 wxDateTime dtBegin = wxDateTime::GetBeginDST(year, wxDateTime::USA),
3658 dtEnd = wxDateTime::GetEndDST(year, wxDateTime::USA);
3659
3660 printf("DST period in the US for year %d: from %s to %s",
3661 year, dtBegin.Format().c_str(), dtEnd.Format().c_str());
3662
3663 size_t n = year - 1990;
3664 const Date& dBegin = datesDST[0][n];
3665 const Date& dEnd = datesDST[1][n];
3666
3667 if ( dBegin.SameDay(dtBegin.GetTm()) && dEnd.SameDay(dtEnd.GetTm()) )
3668 {
3669 puts(" (ok)");
3670 }
3671 else
3672 {
3673 printf(" (ERROR: should be %s %d to %s %d)\n",
3674 wxDateTime::GetMonthName(dBegin.month).c_str(), dBegin.day,
3675 wxDateTime::GetMonthName(dEnd.month).c_str(), dEnd.day);
3676 }
3677 }
3678
3679 puts("");
3680
3681 for ( year = 1990; year < 2005; year++ )
3682 {
3683 printf("DST period in Europe for year %d: from %s to %s\n",
3684 year,
3685 wxDateTime::GetBeginDST(year, wxDateTime::Country_EEC).Format().c_str(),
3686 wxDateTime::GetEndDST(year, wxDateTime::Country_EEC).Format().c_str());
3687 }
3688 }
3689
3690 // test wxDateTime -> text conversion
3691 static void TestTimeFormat()
3692 {
3693 puts("\n*** wxDateTime formatting test ***");
3694
3695 // some information may be lost during conversion, so store what kind
3696 // of info should we recover after a round trip
3697 enum CompareKind
3698 {
3699 CompareNone, // don't try comparing
3700 CompareBoth, // dates and times should be identical
3701 CompareDate, // dates only
3702 CompareTime // time only
3703 };
3704
3705 static const struct
3706 {
3707 CompareKind compareKind;
3708 const char *format;
3709 } formatTestFormats[] =
3710 {
3711 { CompareBoth, "---> %c" },
3712 { CompareDate, "Date is %A, %d of %B, in year %Y" },
3713 { CompareBoth, "Date is %x, time is %X" },
3714 { CompareTime, "Time is %H:%M:%S or %I:%M:%S %p" },
3715 { CompareNone, "The day of year: %j, the week of year: %W" },
3716 { CompareDate, "ISO date without separators: %4Y%2m%2d" },
3717 };
3718
3719 static const Date formatTestDates[] =
3720 {
3721 { 29, wxDateTime::May, 1976, 18, 30, 00 },
3722 { 31, wxDateTime::Dec, 1999, 23, 30, 00 },
3723 #if 0
3724 // this test can't work for other centuries because it uses two digit
3725 // years in formats, so don't even try it
3726 { 29, wxDateTime::May, 2076, 18, 30, 00 },
3727 { 29, wxDateTime::Feb, 2400, 02, 15, 25 },
3728 { 01, wxDateTime::Jan, -52, 03, 16, 47 },
3729 #endif
3730 };
3731
3732 // an extra test (as it doesn't depend on date, don't do it in the loop)
3733 printf("%s\n", wxDateTime::Now().Format("Our timezone is %Z").c_str());
3734
3735 for ( size_t d = 0; d < WXSIZEOF(formatTestDates) + 1; d++ )
3736 {
3737 puts("");
3738
3739 wxDateTime dt = d == 0 ? wxDateTime::Now() : formatTestDates[d - 1].DT();
3740 for ( size_t n = 0; n < WXSIZEOF(formatTestFormats); n++ )
3741 {
3742 wxString s = dt.Format(formatTestFormats[n].format);
3743 printf("%s", s.c_str());
3744
3745 // what can we recover?
3746 int kind = formatTestFormats[n].compareKind;
3747
3748 // convert back
3749 wxDateTime dt2;
3750 const wxChar *result = dt2.ParseFormat(s, formatTestFormats[n].format);
3751 if ( !result )
3752 {
3753 // converion failed - should it have?
3754 if ( kind == CompareNone )
3755 puts(" (ok)");
3756 else
3757 puts(" (ERROR: conversion back failed)");
3758 }
3759 else if ( *result )
3760 {
3761 // should have parsed the entire string
3762 puts(" (ERROR: conversion back stopped too soon)");
3763 }
3764 else
3765 {
3766 bool equal = FALSE; // suppress compilaer warning
3767 switch ( kind )
3768 {
3769 case CompareBoth:
3770 equal = dt2 == dt;
3771 break;
3772
3773 case CompareDate:
3774 equal = dt.IsSameDate(dt2);
3775 break;
3776
3777 case CompareTime:
3778 equal = dt.IsSameTime(dt2);
3779 break;
3780 }
3781
3782 if ( !equal )
3783 {
3784 printf(" (ERROR: got back '%s' instead of '%s')\n",
3785 dt2.Format().c_str(), dt.Format().c_str());
3786 }
3787 else
3788 {
3789 puts(" (ok)");
3790 }
3791 }
3792 }
3793 }
3794 }
3795
3796 // test text -> wxDateTime conversion
3797 static void TestTimeParse()
3798 {
3799 puts("\n*** wxDateTime parse test ***");
3800
3801 struct ParseTestData
3802 {
3803 const char *format;
3804 Date date;
3805 bool good;
3806 };
3807
3808 static const ParseTestData parseTestDates[] =
3809 {
3810 { "Sat, 18 Dec 1999 00:46:40 +0100", { 18, wxDateTime::Dec, 1999, 00, 46, 40 }, TRUE },
3811 { "Wed, 1 Dec 1999 05:17:20 +0300", { 1, wxDateTime::Dec, 1999, 03, 17, 20 }, TRUE },
3812 };
3813
3814 for ( size_t n = 0; n < WXSIZEOF(parseTestDates); n++ )
3815 {
3816 const char *format = parseTestDates[n].format;
3817
3818 printf("%s => ", format);
3819
3820 wxDateTime dt;
3821 if ( dt.ParseRfc822Date(format) )
3822 {
3823 printf("%s ", dt.Format().c_str());
3824
3825 if ( parseTestDates[n].good )
3826 {
3827 wxDateTime dtReal = parseTestDates[n].date.DT();
3828 if ( dt == dtReal )
3829 {
3830 puts("(ok)");
3831 }
3832 else
3833 {
3834 printf("(ERROR: should be %s)\n", dtReal.Format().c_str());
3835 }
3836 }
3837 else
3838 {
3839 puts("(ERROR: bad format)");
3840 }
3841 }
3842 else
3843 {
3844 printf("bad format (%s)\n",
3845 parseTestDates[n].good ? "ERROR" : "ok");
3846 }
3847 }
3848 }
3849
3850 static void TestDateTimeInteractive()
3851 {
3852 puts("\n*** interactive wxDateTime tests ***");
3853
3854 char buf[128];
3855
3856 for ( ;; )
3857 {
3858 printf("Enter a date: ");
3859 if ( !fgets(buf, WXSIZEOF(buf), stdin) )
3860 break;
3861
3862 // kill the last '\n'
3863 buf[strlen(buf) - 1] = 0;
3864
3865 wxDateTime dt;
3866 const char *p = dt.ParseDate(buf);
3867 if ( !p )
3868 {
3869 printf("ERROR: failed to parse the date '%s'.\n", buf);
3870
3871 continue;
3872 }
3873 else if ( *p )
3874 {
3875 printf("WARNING: parsed only first %u characters.\n", p - buf);
3876 }
3877
3878 printf("%s: day %u, week of month %u/%u, week of year %u\n",
3879 dt.Format("%b %d, %Y").c_str(),
3880 dt.GetDayOfYear(),
3881 dt.GetWeekOfMonth(wxDateTime::Monday_First),
3882 dt.GetWeekOfMonth(wxDateTime::Sunday_First),
3883 dt.GetWeekOfYear(wxDateTime::Monday_First));
3884 }
3885
3886 puts("\n*** done ***");
3887 }
3888
3889 static void TestTimeMS()
3890 {
3891 puts("*** testing millisecond-resolution support in wxDateTime ***");
3892
3893 wxDateTime dt1 = wxDateTime::Now(),
3894 dt2 = wxDateTime::UNow();
3895
3896 printf("Now = %s\n", dt1.Format("%H:%M:%S:%l").c_str());
3897 printf("UNow = %s\n", dt2.Format("%H:%M:%S:%l").c_str());
3898 printf("Dummy loop: ");
3899 for ( int i = 0; i < 6000; i++ )
3900 {
3901 //for ( int j = 0; j < 10; j++ )
3902 {
3903 wxString s;
3904 s.Printf("%g", sqrt(i));
3905 }
3906
3907 if ( !(i % 100) )
3908 putchar('.');
3909 }
3910 puts(", done");
3911
3912 dt1 = dt2;
3913 dt2 = wxDateTime::UNow();
3914 printf("UNow = %s\n", dt2.Format("%H:%M:%S:%l").c_str());
3915
3916 printf("Loop executed in %s ms\n", (dt2 - dt1).Format("%l").c_str());
3917
3918 puts("\n*** done ***");
3919 }
3920
3921 static void TestTimeArithmetics()
3922 {
3923 puts("\n*** testing arithmetic operations on wxDateTime ***");
3924
3925 static const struct ArithmData
3926 {
3927 ArithmData(const wxDateSpan& sp, const char *nam)
3928 : span(sp), name(nam) { }
3929
3930 wxDateSpan span;
3931 const char *name;
3932 } testArithmData[] =
3933 {
3934 ArithmData(wxDateSpan::Day(), "day"),
3935 ArithmData(wxDateSpan::Week(), "week"),
3936 ArithmData(wxDateSpan::Month(), "month"),
3937 ArithmData(wxDateSpan::Year(), "year"),
3938 ArithmData(wxDateSpan(1, 2, 3, 4), "year, 2 months, 3 weeks, 4 days"),
3939 };
3940
3941 wxDateTime dt(29, wxDateTime::Dec, 1999), dt1, dt2;
3942
3943 for ( size_t n = 0; n < WXSIZEOF(testArithmData); n++ )
3944 {
3945 wxDateSpan span = testArithmData[n].span;
3946 dt1 = dt + span;
3947 dt2 = dt - span;
3948
3949 const char *name = testArithmData[n].name;
3950 printf("%s + %s = %s, %s - %s = %s\n",
3951 dt.FormatISODate().c_str(), name, dt1.FormatISODate().c_str(),
3952 dt.FormatISODate().c_str(), name, dt2.FormatISODate().c_str());
3953
3954 printf("Going back: %s", (dt1 - span).FormatISODate().c_str());
3955 if ( dt1 - span == dt )
3956 {
3957 puts(" (ok)");
3958 }
3959 else
3960 {
3961 printf(" (ERROR: should be %s)\n", dt.FormatISODate().c_str());
3962 }
3963
3964 printf("Going forward: %s", (dt2 + span).FormatISODate().c_str());
3965 if ( dt2 + span == dt )
3966 {
3967 puts(" (ok)");
3968 }
3969 else
3970 {
3971 printf(" (ERROR: should be %s)\n", dt.FormatISODate().c_str());
3972 }
3973
3974 printf("Double increment: %s", (dt2 + 2*span).FormatISODate().c_str());
3975 if ( dt2 + 2*span == dt1 )
3976 {
3977 puts(" (ok)");
3978 }
3979 else
3980 {
3981 printf(" (ERROR: should be %s)\n", dt2.FormatISODate().c_str());
3982 }
3983
3984 puts("");
3985 }
3986 }
3987
3988 static void TestTimeHolidays()
3989 {
3990 puts("\n*** testing wxDateTimeHolidayAuthority ***\n");
3991
3992 wxDateTime::Tm tm = wxDateTime(29, wxDateTime::May, 2000).GetTm();
3993 wxDateTime dtStart(1, tm.mon, tm.year),
3994 dtEnd = dtStart.GetLastMonthDay();
3995
3996 wxDateTimeArray hol;
3997 wxDateTimeHolidayAuthority::GetHolidaysInRange(dtStart, dtEnd, hol);
3998
3999 const wxChar *format = "%d-%b-%Y (%a)";
4000
4001 printf("All holidays between %s and %s:\n",
4002 dtStart.Format(format).c_str(), dtEnd.Format(format).c_str());
4003
4004 size_t count = hol.GetCount();
4005 for ( size_t n = 0; n < count; n++ )
4006 {
4007 printf("\t%s\n", hol[n].Format(format).c_str());
4008 }
4009
4010 puts("");
4011 }
4012
4013 static void TestTimeZoneBug()
4014 {
4015 puts("\n*** testing for DST/timezone bug ***\n");
4016
4017 wxDateTime date = wxDateTime(1, wxDateTime::Mar, 2000);
4018 for ( int i = 0; i < 31; i++ )
4019 {
4020 printf("Date %s: week day %s.\n",
4021 date.Format(_T("%d-%m-%Y")).c_str(),
4022 date.GetWeekDayName(date.GetWeekDay()).c_str());
4023
4024 date += wxDateSpan::Day();
4025 }
4026
4027 puts("");
4028 }
4029
4030 static void TestTimeSpanFormat()
4031 {
4032 puts("\n*** wxTimeSpan tests ***");
4033
4034 static const char *formats[] =
4035 {
4036 _T("(default) %H:%M:%S"),
4037 _T("%E weeks and %D days"),
4038 _T("%l milliseconds"),
4039 _T("(with ms) %H:%M:%S:%l"),
4040 _T("100%% of minutes is %M"), // test "%%"
4041 _T("%D days and %H hours"),
4042 };
4043
4044 wxTimeSpan ts1(1, 2, 3, 4),
4045 ts2(111, 222, 333);
4046 for ( size_t n = 0; n < WXSIZEOF(formats); n++ )
4047 {
4048 printf("ts1 = %s\tts2 = %s\n",
4049 ts1.Format(formats[n]).c_str(),
4050 ts2.Format(formats[n]).c_str());
4051 }
4052
4053 puts("");
4054 }
4055
4056 #if 0
4057
4058 // test compatibility with the old wxDate/wxTime classes
4059 static void TestTimeCompatibility()
4060 {
4061 puts("\n*** wxDateTime compatibility test ***");
4062
4063 printf("wxDate for JDN 0: %s\n", wxDate(0l).FormatDate().c_str());
4064 printf("wxDate for MJD 0: %s\n", wxDate(2400000).FormatDate().c_str());
4065
4066 double jdnNow = wxDateTime::Now().GetJDN();
4067 long jdnMidnight = (long)(jdnNow - 0.5);
4068 printf("wxDate for today: %s\n", wxDate(jdnMidnight).FormatDate().c_str());
4069
4070 jdnMidnight = wxDate().Set().GetJulianDate();
4071 printf("wxDateTime for today: %s\n",
4072 wxDateTime((double)(jdnMidnight + 0.5)).Format("%c", wxDateTime::GMT0).c_str());
4073
4074 int flags = wxEUROPEAN;//wxFULL;
4075 wxDate date;
4076 date.Set();
4077 printf("Today is %s\n", date.FormatDate(flags).c_str());
4078 for ( int n = 0; n < 7; n++ )
4079 {
4080 printf("Previous %s is %s\n",
4081 wxDateTime::GetWeekDayName((wxDateTime::WeekDay)n),
4082 date.Previous(n + 1).FormatDate(flags).c_str());
4083 }
4084 }
4085
4086 #endif // 0
4087
4088 #endif // TEST_DATETIME
4089
4090 // ----------------------------------------------------------------------------
4091 // threads
4092 // ----------------------------------------------------------------------------
4093
4094 #ifdef TEST_THREADS
4095
4096 #include <wx/thread.h>
4097
4098 static size_t gs_counter = (size_t)-1;
4099 static wxCriticalSection gs_critsect;
4100 static wxCondition gs_cond;
4101
4102 class MyJoinableThread : public wxThread
4103 {
4104 public:
4105 MyJoinableThread(size_t n) : wxThread(wxTHREAD_JOINABLE)
4106 { m_n = n; Create(); }
4107
4108 // thread execution starts here
4109 virtual ExitCode Entry();
4110
4111 private:
4112 size_t m_n;
4113 };
4114
4115 wxThread::ExitCode MyJoinableThread::Entry()
4116 {
4117 unsigned long res = 1;
4118 for ( size_t n = 1; n < m_n; n++ )
4119 {
4120 res *= n;
4121
4122 // it's a loooong calculation :-)
4123 Sleep(100);
4124 }
4125
4126 return (ExitCode)res;
4127 }
4128
4129 class MyDetachedThread : public wxThread
4130 {
4131 public:
4132 MyDetachedThread(size_t n, char ch)
4133 {
4134 m_n = n;
4135 m_ch = ch;
4136 m_cancelled = FALSE;
4137
4138 Create();
4139 }
4140
4141 // thread execution starts here
4142 virtual ExitCode Entry();
4143
4144 // and stops here
4145 virtual void OnExit();
4146
4147 private:
4148 size_t m_n; // number of characters to write
4149 char m_ch; // character to write
4150
4151 bool m_cancelled; // FALSE if we exit normally
4152 };
4153
4154 wxThread::ExitCode MyDetachedThread::Entry()
4155 {
4156 {
4157 wxCriticalSectionLocker lock(gs_critsect);
4158 if ( gs_counter == (size_t)-1 )
4159 gs_counter = 1;
4160 else
4161 gs_counter++;
4162 }
4163
4164 for ( size_t n = 0; n < m_n; n++ )
4165 {
4166 if ( TestDestroy() )
4167 {
4168 m_cancelled = TRUE;
4169
4170 break;
4171 }
4172
4173 putchar(m_ch);
4174 fflush(stdout);
4175
4176 wxThread::Sleep(100);
4177 }
4178
4179 return 0;
4180 }
4181
4182 void MyDetachedThread::OnExit()
4183 {
4184 wxLogTrace("thread", "Thread %ld is in OnExit", GetId());
4185
4186 wxCriticalSectionLocker lock(gs_critsect);
4187 if ( !--gs_counter && !m_cancelled )
4188 gs_cond.Signal();
4189 }
4190
4191 void TestDetachedThreads()
4192 {
4193 puts("\n*** Testing detached threads ***");
4194
4195 static const size_t nThreads = 3;
4196 MyDetachedThread *threads[nThreads];
4197 size_t n;
4198 for ( n = 0; n < nThreads; n++ )
4199 {
4200 threads[n] = new MyDetachedThread(10, 'A' + n);
4201 }
4202
4203 threads[0]->SetPriority(WXTHREAD_MIN_PRIORITY);
4204 threads[1]->SetPriority(WXTHREAD_MAX_PRIORITY);
4205
4206 for ( n = 0; n < nThreads; n++ )
4207 {
4208 threads[n]->Run();
4209 }
4210
4211 // wait until all threads terminate
4212 gs_cond.Wait();
4213
4214 puts("");
4215 }
4216
4217 void TestJoinableThreads()
4218 {
4219 puts("\n*** Testing a joinable thread (a loooong calculation...) ***");
4220
4221 // calc 10! in the background
4222 MyJoinableThread thread(10);
4223 thread.Run();
4224
4225 printf("\nThread terminated with exit code %lu.\n",
4226 (unsigned long)thread.Wait());
4227 }
4228
4229 void TestThreadSuspend()
4230 {
4231 puts("\n*** Testing thread suspend/resume functions ***");
4232
4233 MyDetachedThread *thread = new MyDetachedThread(15, 'X');
4234
4235 thread->Run();
4236
4237 // this is for this demo only, in a real life program we'd use another
4238 // condition variable which would be signaled from wxThread::Entry() to
4239 // tell us that the thread really started running - but here just wait a
4240 // bit and hope that it will be enough (the problem is, of course, that
4241 // the thread might still not run when we call Pause() which will result
4242 // in an error)
4243 wxThread::Sleep(300);
4244
4245 for ( size_t n = 0; n < 3; n++ )
4246 {
4247 thread->Pause();
4248
4249 puts("\nThread suspended");
4250 if ( n > 0 )
4251 {
4252 // don't sleep but resume immediately the first time
4253 wxThread::Sleep(300);
4254 }
4255 puts("Going to resume the thread");
4256
4257 thread->Resume();
4258 }
4259
4260 puts("Waiting until it terminates now");
4261
4262 // wait until the thread terminates
4263 gs_cond.Wait();
4264
4265 puts("");
4266 }
4267
4268 void TestThreadDelete()
4269 {
4270 // As above, using Sleep() is only for testing here - we must use some
4271 // synchronisation object instead to ensure that the thread is still
4272 // running when we delete it - deleting a detached thread which already
4273 // terminated will lead to a crash!
4274
4275 puts("\n*** Testing thread delete function ***");
4276
4277 MyDetachedThread *thread0 = new MyDetachedThread(30, 'W');
4278
4279 thread0->Delete();
4280
4281 puts("\nDeleted a thread which didn't start to run yet.");
4282
4283 MyDetachedThread *thread1 = new MyDetachedThread(30, 'Y');
4284
4285 thread1->Run();
4286
4287 wxThread::Sleep(300);
4288
4289 thread1->Delete();
4290
4291 puts("\nDeleted a running thread.");
4292
4293 MyDetachedThread *thread2 = new MyDetachedThread(30, 'Z');
4294
4295 thread2->Run();
4296
4297 wxThread::Sleep(300);
4298
4299 thread2->Pause();
4300
4301 thread2->Delete();
4302
4303 puts("\nDeleted a sleeping thread.");
4304
4305 MyJoinableThread thread3(20);
4306 thread3.Run();
4307
4308 thread3.Delete();
4309
4310 puts("\nDeleted a joinable thread.");
4311
4312 MyJoinableThread thread4(2);
4313 thread4.Run();
4314
4315 wxThread::Sleep(300);
4316
4317 thread4.Delete();
4318
4319 puts("\nDeleted a joinable thread which already terminated.");
4320
4321 puts("");
4322 }
4323
4324 #endif // TEST_THREADS
4325
4326 // ----------------------------------------------------------------------------
4327 // arrays
4328 // ----------------------------------------------------------------------------
4329
4330 #ifdef TEST_ARRAYS
4331
4332 static void PrintArray(const char* name, const wxArrayString& array)
4333 {
4334 printf("Dump of the array '%s'\n", name);
4335
4336 size_t nCount = array.GetCount();
4337 for ( size_t n = 0; n < nCount; n++ )
4338 {
4339 printf("\t%s[%u] = '%s'\n", name, n, array[n].c_str());
4340 }
4341 }
4342
4343 static void PrintArray(const char* name, const wxArrayInt& array)
4344 {
4345 printf("Dump of the array '%s'\n", name);
4346
4347 size_t nCount = array.GetCount();
4348 for ( size_t n = 0; n < nCount; n++ )
4349 {
4350 printf("\t%s[%u] = %d\n", name, n, array[n]);
4351 }
4352 }
4353
4354 int wxCMPFUNC_CONV StringLenCompare(const wxString& first,
4355 const wxString& second)
4356 {
4357 return first.length() - second.length();
4358 }
4359
4360 int wxCMPFUNC_CONV IntCompare(int *first,
4361 int *second)
4362 {
4363 return *first - *second;
4364 }
4365
4366 int wxCMPFUNC_CONV IntRevCompare(int *first,
4367 int *second)
4368 {
4369 return *second - *first;
4370 }
4371
4372 static void TestArrayOfInts()
4373 {
4374 puts("*** Testing wxArrayInt ***\n");
4375
4376 wxArrayInt a;
4377 a.Add(1);
4378 a.Add(17);
4379 a.Add(5);
4380 a.Add(3);
4381
4382 puts("Initially:");
4383 PrintArray("a", a);
4384
4385 puts("After sort:");
4386 a.Sort(IntCompare);
4387 PrintArray("a", a);
4388
4389 puts("After reverse sort:");
4390 a.Sort(IntRevCompare);
4391 PrintArray("a", a);
4392 }
4393
4394 #include "wx/dynarray.h"
4395
4396 WX_DECLARE_OBJARRAY(Bar, ArrayBars);
4397 #include "wx/arrimpl.cpp"
4398 WX_DEFINE_OBJARRAY(ArrayBars);
4399
4400 static void TestArrayOfObjects()
4401 {
4402 puts("*** Testing wxObjArray ***\n");
4403
4404 {
4405 ArrayBars bars;
4406 Bar bar("second bar");
4407
4408 printf("Initially: %u objects in the array, %u objects total.\n",
4409 bars.GetCount(), Bar::GetNumber());
4410
4411 bars.Add(new Bar("first bar"));
4412 bars.Add(bar);
4413
4414 printf("Now: %u objects in the array, %u objects total.\n",
4415 bars.GetCount(), Bar::GetNumber());
4416
4417 bars.Empty();
4418
4419 printf("After Empty(): %u objects in the array, %u objects total.\n",
4420 bars.GetCount(), Bar::GetNumber());
4421 }
4422
4423 printf("Finally: no more objects in the array, %u objects total.\n",
4424 Bar::GetNumber());
4425 }
4426
4427 #endif // TEST_ARRAYS
4428
4429 // ----------------------------------------------------------------------------
4430 // strings
4431 // ----------------------------------------------------------------------------
4432
4433 #ifdef TEST_STRINGS
4434
4435 #include "wx/timer.h"
4436 #include "wx/tokenzr.h"
4437
4438 static void TestStringConstruction()
4439 {
4440 puts("*** Testing wxString constructores ***");
4441
4442 #define TEST_CTOR(args, res) \
4443 { \
4444 wxString s args ; \
4445 printf("wxString%s = %s ", #args, s.c_str()); \
4446 if ( s == res ) \
4447 { \
4448 puts("(ok)"); \
4449 } \
4450 else \
4451 { \
4452 printf("(ERROR: should be %s)\n", res); \
4453 } \
4454 }
4455
4456 TEST_CTOR((_T('Z'), 4), _T("ZZZZ"));
4457 TEST_CTOR((_T("Hello"), 4), _T("Hell"));
4458 TEST_CTOR((_T("Hello"), 5), _T("Hello"));
4459 // TEST_CTOR((_T("Hello"), 6), _T("Hello")); -- should give assert failure
4460
4461 static const wxChar *s = _T("?really!");
4462 const wxChar *start = wxStrchr(s, _T('r'));
4463 const wxChar *end = wxStrchr(s, _T('!'));
4464 TEST_CTOR((start, end), _T("really"));
4465
4466 puts("");
4467 }
4468
4469 static void TestString()
4470 {
4471 wxStopWatch sw;
4472
4473 wxString a, b, c;
4474
4475 a.reserve (128);
4476 b.reserve (128);
4477 c.reserve (128);
4478
4479 for (int i = 0; i < 1000000; ++i)
4480 {
4481 a = "Hello";
4482 b = " world";
4483 c = "! How'ya doin'?";
4484 a += b;
4485 a += c;
4486 c = "Hello world! What's up?";
4487 if (c != a)
4488 c = "Doh!";
4489 }
4490
4491 printf ("TestString elapsed time: %ld\n", sw.Time());
4492 }
4493
4494 static void TestPChar()
4495 {
4496 wxStopWatch sw;
4497
4498 char a [128];
4499 char b [128];
4500 char c [128];
4501
4502 for (int i = 0; i < 1000000; ++i)
4503 {
4504 strcpy (a, "Hello");
4505 strcpy (b, " world");
4506 strcpy (c, "! How'ya doin'?");
4507 strcat (a, b);
4508 strcat (a, c);
4509 strcpy (c, "Hello world! What's up?");
4510 if (strcmp (c, a) == 0)
4511 strcpy (c, "Doh!");
4512 }
4513
4514 printf ("TestPChar elapsed time: %ld\n", sw.Time());
4515 }
4516
4517 static void TestStringSub()
4518 {
4519 wxString s("Hello, world!");
4520
4521 puts("*** Testing wxString substring extraction ***");
4522
4523 printf("String = '%s'\n", s.c_str());
4524 printf("Left(5) = '%s'\n", s.Left(5).c_str());
4525 printf("Right(6) = '%s'\n", s.Right(6).c_str());
4526 printf("Mid(3, 5) = '%s'\n", s(3, 5).c_str());
4527 printf("Mid(3) = '%s'\n", s.Mid(3).c_str());
4528 printf("substr(3, 5) = '%s'\n", s.substr(3, 5).c_str());
4529 printf("substr(3) = '%s'\n", s.substr(3).c_str());
4530
4531 static const wxChar *prefixes[] =
4532 {
4533 _T("Hello"),
4534 _T("Hello, "),
4535 _T("Hello, world!"),
4536 _T("Hello, world!!!"),
4537 _T(""),
4538 _T("Goodbye"),
4539 _T("Hi"),
4540 };
4541
4542 for ( size_t n = 0; n < WXSIZEOF(prefixes); n++ )
4543 {
4544 wxString prefix = prefixes[n], rest;
4545 bool rc = s.StartsWith(prefix, &rest);
4546 printf("StartsWith('%s') = %s", prefix.c_str(), rc ? "TRUE" : "FALSE");
4547 if ( rc )
4548 {
4549 printf(" (the rest is '%s')\n", rest.c_str());
4550 }
4551 else
4552 {
4553 putchar('\n');
4554 }
4555 }
4556
4557 puts("");
4558 }
4559
4560 static void TestStringFormat()
4561 {
4562 puts("*** Testing wxString formatting ***");
4563
4564 wxString s;
4565 s.Printf("%03d", 18);
4566
4567 printf("Number 18: %s\n", wxString::Format("%03d", 18).c_str());
4568 printf("Number 18: %s\n", s.c_str());
4569
4570 puts("");
4571 }
4572
4573 // returns "not found" for npos, value for all others
4574 static wxString PosToString(size_t res)
4575 {
4576 wxString s = res == wxString::npos ? wxString(_T("not found"))
4577 : wxString::Format(_T("%u"), res);
4578 return s;
4579 }
4580
4581 static void TestStringFind()
4582 {
4583 puts("*** Testing wxString find() functions ***");
4584
4585 static const wxChar *strToFind = _T("ell");
4586 static const struct StringFindTest
4587 {
4588 const wxChar *str;
4589 size_t start,
4590 result; // of searching "ell" in str
4591 } findTestData[] =
4592 {
4593 { _T("Well, hello world"), 0, 1 },
4594 { _T("Well, hello world"), 6, 7 },
4595 { _T("Well, hello world"), 9, wxString::npos },
4596 };
4597
4598 for ( size_t n = 0; n < WXSIZEOF(findTestData); n++ )
4599 {
4600 const StringFindTest& ft = findTestData[n];
4601 size_t res = wxString(ft.str).find(strToFind, ft.start);
4602
4603 printf(_T("Index of '%s' in '%s' starting from %u is %s "),
4604 strToFind, ft.str, ft.start, PosToString(res).c_str());
4605
4606 size_t resTrue = ft.result;
4607 if ( res == resTrue )
4608 {
4609 puts(_T("(ok)"));
4610 }
4611 else
4612 {
4613 printf(_T("(ERROR: should be %s)\n"),
4614 PosToString(resTrue).c_str());
4615 }
4616 }
4617
4618 puts("");
4619 }
4620
4621 static void TestStringTokenizer()
4622 {
4623 puts("*** Testing wxStringTokenizer ***");
4624
4625 static const wxChar *modeNames[] =
4626 {
4627 _T("default"),
4628 _T("return empty"),
4629 _T("return all empty"),
4630 _T("with delims"),
4631 _T("like strtok"),
4632 };
4633
4634 static const struct StringTokenizerTest
4635 {
4636 const wxChar *str; // string to tokenize
4637 const wxChar *delims; // delimiters to use
4638 size_t count; // count of token
4639 wxStringTokenizerMode mode; // how should we tokenize it
4640 } tokenizerTestData[] =
4641 {
4642 { _T(""), _T(" "), 0 },
4643 { _T("Hello, world"), _T(" "), 2 },
4644 { _T("Hello, world "), _T(" "), 2 },
4645 { _T("Hello, world"), _T(","), 2 },
4646 { _T("Hello, world!"), _T(",!"), 2 },
4647 { _T("Hello,, world!"), _T(",!"), 3 },
4648 { _T("Hello, world!"), _T(",!"), 3, wxTOKEN_RET_EMPTY_ALL },
4649 { _T("username:password:uid:gid:gecos:home:shell"), _T(":"), 7 },
4650 { _T("1 \t3\t4 6 "), wxDEFAULT_DELIMITERS, 4 },
4651 { _T("1 \t3\t4 6 "), wxDEFAULT_DELIMITERS, 6, wxTOKEN_RET_EMPTY },
4652 { _T("1 \t3\t4 6 "), wxDEFAULT_DELIMITERS, 9, wxTOKEN_RET_EMPTY_ALL },
4653 { _T("01/02/99"), _T("/-"), 3 },
4654 { _T("01-02/99"), _T("/-"), 3, wxTOKEN_RET_DELIMS },
4655 };
4656
4657 for ( size_t n = 0; n < WXSIZEOF(tokenizerTestData); n++ )
4658 {
4659 const StringTokenizerTest& tt = tokenizerTestData[n];
4660 wxStringTokenizer tkz(tt.str, tt.delims, tt.mode);
4661
4662 size_t count = tkz.CountTokens();
4663 printf(_T("String '%s' has %u tokens delimited by '%s' (mode = %s) "),
4664 MakePrintable(tt.str).c_str(),
4665 count,
4666 MakePrintable(tt.delims).c_str(),
4667 modeNames[tkz.GetMode()]);
4668 if ( count == tt.count )
4669 {
4670 puts(_T("(ok)"));
4671 }
4672 else
4673 {
4674 printf(_T("(ERROR: should be %u)\n"), tt.count);
4675
4676 continue;
4677 }
4678
4679 // if we emulate strtok(), check that we do it correctly
4680 wxChar *buf, *s = NULL, *last;
4681
4682 if ( tkz.GetMode() == wxTOKEN_STRTOK )
4683 {
4684 buf = new wxChar[wxStrlen(tt.str) + 1];
4685 wxStrcpy(buf, tt.str);
4686
4687 s = wxStrtok(buf, tt.delims, &last);
4688 }
4689 else
4690 {
4691 buf = NULL;
4692 }
4693
4694 // now show the tokens themselves
4695 size_t count2 = 0;
4696 while ( tkz.HasMoreTokens() )
4697 {
4698 wxString token = tkz.GetNextToken();
4699
4700 printf(_T("\ttoken %u: '%s'"),
4701 ++count2,
4702 MakePrintable(token).c_str());
4703
4704 if ( buf )
4705 {
4706 if ( token == s )
4707 {
4708 puts(" (ok)");
4709 }
4710 else
4711 {
4712 printf(" (ERROR: should be %s)\n", s);
4713 }
4714
4715 s = wxStrtok(NULL, tt.delims, &last);
4716 }
4717 else
4718 {
4719 // nothing to compare with
4720 puts("");
4721 }
4722 }
4723
4724 if ( count2 != count )
4725 {
4726 puts(_T("\tERROR: token count mismatch"));
4727 }
4728
4729 delete [] buf;
4730 }
4731
4732 puts("");
4733 }
4734
4735 static void TestStringReplace()
4736 {
4737 puts("*** Testing wxString::replace ***");
4738
4739 static const struct StringReplaceTestData
4740 {
4741 const wxChar *original; // original test string
4742 size_t start, len; // the part to replace
4743 const wxChar *replacement; // the replacement string
4744 const wxChar *result; // and the expected result
4745 } stringReplaceTestData[] =
4746 {
4747 { _T("012-AWORD-XYZ"), 4, 5, _T("BWORD"), _T("012-BWORD-XYZ") },
4748 { _T("increase"), 0, 2, _T("de"), _T("decrease") },
4749 { _T("wxWindow"), 8, 0, _T("s"), _T("wxWindows") },
4750 { _T("foobar"), 3, 0, _T("-"), _T("foo-bar") },
4751 { _T("barfoo"), 0, 6, _T("foobar"), _T("foobar") },
4752 };
4753
4754 for ( size_t n = 0; n < WXSIZEOF(stringReplaceTestData); n++ )
4755 {
4756 const StringReplaceTestData data = stringReplaceTestData[n];
4757
4758 wxString original = data.original;
4759 original.replace(data.start, data.len, data.replacement);
4760
4761 wxPrintf(_T("wxString(\"%s\").replace(%u, %u, %s) = %s "),
4762 data.original, data.start, data.len, data.replacement,
4763 original.c_str());
4764
4765 if ( original == data.result )
4766 {
4767 puts("(ok)");
4768 }
4769 else
4770 {
4771 wxPrintf(_T("(ERROR: should be '%s')\n"), data.result);
4772 }
4773 }
4774
4775 puts("");
4776 }
4777
4778 static void TestStringMatch()
4779 {
4780 wxPuts(_T("*** Testing wxString::Matches() ***"));
4781
4782 static const struct StringMatchTestData
4783 {
4784 const wxChar *text;
4785 const wxChar *wildcard;
4786 bool matches;
4787 } stringMatchTestData[] =
4788 {
4789 { _T("foobar"), _T("foo*"), 1 },
4790 { _T("foobar"), _T("*oo*"), 1 },
4791 { _T("foobar"), _T("*bar"), 1 },
4792 { _T("foobar"), _T("??????"), 1 },
4793 { _T("foobar"), _T("f??b*"), 1 },
4794 { _T("foobar"), _T("f?b*"), 0 },
4795 { _T("foobar"), _T("*goo*"), 0 },
4796 { _T("foobar"), _T("*foo"), 0 },
4797 { _T("foobarfoo"), _T("*foo"), 1 },
4798 { _T(""), _T("*"), 1 },
4799 { _T(""), _T("?"), 0 },
4800 };
4801
4802 for ( size_t n = 0; n < WXSIZEOF(stringMatchTestData); n++ )
4803 {
4804 const StringMatchTestData& data = stringMatchTestData[n];
4805 bool matches = wxString(data.text).Matches(data.wildcard);
4806 wxPrintf(_T("'%s' %s '%s' (%s)\n"),
4807 data.wildcard,
4808 matches ? _T("matches") : _T("doesn't match"),
4809 data.text,
4810 matches == data.matches ? _T("ok") : _T("ERROR"));
4811 }
4812
4813 wxPuts(_T(""));
4814 }
4815
4816 #endif // TEST_STRINGS
4817
4818 // ----------------------------------------------------------------------------
4819 // entry point
4820 // ----------------------------------------------------------------------------
4821
4822 int main(int argc, char **argv)
4823 {
4824 wxInitializer initializer;
4825 if ( !initializer )
4826 {
4827 fprintf(stderr, "Failed to initialize the wxWindows library, aborting.");
4828
4829 return -1;
4830 }
4831
4832 #ifdef TEST_SNGLINST
4833 wxSingleInstanceChecker checker;
4834 if ( checker.Create(_T(".wxconsole.lock")) )
4835 {
4836 if ( checker.IsAnotherRunning() )
4837 {
4838 wxPrintf(_T("Another instance of the program is running, exiting.\n"));
4839
4840 return 1;
4841 }
4842
4843 // wait some time to give time to launch another instance
4844 wxPrintf(_T("Press \"Enter\" to continue..."));
4845 wxFgetc(stdin);
4846 }
4847 else // failed to create
4848 {
4849 wxPrintf(_T("Failed to init wxSingleInstanceChecker.\n"));
4850 }
4851 #endif // TEST_SNGLINST
4852
4853 #ifdef TEST_CHARSET
4854 TestCharset();
4855 #endif // TEST_CHARSET
4856
4857 #ifdef TEST_CMDLINE
4858 static const wxCmdLineEntryDesc cmdLineDesc[] =
4859 {
4860 { wxCMD_LINE_SWITCH, "v", "verbose", "be verbose" },
4861 { wxCMD_LINE_SWITCH, "q", "quiet", "be quiet" },
4862
4863 { wxCMD_LINE_OPTION, "o", "output", "output file" },
4864 { wxCMD_LINE_OPTION, "i", "input", "input dir" },
4865 { wxCMD_LINE_OPTION, "s", "size", "output block size", wxCMD_LINE_VAL_NUMBER },
4866 { wxCMD_LINE_OPTION, "d", "date", "output file date", wxCMD_LINE_VAL_DATE },
4867
4868 { wxCMD_LINE_PARAM, NULL, NULL, "input file",
4869 wxCMD_LINE_VAL_STRING, wxCMD_LINE_PARAM_MULTIPLE },
4870
4871 { wxCMD_LINE_NONE }
4872 };
4873
4874 wxCmdLineParser parser(cmdLineDesc, argc, argv);
4875
4876 parser.AddOption("project_name", "", "full path to project file",
4877 wxCMD_LINE_VAL_STRING,
4878 wxCMD_LINE_OPTION_MANDATORY | wxCMD_LINE_NEEDS_SEPARATOR);
4879
4880 switch ( parser.Parse() )
4881 {
4882 case -1:
4883 wxLogMessage("Help was given, terminating.");
4884 break;
4885
4886 case 0:
4887 ShowCmdLine(parser);
4888 break;
4889
4890 default:
4891 wxLogMessage("Syntax error detected, aborting.");
4892 break;
4893 }
4894 #endif // TEST_CMDLINE
4895
4896 #ifdef TEST_STRINGS
4897 if ( 0 )
4898 {
4899 TestPChar();
4900 TestString();
4901 TestStringSub();
4902 TestStringConstruction();
4903 TestStringFormat();
4904 TestStringFind();
4905 TestStringTokenizer();
4906 TestStringReplace();
4907 }
4908 TestStringMatch();
4909 #endif // TEST_STRINGS
4910
4911 #ifdef TEST_ARRAYS
4912 if ( 0 )
4913 {
4914 wxArrayString a1;
4915 a1.Add("tiger");
4916 a1.Add("cat");
4917 a1.Add("lion");
4918 a1.Add("dog");
4919 a1.Add("human");
4920 a1.Add("ape");
4921
4922 puts("*** Initially:");
4923
4924 PrintArray("a1", a1);
4925
4926 wxArrayString a2(a1);
4927 PrintArray("a2", a2);
4928
4929 wxSortedArrayString a3(a1);
4930 PrintArray("a3", a3);
4931
4932 puts("*** After deleting a string from a1");
4933 a1.Remove(2);
4934
4935 PrintArray("a1", a1);
4936 PrintArray("a2", a2);
4937 PrintArray("a3", a3);
4938
4939 puts("*** After reassigning a1 to a2 and a3");
4940 a3 = a2 = a1;
4941 PrintArray("a2", a2);
4942 PrintArray("a3", a3);
4943
4944 puts("*** After sorting a1");
4945 a1.Sort();
4946 PrintArray("a1", a1);
4947
4948 puts("*** After sorting a1 in reverse order");
4949 a1.Sort(TRUE);
4950 PrintArray("a1", a1);
4951
4952 puts("*** After sorting a1 by the string length");
4953 a1.Sort(StringLenCompare);
4954 PrintArray("a1", a1);
4955
4956 TestArrayOfObjects();
4957 }
4958 TestArrayOfInts();
4959 #endif // TEST_ARRAYS
4960
4961 #ifdef TEST_DIR
4962 if ( 0 )
4963 TestDirEnum();
4964 TestDirTraverse();
4965 #endif // TEST_DIR
4966
4967 #ifdef TEST_DLLLOADER
4968 TestDllLoad();
4969 #endif // TEST_DLLLOADER
4970
4971 #ifdef TEST_ENVIRON
4972 TestEnvironment();
4973 #endif // TEST_ENVIRON
4974
4975 #ifdef TEST_EXECUTE
4976 TestExecute();
4977 #endif // TEST_EXECUTE
4978
4979 #ifdef TEST_FILECONF
4980 TestFileConfRead();
4981 #endif // TEST_FILECONF
4982
4983 #ifdef TEST_LIST
4984 TestListCtor();
4985 #endif // TEST_LIST
4986
4987 #ifdef TEST_LOCALE
4988 TestDefaultLang();
4989 #endif // TEST_LOCALE
4990
4991 #ifdef TEST_LOG
4992 wxString s;
4993 for ( size_t n = 0; n < 8000; n++ )
4994 {
4995 s << (char)('A' + (n % 26));
4996 }
4997
4998 wxString msg;
4999 msg.Printf("A very very long message: '%s', the end!\n", s.c_str());
5000
5001 // this one shouldn't be truncated
5002 printf(msg);
5003
5004 // but this one will because log functions use fixed size buffer
5005 // (note that it doesn't need '\n' at the end neither - will be added
5006 // by wxLog anyhow)
5007 wxLogMessage("A very very long message 2: '%s', the end!", s.c_str());
5008 #endif // TEST_LOG
5009
5010 #ifdef TEST_FILE
5011 if ( 0 )
5012 {
5013 TestFileRead();
5014 TestTextFileRead();
5015 }
5016 TestFileCopy();
5017 #endif // TEST_FILE
5018
5019 #ifdef TEST_FILENAME
5020 TestFileNameSplit();
5021 if ( 0 )
5022 {
5023 TestFileNameConstruction();
5024 TestFileNameCwd();
5025 TestFileNameComparison();
5026 TestFileNameOperations();
5027 }
5028 #endif // TEST_FILENAME
5029
5030 #ifdef TEST_FTP
5031 wxLog::AddTraceMask(FTP_TRACE_MASK);
5032 if ( TestFtpConnect() )
5033 {
5034 TestFtpFileSize();
5035 if ( 0 )
5036 {
5037 TestFtpList();
5038 TestFtpDownload();
5039 TestFtpMisc();
5040 TestFtpUpload();
5041 }
5042 if ( 0 )
5043 TestFtpInteractive();
5044 }
5045 //else: connecting to the FTP server failed
5046
5047 if ( 0 )
5048 TestFtpWuFtpd();
5049 #endif // TEST_FTP
5050
5051 #ifdef TEST_THREADS
5052 int nCPUs = wxThread::GetCPUCount();
5053 printf("This system has %d CPUs\n", nCPUs);
5054 if ( nCPUs != -1 )
5055 wxThread::SetConcurrency(nCPUs);
5056
5057 if ( argc > 1 && argv[1][0] == 't' )
5058 wxLog::AddTraceMask("thread");
5059
5060 if ( 1 )
5061 TestDetachedThreads();
5062 if ( 1 )
5063 TestJoinableThreads();
5064 if ( 1 )
5065 TestThreadSuspend();
5066 if ( 1 )
5067 TestThreadDelete();
5068
5069 #endif // TEST_THREADS
5070
5071 #ifdef TEST_LONGLONG
5072 // seed pseudo random generator
5073 srand((unsigned)time(NULL));
5074
5075 if ( 0 )
5076 {
5077 TestSpeed();
5078 }
5079 if ( 0 )
5080 {
5081 TestMultiplication();
5082 TestDivision();
5083 TestAddition();
5084 TestLongLongConversion();
5085 TestBitOperations();
5086 }
5087 TestLongLongComparison();
5088 #endif // TEST_LONGLONG
5089
5090 #ifdef TEST_HASH
5091 TestHash();
5092 #endif // TEST_HASH
5093
5094 #ifdef TEST_MIME
5095 wxLog::AddTraceMask(_T("mime"));
5096 if ( 1 )
5097 {
5098 TestMimeEnum();
5099 TestMimeOverride();
5100 TestMimeFilename();
5101 }
5102 else
5103 TestMimeAssociate();
5104 #endif // TEST_MIME
5105
5106 #ifdef TEST_INFO_FUNCTIONS
5107 TestOsInfo();
5108 TestUserInfo();
5109 #endif // TEST_INFO_FUNCTIONS
5110
5111 #ifdef TEST_PATHLIST
5112 TestPathList();
5113 #endif // TEST_PATHLIST
5114
5115 #ifdef TEST_REGCONF
5116 TestRegConfWrite();
5117 #endif // TEST_REGCONF
5118
5119 #ifdef TEST_REGEX
5120 // TODO: write a real test using src/regex/tests file
5121 if ( 0 )
5122 {
5123 TestRegExCompile();
5124 TestRegExMatch();
5125 TestRegExSubmatch();
5126 TestRegExInteractive();
5127 }
5128 TestRegExReplacement();
5129 #endif // TEST_REGEX
5130
5131 #ifdef TEST_REGISTRY
5132 if ( 0 )
5133 TestRegistryRead();
5134 TestRegistryAssociation();
5135 #endif // TEST_REGISTRY
5136
5137 #ifdef TEST_SOCKETS
5138 if ( 0 )
5139 {
5140 TestSocketServer();
5141 }
5142 TestSocketClient();
5143 #endif // TEST_SOCKETS
5144
5145 #ifdef TEST_STREAMS
5146 if ( 0 )
5147 TestFileStream();
5148 TestMemoryStream();
5149 #endif // TEST_STREAMS
5150
5151 #ifdef TEST_TIMER
5152 TestStopWatch();
5153 #endif // TEST_TIMER
5154
5155 #ifdef TEST_DATETIME
5156 if ( 0 )
5157 {
5158 TestTimeSet();
5159 TestTimeStatic();
5160 TestTimeRange();
5161 TestTimeZones();
5162 TestTimeTicks();
5163 TestTimeJDN();
5164 TestTimeDST();
5165 TestTimeWDays();
5166 TestTimeWNumber();
5167 TestTimeParse();
5168 TestTimeArithmetics();
5169 TestTimeHolidays();
5170 TestTimeFormat();
5171 TestTimeMS();
5172
5173 TestTimeZoneBug();
5174 }
5175 TestTimeSpanFormat();
5176 if ( 0 )
5177 TestDateTimeInteractive();
5178 #endif // TEST_DATETIME
5179
5180 #ifdef TEST_USLEEP
5181 puts("Sleeping for 3 seconds... z-z-z-z-z...");
5182 wxUsleep(3000);
5183 #endif // TEST_USLEEP
5184
5185 #ifdef TEST_VCARD
5186 if ( 0 )
5187 TestVCardRead();
5188 TestVCardWrite();
5189 #endif // TEST_VCARD
5190
5191 #ifdef TEST_WCHAR
5192 TestUtf8();
5193 #endif // TEST_WCHAR
5194
5195 #ifdef TEST_ZIP
5196 if ( 0 )
5197 TestZipStreamRead();
5198 TestZipFileSystem();
5199 #endif // TEST_ZIP
5200
5201 #ifdef TEST_ZLIB
5202 if ( 0 )
5203 TestZlibStreamWrite();
5204 TestZlibStreamRead();
5205 #endif // TEST_ZLIB
5206
5207 return 0;
5208 }
5209