VirtualBox

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

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

tstIprtMiniString.cpp: NULL construction and assignment tests.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 14.4 KB
Line 
1/* $Id: tstIprtMiniString.cpp 33819 2010-11-06 14:47:41Z 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("") < iprt::MiniString("def"));
114 CHECK(iprt::MiniString("abc") > iprt::MiniString(""));
115 CHECK(iprt::MiniString("abc") != iprt::MiniString("def"));
116 CHECK_DUMP_I(iprt::MiniString("def") > iprt::MiniString("abc"));
117 CHECK(iprt::MiniString("abc") == iprt::MiniString("abc"));
118 CHECK(iprt::MiniString("").compare("") == 0);
119 CHECK(iprt::MiniString("").compare(NULL) == 0);
120 CHECK(iprt::MiniString("").compare("a") < 0);
121 CHECK(iprt::MiniString("a").compare("") > 0);
122 CHECK(iprt::MiniString("a").compare(NULL) > 0);
123
124 CHECK(iprt::MiniString("abc") < "def");
125 CHECK(iprt::MiniString("abc") != "def");
126 CHECK_DUMP_I(iprt::MiniString("def") > "abc");
127 CHECK(iprt::MiniString("abc") == "abc");
128
129 CHECK(iprt::MiniString("abc").equals("abc"));
130 CHECK(!iprt::MiniString("abc").equals("def"));
131 CHECK(iprt::MiniString("abc").equalsIgnoreCase("Abc"));
132 CHECK(iprt::MiniString("abc").equalsIgnoreCase("ABc"));
133 CHECK(iprt::MiniString("abc").equalsIgnoreCase("ABC"));
134 CHECK(!iprt::MiniString("abc").equalsIgnoreCase("dBC"));
135 CHECK(iprt::MiniString("").equals(""));
136 CHECK(iprt::MiniString("").equals(NULL));
137 CHECK(!iprt::MiniString("").equals("a"));
138 CHECK(!iprt::MiniString("a").equals(""));
139 CHECK(!iprt::MiniString("a").equals(NULL));
140 CHECK(iprt::MiniString("").equalsIgnoreCase(""));
141 CHECK(iprt::MiniString("").equalsIgnoreCase(NULL));
142 CHECK(!iprt::MiniString("").equalsIgnoreCase("a"));
143 CHECK(!iprt::MiniString("a").equalsIgnoreCase(""));
144
145 copy2.setNull();
146 for (int i = 0; i < 100; ++i)
147 {
148 copy2.reserve(50); // should be ignored after 50 loops
149 copy2.append("1");
150 }
151 CHECK(copy2.length() == 100);
152
153 copy2.setNull();
154 for (int i = 0; i < 100; ++i)
155 {
156 copy2.reserve(50); // should be ignored after 50 loops
157 copy2.append('1');
158 }
159 CHECK(copy2.length() == 100);
160
161 /* printf */
162 iprt::MiniString StrFmt;
163 CHECK(StrFmt.printf("%s-%s-%d", "abc", "def", 42).equals("abc-def-42"));
164 test1Hlp1("abc-42-def", "%s-%d-%s", "abc", 42, "def");
165 test1Hlp1("", "");
166 test1Hlp1("1", "1");
167 test1Hlp1("foobar", "%s", "foobar");
168
169 /* special constructor and assignment arguments */
170 iprt::MiniString StrCtor1("");
171 RTTESTI_CHECK(StrCtor1.isEmpty());
172 RTTESTI_CHECK(StrCtor1.length() == 0);
173
174 iprt::MiniString StrCtor2(NULL);
175 RTTESTI_CHECK(StrCtor2.isEmpty());
176 RTTESTI_CHECK(StrCtor2.length() == 0);
177
178 iprt::MiniString StrCtor1d(StrCtor1);
179 RTTESTI_CHECK(StrCtor1d.isEmpty());
180 RTTESTI_CHECK(StrCtor1d.length() == 0);
181
182 iprt::MiniString StrCtor2d(StrCtor2);
183 RTTESTI_CHECK(StrCtor2d.isEmpty());
184 RTTESTI_CHECK(StrCtor2d.length() == 0);
185
186 for (unsigned i = 0; i < 2; i++)
187 {
188 iprt::MiniString StrAssign;
189 if (i) StrAssign = "abcdef";
190 StrAssign = (char *)NULL;
191 RTTESTI_CHECK(StrAssign.isEmpty());
192 RTTESTI_CHECK(StrAssign.length() == 0);
193
194 if (i) StrAssign = "abcdef";
195 StrAssign = "";
196 RTTESTI_CHECK(StrAssign.isEmpty());
197 RTTESTI_CHECK(StrAssign.length() == 0);
198
199 if (i) StrAssign = "abcdef";
200 StrAssign = StrCtor1;
201 RTTESTI_CHECK(StrAssign.isEmpty());
202 RTTESTI_CHECK(StrAssign.length() == 0);
203
204 if (i) StrAssign = "abcdef";
205 StrAssign = StrCtor2;
206 RTTESTI_CHECK(StrAssign.isEmpty());
207 RTTESTI_CHECK(StrAssign.length() == 0);
208 }
209
210#undef CHECK
211#undef CHECK_DUMP
212#undef CHECK_DUMP_I
213}
214
215
216static int mymemcmp(const char *psz1, const char *psz2, size_t cch)
217{
218 for (size_t off = 0; off < cch; off++)
219 if (psz1[off] != psz2[off])
220 {
221 RTTestIFailed("off=%#x psz1=%.*Rhxs psz2=%.*Rhxs\n", off,
222 RT_MIN(cch - off, 8), &psz1[off],
223 RT_MIN(cch - off, 8), &psz2[off]);
224 return psz1[off] > psz2[off] ? 1 : -1;
225 }
226 return 0;
227}
228
229static void test2(RTTEST hTest)
230{
231 RTTestSub(hTest, "UTF-8 upper/lower encoding assumption");
232
233#define CHECK_EQUAL(str1, str2) \
234 do \
235 { \
236 RTTESTI_CHECK(strlen((str1).c_str()) == (str1).length()); \
237 RTTESTI_CHECK((str1).length() == (str2).length()); \
238 RTTESTI_CHECK(mymemcmp((str1).c_str(), (str2).c_str(), (str2).length() + 1) == 0); \
239 } while (0)
240
241 iprt::MiniString strTmp;
242 char szDst[16];
243
244 /* Collect all upper and lower case code points. */
245 iprt::MiniString strLower("");
246 strLower.reserve(_4M);
247
248 iprt::MiniString strUpper("");
249 strUpper.reserve(_4M);
250
251 for (RTUNICP uc = 1; uc <= 0x10fffd; uc++)
252 {
253 if (RTUniCpIsLower(uc))
254 {
255 RTTESTI_CHECK_MSG(uc < 0xd800 || (uc > 0xdfff && uc != 0xfffe && uc != 0xffff), ("%#x\n", uc));
256 strLower.appendCodePoint(uc);
257 }
258 if (RTUniCpIsUpper(uc))
259 {
260 RTTESTI_CHECK_MSG(uc < 0xd800 || (uc > 0xdfff && uc != 0xfffe && uc != 0xffff), ("%#x\n", uc));
261 strUpper.appendCodePoint(uc);
262 }
263 }
264 RTTESTI_CHECK(strlen(strLower.c_str()) == strLower.length());
265 RTTESTI_CHECK(strlen(strUpper.c_str()) == strUpper.length());
266
267 /* Fold each code point in the lower case string and check that it encodes
268 into the same or less number of bytes. */
269 size_t cch = 0;
270 const char *pszCur = strLower.c_str();
271 iprt::MiniString strUpper2("");
272 strUpper2.reserve(strLower.length() + 64);
273 for (;;)
274 {
275 RTUNICP ucLower;
276 const char * const pszPrev = pszCur;
277 RTTESTI_CHECK_RC_BREAK(RTStrGetCpEx(&pszCur, &ucLower), VINF_SUCCESS);
278 size_t const cchSrc = pszCur - pszPrev;
279 if (!ucLower)
280 break;
281
282 RTUNICP const ucUpper = RTUniCpToUpper(ucLower);
283 const char *pszDstEnd = RTStrPutCp(szDst, ucUpper);
284 size_t const cchDst = pszDstEnd - &szDst[0];
285 RTTESTI_CHECK_MSG(cchSrc >= cchDst,
286 ("ucLower=%#x %u bytes; ucUpper=%#x %u bytes\n",
287 ucLower, cchSrc, ucUpper, cchDst));
288 cch += cchDst;
289 strUpper2.appendCodePoint(ucUpper);
290
291 /* roundtrip stability */
292 RTUNICP const ucUpper2 = RTUniCpToUpper(ucUpper);
293 RTTESTI_CHECK_MSG(ucUpper2 == ucUpper, ("ucUpper2=%#x ucUpper=%#x\n", ucUpper2, ucUpper));
294
295 RTUNICP const ucLower2 = RTUniCpToLower(ucUpper);
296 RTUNICP const ucUpper3 = RTUniCpToUpper(ucLower2);
297 RTTESTI_CHECK_MSG(ucUpper3 == ucUpper, ("ucUpper3=%#x ucUpper=%#x\n", ucUpper3, ucUpper));
298
299 pszDstEnd = RTStrPutCp(szDst, ucLower2);
300 size_t const cchLower2 = pszDstEnd - &szDst[0];
301 RTTESTI_CHECK_MSG(cchDst == cchLower2,
302 ("ucLower2=%#x %u bytes; ucUpper=%#x %u bytes\n",
303 ucLower2, cchLower2, ucUpper, cchDst));
304 }
305 RTTESTI_CHECK(strlen(strUpper2.c_str()) == strUpper2.length());
306 RTTESTI_CHECK_MSG(cch == strUpper2.length(), ("cch=%u length()=%u\n", cch, strUpper2.length()));
307
308 /* the toUpper method shall do the same thing. */
309 strTmp = strLower; CHECK_EQUAL(strTmp, strLower);
310 strTmp.toUpper(); CHECK_EQUAL(strTmp, strUpper2);
311
312 /* Ditto for the upper case string. */
313 cch = 0;
314 pszCur = strUpper.c_str();
315 iprt::MiniString strLower2("");
316 strLower2.reserve(strUpper.length() + 64);
317 for (;;)
318 {
319 RTUNICP ucUpper;
320 const char * const pszPrev = pszCur;
321 RTTESTI_CHECK_RC_BREAK(RTStrGetCpEx(&pszCur, &ucUpper), VINF_SUCCESS);
322 size_t const cchSrc = pszCur - pszPrev;
323 if (!ucUpper)
324 break;
325
326 RTUNICP const ucLower = RTUniCpToLower(ucUpper);
327 const char *pszDstEnd = RTStrPutCp(szDst, ucLower);
328 size_t const cchDst = pszDstEnd - &szDst[0];
329 RTTESTI_CHECK_MSG(cchSrc >= cchDst,
330 ("ucUpper=%#x %u bytes; ucLower=%#x %u bytes\n",
331 ucUpper, cchSrc, ucLower, cchDst));
332
333 cch += cchDst;
334 strLower2.appendCodePoint(ucLower);
335
336 /* roundtrip stability */
337 RTUNICP const ucLower2 = RTUniCpToLower(ucLower);
338 RTTESTI_CHECK_MSG(ucLower2 == ucLower, ("ucLower2=%#x ucLower=%#x\n", ucLower2, ucLower));
339
340 RTUNICP const ucUpper2 = RTUniCpToUpper(ucLower);
341 RTUNICP const ucLower3 = RTUniCpToLower(ucUpper2);
342 RTTESTI_CHECK_MSG(ucLower3 == ucLower, ("ucLower3=%#x ucLower=%#x\n", ucLower3, ucLower));
343
344 pszDstEnd = RTStrPutCp(szDst, ucUpper2);
345 size_t const cchUpper2 = pszDstEnd - &szDst[0];
346 RTTESTI_CHECK_MSG(cchDst == cchUpper2,
347 ("ucUpper2=%#x %u bytes; ucLower=%#x %u bytes\n",
348 ucUpper2, cchUpper2, ucLower, cchDst));
349 }
350 RTTESTI_CHECK(strlen(strLower2.c_str()) == strLower2.length());
351 RTTESTI_CHECK_MSG(cch == strLower2.length(), ("cch=%u length()=%u\n", cch, strLower2.length()));
352
353 strTmp = strUpper; CHECK_EQUAL(strTmp, strUpper);
354 strTmp.toLower(); CHECK_EQUAL(strTmp, strLower2);
355
356 /* Checks of folding stability when nothing shall change. */
357 strTmp = strUpper; CHECK_EQUAL(strTmp, strUpper);
358 strTmp.toUpper(); CHECK_EQUAL(strTmp, strUpper);
359 strTmp.toUpper(); CHECK_EQUAL(strTmp, strUpper);
360 strTmp.toUpper(); CHECK_EQUAL(strTmp, strUpper);
361
362 strTmp = strUpper2; CHECK_EQUAL(strTmp, strUpper2);
363 strTmp.toUpper(); CHECK_EQUAL(strTmp, strUpper2);
364 strTmp.toUpper(); CHECK_EQUAL(strTmp, strUpper2);
365 strTmp.toUpper(); CHECK_EQUAL(strTmp, strUpper2);
366
367 strTmp = strLower; CHECK_EQUAL(strTmp, strLower);
368 strTmp.toLower(); CHECK_EQUAL(strTmp, strLower);
369 strTmp.toLower(); CHECK_EQUAL(strTmp, strLower);
370 strTmp.toLower(); CHECK_EQUAL(strTmp, strLower);
371
372 strTmp = strLower2; CHECK_EQUAL(strTmp, strLower2);
373 strTmp.toLower(); CHECK_EQUAL(strTmp, strLower2);
374 strTmp.toLower(); CHECK_EQUAL(strTmp, strLower2);
375 strTmp.toLower(); CHECK_EQUAL(strTmp, strLower2);
376
377 /* Check folding stability for roundtrips. */
378 strTmp = strUpper; CHECK_EQUAL(strTmp, strUpper);
379 strTmp.toLower(); CHECK_EQUAL(strTmp, strLower2);
380 strTmp.toUpper();
381 strTmp.toLower(); CHECK_EQUAL(strTmp, strLower2);
382 strTmp.toUpper();
383 strTmp.toLower(); CHECK_EQUAL(strTmp, strLower2);
384
385 strTmp = strLower; CHECK_EQUAL(strTmp, strLower);
386 strTmp.toUpper(); CHECK_EQUAL(strTmp, strUpper2);
387 strTmp.toLower();
388 strTmp.toUpper(); CHECK_EQUAL(strTmp, strUpper2);
389 strTmp.toLower();
390 strTmp.toUpper(); CHECK_EQUAL(strTmp, strUpper2);
391}
392
393
394int main()
395{
396 RTTEST hTest;
397 RTEXITCODE rcExit = RTTestInitAndCreate("tstIprtMiniString", &hTest);
398 if (rcExit == RTEXITCODE_SUCCESS)
399 {
400 RTTestBanner(hTest);
401
402 test1(hTest);
403 test2(hTest);
404
405 rcExit = RTTestSummaryAndDestroy(hTest);
406 }
407 return rcExit;
408}
409
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