TraitsTest.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338
  1. /*
  2. * Copyright 2012-present Facebook, Inc.
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. #include <folly/Traits.h>
  17. #include <cstring>
  18. #include <string>
  19. #include <type_traits>
  20. #include <utility>
  21. #include <folly/ScopeGuard.h>
  22. #include <folly/portability/GTest.h>
  23. using namespace folly;
  24. using namespace std;
  25. namespace {
  26. FOLLY_CREATE_HAS_MEMBER_TYPE_TRAITS(has_member_type_x, x);
  27. } // namespace
  28. TEST(Traits, has_member_type) {
  29. struct membership_no {};
  30. struct membership_yes {
  31. using x = void;
  32. };
  33. EXPECT_TRUE((is_same<false_type, has_member_type_x<membership_no>>::value));
  34. EXPECT_TRUE((is_same<true_type, has_member_type_x<membership_yes>>::value));
  35. }
  36. // Note: FOLLY_CREATE_HAS_MEMBER_FN_TRAITS tests are in
  37. // folly/test/HasMemberFnTraitsTest.cpp.
  38. struct T1 {}; // old-style IsRelocatable, below
  39. struct T2 {}; // old-style IsRelocatable, below
  40. struct T3 {
  41. typedef std::true_type IsRelocatable;
  42. };
  43. struct T5 : T3 {};
  44. struct F1 {};
  45. struct F2 {
  46. typedef int IsRelocatable;
  47. };
  48. struct F3 : T3 {
  49. typedef std::false_type IsRelocatable;
  50. };
  51. struct F4 : T1 {};
  52. namespace folly {
  53. template <>
  54. struct IsRelocatable<T1> : std::true_type {};
  55. template <>
  56. FOLLY_ASSUME_RELOCATABLE(T2);
  57. } // namespace folly
  58. TEST(Traits, scalars) {
  59. EXPECT_TRUE(IsRelocatable<int>::value);
  60. EXPECT_TRUE(IsRelocatable<bool>::value);
  61. EXPECT_TRUE(IsRelocatable<double>::value);
  62. EXPECT_TRUE(IsRelocatable<void*>::value);
  63. }
  64. TEST(Traits, containers) {
  65. EXPECT_TRUE(IsRelocatable<vector<F1>>::value);
  66. EXPECT_TRUE((IsRelocatable<pair<F1, F1>>::value));
  67. EXPECT_TRUE((IsRelocatable<pair<T1, T2>>::value));
  68. }
  69. TEST(Traits, original) {
  70. EXPECT_TRUE(IsRelocatable<T1>::value);
  71. EXPECT_TRUE(IsRelocatable<T2>::value);
  72. }
  73. TEST(Traits, typedefd) {
  74. EXPECT_TRUE(IsRelocatable<T3>::value);
  75. EXPECT_TRUE(IsRelocatable<T5>::value);
  76. EXPECT_FALSE(IsRelocatable<F2>::value);
  77. EXPECT_FALSE(IsRelocatable<F3>::value);
  78. }
  79. TEST(Traits, unset) {
  80. EXPECT_TRUE(IsRelocatable<F1>::value);
  81. EXPECT_TRUE(IsRelocatable<F4>::value);
  82. }
  83. TEST(Traits, bitAndInit) {
  84. EXPECT_TRUE(IsZeroInitializable<int>::value);
  85. EXPECT_FALSE(IsZeroInitializable<vector<int>>::value);
  86. }
  87. TEST(Trait, logicOperators) {
  88. static_assert(Conjunction<true_type>::value, "");
  89. static_assert(!Conjunction<false_type>::value, "");
  90. static_assert(is_same<Conjunction<true_type>::type, true_type>::value, "");
  91. static_assert(is_same<Conjunction<false_type>::type, false_type>::value, "");
  92. static_assert(Conjunction<true_type, true_type>::value, "");
  93. static_assert(!Conjunction<true_type, false_type>::value, "");
  94. static_assert(Disjunction<true_type>::value, "");
  95. static_assert(!Disjunction<false_type>::value, "");
  96. static_assert(is_same<Disjunction<true_type>::type, true_type>::value, "");
  97. static_assert(is_same<Disjunction<false_type>::type, false_type>::value, "");
  98. static_assert(Disjunction<true_type, true_type>::value, "");
  99. static_assert(Disjunction<true_type, false_type>::value, "");
  100. static_assert(!Negation<true_type>::value, "");
  101. static_assert(Negation<false_type>::value, "");
  102. }
  103. TEST(Traits, is_negative) {
  104. EXPECT_TRUE(folly::is_negative(-1));
  105. EXPECT_FALSE(folly::is_negative(0));
  106. EXPECT_FALSE(folly::is_negative(1));
  107. EXPECT_FALSE(folly::is_negative(0u));
  108. EXPECT_FALSE(folly::is_negative(1u));
  109. EXPECT_TRUE(folly::is_non_positive(-1));
  110. EXPECT_TRUE(folly::is_non_positive(0));
  111. EXPECT_FALSE(folly::is_non_positive(1));
  112. EXPECT_TRUE(folly::is_non_positive(0u));
  113. EXPECT_FALSE(folly::is_non_positive(1u));
  114. }
  115. TEST(Traits, relational) {
  116. // We test, especially, the edge cases to make sure we don't
  117. // trip -Wtautological-comparisons
  118. EXPECT_FALSE((folly::less_than<uint8_t, 0u, uint8_t>(0u)));
  119. EXPECT_FALSE((folly::less_than<uint8_t, 0u, uint8_t>(254u)));
  120. EXPECT_FALSE((folly::less_than<uint8_t, 255u, uint8_t>(255u)));
  121. EXPECT_TRUE((folly::less_than<uint8_t, 255u, uint8_t>(254u)));
  122. EXPECT_FALSE((folly::greater_than<uint8_t, 0u, uint8_t>(0u)));
  123. EXPECT_TRUE((folly::greater_than<uint8_t, 0u, uint8_t>(254u)));
  124. EXPECT_FALSE((folly::greater_than<uint8_t, 255u, uint8_t>(255u)));
  125. EXPECT_FALSE((folly::greater_than<uint8_t, 255u, uint8_t>(254u)));
  126. }
  127. #if FOLLY_HAVE_INT128_T
  128. TEST(Traits, int128) {
  129. EXPECT_TRUE(
  130. (::std::is_same<::std::make_unsigned<__int128_t>::type, __uint128_t>::
  131. value));
  132. EXPECT_TRUE((
  133. ::std::is_same<::std::make_signed<__int128_t>::type, __int128_t>::value));
  134. EXPECT_TRUE(
  135. (::std::is_same<::std::make_unsigned<__uint128_t>::type, __uint128_t>::
  136. value));
  137. EXPECT_TRUE(
  138. (::std::is_same<::std::make_signed<__uint128_t>::type, __int128_t>::
  139. value));
  140. EXPECT_TRUE((::std::is_arithmetic<__int128_t>::value));
  141. EXPECT_TRUE((::std::is_arithmetic<__uint128_t>::value));
  142. EXPECT_TRUE((::std::is_integral<__int128_t>::value));
  143. EXPECT_TRUE((::std::is_integral<__uint128_t>::value));
  144. EXPECT_FALSE((::std::is_unsigned<__int128_t>::value));
  145. EXPECT_TRUE((::std::is_signed<__int128_t>::value));
  146. EXPECT_TRUE((::std::is_unsigned<__uint128_t>::value));
  147. EXPECT_FALSE((::std::is_signed<__uint128_t>::value));
  148. EXPECT_TRUE((::std::is_fundamental<__int128_t>::value));
  149. EXPECT_TRUE((::std::is_fundamental<__uint128_t>::value));
  150. EXPECT_TRUE((::std::is_scalar<__int128_t>::value));
  151. EXPECT_TRUE((::std::is_scalar<__uint128_t>::value));
  152. }
  153. #endif // FOLLY_HAVE_INT128_T
  154. template <typename T, typename... Args>
  155. void testIsRelocatable(Args&&... args) {
  156. if (!IsRelocatable<T>::value) {
  157. return;
  158. }
  159. // We use placement new on zeroed memory to avoid garbage subsections
  160. char vsrc[sizeof(T)] = {0};
  161. char vdst[sizeof(T)] = {0};
  162. char vcpy[sizeof(T)];
  163. T* src = new (vsrc) T(std::forward<Args>(args)...);
  164. SCOPE_EXIT {
  165. src->~T();
  166. };
  167. std::memcpy(vcpy, vsrc, sizeof(T));
  168. T deep(*src);
  169. T* dst = new (vdst) T(std::move(*src));
  170. SCOPE_EXIT {
  171. dst->~T();
  172. };
  173. EXPECT_EQ(deep, *dst);
  174. #pragma GCC diagnostic push
  175. #pragma GCC diagnostic ignored "-Wstrict-aliasing"
  176. EXPECT_EQ(deep, *reinterpret_cast<T*>(vcpy));
  177. #pragma GCC diagnostic pop
  178. // This test could technically fail; however, this is what relocation
  179. // almost always means, so it's a good test to have
  180. EXPECT_EQ(std::memcmp(vcpy, vdst, sizeof(T)), 0);
  181. }
  182. TEST(Traits, actuallyRelocatable) {
  183. // Ensure that we test stack and heap allocation for strings with in-situ
  184. // capacity
  185. testIsRelocatable<std::string>("1");
  186. testIsRelocatable<std::string>(sizeof(std::string) + 1, 'x');
  187. testIsRelocatable<std::vector<char>>(5, 'g');
  188. }
  189. namespace {
  190. // has_value_type<T>::value is true if T has a nested type `value_type`
  191. template <class T, class = void>
  192. struct has_value_type : std::false_type {};
  193. template <class T>
  194. struct has_value_type<T, folly::void_t<typename T::value_type>>
  195. : std::true_type {};
  196. struct some_tag {};
  197. template <typename T>
  198. struct container {
  199. template <class... Args>
  200. container(
  201. folly::type_t<some_tag, decltype(T(std::declval<Args>()...))>,
  202. Args&&...) {}
  203. };
  204. } // namespace
  205. TEST(Traits, void_t) {
  206. EXPECT_TRUE((::std::is_same<folly::void_t<>, void>::value));
  207. EXPECT_TRUE((::std::is_same<folly::void_t<int>, void>::value));
  208. EXPECT_TRUE((::std::is_same<folly::void_t<int, short>, void>::value));
  209. EXPECT_TRUE(
  210. (::std::is_same<folly::void_t<int, short, std::string>, void>::value));
  211. EXPECT_TRUE((::has_value_type<std::string>::value));
  212. EXPECT_FALSE((::has_value_type<int>::value));
  213. }
  214. TEST(Traits, type_t) {
  215. EXPECT_TRUE((::std::is_same<folly::type_t<float>, float>::value));
  216. EXPECT_TRUE((::std::is_same<folly::type_t<float, int>, float>::value));
  217. EXPECT_TRUE((::std::is_same<folly::type_t<float, int, short>, float>::value));
  218. EXPECT_TRUE(
  219. (::std::is_same<folly::type_t<float, int, short, std::string>, float>::
  220. value));
  221. EXPECT_TRUE((
  222. ::std::is_constructible<::container<std::string>, some_tag, std::string>::
  223. value));
  224. EXPECT_FALSE(
  225. (::std::is_constructible<::container<std::string>, some_tag, float>::
  226. value));
  227. }
  228. TEST(Traits, remove_cvref) {
  229. using folly::remove_cvref;
  230. using folly::remove_cvref_t;
  231. // test all possible c-ref qualifiers without volatile
  232. EXPECT_TRUE((std::is_same<remove_cvref_t<int>, int>::value));
  233. EXPECT_TRUE((std::is_same<remove_cvref<int>::type, int>::value));
  234. EXPECT_TRUE((std::is_same<remove_cvref_t<int&&>, int>::value));
  235. EXPECT_TRUE((std::is_same<remove_cvref<int&&>::type, int>::value));
  236. EXPECT_TRUE((std::is_same<remove_cvref_t<int&>, int>::value));
  237. EXPECT_TRUE((std::is_same<remove_cvref<int&>::type, int>::value));
  238. EXPECT_TRUE((std::is_same<remove_cvref_t<int const>, int>::value));
  239. EXPECT_TRUE((std::is_same<remove_cvref<int const>::type, int>::value));
  240. EXPECT_TRUE((std::is_same<remove_cvref_t<int const&>, int>::value));
  241. EXPECT_TRUE((std::is_same<remove_cvref<int const&>::type, int>::value));
  242. EXPECT_TRUE((std::is_same<remove_cvref_t<int const&&>, int>::value));
  243. EXPECT_TRUE((std::is_same<remove_cvref<int const&&>::type, int>::value));
  244. // test all possible c-ref qualifiers with volatile
  245. EXPECT_TRUE((std::is_same<remove_cvref_t<int volatile>, int>::value));
  246. EXPECT_TRUE((std::is_same<remove_cvref<int volatile>::type, int>::value));
  247. EXPECT_TRUE((std::is_same<remove_cvref_t<int volatile&&>, int>::value));
  248. EXPECT_TRUE((std::is_same<remove_cvref<int volatile&&>::type, int>::value));
  249. EXPECT_TRUE((std::is_same<remove_cvref_t<int volatile&>, int>::value));
  250. EXPECT_TRUE((std::is_same<remove_cvref<int volatile&>::type, int>::value));
  251. EXPECT_TRUE((std::is_same<remove_cvref_t<int volatile const>, int>::value));
  252. EXPECT_TRUE(
  253. (std::is_same<remove_cvref<int volatile const>::type, int>::value));
  254. EXPECT_TRUE((std::is_same<remove_cvref_t<int volatile const&>, int>::value));
  255. EXPECT_TRUE(
  256. (std::is_same<remove_cvref<int volatile const&>::type, int>::value));
  257. EXPECT_TRUE((std::is_same<remove_cvref_t<int volatile const&&>, int>::value));
  258. EXPECT_TRUE(
  259. (std::is_same<remove_cvref<int volatile const&&>::type, int>::value));
  260. }
  261. TEST(Traits, like) {
  262. EXPECT_TRUE((std::is_same<like_t<int, char>, char>::value));
  263. EXPECT_TRUE((std::is_same<like_t<int const, char>, char const>::value));
  264. EXPECT_TRUE((std::is_same<like_t<int volatile, char>, char volatile>::value));
  265. EXPECT_TRUE(
  266. (std::is_same<like_t<int const volatile, char>, char const volatile>::
  267. value));
  268. EXPECT_TRUE((std::is_same<like_t<int&, char>, char&>::value));
  269. EXPECT_TRUE((std::is_same<like_t<int const&, char>, char const&>::value));
  270. EXPECT_TRUE(
  271. (std::is_same<like_t<int volatile&, char>, char volatile&>::value));
  272. EXPECT_TRUE(
  273. (std::is_same<like_t<int const volatile&, char>, char const volatile&>::
  274. value));
  275. EXPECT_TRUE((std::is_same<like_t<int&&, char>, char&&>::value));
  276. EXPECT_TRUE((std::is_same<like_t<int const&&, char>, char const&&>::value));
  277. EXPECT_TRUE(
  278. (std::is_same<like_t<int volatile&&, char>, char volatile&&>::value));
  279. EXPECT_TRUE(
  280. (std::is_same<like_t<int const volatile&&, char>, char const volatile&&>::
  281. value));
  282. }