Squid Web Cache master
Loading...
Searching...
No Matches
testSBuf.cc
Go to the documentation of this file.
1/*
2 * Copyright (C) 1996-2025 The Squid Software Foundation and contributors
3 *
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.
7 */
8
9#include "squid.h"
10#include "base/CharacterSet.h"
11#include "base/TextException.h"
12#include "compat/cppunit.h"
13#include "event.h"
14#include "HttpReply.h"
15#include "MemObject.h"
16#include "sbuf/Algorithms.h"
17#include "sbuf/SBuf.h"
18#include "sbuf/Stream.h"
19#include "tests/SBufFindTest.h"
20#include "unitTestMain.h"
21
22#include <algorithm>
23#include <iostream>
24#include <stdexcept>
25#include <unordered_map>
26
27/*
28 * test the SBuf functionalities
29 */
30
31class TestSBuf : public CPPUNIT_NS::TestFixture
32{
69 // CPPUNIT_TEST( testDumpStats ); //fake test, to print alloc stats
71
72protected:
73 void commonInit();
76 void testEqualityTest();
77 void testAppendSBuf();
78 void testAppendCString();
80 void testAppendf();
81 void testPrintf();
82 void testSubscriptOp();
84 void testDumpStats();
85 void testComparisons();
86 void testConsume();
87 void testRawContent();
88 void testRawSpace();
89 void testChop();
90 void testChomp();
91 void testSubstr();
93 void testSBufLength();
94 void testFindChar();
95 void testFindSBuf();
96 void testRFindChar();
97 void testRFindSBuf();
99 void testCopy();
100 void testStringOps();
101 void testGrow();
102 void testReserve();
103 void testStartsWith();
104 void testSBufStream();
105 void testFindFirstOf();
106 void testFindFirstNotOf();
107 void testAutoFind();
108 void testStdStringOps();
109 void testIterators();
110 void testSBufHash();
111 void testStdAlgorithm();
112};
114
115/* let this test link sanely */
116void
117eventAdd(const char *, EVH *, void *, double, int, bool)
118{}
119int64_t
121{ return 0; }
122/* end of stubs */
123
124// test string
125static const char fox[] = "The quick brown fox jumped over the lazy dog";
126static const char fox1[] = "The quick brown fox ";
127static const char fox2[] = "jumped over the lazy dog";
128
129// TEST: globals variables (default/empty and with contents) are
130// created outside and before any unit tests and memory subsystem
131// initialization. Check for correct constructor operation.
133SBuf literal("The quick brown fox jumped over the lazy dog");
134
135void
137{
138 /* NOTE: Do not initialize memory here because we need
139 * to test correct operation before and after Mem::Init
140 */
141
142 // XXX: partial demo below of how to do constructor unit-test. use scope to ensure each test
143 // is working on local-scope variables constructed fresh for the test, and destructed when
144 // scope exists. use nested scopes to test destructor affects on copied data (MemBlob etc)
145
146 // TEST: default constructor (implicit destructor non-crash test)
147 // test accessors on empty SBuf.
148 {
149 SBuf s1;
150 CPPUNIT_ASSERT_EQUAL(0U,s1.length());
151 CPPUNIT_ASSERT_EQUAL(SBuf(""),s1);
152 CPPUNIT_ASSERT_EQUAL(empty_sbuf,s1);
153 CPPUNIT_ASSERT_EQUAL(0,strcmp("",s1.c_str()));
154 }
155
156 // TEST: copy-construct NULL string (implicit destructor non-crash test)
157 {
158 SBuf s1(nullptr);
159 CPPUNIT_ASSERT_EQUAL(0U,s1.length());
160 CPPUNIT_ASSERT_EQUAL(SBuf(""),s1);
161 CPPUNIT_ASSERT_EQUAL(empty_sbuf,s1);
162 CPPUNIT_ASSERT_EQUAL(0,strcmp("",s1.c_str()));
163 }
164
165 // TEST: copy-construct empty string (implicit destructor non-crash test)
166 {
167 SBuf s1("");
168 CPPUNIT_ASSERT_EQUAL(0U,s1.length());
169 CPPUNIT_ASSERT_EQUAL(SBuf(""),s1);
170 CPPUNIT_ASSERT_EQUAL(empty_sbuf,s1);
171 CPPUNIT_ASSERT_EQUAL(0,strcmp("",s1.c_str()));
172 }
173
174 // TEST: copy-construct from a SBuf
175 {
177 CPPUNIT_ASSERT_EQUAL(0U,s1.length());
178 CPPUNIT_ASSERT_EQUAL(SBuf(""),s1);
179 CPPUNIT_ASSERT_EQUAL(empty_sbuf,s1);
180 CPPUNIT_ASSERT_EQUAL(0,strcmp("",s1.c_str()));
181
182 SBuf s5(literal);
183 CPPUNIT_ASSERT_EQUAL(literal,s5);
184 SBuf s6(fox);
185 CPPUNIT_ASSERT_EQUAL(literal,s6);
186 // XXX: other state checks. expected result of calling any state accessor on s4 ?
187 }
188
189 // TEST: check that COW doesn't happen upon copy-construction
190 {
191 SBuf s1(empty_sbuf), s2(s1);
192 CPPUNIT_ASSERT_EQUAL(s1.rawContent(), s2.rawContent());
193 SBuf s3(literal), s4(literal);
194 CPPUNIT_ASSERT_EQUAL(s3.rawContent(), s4.rawContent());
195 }
196
197 // TEST: sub-string copy
198 {
199 SBuf s1=SBuf(fox+4), s2(fox);
200 SBuf s3=s2.substr(4,s2.length()); //n is out-of-bounds
201 CPPUNIT_ASSERT_EQUAL(s1,s3);
202 SBuf s4=SBuf(fox,4);
203 s3=s2.substr(0,4);
204 CPPUNIT_ASSERT_EQUAL(s4,s3);
205 }
206
207 // TEST: go via std::string adapter.
208 {
209 std::string str(fox);
210 SBuf s1(str);
211 CPPUNIT_ASSERT_EQUAL(literal,s1);
212 }
213}
214
215void
221
222void
224{
225 SBuf s1(fox),s2(fox);
226 CPPUNIT_ASSERT_EQUAL(s1,s1); //self-equality
227 CPPUNIT_ASSERT_EQUAL(s1,s2); //same contents
228 s2.assign("The quick brown fox jumped over the lazy doe");
229 CPPUNIT_ASSERT(!(s1 == s2)); //same length, different contents
230 s2.assign("foo");
231 CPPUNIT_ASSERT(!(s1 == s2)); //different length and contents
232 CPPUNIT_ASSERT(s1 != s2); //while we're ready, let's test inequality
233 s2.clear();
234 CPPUNIT_ASSERT(!(s1 == s2)); //null and not-null
235 CPPUNIT_ASSERT(s1 != s2); //while we're ready, let's test inequality
236 s1.clear();
237 CPPUNIT_ASSERT_EQUAL(s1,s2); //null and null
238}
239
240void
242{
243 const SBuf appendix(fox1);
244 const char * const rawAppendix = appendix.rawContent();
245
246 // check whether the optimization that prevents copying when append()ing to
247 // default-constructed SBuf actually works
248 SBuf s0;
249 s0.append(appendix);
250 CPPUNIT_ASSERT_EQUAL(s0.rawContent(), appendix.rawContent());
251 CPPUNIT_ASSERT_EQUAL(s0, appendix);
252
253 // paranoid: check that the above code can actually detect copies
254 SBuf s1(fox1);
255 s1.append(appendix);
256 CPPUNIT_ASSERT(s1.rawContent() != appendix.rawContent());
257 CPPUNIT_ASSERT(s1 != appendix);
258 CPPUNIT_ASSERT_EQUAL(rawAppendix, appendix.rawContent());
259}
260
261void
263{
264 SBuf s1,s2;
265 s1.Printf("%s:%d:%03.3f","fox",10,12345.67);
266 s2.assign("fox:10:12345.670");
267 CPPUNIT_ASSERT_EQUAL(s1,s2);
268}
269
270void
272{
273 SBuf s1(fox1);
274 s1.append(fox2);
275 CPPUNIT_ASSERT_EQUAL(s1,literal);
276}
277
278void
280{
281 const char *alphabet="abcdefghijklmnopqrstuvwxyz";
282 {
283 SBuf alpha(alphabet), s;
284 s.append(alphabet,5).append(alphabet+5);
285 CPPUNIT_ASSERT_EQUAL(alpha,s);
286 }
287 {
288 SBuf s;
289 std::string control;
290 s.append(alphabet,5).append("\0",1).append(alphabet+6,SBuf::npos);
291 control.append(alphabet,5).append(1,'\0').append(alphabet,6,std::string::npos);
292 SBuf scontrol(control); // we need this to test the equality. sigh.
293 CPPUNIT_ASSERT_EQUAL(scontrol,s);
294 }
295 {
296 const char *alphazero="abcdefghijk\0mnopqrstuvwxyz";
297 SBuf s(alphazero,26);
298 std::string str(alphazero,26);
299 CPPUNIT_ASSERT_EQUAL(0,memcmp(str.data(),s.rawContent(),26));
300 }
301}
302
303void
305{
306 SBuf s1,s2;
307 s1.appendf("%s:%d:%03.2f",fox,1234,1234.56);
308 s2.assign("The quick brown fox jumped over the lazy dog:1234:1234.56");
309 CPPUNIT_ASSERT_EQUAL(s2,s1);
310}
311
312void
314{
315 SBuf::GetStats().dump(std::cout);
316 MemBlob::GetStats().dump(std::cout);
317 std::cout << "sizeof(SBuf): " << sizeof(SBuf) << std::endl;
318 std::cout << "sizeof(MemBlob): " << sizeof(MemBlob) << std::endl;
319}
320
321void
323{
324 SBuf chg(literal);
325 CPPUNIT_ASSERT_EQUAL(chg[5],'u');
326 chg.setAt(5,'e');
327 CPPUNIT_ASSERT_EQUAL(literal[5],'u');
328 CPPUNIT_ASSERT_EQUAL(chg[5],'e');
329}
330
331// note: can't use cppunit's CPPUNIT_TEST_EXCEPTION because TextException asserts, and
332// so the test can't be properly completed.
333void
335{
336 char c;
337 c=literal.at(literal.length()); //out of bounds by 1
338 //notreached
339 std::cout << c << std::endl;
340}
341
342static int sign(int v)
343{
344 if (v < 0)
345 return -1;
346 if (v>0)
347 return 1;
348 return 0;
349}
350
351static void
352testComparisonStdFull(const char *left, const char *right)
353{
354 if (sign(strcmp(left, right)) != sign(SBuf(left).cmp(SBuf(right))))
355 std::cerr << std::endl << " cmp(SBuf) npos " << left << " ?= " << right << std::endl;
356 CPPUNIT_ASSERT_EQUAL(sign(strcmp(left, right)), sign(SBuf(left).cmp(SBuf(right))));
357
358 if (sign(strcmp(left, right)) != sign(SBuf(left).cmp(right)))
359 std::cerr << std::endl << " cmp(char*) npos " << left << " ?= " << right << std::endl;
360 CPPUNIT_ASSERT_EQUAL(sign(strcmp(left, right)), sign(SBuf(left).cmp(right)));
361
362 if (sign(strcasecmp(left, right)) != sign(SBuf(left).caseCmp(SBuf(right))))
363 std::cerr << std::endl << " caseCmp(SBuf) npos " << left << " ?= " << right << std::endl;
364 CPPUNIT_ASSERT_EQUAL(sign(strcasecmp(left, right)), sign(SBuf(left).caseCmp(SBuf(right))));
365
366 if (sign(strcasecmp(left, right)) != sign(SBuf(left).caseCmp(right)))
367 std::cerr << std::endl << " caseCmp(char*) npos " << left << " ?= " << right << std::endl;
368 CPPUNIT_ASSERT_EQUAL(sign(strcasecmp(left, right)), sign(SBuf(left).caseCmp(right)));
369}
370
371static void
372testComparisonStdN(const char *left, const char *right, const size_t n)
373{
374 if (sign(strncmp(left, right, n)) != sign(SBuf(left).cmp(SBuf(right), n)))
375 std::cerr << std::endl << " cmp(SBuf) " << n << ' ' << left << " ?= " << right << std::endl;
376 CPPUNIT_ASSERT_EQUAL(sign(strncmp(left, right, n)), sign(SBuf(left).cmp(SBuf(right), n)));
377
378 if (sign(strncmp(left, right, n)) != sign(SBuf(left).cmp(right, n)))
379 std::cerr << std::endl << " cmp(char*) " << n << ' ' << SBuf(left) << " ?= " << right << std::endl;
380 CPPUNIT_ASSERT_EQUAL(sign(strncmp(left, right, n)), sign(SBuf(left).cmp(right, n)));
381
382 if (sign(strncasecmp(left, right, n)) != sign(SBuf(left).caseCmp(SBuf(right), n)))
383 std::cerr << std::endl << " caseCmp(SBuf) " << n << ' ' << left << " ?= " << right << std::endl;
384 CPPUNIT_ASSERT_EQUAL(sign(strncasecmp(left, right, n)), sign(SBuf(left).caseCmp(SBuf(right), n)));
385
386 if (sign(strncasecmp(left, right, n)) != sign(SBuf(left).caseCmp(right, n)))
387 std::cerr << std::endl << " caseCmp(char*) " << n << ' ' << SBuf(left) << " ?= " << right << std::endl;
388 CPPUNIT_ASSERT_EQUAL(sign(strncasecmp(left, right, n)), sign(SBuf(left).caseCmp(right, n)));
389}
390
391static void
392testComparisonStdOneWay(const char *left, const char *right)
393{
394 testComparisonStdFull(left, right);
395 const size_t maxN = 2 + min(strlen(left), strlen(right));
396 for (size_t n = 0; n <= maxN; ++n) {
397 testComparisonStdN(left, right, n);
398 }
399}
400
401static void
402testComparisonStd(const char *s1, const char *s2)
403{
406}
407
408void
410{
411 //same length
412 SBuf s1("foo"),s2("foe");
413 CPPUNIT_ASSERT(s1.cmp(s2)>0);
414 CPPUNIT_ASSERT(s1.caseCmp(s2)>0);
415 CPPUNIT_ASSERT(s2.cmp(s1)<0);
416 CPPUNIT_ASSERT_EQUAL(0,s1.cmp(s2,2));
417 CPPUNIT_ASSERT_EQUAL(0,s1.caseCmp(s2,2));
418 CPPUNIT_ASSERT(s1 > s2);
419 CPPUNIT_ASSERT(s2 < s1);
420 CPPUNIT_ASSERT_EQUAL(sign(s1.cmp(s2)),sign(strcmp(s1.c_str(),s2.c_str())));
421 //different lengths
422 s1.assign("foo");
423 s2.assign("foof");
424 CPPUNIT_ASSERT(s1.cmp(s2)<0);
425 CPPUNIT_ASSERT_EQUAL(sign(s1.cmp(s2)),sign(strcmp(s1.c_str(),s2.c_str())));
426 CPPUNIT_ASSERT(s1 < s2);
427 // specifying the max-length and overhanging size
428 CPPUNIT_ASSERT_EQUAL(1,SBuf("foolong").caseCmp(SBuf("foo"), 5));
429 // case-insensive comparison
430 s1 = "foo";
431 s2 = "fOo";
432 CPPUNIT_ASSERT_EQUAL(0,s1.caseCmp(s2));
433 CPPUNIT_ASSERT_EQUAL(0,s1.caseCmp(s2,2));
434 // \0-clenliness test
435 s1.assign("f\0oo",4);
436 s2.assign("f\0Oo",4);
437 CPPUNIT_ASSERT(s1.cmp(s2) > 0);
438 CPPUNIT_ASSERT_EQUAL(0,s1.caseCmp(s2));
439 CPPUNIT_ASSERT_EQUAL(0,s1.caseCmp(s2,3));
440 CPPUNIT_ASSERT_EQUAL(0,s1.caseCmp(s2,2));
441 CPPUNIT_ASSERT_EQUAL(0,s1.cmp(s2,2));
442
443 testComparisonStd("foo", "fooz");
444 testComparisonStd("foo", "foo");
445 testComparisonStd("foo", "f");
446 testComparisonStd("foo", "bar");
447
448 testComparisonStd("foo", "FOOZ");
449 testComparisonStd("foo", "FOO");
450 testComparisonStd("foo", "F");
451
453
454 // rare case C-string input matching SBuf with N>strlen(s)
455 {
456 char *right = xstrdup("foo34567890123456789012345678");
457 SBuf left("fooZYXWVUTSRQPONMLKJIHGFEDCBA");
458 // is 3 bytes in length. NEVER more.
459 right[3] = '\0';
460 left.setAt(3, '\0');
461
462 // pick another spot to truncate at if something goes horribly wrong.
463 right[14] = '\0';
464 left.setAt(14, '\0');
465
466 const SBuf::size_type maxN = 20 + min(left.length(), static_cast<SBuf::size_type>(strlen(right)));
467 for (SBuf::size_type n = 0; n <= maxN; ++n) {
468 if (sign(strncmp(left.rawContent(), right, n)) != sign(left.cmp(right, n)) )
469 std::cerr << std::endl << " cmp(char*) " << n << ' ' << left << " ?= " << right;
470 CPPUNIT_ASSERT_EQUAL(sign(strncmp(left.rawContent(), right, n)), sign(left.cmp(right, n)));
471 if (sign(strncasecmp(left.rawContent(), right, n)) != sign(left.caseCmp(right, n)))
472 std::cerr << std::endl << " caseCmp(char*) " << n << ' ' << left << " ?= " << right;
473 CPPUNIT_ASSERT_EQUAL(sign(strncasecmp(left.rawContent(), right, n)), sign(left.caseCmp(right, n)));
474 }
475 xfree(right);
476 }
477}
478
479void
481{
482 SBuf s1(literal),s2,s3;
483 s2=s1.consume(4);
484 s3.assign("The ");
485 CPPUNIT_ASSERT_EQUAL(s2,s3);
486 s3.assign("quick brown fox jumped over the lazy dog");
487 CPPUNIT_ASSERT_EQUAL(s1,s3);
488 s1.consume(40);
489 CPPUNIT_ASSERT_EQUAL(s1,SBuf());
490}
491
492void
494{
495 SBuf s1(literal);
496 SBuf s2(s1);
497 s2.append("foo");
498 const char *foo;
499 foo = s1.rawContent();
500 CPPUNIT_ASSERT_EQUAL(0,strncmp(fox,foo,s1.length()));
501 foo = s1.c_str();
502 CPPUNIT_ASSERT(!strcmp(fox,foo));
503}
504
505void
507{
508 SBuf s1(literal);
509 SBuf s2(fox1);
510 char *rb=s2.rawAppendStart(strlen(fox2)+1);
511 strcpy(rb,fox2);
512 s2.rawAppendFinish(rb, strlen(fox2));
513 CPPUNIT_ASSERT_EQUAL(s1,s2);
514}
515
516void
518{
519 SBuf s1(literal),s2;
520 s1.chop(4,5);
521 s2.assign("quick");
522 CPPUNIT_ASSERT_EQUAL(s1,s2);
523 s1=literal;
524 s2.clear();
525 s1.chop(5,0);
526 CPPUNIT_ASSERT_EQUAL(s1,s2);
527 const char *alphabet="abcdefghijklmnopqrstuvwxyz";
528 SBuf a(alphabet);
529 std::string s(alphabet); // TODO
530 { //regular chopping
531 SBuf b(a);
532 b.chop(3,3);
533 SBuf ref("def");
534 CPPUNIT_ASSERT_EQUAL(ref,b);
535 }
536 { // chop at end
537 SBuf b(a);
538 b.chop(b.length()-3);
539 SBuf ref("xyz");
540 CPPUNIT_ASSERT_EQUAL(ref,b);
541 }
542 { // chop at beginning
543 SBuf b(a);
544 b.chop(0,3);
545 SBuf ref("abc");
546 CPPUNIT_ASSERT_EQUAL(ref,b);
547 }
548 { // chop to zero length
549 SBuf b(a);
550 b.chop(5,0);
551 SBuf ref("");
552 CPPUNIT_ASSERT_EQUAL(ref,b);
553 }
554 { // chop beyond end (at npos)
555 SBuf b(a);
556 b.chop(SBuf::npos,4);
557 SBuf ref("");
558 CPPUNIT_ASSERT_EQUAL(ref,b);
559 }
560 { // chop beyond end
561 SBuf b(a);
562 b.chop(b.length()+2,4);
563 SBuf ref("");
564 CPPUNIT_ASSERT_EQUAL(ref,b);
565 }
566 { // null-chop
567 SBuf b(a);
568 b.chop(0,b.length());
569 SBuf ref(a);
570 CPPUNIT_ASSERT_EQUAL(ref,b);
571 }
572 { // overflow chopped area
573 SBuf b(a);
574 b.chop(b.length()-3,b.length());
575 SBuf ref("xyz");
576 CPPUNIT_ASSERT_EQUAL(ref,b);
577 }
578}
579
580void
582{
583 SBuf s1("complete string");
584 SBuf s2(s1);
585 s2.trim(SBuf(" ,"));
586 CPPUNIT_ASSERT_EQUAL(s1,s2);
587 s2.assign(" complete string ,");
588 s2.trim(SBuf(" ,"));
589 CPPUNIT_ASSERT_EQUAL(s1,s2);
590 s1.assign(", complete string ,");
591 s2=s1;
592 s2.trim(SBuf(" "));
593 CPPUNIT_ASSERT_EQUAL(s1,s2);
594}
595
596// inspired by SBufFindTest; to be expanded.
598{
600 std::string fullReference, str;
601public:
603 SBuf ref(str);
604 CPPUNIT_ASSERT_EQUAL(ref,sb);
605 }
607 for (int offset=fullString.length()-1; offset >= 0; --offset ) {
608 for (int length=fullString.length()-1-offset; length >= 0; --length) {
609 sb=fullString.substr(offset,length);
610 str=fullReference.substr(offset,length);
612 }
613 }
614 }
615};
616
617void
619{
620 SBuf s1(literal),s2,s3;
621 s2=s1.substr(4,5);
622 s3.assign("quick");
623 CPPUNIT_ASSERT_EQUAL(s2,s3);
624 s1.chop(4,5);
625 CPPUNIT_ASSERT_EQUAL(s1,s2);
626 SBufSubstrAutoTest sat; // work done in the constructor
627}
628
629void
631{
632 const char *alphabet="abcdefghijklmnopqrstuvwxyz";
633 SBuf s1(alphabet);
634 SBuf::size_type idx;
635 SBuf::size_type nposResult=SBuf::npos;
636
637 // FORWARD SEARCH
638 // needle in haystack
639 idx=s1.find('d');
640 CPPUNIT_ASSERT_EQUAL(3U,idx);
641 CPPUNIT_ASSERT_EQUAL('d',s1[idx]);
642
643 // needle not present in haystack
644 idx=s1.find(' '); //fails
645 CPPUNIT_ASSERT_EQUAL(nposResult,idx);
646
647 // search in portion
648 idx=s1.find('e',3U);
649 CPPUNIT_ASSERT_EQUAL(4U,idx);
650
651 // char not in searched portion
652 idx=s1.find('e',5U);
653 CPPUNIT_ASSERT_EQUAL(nposResult,idx);
654
655 // invalid start position
656 idx=s1.find('d',SBuf::npos);
657 CPPUNIT_ASSERT_EQUAL(nposResult,idx);
658
659 // search outside of haystack
660 idx=s1.find('d',s1.length()+1);
661 CPPUNIT_ASSERT_EQUAL(nposResult,idx);
662
663 // REVERSE SEARCH
664 // needle in haystack
665 idx=s1.rfind('d');
666 CPPUNIT_ASSERT_EQUAL(3U, idx);
667 CPPUNIT_ASSERT_EQUAL('d', s1[idx]);
668
669 // needle not present in haystack
670 idx=s1.rfind(' '); //fails
671 CPPUNIT_ASSERT_EQUAL(nposResult,idx);
672
673 // search in portion
674 idx=s1.rfind('e',5);
675 CPPUNIT_ASSERT_EQUAL(4U,idx);
676
677 // char not in searched portion
678 idx=s1.rfind('e',3);
679 CPPUNIT_ASSERT_EQUAL(nposResult,idx);
680
681 // overlong haystack specification
682 idx=s1.rfind('d',s1.length()+1);
683 CPPUNIT_ASSERT_EQUAL(3U,idx);
684}
685
686void
688{
689 const char *alphabet="abcdefghijklmnopqrstuvwxyz";
690 SBuf haystack(alphabet);
691 SBuf::size_type idx;
692 SBuf::size_type nposResult=SBuf::npos;
693
694 // FORWARD search
695 // needle in haystack
696 idx = haystack.find(SBuf("def"));
697 CPPUNIT_ASSERT_EQUAL(3U,idx);
698
699 idx = haystack.find(SBuf("xyz"));
700 CPPUNIT_ASSERT_EQUAL(23U,idx);
701
702 // needle not in haystack, no initial char match
703 idx = haystack.find(SBuf(" eq"));
704 CPPUNIT_ASSERT_EQUAL(nposResult, idx);
705
706 // needle not in haystack, initial sequence match
707 idx = haystack.find(SBuf("deg"));
708 CPPUNIT_ASSERT_EQUAL(nposResult, idx);
709
710 // needle past end of haystack
711 idx = haystack.find(SBuf("xyz1"));
712 CPPUNIT_ASSERT_EQUAL(nposResult, idx);
713
714 // search in portion: needle not in searched part
715 idx = haystack.find(SBuf("def"),7);
716 CPPUNIT_ASSERT_EQUAL(nposResult, idx);
717
718 // search in portion: overhang
719 idx = haystack.find(SBuf("def"),4);
720 CPPUNIT_ASSERT_EQUAL(nposResult, idx);
721
722 // invalid start position
723 idx = haystack.find(SBuf("def"),SBuf::npos);
724 CPPUNIT_ASSERT_EQUAL(nposResult, idx);
725
726 // needle bigger than haystack
727 idx = SBuf("def").find(haystack);
728 CPPUNIT_ASSERT_EQUAL(nposResult, idx);
729
730 // search in a double-matching haystack
731 {
732 SBuf h2=haystack;
733 h2.append(haystack);
734
735 idx = h2.find(SBuf("def"));
736 CPPUNIT_ASSERT_EQUAL(3U,idx);
737
738 idx = h2.find(SBuf("xyzab"));
739 CPPUNIT_ASSERT_EQUAL(23U,idx);
740 }
741
742 // REVERSE search
743 // needle in haystack
744 idx = haystack.rfind(SBuf("def"));
745 CPPUNIT_ASSERT_EQUAL(3U,idx);
746
747 idx = haystack.rfind(SBuf("xyz"));
748 CPPUNIT_ASSERT_EQUAL(23U,idx);
749
750 // needle not in haystack, no initial char match
751 idx = haystack.rfind(SBuf(" eq"));
752 CPPUNIT_ASSERT_EQUAL(nposResult, idx);
753
754 // needle not in haystack, initial sequence match
755 idx = haystack.rfind(SBuf("deg"));
756 CPPUNIT_ASSERT_EQUAL(nposResult, idx);
757
758 // needle past end of haystack
759 idx = haystack.rfind(SBuf("xyz1"));
760 CPPUNIT_ASSERT_EQUAL(nposResult, idx);
761
762 // search in portion: needle in searched part
763 idx = haystack.rfind(SBuf("def"),7);
764 CPPUNIT_ASSERT_EQUAL(3U, idx);
765
766 // search in portion: needle not in searched part
767 idx = haystack.rfind(SBuf("mno"),3);
768 CPPUNIT_ASSERT_EQUAL(nposResult, idx);
769
770 // search in portion: overhang
771 idx = haystack.rfind(SBuf("def"),4);
772 CPPUNIT_ASSERT_EQUAL(3U, idx);
773
774 // npos start position
775 idx = haystack.rfind(SBuf("def"),SBuf::npos);
776 CPPUNIT_ASSERT_EQUAL(3U, idx);
777
778 // needle bigger than haystack
779 idx = SBuf("def").rfind(haystack);
780 CPPUNIT_ASSERT_EQUAL(nposResult, idx);
781
782 // search in a double-matching haystack
783 {
784 SBuf h2=haystack;
785 h2.append(haystack);
786
787 idx = h2.rfind(SBuf("def"));
788 CPPUNIT_ASSERT_EQUAL(29U,idx);
789
790 idx = h2.find(SBuf("xyzab"));
791 CPPUNIT_ASSERT_EQUAL(23U,idx);
792 }
793}
794
795void
797{
798 SBuf s1(literal);
799 SBuf::size_type idx;
800 idx=s1.rfind(' ');
801 CPPUNIT_ASSERT_EQUAL(40U,idx);
802 CPPUNIT_ASSERT_EQUAL(' ',s1[idx]);
803}
804
805void
807{
808 SBuf haystack(literal),afox("fox");
809 SBuf goobar("goobar");
810 SBuf::size_type idx;
811
812 // corner case: search for a zero-length SBuf
813 idx=haystack.rfind(SBuf(""));
814 CPPUNIT_ASSERT_EQUAL(haystack.length(),idx);
815
816 // corner case: search for a needle longer than the haystack
817 idx=afox.rfind(SBuf(" "));
818 CPPUNIT_ASSERT_EQUAL(SBuf::npos,idx);
819
820 idx=haystack.rfind(SBuf("fox"));
821 CPPUNIT_ASSERT_EQUAL(16U,idx);
822
823 // needle not found, no match for first char
824 idx=goobar.rfind(SBuf("foo"));
825 CPPUNIT_ASSERT_EQUAL(SBuf::npos,idx);
826
827 // needle not found, match for first char but no match for SBuf
828 idx=haystack.rfind(SBuf("foe"));
829 CPPUNIT_ASSERT_EQUAL(SBuf::npos,idx);
830
831 SBuf g("g"); //match at the last char
832 idx=haystack.rfind(g);
833 CPPUNIT_ASSERT_EQUAL(43U,idx);
834 CPPUNIT_ASSERT_EQUAL('g',haystack[idx]);
835
836 idx=haystack.rfind(SBuf("The"));
837 CPPUNIT_ASSERT_EQUAL(0U,idx);
838
839 haystack.append("The");
840 idx=haystack.rfind(SBuf("The"));
841 CPPUNIT_ASSERT_EQUAL(44U,idx);
842
843 //partial match
844 haystack="The quick brown fox";
845 SBuf needle("foxy lady");
846 idx=haystack.rfind(needle);
847 CPPUNIT_ASSERT_EQUAL(SBuf::npos,idx);
848}
849
850void
852{
853 SBuf s(fox);
854 CPPUNIT_ASSERT_EQUAL(strlen(fox),(size_t)s.length());
855}
856
857void
859{
860 char buf[40]; //shorter than literal()
861 SBuf s(fox1),s2;
862 CPPUNIT_ASSERT_EQUAL(s.length(),s.copy(buf,40));
863 CPPUNIT_ASSERT_EQUAL(0,strncmp(s.rawContent(),buf,s.length()));
864 s=literal;
865 CPPUNIT_ASSERT_EQUAL(40U,s.copy(buf,40));
866 s2.assign(buf,40);
867 s.chop(0,40);
868 CPPUNIT_ASSERT_EQUAL(s2,s);
869}
870
871void
873{
874 SBuf sng(ToLower(literal)),
875 ref("the quick brown fox jumped over the lazy dog");
876 CPPUNIT_ASSERT_EQUAL(ref,sng);
877 sng=literal;
878 CPPUNIT_ASSERT_EQUAL(0,sng.compare(ref,caseInsensitive));
879 // max-size comparison
880 CPPUNIT_ASSERT_EQUAL(0,ref.compare(SBuf("THE"),caseInsensitive,3));
881 CPPUNIT_ASSERT_EQUAL(1,ref.compare(SBuf("THE"),caseInsensitive,6));
882 CPPUNIT_ASSERT_EQUAL(0,SBuf("the").compare(SBuf("THE"),caseInsensitive,6));
883}
884
885void
887{
888 SBuf t;
889 t.assign("foo");
890 const char *ref=t.rawContent();
891 t.reserveCapacity(10240);
892 const char *match=t.rawContent();
893 CPPUNIT_ASSERT(match!=ref);
894 ref=match;
896 t.append(t).append(t).append(t).append(t).append(t);
897 CPPUNIT_ASSERT_EQUAL(ref,match);
898}
899
900void
902{
903 SBufReservationRequirements requirements;
904 // use unusual numbers to ensure we do not hit a lucky boundary situation
905 requirements.minSpace = 10;
906 requirements.idealSpace = 82;
907 requirements.maxCapacity = 259;
908 requirements.allowShared = true;
909
910 // for each possible starting buffer length within the capacity
911 for (SBuf::size_type startLength = 0; startLength <= requirements.maxCapacity; ++startLength) {
912 std::cerr << ".";
913 SBuf b;
914 b.reserveCapacity(startLength);
915 CPPUNIT_ASSERT_EQUAL(b.length(), static_cast<unsigned int>(0));
916 CPPUNIT_ASSERT_EQUAL(b.spaceSize(), startLength);
917
918 // check that it never grows outside capacity.
919 // do 5 excess cycles to check that.
920 for (SBuf::size_type filled = 0; filled < requirements.maxCapacity +5; ++filled) {
921 CPPUNIT_ASSERT_EQUAL(b.length(), min(filled, requirements.maxCapacity));
922 auto x = b.reserve(requirements);
923 // the amount of space advertised must not cause users to exceed capacity
924 CPPUNIT_ASSERT(x <= requirements.maxCapacity - filled);
925 CPPUNIT_ASSERT(b.spaceSize() <= requirements.maxCapacity - filled);
926 // the total size of buffer must not cause users to exceed capacity
927 CPPUNIT_ASSERT(b.length() + b.spaceSize() <= requirements.maxCapacity);
928 if (x > 0)
929 b.append('X');
930 }
931 }
932
933 // the minimal space requirement should overwrite idealSpace preferences
934 requirements.minSpace = 10;
935 for (const int delta: {-1,0,+1}) {
936 requirements.idealSpace = requirements.minSpace + delta;
937 SBuf buffer;
938 buffer.reserve(requirements);
939 CPPUNIT_ASSERT(buffer.spaceSize() >= requirements.minSpace);
940 }
941
942 // TODO: Decide whether to encapsulate the (nearly identical) code of the
943 // gap-related test cases below into a function, obscuring each case logic a
944 // little, but facilitating new test cases (and removing code duplication).
945
946 { // reserveSpace() uses the trailing space before the front gap
947 SBuf buffer(fox);
948
949 // assure there is some trailing space
950 buffer.reserveSpace(1);
951 CPPUNIT_ASSERT(buffer.spaceSize() > 0);
952
953 // create a leading gap and (weak-)check that it was created
954 const auto gap = 1U; // the smallest gap may be the most challenging
955 CPPUNIT_ASSERT(gap < buffer.length());
956 const void *gapEnd = buffer.rawContent() + gap;
957 buffer.consume(gap);
958 CPPUNIT_ASSERT_EQUAL(gapEnd, static_cast<const void*>(buffer.rawContent()));
959
960 const auto before = SBuf::GetStats();
961 const auto beforeSpaceSize = buffer.spaceSize();
962 const void * const beforePosition = buffer.rawContent();
963 buffer.reserveSpace(beforeSpaceSize);
964 const auto after = SBuf::GetStats();
965 const void * const afterPosition = buffer.rawContent();
966 CPPUNIT_ASSERT_EQUAL(before.cowAvoided + 1, after.cowAvoided);
967 CPPUNIT_ASSERT_EQUAL(before.cowShift, after.cowShift);
968 CPPUNIT_ASSERT_EQUAL(before.cowJustAlloc, after.cowJustAlloc);
969 CPPUNIT_ASSERT_EQUAL(before.cowAllocCopy, after.cowAllocCopy);
970 CPPUNIT_ASSERT_EQUAL(beforeSpaceSize, buffer.spaceSize());
971 CPPUNIT_ASSERT_EQUAL(beforePosition, afterPosition);
972 CPPUNIT_ASSERT(strcmp(fox + gap, buffer.c_str()) == 0);
973 }
974
975 { // reserveSpace() uses the front gap when the trailing space is not enough
976 SBuf buffer(fox);
977
978 // assure there is some trailing space to keep the test case challenging
979 buffer.reserveSpace(1);
980 CPPUNIT_ASSERT(buffer.spaceSize() > 0);
981 const void * const initialStorage = buffer.rawContent();
982
983 // create a leading gap and (weak-)check that it was created
984 const auto gap = 1U; // the smallest gap may be the most challenging
985 CPPUNIT_ASSERT(gap < buffer.length());
986 const void *gapEnd = buffer.rawContent() + gap;
987 buffer.consume(gap);
988 CPPUNIT_ASSERT_EQUAL(gapEnd, static_cast<const void*>(buffer.rawContent()));
989
990 const auto before = SBuf::GetStats();
991 const auto beforeSpaceSize = buffer.spaceSize();
992 buffer.reserveSpace(beforeSpaceSize + gap); // force (entire) gap use
993 const auto after = SBuf::GetStats();
994 const void * const afterStorage = buffer.rawContent();
995 CPPUNIT_ASSERT_EQUAL(before.cowAvoided, after.cowAvoided);
996 CPPUNIT_ASSERT_EQUAL(before.cowShift + 1, after.cowShift);
997 CPPUNIT_ASSERT_EQUAL(before.cowJustAlloc, after.cowJustAlloc);
998 CPPUNIT_ASSERT_EQUAL(before.cowAllocCopy, after.cowAllocCopy);
999 CPPUNIT_ASSERT_EQUAL(initialStorage, afterStorage);
1000 CPPUNIT_ASSERT(beforeSpaceSize + gap <= buffer.spaceSize());
1001 CPPUNIT_ASSERT(strcmp(fox + gap, buffer.c_str()) == 0);
1002 }
1003
1004 { // reserveSpace() uses the entire front gap when using the front gap
1005 SBuf buffer(fox);
1006
1007 // assure there is some trailing space to keep the test case challenging
1008 buffer.reserveSpace(1);
1009 CPPUNIT_ASSERT(buffer.spaceSize() > 0);
1010 const void * const initialStorage = buffer.rawContent();
1011
1012 // create a leading gap and (weak-)check that it was created
1013 const auto gap = 2U; // the smallest extra gap may be the most challenging
1014 CPPUNIT_ASSERT(gap < buffer.length());
1015 const void *gapEnd = buffer.rawContent() + gap;
1016 buffer.consume(gap);
1017 CPPUNIT_ASSERT_EQUAL(gapEnd, static_cast<const void*>(buffer.rawContent()));
1018
1019 const auto before = SBuf::GetStats();
1020 const auto beforeSpaceSize = buffer.spaceSize();
1021 buffer.reserveSpace(beforeSpaceSize + 1); // force (minimal) gap use
1022 const auto after = SBuf::GetStats();
1023 const void * const afterStorage = buffer.rawContent();
1024 CPPUNIT_ASSERT_EQUAL(before.cowAvoided, after.cowAvoided);
1025 CPPUNIT_ASSERT_EQUAL(before.cowShift + 1, after.cowShift);
1026 CPPUNIT_ASSERT_EQUAL(before.cowJustAlloc, after.cowJustAlloc);
1027 CPPUNIT_ASSERT_EQUAL(before.cowAllocCopy, after.cowAllocCopy);
1028 CPPUNIT_ASSERT_EQUAL(initialStorage, afterStorage);
1029 CPPUNIT_ASSERT(beforeSpaceSize + gap <= buffer.spaceSize());
1030 CPPUNIT_ASSERT(strcmp(fox + gap, buffer.c_str()) == 0);
1031 }
1032}
1033
1034void
1036{
1037 static SBuf casebuf("THE QUICK");
1038 CPPUNIT_ASSERT(literal.startsWith(SBuf(fox1)));
1039 CPPUNIT_ASSERT(!SBuf("The quick brown").startsWith(SBuf(fox1))); //too short
1040 CPPUNIT_ASSERT(!literal.startsWith(SBuf(fox2))); //different contents
1041
1042 // case-insensitive checks
1043 CPPUNIT_ASSERT(literal.startsWith(casebuf,caseInsensitive));
1044 casebuf=ToUpper(SBuf(fox1));
1045 CPPUNIT_ASSERT(literal.startsWith(casebuf,caseInsensitive));
1046 CPPUNIT_ASSERT(literal.startsWith(SBuf(fox1),caseInsensitive));
1047 casebuf = "tha quick";
1048 CPPUNIT_ASSERT_EQUAL(false,literal.startsWith(casebuf,caseInsensitive));
1049}
1050
1051void
1053{
1054 SBuf b("const.string, int 10 and a float 10.5");
1055 SBufStream ss;
1056 ss << "const.string, int " << 10 << " and a float " << 10.5;
1057 SBuf o=ss.buf();
1058 CPPUNIT_ASSERT_EQUAL(b,o);
1059 ss.clearBuf();
1060 o=ss.buf();
1061 CPPUNIT_ASSERT_EQUAL(SBuf(),o);
1062 SBuf f1(fox1);
1063 SBufStream ss2(f1);
1064 ss2 << fox2;
1065 CPPUNIT_ASSERT_EQUAL(ss2.buf(),literal);
1066 CPPUNIT_ASSERT_EQUAL(f1,SBuf(fox1));
1067}
1068
1069void
1071{
1072 SBuf haystack(literal);
1073 SBuf::size_type idx;
1074
1075 // not found
1076 idx=haystack.findFirstOf(CharacterSet("t1","ADHRWYP"));
1077 CPPUNIT_ASSERT_EQUAL(SBuf::npos,idx);
1078
1079 // found at beginning
1080 idx=haystack.findFirstOf(CharacterSet("t2","THANDF"));
1081 CPPUNIT_ASSERT_EQUAL(0U,idx);
1082
1083 //found at end of haystack
1084 idx=haystack.findFirstOf(CharacterSet("t3","QWERYVg"));
1085 CPPUNIT_ASSERT_EQUAL(haystack.length()-1,idx);
1086
1087 //found in the middle of haystack
1088 idx=haystack.findFirstOf(CharacterSet("t4","QWERqYV"));
1089 CPPUNIT_ASSERT_EQUAL(4U,idx);
1090}
1091
1092void
1094{
1095 SBuf haystack(literal);
1096 SBuf::size_type idx;
1097
1098 // all chars from the set
1099 idx=haystack.findFirstNotOf(CharacterSet("t1",literal.c_str()));
1100 CPPUNIT_ASSERT_EQUAL(SBuf::npos,idx);
1101
1102 // found at beginning
1103 idx=haystack.findFirstNotOf(CharacterSet("t2","a"));
1104 CPPUNIT_ASSERT_EQUAL(0U,idx);
1105
1106 //found at end of haystack
1107 idx=haystack.findFirstNotOf(CharacterSet("t3",literal.substr(0,literal.length()-1).c_str()));
1108 CPPUNIT_ASSERT_EQUAL(haystack.length()-1,idx);
1109
1110 //found in the middle of haystack
1111 idx=haystack.findFirstNotOf(CharacterSet("t4","The"));
1112 CPPUNIT_ASSERT_EQUAL(3U,idx);
1113}
1114
1115void
1117{
1118 SBufFindTest test;
1119 test.run();
1120}
1121
1122void
1124{
1125 const char *alphabet="abcdefghijklmnopqrstuvwxyz";
1126 std::string astr(alphabet);
1127 SBuf sb(alphabet);
1128 CPPUNIT_ASSERT_EQUAL(astr,sb.toStdString());
1129}
1130
1131void
1133{
1134 SBuf text("foo"), text2("foo");
1135 CPPUNIT_ASSERT(text.begin() == text.begin());
1136 CPPUNIT_ASSERT(text.begin() != text.end());
1137 CPPUNIT_ASSERT(text.begin() != text2.begin());
1138 {
1139 auto i = text.begin();
1140 auto e = text.end();
1141 CPPUNIT_ASSERT_EQUAL('f', *i);
1142 CPPUNIT_ASSERT(i != e);
1143 ++i;
1144 CPPUNIT_ASSERT_EQUAL('o', *i);
1145 CPPUNIT_ASSERT(i != e);
1146 ++i;
1147 CPPUNIT_ASSERT_EQUAL('o', *i);
1148 CPPUNIT_ASSERT(i != e);
1149 ++i;
1150 CPPUNIT_ASSERT(i == e);
1151 }
1152 {
1153 auto i = text.rbegin();
1154 auto e = text.rend();
1155 CPPUNIT_ASSERT_EQUAL('o', *i);
1156 CPPUNIT_ASSERT(i != e);
1157 ++i;
1158 CPPUNIT_ASSERT_EQUAL('o', *i);
1159 CPPUNIT_ASSERT(i != e);
1160 ++i;
1161 CPPUNIT_ASSERT_EQUAL('f', *i);
1162 CPPUNIT_ASSERT(i != e);
1163 ++i;
1164 CPPUNIT_ASSERT(i == e);
1165 }
1166}
1167
1168void
1170{
1171 // same SBuf must have same hash
1172 auto hasher=std::hash<SBuf>();
1173 CPPUNIT_ASSERT_EQUAL(hasher(literal),hasher(literal));
1174
1175 // same content must have same hash
1176 CPPUNIT_ASSERT_EQUAL(hasher(literal),hasher(SBuf(fox)));
1177 CPPUNIT_ASSERT_EQUAL(hasher(SBuf(fox)),hasher(SBuf(fox)));
1178
1179 //different content should have different hash
1180 CPPUNIT_ASSERT(hasher(SBuf(fox)) != hasher(SBuf(fox1)));
1181
1182 {
1183 std::unordered_map<SBuf, int> um;
1184 um[SBuf("one")] = 1;
1185 um[SBuf("two")] = 2;
1186
1187 auto i = um.find(SBuf("one"));
1188 CPPUNIT_ASSERT(i != um.end());
1189 CPPUNIT_ASSERT(i->second == 1);
1190
1191 i = um.find(SBuf("eleventy"));
1192 CPPUNIT_ASSERT(i == um.end());
1193 }
1194}
1195
1196void
1198{
1199 {
1200 SBuf src(fox), dst;
1201 std::copy(src.begin(), src.end(), std::back_inserter(dst));
1202 CPPUNIT_ASSERT_EQUAL(src, dst);
1203 }
1204
1205 {
1206 SBuf src(fox), dst;
1207 std::copy_if(src.begin(), src.end(), std::back_inserter(dst),
1208 [](char c) { return c != 'o'; });
1209 CPPUNIT_ASSERT_EQUAL(SBuf("The quick brwn fx jumped ver the lazy dg"), dst);
1210 }
1211}
1212
1213int
1214main(int argc, char *argv[])
1215{
1216 return TestProgram().run(argc, argv);
1217}
1218
IcmpPinger control
pinger helper contains one of these as a global object.
Definition pinger.cc:93
SBuf ToUpper(SBuf buf)
Returns a lower-cased copy of its parameter.
Definition SBuf.h:725
@ caseInsensitive
Definition SBuf.h:38
SBuf ToLower(SBuf buf)
Returns an upper-cased copy of its parameter.
Definition SBuf.h:733
@ s1
Definition cf_gen.cc:55
optimized set of C chars, with quick membership test and merge support
std::ostream & dump(std::ostream &os) const
dumps class-wide statistics
Definition MemBlob.cc:33
static const MemBlobStats & GetStats()
obtain a const view of class-wide statistics
Definition MemBlob.cc:53
int64_t endOffset() const
Definition MemObject.cc:214
void run()
generates and executes cases using configuration params
Named SBuf::reserve() parameters. Defaults ask for and restrict nothing.
Definition SBuf.h:701
bool allowShared
whether sharing our storage with others is OK
Definition SBuf.h:713
size_type minSpace
allocate [at least this much] if spaceSize() is smaller
Definition SBuf.h:711
size_type maxCapacity
do not allocate more than this
Definition SBuf.h:712
size_type idealSpace
if allocating anyway, provide this much space
Definition SBuf.h:710
std::ostream & dump(std::ostream &os) const
Dump statistics to an ostream.
Definition Stats.cc:65
SBuf buf()
bytes written so far
Definition Stream.h:41
SBufStream & clearBuf()
Clear the stream's backing store.
Definition Stream.h:47
std::string str
Definition testSBuf.cc:600
void performEqualityTest()
Definition testSBuf.cc:602
std::string fullReference
Definition testSBuf.cc:600
Definition SBuf.h:94
char * rawAppendStart(size_type anticipatedSize)
Definition SBuf.cc:136
int caseCmp(const SBuf &S, const size_type n) const
shorthand version for case-insensitive compare()
Definition SBuf.h:287
const char * rawContent() const
Definition SBuf.cc:509
static const size_type npos
Definition SBuf.h:100
char at(size_type pos) const
Definition SBuf.h:253
SBuf consume(size_type n=npos)
Definition SBuf.cc:481
const char * c_str()
Definition SBuf.cc:516
SBuf & chop(size_type pos, size_type n=npos)
Definition SBuf.cc:530
void reserveCapacity(size_type minCapacity)
Definition SBuf.cc:105
static const SBufStats & GetStats()
gets global statistic information
Definition SBuf.cc:494
size_type length() const
Returns the number of bytes stored in SBuf.
Definition SBuf.h:419
SBuf & appendf(const char *fmt,...) PRINTF_FORMAT_ARG2
Definition SBuf.cc:229
size_type rfind(char c, size_type endPos=npos) const
Definition SBuf.cc:692
size_type reserve(const SBufReservationRequirements &requirements)
Definition SBuf.cc:112
SBuf & Printf(const char *fmt,...) PRINTF_FORMAT_ARG2
Definition SBuf.cc:214
int cmp(const SBuf &S, const size_type n) const
shorthand version for compare()
Definition SBuf.h:279
size_type findFirstNotOf(const CharacterSet &set, size_type startPos=0) const
Definition SBuf.cc:746
SBuf & trim(const SBuf &toRemove, bool atBeginning=true, bool atEnd=true)
Definition SBuf.cc:551
size_type spaceSize() const
Definition SBuf.h:397
size_type find(char c, size_type startPos=0) const
Definition SBuf.cc:584
size_type findFirstOf(const CharacterSet &set, size_type startPos=0) const
Definition SBuf.cc:723
std::string toStdString() const
std::string export function
Definition SBuf.h:585
const_iterator begin() const
Definition SBuf.h:587
SBuf & append(const SBuf &S)
Definition SBuf.cc:185
const_reverse_iterator rbegin() const
Definition SBuf.h:595
void reserveSpace(size_type minSpace)
Definition SBuf.h:444
const_iterator end() const
Definition SBuf.h:591
bool startsWith(const SBuf &S, const SBufCaseSensitive isCaseSensitive=caseSensitive) const
Definition SBuf.cc:442
void clear()
Definition SBuf.cc:175
SBuf substr(size_type pos, size_type n=npos) const
Definition SBuf.cc:576
MemBlob::size_type size_type
Definition SBuf.h:96
void rawAppendFinish(const char *start, size_type actualSize)
Definition SBuf.cc:144
SBuf & assign(const SBuf &S)
Definition SBuf.cc:83
const_reverse_iterator rend() const
Definition SBuf.h:599
void setAt(size_type pos, char toset)
Definition SBuf.cc:328
int compare(const SBuf &S, const SBufCaseSensitive isCaseSensitive, const size_type n) const
Definition SBuf.cc:352
implements test program's main() function while enabling customization
int run(int argc, char *argv[])
CPPUNIT_TEST(testAutoFind)
CPPUNIT_TEST(testRFindChar)
void testFindSBuf()
Definition testSBuf.cc:687
void testSBufStream()
Definition testSBuf.cc:1052
void testRawSpace()
Definition testSBuf.cc:506
void testRFindSBuf()
Definition testSBuf.cc:806
CPPUNIT_TEST(testFindFirstNotOf)
void testSubstr()
Definition testSBuf.cc:618
void testStdStringOps()
Definition testSBuf.cc:1123
void testSubscriptOpFail()
Definition testSBuf.cc:334
CPPUNIT_TEST(testAppendCString)
CPPUNIT_TEST(testConsume)
CPPUNIT_TEST(testFindFirstOf)
void testAppendf()
Definition testSBuf.cc:304
void testSBufConstructDestruct()
Definition testSBuf.cc:136
CPPUNIT_TEST(testStdAlgorithm)
void testStdAlgorithm()
Definition testSBuf.cc:1197
void testGrow()
Definition testSBuf.cc:886
CPPUNIT_TEST(testCopy)
void testFindChar()
Definition testSBuf.cc:630
void testSubscriptOp()
Definition testSBuf.cc:322
CPPUNIT_TEST(testSubscriptOp)
CPPUNIT_TEST(testAppendSBuf)
CPPUNIT_TEST_EXCEPTION(testSubscriptOpFail, TextException)
CPPUNIT_TEST(testGrow)
CPPUNIT_TEST(testChop)
void testAppendSBuf()
Definition testSBuf.cc:241
CPPUNIT_TEST(testFindChar)
CPPUNIT_TEST(testChomp)
CPPUNIT_TEST(testSBufHash)
void testTailCopy()
void testIterators()
Definition testSBuf.cc:1132
void testSearchFail()
CPPUNIT_TEST_SUITE_END()
CPPUNIT_TEST_SUITE(TestSBuf)
CPPUNIT_TEST(testSubstr)
CPPUNIT_TEST(testStartsWith)
void testAppendCString()
Definition testSBuf.cc:271
CPPUNIT_TEST(testIterators)
void testPrintf()
Definition testSBuf.cc:262
CPPUNIT_TEST(testReserve)
void testSBufConstructDestructAfterMemInit()
Definition testSBuf.cc:216
void testAppendStdString()
Definition testSBuf.cc:279
void testFindFirstNotOf()
Definition testSBuf.cc:1093
void testCopy()
Definition testSBuf.cc:858
void testConsume()
Definition testSBuf.cc:480
CPPUNIT_TEST(testAppendf)
CPPUNIT_TEST(testStringOps)
void testComparisons()
Definition testSBuf.cc:409
void testEqualityTest()
Definition testSBuf.cc:223
CPPUNIT_TEST(testRFindSBuf)
CPPUNIT_TEST(testEqualityTest)
void commonInit()
CPPUNIT_TEST(testSBufConstructDestruct)
void testSBufHash()
Definition testSBuf.cc:1169
CPPUNIT_TEST(testPrintf)
CPPUNIT_TEST(testSBufLength)
void testStringOps()
Definition testSBuf.cc:872
void testChop()
Definition testSBuf.cc:517
CPPUNIT_TEST(testFindSBuf)
CPPUNIT_TEST(testRawSpace)
CPPUNIT_TEST(testSBufConstructDestructAfterMemInit)
CPPUNIT_TEST(testRawContent)
void testRawContent()
Definition testSBuf.cc:493
void testRFindChar()
Definition testSBuf.cc:796
void testStartsWith()
Definition testSBuf.cc:1035
CPPUNIT_TEST(testStdStringOps)
void testSBufLength()
Definition testSBuf.cc:851
void testChomp()
Definition testSBuf.cc:581
CPPUNIT_TEST(testSBufStream)
void testFindFirstOf()
Definition testSBuf.cc:1070
CPPUNIT_TEST(testAppendStdString)
void testReserve()
Definition testSBuf.cc:901
void testDumpStats()
Definition testSBuf.cc:313
void testAutoFind()
Definition testSBuf.cc:1116
CPPUNIT_TEST(testComparisons)
an std::runtime_error with thrower location info
A const & min(A const &lhs, A const &rhs)
void EVH(void *)
Definition event.h:18
int main()
void Init()
Definition old_api.cc:281
#define xfree
#define xstrdup
void eventAdd(const char *, EVH *, void *, double, int, bool)
Definition testSBuf.cc:117
static const char fox2[]
Definition testSBuf.cc:127
static const char fox[]
Definition testSBuf.cc:125
static int sign(int v)
Definition testSBuf.cc:342
static void testComparisonStdFull(const char *left, const char *right)
Definition testSBuf.cc:352
static const char fox1[]
Definition testSBuf.cc:126
SBuf empty_sbuf
Definition testSBuf.cc:132
CPPUNIT_TEST_SUITE_REGISTRATION(TestSBuf)
static void testComparisonStd(const char *s1, const char *s2)
Definition testSBuf.cc:402
SBuf literal("The quick brown fox jumped over the lazy dog")
static void testComparisonStdN(const char *left, const char *right, const size_t n)
Definition testSBuf.cc:372
static void testComparisonStdOneWay(const char *left, const char *right)
Definition testSBuf.cc:392
SBuf text("GET http://resource.com/path HTTP/1.1\r\n" "Host: resource.com\r\n" "Cookie: laijkpk3422r j1noin \r\n" "\r\n")
const CharacterSet alpha("alpha","abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")