1 ///////////////////////////////////////////////////////////////////////////////
2 //
3 // Copyright (c) 2015 Microsoft Corporation. All rights reserved.
4 //
5 // This code is licensed under the MIT License (MIT).
6 //
7 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
8 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
9 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
10 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
11 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
12 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
13 // THE SOFTWARE.
14 //
15 ///////////////////////////////////////////////////////////////////////////////
16 
17 #include <gtest/gtest.h>
18 
19 #include <gsl/gsl_util> // for narrow_cast, at
20 #include <gsl/span_ext> // for operator==, operator!=, make_span
21 
22 #include <array>       // for array
23 #include <iostream>    // for cerr
24 #include <vector>      // for vector
25 
26 using namespace std;
27 using namespace gsl;
28 
29 namespace
30 {
31 static constexpr char deathstring[] = "Expected Death";
32 } // namespace
33 
TEST(span_ext_test,make_span_from_pointer_length_constructor)34 TEST(span_ext_test, make_span_from_pointer_length_constructor)
35 {
36     std::set_terminate([] {
37         std::cerr << "Expected Death. from_pointer_length_constructor";
38         std::abort();
39     });
40     int arr[4] = {1, 2, 3, 4};
41 
42     {
43         auto s = make_span(&arr[0], 2);
44         EXPECT_TRUE(s.size() == 2);
45         EXPECT_TRUE(s.data() == &arr[0]);
46         EXPECT_TRUE(s[0] == 1);
47         EXPECT_TRUE(s[1] == 2);
48     }
49 
50     {
51         int* p = nullptr;
52         auto s = make_span(p, narrow_cast<span<int>::size_type>(0));
53         EXPECT_TRUE(s.size() == 0);
54         EXPECT_TRUE(s.data() == nullptr);
55     }
56 
57     {
58         int* p = nullptr;
59         auto workaround_macro = [=]() { make_span(p, 2); };
60         EXPECT_DEATH(workaround_macro(), deathstring);
61     }
62 }
63 
TEST(span_ext_test,make_span_from_pointer_pointer_construction)64 TEST(span_ext_test, make_span_from_pointer_pointer_construction)
65 {
66     int arr[4] = {1, 2, 3, 4};
67 
68     {
69         auto s = make_span(&arr[0], &arr[2]);
70         EXPECT_TRUE(s.size() == 2);
71         EXPECT_TRUE(s.data() == &arr[0]);
72         EXPECT_TRUE(s[0] == 1);
73         EXPECT_TRUE(s[1] == 2);
74     }
75 
76     {
77         auto s = make_span(&arr[0], &arr[0]);
78         EXPECT_TRUE(s.size() == 0);
79         EXPECT_TRUE(s.data() == &arr[0]);
80     }
81 
82     {
83         int* p = nullptr;
84         auto s = make_span(p, p);
85         EXPECT_TRUE(s.size() == 0);
86         EXPECT_TRUE(s.data() == nullptr);
87     }
88 }
89 
TEST(span_ext_test,make_span_from_array_constructor)90 TEST(span_ext_test, make_span_from_array_constructor)
91  {
92      int arr[5] = {1, 2, 3, 4, 5};
93      int arr2d[2][3] = {1, 2, 3, 4, 5, 6};
94      int arr3d[2][3][2] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
95 
96      {
97          const auto s = make_span(arr);
98          EXPECT_TRUE(s.size() == 5);
99          EXPECT_TRUE(s.data() == std::addressof(arr[0]));
100      }
101 
102      {
103          const auto s = make_span(std::addressof(arr2d[0]), 1);
104          EXPECT_TRUE(s.size() == 1);
105          EXPECT_TRUE(s.data() == std::addressof(arr2d[0]));
106      }
107 
108      {
109          const auto s = make_span(std::addressof(arr3d[0]), 1);
110          EXPECT_TRUE(s.size() == 1);
111          EXPECT_TRUE(s.data() == std::addressof(arr3d[0]));
112      }
113  }
114 
TEST(span_ext_test,make_span_from_dynamic_array_constructor)115  TEST(span_ext_test, make_span_from_dynamic_array_constructor)
116  {
117      double(*arr)[3][4] = new double[100][3][4];
118 
119      {
120          auto s = make_span(&arr[0][0][0], 10);
121          EXPECT_TRUE(s.size() == 10);
122          EXPECT_TRUE(s.data() == &arr[0][0][0]);
123      }
124 
125      delete[] arr;
126  }
127 
TEST(span_ext_test,make_span_from_std_array_constructor)128  TEST(span_ext_test, make_span_from_std_array_constructor)
129  {
130      std::array<int, 4> arr = {1, 2, 3, 4};
131 
132      {
133          auto s = make_span(arr);
134          EXPECT_TRUE(s.size() == arr.size());
135          EXPECT_TRUE(s.data() == arr.data());
136      }
137 
138      // This test checks for the bug found in gcc 6.1, 6.2, 6.3, 6.4, 6.5 7.1, 7.2, 7.3 - issue #590
139      {
140          span<int> s1 = make_span(arr);
141 
142          static span<int> s2;
143          s2 = s1;
144 
145  #if defined(__GNUC__) && __GNUC__ == 6 && (__GNUC_MINOR__ == 4 || __GNUC_MINOR__ == 5) &&          \
146      __GNUC_PATCHLEVEL__ == 0 && defined(__OPTIMIZE__)
147          // Known to be broken in gcc 6.4 and 6.5 with optimizations
148          // Issue in gcc: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=83116
149          EXPECT_TRUE(s1.size() == 4);
150          EXPECT_TRUE(s2.size() == 0);
151  #else
152          EXPECT_TRUE(s1.size() == s2.size());
153  #endif
154      }
155  }
156 
TEST(span_ext_test,make_span_from_const_std_array_constructor)157  TEST(span_ext_test, make_span_from_const_std_array_constructor)
158  {
159      const std::array<int, 4> arr = {1, 2, 3, 4};
160 
161      {
162          auto s = make_span(arr);
163          EXPECT_TRUE(s.size() == arr.size());
164          EXPECT_TRUE(s.data() == arr.data());
165      }
166  }
167 
TEST(span_ext_test,make_span_from_std_array_const_constructor)168  TEST(span_ext_test, make_span_from_std_array_const_constructor)
169  {
170      std::array<const int, 4> arr = {1, 2, 3, 4};
171 
172      {
173          auto s = make_span(arr);
174          EXPECT_TRUE(s.size() == arr.size());
175          EXPECT_TRUE(s.data() == arr.data());
176      }
177  }
178 
TEST(span_ext_test,make_span_from_container_constructor)179  TEST(span_ext_test, make_span_from_container_constructor)
180  {
181      std::vector<int> v = {1, 2, 3};
182      const std::vector<int> cv = v;
183 
184      {
185          auto s = make_span(v);
186          EXPECT_TRUE(s.size() == v.size());
187          EXPECT_TRUE(s.data() == v.data());
188 
189          auto cs = make_span(cv);
190          EXPECT_TRUE(cs.size() == cv.size());
191          EXPECT_TRUE(cs.data() == cv.data());
192      }
193  }
194 
TEST(span_test,interop_with_gsl_at)195  TEST(span_test, interop_with_gsl_at)
196  {
197      int arr[5] = {1, 2, 3, 4, 5};
198      span<int> s{arr};
199      EXPECT_TRUE(at(s, 0) ==  1);
200      EXPECT_TRUE(at(s, 1) == 2);
201  }
202 
TEST(span_ext_test,iterator_free_functions)203  TEST(span_ext_test, iterator_free_functions)
204  {
205      int a[] = {1, 2, 3, 4};
206      span<int> s{a};
207 
208      EXPECT_TRUE((std::is_same<decltype(s.begin()), decltype(begin(s))>::value));
209      EXPECT_TRUE((std::is_same<decltype(s.end()), decltype(end(s))>::value));
210 
211      EXPECT_TRUE((std::is_same<decltype(std::cbegin(s)), decltype(cbegin(s))>::value));
212      EXPECT_TRUE((std::is_same<decltype(std::cend(s)), decltype(cend(s))>::value));
213 
214      EXPECT_TRUE((std::is_same<decltype(s.rbegin()), decltype(rbegin(s))>::value));
215      EXPECT_TRUE((std::is_same<decltype(s.rend()), decltype(rend(s))>::value));
216 
217      EXPECT_TRUE((std::is_same<decltype(std::crbegin(s)), decltype(crbegin(s))>::value));
218      EXPECT_TRUE((std::is_same<decltype(std::crend(s)), decltype(crend(s))>::value));
219 
220      EXPECT_TRUE(s.begin() == begin(s));
221      EXPECT_TRUE(s.end() == end(s));
222 
223      EXPECT_TRUE(s.rbegin() == rbegin(s));
224      EXPECT_TRUE(s.rend() == rend(s));
225 
226      EXPECT_TRUE(s.begin() == cbegin(s));
227      EXPECT_TRUE(s.end() == cend(s));
228 
229      EXPECT_TRUE(s.rbegin() == crbegin(s));
230      EXPECT_TRUE(s.rend() == crend(s));
231  }
232 
TEST(span_ext_test,ssize_free_function)233  TEST(span_ext_test, ssize_free_function)
234  {
235      int a[] = {1, 2, 3, 4};
236      span<int> s{a};
237 
238      EXPECT_FALSE((std::is_same<decltype(s.size()), decltype(ssize(s))>::value));
239      EXPECT_TRUE(s.size() == static_cast<std::size_t>(ssize(s)));
240  }
241 
TEST(span_ext_test,comparison_operators)242   TEST(span_ext_test, comparison_operators)
243  {
244      {
245          span<int> s1;
246          span<int> s2;
247          EXPECT_TRUE(s1 == s2);
248          EXPECT_FALSE(s1 != s2);
249          EXPECT_FALSE(s1 < s2);
250          EXPECT_TRUE(s1 <= s2);
251          EXPECT_FALSE(s1 > s2);
252          EXPECT_TRUE(s1 >= s2);
253          EXPECT_TRUE(s2 == s1);
254          EXPECT_FALSE(s2 != s1);
255          EXPECT_FALSE(s2 != s1);
256          EXPECT_TRUE(s2 <= s1);
257          EXPECT_FALSE(s2 > s1);
258          EXPECT_TRUE(s2 >= s1);
259      }
260 
261      {
262          int arr[] = {2, 1};
263          span<int> s1 = arr;
264          span<int> s2 = arr;
265 
266          EXPECT_TRUE(s1 == s2);
267          EXPECT_FALSE(s1 != s2);
268          EXPECT_FALSE(s1 < s2);
269          EXPECT_TRUE(s1 <= s2);
270          EXPECT_FALSE(s1 > s2);
271          EXPECT_TRUE(s1 >= s2);
272          EXPECT_TRUE(s2 == s1);
273          EXPECT_FALSE(s2 != s1);
274          EXPECT_FALSE(s2 < s1);
275          EXPECT_TRUE(s2 <= s1);
276          EXPECT_FALSE(s2 > s1);
277          EXPECT_TRUE(s2 >= s1);
278      }
279 
280      {
281          int arr[] = {2, 1}; // bigger
282 
283          span<int> s1;
284          span<int> s2 = arr;
285 
286          EXPECT_TRUE(s1 != s2);
287          EXPECT_TRUE(s2 != s1);
288          EXPECT_FALSE(s1 == s2);
289          EXPECT_FALSE(s2 == s1);
290          EXPECT_TRUE(s1 < s2);
291          EXPECT_FALSE(s2 < s1);
292          EXPECT_TRUE(s1 <= s2);
293          EXPECT_FALSE(s2 <= s1);
294          EXPECT_TRUE(s2 > s1);
295          EXPECT_FALSE(s1 > s2);
296          EXPECT_TRUE(s2 >= s1);
297          EXPECT_FALSE(s1 >= s2);
298      }
299 
300      {
301          int arr1[] = {1, 2};
302          int arr2[] = {1, 2};
303          span<int> s1 = arr1;
304          span<int> s2 = arr2;
305 
306          EXPECT_TRUE(s1 == s2);
307          EXPECT_FALSE(s1 != s2);
308          EXPECT_FALSE(s1 < s2);
309          EXPECT_TRUE(s1 <= s2);
310          EXPECT_FALSE(s1 > s2);
311          EXPECT_TRUE(s1 >= s2);
312          EXPECT_TRUE(s2 == s1);
313          EXPECT_FALSE(s2 != s1);
314          EXPECT_FALSE(s2 < s1);
315          EXPECT_TRUE(s2 <= s1);
316          EXPECT_FALSE(s2 > s1);
317          EXPECT_TRUE(s2 >= s1);
318      }
319 
320      {
321          int arr[] = {1, 2, 3};
322 
323          span<int> s1 = {&arr[0], 2}; // shorter
324          span<int> s2 = arr;          // longer
325 
326          EXPECT_TRUE(s1 != s2);
327          EXPECT_TRUE(s2 != s1);
328          EXPECT_FALSE(s1 == s2);
329          EXPECT_FALSE(s2 == s1);
330          EXPECT_TRUE(s1 < s2);
331          EXPECT_FALSE(s2 < s1);
332          EXPECT_TRUE(s1 <= s2);
333          EXPECT_FALSE(s2 <= s1);
334          EXPECT_TRUE(s2 > s1);
335          EXPECT_FALSE(s1 > s2);
336          EXPECT_TRUE(s2 >= s1);
337          EXPECT_FALSE(s1 >= s2);
338      }
339 
340      {
341          int arr1[] = {1, 2}; // smaller
342          int arr2[] = {2, 1}; // bigger
343 
344          span<int> s1 = arr1;
345          span<int> s2 = arr2;
346 
347          EXPECT_TRUE(s1 != s2);
348          EXPECT_TRUE(s2 != s1);
349          EXPECT_FALSE(s1 == s2);
350          EXPECT_FALSE(s2 == s1);
351          EXPECT_TRUE(s1 < s2);
352          EXPECT_FALSE(s2 < s1);
353          EXPECT_TRUE(s1 <= s2);
354          EXPECT_FALSE(s2 <= s1);
355          EXPECT_TRUE(s2 > s1);
356          EXPECT_FALSE(s1 > s2);
357          EXPECT_TRUE(s2 >= s1);
358          EXPECT_FALSE(s1 >= s2);
359      }
360  }
361