/////////////////////////////////////////////////////////////////////////////// // Name: tests/formatconverter/formatconverter.cpp // Purpose: Test wxFormatConverter // Author: Mike Wetherell // RCS-ID: $Id$ // Copyright: (c) 2004 Mike Wetherell // Licence: wxWidgets licence /////////////////////////////////////////////////////////////////////////////// // // Notes: // // The conversions wxFormatConverter currently does are as follows: // // %s, %lS -> %ls // %S, %hS -> %s // %c, %lC -> %lc // %C, %hC -> %c // // %hs and %hc stay the same. // // %S and %C aren't actually in the ISO C or C++ standards, but they can be // avoided when writing portable code. // // Nor are %hs or %hc in the standards, which means wxWidgets currently doesn't // have a specifier for 'char' types that is ok for all builds and platforms. // // The effect of using %hs/%hc is undefined, though RTLs are quite likely // to just ignore the 'h', so maybe it works as required even though it's // not legal. // // I've put in some checks, such as this which will flag up any platforms // where this is not the case: // // CPPUNIT_ASSERT(wxString::Format(_T("%hs"), "test") == _T("test")); // #if defined(__GNUG__) && !defined(__APPLE__) #pragma implementation #pragma interface #endif // For compilers that support precompilation, includes "wx/wx.h". #include "wx/wxprec.h" #ifdef __BORLANDC__ #pragma hdrstop #endif // for all others, include the necessary headers #ifndef WX_PRECOMP #include "wx/wx.h" #endif #include "wx/cppunit.h" // wxFormatConverter can only be tested in a Unicode non-Windows debug build // #if defined(wxNEED_PRINTF_CONVERSION) && defined(__WXDEBUG__) #define CAN_TEST extern wxString wxConvertFormat(const wxChar *format); #endif using namespace std; using namespace CppUnit; /////////////////////////////////////////////////////////////////////////////// // The test case // // wxFormatConverter only changes %s, %c, %S and %C, all others are treated // equally, therefore it is enough to choose just one other for testing, %d // will do. class FormatConverterTestCase : public TestCase { CPPUNIT_TEST_SUITE(FormatConverterTestCase); CPPUNIT_TEST(format_d); CPPUNIT_TEST(format_hd); CPPUNIT_TEST(format_ld); CPPUNIT_TEST(format_s); CPPUNIT_TEST(format_hs); CPPUNIT_TEST(format_ls); CPPUNIT_TEST(format_c); CPPUNIT_TEST(format_hc); CPPUNIT_TEST(format_lc); #ifdef CAN_TEST CPPUNIT_TEST(format_S); CPPUNIT_TEST(format_hS); CPPUNIT_TEST(format_lS); CPPUNIT_TEST(format_C); CPPUNIT_TEST(format_hC); CPPUNIT_TEST(format_lC); CPPUNIT_TEST(testLonger); #endif CPPUNIT_TEST_SUITE_END(); private: void format_d(); void format_hd(); void format_ld(); void format_s(); void format_hs(); void format_ls(); void format_c(); void format_hc(); void format_lc(); #ifdef CAN_TEST void format_S(); void format_hS(); void format_lS(); void format_C(); void format_hC(); void format_lC(); void testLonger(); void doTest(const wxChar *input, const wxChar *expected); void check(const wxString& input, const wxString& expected); #endif }; void FormatConverterTestCase::format_d() { #ifdef CAN_TEST doTest(_T("d"), _T("d")); #endif CPPUNIT_ASSERT(wxString::Format(_T("%d"), 255) == _T("255")); } void FormatConverterTestCase::format_hd() { #ifdef CAN_TEST doTest(_T("hd"), _T("hd")); #endif short s = 32767; CPPUNIT_ASSERT(wxString::Format(_T("%hd"), s) == _T("32767")); } void FormatConverterTestCase::format_ld() { #ifdef CAN_TEST doTest(_T("ld"), _T("ld")); #endif long l = 2147483647L; CPPUNIT_ASSERT(wxString::Format(_T("%ld"), l) == _T("2147483647")); } void FormatConverterTestCase::format_s() { #ifdef CAN_TEST doTest(_T("s"), _T("ls")); #endif CPPUNIT_ASSERT(wxString::Format(_T("%s"), _T("test")) == _T("test")); } void FormatConverterTestCase::format_hs() { #ifdef CAN_TEST doTest(_T("hs"), _T("hs")); #endif CPPUNIT_ASSERT(wxString::Format(_T("%hs"), "test") == _T("test")); } void FormatConverterTestCase::format_ls() { #ifdef CAN_TEST doTest(_T("ls"), _T("ls")); #endif CPPUNIT_ASSERT(wxString::Format(_T("%ls"), L"test") == _T("test")); } void FormatConverterTestCase::format_c() { #ifdef CAN_TEST doTest(_T("c"), _T("lc")); #endif CPPUNIT_ASSERT(wxString::Format(_T("%c"), _T('x')) == _T("x")); } void FormatConverterTestCase::format_hc() { #ifdef CAN_TEST doTest(_T("hc"), _T("hc")); #endif CPPUNIT_ASSERT(wxString::Format(_T("%hc"), 'x') == _T("x")); } void FormatConverterTestCase::format_lc() { #ifdef CAN_TEST doTest(_T("lc"), _T("lc")); #endif CPPUNIT_ASSERT(wxString::Format(_T("%lc"), L'x') == _T("x")); } #ifdef CAN_TEST void FormatConverterTestCase::format_S() { doTest(_T("S"), _T("s")); } void FormatConverterTestCase::format_hS() { doTest(_T("hS"), _T("s")); } void FormatConverterTestCase::format_lS() { doTest(_T("lS"), _T("ls")); } void FormatConverterTestCase::format_C() { doTest(_T("C"), _T("c")); } void FormatConverterTestCase::format_hC() { doTest(_T("hC"), _T("c")); } void FormatConverterTestCase::format_lC() { doTest(_T("lC"), _T("lc")); } // It's possible that although a format converts correctly alone, it leaves // the converter in a bad state that will affect subsequent formats, so // check with a selection of longer patterns. // void FormatConverterTestCase::testLonger() { struct { const wxChar *input; const wxChar *expected; } formats[] = { { _T("%d"), _T("%d"), }, { _T("%*hd"), _T("%*hd") }, { _T("%.4ld"), _T("%.4ld") }, { _T("%-.*s"), _T("%-.*ls") }, { _T("%.*hs"), _T("%.*hs"), }, { _T("%-.9ls"), _T("%-.9ls") }, { _T("%-*c"), _T("%-*lc") }, { _T("%3hc"), _T("%3hc") }, { _T("%-5lc"), _T("%-5lc") } }; size_t i, j; // exclude patterns that don't translate correctly alone from the test for (i = 0; i < WXSIZEOF(formats); i++) if (wxConvertFormat(formats[i].input) != formats[i].expected) formats[i].input = NULL; // test all possible pairs of the above patterns for (i = 0; i < WXSIZEOF(formats); i++) { if (formats[i].input) { wxString input(formats[i].input); wxString expected(formats[i].expected); for (j = 0; j < WXSIZEOF(formats); j++) if (formats[j].input) check(input + formats[j].input, expected + formats[j].expected); } } } void FormatConverterTestCase::doTest(const wxChar *input, const wxChar *expected) { static const wxChar *flag_width[] = { _T(""), _T("*"), _T("10"), _T("-*"), _T("-10"), NULL }; static const wxChar *precision[] = { _T(""), _T(".*"), _T(".10"), NULL }; static const wxChar *empty[] = { _T(""), NULL }; // no precision for %c or %C const wxChar **precs = wxTolower(input[wxStrlen(input)-1]) == _T('c') ? empty : precision; wxString fmt(_T("%")); // try the test for a variety of combinations of flag, width and precision for (const wxChar **prec = precs; *prec; prec++) for (const wxChar **width = flag_width; *width; width++) check(fmt + *width + *prec + input, fmt + *width + *prec + expected); } void FormatConverterTestCase::check(const wxString& input, const wxString& expected) { wxString result = wxConvertFormat(input); wxString msg = _T("input: '") + input + _T("', result: '") + result + _T("', expected: '") + expected + _T("'"); CPPUNIT_ASSERT_MESSAGE(string(msg.mb_str()), result == expected); } #endif // CAN_TEST // register in the unnamed registry so that these tests are run by default CPPUNIT_TEST_SUITE_REGISTRATION(FormatConverterTestCase); // also include in it's own registry so that these tests can be run alone CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(FormatConverterTestCase, "FormatConverterTestCase");