]> git.ipfire.org Git - thirdparty/squid.git/blob - src/tests/testSBuf.cc
Rename SBuf::find_first_of and find_first_not_of to camelCase.
[thirdparty/squid.git] / src / tests / testSBuf.cc
1 #include "squid.h"
2 #include "base/CharacterSet.h"
3 #include "Mem.h"
4 #include "SBuf.h"
5 #include "SBufFindTest.h"
6 #include "SBufStream.h"
7 #include "SquidString.h"
8 #include "testSBuf.h"
9
10 #include <iostream>
11 #include <stdexcept>
12
13 CPPUNIT_TEST_SUITE_REGISTRATION( testSBuf );
14
15 /* let this test link sanely */
16 #include "event.h"
17 #include "MemObject.h"
18 void
19 eventAdd(const char *name, EVH * func, void *arg, double when, int, bool cbdata)
20 {}
21 int64_t
22 MemObject::endOffset() const
23 { return 0; }
24 /* end of stubs */
25
26 // test string
27 static char fox[]="The quick brown fox jumped over the lazy dog";
28 static char fox1[]="The quick brown fox ";
29 static char fox2[]="jumped over the lazy dog";
30
31 // TEST: globals variables (default/empty and with contents) are
32 // created outside and before any unit tests and memory subsystem
33 // initialization. Check for correct constructor operation.
34 SBuf empty_sbuf;
35 SBuf literal("The quick brown fox jumped over the lazy dog");
36
37 void
38 testSBuf::testSBufConstructDestruct()
39 {
40 /* NOTE: Do not initialize memory here because we need
41 * to test correct operation before and after Mem::Init
42 */
43
44 // XXX: partial demo below of how to do constructor unit-test. use scope to ensure each test
45 // is working on local-scope variables constructed fresh for the test, and destructed when
46 // scope exists. use nested scopes to test destructor affects on copied data (MemBlob etc)
47
48 // TEST: default constructor (implicit destructor non-crash test)
49 // test accessors on empty SBuf.
50 {
51 SBuf s1;
52 CPPUNIT_ASSERT_EQUAL(0U,s1.length());
53 CPPUNIT_ASSERT_EQUAL(SBuf(""),s1);
54 CPPUNIT_ASSERT_EQUAL(empty_sbuf,s1);
55 CPPUNIT_ASSERT_EQUAL(0,strcmp("",s1.c_str()));
56 }
57
58 // TEST: copy-construct NULL string (implicit destructor non-crash test)
59 {
60 SBuf s1(NULL);
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()));
65 }
66
67 // TEST: copy-construct empty string (implicit destructor non-crash test)
68 {
69 SBuf s1("");
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()));
74 }
75
76 // TEST: copy-construct from a SBuf
77 {
78 SBuf s1(empty_sbuf);
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()));
83
84 SBuf s5(literal);
85 CPPUNIT_ASSERT_EQUAL(literal,s5);
86 SBuf s6(fox);
87 CPPUNIT_ASSERT_EQUAL(literal,s6);
88 // XXX: other state checks. expected result of calling any state accessor on s4 ?
89 }
90
91 // TEST: check that COW doesn't happen upon copy-construction
92 {
93 SBuf s1(empty_sbuf), s2(s1);
94 CPPUNIT_ASSERT_EQUAL(s1.rawContent(), s2.rawContent());
95 SBuf s3(literal), s4(literal);
96 CPPUNIT_ASSERT_EQUAL(s3.rawContent(), s4.rawContent());
97 }
98
99 // TEST: sub-string copy
100 {
101 SBuf s1=SBuf(fox+4), s2(fox);
102 SBuf s3=s2.substr(4,s2.length()); //n is out-of-bounds
103 CPPUNIT_ASSERT_EQUAL(s1,s3);
104 SBuf s4=SBuf(fox,4);
105 s3=s2.substr(0,4);
106 CPPUNIT_ASSERT_EQUAL(s4,s3);
107 }
108
109 // TEST: go via SquidString adapters.
110 {
111 String str(fox);
112 SBuf s1(str);
113 CPPUNIT_ASSERT_EQUAL(literal,s1);
114 }
115
116 // TEST: go via std::string adapter.
117 {
118 std::string str(fox);
119 SBuf s1(str);
120 CPPUNIT_ASSERT_EQUAL(literal,s1);
121 }
122 }
123
124 void
125 testSBuf::testSBufConstructDestructAfterMemInit()
126 {
127 Mem::Init();
128 testSBufConstructDestruct();
129 }
130
131 void
132 testSBuf::testEqualityTest()
133 {
134 SBuf s1(fox),s2(fox);
135 CPPUNIT_ASSERT_EQUAL(s1,s1); //self-equality
136 CPPUNIT_ASSERT_EQUAL(s1,s2); //same contents
137 s2.assign("The quick brown fox jumped over the lazy doe");
138 CPPUNIT_ASSERT(!(s1 == s2)); //same length, different contents
139 s2.assign("foo");
140 CPPUNIT_ASSERT(!(s1 == s2)); //different length and contents
141 CPPUNIT_ASSERT(s1 != s2); //while we're ready, let's test inequality
142 s2.clear();
143 CPPUNIT_ASSERT(!(s1 == s2)); //null and not-null
144 CPPUNIT_ASSERT(s1 != s2); //while we're ready, let's test inequality
145 s1.clear();
146 CPPUNIT_ASSERT_EQUAL(s1,s2); //null and null
147 }
148
149 void
150 testSBuf::testAppendSBuf()
151 {
152 SBuf s1(fox1),s2(fox2);
153 s1.append(s2);
154 CPPUNIT_ASSERT_EQUAL(s1,literal);
155 }
156
157 void
158 testSBuf::testPrintf()
159 {
160 SBuf s1,s2;
161 s1.Printf("%s:%d:%03.3f","fox",10,12345.67);
162 s2.assign("fox:10:12345.670");
163 CPPUNIT_ASSERT_EQUAL(s1,s2);
164 }
165
166 void
167 testSBuf::testAppendCString()
168 {
169 SBuf s1(fox1);
170 s1.append(fox2);
171 CPPUNIT_ASSERT_EQUAL(s1,literal);
172 }
173
174 void
175 testSBuf::testAppendStdString()
176 {
177 const char *alphabet="abcdefghijklmnopqrstuvwxyz";
178 {
179 SBuf alpha(alphabet), s;
180 s.append(alphabet,5).append(alphabet+5);
181 CPPUNIT_ASSERT_EQUAL(alpha,s);
182 }
183 {
184 SBuf s;
185 std::string control;
186 s.append(alphabet,5).append("\0",1).append(alphabet+6,SBuf::npos);
187 control.append(alphabet,5).append(1,'\0').append(alphabet,6,std::string::npos);
188 SBuf scontrol(control); // we need this to test the equality. sigh.
189 CPPUNIT_ASSERT_EQUAL(scontrol,s);
190 }
191 {
192 const char *alphazero="abcdefghijk\0mnopqrstuvwxyz";
193 SBuf s(alphazero,26);
194 std::string str(alphazero,26);
195 CPPUNIT_ASSERT_EQUAL(0,memcmp(str.data(),s.rawContent(),26));
196 }
197 }
198
199 void
200 testSBuf::testAppendf()
201 {
202 SBuf s1,s2;
203 s1.appendf("%s:%d:%03.2f",fox,1234,1234.56);
204 s2.assign("The quick brown fox jumped over the lazy dog:1234:1234.56");
205 CPPUNIT_ASSERT_EQUAL(s2,s1);
206 }
207
208 void
209 testSBuf::testDumpStats()
210 {
211 SBuf::GetStats().dump(std::cout);
212 MemBlob::GetStats().dump(std::cout);
213 std::cout << "sizeof(SBuf): " << sizeof(SBuf) << std::endl;
214 std::cout << "sizeof(MemBlob): " << sizeof(MemBlob) << std::endl;
215 }
216
217 void
218 testSBuf::testSubscriptOp()
219 {
220 SBuf chg(literal);
221 CPPUNIT_ASSERT_EQUAL(chg[5],'u');
222 chg.setAt(5,'e');
223 CPPUNIT_ASSERT_EQUAL(literal[5],'u');
224 CPPUNIT_ASSERT_EQUAL(chg[5],'e');
225 }
226
227 // note: can't use cppunit's CPPUNIT_TEST_EXCEPTION because TextException asserts, and
228 // so the test can't be properly completed.
229 void
230 testSBuf::testSubscriptOpFail()
231 {
232 char c;
233 c=literal.at(literal.length()); //out of bounds by 1
234 //notreached
235 std::cout << c << std::endl;
236 }
237
238 static int sign(int v)
239 {
240 if (v < 0)
241 return -1;
242 if (v>0)
243 return 1;
244 return 0;
245 }
246
247 void
248 testSBuf::testComparisons()
249 {
250 //same length
251 SBuf s1("foo"),s2("foe");
252 CPPUNIT_ASSERT(s1.cmp(s2)>0);
253 CPPUNIT_ASSERT(s1.caseCmp(s2)>0);
254 CPPUNIT_ASSERT(s2.cmp(s1)<0);
255 CPPUNIT_ASSERT_EQUAL(0,s1.cmp(s2,2));
256 CPPUNIT_ASSERT_EQUAL(0,s1.caseCmp(s2,2));
257 CPPUNIT_ASSERT(s1 > s2);
258 CPPUNIT_ASSERT(s2 < s1);
259 CPPUNIT_ASSERT_EQUAL(sign(s1.cmp(s2)),sign(strcmp(s1.c_str(),s2.c_str())));
260 //different lengths
261 s1.assign("foo");
262 s2.assign("foof");
263 CPPUNIT_ASSERT(s1.cmp(s2)<0);
264 CPPUNIT_ASSERT_EQUAL(sign(s1.cmp(s2)),sign(strcmp(s1.c_str(),s2.c_str())));
265 CPPUNIT_ASSERT(s1 < s2);
266 // specifying the max-length and overhanging size
267 CPPUNIT_ASSERT_EQUAL(1,SBuf("foolong").caseCmp(SBuf("foo"), 5));
268 // case-insensive comaprison
269 s1 = "foo";
270 s2 = "fOo";
271 CPPUNIT_ASSERT_EQUAL(0,s1.caseCmp(s2));
272 CPPUNIT_ASSERT_EQUAL(0,s1.caseCmp(s2,2));
273 // \0-clenliness test
274 s1.assign("f\0oo",4);
275 s2.assign("f\0Oo",4);
276 CPPUNIT_ASSERT(s1.cmp(s2) > 0);
277 CPPUNIT_ASSERT_EQUAL(0,s1.caseCmp(s2));
278 CPPUNIT_ASSERT_EQUAL(0,s1.caseCmp(s2,3));
279 CPPUNIT_ASSERT_EQUAL(0,s1.caseCmp(s2,2));
280 CPPUNIT_ASSERT_EQUAL(0,s1.cmp(s2,2));
281 }
282
283 void
284 testSBuf::testConsume()
285 {
286 SBuf s1(literal),s2,s3;
287 s2=s1.consume(4);
288 s3.assign("The ");
289 CPPUNIT_ASSERT_EQUAL(s2,s3);
290 s3.assign("quick brown fox jumped over the lazy dog");
291 CPPUNIT_ASSERT_EQUAL(s1,s3);
292 s1.consume(40);
293 CPPUNIT_ASSERT_EQUAL(s1,SBuf());
294 }
295
296 void
297 testSBuf::testRawContent()
298 {
299 SBuf s1(literal);
300 SBuf s2(s1);
301 s2.append("foo");
302 const char *foo;
303 foo = s1.rawContent();
304 CPPUNIT_ASSERT_EQUAL(0,strncmp(fox,foo,s1.length()));
305 foo = s1.c_str();
306 CPPUNIT_ASSERT(!strcmp(fox,foo));
307 }
308
309 void
310 testSBuf::testRawSpace()
311 {
312 SBuf s1(literal);
313 SBuf s2(fox1);
314 SBuf::size_type sz=s2.length();
315 char *rb=s2.rawSpace(strlen(fox2)+1);
316 strcpy(rb,fox2);
317 s2.forceSize(sz+strlen(fox2));
318 CPPUNIT_ASSERT_EQUAL(s1,s2);
319 }
320
321 void
322 testSBuf::testChop()
323 {
324 SBuf s1(literal),s2;
325 s1.chop(4,5);
326 s2.assign("quick");
327 CPPUNIT_ASSERT_EQUAL(s1,s2);
328 s1=literal;
329 s2.clear();
330 s1.chop(5,0);
331 CPPUNIT_ASSERT_EQUAL(s1,s2);
332 const char *alphabet="abcdefghijklmnopqrstuvwxyz";
333 SBuf a(alphabet);
334 std::string s(alphabet); // TODO
335 { //regular chopping
336 SBuf b(a);
337 b.chop(3,3);
338 SBuf ref("def");
339 CPPUNIT_ASSERT_EQUAL(ref,b);
340 }
341 { // chop at end
342 SBuf b(a);
343 b.chop(b.length()-3);
344 SBuf ref("xyz");
345 CPPUNIT_ASSERT_EQUAL(ref,b);
346 }
347 { // chop at beginning
348 SBuf b(a);
349 b.chop(0,3);
350 SBuf ref("abc");
351 CPPUNIT_ASSERT_EQUAL(ref,b);
352 }
353 { // chop to zero length
354 SBuf b(a);
355 b.chop(5,0);
356 SBuf ref("");
357 CPPUNIT_ASSERT_EQUAL(ref,b);
358 }
359 { // chop beyond end (at npos)
360 SBuf b(a);
361 b.chop(SBuf::npos,4);
362 SBuf ref("");
363 CPPUNIT_ASSERT_EQUAL(ref,b);
364 }
365 { // chop beyond end
366 SBuf b(a);
367 b.chop(b.length()+2,4);
368 SBuf ref("");
369 CPPUNIT_ASSERT_EQUAL(ref,b);
370 }
371 { // null-chop
372 SBuf b(a);
373 b.chop(0,b.length());
374 SBuf ref(a);
375 CPPUNIT_ASSERT_EQUAL(ref,b);
376 }
377 { // overflow chopped area
378 SBuf b(a);
379 b.chop(b.length()-3,b.length());
380 SBuf ref("xyz");
381 CPPUNIT_ASSERT_EQUAL(ref,b);
382 }
383 }
384
385 void
386 testSBuf::testChomp()
387 {
388 SBuf s1("complete string");
389 SBuf s2(s1);
390 s2.trim(SBuf(" ,"));
391 CPPUNIT_ASSERT_EQUAL(s1,s2);
392 s2.assign(" complete string ,");
393 s2.trim(SBuf(" ,"));
394 CPPUNIT_ASSERT_EQUAL(s1,s2);
395 s1.assign(", complete string ,");
396 s2=s1;
397 s2.trim(SBuf(" "));
398 CPPUNIT_ASSERT_EQUAL(s1,s2);
399 }
400
401 // inspired by SBufFindTest; to be expanded.
402 class SBufSubstrAutoTest
403 {
404 SBuf fullString, sb;
405 std::string fullReference, str;
406 public:
407 void performEqualityTest() {
408 SBuf ref(str);
409 CPPUNIT_ASSERT_EQUAL(ref,sb);
410 }
411 SBufSubstrAutoTest() : fullString(fox), fullReference(fox) {
412 for (int offset=fullString.length()-1; offset >= 0; --offset ) {
413 for (int length=fullString.length()-1-offset; length >= 0; --length) {
414 sb=fullString.substr(offset,length);
415 str=fullReference.substr(offset,length);
416 performEqualityTest();
417 }
418 }
419 }
420 };
421
422 void
423 testSBuf::testSubstr()
424 {
425 SBuf s1(literal),s2,s3;
426 s2=s1.substr(4,5);
427 s3.assign("quick");
428 CPPUNIT_ASSERT_EQUAL(s2,s3);
429 s1.chop(4,5);
430 CPPUNIT_ASSERT_EQUAL(s1,s2);
431 SBufSubstrAutoTest sat; // work done in the constructor
432 }
433
434 void
435 testSBuf::testFindChar()
436 {
437 const char *alphabet="abcdefghijklmnopqrstuvwxyz";
438 SBuf s1(alphabet);
439 SBuf::size_type idx;
440 SBuf::size_type nposResult=SBuf::npos;
441
442 // FORWARD SEARCH
443 // needle in haystack
444 idx=s1.find('d');
445 CPPUNIT_ASSERT_EQUAL(3U,idx);
446 CPPUNIT_ASSERT_EQUAL('d',s1[idx]);
447
448 // needle not present in haystack
449 idx=s1.find(' '); //fails
450 CPPUNIT_ASSERT_EQUAL(nposResult,idx);
451
452 // search in portion
453 idx=s1.find('e',3U);
454 CPPUNIT_ASSERT_EQUAL(4U,idx);
455
456 // char not in searched portion
457 idx=s1.find('e',5U);
458 CPPUNIT_ASSERT_EQUAL(nposResult,idx);
459
460 // invalid start position
461 idx=s1.find('d',SBuf::npos);
462 CPPUNIT_ASSERT_EQUAL(nposResult,idx);
463
464 // search outside of haystack
465 idx=s1.find('d',s1.length()+1);
466 CPPUNIT_ASSERT_EQUAL(nposResult,idx);
467
468 // REVERSE SEARCH
469 // needle in haystack
470 idx=s1.rfind('d');
471 CPPUNIT_ASSERT_EQUAL(3U, idx);
472 CPPUNIT_ASSERT_EQUAL('d', s1[idx]);
473
474 // needle not present in haystack
475 idx=s1.rfind(' '); //fails
476 CPPUNIT_ASSERT_EQUAL(nposResult,idx);
477
478 // search in portion
479 idx=s1.rfind('e',5);
480 CPPUNIT_ASSERT_EQUAL(4U,idx);
481
482 // char not in searched portion
483 idx=s1.rfind('e',3);
484 CPPUNIT_ASSERT_EQUAL(nposResult,idx);
485
486 // overlong haystack specification
487 idx=s1.rfind('d',s1.length()+1);
488 CPPUNIT_ASSERT_EQUAL(3U,idx);
489 }
490
491 void
492 testSBuf::testFindSBuf()
493 {
494 const char *alphabet="abcdefghijklmnopqrstuvwxyz";
495 SBuf haystack(alphabet);
496 SBuf::size_type idx;
497 SBuf::size_type nposResult=SBuf::npos;
498
499 // FORWARD search
500 // needle in haystack
501 idx = haystack.find(SBuf("def"));
502 CPPUNIT_ASSERT_EQUAL(3U,idx);
503
504 idx = haystack.find(SBuf("xyz"));
505 CPPUNIT_ASSERT_EQUAL(23U,idx);
506
507 // needle not in haystack, no initial char match
508 idx = haystack.find(SBuf(" eq"));
509 CPPUNIT_ASSERT_EQUAL(nposResult, idx);
510
511 // needle not in haystack, initial sequence match
512 idx = haystack.find(SBuf("deg"));
513 CPPUNIT_ASSERT_EQUAL(nposResult, idx);
514
515 // needle past end of haystack
516 idx = haystack.find(SBuf("xyz1"));
517 CPPUNIT_ASSERT_EQUAL(nposResult, idx);
518
519 // search in portion: needle not in searched part
520 idx = haystack.find(SBuf("def"),7);
521 CPPUNIT_ASSERT_EQUAL(nposResult, idx);
522
523 // search in portion: overhang
524 idx = haystack.find(SBuf("def"),4);
525 CPPUNIT_ASSERT_EQUAL(nposResult, idx);
526
527 // invalid start position
528 idx = haystack.find(SBuf("def"),SBuf::npos);
529 CPPUNIT_ASSERT_EQUAL(nposResult, idx);
530
531 // needle bigger than haystack
532 idx = SBuf("def").find(haystack);
533 CPPUNIT_ASSERT_EQUAL(nposResult, idx);
534
535 // search in a double-matching haystack
536 {
537 SBuf h2=haystack;
538 h2.append(haystack);
539
540 idx = h2.find(SBuf("def"));
541 CPPUNIT_ASSERT_EQUAL(3U,idx);
542
543 idx = h2.find(SBuf("xyzab"));
544 CPPUNIT_ASSERT_EQUAL(23U,idx);
545 }
546
547 // REVERSE search
548 // needle in haystack
549 idx = haystack.rfind(SBuf("def"));
550 CPPUNIT_ASSERT_EQUAL(3U,idx);
551
552 idx = haystack.rfind(SBuf("xyz"));
553 CPPUNIT_ASSERT_EQUAL(23U,idx);
554
555 // needle not in haystack, no initial char match
556 idx = haystack.rfind(SBuf(" eq"));
557 CPPUNIT_ASSERT_EQUAL(nposResult, idx);
558
559 // needle not in haystack, initial sequence match
560 idx = haystack.rfind(SBuf("deg"));
561 CPPUNIT_ASSERT_EQUAL(nposResult, idx);
562
563 // needle past end of haystack
564 idx = haystack.rfind(SBuf("xyz1"));
565 CPPUNIT_ASSERT_EQUAL(nposResult, idx);
566
567 // search in portion: needle in searched part
568 idx = haystack.rfind(SBuf("def"),7);
569 CPPUNIT_ASSERT_EQUAL(3U, idx);
570
571 // search in portion: needle not in searched part
572 idx = haystack.rfind(SBuf("mno"),3);
573 CPPUNIT_ASSERT_EQUAL(nposResult, idx);
574
575 // search in portion: overhang
576 idx = haystack.rfind(SBuf("def"),4);
577 CPPUNIT_ASSERT_EQUAL(3U, idx);
578
579 // npos start position
580 idx = haystack.rfind(SBuf("def"),SBuf::npos);
581 CPPUNIT_ASSERT_EQUAL(3U, idx);
582
583 // needle bigger than haystack
584 idx = SBuf("def").rfind(haystack);
585 CPPUNIT_ASSERT_EQUAL(nposResult, idx);
586
587 // search in a double-matching haystack
588 {
589 SBuf h2=haystack;
590 h2.append(haystack);
591
592 idx = h2.rfind(SBuf("def"));
593 CPPUNIT_ASSERT_EQUAL(29U,idx);
594
595 idx = h2.find(SBuf("xyzab"));
596 CPPUNIT_ASSERT_EQUAL(23U,idx);
597 }
598 }
599
600 void
601 testSBuf::testRFindChar()
602 {
603 SBuf s1(literal);
604 SBuf::size_type idx;
605 idx=s1.rfind(' ');
606 CPPUNIT_ASSERT_EQUAL(40U,idx);
607 CPPUNIT_ASSERT_EQUAL(' ',s1[idx]);
608 }
609
610 void
611 testSBuf::testRFindSBuf()
612 {
613 SBuf haystack(literal),afox("fox");
614 SBuf goobar("goobar");
615 SBuf::size_type idx;
616
617 // corner case: search for a zero-length SBuf
618 idx=haystack.rfind(SBuf(""));
619 CPPUNIT_ASSERT_EQUAL(haystack.length(),idx);
620
621 // corner case: search for a needle longer than the haystack
622 idx=afox.rfind(SBuf(" "));
623 CPPUNIT_ASSERT_EQUAL(SBuf::npos,idx);
624
625 idx=haystack.rfind(SBuf("fox"));
626 CPPUNIT_ASSERT_EQUAL(16U,idx);
627
628 // needle not found, no match for first char
629 idx=goobar.rfind(SBuf("foo"));
630 CPPUNIT_ASSERT_EQUAL(SBuf::npos,idx);
631
632 // needle not found, match for first char but no match for SBuf
633 idx=haystack.rfind(SBuf("foe"));
634 CPPUNIT_ASSERT_EQUAL(SBuf::npos,idx);
635
636 SBuf g("g"); //match at the last char
637 idx=haystack.rfind(g);
638 CPPUNIT_ASSERT_EQUAL(43U,idx);
639 CPPUNIT_ASSERT_EQUAL('g',haystack[idx]);
640
641 idx=haystack.rfind(SBuf("The"));
642 CPPUNIT_ASSERT_EQUAL(0U,idx);
643
644 haystack.append("The");
645 idx=haystack.rfind(SBuf("The"));
646 CPPUNIT_ASSERT_EQUAL(44U,idx);
647
648 //partial match
649 haystack="The quick brown fox";
650 SBuf needle("foxy lady");
651 idx=haystack.rfind(needle);
652 CPPUNIT_ASSERT_EQUAL(SBuf::npos,idx);
653 }
654
655 void
656 testSBuf::testSBufLength()
657 {
658 SBuf s(fox);
659 CPPUNIT_ASSERT_EQUAL(strlen(fox),(size_t)s.length());
660 }
661
662 void
663 testSBuf::testScanf()
664 {
665 SBuf s1;
666 char s[128];
667 int i;
668 float f;
669 int rv;
670 s1.assign("string , 123 , 123.50");
671 rv=s1.scanf("%s , %d , %f",s,&i,&f);
672 CPPUNIT_ASSERT_EQUAL(3,rv);
673 CPPUNIT_ASSERT_EQUAL(0,strcmp(s,"string"));
674 CPPUNIT_ASSERT_EQUAL(123,i);
675 CPPUNIT_ASSERT_EQUAL(static_cast<float>(123.5),f);
676 }
677
678 void
679 testSBuf::testCopy()
680 {
681 char buf[40]; //shorter than literal()
682 SBuf s(fox1),s2;
683 CPPUNIT_ASSERT_EQUAL(s.length(),s.copy(buf,40));
684 CPPUNIT_ASSERT_EQUAL(0,strncmp(s.rawContent(),buf,s.length()));
685 s=literal;
686 CPPUNIT_ASSERT_EQUAL(40U,s.copy(buf,40));
687 s2.assign(buf,40);
688 s.chop(0,40);
689 CPPUNIT_ASSERT_EQUAL(s2,s);
690 }
691
692 void
693 testSBuf::testStringOps()
694 {
695 SBuf sng(literal.toLower()),
696 ref("the quick brown fox jumped over the lazy dog");
697 CPPUNIT_ASSERT_EQUAL(ref,sng);
698 sng=literal;
699 CPPUNIT_ASSERT_EQUAL(0,sng.compare(ref,caseInsensitive));
700 // max-size comparison
701 CPPUNIT_ASSERT_EQUAL(0,ref.compare(SBuf("THE"),caseInsensitive,3));
702 CPPUNIT_ASSERT_EQUAL(1,ref.compare(SBuf("THE"),caseInsensitive,6));
703 CPPUNIT_ASSERT_EQUAL(0,SBuf("the").compare(SBuf("THE"),caseInsensitive,6));
704 }
705
706 void
707 testSBuf::testGrow()
708 {
709 SBuf t;
710 t.assign("foo");
711 const char *ref=t.rawContent();
712 t.reserveCapacity(10240);
713 const char *match=t.rawContent();
714 CPPUNIT_ASSERT(match!=ref);
715 ref=match;
716 t.append(literal).append(literal).append(literal).append(literal).append(literal);
717 t.append(t).append(t).append(t).append(t).append(t);
718 CPPUNIT_ASSERT_EQUAL(ref,match);
719 }
720
721 void
722 testSBuf::testStartsWith()
723 {
724 static SBuf casebuf("THE QUICK");
725 CPPUNIT_ASSERT(literal.startsWith(SBuf(fox1)));
726 CPPUNIT_ASSERT(!SBuf("The quick brown").startsWith(SBuf(fox1))); //too short
727 CPPUNIT_ASSERT(!literal.startsWith(SBuf(fox2))); //different contents
728
729 // case-insensitive checks
730 CPPUNIT_ASSERT(literal.startsWith(casebuf,caseInsensitive));
731 casebuf=SBuf(fox1).toUpper();
732 CPPUNIT_ASSERT(literal.startsWith(casebuf,caseInsensitive));
733 CPPUNIT_ASSERT(literal.startsWith(SBuf(fox1),caseInsensitive));
734 casebuf = "tha quick";
735 CPPUNIT_ASSERT_EQUAL(false,literal.startsWith(casebuf,caseInsensitive));
736 }
737
738 void
739 testSBuf::testSBufStream()
740 {
741 SBuf b("const.string, int 10 and a float 10.5");
742 SBufStream ss;
743 ss << "const.string, int " << 10 << " and a float " << 10.5;
744 SBuf o=ss.buf();
745 CPPUNIT_ASSERT_EQUAL(b,o);
746 ss.clearBuf();
747 o=ss.buf();
748 CPPUNIT_ASSERT_EQUAL(SBuf(),o);
749 SBuf f1(fox1);
750 SBufStream ss2(f1);
751 ss2 << fox2;
752 CPPUNIT_ASSERT_EQUAL(ss2.buf(),literal);
753 CPPUNIT_ASSERT_EQUAL(f1,SBuf(fox1));
754 }
755
756 void
757 testSBuf::testFindFirstOf()
758 {
759 SBuf haystack(literal);
760 SBuf::size_type idx;
761
762 // not found
763 idx=haystack.findFirstOf(CharacterSet("t1","ADHRWYP"));
764 CPPUNIT_ASSERT_EQUAL(SBuf::npos,idx);
765
766 // found at beginning
767 idx=haystack.findFirstOf(CharacterSet("t2","THANDF"));
768 CPPUNIT_ASSERT_EQUAL(0U,idx);
769
770 //found at end of haystack
771 idx=haystack.findFirstOf(CharacterSet("t3","QWERYVg"));
772 CPPUNIT_ASSERT_EQUAL(haystack.length()-1,idx);
773
774 //found in the middle of haystack
775 idx=haystack.findFirstOf(CharacterSet("t4","QWERqYV"));
776 CPPUNIT_ASSERT_EQUAL(4U,idx);
777 }
778
779 void
780 testSBuf::testFindFirstNotOf()
781 {
782 SBuf haystack(literal);
783 SBuf::size_type idx;
784
785 // all chars from the set
786 idx=haystack.findFirstNotOf(CharacterSet("t1",literal.c_str()));
787 CPPUNIT_ASSERT_EQUAL(SBuf::npos,idx);
788
789 // found at beginning
790 idx=haystack.findFirstNotOf(CharacterSet("t2","a"));
791 CPPUNIT_ASSERT_EQUAL(0U,idx);
792
793 //found at end of haystack
794 idx=haystack.findFirstNotOf(CharacterSet("t3",literal.substr(0,literal.length()-1).c_str()));
795 CPPUNIT_ASSERT_EQUAL(haystack.length()-1,idx);
796
797 //found in the middle of haystack
798 idx=haystack.findFirstNotOf(CharacterSet("t4","The"));
799 CPPUNIT_ASSERT_EQUAL(3U,idx);
800 }
801
802
803 void
804 testSBuf::testAutoFind()
805 {
806 SBufFindTest test;
807 test.run();
808 }
809
810 void
811 testSBuf::testStdStringOps()
812 {
813 const char *alphabet="abcdefghijklmnopqrstuvwxyz";
814 std::string astr(alphabet);
815 SBuf sb(alphabet);
816 CPPUNIT_ASSERT_EQUAL(astr,sb.toStdString());
817 }