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