openMSX
view_test.cc
Go to the documentation of this file.
1#include "catch.hpp"
2#include "view.hh"
3
4#include "hash_map.hh"
5#include "ranges.hh"
6#include "stl.hh"
7#include "xrange.hh"
8#include "StringOp.hh"
9
10#include <algorithm>
11#include <list>
12#include <map>
13#include <string>
14#include <tuple>
15#include <vector>
16
17using std::vector;
18using namespace view;
19
20static vector<int> getVector(int n)
21{
22 return to_vector(xrange(n));
23}
24
25TEST_CASE("view::drop random-access-range")
26{
27 SECTION("empty") {
28 vector<int> v;
29 CHECK(to_vector(drop(v, 0)) == vector<int>{});
30 CHECK(to_vector(drop(v, 3)) == vector<int>{});
31 }
32 SECTION("non-empty") {
33 vector<int> v = {1, 2, 3, 4, 5};
34 CHECK(to_vector(drop(v, 0)) == vector<int>{1, 2, 3, 4, 5});
35 CHECK(to_vector(drop(v, 1)) == vector<int>{2, 3, 4, 5});
36 CHECK(to_vector(drop(v, 2)) == vector<int>{3, 4, 5});
37 CHECK(to_vector(drop(v, 3)) == vector<int>{4, 5});
38 CHECK(to_vector(drop(v, 4)) == vector<int>{5});
39 CHECK(to_vector(drop(v, 5)) == vector<int>{});
40 CHECK(to_vector(drop(v, 6)) == vector<int>{});
41 CHECK(to_vector(drop(v, 7)) == vector<int>{});
42 }
43 SECTION("r-value") {
44 CHECK(to_vector(drop(getVector(6), 3)) == vector<int>{3, 4, 5});
45 }
46}
47
48TEST_CASE("view::drop non-random-access-range")
49{
50 SECTION("empty") {
51 std::list<int> l;
52 CHECK(to_vector(drop(l, 0)) == vector<int>{});
53 CHECK(to_vector(drop(l, 3)) == vector<int>{});
54 }
55 SECTION("non-empty") {
56 std::list<int> l = {1, 2, 3, 4, 5};
57 CHECK(to_vector(drop(l, 0)) == vector<int>{1, 2, 3, 4, 5});
58 CHECK(to_vector(drop(l, 1)) == vector<int>{2, 3, 4, 5});
59 CHECK(to_vector(drop(l, 2)) == vector<int>{3, 4, 5});
60 CHECK(to_vector(drop(l, 3)) == vector<int>{4, 5});
61 CHECK(to_vector(drop(l, 4)) == vector<int>{5});
62 CHECK(to_vector(drop(l, 5)) == vector<int>{});
63 CHECK(to_vector(drop(l, 6)) == vector<int>{});
64 CHECK(to_vector(drop(l, 7)) == vector<int>{});
65 }
66}
67
68TEST_CASE("view::drop capture")
69{
70 REQUIRE(sizeof(vector<int>*) != sizeof(vector<int>));
71 SECTION("l-value") {
72 vector<int> v = {0, 1, 2, 3};
73 auto d = drop(v, 1);
74 // 'd' stores a reference to 'v'
75 CHECK(sizeof(d) == (sizeof(vector<int>*) + sizeof(size_t)));
76 }
77 SECTION("r-value") {
78 auto d = drop(getVector(4), 1);
79 // 'd' stores a vector by value
80 CHECK(sizeof(d) == (sizeof(vector<int>) + sizeof(size_t)));
81 }
82}
83
84
85TEST_CASE("view::drop_back random-access-range")
86{
87 SECTION("empty") {
88 vector<int> v;
89 CHECK(to_vector(drop_back(v, 0)) == vector<int>{});
90 CHECK(to_vector(drop_back(v, 3)) == vector<int>{});
91 }
92 SECTION("non-empty") {
93 vector<int> v = {1, 2, 3, 4, 5};
94 CHECK(to_vector(drop_back(v, 0)) == vector<int>{1, 2, 3, 4, 5});
95 CHECK(to_vector(drop_back(v, 1)) == vector<int>{1, 2, 3, 4});
96 CHECK(to_vector(drop_back(v, 2)) == vector<int>{1, 2, 3});
97 CHECK(to_vector(drop_back(v, 3)) == vector<int>{1, 2});
98 CHECK(to_vector(drop_back(v, 4)) == vector<int>{1});
99 CHECK(to_vector(drop_back(v, 5)) == vector<int>{});
100 CHECK(to_vector(drop_back(v, 6)) == vector<int>{});
101 CHECK(to_vector(drop_back(v, 7)) == vector<int>{});
102 }
103 SECTION("r-value") {
104 CHECK(to_vector(drop_back(getVector(6), 3)) == vector<int>{0, 1, 2});
105 }
106}
107
108TEST_CASE("view::drop_back non-random-access-range")
109{
110 SECTION("empty") {
111 std::list<int> l;
112 CHECK(to_vector(drop_back(l, 0)) == vector<int>{});
113 CHECK(to_vector(drop_back(l, 3)) == vector<int>{});
114 }
115 SECTION("non-empty") {
116 std::list<int> l = {1, 2, 3, 4, 5};
117 CHECK(to_vector(drop_back(l, 0)) == vector<int>{1, 2, 3, 4, 5});
118 CHECK(to_vector(drop_back(l, 1)) == vector<int>{1, 2, 3, 4});
119 CHECK(to_vector(drop_back(l, 2)) == vector<int>{1, 2, 3});
120 CHECK(to_vector(drop_back(l, 3)) == vector<int>{1, 2});
121 CHECK(to_vector(drop_back(l, 4)) == vector<int>{1});
122 CHECK(to_vector(drop_back(l, 5)) == vector<int>{});
123 CHECK(to_vector(drop_back(l, 6)) == vector<int>{});
124 CHECK(to_vector(drop_back(l, 7)) == vector<int>{});
125 }
126}
127
128
129TEST_CASE("view::reverse")
130{
131 vector<int> out;
132 SECTION("l-value") {
133 vector<int> in = {1, 2, 3, 4};
134 for (auto& e : reverse(in)) out.push_back(e);
135 CHECK(out == vector<int>{4, 3, 2, 1});
136 }
137 SECTION("r-value") {
138 for (auto& e : reverse(getVector(3))) out.push_back(e);
139 CHECK(out == vector<int>{2, 1, 0});
140 }
141 SECTION("2 x reverse") {
142 for (auto& e : reverse(reverse(getVector(4)))) out.push_back(e);
143 CHECK(out == vector<int>{0, 1, 2, 3});
144 }
145}
146
147TEST_CASE("view::transform")
148{
149 auto square = [](auto& x) { return x * x; };
150 size_t i = 1;
151 auto plus_i = [&](auto& x) { return int(x + i); };
152
153 SECTION("l-value") {
154 vector<int> v = {1, 2, 3, 4};
155 CHECK(to_vector(transform(v, square)) == vector<int>{1, 4, 9, 16});
156 }
157 SECTION("r-value") {
158 i = 10;
159 CHECK(to_vector(transform(getVector(4), plus_i)) == vector<int>{10, 11, 12, 13});
160 }
161}
162
163/*
164No longer true since we use semiregular_t<> in TransformIterator
165TEST_CASE("view::transform sizes")
166{
167 auto square = [](auto& x) { return x * x; };
168 size_t i = 1;
169 auto plus_i = [&](auto& x) { return int(x + i); };
170
171 vector<int> v = {1, 2, 3, 4};
172
173 SECTION("l-value, stateless") {
174 auto vw = transform(v, square);
175 CHECK(sizeof(vw) == sizeof(std::vector<int>*));
176 CHECK(sizeof(vw.begin()) == sizeof(std::vector<int>::iterator));
177 }
178 SECTION("l-value, state") {
179 auto vw = transform(v, plus_i);
180 CHECK(sizeof(vw) == (sizeof(size_t&) + sizeof(std::vector<int>*)));
181 CHECK(sizeof(vw.begin()) == (sizeof(size_t&) + sizeof(std::vector<int>::iterator)));
182 }
183 SECTION("r-value, stateless") {
184 auto vw = transform(getVector(3), square);
185 CHECK(sizeof(vw) == sizeof(std::vector<int>));
186 CHECK(sizeof(vw.begin()) == sizeof(std::vector<int>::iterator));
187 }
188 SECTION("r-value, state") {
189 auto vw = transform(getVector(3), plus_i);
190 CHECK(sizeof(vw) == (sizeof(size_t&) + sizeof(std::vector<int>)));
191 CHECK(sizeof(vw.begin()) == (sizeof(size_t&) + sizeof(std::vector<int>::iterator)));
192 }
193}*/
194
195template<typename RANGE, typename T>
196static void check(const RANGE& range, const vector<T>& expected)
197{
198 CHECK(ranges::equal(range, expected));
199}
200
201template<typename RANGE, typename T>
202static void check_unordered(const RANGE& range, const vector<T>& expected_)
203{
204 auto result = to_vector<T>(range);
205 auto expected = expected_;
206 ranges::sort(result);
207 ranges::sort(expected);
208 CHECK(result == expected);
209}
210
211TEST_CASE("view::keys, view::values") {
212 SECTION("std::map") {
213 std::map<int, int> m = {{1, 2}, {3, 4}, {5, 6}, {7, 8}};
214 check(keys (m), vector<int>{1, 3, 5, 7});
215 check(values(m), vector<int>{2, 4, 6, 8});
216 }
217 SECTION("std::vector<std::pair>") {
218 vector<std::pair<int, int>> v = {{1, 2}, {3, 4}, {5, 6}, {7, 8}};
219 check(keys (v), vector<int>{1, 3, 5, 7});
220 check(values(v), vector<int>{2, 4, 6, 8});
221 }
222 SECTION("hash_map") {
224 {{"foo", 1}, {"bar", 2}, {"qux", 3},
225 {"baz", 4}, {"a", 5}, {"z", 6}};
226 check_unordered(keys(m), vector<std::string>{
227 "foo", "bar", "qux", "baz", "a", "z"});
228 check_unordered(values(m), vector<int>{1, 2, 3, 4, 5, 6});
229 }
230 SECTION("std::vector<std::tuple>") {
231 vector<std::tuple<int, char, double, std::string>> v = {
232 std::tuple(1, 2, 1.2, "foo"),
233 std::tuple(3, 4, 3.4, "bar"),
234 std::tuple(5, 6, 5.6, "qux")
235 };
236 check(keys (v), vector<int>{1, 3, 5});
237 check(values(v), vector<char>{2, 4, 6});
238 }
239}
240
241struct F {
242 int i;
243 F(int i_) : i(i_) {}
244 operator int() const { return i; }
245 bool isOdd() const { return i & 1; }
246};
247
248TEST_CASE("view::filter") {
249 vector v = {1, 2, 3, 4, 5, 6, 7, 8, 9};
250
251 SECTION("removed front") {
252 check(view::filter(v, [](int i) { return i > 5; }),
253 vector{6, 7, 8, 9});
254 }
255 SECTION("removed back") {
256 check(view::filter(v, [](int i) { return i < 5; }),
257 vector{1, 2, 3, 4});
258 }
259 SECTION("keep front and back") {
260 check(view::filter(v, [](int i) { return i & 1; }),
261 vector{1, 3, 5, 7, 9});
262 }
263 SECTION("remove front and back") {
264 check(view::filter(v, [](int i) { return (i & 1) == 0; }),
265 vector{2, 4, 6, 8});
266 }
267
268 SECTION("projection") {
269 vector<F> f = {1, 2, 3, 4, 5};
270 auto view = view::filter(f, &F::isOdd);
271 auto it = view.begin();
272 auto et = view.end();
273 REQUIRE(it != et);
274 CHECK(*it == 1);
275 ++it;
276 REQUIRE(it != et);
277 CHECK(*it == 3);
278 it++;
279 REQUIRE(it != et);
280 CHECK(*it == 5);
281 ++it;
282 REQUIRE(it == et);
283 }
284}
285
286TEST_CASE("view::take") {
287 SECTION("n") {
288 vector v = {1, 2, 3, 4};
289 check(view::take(v, 0), vector<int>{});
290 check(view::take(v, 1), vector{1});
291 check(view::take(v, 2), vector{1, 2});
292 check(view::take(v, 3), vector{1, 2, 3});
293 check(view::take(v, 4), vector{1, 2, 3, 4});
294 check(view::take(v, 5), vector{1, 2, 3, 4});
295 check(view::take(v, 6), vector{1, 2, 3, 4});
296 }
297 SECTION("split_view") {
298 std::string_view str = "abc def\t \tghi jkl mno pqr";
299 auto v = view::take(StringOp::split_view<StringOp::REMOVE_EMPTY_PARTS>(str, " \t"), 3);
300
301 auto it = v.begin();
302 auto et = v.end();
303 REQUIRE(it != et);
304 CHECK(*it == "abc");
305
306 ++it;
307 REQUIRE(it != et);
308 CHECK(*it == "def");
309
310 ++it;
311 REQUIRE(it != et);
312 CHECK(*it == "ghi");
313
314 ++it;
315 REQUIRE(it == et);
316 }
317}
318
319template<typename In1, typename In2, typename Expected>
320void test_zip(const In1& in1, const In2& in2, const Expected& expected)
321{
322 Expected result;
323 for (const auto& t : view::zip(in1, in2)) {
324 result.push_back(t);
325 }
326 CHECK(result == expected);
327}
328
329template<typename In1, typename In2, typename In3, typename Expected>
330void test_zip(const In1& in1, const In2& in2, const In3& in3, const Expected& expected)
331{
332 Expected result;
333 for (const auto& t : view::zip(in1, in2, in3)) {
334 result.push_back(t);
335 }
336 CHECK(result == expected);
337}
338
339TEST_CASE("view::zip")
340{
341 std::vector v4 = {1, 2, 3, 4};
342 std::array a3 = {'a', 'b', 'c'};
343 std::list l4 = {1.2, 2.3, 3.4, 4.5};
344
345 test_zip(v4, a3, std::vector<std::tuple<int, char>>{{1, 'a'}, {2, 'b'}, {3, 'c'}});
346 test_zip(a3, v4, std::vector<std::tuple<char, int>>{{'a', 1}, {'b', 2}, {'c', 3}});
347
348 test_zip(v4, l4, std::vector<std::tuple<int, double>>{{1, 1.2}, {2, 2.3}, {3, 3.4}, {4, 4.5}});
349 test_zip(l4, v4, std::vector<std::tuple<double, int>>{{1.2, 1}, {2.3, 2}, {3.4, 3}, {4.5, 4}});
350
351 test_zip(a3, l4, std::vector<std::tuple<char, double>>{{'a', 1.2}, {'b', 2.3}, {'c', 3.4}});
352 test_zip(l4, a3, std::vector<std::tuple<double, char>>{{1.2, 'a'}, {2.3, 'b'}, {3.4, 'c'}});
353
354 test_zip(v4, a3, l4, std::vector<std::tuple<int, char, double>>{{1, 'a', 1.2}, {2, 'b', 2.3}, {3, 'c', 3.4}});
355
356 for (auto [x, y] : zip(v4, a3)) {
357 x = 0;
358 ++y;
359 }
360 CHECK(v4 == std::vector{0, 0, 0, 4});
361 CHECK(a3 == std::array{'b', 'c', 'd'});
362}
363
364template<typename In1, typename In2, typename Expected>
365void test_zip_equal(const In1& in1, const In2& in2, const Expected& expected)
366{
367 Expected result;
368 for (const auto& t : view::zip_equal(in1, in2)) {
369 result.push_back(t);
370 }
371 CHECK(result == expected);
372}
373
374template<typename In1, typename In2, typename In3, typename Expected>
375void test_zip_equal(const In1& in1, const In2& in2, const In3& in3, const Expected& expected)
376{
377 Expected result;
378 for (const auto& t : view::zip_equal(in1, in2, in3)) {
379 result.push_back(t);
380 }
381 CHECK(result == expected);
382}
383
384TEST_CASE("view::zip_equal")
385{
386 std::vector v = {1, 2, 3};
387 std::array a = {'a', 'b', 'c'};
388 std::list l = {1.2, 2.3, 3.4};
389
390 test_zip_equal(v, a, std::vector<std::tuple<int, char>>{{1, 'a'}, {2, 'b'}, {3, 'c'}});
391 test_zip_equal(v, l, std::vector<std::tuple<int, double>>{{1, 1.2}, {2, 2.3}, {3, 3.4}});
392 test_zip_equal(a, l, std::vector<std::tuple<char, double>>{{'a', 1.2}, {'b', 2.3}, {'c', 3.4}});
393
394 test_zip_equal(v, a, l, std::vector<std::tuple<int, char, double>>{{1, 'a', 1.2}, {2, 'b', 2.3}, {3, 'c', 3.4}});
395
396 for (auto [x, y, z] : zip_equal(v, l, a)) {
397 x = 0;
398 y *= 2.0;
399 z += 2;
400 }
401 CHECK(v == std::vector{0, 0, 0});
402 CHECK(a == std::array{'c', 'd', 'e'});
403 CHECK(l == std::list{2.4, 4.6, 6.8});
404}
TclObject t
CHECK(m3==m3)
imat4 l4(ivec4(1, 2, 3, 4), ivec4(3, 4, 5, 6), ivec4(5, 6, 7, 0), ivec4(7, 8, 9, 0))
vec4 v4(2, 1, -4, -3)
constexpr double e
Definition: Math.hh:21
bool equal(InputRange1 &&range1, InputRange2 &&range2, Pred pred={}, Proj1 proj1={}, Proj2 proj2={})
Definition: ranges.hh:368
auto transform(InputRange &&range, OutputIter out, UnaryOperation op)
Definition: ranges.hh:269
constexpr void sort(RandomAccessRange &&range)
Definition: ranges.hh:49
Zip< true, RangesTuple, Is... > zip(RangesTuple &&ranges, std::index_sequence< Is... >)
Definition: view.hh:487
Zip< false, RangesTuple, Is... > zip_equal(RangesTuple &&ranges, std::index_sequence< Is... >)
Definition: view.hh:492
Definition: view.hh:15
auto zip_equal(Ranges &&... ranges)
Definition: view.hh:559
auto filter(ForwardRange &&range, Predicate pred)
Definition: view.hh:538
constexpr auto take(ForwardRange &&range, size_t n)
Definition: view.hh:544
constexpr auto reverse(Range &&range)
Definition: view.hh:514
constexpr auto drop(Range &&range, size_t n)
Definition: view.hh:502
constexpr auto drop_back(Range &&range, size_t n)
Definition: view.hh:508
auto zip(Ranges &&... ranges)
Definition: view.hh:551
constexpr auto keys(Map &&map)
Definition: view.hh:525
constexpr auto values(Map &&map)
Definition: view.hh:531
auto to_vector(Range &&range) -> std::vector< detail::ToVectorType< T, decltype(std::begin(range))> >
Definition: stl.hh:275
Definition: view_test.cc:241
int i
Definition: view_test.cc:242
F(int i_)
Definition: view_test.cc:243
bool isOdd() const
Definition: view_test.cc:245
TEST_CASE("view::drop random-access-range")
Definition: view_test.cc:25
void test_zip(const In1 &in1, const In2 &in2, const Expected &expected)
Definition: view_test.cc:320
void test_zip_equal(const In1 &in1, const In2 &in2, const Expected &expected)
Definition: view_test.cc:365
constexpr auto xrange(T e)
Definition: xrange.hh:132