Home | History | Annotate | Download | only in tests
      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 
     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 
    968 int main(int, const char *[])
    969 {
    970     return UnitTest::RunAllTests();
    971 }
    972