test/test_string.cpp

Tue, 04 Oct 2022 18:49:14 +0200

author
Mike Becker <universe@uap-core.de>
date
Tue, 04 Oct 2022 18:49:14 +0200
changeset 589
c290f8fd979e
parent 588
6a3cd8f0a2cf
child 597
8b48126671cf
permissions
-rw-r--r--

add zero-termination guarantees

     1 /*
     2  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
     3  *
     4  * Copyright 2021 Mike Becker, Olaf Wintermann All rights reserved.
     5  *
     6  * Redistribution and use in source and binary forms, with or without
     7  * modification, are permitted provided that the following conditions are met:
     8  *
     9  *   1. Redistributions of source code must retain the above copyright
    10  *      notice, this list of conditions and the following disclaimer.
    11  *
    12  *   2. Redistributions in binary form must reproduce the above copyright
    13  *      notice, this list of conditions and the following disclaimer in the
    14  *      documentation and/or other materials provided with the distribution.
    15  *
    16  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
    17  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
    18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
    19  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
    20  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
    21  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
    22  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
    23  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
    24  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
    25  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
    26  * POSSIBILITY OF SUCH DAMAGE.
    27  */
    29 #include "cx/string.h"
    30 #include "util_allocator.h"
    32 #include <gtest/gtest.h>
    34 #define EXPECT_ZERO_TERMINATED(str) EXPECT_EQ((str).ptr[(str).length], '\0')
    36 TEST(String, construct) {
    37     cxstring s1 = cx_str("1234");
    38     cxstring s2 = cx_strn("abcd", 2);
    39     cxmutstr s3 = cx_mutstr((char *) "1234");
    40     cxmutstr s4 = cx_mutstrn((char *) "abcd", 2);
    42     EXPECT_EQ(s1.length, 4);
    43     EXPECT_EQ(s2.length, 2);
    44     EXPECT_EQ(s3.length, 4);
    45     EXPECT_EQ(s4.length, 2);
    46 }
    48 TEST(String, strfree) {
    49     CxTestingAllocator alloc;
    50     auto test = (char *) cxMalloc(&alloc, 16);
    51     cxmutstr str = cx_mutstrn(test, 16);
    52     ASSERT_EQ(str.ptr, test);
    53     EXPECT_EQ(str.length, 16);
    54     cx_strfree_a(&alloc, &str);
    55     EXPECT_EQ(str.ptr, nullptr);
    56     EXPECT_EQ(str.length, 0);
    57     EXPECT_TRUE(alloc.verify());
    58 }
    60 TEST(String, strdup) {
    61     cxstring str = CX_STR("test");
    62     cxmutstr dup = cx_strdup(str);
    63     ASSERT_EQ(dup.length, str.length);
    64     EXPECT_STREQ(dup.ptr, str.ptr);
    65     EXPECT_ZERO_TERMINATED(dup);
    66     cx_strfree(&dup);
    68     str.length = 2;
    69     dup = cx_strdup(str);
    70     ASSERT_EQ(dup.length, str.length);
    71     EXPECT_STREQ(dup.ptr, "te");
    72     EXPECT_ZERO_TERMINATED(dup);
    73     cx_strfree(&dup);
    74 }
    76 TEST(String, strlen) {
    77     cxstring s1 = CX_STR("1234");
    78     cxstring s2 = CX_STR(".:.:.");
    79     cxstring s3 = CX_STR("X");
    81     size_t len0 = cx_strlen(0);
    82     size_t len1 = cx_strlen(1, s1);
    83     size_t len2 = cx_strlen(2, s1, s2);
    84     size_t len3 = cx_strlen(3, s1, s2, s3);
    86     EXPECT_EQ(len0, 0);
    87     EXPECT_EQ(len1, 4);
    88     EXPECT_EQ(len2, 9);
    89     EXPECT_EQ(len3, 10);
    90 }
    92 TEST(String, strsubs) {
    93     cxstring str = CX_STR("A test string");
    95     cxstring sub = cx_strsubs(str, 0);
    96     EXPECT_EQ(cx_strcmp(sub, str), 0);
    98     sub = cx_strsubs(str, 2);
    99     EXPECT_EQ(cx_strcmp(sub, cx_str("test string")), 0);
   101     sub = cx_strsubs(str, 7);
   102     EXPECT_EQ(cx_strcmp(sub, cx_str("string")), 0);
   104     sub = cx_strsubs(str, 15);
   105     EXPECT_EQ(cx_strcmp(sub, cx_str("")), 0);
   107     sub = cx_strsubsl(str, 2, 4);
   108     EXPECT_EQ(cx_strcmp(sub, cx_str("test")), 0);
   110     sub = cx_strsubsl(str, 7, 3);
   111     EXPECT_EQ(cx_strcmp(sub, cx_str("str")), 0);
   113     sub = cx_strsubsl(str, 7, 20);
   114     EXPECT_EQ(cx_strcmp(sub, cx_str("string")), 0);
   116     // just for coverage, call the _m variant
   117     auto m = cx_strsubs_m(cx_mutstrn(nullptr, 0), 0);
   118     EXPECT_EQ(cx_strcmp(cx_strcast(m), cx_str("")), 0);
   119 }
   121 TEST(String, strchr) {
   122     cxstring str = CX_STR("I will find you - and I will kill you");
   124     cxstring notfound = cx_strchr(str, 'x');
   125     EXPECT_EQ(notfound.length, 0);
   127     cxstring result = cx_strchr(str, 'w');
   128     EXPECT_EQ(result.length, 35);
   129     EXPECT_STREQ(result.ptr, "will find you - and I will kill you");
   131     // just for coverage, call the _m variant
   132     auto m = cx_strchr_m(cx_mutstrn(nullptr, 0), 'a');
   133     EXPECT_EQ(cx_strcmp(cx_strcast(m), cx_str("")), 0);
   134 }
   136 TEST(String, strrchr) {
   137     cxstring str = CX_STR("I will find you - and I will kill you");
   139     cxstring notfound = cx_strrchr(str, 'x');
   140     EXPECT_EQ(notfound.length, 0);
   142     cxstring result = cx_strrchr(str, 'w');
   143     EXPECT_EQ(result.length, 13);
   144     EXPECT_STREQ(result.ptr, "will kill you");
   146     // just for coverage, call the _m variant
   147     auto m = cx_strrchr_m(cx_mutstrn(nullptr, 0), 'a');
   148     EXPECT_EQ(cx_strcmp(cx_strcast(m), cx_str("")), 0);
   149 }
   151 TEST(String, strstr) {
   152     cxstring str = CX_STR("find the match in this string");
   153     cxstring longstr = CX_STR(
   154             "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijkl"
   155             "mnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwx"
   156             "yzabcdeababababnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghij"
   157             "klmnopqrstuvwxyzaababababababababrstuvwxyzabcdefghijklmnopqrstuv"
   158             "abababababababababababababababababababababababababababababababab"
   159             "abababababababababababababababababababababababababababababababab"
   160             "abababababababababababababababababababababababababababababababab"
   161             "abababababababababababababababababababababababababababababababab"
   162             "abababababababababababababababababababababababababababababababab"
   163             "abababababababababababababababababababababababababababababababab"
   164             "wxyz1234567890");
   165     cxstring longstrpattern = CX_STR(
   166             "abababababababababababababababababababababababababababababababab"
   167             "abababababababababababababababababababababababababababababababab"
   168             "abababababababababababababababababababababababababababababababab"
   169             "abababababababababababababababababababababababababababababababab"
   170             "abababababababababababababababababababababababababababababababab"
   171     );
   172     cxstring longstrresult = CX_STR(
   173             "abababababababababababababababababababababababababababababababab"
   174             "abababababababababababababababababababababababababababababababab"
   175             "abababababababababababababababababababababababababababababababab"
   176             "abababababababababababababababababababababababababababababababab"
   177             "abababababababababababababababababababababababababababababababab"
   178             "abababababababababababababababababababababababababababababababab"
   179             "wxyz1234567890"
   180     );
   182     cxstring notfound = cx_strstr(str, cx_str("no match"));
   183     EXPECT_EQ(notfound.length, 0);
   185     cxstring result = cx_strstr(str, cx_str("match"));
   186     EXPECT_EQ(result.length, 20);
   187     EXPECT_STREQ(result.ptr, "match in this string");
   189     result = cx_strstr(str, cx_str(""));
   190     EXPECT_EQ(result.length, str.length);
   191     EXPECT_STREQ(result.ptr, str.ptr);
   193     result = cx_strstr(longstr, longstrpattern);
   194     EXPECT_EQ(result.length, longstrresult.length);
   195     EXPECT_STREQ(result.ptr, longstrresult.ptr);
   197     // just for coverage, call the _m variant
   198     auto mstr = cx_strdup(longstr);
   199     auto m = cx_strstr_m(mstr, longstrpattern);
   200     EXPECT_EQ(m.length, longstrresult.length);
   201     EXPECT_STREQ(m.ptr, longstrresult.ptr);
   202     cx_strfree(&mstr);
   203 }
   205 TEST(String, strcmp) {
   206     cxstring str = CX_STR("compare this");
   208     EXPECT_EQ(cx_strcmp(cx_str(""), cx_str("")), 0);
   209     EXPECT_GT(cx_strcmp(str, cx_str("")), 0);
   210     EXPECT_EQ(cx_strcmp(str, cx_str("compare this")), 0);
   211     EXPECT_NE(cx_strcmp(str, cx_str("Compare This")), 0);
   212     EXPECT_LT(cx_strcmp(str, cx_str("compare tool")), 0);
   213     EXPECT_GT(cx_strcmp(str, cx_str("compare shit")), 0);
   214     EXPECT_LT(cx_strcmp(str, cx_str("compare this not")), 0);
   215     EXPECT_GT(cx_strcmp(str, cx_str("compare")), 0);
   216 }
   218 TEST(String, strcasecmp) {
   219     cxstring str = CX_STR("compare this");
   221     EXPECT_EQ(cx_strcasecmp(cx_str(""), cx_str("")), 0);
   222     EXPECT_GT(cx_strcasecmp(str, cx_str("")), 0);
   223     EXPECT_EQ(cx_strcasecmp(str, cx_str("compare this")), 0);
   224     EXPECT_EQ(cx_strcasecmp(str, cx_str("Compare This")), 0);
   225     EXPECT_LT(cx_strcasecmp(str, cx_str("compare tool")), 0);
   226     EXPECT_GT(cx_strcasecmp(str, cx_str("compare shit")), 0);
   227     EXPECT_LT(cx_strcasecmp(str, cx_str("compare this not")), 0);
   228     EXPECT_GT(cx_strcasecmp(str, cx_str("compare")), 0);
   229 }
   231 TEST(String, strcat) {
   232     cxstring s1 = CX_STR("12");
   233     cxstring s2 = CX_STR("34");
   234     cxstring s3 = CX_STR("56");
   235     cxstring sn = {nullptr, 0};
   237     CxTestingAllocator alloc;
   239     cxmutstr t1 = cx_strcat_a(&alloc, 2, s1, s2);
   240     EXPECT_EQ(cx_strcmp(cx_strcast(t1), cx_str("1234")), 0);
   241     EXPECT_ZERO_TERMINATED(t1);
   242     cx_strfree_a(&alloc, &t1);
   244     cxmutstr t2 = cx_strcat_a(&alloc, 3, s1, s2, s3);
   245     EXPECT_EQ(cx_strcmp(cx_strcast(t2), cx_str("123456")), 0);
   246     EXPECT_ZERO_TERMINATED(t2);
   247     cx_strfree_a(&alloc, &t2);
   249     cxmutstr t3 = cx_strcat_a(&alloc, 6, s1, sn, s2, sn, s3, sn);
   250     EXPECT_EQ(cx_strcmp(cx_strcast(t3), cx_str("123456")), 0);
   251     EXPECT_ZERO_TERMINATED(t3);
   252     cx_strfree_a(&alloc, &t3);
   254     cxmutstr t4 = cx_strcat_a(&alloc, 2, sn, sn);
   255     EXPECT_EQ(cx_strcmp(cx_strcast(t4), cx_str("")), 0);
   256     EXPECT_ZERO_TERMINATED(t4);
   257     cx_strfree_a(&alloc, &t4);
   259     EXPECT_TRUE(alloc.verify());
   260 }
   262 TEST(String, strsplit) {
   264     cxstring test = cx_str("this,is,a,csv,string");
   265     size_t capa = 8;
   266     cxstring list[8];
   267     size_t n;
   269     /* special case: empty string */
   270     n = cx_strsplit(test, cx_str(""), capa, list);
   271     ASSERT_EQ(n, 1);
   272     EXPECT_EQ(cx_strcmp(list[0], test), 0);
   274     /* no delimiter occurrence */
   275     n = cx_strsplit(test, cx_str("z"), capa, list);
   276     ASSERT_EQ(n, 1);
   277     EXPECT_EQ(cx_strcmp(list[0], test), 0);
   279     /* partially matching delimiter */
   280     n = cx_strsplit(test, cx_str("is,not"), capa, list);
   281     ASSERT_EQ(n, 1);
   282     EXPECT_EQ(cx_strcmp(list[0], test), 0);
   284     /* matching single-char delimiter */
   285     n = cx_strsplit(test, cx_str(","), capa, list);
   286     ASSERT_EQ(n, 5);
   287     EXPECT_EQ(cx_strcmp(list[0], cx_str("this")), 0);
   288     EXPECT_EQ(cx_strcmp(list[1], cx_str("is")), 0);
   289     EXPECT_EQ(cx_strcmp(list[2], cx_str("a")), 0);
   290     EXPECT_EQ(cx_strcmp(list[3], cx_str("csv")), 0);
   291     EXPECT_EQ(cx_strcmp(list[4], cx_str("string")), 0);
   293     /* matching multi-char delimiter */
   294     n = cx_strsplit(test, cx_str("is"), capa, list);
   295     ASSERT_EQ(n, 3);
   296     EXPECT_EQ(cx_strcmp(list[0], cx_str("th")), 0);
   297     EXPECT_EQ(cx_strcmp(list[1], cx_str(",")), 0);
   298     EXPECT_EQ(cx_strcmp(list[2], cx_str(",a,csv,string")), 0);
   300     /* bounded list using single-char delimiter */
   301     n = cx_strsplit(test, cx_str(","), 3, list);
   302     ASSERT_EQ(n, 3);
   303     EXPECT_EQ(cx_strcmp(list[0], cx_str("this")), 0);
   304     EXPECT_EQ(cx_strcmp(list[1], cx_str("is")), 0);
   305     EXPECT_EQ(cx_strcmp(list[2], cx_str("a,csv,string")), 0);
   307     /* bounded list using multi-char delimiter */
   308     n = cx_strsplit(test, cx_str("is"), 2, list);
   309     ASSERT_EQ(n, 2);
   310     EXPECT_EQ(cx_strcmp(list[0], cx_str("th")), 0);
   311     EXPECT_EQ(cx_strcmp(list[1], cx_str(",is,a,csv,string")), 0);
   313     /* start with delimiter */
   314     n = cx_strsplit(test, cx_str("this"), capa, list);
   315     ASSERT_EQ(n, 2);
   316     EXPECT_EQ(cx_strcmp(list[0], cx_str("")), 0);
   317     EXPECT_EQ(cx_strcmp(list[1], cx_str(",is,a,csv,string")), 0);
   319     /* end with delimiter */
   320     n = cx_strsplit(test, cx_str("string"), capa, list);
   321     ASSERT_EQ(n, 2);
   322     EXPECT_EQ(cx_strcmp(list[0], cx_str("this,is,a,csv,")), 0);
   323     EXPECT_EQ(cx_strcmp(list[1], cx_str("")), 0);
   326     /* end with delimiter exceed bound */
   327     n = cx_strsplit(cx_str("a,b,c,"), cx_str(","), 3, list);
   328     ASSERT_EQ(n, 3);
   329     EXPECT_EQ(cx_strcmp(list[0], cx_str("a")), 0);
   330     EXPECT_EQ(cx_strcmp(list[1], cx_str("b")), 0);
   331     EXPECT_EQ(cx_strcmp(list[2], cx_str("c,")), 0);
   333     /* exact match */
   334     n = cx_strsplit(test, cx_str("this,is,a,csv,string"), capa, list);
   335     ASSERT_EQ(n, 2);
   336     EXPECT_EQ(cx_strcmp(list[0], cx_str("")), 0);
   337     EXPECT_EQ(cx_strcmp(list[1], cx_str("")), 0);
   339     /* string to be split is only substring */
   340     n = cx_strsplit(test, cx_str("this,is,a,csv,string,with,extension"), capa, list);
   341     ASSERT_EQ(n, 1);
   342     EXPECT_EQ(cx_strcmp(list[0], test), 0);
   344     /* subsequent encounter of delimiter (the string between is empty) */
   345     n = cx_strsplit(test, cx_str("is,"), capa, list);
   346     ASSERT_EQ(n, 3);
   347     EXPECT_EQ(cx_strcmp(list[0], cx_str("th")), 0);
   348     EXPECT_EQ(cx_strcmp(list[1], cx_str("")), 0);
   349     EXPECT_EQ(cx_strcmp(list[2], cx_str("a,csv,string")), 0);
   351     /* call the _m variant just for coverage */
   352     auto mtest = cx_strdup(test);
   353     cxmutstr mlist[4];
   354     n = cx_strsplit_m(mtest, cx_str("is,"), 4, mlist);
   355     ASSERT_EQ(n, 3);
   356     EXPECT_EQ(cx_strcmp(cx_strcast(mlist[0]), cx_str("th")), 0);
   357     EXPECT_EQ(cx_strcmp(cx_strcast(mlist[1]), cx_str("")), 0);
   358     EXPECT_EQ(cx_strcmp(cx_strcast(mlist[2]), cx_str("a,csv,string")), 0);
   359     cx_strfree(&mtest);
   360 }
   362 TEST(String, strsplit_a) {
   363     CxTestingAllocator alloc;
   365     cxstring test = cx_str("this,is,a,csv,string");
   366     size_t capa = 8;
   367     cxstring *list;
   368     size_t n;
   370     /* special case: empty string */
   371     n = cx_strsplit_a(&alloc, test, cx_str(""), capa, &list);
   372     ASSERT_EQ(n, 1);
   373     EXPECT_EQ(cx_strcmp(list[0], test), 0);
   374     cxFree(&alloc, list);
   376     /* no delimiter occurrence */
   377     n = cx_strsplit_a(&alloc, test, cx_str("z"), capa, &list);
   378     ASSERT_EQ(n, 1);
   379     EXPECT_EQ(cx_strcmp(list[0], test), 0);
   380     cxFree(&alloc, list);
   382     /* partially matching delimiter */
   383     n = cx_strsplit_a(&alloc, test, cx_str("is,not"), capa, &list);
   384     ASSERT_EQ(n, 1);
   385     EXPECT_EQ(cx_strcmp(list[0], test), 0);
   386     cxFree(&alloc, list);
   388     /* matching single-char delimiter */
   389     n = cx_strsplit_a(&alloc, test, cx_str(","), capa, &list);
   390     ASSERT_EQ(n, 5);
   391     EXPECT_EQ(cx_strcmp(list[0], cx_str("this")), 0);
   392     EXPECT_EQ(cx_strcmp(list[1], cx_str("is")), 0);
   393     EXPECT_EQ(cx_strcmp(list[2], cx_str("a")), 0);
   394     EXPECT_EQ(cx_strcmp(list[3], cx_str("csv")), 0);
   395     EXPECT_EQ(cx_strcmp(list[4], cx_str("string")), 0);
   396     cxFree(&alloc, list);
   398     /* matching multi-char delimiter */
   399     n = cx_strsplit_a(&alloc, test, cx_str("is"), capa, &list);
   400     ASSERT_EQ(n, 3);
   401     EXPECT_EQ(cx_strcmp(list[0], cx_str("th")), 0);
   402     EXPECT_EQ(cx_strcmp(list[1], cx_str(",")), 0);
   403     EXPECT_EQ(cx_strcmp(list[2], cx_str(",a,csv,string")), 0);
   404     cxFree(&alloc, list);
   406     /* bounded list using single-char delimiter */
   407     n = cx_strsplit_a(&alloc, test, cx_str(","), 3, &list);
   408     ASSERT_EQ(n, 3);
   409     EXPECT_EQ(cx_strcmp(list[0], cx_str("this")), 0);
   410     EXPECT_EQ(cx_strcmp(list[1], cx_str("is")), 0);
   411     EXPECT_EQ(cx_strcmp(list[2], cx_str("a,csv,string")), 0);
   412     cxFree(&alloc, list);
   414     /* bounded list using multi-char delimiter */
   415     n = cx_strsplit_a(&alloc, test, cx_str("is"), 2, &list);
   416     ASSERT_EQ(n, 2);
   417     EXPECT_EQ(cx_strcmp(list[0], cx_str("th")), 0);
   418     EXPECT_EQ(cx_strcmp(list[1], cx_str(",is,a,csv,string")), 0);
   419     cxFree(&alloc, list);
   421     /* start with delimiter */
   422     n = cx_strsplit_a(&alloc, test, cx_str("this"), capa, &list);
   423     ASSERT_EQ(n, 2);
   424     EXPECT_EQ(cx_strcmp(list[0], cx_str("")), 0);
   425     EXPECT_EQ(cx_strcmp(list[1], cx_str(",is,a,csv,string")), 0);
   426     cxFree(&alloc, list);
   428     /* end with delimiter */
   429     n = cx_strsplit_a(&alloc, test, cx_str("string"), capa, &list);
   430     ASSERT_EQ(n, 2);
   431     EXPECT_EQ(cx_strcmp(list[0], cx_str("this,is,a,csv,")), 0);
   432     EXPECT_EQ(cx_strcmp(list[1], cx_str("")), 0);
   433     cxFree(&alloc, list);
   435     /* end with delimiter exceed bound */
   436     n = cx_strsplit_a(&alloc, cx_str("a,b,c,"), cx_str(","), 3, &list);
   437     ASSERT_EQ(n, 3);
   438     EXPECT_EQ(cx_strcmp(list[0], cx_str("a")), 0);
   439     EXPECT_EQ(cx_strcmp(list[1], cx_str("b")), 0);
   440     EXPECT_EQ(cx_strcmp(list[2], cx_str("c,")), 0);
   441     cxFree(&alloc, list);
   443     /* exact match */
   444     n = cx_strsplit_a(&alloc, test, cx_str("this,is,a,csv,string"), capa, &list);
   445     ASSERT_EQ(n, 2);
   446     EXPECT_EQ(cx_strcmp(list[0], cx_str("")), 0);
   447     EXPECT_EQ(cx_strcmp(list[1], cx_str("")), 0);
   448     cxFree(&alloc, list);
   450     /* string to be split is only substring */
   451     n = cx_strsplit_a(&alloc, test, cx_str("this,is,a,csv,string,with,extension"), capa, &list);
   452     ASSERT_EQ(n, 1);
   453     EXPECT_EQ(cx_strcmp(list[0], test), 0);
   454     cxFree(&alloc, list);
   456     /* subsequent encounter of delimiter (the string between is empty) */
   457     n = cx_strsplit_a(&alloc, test, cx_str("is,"), capa, &list);
   458     ASSERT_EQ(n, 3);
   459     EXPECT_EQ(cx_strcmp(list[0], cx_str("th")), 0);
   460     EXPECT_EQ(cx_strcmp(list[1], cx_str("")), 0);
   461     EXPECT_EQ(cx_strcmp(list[2], cx_str("a,csv,string")), 0);
   462     cxFree(&alloc, list);
   464     /* call the _m variant just for coverage */
   465     auto mtest = cx_strdup(test);
   466     cxmutstr *mlist;
   467     n = cx_strsplit_ma(&alloc, mtest, cx_str("is,"), 4, &mlist);
   468     ASSERT_EQ(n, 3);
   469     EXPECT_EQ(cx_strcmp(cx_strcast(mlist[0]), cx_str("th")), 0);
   470     EXPECT_EQ(cx_strcmp(cx_strcast(mlist[1]), cx_str("")), 0);
   471     EXPECT_EQ(cx_strcmp(cx_strcast(mlist[2]), cx_str("a,csv,string")), 0);
   472     cxFree(&alloc, mlist);
   473     cx_strfree(&mtest);
   475     EXPECT_TRUE(alloc.verify());
   476 }
   478 TEST(String, strtrim) {
   479     cxstring t1 = cx_strtrim(cx_str("  ein test  \t "));
   480     cxstring t2 = cx_strtrim(cx_str("abc"));
   481     cxstring t3 = cx_strtrim(cx_str(" 123"));
   482     cxstring t4 = cx_strtrim(cx_str("xyz "));
   483     cxstring t5 = cx_strtrim(cx_str("   "));
   484     cxstring empty = cx_strtrim(cx_str(""));
   486     EXPECT_EQ(cx_strcmp(t1, cx_str("ein test")), 0);
   487     EXPECT_EQ(cx_strcmp(t2, cx_str("abc")), 0);
   488     EXPECT_EQ(cx_strcmp(t3, cx_str("123")), 0);
   489     EXPECT_EQ(cx_strcmp(t4, cx_str("xyz")), 0);
   490     EXPECT_EQ(cx_strcmp(t5, cx_str("")), 0);
   491     EXPECT_EQ(cx_strcmp(empty, cx_str("")), 0);
   493     /* call the _m variant just for coverage */
   494     cxmutstr m1 = cx_strtrim_m(cx_mutstr((char *) "  ein test  \t "));
   495     EXPECT_EQ(cx_strcmp(cx_strcast(m1), cx_str("ein test")), 0);
   496 }
   498 TEST(String, strprefix) {
   499     cxstring str = CX_STR("test my prefix and my suffix");
   500     cxstring empty = CX_STR("");
   501     EXPECT_FALSE(cx_strprefix(empty, cx_str("pref")));
   502     EXPECT_TRUE(cx_strprefix(str, empty));
   503     EXPECT_TRUE(cx_strprefix(empty, empty));
   504     EXPECT_TRUE(cx_strprefix(str, cx_str("test ")));
   505     EXPECT_FALSE(cx_strprefix(str, cx_str("8-) fsck ")));
   506 }
   508 TEST(String, strsuffix) {
   509     cxstring str = CX_STR("test my prefix and my suffix");
   510     cxstring empty = CX_STR("");
   511     EXPECT_FALSE(cx_strsuffix(empty, cx_str("suf")));
   512     EXPECT_TRUE(cx_strsuffix(str, empty));
   513     EXPECT_TRUE(cx_strsuffix(empty, empty));
   514     EXPECT_TRUE(cx_strsuffix(str, cx_str("fix")));
   515     EXPECT_FALSE(cx_strsuffix(str, cx_str("fox")));
   516 }
   518 TEST(String, strcaseprefix) {
   519     cxstring str = CX_STR("test my prefix and my suffix");
   520     cxstring empty = CX_STR("");
   521     EXPECT_FALSE(cx_strcaseprefix(empty, cx_str("pREf")));
   522     EXPECT_TRUE(cx_strcaseprefix(str, empty));
   523     EXPECT_TRUE(cx_strcaseprefix(empty, empty));
   524     EXPECT_TRUE(cx_strcaseprefix(str, cx_str("TEST ")));
   525     EXPECT_FALSE(cx_strcaseprefix(str, cx_str("8-) fsck ")));
   526 }
   528 TEST(String, strcasesuffix) {
   529     cxstring str = CX_STR("test my prefix and my suffix");
   530     cxstring empty = CX_STR("");
   531     EXPECT_FALSE(cx_strcasesuffix(empty, cx_str("sUf")));
   532     EXPECT_TRUE(cx_strcasesuffix(str, empty));
   533     EXPECT_TRUE(cx_strcasesuffix(empty, empty));
   534     EXPECT_TRUE(cx_strcasesuffix(str, cx_str("FIX")));
   535     EXPECT_FALSE(cx_strcasesuffix(str, cx_str("fox")));
   536 }
   538 TEST(String, strreplace) {
   539     cxstring str = CX_STR("test ababab string aba");
   540     cxstring longstr = CX_STR(
   541             "xyaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacd");
   542     cxstring notrail = CX_STR("test abab");
   543     cxstring empty = CX_STR("");
   544     cxstring astr = CX_STR("aaaaaaaaaa");
   545     cxstring csstr = CX_STR("test AB ab TEST xyz");
   547     cxmutstr repl = cx_strreplace(str, cx_str("abab"), cx_str("muchlonger"));
   548     auto expected = "test muchlongerab string aba";
   550     cxmutstr repln = cx_strreplacen(str, cx_str("ab"), cx_str("c"), 2);
   551     auto expectedn = "test ccab string aba";
   553     cxmutstr longrepl = cx_strreplace(longstr, cx_str("a"), cx_str("z"));
   554     auto longexpect = "xyzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzcd";
   556     cxmutstr replnotrail = cx_strreplace(notrail, cx_str("ab"), cx_str("z"));
   557     auto notrailexpect = "test zz";
   559     cxmutstr repleq = cx_strreplace(str, str, cx_str("hello"));
   560     auto eqexpect = "hello";
   562     cxmutstr replempty1 = cx_strreplace(empty, cx_str("ab"), cx_str("c")); // expect: empty
   563     cxmutstr replempty2 = cx_strreplace(str, cx_str("abab"), empty);
   564     auto emptyexpect2 = "test ab string aba";
   566     cxmutstr replpre = cx_strreplace(str, cx_str("test "), cx_str("TEST "));
   567     auto preexpected = "TEST ababab string aba";
   569     cxmutstr replan1 = cx_strreplacen(astr, cx_str("a"), cx_str("x"), 1);
   570     auto an1expected = "xaaaaaaaaa";
   572     cxmutstr replan4 = cx_strreplacen(astr, cx_str("a"), cx_str("x"), 4);
   573     auto an4expected = "xxxxaaaaaa";
   575     cxmutstr replan9 = cx_strreplacen(astr, cx_str("a"), cx_str("x"), 9);
   576     auto an9expected = "xxxxxxxxxa";
   578     cxmutstr replan10 = cx_strreplacen(astr, cx_str("a"), cx_str("x"), 10);
   579     auto an10expected = "xxxxxxxxxx";
   581     cxmutstr replcs1 = cx_strreplace(csstr, cx_str("AB"), cx_str("*"));
   582     auto cs1expected = "test * ab TEST xyz";
   584     cxmutstr replcs2 = cx_strreplace(csstr, cx_str("test"), cx_str("TEST"));
   585     auto cs2expected = "TEST AB ab TEST xyz";
   588     EXPECT_NE(repl.ptr, str.ptr);
   589     EXPECT_ZERO_TERMINATED(repl);
   590     EXPECT_STREQ(repl.ptr, expected);
   591     EXPECT_ZERO_TERMINATED(repln);
   592     EXPECT_STREQ(repln.ptr, expectedn);
   593     EXPECT_ZERO_TERMINATED(longrepl);
   594     EXPECT_STREQ(longrepl.ptr, longexpect);
   595     EXPECT_ZERO_TERMINATED(replnotrail);
   596     EXPECT_STREQ(replnotrail.ptr, notrailexpect);
   597     EXPECT_ZERO_TERMINATED(repleq);
   598     EXPECT_STREQ(repleq.ptr, eqexpect);
   599     EXPECT_ZERO_TERMINATED(replempty1);
   600     EXPECT_STREQ(replempty1.ptr, "");
   601     EXPECT_ZERO_TERMINATED(replempty2);
   602     EXPECT_STREQ(replempty2.ptr, emptyexpect2);
   603     EXPECT_ZERO_TERMINATED(replpre);
   604     EXPECT_STREQ(replpre.ptr, preexpected);
   605     EXPECT_ZERO_TERMINATED(replan1);
   606     EXPECT_STREQ(replan1.ptr, an1expected);
   607     EXPECT_ZERO_TERMINATED(replan4);
   608     EXPECT_STREQ(replan4.ptr, an4expected);
   609     EXPECT_ZERO_TERMINATED(replan9);
   610     EXPECT_STREQ(replan9.ptr, an9expected);
   611     EXPECT_ZERO_TERMINATED(replan10);
   612     EXPECT_STREQ(replan10.ptr, an10expected);
   613     EXPECT_ZERO_TERMINATED(replcs1);
   614     EXPECT_STREQ(replcs1.ptr, cs1expected);
   615     EXPECT_ZERO_TERMINATED(replcs2);
   616     EXPECT_STREQ(replcs2.ptr, cs2expected);
   618     cx_strfree(&repl);
   619     cx_strfree(&repln);
   620     cx_strfree(&longrepl);
   621     cx_strfree(&replnotrail);
   622     cx_strfree(&repleq);
   623     cx_strfree(&replempty1);
   624     cx_strfree(&replempty2);
   625     cx_strfree(&replpre);
   626     cx_strfree(&replan1);
   627     cx_strfree(&replan4);
   628     cx_strfree(&replan9);
   629     cx_strfree(&replan10);
   630     cx_strfree(&replcs1);
   631     cx_strfree(&replcs2);
   632 }
   634 TEST(String, strupper) {
   635     cxmutstr str = cx_strdup(cx_str("thIs 1s @ Te$t"));
   636     cx_strupper(str);
   637     EXPECT_STREQ(str.ptr, "THIS 1S @ TE$T");
   638     cx_strfree(&str);
   639 }
   641 TEST(String, strlower) {
   642     cxmutstr str = cx_strdup(cx_str("thIs 1s @ Te$t"));
   643     cx_strlower(str);
   644     EXPECT_STREQ(str.ptr, "this 1s @ te$t");
   645     cx_strfree(&str);
   646 }

mercurial