1fd4e5da5Sopenharmony_ci// Copyright (c) 2016 Google Inc.
2fd4e5da5Sopenharmony_ci//
3fd4e5da5Sopenharmony_ci// Licensed under the Apache License, Version 2.0 (the "License");
4fd4e5da5Sopenharmony_ci// you may not use this file except in compliance with the License.
5fd4e5da5Sopenharmony_ci// You may obtain a copy of the License at
6fd4e5da5Sopenharmony_ci//
7fd4e5da5Sopenharmony_ci//     http://www.apache.org/licenses/LICENSE-2.0
8fd4e5da5Sopenharmony_ci//
9fd4e5da5Sopenharmony_ci// Unless required by applicable law or agreed to in writing, software
10fd4e5da5Sopenharmony_ci// distributed under the License is distributed on an "AS IS" BASIS,
11fd4e5da5Sopenharmony_ci// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12fd4e5da5Sopenharmony_ci// See the License for the specific language governing permissions and
13fd4e5da5Sopenharmony_ci// limitations under the License.
14fd4e5da5Sopenharmony_ci
15fd4e5da5Sopenharmony_ci#include <memory>
16fd4e5da5Sopenharmony_ci#include <vector>
17fd4e5da5Sopenharmony_ci
18fd4e5da5Sopenharmony_ci#include "gmock/gmock.h"
19fd4e5da5Sopenharmony_ci
20fd4e5da5Sopenharmony_ci#include "source/opt/iterator.h"
21fd4e5da5Sopenharmony_ci#include "source/util/make_unique.h"
22fd4e5da5Sopenharmony_ci
23fd4e5da5Sopenharmony_cinamespace spvtools {
24fd4e5da5Sopenharmony_cinamespace opt {
25fd4e5da5Sopenharmony_cinamespace {
26fd4e5da5Sopenharmony_ci
27fd4e5da5Sopenharmony_ciusing ::testing::ContainerEq;
28fd4e5da5Sopenharmony_ci
29fd4e5da5Sopenharmony_ciTEST(Iterator, IncrementDeref) {
30fd4e5da5Sopenharmony_ci  const int count = 100;
31fd4e5da5Sopenharmony_ci  std::vector<std::unique_ptr<int>> data;
32fd4e5da5Sopenharmony_ci  for (int i = 0; i < count; ++i) {
33fd4e5da5Sopenharmony_ci    data.emplace_back(new int(i));
34fd4e5da5Sopenharmony_ci  }
35fd4e5da5Sopenharmony_ci
36fd4e5da5Sopenharmony_ci  UptrVectorIterator<int> it(&data, data.begin());
37fd4e5da5Sopenharmony_ci  UptrVectorIterator<int> end(&data, data.end());
38fd4e5da5Sopenharmony_ci
39fd4e5da5Sopenharmony_ci  EXPECT_EQ(*data[0], *it);
40fd4e5da5Sopenharmony_ci  for (int i = 1; i < count; ++i) {
41fd4e5da5Sopenharmony_ci    EXPECT_NE(end, it);
42fd4e5da5Sopenharmony_ci    EXPECT_EQ(*data[i], *(++it));
43fd4e5da5Sopenharmony_ci  }
44fd4e5da5Sopenharmony_ci  EXPECT_EQ(end, ++it);
45fd4e5da5Sopenharmony_ci}
46fd4e5da5Sopenharmony_ci
47fd4e5da5Sopenharmony_ciTEST(Iterator, DecrementDeref) {
48fd4e5da5Sopenharmony_ci  const int count = 100;
49fd4e5da5Sopenharmony_ci  std::vector<std::unique_ptr<int>> data;
50fd4e5da5Sopenharmony_ci  for (int i = 0; i < count; ++i) {
51fd4e5da5Sopenharmony_ci    data.emplace_back(new int(i));
52fd4e5da5Sopenharmony_ci  }
53fd4e5da5Sopenharmony_ci
54fd4e5da5Sopenharmony_ci  UptrVectorIterator<int> begin(&data, data.begin());
55fd4e5da5Sopenharmony_ci  UptrVectorIterator<int> it(&data, data.end());
56fd4e5da5Sopenharmony_ci
57fd4e5da5Sopenharmony_ci  for (int i = count - 1; i >= 0; --i) {
58fd4e5da5Sopenharmony_ci    EXPECT_NE(begin, it);
59fd4e5da5Sopenharmony_ci    EXPECT_EQ(*data[i], *(--it));
60fd4e5da5Sopenharmony_ci  }
61fd4e5da5Sopenharmony_ci  EXPECT_EQ(begin, it);
62fd4e5da5Sopenharmony_ci}
63fd4e5da5Sopenharmony_ci
64fd4e5da5Sopenharmony_ciTEST(Iterator, PostIncrementDeref) {
65fd4e5da5Sopenharmony_ci  const int count = 100;
66fd4e5da5Sopenharmony_ci  std::vector<std::unique_ptr<int>> data;
67fd4e5da5Sopenharmony_ci  for (int i = 0; i < count; ++i) {
68fd4e5da5Sopenharmony_ci    data.emplace_back(new int(i));
69fd4e5da5Sopenharmony_ci  }
70fd4e5da5Sopenharmony_ci
71fd4e5da5Sopenharmony_ci  UptrVectorIterator<int> it(&data, data.begin());
72fd4e5da5Sopenharmony_ci  UptrVectorIterator<int> end(&data, data.end());
73fd4e5da5Sopenharmony_ci
74fd4e5da5Sopenharmony_ci  for (int i = 0; i < count; ++i) {
75fd4e5da5Sopenharmony_ci    EXPECT_NE(end, it);
76fd4e5da5Sopenharmony_ci    EXPECT_EQ(*data[i], *(it++));
77fd4e5da5Sopenharmony_ci  }
78fd4e5da5Sopenharmony_ci  EXPECT_EQ(end, it);
79fd4e5da5Sopenharmony_ci}
80fd4e5da5Sopenharmony_ci
81fd4e5da5Sopenharmony_ciTEST(Iterator, PostDecrementDeref) {
82fd4e5da5Sopenharmony_ci  const int count = 100;
83fd4e5da5Sopenharmony_ci  std::vector<std::unique_ptr<int>> data;
84fd4e5da5Sopenharmony_ci  for (int i = 0; i < count; ++i) {
85fd4e5da5Sopenharmony_ci    data.emplace_back(new int(i));
86fd4e5da5Sopenharmony_ci  }
87fd4e5da5Sopenharmony_ci
88fd4e5da5Sopenharmony_ci  UptrVectorIterator<int> begin(&data, data.begin());
89fd4e5da5Sopenharmony_ci  UptrVectorIterator<int> end(&data, data.end());
90fd4e5da5Sopenharmony_ci  UptrVectorIterator<int> it(&data, data.end());
91fd4e5da5Sopenharmony_ci
92fd4e5da5Sopenharmony_ci  EXPECT_EQ(end, it--);
93fd4e5da5Sopenharmony_ci  for (int i = count - 1; i >= 1; --i) {
94fd4e5da5Sopenharmony_ci    EXPECT_EQ(*data[i], *(it--));
95fd4e5da5Sopenharmony_ci  }
96fd4e5da5Sopenharmony_ci  // Decrementing .begin() is undefined behavior.
97fd4e5da5Sopenharmony_ci  EXPECT_EQ(*data[0], *it);
98fd4e5da5Sopenharmony_ci}
99fd4e5da5Sopenharmony_ci
100fd4e5da5Sopenharmony_ciTEST(Iterator, Access) {
101fd4e5da5Sopenharmony_ci  const int count = 100;
102fd4e5da5Sopenharmony_ci  std::vector<std::unique_ptr<int>> data;
103fd4e5da5Sopenharmony_ci  for (int i = 0; i < count; ++i) {
104fd4e5da5Sopenharmony_ci    data.emplace_back(new int(i));
105fd4e5da5Sopenharmony_ci  }
106fd4e5da5Sopenharmony_ci
107fd4e5da5Sopenharmony_ci  UptrVectorIterator<int> it(&data, data.begin());
108fd4e5da5Sopenharmony_ci
109fd4e5da5Sopenharmony_ci  for (int i = 0; i < count; ++i) EXPECT_EQ(*data[i], it[i]);
110fd4e5da5Sopenharmony_ci}
111fd4e5da5Sopenharmony_ci
112fd4e5da5Sopenharmony_ciTEST(Iterator, Comparison) {
113fd4e5da5Sopenharmony_ci  const int count = 100;
114fd4e5da5Sopenharmony_ci  std::vector<std::unique_ptr<int>> data;
115fd4e5da5Sopenharmony_ci  for (int i = 0; i < count; ++i) {
116fd4e5da5Sopenharmony_ci    data.emplace_back(new int(i));
117fd4e5da5Sopenharmony_ci  }
118fd4e5da5Sopenharmony_ci
119fd4e5da5Sopenharmony_ci  UptrVectorIterator<int> it(&data, data.begin());
120fd4e5da5Sopenharmony_ci  UptrVectorIterator<int> end(&data, data.end());
121fd4e5da5Sopenharmony_ci
122fd4e5da5Sopenharmony_ci  for (int i = 0; i < count; ++i, ++it) EXPECT_TRUE(it < end);
123fd4e5da5Sopenharmony_ci  EXPECT_EQ(end, it);
124fd4e5da5Sopenharmony_ci}
125fd4e5da5Sopenharmony_ci
126fd4e5da5Sopenharmony_ciTEST(Iterator, InsertBeginEnd) {
127fd4e5da5Sopenharmony_ci  const int count = 100;
128fd4e5da5Sopenharmony_ci
129fd4e5da5Sopenharmony_ci  std::vector<std::unique_ptr<int>> data;
130fd4e5da5Sopenharmony_ci  std::vector<int> expected;
131fd4e5da5Sopenharmony_ci  std::vector<int> actual;
132fd4e5da5Sopenharmony_ci
133fd4e5da5Sopenharmony_ci  for (int i = 0; i < count; ++i) {
134fd4e5da5Sopenharmony_ci    data.emplace_back(new int(i));
135fd4e5da5Sopenharmony_ci    expected.push_back(i);
136fd4e5da5Sopenharmony_ci  }
137fd4e5da5Sopenharmony_ci
138fd4e5da5Sopenharmony_ci  // Insert at the beginning
139fd4e5da5Sopenharmony_ci  expected.insert(expected.begin(), -100);
140fd4e5da5Sopenharmony_ci  UptrVectorIterator<int> begin(&data, data.begin());
141fd4e5da5Sopenharmony_ci  auto insert_point = begin.InsertBefore(MakeUnique<int>(-100));
142fd4e5da5Sopenharmony_ci  for (int i = 0; i < count + 1; ++i) {
143fd4e5da5Sopenharmony_ci    actual.push_back(*(insert_point++));
144fd4e5da5Sopenharmony_ci  }
145fd4e5da5Sopenharmony_ci  EXPECT_THAT(actual, ContainerEq(expected));
146fd4e5da5Sopenharmony_ci
147fd4e5da5Sopenharmony_ci  // Insert at the end
148fd4e5da5Sopenharmony_ci  expected.push_back(-42);
149fd4e5da5Sopenharmony_ci  expected.push_back(-36);
150fd4e5da5Sopenharmony_ci  expected.push_back(-77);
151fd4e5da5Sopenharmony_ci  UptrVectorIterator<int> end(&data, data.end());
152fd4e5da5Sopenharmony_ci  end = end.InsertBefore(MakeUnique<int>(-77));
153fd4e5da5Sopenharmony_ci  end = end.InsertBefore(MakeUnique<int>(-36));
154fd4e5da5Sopenharmony_ci  end = end.InsertBefore(MakeUnique<int>(-42));
155fd4e5da5Sopenharmony_ci
156fd4e5da5Sopenharmony_ci  actual.clear();
157fd4e5da5Sopenharmony_ci  begin = UptrVectorIterator<int>(&data, data.begin());
158fd4e5da5Sopenharmony_ci  for (int i = 0; i < count + 4; ++i) {
159fd4e5da5Sopenharmony_ci    actual.push_back(*(begin++));
160fd4e5da5Sopenharmony_ci  }
161fd4e5da5Sopenharmony_ci  EXPECT_THAT(actual, ContainerEq(expected));
162fd4e5da5Sopenharmony_ci}
163fd4e5da5Sopenharmony_ci
164fd4e5da5Sopenharmony_ciTEST(Iterator, InsertMiddle) {
165fd4e5da5Sopenharmony_ci  const int count = 100;
166fd4e5da5Sopenharmony_ci
167fd4e5da5Sopenharmony_ci  std::vector<std::unique_ptr<int>> data;
168fd4e5da5Sopenharmony_ci  std::vector<int> expected;
169fd4e5da5Sopenharmony_ci  std::vector<int> actual;
170fd4e5da5Sopenharmony_ci
171fd4e5da5Sopenharmony_ci  for (int i = 0; i < count; ++i) {
172fd4e5da5Sopenharmony_ci    data.emplace_back(new int(i));
173fd4e5da5Sopenharmony_ci    expected.push_back(i);
174fd4e5da5Sopenharmony_ci  }
175fd4e5da5Sopenharmony_ci
176fd4e5da5Sopenharmony_ci  const int insert_pos = 42;
177fd4e5da5Sopenharmony_ci  expected.insert(expected.begin() + insert_pos, -100);
178fd4e5da5Sopenharmony_ci  expected.insert(expected.begin() + insert_pos, -42);
179fd4e5da5Sopenharmony_ci
180fd4e5da5Sopenharmony_ci  UptrVectorIterator<int> it(&data, data.begin());
181fd4e5da5Sopenharmony_ci  for (int i = 0; i < insert_pos; ++i) ++it;
182fd4e5da5Sopenharmony_ci  it = it.InsertBefore(MakeUnique<int>(-100));
183fd4e5da5Sopenharmony_ci  it = it.InsertBefore(MakeUnique<int>(-42));
184fd4e5da5Sopenharmony_ci  auto begin = UptrVectorIterator<int>(&data, data.begin());
185fd4e5da5Sopenharmony_ci  for (int i = 0; i < count + 2; ++i) {
186fd4e5da5Sopenharmony_ci    actual.push_back(*(begin++));
187fd4e5da5Sopenharmony_ci  }
188fd4e5da5Sopenharmony_ci  EXPECT_THAT(actual, ContainerEq(expected));
189fd4e5da5Sopenharmony_ci}
190fd4e5da5Sopenharmony_ci
191fd4e5da5Sopenharmony_ciTEST(IteratorRange, Interface) {
192fd4e5da5Sopenharmony_ci  const uint32_t count = 100;
193fd4e5da5Sopenharmony_ci
194fd4e5da5Sopenharmony_ci  std::vector<std::unique_ptr<uint32_t>> data;
195fd4e5da5Sopenharmony_ci
196fd4e5da5Sopenharmony_ci  for (uint32_t i = 0; i < count; ++i) {
197fd4e5da5Sopenharmony_ci    data.emplace_back(new uint32_t(i));
198fd4e5da5Sopenharmony_ci  }
199fd4e5da5Sopenharmony_ci
200fd4e5da5Sopenharmony_ci  auto b = UptrVectorIterator<uint32_t>(&data, data.begin());
201fd4e5da5Sopenharmony_ci  auto e = UptrVectorIterator<uint32_t>(&data, data.end());
202fd4e5da5Sopenharmony_ci  auto range = IteratorRange<decltype(b)>(b, e);
203fd4e5da5Sopenharmony_ci
204fd4e5da5Sopenharmony_ci  EXPECT_EQ(b, range.begin());
205fd4e5da5Sopenharmony_ci  EXPECT_EQ(e, range.end());
206fd4e5da5Sopenharmony_ci  EXPECT_FALSE(range.empty());
207fd4e5da5Sopenharmony_ci  EXPECT_EQ(count, range.size());
208fd4e5da5Sopenharmony_ci  EXPECT_EQ(0u, *range.begin());
209fd4e5da5Sopenharmony_ci  EXPECT_EQ(99u, *(--range.end()));
210fd4e5da5Sopenharmony_ci
211fd4e5da5Sopenharmony_ci  // IteratorRange itself is immutable.
212fd4e5da5Sopenharmony_ci  ++b, --e;
213fd4e5da5Sopenharmony_ci  EXPECT_EQ(count, range.size());
214fd4e5da5Sopenharmony_ci  ++range.begin(), --range.end();
215fd4e5da5Sopenharmony_ci  EXPECT_EQ(count, range.size());
216fd4e5da5Sopenharmony_ci}
217fd4e5da5Sopenharmony_ci
218fd4e5da5Sopenharmony_ciTEST(Iterator, FilterIterator) {
219fd4e5da5Sopenharmony_ci  struct Placeholder {
220fd4e5da5Sopenharmony_ci    int val;
221fd4e5da5Sopenharmony_ci  };
222fd4e5da5Sopenharmony_ci  std::vector<Placeholder> data = {{1}, {2}, {3}, {4}, {5},
223fd4e5da5Sopenharmony_ci                                   {6}, {7}, {8}, {9}, {10}};
224fd4e5da5Sopenharmony_ci
225fd4e5da5Sopenharmony_ci  // Predicate to only consider odd values.
226fd4e5da5Sopenharmony_ci  struct Predicate {
227fd4e5da5Sopenharmony_ci    bool operator()(const Placeholder& data) { return data.val % 2; }
228fd4e5da5Sopenharmony_ci  };
229fd4e5da5Sopenharmony_ci  Predicate pred;
230fd4e5da5Sopenharmony_ci
231fd4e5da5Sopenharmony_ci  auto filter_range = MakeFilterIteratorRange(data.begin(), data.end(), pred);
232fd4e5da5Sopenharmony_ci
233fd4e5da5Sopenharmony_ci  EXPECT_EQ(filter_range.begin().Get(), data.begin());
234fd4e5da5Sopenharmony_ci  EXPECT_EQ(filter_range.end(), filter_range.begin().GetEnd());
235fd4e5da5Sopenharmony_ci
236fd4e5da5Sopenharmony_ci  for (Placeholder& data : filter_range) {
237fd4e5da5Sopenharmony_ci    EXPECT_EQ(data.val % 2, 1);
238fd4e5da5Sopenharmony_ci  }
239fd4e5da5Sopenharmony_ci
240fd4e5da5Sopenharmony_ci  for (auto it = filter_range.begin(); it != filter_range.end(); it++) {
241fd4e5da5Sopenharmony_ci    EXPECT_EQ(it->val % 2, 1);
242fd4e5da5Sopenharmony_ci    EXPECT_EQ((*it).val % 2, 1);
243fd4e5da5Sopenharmony_ci  }
244fd4e5da5Sopenharmony_ci
245fd4e5da5Sopenharmony_ci  for (auto it = filter_range.begin(); it != filter_range.end(); ++it) {
246fd4e5da5Sopenharmony_ci    EXPECT_EQ(it->val % 2, 1);
247fd4e5da5Sopenharmony_ci    EXPECT_EQ((*it).val % 2, 1);
248fd4e5da5Sopenharmony_ci  }
249fd4e5da5Sopenharmony_ci
250fd4e5da5Sopenharmony_ci  EXPECT_EQ(MakeFilterIterator(data.begin(), data.end(), pred).Get(),
251fd4e5da5Sopenharmony_ci            data.begin());
252fd4e5da5Sopenharmony_ci  EXPECT_EQ(MakeFilterIterator(data.end(), data.end(), pred).Get(), data.end());
253fd4e5da5Sopenharmony_ci  EXPECT_EQ(MakeFilterIterator(data.begin(), data.end(), pred).GetEnd(),
254fd4e5da5Sopenharmony_ci            MakeFilterIterator(data.end(), data.end(), pred));
255fd4e5da5Sopenharmony_ci  EXPECT_NE(MakeFilterIterator(data.begin(), data.end(), pred),
256fd4e5da5Sopenharmony_ci            MakeFilterIterator(data.end(), data.end(), pred));
257fd4e5da5Sopenharmony_ci
258fd4e5da5Sopenharmony_ci  // Empty range: no values satisfies the predicate.
259fd4e5da5Sopenharmony_ci  auto empty_range = MakeFilterIteratorRange(
260fd4e5da5Sopenharmony_ci      data.begin(), data.end(),
261fd4e5da5Sopenharmony_ci      [](const Placeholder& data) { return data.val > 10; });
262fd4e5da5Sopenharmony_ci  EXPECT_EQ(empty_range.begin(), empty_range.end());
263fd4e5da5Sopenharmony_ci}
264fd4e5da5Sopenharmony_ci
265fd4e5da5Sopenharmony_ci}  // namespace
266fd4e5da5Sopenharmony_ci}  // namespace opt
267fd4e5da5Sopenharmony_ci}  // namespace spvtools
268