proxygen
TraitsTest.cpp
Go to the documentation of this file.
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 
17 #include <folly/Traits.h>
18 
19 #include <cstring>
20 #include <string>
21 #include <type_traits>
22 #include <utility>
23 
24 #include <folly/ScopeGuard.h>
26 
27 using namespace folly;
28 using namespace std;
29 
30 namespace {
31 
32 FOLLY_CREATE_HAS_MEMBER_TYPE_TRAITS(has_member_type_x, x);
33 } // namespace
34 
35 TEST(Traits, has_member_type) {
36  struct membership_no {};
37  struct membership_yes {
38  using x = void;
39  };
40 
41  EXPECT_TRUE((is_same<false_type, has_member_type_x<membership_no>>::value));
42  EXPECT_TRUE((is_same<true_type, has_member_type_x<membership_yes>>::value));
43 }
44 
45 // Note: FOLLY_CREATE_HAS_MEMBER_FN_TRAITS tests are in
46 // folly/test/HasMemberFnTraitsTest.cpp.
47 
48 struct T1 {}; // old-style IsRelocatable, below
49 struct T2 {}; // old-style IsRelocatable, below
50 struct T3 {
52 };
53 struct T5 : T3 {};
54 
55 struct F1 {};
56 struct F2 {
57  typedef int IsRelocatable;
58 };
59 struct F3 : T3 {
61 };
62 struct F4 : T1 {};
63 
64 namespace folly {
65 template <>
67 template <>
69 } // namespace folly
70 
71 TEST(Traits, scalars) {
76 }
77 
78 TEST(Traits, containers) {
79  EXPECT_TRUE(IsRelocatable<vector<F1>>::value);
80  EXPECT_TRUE((IsRelocatable<pair<F1, F1>>::value));
81  EXPECT_TRUE((IsRelocatable<pair<T1, T2>>::value));
82 }
83 
84 TEST(Traits, original) {
87 }
88 
89 TEST(Traits, typedefd) {
94 }
95 
96 TEST(Traits, unset) {
99 }
100 
101 TEST(Traits, bitAndInit) {
103  EXPECT_FALSE(IsZeroInitializable<vector<int>>::value);
104 }
105 
106 TEST(Trait, logicOperators) {
107  static_assert(Conjunction<true_type>::value, "");
108  static_assert(!Conjunction<false_type>::value, "");
109  static_assert(is_same<Conjunction<true_type>::type, true_type>::value, "");
110  static_assert(is_same<Conjunction<false_type>::type, false_type>::value, "");
111  static_assert(Conjunction<true_type, true_type>::value, "");
112  static_assert(!Conjunction<true_type, false_type>::value, "");
113 
114  static_assert(Disjunction<true_type>::value, "");
115  static_assert(!Disjunction<false_type>::value, "");
116  static_assert(is_same<Disjunction<true_type>::type, true_type>::value, "");
117  static_assert(is_same<Disjunction<false_type>::type, false_type>::value, "");
118  static_assert(Disjunction<true_type, true_type>::value, "");
120 
121  static_assert(!Negation<true_type>::value, "");
122  static_assert(Negation<false_type>::value, "");
123 }
124 
125 TEST(Traits, is_negative) {
131 
137 }
138 
139 TEST(Traits, relational) {
140  // We test, especially, the edge cases to make sure we don't
141  // trip -Wtautological-comparisons
142 
143  EXPECT_FALSE((folly::less_than<uint8_t, 0u, uint8_t>(0u)));
144  EXPECT_FALSE((folly::less_than<uint8_t, 0u, uint8_t>(254u)));
145  EXPECT_FALSE((folly::less_than<uint8_t, 255u, uint8_t>(255u)));
146  EXPECT_TRUE((folly::less_than<uint8_t, 255u, uint8_t>(254u)));
147 
148  EXPECT_FALSE((folly::greater_than<uint8_t, 0u, uint8_t>(0u)));
149  EXPECT_TRUE((folly::greater_than<uint8_t, 0u, uint8_t>(254u)));
150  EXPECT_FALSE((folly::greater_than<uint8_t, 255u, uint8_t>(255u)));
151  EXPECT_FALSE((folly::greater_than<uint8_t, 255u, uint8_t>(254u)));
152 }
153 
154 #if FOLLY_HAVE_INT128_T
155 
156 TEST(Traits, int128) {
157  EXPECT_TRUE(
158  (::std::is_same<::std::make_unsigned<__int128_t>::type, __uint128_t>::
159  value));
160  EXPECT_TRUE((
161  ::std::is_same<::std::make_signed<__int128_t>::type, __int128_t>::value));
162  EXPECT_TRUE(
163  (::std::is_same<::std::make_unsigned<__uint128_t>::type, __uint128_t>::
164  value));
165  EXPECT_TRUE(
166  (::std::is_same<::std::make_signed<__uint128_t>::type, __int128_t>::
167  value));
180 }
181 
182 #endif // FOLLY_HAVE_INT128_T
183 
184 template <typename T, typename... Args>
185 void testIsRelocatable(Args&&... args) {
187  return;
188  }
189 
190  // We use placement new on zeroed memory to avoid garbage subsections
191  char vsrc[sizeof(T)] = {0};
192  char vdst[sizeof(T)] = {0};
193  char vcpy[sizeof(T)];
194 
195  T* src = new (vsrc) T(std::forward<Args>(args)...);
196  SCOPE_EXIT {
197  src->~T();
198  };
199  std::memcpy(vcpy, vsrc, sizeof(T));
200  T deep(*src);
201  T* dst = new (vdst) T(std::move(*src));
202  SCOPE_EXIT {
203  dst->~T();
204  };
205 
206  EXPECT_EQ(deep, *dst);
207 #pragma GCC diagnostic push
208 #pragma GCC diagnostic ignored "-Wstrict-aliasing"
209  EXPECT_EQ(deep, *reinterpret_cast<T*>(vcpy));
210 #pragma GCC diagnostic pop
211 
212  // This test could technically fail; however, this is what relocation
213  // almost always means, so it's a good test to have
214  EXPECT_EQ(std::memcmp(vcpy, vdst, sizeof(T)), 0);
215 }
216 
217 TEST(Traits, actuallyRelocatable) {
218  // Ensure that we test stack and heap allocation for strings with in-situ
219  // capacity
220  testIsRelocatable<std::string>("1");
221  testIsRelocatable<std::string>(sizeof(std::string) + 1, 'x');
222 
223  testIsRelocatable<std::vector<char>>(5, 'g');
224 }
225 
226 namespace {
227 // has_value_type<T>::value is true if T has a nested type `value_type`
228 template <class T, class = void>
229 struct has_value_type : std::false_type {};
230 
231 template <class T>
232 struct has_value_type<T, folly::void_t<typename T::value_type>>
233  : std::true_type {};
234 
235 struct some_tag {};
236 
237 template <typename T>
238 struct container {
239  template <class... Args>
240  container(
241  folly::type_t<some_tag, decltype(T(std::declval<Args>()...))>,
242  Args&&...) {}
243 };
244 } // namespace
245 
246 TEST(Traits, void_t) {
247  EXPECT_TRUE((::std::is_same<folly::void_t<>, void>::value));
248  EXPECT_TRUE((::std::is_same<folly::void_t<int>, void>::value));
249  EXPECT_TRUE((::std::is_same<folly::void_t<int, short>, void>::value));
250  EXPECT_TRUE(
251  (::std::is_same<folly::void_t<int, short, std::string>, void>::value));
254 }
255 
256 TEST(Traits, type_t) {
257  EXPECT_TRUE((::std::is_same<folly::type_t<float>, float>::value));
258  EXPECT_TRUE((::std::is_same<folly::type_t<float, int>, float>::value));
259  EXPECT_TRUE((::std::is_same<folly::type_t<float, int, short>, float>::value));
260  EXPECT_TRUE(
261  (::std::is_same<folly::type_t<float, int, short, std::string>, float>::
262  value));
263  EXPECT_TRUE((
264  ::std::is_constructible<::container<std::string>, some_tag, std::string>::
265  value));
266  EXPECT_FALSE(
267  (::std::is_constructible<::container<std::string>, some_tag, float>::
268  value));
269 }
270 
271 TEST(Traits, remove_cvref) {
272  using folly::remove_cvref;
273  using folly::remove_cvref_t;
274 
275  // test all possible c-ref qualifiers without volatile
276  EXPECT_TRUE((std::is_same<remove_cvref_t<int>, int>::value));
277  EXPECT_TRUE((std::is_same<remove_cvref<int>::type, int>::value));
278 
279  EXPECT_TRUE((std::is_same<remove_cvref_t<int&&>, int>::value));
280  EXPECT_TRUE((std::is_same<remove_cvref<int&&>::type, int>::value));
281 
282  EXPECT_TRUE((std::is_same<remove_cvref_t<int&>, int>::value));
283  EXPECT_TRUE((std::is_same<remove_cvref<int&>::type, int>::value));
284 
285  EXPECT_TRUE((std::is_same<remove_cvref_t<int const>, int>::value));
286  EXPECT_TRUE((std::is_same<remove_cvref<int const>::type, int>::value));
287 
288  EXPECT_TRUE((std::is_same<remove_cvref_t<int const&>, int>::value));
289  EXPECT_TRUE((std::is_same<remove_cvref<int const&>::type, int>::value));
290 
291  EXPECT_TRUE((std::is_same<remove_cvref_t<int const&&>, int>::value));
292  EXPECT_TRUE((std::is_same<remove_cvref<int const&&>::type, int>::value));
293 
294  // test all possible c-ref qualifiers with volatile
295  EXPECT_TRUE((std::is_same<remove_cvref_t<int volatile>, int>::value));
296  EXPECT_TRUE((std::is_same<remove_cvref<int volatile>::type, int>::value));
297 
298  EXPECT_TRUE((std::is_same<remove_cvref_t<int volatile&&>, int>::value));
300 
301  EXPECT_TRUE((std::is_same<remove_cvref_t<int volatile&>, int>::value));
302  EXPECT_TRUE((std::is_same<remove_cvref<int volatile&>::type, int>::value));
303 
305  EXPECT_TRUE(
306  (std::is_same<remove_cvref<int volatile const>::type, int>::value));
307 
309  EXPECT_TRUE(
310  (std::is_same<remove_cvref<int volatile const&>::type, int>::value));
311 
313  EXPECT_TRUE(
314  (std::is_same<remove_cvref<int volatile const&&>::type, int>::value));
315 }
316 
317 TEST(Traits, like) {
318  EXPECT_TRUE((std::is_same<like_t<int, char>, char>::value));
319  EXPECT_TRUE((std::is_same<like_t<int const, char>, char const>::value));
320  EXPECT_TRUE((std::is_same<like_t<int volatile, char>, char volatile>::value));
321  EXPECT_TRUE(
322  (std::is_same<like_t<int const volatile, char>, char const volatile>::
323  value));
324  EXPECT_TRUE((std::is_same<like_t<int&, char>, char&>::value));
325  EXPECT_TRUE((std::is_same<like_t<int const&, char>, char const&>::value));
326  EXPECT_TRUE(
327  (std::is_same<like_t<int volatile&, char>, char volatile&>::value));
328  EXPECT_TRUE(
329  (std::is_same<like_t<int const volatile&, char>, char const volatile&>::
330  value));
331  EXPECT_TRUE((std::is_same<like_t<int&&, char>, char&&>::value));
332  EXPECT_TRUE((std::is_same<like_t<int const&&, char>, char const&&>::value));
333  EXPECT_TRUE(
334  (std::is_same<like_t<int volatile&&, char>, char volatile&&>::value));
335  EXPECT_TRUE(
336  (std::is_same<like_t<int const volatile&&, char>, char const volatile&&>::
337  value));
338 }
Definition: InvokeTest.cpp:58
std::false_type IsRelocatable
Definition: TraitsTest.cpp:60
typename remove_cvref< T >::type remove_cvref_t
Definition: Traits.h:183
FOLLY_ASSUME_RELOCATABLE(basic_fbstring< T, R, A, S >)
PskType type
#define EXPECT_EQ(val1, val2)
Definition: gtest.h:1922
constexpr detail::Map< Move > move
Definition: Base-inl.h:2567
STL namespace.
#define SCOPE_EXIT
Definition: ScopeGuard.h:274
folly::std T
internal::ArgsMatcher< InnerMatcher > Args(const InnerMatcher &matcher)
—— Concurrent Priority Queue Implementation ——
Definition: AtomicBitSet.h:29
std::true_type IsRelocatable
Definition: TraitsTest.cpp:51
typename traits_detail::type_t_< T, Ts... >::type type_t
Definition: Traits.h:300
bool_constant< true > true_type
Definition: gtest-port.h:2210
constexpr bool is_non_positive(T x)
Definition: Traits.h:681
typename detail::like_< Src >::template apply< remove_cvref_t< Dst >> like_t
Definition: Traits.h:220
type_t< void, Ts... > void_t
Definition: Traits.h:302
#define FOLLY_CREATE_HAS_MEMBER_TYPE_TRAITS(classname, type_name)
Definition: Traits.h:39
static const char *const value
Definition: Conv.cpp:50
void testIsRelocatable(Args &&...args)
Definition: TraitsTest.cpp:185
#define EXPECT_TRUE(condition)
Definition: gtest.h:1859
typename std::remove_cv< typename std::remove_reference< T >::type >::type type
Definition: Traits.h:180
constexpr bool is_negative(T x)
Definition: Traits.h:675
const char * string
Definition: Conv.cpp:212
uint64_t value(const typename LockFreeRingBuffer< T, Atom >::Cursor &rbcursor)
bool_constant< false > false_type
Definition: gtest-port.h:2209
#define EXPECT_FALSE(condition)
Definition: gtest.h:1862
TEST(SequencedExecutor, CPUThreadPoolExecutor)
int IsRelocatable
Definition: TraitsTest.cpp:57