Fix copyright lines
[folly.git] / folly / experimental / test / BitsTest.cpp
index 9ac5bc82ae03e0df008c65dda1bbc57a209e1df8..e489910ef58d36a02f92284993527c440840e62e 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2014 Facebook, Inc.
+ * Copyright 2012-present Facebook, Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * limitations under the License.
  */
 
+#include <cmath>
+
 #include <folly/experimental/Bits.h>
 
 #include <glog/logging.h>
-#include <gtest/gtest.h>
+
+#include <folly/portability/GTest.h>
 
 using namespace folly;
 
@@ -245,72 +248,134 @@ T testValue(int bits) {
   if (std::is_signed<T>::value) {
     --bits;
   }
-  auto value = pow(2, bits) * (negate ? -2.0 : 2.0) / 3.0;
+  auto value = std::pow(2, bits) * (negate ? -2.0 : 2.0) / 3.0;
   CHECK_GE(value, std::numeric_limits<T>::min());
   CHECK_LE(value, std::numeric_limits<T>::max());
   return static_cast<T>(value);
 }
+} // namespace
+
+TEST(Bits, Boundaries) {
+  uint8_t buf[20];
+  for (size_t offset = 0; offset <= 64; ++offset) {
+    for (size_t size = 0; size <= 32; ++size) {
+      int32_t value = testValue<int32_t>(size);
+      testSet<true>(buf, offset, size, value);
+      EXPECT_EQ(value, (testGet<true, int32_t>(buf, offset, size)));
+    }
+  }
+}
+
+template <size_t N>
+void accSize(size_t& w) {
+  for (size_t s = 0; s <= N; ++s) {
+    w += s;
+  }
+}
+
+template <size_t N, typename T, bool NEG, bool aligned>
+void testSetLoop(size_t& w, size_t bufSize, uint8_t* buf) {
+  for (size_t s = 0; s <= N; ++s) {
+    CHECK_LE(s + w, 8 * bufSize) << s << ' ' << w << ' ' << bufSize;
+    testSet<aligned>(buf, w, s, testValue<T, NEG>(s));
+    EXPECT_EQ((testValue<T, NEG>(s)), (testGet<aligned, T>(buf, w, s))) << s;
+    w += s;
+  }
+}
+
+template <size_t N, typename T, bool NEG, bool aligned>
+void testGetLoop(size_t& r, size_t bufSize, uint8_t* buf) {
+  for (size_t s = 0; s <= N; ++s) {
+    CHECK_LE(s + r, 8 * bufSize);
+    EXPECT_EQ((testValue<T, NEG>(s)), (testGet<aligned, T>(buf, r, s))) << s;
+    r += s;
+  }
 }
 
