proxygen
IteratorTest.cpp File Reference
#include <algorithm>
#include <cassert>
#include <cstddef>
#include <deque>
#include <functional>
#include <map>
#include <set>
#include <tuple>
#include <type_traits>
#include <utility>
#include <vector>
#include <folly/container/Iterator.h>
#include <folly/portability/GTest.h>

Go to the source code of this file.

Functions

 TEST (EmplaceIterator, EmplacerTest)
 
 TEST (EmplaceIterator, FrontEmplacerTest)
 
 TEST (EmplaceIterator, BackEmplacerTest)
 
 TEST (EmplaceIterator, HintEmplacerTest)
 
 TEST (EmplaceIterator, Copy)
 
 TEST (EmplaceIterator, Transform)
 
 TEST (EmplaceIterator, EmplaceArgs)
 
 TEST (EmplaceIterator, ImplicitUnpack)
 

Function Documentation

TEST ( EmplaceIterator  ,
EmplacerTest   
)

Basic tests for folly::emplace_iterator.

Definition at line 153 of file IteratorTest.cpp.

References copy_and_move_test(), folly::emplacer(), and EXPECT_EQ.

153  {
154  {
155  Container<int> q;
156  copy_and_move_test(q, emplacer(q, q.begin()));
157  }
158  {
159  Container<Object> q;
160  emplace_test(q, emplacer(q, q.begin()));
161  }
162  {
163  Container<int> q;
164  auto it = emplacer(q, q.begin());
165  it = 0;
166  it = 1;
167  it = 2;
168  it = emplacer(q, q.begin());
169  it = 3;
170  it = 4;
171  EXPECT_EQ(q, Container<int>({3, 4, 0, 1, 2}));
172  }
173 }
emplace_iterator< Container, implicit_unpack > emplacer(Container &c, typename Container::iterator i)
Definition: Iterator.h:445
#define EXPECT_EQ(val1, val2)
Definition: gtest.h:1922
void copy_and_move_test()
Definition: HazptrTest.cpp:317
TEST ( EmplaceIterator  ,
FrontEmplacerTest   
)

Basic tests for folly::front_emplace_iterator.

Definition at line 178 of file IteratorTest.cpp.

References copy_and_move_test(), EXPECT_EQ, and folly::front_emplacer().

178  {
179  {
180  Container<int> q;
182  }
183  {
184  Container<Object> q;
185  emplace_test(q, front_emplacer(q));
186  }
187  {
188  Container<int> q;
189  auto it = front_emplacer(q);
190  it = 0;
191  it = 1;
192  it = 2;
193  it = front_emplacer(q);
194  it = 3;
195  it = 4;
196  EXPECT_EQ(q, Container<int>({4, 3, 2, 1, 0}));
197  }
198 }
front_emplace_iterator< Container, implicit_unpack > front_emplacer(Container &c)
Definition: Iterator.h:477
#define EXPECT_EQ(val1, val2)
Definition: gtest.h:1922
void copy_and_move_test()
Definition: HazptrTest.cpp:317
TEST ( EmplaceIterator  ,
BackEmplacerTest   
)

Basic tests for folly::back_emplace_iterator.

Definition at line 203 of file IteratorTest.cpp.

References folly::back_emplacer(), copy_and_move_test(), and EXPECT_EQ.

203  {
204  {
205  Container<int> q;
207  }
208  {
209  Container<Object> q;
210  emplace_test(q, back_emplacer(q));
211  }
212  {
213  Container<int> q;
214  auto it = back_emplacer(q);
215  it = 0;
216  it = 1;
217  it = 2;
218  it = back_emplacer(q);
219  it = 3;
220  it = 4;
221  EXPECT_EQ(q, Container<int>({0, 1, 2, 3, 4}));
222  }
223 }
#define EXPECT_EQ(val1, val2)
Definition: gtest.h:1922
back_emplace_iterator< Container, implicit_unpack > back_emplacer(Container &c)
Definition: Iterator.h:492
void copy_and_move_test()
Definition: HazptrTest.cpp:317
TEST ( EmplaceIterator  ,
HintEmplacerTest   
)

Basic tests for folly::hint_emplace_iterator.

