StringPiece comparisons are broken
authorTudor Bosman <tudorb@fb.com>
Mon, 24 Jun 2013 19:48:43 +0000 (12:48 -0700)
committerJordan DeLong <jdelong@fb.com>
Wed, 26 Jun 2013 02:46:59 +0000 (19:46 -0700)
Summary:
8-bit StringPiece comparisons are broken.
The reason is char_traits is magic for 'char', but not 'const char'.

Test Plan: test added

Reviewed By: chip@fb.com

FB internal diff: D861521

folly/Range.h
folly/test/RangeTest.cpp

index 21f586da3f7ac1941a66396a3fb3504aad5b26cb..188a534abe118b53eb0196ed9a8eee602ba90a53 100644 (file)
@@ -123,7 +123,8 @@ public:
     typename std::iterator_traits<Iter>::reference>::type
   value_type;
   typedef typename std::iterator_traits<Iter>::reference reference;
     typename std::iterator_traits<Iter>::reference>::type
   value_type;
   typedef typename std::iterator_traits<Iter>::reference reference;
-  typedef std::char_traits<value_type> traits_type;
+  typedef std::char_traits<typename std::remove_const<value_type>::type>
+    traits_type;
 
   static const size_type npos;
 
 
   static const size_type npos;
 
index ebc20a5f221a5ff6c8add654eed5d5e2337507de..b82ac85f851af62ae23503d858bccfa15d0d3d36 100644 (file)
@@ -207,6 +207,47 @@ TEST(StringPiece, All) {
   EXPECT_EQ(s2, s);
 }
 
   EXPECT_EQ(s2, s);
 }
 
+template <class T>
+void expectLT(const T& a, const T& b) {
+  EXPECT_TRUE(a < b);
+  EXPECT_TRUE(a <= b);
+  EXPECT_FALSE(a == b);
+  EXPECT_FALSE(a >= b);
+  EXPECT_FALSE(a > b);
+
+  EXPECT_FALSE(b < a);
+  EXPECT_FALSE(b <= a);
+  EXPECT_TRUE(b >= a);
+  EXPECT_TRUE(b > a);
+}
+
+template <class T>
+void expectEQ(const T& a, const T& b) {
+  EXPECT_FALSE(a < b);
+  EXPECT_TRUE(a <= b);
+  EXPECT_TRUE(a == b);
+  EXPECT_TRUE(a >= b);
+  EXPECT_FALSE(a > b);
+}
+
+TEST(StringPiece, EightBitComparisons) {
+  char values[] = {'\x00', '\x20', '\x40', '\x7f', '\x80', '\xc0', '\xff'};
+  constexpr size_t count = sizeof(values) / sizeof(values[0]);
+  for (size_t i = 0; i < count; ++i) {
+    std::string a(1, values[i]);
+    // Defeat copy-on-write
+    std::string aCopy(a.data(), a.size());
+    expectEQ(a, aCopy);
+    expectEQ(StringPiece(a), StringPiece(aCopy));
+
+    for (size_t j = i + 1; j < count; ++j) {
+      std::string b(1, values[j]);
+      expectLT(a, b);
+      expectLT(StringPiece(a), StringPiece(b));
+    }
+  }
+}
+
 TEST(StringPiece, ToByteRange) {
   StringPiece a("hello");
   ByteRange b(a);
 TEST(StringPiece, ToByteRange) {
   StringPiece a("hello");
   ByteRange b(a);