-static_assert((-4) >> 1 == -2, "OH");
 template <bool aligned>
 void testConcatenation() {
   // concatenate fields of length 1, 2, 3, ... 64, all unsigned, storing 2/3s
   // the maximum value in each.
-  const size_t bitLimit = 64;
-  const size_t bitsPerPass = (1 + bitLimit) * bitLimit / 2;
-  const size_t totalBits = bitsPerPass * 3;
-  uint8_t buf[(totalBits + 7) / 8];
-#define EACH_UNSIGNED_SIZE(MACRO, ARG) \
-  MACRO(8, uint8_t, ARG);              \
-  MACRO(16, uint16_t, ARG);            \
-  MACRO(32, uint32_t, ARG);            \
-  MACRO(64, uint64_t, ARG);
-#define EACH_SIGNED_SIZE(MACRO, ARG) \
-  MACRO(7, int8_t, ARG);             \
-  MACRO(15, int16_t, ARG);           \
-  MACRO(31, int32_t, ARG);           \
-  MACRO(63, int64_t, ARG);
+
+  // calculate how much buffer size we need
+  size_t bufSize = 0;
   {
-    size_t w = 0, s;
-#define WRITE_TEST(N, T, NEG)                                                 \
-  for (; s <= N; ++s, w += s) {                                               \
-    testSet<aligned>(buf, w, s, testValue<T, NEG>(s));                        \
-    EXPECT_EQ((testValue<T, NEG>(s)), (testGet<aligned, T>(buf, w, s))) << s; \
+    size_t w = 0;
+    // Unsigned
+    accSize<8>(w);
+    accSize<16>(w);
+    accSize<32>(w);
+    accSize<64>(w);
+
+    // Signed NEG=false
+    accSize<7>(w);
+    accSize<15>(w);
+    accSize<31>(w);
+    accSize<63>(w);
+
+    // Signed NEG=true
+    accSize<7>(w);
+    accSize<15>(w);
+    accSize<31>(w);
+    accSize<63>(w);
+
+    bufSize = w;
   }
-    s = 0;
-    EACH_UNSIGNED_SIZE(WRITE_TEST, false)
-    s = 0;
-    EACH_SIGNED_SIZE(WRITE_TEST, false)
-    s = 0;
-    EACH_SIGNED_SIZE(WRITE_TEST, true)
-#undef WRITE_TEST
+  // bits->bytes, rounding up
+  bufSize = (bufSize + 7) / 8;
+  // round up to next multiple of 8
+  bufSize = (bufSize + 7) / 8 * 8;
+  std::vector<uint8_t> buffer(bufSize);
+  uint8_t *buf = buffer.data();
+  {
+    size_t w = 0;
+    // Unsigned
+    testSetLoop<8, uint8_t, false, aligned>(w, bufSize, buf);
+    testSetLoop<16, uint16_t, false, aligned>(w, bufSize, buf);
+    testSetLoop<32, uint32_t, false, aligned>(w, bufSize, buf);
+    testSetLoop<64, uint64_t, false, aligned>(w, bufSize, buf);
+
+    // Signed NEG=false
+    testSetLoop<7, int8_t, false, aligned>(w, bufSize, buf);
+    testSetLoop<15, int16_t, false, aligned>(w, bufSize, buf);
+    testSetLoop<31, int32_t, false, aligned>(w, bufSize, buf);
+    testSetLoop<63, int64_t, false, aligned>(w, bufSize, buf);
+
+    // Signed NEG=true
+    testSetLoop<7, int8_t, true, aligned>(w, bufSize, buf);
+    testSetLoop<15, int16_t, true, aligned>(w, bufSize, buf);
+    testSetLoop<31, int32_t, true, aligned>(w, bufSize, buf);
+    testSetLoop<63, int64_t, true, aligned>(w, bufSize, buf);
   }
+
   {
-    size_t r = 0, s;
-#define READ_TEST(N, T, NEG)  \
-  for (; s <= N; ++s, r += s) \
-    EXPECT_EQ((testValue<T, NEG>(s)), (testGet<aligned, T>(buf, r, s))) << s;
-    s = 0;
-    EACH_UNSIGNED_SIZE(READ_TEST, false)
-    s = 0;
-    EACH_SIGNED_SIZE(READ_TEST, false)
-    s = 0;
-    EACH_SIGNED_SIZE(READ_TEST, true)
-#undef READ_TEST
+    size_t r = 0;
+    // Unsigned
+    testGetLoop<8, uint8_t, false, aligned>(r, bufSize, buf);
+    testGetLoop<16, uint16_t, false, aligned>(r, bufSize, buf);
+    testGetLoop<32, uint32_t, false, aligned>(r, bufSize, buf);
+    testGetLoop<64, uint64_t, false, aligned>(r, bufSize, buf);
+
+    // Signed NEG=false
+    testGetLoop<7, int8_t, false, aligned>(r, bufSize, buf);
+    testGetLoop<15, int16_t, false, aligned>(r, bufSize, buf);
+    testGetLoop<31, int32_t, false, aligned>(r, bufSize, buf);
+    testGetLoop<63, int64_t, false, aligned>(r, bufSize, buf);
+
+    // Signed NEG=true
+    testGetLoop<7, int8_t, true, aligned>(r, bufSize, buf);
+    testGetLoop<15, int16_t, true, aligned>(r, bufSize, buf);
+    testGetLoop<31, int32_t, true, aligned>(r, bufSize, buf);
+    testGetLoop<63, int64_t, true, aligned>(r, bufSize, buf);
   }
-#undef EACH_UNSIGNED_SIZE
 }
 
 TEST(Bits, ConcatenationUnalignedUnsigned) { testConcatenation<false>(); }
 
-TEST(Bits, ConcatenationAligned) {
-  testConcatenation<true>();
-}
+TEST(Bits, ConcatenationAligned) { testConcatenation<true>(); }
 
 int main(int argc, char *argv[]) {
   testing::InitGoogleTest(&argc, argv);
-  google::ParseCommandLineFlags(&argc, &argv, true);
+  gflags::ParseCommandLineFlags(&argc, &argv, true);
   return RUN_ALL_TESTS();
 }
-