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