]> git.saurik.com Git - wxWidgets.git/blob - tests/formatconverter/formatconverter.cpp
db20c22098d9d2a47513db0032f2e492f16cb3db
[wxWidgets.git] / tests / formatconverter / formatconverter.cpp
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
38 #if defined(__GNUG__) && !defined(__APPLE__)
39 #pragma implementation
40 #pragma interface
41 #endif
42
43 // For compilers that support precompilation, includes "wx/wx.h".
44 #include "wx/wxprec.h"
45
46 #ifdef __BORLANDC__
47 #pragma hdrstop
48 #endif
49
50 // for all others, include the necessary headers
51 #ifndef WX_PRECOMP
52 #include "wx/wx.h"
53 #endif
54
55 #include "wx/cppunit.h"
56
57 // wxFormatConverter can only be tested in a Unicode non-Windows debug build
58 //
59 #if defined(wxNEED_PRINTF_CONVERSION) && defined(__WXDEBUG__)
60 #define CAN_TEST
61 extern wxString wxConvertFormat(const wxChar *format);
62 #endif
63
64 using namespace std;
65 using namespace CppUnit;
66
67
68 ///////////////////////////////////////////////////////////////////////////////
69 // The test case
70 //
71 // wxFormatConverter only changes %s, %c, %S and %C, all others are treated
72 // equally, therefore it is enough to choose just one other for testing, %d
73 // will do.
74
75 class FormatConverterTestCase : public TestCase
76 {
77 CPPUNIT_TEST_SUITE(FormatConverterTestCase);
78 CPPUNIT_TEST(format_d);
79 CPPUNIT_TEST(format_hd);
80 CPPUNIT_TEST(format_ld);
81 CPPUNIT_TEST(format_s);
82 CPPUNIT_TEST(format_hs);
83 CPPUNIT_TEST(format_ls);
84 CPPUNIT_TEST(format_c);
85 CPPUNIT_TEST(format_hc);
86 CPPUNIT_TEST(format_lc);
87 #ifdef CAN_TEST
88 CPPUNIT_TEST(format_S);
89 CPPUNIT_TEST(format_hS);
90 CPPUNIT_TEST(format_lS);
91 CPPUNIT_TEST(format_C);
92 CPPUNIT_TEST(format_hC);
93 CPPUNIT_TEST(format_lC);
94 CPPUNIT_TEST(testLonger);
95 #endif
96 CPPUNIT_TEST_SUITE_END();
97
98 private:
99 void format_d();
100 void format_hd();
101 void format_ld();
102 void format_s();
103 void format_hs();
104 void format_ls();
105 void format_c();
106 void format_hc();
107 void format_lc();
108
109 #ifdef CAN_TEST
110 void format_S();
111 void format_hS();
112 void format_lS();
113 void format_C();
114 void format_hC();
115 void format_lC();
116 void testLonger();
117
118 void doTest(const wxChar *input, const wxChar *expected);
119 void check(const wxString& input, const wxString& expected);
120 #endif
121 };
122
123 void FormatConverterTestCase::format_d()
124 {
125 #ifdef CAN_TEST
126 doTest(_T("d"), _T("d"));
127 #endif
128 CPPUNIT_ASSERT(wxString::Format(_T("%d"), 255) == _T("255"));
129 }
130
131 void FormatConverterTestCase::format_hd()
132 {
133 #ifdef CAN_TEST
134 doTest(_T("hd"), _T("hd"));
135 #endif
136 short s = 32767;
137 CPPUNIT_ASSERT(wxString::Format(_T("%hd"), s) == _T("32767"));
138 }
139
140 void FormatConverterTestCase::format_ld()
141 {
142 #ifdef CAN_TEST
143 doTest(_T("ld"), _T("ld"));
144 #endif
145 long l = 2147483647L;
146 CPPUNIT_ASSERT(wxString::Format(_T("%ld"), l) == _T("2147483647"));
147 }
148
149 void FormatConverterTestCase::format_s()
150 {
151 #ifdef CAN_TEST
152 doTest(_T("s"), _T("ls"));
153 #endif
154 CPPUNIT_ASSERT(wxString::Format(_T("%s"), _T("test")) == _T("test"));
155 }
156
157 void FormatConverterTestCase::format_hs()
158 {
159 #ifdef CAN_TEST
160 doTest(_T("hs"), _T("hs"));
161 #endif
162 CPPUNIT_ASSERT(wxString::Format(_T("%hs"), "test") == _T("test"));
163 }
164
165 void FormatConverterTestCase::format_ls()
166 {
167 #ifdef CAN_TEST
168 doTest(_T("ls"), _T("ls"));
169 #endif
170 CPPUNIT_ASSERT(wxString::Format(_T("%ls"), L"test") == _T("test"));
171 }
172
173 void FormatConverterTestCase::format_c()
174 {
175 #ifdef CAN_TEST
176 doTest(_T("c"), _T("lc"));
177 #endif
178 CPPUNIT_ASSERT(wxString::Format(_T("%c"), _T('x')) == _T("x"));
179 }
180
181 void FormatConverterTestCase::format_hc()
182 {
183 #ifdef CAN_TEST
184 doTest(_T("hc"), _T("hc"));
185 #endif
186 CPPUNIT_ASSERT(wxString::Format(_T("%hc"), 'x') == _T("x"));
187 }
188
189 void FormatConverterTestCase::format_lc()
190 {
191 #ifdef CAN_TEST
192 doTest(_T("lc"), _T("lc"));
193 #endif
194 CPPUNIT_ASSERT(wxString::Format(_T("%lc"), L'x') == _T("x"));
195 }
196
197 #ifdef CAN_TEST
198
199 void FormatConverterTestCase::format_S() { doTest(_T("S"), _T("s")); }
200 void FormatConverterTestCase::format_hS() { doTest(_T("hS"), _T("s")); }
201 void FormatConverterTestCase::format_lS() { doTest(_T("lS"), _T("ls")); }
202
203 void FormatConverterTestCase::format_C() { doTest(_T("C"), _T("c")); }
204 void FormatConverterTestCase::format_hC() { doTest(_T("hC"), _T("c")); }
205 void FormatConverterTestCase::format_lC() { doTest(_T("lC"), _T("lc")); }
206
207 // It's possible that although a format converts correctly alone, it leaves
208 // the converter in a bad state that will affect subsequent formats, so
209 // check with a selection of longer patterns.
210 //
211 void FormatConverterTestCase::testLonger()
212 {
213 struct {
214 const wxChar *input;
215 const wxChar *expected;
216 } formats[] = {
217 { _T("%d"), _T("%d"), },
218 { _T("%*hd"), _T("%*hd") },
219 { _T("%.4ld"), _T("%.4ld") },
220 { _T("%-.*s"), _T("%-.*ls") },
221 { _T("%.*hs"), _T("%.*hs"), },
222 { _T("%-.9ls"), _T("%-.9ls") },
223 { _T("%-*c"), _T("%-*lc") },
224 { _T("%3hc"), _T("%3hc") },
225 { _T("%-5lc"), _T("%-5lc") }
226 };
227 size_t i, j;
228
229 // exclude patterns that don't translate correctly alone from the test
230 for (i = 0; i < WXSIZEOF(formats); i++)
231 if (wxConvertFormat(formats[i].input) != formats[i].expected)
232 formats[i].input = NULL;
233
234 // test all possible pairs of the above patterns
235 for (i = 0; i < WXSIZEOF(formats); i++) {
236 if (formats[i].input) {
237 wxString input(formats[i].input);
238 wxString expected(formats[i].expected);
239
240 for (j = 0; j < WXSIZEOF(formats); j++)
241 if (formats[j].input)
242 check(input + formats[j].input,
243 expected + formats[j].expected);
244 }
245 }
246 }
247
248 void FormatConverterTestCase::doTest(const wxChar *input,
249 const wxChar *expected)
250 {
251 static const wxChar *flag_width[] =
252 { _T(""), _T("*"), _T("10"), _T("-*"), _T("-10"), NULL };
253 static const wxChar *precision[] =
254 { _T(""), _T(".*"), _T(".10"), NULL };
255 static const wxChar *empty[] =
256 { _T(""), NULL };
257
258 // no precision for %c or %C
259 const wxChar **precs = wxTolower(input[wxStrlen(input)-1]) == _T('c') ?
260 empty : precision;
261
262 wxString fmt(_T("%"));
263
264 // try the test for a variety of combinations of flag, width and precision
265 for (const wxChar **prec = precs; *prec; prec++)
266 for (const wxChar **width = flag_width; *width; width++)
267 check(fmt + *width + *prec + input,
268 fmt + *width + *prec + expected);
269 }
270
271 void FormatConverterTestCase::check(const wxString& input,
272 const wxString& expected)
273 {
274 wxString result = wxConvertFormat(input);
275 wxString msg = _T("input: '") + input +
276 _T("', result: '") + result +
277 _T("', expected: '") + expected + _T("'");
278 CPPUNIT_ASSERT_MESSAGE(string(msg.mb_str()), result == expected);
279 }
280
281 #endif // CAN_TEST
282
283 // register in the unnamed registry so that these tests are run by default
284 CPPUNIT_TEST_SUITE_REGISTRATION(FormatConverterTestCase);
285
286 // also include in it's own registry so that these tests can be run alone
287 CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(FormatConverterTestCase,
288 "FormatConverterTestCase");
289