Definition at line 228 of file IteratorTest.cpp.

References ASSERT_EQ, diff(), EXPECT_EQ, folly::hint_emplacer(), i, m, folly::make_emplace_args(), folly::operator<(), and operator==().

228  {
229  {
230  init_counters();
231  std::map<int, Object> m;
232  auto it = hint_emplacer(m, m.end());
233  it = make_emplace_args(
234  std::piecewise_construct,
235  std::forward_as_tuple(0),
236  std::forward_as_tuple(0));
237  it = make_emplace_args(
238  std::piecewise_construct,
239  std::forward_as_tuple(1),
240  std::forward_as_tuple(0, 0));
241  it = make_emplace_args(
242  std::piecewise_construct,
243  std::forward_as_tuple(2),
244  std::forward_as_tuple(Object{}));
245  ASSERT_EQ(m.size(), 3);
246  EXPECT_EQ(gDefaultCtrCnt, 1);
247  EXPECT_EQ(gCopyCtrCnt, 0);
248  EXPECT_EQ(gMoveCtrCnt, 1);
249  EXPECT_EQ(gExplicitCtrCnt, 1);
250  EXPECT_EQ(gMultiargCtrCnt, 1);
251  EXPECT_EQ(gCopyOpCnt, 0);
252  EXPECT_EQ(gMoveOpCnt, 0);
253  EXPECT_EQ(gConvertOpCnt, 0);
254  }
255  {
256  struct O {
257  explicit O(int i_) : i(i_) {}
258  bool operator<(const O& other) const {
259  return i < other.i;
260  }
261  bool operator==(const O& other) const {
262  return i == other.i;
263  }
264  int i;
265  };
266  std::vector<int> v1 = {0, 1, 2, 3, 4};
267  std::vector<int> v2 = {0, 2, 4};
268  std::set<O> diff;
269  std::set_difference(
270  v1.begin(),
271  v1.end(),
272  v2.begin(),
273  v2.end(),
274  hint_emplacer(diff, diff.end()));
275  std::set<O> expected = {O(1), O(3)};
276  ASSERT_EQ(diff, expected);
277  }
278 }
bool operator==(const char *c, CStringRange::Sentinel)
#define ASSERT_EQ(val1, val2)
Definition: gtest.h:1956
#define EXPECT_EQ(val1, val2)
Definition: gtest.h:1922
hint_emplace_iterator< Container, implicit_unpack > hint_emplacer(Container &c, typename Container::iterator i)
Definition: Iterator.h:461
static map< string, int > m
emplace_args< Args... > make_emplace_args(Args &&...args) noexcept(noexcept(emplace_args< Args... >(std::forward< Args >(args)...)))
Definition: Iterator.h:92
uint64_t diff(uint64_t a, uint64_t b)
Definition: FutexTest.cpp:135
std::enable_if< IsLessThanComparable< Value >::value, bool >::type operator<(const Expected< Value, Error > &lhs, const Expected< Value, Error > &rhs)
Definition: Expected.h:1321
TEST ( EmplaceIterator  ,
Copy   
)

Test std::copy() with explicit conversion. This would not compile with a std::back_insert_iterator, because the constructor of Object that takes a single int is explicit.

Definition at line 285 of file IteratorTest.cpp.

References folly::back_emplacer(), folly::copy(), and EXPECT_EQ.

285  {
286  init_counters();
287  Container<int> in({0, 1, 2});
288  Container<Object> out;
289  std::copy(in.begin(), in.end(), back_emplacer(out));
290  EXPECT_EQ(3, out.size());
291  EXPECT_EQ(gDefaultCtrCnt, 0);
292  EXPECT_EQ(gCopyCtrCnt, 0);
293  EXPECT_EQ(gMoveCtrCnt, 0);
294  EXPECT_EQ(gExplicitCtrCnt, 3);
295  EXPECT_EQ(gMultiargCtrCnt, 0);
296  EXPECT_EQ(gCopyOpCnt, 0);
297  EXPECT_EQ(gMoveOpCnt, 0);
298  EXPECT_EQ(gConvertOpCnt, 0);
299 }
#define EXPECT_EQ(val1, val2)
Definition: gtest.h:1922
back_emplace_iterator< Container, implicit_unpack > back_emplacer(Container &c)
Definition: Iterator.h:492
constexpr std::decay< T >::type copy(T &&value) noexcept(noexcept(typename std::decay< T >::type(std::forward< T >(value))))
Definition: Utility.h:72
TEST ( EmplaceIterator  ,
Transform   
)

