OXYGENHUB
◆ main openmsx / src / unittest / ranges_test.cc
5.3 KiB · C++ · last changed chore(): initial commit 1 month ago source blame history raw
1
#include "catch.hpp"
2
3
#include "ranges.hh"
4
#include "stl.hh"
5
6
#include <array>
7
#include <ranges>
8
#include <span>
9
#include <string>
10
#include <vector>
11
12
TEST_CASE("copy_to_range")
13
{
14
	std::array a = {1, 2, 3, 4, 5};
15
	std::vector v = {9, 9, 9, 9, 9, 9, 9, 9};
16
17
	copy_to_range(a, subspan(v, 1));
18
	CHECK(v == std::vector{9, 1, 2, 3, 4, 5, 9, 9});
19
20
	copy_to_range(a, v);
21
	CHECK(v == std::vector{1, 2, 3, 4, 5, 5, 9, 9});
22
}
23
24
TEST_CASE("ranges::all_equal")
25
{
26
	std::array<int, 0> a = {};
27
	std::array b = {3};
28
	std::array c = {3, 3};
29
	std::array d = {3, 3, 3};
30
	std::array e = {1, 3, 3};
31
	std::array f = {3, 1, 3};
32
	std::array g = {3, 3, 1};
33
	CHECK( ranges::all_equal(a));
34
	CHECK( ranges::all_equal(b));
35
	CHECK( ranges::all_equal(c));
36
	CHECK( ranges::all_equal(d));
37
	CHECK(!ranges::all_equal(e));
38
	CHECK(!ranges::all_equal(f));
39
	CHECK(!ranges::all_equal(g));
40
41
	struct S {
42
		int x, y;
43
	};
44
	std::array s = {S{9, 1}, S{9, 3}, S{9, 5}, S{9, 7}};
45
	CHECK( ranges::all_equal(s, &S::x));
46
	CHECK(!ranges::all_equal(s, &S::y));
47
}
48
49
TEST_CASE("binary_find")
50
{
51
	SECTION("no projection") {
52
		std::array a = {3, 5, 9, 13, 19, 22, 45, 87, 98};
53
54
		SECTION("found") {
55
			SECTION("first") {
56
				auto f = binary_find(a, 3);
57
				CHECK(*f == 3);
58
				CHECK(f == &a[0]);
59
			}
60
			SECTION("middle") {
61
				auto f = binary_find(a, 19);
62
				CHECK(*f == 19);
63
				CHECK(f == &a[4]);
64
			}
65
			SECTION("last") {
66
				auto f = binary_find(a, 98);
67
				CHECK(*f == 98);
68
				CHECK(f == &a[8]);
69
			}
70
		}
71
		SECTION("not found") {
72
			SECTION("before") {
73
				CHECK(binary_find(a, 2) == nullptr);
74
			}
75
			SECTION("middle") {
76
				CHECK(binary_find(a, 28) == nullptr);
77
			}
78
			SECTION("after") {
79
				CHECK(binary_find(a, 99) == nullptr);
80
			}
81
		}
82
	}
83
	SECTION("no projection, reverse sorted") {
84
		std::vector v = {86, 54, 33, 29, 14, 3};
85
		CHECK(binary_find(v, 33, std::greater{}) == &v[2]);
86
		CHECK(binary_find(v, 14, std::greater{}) == &v[4]);
87
		CHECK(binary_find(v, 48, std::greater{}) == nullptr);
88
		CHECK(binary_find(v,  7, std::greater{}) == nullptr);
89
	}
90
	SECTION("projection") {
91
		struct S {
92
			int i;
93
			std::string s;
94
		};
95
		std::vector v = {S{4, "four"}, S{6, "six"}, S{10, "ten"}, S{99, "a lot"}};
96
97
		CHECK(binary_find(v,  4, {}, &S::i) == &v[0]);
98
		CHECK(binary_find(v, 99, {}, &S::i) == &v[3]);
99
		CHECK(binary_find(v,  6, {}, &S::i)->s == "six");
100
		CHECK(binary_find(v, 10, {}, &S::i)->s == "ten");
101
		CHECK(binary_find(v,   1, {}, &S::i) == nullptr);
102
		CHECK(binary_find(v,  17, {}, &S::i) == nullptr);
103
		CHECK(binary_find(v, 100, {}, &S::i) == nullptr);
104
	}
105
}
106
107
TEST_CASE("subspan")
108
{
109
	SECTION("from vector") {
110
		std::vector v = {2, 6, 7, 9, 1, 3, 4, 5, 6, 0, 1};
111
		SECTION("dynamic size") {
112
			SECTION("full") {
113
				auto s = subspan(v, 0);
114
				CHECK(s.data() == &v[0]);
115
				CHECK(s.size() == 11);
116
				CHECK(s.extent == std::dynamic_extent);
117
			}
118
			SECTION("till end") {
119
				auto s = subspan(v, 6);
120
				CHECK(s.data() == &v[6]);
121
				CHECK(s.size() == 5);
122
				CHECK(s.extent == std::dynamic_extent);
123
			}
124
			SECTION("till end, empty") {
125
				auto s = subspan(v, 11);
126
				CHECK(s.empty());
127
				CHECK(s.extent == std::dynamic_extent);
128
			}
129
			SECTION("from start, with size") {
130
				auto s = subspan(v, 0, 3);
131
				CHECK(s.data() == &v[0]);
132
				CHECK(s.size() == 3);
133
				CHECK(s.extent == std::dynamic_extent);
134
			}
135
			SECTION("middle") {
136
				auto s = subspan(v, 4, 5);
137
				CHECK(s.data() == &v[4]);
138
				CHECK(s.size() == 5);
139
				CHECK(s.extent == std::dynamic_extent);
140
			}
141
		}
142
		SECTION("fixed size") {
143
			SECTION("full") {
144
				auto s = subspan<11>(v);
145
				CHECK(s.data() == &v[0]);
146
				CHECK(s.size() == 11);
147
				CHECK(s.extent == 11);
148
			}
149
			SECTION("from start") {
150
				auto s = subspan<5>(v);
151
				CHECK(s.data() == &v[0]);
152
				CHECK(s.size() == 5);
153
				CHECK(s.extent == 5);
154
			}
155
			SECTION("middle") {
156
				auto s = subspan<7>(v, 2);
157
				CHECK(s.data() == &v[2]);
158
				CHECK(s.size() == 7);
159
				CHECK(s.extent == 7);
160
			}
161
			SECTION("empty") {
162
				auto s = subspan<0>(v, 2);
163
				CHECK(s.empty());
164
				CHECK(s.extent == 0);
165
			}
166
		}
167
	}
168
	SECTION("from array") {
169
		std::array a = {3, 5, 1, 2, 3, 9, 1, 0};
170
171
		auto s1 = subspan(a, 2, 3);
172
		CHECK(s1.data() == &a[2]);
173
		CHECK(s1.size() == 3);
174
		CHECK(s1.extent == std::dynamic_extent);
175
176
		auto s2 = subspan<4>(a, 1);
177
		CHECK(s2.data() == &a[1]);
178
		CHECK(s2.size() == 4);
179
		CHECK(s2.extent == 4);
180
	}
181
	SECTION("from string") {
182
		std::string s = "abcdefghijklmnopqrstuvwxyz";
183
184
		auto s1 = subspan(s, 20);
185
		CHECK(s1.data() == &s[20]);
186
		CHECK(s1.size() == 6);
187
		CHECK(s1.extent == std::dynamic_extent);
188
189
		auto s2 = subspan<3>(s, 6);
190
		CHECK(s2.data() == &s[6]);
191
		CHECK(s2.size() == 3);
192
		CHECK(s2.extent == 3);
193
	}
194
	SECTION("from another span") {
195
		std::vector v = {2, 4, 6, 8, 4, 2};
196
		std::span s = v;
197
198
		auto s1 = subspan(s, 0, 3);
199
		CHECK(s1.data() == &v[0]);
200
		CHECK(s1.size() == 3);
201
		CHECK(s1.extent == std::dynamic_extent);
202
203
		auto s2 = subspan<4>(s, 2);
204
		CHECK(s2.data() == &v[2]);
205
		CHECK(s2.size() == 4);
206
		CHECK(s2.extent == 4);
207
	}
208
	SECTION("from a class with begin/end methods") {
209
		struct S {
210
			const auto* begin() const { return a.begin(); }
211
			const auto* end()   const { return a.end(); }
212
			std::array<int, 10> a;
213
		} s;
214
215
		auto s1 = subspan(s, 4, 5);
216
		CHECK(s1.data() == &s.a[4]);
217
		CHECK(s1.size() == 5);
218
		CHECK(s1.extent == std::dynamic_extent);
219
220
		auto s2 = subspan<7>(s, 1);
221
		CHECK(s2.data() == &s.a[1]);
222
		CHECK(s2.size() == 7);
223
		CHECK(s2.extent == 7);
224
	}
225
}