capnproto

FORK: Cap'n Proto serialization/RPC system - core tools and C++ library
git clone https://git.neptards.moe/neptards/capnproto.git
Log | Files | Refs | README | LICENSE

string-test.c++ (12137B)


      1 // Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors
      2 // Licensed under the MIT License:
      3 //
      4 // Permission is hereby granted, free of charge, to any person obtaining a copy
      5 // of this software and associated documentation files (the "Software"), to deal
      6 // in the Software without restriction, including without limitation the rights
      7 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
      8 // copies of the Software, and to permit persons to whom the Software is
      9 // furnished to do so, subject to the following conditions:
     10 //
     11 // The above copyright notice and this permission notice shall be included in
     12 // all copies or substantial portions of the Software.
     13 //
     14 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     15 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     16 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
     17 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     18 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
     19 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
     20 // THE SOFTWARE.
     21 
     22 #include "string.h"
     23 #include <kj/compat/gtest.h>
     24 #include <string>
     25 #include "vector.h"
     26 #include <locale.h>
     27 
     28 namespace kj {
     29 namespace _ {  // private
     30 namespace {
     31 
     32 TEST(String, Str) {
     33   EXPECT_EQ("foobar", str("foo", "bar"));
     34   EXPECT_EQ("1 2 3 4", str(1, " ", 2u, " ", 3l, " ", 4ll));
     35   EXPECT_EQ("1.5 foo 1e15 bar -3", str(1.5f, " foo ", 1e15, " bar ", -3));
     36   EXPECT_EQ("foo", str('f', 'o', 'o'));
     37   EXPECT_EQ("123 234 -123 e7",
     38             str((int8_t)123, " ", (uint8_t)234, " ", (int8_t)-123, " ", hex((uint8_t)0xe7)));
     39   EXPECT_EQ("-128 -32768 -2147483648 -9223372036854775808",
     40       str((signed char)-128, ' ', (signed short)-32768, ' ',
     41           ((int)-2147483647) - 1, ' ', ((long long)-9223372036854775807ll) - 1))
     42   EXPECT_EQ("ff ffff ffffffff ffffffffffffffff",
     43       str(hex((uint8_t)0xff), ' ', hex((uint16_t)0xffff), ' ', hex((uint32_t)0xffffffffu), ' ',
     44           hex((uint64_t)0xffffffffffffffffull)));
     45 
     46   char buf[3] = {'f', 'o', 'o'};
     47   ArrayPtr<char> a = buf;
     48   ArrayPtr<const char> ca = a;
     49   Vector<char> v;
     50   v.addAll(a);
     51   FixedArray<char, 3> f;
     52   memcpy(f.begin(), buf, 3);
     53 
     54   EXPECT_EQ("foo", str(a));
     55   EXPECT_EQ("foo", str(ca));
     56   EXPECT_EQ("foo", str(v));
     57   EXPECT_EQ("foo", str(f));
     58   EXPECT_EQ("foo", str(mv(a)));
     59   EXPECT_EQ("foo", str(mv(ca)));
     60   EXPECT_EQ("foo", str(mv(v)));
     61   EXPECT_EQ("foo", str(mv(f)));
     62 }
     63 
     64 TEST(String, Nullptr) {
     65   EXPECT_EQ(String(nullptr), "");
     66   EXPECT_EQ(StringPtr(String(nullptr)).size(), 0u);
     67   EXPECT_EQ(StringPtr(String(nullptr))[0], '\0');
     68 }
     69 
     70 TEST(String, StartsEndsWith) {
     71   EXPECT_TRUE(StringPtr("foobar").startsWith("foo"));
     72   EXPECT_FALSE(StringPtr("foobar").startsWith("bar"));
     73   EXPECT_FALSE(StringPtr("foobar").endsWith("foo"));
     74   EXPECT_TRUE(StringPtr("foobar").endsWith("bar"));
     75 
     76   EXPECT_FALSE(StringPtr("fo").startsWith("foo"));
     77   EXPECT_FALSE(StringPtr("fo").endsWith("foo"));
     78 
     79   EXPECT_TRUE(StringPtr("foobar").startsWith(""));
     80   EXPECT_TRUE(StringPtr("foobar").endsWith(""));
     81 }
     82 
     83 TEST(String, parseAs) {
     84   EXPECT_EQ(StringPtr("0").parseAs<double>(), 0.0);
     85   EXPECT_EQ(StringPtr("0.0").parseAs<double>(), 0.0);
     86   EXPECT_EQ(StringPtr("1").parseAs<double>(), 1.0);
     87   EXPECT_EQ(StringPtr("1.0").parseAs<double>(), 1.0);
     88   EXPECT_EQ(StringPtr("1e100").parseAs<double>(), 1e100);
     89   EXPECT_EQ(StringPtr("inf").parseAs<double>(), inf());
     90   EXPECT_EQ(StringPtr("infinity").parseAs<double>(), inf());
     91   EXPECT_EQ(StringPtr("INF").parseAs<double>(), inf());
     92   EXPECT_EQ(StringPtr("INFINITY").parseAs<double>(), inf());
     93   EXPECT_EQ(StringPtr("1e100000").parseAs<double>(), inf());
     94   EXPECT_EQ(StringPtr("-inf").parseAs<double>(), -inf());
     95   EXPECT_EQ(StringPtr("-infinity").parseAs<double>(), -inf());
     96   EXPECT_EQ(StringPtr("-INF").parseAs<double>(), -inf());
     97   EXPECT_EQ(StringPtr("-INFINITY").parseAs<double>(), -inf());
     98   EXPECT_EQ(StringPtr("-1e100000").parseAs<double>(), -inf());
     99   EXPECT_TRUE(isNaN(StringPtr("nan").parseAs<double>()));
    100   EXPECT_TRUE(isNaN(StringPtr("NAN").parseAs<double>()));
    101   EXPECT_TRUE(isNaN(StringPtr("NaN").parseAs<double>()));
    102   KJ_EXPECT_THROW_RECOVERABLE_MESSAGE("not contain valid", StringPtr("").parseAs<double>());
    103   KJ_EXPECT_THROW_RECOVERABLE_MESSAGE("not contain valid", StringPtr("a").parseAs<double>());
    104   KJ_EXPECT_THROW_RECOVERABLE_MESSAGE("not contain valid", StringPtr("1a").parseAs<double>());
    105   KJ_EXPECT_THROW_RECOVERABLE_MESSAGE("not contain valid", StringPtr("+-1").parseAs<double>());
    106 
    107   EXPECT_EQ(StringPtr("1").parseAs<float>(), 1.0);
    108 
    109   EXPECT_EQ(StringPtr("1").parseAs<int64_t>(), 1);
    110   EXPECT_EQ(StringPtr("9223372036854775807").parseAs<int64_t>(), 9223372036854775807LL);
    111   EXPECT_EQ(StringPtr("-9223372036854775808").parseAs<int64_t>(), -9223372036854775808ULL);
    112   KJ_EXPECT_THROW_RECOVERABLE_MESSAGE("out-of-range", StringPtr("9223372036854775808").parseAs<int64_t>());
    113   KJ_EXPECT_THROW_RECOVERABLE_MESSAGE("out-of-range", StringPtr("-9223372036854775809").parseAs<int64_t>());
    114   KJ_EXPECT_THROW_RECOVERABLE_MESSAGE("not contain valid", StringPtr("").parseAs<int64_t>());
    115   KJ_EXPECT_THROW_RECOVERABLE_MESSAGE("not contain valid", StringPtr("a").parseAs<int64_t>());
    116   KJ_EXPECT_THROW_RECOVERABLE_MESSAGE("not contain valid", StringPtr("1a").parseAs<int64_t>());
    117   KJ_EXPECT_THROW_RECOVERABLE_MESSAGE("not contain valid", StringPtr("+-1").parseAs<int64_t>());
    118   EXPECT_EQ(StringPtr("010").parseAs<int64_t>(), 10);
    119   EXPECT_EQ(StringPtr("0010").parseAs<int64_t>(), 10);
    120   EXPECT_EQ(StringPtr("0x10").parseAs<int64_t>(), 16);
    121   EXPECT_EQ(StringPtr("0X10").parseAs<int64_t>(), 16);
    122   EXPECT_EQ(StringPtr("-010").parseAs<int64_t>(), -10);
    123   EXPECT_EQ(StringPtr("-0x10").parseAs<int64_t>(), -16);
    124   EXPECT_EQ(StringPtr("-0X10").parseAs<int64_t>(), -16);
    125 
    126   EXPECT_EQ(StringPtr("1").parseAs<uint64_t>(), 1);
    127   EXPECT_EQ(StringPtr("0").parseAs<uint64_t>(), 0);
    128   EXPECT_EQ(StringPtr("18446744073709551615").parseAs<uint64_t>(), 18446744073709551615ULL);
    129   KJ_EXPECT_THROW_RECOVERABLE_MESSAGE("out-of-range", StringPtr("-1").parseAs<uint64_t>());
    130   KJ_EXPECT_THROW_RECOVERABLE_MESSAGE("out-of-range", StringPtr("18446744073709551616").parseAs<uint64_t>());
    131   KJ_EXPECT_THROW_RECOVERABLE_MESSAGE("not contain valid", StringPtr("").parseAs<uint64_t>());
    132   KJ_EXPECT_THROW_RECOVERABLE_MESSAGE("not contain valid", StringPtr("a").parseAs<uint64_t>());
    133   KJ_EXPECT_THROW_RECOVERABLE_MESSAGE("not contain valid", StringPtr("1a").parseAs<uint64_t>());
    134   KJ_EXPECT_THROW_RECOVERABLE_MESSAGE("not contain valid", StringPtr("+-1").parseAs<uint64_t>());
    135 
    136   EXPECT_EQ(StringPtr("1").parseAs<int32_t>(), 1);
    137   EXPECT_EQ(StringPtr("2147483647").parseAs<int32_t>(), 2147483647);
    138   EXPECT_EQ(StringPtr("-2147483648").parseAs<int32_t>(), -2147483648);
    139   KJ_EXPECT_THROW_RECOVERABLE_MESSAGE("out-of-range", StringPtr("2147483648").parseAs<int32_t>());
    140   KJ_EXPECT_THROW_RECOVERABLE_MESSAGE("out-of-range", StringPtr("-2147483649").parseAs<int32_t>());
    141 
    142   EXPECT_EQ(StringPtr("1").parseAs<uint32_t>(), 1);
    143   EXPECT_EQ(StringPtr("0").parseAs<uint32_t>(), 0U);
    144   EXPECT_EQ(StringPtr("4294967295").parseAs<uint32_t>(), 4294967295U);
    145   KJ_EXPECT_THROW_RECOVERABLE_MESSAGE("out-of-range", StringPtr("-1").parseAs<uint32_t>());
    146   KJ_EXPECT_THROW_RECOVERABLE_MESSAGE("out-of-range", StringPtr("4294967296").parseAs<uint32_t>());
    147 
    148   EXPECT_EQ(StringPtr("1").parseAs<int16_t>(), 1);
    149   EXPECT_EQ(StringPtr("1").parseAs<uint16_t>(), 1);
    150   EXPECT_EQ(StringPtr("1").parseAs<int8_t>(), 1);
    151   EXPECT_EQ(StringPtr("1").parseAs<uint8_t>(), 1);
    152   EXPECT_EQ(StringPtr("1").parseAs<char>(), 1);
    153   EXPECT_EQ(StringPtr("1").parseAs<signed char>(), 1);
    154   EXPECT_EQ(StringPtr("1").parseAs<unsigned char>(), 1);
    155   EXPECT_EQ(StringPtr("1").parseAs<short>(), 1);
    156   EXPECT_EQ(StringPtr("1").parseAs<unsigned short>(), 1);
    157   EXPECT_EQ(StringPtr("1").parseAs<int>(), 1);
    158   EXPECT_EQ(StringPtr("1").parseAs<unsigned>(), 1);
    159   EXPECT_EQ(StringPtr("1").parseAs<long>(), 1);
    160   EXPECT_EQ(StringPtr("1").parseAs<unsigned long>(), 1);
    161   EXPECT_EQ(StringPtr("1").parseAs<long long>(), 1);
    162   EXPECT_EQ(StringPtr("1").parseAs<unsigned long long>(), 1);
    163 
    164   EXPECT_EQ(heapString("1").parseAs<int>(), 1);
    165 }
    166 
    167 #if KJ_COMPILER_SUPPORTS_STL_STRING_INTEROP
    168 TEST(String, StlInterop) {
    169   std::string foo = "foo";
    170   StringPtr ptr = foo;
    171   EXPECT_EQ("foo", ptr);
    172 
    173   std::string bar = ptr;
    174   EXPECT_EQ("foo", bar);
    175 
    176   EXPECT_EQ("foo", kj::str(foo));
    177   EXPECT_EQ("foo", kj::heapString(foo));
    178 }
    179 
    180 struct Stringable {
    181   kj::StringPtr toString() { return "foo"; }
    182 };
    183 
    184 TEST(String, ToString) {
    185   EXPECT_EQ("foo", kj::str(Stringable()));
    186 }
    187 #endif
    188 
    189 KJ_TEST("string literals with _kj suffix") {
    190   static constexpr StringPtr FOO = "foo"_kj;
    191   KJ_EXPECT(FOO == "foo", FOO);
    192   KJ_EXPECT(FOO[3] == 0);
    193 
    194   KJ_EXPECT("foo\0bar"_kj == StringPtr("foo\0bar", 7));
    195 
    196   static constexpr ArrayPtr<const char> ARR = "foo"_kj;
    197   KJ_EXPECT(ARR.size() == 3);
    198   KJ_EXPECT(kj::str(ARR) == "foo");
    199 }
    200 
    201 KJ_TEST("kj::delimited() and kj::strPreallocated()") {
    202   int rawArray[] = {1, 23, 456, 78};
    203   ArrayPtr<int> array = rawArray;
    204   KJ_EXPECT(str(delimited(array, "::")) == "1::23::456::78");
    205 
    206   {
    207     char buffer[256];
    208     KJ_EXPECT(strPreallocated(buffer, delimited(array, "::"), 'x')
    209         == "1::23::456::78x");
    210     KJ_EXPECT(strPreallocated(buffer, "foo", 123, true) == "foo123true");
    211   }
    212 
    213   {
    214     char buffer[5];
    215     KJ_EXPECT(strPreallocated(buffer, delimited(array, "::"), 'x') == "1::2");
    216     KJ_EXPECT(strPreallocated(buffer, "foo", 123, true) == "foo1");
    217   }
    218 }
    219 
    220 KJ_TEST("parsing 'nan' returns canonical NaN value") {
    221   // There are many representations of NaN. We would prefer that parsing "NaN" produces exactly the
    222   // same bits that kj::nan() returns.
    223   {
    224     double parsedNan = StringPtr("NaN").parseAs<double>();
    225     double canonicalNan = kj::nan();
    226     KJ_EXPECT(memcmp(&parsedNan, &canonicalNan, sizeof(parsedNan)) == 0);
    227   }
    228   {
    229     float parsedNan = StringPtr("NaN").parseAs<float>();
    230     float canonicalNan = kj::nan();
    231     KJ_EXPECT(memcmp(&parsedNan, &canonicalNan, sizeof(parsedNan)) == 0);
    232   }
    233 }
    234 
    235 KJ_TEST("stringify array-of-array") {
    236   int arr1[] = {1, 23};
    237   int arr2[] = {456, 7890};
    238   ArrayPtr<int> arr3[] = {arr1, arr2};
    239   ArrayPtr<ArrayPtr<int>> array = arr3;
    240 
    241   KJ_EXPECT(str(array) == "1, 23, 456, 7890");
    242 }
    243 
    244 KJ_TEST("ArrayPtr == StringPtr") {
    245   StringPtr s = "foo"_kj;
    246   ArrayPtr<const char> a = s;
    247 
    248   KJ_EXPECT(a == s);
    249 #if __cplusplus >= 202000L
    250   KJ_EXPECT(s == a);
    251 #endif
    252 }
    253 
    254 KJ_TEST("String == String") {
    255   String a = kj::str("foo");
    256   String b = kj::str("foo");
    257   String c = kj::str("bar");
    258 
    259   // We're trying to trigger the -Wambiguous-reversed-operator warning in Clang, but it seems
    260   // magic asserts inadvertently squelch it. So, we use an alternate macro with no magic.
    261 #define KJ_EXPECT_NOMAGIC(cond) \
    262     if (cond) {} else { KJ_FAIL_ASSERT("expected " #cond); }
    263 
    264   KJ_EXPECT_NOMAGIC(a == a);
    265   KJ_EXPECT_NOMAGIC(a == b);
    266   KJ_EXPECT_NOMAGIC(a != c);
    267 }
    268 
    269 KJ_TEST("float stringification and parsing is not locale-dependent") {
    270   // Remember the old locale, set it back when we're done.
    271   char* oldLocaleCstr = setlocale(LC_NUMERIC, nullptr);
    272   KJ_ASSERT(oldLocaleCstr != nullptr);
    273   auto oldLocale = kj::str(oldLocaleCstr);
    274   KJ_DEFER(setlocale(LC_NUMERIC, oldLocale.cStr()));
    275 
    276   // Set the locale to "C".
    277   KJ_ASSERT(setlocale(LC_NUMERIC, "C") != nullptr);
    278 
    279   KJ_ASSERT(kj::str(1.5) == "1.5");
    280   KJ_ASSERT(kj::str(1.5f) == "1.5");
    281   KJ_EXPECT("1.5"_kj.parseAs<float>() == 1.5);
    282   KJ_EXPECT("1.5"_kj.parseAs<double>() == 1.5);
    283 
    284   if (setlocale(LC_NUMERIC, "es_ES") == nullptr &&
    285       setlocale(LC_NUMERIC, "es_ES.utf8") == nullptr &&
    286       setlocale(LC_NUMERIC, "es_ES.UTF-8") == nullptr) {
    287     // Some systems may not have the desired locale available.
    288     KJ_LOG(WARNING, "Couldn't set locale to es_ES. Skipping this test.");
    289   } else {
    290     KJ_EXPECT(kj::str(1.5) == "1.5");
    291     KJ_EXPECT(kj::str(1.5f) == "1.5");
    292     KJ_EXPECT("1.5"_kj.parseAs<float>() == 1.5);
    293     KJ_EXPECT("1.5"_kj.parseAs<double>() == 1.5);
    294   }
    295 }
    296 }  // namespace
    297 }  // namespace _ (private)
    298 }  // namespace kj