• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <UnitTest++/UnitTest++.h>
18 #include <cstdlib>
19 #include <gsl/string_span>
20 #include <vector>
21 #include <map>
22 
23 using namespace std;
24 using namespace gsl;
25 
26 
SUITE(string_span_tests)27 SUITE(string_span_tests)
28 {
29 
30     TEST(TestLiteralConstruction)
31     {
32         cwstring_span<> v = ensure_z(L"Hello");
33         CHECK(5 == v.length());
34 
35 #ifdef CONFIRM_COMPILATION_ERRORS
36         wstring_span<> v2 = ensure0(L"Hello");
37 #endif
38     }
39 
40     TEST(TestConstructFromStdString)
41     {
42         std::string s = "Hello there world";
43         cstring_span<> v = s;
44         CHECK(v.length() == static_cast<cstring_span<>::index_type>(s.length()));
45     }
46 
47     TEST(TestConstructFromStdVector)
48     {
49         std::vector<char> vec(5, 'h');
50         string_span<> v {vec};
51         CHECK(v.length() == static_cast<string_span<>::index_type>(vec.size()));
52     }
53 
54     TEST(TestStackArrayConstruction)
55     {
56         wchar_t stack_string[] = L"Hello";
57 
58         {
59             cwstring_span<> v = ensure_z(stack_string);
60             CHECK(v.length() == 5);
61         }
62 
63         {
64             cwstring_span<> v = stack_string;
65             CHECK(v.length() == 5);
66         }
67 
68         {
69             wstring_span<> v = ensure_z(stack_string);
70             CHECK(v.length() == 5);
71         }
72 
73         {
74             wstring_span<> v = stack_string;
75             CHECK(v.length() == 5);
76         }
77     }
78 
79     TEST(TestConstructFromConstCharPointer)
80     {
81         const char* s = "Hello";
82         cstring_span<> v = ensure_z(s);
83         CHECK(v.length() == 5);
84     }
85 
86     TEST(TestConversionToConst)
87     {
88         char stack_string[] = "Hello";
89         string_span<> v = ensure_z(stack_string);
90         cstring_span<> v2 = v;
91         CHECK(v.length() == v2.length());
92     }
93 
94     TEST(TestConversionFromConst)
95     {
96         char stack_string[] = "Hello";
97         cstring_span<> v = ensure_z(stack_string);
98         (void)v;
99 #ifdef CONFIRM_COMPILATION_ERRORS
100         string_span<> v2 = v;
101         string_span<> v3 = "Hello";
102 #endif
103     }
104 
105     TEST(TestToString)
106     {
107         auto s = gsl::to_string(cstring_span<>{});
108         CHECK(s.length() == 0);
109 
110         char stack_string[] = "Hello";
111         cstring_span<> v = ensure_z(stack_string);
112         auto s2 = gsl::to_string(v);
113         CHECK(static_cast<cstring_span<>::index_type>(s2.length()) == v.length());
114         CHECK(s2.length() == 5);
115     }
116 
117     TEST(TestToBasicString)
118     {
119         auto s = gsl::to_basic_string<char,std::char_traits<char>,::std::allocator<char>>(cstring_span<>{});
120         CHECK(s.length() == 0);
121 
122         char stack_string[] = "Hello";
123         cstring_span<> v = ensure_z(stack_string);
124         auto s2 = gsl::to_basic_string<char,std::char_traits<char>,::std::allocator<char>>(v);
125         CHECK(static_cast<cstring_span<>::index_type>(s2.length()) == v.length());
126         CHECK(s2.length() == 5);
127     }
128 
129     TEST(EqualityAndImplicitConstructors)
130     {
131         {
132             cstring_span<> span = "Hello";
133             cstring_span<> span1;
134 
135             // comparison to empty span
136             CHECK(span1 != span);
137             CHECK(span != span1);
138         }
139 
140         {
141             cstring_span<> span = "Hello";
142             cstring_span<> span1 = "Hello1";
143 
144             // comparison to different span
145             CHECK(span1 != span);
146             CHECK(span != span1);
147         }
148 
149         {
150             cstring_span<> span = "Hello";
151 
152             const char ar[] = { 'H', 'e', 'l', 'l', 'o' };
153             const char ar1[] = "Hello";
154             const char ar2[10] = "Hello";
155             const char* ptr = "Hello";
156             const std::string str = "Hello";
157             const std::vector<char> vec = { 'H', 'e', 'l', 'l', 'o' };
158             gsl::span<const char> sp = ensure_z("Hello");
159 
160             // comparison to  literal
161             CHECK(span == cstring_span<>("Hello"));
162 
163             // comparison to static array with no null termination
164             CHECK(span == cstring_span<>(ar));
165 
166             // comparison to static array with null at the end
167             CHECK(span == cstring_span<>(ar1));
168 
169             // comparison to static array with null in the middle
170             CHECK(span == cstring_span<>(ar2));
171 
172             // comparison to null-terminated c string
173             CHECK(span == cstring_span<>(ptr, 5));
174 
175             // comparison to string
176             CHECK(span == cstring_span<>(str));
177 
178             // comparison to vector of charaters with no null termination
179             CHECK(span == cstring_span<>(vec));
180 
181             // comparison to span
182             CHECK(span == cstring_span<>(sp));
183 
184             // comparison to string_span
185             CHECK(span == span);
186         }
187 
188         {
189             char ar[] = { 'H', 'e', 'l', 'l', 'o' };
190 
191             string_span<> span = ar;
192 
193             char ar1[] = "Hello";
194             char ar2[10] = "Hello";
195             char* ptr = ar;
196             std::string str = "Hello";
197             std::vector<char> vec = { 'H', 'e', 'l', 'l', 'o' };
198             gsl::span<char> sp = ensure_z(ar1);
199 
200             // comparison to static array with no null termination
201             CHECK(span == string_span<>(ar));
202 
203             // comparison to static array with null at the end
204             CHECK(span == string_span<>(ar1));
205 
206             // comparison to static array with null in the middle
207             CHECK(span == string_span<>(ar2));
208 
209             // comparison to null-terminated c string
210             CHECK(span == string_span<>(ptr, 5));
211 
212             // comparison to string
213             CHECK(span == string_span<>(str));
214 
215             // comparison to vector of charaters with no null termination
216             CHECK(span == string_span<>(vec));
217 
218             // comparison to span
219             CHECK(span == string_span<>(sp));
220 
221             // comparison to string_span
222             CHECK(span == span);
223         }
224 
225 
226         {
227             const char ar[] = { 'H', 'e', 'l', 'l', 'o' };
228             const char ar1[] = "Hello";
229             const char ar2[10] = "Hello";
230             const std::string str = "Hello";
231             const std::vector<char> vec = { 'H', 'e', 'l', 'l', 'o' };
232             gsl::span<const char> sp = ensure_z("Hello");
233 
234             cstring_span<> span = "Hello";
235 
236             // const span, const other type
237 
238             CHECK(span == "Hello");
239             CHECK(span == ar);
240             CHECK(span == ar1);
241             CHECK(span == ar2);
242 #ifdef CONFIRM_COMPILATION_ERRORS
243             const char* ptr = "Hello";
244             CHECK(span == ptr);
245 #endif
246             CHECK(span == str);
247             CHECK(span == vec);
248             CHECK(span == sp);
249 
250             CHECK("Hello" == span);
251             CHECK(ar == span);
252             CHECK(ar1 == span);
253             CHECK(ar2 == span);
254 #ifdef CONFIRM_COMPILATION_ERRORS
255             CHECK(ptr == span);
256 #endif
257             CHECK(str == span);
258             CHECK(vec == span);
259             CHECK(sp == span);
260 
261             // const span, non-const other type
262 
263             char _ar[] = { 'H', 'e', 'l', 'l', 'o' };
264             char _ar1[] = "Hello";
265             char _ar2[10] = "Hello";
266             char* _ptr = _ar;
267             std::string _str = "Hello";
268             std::vector<char> _vec = { 'H', 'e', 'l', 'l', 'o' };
269             gsl::span<char> _sp{ _ar, 5 };
270 
271             CHECK(span == _ar);
272             CHECK(span == _ar1);
273             CHECK(span == _ar2);
274 #ifdef CONFIRM_COMPILATION_ERRORS
275             CHECK(span == _ptr);
276 #endif
277             CHECK(span == _str);
278             CHECK(span == _vec);
279             CHECK(span == _sp);
280 
281             CHECK(_ar == span);
282             CHECK(_ar1 == span);
283             CHECK(_ar2 == span);
284 #ifdef CONFIRM_COMPILATION_ERRORS
285             CHECK(_ptr == span);
286 #endif
287             CHECK(_str == span);
288             CHECK(_vec == span);
289             CHECK(_sp == span);
290 
291             string_span<> _span{ _ptr, 5 };
292 
293             // non-const span, non-const other type
294 
295             CHECK(_span == _ar);
296             CHECK(_span == _ar1);
297             CHECK(_span == _ar2);
298 #ifdef CONFIRM_COMPILATION_ERRORS
299             CHECK(_span == _ptr);
300 #endif
301             CHECK(_span == _str);
302             CHECK(_span == _vec);
303             CHECK(_span == _sp);
304 
305             CHECK(_ar == _span);
306             CHECK(_ar1 == _span);
307             CHECK(_ar2 == _span);
308 #ifdef CONFIRM_COMPILATION_ERRORS
309             CHECK(_ptr == _span);
310 #endif
311             CHECK(_str == _span);
312             CHECK(_vec == _span);
313             CHECK(_sp == _span);
314 
315             // non-const span, const other type
316 
317             CHECK(_span == "Hello");
318             CHECK(_span == ar);
319             CHECK(_span == ar1);
320             CHECK(_span == ar2);
321 #ifdef CONFIRM_COMPILATION_ERRORS
322             CHECK(_span == ptr);
323 #endif
324             CHECK(_span == str);
325             CHECK(_span == vec);
326             CHECK(_span == sp);
327 
328             CHECK("Hello" == _span);
329             CHECK(ar == _span);
330             CHECK(ar1 == _span);
331             CHECK(ar2 == _span);
332 #ifdef CONFIRM_COMPILATION_ERRORS
333             CHECK(ptr == _span);
334 #endif
335             CHECK(str == _span);
336             CHECK(vec == _span);
337             CHECK(sp == _span);
338 
339             // two spans
340 
341             CHECK(_span == span);
342             CHECK(span == _span);
343         }
344 
345         {
346             std::vector<char> str1 = { 'H', 'e', 'l', 'l', 'o' };
347             cstring_span<> span1 = str1;
348             std::vector<char> str2 = std::move(str1);
349             cstring_span<> span2 = str2;
350 
351             // comparison of spans from the same vector before and after move (ok)
352             CHECK(span1 == span2);
353         }
354     }
355 
356     TEST(ComparisonAndImplicitConstructors)
357     {
358         {
359             cstring_span<> span = "Hello";
360 
361             const char ar[] = { 'H', 'e', 'l', 'l', 'o' };
362             const char ar1[] = "Hello";
363             const char ar2[10] = "Hello";
364             const char* ptr = "Hello";
365             const std::string str = "Hello";
366             const std::vector<char> vec = { 'H', 'e', 'l', 'l', 'o' };
367 
368             // comparison to  literal
369             CHECK(span < cstring_span<>("Helloo"));
370             CHECK(span > cstring_span<>("Hell"));
371 
372             // comparison to static array with no null termination
373             CHECK(span >= cstring_span<>(ar));
374 
375             // comparison to static array with null at the end
376             CHECK(span <= cstring_span<>(ar1));
377 
378             // comparison to static array with null in the middle
379             CHECK(span >= cstring_span<>(ar2));
380 
381             // comparison to null-terminated c string
382             CHECK(span <= cstring_span<>(ptr, 5));
383 
384             // comparison to string
385             CHECK(span >= cstring_span<>(str));
386 
387             // comparison to vector of charaters with no null termination
388             CHECK(span <= cstring_span<>(vec));
389         }
390 
391         {
392             char ar[] = { 'H', 'e', 'l', 'l', 'o' };
393 
394             string_span<> span = ar;
395 
396             char larr[] = "Hell";
397             char rarr[] = "Helloo";
398 
399             char ar1[] = "Hello";
400             char ar2[10] = "Hello";
401             char* ptr = ar;
402             std::string str = "Hello";
403             std::vector<char> vec = { 'H', 'e', 'l', 'l', 'o' };
404 
405 
406             // comparison to static array with no null termination
407             CHECK(span <= string_span<>(ar));
408             CHECK(span < string_span<>(rarr));
409             CHECK(span > string_span<>(larr));
410 
411             // comparison to static array with null at the end
412             CHECK(span >= string_span<>(ar1));
413 
414             // comparison to static array with null in the middle
415             CHECK(span <= string_span<>(ar2));
416 
417             // comparison to null-terminated c string
418             CHECK(span >= string_span<>(ptr, 5));
419 
420             // comparison to string
421             CHECK(span <= string_span<>(str));
422 
423             // comparison to vector of charaters with no null termination
424             CHECK(span >= string_span<>(vec));
425         }
426     }
427     TEST(ConstrutorsEnsureZ)
428     {
429         // remove z from literals
430         {
431             cstring_span<> sp = "hello";
432             CHECK((sp.length() == 5));
433         }
434 
435         // take the string as is
436         {
437             auto str = std::string("hello");
438             cstring_span<> sp = str;
439             CHECK((sp.length() == 5));
440         }
441 
442         // ensure z on c strings
443         {
444             char* ptr = new char[3];
445 
446             ptr[0] = 'a';
447             ptr[1] = 'b';
448             ptr[2] = '\0';
449 
450             string_span<> span = ensure_z(ptr);
451             CHECK(span.length() == 2);
452 
453             delete[] ptr;
454         }
455     }
456 
457     TEST(Constructors)
458     {
459         // creating cstring_span
460 
461         // from span of a final extent
462         {
463             span<const char, 6> sp = "Hello";
464             cstring_span<> span = sp;
465             CHECK(span.length() == 6);
466         }
467 
468         // from const span of a final extent to non-const string_span
469 #ifdef CONFIRM_COMPILATION_ERRORS
470         {
471             span<const char, 6> sp = "Hello";
472             string_span<> span = sp;
473             CHECK(span.length() == 6);
474         }
475 #endif
476 
477         // from string temporary
478 #ifdef CONFIRM_COMPILATION_ERRORS
479         {
480             cstring_span<> span = std::string("Hello");
481         }
482 #endif
483 
484         // default
485         {
486             cstring_span<> span;
487             CHECK(span.length() == 0);
488         }
489 
490         // from nullptr
491         {
492             cstring_span<> span(nullptr);
493             CHECK(span.length() == 0);
494         }
495 
496         // from string literal
497         {
498             cstring_span<> span = "Hello";
499             CHECK(span.length() == 5);
500         }
501 
502         // from const static array
503         {
504             const char ar[] = { 'H', 'e', 'l', 'l', 'o' };
505             cstring_span<> span = ar;
506             CHECK(span.length() == 5);
507         }
508 
509         // from non-const static array
510         {
511             char ar[] = { 'H', 'e', 'l', 'l', 'o' };
512             cstring_span<> span = ar;
513             CHECK(span.length() == 5);
514         }
515 
516         // from const ptr and length
517         {
518             const char* ptr = "Hello";
519             cstring_span<> span{ ptr, 5 };
520             CHECK(span.length() == 5);
521         }
522 
523         // from const ptr and length, include 0
524         {
525             const char* ptr = "Hello";
526             cstring_span<> span{ ptr, 6 };
527             CHECK(span.length() == 6);
528         }
529 
530         // from const ptr and length, 0 inside
531         {
532             const char* ptr = "He\0lo";
533             cstring_span<> span{ ptr, 5 };
534             CHECK(span.length() == 5);
535         }
536 
537         // from non-const ptr and length
538         {
539             char ar[] = { 'H', 'e', 'l', 'l', 'o' };
540             char* ptr = ar;
541             cstring_span<> span{ ptr, 5 };
542             CHECK(span.length() == 5);
543         }
544 
545         // from non-const ptr and length, 0 inside
546         {
547             char ar[] = { 'H', 'e', '\0', 'l', 'o' };
548             char* ptr = ar;
549             cstring_span<> span{ ptr, 5 };
550             CHECK(span.length() == 5);
551         }
552 
553         // from const string
554         {
555             const std::string str = "Hello";
556             cstring_span<> span = str;
557             CHECK(span.length() == 5);
558         }
559 
560         // from non-const string
561         {
562             std::string str = "Hello";
563             cstring_span<> span = str;
564             CHECK(span.length() == 5);
565         }
566 
567         // from const vector
568         {
569             const std::vector<char> vec = { 'H', 'e', 'l', 'l', 'o' };
570             cstring_span<> span = vec;
571             CHECK(span.length() == 5);
572         }
573 
574         // from non-const vector
575         {
576             std::vector<char> vec = { 'H', 'e', 'l', 'l', 'o' };
577             cstring_span<> span = vec;
578             CHECK(span.length() == 5);
579         }
580 
581         // from const span
582         {
583             std::vector<char> vec = { 'H', 'e', 'l', 'l', 'o' };
584             const span<const char> inner = vec;
585             cstring_span<> span = inner;
586             CHECK(span.length() == 5);
587         }
588 
589         // from non-const span
590         {
591             std::vector<char> vec = { 'H', 'e', 'l', 'l', 'o' };
592             span<char> inner = vec;
593             cstring_span<> span = inner;
594             CHECK(span.length() == 5);
595         }
596 
597         // from const string_span
598         {
599             std::vector<char> vec = { 'H', 'e', 'l', 'l', 'o' };
600             cstring_span<> tmp = vec;
601             cstring_span<> span = tmp;
602             CHECK(span.length() == 5);
603         }
604 
605         // from non-const string_span
606         {
607             std::vector<char> vec = { 'H', 'e', 'l', 'l', 'o' };
608             string_span<> tmp = vec;
609             cstring_span<> span = tmp;
610             CHECK(span.length() == 5);
611         }
612 
613         // creating string_span
614 
615         // from string literal
616         {
617 #ifdef CONFIRM_COMPILATION_ERRORS
618             string_span<> span = "Hello";
619 #endif
620         }
621 
622         // from const static array
623         {
624 #ifdef CONFIRM_COMPILATION_ERRORS
625             const char ar[] = { 'H', 'e', 'l', 'l', 'o' };
626             string_span<> span = ar;
627             CHECK(span.length() == 5);
628 #endif
629         }
630 
631         // from non-const static array
632         {
633             char ar[] = { 'H', 'e', 'l', 'l', 'o' };
634             string_span<> span = ar;
635             CHECK(span.length() == 5);
636         }
637 
638         // from const ptr and length
639         {
640 #ifdef CONFIRM_COMPILATION_ERRORS
641             const char* ptr = "Hello";
642             string_span<> span{ ptr, 5 };
643             CHECK(span.length() == 5);
644 #endif
645         }
646 
647         // from non-const ptr and length
648         {
649             char ar[] = { 'H', 'e', 'l', 'l', 'o' };
650             char* ptr = ar;
651             string_span<> span{ ptr, 5 };
652             CHECK(span.length() == 5);
653         }
654 
655         // from const string
656         {
657 #ifdef CONFIRM_COMPILATION_ERRORS
658             const std::string str = "Hello";
659             string_span<> span = str;
660             CHECK(span.length() == 5);
661 #endif
662         }
663 
664         // from non-const string
665         {
666             std::string str = "Hello";
667             string_span<> span = str;
668             CHECK(span.length() == 5);
669         }
670 
671         // from const vector
672         {
673 #ifdef CONFIRM_COMPILATION_ERRORS
674             const std::vector<char> vec = { 'H', 'e', 'l', 'l', 'o' };
675             string_span<> span = vec;
676             CHECK(span.length() == 5);
677 #endif
678         }
679 
680         // from non-const vector
681         {
682             std::vector<char> vec = { 'H', 'e', 'l', 'l', 'o' };
683             string_span<> span = vec;
684             CHECK(span.length() == 5);
685         }
686 
687         // from const span
688         {
689 #ifdef CONFIRM_COMPILATION_ERRORS
690             std::vector<char> vec = { 'H', 'e', 'l', 'l', 'o' };
691             const span<const char> inner = vec;
692             string_span<> span = inner;
693             CHECK(span.length() == 5);
694 #endif
695         }
696 
697         // from non-const span
698         {
699             std::vector<char> vec = { 'H', 'e', 'l', 'l', 'o' };
700             span<char> inner = vec;
701             string_span<> span = inner;
702             CHECK(span.length() == 5);
703         }
704 
705         // from non-const span of non-const data from const vector
706         {
707 #ifdef CONFIRM_COMPILATION_ERRORS
708             const std::vector<char> vec = { 'H', 'e', 'l', 'l', 'o' };
709             const span<char> inner = vec;
710             string_span<> span = inner;
711             CHECK(span.length() == 5);
712 #endif
713         }
714 
715         // from const string_span
716         {
717 #ifdef CONFIRM_COMPILATION_ERRORS
718             std::vector<char> vec = { 'H', 'e', 'l', 'l', 'o' };
719             cstring_span<> tmp = vec;
720             string_span<> span = tmp;
721             CHECK(span.length() == 5);
722 #endif
723         }
724 
725         // from non-const string_span
726         {
727             std::vector<char> vec = { 'H', 'e', 'l', 'l', 'o' };
728             string_span<> tmp = vec;
729             string_span<> span = tmp;
730             CHECK(span.length() == 5);
731         }
732 
733         // from non-const string_span from const vector
734         {
735 #ifdef CONFIRM_COMPILATION_ERRORS
736             const std::vector<char> vec = { 'H', 'e', 'l', 'l', 'o' };
737             string_span<> tmp = vec;
738             string_span<> span = tmp;
739             CHECK(span.length() == 5);
740 #endif
741         }
742 
743         // from const string_span of non-const data
744         {
745             std::vector<char> vec = { 'H', 'e', 'l', 'l', 'o' };
746             const string_span<> tmp = vec;
747             string_span<> span = tmp;
748             CHECK(span.length() == 5);
749         }
750     }
751 
752     template<typename T>
753     T move_wrapper(T&& t)
754     {
755         return std::move(t);
756     }
757 
758     template <class T>
759     T create() { return T{}; }
760 
761     template <class T>
762     void use(basic_string_span<T, gsl::dynamic_extent> s) {}
763 
764     TEST(MoveConstructors)
765     {
766         // move string_span
767         {
768             cstring_span<> span = "Hello";
769             auto span1 = std::move(span);
770             CHECK(span1.length() == 5);
771         }
772         {
773             cstring_span<> span = "Hello";
774             auto span1 = move_wrapper(std::move(span));
775             CHECK(span1.length() == 5);
776         }
777         {
778             cstring_span<> span = "Hello";
779             auto span1 = move_wrapper(std::move(span));
780             CHECK(span1.length() == 5);
781         }
782 
783         // move span
784         {
785             span<const char> span = ensure_z("Hello");
786             cstring_span<> span1 = std::move(span);
787             CHECK(span1.length() == 5);
788         }
789         {
790             span<const char> span = ensure_z("Hello");
791             cstring_span<> span2 = move_wrapper(std::move(span));
792             CHECK(span2.length() == 5);
793         }
794 
795         // move string
796         {
797 #ifdef CONFIRM_COMPILATION_ERRORS
798             std::string str = "Hello";
799             string_span<> span = std::move(str);
800             CHECK(span.length() == 5);
801 #endif
802         }
803         {
804 #ifdef CONFIRM_COMPILATION_ERRORS
805             std::string str = "Hello";
806             string_span<> span = move_wrapper<std::string>(std::move(str));
807             CHECK(span.length() == 5);
808 #endif
809         }
810         {
811 #ifdef CONFIRM_COMPILATION_ERRORS
812             use<char>(create<string>());
813 #endif
814         }
815 
816         // move container
817         {
818 #ifdef CONFIRM_COMPILATION_ERRORS
819             std::vector<char> vec = { 'H', 'e', 'l', 'l', 'o' };
820             string_span<> span = std::move(vec);
821             CHECK(span.length() == 5);
822 #endif
823         }
824         {
825 #ifdef CONFIRM_COMPILATION_ERRORS
826             std::vector<char> vec = { 'H', 'e', 'l', 'l', 'o' };
827             string_span<> span = move_wrapper<std::vector<char>>(std::move(vec));
828             CHECK(span.length() == 5);
829 #endif
830         }
831         {
832 #ifdef CONFIRM_COMPILATION_ERRORS
833             use<char>(create<std::vector<char>>());
834 #endif
835         }
836     }
837 
838     TEST(Conversion)
839     {
840 #ifdef CONFIRM_COMPILATION_ERRORS
841         cstring_span<> span = "Hello";
842         cwstring_span<> wspan{ span };
843         CHECK(wspan.length() == 5);
844 #endif
845     }
846 
847     czstring_span<> CreateTempName(string_span<> span)
848     {
849         Expects(span.size() > 1);
850 
851         int last = 0;
852         if (span.size() > 4)
853         {
854             span[0] = 't';
855             span[1] = 'm';
856             span[2] = 'p';
857             last = 3;
858         }
859         span[last] = '\0';
860 
861         auto ret = span.subspan(0, 4);
862         return{ ret };
863     }
864 
865     TEST(zstring)
866     {
867 
868         // create zspan from zero terminated string
869         {
870             char buf[1];
871             buf[0] = '\0';
872 
873             zstring_span<> zspan({ buf, 1 });
874 
875             CHECK(strlen(zspan.assume_z()) == 0);
876             CHECK(zspan.as_string_span().size() == 0);
877             CHECK(zspan.ensure_z().size() == 0);
878         }
879 
880         // create zspan from non-zero terminated string
881         {
882             char buf[1];
883             buf[0] = 'a';
884 
885             auto workaround_macro = [&]() { zstring_span<> zspan({ buf, 1 }); };
886             CHECK_THROW(workaround_macro(), fail_fast);
887         }
888 
889         // usage scenario: create zero-terminated temp file name and pass to a legacy API
890         {
891             char buf[10];
892 
893             auto name = CreateTempName({ buf, 10 });
894             if (!name.empty())
895             {
896                 czstring<> str = name.assume_z();
897                 CHECK(strlen(str) == 3);
898                 CHECK(*(str+3) == '\0');
899             }
900         }
901 
902     }
903 
904     cwzstring_span<> CreateTempNameW(wstring_span<> span)
905     {
906         Expects(span.size() > 1);
907 
908         int last = 0;
909         if (span.size() > 4)
910         {
911             span[0] = L't';
912             span[1] = L'm';
913             span[2] = L'p';
914             last = 3;
915         }
916         span[last] = L'\0';
917 
918         auto ret = span.subspan(0, 4);
919         return{ ret };
920     }
921 
922     TEST(wzstring)
923     {
924 
925         // create zspan from zero terminated string
926         {
927             wchar_t buf[1];
928             buf[0] = L'\0';
929 
930             wzstring_span<> zspan({ buf, 1 });
931 
932             CHECK(wcsnlen(zspan.assume_z(), 1) == 0);
933             CHECK(zspan.as_string_span().size() == 0);
934             CHECK(zspan.ensure_z().size() == 0);
935         }
936 
937         // create zspan from non-zero terminated string
938         {
939             wchar_t buf[1];
940             buf[0] = L'a';
941 
942             auto workaround_macro = [&]() { wzstring_span<> zspan({ buf, 1 }); };
943             CHECK_THROW(workaround_macro(), fail_fast);
944         }
945 
946         // usage scenario: create zero-terminated temp file name and pass to a legacy API
947         {
948             wchar_t buf[10];
949 
950             auto name = CreateTempNameW({ buf, 10 });
951             if (!name.empty())
952             {
953                 cwzstring<> str = name.assume_z();
954                 CHECK(wcsnlen(str, 10) == 3);
955                 CHECK(*(str + 3) == L'\0');
956             }
957         }
958     }
959 
960     TEST(Issue305)
961     {
962         std::map<gsl::cstring_span<>, int> foo = { { "foo", 0 },{ "bar", 1 } };
963         CHECK(foo["foo"] == 0);
964         CHECK(foo["bar"] == 1);
965     }
966 }
967 
main(int,const char * [])968 int main(int, const char *[])
969 {
970     return UnitTest::RunAllTests();
971 }
972