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