Make folly's T_CHECK_TIMEOUT/T_CHECK_TIME_LT use SKIP() on failure
[folly.git] / folly / test / ConvTest.cpp
index f692af7bf527c8497f6a1eb6d78c7d931741a1d2..3cf6d5b8a06e735894bfb5175b6b458dbf8eab01 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2014 Facebook, Inc.
+ * Copyright 2015 Facebook, Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
 using namespace std;
 using namespace folly;
 
-static int8_t s8;
-static uint8_t u8;
-static int16_t s16;
-static uint16_t u16;
-static int32_t s32;
-static uint32_t u32;
-static int64_t s64;
-static uint64_t u64;
+
+
+TEST(Conv, digits10Minimal) {
+  // Not much of a test (and it's included in the test below anyway).
+  // I just want to inspect the generated assembly for this function.
+  folly::doNotOptimizeAway(digits10(random() * random()));
+}
+
+TEST(Conv, digits10) {
+  char buffer[100];
+  uint64_t power;
+
+  // first, some basic sniff tests
+  EXPECT_EQ( 1, digits10(0));
+  EXPECT_EQ( 1, digits10(1));
+  EXPECT_EQ( 1, digits10(9));
+  EXPECT_EQ( 2, digits10(10));
+  EXPECT_EQ( 2, digits10(99));
+  EXPECT_EQ( 3, digits10(100));
+  EXPECT_EQ( 3, digits10(999));
+  EXPECT_EQ( 4, digits10(1000));
+  EXPECT_EQ( 4, digits10(9999));
+  EXPECT_EQ(20, digits10(18446744073709551615ULL));
+
+  // try the first X nonnegatives.
+  // Covers some more cases of 2^p, 10^p
+  for (uint64_t i = 0; i < 100000; i++) {
+    snprintf(buffer, sizeof(buffer), "%lu", i);
+    EXPECT_EQ(strlen(buffer), digits10(i));
+  }
+
+  // try powers of 2
+  power = 1;
+  for (int p = 0; p < 64; p++) {
+    snprintf(buffer, sizeof(buffer), "%lu", power);
+    EXPECT_EQ(strlen(buffer), digits10(power));
+    snprintf(buffer, sizeof(buffer), "%lu", power - 1);
+    EXPECT_EQ(strlen(buffer), digits10(power - 1));
+    snprintf(buffer, sizeof(buffer), "%lu", power + 1);
+    EXPECT_EQ(strlen(buffer), digits10(power + 1));
+    power *= 2;
+  }
+
+  // try powers of 10
+  power = 1;
+  for (int p = 0; p < 20; p++) {
+    snprintf(buffer, sizeof(buffer), "%lu", power);
+    EXPECT_EQ(strlen(buffer), digits10(power));
+    snprintf(buffer, sizeof(buffer), "%lu", power - 1);
+    EXPECT_EQ(strlen(buffer), digits10(power - 1));
+    snprintf(buffer, sizeof(buffer), "%lu", power + 1);
+    EXPECT_EQ(strlen(buffer), digits10(power + 1));
+    power *= 10;
+  }
+}
+
+// Test to<T>(T)
+TEST(Conv, Type2Type) {
+  bool boolV = true;
+  EXPECT_EQ(to<bool>(boolV), true);
+
+  int intV = 42;
+  EXPECT_EQ(to<int>(intV), 42);
+
+  float floatV = 4.2;
+  EXPECT_EQ(to<float>(floatV), 4.2f);
+
+  double doubleV = 0.42;
+  EXPECT_EQ(to<double>(doubleV), 0.42);
+
+  std::string stringV = "StdString";
+  EXPECT_EQ(to<std::string>(stringV), "StdString");
+
+  folly::fbstring fbStrV = "FBString";
+  EXPECT_EQ(to<folly::fbstring>(fbStrV), "FBString");
+
+  folly::StringPiece spV("StringPiece");
+  EXPECT_EQ(to<folly::StringPiece>(spV), "StringPiece");
+
+  // Rvalues
+  EXPECT_EQ(to<bool>(true), true);
+  EXPECT_EQ(to<int>(42), 42);
+  EXPECT_EQ(to<float>(4.2f), 4.2f);
+  EXPECT_EQ(to<double>(.42), .42);
+  EXPECT_EQ(to<std::string>(std::string("Hello")), "Hello");
+  EXPECT_EQ(to<folly::fbstring>(folly::fbstring("hello")), "hello");
+  EXPECT_EQ(to<folly::StringPiece>(folly::StringPiece("Forty Two")),
+            "Forty Two");
+}
 
 TEST(Conv, Integral2Integral) {
   // Same size, different signs
-  s64 = numeric_limits<uint8_t>::max();
+  int64_t s64 = numeric_limits<uint8_t>::max();
   EXPECT_EQ(to<uint8_t>(s64), s64);
 
   s64 = numeric_limits<int8_t>::max();
@@ -556,6 +637,7 @@ TEST(Conv, DoubleToInt) {
   EXPECT_EQ(i, 42);
   try {
     auto i = to<int>(42.1);
+    LOG(ERROR) << "to<int> returned " << i << " instead of throwing";
     EXPECT_TRUE(false);
   } catch (std::range_error& e) {
     //LOG(INFO) << e.what();
@@ -570,7 +652,9 @@ TEST(Conv, EnumToInt) {
   EXPECT_EQ(j, 42);
   try {
     auto i = to<char>(y);
-    LOG(ERROR) << static_cast<unsigned int>(i);
+    LOG(ERROR) << "to<char> returned "
+               << static_cast<unsigned int>(i)
+               << " instead of throwing";
     EXPECT_TRUE(false);
   } catch (std::range_error& e) {
     //LOG(INFO) << e.what();
@@ -593,6 +677,9 @@ TEST(Conv, IntToEnum) {
   EXPECT_EQ(j, 100);
   try {
     auto i = to<A>(5000000000L);
+    LOG(ERROR) << "to<A> returned "
+               << static_cast<unsigned int>(i)
+               << " instead of throwing";
     EXPECT_TRUE(false);
   } catch (std::range_error& e) {
     //LOG(INFO) << e.what();
@@ -609,15 +696,12 @@ TEST(Conv, UnsignedEnum) {
   EXPECT_EQ(e, x);
   try {
     auto i = to<int32_t>(x);
-    LOG(ERROR) << to<uint32_t>(x);
+    LOG(ERROR) << "to<int32_t> returned " << i << " instead of throwing";
     EXPECT_TRUE(false);
   } catch (std::range_error& e) {
   }
 }
 
-#if defined(__clang__) || __GNUC_PREREQ(4, 7)
-// to<enum class> and to(enum class) only supported in gcc 4.7 onwards
-
 TEST(Conv, UnsignedEnumClass) {
   enum class E : uint32_t { x = 3000000000U };
   auto u = to<uint32_t>(E::x);
@@ -629,7 +713,7 @@ TEST(Conv, UnsignedEnumClass) {
   EXPECT_EQ(e, E::x);
   try {
     auto i = to<int32_t>(E::x);
-    LOG(ERROR) << to<uint32_t>(E::x);
+    LOG(ERROR) << "to<int32_t> returned " << i << " instead of throwing";
     EXPECT_TRUE(false);
   } catch (std::range_error& e) {
   }
@@ -644,7 +728,16 @@ TEST(Conv, EnumClassToString) {
   EXPECT_EQ("foo.65", to<string>("foo.", A::z));
 }
 
-#endif // gcc 4.7 onwards
+TEST(Conv, IntegralToBool) {
+  EXPECT_FALSE(to<bool>(0));
+  EXPECT_FALSE(to<bool>(0ul));
+
+  EXPECT_TRUE(to<bool>(1));
+  EXPECT_TRUE(to<bool>(1ul));
+
+  EXPECT_TRUE(to<bool>(-42));
+  EXPECT_TRUE(to<bool>(42ul));
+}
 
 template<typename Src>
 void testStr2Bool() {
@@ -748,6 +841,22 @@ TEST(Conv, NewUint64ToString) {
 #undef THE_GREAT_EXPECTATIONS
 }
 
+TEST(Conv, allocate_size) {
+  std::string str1 = "meh meh meh";
+  std::string str2 = "zdech zdech zdech";
+
+  auto res1 = folly::to<std::string>(str1, ".", str2);
+  EXPECT_EQ(res1, str1 + "." + str2);
+
+  std::string res2; //empty
+  toAppendFit(str1, str2, 1, &res2);
+  EXPECT_EQ(res2, str1 + str2 + "1");
+
+  std::string res3;
+  toAppendDelimFit(",", str1, str2, &res3);
+  EXPECT_EQ(res3, str1 + "," + str2);
+}
+
 ////////////////////////////////////////////////////////////////////////////////
 // Benchmarks for ASCII to int conversion
 ////////////////////////////////////////////////////////////////////////////////
@@ -912,6 +1021,22 @@ void u64ToAsciiFollyBM(unsigned int n, uint64_t value) {
   }
 }
 
+// Benchmark unsigned to string conversion
+
+void u64ToStringClibMeasure(unsigned int n, uint64_t value) {
+  // FOLLY_RANGE_CHECK_TO_STRING expands to std::to_string, except on Android
+  // where std::to_string is not supported
+  FOR_EACH_RANGE (i, 0, n) {
+    FOLLY_RANGE_CHECK_TO_STRING(value + n);
+  }
+}
+
+void u64ToStringFollyMeasure(unsigned int n, uint64_t value) {
+  FOR_EACH_RANGE (i, 0, n) {
+    to<std::string>(value + n);
+  }
+}
+
 // Benchmark uitoa with string append
 
 void u2aAppendClassicBM(unsigned int n, uint64_t value) {
@@ -936,6 +1061,7 @@ void u2aAppendFollyBM(unsigned int n, uint64_t value) {
 
 template <class String>
 struct StringIdenticalToBM {
+  StringIdenticalToBM() {}
   void operator()(unsigned int n, size_t len) const {
     String s;
     BENCHMARK_SUSPEND { s.append(len, '0'); }
@@ -948,6 +1074,7 @@ struct StringIdenticalToBM {
 
 template <class String>
 struct StringVariadicToBM {
+  StringVariadicToBM() {}
   void operator()(unsigned int n, size_t len) const {
     String s;
     BENCHMARK_SUSPEND { s.append(len, '0'); }
@@ -958,6 +1085,33 @@ struct StringVariadicToBM {
   }
 };
 
+static size_t bigInt = 11424545345345;
+static size_t smallInt = 104;
+static char someString[] = "this is some nice string";
+static char otherString[] = "this is a long string, so it's not so nice";
+static char reallyShort[] = "meh";
+static std::string stdString = "std::strings are very nice";
+static float fValue = 1.2355;
+static double dValue = 345345345.435;
+
+BENCHMARK(preallocateTestNoFloat, n) {
+  for (size_t i = 0; i < n; ++i) {
+    auto val1 = to<std::string>(bigInt, someString, stdString, otherString);
+    auto val3 = to<std::string>(reallyShort, smallInt);
+    auto val2 = to<std::string>(bigInt, stdString);
+    auto val4 = to<std::string>(bigInt, stdString, dValue, otherString);
+    auto val5 = to<std::string>(bigInt, someString, reallyShort);
+  }
+}
+
+BENCHMARK(preallocateTestFloat, n) {
+  for (size_t i = 0; i < n; ++i) {
+    auto val1 = to<std::string>(stdString, ',', fValue, dValue);
+    auto val2 = to<std::string>(stdString, ',', dValue);
+  }
+}
+BENCHMARK_DRAW_LINE();
+
 static const StringIdenticalToBM<std::string> stringIdenticalToBM;
 static const StringVariadicToBM<std::string> stringVariadicToBM;
 static const StringIdenticalToBM<fbstring> fbstringIdenticalToBM;
@@ -992,6 +1146,34 @@ DEFINE_BENCHMARK_GROUP(12345678901234567890U);
 
 #undef DEFINE_BENCHMARK_GROUP
 
+#define DEFINE_BENCHMARK_GROUP(n)                        \
+  BENCHMARK_PARAM(u64ToStringClibMeasure, n);            \
+  BENCHMARK_RELATIVE_PARAM(u64ToStringFollyMeasure, n);  \
+  BENCHMARK_DRAW_LINE();
+
+DEFINE_BENCHMARK_GROUP(1);
+DEFINE_BENCHMARK_GROUP(12);
+DEFINE_BENCHMARK_GROUP(123);
+DEFINE_BENCHMARK_GROUP(1234);
+DEFINE_BENCHMARK_GROUP(12345);
+DEFINE_BENCHMARK_GROUP(123456);
+DEFINE_BENCHMARK_GROUP(1234567);
+DEFINE_BENCHMARK_GROUP(12345678);
+DEFINE_BENCHMARK_GROUP(123456789);
+DEFINE_BENCHMARK_GROUP(1234567890);
+DEFINE_BENCHMARK_GROUP(12345678901);
+DEFINE_BENCHMARK_GROUP(123456789012);
+DEFINE_BENCHMARK_GROUP(1234567890123);
+DEFINE_BENCHMARK_GROUP(12345678901234);
+DEFINE_BENCHMARK_GROUP(123456789012345);
+DEFINE_BENCHMARK_GROUP(1234567890123456);
+DEFINE_BENCHMARK_GROUP(12345678901234567);
+DEFINE_BENCHMARK_GROUP(123456789012345678);
+DEFINE_BENCHMARK_GROUP(1234567890123456789);
+DEFINE_BENCHMARK_GROUP(12345678901234567890U);
+
+#undef DEFINE_BENCHMARK_GROUP
+
 #define DEFINE_BENCHMARK_GROUP(n)                       \
   BENCHMARK_PARAM(clibAtoiMeasure, n);                  \
   BENCHMARK_RELATIVE_PARAM(lexicalCastMeasure, n);      \
@@ -1037,7 +1219,7 @@ DEFINE_BENCHMARK_GROUP(fbstring, 32768);
 
 int main(int argc, char** argv) {
   testing::InitGoogleTest(&argc, argv);
-  google::ParseCommandLineFlags(&argc, &argv, true);
+  gflags::ParseCommandLineFlags(&argc, &argv, true);
   auto ret = RUN_ALL_TESTS();
   if (!ret && FLAGS_benchmark) {
     folly::runBenchmarks();