vararg.cpp 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278
  1. ///////////////////////////////////////////////////////////////////////////////
  2. // Name: tests/strings/vararg.cpp
  3. // Purpose: Test for wx vararg look-alike macros
  4. // Author: Vaclav Slavik
  5. // Created: 2007-02-20
  6. // Copyright: (c) 2007 REA Elektronik GmbH
  7. // Licence: wxWindows licence
  8. ///////////////////////////////////////////////////////////////////////////////
  9. // ----------------------------------------------------------------------------
  10. // headers
  11. // ----------------------------------------------------------------------------
  12. #include "testprec.h"
  13. #ifdef __BORLANDC__
  14. #pragma hdrstop
  15. #endif
  16. #ifndef WX_PRECOMP
  17. #include "wx/wx.h"
  18. #endif // WX_PRECOMP
  19. #include "wx/string.h"
  20. // ----------------------------------------------------------------------------
  21. // test class
  22. // ----------------------------------------------------------------------------
  23. class VarArgTestCase : public CppUnit::TestCase
  24. {
  25. public:
  26. VarArgTestCase() {}
  27. private:
  28. CPPUNIT_TEST_SUITE( VarArgTestCase );
  29. CPPUNIT_TEST( StringPrintf );
  30. CPPUNIT_TEST( CharPrintf );
  31. #if wxUSE_STD_STRING
  32. CPPUNIT_TEST( StdString );
  33. #endif
  34. #if wxUSE_LONGLONG
  35. CPPUNIT_TEST( LongLongPrintf );
  36. #endif
  37. CPPUNIT_TEST( Sscanf );
  38. CPPUNIT_TEST( RepeatedPrintf );
  39. CPPUNIT_TEST( ArgsValidation );
  40. CPPUNIT_TEST_SUITE_END();
  41. void StringPrintf();
  42. void CharPrintf();
  43. #if wxUSE_STD_STRING
  44. void StdString();
  45. #endif
  46. #if wxUSE_LONGLONG
  47. void LongLongPrintf();
  48. #endif
  49. void Sscanf();
  50. void RepeatedPrintf();
  51. void ArgsValidation();
  52. DECLARE_NO_COPY_CLASS(VarArgTestCase)
  53. };
  54. // register in the unnamed registry so that these tests are run by default
  55. CPPUNIT_TEST_SUITE_REGISTRATION( VarArgTestCase );
  56. // also include in its own registry so that these tests can be run alone
  57. CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( VarArgTestCase, "VarArgTestCase" );
  58. void VarArgTestCase::StringPrintf()
  59. {
  60. wxString s, s2;
  61. // test passing literals:
  62. s.Printf("%s %i", "foo", 42);
  63. CPPUNIT_ASSERT( s == "foo 42" );
  64. s.Printf("%s %s %i", wxT("bar"), "=", 11);
  65. // test passing c_str():
  66. CPPUNIT_ASSERT( s == "bar = 11" );
  67. s2.Printf("(%s)", s.c_str());
  68. CPPUNIT_ASSERT( s2 == "(bar = 11)" );
  69. s2.Printf(wxT("[%s](%s)"), s.c_str(), "str");
  70. CPPUNIT_ASSERT( s2 == "[bar = 11](str)" );
  71. s2.Printf("%s mailbox", wxString("Opening").c_str());
  72. CPPUNIT_ASSERT( s2 == "Opening mailbox" );
  73. // test passing wxString directly:
  74. s2.Printf(wxT("[%s](%s)"), s, "str");
  75. CPPUNIT_ASSERT( s2 == "[bar = 11](str)" );
  76. // test passing wxCharBufferType<T>:
  77. s = "FooBar";
  78. s2.Printf(wxT("(%s)"), s.mb_str());
  79. CPPUNIT_ASSERT( s2 == "(FooBar)" );
  80. s2.Printf(wxT("value=%s;"), s.wc_str());
  81. CPPUNIT_ASSERT( s2 == "value=FooBar;" );
  82. // this tests correct passing of wxCStrData constructed from string
  83. // literal:
  84. bool cond = true;
  85. s2.Printf(wxT("foo %s"), !cond ? s.c_str() : wxT("bar"));
  86. }
  87. void VarArgTestCase::CharPrintf()
  88. {
  89. wxString foo("foo");
  90. wxString s;
  91. // test using wchar_t:
  92. s.Printf("char=%c", L'c');
  93. CPPUNIT_ASSERT_EQUAL( "char=c", s );
  94. // test wxUniCharRef:
  95. s.Printf("string[1] is %c", foo[1]);
  96. CPPUNIT_ASSERT_EQUAL( "string[1] is o", s );
  97. // test char
  98. char c = 'z';
  99. s.Printf("%c to %c", 'a', c);
  100. CPPUNIT_ASSERT_EQUAL( "a to z", s );
  101. // test char used as integer:
  102. #ifdef _MSC_VER
  103. #pragma warning(disable:4305) // truncation of constant value in VC6
  104. #pragma warning(disable:4309) // truncation of constant value
  105. #endif
  106. c = 240;
  107. #ifdef _MSC_VER
  108. #pragma warning(default:4305) // truncation of constant value in VC6
  109. #pragma warning(default:4309)
  110. #endif
  111. s.Printf("value is %i (int)", c);
  112. CPPUNIT_ASSERT_EQUAL( wxString("value is -16 (int)"), s );
  113. unsigned char u = 240;
  114. s.Printf("value is %i (int)", u);
  115. CPPUNIT_ASSERT_EQUAL( "value is 240 (int)", s );
  116. }
  117. #if wxUSE_STD_STRING
  118. void VarArgTestCase::StdString()
  119. {
  120. // test passing std::[w]string
  121. wxString s;
  122. std::string mb("multi-byte");
  123. std::string wc("widechar");
  124. s.Printf("string %s(%i).", mb, 1);
  125. CPPUNIT_ASSERT_EQUAL( "string multi-byte(1).", s );
  126. s.Printf("string %s(%i).", wc, 2);
  127. CPPUNIT_ASSERT_EQUAL( "string widechar(2).", s );
  128. }
  129. #endif // wxUSE_STD_STRING
  130. #if wxUSE_LONGLONG
  131. void VarArgTestCase::LongLongPrintf()
  132. {
  133. const char * const llfmt = "%" wxLongLongFmtSpec "d";
  134. CPPUNIT_ASSERT_EQUAL( "17", wxString::Format(llfmt, wxLL(17)) );
  135. wxLongLong ll = 1234567890;
  136. CPPUNIT_ASSERT_EQUAL( "1234567890", wxString::Format(llfmt, ll) );
  137. }
  138. #endif // wxUSE_LONGLONG
  139. void VarArgTestCase::Sscanf()
  140. {
  141. int i = 0;
  142. char str[20];
  143. wchar_t wstr[20];
  144. wxString input("42 test");
  145. wxSscanf(input, "%d %s", &i, &str);
  146. CPPUNIT_ASSERT( i == 42 );
  147. CPPUNIT_ASSERT( wxStrcmp(str, "test") == 0 );
  148. i = 0;
  149. wxSscanf(input, L"%d %s", &i, &wstr);
  150. CPPUNIT_ASSERT( i == 42 );
  151. CPPUNIT_ASSERT( wxStrcmp(wstr, "test") == 0 );
  152. }
  153. void VarArgTestCase::RepeatedPrintf()
  154. {
  155. wxCharBuffer buffer(2);
  156. char *p = buffer.data();
  157. *p = 'h';
  158. p++;
  159. *p = 'i';
  160. wxString s;
  161. s = wxString::Format("buffer %s, len %d", buffer, (int)wxStrlen(buffer));
  162. CPPUNIT_ASSERT_EQUAL("buffer hi, len 2", s);
  163. s = wxString::Format("buffer %s, len %d", buffer, (int)wxStrlen(buffer));
  164. CPPUNIT_ASSERT_EQUAL("buffer hi, len 2", s);
  165. }
  166. void VarArgTestCase::ArgsValidation()
  167. {
  168. void *ptr = this;
  169. int written;
  170. short int swritten;
  171. // these are valid:
  172. wxString::Format("a string(%s,%s), ptr %p, int %i",
  173. wxString(), "foo", "char* as pointer", 1);
  174. // Microsoft has helpfully disabled support for "%n" in their CRT by
  175. // default starting from VC8 and somehow even calling
  176. // _set_printf_count_output() doesn't help here, so don't use "%n" at all
  177. // with it.
  178. #if wxCHECK_VISUALC_VERSION(8)
  179. #define wxNO_PRINTF_PERCENT_N
  180. #endif // VC8+
  181. // Similarly, many modern Linux distributions ship with g++ that uses
  182. // -D_FORTIFY_SOURCE=2 flag by default and this option prevents "%n" from
  183. // being used in a string outside of read-only memory, meaning that it
  184. // can't be used in wxString to which we (may, depending on build options)
  185. // assign it, so also disable testing of "%n" in this case lest we die with
  186. // an abort inside vswprintf().
  187. #if defined(_FORTIFY_SOURCE)
  188. #if _FORTIFY_SOURCE >= 2
  189. #define wxNO_PRINTF_PERCENT_N
  190. #endif
  191. #endif
  192. #ifndef wxNO_PRINTF_PERCENT_N
  193. wxString::Format("foo%i%n", 42, &written);
  194. CPPUNIT_ASSERT_EQUAL( 5, written );
  195. #endif
  196. // but these are not:
  197. WX_ASSERT_FAILS_WITH_ASSERT( wxString::Format("%i", "foo") );
  198. WX_ASSERT_FAILS_WITH_ASSERT( wxString::Format("%s", (void*)this) );
  199. // for some reason assert is not generated with VC6, don't know what's
  200. // going there so disable it for now to make the test suite pass when using
  201. // this compiler until someone has time to debug this (FIXME-VC6)
  202. #ifndef __VISUALC6__
  203. WX_ASSERT_FAILS_WITH_ASSERT( wxString::Format("%d", ptr) );
  204. #endif
  205. // we don't check wxNO_PRINTF_PERCENT_N here as these expressions should
  206. // result in an assert in our code before the CRT functions are even called
  207. WX_ASSERT_FAILS_WITH_ASSERT( wxString::Format("foo%i%n", &written) );
  208. WX_ASSERT_FAILS_WITH_ASSERT( wxString::Format("foo%n", ptr) );
  209. WX_ASSERT_FAILS_WITH_ASSERT( wxString::Format("foo%i%n", 42, &swritten) );
  210. // the following test (correctly) fails at compile-time with <type_traits>
  211. #if !defined(HAVE_TYPE_TRAITS) && !defined(HAVE_TR1_TYPE_TRAITS)
  212. wxObject obj;
  213. WX_ASSERT_FAILS_WITH_ASSERT( wxString::Format("%s", obj) );
  214. wxObject& ref = obj;
  215. WX_ASSERT_FAILS_WITH_ASSERT( wxString::Format("%s", ref) );
  216. #endif
  217. // %c should accept integers too
  218. wxString::Format("%c", 80);
  219. wxString::Format("%c", wxChar(80) + wxChar(1));
  220. // check size_t handling
  221. size_t len = sizeof(*this);
  222. #ifdef __WINDOWS__
  223. wxString::Format("%Iu", len);
  224. #else
  225. wxString::Format("%zu", len);
  226. #endif
  227. }