+/*
+ * Copyright (C) 1996-2016 The Squid Software Foundation and contributors
+ *
+ * Squid software is distributed under GPLv2+ license and includes
+ * contributions from numerous individuals and organizations.
+ * Please see the COPYING and CONTRIBUTORS files for details.
+ */
+
#include "squid.h"
#include "base/CharacterSet.h"
-#include "Mem.h"
-#include "SBuf.h"
-#include "SBufFindTest.h"
-#include "SBufStream.h"
-#include "SquidString.h"
-#include "testSBuf.h"
+#include "sbuf/SBuf.h"
+#include "sbuf/Algorithms.h"
+#include "sbuf/SBufStream.h"
+#include "tests/SBufFindTest.h"
+#include "tests/testSBuf.h"
+#include "unitTestMain.h"
#include <iostream>
#include <stdexcept>
+#include <unordered_map>
CPPUNIT_TEST_SUITE_REGISTRATION( testSBuf );
CPPUNIT_ASSERT_EQUAL(s4,s3);
}
- // TEST: go via SquidString adapters.
- {
- String str(fox);
- SBuf s1(str);
- CPPUNIT_ASSERT_EQUAL(literal,s1);
- }
-
// TEST: go via std::string adapter.
{
std::string str(fox);
return 0;
}
+static void
+testComparisonStdFull(const char *left, const char *right)
+{
+ if (sign(strcmp(left, right)) != sign(SBuf(left).cmp(SBuf(right))))
+ std::cerr << std::endl << " cmp(SBuf) npos " << left << " ?= " << right << std::endl;
+ CPPUNIT_ASSERT_EQUAL(sign(strcmp(left, right)), sign(SBuf(left).cmp(SBuf(right))));
+
+ if (sign(strcmp(left, right)) != sign(SBuf(left).cmp(right)))
+ std::cerr << std::endl << " cmp(char*) npos " << left << " ?= " << right << std::endl;
+ CPPUNIT_ASSERT_EQUAL(sign(strcmp(left, right)), sign(SBuf(left).cmp(right)));
+
+ if (sign(strcasecmp(left, right)) != sign(SBuf(left).caseCmp(SBuf(right))))
+ std::cerr << std::endl << " caseCmp(SBuf) npos " << left << " ?= " << right << std::endl;
+ CPPUNIT_ASSERT_EQUAL(sign(strcasecmp(left, right)), sign(SBuf(left).caseCmp(SBuf(right))));
+
+ if (sign(strcasecmp(left, right)) != sign(SBuf(left).caseCmp(right)))
+ std::cerr << std::endl << " caseCmp(char*) npos " << left << " ?= " << right << std::endl;
+ CPPUNIT_ASSERT_EQUAL(sign(strcasecmp(left, right)), sign(SBuf(left).caseCmp(right)));
+}
+
+static void
+testComparisonStdN(const char *left, const char *right, const size_t n)
+{
+ if (sign(strncmp(left, right, n)) != sign(SBuf(left).cmp(SBuf(right), n)))
+ std::cerr << std::endl << " cmp(SBuf) " << n << ' ' << left << " ?= " << right << std::endl;
+ CPPUNIT_ASSERT_EQUAL(sign(strncmp(left, right, n)), sign(SBuf(left).cmp(SBuf(right), n)));
+
+ if (sign(strncmp(left, right, n)) != sign(SBuf(left).cmp(right, n)))
+ std::cerr << std::endl << " cmp(char*) " << n << ' ' << SBuf(left) << " ?= " << right << std::endl;
+ CPPUNIT_ASSERT_EQUAL(sign(strncmp(left, right, n)), sign(SBuf(left).cmp(right, n)));
+
+ if (sign(strncasecmp(left, right, n)) != sign(SBuf(left).caseCmp(SBuf(right), n)))
+ std::cerr << std::endl << " caseCmp(SBuf) " << n << ' ' << left << " ?= " << right << std::endl;
+ CPPUNIT_ASSERT_EQUAL(sign(strncasecmp(left, right, n)), sign(SBuf(left).caseCmp(SBuf(right), n)));
+
+ if (sign(strncasecmp(left, right, n)) != sign(SBuf(left).caseCmp(right, n)))
+ std::cerr << std::endl << " caseCmp(char*) " << n << ' ' << SBuf(left) << " ?= " << right << std::endl;
+ CPPUNIT_ASSERT_EQUAL(sign(strncasecmp(left, right, n)), sign(SBuf(left).caseCmp(right, n)));
+}
+
+static void
+testComparisonStdOneWay(const char *left, const char *right)
+{
+ testComparisonStdFull(left, right);
+ const size_t maxN = 2 + min(strlen(left), strlen(right));
+ for (size_t n = 0; n <= maxN; ++n) {
+ testComparisonStdN(left, right, n);
+ }
+}
+
+static void
+testComparisonStd(const char *s1, const char *s2)
+{
+ testComparisonStdOneWay(s1, s2);
+ testComparisonStdOneWay(s2, s1);
+}
+
void
testSBuf::testComparisons()
{
CPPUNIT_ASSERT_EQUAL(0,s1.caseCmp(s2,3));
CPPUNIT_ASSERT_EQUAL(0,s1.caseCmp(s2,2));
CPPUNIT_ASSERT_EQUAL(0,s1.cmp(s2,2));
+
+ testComparisonStd("foo", "fooz");
+ testComparisonStd("foo", "foo");
+ testComparisonStd("foo", "f");
+ testComparisonStd("foo", "bar");
+
+ testComparisonStd("foo", "FOOZ");
+ testComparisonStd("foo", "FOO");
+ testComparisonStd("foo", "F");
+
+ testComparisonStdOneWay("", "");
+
+ // rare case C-string input matching SBuf with N>strlen(s)
+ {
+ char *right = xstrdup("foo34567890123456789012345678");
+ SBuf left("fooZYXWVUTSRQPONMLKJIHGFEDCBA");
+ // is 3 bytes in length. NEVER more.
+ right[3] = '\0';
+ left.setAt(3, '\0');
+
+ // pick another spot to truncate at if something goes horribly wrong.
+ right[14] = '\0';
+ left.setAt(14, '\0');
+
+ const SBuf::size_type maxN = 20 + min(left.length(), static_cast<SBuf::size_type>(strlen(right)));
+ for (SBuf::size_type n = 0; n <= maxN; ++n) {
+ if (sign(strncmp(left.rawContent(), right, n)) != sign(left.cmp(right, n)) )
+ std::cerr << std::endl << " cmp(char*) " << n << ' ' << left << " ?= " << right;
+ CPPUNIT_ASSERT_EQUAL(sign(strncmp(left.rawContent(), right, n)), sign(left.cmp(right, n)));
+ if (sign(strncasecmp(left.rawContent(), right, n)) != sign(left.caseCmp(right, n)))
+ std::cerr << std::endl << " caseCmp(char*) " << n << ' ' << left << " ?= " << right;
+ CPPUNIT_ASSERT_EQUAL(sign(strncasecmp(left.rawContent(), right, n)), sign(left.caseCmp(right, n)));
+ }
+ xfree(right);
+ }
}
void
const char *alphabet="abcdefghijklmnopqrstuvwxyz";
SBuf a(alphabet);
std::string s(alphabet); // TODO
- { //regular chopping
+ { //regular chopping
SBuf b(a);
b.chop(3,3);
SBuf ref("def");
CPPUNIT_ASSERT_EQUAL(ref,b);
}
- { // chop at end
+ { // chop at end
SBuf b(a);
b.chop(b.length()-3);
SBuf ref("xyz");
CPPUNIT_ASSERT_EQUAL(ref,b);
}
- { // chop at beginning
+ { // chop at beginning
SBuf b(a);
b.chop(0,3);
SBuf ref("abc");
CPPUNIT_ASSERT_EQUAL(ref,b);
}
- { // chop to zero length
+ { // chop to zero length
SBuf b(a);
b.chop(5,0);
SBuf ref("");
CPPUNIT_ASSERT_EQUAL(ref,b);
}
- { // chop beyond end (at npos)
+ { // chop beyond end (at npos)
SBuf b(a);
b.chop(SBuf::npos,4);
SBuf ref("");
CPPUNIT_ASSERT_EQUAL(ref,b);
}
- { // chop beyond end
+ { // chop beyond end
SBuf b(a);
b.chop(b.length()+2,4);
SBuf ref("");
CPPUNIT_ASSERT_EQUAL(ref,b);
}
- { // null-chop
+ { // null-chop
SBuf b(a);
b.chop(0,b.length());
SBuf ref(a);
CPPUNIT_ASSERT_EQUAL(ref,b);
}
- { // overflow chopped area
+ { // overflow chopped area
SBuf b(a);
b.chop(b.length()-3,b.length());
SBuf ref("xyz");
void
testSBuf::testStringOps()
{
- SBuf sng(literal.toLower()),
- ref("the quick brown fox jumped over the lazy dog");
+ SBuf sng(ToLower(literal)),
+ ref("the quick brown fox jumped over the lazy dog");
CPPUNIT_ASSERT_EQUAL(ref,sng);
sng=literal;
CPPUNIT_ASSERT_EQUAL(0,sng.compare(ref,caseInsensitive));
// case-insensitive checks
CPPUNIT_ASSERT(literal.startsWith(casebuf,caseInsensitive));
- casebuf=SBuf(fox1).toUpper();
+ casebuf=ToUpper(SBuf(fox1));
CPPUNIT_ASSERT(literal.startsWith(casebuf,caseInsensitive));
CPPUNIT_ASSERT(literal.startsWith(SBuf(fox1),caseInsensitive));
casebuf = "tha quick";
SBuf sb(alphabet);
CPPUNIT_ASSERT_EQUAL(astr,sb.toStdString());
}
+
+void
+testSBuf::testIterators()
+{
+ SBuf text("foo"), text2("foo");
+ CPPUNIT_ASSERT(text.begin() == text.begin());
+ CPPUNIT_ASSERT(text.begin() != text.end());
+ CPPUNIT_ASSERT(text.begin() != text2.begin());
+ {
+ auto i = text.begin();
+ auto e = text.end();
+ CPPUNIT_ASSERT_EQUAL('f', *i);
+ CPPUNIT_ASSERT(i != e);
+ ++i;
+ CPPUNIT_ASSERT_EQUAL('o', *i);
+ CPPUNIT_ASSERT(i != e);
+ ++i;
+ CPPUNIT_ASSERT_EQUAL('o', *i);
+ CPPUNIT_ASSERT(i != e);
+ ++i;
+ CPPUNIT_ASSERT(i == e);
+ }
+ {
+ auto i = text.rbegin();
+ auto e = text.rend();
+ CPPUNIT_ASSERT_EQUAL('o', *i);
+ CPPUNIT_ASSERT(i != e);
+ ++i;
+ CPPUNIT_ASSERT_EQUAL('o', *i);
+ CPPUNIT_ASSERT(i != e);
+ ++i;
+ CPPUNIT_ASSERT_EQUAL('f', *i);
+ CPPUNIT_ASSERT(i != e);
+ ++i;
+ CPPUNIT_ASSERT(i == e);
+ }
+}
+
+void
+testSBuf::testSBufHash()
+{
+ // same SBuf must have same hash
+ auto hasher=std::hash<SBuf>();
+ CPPUNIT_ASSERT_EQUAL(hasher(literal),hasher(literal));
+
+ // same content must have same hash
+ CPPUNIT_ASSERT_EQUAL(hasher(literal),hasher(SBuf(fox)));
+ CPPUNIT_ASSERT_EQUAL(hasher(SBuf(fox)),hasher(SBuf(fox)));
+
+ //differen content should have different hash
+ CPPUNIT_ASSERT(hasher(SBuf(fox)) != hasher(SBuf(fox1)));
+
+ {
+ std::unordered_map<SBuf, int> um;
+ um[SBuf("one")] = 1;
+ um[SBuf("two")] = 2;
+
+ auto i = um.find(SBuf("one"));
+ CPPUNIT_ASSERT(i != um.end());
+ CPPUNIT_ASSERT(i->second == 1);
+
+ i = um.find(SBuf("eleventy"));
+ CPPUNIT_ASSERT(i == um.end());
+ }
+}
+