Test std::transform() with multi-argument constructors. This would require a temporary Object with std::back_insert_iterator.

Definition at line 305 of file IteratorTest.cpp.

References folly::back_emplacer(), EXPECT_EQ, i, folly::make_emplace_args(), and folly::pushmi::operators::transform.

305  {
306  init_counters();
307  Container<int> in({0, 1, 2});
308  Container<Object> out;
309  std::transform(in.begin(), in.end(), back_emplacer(out), [](int i) {
310  return make_emplace_args(i, i);
311  });
312  EXPECT_EQ(3, out.size());
313  EXPECT_EQ(gDefaultCtrCnt, 0);
314  EXPECT_EQ(gCopyCtrCnt, 0);
315  EXPECT_EQ(gMoveCtrCnt, 0);
316  EXPECT_EQ(gExplicitCtrCnt, 0);
317  EXPECT_EQ(gMultiargCtrCnt, 3);
318  EXPECT_EQ(gCopyOpCnt, 0);
319  EXPECT_EQ(gMoveOpCnt, 0);
320  EXPECT_EQ(gConvertOpCnt, 0);
321 }
#define EXPECT_EQ(val1, val2)
Definition: gtest.h:1922
back_emplace_iterator< Container, implicit_unpack > back_emplacer(Container &c)
Definition: Iterator.h:492
PUSHMI_INLINE_VAR constexpr detail::transform_fn transform
Definition: transform.h:158
emplace_args< Args... > make_emplace_args(Args &&...args) noexcept(noexcept(emplace_args< Args... >(std::forward< Args >(args)...)))
Definition: Iterator.h:92
TEST ( EmplaceIterator  ,
EmplaceArgs   
)

Test multi-argument store and forward.

Definition at line 326 of file IteratorTest.cpp.

References EXPECT_EQ, folly::make_emplace_args(), folly::gen::move, folly::rref(), and value.

