Disable test of format string with "%n" for MSVC 8+.
[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 // RCS-ID: $Id$
7 // Copyright: (c) 2007 REA Elektronik GmbH
8 // Licence: wxWindows licence
9 ///////////////////////////////////////////////////////////////////////////////
10
11 // ----------------------------------------------------------------------------
12 // headers
13 // ----------------------------------------------------------------------------
14
15 #include "testprec.h"
16
17 #ifdef __BORLANDC__
18 #pragma hdrstop
19 #endif
20
21 #ifndef WX_PRECOMP
22 #include "wx/wx.h"
23 #endif // WX_PRECOMP
24
25 #include "wx/string.h"
26
27 // ----------------------------------------------------------------------------
28 // test class
29 // ----------------------------------------------------------------------------
30
31 class VarArgTestCase : public CppUnit::TestCase
32 {
33 public:
34 VarArgTestCase() {}
35
36 private:
37 CPPUNIT_TEST_SUITE( VarArgTestCase );
38 CPPUNIT_TEST( StringPrintf );
39 CPPUNIT_TEST( CharPrintf );
40 #if wxUSE_STD_STRING
41 CPPUNIT_TEST( StdString );
42 #endif
43 CPPUNIT_TEST( Sscanf );
44 CPPUNIT_TEST( RepeatedPrintf );
45 CPPUNIT_TEST( ArgsValidation );
46 CPPUNIT_TEST_SUITE_END();
47
48 void StringPrintf();
49 void CharPrintf();
50 #if wxUSE_STD_STRING
51 void StdString();
52 #endif
53 void Sscanf();
54 void RepeatedPrintf();
55 void ArgsValidation();
56
57 DECLARE_NO_COPY_CLASS(VarArgTestCase)
58 };
59
60 // register in the unnamed registry so that these tests are run by default
61 CPPUNIT_TEST_SUITE_REGISTRATION( VarArgTestCase );
62
63 // also include in it's own registry so that these tests can be run alone
64 CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( VarArgTestCase, "VarArgTestCase" );
65
66 void VarArgTestCase::StringPrintf()
67 {
68 wxString s, s2;
69
70 // test passing literals:
71 s.Printf("%s %i", "foo", 42);
72 CPPUNIT_ASSERT( s == "foo 42" );
73 s.Printf("%s %s %i", wxT("bar"), "=", 11);
74
75 // test passing c_str():
76 CPPUNIT_ASSERT( s == "bar = 11" );
77 s2.Printf("(%s)", s.c_str());
78 CPPUNIT_ASSERT( s2 == "(bar = 11)" );
79 s2.Printf(wxT("[%s](%s)"), s.c_str(), "str");
80 CPPUNIT_ASSERT( s2 == "[bar = 11](str)" );
81
82 s2.Printf("%s mailbox", wxString("Opening").c_str());
83 CPPUNIT_ASSERT( s2 == "Opening mailbox" );
84
85 // test passing wxString directly:
86 s2.Printf(wxT("[%s](%s)"), s, "str");
87 CPPUNIT_ASSERT( s2 == "[bar = 11](str)" );
88
89 // test passing wxCharBufferType<T>:
90 s = "FooBar";
91 s2.Printf(wxT("(%s)"), s.mb_str());
92 CPPUNIT_ASSERT( s2 == "(FooBar)" );
93 s2.Printf(wxT("value=%s;"), s.wc_str());
94 CPPUNIT_ASSERT( s2 == "value=FooBar;" );
95
96 // this tests correct passing of wxCStrData constructed from string
97 // literal:
98 bool cond = true;
99 s2.Printf(wxT("foo %s"), !cond ? s.c_str() : wxT("bar"));
100 }
101
102 void VarArgTestCase::CharPrintf()
103 {
104 wxString foo("foo");
105 wxString s;
106
107 // test using wchar_t:
108 s.Printf("char=%c", L'c');
109 CPPUNIT_ASSERT_EQUAL( "char=c", s );
110
111 // test wxUniCharRef:
112 s.Printf("string[1] is %c", foo[1]);
113 CPPUNIT_ASSERT_EQUAL( "string[1] is o", s );
114
115 // test char
116 char c = 'z';
117 s.Printf("%c to %c", 'a', c);
118 CPPUNIT_ASSERT_EQUAL( "a to z", s );
119
120 // test char used as integer:
121 #ifdef _MSC_VER
122 #pragma warning(disable:4305) // truncation of constant value in VC6
123 #pragma warning(disable:4309) // truncation of constant value
124 #endif
125 c = 240;
126 #ifdef _MSC_VER
127 #pragma warning(default:4305) // truncation of constant value in VC6
128 #pragma warning(default:4309)
129 #endif
130 s.Printf("value is %i (int)", c);
131 CPPUNIT_ASSERT_EQUAL( wxString("value is -16 (int)"), s );
132
133 unsigned char u = 240;
134 s.Printf("value is %i (int)", u);
135 CPPUNIT_ASSERT_EQUAL( "value is 240 (int)", s );
136 }
137
138 #if wxUSE_STD_STRING
139 void VarArgTestCase::StdString()
140 {
141 // test passing std::[w]string
142 wxString s;
143
144 std::string mb("multi-byte");
145 std::string wc("widechar");
146
147 s.Printf("string %s(%i).", mb, 1);
148 CPPUNIT_ASSERT_EQUAL( "string multi-byte(1).", s );
149
150 s.Printf("string %s(%i).", wc, 2);
151 CPPUNIT_ASSERT_EQUAL( "string widechar(2).", s );
152 }
153 #endif // wxUSE_STD_STRING
154
155 void VarArgTestCase::Sscanf()
156 {
157 int i = 0;
158 char str[20];
159 wchar_t wstr[20];
160
161 wxString input("42 test");
162
163 wxSscanf(input, "%d %s", &i, &str);
164 CPPUNIT_ASSERT( i == 42 );
165 CPPUNIT_ASSERT( wxStrcmp(str, "test") == 0 );
166
167 i = 0;
168 wxSscanf(input, L"%d %s", &i, &wstr);
169 CPPUNIT_ASSERT( i == 42 );
170 CPPUNIT_ASSERT( wxStrcmp(wstr, "test") == 0 );
171 }
172
173 void VarArgTestCase::RepeatedPrintf()
174 {
175 wxCharBuffer buffer(2);
176 char *p = buffer.data();
177 *p = 'h';
178 p++;
179 *p = 'i';
180
181 wxString s;
182 s = wxString::Format("buffer %s, len %d", buffer, (int)wxStrlen(buffer));
183 CPPUNIT_ASSERT_EQUAL("buffer hi, len 2", s);
184
185 s = wxString::Format("buffer %s, len %d", buffer, (int)wxStrlen(buffer));
186 CPPUNIT_ASSERT_EQUAL("buffer hi, len 2", s);
187 }
188
189 void VarArgTestCase::ArgsValidation()
190 {
191 void *ptr = this;
192 int written;
193 short int swritten;
194
195 // these are valid:
196 wxString::Format("a string(%s,%s), ptr %p, int %i",
197 wxString(), "foo", "char* as pointer", 1);
198
199 #if !wxCHECK_VISUALC_VERSION(8)
200 // Microsoft has helpfully disabled support for "%n" in their CRT by
201 // default starting from VC8 and somehow even calling
202 // _set_printf_count_output() doesn't help here, so just disable this test
203 // for it.
204 wxString::Format("foo%i%n", 42, &written);
205 CPPUNIT_ASSERT_EQUAL( 5, written );
206 #endif // VC8+
207
208 // but these are not:
209 WX_ASSERT_FAILS_WITH_ASSERT( wxString::Format("%i: too many arguments", 42, 1, 2, 3) );
210 WX_ASSERT_FAILS_WITH_ASSERT( wxString::Format("%i", "foo") );
211 WX_ASSERT_FAILS_WITH_ASSERT( wxString::Format("%s", (void*)this) );
212
213 WX_ASSERT_FAILS_WITH_ASSERT( wxString::Format("%d", ptr) );
214
215 WX_ASSERT_FAILS_WITH_ASSERT( wxString::Format("foo%i%n", &written) );
216 WX_ASSERT_FAILS_WITH_ASSERT( wxString::Format("foo%n", ptr) );
217 WX_ASSERT_FAILS_WITH_ASSERT( wxString::Format("foo%i%n", 42, &swritten) );
218
219 #if !defined(HAVE_TYPE_TRAITS) && !defined(HAVE_TR1_TYPE_TRAITS)
220 // this fails at compile-time with <type_traits>
221 VarArgTestCase& somePOD = *this;
222 WX_ASSERT_FAILS_WITH_ASSERT( wxString::Format("%s", somePOD) );
223 #endif
224
225 // %c should accept integers too
226 wxString::Format("%c", 80);
227 wxString::Format("%c", wxChar(80) + wxChar(1));
228
229 // check size_t handling
230 size_t len = sizeof(*this);
231 #ifdef __WXMSW__
232 wxString::Format("%Iu", len);
233 #else
234 wxString::Format("%zu", len);
235 #endif
236 }