]>
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"
11 #include "sbuf/SBuf.h"
12 #include "sbuf/Algorithms.h"
13 #include "sbuf/SBufStream.h"
14 #include "tests/SBufFindTest.h"
15 #include "tests/testSBuf.h"
16 #include "unitTestMain.h"
20 #include <unordered_map>
22 CPPUNIT_TEST_SUITE_REGISTRATION( testSBuf
);
24 /* let this test link sanely */
26 #include "MemObject.h"
28 eventAdd(const char *name
, EVH
* func
, void *arg
, double when
, int, bool cbdata
)
31 MemObject::endOffset() const
36 static char fox
[]="The quick brown fox jumped over the lazy dog";
37 static char fox1
[]="The quick brown fox ";
38 static char fox2
[]="jumped over the lazy dog";
40 // TEST: globals variables (default/empty and with contents) are
41 // created outside and before any unit tests and memory subsystem
42 // initialization. Check for correct constructor operation.
44 SBuf
literal("The quick brown fox jumped over the lazy dog");
47 testSBuf::testSBufConstructDestruct()
49 /* NOTE: Do not initialize memory here because we need
50 * to test correct operation before and after Mem::Init
53 // XXX: partial demo below of how to do constructor unit-test. use scope to ensure each test
54 // is working on local-scope variables constructed fresh for the test, and destructed when
55 // scope exists. use nested scopes to test destructor affects on copied data (MemBlob etc)
57 // TEST: default constructor (implicit destructor non-crash test)
58 // test accessors on empty SBuf.
61 CPPUNIT_ASSERT_EQUAL(0U,s1
.length());
62 CPPUNIT_ASSERT_EQUAL(SBuf(""),s1
);
63 CPPUNIT_ASSERT_EQUAL(empty_sbuf
,s1
);
64 CPPUNIT_ASSERT_EQUAL(0,strcmp("",s1
.c_str()));
67 // TEST: copy-construct NULL string (implicit destructor non-crash test)
70 CPPUNIT_ASSERT_EQUAL(0U,s1
.length());
71 CPPUNIT_ASSERT_EQUAL(SBuf(""),s1
);
72 CPPUNIT_ASSERT_EQUAL(empty_sbuf
,s1
);
73 CPPUNIT_ASSERT_EQUAL(0,strcmp("",s1
.c_str()));
76 // TEST: copy-construct empty string (implicit destructor non-crash test)
79 CPPUNIT_ASSERT_EQUAL(0U,s1
.length());
80 CPPUNIT_ASSERT_EQUAL(SBuf(""),s1
);
81 CPPUNIT_ASSERT_EQUAL(empty_sbuf
,s1
);
82 CPPUNIT_ASSERT_EQUAL(0,strcmp("",s1
.c_str()));
85 // TEST: copy-construct from a SBuf
88 CPPUNIT_ASSERT_EQUAL(0U,s1
.length());
89 CPPUNIT_ASSERT_EQUAL(SBuf(""),s1
);
90 CPPUNIT_ASSERT_EQUAL(empty_sbuf
,s1
);
91 CPPUNIT_ASSERT_EQUAL(0,strcmp("",s1
.c_str()));
94 CPPUNIT_ASSERT_EQUAL(literal
,s5
);
96 CPPUNIT_ASSERT_EQUAL(literal
,s6
);
97 // XXX: other state checks. expected result of calling any state accessor on s4 ?
100 // TEST: check that COW doesn't happen upon copy-construction
102 SBuf
s1(empty_sbuf
), s2(s1
);
103 CPPUNIT_ASSERT_EQUAL(s1
.rawContent(), s2
.rawContent());
104 SBuf
s3(literal
), s4(literal
);
105 CPPUNIT_ASSERT_EQUAL(s3
.rawContent(), s4
.rawContent());
108 // TEST: sub-string copy
110 SBuf s1
=SBuf(fox
+4), s2(fox
);
111 SBuf s3
=s2
.substr(4,s2
.length()); //n is out-of-bounds
112 CPPUNIT_ASSERT_EQUAL(s1
,s3
);
115 CPPUNIT_ASSERT_EQUAL(s4
,s3
);
118 // TEST: go via std::string adapter.
120 std::string
str(fox
);
122 CPPUNIT_ASSERT_EQUAL(literal
,s1
);
127 testSBuf::testSBufConstructDestructAfterMemInit()
130 testSBufConstructDestruct();
134 testSBuf::testEqualityTest()
136 SBuf
s1(fox
),s2(fox
);
137 CPPUNIT_ASSERT_EQUAL(s1
,s1
); //self-equality
138 CPPUNIT_ASSERT_EQUAL(s1
,s2
); //same contents
139 s2
.assign("The quick brown fox jumped over the lazy doe");
140 CPPUNIT_ASSERT(!(s1
== s2
)); //same length, different contents
142 CPPUNIT_ASSERT(!(s1
== s2
)); //different length and contents
143 CPPUNIT_ASSERT(s1
!= s2
); //while we're ready, let's test inequality
145 CPPUNIT_ASSERT(!(s1
== s2
)); //null and not-null
146 CPPUNIT_ASSERT(s1
!= s2
); //while we're ready, let's test inequality
148 CPPUNIT_ASSERT_EQUAL(s1
,s2
); //null and null
152 testSBuf::testAppendSBuf()
154 SBuf
s1(fox1
),s2(fox2
);
156 CPPUNIT_ASSERT_EQUAL(s1
,literal
);
160 testSBuf::testPrintf()
163 s1
.Printf("%s:%d:%03.3f","fox",10,12345.67);
164 s2
.assign("fox:10:12345.670");
165 CPPUNIT_ASSERT_EQUAL(s1
,s2
);
169 testSBuf::testAppendCString()
173 CPPUNIT_ASSERT_EQUAL(s1
,literal
);
177 testSBuf::testAppendStdString()
179 const char *alphabet
="abcdefghijklmnopqrstuvwxyz";
181 SBuf
alpha(alphabet
), s
;
182 s
.append(alphabet
,5).append(alphabet
+5);
183 CPPUNIT_ASSERT_EQUAL(alpha
,s
);
188 s
.append(alphabet
,5).append("\0",1).append(alphabet
+6,SBuf::npos
);
189 control
.append(alphabet
,5).append(1,'\0').append(alphabet
,6,std::string::npos
);
190 SBuf
scontrol(control
); // we need this to test the equality. sigh.
191 CPPUNIT_ASSERT_EQUAL(scontrol
,s
);
194 const char *alphazero
="abcdefghijk\0mnopqrstuvwxyz";
195 SBuf
s(alphazero
,26);
196 std::string
str(alphazero
,26);
197 CPPUNIT_ASSERT_EQUAL(0,memcmp(str
.data(),s
.rawContent(),26));
202 testSBuf::testAppendf()
205 s1
.appendf("%s:%d:%03.2f",fox
,1234,1234.56);
206 s2
.assign("The quick brown fox jumped over the lazy dog:1234:1234.56");
207 CPPUNIT_ASSERT_EQUAL(s2
,s1
);
211 testSBuf::testDumpStats()
213 SBuf::GetStats().dump(std::cout
);
214 MemBlob::GetStats().dump(std::cout
);
215 std::cout
<< "sizeof(SBuf): " << sizeof(SBuf
) << std::endl
;
216 std::cout
<< "sizeof(MemBlob): " << sizeof(MemBlob
) << std::endl
;
220 testSBuf::testSubscriptOp()
223 CPPUNIT_ASSERT_EQUAL(chg
[5],'u');
225 CPPUNIT_ASSERT_EQUAL(literal
[5],'u');
226 CPPUNIT_ASSERT_EQUAL(chg
[5],'e');
229 // note: can't use cppunit's CPPUNIT_TEST_EXCEPTION because TextException asserts, and
230 // so the test can't be properly completed.
232 testSBuf::testSubscriptOpFail()
235 c
=literal
.at(literal
.length()); //out of bounds by 1
237 std::cout
<< c
<< std::endl
;
240 static int sign(int v
)
250 testComparisonStdFull(const char *left
, const char *right
)
252 if (sign(strcmp(left
, right
)) != sign(SBuf(left
).cmp(SBuf(right
))))
253 std::cerr
<< std::endl
<< " cmp(SBuf) npos " << left
<< " ?= " << right
<< std::endl
;
254 CPPUNIT_ASSERT_EQUAL(sign(strcmp(left
, right
)), sign(SBuf(left
).cmp(SBuf(right
))));
256 if (sign(strcmp(left
, right
)) != sign(SBuf(left
).cmp(right
)))
257 std::cerr
<< std::endl
<< " cmp(char*) npos " << left
<< " ?= " << right
<< std::endl
;
258 CPPUNIT_ASSERT_EQUAL(sign(strcmp(left
, right
)), sign(SBuf(left
).cmp(right
)));
260 if (sign(strcasecmp(left
, right
)) != sign(SBuf(left
).caseCmp(SBuf(right
))))
261 std::cerr
<< std::endl
<< " caseCmp(SBuf) npos " << left
<< " ?= " << right
<< std::endl
;
262 CPPUNIT_ASSERT_EQUAL(sign(strcasecmp(left
, right
)), sign(SBuf(left
).caseCmp(SBuf(right
))));
264 if (sign(strcasecmp(left
, right
)) != sign(SBuf(left
).caseCmp(right
)))
265 std::cerr
<< std::endl
<< " caseCmp(char*) npos " << left
<< " ?= " << right
<< std::endl
;
266 CPPUNIT_ASSERT_EQUAL(sign(strcasecmp(left
, right
)), sign(SBuf(left
).caseCmp(right
)));
270 testComparisonStdN(const char *left
, const char *right
, const size_t n
)
272 if (sign(strncmp(left
, right
, n
)) != sign(SBuf(left
).cmp(SBuf(right
), n
)))
273 std::cerr
<< std::endl
<< " cmp(SBuf) " << n
<< ' ' << left
<< " ?= " << right
<< std::endl
;
274 CPPUNIT_ASSERT_EQUAL(sign(strncmp(left
, right
, n
)), sign(SBuf(left
).cmp(SBuf(right
), n
)));
276 if (sign(strncmp(left
, right
, n
)) != sign(SBuf(left
).cmp(right
, n
)))
277 std::cerr
<< std::endl
<< " cmp(char*) " << n
<< ' ' << SBuf(left
) << " ?= " << right
<< std::endl
;
278 CPPUNIT_ASSERT_EQUAL(sign(strncmp(left
, right
, n
)), sign(SBuf(left
).cmp(right
, n
)));
280 if (sign(strncasecmp(left
, right
, n
)) != sign(SBuf(left
).caseCmp(SBuf(right
), n
)))
281 std::cerr
<< std::endl
<< " caseCmp(SBuf) " << n
<< ' ' << left
<< " ?= " << right
<< std::endl
;
282 CPPUNIT_ASSERT_EQUAL(sign(strncasecmp(left
, right
, n
)), sign(SBuf(left
).caseCmp(SBuf(right
), n
)));
284 if (sign(strncasecmp(left
, right
, n
)) != sign(SBuf(left
).caseCmp(right
, n
)))
285 std::cerr
<< std::endl
<< " caseCmp(char*) " << n
<< ' ' << SBuf(left
) << " ?= " << right
<< std::endl
;
286 CPPUNIT_ASSERT_EQUAL(sign(strncasecmp(left
, right
, n
)), sign(SBuf(left
).caseCmp(right
, n
)));
290 testComparisonStdOneWay(const char *left
, const char *right
)
292 testComparisonStdFull(left
, right
);
293 const size_t maxN
= 2 + min(strlen(left
), strlen(right
));
294 for (size_t n
= 0; n
<= maxN
; ++n
) {
295 testComparisonStdN(left
, right
, n
);
300 testComparisonStd(const char *s1
, const char *s2
)
302 testComparisonStdOneWay(s1
, s2
);
303 testComparisonStdOneWay(s2
, s1
);
307 testSBuf::testComparisons()
310 SBuf
s1("foo"),s2("foe");
311 CPPUNIT_ASSERT(s1
.cmp(s2
)>0);
312 CPPUNIT_ASSERT(s1
.caseCmp(s2
)>0);
313 CPPUNIT_ASSERT(s2
.cmp(s1
)<0);
314 CPPUNIT_ASSERT_EQUAL(0,s1
.cmp(s2
,2));
315 CPPUNIT_ASSERT_EQUAL(0,s1
.caseCmp(s2
,2));
316 CPPUNIT_ASSERT(s1
> s2
);
317 CPPUNIT_ASSERT(s2
< s1
);
318 CPPUNIT_ASSERT_EQUAL(sign(s1
.cmp(s2
)),sign(strcmp(s1
.c_str(),s2
.c_str())));
322 CPPUNIT_ASSERT(s1
.cmp(s2
)<0);
323 CPPUNIT_ASSERT_EQUAL(sign(s1
.cmp(s2
)),sign(strcmp(s1
.c_str(),s2
.c_str())));
324 CPPUNIT_ASSERT(s1
< s2
);
325 // specifying the max-length and overhanging size
326 CPPUNIT_ASSERT_EQUAL(1,SBuf("foolong").caseCmp(SBuf("foo"), 5));
327 // case-insensive comaprison
330 CPPUNIT_ASSERT_EQUAL(0,s1
.caseCmp(s2
));
331 CPPUNIT_ASSERT_EQUAL(0,s1
.caseCmp(s2
,2));
332 // \0-clenliness test
333 s1
.assign("f\0oo",4);
334 s2
.assign("f\0Oo",4);
335 CPPUNIT_ASSERT(s1
.cmp(s2
) > 0);
336 CPPUNIT_ASSERT_EQUAL(0,s1
.caseCmp(s2
));
337 CPPUNIT_ASSERT_EQUAL(0,s1
.caseCmp(s2
,3));
338 CPPUNIT_ASSERT_EQUAL(0,s1
.caseCmp(s2
,2));
339 CPPUNIT_ASSERT_EQUAL(0,s1
.cmp(s2
,2));
341 testComparisonStd("foo", "fooz");
342 testComparisonStd("foo", "foo");
343 testComparisonStd("foo", "f");
344 testComparisonStd("foo", "bar");
346 testComparisonStd("foo", "FOOZ");
347 testComparisonStd("foo", "FOO");
348 testComparisonStd("foo", "F");
350 testComparisonStdOneWay("", "");
352 // rare case C-string input matching SBuf with N>strlen(s)
354 char *right
= xstrdup("foo34567890123456789012345678");
355 SBuf
left("fooZYXWVUTSRQPONMLKJIHGFEDCBA");
356 // is 3 bytes in length. NEVER more.
360 // pick another spot to truncate at if something goes horribly wrong.
362 left
.setAt(14, '\0');
364 const SBuf::size_type maxN
= 20 + min(left
.length(), static_cast<SBuf::size_type
>(strlen(right
)));
365 for (SBuf::size_type n
= 0; n
<= maxN
; ++n
) {
366 if (sign(strncmp(left
.rawContent(), right
, n
)) != sign(left
.cmp(right
, n
)) )
367 std::cerr
<< std::endl
<< " cmp(char*) " << n
<< ' ' << left
<< " ?= " << right
;
368 CPPUNIT_ASSERT_EQUAL(sign(strncmp(left
.rawContent(), right
, n
)), sign(left
.cmp(right
, n
)));
369 if (sign(strncasecmp(left
.rawContent(), right
, n
)) != sign(left
.caseCmp(right
, n
)))
370 std::cerr
<< std::endl
<< " caseCmp(char*) " << n
<< ' ' << left
<< " ?= " << right
;
371 CPPUNIT_ASSERT_EQUAL(sign(strncasecmp(left
.rawContent(), right
, n
)), sign(left
.caseCmp(right
, n
)));
378 testSBuf::testConsume()
380 SBuf
s1(literal
),s2
,s3
;
383 CPPUNIT_ASSERT_EQUAL(s2
,s3
);
384 s3
.assign("quick brown fox jumped over the lazy dog");
385 CPPUNIT_ASSERT_EQUAL(s1
,s3
);
387 CPPUNIT_ASSERT_EQUAL(s1
,SBuf());
391 testSBuf::testRawContent()
397 foo
= s1
.rawContent();
398 CPPUNIT_ASSERT_EQUAL(0,strncmp(fox
,foo
,s1
.length()));
400 CPPUNIT_ASSERT(!strcmp(fox
,foo
));
404 testSBuf::testRawSpace()
408 SBuf::size_type sz
=s2
.length();
409 char *rb
=s2
.rawSpace(strlen(fox2
)+1);
411 s2
.forceSize(sz
+strlen(fox2
));
412 CPPUNIT_ASSERT_EQUAL(s1
,s2
);
421 CPPUNIT_ASSERT_EQUAL(s1
,s2
);
425 CPPUNIT_ASSERT_EQUAL(s1
,s2
);
426 const char *alphabet
="abcdefghijklmnopqrstuvwxyz";
428 std::string
s(alphabet
); // TODO
433 CPPUNIT_ASSERT_EQUAL(ref
,b
);
437 b
.chop(b
.length()-3);
439 CPPUNIT_ASSERT_EQUAL(ref
,b
);
441 { // chop at beginning
445 CPPUNIT_ASSERT_EQUAL(ref
,b
);
447 { // chop to zero length
451 CPPUNIT_ASSERT_EQUAL(ref
,b
);
453 { // chop beyond end (at npos)
455 b
.chop(SBuf::npos
,4);
457 CPPUNIT_ASSERT_EQUAL(ref
,b
);
461 b
.chop(b
.length()+2,4);
463 CPPUNIT_ASSERT_EQUAL(ref
,b
);
467 b
.chop(0,b
.length());
469 CPPUNIT_ASSERT_EQUAL(ref
,b
);
471 { // overflow chopped area
473 b
.chop(b
.length()-3,b
.length());
475 CPPUNIT_ASSERT_EQUAL(ref
,b
);
480 testSBuf::testChomp()
482 SBuf
s1("complete string");
485 CPPUNIT_ASSERT_EQUAL(s1
,s2
);
486 s2
.assign(" complete string ,");
488 CPPUNIT_ASSERT_EQUAL(s1
,s2
);
489 s1
.assign(", complete string ,");
492 CPPUNIT_ASSERT_EQUAL(s1
,s2
);
495 // inspired by SBufFindTest; to be expanded.
496 class SBufSubstrAutoTest
499 std::string fullReference
, str
;
501 void performEqualityTest() {
503 CPPUNIT_ASSERT_EQUAL(ref
,sb
);
505 SBufSubstrAutoTest() : fullString(fox
), fullReference(fox
) {
506 for (int offset
=fullString
.length()-1; offset
>= 0; --offset
) {
507 for (int length
=fullString
.length()-1-offset
; length
>= 0; --length
) {
508 sb
=fullString
.substr(offset
,length
);
509 str
=fullReference
.substr(offset
,length
);
510 performEqualityTest();
517 testSBuf::testSubstr()
519 SBuf
s1(literal
),s2
,s3
;
522 CPPUNIT_ASSERT_EQUAL(s2
,s3
);
524 CPPUNIT_ASSERT_EQUAL(s1
,s2
);
525 SBufSubstrAutoTest sat
; // work done in the constructor
529 testSBuf::testFindChar()
531 const char *alphabet
="abcdefghijklmnopqrstuvwxyz";
534 SBuf::size_type nposResult
=SBuf::npos
;
537 // needle in haystack
539 CPPUNIT_ASSERT_EQUAL(3U,idx
);
540 CPPUNIT_ASSERT_EQUAL('d',s1
[idx
]);
542 // needle not present in haystack
543 idx
=s1
.find(' '); //fails
544 CPPUNIT_ASSERT_EQUAL(nposResult
,idx
);
548 CPPUNIT_ASSERT_EQUAL(4U,idx
);
550 // char not in searched portion
552 CPPUNIT_ASSERT_EQUAL(nposResult
,idx
);
554 // invalid start position
555 idx
=s1
.find('d',SBuf::npos
);
556 CPPUNIT_ASSERT_EQUAL(nposResult
,idx
);
558 // search outside of haystack
559 idx
=s1
.find('d',s1
.length()+1);
560 CPPUNIT_ASSERT_EQUAL(nposResult
,idx
);
563 // needle in haystack
565 CPPUNIT_ASSERT_EQUAL(3U, idx
);
566 CPPUNIT_ASSERT_EQUAL('d', s1
[idx
]);
568 // needle not present in haystack
569 idx
=s1
.rfind(' '); //fails
570 CPPUNIT_ASSERT_EQUAL(nposResult
,idx
);
574 CPPUNIT_ASSERT_EQUAL(4U,idx
);
576 // char not in searched portion
578 CPPUNIT_ASSERT_EQUAL(nposResult
,idx
);
580 // overlong haystack specification
581 idx
=s1
.rfind('d',s1
.length()+1);
582 CPPUNIT_ASSERT_EQUAL(3U,idx
);
586 testSBuf::testFindSBuf()
588 const char *alphabet
="abcdefghijklmnopqrstuvwxyz";
589 SBuf
haystack(alphabet
);
591 SBuf::size_type nposResult
=SBuf::npos
;
594 // needle in haystack
595 idx
= haystack
.find(SBuf("def"));
596 CPPUNIT_ASSERT_EQUAL(3U,idx
);
598 idx
= haystack
.find(SBuf("xyz"));
599 CPPUNIT_ASSERT_EQUAL(23U,idx
);
601 // needle not in haystack, no initial char match
602 idx
= haystack
.find(SBuf(" eq"));
603 CPPUNIT_ASSERT_EQUAL(nposResult
, idx
);
605 // needle not in haystack, initial sequence match
606 idx
= haystack
.find(SBuf("deg"));
607 CPPUNIT_ASSERT_EQUAL(nposResult
, idx
);
609 // needle past end of haystack
610 idx
= haystack
.find(SBuf("xyz1"));
611 CPPUNIT_ASSERT_EQUAL(nposResult
, idx
);
613 // search in portion: needle not in searched part
614 idx
= haystack
.find(SBuf("def"),7);
615 CPPUNIT_ASSERT_EQUAL(nposResult
, idx
);
617 // search in portion: overhang
618 idx
= haystack
.find(SBuf("def"),4);
619 CPPUNIT_ASSERT_EQUAL(nposResult
, idx
);
621 // invalid start position
622 idx
= haystack
.find(SBuf("def"),SBuf::npos
);
623 CPPUNIT_ASSERT_EQUAL(nposResult
, idx
);
625 // needle bigger than haystack
626 idx
= SBuf("def").find(haystack
);
627 CPPUNIT_ASSERT_EQUAL(nposResult
, idx
);
629 // search in a double-matching haystack
634 idx
= h2
.find(SBuf("def"));
635 CPPUNIT_ASSERT_EQUAL(3U,idx
);
637 idx
= h2
.find(SBuf("xyzab"));
638 CPPUNIT_ASSERT_EQUAL(23U,idx
);
642 // needle in haystack
643 idx
= haystack
.rfind(SBuf("def"));
644 CPPUNIT_ASSERT_EQUAL(3U,idx
);
646 idx
= haystack
.rfind(SBuf("xyz"));
647 CPPUNIT_ASSERT_EQUAL(23U,idx
);
649 // needle not in haystack, no initial char match
650 idx
= haystack
.rfind(SBuf(" eq"));
651 CPPUNIT_ASSERT_EQUAL(nposResult
, idx
);
653 // needle not in haystack, initial sequence match
654 idx
= haystack
.rfind(SBuf("deg"));
655 CPPUNIT_ASSERT_EQUAL(nposResult
, idx
);
657 // needle past end of haystack
658 idx
= haystack
.rfind(SBuf("xyz1"));
659 CPPUNIT_ASSERT_EQUAL(nposResult
, idx
);
661 // search in portion: needle in searched part
662 idx
= haystack
.rfind(SBuf("def"),7);
663 CPPUNIT_ASSERT_EQUAL(3U, idx
);
665 // search in portion: needle not in searched part
666 idx
= haystack
.rfind(SBuf("mno"),3);
667 CPPUNIT_ASSERT_EQUAL(nposResult
, idx
);
669 // search in portion: overhang
670 idx
= haystack
.rfind(SBuf("def"),4);
671 CPPUNIT_ASSERT_EQUAL(3U, idx
);
673 // npos start position
674 idx
= haystack
.rfind(SBuf("def"),SBuf::npos
);
675 CPPUNIT_ASSERT_EQUAL(3U, idx
);
677 // needle bigger than haystack
678 idx
= SBuf("def").rfind(haystack
);
679 CPPUNIT_ASSERT_EQUAL(nposResult
, idx
);
681 // search in a double-matching haystack
686 idx
= h2
.rfind(SBuf("def"));
687 CPPUNIT_ASSERT_EQUAL(29U,idx
);
689 idx
= h2
.find(SBuf("xyzab"));
690 CPPUNIT_ASSERT_EQUAL(23U,idx
);
695 testSBuf::testRFindChar()
700 CPPUNIT_ASSERT_EQUAL(40U,idx
);
701 CPPUNIT_ASSERT_EQUAL(' ',s1
[idx
]);
705 testSBuf::testRFindSBuf()
707 SBuf
haystack(literal
),afox("fox");
708 SBuf
goobar("goobar");
711 // corner case: search for a zero-length SBuf
712 idx
=haystack
.rfind(SBuf(""));
713 CPPUNIT_ASSERT_EQUAL(haystack
.length(),idx
);
715 // corner case: search for a needle longer than the haystack
716 idx
=afox
.rfind(SBuf(" "));
717 CPPUNIT_ASSERT_EQUAL(SBuf::npos
,idx
);
719 idx
=haystack
.rfind(SBuf("fox"));
720 CPPUNIT_ASSERT_EQUAL(16U,idx
);
722 // needle not found, no match for first char
723 idx
=goobar
.rfind(SBuf("foo"));
724 CPPUNIT_ASSERT_EQUAL(SBuf::npos
,idx
);
726 // needle not found, match for first char but no match for SBuf
727 idx
=haystack
.rfind(SBuf("foe"));
728 CPPUNIT_ASSERT_EQUAL(SBuf::npos
,idx
);
730 SBuf
g("g"); //match at the last char
731 idx
=haystack
.rfind(g
);
732 CPPUNIT_ASSERT_EQUAL(43U,idx
);
733 CPPUNIT_ASSERT_EQUAL('g',haystack
[idx
]);
735 idx
=haystack
.rfind(SBuf("The"));
736 CPPUNIT_ASSERT_EQUAL(0U,idx
);
738 haystack
.append("The");
739 idx
=haystack
.rfind(SBuf("The"));
740 CPPUNIT_ASSERT_EQUAL(44U,idx
);
743 haystack
="The quick brown fox";
744 SBuf
needle("foxy lady");
745 idx
=haystack
.rfind(needle
);
746 CPPUNIT_ASSERT_EQUAL(SBuf::npos
,idx
);
750 testSBuf::testSBufLength()
753 CPPUNIT_ASSERT_EQUAL(strlen(fox
),(size_t)s
.length());
757 testSBuf::testScanf()
764 s1
.assign("string , 123 , 123.50");
765 rv
=s1
.scanf("%s , %d , %f",s
,&i
,&f
);
766 CPPUNIT_ASSERT_EQUAL(3,rv
);
767 CPPUNIT_ASSERT_EQUAL(0,strcmp(s
,"string"));
768 CPPUNIT_ASSERT_EQUAL(123,i
);
769 CPPUNIT_ASSERT_EQUAL(static_cast<float>(123.5),f
);
775 char buf
[40]; //shorter than literal()
777 CPPUNIT_ASSERT_EQUAL(s
.length(),s
.copy(buf
,40));
778 CPPUNIT_ASSERT_EQUAL(0,strncmp(s
.rawContent(),buf
,s
.length()));
780 CPPUNIT_ASSERT_EQUAL(40U,s
.copy(buf
,40));
783 CPPUNIT_ASSERT_EQUAL(s2
,s
);
787 testSBuf::testStringOps()
789 SBuf
sng(ToLower(literal
)),
790 ref("the quick brown fox jumped over the lazy dog");
791 CPPUNIT_ASSERT_EQUAL(ref
,sng
);
793 CPPUNIT_ASSERT_EQUAL(0,sng
.compare(ref
,caseInsensitive
));
794 // max-size comparison
795 CPPUNIT_ASSERT_EQUAL(0,ref
.compare(SBuf("THE"),caseInsensitive
,3));
796 CPPUNIT_ASSERT_EQUAL(1,ref
.compare(SBuf("THE"),caseInsensitive
,6));
797 CPPUNIT_ASSERT_EQUAL(0,SBuf("the").compare(SBuf("THE"),caseInsensitive
,6));
805 const char *ref
=t
.rawContent();
806 t
.reserveCapacity(10240);
807 const char *match
=t
.rawContent();
808 CPPUNIT_ASSERT(match
!=ref
);
810 t
.append(literal
).append(literal
).append(literal
).append(literal
).append(literal
);
811 t
.append(t
).append(t
).append(t
).append(t
).append(t
);
812 CPPUNIT_ASSERT_EQUAL(ref
,match
);
816 testSBuf::testStartsWith()
818 static SBuf
casebuf("THE QUICK");
819 CPPUNIT_ASSERT(literal
.startsWith(SBuf(fox1
)));
820 CPPUNIT_ASSERT(!SBuf("The quick brown").startsWith(SBuf(fox1
))); //too short
821 CPPUNIT_ASSERT(!literal
.startsWith(SBuf(fox2
))); //different contents
823 // case-insensitive checks
824 CPPUNIT_ASSERT(literal
.startsWith(casebuf
,caseInsensitive
));
825 casebuf
=ToUpper(SBuf(fox1
));
826 CPPUNIT_ASSERT(literal
.startsWith(casebuf
,caseInsensitive
));
827 CPPUNIT_ASSERT(literal
.startsWith(SBuf(fox1
),caseInsensitive
));
828 casebuf
= "tha quick";
829 CPPUNIT_ASSERT_EQUAL(false,literal
.startsWith(casebuf
,caseInsensitive
));
833 testSBuf::testSBufStream()
835 SBuf
b("const.string, int 10 and a float 10.5");
837 ss
<< "const.string, int " << 10 << " and a float " << 10.5;
839 CPPUNIT_ASSERT_EQUAL(b
,o
);
842 CPPUNIT_ASSERT_EQUAL(SBuf(),o
);
846 CPPUNIT_ASSERT_EQUAL(ss2
.buf(),literal
);
847 CPPUNIT_ASSERT_EQUAL(f1
,SBuf(fox1
));
851 testSBuf::testFindFirstOf()
853 SBuf
haystack(literal
);
857 idx
=haystack
.findFirstOf(CharacterSet("t1","ADHRWYP"));
858 CPPUNIT_ASSERT_EQUAL(SBuf::npos
,idx
);
860 // found at beginning
861 idx
=haystack
.findFirstOf(CharacterSet("t2","THANDF"));
862 CPPUNIT_ASSERT_EQUAL(0U,idx
);
864 //found at end of haystack
865 idx
=haystack
.findFirstOf(CharacterSet("t3","QWERYVg"));
866 CPPUNIT_ASSERT_EQUAL(haystack
.length()-1,idx
);
868 //found in the middle of haystack
869 idx
=haystack
.findFirstOf(CharacterSet("t4","QWERqYV"));
870 CPPUNIT_ASSERT_EQUAL(4U,idx
);
874 testSBuf::testFindFirstNotOf()
876 SBuf
haystack(literal
);
879 // all chars from the set
880 idx
=haystack
.findFirstNotOf(CharacterSet("t1",literal
.c_str()));
881 CPPUNIT_ASSERT_EQUAL(SBuf::npos
,idx
);
883 // found at beginning
884 idx
=haystack
.findFirstNotOf(CharacterSet("t2","a"));
885 CPPUNIT_ASSERT_EQUAL(0U,idx
);
887 //found at end of haystack
888 idx
=haystack
.findFirstNotOf(CharacterSet("t3",literal
.substr(0,literal
.length()-1).c_str()));
889 CPPUNIT_ASSERT_EQUAL(haystack
.length()-1,idx
);
891 //found in the middle of haystack
892 idx
=haystack
.findFirstNotOf(CharacterSet("t4","The"));
893 CPPUNIT_ASSERT_EQUAL(3U,idx
);
897 testSBuf::testAutoFind()
904 testSBuf::testStdStringOps()
906 const char *alphabet
="abcdefghijklmnopqrstuvwxyz";
907 std::string
astr(alphabet
);
909 CPPUNIT_ASSERT_EQUAL(astr
,sb
.toStdString());
913 testSBuf::testIterators()
915 SBuf
text("foo"), text2("foo");
916 CPPUNIT_ASSERT(text
.begin() == text
.begin());
917 CPPUNIT_ASSERT(text
.begin() != text
.end());
918 CPPUNIT_ASSERT(text
.begin() != text2
.begin());
920 auto i
= text
.begin();
922 CPPUNIT_ASSERT_EQUAL('f', *i
);
923 CPPUNIT_ASSERT(i
!= e
);
925 CPPUNIT_ASSERT_EQUAL('o', *i
);
926 CPPUNIT_ASSERT(i
!= e
);
928 CPPUNIT_ASSERT_EQUAL('o', *i
);
929 CPPUNIT_ASSERT(i
!= e
);
931 CPPUNIT_ASSERT(i
== e
);
934 auto i
= text
.rbegin();
935 auto e
= text
.rend();
936 CPPUNIT_ASSERT_EQUAL('o', *i
);
937 CPPUNIT_ASSERT(i
!= e
);
939 CPPUNIT_ASSERT_EQUAL('o', *i
);
940 CPPUNIT_ASSERT(i
!= e
);
942 CPPUNIT_ASSERT_EQUAL('f', *i
);
943 CPPUNIT_ASSERT(i
!= e
);
945 CPPUNIT_ASSERT(i
== e
);
950 testSBuf::testSBufHash()
952 // same SBuf must have same hash
953 auto hasher
=std::hash
<SBuf
>();
954 CPPUNIT_ASSERT_EQUAL(hasher(literal
),hasher(literal
));
956 // same content must have same hash
957 CPPUNIT_ASSERT_EQUAL(hasher(literal
),hasher(SBuf(fox
)));
958 CPPUNIT_ASSERT_EQUAL(hasher(SBuf(fox
)),hasher(SBuf(fox
)));
960 //differen content should have different hash
961 CPPUNIT_ASSERT(hasher(SBuf(fox
)) != hasher(SBuf(fox1
)));
964 std::unordered_map
<SBuf
, int> um
;
968 auto i
= um
.find(SBuf("one"));
969 CPPUNIT_ASSERT(i
!= um
.end());
970 CPPUNIT_ASSERT(i
->second
== 1);
972 i
= um
.find(SBuf("eleventy"));
973 CPPUNIT_ASSERT(i
== um
.end());