VirtualBox

source: vbox/trunk/src/VBox/Runtime/testcase/tstIprtMiniString.cpp@ 33610

Last change on this file since 33610 was 33610, checked in by vboxsync, 14 years ago

iprt::MiniString: Fixed bug in compare("") and equals("") caused by m_psz=NULL when m_cch=0 and RTStr[I]Cmp regarding NULL and "" as different things. Added format+va_list constructor.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 12.4 KB
Line 
1/* $Id: tstIprtMiniString.cpp 33610 2010-10-29 14:42:36Z vboxsync $ */
2/** @file
3 * IPRT Testcase - iprt::MiniString.
4 */
5
6/*
7 * Copyright (C) 2006-2010 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 *
17 * The contents of this file may alternatively be used under the terms
18 * of the Common Development and Distribution License Version 1.0
19 * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
20 * VirtualBox OSE distribution, in which case the provisions of the
21 * CDDL are applicable instead of those of the GPL.
22 *
23 * You may elect to license modified versions of this file under the
24 * terms and conditions of either the GPL or the CDDL or both.
25 */
26
27/*******************************************************************************
28* Header Files *
29*******************************************************************************/
30#include <iprt/cpp/ministring.h>
31
32#include <iprt/err.h>
33#include <iprt/mem.h>
34#include <iprt/string.h>
35#include <iprt/test.h>
36#include <iprt/uni.h>
37
38
39static void test1Hlp1(const char *pszExpect, const char *pszFormat, ...)
40{
41 va_list va;
42 va_start(va, pszFormat);
43 iprt::MiniString strTst(pszFormat, va);
44 va_end(va);
45 RTTESTI_CHECK_MSG(strTst.equals(pszExpect), ("strTst='%s' expected='%s'\n", strTst.c_str(), pszExpect));
46}
47
48static void test1(RTTEST hTest)
49{
50 RTTestSub(hTest, "Basics");
51
52#define CHECK(expr) RTTESTI_CHECK(expr)
53#define CHECK_DUMP(expr, value) \
54 do { \
55 if (!(expr)) \
56 RTTestFailed(hTest, "%d: FAILED %s, got \"%s\"", __LINE__, #expr, value); \
57 } while (0)
58
59#define CHECK_DUMP_I(expr) \
60 do { \
61 if (!(expr)) \
62 RTTestFailed(hTest, "%d: FAILED %s, got \"%d\"", __LINE__, #expr, expr); \
63 } while (0)
64
65 iprt::MiniString empty;
66 CHECK(empty.length() == 0);
67 CHECK(empty.capacity() == 0);
68
69 iprt::MiniString sixbytes("12345");
70 CHECK(sixbytes.length() == 5);
71 CHECK(sixbytes.capacity() == 6);
72
73 sixbytes.append(iprt::MiniString("678"));
74 CHECK(sixbytes.length() == 8);
75 CHECK(sixbytes.capacity() >= 9);
76
77 sixbytes.append("9a");
78 CHECK(sixbytes.length() == 10);
79 CHECK(sixbytes.capacity() >= 11);
80
81 char *psz = sixbytes.mutableRaw();
82 // 123456789a
83 // ^
84 // 0123456
85 psz[6] = '\0';
86 sixbytes.jolt();
87 CHECK(sixbytes.length() == 6);
88 CHECK(sixbytes.capacity() == 7);
89
90 iprt::MiniString morebytes("tobereplaced");
91 morebytes = "newstring ";
92 morebytes.append(sixbytes);
93
94 CHECK_DUMP(morebytes == "newstring 123456", morebytes.c_str());
95
96 iprt::MiniString third(morebytes);
97 third.reserve(100 * 1024); // 100 KB
98 CHECK_DUMP(third == "newstring 123456", morebytes.c_str() );
99 CHECK(third.capacity() == 100 * 1024);
100 CHECK(third.length() == morebytes.length()); // must not have changed
101
102 iprt::MiniString copy1(morebytes);
103 iprt::MiniString copy2 = morebytes;
104 CHECK(copy1 == copy2);
105
106 copy1 = NULL;
107 CHECK(copy1.length() == 0);
108
109 copy1 = "";
110 CHECK(copy1.length() == 0);
111
112 CHECK(iprt::MiniString("abc") < iprt::MiniString("def"));
113 CHECK(iprt::MiniString("abc") != iprt::MiniString("def"));
114 CHECK_DUMP_I(iprt::MiniString("def") > iprt::MiniString("abc"));
115 CHECK(iprt::MiniString("abc") == iprt::MiniString("abc"));
116
117 CHECK(iprt::MiniString("abc") < "def");
118 CHECK(iprt::MiniString("abc") != "def");
119 CHECK_DUMP_I(iprt::MiniString("def") > "abc");
120 CHECK(iprt::MiniString("abc") == "abc");
121
122 CHECK(iprt::MiniString("abc").equals("abc"));
123 CHECK(!iprt::MiniString("abc").equals("def"));
124 CHECK(iprt::MiniString("abc").equalsIgnoreCase("Abc"));
125 CHECK(iprt::MiniString("abc").equalsIgnoreCase("ABc"));
126 CHECK(iprt::MiniString("abc").equalsIgnoreCase("ABC"));
127 CHECK(!iprt::MiniString("abc").equalsIgnoreCase("dBC"));
128 CHECK(iprt::MiniString("").equals(""));
129 CHECK(iprt::MiniString("").equalsIgnoreCase(""));
130
131 copy2.setNull();
132 for (int i = 0; i < 100; ++i)
133 {
134 copy2.reserve(50); // should be ignored after 50 loops
135 copy2.append("1");
136 }
137 CHECK(copy2.length() == 100);
138
139 copy2.setNull();
140 for (int i = 0; i < 100; ++i)
141 {
142 copy2.reserve(50); // should be ignored after 50 loops
143 copy2.append('1');
144 }
145 CHECK(copy2.length() == 100);
146
147 /* printf */
148 iprt::MiniString StrFmt;
149 CHECK(StrFmt.printf("%s-%s-%d", "abc", "def", 42).equals("abc-def-42"));
150 test1Hlp1("abc-42-def", "%s-%d-%s", "abc", 42, "def");
151 test1Hlp1("", "");
152 test1Hlp1("1", "1");
153 test1Hlp1("foobar", "%s", "foobar");
154
155#undef CHECK
156#undef CHECK_DUMP
157#undef CHECK_DUMP_I
158}
159
160
161static int mymemcmp(const char *psz1, const char *psz2, size_t cch)
162{
163 for (size_t off = 0; off < cch; off++)
164 if (psz1[off] != psz2[off])
165 {
166 RTTestIFailed("off=%#x psz1=%.*Rhxs psz2=%.*Rhxs\n", off,
167 RT_MIN(cch - off, 8), &psz1[off],
168 RT_MIN(cch - off, 8), &psz2[off]);
169 return psz1[off] > psz2[off] ? 1 : -1;
170 }
171 return 0;
172}
173
174static void test2(RTTEST hTest)
175{
176 RTTestSub(hTest, "UTF-8 upper/lower encoding assumption");
177
178#define CHECK_EQUAL(str1, str2) \
179 do \
180 { \
181 RTTESTI_CHECK(strlen((str1).c_str()) == (str1).length()); \
182 RTTESTI_CHECK((str1).length() == (str2).length()); \
183 RTTESTI_CHECK(mymemcmp((str1).c_str(), (str2).c_str(), (str2).length() + 1) == 0); \
184 } while (0)
185
186 iprt::MiniString strTmp;
187 char szDst[16];
188
189 /* Collect all upper and lower case code points. */
190 iprt::MiniString strLower("");
191 strLower.reserve(_4M);
192
193 iprt::MiniString strUpper("");
194 strUpper.reserve(_4M);
195
196 for (RTUNICP uc = 1; uc <= 0x10fffd; uc++)
197 {
198 if (RTUniCpIsLower(uc))
199 {
200 RTTESTI_CHECK_MSG(uc < 0xd800 || (uc > 0xdfff && uc != 0xfffe && uc != 0xffff), ("%#x\n", uc));
201 strLower.appendCodePoint(uc);
202 }
203 if (RTUniCpIsUpper(uc))
204 {
205 RTTESTI_CHECK_MSG(uc < 0xd800 || (uc > 0xdfff && uc != 0xfffe && uc != 0xffff), ("%#x\n", uc));
206 strUpper.appendCodePoint(uc);
207 }
208 }
209 RTTESTI_CHECK(strlen(strLower.c_str()) == strLower.length());
210 RTTESTI_CHECK(strlen(strUpper.c_str()) == strUpper.length());
211
212 /* Fold each code point in the lower case string and check that it encodes
213 into the same or less number of bytes. */
214 size_t cch = 0;
215 const char *pszCur = strLower.c_str();
216 iprt::MiniString strUpper2("");
217 strUpper2.reserve(strLower.length() + 64);
218 for (;;)
219 {
220 RTUNICP ucLower;
221 const char * const pszPrev = pszCur;
222 RTTESTI_CHECK_RC_BREAK(RTStrGetCpEx(&pszCur, &ucLower), VINF_SUCCESS);
223 size_t const cchSrc = pszCur - pszPrev;
224 if (!ucLower)
225 break;
226
227 RTUNICP const ucUpper = RTUniCpToUpper(ucLower);
228 const char *pszDstEnd = RTStrPutCp(szDst, ucUpper);
229 size_t const cchDst = pszDstEnd - &szDst[0];
230 RTTESTI_CHECK_MSG(cchSrc >= cchDst,
231 ("ucLower=%#x %u bytes; ucUpper=%#x %u bytes\n",
232 ucLower, cchSrc, ucUpper, cchDst));
233 cch += cchDst;
234 strUpper2.appendCodePoint(ucUpper);
235
236 /* roundtrip stability */
237 RTUNICP const ucUpper2 = RTUniCpToUpper(ucUpper);
238 RTTESTI_CHECK_MSG(ucUpper2 == ucUpper, ("ucUpper2=%#x ucUpper=%#x\n", ucUpper2, ucUpper));
239
240 RTUNICP const ucLower2 = RTUniCpToLower(ucUpper);
241 RTUNICP const ucUpper3 = RTUniCpToUpper(ucLower2);
242 RTTESTI_CHECK_MSG(ucUpper3 == ucUpper, ("ucUpper3=%#x ucUpper=%#x\n", ucUpper3, ucUpper));
243
244 pszDstEnd = RTStrPutCp(szDst, ucLower2);
245 size_t const cchLower2 = pszDstEnd - &szDst[0];
246 RTTESTI_CHECK_MSG(cchDst == cchLower2,
247 ("ucLower2=%#x %u bytes; ucUpper=%#x %u bytes\n",
248 ucLower2, cchLower2, ucUpper, cchDst));
249 }
250 RTTESTI_CHECK(strlen(strUpper2.c_str()) == strUpper2.length());
251 RTTESTI_CHECK_MSG(cch == strUpper2.length(), ("cch=%u length()=%u\n", cch, strUpper2.length()));
252
253 /* the toUpper method shall do the same thing. */
254 strTmp = strLower; CHECK_EQUAL(strTmp, strLower);
255 strTmp.toUpper(); CHECK_EQUAL(strTmp, strUpper2);
256
257 /* Ditto for the upper case string. */
258 cch = 0;
259 pszCur = strUpper.c_str();
260 iprt::MiniString strLower2("");
261 strLower2.reserve(strUpper.length() + 64);
262 for (;;)
263 {
264 RTUNICP ucUpper;
265 const char * const pszPrev = pszCur;
266 RTTESTI_CHECK_RC_BREAK(RTStrGetCpEx(&pszCur, &ucUpper), VINF_SUCCESS);
267 size_t const cchSrc = pszCur - pszPrev;
268 if (!ucUpper)
269 break;
270
271 RTUNICP const ucLower = RTUniCpToLower(ucUpper);
272 const char *pszDstEnd = RTStrPutCp(szDst, ucLower);
273 size_t const cchDst = pszDstEnd - &szDst[0];
274 RTTESTI_CHECK_MSG(cchSrc >= cchDst,
275 ("ucUpper=%#x %u bytes; ucLower=%#x %u bytes\n",
276 ucUpper, cchSrc, ucLower, cchDst));
277
278 cch += cchDst;
279 strLower2.appendCodePoint(ucLower);
280
281 /* roundtrip stability */
282 RTUNICP const ucLower2 = RTUniCpToLower(ucLower);
283 RTTESTI_CHECK_MSG(ucLower2 == ucLower, ("ucLower2=%#x ucLower=%#x\n", ucLower2, ucLower));
284
285 RTUNICP const ucUpper2 = RTUniCpToUpper(ucLower);
286 RTUNICP const ucLower3 = RTUniCpToLower(ucUpper2);
287 RTTESTI_CHECK_MSG(ucLower3 == ucLower, ("ucLower3=%#x ucLower=%#x\n", ucLower3, ucLower));
288
289 pszDstEnd = RTStrPutCp(szDst, ucUpper2);
290 size_t const cchUpper2 = pszDstEnd - &szDst[0];
291 RTTESTI_CHECK_MSG(cchDst == cchUpper2,
292 ("ucUpper2=%#x %u bytes; ucLower=%#x %u bytes\n",
293 ucUpper2, cchUpper2, ucLower, cchDst));
294 }
295 RTTESTI_CHECK(strlen(strLower2.c_str()) == strLower2.length());
296 RTTESTI_CHECK_MSG(cch == strLower2.length(), ("cch=%u length()=%u\n", cch, strLower2.length()));
297
298 strTmp = strUpper; CHECK_EQUAL(strTmp, strUpper);
299 strTmp.toLower(); CHECK_EQUAL(strTmp, strLower2);
300
301 /* Checks of folding stability when nothing shall change. */
302 strTmp = strUpper; CHECK_EQUAL(strTmp, strUpper);
303 strTmp.toUpper(); CHECK_EQUAL(strTmp, strUpper);
304 strTmp.toUpper(); CHECK_EQUAL(strTmp, strUpper);
305 strTmp.toUpper(); CHECK_EQUAL(strTmp, strUpper);
306
307 strTmp = strUpper2; CHECK_EQUAL(strTmp, strUpper2);
308 strTmp.toUpper(); CHECK_EQUAL(strTmp, strUpper2);
309 strTmp.toUpper(); CHECK_EQUAL(strTmp, strUpper2);
310 strTmp.toUpper(); CHECK_EQUAL(strTmp, strUpper2);
311
312 strTmp = strLower; CHECK_EQUAL(strTmp, strLower);
313 strTmp.toLower(); CHECK_EQUAL(strTmp, strLower);
314 strTmp.toLower(); CHECK_EQUAL(strTmp, strLower);
315 strTmp.toLower(); CHECK_EQUAL(strTmp, strLower);
316
317 strTmp = strLower2; CHECK_EQUAL(strTmp, strLower2);
318 strTmp.toLower(); CHECK_EQUAL(strTmp, strLower2);
319 strTmp.toLower(); CHECK_EQUAL(strTmp, strLower2);
320 strTmp.toLower(); CHECK_EQUAL(strTmp, strLower2);
321
322 /* Check folding stability for roundtrips. */
323 strTmp = strUpper; CHECK_EQUAL(strTmp, strUpper);
324 strTmp.toLower(); CHECK_EQUAL(strTmp, strLower2);
325 strTmp.toUpper();
326 strTmp.toLower(); CHECK_EQUAL(strTmp, strLower2);
327 strTmp.toUpper();
328 strTmp.toLower(); CHECK_EQUAL(strTmp, strLower2);
329
330 strTmp = strLower; CHECK_EQUAL(strTmp, strLower);
331 strTmp.toUpper(); CHECK_EQUAL(strTmp, strUpper2);
332 strTmp.toLower();
333 strTmp.toUpper(); CHECK_EQUAL(strTmp, strUpper2);
334 strTmp.toLower();
335 strTmp.toUpper(); CHECK_EQUAL(strTmp, strUpper2);
336}
337
338
339int main()
340{
341 RTTEST hTest;
342 RTEXITCODE rcExit = RTTestInitAndCreate("tstIprtMiniString", &hTest);
343 if (rcExit == RTEXITCODE_SUCCESS)
344 {
345 RTTestBanner(hTest);
346
347 test1(hTest);
348 test2(hTest);
349
350 rcExit = RTTestSummaryAndDestroy(hTest);
351 }
352 return rcExit;
353}
354
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette