]> git.saurik.com Git - wxWidgets.git/blame - tests/formatconverter/formatconvertertest.cpp
undid change of r44565: not taking hyphens into account entirely is a bad idea as...
[wxWidgets.git] / tests / formatconverter / formatconvertertest.cpp
CommitLineData
7d5ab151
VS
1///////////////////////////////////////////////////////////////////////////////
2// Name: tests/formatconverter/formatconverter.cpp
3// Purpose: Test wxFormatConverter
4// Author: Mike Wetherell
5// RCS-ID: $Id$
6// Copyright: (c) 2004 Mike Wetherell
7// Licence: wxWidgets licence
8///////////////////////////////////////////////////////////////////////////////
9
10//
11// Notes:
12//
13// The conversions wxFormatConverter currently does are as follows:
14//
15// %s, %lS -> %ls
16// %S, %hS -> %s
17// %c, %lC -> %lc
18// %C, %hC -> %c
19//
20// %hs and %hc stay the same.
21//
22// %S and %C aren't actually in the ISO C or C++ standards, but they can be
23// avoided when writing portable code.
24//
25// Nor are %hs or %hc in the standards, which means wxWidgets currently doesn't
26// have a specifier for 'char' types that is ok for all builds and platforms.
27//
28// The effect of using %hs/%hc is undefined, though RTLs are quite likely
29// to just ignore the 'h', so maybe it works as required even though it's
30// not legal.
31//
32// I've put in some checks, such as this which will flag up any platforms
33// where this is not the case:
34//
35// CPPUNIT_ASSERT(wxString::Format(_T("%hs"), "test") == _T("test"));
36//
37
7d5ab151 38// For compilers that support precompilation, includes "wx/wx.h".
8899b155 39#include "testprec.h"
7d5ab151
VS
40
41#ifdef __BORLANDC__
42 #pragma hdrstop
43#endif
44
45// for all others, include the necessary headers
46#ifndef WX_PRECOMP
47 #include "wx/wx.h"
48#endif
49
7d5ab151 50
3e5f6c1c
WS
51using CppUnit::TestCase;
52using std::string;
7d5ab151
VS
53
54///////////////////////////////////////////////////////////////////////////////
55// The test case
56//
57// wxFormatConverter only changes %s, %c, %S and %C, all others are treated
58// equally, therefore it is enough to choose just one other for testing, %d
59// will do.
60
61class FormatConverterTestCase : public TestCase
62{
63 CPPUNIT_TEST_SUITE(FormatConverterTestCase);
64 CPPUNIT_TEST(format_d);
65 CPPUNIT_TEST(format_hd);
66 CPPUNIT_TEST(format_ld);
67 CPPUNIT_TEST(format_s);
68 CPPUNIT_TEST(format_hs);
69 CPPUNIT_TEST(format_ls);
70 CPPUNIT_TEST(format_c);
71 CPPUNIT_TEST(format_hc);
72 CPPUNIT_TEST(format_lc);
7d5ab151
VS
73 CPPUNIT_TEST(format_S);
74 CPPUNIT_TEST(format_hS);
75 CPPUNIT_TEST(format_lS);
76 CPPUNIT_TEST(format_C);
77 CPPUNIT_TEST(format_hC);
78 CPPUNIT_TEST(format_lC);
79 CPPUNIT_TEST(testLonger);
7d5ab151
VS
80 CPPUNIT_TEST_SUITE_END();
81
7d5ab151
VS
82 void format_d();
83 void format_hd();
84 void format_ld();
85 void format_s();
86 void format_hs();
87 void format_ls();
88 void format_c();
89 void format_hc();
90 void format_lc();
91
7d5ab151
VS
92 void format_S();
93 void format_hS();
94 void format_lS();
95 void format_C();
96 void format_hC();
97 void format_lC();
98 void testLonger();
99
50e27899
VS
100 void doTest(const char *input, const char *expectedScanf,
101 const char *expectedUtf8,
102 const char *expectedWcharUnix,
103 const char *expectedWcharWindows);
104 void check(const wxString& input, const wxString& expectedScanf,
105 const wxString& expectedUtf8,
106 const wxString& expectedWcharUnix,
107 const wxString& expectedWcharWindows);
7d5ab151
VS
108};
109
110void FormatConverterTestCase::format_d()
111{
50e27899 112 doTest("d", "d", "d", "d", "d");
7d5ab151 113 CPPUNIT_ASSERT(wxString::Format(_T("%d"), 255) == _T("255"));
8dae9169
VS
114 CPPUNIT_ASSERT(wxString::Format(_T("%05d"), 255) == _T("00255"));
115 CPPUNIT_ASSERT(wxString::Format(_T("% 5d"), 255) == _T(" 255"));
116 CPPUNIT_ASSERT(wxString::Format(_T("% 5d"), -255) == _T(" -255"));
117 CPPUNIT_ASSERT(wxString::Format(_T("%-5d"), -255) == _T("-255 "));
118 CPPUNIT_ASSERT(wxString::Format(_T("%+5d"), 255) == _T(" +255"));
119 CPPUNIT_ASSERT(wxString::Format(_T("%*d"), 5, 255) == _T(" 255"));
7d5ab151
VS
120}
121
122void FormatConverterTestCase::format_hd()
123{
50e27899 124 doTest("hd", "hd", "hd", "hd", "hd");
7d5ab151
VS
125 short s = 32767;
126 CPPUNIT_ASSERT(wxString::Format(_T("%hd"), s) == _T("32767"));
127}
128
129void FormatConverterTestCase::format_ld()
130{
50e27899 131 doTest("ld", "ld", "ld", "ld", "ld");
7d5ab151
VS
132 long l = 2147483647L;
133 CPPUNIT_ASSERT(wxString::Format(_T("%ld"), l) == _T("2147483647"));
134}
135
136void FormatConverterTestCase::format_s()
137{
50e27899 138 doTest("s", "ls", "s", "ls", "s");
8dae9169
VS
139 CPPUNIT_ASSERT(wxString::Format(_T("%s!"), _T("test")) == _T("test!"));
140 CPPUNIT_ASSERT(wxString::Format(_T("%6s!"), _T("test")) == _T(" test!"));
141 CPPUNIT_ASSERT(wxString::Format(_T("%-6s!"), _T("test")) == _T("test !"));
142 CPPUNIT_ASSERT(wxString::Format(_T("%.6s!"), _T("test")) == _T("test!"));
143 CPPUNIT_ASSERT(wxString::Format(_T("%6.4s!"), _T("testing")) == _T(" test!"));
7d5ab151
VS
144}
145
146void FormatConverterTestCase::format_hs()
147{
50e27899 148 doTest("hs", "hs", "s", "ls", "s");
8dae9169
VS
149 CPPUNIT_ASSERT(wxString::Format(wxString(_T("%hs!")), "test") == _T("test!"));
150 CPPUNIT_ASSERT(wxString::Format(wxString(_T("%6hs!")), "test") == _T(" test!"));
151 CPPUNIT_ASSERT(wxString::Format(wxString(_T("%-6hs!")), "test") == _T("test !"));
152 CPPUNIT_ASSERT(wxString::Format(wxString(_T("%.6hs!")), "test") == _T("test!"));
153 CPPUNIT_ASSERT(wxString::Format(wxString(_T("%6.4hs!")), "testing") == _T(" test!"));
7d5ab151
VS
154}
155
156void FormatConverterTestCase::format_ls()
157{
50e27899 158 doTest("ls", "ls", "s", "ls", "s");
8dae9169
VS
159 CPPUNIT_ASSERT(wxString::Format(_T("%ls!"), L"test") == _T("test!"));
160 CPPUNIT_ASSERT(wxString::Format(_T("%6ls!"), L"test") == _T(" test!"));
161 CPPUNIT_ASSERT(wxString::Format(_T("%-6ls!"), L"test") == _T("test !"));
162 CPPUNIT_ASSERT(wxString::Format(_T("%.6ls!"), L"test") == _T("test!"));
163 CPPUNIT_ASSERT(wxString::Format(_T("%6.4ls!"), L"testing") == _T(" test!"));
7d5ab151
VS
164}
165
166void FormatConverterTestCase::format_c()
167{
50e27899 168 doTest("c", "lc", "s", "lc", "c");
7d5ab151 169 CPPUNIT_ASSERT(wxString::Format(_T("%c"), _T('x')) == _T("x"));
8dae9169
VS
170 CPPUNIT_ASSERT(wxString::Format(_T("%2c"), _T('x')) == _T(" x"));
171 CPPUNIT_ASSERT(wxString::Format(_T("%-2c"), _T('x')) == _T("x "));
7d5ab151
VS
172}
173
174void FormatConverterTestCase::format_hc()
175{
50e27899 176 doTest("hc", "hc", "s", "lc", "c");
8dae9169
VS
177 CPPUNIT_ASSERT(wxString::Format(wxString(_T("%hc")), 'x') == _T("x"));
178 CPPUNIT_ASSERT(wxString::Format(wxString(_T("%2hc")), 'x') == _T(" x"));
179 CPPUNIT_ASSERT(wxString::Format(wxString(_T("%-2hc")), 'x') == _T("x "));
7d5ab151
VS
180}
181
182void FormatConverterTestCase::format_lc()
183{
50e27899 184 doTest("lc", "lc", "s", "lc", "c");
7d5ab151 185 CPPUNIT_ASSERT(wxString::Format(_T("%lc"), L'x') == _T("x"));
8dae9169
VS
186 CPPUNIT_ASSERT(wxString::Format(_T("%2lc"), L'x') == _T(" x"));
187 CPPUNIT_ASSERT(wxString::Format(_T("%-2lc"), L'x') == _T("x "));
7d5ab151
VS
188}
189
7d5ab151 190
50e27899
VS
191void FormatConverterTestCase::format_S()
192 { doTest("S", "s", "s", "ls", "s"); }
193void FormatConverterTestCase::format_hS()
194 { doTest("hS", "s", "s", "ls", "s"); }
195void FormatConverterTestCase::format_lS()
196 { doTest("lS", "ls", "s", "ls", "s"); }
7d5ab151 197
50e27899
VS
198void FormatConverterTestCase::format_C()
199 { doTest("C", "c", "s", "lc", "c"); }
200void FormatConverterTestCase::format_hC()
201 { doTest("hC", "c", "s", "lc", "c"); }
202void FormatConverterTestCase::format_lC()
203 { doTest("lC", "lc", "s", "lc", "c"); }
7d5ab151
VS
204
205// It's possible that although a format converts correctly alone, it leaves
206// the converter in a bad state that will affect subsequent formats, so
207// check with a selection of longer patterns.
208//
209void FormatConverterTestCase::testLonger()
210{
211 struct {
50e27899
VS
212 const char *input;
213 const char *expectedScanf;
214 const char *expectedWcharUnix;
215 const char *expectedWcharWindows;
216 const char *expectedUtf8;
7d5ab151 217 } formats[] = {
50e27899
VS
218 { "%d", "%d", "%d", "%d", "%d" },
219 { "%*hd", "%*hd", "%*hd", "%*hd", "%*hd" },
220 { "%.4ld", "%.4ld", "%.4ld", "%.4ld", "%.4ld" },
221 { "%-.*s", "%-.*ls", "%-.*ls", "%-.*s", "%-.*s" },
222 { "%.*hs", "%.*hs", "%.*ls", "%.*s", "%.*s" },
223 { "%-.9ls", "%-.9ls", "%-.9ls", "%-.9s", "%-.9s" },
224 { "%-*c", "%-*lc", "%-*lc", "%-*c", "%-*s" },
225 { "%3hc", "%3hc", "%3lc", "%3c", "%3s" },
226 { "%-5lc", "%-5lc", "%-5lc", "%-5c", "%-5s" }
7d5ab151
VS
227 };
228 size_t i, j;
229
7d5ab151
VS
230 // test all possible pairs of the above patterns
231 for (i = 0; i < WXSIZEOF(formats); i++) {
232 if (formats[i].input) {
233 wxString input(formats[i].input);
50e27899
VS
234 wxString expectedScanf(formats[i].expectedScanf);
235 wxString expectedUtf8(formats[i].expectedUtf8);
236 wxString expectedWcharUnix(formats[i].expectedWcharUnix);
237 wxString expectedWcharWindows(formats[i].expectedWcharWindows);
7d5ab151
VS
238
239 for (j = 0; j < WXSIZEOF(formats); j++)
240 if (formats[j].input)
241 check(input + formats[j].input,
50e27899
VS
242 expectedScanf + formats[j].expectedScanf,
243 expectedUtf8 + formats[j].expectedUtf8,
244 expectedWcharUnix + formats[j].expectedWcharUnix,
245 expectedWcharWindows + formats[j].expectedWcharWindows);
7d5ab151
VS
246 }
247 }
248}
249
50e27899
VS
250void FormatConverterTestCase::doTest(const char *input,
251 const char *expectedScanf,
252 const char *expectedUtf8,
253 const char *expectedWcharUnix,
254 const char *expectedWcharWindows)
7d5ab151
VS
255{
256 static const wxChar *flag_width[] =
257 { _T(""), _T("*"), _T("10"), _T("-*"), _T("-10"), NULL };
258 static const wxChar *precision[] =
259 { _T(""), _T(".*"), _T(".10"), NULL };
260 static const wxChar *empty[] =
261 { _T(""), NULL };
262
263 // no precision for %c or %C
264 const wxChar **precs = wxTolower(input[wxStrlen(input)-1]) == _T('c') ?
265 empty : precision;
266
267 wxString fmt(_T("%"));
268
269 // try the test for a variety of combinations of flag, width and precision
270 for (const wxChar **prec = precs; *prec; prec++)
271 for (const wxChar **width = flag_width; *width; width++)
272 check(fmt + *width + *prec + input,
50e27899
VS
273 fmt + *width + *prec + expectedScanf,
274 fmt + *width + *prec + expectedUtf8,
275 fmt + *width + *prec + expectedWcharUnix,
276 fmt + *width + *prec + expectedWcharWindows);
7d5ab151
VS
277}
278
279void FormatConverterTestCase::check(const wxString& input,
50e27899
VS
280 const wxString& expectedScanf,
281 const wxString& expectedUtf8,
282 const wxString& expectedWcharUnix,
283 const wxString& expectedWcharWindows)
7d5ab151 284{
2452025c
VZ
285 // all of them are unused in some build configurations
286 wxUnusedVar(expectedScanf);
287 wxUnusedVar(expectedUtf8);
288 wxUnusedVar(expectedWcharUnix);
289 wxUnusedVar(expectedWcharWindows);
290
50e27899
VS
291 wxString result, msg;
292
293#ifndef __WINDOWS__
294 // on windows, wxScanf() string needs no modifications
295 result = wxScanfConvertFormatW(input.wc_str());
296
297 msg = _T("input: '") + input +
298 _T("', result (scanf): '") + result +
299 _T("', expected: '") + expectedScanf + _T("'");
300 CPPUNIT_ASSERT_MESSAGE(string(msg.mb_str()), result == expectedScanf);
301#endif // !__WINDOWS__
302
303#if wxUSE_UNICODE_UTF8
304 result = (const char*)wxFormatString(input);
305
306 msg = _T("input: '") + input +
307 _T("', result (UTF-8): '") + result +
308 _T("', expected: '") + expectedUtf8 + _T("'");
309 CPPUNIT_ASSERT_MESSAGE(string(msg.mb_str()), result == expectedUtf8);
310#endif // wxUSE_UNICODE_UTF8
311
312#if wxUSE_UNICODE && !wxUSE_UTF8_LOCALE_ONLY
313 result = (const wchar_t*)wxFormatString(input);
314
315#ifdef __WINDOWS__
316 wxString expectedWchar(expectedWcharWindows);
317#else
318 wxString expectedWchar(expectedWcharUnix);
319#endif
320
321 msg = _T("input: '") + input +
322 _T("', result (wchar_t): '") + result +
323 _T("', expected: '") + expectedWchar + _T("'");
324 CPPUNIT_ASSERT_MESSAGE(string(msg.mb_str()), result == expectedWchar);
325#endif // wxUSE_UNICODE && !wxUSE_UTF8_LOCALE_ONLY
7d5ab151
VS
326}
327
7d5ab151
VS
328
329// register in the unnamed registry so that these tests are run by default
330CPPUNIT_TEST_SUITE_REGISTRATION(FormatConverterTestCase);
331
332// also include in it's own registry so that these tests can be run alone
333CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(FormatConverterTestCase,
334 "FormatConverterTestCase");
335