1///////////////////////////////////////////////////////////////////////////////
2// Name:        tests/strings/strings.cpp
3// Purpose:     wxString unit test
4// Author:      Vadim Zeitlin, Wlodzimierz ABX Skiba
5// Created:     2004-04-19
6// RCS-ID:      $Id: strings.cpp 58428 2009-01-26 12:59:01Z VZ $
7// Copyright:   (c) 2004 Vadim Zeitlin, Wlodzimierz Skiba
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// ----------------------------------------------------------------------------
25// test class
26// ----------------------------------------------------------------------------
27
28class StringTestCase : public CppUnit::TestCase
29{
30public:
31    StringTestCase();
32
33private:
34    CPPUNIT_TEST_SUITE( StringTestCase );
35        CPPUNIT_TEST( String );
36        CPPUNIT_TEST( PChar );
37        CPPUNIT_TEST( Format );
38        CPPUNIT_TEST( Constructors );
39        CPPUNIT_TEST( Extraction );
40        CPPUNIT_TEST( Trim );
41        CPPUNIT_TEST( Find );
42        CPPUNIT_TEST( Replace );
43        CPPUNIT_TEST( Match );
44        CPPUNIT_TEST( CaseChanges );
45        CPPUNIT_TEST( Compare );
46        CPPUNIT_TEST( CompareNoCase );
47        CPPUNIT_TEST( Contains );
48        CPPUNIT_TEST( ToLong );
49        CPPUNIT_TEST( ToULong );
50#ifdef wxHAS_STRTOLL
51        CPPUNIT_TEST( ToLongLong );
52        CPPUNIT_TEST( ToULongLong );
53#endif // wxHAS_STRTOLL
54        CPPUNIT_TEST( ToDouble );
55#if !wxUSE_STL
56        CPPUNIT_TEST( WriteBuf );
57#endif //!wxUSE_STL
58        CPPUNIT_TEST( CharStr );
59    CPPUNIT_TEST_SUITE_END();
60
61    void String();
62    void PChar();
63    void Format();
64    void Constructors();
65    void Extraction();
66    void Trim();
67    void Find();
68    void Replace();
69    void Match();
70    void CaseChanges();
71    void Compare();
72    void CompareNoCase();
73    void Contains();
74    void ToLong();
75    void ToULong();
76#ifdef wxHAS_STRTOLL
77    void ToLongLong();
78    void ToULongLong();
79#endif // wxHAS_STRTOLL
80    void ToDouble();
81#if !wxUSE_STL
82    void WriteBuf();
83#endif //!wxUSE_STL
84    void CharStr();
85
86    DECLARE_NO_COPY_CLASS(StringTestCase)
87};
88
89// register in the unnamed registry so that these tests are run by default
90CPPUNIT_TEST_SUITE_REGISTRATION( StringTestCase );
91
92// also include in it's own registry so that these tests can be run alone
93CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( StringTestCase, "StringTestCase" );
94
95StringTestCase::StringTestCase()
96{
97}
98
99void StringTestCase::String()
100{
101    wxString a, b, c;
102
103    a.reserve (128);
104    b.reserve (128);
105    c.reserve (128);
106
107    for (int i = 0; i < 2; ++i)
108    {
109        a = _T("Hello");
110        b = _T(" world");
111        c = _T("! How'ya doin'?");
112        a += b;
113        a += c;
114        c = _T("Hello world! What's up?");
115        CPPUNIT_ASSERT( c != a );
116    }
117}
118
119void StringTestCase::PChar()
120{
121    wxChar a [128];
122    wxChar b [128];
123    wxChar c [128];
124
125    for (int i = 0; i < 2; ++i)
126    {
127        wxStrcpy (a, _T("Hello"));
128        wxStrcpy (b, _T(" world"));
129        wxStrcpy (c, _T("! How'ya doin'?"));
130        wxStrcat (a, b);
131        wxStrcat (a, c);
132        wxStrcpy (c, _T("Hello world! What's up?"));
133        CPPUNIT_ASSERT( wxStrcmp (c, a) != 0 );
134    }
135}
136
137void StringTestCase::Format()
138{
139    wxString s1,s2;
140    s1.Printf(_T("%03d"), 18);
141    CPPUNIT_ASSERT( s1 == wxString::Format(_T("%03d"), 18) );
142    s2.Printf(_T("Number 18: %s\n"), s1.c_str());
143    CPPUNIT_ASSERT( s2 == wxString::Format(_T("Number 18: %s\n"), s1.c_str()) );
144
145    static const size_t lengths[] = { 1, 512, 1024, 1025, 2048, 4096, 4097 };
146    for ( size_t n = 0; n < WXSIZEOF(lengths); n++ )
147    {
148        const size_t len = lengths[n];
149
150        wxString s(_T('Z'), len);
151        CPPUNIT_ASSERT_EQUAL( len, wxString::Format(_T("%s"), s.c_str()).length());
152    }
153}
154
155void StringTestCase::Constructors()
156{
157    #define TEST_CTOR(args, res)                                               \
158        {                                                                      \
159            wxString s args ;                                                  \
160            CPPUNIT_ASSERT( s == res );                                        \
161        }
162
163    TEST_CTOR((_T('Z'), 4), _T("ZZZZ"));
164    TEST_CTOR((_T("Hello"), 4), _T("Hell"));
165    TEST_CTOR((_T("Hello"), 5), _T("Hello"));
166
167    static const wxChar *s = _T("?really!");
168    const wxChar *start = wxStrchr(s, _T('r'));
169    const wxChar *end = wxStrchr(s, _T('!'));
170    TEST_CTOR((start, end), _T("really"));
171}
172
173
174void StringTestCase::Extraction()
175{
176    wxString s(_T("Hello, world!"));
177
178    CPPUNIT_ASSERT( wxStrcmp( s.c_str() , _T("Hello, world!") ) == 0 );
179    CPPUNIT_ASSERT( wxStrcmp( s.Left(5).c_str() , _T("Hello") ) == 0 );
180    CPPUNIT_ASSERT( wxStrcmp( s.Right(6).c_str() , _T("world!") ) == 0 );
181    CPPUNIT_ASSERT( wxStrcmp( s(3, 5).c_str() , _T("lo, w") ) == 0 );
182    CPPUNIT_ASSERT( wxStrcmp( s.Mid(3).c_str() , _T("lo, world!") ) == 0 );
183    CPPUNIT_ASSERT( wxStrcmp( s.substr(3, 5).c_str() , _T("lo, w") ) == 0 );
184    CPPUNIT_ASSERT( wxStrcmp( s.substr(3).c_str() , _T("lo, world!") ) == 0 );
185
186    wxString rest;
187
188    #define TEST_STARTS_WITH(prefix, correct_rest, result)                    \
189        CPPUNIT_ASSERT_EQUAL(result, s.StartsWith(prefix, &rest));            \
190        if ( result )                                                         \
191            CPPUNIT_ASSERT_EQUAL(wxString(correct_rest), rest)
192
193    TEST_STARTS_WITH( _T("Hello"),           _T(", world!"),      true  );
194    TEST_STARTS_WITH( _T("Hello, "),         _T("world!"),        true  );
195    TEST_STARTS_WITH( _T("Hello, world!"),   _T(""),              true  );
196    TEST_STARTS_WITH( _T("Hello, world!!!"), _T(""),              false );
197    TEST_STARTS_WITH( _T(""),                _T("Hello, world!"), true  );
198    TEST_STARTS_WITH( _T("Goodbye"),         _T(""),              false );
199    TEST_STARTS_WITH( _T("Hi"),              _T(""),              false );
200
201    #undef TEST_STARTS_WITH
202
203    #define TEST_ENDS_WITH(suffix, correct_rest, result)                      \
204        CPPUNIT_ASSERT_EQUAL(result, s.EndsWith(suffix, &rest));              \
205        if ( result )                                                         \
206            CPPUNIT_ASSERT_EQUAL(wxString(correct_rest), rest)
207
208    TEST_ENDS_WITH( _T(""),                 _T("Hello, world!"), true  );
209    TEST_ENDS_WITH( _T("!"),                _T("Hello, world"),  true  );
210    TEST_ENDS_WITH( _T(", world!"),         _T("Hello"),         true  );
211    TEST_ENDS_WITH( _T("ello, world!"),     _T("H"),             true  );
212    TEST_ENDS_WITH( _T("Hello, world!"),    _T(""),              true  );
213    TEST_ENDS_WITH( _T("very long string"), _T(""),              false );
214    TEST_ENDS_WITH( _T("?"),                _T(""),              false );
215    TEST_ENDS_WITH( _T("Hello, world"),     _T(""),              false );
216    TEST_ENDS_WITH( _T("Gello, world!"),    _T(""),              false );
217
218    #undef TEST_ENDS_WITH
219}
220
221void StringTestCase::Trim()
222{
223    #define TEST_TRIM( str , dir , result )  \
224        CPPUNIT_ASSERT( wxString(str).Trim(dir) == result )
225
226    TEST_TRIM( _T("  Test  "),  true, _T("  Test") );
227    TEST_TRIM( _T("    "),      true, _T("")       );
228    TEST_TRIM( _T(" "),         true, _T("")       );
229    TEST_TRIM( _T(""),          true, _T("")       );
230
231    TEST_TRIM( _T("  Test  "),  false, _T("Test  ") );
232    TEST_TRIM( _T("    "),      false, _T("")       );
233    TEST_TRIM( _T(" "),         false, _T("")       );
234    TEST_TRIM( _T(""),          false, _T("")       );
235
236    #undef TEST_TRIM
237}
238
239void StringTestCase::Find()
240{
241    #define TEST_FIND( str , start , result )  \
242        CPPUNIT_ASSERT( wxString(str).find(_T("ell"), start) == result );
243
244    TEST_FIND( _T("Well, hello world"),  0, 1              );
245    TEST_FIND( _T("Well, hello world"),  6, 7              );
246    TEST_FIND( _T("Well, hello world"),  9, wxString::npos );
247
248    #undef TEST_FIND
249}
250
251void StringTestCase::Replace()
252{
253    #define TEST_REPLACE( original , pos , len , replacement , result ) \
254        { \
255            wxString s = original; \
256            s.replace( pos , len , replacement ); \
257            CPPUNIT_ASSERT( s == result ); \
258        }
259
260    TEST_REPLACE( _T("012-AWORD-XYZ"), 4, 5, _T("BWORD"),  _T("012-BWORD-XYZ") );
261    TEST_REPLACE( _T("increase"),      0, 2, _T("de"),     _T("decrease")      );
262    TEST_REPLACE( _T("wxWindow"),      8, 0, _T("s"),      _T("wxWindows")     );
263    TEST_REPLACE( _T("foobar"),        3, 0, _T("-"),      _T("foo-bar")       );
264    TEST_REPLACE( _T("barfoo"),        0, 6, _T("foobar"), _T("foobar")        );
265
266
267    #define TEST_NULLCHARREPLACE( o , olen, pos , len , replacement , r, rlen ) \
268        { \
269            wxString s(o,olen); \
270            s.replace( pos , len , replacement ); \
271            CPPUNIT_ASSERT( s == wxString(r,rlen) ); \
272        }
273
274    TEST_NULLCHARREPLACE( _T("null\0char"), 9, 5, 1, _T("d"),
275                          _T("null\0dhar"), 9 );
276
277    #define TEST_WXREPLACE( o , olen, olds, news, all, r, rlen ) \
278        { \
279            wxString s(o,olen); \
280            s.Replace( olds, news, all ); \
281            CPPUNIT_ASSERT( s == wxString(r,rlen) ); \
282        }
283
284    TEST_WXREPLACE( _T("null\0char"), 9, _T("c"), _T("de"), true,
285                          _T("null\0dehar"), 10 );
286
287    TEST_WXREPLACE( _T("null\0dehar"), 10, _T("de"), _T("c"), true,
288                          _T("null\0char"), 9 );
289
290    #undef TEST_WXREPLACE
291    #undef TEST_NULLCHARREPLACE
292    #undef TEST_REPLACE
293}
294
295void StringTestCase::Match()
296{
297    #define TEST_MATCH( s1 , s2 , result ) \
298        CPPUNIT_ASSERT( wxString(s1).Matches(s2) == result )
299
300    TEST_MATCH( _T("foobar"),    _T("foo*"),   true  );
301    TEST_MATCH( _T("foobar"),    _T("*oo*"),   true  );
302    TEST_MATCH( _T("foobar"),    _T("*bar"),   true  );
303    TEST_MATCH( _T("foobar"),    _T("??????"), true  );
304    TEST_MATCH( _T("foobar"),    _T("f??b*"),  true  );
305    TEST_MATCH( _T("foobar"),    _T("f?b*"),   false );
306    TEST_MATCH( _T("foobar"),    _T("*goo*"),  false );
307    TEST_MATCH( _T("foobar"),    _T("*foo"),   false );
308    TEST_MATCH( _T("foobarfoo"), _T("*foo"),   true  );
309    TEST_MATCH( _T(""),          _T("*"),      true  );
310    TEST_MATCH( _T(""),          _T("?"),      false );
311
312    #undef TEST_MATCH
313}
314
315
316void StringTestCase::CaseChanges()
317{
318    wxString s1(_T("Hello!"));
319    wxString s1u(s1);
320    wxString s1l(s1);
321    s1u.MakeUpper();
322    s1l.MakeLower();
323    wxString s2u, s2l;
324    s2u.MakeUpper();
325    s2l.MakeLower();
326
327    CPPUNIT_ASSERT( s1u == _T("HELLO!") );
328    CPPUNIT_ASSERT( s1l == _T("hello!") );
329    CPPUNIT_ASSERT( s2u == wxEmptyString );
330    CPPUNIT_ASSERT( s2l == wxEmptyString );
331}
332
333void StringTestCase::Compare()
334{
335    wxString s1 = wxT("AHH");
336    wxString eq = wxT("AHH");
337    wxString neq1 = wxT("HAH");
338    wxString neq2 = wxT("AH");
339    wxString neq3 = wxT("AHHH");
340    wxString neq4 = wxT("AhH");
341
342    CPPUNIT_ASSERT( s1 == eq );
343    CPPUNIT_ASSERT( s1 != neq1 );
344    CPPUNIT_ASSERT( s1 != neq2 );
345    CPPUNIT_ASSERT( s1 != neq3 );
346    CPPUNIT_ASSERT( s1 != neq4 );
347
348//    wxString _s1 = wxT("A\0HH");
349//    wxString _eq = wxT("A\0HH");
350//    wxString _neq1 = wxT("H\0AH");
351//    wxString _neq2 = wxT("A\0H");
352//    wxString _neq3 = wxT("A\0HHH");
353//    wxString _neq4 = wxT("A\0hH");
354    s1.insert(1,1,'\0');
355    eq.insert(1,1,'\0');
356    neq1.insert(1,1,'\0');
357    neq2.insert(1,1,'\0');
358    neq3.insert(1,1,'\0');
359    neq4.insert(1,1,'\0');
360
361    CPPUNIT_ASSERT( s1 == eq );
362    CPPUNIT_ASSERT( s1 != neq1 );
363    CPPUNIT_ASSERT( s1 != neq2 );
364    CPPUNIT_ASSERT( s1 != neq3 );
365    CPPUNIT_ASSERT( s1 != neq4 );
366}
367
368void StringTestCase::CompareNoCase()
369{
370    wxString s1 = wxT("AHH");
371    wxString eq = wxT("AHH");
372    wxString eq2 = wxT("AhH");
373    wxString eq3 = wxT("ahh");
374    wxString neq = wxT("HAH");
375    wxString neq2 = wxT("AH");
376    wxString neq3 = wxT("AHHH");
377
378    #define CPPUNIT_CNCEQ_ASSERT(s1, s2) CPPUNIT_ASSERT( s1.CmpNoCase(s2) == 0)
379    #define CPPUNIT_CNCNEQ_ASSERT(s1, s2) CPPUNIT_ASSERT( s1.CmpNoCase(s2) != 0)
380
381    CPPUNIT_CNCEQ_ASSERT( s1, eq );
382    CPPUNIT_CNCEQ_ASSERT( s1, eq2 );
383    CPPUNIT_CNCEQ_ASSERT( s1, eq3 );
384
385    CPPUNIT_CNCNEQ_ASSERT( s1, neq );
386    CPPUNIT_CNCNEQ_ASSERT( s1, neq2 );
387    CPPUNIT_CNCNEQ_ASSERT( s1, neq3 );
388
389
390//    wxString _s1 = wxT("A\0HH");
391//    wxString _eq = wxT("A\0HH");
392//    wxString _eq2 = wxT("A\0hH");
393//    wxString _eq3 = wxT("a\0hh");
394//    wxString _neq = wxT("H\0AH");
395//    wxString _neq2 = wxT("A\0H");
396//    wxString _neq3 = wxT("A\0HHH");
397
398    s1.insert(1,1,'\0');
399    eq.insert(1,1,'\0');
400    eq2.insert(1,1,'\0');
401    eq3.insert(1,1,'\0');
402    neq.insert(1,1,'\0');
403    neq2.insert(1,1,'\0');
404    neq3.insert(1,1,'\0');
405
406    CPPUNIT_CNCEQ_ASSERT( s1, eq );
407    CPPUNIT_CNCEQ_ASSERT( s1, eq2 );
408    CPPUNIT_CNCEQ_ASSERT( s1, eq3 );
409
410    CPPUNIT_CNCNEQ_ASSERT( s1, neq );
411    CPPUNIT_CNCNEQ_ASSERT( s1, neq2 );
412    CPPUNIT_CNCNEQ_ASSERT( s1, neq3 );
413}
414
415void StringTestCase::Contains()
416{
417    static const struct ContainsData
418    {
419        const wxChar *hay;
420        const wxChar *needle;
421        bool contains;
422    } containsData[] =
423    {
424        { _T(""),       _T(""),         true  },
425        { _T(""),       _T("foo"),      false },
426        { _T("foo"),    _T(""),         true  },
427        { _T("foo"),    _T("f"),        true  },
428        { _T("foo"),    _T("o"),        true  },
429        { _T("foo"),    _T("oo"),       true  },
430        { _T("foo"),    _T("ooo"),      false },
431        { _T("foo"),    _T("oooo"),     false },
432        { _T("foo"),    _T("fooo"),     false },
433    };
434
435    for ( size_t n = 0; n < WXSIZEOF(containsData); n++ )
436    {
437        const ContainsData& cd = containsData[n];
438        CPPUNIT_ASSERT_EQUAL( cd.contains, wxString(cd.hay).Contains(cd.needle) );
439    }
440}
441
442// flags used in ToLongData.flags
443enum
444{
445    Number_Ok       = 0,
446    Number_Invalid  = 1,
447    Number_Unsigned = 2,    // if not specified, works for signed conversion
448    Number_Signed   = 4,    // if not specified, works for unsigned
449    Number_LongLong = 8,    // only for long long tests
450    Number_Long     = 16,   // only for long tests
451};
452
453static const struct ToLongData
454{
455    const wxChar *str;
456#ifdef wxLongLong_t
457    wxLongLong_t value;
458#else
459    long value;
460#endif // wxLongLong_t
461    int flags;
462
463    long LValue() const { return value; }
464    unsigned long ULValue() const { return value; }
465#ifdef wxLongLong_t
466    wxLongLong_t LLValue() const { return value; }
467    wxULongLong_t ULLValue() const { return (wxULongLong_t)value; }
468#endif // wxLongLong_t
469
470    bool IsOk() const { return !(flags & Number_Invalid); }
471} longData[] =
472{
473    { _T("1"), 1, Number_Ok },
474    { _T("0"), 0, Number_Ok },
475    { _T("a"), 0, Number_Invalid },
476    { _T("12345"), 12345, Number_Ok },
477    { _T("--1"), 0, Number_Invalid },
478
479    { _T("-1"), -1, Number_Signed | Number_Long },
480    // this is surprizing but consistent with strtoul() behaviour
481    { _T("-1"), ULONG_MAX, Number_Unsigned | Number_Long },
482
483    // this must overflow, even with 64 bit long
484    { _T("922337203685477580711"), 0, Number_Invalid },
485
486#ifdef wxLongLong_t
487    { _T("2147483648"), wxLL(2147483648), Number_LongLong },
488    { _T("-2147483648"), wxLL(-2147483648), Number_LongLong | Number_Signed },
489    { _T("9223372036854775808"), wxULL(9223372036854775808), Number_LongLong |
490                                                             Number_Unsigned },
491#endif // wxLongLong_t
492};
493
494void StringTestCase::ToLong()
495{
496    long l;
497    for ( size_t n = 0; n < WXSIZEOF(longData); n++ )
498    {
499        const ToLongData& ld = longData[n];
500
501        if ( ld.flags & (Number_LongLong | Number_Unsigned) )
502            continue;
503
504        CPPUNIT_ASSERT_EQUAL( ld.IsOk(), wxString(ld.str).ToLong(&l) );
505        if ( ld.IsOk() )
506            CPPUNIT_ASSERT_EQUAL( ld.LValue(), l );
507    }
508}
509
510void StringTestCase::ToULong()
511{
512    unsigned long ul;
513    for ( size_t n = 0; n < WXSIZEOF(longData); n++ )
514    {
515        const ToLongData& ld = longData[n];
516
517        if ( ld.flags & (Number_LongLong | Number_Signed) )
518            continue;
519
520        CPPUNIT_ASSERT_EQUAL( ld.IsOk(), wxString(ld.str).ToULong(&ul) );
521        if ( ld.IsOk() )
522            CPPUNIT_ASSERT_EQUAL( ld.ULValue(), ul );
523    }
524}
525
526#ifdef wxHAS_STRTOLL
527
528void StringTestCase::ToLongLong()
529{
530    wxLongLong_t l;
531    for ( size_t n = 0; n < WXSIZEOF(longData); n++ )
532    {
533        const ToLongData& ld = longData[n];
534
535        if ( ld.flags & (Number_Long | Number_Unsigned) )
536            continue;
537
538        if ( ld.IsOk() )
539        {
540            CPPUNIT_ASSERT_MESSAGE
541            (
542                std::string(wxString::Format
543                (
544                    _T("Conversion of \"%s\" to long long failed"),
545                    ld.str
546                ).mb_str()),
547                wxString(ld.str).ToLongLong(&l)
548            );
549            CPPUNIT_ASSERT_EQUAL( ld.LLValue(), l );
550        }
551        else
552        {
553            CPPUNIT_ASSERT_MESSAGE
554            (
555                std::string(wxString::Format
556                (
557                    _T("Conversion of \"%s\" to long long succeeded"),
558                    ld.str
559                ).mb_str()),
560                !wxString(ld.str).ToLongLong(&l)
561            );
562        }
563    }
564}
565
566void StringTestCase::ToULongLong()
567{
568    wxULongLong_t ul;
569    for ( size_t n = 0; n < WXSIZEOF(longData); n++ )
570    {
571        const ToLongData& ld = longData[n];
572
573        if ( ld.flags & (Number_Long | Number_Signed) )
574            continue;
575
576        if ( ld.IsOk() )
577        {
578            CPPUNIT_ASSERT_MESSAGE
579            (
580                std::string(wxString::Format
581                (
582                    _T("Conversion of \"%s\" to unsigned long long failed"),
583                    ld.str
584                ).mb_str()),
585                wxString(ld.str).ToULongLong(&ul)
586            );
587            CPPUNIT_ASSERT_EQUAL( ld.ULLValue(), ul );
588        }
589        else
590        {
591            CPPUNIT_ASSERT_MESSAGE
592            (
593                std::string(wxString::Format
594                (
595                    _T("Conversion of \"%s\" to unsigned long long succeeded"),
596                    ld.str
597                ).mb_str()),
598                !wxString(ld.str).ToULongLong(&ul)
599            );
600        }
601    }
602}
603
604#endif // wxHAS_STRTOLL
605
606void StringTestCase::ToDouble()
607{
608    double d;
609    static const struct ToDoubleData
610    {
611        const wxChar *str;
612        double value;
613        bool ok;
614    } doubleData[] =
615    {
616        { _T("1"), 1, true },
617        { _T("1.23"), 1.23, true },
618        { _T(".1"), .1, true },
619        { _T("1."), 1, true },
620        { _T("1.."), 0, false },
621        { _T("0"), 0, true },
622        { _T("a"), 0, false },
623        { _T("12345"), 12345, true },
624        { _T("-1"), -1, true },
625        { _T("--1"), 0, false },
626    };
627
628    // we need to use decimal point, not comma or whatever is its value for the
629    // current locale
630    wxSetlocale(LC_ALL, _T("C"));
631
632    size_t n;
633    for ( n = 0; n < WXSIZEOF(doubleData); n++ )
634    {
635        const ToDoubleData& ld = doubleData[n];
636        CPPUNIT_ASSERT_EQUAL( ld.ok, wxString(ld.str).ToDouble(&d) );
637        if ( ld.ok )
638            CPPUNIT_ASSERT_EQUAL( ld.value, d );
639    }
640}
641
642#if !wxUSE_STL
643void StringTestCase::WriteBuf()
644{
645    wxString s;
646    wxStrcpy(wxStringBuffer(s, 10), _T("foo"));
647
648    CPPUNIT_ASSERT_EQUAL(_T('f'), s[0u]);
649    CPPUNIT_ASSERT_EQUAL(_T('o'), s[1]);
650    CPPUNIT_ASSERT_EQUAL(_T('o'), s[2]);
651    WX_ASSERT_SIZET_EQUAL(3, s.length());
652
653    {
654        wxChar *p = s.GetWriteBuf(10);
655        wxStrcpy(p, _T("barrbaz"));
656        s.UngetWriteBuf(4);
657
658        CPPUNIT_ASSERT_EQUAL(_T('b'), s[0u]);
659        CPPUNIT_ASSERT_EQUAL(_T('a'), s[1]);
660        CPPUNIT_ASSERT_EQUAL(_T('r'), s[2]);
661        CPPUNIT_ASSERT_EQUAL(_T('r'), s[3]);
662        WX_ASSERT_SIZET_EQUAL(4, s.length());
663
664        CPPUNIT_ASSERT_EQUAL( 0, wxStrcmp(_T("barr"), s) );
665    }
666}
667#endif //!wxUSE_STL
668
669
670static bool IsFoo(/* non-const */ char *s)
671{
672    return strcmp(s, "foo") == 0;
673}
674
675void StringTestCase::CharStr()
676{
677    wxString s(_T("foo"));
678
679    CPPUNIT_ASSERT( IsFoo(s.char_str()) );
680}
681