326  {
327  Object o1;
328  const Object o2;
329  Object& o3 = o1;
330  const Object& o4 = o3;
331  Object o5;
332 
333  {
334  // Test copy construction.
335  auto args = make_emplace_args(0, o1, o2, o3, o4, Object{}, std::cref(o2));
336  init_counters();
337  auto args2 = args;
338  EXPECT_EQ(gDefaultCtrCnt, 0);
339  EXPECT_EQ(gCopyCtrCnt, 5);
340  EXPECT_EQ(gMoveCtrCnt, 0);
341  EXPECT_EQ(gExplicitCtrCnt, 0);
342  EXPECT_EQ(gMultiargCtrCnt, 0);
343  EXPECT_EQ(gCopyOpCnt, 0);
344  EXPECT_EQ(gMoveOpCnt, 0);
345  EXPECT_EQ(gConvertOpCnt, 0);
346 
347  // Test copy assignment.
348  init_counters();
349  args = args2;
350  EXPECT_EQ(gDefaultCtrCnt, 0);
351  EXPECT_EQ(gCopyCtrCnt, 0);
352  EXPECT_EQ(gMoveCtrCnt, 0);
353  EXPECT_EQ(gExplicitCtrCnt, 0);
354  EXPECT_EQ(gMultiargCtrCnt, 0);
355  EXPECT_EQ(gCopyOpCnt, 5);
356  EXPECT_EQ(gMoveOpCnt, 0);
357  EXPECT_EQ(gConvertOpCnt, 0);
358  }
359 
360  {
361  // Test RVO.
362  init_counters();
363  auto args = make_emplace_args(
364  0, o1, o2, o3, o4, Object{}, std::cref(o2), rref(std::move(o5)));
365  EXPECT_EQ(gDefaultCtrCnt, 1);
366  EXPECT_EQ(gCopyCtrCnt, 4);
367  EXPECT_EQ(gMoveCtrCnt, 1);
368  EXPECT_EQ(gExplicitCtrCnt, 0);
369  EXPECT_EQ(gMultiargCtrCnt, 0);
370  EXPECT_EQ(gCopyOpCnt, 0);
371  EXPECT_EQ(gMoveOpCnt, 0);
372  EXPECT_EQ(gConvertOpCnt, 0);
373 
374  // Test move construction.
375  init_counters();
376  auto args2 = std::move(args);
377  EXPECT_EQ(gDefaultCtrCnt, 0);
378  EXPECT_EQ(gCopyCtrCnt, 0);
379  EXPECT_EQ(gMoveCtrCnt, 5);
380  EXPECT_EQ(gExplicitCtrCnt, 0);
381  EXPECT_EQ(gMultiargCtrCnt, 0);
382  EXPECT_EQ(gCopyOpCnt, 0);
383  EXPECT_EQ(gMoveOpCnt, 0);
384  EXPECT_EQ(gConvertOpCnt, 0);
385 
386  // Test move assignment.
387  init_counters();
388  args = std::move(args2);
389  EXPECT_EQ(gDefaultCtrCnt, 0);
390  EXPECT_EQ(gCopyCtrCnt, 0);
391  EXPECT_EQ(gMoveCtrCnt, 0);
392  EXPECT_EQ(gExplicitCtrCnt, 0);
393  EXPECT_EQ(gMultiargCtrCnt, 0);
394  EXPECT_EQ(gCopyOpCnt, 0);
395  EXPECT_EQ(gMoveOpCnt, 5);
396  EXPECT_EQ(gConvertOpCnt, 0);
397 
398  // Make sure arguments are stored correctly. lvalues by reference, rvalues
399  // by (moved) copy. Rvalues cannot be stored by reference because they may
400  // refer to an expired temporary by the time they are accessed.
401  static_assert(
402  std::is_same<
403  int,
404  std::tuple_element_t<0, decltype(args)::storage_type>>::value,
405  "");
406  static_assert(
407  std::is_same<
408  Object,
409  std::tuple_element_t<1, decltype(args)::storage_type>>::value,
410  "");
411  static_assert(
412  std::is_same<
413  Object,
414  std::tuple_element_t<2, decltype(args)::storage_type>>::value,
415  "");
416  static_assert(
417  std::is_same<
418  Object,
419  std::tuple_element_t<3, decltype(args)::storage_type>>::value,
420  "");
421  static_assert(
422  std::is_same<
423  Object,
424  std::tuple_element_t<4, decltype(args)::storage_type>>::value,
425  "");
426  static_assert(
427  std::is_same<
428  Object,
429  std::tuple_element_t<5, decltype(args)::storage_type>>::value,
430  "");
431  static_assert(
432  std::is_same<
433  std::reference_wrapper<const Object>,
434  std::tuple_element_t<6, decltype(args)::storage_type>>::value,
435  "");
436  static_assert(
437  std::is_same<
439  std::tuple_element_t<7, decltype(args)::storage_type>>::value,
440  "");
441 
442  // Check whether args.get() restores the original argument type for
443  // rvalue references to emplace_args.
444  static_assert(
445  std::is_same<int&&, decltype(get_emplace_arg<0>(std::move(args)))>::
446  value,
447  "");
448  static_assert(
449  std::is_same<Object&, decltype(get_emplace_arg<1>(std::move(args)))>::
450  value,
451  "");
452  static_assert(
453  std::is_same<
454  const Object&,
455  decltype(get_emplace_arg<2>(std::move(args)))>::value,
456  "");
457  static_assert(
458  std::is_same<Object&, decltype(get_emplace_arg<3>(std::move(args)))>::
459  value,
460  "");
461  static_assert(
462  std::is_same<
463  const Object&,
464  decltype(get_emplace_arg<4>(std::move(args)))>::value,
465  "");
466  static_assert(
467  std::is_same<Object&&, decltype(get_emplace_arg<5>(std::move(args)))>::
468  value,
469  "");
470  static_assert(
471  std::is_same<
472  const Object&,
473  decltype(get_emplace_arg<6>(std::move(args)))>::value,
474  "");
475  static_assert(
476  std::is_same<Object&&, decltype(get_emplace_arg<7>(std::move(args)))>::
477  value,
478  "");
479 
480  // lvalue references to emplace_args should behave mostly like std::tuples.
481  // Note that get_emplace_arg<7>(args) does not compile, because
482  // folly::rvalue_reference_wrappers can only be unwrapped through an rvalue
483  // reference.
484  static_assert(
485  std::is_same<int&, decltype(get_emplace_arg<0>(args))>::value, "");
486  static_assert(
487  std::is_same<Object&, decltype(get_emplace_arg<1>(args))>::value, "");
488  static_assert(
489  std::is_same<Object&, decltype(get_emplace_arg<2>(args))>::value, "");
490  static_assert(
491  std::is_same<Object&, decltype(get_emplace_arg<3>(args))>::value, "");
492  static_assert(
493  std::is_same<Object&, decltype(get_emplace_arg<4>(args))>::value, "");
494  static_assert(
495  std::is_same<Object&, decltype(get_emplace_arg<5>(args))>::value, "");
496  static_assert(
497  std::is_same<const Object&, decltype(get_emplace_arg<6>(args))>::value,
498  "");
499  }
500 }
#define EXPECT_EQ(val1, val2)
Definition: gtest.h:1922
constexpr detail::Map< Move > move
Definition: Base-inl.h:2567
rvalue_reference_wrapper< T > rref(T &&value) noexcept
static const char *const value
Definition: Conv.cpp:50
emplace_args< Args... > make_emplace_args(Args &&...args) noexcept(noexcept(emplace_args< Args... >(std::forward< Args >(args)...)))
Definition: Iterator.h:92
TEST ( EmplaceIterator  ,
ImplicitUnpack   
)

