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