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