11cb0ef41Sopenharmony_ci#include "debug_utils-inl.h" 21cb0ef41Sopenharmony_ci#include "env-inl.h" 31cb0ef41Sopenharmony_ci#include "gtest/gtest.h" 41cb0ef41Sopenharmony_ci#include "simdutf.h" 51cb0ef41Sopenharmony_ci#include "util-inl.h" 61cb0ef41Sopenharmony_ci 71cb0ef41Sopenharmony_ciusing node::Calloc; 81cb0ef41Sopenharmony_ciusing node::Malloc; 91cb0ef41Sopenharmony_ciusing node::MaybeStackBuffer; 101cb0ef41Sopenharmony_ciusing node::SPrintF; 111cb0ef41Sopenharmony_ciusing node::StringEqualNoCase; 121cb0ef41Sopenharmony_ciusing node::StringEqualNoCaseN; 131cb0ef41Sopenharmony_ciusing node::ToLower; 141cb0ef41Sopenharmony_ciusing node::UncheckedCalloc; 151cb0ef41Sopenharmony_ciusing node::UncheckedMalloc; 161cb0ef41Sopenharmony_ci 171cb0ef41Sopenharmony_ciTEST(UtilTest, ListHead) { 181cb0ef41Sopenharmony_ci struct Item { node::ListNode<Item> node_; }; 191cb0ef41Sopenharmony_ci typedef node::ListHead<Item, &Item::node_> List; 201cb0ef41Sopenharmony_ci 211cb0ef41Sopenharmony_ci List list; 221cb0ef41Sopenharmony_ci EXPECT_TRUE(list.IsEmpty()); 231cb0ef41Sopenharmony_ci 241cb0ef41Sopenharmony_ci Item one; 251cb0ef41Sopenharmony_ci EXPECT_TRUE(one.node_.IsEmpty()); 261cb0ef41Sopenharmony_ci 271cb0ef41Sopenharmony_ci list.PushBack(&one); 281cb0ef41Sopenharmony_ci EXPECT_FALSE(list.IsEmpty()); 291cb0ef41Sopenharmony_ci EXPECT_FALSE(one.node_.IsEmpty()); 301cb0ef41Sopenharmony_ci 311cb0ef41Sopenharmony_ci { 321cb0ef41Sopenharmony_ci List::Iterator it = list.begin(); 331cb0ef41Sopenharmony_ci EXPECT_NE(list.end(), it); 341cb0ef41Sopenharmony_ci EXPECT_EQ(&one, *it); 351cb0ef41Sopenharmony_ci ++it; 361cb0ef41Sopenharmony_ci EXPECT_FALSE(it != list.end()); // Iterator only implements != operator. 371cb0ef41Sopenharmony_ci } 381cb0ef41Sopenharmony_ci 391cb0ef41Sopenharmony_ci Item two; 401cb0ef41Sopenharmony_ci list.PushBack(&two); 411cb0ef41Sopenharmony_ci 421cb0ef41Sopenharmony_ci { 431cb0ef41Sopenharmony_ci List::Iterator it = list.begin(); 441cb0ef41Sopenharmony_ci EXPECT_NE(list.end(), it); 451cb0ef41Sopenharmony_ci EXPECT_EQ(&one, *it); 461cb0ef41Sopenharmony_ci ++it; 471cb0ef41Sopenharmony_ci EXPECT_NE(list.end(), it); 481cb0ef41Sopenharmony_ci EXPECT_EQ(&two, *it); 491cb0ef41Sopenharmony_ci ++it; 501cb0ef41Sopenharmony_ci EXPECT_FALSE(it != list.end()); // Iterator only implements != operator. 511cb0ef41Sopenharmony_ci } 521cb0ef41Sopenharmony_ci 531cb0ef41Sopenharmony_ci EXPECT_EQ(&one, list.PopFront()); 541cb0ef41Sopenharmony_ci EXPECT_TRUE(one.node_.IsEmpty()); 551cb0ef41Sopenharmony_ci EXPECT_FALSE(list.IsEmpty()); 561cb0ef41Sopenharmony_ci 571cb0ef41Sopenharmony_ci { 581cb0ef41Sopenharmony_ci List::Iterator it = list.begin(); 591cb0ef41Sopenharmony_ci EXPECT_NE(list.end(), it); 601cb0ef41Sopenharmony_ci EXPECT_EQ(&two, *it); 611cb0ef41Sopenharmony_ci ++it; 621cb0ef41Sopenharmony_ci EXPECT_FALSE(it != list.end()); // Iterator only implements != operator. 631cb0ef41Sopenharmony_ci } 641cb0ef41Sopenharmony_ci 651cb0ef41Sopenharmony_ci EXPECT_EQ(&two, list.PopFront()); 661cb0ef41Sopenharmony_ci EXPECT_TRUE(two.node_.IsEmpty()); 671cb0ef41Sopenharmony_ci EXPECT_TRUE(list.IsEmpty()); 681cb0ef41Sopenharmony_ci EXPECT_FALSE(list.begin() != list.end()); 691cb0ef41Sopenharmony_ci} 701cb0ef41Sopenharmony_ci 711cb0ef41Sopenharmony_ciTEST(UtilTest, StringEqualNoCase) { 721cb0ef41Sopenharmony_ci EXPECT_FALSE(StringEqualNoCase("a", "b")); 731cb0ef41Sopenharmony_ci EXPECT_TRUE(StringEqualNoCase("", "")); 741cb0ef41Sopenharmony_ci EXPECT_TRUE(StringEqualNoCase("equal", "equal")); 751cb0ef41Sopenharmony_ci EXPECT_TRUE(StringEqualNoCase("equal", "EQUAL")); 761cb0ef41Sopenharmony_ci EXPECT_TRUE(StringEqualNoCase("EQUAL", "EQUAL")); 771cb0ef41Sopenharmony_ci EXPECT_FALSE(StringEqualNoCase("equal", "equals")); 781cb0ef41Sopenharmony_ci EXPECT_FALSE(StringEqualNoCase("equals", "equal")); 791cb0ef41Sopenharmony_ci} 801cb0ef41Sopenharmony_ci 811cb0ef41Sopenharmony_ciTEST(UtilTest, StringEqualNoCaseN) { 821cb0ef41Sopenharmony_ci EXPECT_FALSE(StringEqualNoCaseN("a", "b", strlen("a"))); 831cb0ef41Sopenharmony_ci EXPECT_TRUE(StringEqualNoCaseN("", "", strlen(""))); 841cb0ef41Sopenharmony_ci EXPECT_TRUE(StringEqualNoCaseN("equal", "equal", strlen("equal"))); 851cb0ef41Sopenharmony_ci EXPECT_TRUE(StringEqualNoCaseN("equal", "EQUAL", strlen("equal"))); 861cb0ef41Sopenharmony_ci EXPECT_TRUE(StringEqualNoCaseN("EQUAL", "EQUAL", strlen("equal"))); 871cb0ef41Sopenharmony_ci EXPECT_TRUE(StringEqualNoCaseN("equal", "equals", strlen("equal"))); 881cb0ef41Sopenharmony_ci EXPECT_FALSE(StringEqualNoCaseN("equal", "equals", strlen("equals"))); 891cb0ef41Sopenharmony_ci EXPECT_TRUE(StringEqualNoCaseN("equals", "equal", strlen("equal"))); 901cb0ef41Sopenharmony_ci EXPECT_FALSE(StringEqualNoCaseN("equals", "equal", strlen("equals"))); 911cb0ef41Sopenharmony_ci EXPECT_TRUE(StringEqualNoCaseN("abc\0abc", "abc\0efg", strlen("abcdefgh"))); 921cb0ef41Sopenharmony_ci EXPECT_FALSE(StringEqualNoCaseN("abc\0abc", "abcd\0efg", strlen("abcdefgh"))); 931cb0ef41Sopenharmony_ci} 941cb0ef41Sopenharmony_ci 951cb0ef41Sopenharmony_ciTEST(UtilTest, ToLower) { 961cb0ef41Sopenharmony_ci EXPECT_EQ('0', ToLower('0')); 971cb0ef41Sopenharmony_ci EXPECT_EQ('a', ToLower('a')); 981cb0ef41Sopenharmony_ci EXPECT_EQ('a', ToLower('A')); 991cb0ef41Sopenharmony_ci} 1001cb0ef41Sopenharmony_ci 1011cb0ef41Sopenharmony_ci#define TEST_AND_FREE(expression, size) \ 1021cb0ef41Sopenharmony_ci do { \ 1031cb0ef41Sopenharmony_ci auto pointer = expression(size); \ 1041cb0ef41Sopenharmony_ci EXPECT_EQ(pointer == nullptr, size == 0); \ 1051cb0ef41Sopenharmony_ci free(pointer); \ 1061cb0ef41Sopenharmony_ci } while (0) 1071cb0ef41Sopenharmony_ci 1081cb0ef41Sopenharmony_ciTEST(UtilTest, Malloc) { 1091cb0ef41Sopenharmony_ci TEST_AND_FREE(Malloc<char>, 0); 1101cb0ef41Sopenharmony_ci TEST_AND_FREE(Malloc<char>, 1); 1111cb0ef41Sopenharmony_ci TEST_AND_FREE(Malloc, 0); 1121cb0ef41Sopenharmony_ci TEST_AND_FREE(Malloc, 1); 1131cb0ef41Sopenharmony_ci} 1141cb0ef41Sopenharmony_ci 1151cb0ef41Sopenharmony_ciTEST(UtilTest, Calloc) { 1161cb0ef41Sopenharmony_ci TEST_AND_FREE(Calloc<char>, 0); 1171cb0ef41Sopenharmony_ci TEST_AND_FREE(Calloc<char>, 1); 1181cb0ef41Sopenharmony_ci TEST_AND_FREE(Calloc, 0); 1191cb0ef41Sopenharmony_ci TEST_AND_FREE(Calloc, 1); 1201cb0ef41Sopenharmony_ci} 1211cb0ef41Sopenharmony_ci 1221cb0ef41Sopenharmony_ciTEST(UtilTest, UncheckedMalloc) { 1231cb0ef41Sopenharmony_ci TEST_AND_FREE(UncheckedMalloc<char>, 0); 1241cb0ef41Sopenharmony_ci TEST_AND_FREE(UncheckedMalloc<char>, 1); 1251cb0ef41Sopenharmony_ci TEST_AND_FREE(UncheckedMalloc, 0); 1261cb0ef41Sopenharmony_ci TEST_AND_FREE(UncheckedMalloc, 1); 1271cb0ef41Sopenharmony_ci} 1281cb0ef41Sopenharmony_ci 1291cb0ef41Sopenharmony_ciTEST(UtilTest, UncheckedCalloc) { 1301cb0ef41Sopenharmony_ci TEST_AND_FREE(UncheckedCalloc<char>, 0); 1311cb0ef41Sopenharmony_ci TEST_AND_FREE(UncheckedCalloc<char>, 1); 1321cb0ef41Sopenharmony_ci TEST_AND_FREE(UncheckedCalloc, 0); 1331cb0ef41Sopenharmony_ci TEST_AND_FREE(UncheckedCalloc, 1); 1341cb0ef41Sopenharmony_ci} 1351cb0ef41Sopenharmony_ci 1361cb0ef41Sopenharmony_citemplate <typename T> 1371cb0ef41Sopenharmony_cistatic void MaybeStackBufferBasic() { 1381cb0ef41Sopenharmony_ci MaybeStackBuffer<T> buf; 1391cb0ef41Sopenharmony_ci size_t old_length; 1401cb0ef41Sopenharmony_ci size_t old_capacity; 1411cb0ef41Sopenharmony_ci 1421cb0ef41Sopenharmony_ci // Default constructor. 1431cb0ef41Sopenharmony_ci EXPECT_EQ(0U, buf.length()); 1441cb0ef41Sopenharmony_ci EXPECT_FALSE(buf.IsAllocated()); 1451cb0ef41Sopenharmony_ci EXPECT_GT(buf.capacity(), buf.length()); 1461cb0ef41Sopenharmony_ci 1471cb0ef41Sopenharmony_ci // SetLength() expansion. 1481cb0ef41Sopenharmony_ci buf.SetLength(buf.capacity()); 1491cb0ef41Sopenharmony_ci EXPECT_EQ(buf.capacity(), buf.length()); 1501cb0ef41Sopenharmony_ci EXPECT_FALSE(buf.IsAllocated()); 1511cb0ef41Sopenharmony_ci 1521cb0ef41Sopenharmony_ci // Means of accessing raw buffer. 1531cb0ef41Sopenharmony_ci EXPECT_EQ(buf.out(), *buf); 1541cb0ef41Sopenharmony_ci EXPECT_EQ(&buf[0], *buf); 1551cb0ef41Sopenharmony_ci 1561cb0ef41Sopenharmony_ci // Basic I/O. 1571cb0ef41Sopenharmony_ci for (size_t i = 0; i < buf.length(); i++) 1581cb0ef41Sopenharmony_ci buf[i] = static_cast<T>(i); 1591cb0ef41Sopenharmony_ci for (size_t i = 0; i < buf.length(); i++) 1601cb0ef41Sopenharmony_ci EXPECT_EQ(static_cast<T>(i), buf[i]); 1611cb0ef41Sopenharmony_ci 1621cb0ef41Sopenharmony_ci // SetLengthAndZeroTerminate(). 1631cb0ef41Sopenharmony_ci buf.SetLengthAndZeroTerminate(buf.capacity() - 1); 1641cb0ef41Sopenharmony_ci EXPECT_EQ(buf.capacity() - 1, buf.length()); 1651cb0ef41Sopenharmony_ci for (size_t i = 0; i < buf.length(); i++) 1661cb0ef41Sopenharmony_ci EXPECT_EQ(static_cast<T>(i), buf[i]); 1671cb0ef41Sopenharmony_ci buf.SetLength(buf.capacity()); 1681cb0ef41Sopenharmony_ci EXPECT_EQ(0, buf[buf.length() - 1]); 1691cb0ef41Sopenharmony_ci 1701cb0ef41Sopenharmony_ci // Initial Realloc. 1711cb0ef41Sopenharmony_ci old_length = buf.length() - 1; 1721cb0ef41Sopenharmony_ci old_capacity = buf.capacity(); 1731cb0ef41Sopenharmony_ci buf.AllocateSufficientStorage(buf.capacity() * 2); 1741cb0ef41Sopenharmony_ci EXPECT_EQ(buf.capacity(), buf.length()); 1751cb0ef41Sopenharmony_ci EXPECT_TRUE(buf.IsAllocated()); 1761cb0ef41Sopenharmony_ci for (size_t i = 0; i < old_length; i++) 1771cb0ef41Sopenharmony_ci EXPECT_EQ(static_cast<T>(i), buf[i]); 1781cb0ef41Sopenharmony_ci EXPECT_EQ(0, buf[old_length]); 1791cb0ef41Sopenharmony_ci 1801cb0ef41Sopenharmony_ci // SetLength() reduction and expansion. 1811cb0ef41Sopenharmony_ci for (size_t i = 0; i < buf.length(); i++) 1821cb0ef41Sopenharmony_ci buf[i] = static_cast<T>(i); 1831cb0ef41Sopenharmony_ci buf.SetLength(10); 1841cb0ef41Sopenharmony_ci for (size_t i = 0; i < buf.length(); i++) 1851cb0ef41Sopenharmony_ci EXPECT_EQ(static_cast<T>(i), buf[i]); 1861cb0ef41Sopenharmony_ci buf.SetLength(buf.capacity()); 1871cb0ef41Sopenharmony_ci for (size_t i = 0; i < buf.length(); i++) 1881cb0ef41Sopenharmony_ci EXPECT_EQ(static_cast<T>(i), buf[i]); 1891cb0ef41Sopenharmony_ci 1901cb0ef41Sopenharmony_ci // Subsequent Realloc. 1911cb0ef41Sopenharmony_ci old_length = buf.length(); 1921cb0ef41Sopenharmony_ci old_capacity = buf.capacity(); 1931cb0ef41Sopenharmony_ci buf.AllocateSufficientStorage(old_capacity * 1.5); 1941cb0ef41Sopenharmony_ci EXPECT_EQ(buf.capacity(), buf.length()); 1951cb0ef41Sopenharmony_ci EXPECT_EQ(static_cast<size_t>(old_capacity * 1.5), buf.length()); 1961cb0ef41Sopenharmony_ci EXPECT_TRUE(buf.IsAllocated()); 1971cb0ef41Sopenharmony_ci for (size_t i = 0; i < old_length; i++) 1981cb0ef41Sopenharmony_ci EXPECT_EQ(static_cast<T>(i), buf[i]); 1991cb0ef41Sopenharmony_ci 2001cb0ef41Sopenharmony_ci // Basic I/O on Realloc'd buffer. 2011cb0ef41Sopenharmony_ci for (size_t i = 0; i < buf.length(); i++) 2021cb0ef41Sopenharmony_ci buf[i] = static_cast<T>(i); 2031cb0ef41Sopenharmony_ci for (size_t i = 0; i < buf.length(); i++) 2041cb0ef41Sopenharmony_ci EXPECT_EQ(static_cast<T>(i), buf[i]); 2051cb0ef41Sopenharmony_ci 2061cb0ef41Sopenharmony_ci // Release(). 2071cb0ef41Sopenharmony_ci T* rawbuf = buf.out(); 2081cb0ef41Sopenharmony_ci buf.Release(); 2091cb0ef41Sopenharmony_ci EXPECT_EQ(0U, buf.length()); 2101cb0ef41Sopenharmony_ci EXPECT_FALSE(buf.IsAllocated()); 2111cb0ef41Sopenharmony_ci EXPECT_GT(buf.capacity(), buf.length()); 2121cb0ef41Sopenharmony_ci free(rawbuf); 2131cb0ef41Sopenharmony_ci} 2141cb0ef41Sopenharmony_ci 2151cb0ef41Sopenharmony_ciTEST(UtilTest, MaybeStackBuffer) { 2161cb0ef41Sopenharmony_ci MaybeStackBufferBasic<uint8_t>(); 2171cb0ef41Sopenharmony_ci MaybeStackBufferBasic<uint16_t>(); 2181cb0ef41Sopenharmony_ci 2191cb0ef41Sopenharmony_ci // Constructor with size parameter. 2201cb0ef41Sopenharmony_ci { 2211cb0ef41Sopenharmony_ci MaybeStackBuffer<unsigned char> buf(100); 2221cb0ef41Sopenharmony_ci EXPECT_EQ(100U, buf.length()); 2231cb0ef41Sopenharmony_ci EXPECT_FALSE(buf.IsAllocated()); 2241cb0ef41Sopenharmony_ci EXPECT_GT(buf.capacity(), buf.length()); 2251cb0ef41Sopenharmony_ci buf.SetLength(buf.capacity()); 2261cb0ef41Sopenharmony_ci EXPECT_EQ(buf.capacity(), buf.length()); 2271cb0ef41Sopenharmony_ci EXPECT_FALSE(buf.IsAllocated()); 2281cb0ef41Sopenharmony_ci for (size_t i = 0; i < buf.length(); i++) 2291cb0ef41Sopenharmony_ci buf[i] = static_cast<unsigned char>(i); 2301cb0ef41Sopenharmony_ci for (size_t i = 0; i < buf.length(); i++) 2311cb0ef41Sopenharmony_ci EXPECT_EQ(static_cast<unsigned char>(i), buf[i]); 2321cb0ef41Sopenharmony_ci 2331cb0ef41Sopenharmony_ci MaybeStackBuffer<unsigned char> bigbuf(10000); 2341cb0ef41Sopenharmony_ci EXPECT_EQ(10000U, bigbuf.length()); 2351cb0ef41Sopenharmony_ci EXPECT_TRUE(bigbuf.IsAllocated()); 2361cb0ef41Sopenharmony_ci EXPECT_EQ(bigbuf.length(), bigbuf.capacity()); 2371cb0ef41Sopenharmony_ci for (size_t i = 0; i < bigbuf.length(); i++) 2381cb0ef41Sopenharmony_ci bigbuf[i] = static_cast<unsigned char>(i); 2391cb0ef41Sopenharmony_ci for (size_t i = 0; i < bigbuf.length(); i++) 2401cb0ef41Sopenharmony_ci EXPECT_EQ(static_cast<unsigned char>(i), bigbuf[i]); 2411cb0ef41Sopenharmony_ci } 2421cb0ef41Sopenharmony_ci 2431cb0ef41Sopenharmony_ci // Invalidated buffer. 2441cb0ef41Sopenharmony_ci { 2451cb0ef41Sopenharmony_ci MaybeStackBuffer<char> buf; 2461cb0ef41Sopenharmony_ci buf.Invalidate(); 2471cb0ef41Sopenharmony_ci EXPECT_TRUE(buf.IsInvalidated()); 2481cb0ef41Sopenharmony_ci EXPECT_FALSE(buf.IsAllocated()); 2491cb0ef41Sopenharmony_ci EXPECT_EQ(0U, buf.length()); 2501cb0ef41Sopenharmony_ci EXPECT_EQ(0U, buf.capacity()); 2511cb0ef41Sopenharmony_ci buf.Invalidate(); 2521cb0ef41Sopenharmony_ci EXPECT_TRUE(buf.IsInvalidated()); 2531cb0ef41Sopenharmony_ci } 2541cb0ef41Sopenharmony_ci} 2551cb0ef41Sopenharmony_ci 2561cb0ef41Sopenharmony_ciTEST(UtilTest, SPrintF) { 2571cb0ef41Sopenharmony_ci // %d, %u and %s all do the same thing. The actual C++ type is used to infer 2581cb0ef41Sopenharmony_ci // the right representation. 2591cb0ef41Sopenharmony_ci EXPECT_EQ(SPrintF("%s", false), "false"); 2601cb0ef41Sopenharmony_ci EXPECT_EQ(SPrintF("%s", true), "true"); 2611cb0ef41Sopenharmony_ci EXPECT_EQ(SPrintF("%d", true), "true"); 2621cb0ef41Sopenharmony_ci EXPECT_EQ(SPrintF("%u", true), "true"); 2631cb0ef41Sopenharmony_ci EXPECT_EQ(SPrintF("%d", 10000000000LL), "10000000000"); 2641cb0ef41Sopenharmony_ci EXPECT_EQ(SPrintF("%d", -10000000000LL), "-10000000000"); 2651cb0ef41Sopenharmony_ci EXPECT_EQ(SPrintF("%u", 10000000000LL), "10000000000"); 2661cb0ef41Sopenharmony_ci EXPECT_EQ(SPrintF("%u", -10000000000LL), "-10000000000"); 2671cb0ef41Sopenharmony_ci EXPECT_EQ(SPrintF("%i", 10), "10"); 2681cb0ef41Sopenharmony_ci EXPECT_EQ(SPrintF("%d", 10), "10"); 2691cb0ef41Sopenharmony_ci EXPECT_EQ(SPrintF("%x", 15), "f"); 2701cb0ef41Sopenharmony_ci EXPECT_EQ(SPrintF("%x", 16), "10"); 2711cb0ef41Sopenharmony_ci EXPECT_EQ(SPrintF("%X", 15), "F"); 2721cb0ef41Sopenharmony_ci EXPECT_EQ(SPrintF("%X", 16), "10"); 2731cb0ef41Sopenharmony_ci EXPECT_EQ(SPrintF("%o", 7), "7"); 2741cb0ef41Sopenharmony_ci EXPECT_EQ(SPrintF("%o", 8), "10"); 2751cb0ef41Sopenharmony_ci 2761cb0ef41Sopenharmony_ci EXPECT_EQ(atof(SPrintF("%s", 0.5).c_str()), 0.5); 2771cb0ef41Sopenharmony_ci EXPECT_EQ(atof(SPrintF("%s", -0.5).c_str()), -0.5); 2781cb0ef41Sopenharmony_ci 2791cb0ef41Sopenharmony_ci void (*fn)() = []() {}; 2801cb0ef41Sopenharmony_ci void* p = reinterpret_cast<void*>(&fn); 2811cb0ef41Sopenharmony_ci EXPECT_GE(SPrintF("%p", fn).size(), 4u); 2821cb0ef41Sopenharmony_ci EXPECT_GE(SPrintF("%p", p).size(), 4u); 2831cb0ef41Sopenharmony_ci 2841cb0ef41Sopenharmony_ci const std::string foo = "foo"; 2851cb0ef41Sopenharmony_ci const char* bar = "bar"; 2861cb0ef41Sopenharmony_ci EXPECT_EQ(SPrintF("%s %s", foo, "bar"), "foo bar"); 2871cb0ef41Sopenharmony_ci EXPECT_EQ(SPrintF("%s %s", foo, bar), "foo bar"); 2881cb0ef41Sopenharmony_ci EXPECT_EQ(SPrintF("%s", nullptr), "(null)"); 2891cb0ef41Sopenharmony_ci 2901cb0ef41Sopenharmony_ci EXPECT_EQ(SPrintF("[%% %s %%]", foo), "[% foo %]"); 2911cb0ef41Sopenharmony_ci 2921cb0ef41Sopenharmony_ci struct HasToString { 2931cb0ef41Sopenharmony_ci std::string ToString() const { 2941cb0ef41Sopenharmony_ci return "meow"; 2951cb0ef41Sopenharmony_ci } 2961cb0ef41Sopenharmony_ci }; 2971cb0ef41Sopenharmony_ci EXPECT_EQ(SPrintF("%s", HasToString{}), "meow"); 2981cb0ef41Sopenharmony_ci 2991cb0ef41Sopenharmony_ci const std::string with_zero = std::string("a") + '\0' + 'b'; 3001cb0ef41Sopenharmony_ci EXPECT_EQ(SPrintF("%s", with_zero), with_zero); 3011cb0ef41Sopenharmony_ci} 302