brintos

brintos / llvm-project-archived public Read only

0
0
Text · 7.4 KiB · 8ea3dbc Raw
305 lines · cpp
1//===------ MappedIteratorTest.cpp - Unit tests for mapped_iterator -------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include "llvm/ADT/STLExtras.h"10#include "gtest/gtest.h"11 12using namespace llvm;13 14namespace {15 16template <typename T> class MappedIteratorTestBasic : public testing::Test {};17 18struct Plus1Lambda {19  auto operator()() const {20    return [](int X) { return X + 1; };21  }22};23 24struct Plus1LambdaWithCapture {25  const int One = 1;26 27  auto operator()() const {28    return [=](int X) { return X + One; };29  }30};31 32struct Plus1FunctionRef {33  static int plus1(int X) { return X + 1; }34 35  using FuncT = int (&)(int);36 37  FuncT operator()() const { return (FuncT)*plus1; }38};39 40struct Plus1FunctionPtr {41  static int plus1(int X) { return X + 1; }42 43  using FuncT = int (*)(int);44 45  FuncT operator()() const { return plus1; }46};47 48struct Plus1Functor {49  struct Plus1 {50    int operator()(int X) const { return X + 1; }51  };52 53  auto operator()() const { return Plus1(); }54};55 56struct Plus1FunctorNotDefaultConstructible {57  class PlusN {58    const int N;59 60  public:61    PlusN(int NArg) : N(NArg) {}62 63    int operator()(int X) const { return X + N; }64  };65 66  auto operator()() const { return PlusN(1); }67};68 69// clang-format off70using FunctionTypes =71  ::testing::Types<72    Plus1Lambda,73    Plus1LambdaWithCapture,74    Plus1FunctionRef,75    Plus1FunctionPtr,76    Plus1Functor,77    Plus1FunctorNotDefaultConstructible78  >;79// clang-format on80 81TYPED_TEST_SUITE(MappedIteratorTestBasic, FunctionTypes, );82 83template <typename T> using GetFuncT = decltype(std::declval<T>().operator()());84 85TYPED_TEST(MappedIteratorTestBasic, DefaultConstruct) {86  using FuncT = GetFuncT<TypeParam>;87  using IterT = mapped_iterator<typename std::vector<int>::iterator, FuncT>;88  TypeParam GetCallable;89 90  auto Func = GetCallable();91  (void)Func;92  constexpr bool DefaultConstruct =93      std::is_default_constructible_v<callable_detail::Callable<FuncT>>;94  EXPECT_TRUE(DefaultConstruct);95  EXPECT_TRUE(std::is_default_constructible_v<IterT>);96 97  if constexpr (std::is_default_constructible_v<IterT>) {98    IterT I;99    (void)I;100  }101}102 103TYPED_TEST(MappedIteratorTestBasic, CopyConstruct) {104  std::vector<int> V({0});105 106  using FuncT = GetFuncT<TypeParam>;107  using IterT = mapped_iterator<decltype(V)::iterator, FuncT>;108 109  EXPECT_TRUE(std::is_copy_constructible_v<IterT>);110 111  if constexpr (std::is_copy_constructible_v<IterT>) {112    TypeParam GetCallable;113 114    IterT I1(V.begin(), GetCallable());115    IterT I2(I1);116 117    EXPECT_EQ(I2, I1) << "copy constructed iterator is a different position";118  }119}120 121TYPED_TEST(MappedIteratorTestBasic, MoveConstruct) {122  std::vector<int> V({0});123 124  using FuncT = GetFuncT<TypeParam>;125  using IterT = mapped_iterator<decltype(V)::iterator, FuncT>;126 127  EXPECT_TRUE(std::is_move_constructible_v<IterT>);128 129  if constexpr (std::is_move_constructible_v<IterT>) {130    TypeParam GetCallable;131 132    IterT I1(V.begin(), GetCallable());133    IterT I2(V.begin(), GetCallable());134    IterT I3(std::move(I2));135 136    EXPECT_EQ(I3, I1) << "move constructed iterator is a different position";137  }138}139 140TYPED_TEST(MappedIteratorTestBasic, CopyAssign) {141  std::vector<int> V({0});142 143  using FuncT = GetFuncT<TypeParam>;144  using IterT = mapped_iterator<decltype(V)::iterator, FuncT>;145 146  EXPECT_TRUE(std::is_copy_assignable_v<IterT>);147 148  if constexpr (std::is_copy_assignable_v<IterT>) {149    TypeParam GetCallable;150 151    IterT I1(V.begin(), GetCallable());152    IterT I2(V.end(), GetCallable());153 154    I2 = I1;155 156    EXPECT_EQ(I2, I1) << "copy assigned iterator is a different position";157  }158}159 160TYPED_TEST(MappedIteratorTestBasic, MoveAssign) {161  std::vector<int> V({0});162 163  using FuncT = GetFuncT<TypeParam>;164  using IterT = mapped_iterator<decltype(V)::iterator, FuncT>;165 166  EXPECT_TRUE(std::is_move_assignable_v<IterT>);167 168  if constexpr (std::is_move_assignable_v<IterT>) {169    TypeParam GetCallable;170 171    IterT I1(V.begin(), GetCallable());172    IterT I2(V.begin(), GetCallable());173    IterT I3(V.end(), GetCallable());174 175    I3 = std::move(I2);176 177    EXPECT_EQ(I3, I1) << "move assigned iterator is a different position";178  }179}180 181TYPED_TEST(MappedIteratorTestBasic, GetFunction) {182  std::vector<int> V({0});183 184  using FuncT = GetFuncT<TypeParam>;185  using IterT = mapped_iterator<decltype(V)::iterator, FuncT>;186 187  TypeParam GetCallable;188  IterT I(V.begin(), GetCallable());189 190  EXPECT_EQ(I.getFunction()(200), 201);191}192 193TYPED_TEST(MappedIteratorTestBasic, GetCurrent) {194  std::vector<int> V({0});195 196  using FuncT = GetFuncT<TypeParam>;197  using IterT = mapped_iterator<decltype(V)::iterator, FuncT>;198 199  TypeParam GetCallable;200  IterT I(V.begin(), GetCallable());201 202  EXPECT_EQ(I.getCurrent(), V.begin());203  EXPECT_EQ(std::next(I).getCurrent(), V.end());204}205 206TYPED_TEST(MappedIteratorTestBasic, ApplyFunctionOnDereference) {207  std::vector<int> V({0});208  TypeParam GetCallable;209 210  auto I = map_iterator(V.begin(), GetCallable());211 212  EXPECT_EQ(*I, 1) << "should have applied function in dereference";213}214 215TEST(MappedIteratorTest, ApplyFunctionOnArrow) {216  struct S {217    int Z = 0;218  };219 220  std::vector<int> V({0});221  S Y;222  S *P = &Y;223 224  auto I = map_iterator(V.begin(), [&](int X) -> S & { return *(P + X); });225 226  I->Z = 42;227 228  EXPECT_EQ(Y.Z, 42) << "should have applied function during arrow";229}230 231TEST(MappedIteratorTest, FunctionPreservesReferences) {232  std::vector<int> V({1});233  std::map<int, int> M({{1, 1}});234 235  auto I = map_iterator(V.begin(), [&](int X) -> int & { return M[X]; });236  *I = 42;237 238  EXPECT_EQ(M[1], 42) << "assignment should have modified M";239}240 241TEST(MappedIteratorTest, CustomIteratorApplyFunctionOnDereference) {242  struct CustomMapIterator243      : public llvm::mapped_iterator_base<CustomMapIterator,244                                          std::vector<int>::iterator, int> {245    using BaseT::BaseT;246 247    /// Map the element to the iterator result type.248    int mapElement(int X) const { return X + 1; }249  };250 251  std::vector<int> V({0});252 253  CustomMapIterator I(V.begin());254 255  EXPECT_EQ(*I, 1) << "should have applied function in dereference";256}257 258TEST(MappedIteratorTest, CustomIteratorApplyFunctionOnArrow) {259  struct S {260    int Z = 0;261  };262  struct CustomMapIterator263      : public llvm::mapped_iterator_base<CustomMapIterator,264                                          std::vector<int>::iterator, S &> {265    CustomMapIterator(std::vector<int>::iterator it, S *P) : BaseT(it), P(P) {}266 267    /// Map the element to the iterator result type.268    S &mapElement(int X) const { return *(P + X); }269 270    S *P;271  };272 273  std::vector<int> V({0});274  S Y;275 276  CustomMapIterator I(V.begin(), &Y);277 278  I->Z = 42;279 280  EXPECT_EQ(Y.Z, 42) << "should have applied function during arrow";281}282 283TEST(MappedIteratorTest, CustomIteratorFunctionPreservesReferences) {284  struct CustomMapIterator285      : public llvm::mapped_iterator_base<CustomMapIterator,286                                          std::vector<int>::iterator, int &> {287    CustomMapIterator(std::vector<int>::iterator it, std::map<int, int> &M)288        : BaseT(it), M(M) {}289 290    /// Map the element to the iterator result type.291    int &mapElement(int X) const { return M[X]; }292 293    std::map<int, int> &M;294  };295  std::vector<int> V({1});296  std::map<int, int> M({{1, 1}});297 298  auto I = CustomMapIterator(V.begin(), M);299  *I = 42;300 301  EXPECT_EQ(M[1], 42) << "assignment should have modified M";302}303 304} // anonymous namespace305