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