]>
git.ipfire.org Git - thirdparty/squid.git/blob - src/tests/testSBuf.cc
2 * Copyright (C) 1996-2016 The Squid Software Foundation and contributors
4 * Squid software is distributed under GPLv2+ license and includes
5 * contributions from numerous individuals and organizations.
6 * Please see the COPYING and CONTRIBUTORS files for details.
10 #include "base/CharacterSet.h"
12 #include "SBufAlgos.h"
13 #include "SBufFindTest.h"
14 #include "SBufStream.h"
15 #include "SquidString.h"
17 #include "unitTestMain.h"
21 #include <unordered_map>
23 CPPUNIT_TEST_SUITE_REGISTRATION( testSBuf
);
25 /* let this test link sanely */
27 #include "MemObject.h"
29 eventAdd(const char *name
, EVH
* func
, void *arg
, double when
, int, bool cbdata
)
32 MemObject::endOffset() const
37 static char fox
[]="The quick brown fox jumped over the lazy dog";
38 static char fox1
[]="The quick brown fox ";
39 static char fox2
[]="jumped over the lazy dog";
41 // TEST: globals variables (default/empty and with contents) are
42 // created outside and before any unit tests and memory subsystem
43 // initialization. Check for correct constructor operation.
45 SBuf
literal("The quick brown fox jumped over the lazy dog");
48 testSBuf::testSBufConstructDestruct()
50 /* NOTE: Do not initialize memory here because we need
51 * to test correct operation before and after Mem::Init
54 // XXX: partial demo below of how to do constructor unit-test. use scope to ensure each test
55 // is working on local-scope variables constructed fresh for the test, and destructed when
56 // scope exists. use nested scopes to test destructor affects on copied data (MemBlob etc)
58 // TEST: default constructor (implicit destructor non-crash test)
59 // test accessors on empty SBuf.
62 CPPUNIT_ASSERT_EQUAL(0U,s1
.length());
63 CPPUNIT_ASSERT_EQUAL(SBuf(""),s1
);
64 CPPUNIT_ASSERT_EQUAL(empty_sbuf
,s1
);
65 CPPUNIT_ASSERT_EQUAL(0,strcmp("",s1
.c_str()));
68 // TEST: copy-construct NULL string (implicit destructor non-crash test)
71 CPPUNIT_ASSERT_EQUAL(0U,s1
.length());
72 CPPUNIT_ASSERT_EQUAL(SBuf(""),s1
);
73 CPPUNIT_ASSERT_EQUAL(empty_sbuf
,s1
);
74 CPPUNIT_ASSERT_EQUAL(0,strcmp("",s1
.c_str()));
77 // TEST: copy-construct empty string (implicit destructor non-crash test)
80 CPPUNIT_ASSERT_EQUAL(0U,s1
.length());
81 CPPUNIT_ASSERT_EQUAL(SBuf(""),s1
);
82 CPPUNIT_ASSERT_EQUAL(empty_sbuf
,s1
);
83 CPPUNIT_ASSERT_EQUAL(0,strcmp("",s1
.c_str()));
86 // TEST: copy-construct from a SBuf
89 CPPUNIT_ASSERT_EQUAL(0U,s1
.length());
90 CPPUNIT_ASSERT_EQUAL(SBuf(""),s1
);
91 CPPUNIT_ASSERT_EQUAL(empty_sbuf
,s1
);
92 CPPUNIT_ASSERT_EQUAL(0,strcmp("",s1
.c_str()));
95 CPPUNIT_ASSERT_EQUAL(literal
,s5
);
97 CPPUNIT_ASSERT_EQUAL(literal
,s6
);
98 // XXX: other state checks. expected result of calling any state accessor on s4 ?
101 // TEST: check that COW doesn't happen upon copy-construction
103 SBuf
s1(empty_sbuf
), s2(s1
);
104 CPPUNIT_ASSERT_EQUAL(s1
.rawContent(), s2
.rawContent());
105 SBuf
s3(literal
), s4(literal
);
106 CPPUNIT_ASSERT_EQUAL(s3
.rawContent(), s4
.rawContent());
109 // TEST: sub-string copy
111 SBuf s1
=SBuf(fox
+4), s2(fox
);
112 SBuf s3
=s2
.substr(4,s2
.length()); //n is out-of-bounds
113 CPPUNIT_ASSERT_EQUAL(s1
,s3
);
116 CPPUNIT_ASSERT_EQUAL(s4
,s3
);
119 // TEST: go via SquidString adapters.
123 CPPUNIT_ASSERT_EQUAL(literal
,s1
);
126 // TEST: go via std::string adapter.
128 std::string
str(fox
);
130 CPPUNIT_ASSERT_EQUAL(literal
,s1
);
135 testSBuf::testSBufConstructDestructAfterMemInit()
138 testSBufConstructDestruct();
142 testSBuf::testEqualityTest()
144 SBuf
s1(fox
),s2(fox
);
145 CPPUNIT_ASSERT_EQUAL(s1
,s1
); //self-equality
146 CPPUNIT_ASSERT_EQUAL(s1
,s2
); //same contents
147 s2
.assign("The quick brown fox jumped over the lazy doe");
148 CPPUNIT_ASSERT(!(s1
== s2
)); //same length, different contents
150 CPPUNIT_ASSERT(!(s1
== s2
)); //different length and contents
151 CPPUNIT_ASSERT(s1
!= s2
); //while we're ready, let's test inequality
153 CPPUNIT_ASSERT(!(s1
== s2
)); //null and not-null
154 CPPUNIT_ASSERT(s1
!= s2
); //while we're ready, let's test inequality
156 CPPUNIT_ASSERT_EQUAL(s1
,s2
); //null and null
160 testSBuf::testAppendSBuf()
162 SBuf
s1(fox1
),s2(fox2
);
164 CPPUNIT_ASSERT_EQUAL(s1
,literal
);
168 testSBuf::testPrintf()
171 s1
.Printf("%s:%d:%03.3f","fox",10,12345.67);
172 s2
.assign("fox:10:12345.670");
173 CPPUNIT_ASSERT_EQUAL(s1
,s2
);
177 testSBuf::testAppendCString()
181 CPPUNIT_ASSERT_EQUAL(s1
,literal
);
185 testSBuf::testAppendStdString()
187 const char *alphabet
="abcdefghijklmnopqrstuvwxyz";
189 SBuf
alpha(alphabet
), s
;
190 s
.append(alphabet
,5).append(alphabet
+5);
191 CPPUNIT_ASSERT_EQUAL(alpha
,s
);
196 s
.append(alphabet
,5).append("\0",1).append(alphabet
+6,SBuf::npos
);
197 control
.append(alphabet
,5).append(1,'\0').append(alphabet
,6,std::string::npos
);
198 SBuf
scontrol(control
); // we need this to test the equality. sigh.
199 CPPUNIT_ASSERT_EQUAL(scontrol
,s
);
202 const char *alphazero
="abcdefghijk\0mnopqrstuvwxyz";
203 SBuf
s(alphazero
,26);
204 std::string
str(alphazero
,26);
205 CPPUNIT_ASSERT_EQUAL(0,memcmp(str
.data(),s
.rawContent(),26));
210 testSBuf::testAppendf()
213 s1
.appendf("%s:%d:%03.2f",fox
,1234,1234.56);
214 s2
.assign("The quick brown fox jumped over the lazy dog:1234:1234.56");
215 CPPUNIT_ASSERT_EQUAL(s2
,s1
);
219 testSBuf::testDumpStats()
221 SBuf::GetStats().dump(std::cout
);
222 MemBlob::GetStats().dump(std::cout
);
223 std::cout
<< "sizeof(SBuf): " << sizeof(SBuf
) << std::endl
;
224 std::cout
<< "sizeof(MemBlob): " << sizeof(MemBlob
) << std::endl
;
228 testSBuf::testSubscriptOp()
231 CPPUNIT_ASSERT_EQUAL(chg
[5],'u');
233 CPPUNIT_ASSERT_EQUAL(literal
[5],'u');
234 CPPUNIT_ASSERT_EQUAL(chg
[5],'e');
237 // note: can't use cppunit's CPPUNIT_TEST_EXCEPTION because TextException asserts, and
238 // so the test can't be properly completed.
240 testSBuf::testSubscriptOpFail()
243 c
=literal
.at(literal
.length()); //out of bounds by 1
245 std::cout
<< c
<< std::endl
;
248 static int sign(int v
)
258 testComparisonStdFull(const char *left
, const char *right
)
260 if (sign(strcmp(left
, right
)) != sign(SBuf(left
).cmp(SBuf(right
))))
261 std::cerr
<< std::endl
<< " cmp(SBuf) npos " << left
<< " ?= " << right
<< std::endl
;
262 CPPUNIT_ASSERT_EQUAL(sign(strcmp(left
, right
)), sign(SBuf(left
).cmp(SBuf(right
))));
264 if (sign(strcmp(left
, right
)) != sign(SBuf(left
).cmp(right
)))
265 std::cerr
<< std::endl
<< " cmp(char*) npos " << left
<< " ?= " << right
<< std::endl
;
266 CPPUNIT_ASSERT_EQUAL(sign(strcmp(left
, right
)), sign(SBuf(left
).cmp(right
)));
268 if (sign(strcasecmp(left
, right
)) != sign(SBuf(left
).caseCmp(SBuf(right
))))
269 std::cerr
<< std::endl
<< " caseCmp(SBuf) npos " << left
<< " ?= " << right
<< std::endl
;
270 CPPUNIT_ASSERT_EQUAL(sign(strcasecmp(left
, right
)), sign(SBuf(left
).caseCmp(SBuf(right
))));
272 if (sign(strcasecmp(left
, right
)) != sign(SBuf(left
).caseCmp(right
)))
273 std::cerr
<< std::endl
<< " caseCmp(char*) npos " << left
<< " ?= " << right
<< std::endl
;
274 CPPUNIT_ASSERT_EQUAL(sign(strcasecmp(left
, right
)), sign(SBuf(left
).caseCmp(right
)));
278 testComparisonStdN(const char *left
, const char *right
, const size_t n
)
280 if (sign(strncmp(left
, right
, n
)) != sign(SBuf(left
).cmp(SBuf(right
), n
)))
281 std::cerr
<< std::endl
<< " cmp(SBuf) " << n
<< ' ' << left
<< " ?= " << right
<< std::endl
;
282 CPPUNIT_ASSERT_EQUAL(sign(strncmp(left
, right
, n
)), sign(SBuf(left
).cmp(SBuf(right
), n
)));
284 if (sign(strncmp(left
, right
, n
)) != sign(SBuf(left
).cmp(right
, n
)))
285 std::cerr
<< std::endl
<< " cmp(char*) " << n
<< ' ' << SBuf(left
) << " ?= " << right
<< std::endl
;
286 CPPUNIT_ASSERT_EQUAL(sign(strncmp(left
, right
, n
)), sign(SBuf(left
).cmp(right
, n
)));
288 if (sign(strncasecmp(left
, right
, n
)) != sign(SBuf(left
).caseCmp(SBuf(right
), n
)))
289 std::cerr
<< std::endl
<< " caseCmp(SBuf) " << n
<< ' ' << left
<< " ?= " << right
<< std::endl
;
290 CPPUNIT_ASSERT_EQUAL(sign(strncasecmp(left
, right
, n
)), sign(SBuf(left
).caseCmp(SBuf(right
), n
)));
292 if (sign(strncasecmp(left
, right
, n
)) != sign(SBuf(left
).caseCmp(right
, n
)))
293 std::cerr
<< std::endl
<< " caseCmp(char*) " << n
<< ' ' << SBuf(left
) << " ?= " << right
<< std::endl
;
294 CPPUNIT_ASSERT_EQUAL(sign(strncasecmp(left
, right
, n
)), sign(SBuf(left
).caseCmp(right
, n
)));
298 testComparisonStdOneWay(const char *left
, const char *right
)
300 testComparisonStdFull(left
, right
);
301 const size_t maxN
= 2 + min(strlen(left
), strlen(right
));
302 for (size_t n
= 0; n
<= maxN
; ++n
) {
303 testComparisonStdN(left
, right
, n
);
308 testComparisonStd(const char *s1
, const char *s2
)
310 testComparisonStdOneWay(s1
, s2
);
311 testComparisonStdOneWay(s2
, s1
);
315 testSBuf::testComparisons()
318 SBuf
s1("foo"),s2("foe");
319 CPPUNIT_ASSERT(s1
.cmp(s2
)>0);
320 CPPUNIT_ASSERT(s1
.caseCmp(s2
)>0);
321 CPPUNIT_ASSERT(s2
.cmp(s1
)<0);
322 CPPUNIT_ASSERT_EQUAL(0,s1
.cmp(s2
,2));
323 CPPUNIT_ASSERT_EQUAL(0,s1
.caseCmp(s2
,2));
324 CPPUNIT_ASSERT(s1
> s2
);
325 CPPUNIT_ASSERT(s2
< s1
);
326 CPPUNIT_ASSERT_EQUAL(sign(s1
.cmp(s2
)),sign(strcmp(s1
.c_str(),s2
.c_str())));
330 CPPUNIT_ASSERT(s1
.cmp(s2
)<0);
331 CPPUNIT_ASSERT_EQUAL(sign(s1
.cmp(s2
)),sign(strcmp(s1
.c_str(),s2
.c_str())));
332 CPPUNIT_ASSERT(s1
< s2
);
333 // specifying the max-length and overhanging size
334 CPPUNIT_ASSERT_EQUAL(1,SBuf("foolong").caseCmp(SBuf("foo"), 5));
335 // case-insensive comaprison
338 CPPUNIT_ASSERT_EQUAL(0,s1
.caseCmp(s2
));
339 CPPUNIT_ASSERT_EQUAL(0,s1
.caseCmp(s2
,2));
340 // \0-clenliness test
341 s1
.assign("f\0oo",4);
342 s2
.assign("f\0Oo",4);
343 CPPUNIT_ASSERT(s1
.cmp(s2
) > 0);
344 CPPUNIT_ASSERT_EQUAL(0,s1
.caseCmp(s2
));
345 CPPUNIT_ASSERT_EQUAL(0,s1
.caseCmp(s2
,3));
346 CPPUNIT_ASSERT_EQUAL(0,s1
.caseCmp(s2
,2));
347 CPPUNIT_ASSERT_EQUAL(0,s1
.cmp(s2
,2));
349 testComparisonStd("foo", "fooz");
350 testComparisonStd("foo", "foo");
351 testComparisonStd("foo", "f");
352 testComparisonStd("foo", "bar");
354 testComparisonStd("foo", "FOOZ");
355 testComparisonStd("foo", "FOO");
356 testComparisonStd("foo", "F");
358 testComparisonStdOneWay("", "");
360 // rare case C-string input matching SBuf with N>strlen(s)
362 char *right
= xstrdup("foo34567890123456789012345678");
363 SBuf
left("fooZYXWVUTSRQPONMLKJIHGFEDCBA");
364 // is 3 bytes in length. NEVER more.
368 // pick another spot to truncate at if something goes horribly wrong.
370 left
.setAt(14, '\0');
372 const SBuf::size_type maxN
= 20 + min(left
.length(), static_cast<SBuf::size_type
>(strlen(right
)));
373 for (SBuf::size_type n
= 0; n
<= maxN
; ++n
) {
374 if (sign(strncmp(left
.rawContent(), right
, n
)) != sign(left
.cmp(right
, n
)) )
375 std::cerr
<< std::endl
<< " cmp(char*) " << n
<< ' ' << left
<< " ?= " << right
;
376 CPPUNIT_ASSERT_EQUAL(sign(strncmp(left
.rawContent(), right
, n
)), sign(left
.cmp(right
, n
)));
377 if (sign(strncasecmp(left
.rawContent(), right
, n
)) != sign(left
.caseCmp(right
, n
)))
378 std::cerr
<< std::endl
<< " caseCmp(char*) " << n
<< ' ' << left
<< " ?= " << right
;
379 CPPUNIT_ASSERT_EQUAL(sign(strncasecmp(left
.rawContent(), right
, n
)), sign(left
.caseCmp(right
, n
)));
386 testSBuf::testConsume()
388 SBuf
s1(literal
),s2
,s3
;
391 CPPUNIT_ASSERT_EQUAL(s2
,s3
);
392 s3
.assign("quick brown fox jumped over the lazy dog");
393 CPPUNIT_ASSERT_EQUAL(s1
,s3
);
395 CPPUNIT_ASSERT_EQUAL(s1
,SBuf());
399 testSBuf::testRawContent()
405 foo
= s1
.rawContent();
406 CPPUNIT_ASSERT_EQUAL(0,strncmp(fox
,foo
,s1
.length()));
408 CPPUNIT_ASSERT(!strcmp(fox
,foo
));
412 testSBuf::testRawSpace()
416 SBuf::size_type sz
=s2
.length();
417 char *rb
=s2
.rawSpace(strlen(fox2
)+1);
419 s2
.forceSize(sz
+strlen(fox2
));
420 CPPUNIT_ASSERT_EQUAL(s1
,s2
);
429 CPPUNIT_ASSERT_EQUAL(s1
,s2
);
433 CPPUNIT_ASSERT_EQUAL(s1
,s2
);
434 const char *alphabet
="abcdefghijklmnopqrstuvwxyz";
436 std::string
s(alphabet
); // TODO
441 CPPUNIT_ASSERT_EQUAL(ref
,b
);
445 b
.chop(b
.length()-3);
447 CPPUNIT_ASSERT_EQUAL(ref
,b
);
449 { // chop at beginning
453 CPPUNIT_ASSERT_EQUAL(ref
,b
);
455 { // chop to zero length
459 CPPUNIT_ASSERT_EQUAL(ref
,b
);
461 { // chop beyond end (at npos)
463 b
.chop(SBuf::npos
,4);
465 CPPUNIT_ASSERT_EQUAL(ref
,b
);
469 b
.chop(b
.length()+2,4);
471 CPPUNIT_ASSERT_EQUAL(ref
,b
);
475 b
.chop(0,b
.length());
477 CPPUNIT_ASSERT_EQUAL(ref
,b
);
479 { // overflow chopped area
481 b
.chop(b
.length()-3,b
.length());
483 CPPUNIT_ASSERT_EQUAL(ref
,b
);
488 testSBuf::testChomp()
490 SBuf
s1("complete string");
493 CPPUNIT_ASSERT_EQUAL(s1
,s2
);
494 s2
.assign(" complete string ,");
496 CPPUNIT_ASSERT_EQUAL(s1
,s2
);
497 s1
.assign(", complete string ,");
500 CPPUNIT_ASSERT_EQUAL(s1
,s2
);
503 // inspired by SBufFindTest; to be expanded.
504 class SBufSubstrAutoTest
507 std::string fullReference
, str
;
509 void performEqualityTest() {
511 CPPUNIT_ASSERT_EQUAL(ref
,sb
);
513 SBufSubstrAutoTest() : fullString(fox
), fullReference(fox
) {
514 for (int offset
=fullString
.length()-1; offset
>= 0; --offset
) {
515 for (int length
=fullString
.length()-1-offset
; length
>= 0; --length
) {
516 sb
=fullString
.substr(offset
,length
);
517 str
=fullReference
.substr(offset
,length
);
518 performEqualityTest();
525 testSBuf::testSubstr()
527 SBuf
s1(literal
),s2
,s3
;
530 CPPUNIT_ASSERT_EQUAL(s2
,s3
);
532 CPPUNIT_ASSERT_EQUAL(s1
,s2
);
533 SBufSubstrAutoTest sat
; // work done in the constructor
537 testSBuf::testFindChar()
539 const char *alphabet
="abcdefghijklmnopqrstuvwxyz";
542 SBuf::size_type nposResult
=SBuf::npos
;
545 // needle in haystack
547 CPPUNIT_ASSERT_EQUAL(3U,idx
);
548 CPPUNIT_ASSERT_EQUAL('d',s1
[idx
]);
550 // needle not present in haystack
551 idx
=s1
.find(' '); //fails
552 CPPUNIT_ASSERT_EQUAL(nposResult
,idx
);
556 CPPUNIT_ASSERT_EQUAL(4U,idx
);
558 // char not in searched portion
560 CPPUNIT_ASSERT_EQUAL(nposResult
,idx
);
562 // invalid start position
563 idx
=s1
.find('d',SBuf::npos
);
564 CPPUNIT_ASSERT_EQUAL(nposResult
,idx
);
566 // search outside of haystack
567 idx
=s1
.find('d',s1
.length()+1);
568 CPPUNIT_ASSERT_EQUAL(nposResult
,idx
);
571 // needle in haystack
573 CPPUNIT_ASSERT_EQUAL(3U, idx
);
574 CPPUNIT_ASSERT_EQUAL('d', s1
[idx
]);
576 // needle not present in haystack
577 idx
=s1
.rfind(' '); //fails
578 CPPUNIT_ASSERT_EQUAL(nposResult
,idx
);
582 CPPUNIT_ASSERT_EQUAL(4U,idx
);
584 // char not in searched portion
586 CPPUNIT_ASSERT_EQUAL(nposResult
,idx
);
588 // overlong haystack specification
589 idx
=s1
.rfind('d',s1
.length()+1);
590 CPPUNIT_ASSERT_EQUAL(3U,idx
);
594 testSBuf::testFindSBuf()
596 const char *alphabet
="abcdefghijklmnopqrstuvwxyz";
597 SBuf
haystack(alphabet
);
599 SBuf::size_type nposResult
=SBuf::npos
;
602 // needle in haystack
603 idx
= haystack
.find(SBuf("def"));
604 CPPUNIT_ASSERT_EQUAL(3U,idx
);
606 idx
= haystack
.find(SBuf("xyz"));
607 CPPUNIT_ASSERT_EQUAL(23U,idx
);
609 // needle not in haystack, no initial char match
610 idx
= haystack
.find(SBuf(" eq"));
611 CPPUNIT_ASSERT_EQUAL(nposResult
, idx
);
613 // needle not in haystack, initial sequence match
614 idx
= haystack
.find(SBuf("deg"));
615 CPPUNIT_ASSERT_EQUAL(nposResult
, idx
);
617 // needle past end of haystack
618 idx
= haystack
.find(SBuf("xyz1"));
619 CPPUNIT_ASSERT_EQUAL(nposResult
, idx
);
621 // search in portion: needle not in searched part
622 idx
= haystack
.find(SBuf("def"),7);
623 CPPUNIT_ASSERT_EQUAL(nposResult
, idx
);
625 // search in portion: overhang
626 idx
= haystack
.find(SBuf("def"),4);
627 CPPUNIT_ASSERT_EQUAL(nposResult
, idx
);
629 // invalid start position
630 idx
= haystack
.find(SBuf("def"),SBuf::npos
);
631 CPPUNIT_ASSERT_EQUAL(nposResult
, idx
);
633 // needle bigger than haystack
634 idx
= SBuf("def").find(haystack
);
635 CPPUNIT_ASSERT_EQUAL(nposResult
, idx
);
637 // search in a double-matching haystack
642 idx
= h2
.find(SBuf("def"));
643 CPPUNIT_ASSERT_EQUAL(3U,idx
);
645 idx
= h2
.find(SBuf("xyzab"));
646 CPPUNIT_ASSERT_EQUAL(23U,idx
);
650 // needle in haystack
651 idx
= haystack
.rfind(SBuf("def"));
652 CPPUNIT_ASSERT_EQUAL(3U,idx
);
654 idx
= haystack
.rfind(SBuf("xyz"));
655 CPPUNIT_ASSERT_EQUAL(23U,idx
);
657 // needle not in haystack, no initial char match
658 idx
= haystack
.rfind(SBuf(" eq"));
659 CPPUNIT_ASSERT_EQUAL(nposResult
, idx
);
661 // needle not in haystack, initial sequence match
662 idx
= haystack
.rfind(SBuf("deg"));
663 CPPUNIT_ASSERT_EQUAL(nposResult
, idx
);
665 // needle past end of haystack
666 idx
= haystack
.rfind(SBuf("xyz1"));
667 CPPUNIT_ASSERT_EQUAL(nposResult
, idx
);
669 // search in portion: needle in searched part
670 idx
= haystack
.rfind(SBuf("def"),7);
671 CPPUNIT_ASSERT_EQUAL(3U, idx
);
673 // search in portion: needle not in searched part
674 idx
= haystack
.rfind(SBuf("mno"),3);
675 CPPUNIT_ASSERT_EQUAL(nposResult
, idx
);
677 // search in portion: overhang
678 idx
= haystack
.rfind(SBuf("def"),4);
679 CPPUNIT_ASSERT_EQUAL(3U, idx
);
681 // npos start position
682 idx
= haystack
.rfind(SBuf("def"),SBuf::npos
);
683 CPPUNIT_ASSERT_EQUAL(3U, idx
);
685 // needle bigger than haystack
686 idx
= SBuf("def").rfind(haystack
);
687 CPPUNIT_ASSERT_EQUAL(nposResult
, idx
);
689 // search in a double-matching haystack
694 idx
= h2
.rfind(SBuf("def"));
695 CPPUNIT_ASSERT_EQUAL(29U,idx
);
697 idx
= h2
.find(SBuf("xyzab"));
698 CPPUNIT_ASSERT_EQUAL(23U,idx
);
703 testSBuf::testRFindChar()
708 CPPUNIT_ASSERT_EQUAL(40U,idx
);
709 CPPUNIT_ASSERT_EQUAL(' ',s1
[idx
]);
713 testSBuf::testRFindSBuf()
715 SBuf
haystack(literal
),afox("fox");
716 SBuf
goobar("goobar");
719 // corner case: search for a zero-length SBuf
720 idx
=haystack
.rfind(SBuf(""));
721 CPPUNIT_ASSERT_EQUAL(haystack
.length(),idx
);
723 // corner case: search for a needle longer than the haystack
724 idx
=afox
.rfind(SBuf(" "));
725 CPPUNIT_ASSERT_EQUAL(SBuf::npos
,idx
);
727 idx
=haystack
.rfind(SBuf("fox"));
728 CPPUNIT_ASSERT_EQUAL(16U,idx
);
730 // needle not found, no match for first char
731 idx
=goobar
.rfind(SBuf("foo"));
732 CPPUNIT_ASSERT_EQUAL(SBuf::npos
,idx
);
734 // needle not found, match for first char but no match for SBuf
735 idx
=haystack
.rfind(SBuf("foe"));
736 CPPUNIT_ASSERT_EQUAL(SBuf::npos
,idx
);
738 SBuf
g("g"); //match at the last char
739 idx
=haystack
.rfind(g
);
740 CPPUNIT_ASSERT_EQUAL(43U,idx
);
741 CPPUNIT_ASSERT_EQUAL('g',haystack
[idx
]);
743 idx
=haystack
.rfind(SBuf("The"));
744 CPPUNIT_ASSERT_EQUAL(0U,idx
);
746 haystack
.append("The");
747 idx
=haystack
.rfind(SBuf("The"));
748 CPPUNIT_ASSERT_EQUAL(44U,idx
);
751 haystack
="The quick brown fox";
752 SBuf
needle("foxy lady");
753 idx
=haystack
.rfind(needle
);
754 CPPUNIT_ASSERT_EQUAL(SBuf::npos
,idx
);
758 testSBuf::testSBufLength()
761 CPPUNIT_ASSERT_EQUAL(strlen(fox
),(size_t)s
.length());
765 testSBuf::testScanf()
772 s1
.assign("string , 123 , 123.50");
773 rv
=s1
.scanf("%s , %d , %f",s
,&i
,&f
);
774 CPPUNIT_ASSERT_EQUAL(3,rv
);
775 CPPUNIT_ASSERT_EQUAL(0,strcmp(s
,"string"));
776 CPPUNIT_ASSERT_EQUAL(123,i
);
777 CPPUNIT_ASSERT_EQUAL(static_cast<float>(123.5),f
);
783 char buf
[40]; //shorter than literal()
785 CPPUNIT_ASSERT_EQUAL(s
.length(),s
.copy(buf
,40));
786 CPPUNIT_ASSERT_EQUAL(0,strncmp(s
.rawContent(),buf
,s
.length()));
788 CPPUNIT_ASSERT_EQUAL(40U,s
.copy(buf
,40));
791 CPPUNIT_ASSERT_EQUAL(s2
,s
);
795 testSBuf::testStringOps()
797 SBuf
sng(ToLower(literal
)),
798 ref("the quick brown fox jumped over the lazy dog");
799 CPPUNIT_ASSERT_EQUAL(ref
,sng
);
801 CPPUNIT_ASSERT_EQUAL(0,sng
.compare(ref
,caseInsensitive
));
802 // max-size comparison
803 CPPUNIT_ASSERT_EQUAL(0,ref
.compare(SBuf("THE"),caseInsensitive
,3));
804 CPPUNIT_ASSERT_EQUAL(1,ref
.compare(SBuf("THE"),caseInsensitive
,6));
805 CPPUNIT_ASSERT_EQUAL(0,SBuf("the").compare(SBuf("THE"),caseInsensitive
,6));
813 const char *ref
=t
.rawContent();
814 t
.reserveCapacity(10240);
815 const char *match
=t
.rawContent();
816 CPPUNIT_ASSERT(match
!=ref
);
818 t
.append(literal
).append(literal
).append(literal
).append(literal
).append(literal
);
819 t
.append(t
).append(t
).append(t
).append(t
).append(t
);
820 CPPUNIT_ASSERT_EQUAL(ref
,match
);
824 testSBuf::testStartsWith()
826 static SBuf
casebuf("THE QUICK");
827 CPPUNIT_ASSERT(literal
.startsWith(SBuf(fox1
)));
828 CPPUNIT_ASSERT(!SBuf("The quick brown").startsWith(SBuf(fox1
))); //too short
829 CPPUNIT_ASSERT(!literal
.startsWith(SBuf(fox2
))); //different contents
831 // case-insensitive checks
832 CPPUNIT_ASSERT(literal
.startsWith(casebuf
,caseInsensitive
));
833 casebuf
=ToUpper(SBuf(fox1
));
834 CPPUNIT_ASSERT(literal
.startsWith(casebuf
,caseInsensitive
));
835 CPPUNIT_ASSERT(literal
.startsWith(SBuf(fox1
),caseInsensitive
));
836 casebuf
= "tha quick";
837 CPPUNIT_ASSERT_EQUAL(false,literal
.startsWith(casebuf
,caseInsensitive
));
841 testSBuf::testSBufStream()
843 SBuf
b("const.string, int 10 and a float 10.5");
845 ss
<< "const.string, int " << 10 << " and a float " << 10.5;
847 CPPUNIT_ASSERT_EQUAL(b
,o
);
850 CPPUNIT_ASSERT_EQUAL(SBuf(),o
);
854 CPPUNIT_ASSERT_EQUAL(ss2
.buf(),literal
);
855 CPPUNIT_ASSERT_EQUAL(f1
,SBuf(fox1
));
859 testSBuf::testFindFirstOf()
861 SBuf
haystack(literal
);
865 idx
=haystack
.findFirstOf(CharacterSet("t1","ADHRWYP"));
866 CPPUNIT_ASSERT_EQUAL(SBuf::npos
,idx
);
868 // found at beginning
869 idx
=haystack
.findFirstOf(CharacterSet("t2","THANDF"));
870 CPPUNIT_ASSERT_EQUAL(0U,idx
);
872 //found at end of haystack
873 idx
=haystack
.findFirstOf(CharacterSet("t3","QWERYVg"));
874 CPPUNIT_ASSERT_EQUAL(haystack
.length()-1,idx
);
876 //found in the middle of haystack
877 idx
=haystack
.findFirstOf(CharacterSet("t4","QWERqYV"));
878 CPPUNIT_ASSERT_EQUAL(4U,idx
);
882 testSBuf::testFindFirstNotOf()
884 SBuf
haystack(literal
);
887 // all chars from the set
888 idx
=haystack
.findFirstNotOf(CharacterSet("t1",literal
.c_str()));
889 CPPUNIT_ASSERT_EQUAL(SBuf::npos
,idx
);
891 // found at beginning
892 idx
=haystack
.findFirstNotOf(CharacterSet("t2","a"));
893 CPPUNIT_ASSERT_EQUAL(0U,idx
);
895 //found at end of haystack
896 idx
=haystack
.findFirstNotOf(CharacterSet("t3",literal
.substr(0,literal
.length()-1).c_str()));
897 CPPUNIT_ASSERT_EQUAL(haystack
.length()-1,idx
);
899 //found in the middle of haystack
900 idx
=haystack
.findFirstNotOf(CharacterSet("t4","The"));
901 CPPUNIT_ASSERT_EQUAL(3U,idx
);
905 testSBuf::testAutoFind()
912 testSBuf::testStdStringOps()
914 const char *alphabet
="abcdefghijklmnopqrstuvwxyz";
915 std::string
astr(alphabet
);
917 CPPUNIT_ASSERT_EQUAL(astr
,sb
.toStdString());
921 testSBuf::testIterators()
923 SBuf
text("foo"), text2("foo");
924 CPPUNIT_ASSERT(text
.begin() == text
.begin());
925 CPPUNIT_ASSERT(text
.begin() != text
.end());
926 CPPUNIT_ASSERT(text
.begin() != text2
.begin());
928 auto i
= text
.begin();
930 CPPUNIT_ASSERT_EQUAL('f', *i
);
931 CPPUNIT_ASSERT(i
!= e
);
933 CPPUNIT_ASSERT_EQUAL('o', *i
);
934 CPPUNIT_ASSERT(i
!= e
);
936 CPPUNIT_ASSERT_EQUAL('o', *i
);
937 CPPUNIT_ASSERT(i
!= e
);
939 CPPUNIT_ASSERT(i
== e
);
942 auto i
= text
.rbegin();
943 auto e
= text
.rend();
944 CPPUNIT_ASSERT_EQUAL('o', *i
);
945 CPPUNIT_ASSERT(i
!= e
);
947 CPPUNIT_ASSERT_EQUAL('o', *i
);
948 CPPUNIT_ASSERT(i
!= e
);
950 CPPUNIT_ASSERT_EQUAL('f', *i
);
951 CPPUNIT_ASSERT(i
!= e
);
953 CPPUNIT_ASSERT(i
== e
);
958 testSBuf::testSBufHash()
960 // same SBuf must have same hash
961 auto hasher
=std::hash
<SBuf
>();
962 CPPUNIT_ASSERT_EQUAL(hasher(literal
),hasher(literal
));
964 // same content must have same hash
965 CPPUNIT_ASSERT_EQUAL(hasher(literal
),hasher(SBuf(fox
)));
966 CPPUNIT_ASSERT_EQUAL(hasher(SBuf(fox
)),hasher(SBuf(fox
)));
968 //differen content should have different hash
969 CPPUNIT_ASSERT(hasher(SBuf(fox
)) != hasher(SBuf(fox1
)));
972 std::unordered_map
<SBuf
, int> um
;
976 auto i
= um
.find(SBuf("one"));
977 CPPUNIT_ASSERT(i
!= um
.end());
978 CPPUNIT_ASSERT(i
->second
== 1);
980 i
= um
.find(SBuf("eleventy"));
981 CPPUNIT_ASSERT(i
== um
.end());