1 //
2 // Tests for
3 //  bounded_array_ref<T, TrappingPolicy> slice(size_t n, size_t m) const;
4 //
5 
6 #include <libkern/c++/bounded_array_ref.h>
7 #include "test_policy.h"
8 #include <cstddef>
9 #include <cstdint>
10 #include <darwintest.h>
11 #include <darwintest_utils.h>
12 #include <limits>
13 
14 struct T { int i; };
15 
16 template <typename T>
17 using tracking_bounded_array_ref = libkern::bounded_array_ref<T, tracking_policy>;
18 
19 template <typename T>
20 static void
tests()21 tests()
22 {
23 	T array[5] = {T{0}, T{1}, T{2}, T{3}, T{4}};
24 
25 	// Slices starting at 0
26 	{
27 		test_bounded_array_ref<T> view(array);
28 		test_bounded_array_ref<T> slice = view.slice(0, 0);
29 		CHECK(slice.size() == 0);
30 	}
31 	{
32 		test_bounded_array_ref<T> view(array);
33 		test_bounded_array_ref<T> slice = view.slice(0, 1);
34 		CHECK(slice.size() == 1);
35 		CHECK(&slice[0] == &array[0]);
36 	}
37 	{
38 		test_bounded_array_ref<T> view(array);
39 		test_bounded_array_ref<T> slice = view.slice(0, 2);
40 		CHECK(slice.size() == 2);
41 		CHECK(&slice[0] == &array[0]);
42 		CHECK(&slice[1] == &array[1]);
43 	}
44 	{
45 		test_bounded_array_ref<T> view(array);
46 		test_bounded_array_ref<T> slice = view.slice(0, 5);
47 		CHECK(slice.size() == 5);
48 		CHECK(&slice[0] == &array[0]);
49 		CHECK(&slice[1] == &array[1]);
50 		CHECK(&slice[2] == &array[2]);
51 		CHECK(&slice[3] == &array[3]);
52 		CHECK(&slice[4] == &array[4]);
53 	}
54 	{
55 		tracking_bounded_array_ref<T> view(array);
56 		tracking_policy::reset();
57 		tracking_bounded_array_ref<T> slice = view.slice(0, 6);
58 		CHECK(tracking_policy::did_trap);
59 		CHECK(tracking_policy::message == "bounded_array_ref: invalid slice provided, the indices are of bounds for the bounded_array_ref");
60 	}
61 
62 	// Slices starting at 1 (near the beginning)
63 	{
64 		test_bounded_array_ref<T> view(array);
65 		test_bounded_array_ref<T> slice = view.slice(1, 0);
66 		CHECK(slice.size() == 0);
67 	}
68 	{
69 		test_bounded_array_ref<T> view(array);
70 		test_bounded_array_ref<T> slice = view.slice(1, 3);
71 		CHECK(slice.size() == 3);
72 		CHECK(&slice[0] == &array[1]);
73 		CHECK(&slice[1] == &array[2]);
74 		CHECK(&slice[2] == &array[3]);
75 	}
76 	{
77 		test_bounded_array_ref<T> view(array);
78 		test_bounded_array_ref<T> slice = view.slice(1, 4);
79 		CHECK(slice.size() == 4);
80 		CHECK(&slice[0] == &array[1]);
81 		CHECK(&slice[1] == &array[2]);
82 		CHECK(&slice[2] == &array[3]);
83 		CHECK(&slice[3] == &array[4]);
84 	}
85 	{
86 		tracking_bounded_array_ref<T> view(array);
87 		tracking_policy::reset();
88 		tracking_bounded_array_ref<T> slice = view.slice(1, 5);
89 		CHECK(tracking_policy::did_trap);
90 	}
91 	{
92 		tracking_bounded_array_ref<T> view(array);
93 		tracking_policy::reset();
94 		tracking_bounded_array_ref<T> slice = view.slice(1, 10);
95 		CHECK(tracking_policy::did_trap);
96 	}
97 
98 	// Slices starting at 3 (in the middle)
99 	{
100 		test_bounded_array_ref<T> view(array);
101 		test_bounded_array_ref<T> slice = view.slice(3, 0);
102 		CHECK(slice.size() == 0);
103 	}
104 	{
105 		test_bounded_array_ref<T> view(array);
106 		test_bounded_array_ref<T> slice = view.slice(3, 2);
107 		CHECK(slice.size() == 2);
108 		CHECK(&slice[0] == &array[3]);
109 		CHECK(&slice[1] == &array[4]);
110 	}
111 	{
112 		tracking_bounded_array_ref<T> view(array);
113 		tracking_policy::reset();
114 		tracking_bounded_array_ref<T> slice = view.slice(3, 3);
115 		CHECK(tracking_policy::did_trap);
116 	}
117 	{
118 		tracking_bounded_array_ref<T> view(array);
119 		tracking_policy::reset();
120 		tracking_bounded_array_ref<T> slice = view.slice(3, 100);
121 		CHECK(tracking_policy::did_trap);
122 	}
123 
124 	// Slices starting at 4 (near the end)
125 	{
126 		test_bounded_array_ref<T> view(array);
127 		test_bounded_array_ref<T> slice = view.slice(4, 0);
128 		CHECK(slice.size() == 0);
129 	}
130 	{
131 		test_bounded_array_ref<T> view(array);
132 		test_bounded_array_ref<T> slice = view.slice(4, 1);
133 		CHECK(slice.size() == 1);
134 		CHECK(&slice[0] == &array[4]);
135 	}
136 	{
137 		tracking_bounded_array_ref<T> view(array);
138 		tracking_policy::reset();
139 		tracking_bounded_array_ref<T> slice = view.slice(4, 2);
140 		CHECK(tracking_policy::did_trap);
141 	}
142 
143 	// Slices starting at the end
144 	{
145 		test_bounded_array_ref<T> view(array);
146 		test_bounded_array_ref<T> slice = view.slice(5, 0);
147 		CHECK(slice.size() == 0);
148 	}
149 	{
150 		tracking_bounded_array_ref<T> view(array);
151 		tracking_policy::reset();
152 		tracking_bounded_array_ref<T> slice = view.slice(5, 1);
153 		CHECK(tracking_policy::did_trap);
154 	}
155 	{
156 		tracking_bounded_array_ref<T> view(array);
157 		tracking_policy::reset();
158 		tracking_bounded_array_ref<T> slice = view.slice(5, 10);
159 		CHECK(tracking_policy::did_trap);
160 	}
161 
162 	// Slices starting after the end
163 	{
164 		tracking_bounded_array_ref<T> view(array);
165 		tracking_policy::reset();
166 		tracking_bounded_array_ref<T> slice = view.slice(6, 0);
167 		CHECK(tracking_policy::did_trap);
168 	}
169 	{
170 		tracking_bounded_array_ref<T> view(array);
171 		tracking_policy::reset();
172 		tracking_bounded_array_ref<T> slice = view.slice(6, 1);
173 		CHECK(tracking_policy::did_trap);
174 	}
175 	{
176 		tracking_bounded_array_ref<T> view(array);
177 		tracking_policy::reset();
178 		tracking_bounded_array_ref<T> slice = view.slice(8, 10);
179 		CHECK(tracking_policy::did_trap);
180 	}
181 
182 	// Slices overflowing a uint32_t
183 	{
184 		std::uint32_t n = std::numeric_limits<std::uint32_t>::max() / 2 + 1;
185 		std::uint32_t m = std::numeric_limits<std::uint32_t>::max() / 2 + 1;
186 		tracking_bounded_array_ref<T> view(array);
187 		tracking_policy::reset();
188 		tracking_bounded_array_ref<T> slice = view.slice(n, m);
189 		CHECK(tracking_policy::did_trap);
190 		CHECK(tracking_policy::message == "bounded_array_ref: n + m is larger than the size of any bounded_array_ref");
191 	}
192 
193 	// Check the documented range equivalent
194 	{
195 		test_bounded_array_ref<T> view(array);
196 		test_bounded_array_ref<T> slice = view.slice(3, 2);
197 		CHECK(slice.begin() == view.begin() + 3);
198 		CHECK(slice.end() == view.begin() + 3 + 2);
199 	}
200 
201 	// Chaining calls to slice()
202 	{
203 		test_bounded_array_ref<T> view(array);
204 		test_bounded_array_ref<T> slice = view.slice(1, 4).slice(2, 2);
205 		CHECK(slice.size() == 2);
206 		CHECK(&slice[0] == &array[3]);
207 		CHECK(&slice[1] == &array[4]);
208 	}
209 
210 	// Slicing an empty view
211 	{
212 		test_bounded_array_ref<T> view;
213 		test_bounded_array_ref<T> slice = view.slice(0, 0);
214 		CHECK(slice.size() == 0);
215 	}
216 	{
217 		tracking_bounded_array_ref<T> view;
218 		tracking_policy::reset();
219 		tracking_bounded_array_ref<T> slice = view.slice(0, 1);
220 		CHECK(tracking_policy::did_trap);
221 	}
222 }
223 
224 T_DECL(slice, "bounded_array_ref.slice", T_META_TAG_VM_PREFERRED) {
225 	tests<T>();
226 	tests<T const>();
227 }
228