formatconvertertest.cpp 12 KB

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