Test implicit unpacking.

Definition at line 505 of file IteratorTest.cpp.

References folly::back_emplacer(), folly::emplacer(), EXPECT_EQ, folly::front_emplacer(), std::tr1::make_tuple(), and test().

505  {
506  static std::size_t multiCtrCnt;
507  static std::size_t pairCtrCnt;
508  static std::size_t tupleCtrCnt;
509 
510  struct Object2 {
511  Object2(int, int) {
512  ++multiCtrCnt;
513  }
514  explicit Object2(const std::pair<int, int>&) {
515  ++pairCtrCnt;
516  }
517  explicit Object2(const std::tuple<int, int>&) {
518  ++tupleCtrCnt;
519  }
520  };
521 
522  auto test = [](auto&& it, bool expectUnpack) {
523  multiCtrCnt = pairCtrCnt = tupleCtrCnt = 0;
524  it = std::make_pair(0, 0);
525  it = std::make_tuple(0, 0);
526  if (expectUnpack) {
527  EXPECT_EQ(multiCtrCnt, 2);
528  EXPECT_EQ(pairCtrCnt, 0);
529  EXPECT_EQ(tupleCtrCnt, 0);
530  } else {
531  EXPECT_EQ(multiCtrCnt, 0);
532  EXPECT_EQ(pairCtrCnt, 1);
533  EXPECT_EQ(tupleCtrCnt, 1);
534  }
535  };
536 
537  Container<Object2> q;
538 
539  test(emplacer(q, q.begin()), true);
540  test(emplacer<false>(q, q.begin()), false);
541  test(front_emplacer(q), true);
542  test(front_emplacer<false>(q), false);
543  test(back_emplacer(q), true);
544  test(back_emplacer<false>(q), false);
545 }
emplace_iterator< Container, implicit_unpack > emplacer(Container &c, typename Container::iterator i)
Definition: Iterator.h:445
front_emplace_iterator< Container, implicit_unpack > front_emplacer(Container &c)
Definition: Iterator.h:477
#define EXPECT_EQ(val1, val2)
Definition: gtest.h:1922
static uint64_t test(std::string name, bool fc_, bool dedicated_, bool tc_, bool syncops_, uint64_t base)
back_emplace_iterator< Container, implicit_unpack > back_emplacer(Container &c)
Definition: Iterator.h:492
tuple make_tuple()
Definition: gtest-tuple.h:675