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 (const auto& e : reverse(in)) out.push_back(e);
135 CHECK(out == vector<int>{4, 3, 2, 1});
136 }
137 SECTION("r-value") {
138 for (const 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 (const 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 };
227 check_unordered(keys(m), vector<std::string>{
228 "foo", "bar", "qux", "baz", "a", "z"});
229 check_unordered(values(m), vector<int>{1, 2, 3, 4, 5, 6});
230 }
231 SECTION("std::vector<std::tuple>") {
232 vector<std::tuple<int, char, double, std::string>> v = {
233 std::tuple(1, 2, 1.2, "foo"),
234 std::tuple(3, 4, 3.4, "bar"),
235 std::tuple(5, 6, 5.6, "qux")
236 };
237 check(keys (v), vector<int>{1, 3, 5});
238 check(values(v), vector<char>{2, 4, 6});
239 }
240}
241
242struct F {
243 int i;
244 explicit(false) F(int i_) : i(i_) {}
245 explicit(false) operator int() const { return i; }
246 bool isOdd() const { return i & 1; }
247};
248
249TEST_CASE("view::filter") {
250 vector v = {1, 2, 3, 4, 5, 6, 7, 8, 9};
251
252 SECTION("removed front") {
253 check(view::filter(v, [](int i) { return i > 5; }),
254 vector{6, 7, 8, 9});
255 }
256 SECTION("removed back") {
257 check(view::filter(v, [](int i) { return i < 5; }),
258 vector{1, 2, 3, 4});
259 }
260 SECTION("keep front and back") {
261 check(view::filter(v, [](int i) { return i & 1; }),
262 vector{1, 3, 5, 7, 9});
263 }
264 SECTION("remove front and back") {
265 check(view::filter(v, [](int i) { return (i & 1) == 0; }),
266 vector{2, 4, 6, 8});
267 }
268
269 SECTION("projection") {
270 vector<F> f = {1, 2, 3, 4, 5};
271 auto view = view::filter(f, &F::isOdd);
272 auto it = view.begin();
273 auto et = view.end();
274 REQUIRE(it != et);
275 CHECK(*it == 1);
276 ++it;
277 REQUIRE(it != et);
278 CHECK(*it == 3);
279 it++;
280 REQUIRE(it != et);
281 CHECK(*it == 5);
282 ++it;
283 REQUIRE(it == et);
284 }
285}
286
287TEST_CASE("view::take") {
288 SECTION("n") {
289 vector v = {1, 2, 3, 4};
290 check(view::take(v, 0), vector<int>{});
291 check(view::take(v, 1), vector{1});
292 check(view::take(v, 2), vector{1, 2});
293 check(view::take(v, 3), vector{1, 2, 3});
294 check(view::take(v, 4), vector{1, 2, 3, 4});
295 check(view::take(v, 5), vector{1, 2, 3, 4});
296 check(view::take(v, 6), vector{1, 2, 3, 4});
297 }
298 SECTION("split_view") {
299 std::string_view str = "abc def\t \tghi jkl mno pqr";
300 auto v = view::take(StringOp::split_view<StringOp::EmptyParts::REMOVE>(str, " \t"), 3);
301
302 auto it = v.begin();
303 auto et = v.end();
304 REQUIRE(it != et);
305 CHECK(*it == "abc");
306
307 ++it;
308 REQUIRE(it != et);
309 CHECK(*it == "def");
310
311 ++it;
312 REQUIRE(it != et);
313 CHECK(*it == "ghi");
314
315 ++it;
316 REQUIRE(it == et);
317 }
318}
CHECK(m3==m3)
constexpr bool equal(InputRange1 &&range1, InputRange2 &&range2, Pred pred={}, Proj1 proj1={}, Proj2 proj2={})
Definition ranges.hh:378
constexpr void sort(RandomAccessRange &&range)
Definition ranges.hh:51
Definition view.hh:15
auto filter(ForwardRange &&range, Predicate pred)
Definition view.hh:459
constexpr auto transform(Range &&range, UnaryOp op)
Definition view.hh:441
constexpr auto take(ForwardRange &&range, size_t n)
Definition view.hh:465
constexpr auto reverse(Range &&range)
Definition view.hh:435
constexpr auto drop(Range &&range, size_t n)
Definition view.hh:423
constexpr auto drop_back(Range &&range, size_t n)
Definition view.hh:429
constexpr auto keys(Map &&map)
Definition view.hh:446
constexpr auto values(Map &&map)
Definition view.hh:452
auto to_vector(Range &&range) -> std::vector< detail::ToVectorType< T, decltype(std::begin(range))> >
Definition stl.hh:278
int i
Definition view_test.cc:243
bool isOdd() const
Definition view_test.cc:246
TEST_CASE("view::drop random-access-range")
Definition view_test.cc:25
constexpr auto xrange(T e)
Definition xrange.hh:132