Fix the unaligned string toLowerAscii test
authorBrian Pane <brianp@fb.com>
Mon, 21 Jul 2014 18:26:19 +0000 (11:26 -0700)
committerChip Turner <chip@fb.com>
Fri, 25 Jul 2014 16:06:09 +0000 (09:06 -0700)
Summary:
* The test computed nonaligned inputs but then copied them into temporary
buffers to compare different implementations. The temporary buffers
were word-aligned.
* This diff keeps the temp buffers but ensures that the data in them
keeps the original input's alignment.

Test Plan:
* Ran the test case with a modified String.cpp containing an assert to
catch unaligned reads.  The assert failed, as expected, on a copy
of the code without the fix from D1434585

Reviewed By: meyering@fb.com

Subscribers: ruibalp

FB internal diff: D1435028

Tasks: 4696800

folly/test/StringTest.cpp

index b283161a43cd1ec32fc886ddb4c30e1a5ce61d7e..f2162567dd8830b2e8d91d7545653e95dbfc0f3c 100644 (file)
@@ -1079,11 +1079,37 @@ TEST(String, humanify) {
 
 namespace {
 
+/**
+ * Copy bytes from src to somewhere in the buffer referenced by dst. The
+ * actual starting position of the copy will be the first address in the
+ * destination buffer whose address mod 8 is equal to the src address mod 8.
+ * The caller is responsible for ensuring that the destination buffer has
+ * enough extra space to accommodate the shifted copy.
+ */
+char* copyWithSameAlignment(char* dst, const char* src, size_t length) {
+  const char* originalDst = dst;
+  size_t dstOffset = size_t(dst) & 0x7;
+  size_t srcOffset = size_t(src) & 0x7;
+  while (dstOffset != srcOffset) {
+    dst++;
+    dstOffset++;
+    dstOffset &= 0x7;
+  }
+  CHECK(dst <= originalDst + 7);
+  CHECK((size_t(dst) & 0x7) == (size_t(src) & 0x7));
+  memcpy(dst, src, length);
+  return dst;
+}
+
 void testToLowerAscii(Range<const char*> src) {
-  char control[src.size()];
-  memcpy(control, src.begin(), src.size());
-  char test[src.size()];
-  memcpy(test, src.begin(), src.size());
+  // Allocate extra space so we can make copies that start at the
+  // same alignment (byte, word, quadword, etc) as the source buffer.
+  char controlBuf[src.size() + 7];
+  char* control = copyWithSameAlignment(controlBuf, src.begin(), src.size());
+
+  char testBuf[src.size() + 7];
+  char* test = copyWithSameAlignment(testBuf, src.begin(), src.size());
+
   for (size_t i = 0; i < src.size(); i++) {
     control[i] = tolower(control[i]);
   }
@@ -1112,8 +1138,10 @@ TEST(String, toLowerAsciiUnaligned) {
   }
   // Test input buffers of several lengths to exercise all the
   // cases: buffer at the start/middle/end of an aligned block, plus
-  // buffers that span multiple aligned blocks.
-  for (size_t length = 1; length < 11; length++) {
+  // buffers that span multiple aligned blocks.  The longest test input
+  // is 3 unaligned bytes + 4 32-bit aligned bytes + 8 64-bit aligned
+  // + 4 32-bit aligned + 3 unaligned = 22 bytes.
+  for (size_t length = 1; length < 23; length++) {
     for (size_t offset = 0; offset + length <= kSize; offset++) {
       testToLowerAscii(Range<const char*>(input + offset, length));
     }