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