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 #include <gsl/gsl_algorithm> // for copy
19 #include <gsl/span>          // for span
20 #include <array>   // for array
21 #include <cstddef> // for size_t
22 
23 namespace
24 {
25     static constexpr char deathstring[] = "Expected Death";
26 }
27 
28 namespace gsl
29 {
30 struct fail_fast;
31 } // namespace gsl
32 
33 using namespace std;
34 using namespace gsl;
35 
TEST(algorithm_tests,same_type)36 TEST(algorithm_tests, same_type)
37 {
38     // dynamic source and destination span
39     {
40         std::array<int, 5> src{1, 2, 3, 4, 5};
41         std::array<int, 10> dst{};
42 
43         const span<int> src_span(src);
44         const span<int> dst_span(dst);
45 
46         copy(src_span, dst_span);
47         copy(src_span, dst_span.subspan(src_span.size()));
48 
49         for (std::size_t i = 0; i < src.size(); ++i)
50         {
51             EXPECT_TRUE(dst[i] == src[i]);
52             EXPECT_TRUE(dst[i + src.size()] == src[i]);
53         }
54     }
55 
56     // static source and dynamic destination span
57     {
58         std::array<int, 5> src{1, 2, 3, 4, 5};
59         std::array<int, 10> dst{};
60 
61         const span<int, 5> src_span(src);
62         const span<int> dst_span(dst);
63 
64         copy(src_span, dst_span);
65         copy(src_span, dst_span.subspan(src_span.size()));
66 
67         for (std::size_t i = 0; i < src.size(); ++i)
68         {
69             EXPECT_TRUE(dst[i] == src[i]);
70             EXPECT_TRUE(dst[i + src.size()] == src[i]);
71         }
72     }
73 
74     // dynamic source and static destination span
75     {
76         std::array<int, 5> src{1, 2, 3, 4, 5};
77         std::array<int, 10> dst{};
78 
79         const span<int> src_span(src);
80         const span<int, 10> dst_span(dst);
81 
82         copy(src_span, dst_span);
83         copy(src_span, dst_span.subspan(src_span.size()));
84 
85         for (std::size_t i = 0; i < src.size(); ++i)
86         {
87             EXPECT_TRUE(dst[i] == src[i]);
88             EXPECT_TRUE(dst[i + src.size()] == src[i]);
89         }
90     }
91 
92     // static source and destination span
93     {
94         std::array<int, 5> src{1, 2, 3, 4, 5};
95         std::array<int, 10> dst{};
96 
97         const span<int, 5> src_span(src);
98         const span<int, 10> dst_span(dst);
99 
100         copy(src_span, dst_span);
101         copy(src_span, dst_span.subspan(src_span.size()));
102 
103         for (std::size_t i = 0; i < src.size(); ++i)
104         {
105             EXPECT_TRUE(dst[i] == src[i]);
106             EXPECT_TRUE(dst[i + src.size()] == src[i]);
107         }
108     }
109 }
110 
TEST(algorithm_tests,compatible_type)111 TEST(algorithm_tests, compatible_type)
112 {
113     // dynamic source and destination span
114     {
115         std::array<short, 5> src{1, 2, 3, 4, 5};
116         std::array<int, 10> dst{};
117 
118         const span<short> src_span(src);
119         const span<int> dst_span(dst);
120 
121         copy(src_span, dst_span);
122         copy(src_span, dst_span.subspan(src_span.size()));
123 
124         for (std::size_t i = 0; i < src.size(); ++i)
125         {
126             EXPECT_TRUE(dst[i] == src[i]);
127             EXPECT_TRUE(dst[i + src.size()] == src[i]);
128         }
129     }
130 
131     // static source and dynamic destination span
132     {
133         std::array<short, 5> src{1, 2, 3, 4, 5};
134         std::array<int, 10> dst{};
135 
136         const span<short, 5> src_span(src);
137         const span<int> dst_span(dst);
138 
139         copy(src_span, dst_span);
140         copy(src_span, dst_span.subspan(src_span.size()));
141 
142         for (std::size_t i = 0; i < src.size(); ++i)
143         {
144             EXPECT_TRUE(dst[i] == src[i]);
145             EXPECT_TRUE(dst[i + src.size()] == src[i]);
146         }
147     }
148 
149     // dynamic source and static destination span
150     {
151         std::array<short, 5> src{1, 2, 3, 4, 5};
152         std::array<int, 10> dst{};
153 
154         const span<short> src_span(src);
155         const span<int, 10> dst_span(dst);
156 
157         copy(src_span, dst_span);
158         copy(src_span, dst_span.subspan(src_span.size()));
159 
160         for (std::size_t i = 0; i < src.size(); ++i)
161         {
162             EXPECT_TRUE(dst[i] == src[i]);
163             EXPECT_TRUE(dst[i + src.size()] == src[i]);
164         }
165     }
166 
167     // static source and destination span
168     {
169         std::array<short, 5> src{1, 2, 3, 4, 5};
170         std::array<int, 10> dst{};
171 
172         const span<short, 5> src_span(src);
173         const span<int, 10> dst_span(dst);
174 
175         copy(src_span, dst_span);
176         copy(src_span, dst_span.subspan(src_span.size()));
177 
178         for (std::size_t i = 0; i < src.size(); ++i)
179         {
180             EXPECT_TRUE(dst[i] == src[i]);
181             EXPECT_TRUE(dst[i + src.size()] == src[i]);
182         }
183     }
184 }
185 
186 #ifdef CONFIRM_COMPILATION_ERRORS
TEST(algorithm_tests,incompatible_type)187 TEST(algorithm_tests, incompatible_type)
188 {
189     std::array<int, 4> src{1, 2, 3, 4};
190     std::array<int*, 12> dst{};
191 
192     span<int> src_span_dyn(src);
193     span<int, 4> src_span_static(src);
194     span<int*> dst_span_dyn(dst);
195     span<int*, 4> dst_span_static(dst);
196 
197     // every line should produce a compilation error
198     copy(src_span_dyn, dst_span_dyn);
199     copy(src_span_dyn, dst_span_static);
200     copy(src_span_static, dst_span_dyn);
201     copy(src_span_static, dst_span_static);
202 }
203 #endif
204 
TEST(algorithm_tests,small_destination_span)205 TEST(algorithm_tests, small_destination_span)
206 {
207     std::set_terminate([] {
208         std::cerr << "Expected Death. small_destination_span";
209         std::abort();
210     });
211 
212     std::array<int, 12> src{1, 2, 3, 4};
213     std::array<int, 4> dst{};
214 
215     const span<int> src_span_dyn(src);
216     const span<int, 12> src_span_static(src);
217     const span<int> dst_span_dyn(dst);
218     const span<int, 4> dst_span_static(dst);
219 
220     EXPECT_DEATH(copy(src_span_dyn, dst_span_dyn), deathstring);
221     EXPECT_DEATH(copy(src_span_dyn, dst_span_static), deathstring);
222     EXPECT_DEATH(copy(src_span_static, dst_span_dyn), deathstring);
223 
224 #ifdef CONFIRM_COMPILATION_ERRORS
225     copy(src_span_static, dst_span_static);
226 #endif
227 }
228