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 <algorithm>
8 #include <list>
9 #include <map>
10 #include <string>
11 #include <tuple>
12 #include <vector>
13 
14 using namespace std;
15 using namespace view;
16 
17 static vector<int> getVector(int n)
18 {
19  vector<int> result;
20  for (int i = 0; i < n; ++i) {
21  result.push_back(i);
22  }
23  return result;
24 }
25 
26 TEST_CASE("view::drop random-access-range")
27 {
28  SECTION("empty") {
29  vector<int> v;
30  CHECK(to_vector(drop(v, 0)) == vector<int>{});
31  CHECK(to_vector(drop(v, 3)) == vector<int>{});
32  }
33  SECTION("non-empty") {
34  vector<int> v = {1, 2, 3, 4, 5};
35  CHECK(to_vector(drop(v, 0)) == vector<int>{1, 2, 3, 4, 5});
36  CHECK(to_vector(drop(v, 1)) == vector<int>{2, 3, 4, 5});
37  CHECK(to_vector(drop(v, 2)) == vector<int>{3, 4, 5});
38  CHECK(to_vector(drop(v, 3)) == vector<int>{4, 5});
39  CHECK(to_vector(drop(v, 4)) == vector<int>{5});
40  CHECK(to_vector(drop(v, 5)) == vector<int>{});
41  CHECK(to_vector(drop(v, 6)) == vector<int>{});
42  CHECK(to_vector(drop(v, 7)) == vector<int>{});
43  }
44  SECTION("r-value") {
45  CHECK(to_vector(drop(getVector(6), 3)) == vector<int>{3, 4, 5});
46  }
47 }
48 
49 TEST_CASE("view::drop non-random-access-range")
50 {
51  SECTION("empty") {
52  list<int> l;
53  CHECK(to_vector(drop(l, 0)) == vector<int>{});
54  CHECK(to_vector(drop(l, 3)) == vector<int>{});
55  }
56  SECTION("non-empty") {
57  list<int> l = {1, 2, 3, 4, 5};
58  CHECK(to_vector(drop(l, 0)) == vector<int>{1, 2, 3, 4, 5});
59  CHECK(to_vector(drop(l, 1)) == vector<int>{2, 3, 4, 5});
60  CHECK(to_vector(drop(l, 2)) == vector<int>{3, 4, 5});
61  CHECK(to_vector(drop(l, 3)) == vector<int>{4, 5});
62  CHECK(to_vector(drop(l, 4)) == vector<int>{5});
63  CHECK(to_vector(drop(l, 5)) == vector<int>{});
64  CHECK(to_vector(drop(l, 6)) == vector<int>{});
65  CHECK(to_vector(drop(l, 7)) == vector<int>{});
66  }
67 }
68 
69 TEST_CASE("view::drop capture")
70 {
71  REQUIRE(sizeof(vector<int>*) != sizeof(vector<int>));
72  SECTION("l-value") {
73  vector<int> v = {0, 1, 2, 3};
74  auto d = drop(v, 1);
75  // 'd' stores a reference to 'v'
76  CHECK(sizeof(d) == (sizeof(vector<int>*) + sizeof(size_t)));
77  }
78  SECTION("r-value") {
79  auto d = drop(getVector(4), 1);
80  // 'd' stores a vector by value
81  CHECK(sizeof(d) == (sizeof(vector<int>) + sizeof(size_t)));
82  }
83 }
84 
85 
86 TEST_CASE("view::drop_back random-access-range")
87 {
88  SECTION("empty") {
89  vector<int> v;
90  CHECK(to_vector(drop_back(v, 0)) == vector<int>{});
91  CHECK(to_vector(drop_back(v, 3)) == vector<int>{});
92  }
93  SECTION("non-empty") {
94  vector<int> v = {1, 2, 3, 4, 5};
95  CHECK(to_vector(drop_back(v, 0)) == vector<int>{1, 2, 3, 4, 5});
96  CHECK(to_vector(drop_back(v, 1)) == vector<int>{1, 2, 3, 4});
97  CHECK(to_vector(drop_back(v, 2)) == vector<int>{1, 2, 3});
98  CHECK(to_vector(drop_back(v, 3)) == vector<int>{1, 2});
99  CHECK(to_vector(drop_back(v, 4)) == vector<int>{1});
100  CHECK(to_vector(drop_back(v, 5)) == vector<int>{});
101  CHECK(to_vector(drop_back(v, 6)) == vector<int>{});
102  CHECK(to_vector(drop_back(v, 7)) == vector<int>{});
103  }
104  SECTION("r-value") {
105  CHECK(to_vector(drop_back(getVector(6), 3)) == vector<int>{0, 1, 2});
106  }
107 }
108 
109 TEST_CASE("view::drop_back non-random-access-range")
110 {
111  SECTION("empty") {
112  list<int> l;
113  CHECK(to_vector(drop_back(l, 0)) == vector<int>{});
114  CHECK(to_vector(drop_back(l, 3)) == vector<int>{});
115  }
116  SECTION("non-empty") {
117  list<int> l = {1, 2, 3, 4, 5};
118  CHECK(to_vector(drop_back(l, 0)) == vector<int>{1, 2, 3, 4, 5});
119  CHECK(to_vector(drop_back(l, 1)) == vector<int>{1, 2, 3, 4});
120  CHECK(to_vector(drop_back(l, 2)) == vector<int>{1, 2, 3});
121  CHECK(to_vector(drop_back(l, 3)) == vector<int>{1, 2});
122  CHECK(to_vector(drop_back(l, 4)) == vector<int>{1});
123  CHECK(to_vector(drop_back(l, 5)) == vector<int>{});
124  CHECK(to_vector(drop_back(l, 6)) == vector<int>{});
125  CHECK(to_vector(drop_back(l, 7)) == vector<int>{});
126  }
127 }
128 
129 
130 TEST_CASE("view::reverse")
131 {
132  vector<int> out;
133  SECTION("l-value") {
134  vector<int> in = {1, 2, 3, 4};
135  for (auto& e : reverse(in)) out.push_back(e);
136  CHECK(out == vector<int>{4, 3, 2, 1});
137  }
138  SECTION("r-value") {
139  for (auto& e : reverse(getVector(3))) out.push_back(e);
140  CHECK(out == vector<int>{2, 1, 0});
141  }
142  SECTION("2 x reverse") {
143  for (auto& e : reverse(reverse(getVector(4)))) out.push_back(e);
144  CHECK(out == vector<int>{0, 1, 2, 3});
145  }
146 }
147 
148 TEST_CASE("view::transform")
149 {
150  auto square = [](auto& x) { return x * x; };
151  size_t i = 1;
152  auto plus_i = [&](auto& x) { return int(x + i); };
153 
154  SECTION("l-value") {
155  vector<int> v = {1, 2, 3, 4};
156  CHECK(to_vector(transform(v, square)) == vector<int>{1, 4, 9, 16});
157  }
158  SECTION("r-value") {
159  i = 10;
160  CHECK(to_vector(transform(getVector(4), plus_i)) == vector<int>{10, 11, 12, 13});
161  }
162 }
163 
164 /*
165 No longer true since we use semiregular_t<> in TransformIterator
166 TEST_CASE("view::transform sizes")
167 {
168  auto square = [](auto& x) { return x * x; };
169  size_t i = 1;
170  auto plus_i = [&](auto& x) { return int(x + i); };
171 
172  vector<int> v = {1, 2, 3, 4};
173 
174  SECTION("l-value, stateless") {
175  auto vw = transform(v, square);
176  CHECK(sizeof(vw) == sizeof(std::vector<int>*));
177  CHECK(sizeof(vw.begin()) == sizeof(std::vector<int>::iterator));
178  }
179  SECTION("l-value, state") {
180  auto vw = transform(v, plus_i);
181  CHECK(sizeof(vw) == (sizeof(size_t&) + sizeof(std::vector<int>*)));
182  CHECK(sizeof(vw.begin()) == (sizeof(size_t&) + sizeof(std::vector<int>::iterator)));
183  }
184  SECTION("r-value, stateless") {
185  auto vw = transform(getVector(3), square);
186  CHECK(sizeof(vw) == sizeof(std::vector<int>));
187  CHECK(sizeof(vw.begin()) == sizeof(std::vector<int>::iterator));
188  }
189  SECTION("r-value, state") {
190  auto vw = transform(getVector(3), plus_i);
191  CHECK(sizeof(vw) == (sizeof(size_t&) + sizeof(std::vector<int>)));
192  CHECK(sizeof(vw.begin()) == (sizeof(size_t&) + sizeof(std::vector<int>::iterator)));
193  }
194 }*/
195 
196 
197 template<typename RANGE, typename T>
198 static void check(const RANGE& range, const vector<T>& expected)
199 {
200  CHECK(equal(range.begin(), range.end(), expected.begin(), expected.end()));
201 }
202 
203 template<typename RANGE, typename T>
204 static void check_unordered(const RANGE& range, const vector<T>& expected_)
205 {
206  auto result = to_vector<T>(range);
207  auto expected = expected_;
208  ranges::sort(result);
209  ranges::sort(expected);
210  CHECK(result == expected);
211 }
212 
213 TEST_CASE("view::keys, view::values") {
214  SECTION("std::map") {
215  map<int, int> m = {{1, 2}, {3, 4}, {5, 6}, {7, 8}};
216  check(keys (m), vector<int>{1, 3, 5, 7});
217  check(values(m), vector<int>{2, 4, 6, 8});
218  }
219  SECTION("std::vector<pair>") {
220  vector<pair<int, int>> v = {{1, 2}, {3, 4}, {5, 6}, {7, 8}};
221  check(keys (v), vector<int>{1, 3, 5, 7});
222  check(values(v), vector<int>{2, 4, 6, 8});
223  }
224  SECTION("hash_map") {
226  {{"foo", 1}, {"bar", 2}, {"qux", 3},
227  {"baz", 4}, {"a", 5}, {"z", 6}};
228  check_unordered(keys(m), vector<string>{
229  "foo", "bar", "qux", "baz", "a", "z"});
230  check_unordered(values(m), vector<int>{1, 2, 3, 4, 5, 6});
231  }
232  SECTION("std::vector<tuple>") {
233  vector<tuple<int, char, double, string>> v = {
234  tuple(1, 2, 1.2, "foo"),
235  tuple(3, 4, 3.4, "bar"),
236  tuple(5, 6, 5.6, "qux")
237  };
238  check(keys (v), vector<int>{1, 3, 5});
239  check(values(v), vector<char>{2, 4, 6});
240  }
241 }
auto values(Map &&map)
Definition: view.hh:317
Definition: view.hh:10
STL namespace.
CHECK(m3==m3)
auto reverse(Range &&range)
Definition: view.hh:300
auto keys(Map &&map)
Definition: view.hh:311
void sort(RandomAccessRange &&range)
Definition: ranges.hh:35
auto drop_back(Range &&range, size_t n)
Definition: view.hh:294
auto transform(InputRange &&range, OutputIter out, UnaryOperation op)
Definition: ranges.hh:161
auto drop(Range &&range, size_t n)
Definition: view.hh:288
TEST_CASE("view::drop random-access-range")
Definition: view_test.cc:26
auto to_vector(Range &&range) -> std::vector< detail::ToVectorType< T, decltype(std::begin(range))>>
Definition: stl.hh:325