1 /* 2 * Copyright (C) 2016 The Android Open Source Project 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 <algorithm> 18 #include <vector> 19 20 #include "gtest/gtest.h" 21 22 #include "base/transform_array_ref.h" 23 24 namespace art { 25 26 namespace { // anonymous namespace 27 28 struct ValueHolder { 29 // Deliberately not explicit. 30 ValueHolder(int v) : value(v) { } // NOLINT 31 int value; 32 }; 33 34 ATTRIBUTE_UNUSED bool operator==(const ValueHolder& lhs, const ValueHolder& rhs) { 35 return lhs.value == rhs.value; 36 } 37 38 } // anonymous namespace 39 40 TEST(TransformArrayRef, ConstRefAdd1) { 41 auto add1 = [](const ValueHolder& h) { return h.value + 1; }; 42 std::vector<ValueHolder> input({ 7, 6, 4, 0 }); 43 std::vector<int> output; 44 45 auto taref = MakeTransformArrayRef(input, add1); 46 using TarefIter = decltype(taref)::iterator; 47 using ConstTarefIter = decltype(taref)::const_iterator; 48 static_assert(std::is_same<int, decltype(taref)::value_type>::value, "value_type"); 49 static_assert(std::is_same<TarefIter, decltype(taref)::pointer>::value, "pointer"); 50 static_assert(std::is_same<int, decltype(taref)::reference>::value, "reference"); 51 static_assert(std::is_same<ConstTarefIter, decltype(taref)::const_pointer>::value, 52 "const_pointer"); 53 static_assert(std::is_same<int, decltype(taref)::const_reference>::value, "const_reference"); 54 55 std::copy(taref.begin(), taref.end(), std::back_inserter(output)); 56 ASSERT_EQ(std::vector<int>({ 8, 7, 5, 1 }), output); 57 output.clear(); 58 59 std::copy(taref.cbegin(), taref.cend(), std::back_inserter(output)); 60 ASSERT_EQ(std::vector<int>({ 8, 7, 5, 1 }), output); 61 output.clear(); 62 63 std::copy(taref.rbegin(), taref.rend(), std::back_inserter(output)); 64 ASSERT_EQ(std::vector<int>({ 1, 5, 7, 8 }), output); 65 output.clear(); 66 67 std::copy(taref.crbegin(), taref.crend(), std::back_inserter(output)); 68 ASSERT_EQ(std::vector<int>({ 1, 5, 7, 8 }), output); 69 output.clear(); 70 71 ASSERT_EQ(input.size(), taref.size()); 72 ASSERT_EQ(input.empty(), taref.empty()); 73 ASSERT_EQ(input.front().value + 1, taref.front()); 74 ASSERT_EQ(input.back().value + 1, taref.back()); 75 76 for (size_t i = 0; i != input.size(); ++i) { 77 ASSERT_EQ(input[i].value + 1, taref[i]); 78 } 79 } 80 81 TEST(TransformArrayRef, NonConstRefSub1) { 82 auto sub1 = [](ValueHolder& h) { return h.value - 1; }; 83 std::vector<ValueHolder> input({ 4, 4, 5, 7, 10 }); 84 std::vector<int> output; 85 86 auto taref = MakeTransformArrayRef(input, sub1); 87 using TarefIter = decltype(taref)::iterator; 88 static_assert(std::is_same<void, decltype(taref)::const_iterator>::value, "const_iterator"); 89 static_assert(std::is_same<int, decltype(taref)::value_type>::value, "value_type"); 90 static_assert(std::is_same<TarefIter, decltype(taref)::pointer>::value, "pointer"); 91 static_assert(std::is_same<int, decltype(taref)::reference>::value, "reference"); 92 static_assert(std::is_same<void, decltype(taref)::const_pointer>::value, "const_pointer"); 93 static_assert(std::is_same<void, decltype(taref)::const_reference>::value, "const_reference"); 94 95 std::copy(taref.begin(), taref.end(), std::back_inserter(output)); 96 ASSERT_EQ(std::vector<int>({ 3, 3, 4, 6, 9 }), output); 97 output.clear(); 98 99 std::copy(taref.rbegin(), taref.rend(), std::back_inserter(output)); 100 ASSERT_EQ(std::vector<int>({ 9, 6, 4, 3, 3 }), output); 101 output.clear(); 102 103 ASSERT_EQ(input.size(), taref.size()); 104 ASSERT_EQ(input.empty(), taref.empty()); 105 ASSERT_EQ(input.front().value - 1, taref.front()); 106 ASSERT_EQ(input.back().value - 1, taref.back()); 107 108 for (size_t i = 0; i != input.size(); ++i) { 109 ASSERT_EQ(input[i].value - 1, taref[i]); 110 } 111 } 112 113 TEST(TransformArrayRef, ConstAndNonConstRef) { 114 struct Ref { 115 int& operator()(ValueHolder& h) const { return h.value; } 116 const int& operator()(const ValueHolder& h) const { return h.value; } 117 }; 118 Ref ref; 119 std::vector<ValueHolder> input({ 1, 0, 1, 0, 3, 1 }); 120 std::vector<int> output; 121 122 auto taref = MakeTransformArrayRef(input, ref); 123 static_assert(std::is_same<int, decltype(taref)::value_type>::value, "value_type"); 124 static_assert(std::is_same<int*, decltype(taref)::pointer>::value, "pointer"); 125 static_assert(std::is_same<int&, decltype(taref)::reference>::value, "reference"); 126 static_assert(std::is_same<const int*, decltype(taref)::const_pointer>::value, "const_pointer"); 127 static_assert(std::is_same<const int&, decltype(taref)::const_reference>::value, 128 "const_reference"); 129 130 std::copy(taref.begin(), taref.end(), std::back_inserter(output)); 131 ASSERT_EQ(std::vector<int>({ 1, 0, 1, 0, 3, 1 }), output); 132 output.clear(); 133 134 std::copy(taref.cbegin(), taref.cend(), std::back_inserter(output)); 135 ASSERT_EQ(std::vector<int>({ 1, 0, 1, 0, 3, 1 }), output); 136 output.clear(); 137 138 std::copy(taref.rbegin(), taref.rend(), std::back_inserter(output)); 139 ASSERT_EQ(std::vector<int>({ 1, 3, 0, 1, 0, 1 }), output); 140 output.clear(); 141 142 std::copy(taref.crbegin(), taref.crend(), std::back_inserter(output)); 143 ASSERT_EQ(std::vector<int>({ 1, 3, 0, 1, 0, 1 }), output); 144 output.clear(); 145 146 ASSERT_EQ(input.size(), taref.size()); 147 ASSERT_EQ(input.empty(), taref.empty()); 148 ASSERT_EQ(input.front().value, taref.front()); 149 ASSERT_EQ(input.back().value, taref.back()); 150 151 for (size_t i = 0; i != input.size(); ++i) { 152 ASSERT_EQ(input[i].value, taref[i]); 153 } 154 155 // Test writing through the transform iterator. 156 std::vector<int> transform_input({ 24, 37, 11, 71 }); 157 std::vector<ValueHolder> transformed(transform_input.size(), 0); 158 taref = MakeTransformArrayRef(transformed, ref); 159 for (size_t i = 0; i != transform_input.size(); ++i) { 160 taref[i] = transform_input[i]; 161 } 162 ASSERT_EQ(std::vector<ValueHolder>({ 24, 37, 11, 71 }), transformed); 163 164 const std::vector<ValueHolder>& cinput = input; 165 166 auto ctaref = MakeTransformArrayRef(cinput, ref); 167 static_assert(std::is_same<int, decltype(ctaref)::value_type>::value, "value_type"); 168 static_assert(std::is_same<const int*, decltype(ctaref)::pointer>::value, "pointer"); 169 static_assert(std::is_same<const int&, decltype(ctaref)::reference>::value, "reference"); 170 static_assert(std::is_same<const int*, decltype(ctaref)::const_pointer>::value, "const_pointer"); 171 static_assert(std::is_same<const int&, decltype(ctaref)::const_reference>::value, 172 "const_reference"); 173 174 std::copy(ctaref.begin(), ctaref.end(), std::back_inserter(output)); 175 ASSERT_EQ(std::vector<int>({ 1, 0, 1, 0, 3, 1 }), output); 176 output.clear(); 177 178 std::copy(ctaref.cbegin(), ctaref.cend(), std::back_inserter(output)); 179 ASSERT_EQ(std::vector<int>({ 1, 0, 1, 0, 3, 1 }), output); 180 output.clear(); 181 182 std::copy(ctaref.rbegin(), ctaref.rend(), std::back_inserter(output)); 183 ASSERT_EQ(std::vector<int>({ 1, 3, 0, 1, 0, 1 }), output); 184 output.clear(); 185 186 std::copy(ctaref.crbegin(), ctaref.crend(), std::back_inserter(output)); 187 ASSERT_EQ(std::vector<int>({ 1, 3, 0, 1, 0, 1 }), output); 188 output.clear(); 189 190 ASSERT_EQ(cinput.size(), ctaref.size()); 191 ASSERT_EQ(cinput.empty(), ctaref.empty()); 192 ASSERT_EQ(cinput.front().value, ctaref.front()); 193 ASSERT_EQ(cinput.back().value, ctaref.back()); 194 195 for (size_t i = 0; i != cinput.size(); ++i) { 196 ASSERT_EQ(cinput[i].value, ctaref[i]); 197 } 198 199 // Test conversion adding const. 200 decltype(ctaref) ctaref2 = taref; 201 ASSERT_EQ(taref.size(), ctaref2.size()); 202 for (size_t i = 0; i != taref.size(); ++i) { 203 ASSERT_EQ(taref[i], ctaref2[i]); 204 } 205 } 206 207 } // namespace art 208