/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* vim: set ts=8 sts=2 et sw=2 tw=80: */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include #include #include "nsASCIIMask.h" #include "nsCharSeparatedTokenizer.h" #include "nsPrintfCString.h" #include "nsString.h" #include "nsStringBuffer.h" #include "nsReadableUtils.h" #include "nsCRTGlue.h" #include "mozilla/RefPtr.h" #include "mozilla/TextUtils.h" #include "mozilla/Unused.h" #include "mozilla/Utf8.h" #include "nsTArray.h" #include "gtest/gtest.h" #include "gtest/MozGTestBench.h" // For MOZ_GTEST_BENCH #include "gtest/BlackBox.h" #include "nsBidiUtils.h" #include "js/String.h" #define CONVERSION_ITERATIONS 50000 #define CONVERSION_BENCH(name, func, src, dstType) \ MOZ_GTEST_BENCH_F(Strings, name, [this] { \ for (int i = 0; i < CONVERSION_ITERATIONS; i++) { \ dstType dst; \ func(*BlackBox(&src), *BlackBox(&dst)); \ } \ }); namespace TestStrings { using mozilla::BlackBox; using mozilla::fallible; using mozilla::IsAscii; using mozilla::IsUtf8; using mozilla::Maybe; using mozilla::Nothing; using mozilla::Some; using mozilla::Span; #define TestExample1 \ "Sed ut perspiciatis unde omnis iste natus error sit voluptatem " \ "accusantium doloremque laudantium,\n totam rem aperiam, eaque ipsa quae " \ "ab illo inventore veritatis et quasi\r architecto beatae vitae dicta sunt " \ "explicabo. Nemo enim ipsam voluptatem quia voluptas sit aspernatur\n aut " \ "odit aut fugit, sed quia consequuntur magni dolores eos qui ratione " \ "voluptatem sequi nesciunt. Neque porro quisquam est, qui\r\n\r dolorem " \ "ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non " \ "numquam eius modi tempora incidunt ut labore et dolore magnam aliquam " \ "quaerat voluptatem. Ut enim ad minima veniam, quis nostrum exercitationem " \ "ullam corporis suscipit laboriosam, nisi ut aliquid ex ea commodi " \ "consequatur? Quis autem vel eum iure reprehenderit qui in ea voluptate " \ "velit esse quam nihil molestiae consequatur, vel illum qui dolorem eum " \ "fugiat quo voluptas nulla pariatur?" #define TestExample2 \ "At vero eos et accusamus et iusto odio dignissimos ducimus\n\n qui " \ "blanditiis praesentium voluptatum deleniti atque corrupti quos dolores et " \ "quas molestias excepturi sint occaecati cupiditate non provident, " \ "similique sunt in culpa qui officia deserunt\r\r \n mollitia animi, id " \ "est laborum et dolorum fuga. Et harum quidem rerum facilis est et " \ "expedita distinctio. Nam libero tempore, cum soluta nobis est eligendi " \ "optio cumque nihil impedit quo minus id quod maxime placeat facere " \ "possimus, omnis voluptas assumenda est, omnis dolor repellendus. " \ "Temporibus autem quibusdam et aut officiis debitis aut rerum " \ "necessitatibus saepe eveniet ut et voluptates repudiandae sint et " \ "molestiae non recusandae. Itaque earum rerum hic tenetur a sapiente " \ "delectus, ut aut reiciendis voluptatibus maiores alias consequatur aut " \ "perferendis doloribus asperiores repellat." #define TestExample3 \ " Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis ac tellus " \ "eget velit viverra viverra id sit amet neque. Sed id consectetur mi, " \ "vestibulum aliquet arcu. Curabitur sagittis accumsan convallis. Sed eu " \ "condimentum ipsum, a laoreet tortor. Orci varius natoque penatibus et " \ "magnis dis \r\r\n\n parturient montes, nascetur ridiculus mus. Sed non " \ "tellus nec ante sodales placerat a nec risus. Cras vel bibendum sapien, " \ "nec ullamcorper felis. Pellentesque congue eget nisi sit amet vehicula. " \ "Morbi pulvinar turpis justo, in commodo dolor vulputate id. Curabitur in " \ "dui urna. Vestibulum placerat dui in sem congue, ut faucibus nibh rutrum. " \ "Duis mattis turpis facilisis ullamcorper tincidunt. Vestibulum pharetra " \ "tortor at enim sagittis, dapibus consectetur ex blandit. Curabitur ac " \ "fringilla quam. In ornare lectus ut ipsum mattis venenatis. Etiam in " \ "mollis lectus, sed luctus risus.\nCras dapibus\f\t \n finibus justo sit " \ "amet dictum. Aliquam non elit diam. Fusce magna nulla, bibendum in massa " \ "a, commodo finibus lectus. Sed rutrum a augue id imperdiet. Aliquam " \ "sagittis sodales felis, a tristique ligula. Aliquam erat volutpat. " \ "Pellentesque habitant morbi tristique senectus et netus et malesuada " \ "fames ac turpis egestas. Duis volutpat interdum lorem et congue. " \ "Phasellus porttitor posuere justo eget euismod. Nam a condimentum turpis, " \ "sit amet gravida lacus. Vestibulum dolor diam, lobortis ac metus et, " \ "convallis dapibus tellus. Ut nec metus in velit malesuada tincidunt et " \ "eget justo. Curabitur ut libero bibendum, porttitor diam vitae, aliquet " \ "justo. " #define TestExample4 \ " Donec feugiat volutpat massa. Cras ornare lacinia porta. Fusce in " \ "feugiat nunc. Praesent non felis varius diam feugiat ultrices ultricies a " \ "risus. Donec maximus nisi nisl, non consectetur nulla eleifend in. Nulla " \ "in massa interdum, eleifend orci a, vestibulum est. Mauris aliquet, massa " \ "et convallis mollis, felis augue vestibulum augue, in lobortis metus eros " \ "a quam. Nam ac diam ornare, vestibulum elit sit amet, " \ "consectetur ante. Praesent massa mauris, pulvinar sit amet sapien vel, " \ "tempus gravida neque. Praesent id quam sit amet est maximus molestie eget " \ "at turpis. Nunc sit amet orci id arcu dapibus fermentum non eu " \ "erat.\f\tSuspendisse commodo nunc sem, eu congue eros condimentum vel. " \ "Nullam sit amet posuere arcu. Nulla facilisi. Mauris dapibus iaculis " \ "massa sed gravida. Nullam vitae urna at tortor feugiat auctor ut sit amet " \ "dolor. Proin rutrum at nunc et faucibus. Quisque suscipit id nibh a " \ "aliquet. Pellentesque habitant morbi tristique senectus et netus et " \ "malesuada fames ac turpis egestas. Aliquam a dapibus erat, id imperdiet " \ "mauris. Nulla blandit libero non magna dapibus tristique. Integer " \ "hendrerit imperdiet lorem, quis facilisis lacus semper ut. Vestibulum " \ "ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia " \ "Curae Nullam dignissim elit in congue ultricies. Quisque erat odio, " \ "maximus mollis laoreet id, iaculis at turpis. " #define TestExample5 \ "Donec id risus urna. Nunc consequat lacinia urna id bibendum. Nulla " \ "faucibus faucibus enim. Cras ex risus, ultrices id semper vitae, luctus " \ "ut nulla. Sed vehicula tellus sed purus imperdiet efficitur. Suspendisse " \ "feugiat\n\n\n imperdiet odio, sed porta lorem feugiat nec. Curabitur " \ "laoreet massa venenatis\r\n risus ornare\r\n, vitae feugiat tortor " \ "accumsan. Lorem ipsum dolor sit amet, consectetur adipiscing elit. " \ "Maecenas id scelerisque mauris, eget facilisis erat. Ut nec pulvinar " \ "risus, sed iaculis ante. Mauris tincidunt, risus et pretium elementum, " \ "leo nisi consectetur ligula, tincidunt suscipit erat velit eget libero. " \ "Sed ac est tempus, consequat dolor mattis, mattis mi. " // Originally ReadVPXFile in TestVPXDecoding.cpp static void ReadFile(const char* aPath, nsACString& aBuffer) { FILE* f = fopen(aPath, "rb"); ASSERT_NE(f, (FILE*)nullptr); int r = fseek(f, 0, SEEK_END); ASSERT_EQ(r, 0); long size = ftell(f); ASSERT_NE(size, -1); aBuffer.SetLength(size); r = fseek(f, 0, SEEK_SET); ASSERT_EQ(r, 0); size_t got = fread(aBuffer.BeginWriting(), 1, size, f); ASSERT_EQ(got, size_t(size)); r = fclose(f); ASSERT_EQ(r, 0); } class Strings : public ::testing::Test { protected: void SetUp() override { // Intentionally AssignASCII and not AssignLiteral // to simulate the usual heap case. mExample1Utf8.AssignASCII(TestExample1); mExample2Utf8.AssignASCII(TestExample2); mExample3Utf8.AssignASCII(TestExample3); mExample4Utf8.AssignASCII(TestExample4); mExample5Utf8.AssignASCII(TestExample5); // Use span to make the resulting string as ordinary as possible mAsciiOneUtf8.Append(Span(mExample3Utf8).To(1)); mAsciiThreeUtf8.Append(Span(mExample3Utf8).To(3)); mAsciiFifteenUtf8.Append(Span(mExample3Utf8).To(15)); mAsciiHundredUtf8.Append(Span(mExample3Utf8).To(100)); mAsciiThousandUtf8.Append(Span(mExample3Utf8).To(1000)); ReadFile("ar.txt", mArUtf8); ReadFile("de.txt", mDeUtf8); ReadFile("de-edit.txt", mDeEditUtf8); ReadFile("ru.txt", mRuUtf8); ReadFile("th.txt", mThUtf8); ReadFile("ko.txt", mKoUtf8); ReadFile("ja.txt", mJaUtf8); ReadFile("tr.txt", mTrUtf8); ReadFile("vi.txt", mViUtf8); CopyASCIItoUTF16(mExample1Utf8, mExample1Utf16); CopyASCIItoUTF16(mExample2Utf8, mExample2Utf16); CopyASCIItoUTF16(mExample3Utf8, mExample3Utf16); CopyASCIItoUTF16(mExample4Utf8, mExample4Utf16); CopyASCIItoUTF16(mExample5Utf8, mExample5Utf16); CopyASCIItoUTF16(mAsciiOneUtf8, mAsciiOneUtf16); CopyASCIItoUTF16(mAsciiFifteenUtf8, mAsciiFifteenUtf16); CopyASCIItoUTF16(mAsciiHundredUtf8, mAsciiHundredUtf16); CopyASCIItoUTF16(mAsciiThousandUtf8, mAsciiThousandUtf16); CopyUTF8toUTF16(mArUtf8, mArUtf16); CopyUTF8toUTF16(mDeUtf8, mDeUtf16); CopyUTF8toUTF16(mDeEditUtf8, mDeEditUtf16); CopyUTF8toUTF16(mRuUtf8, mRuUtf16); CopyUTF8toUTF16(mThUtf8, mThUtf16); CopyUTF8toUTF16(mJaUtf8, mJaUtf16); CopyUTF8toUTF16(mKoUtf8, mKoUtf16); CopyUTF8toUTF16(mTrUtf8, mTrUtf16); CopyUTF8toUTF16(mViUtf8, mViUtf16); LossyCopyUTF16toASCII(mDeEditUtf16, mDeEditLatin1); // Use span to make the resulting string as ordinary as possible mArOneUtf16.Append(Span(mArUtf16).To(1)); mDeOneUtf16.Append(Span(mDeUtf16).To(1)); mDeEditOneUtf16.Append(Span(mDeEditUtf16).To(1)); mRuOneUtf16.Append(Span(mRuUtf16).To(1)); mThOneUtf16.Append(Span(mThUtf16).To(1)); mJaOneUtf16.Append(Span(mJaUtf16).To(1)); mKoOneUtf16.Append(Span(mKoUtf16).To(1)); mTrOneUtf16.Append(Span(mTrUtf16).To(1)); mViOneUtf16.Append(Span(mViUtf16).To(1)); mDeEditOneLatin1.Append(Span(mDeEditLatin1).To(1)); mArThreeUtf16.Append(Span(mArUtf16).To(3)); mDeThreeUtf16.Append(Span(mDeUtf16).To(3)); mDeEditThreeUtf16.Append(Span(mDeEditUtf16).To(3)); mRuThreeUtf16.Append(Span(mRuUtf16).To(3)); mThThreeUtf16.Append(Span(mThUtf16).To(3)); mJaThreeUtf16.Append(Span(mJaUtf16).To(3)); mKoThreeUtf16.Append(Span(mKoUtf16).To(3)); mTrThreeUtf16.Append(Span(mTrUtf16).To(3)); mViThreeUtf16.Append(Span(mViUtf16).To(3)); mDeEditThreeLatin1.Append(Span(mDeEditLatin1).To(3)); mArFifteenUtf16.Append(Span(mArUtf16).To(15)); mDeFifteenUtf16.Append(Span(mDeUtf16).To(15)); mDeEditFifteenUtf16.Append(Span(mDeEditUtf16).To(15)); mRuFifteenUtf16.Append(Span(mRuUtf16).To(15)); mThFifteenUtf16.Append(Span(mThUtf16).To(15)); mJaFifteenUtf16.Append(Span(mJaUtf16).To(15)); mKoFifteenUtf16.Append(Span(mKoUtf16).To(15)); mTrFifteenUtf16.Append(Span(mTrUtf16).To(15)); mViFifteenUtf16.Append(Span(mViUtf16).To(15)); mDeEditFifteenLatin1.Append(Span(mDeEditLatin1).To(15)); mArHundredUtf16.Append(Span(mArUtf16).To(100)); mDeHundredUtf16.Append(Span(mDeUtf16).To(100)); mDeEditHundredUtf16.Append(Span(mDeEditUtf16).To(100)); mRuHundredUtf16.Append(Span(mRuUtf16).To(100)); mThHundredUtf16.Append(Span(mThUtf16).To(100)); mJaHundredUtf16.Append(Span(mJaUtf16).To(100)); mKoHundredUtf16.Append(Span(mKoUtf16).To(100)); mTrHundredUtf16.Append(Span(mTrUtf16).To(100)); mViHundredUtf16.Append(Span(mViUtf16).To(100)); mDeEditHundredLatin1.Append(Span(mDeEditLatin1).To(100)); mArThousandUtf16.Append(Span(mArUtf16).To(1000)); mDeThousandUtf16.Append(Span(mDeUtf16).To(1000)); mDeEditThousandUtf16.Append(Span(mDeEditUtf16).To(1000)); mRuThousandUtf16.Append(Span(mRuUtf16).To(1000)); mThThousandUtf16.Append(Span(mThUtf16).To(1000)); mJaThousandUtf16.Append(Span(mJaUtf16).To(1000)); mKoThousandUtf16.Append(Span(mKoUtf16).To(1000)); mTrThousandUtf16.Append(Span(mTrUtf16).To(1000)); mViThousandUtf16.Append(Span(mViUtf16).To(1000)); mDeEditThousandLatin1.Append(Span(mDeEditLatin1).To(1000)); CopyUTF16toUTF8(mArOneUtf16, mArOneUtf8); CopyUTF16toUTF8(mDeOneUtf16, mDeOneUtf8); CopyUTF16toUTF8(mDeEditOneUtf16, mDeEditOneUtf8); CopyUTF16toUTF8(mRuOneUtf16, mRuOneUtf8); CopyUTF16toUTF8(mThOneUtf16, mThOneUtf8); CopyUTF16toUTF8(mJaOneUtf16, mJaOneUtf8); CopyUTF16toUTF8(mKoOneUtf16, mKoOneUtf8); CopyUTF16toUTF8(mTrOneUtf16, mTrOneUtf8); CopyUTF16toUTF8(mViOneUtf16, mViOneUtf8); CopyUTF16toUTF8(mArThreeUtf16, mArThreeUtf8); CopyUTF16toUTF8(mDeThreeUtf16, mDeThreeUtf8); CopyUTF16toUTF8(mDeEditThreeUtf16, mDeEditThreeUtf8); CopyUTF16toUTF8(mRuThreeUtf16, mRuThreeUtf8); CopyUTF16toUTF8(mThThreeUtf16, mThThreeUtf8); CopyUTF16toUTF8(mJaThreeUtf16, mJaThreeUtf8); CopyUTF16toUTF8(mKoThreeUtf16, mKoThreeUtf8); CopyUTF16toUTF8(mTrThreeUtf16, mTrThreeUtf8); CopyUTF16toUTF8(mViThreeUtf16, mViThreeUtf8); CopyUTF16toUTF8(mArFifteenUtf16, mArFifteenUtf8); CopyUTF16toUTF8(mDeFifteenUtf16, mDeFifteenUtf8); CopyUTF16toUTF8(mDeEditFifteenUtf16, mDeEditFifteenUtf8); CopyUTF16toUTF8(mRuFifteenUtf16, mRuFifteenUtf8); CopyUTF16toUTF8(mThFifteenUtf16, mThFifteenUtf8); CopyUTF16toUTF8(mJaFifteenUtf16, mJaFifteenUtf8); CopyUTF16toUTF8(mKoFifteenUtf16, mKoFifteenUtf8); CopyUTF16toUTF8(mTrFifteenUtf16, mTrFifteenUtf8); CopyUTF16toUTF8(mViFifteenUtf16, mViFifteenUtf8); CopyUTF16toUTF8(mArHundredUtf16, mArHundredUtf8); CopyUTF16toUTF8(mDeHundredUtf16, mDeHundredUtf8); CopyUTF16toUTF8(mDeEditHundredUtf16, mDeEditHundredUtf8); CopyUTF16toUTF8(mRuHundredUtf16, mRuHundredUtf8); CopyUTF16toUTF8(mThHundredUtf16, mThHundredUtf8); CopyUTF16toUTF8(mJaHundredUtf16, mJaHundredUtf8); CopyUTF16toUTF8(mKoHundredUtf16, mKoHundredUtf8); CopyUTF16toUTF8(mTrHundredUtf16, mTrHundredUtf8); CopyUTF16toUTF8(mViHundredUtf16, mViHundredUtf8); CopyUTF16toUTF8(mArThousandUtf16, mArThousandUtf8); CopyUTF16toUTF8(mDeThousandUtf16, mDeThousandUtf8); CopyUTF16toUTF8(mDeEditThousandUtf16, mDeEditThousandUtf8); CopyUTF16toUTF8(mRuThousandUtf16, mRuThousandUtf8); CopyUTF16toUTF8(mThThousandUtf16, mThThousandUtf8); CopyUTF16toUTF8(mJaThousandUtf16, mJaThousandUtf8); CopyUTF16toUTF8(mKoThousandUtf16, mKoThousandUtf8); CopyUTF16toUTF8(mTrThousandUtf16, mTrThousandUtf8); CopyUTF16toUTF8(mViThousandUtf16, mViThousandUtf8); } public: nsCString mAsciiOneUtf8; nsCString mAsciiThreeUtf8; nsCString mAsciiFifteenUtf8; nsCString mAsciiHundredUtf8; nsCString mAsciiThousandUtf8; nsCString mExample1Utf8; nsCString mExample2Utf8; nsCString mExample3Utf8; nsCString mExample4Utf8; nsCString mExample5Utf8; nsCString mArUtf8; nsCString mDeUtf8; nsCString mDeEditUtf8; nsCString mRuUtf8; nsCString mThUtf8; nsCString mJaUtf8; nsCString mKoUtf8; nsCString mTrUtf8; nsCString mViUtf8; nsString mAsciiOneUtf16; nsString mAsciiThreeUtf16; nsString mAsciiFifteenUtf16; nsString mAsciiHundredUtf16; nsString mAsciiThousandUtf16; nsString mExample1Utf16; nsString mExample2Utf16; nsString mExample3Utf16; nsString mExample4Utf16; nsString mExample5Utf16; nsString mArUtf16; nsString mDeUtf16; nsString mDeEditUtf16; nsString mRuUtf16; nsString mThUtf16; nsString mJaUtf16; nsString mKoUtf16; nsString mTrUtf16; nsString mViUtf16; nsCString mDeEditLatin1; nsString mArOneUtf16; nsString mDeOneUtf16; nsString mDeEditOneUtf16; nsString mRuOneUtf16; nsString mThOneUtf16; nsString mJaOneUtf16; nsString mKoOneUtf16; nsString mTrOneUtf16; nsString mViOneUtf16; nsCString mDeEditOneLatin1; nsCString mArOneUtf8; nsCString mDeOneUtf8; nsCString mDeEditOneUtf8; nsCString mRuOneUtf8; nsCString mThOneUtf8; nsCString mJaOneUtf8; nsCString mKoOneUtf8; nsCString mTrOneUtf8; nsCString mViOneUtf8; nsString mArThreeUtf16; nsString mDeThreeUtf16; nsString mDeEditThreeUtf16; nsString mRuThreeUtf16; nsString mThThreeUtf16; nsString mJaThreeUtf16; nsString mKoThreeUtf16; nsString mTrThreeUtf16; nsString mViThreeUtf16; nsCString mDeEditThreeLatin1; nsCString mArThreeUtf8; nsCString mDeThreeUtf8; nsCString mDeEditThreeUtf8; nsCString mRuThreeUtf8; nsCString mThThreeUtf8; nsCString mJaThreeUtf8; nsCString mKoThreeUtf8; nsCString mTrThreeUtf8; nsCString mViThreeUtf8; nsString mArFifteenUtf16; nsString mDeFifteenUtf16; nsString mDeEditFifteenUtf16; nsString mRuFifteenUtf16; nsString mThFifteenUtf16; nsString mJaFifteenUtf16; nsString mKoFifteenUtf16; nsString mTrFifteenUtf16; nsString mViFifteenUtf16; nsCString mDeEditFifteenLatin1; nsCString mArFifteenUtf8; nsCString mDeFifteenUtf8; nsCString mDeEditFifteenUtf8; nsCString mRuFifteenUtf8; nsCString mThFifteenUtf8; nsCString mJaFifteenUtf8; nsCString mKoFifteenUtf8; nsCString mTrFifteenUtf8; nsCString mViFifteenUtf8; nsString mArHundredUtf16; nsString mDeHundredUtf16; nsString mDeEditHundredUtf16; nsString mRuHundredUtf16; nsString mThHundredUtf16; nsString mJaHundredUtf16; nsString mKoHundredUtf16; nsString mTrHundredUtf16; nsString mViHundredUtf16; nsCString mDeEditHundredLatin1; nsCString mArHundredUtf8; nsCString mDeHundredUtf8; nsCString mDeEditHundredUtf8; nsCString mRuHundredUtf8; nsCString mThHundredUtf8; nsCString mJaHundredUtf8; nsCString mKoHundredUtf8; nsCString mTrHundredUtf8; nsCString mViHundredUtf8; nsString mArThousandUtf16; nsString mDeThousandUtf16; nsString mDeEditThousandUtf16; nsString mRuThousandUtf16; nsString mThThousandUtf16; nsString mJaThousandUtf16; nsString mKoThousandUtf16; nsString mTrThousandUtf16; nsString mViThousandUtf16; nsCString mDeEditThousandLatin1; nsCString mArThousandUtf8; nsCString mDeThousandUtf8; nsCString mDeEditThousandUtf8; nsCString mRuThousandUtf8; nsCString mThThousandUtf8; nsCString mJaThousandUtf8; nsCString mKoThousandUtf8; nsCString mTrThousandUtf8; nsCString mViThousandUtf8; }; static void test_assign_helper(const nsACString& in, nsACString& _retval) { _retval = in; } // Simple helper struct to test if conditionally enabled string functions are // working. template struct EnableTest { template > bool IsChar16() { return true; } template > bool IsChar16(int dummy = 42) { return false; } template > bool IsChar() { return false; } template > bool IsChar(int dummy = 42) { return true; } }; TEST_F(Strings, IsChar) { EnableTest charTest; EXPECT_TRUE(charTest.IsChar()); EXPECT_FALSE(charTest.IsChar16()); EnableTest char16Test; EXPECT_TRUE(char16Test.IsChar16()); EXPECT_FALSE(char16Test.IsChar()); #ifdef COMPILATION_FAILURE_TEST nsAutoCString a_ctest; nsAutoString a_test; a_ctest.AssignLiteral("hello"); // This should cause a compilation failure. a_ctest.AssignLiteral(u"hello"); a_test.AssignLiteral(u"hello"); a_test.AssignLiteral("hello"); #endif } TEST_F(Strings, DependentStrings) { // A few tests that make sure copying nsTDependentStrings behaves properly. using DataFlags = mozilla::detail::StringDataFlags; { // Test copy ctor. nsDependentCString tmp("foo"); auto data = tmp.Data(); nsDependentCString foo(tmp); // Neither string should be using a shared buffer. EXPECT_FALSE(tmp.GetDataFlags() & DataFlags::REFCOUNTED); EXPECT_FALSE(foo.GetDataFlags() & DataFlags::REFCOUNTED); // Both strings should be pointing to the original buffer. EXPECT_EQ(data, tmp.Data()); EXPECT_EQ(data, foo.Data()); } { // Test move ctor. nsDependentCString tmp("foo"); auto data = tmp.Data(); nsDependentCString foo(std::move(tmp)); // Neither string should be using a shared buffer. EXPECT_FALSE(tmp.GetDataFlags() & DataFlags::REFCOUNTED); EXPECT_FALSE(foo.GetDataFlags() & DataFlags::REFCOUNTED); // First string should be reset, the second should be pointing to the // original buffer. EXPECT_NE(data, tmp.Data()); EXPECT_EQ(data, foo.Data()); EXPECT_TRUE(tmp.IsEmpty()); } { // Test copying to a nsCString. nsDependentCString tmp("foo"); auto data = tmp.Data(); nsCString foo(tmp); // Original string should not be shared, copy should be shared. EXPECT_FALSE(tmp.GetDataFlags() & DataFlags::REFCOUNTED); EXPECT_TRUE(foo.GetDataFlags() & DataFlags::REFCOUNTED); // First string should remain the same, the second should be pointing to // a new buffer. EXPECT_EQ(data, tmp.Data()); EXPECT_NE(data, foo.Data()); } } TEST_F(Strings, assign) { nsCString result; test_assign_helper("a"_ns + "b"_ns, result); EXPECT_STREQ(result.get(), "ab"); } TEST_F(Strings, assign_c) { nsCString c; c.Assign('c'); EXPECT_STREQ(c.get(), "c"); } TEST_F(Strings, test1) { constexpr auto empty = u""_ns; const nsAString& aStr = empty; nsAutoString buf(aStr); int32_t n = buf.FindChar(','); EXPECT_EQ(n, kNotFound); n = buf.Length(); buf.Cut(0, n + 1); n = buf.FindChar(','); EXPECT_EQ(n, kNotFound); } TEST_F(Strings, test2) { nsCString data("hello world"); const nsACString& aStr = data; nsCString temp(aStr); temp.Cut(0, 6); EXPECT_STREQ(temp.get(), "world"); } TEST_F(Strings, find) { nsCString src(""); int32_t i = src.Find("DOCTYPE", 2); EXPECT_EQ(i, 2); i = src.Find("DOCTYPE"); EXPECT_EQ(i, 2); } TEST_F(Strings, lower_case_find) { nsCString src(""); int32_t i = src.LowerCaseFindASCII("doctype", 2); EXPECT_EQ(i, 2); i = src.LowerCaseFindASCII("doctype"); EXPECT_EQ(i, 2); } TEST_F(Strings, rfind) { const char text[] = ""; nsCString src(text); int32_t i; i = src.RFind("bLaH"); EXPECT_EQ(i, 20); i = src.RFind("blah"); EXPECT_EQ(i, 10); i = src.RFind("BLAH"); EXPECT_EQ(i, kNotFound); } TEST_F(Strings, rfind_2) { const char text[] = ""; nsCString src(text); int32_t i = src.RFind("TYPE"); EXPECT_EQ(i, 5); } TEST_F(Strings, rfind_3) { const char text[] = "urn:mozilla:locale:en-US:necko"; nsAutoCString value(text); int32_t i = value.RFind(":"); EXPECT_EQ(i, 24); } TEST_F(Strings, rfind_4) { nsCString value("a.msf"); int32_t i = value.RFind(".msf"); EXPECT_EQ(i, 1); } TEST_F(Strings, findinreadable) { const char text[] = "jar:jar:file:///c:/software/mozilla/mozilla_2006_02_21.jar!/browser/" "chrome/classic.jar!/"; nsAutoCString value(text); nsACString::const_iterator begin, end; value.BeginReading(begin); value.EndReading(end); nsACString::const_iterator delim_begin(begin), delim_end(end); // Search for last !/ at the end of the string EXPECT_TRUE(FindInReadable("!/"_ns, delim_begin, delim_end)); char* r = ToNewCString(Substring(delim_begin, delim_end)); // Should match the first "!/" but not the last EXPECT_NE(delim_end, end); EXPECT_STREQ(r, "!/"); free(r); delim_begin = begin; delim_end = end; // Search for first jar: EXPECT_TRUE(FindInReadable("jar:"_ns, delim_begin, delim_end)); r = ToNewCString(Substring(delim_begin, delim_end)); // Should not match the first jar:, but the second one EXPECT_EQ(delim_begin, begin); EXPECT_STREQ(r, "jar:"); free(r); // Search for jar: in a Substring delim_begin = begin; delim_begin++; delim_end = end; EXPECT_TRUE(FindInReadable("jar:"_ns, delim_begin, delim_end)); r = ToNewCString(Substring(delim_begin, delim_end)); // Should not match the first jar:, but the second one EXPECT_NE(delim_begin, begin); EXPECT_STREQ(r, "jar:"); free(r); // Should not find a match EXPECT_FALSE(FindInReadable("gecko"_ns, delim_begin, delim_end)); // When no match is found, range should be empty EXPECT_EQ(delim_begin, delim_end); // Should not find a match (search not beyond Substring) delim_begin = begin; for (int i = 0; i < 6; i++) delim_begin++; delim_end = end; EXPECT_FALSE(FindInReadable("jar:"_ns, delim_begin, delim_end)); // When no match is found, range should be empty EXPECT_EQ(delim_begin, delim_end); // Should not find a match (search not beyond Substring) delim_begin = begin; delim_end = end; for (int i = 0; i < 7; i++) delim_end--; EXPECT_FALSE(FindInReadable("classic"_ns, delim_begin, delim_end)); // When no match is found, range should be empty EXPECT_EQ(delim_begin, delim_end); } TEST_F(Strings, rfindinreadable) { const char text[] = "jar:jar:file:///c:/software/mozilla/mozilla_2006_02_21.jar!/browser/" "chrome/classic.jar!/"; nsAutoCString value(text); nsACString::const_iterator begin, end; value.BeginReading(begin); value.EndReading(end); nsACString::const_iterator delim_begin(begin), delim_end(end); // Search for last !/ at the end of the string EXPECT_TRUE(RFindInReadable("!/"_ns, delim_begin, delim_end)); char* r = ToNewCString(Substring(delim_begin, delim_end)); // Should match the last "!/" EXPECT_EQ(delim_end, end); EXPECT_STREQ(r, "!/"); free(r); delim_begin = begin; delim_end = end; // Search for last jar: but not the first one... EXPECT_TRUE(RFindInReadable("jar:"_ns, delim_begin, delim_end)); r = ToNewCString(Substring(delim_begin, delim_end)); // Should not match the first jar:, but the second one EXPECT_NE(delim_begin, begin); EXPECT_STREQ(r, "jar:"); free(r); // Search for jar: in a Substring delim_begin = begin; delim_end = begin; for (int i = 0; i < 6; i++) delim_end++; EXPECT_TRUE(RFindInReadable("jar:"_ns, delim_begin, delim_end)); r = ToNewCString(Substring(delim_begin, delim_end)); // Should not match the first jar:, but the second one EXPECT_EQ(delim_begin, begin); EXPECT_STREQ(r, "jar:"); free(r); // Should not find a match delim_begin = begin; delim_end = end; EXPECT_FALSE(RFindInReadable("gecko"_ns, delim_begin, delim_end)); // When no match is found, range should be empty EXPECT_EQ(delim_begin, delim_end); // Should not find a match (search not before Substring) delim_begin = begin; for (int i = 0; i < 6; i++) delim_begin++; delim_end = end; EXPECT_FALSE(RFindInReadable("jar:"_ns, delim_begin, delim_end)); // When no match is found, range should be empty EXPECT_EQ(delim_begin, delim_end); // Should not find a match (search not beyond Substring) delim_begin = begin; delim_end = end; for (int i = 0; i < 7; i++) delim_end--; EXPECT_FALSE(RFindInReadable("classic"_ns, delim_begin, delim_end)); // When no match is found, range should be empty EXPECT_EQ(delim_begin, delim_end); } TEST_F(Strings, distance) { const char text[] = "abc-xyz"; nsCString s(text); nsCString::const_iterator begin, end; s.BeginReading(begin); s.EndReading(end); size_t d = Distance(begin, end); EXPECT_EQ(d, sizeof(text) - 1); } TEST_F(Strings, length) { const char text[] = "abc-xyz"; nsCString s(text); size_t d = s.Length(); EXPECT_EQ(d, sizeof(text) - 1); } TEST_F(Strings, trim) { const char text[] = " a\t $ "; const char set[] = " \t$"; nsCString s(text); s.Trim(set); EXPECT_STREQ(s.get(), "a"); s.AssignLiteral("\t \t\t \t"); s.Trim(set); EXPECT_STREQ(s.get(), ""); s.AssignLiteral(" "); s.Trim(set); EXPECT_STREQ(s.get(), ""); s.AssignLiteral(" "); s.Trim(set, false, true); EXPECT_STREQ(s.get(), ""); s.AssignLiteral(" "); s.Trim(set, true, false); EXPECT_STREQ(s.get(), ""); } TEST_F(Strings, replace_substr) { const char text[] = "abc-ppp-qqq-ppp-xyz"; nsCString s(text); s.ReplaceSubstring("ppp", "www"); EXPECT_STREQ(s.get(), "abc-www-qqq-www-xyz"); s.AssignLiteral("foobar"); s.ReplaceSubstring("foo", "bar"); s.ReplaceSubstring("bar", ""); EXPECT_STREQ(s.get(), ""); s.AssignLiteral("foofoofoo"); s.ReplaceSubstring("foo", "foo"); EXPECT_STREQ(s.get(), "foofoofoo"); s.AssignLiteral("foofoofoo"); s.ReplaceSubstring("of", "fo"); EXPECT_STREQ(s.get(), "fofoofooo"); } TEST_F(Strings, replace_substr_2) { const char* newName = "user"; nsString acctName; acctName.AssignLiteral("forums.foo.com"); nsAutoString newAcctName, oldVal, newVal; CopyASCIItoUTF16(mozilla::MakeStringSpan(newName), newVal); newAcctName.Assign(acctName); // here, oldVal is empty. we are testing that this function // does not hang. see bug 235355. newAcctName.ReplaceSubstring(oldVal, newVal); // we expect that newAcctName will be unchanged. EXPECT_TRUE(newAcctName.Equals(acctName)); } TEST_F(Strings, replace_substr_3) { nsCString s; s.AssignLiteral("abcabcabc"); s.ReplaceSubstring("ca", "X"); EXPECT_STREQ(s.get(), "abXbXbc"); s.AssignLiteral("abcabcabc"); s.ReplaceSubstring("ca", "XYZ"); EXPECT_STREQ(s.get(), "abXYZbXYZbc"); s.AssignLiteral("abcabcabc"); s.ReplaceSubstring("ca", "XY"); EXPECT_STREQ(s.get(), "abXYbXYbc"); s.AssignLiteral("abcabcabc"); s.ReplaceSubstring("ca", "XYZ!"); EXPECT_STREQ(s.get(), "abXYZ!bXYZ!bc"); s.AssignLiteral("abcdabcdabcd"); s.ReplaceSubstring("bcd", "X"); EXPECT_STREQ(s.get(), "aXaXaX"); s.AssignLiteral("abcdabcdabcd"); s.ReplaceSubstring("bcd", "XYZ!"); EXPECT_STREQ(s.get(), "aXYZ!aXYZ!aXYZ!"); s.AssignLiteral("abcdabcdabcd"); s.ReplaceSubstring("bcd", "XY"); EXPECT_STREQ(s.get(), "aXYaXYaXY"); s.AssignLiteral("abcdabcdabcd"); s.ReplaceSubstring("bcd", "XYZABC"); EXPECT_STREQ(s.get(), "aXYZABCaXYZABCaXYZABC"); s.AssignLiteral("abcdabcdabcd"); s.ReplaceSubstring("bcd", "XYZ"); EXPECT_STREQ(s.get(), "aXYZaXYZaXYZ"); s.AssignLiteral("abcdabcdabcd"); s.ReplaceSubstring("bcd", "XYZ!"); EXPECT_STREQ(s.get(), "aXYZ!aXYZ!aXYZ!"); s.AssignLiteral("abcdabcdabcd"); s.ReplaceSubstring("ab", "X"); EXPECT_STREQ(s.get(), "XcdXcdXcd"); s.AssignLiteral("abcdabcdabcd"); s.ReplaceSubstring("ab", "XYZABC"); EXPECT_STREQ(s.get(), "XYZABCcdXYZABCcdXYZABCcd"); s.AssignLiteral("abcdabcdabcd"); s.ReplaceSubstring("ab", "XY"); EXPECT_STREQ(s.get(), "XYcdXYcdXYcd"); s.AssignLiteral("abcdabcdabcd"); s.ReplaceSubstring("ab", "XYZ!"); EXPECT_STREQ(s.get(), "XYZ!cdXYZ!cdXYZ!cd"); s.AssignLiteral("abcdabcdabcd"); s.ReplaceSubstring("notfound", "X"); EXPECT_STREQ(s.get(), "abcdabcdabcd"); s.AssignLiteral("abcdabcdabcd"); s.ReplaceSubstring("notfound", "longlongstring"); EXPECT_STREQ(s.get(), "abcdabcdabcd"); } TEST_F(Strings, strip_ws) { const char* texts[] = {"", " a $ ", "Some\fother\t thing\r\n", "And \f\t\r\n even\nmore\r \f"}; const char* results[] = {"", "a$", "Someotherthing", "Andevenmore"}; for (size_t i = 0; i < sizeof(texts) / sizeof(texts[0]); i++) { nsCString s(texts[i]); s.StripWhitespace(); EXPECT_STREQ(s.get(), results[i]); } } TEST_F(Strings, equals_ic) { nsCString s; EXPECT_FALSE(s.LowerCaseEqualsLiteral("view-source")); } TEST_F(Strings, concat) { nsCString bar("bar"); const nsACString& barRef = bar; const nsPromiseFlatCString& result = PromiseFlatCString("foo"_ns + ","_ns + barRef); EXPECT_STREQ(result.get(), "foo,bar"); } TEST_F(Strings, concat_2) { nsCString fieldTextStr("xyz"); nsCString text("text"); const nsACString& aText = text; nsAutoCString result(fieldTextStr + aText); EXPECT_STREQ(result.get(), "xyztext"); } TEST_F(Strings, concat_3) { nsCString result; nsCString ab("ab"), c("c"); result = ab + result + c; EXPECT_STREQ(result.get(), "abc"); } TEST_F(Strings, empty_assign) { nsCString a; a.AssignLiteral(""); a.AppendLiteral(""); nsCString b; b.SetCapacity(0); } TEST_F(Strings, set_length) { const char kText[] = "Default Plugin"; nsCString buf; buf.SetCapacity(sizeof(kText) - 1); buf.Assign(kText); buf.SetLength(sizeof(kText) - 1); EXPECT_STREQ(buf.get(), kText); } TEST_F(Strings, substring) { nsCString super("hello world"), sub("hello"); // this tests that |super| starts with |sub|, EXPECT_TRUE(sub.Equals(StringHead(super, sub.Length()))); // and verifies that |sub| does not start with |super|. EXPECT_FALSE(super.Equals(StringHead(sub, super.Length()))); } #define test_append_expect(str, int, suffix, expect) \ str.Truncate(); \ str.AppendInt(suffix = int); \ EXPECT_TRUE(str.EqualsLiteral(expect)); #define test_appends_expect(int, suffix, expect) \ test_append_expect(str, int, suffix, expect) \ test_append_expect(cstr, int, suffix, expect) #define test_appendbase(str, prefix, int, suffix, base) \ str.Truncate(); \ str.AppendInt(suffix = prefix##int##suffix, base); \ EXPECT_TRUE(str.EqualsLiteral(#int)); #define test_appendbases(prefix, int, suffix, base) \ test_appendbase(str, prefix, int, suffix, base) \ test_appendbase(cstr, prefix, int, suffix, base) TEST_F(Strings, appendint) { nsString str; nsCString cstr; int32_t L; uint32_t UL; int64_t LL; uint64_t ULL; test_appends_expect(INT32_MAX, L, "2147483647"); test_appends_expect(INT32_MIN, L, "-2147483648"); test_appends_expect(UINT32_MAX, UL, "4294967295"); test_appends_expect(INT64_MAX, LL, "9223372036854775807"); test_appends_expect(INT64_MIN, LL, "-9223372036854775808"); test_appends_expect(UINT64_MAX, ULL, "18446744073709551615"); test_appendbases(0, 17777777777, L, 8); test_appendbases(0, 20000000000, L, 8); test_appendbases(0, 37777777777, UL, 8); test_appendbases(0, 777777777777777777777, LL, 8); test_appendbases(0, 1000000000000000000000, LL, 8); test_appendbases(0, 1777777777777777777777, ULL, 8); test_appendbases(0x, 7fffffff, L, 16); test_appendbases(0x, 80000000, L, 16); test_appendbases(0x, ffffffff, UL, 16); test_appendbases(0x, 7fffffffffffffff, LL, 16); test_appendbases(0x, 8000000000000000, LL, 16); test_appendbases(0x, ffffffffffffffff, ULL, 16); } TEST_F(Strings, appendint64) { nsCString str; int64_t max = INT64_MAX; static const char max_expected[] = "9223372036854775807"; int64_t min = INT64_MIN; static const char min_expected[] = "-9223372036854775808"; static const char min_expected_oct[] = "1000000000000000000000"; int64_t maxint_plus1 = 1LL << 32; static const char maxint_plus1_expected[] = "4294967296"; static const char maxint_plus1_expected_x[] = "100000000"; str.AppendInt(max); EXPECT_TRUE(str.Equals(max_expected)); str.Truncate(); str.AppendInt(min); EXPECT_TRUE(str.Equals(min_expected)); str.Truncate(); str.AppendInt(min, 8); EXPECT_TRUE(str.Equals(min_expected_oct)); str.Truncate(); str.AppendInt(maxint_plus1); EXPECT_TRUE(str.Equals(maxint_plus1_expected)); str.Truncate(); str.AppendInt(maxint_plus1, 16); EXPECT_TRUE(str.Equals(maxint_plus1_expected_x)); } TEST_F(Strings, inttotstring) { EXPECT_EQ("42"_ns, IntToCString(42)); EXPECT_EQ(u"42"_ns, IntToString(42)); EXPECT_EQ("2a"_ns, IntToCString(42, 16)); EXPECT_EQ(u"2a"_ns, IntToString(42, 16)); } TEST_F(Strings, appendfloat) { nsCString str; double bigdouble = 11223344556.66; static const char double_expected[] = "11223344556.66"; static const char float_expected[] = "0.01"; // AppendFloat is used to append doubles, therefore the precision must be // large enough (see bug 327719) str.AppendFloat(bigdouble); EXPECT_TRUE(str.Equals(double_expected)); str.Truncate(); // AppendFloat is used to append floats (bug 327719 #27) str.AppendFloat(0.1f * 0.1f); EXPECT_TRUE(str.Equals(float_expected)); } TEST_F(Strings, findcharinset) { nsCString buf("hello, how are you?"); int32_t index = buf.FindCharInSet(",?", 5); EXPECT_EQ(index, 5); index = buf.FindCharInSet("helo", 0); EXPECT_EQ(index, 0); index = buf.FindCharInSet("z?", 6); EXPECT_EQ(index, (int32_t)buf.Length() - 1); } TEST_F(Strings, rfindcharinset) { nsCString buf("hello, how are you?"); int32_t index = buf.RFindCharInSet(",?", 5); EXPECT_EQ(index, 5); index = buf.RFindCharInSet("helo", 0); EXPECT_EQ(index, 0); index = buf.RFindCharInSet("z?", 6); EXPECT_EQ(index, kNotFound); index = buf.RFindCharInSet("l", 5); EXPECT_EQ(index, 3); buf.AssignLiteral("abcdefghijkabc"); index = buf.RFindCharInSet("ab"); EXPECT_EQ(index, 12); index = buf.RFindCharInSet("ab", 11); EXPECT_EQ(index, 11); index = buf.RFindCharInSet("ab", 10); EXPECT_EQ(index, 1); index = buf.RFindCharInSet("ab", 0); EXPECT_EQ(index, 0); index = buf.RFindCharInSet("cd", 1); EXPECT_EQ(index, kNotFound); index = buf.RFindCharInSet("h"); EXPECT_EQ(index, 7); } TEST_F(Strings, stringbuffer) { const char kData[] = "hello world"; RefPtr buf; buf = nsStringBuffer::Alloc(sizeof(kData)); EXPECT_TRUE(!!buf); buf = nsStringBuffer::Alloc(sizeof(kData)); EXPECT_TRUE(!!buf); char* data = (char*)buf->Data(); memcpy(data, kData, sizeof(kData)); nsCString str; buf->ToString(sizeof(kData) - 1, str); nsStringBuffer* buf2; buf2 = nsStringBuffer::FromString(str); EXPECT_EQ(buf, buf2); } TEST_F(Strings, voided) { const char kData[] = "hello world"; nsCString str; EXPECT_TRUE(!str.IsVoid()); EXPECT_TRUE(str.IsEmpty()); EXPECT_STREQ(str.get(), ""); str.SetIsVoid(true); EXPECT_TRUE(str.IsVoid()); EXPECT_TRUE(str.IsEmpty()); EXPECT_STREQ(str.get(), ""); str.Assign(kData); EXPECT_TRUE(!str.IsVoid()); EXPECT_TRUE(!str.IsEmpty()); EXPECT_STREQ(str.get(), kData); str.SetIsVoid(true); EXPECT_TRUE(str.IsVoid()); EXPECT_TRUE(str.IsEmpty()); EXPECT_STREQ(str.get(), ""); str.SetIsVoid(false); EXPECT_TRUE(!str.IsVoid()); EXPECT_TRUE(str.IsEmpty()); EXPECT_STREQ(str.get(), ""); str.Assign(kData); EXPECT_TRUE(!str.IsVoid()); EXPECT_TRUE(!str.IsEmpty()); EXPECT_STREQ(str.get(), kData); str.Adopt(nullptr); EXPECT_TRUE(str.IsVoid()); EXPECT_TRUE(str.IsEmpty()); EXPECT_STREQ(str.get(), ""); } TEST_F(Strings, voided_autostr) { const char kData[] = "hello world"; nsAutoCString str; EXPECT_FALSE(str.IsVoid()); EXPECT_TRUE(str.IsEmpty()); str.Assign(kData); EXPECT_STREQ(str.get(), kData); str.SetIsVoid(true); EXPECT_TRUE(str.IsVoid()); EXPECT_TRUE(str.IsEmpty()); str.Assign(kData); EXPECT_FALSE(str.IsVoid()); EXPECT_FALSE(str.IsEmpty()); EXPECT_STREQ(str.get(), kData); } TEST_F(Strings, voided_assignment) { nsCString a, b; b.SetIsVoid(true); a = b; EXPECT_TRUE(a.IsVoid()); EXPECT_EQ(a.get(), b.get()); } TEST_F(Strings, empty_assignment) { nsCString a, b; a = b; EXPECT_EQ(a.get(), b.get()); } struct ToIntegerTest { const char* str; uint32_t radix; int32_t result; nsresult rv; }; static const ToIntegerTest kToIntegerTests[] = { {"123", 10, 123, NS_OK}, {"7b", 16, 123, NS_OK}, {"90194313659", 10, 0, NS_ERROR_ILLEGAL_VALUE}, {nullptr, 0, 0, NS_OK}}; TEST_F(Strings, string_tointeger) { nsresult rv; for (const ToIntegerTest* t = kToIntegerTests; t->str; ++t) { int32_t result = nsAutoCString(t->str).ToInteger(&rv, t->radix); EXPECT_EQ(rv, t->rv); EXPECT_EQ(result, t->result); result = nsAutoCString(t->str).ToInteger(&rv, t->radix); EXPECT_EQ(rv, t->rv); EXPECT_EQ(result, t->result); } } struct ToUnsignedIntegerTest { const char* str; uint32_t radix; uint32_t result; nsresult rv; }; static const ToUnsignedIntegerTest kToUnsignedIntegerTests[] = { {"123", 10, 123, NS_OK}, {"7b", 16, 123, NS_OK}, {"90194313659", 10, 0, NS_ERROR_ILLEGAL_VALUE}, {"ffffffff", 16, 0xffffffff, NS_OK}, {"4294967295", 10, 4294967295, NS_OK}, {"8abc1234", 16, 0x8abc1234, NS_OK}, {"-194313659", 10, 0, NS_ERROR_ILLEGAL_VALUE}, {nullptr, 0, 0, NS_OK}}; TEST_F(Strings, string_to_unsigned_integer) { nsresult rv; for (const ToUnsignedIntegerTest* t = kToUnsignedIntegerTests; t->str; ++t) { uint32_t result = nsAutoCString(t->str).ToUnsignedInteger(&rv, t->radix); EXPECT_EQ(rv, t->rv); EXPECT_EQ(result, t->result); } } static void test_parse_string_helper(const char* str, char separator, int len, const char* s1, const char* s2) { nsCString data(str); nsTArray results; ParseString(data, separator, results); EXPECT_EQ(int(results.Length()), len); const char* strings[] = {s1, s2}; for (int i = 0; i < len; ++i) { EXPECT_TRUE(results[i].Equals(strings[i])); } } static void test_parse_string_helper0(const char* str, char separator) { test_parse_string_helper(str, separator, 0, nullptr, nullptr); } static void test_parse_string_helper1(const char* str, char separator, const char* s1) { test_parse_string_helper(str, separator, 1, s1, nullptr); } static void test_parse_string_helper2(const char* str, char separator, const char* s1, const char* s2) { test_parse_string_helper(str, separator, 2, s1, s2); } TEST(String, parse_string) { test_parse_string_helper1("foo, bar", '_', "foo, bar"); test_parse_string_helper2("foo, bar", ',', "foo", " bar"); test_parse_string_helper2("foo, bar ", ' ', "foo,", "bar"); test_parse_string_helper2("foo,bar", 'o', "f", ",bar"); test_parse_string_helper0("", '_'); test_parse_string_helper0(" ", ' '); test_parse_string_helper1(" foo", ' ', "foo"); test_parse_string_helper1(" foo", ' ', "foo"); } static void test_strip_chars_helper(const char16_t* str, const char16_t* strip, const nsAString& result) { nsAutoString data(str); data.StripChars(strip); EXPECT_TRUE(data.Equals(result)); } TEST(String, strip_chars) { test_strip_chars_helper(u"foo \r \nbar", u" \n\r", u"foobar"_ns); test_strip_chars_helper(u"\r\nfoo\r\n", u" \n\r", u"foo"_ns); test_strip_chars_helper(u"foo", u" \n\r", u"foo"_ns); test_strip_chars_helper(u"foo", u"fo", u""_ns); test_strip_chars_helper(u"foo", u"foo", u""_ns); test_strip_chars_helper(u" foo", u" ", u"foo"_ns); } TEST_F(Strings, append_with_capacity) { nsAutoString s; const char16_t* origPtr = s.BeginReading(); s.SetCapacity(8000); const char16_t* ptr = s.BeginReading(); EXPECT_NE(origPtr, ptr); for (int i = 0; i < 100; i++) { s.Append(u'a'); EXPECT_EQ(s.BeginReading(), ptr); EXPECT_EQ(s.Length(), uint32_t(i + 1)); } } TEST_F(Strings, append_string_with_capacity) { nsAutoString aa; aa.Append(u'a'); aa.Append(u'a'); nsAutoString s; const char16_t* origPtr = s.BeginReading(); s.SetCapacity(8000); const char16_t* ptr = s.BeginReading(); EXPECT_NE(origPtr, ptr); nsAutoString empty; s.Append(empty); EXPECT_EQ(s.BeginReading(), ptr); for (int i = 0; i < 100; i++) { s.Append(aa); EXPECT_EQ(s.BeginReading(), ptr); EXPECT_EQ(s.Length(), uint32_t(2 * (i + 1))); } } TEST_F(Strings, append_literal_with_capacity) { nsAutoString s; const char16_t* origPtr = s.BeginReading(); s.SetCapacity(8000); const char16_t* ptr = s.BeginReading(); EXPECT_NE(origPtr, ptr); s.AppendLiteral(u""); EXPECT_EQ(s.BeginReading(), ptr); for (int i = 0; i < 100; i++) { s.AppendLiteral(u"aa"); EXPECT_EQ(s.BeginReading(), ptr); EXPECT_EQ(s.Length(), uint32_t(2 * (i + 1))); } } // The following test is intentionally not memory // checking-clean. #if !(defined(MOZ_HAVE_MEM_CHECKS) || defined(MOZ_MSAN)) TEST_F(Strings, legacy_set_length_semantics) { const char* foobar = "foobar"; nsCString s; s.SetCapacity(2048); memcpy(s.BeginWriting(), foobar, strlen(foobar)); s.SetLength(strlen(foobar)); EXPECT_FALSE(s.EqualsASCII(foobar)); } #endif TEST_F(Strings, bulk_write) { nsCString s; const char* ptrTwoThousand; { auto handleOrErr = s.BulkWrite(500, 0, true); EXPECT_TRUE(handleOrErr.isOk()); auto handle = handleOrErr.unwrap(); auto span = handle.AsSpan(); for (auto&& c : span) { c = 'a'; } mozilla::Unused << handle.RestartBulkWrite(2000, 500, false); span = handle.AsSpan().From(500); for (auto&& c : span) { c = 'b'; } ptrTwoThousand = handle.Elements(); handle.Finish(1000, true); } EXPECT_EQ(s.Length(), 1000U); EXPECT_NE(s.BeginReading(), ptrTwoThousand); EXPECT_EQ(s.BeginReading()[1000], '\0'); for (uint32_t i = 0; i < 500; i++) { EXPECT_EQ(s[i], 'a'); } for (uint32_t i = 500; i < 1000; i++) { EXPECT_EQ(s[i], 'b'); } } TEST_F(Strings, bulk_write_fail) { nsCString s; { auto handleOrErr = s.BulkWrite(500, 0, true); EXPECT_TRUE(handleOrErr.isOk()); } EXPECT_EQ(s.Length(), 3U); EXPECT_TRUE(s.Equals(u8"\uFFFD")); } TEST_F(Strings, huge_capacity) { nsString a, b, c, d, e, f, g, h, i, j, k, l, m, n, o; nsCString n1, o1; // Ignore the result if the address space is less than 64-bit because // some of the allocations above will exhaust the address space. if (sizeof(void*) >= 8) { EXPECT_TRUE(a.SetCapacity(1, fallible)); EXPECT_FALSE(a.SetCapacity(uint32_t(-1) / 2, fallible)); a.Truncate(); // free the allocated memory EXPECT_TRUE(b.SetCapacity(1, fallible)); EXPECT_FALSE(b.SetCapacity(uint32_t(-1) / 2 - 1, fallible)); b.Truncate(); EXPECT_TRUE(c.SetCapacity(1, fallible)); EXPECT_FALSE(c.SetCapacity(uint32_t(-1) / 2, fallible)); c.Truncate(); EXPECT_FALSE(d.SetCapacity(uint32_t(-1) / 2 - 1, fallible)); EXPECT_FALSE(d.SetCapacity(uint32_t(-1) / 2, fallible)); d.Truncate(); EXPECT_FALSE(e.SetCapacity(uint32_t(-1) / 4, fallible)); EXPECT_FALSE(e.SetCapacity(uint32_t(-1) / 4 + 1, fallible)); e.Truncate(); EXPECT_FALSE(f.SetCapacity(uint32_t(-1) / 2, fallible)); f.Truncate(); EXPECT_FALSE(g.SetCapacity(uint32_t(-1) / 4 + 1000, fallible)); EXPECT_FALSE(g.SetCapacity(uint32_t(-1) / 4 + 1001, fallible)); g.Truncate(); EXPECT_FALSE(h.SetCapacity(uint32_t(-1) / 4 + 1, fallible)); EXPECT_FALSE(h.SetCapacity(uint32_t(-1) / 2, fallible)); h.Truncate(); EXPECT_TRUE(i.SetCapacity(1, fallible)); EXPECT_TRUE(i.SetCapacity(uint32_t(-1) / 4 - 1000, fallible)); EXPECT_FALSE(i.SetCapacity(uint32_t(-1) / 4 + 1, fallible)); i.Truncate(); EXPECT_TRUE(j.SetCapacity(uint32_t(-1) / 4 - 1000, fallible)); EXPECT_FALSE(j.SetCapacity(uint32_t(-1) / 4 + 1, fallible)); j.Truncate(); // Disabled due to intermittent failures. // https://bugzilla.mozilla.org/show_bug.cgi?id=1493458 #if 0 EXPECT_TRUE(k.SetCapacity(uint32_t(-1)/8 - 1000, fallible)); EXPECT_TRUE(k.SetCapacity(uint32_t(-1)/4 - 1001, fallible)); EXPECT_TRUE(k.SetCapacity(uint32_t(-1)/4 - 998, fallible)); EXPECT_FALSE(k.SetCapacity(uint32_t(-1)/4 + 1, fallible)); k.Truncate(); #endif EXPECT_TRUE(l.SetCapacity(uint32_t(-1) / 8, fallible)); EXPECT_TRUE(l.SetCapacity(uint32_t(-1) / 8 + 1, fallible)); EXPECT_TRUE(l.SetCapacity(uint32_t(-1) / 8 + 2, fallible)); l.Truncate(); EXPECT_TRUE(m.SetCapacity(uint32_t(-1) / 8 + 1000, fallible)); EXPECT_TRUE(m.SetCapacity(uint32_t(-1) / 8 + 1001, fallible)); m.Truncate(); EXPECT_TRUE(n.SetCapacity(uint32_t(-1) / 8 + 1, fallible)); EXPECT_FALSE(n.SetCapacity(uint32_t(-1) / 4, fallible)); n.Truncate(); n.Truncate(); EXPECT_TRUE(n.SetCapacity((uint32_t(-1) / 2) / 2 - 1, fallible)); n.Truncate(); EXPECT_FALSE(n.SetCapacity((uint32_t(-1) / 2) / 2, fallible)); n.Truncate(); n1.Truncate(); EXPECT_TRUE(n1.SetCapacity((uint32_t(-1) / 2) / 1 - 1, fallible)); n1.Truncate(); EXPECT_FALSE(n1.SetCapacity((uint32_t(-1) / 2) / 1, fallible)); n1.Truncate(); // The longest possible JS string should fit within both a `nsString` and // nsCString. EXPECT_TRUE(o.SetCapacity(JS::MaxStringLength, fallible)); o.Truncate(); EXPECT_TRUE(o1.SetCapacity(JS::MaxStringLength, fallible)); o1.Truncate(); } } static void test_tofloat_helper(const nsString& aStr, mozilla::Maybe aExpected) { nsresult result; float value = aStr.ToFloat(&result); if (aExpected) { EXPECT_TRUE(NS_SUCCEEDED(result)); EXPECT_EQ(value, *aExpected); } else { EXPECT_TRUE(NS_FAILED(result)); } } TEST_F(Strings, tofloat) { test_tofloat_helper(u"42"_ns, Some(42.f)); test_tofloat_helper(u"42.0"_ns, Some(42.f)); test_tofloat_helper(u"-42"_ns, Some(-42.f)); test_tofloat_helper(u"+42"_ns, Some(42)); test_tofloat_helper(u"13.37"_ns, Some(13.37f)); test_tofloat_helper(u"1.23456789"_ns, Some(1.23456789f)); test_tofloat_helper(u"1.98765432123456"_ns, Some(1.98765432123456f)); test_tofloat_helper(u"0"_ns, Some(0.f)); test_tofloat_helper(u"1.e5"_ns, Some(100000)); test_tofloat_helper(u""_ns, Nothing()); test_tofloat_helper(u"42foo"_ns, Nothing()); test_tofloat_helper(u"foo"_ns, Nothing()); test_tofloat_helper(u"1.5e-"_ns, Nothing()); // Leading spaces are ignored test_tofloat_helper(u" \t5"_ns, Some(5.f)); // Values which are too large generate an error test_tofloat_helper(u"3.402823e38"_ns, Some(3.402823e+38)); test_tofloat_helper(u"1e39"_ns, Nothing()); test_tofloat_helper(u"-3.402823e38"_ns, Some(-3.402823e+38)); test_tofloat_helper(u"-1e39"_ns, Nothing()); // Values which are too small round to zero test_tofloat_helper(u"1.4013e-45"_ns, Some(1.4013e-45f)); test_tofloat_helper(u"1e-46"_ns, Some(0.f)); test_tofloat_helper(u"-1.4013e-45"_ns, Some(-1.4013e-45f)); test_tofloat_helper(u"-1e-46"_ns, Some(-0.f)); } static void test_tofloat_allow_trailing_chars_helper(const nsString& aStr, Maybe aExpected) { nsresult result; float value = aStr.ToFloatAllowTrailingChars(&result); if (aExpected) { EXPECT_TRUE(NS_SUCCEEDED(result)); EXPECT_EQ(value, *aExpected); } else { EXPECT_TRUE(NS_FAILED(result)); } } TEST_F(Strings, ToFloatAllowTrailingChars) { test_tofloat_allow_trailing_chars_helper(u""_ns, Nothing()); test_tofloat_allow_trailing_chars_helper(u"foo"_ns, Nothing()); test_tofloat_allow_trailing_chars_helper(u"42foo"_ns, Some(42.f)); test_tofloat_allow_trailing_chars_helper(u"42-5"_ns, Some(42.f)); test_tofloat_allow_trailing_chars_helper(u"13.37.8"_ns, Some(13.37f)); test_tofloat_allow_trailing_chars_helper(u"1.5e-"_ns, Some(1.5f)); } static void test_todouble_helper(const nsString& aStr, Maybe aExpected) { nsresult result; double value = aStr.ToDouble(&result); if (aExpected) { EXPECT_TRUE(NS_SUCCEEDED(result)); EXPECT_EQ(value, *aExpected); } else { EXPECT_TRUE(NS_FAILED(result)); } } TEST_F(Strings, todouble) { test_todouble_helper(u"42"_ns, Some(42)); test_todouble_helper(u"42.0"_ns, Some(42)); test_todouble_helper(u"-42"_ns, Some(-42)); test_todouble_helper(u"+42"_ns, Some(42)); test_todouble_helper(u"13.37"_ns, Some(13.37)); test_todouble_helper(u"1.23456789"_ns, Some(1.23456789)); test_todouble_helper(u"1.98765432123456"_ns, Some(1.98765432123456)); test_todouble_helper(u"123456789.98765432123456"_ns, Some(123456789.98765432123456)); test_todouble_helper(u"0"_ns, Some(0)); test_todouble_helper(u"1.e5"_ns, Some(100000)); test_todouble_helper(u""_ns, Nothing()); test_todouble_helper(u"42foo"_ns, Nothing()); test_todouble_helper(u"foo"_ns, Nothing()); test_todouble_helper(u"1.5e-"_ns, Nothing()); // Leading spaces are ignored test_todouble_helper(u" \t5"_ns, Some(5.)); // Values which are too large generate an error test_todouble_helper(u"1.797693e+308"_ns, Some(1.797693e+308)); test_todouble_helper(u"1e309"_ns, Nothing()); test_todouble_helper(u"-1.797693e+308"_ns, Some(-1.797693e+308)); test_todouble_helper(u"-1e309"_ns, Nothing()); // Values which are too small round to zero test_todouble_helper(u"4.940656e-324"_ns, Some(4.940656e-324)); test_todouble_helper(u"1e-325"_ns, Some(0.)); test_todouble_helper(u"-4.940656e-324"_ns, Some(-4.940656e-324)); test_todouble_helper(u"-1e-325"_ns, Some(-0.)); } static void test_todouble_allow_trailing_chars_helper(const nsString& aStr, Maybe aExpected) { nsresult result; double value = aStr.ToDoubleAllowTrailingChars(&result); if (aExpected) { EXPECT_TRUE(NS_SUCCEEDED(result)); EXPECT_EQ(value, *aExpected); } else { EXPECT_TRUE(NS_FAILED(result)); } } TEST_F(Strings, ToDoubleAllowTrailingChars) { test_todouble_allow_trailing_chars_helper(u""_ns, Nothing()); test_todouble_allow_trailing_chars_helper(u"foo"_ns, Nothing()); test_todouble_allow_trailing_chars_helper(u"42foo"_ns, Some(42)); test_todouble_allow_trailing_chars_helper(u"42-5"_ns, Some(42)); test_todouble_allow_trailing_chars_helper(u"13.37.8"_ns, Some(13.37)); test_todouble_allow_trailing_chars_helper(u"1.5e-"_ns, Some(1.5)); } TEST_F(Strings, Split) { nsCString one("one"), two("one;two"), three("one--three"), empty(""), delimStart("-two"), delimEnd("one-"); nsString wide(u"hello world"); size_t counter = 0; for (const nsACString& token : one.Split(',')) { EXPECT_TRUE(token.EqualsLiteral("one")); counter++; } EXPECT_EQ(counter, (size_t)1); counter = 0; for (const nsACString& token : two.Split(';')) { if (counter == 0) { EXPECT_TRUE(token.EqualsLiteral("one")); } else if (counter == 1) { EXPECT_TRUE(token.EqualsLiteral("two")); } counter++; } EXPECT_EQ(counter, (size_t)2); counter = 0; for (const nsACString& token : three.Split('-')) { if (counter == 0) { EXPECT_TRUE(token.EqualsLiteral("one")); } else if (counter == 1) { EXPECT_TRUE(token.EqualsLiteral("")); } else if (counter == 2) { EXPECT_TRUE(token.EqualsLiteral("three")); } counter++; } EXPECT_EQ(counter, (size_t)3); counter = 0; for (const nsACString& token : empty.Split(',')) { mozilla::Unused << token; counter++; } EXPECT_EQ(counter, (size_t)0); counter = 0; for (const nsACString& token : delimStart.Split('-')) { if (counter == 0) { EXPECT_TRUE(token.EqualsLiteral("")); } else if (counter == 1) { EXPECT_TRUE(token.EqualsLiteral("two")); } counter++; } EXPECT_EQ(counter, (size_t)2); counter = 0; for (const nsACString& token : delimEnd.Split('-')) { if (counter == 0) { EXPECT_TRUE(token.EqualsLiteral("one")); } else if (counter == 1) { EXPECT_TRUE(token.EqualsLiteral("")); } counter++; } EXPECT_EQ(counter, (size_t)2); counter = 0; for (const nsAString& token : wide.Split(' ')) { if (counter == 0) { EXPECT_TRUE(token.Equals(u"hello"_ns)); } else if (counter == 1) { EXPECT_TRUE(token.Equals(u"world"_ns)); } counter++; } EXPECT_EQ(counter, (size_t)2); } TEST_F(Strings, Join) { // Join a sequence of strings. { // 8-bit strings EXPECT_EQ(""_ns, StringJoin(","_ns, std::array{})); EXPECT_EQ("foo"_ns, StringJoin(","_ns, std::array{"foo"_ns})); EXPECT_EQ("foo,bar"_ns, StringJoin(","_ns, std::array{"foo"_ns, "bar"_ns})); // 16-bit strings EXPECT_EQ(u""_ns, StringJoin(u","_ns, std::array{})); EXPECT_EQ(u"foo"_ns, StringJoin(u","_ns, std::array{u"foo"_ns})); EXPECT_EQ(u"foo,bar"_ns, StringJoin(u","_ns, std::array{u"foo"_ns, u"bar"_ns})); } // Join a sequence of strings, appending. { // 8-bit string { nsAutoCString dst{"prefix:"_ns}; StringJoinAppend(dst, ","_ns, std::array{"foo"_ns, "bar"_ns}); EXPECT_EQ("prefix:foo,bar"_ns, dst); } // 16-bit string { nsAutoString dst{u"prefix:"_ns}; StringJoinAppend(dst, u","_ns, std::array{u"foo"_ns, u"bar"_ns}); EXPECT_EQ(u"prefix:foo,bar"_ns, dst); } } } TEST_F(Strings, JoinWithAppendingTransformation) { const auto toCString = [](nsACString& dst, int val) { dst.AppendInt(val); }; const auto toString = [](nsAString& dst, int val) { dst.AppendInt(val); }; // Join a sequence of elements transformed to a string. { // 8-bit strings EXPECT_EQ(""_ns, StringJoin(","_ns, std::array{}, toCString)); EXPECT_EQ("7"_ns, StringJoin(","_ns, std::array{7}, toCString)); EXPECT_EQ("7,42"_ns, StringJoin(","_ns, std::array{7, 42}, toCString)); // 16-bit strings EXPECT_EQ(u""_ns, StringJoin(u","_ns, std::array{}, toString)); EXPECT_EQ(u"7"_ns, StringJoin(u","_ns, std::array{7}, toString)); EXPECT_EQ(u"7,42"_ns, StringJoin(u","_ns, std::array{7, 42}, toString)); } // Join a sequence of elements transformed to a string, appending. { // 8-bit string { nsAutoCString dst{"prefix:"_ns}; StringJoinAppend(dst, ","_ns, std::array{7, 42}, toCString); EXPECT_EQ("prefix:7,42"_ns, dst); } // 16-bit string { nsAutoString dst{u"prefix:"_ns}; StringJoinAppend(dst, u","_ns, std::array{7, 42}, toString); EXPECT_EQ(u"prefix:7,42"_ns, dst); } } } constexpr bool TestSomeChars(char c) { return c == 'a' || c == 'c' || c == 'e' || c == '7' || c == 'G' || c == 'Z' || c == '\b' || c == '?'; } TEST_F(Strings, ASCIIMask) { const ASCIIMaskArray& maskCRLF = mozilla::ASCIIMask::MaskCRLF(); EXPECT_TRUE(maskCRLF['\n'] && mozilla::ASCIIMask::IsMasked(maskCRLF, '\n')); EXPECT_TRUE(maskCRLF['\r'] && mozilla::ASCIIMask::IsMasked(maskCRLF, '\r')); EXPECT_FALSE(maskCRLF['g'] || mozilla::ASCIIMask::IsMasked(maskCRLF, 'g')); EXPECT_FALSE(maskCRLF[' '] || mozilla::ASCIIMask::IsMasked(maskCRLF, ' ')); EXPECT_FALSE(maskCRLF['\0'] || mozilla::ASCIIMask::IsMasked(maskCRLF, '\0')); EXPECT_FALSE(mozilla::ASCIIMask::IsMasked(maskCRLF, 14324)); const ASCIIMaskArray& mask0to9 = mozilla::ASCIIMask::Mask0to9(); EXPECT_TRUE(mask0to9['9'] && mozilla::ASCIIMask::IsMasked(mask0to9, '9')); EXPECT_TRUE(mask0to9['0'] && mozilla::ASCIIMask::IsMasked(mask0to9, '0')); EXPECT_TRUE(mask0to9['4'] && mozilla::ASCIIMask::IsMasked(mask0to9, '4')); EXPECT_FALSE(mask0to9['g'] || mozilla::ASCIIMask::IsMasked(mask0to9, 'g')); EXPECT_FALSE(mask0to9[' '] || mozilla::ASCIIMask::IsMasked(mask0to9, ' ')); EXPECT_FALSE(mask0to9['\n'] || mozilla::ASCIIMask::IsMasked(mask0to9, '\n')); EXPECT_FALSE(mask0to9['\0'] || mozilla::ASCIIMask::IsMasked(mask0to9, '\0')); EXPECT_FALSE(mozilla::ASCIIMask::IsMasked(maskCRLF, 14324)); const ASCIIMaskArray& maskWS = mozilla::ASCIIMask::MaskWhitespace(); EXPECT_TRUE(maskWS[' '] && mozilla::ASCIIMask::IsMasked(maskWS, ' ')); EXPECT_TRUE(maskWS['\t'] && mozilla::ASCIIMask::IsMasked(maskWS, '\t')); EXPECT_FALSE(maskWS['8'] || mozilla::ASCIIMask::IsMasked(maskWS, '8')); EXPECT_FALSE(maskWS['\0'] || mozilla::ASCIIMask::IsMasked(maskWS, '\0')); EXPECT_FALSE(mozilla::ASCIIMask::IsMasked(maskCRLF, 14324)); constexpr ASCIIMaskArray maskSome = mozilla::CreateASCIIMask(TestSomeChars); EXPECT_TRUE(maskSome['a'] && mozilla::ASCIIMask::IsMasked(maskSome, 'a')); EXPECT_TRUE(maskSome['c'] && mozilla::ASCIIMask::IsMasked(maskSome, 'c')); EXPECT_TRUE(maskSome['e'] && mozilla::ASCIIMask::IsMasked(maskSome, 'e')); EXPECT_TRUE(maskSome['7'] && mozilla::ASCIIMask::IsMasked(maskSome, '7')); EXPECT_TRUE(maskSome['G'] && mozilla::ASCIIMask::IsMasked(maskSome, 'G')); EXPECT_TRUE(maskSome['Z'] && mozilla::ASCIIMask::IsMasked(maskSome, 'Z')); EXPECT_TRUE(maskSome['\b'] && mozilla::ASCIIMask::IsMasked(maskSome, '\b')); EXPECT_TRUE(maskSome['?'] && mozilla::ASCIIMask::IsMasked(maskSome, '?')); EXPECT_FALSE(maskSome['8'] || mozilla::ASCIIMask::IsMasked(maskSome, '8')); EXPECT_FALSE(maskSome['\0'] || mozilla::ASCIIMask::IsMasked(maskSome, '\0')); EXPECT_FALSE(mozilla::ASCIIMask::IsMasked(maskCRLF, 14324)); } template void CompressWhitespaceHelper() { T s; s.AssignLiteral("abcabcabc"); s.CompressWhitespace(true, true); EXPECT_TRUE(s.EqualsLiteral("abcabcabc")); s.AssignLiteral(" \n\rabcabcabc\r\n"); s.CompressWhitespace(true, true); EXPECT_TRUE(s.EqualsLiteral("abcabcabc")); s.AssignLiteral(" \n\rabc abc abc\r\n"); s.CompressWhitespace(true, true); EXPECT_TRUE(s.EqualsLiteral("abc abc abc")); s.AssignLiteral(" \n\rabc\r abc\n abc\r\n"); s.CompressWhitespace(true, true); EXPECT_TRUE(s.EqualsLiteral("abc abc abc")); s.AssignLiteral(" \n\rabc\r \nabc\n \rabc\r\n"); s.CompressWhitespace(true, true); EXPECT_TRUE(s.EqualsLiteral("abc abc abc")); s.AssignLiteral(" \n\rabc\r abc\n abc\r\n"); s.CompressWhitespace(false, true); EXPECT_TRUE(s.EqualsLiteral(" abc abc abc")); s.AssignLiteral(" \n\rabc\r abc\n abc\r\n"); s.CompressWhitespace(true, false); EXPECT_TRUE(s.EqualsLiteral("abc abc abc ")); s.AssignLiteral(" \n\rabc\r abc\n abc\r\n"); s.CompressWhitespace(false, false); EXPECT_TRUE(s.EqualsLiteral(" abc abc abc ")); s.AssignLiteral(" \r\n "); s.CompressWhitespace(true, true); EXPECT_TRUE(s.EqualsLiteral("")); s.AssignLiteral(" \r\n \t"); s.CompressWhitespace(true, true); EXPECT_TRUE(s.EqualsLiteral("")); s.AssignLiteral("\n \r\n \t"); s.CompressWhitespace(false, false); EXPECT_TRUE(s.EqualsLiteral(" ")); s.AssignLiteral("\n \r\n \t"); s.CompressWhitespace(false, true); EXPECT_TRUE(s.EqualsLiteral("")); s.AssignLiteral("\n \r\n \t"); s.CompressWhitespace(true, false); EXPECT_TRUE(s.EqualsLiteral("")); s.AssignLiteral(""); s.CompressWhitespace(false, false); EXPECT_TRUE(s.EqualsLiteral("")); s.AssignLiteral(""); s.CompressWhitespace(false, true); EXPECT_TRUE(s.EqualsLiteral("")); s.AssignLiteral(""); s.CompressWhitespace(true, false); EXPECT_TRUE(s.EqualsLiteral("")); s.AssignLiteral(""); s.CompressWhitespace(true, true); EXPECT_TRUE(s.EqualsLiteral("")); } TEST_F(Strings, CompressWhitespace) { CompressWhitespaceHelper(); } TEST_F(Strings, CompressWhitespaceW) { CompressWhitespaceHelper(); nsString str, result; str.AssignLiteral(u"\u263A is\r\n ;-)"); result.AssignLiteral(u"\u263A is ;-)"); str.CompressWhitespace(true, true); EXPECT_TRUE(str == result); } template void StripCRLFHelper() { T s; s.AssignLiteral("abcabcabc"); s.StripCRLF(); EXPECT_TRUE(s.EqualsLiteral("abcabcabc")); s.AssignLiteral(" \n\rabcabcabc\r\n"); s.StripCRLF(); EXPECT_TRUE(s.EqualsLiteral(" abcabcabc")); s.AssignLiteral(" \n\rabc abc abc\r\n"); s.StripCRLF(); EXPECT_TRUE(s.EqualsLiteral(" abc abc abc")); s.AssignLiteral(" \n\rabc\r abc\n abc\r\n"); s.StripCRLF(); EXPECT_TRUE(s.EqualsLiteral(" abc abc abc")); s.AssignLiteral(" \n\rabc\r \nabc\n \rabc\r\n"); s.StripCRLF(); EXPECT_TRUE(s.EqualsLiteral(" abc abc abc")); s.AssignLiteral(" \n\rabc\r abc\n abc\r\n"); s.StripCRLF(); EXPECT_TRUE(s.EqualsLiteral(" abc abc abc")); s.AssignLiteral(" \r\n "); s.StripCRLF(); EXPECT_TRUE(s.EqualsLiteral(" ")); s.AssignLiteral(" \r\n \t"); s.StripCRLF(); EXPECT_TRUE(s.EqualsLiteral(" \t")); s.AssignLiteral("\n \r\n \t"); s.StripCRLF(); EXPECT_TRUE(s.EqualsLiteral(" \t")); s.AssignLiteral(""); s.StripCRLF(); EXPECT_TRUE(s.EqualsLiteral("")); } TEST_F(Strings, StripCRLF) { StripCRLFHelper(); } TEST_F(Strings, StripCRLFW) { StripCRLFHelper(); nsString str, result; str.AssignLiteral(u"\u263A is\r\n ;-)"); result.AssignLiteral(u"\u263A is ;-)"); str.StripCRLF(); EXPECT_TRUE(str == result); } TEST_F(Strings, utf8_to_latin1_sharing) { nsCString s; s.Append('a'); s.Append('b'); s.Append('c'); nsCString t; LossyAppendUTF8toLatin1(s, t); EXPECT_TRUE(t.EqualsLiteral("abc")); EXPECT_EQ(s.BeginReading(), t.BeginReading()); LossyCopyUTF8toLatin1(s, t); EXPECT_TRUE(t.EqualsLiteral("abc")); EXPECT_EQ(s.BeginReading(), t.BeginReading()); } TEST_F(Strings, latin1_to_utf8_sharing) { nsCString s; s.Append('a'); s.Append('b'); s.Append('c'); nsCString t; AppendLatin1toUTF8(s, t); EXPECT_TRUE(t.EqualsLiteral("abc")); EXPECT_EQ(s.BeginReading(), t.BeginReading()); CopyLatin1toUTF8(s, t); EXPECT_TRUE(t.EqualsLiteral("abc")); EXPECT_EQ(s.BeginReading(), t.BeginReading()); } TEST_F(Strings, utf8_to_latin1) { nsCString s; s.AssignLiteral("\xC3\xA4"); nsCString t; LossyCopyUTF8toLatin1(s, t); // EqualsLiteral requires ASCII EXPECT_TRUE(t.Equals("\xE4")); } TEST_F(Strings, latin1_to_utf8) { nsCString s; s.AssignLiteral("\xE4"); nsCString t; CopyLatin1toUTF8(s, t); // EqualsLiteral requires ASCII EXPECT_TRUE(t.Equals("\xC3\xA4")); } TEST_F(Strings, ConvertToSpan) { nsString string; // from const string { const auto& constStringRef = string; auto span = Span{constStringRef}; static_assert(std::is_same_v>); } // from non-const string { auto span = Span{string}; static_assert(std::is_same_v>); } // get mutable data { auto span = string.GetMutableData(); static_assert(std::is_same_v>); } nsCString cstring; // from const string { const auto& constCStringRef = cstring; auto span = Span{constCStringRef}; static_assert(std::is_same_v>); } // from non-const string { auto span = Span{cstring}; static_assert(std::is_same_v>); } // get mutable data { auto span = cstring.GetMutableData(); static_assert(std::is_same_v>); } } template void InsertSpanHelper() { T str1, str2; str1.AssignLiteral("hello world"); str2.AssignLiteral("span "); T expect; expect.AssignLiteral("hello span world"); Span span(str2); str1.Insert(span, 6); EXPECT_TRUE(str1.Equals(expect)); } TEST_F(Strings, InsertSpan) { InsertSpanHelper(); } TEST_F(Strings, InsertSpanW) { InsertSpanHelper(); } TEST_F(Strings, TokenizedRangeEmpty) { // 8-bit strings { for (const auto& token : nsCCharSeparatedTokenizer(""_ns, ',').ToRange()) { (void)token; ADD_FAILURE(); } } // 16-bit strings { for (const auto& token : nsCharSeparatedTokenizer(u""_ns, ',').ToRange()) { (void)token; ADD_FAILURE(); } } } TEST_F(Strings, TokenizedRangeWhitespaceOnly) { // 8-bit strings { for (const auto& token : nsCCharSeparatedTokenizer(" "_ns, ',').ToRange()) { (void)token; ADD_FAILURE(); } } // 16-bit strings { for (const auto& token : nsCharSeparatedTokenizer(u" "_ns, ',').ToRange()) { (void)token; ADD_FAILURE(); } } } TEST_F(Strings, TokenizedRangeNonEmpty) { // 8-bit strings { nsTArray res; for (const auto& token : nsCCharSeparatedTokenizer("foo,bar"_ns, ',').ToRange()) { res.EmplaceBack(token); } EXPECT_EQ(res, (nsTArray{"foo"_ns, "bar"_ns})); } // 16-bit strings { nsTArray res; for (const auto& token : nsCharSeparatedTokenizer(u"foo,bar"_ns, ',').ToRange()) { res.EmplaceBack(token); } EXPECT_EQ(res, (nsTArray{u"foo"_ns, u"bar"_ns})); } } // Macros for reducing verbosity of printf tests. #define create_printf_strings(format, ...) \ nsCString appendPrintfString; \ appendPrintfString.AppendPrintf(format, __VA_ARGS__); \ const nsCString appendVprintfString( \ getAppendVprintfString(format, __VA_ARGS__)); \ const nsPrintfCString printfString(format, __VA_ARGS__); \ const nsVprintfCString vprintfString{getVprintfCString(format, __VA_ARGS__)}; // We don't check every possible combination as we assume equality is // transitive. #define verify_printf_strings(expected) \ EXPECT_TRUE(appendPrintfString.EqualsASCII(expected)) \ << "appendPrintfString != expected:" << appendPrintfString.get() \ << " != " << (expected); \ EXPECT_TRUE(appendPrintfString.Equals(appendVprintfString)) \ << "appendPrintfString != appendVprintfString:" \ << appendPrintfString.get() << " != " << appendVprintfString; \ EXPECT_TRUE(appendPrintfString.Equals(printfString)) \ << "appendPrintfString != printfString:" << appendPrintfString.get() \ << " != " << printfString; \ EXPECT_TRUE(appendPrintfString.Equals(vprintfString)) \ << "appendPrintfString != vprintfString:" << appendPrintfString.get() \ << " != " << vprintfString; TEST_F(Strings, printf) { auto getAppendVprintfString = [](const char* aFormat, ...) { // Helper to get a string with contents set via AppendVprint. nsCString cString; va_list ap; va_start(ap, aFormat); cString.AppendVprintf(aFormat, ap); va_end(ap); return cString; }; auto getVprintfCString = [](const char* aFormat, ...) { // Helper to get a nsVprintfCString. va_list ap; va_start(ap, aFormat); const nsVprintfCString vprintfString(aFormat, ap); va_end(ap); return vprintfString; }; { const char* format = "Characters %c %%"; const char* expectedOutput = "Characters B %"; create_printf_strings(format, 'B'); verify_printf_strings(expectedOutput); } { const char* format = "Strings %s %s"; const char* expectedOutput = "Strings foo bar"; create_printf_strings(format, "foo", "bar"); verify_printf_strings(expectedOutput); } { const int signedThree = 3; const unsigned int unsignedTen = 10; const char* format = "Integers %i %.3d %.2u %o %x %X"; const char* expectedOutput = "Integers 3 003 10 12 a A"; create_printf_strings(format, signedThree, signedThree, unsignedTen, unsignedTen, unsignedTen, unsignedTen); verify_printf_strings(expectedOutput); } { const char* format = "Floats %f %.0f %e %.2E"; const char* expectedOutput = "Floats 1.500000 2 1.500000e+00 1.50E+00"; create_printf_strings(format, 1.5, 1.5, 1.5, 1.5); verify_printf_strings(expectedOutput); } { const char* expectedOutput = "Just a string"; const char* format = "%s"; create_printf_strings(format, "Just a string"); verify_printf_strings(expectedOutput); } { const char* anotherString = "another string"; const char* format = "Just a string and %s"; const char* expectedOutput = "Just a string and another string"; create_printf_strings(format, anotherString); verify_printf_strings(expectedOutput); } { // This case tickles an unexpected overload resolution in MSVC where a // va_list overload will be selected if available. See bug 1673670 and // 1673917 for more detail. char anotherString[] = "another string"; const char* format = "Just a string and %s"; const char* expectedOutput = "Just a string and another string"; // Calling with a non-const pointer triggers selection of va_list overload // in MSVC at time of writing create_printf_strings(format, (char*)anotherString); verify_printf_strings(expectedOutput); } } // We don't need these macros following the printf test. #undef verify_printf_strings #undef create_printf_strings // Note the five calls in the loop, so divide by 100k MOZ_GTEST_BENCH_F(Strings, PerfStripWhitespace, [this] { nsCString test1(mExample1Utf8); nsCString test2(mExample2Utf8); nsCString test3(mExample3Utf8); nsCString test4(mExample4Utf8); nsCString test5(mExample5Utf8); for (int i = 0; i < 20000; i++) { test1.StripWhitespace(); test2.StripWhitespace(); test3.StripWhitespace(); test4.StripWhitespace(); test5.StripWhitespace(); } }); MOZ_GTEST_BENCH_F(Strings, PerfStripCharsWhitespace, [this] { // This is the unoptimized (original) version of // StripWhitespace using StripChars. nsCString test1(mExample1Utf8); nsCString test2(mExample2Utf8); nsCString test3(mExample3Utf8); nsCString test4(mExample4Utf8); nsCString test5(mExample5Utf8); for (int i = 0; i < 20000; i++) { test1.StripChars("\f\t\r\n "); test2.StripChars("\f\t\r\n "); test3.StripChars("\f\t\r\n "); test4.StripChars("\f\t\r\n "); test5.StripChars("\f\t\r\n "); } }); MOZ_GTEST_BENCH_F(Strings, PerfCompressWhitespace, [this] { nsCString test1(mExample1Utf8); nsCString test2(mExample2Utf8); nsCString test3(mExample3Utf8); nsCString test4(mExample4Utf8); nsCString test5(mExample5Utf8); for (int i = 0; i < 20000; i++) { test1.CompressWhitespace(); test2.CompressWhitespace(); test3.CompressWhitespace(); test4.CompressWhitespace(); test5.CompressWhitespace(); } }); MOZ_GTEST_BENCH_F(Strings, PerfStripCRLF, [this] { nsCString test1(mExample1Utf8); nsCString test2(mExample2Utf8); nsCString test3(mExample3Utf8); nsCString test4(mExample4Utf8); nsCString test5(mExample5Utf8); for (int i = 0; i < 20000; i++) { test1.StripCRLF(); test2.StripCRLF(); test3.StripCRLF(); test4.StripCRLF(); test5.StripCRLF(); } }); MOZ_GTEST_BENCH_F(Strings, PerfStripCharsCRLF, [this] { // This is the unoptimized (original) version of // stripping \r\n using StripChars. nsCString test1(mExample1Utf8); nsCString test2(mExample2Utf8); nsCString test3(mExample3Utf8); nsCString test4(mExample4Utf8); nsCString test5(mExample5Utf8); for (int i = 0; i < 20000; i++) { test1.StripChars("\r\n"); test2.StripChars("\r\n"); test3.StripChars("\r\n"); test4.StripChars("\r\n"); test5.StripChars("\r\n"); } }); MOZ_GTEST_BENCH_F(Strings, PerfIsUTF8One, [this] { for (int i = 0; i < 200000; i++) { bool b = IsUtf8(*BlackBox(&mAsciiOneUtf8)); BlackBox(&b); } }); MOZ_GTEST_BENCH_F(Strings, PerfIsUTF8Fifteen, [this] { for (int i = 0; i < 200000; i++) { bool b = IsUtf8(*BlackBox(&mAsciiFifteenUtf8)); BlackBox(&b); } }); MOZ_GTEST_BENCH_F(Strings, PerfIsUTF8Hundred, [this] { for (int i = 0; i < 200000; i++) { bool b = IsUtf8(*BlackBox(&mAsciiHundredUtf8)); BlackBox(&b); } }); MOZ_GTEST_BENCH_F(Strings, PerfIsUTF8Example3, [this] { for (int i = 0; i < 100000; i++) { bool b = IsUtf8(*BlackBox(&mExample3Utf8)); BlackBox(&b); } }); MOZ_GTEST_BENCH_F(Strings, PerfIsASCII8One, [this] { for (int i = 0; i < 200000; i++) { bool b = IsAscii(*BlackBox(&mAsciiOneUtf8)); BlackBox(&b); } }); MOZ_GTEST_BENCH_F(Strings, PerfIsASCIIFifteen, [this] { for (int i = 0; i < 200000; i++) { bool b = IsAscii(*BlackBox(&mAsciiFifteenUtf8)); BlackBox(&b); } }); MOZ_GTEST_BENCH_F(Strings, PerfIsASCIIHundred, [this] { for (int i = 0; i < 200000; i++) { bool b = IsAscii(*BlackBox(&mAsciiHundredUtf8)); BlackBox(&b); } }); MOZ_GTEST_BENCH_F(Strings, PerfIsASCIIExample3, [this] { for (int i = 0; i < 100000; i++) { bool b = IsAscii(*BlackBox(&mExample3Utf8)); BlackBox(&b); } }); MOZ_GTEST_BENCH_F(Strings, PerfHasRTLCharsExample3, [this] { for (int i = 0; i < 5000; i++) { bool b = HasRTLChars(*BlackBox(&mExample3Utf16)); BlackBox(&b); } }); MOZ_GTEST_BENCH_F(Strings, PerfHasRTLCharsDE, [this] { for (int i = 0; i < 5000; i++) { bool b = HasRTLChars(*BlackBox(&mDeUtf16)); BlackBox(&b); } }); MOZ_GTEST_BENCH_F(Strings, PerfHasRTLCharsRU, [this] { for (int i = 0; i < 5000; i++) { bool b = HasRTLChars(*BlackBox(&mRuUtf16)); BlackBox(&b); } }); MOZ_GTEST_BENCH_F(Strings, PerfHasRTLCharsTH, [this] { for (int i = 0; i < 5000; i++) { bool b = HasRTLChars(*BlackBox(&mThUtf16)); BlackBox(&b); } }); MOZ_GTEST_BENCH_F(Strings, PerfHasRTLCharsJA, [this] { for (int i = 0; i < 5000; i++) { bool b = HasRTLChars(*BlackBox(&mJaUtf16)); BlackBox(&b); } }); CONVERSION_BENCH(PerfUTF16toLatin1ASCIIOne, LossyCopyUTF16toASCII, mAsciiOneUtf16, nsAutoCString); CONVERSION_BENCH(PerfUTF16toLatin1ASCIIThree, LossyCopyUTF16toASCII, mAsciiThreeUtf16, nsAutoCString); CONVERSION_BENCH(PerfUTF16toLatin1ASCIIFifteen, LossyCopyUTF16toASCII, mAsciiFifteenUtf16, nsAutoCString); CONVERSION_BENCH(PerfUTF16toLatin1ASCIIHundred, LossyCopyUTF16toASCII, mAsciiHundredUtf16, nsAutoCString); CONVERSION_BENCH(PerfUTF16toLatin1ASCIIThousand, LossyCopyUTF16toASCII, mAsciiThousandUtf16, nsAutoCString); CONVERSION_BENCH(PerfUTF16toLatin1DEOne, LossyCopyUTF16toASCII, mDeEditOneUtf16, nsAutoCString); CONVERSION_BENCH(PerfUTF16toLatin1DEThree, LossyCopyUTF16toASCII, mDeEditThreeUtf16, nsAutoCString); CONVERSION_BENCH(PerfUTF16toLatin1DEFifteen, LossyCopyUTF16toASCII, mDeEditFifteenUtf16, nsAutoCString); CONVERSION_BENCH(PerfUTF16toLatin1DEHundred, LossyCopyUTF16toASCII, mDeEditHundredUtf16, nsAutoCString); CONVERSION_BENCH(PerfUTF16toLatin1DEThousand, LossyCopyUTF16toASCII, mDeEditThousandUtf16, nsAutoCString); CONVERSION_BENCH(PerfLatin1toUTF16AsciiOne, CopyASCIItoUTF16, mAsciiOneUtf8, nsAutoString); CONVERSION_BENCH(PerfLatin1toUTF16AsciiThree, CopyASCIItoUTF16, mAsciiThreeUtf8, nsAutoString); CONVERSION_BENCH(PerfLatin1toUTF16AsciiFifteen, CopyASCIItoUTF16, mAsciiFifteenUtf8, nsAutoString); CONVERSION_BENCH(PerfLatin1toUTF16AsciiHundred, CopyASCIItoUTF16, mAsciiHundredUtf8, nsAutoString); CONVERSION_BENCH(PerfLatin1toUTF16AsciiThousand, CopyASCIItoUTF16, mAsciiThousandUtf8, nsAutoString); CONVERSION_BENCH(PerfLatin1toUTF16DEOne, CopyASCIItoUTF16, mDeEditOneLatin1, nsAutoString); CONVERSION_BENCH(PerfLatin1toUTF16DEThree, CopyASCIItoUTF16, mDeEditThreeLatin1, nsAutoString); CONVERSION_BENCH(PerfLatin1toUTF16DEFifteen, CopyASCIItoUTF16, mDeEditFifteenLatin1, nsAutoString); CONVERSION_BENCH(PerfLatin1toUTF16DEHundred, CopyASCIItoUTF16, mDeEditHundredLatin1, nsAutoString); CONVERSION_BENCH(PerfLatin1toUTF16DEThousand, CopyASCIItoUTF16, mDeEditThousandLatin1, nsAutoString); CONVERSION_BENCH(PerfUTF16toUTF8AsciiOne, CopyUTF16toUTF8, mAsciiOneUtf16, nsAutoCString); CONVERSION_BENCH(PerfUTF16toUTF8AsciiThree, CopyUTF16toUTF8, mAsciiThreeUtf16, nsAutoCString); CONVERSION_BENCH(PerfUTF16toUTF8AsciiFifteen, CopyUTF16toUTF8, mAsciiFifteenUtf16, nsAutoCString); CONVERSION_BENCH(PerfUTF16toUTF8AsciiHundred, CopyUTF16toUTF8, mAsciiHundredUtf16, nsAutoCString); CONVERSION_BENCH(PerfUTF16toUTF8AsciiThousand, CopyUTF16toUTF8, mAsciiThousandUtf16, nsAutoCString); CONVERSION_BENCH(PerfUTF8toUTF16AsciiOne, CopyUTF8toUTF16, mAsciiOneUtf8, nsAutoString); CONVERSION_BENCH(PerfUTF8toUTF16AsciiThree, CopyUTF8toUTF16, mAsciiThreeUtf8, nsAutoString); CONVERSION_BENCH(PerfUTF8toUTF16AsciiFifteen, CopyUTF8toUTF16, mAsciiFifteenUtf8, nsAutoString); CONVERSION_BENCH(PerfUTF8toUTF16AsciiHundred, CopyUTF8toUTF16, mAsciiHundredUtf8, nsAutoString); CONVERSION_BENCH(PerfUTF8toUTF16AsciiThousand, CopyUTF8toUTF16, mAsciiThousandUtf8, nsAutoString); CONVERSION_BENCH(PerfUTF16toUTF8AROne, CopyUTF16toUTF8, mArOneUtf16, nsAutoCString); CONVERSION_BENCH(PerfUTF16toUTF8ARThree, CopyUTF16toUTF8, mArThreeUtf16, nsAutoCString); CONVERSION_BENCH(PerfUTF16toUTF8ARFifteen, CopyUTF16toUTF8, mArFifteenUtf16, nsAutoCString); CONVERSION_BENCH(PerfUTF16toUTF8ARHundred, CopyUTF16toUTF8, mArHundredUtf16, nsAutoCString); CONVERSION_BENCH(PerfUTF16toUTF8ARThousand, CopyUTF16toUTF8, mArThousandUtf16, nsAutoCString); CONVERSION_BENCH(PerfUTF8toUTF16AROne, CopyUTF8toUTF16, mArOneUtf8, nsAutoString); CONVERSION_BENCH(PerfUTF8toUTF16ARThree, CopyUTF8toUTF16, mArThreeUtf8, nsAutoString); CONVERSION_BENCH(PerfUTF8toUTF16ARFifteen, CopyUTF8toUTF16, mArFifteenUtf8, nsAutoString); CONVERSION_BENCH(PerfUTF8toUTF16ARHundred, CopyUTF8toUTF16, mArHundredUtf8, nsAutoString); CONVERSION_BENCH(PerfUTF8toUTF16ARThousand, CopyUTF8toUTF16, mArThousandUtf8, nsAutoString); CONVERSION_BENCH(PerfUTF16toUTF8DEOne, CopyUTF16toUTF8, mDeOneUtf16, nsAutoCString); CONVERSION_BENCH(PerfUTF16toUTF8DEThree, CopyUTF16toUTF8, mDeThreeUtf16, nsAutoCString); CONVERSION_BENCH(PerfUTF16toUTF8DEFifteen, CopyUTF16toUTF8, mDeFifteenUtf16, nsAutoCString); CONVERSION_BENCH(PerfUTF16toUTF8DEHundred, CopyUTF16toUTF8, mDeHundredUtf16, nsAutoCString); CONVERSION_BENCH(PerfUTF16toUTF8DEThousand, CopyUTF16toUTF8, mDeThousandUtf16, nsAutoCString); CONVERSION_BENCH(PerfUTF8toUTF16DEOne, CopyUTF8toUTF16, mDeOneUtf8, nsAutoString); CONVERSION_BENCH(PerfUTF8toUTF16DEThree, CopyUTF8toUTF16, mDeThreeUtf8, nsAutoString); CONVERSION_BENCH(PerfUTF8toUTF16DEFifteen, CopyUTF8toUTF16, mDeFifteenUtf8, nsAutoString); CONVERSION_BENCH(PerfUTF8toUTF16DEHundred, CopyUTF8toUTF16, mDeHundredUtf8, nsAutoString); CONVERSION_BENCH(PerfUTF8toUTF16DEThousand, CopyUTF8toUTF16, mDeThousandUtf8, nsAutoString); CONVERSION_BENCH(PerfUTF16toUTF8RUOne, CopyUTF16toUTF8, mRuOneUtf16, nsAutoCString); CONVERSION_BENCH(PerfUTF16toUTF8RUThree, CopyUTF16toUTF8, mRuThreeUtf16, nsAutoCString); CONVERSION_BENCH(PerfUTF16toUTF8RUFifteen, CopyUTF16toUTF8, mRuFifteenUtf16, nsAutoCString); CONVERSION_BENCH(PerfUTF16toUTF8RUHundred, CopyUTF16toUTF8, mRuHundredUtf16, nsAutoCString); CONVERSION_BENCH(PerfUTF16toUTF8RUThousand, CopyUTF16toUTF8, mRuThousandUtf16, nsAutoCString); CONVERSION_BENCH(PerfUTF8toUTF16RUOne, CopyUTF8toUTF16, mRuOneUtf8, nsAutoString); CONVERSION_BENCH(PerfUTF8toUTF16RUThree, CopyUTF8toUTF16, mRuThreeUtf8, nsAutoString); CONVERSION_BENCH(PerfUTF8toUTF16RUFifteen, CopyUTF8toUTF16, mRuFifteenUtf8, nsAutoString); CONVERSION_BENCH(PerfUTF8toUTF16RUHundred, CopyUTF8toUTF16, mRuHundredUtf8, nsAutoString); CONVERSION_BENCH(PerfUTF8toUTF16RUThousand, CopyUTF8toUTF16, mRuThousandUtf8, nsAutoString); CONVERSION_BENCH(PerfUTF16toUTF8THOne, CopyUTF16toUTF8, mThOneUtf16, nsAutoCString); CONVERSION_BENCH(PerfUTF16toUTF8THThree, CopyUTF16toUTF8, mThThreeUtf16, nsAutoCString); CONVERSION_BENCH(PerfUTF16toUTF8THFifteen, CopyUTF16toUTF8, mThFifteenUtf16, nsAutoCString); CONVERSION_BENCH(PerfUTF16toUTF8THHundred, CopyUTF16toUTF8, mThHundredUtf16, nsAutoCString); CONVERSION_BENCH(PerfUTF16toUTF8THThousand, CopyUTF16toUTF8, mThThousandUtf16, nsAutoCString); CONVERSION_BENCH(PerfUTF8toUTF16THOne, CopyUTF8toUTF16, mThOneUtf8, nsAutoString); CONVERSION_BENCH(PerfUTF8toUTF16THThree, CopyUTF8toUTF16, mThThreeUtf8, nsAutoString); CONVERSION_BENCH(PerfUTF8toUTF16THFifteen, CopyUTF8toUTF16, mThFifteenUtf8, nsAutoString); CONVERSION_BENCH(PerfUTF8toUTF16THHundred, CopyUTF8toUTF16, mThHundredUtf8, nsAutoString); CONVERSION_BENCH(PerfUTF8toUTF16THThousand, CopyUTF8toUTF16, mThThousandUtf8, nsAutoString); CONVERSION_BENCH(PerfUTF16toUTF8JAOne, CopyUTF16toUTF8, mJaOneUtf16, nsAutoCString); CONVERSION_BENCH(PerfUTF16toUTF8JAThree, CopyUTF16toUTF8, mJaThreeUtf16, nsAutoCString); CONVERSION_BENCH(PerfUTF16toUTF8JAFifteen, CopyUTF16toUTF8, mJaFifteenUtf16, nsAutoCString); CONVERSION_BENCH(PerfUTF16toUTF8JAHundred, CopyUTF16toUTF8, mJaHundredUtf16, nsAutoCString); CONVERSION_BENCH(PerfUTF16toUTF8JAThousand, CopyUTF16toUTF8, mJaThousandUtf16, nsAutoCString); CONVERSION_BENCH(PerfUTF8toUTF16JAOne, CopyUTF8toUTF16, mJaOneUtf8, nsAutoString); CONVERSION_BENCH(PerfUTF8toUTF16JAThree, CopyUTF8toUTF16, mJaThreeUtf8, nsAutoString); CONVERSION_BENCH(PerfUTF8toUTF16JAFifteen, CopyUTF8toUTF16, mJaFifteenUtf8, nsAutoString); CONVERSION_BENCH(PerfUTF8toUTF16JAHundred, CopyUTF8toUTF16, mJaHundredUtf8, nsAutoString); CONVERSION_BENCH(PerfUTF8toUTF16JAThousand, CopyUTF8toUTF16, mJaThousandUtf8, nsAutoString); CONVERSION_BENCH(PerfUTF16toUTF8KOOne, CopyUTF16toUTF8, mKoOneUtf16, nsAutoCString); CONVERSION_BENCH(PerfUTF16toUTF8KOThree, CopyUTF16toUTF8, mKoThreeUtf16, nsAutoCString); CONVERSION_BENCH(PerfUTF16toUTF8KOFifteen, CopyUTF16toUTF8, mKoFifteenUtf16, nsAutoCString); CONVERSION_BENCH(PerfUTF16toUTF8KOHundred, CopyUTF16toUTF8, mKoHundredUtf16, nsAutoCString); CONVERSION_BENCH(PerfUTF16toUTF8KOThousand, CopyUTF16toUTF8, mKoThousandUtf16, nsAutoCString); CONVERSION_BENCH(PerfUTF8toUTF16KOOne, CopyUTF8toUTF16, mKoOneUtf8, nsAutoString); CONVERSION_BENCH(PerfUTF8toUTF16KOThree, CopyUTF8toUTF16, mKoThreeUtf8, nsAutoString); CONVERSION_BENCH(PerfUTF8toUTF16KOFifteen, CopyUTF8toUTF16, mKoFifteenUtf8, nsAutoString); CONVERSION_BENCH(PerfUTF8toUTF16KOHundred, CopyUTF8toUTF16, mKoHundredUtf8, nsAutoString); CONVERSION_BENCH(PerfUTF8toUTF16KOThousand, CopyUTF8toUTF16, mKoThousandUtf8, nsAutoString); CONVERSION_BENCH(PerfUTF16toUTF8TROne, CopyUTF16toUTF8, mTrOneUtf16, nsAutoCString); CONVERSION_BENCH(PerfUTF16toUTF8TRThree, CopyUTF16toUTF8, mTrThreeUtf16, nsAutoCString); CONVERSION_BENCH(PerfUTF16toUTF8TRFifteen, CopyUTF16toUTF8, mTrFifteenUtf16, nsAutoCString); CONVERSION_BENCH(PerfUTF16toUTF8TRHundred, CopyUTF16toUTF8, mTrHundredUtf16, nsAutoCString); CONVERSION_BENCH(PerfUTF16toUTF8TRThousand, CopyUTF16toUTF8, mTrThousandUtf16, nsAutoCString); CONVERSION_BENCH(PerfUTF8toUTF16TROne, CopyUTF8toUTF16, mTrOneUtf8, nsAutoString); CONVERSION_BENCH(PerfUTF8toUTF16TRThree, CopyUTF8toUTF16, mTrThreeUtf8, nsAutoString); CONVERSION_BENCH(PerfUTF8toUTF16TRFifteen, CopyUTF8toUTF16, mTrFifteenUtf8, nsAutoString); CONVERSION_BENCH(PerfUTF8toUTF16TRHundred, CopyUTF8toUTF16, mTrHundredUtf8, nsAutoString); CONVERSION_BENCH(PerfUTF8toUTF16TRThousand, CopyUTF8toUTF16, mTrThousandUtf8, nsAutoString); CONVERSION_BENCH(PerfUTF16toUTF8VIOne, CopyUTF16toUTF8, mViOneUtf16, nsAutoCString); CONVERSION_BENCH(PerfUTF16toUTF8VIThree, CopyUTF16toUTF8, mViThreeUtf16, nsAutoCString); CONVERSION_BENCH(PerfUTF16toUTF8VIFifteen, CopyUTF16toUTF8, mViFifteenUtf16, nsAutoCString); CONVERSION_BENCH(PerfUTF16toUTF8VIHundred, CopyUTF16toUTF8, mViHundredUtf16, nsAutoCString); CONVERSION_BENCH(PerfUTF16toUTF8VIThousand, CopyUTF16toUTF8, mViThousandUtf16, nsAutoCString); CONVERSION_BENCH(PerfUTF8toUTF16VIOne, CopyUTF8toUTF16, mViOneUtf8, nsAutoString); CONVERSION_BENCH(PerfUTF8toUTF16VIThree, CopyUTF8toUTF16, mViThreeUtf8, nsAutoString); CONVERSION_BENCH(PerfUTF8toUTF16VIFifteen, CopyUTF8toUTF16, mViFifteenUtf8, nsAutoString); CONVERSION_BENCH(PerfUTF8toUTF16VIHundred, CopyUTF8toUTF16, mViHundredUtf8, nsAutoString); CONVERSION_BENCH(PerfUTF8toUTF16VIThousand, CopyUTF8toUTF16, mViThousandUtf8, nsAutoString); // Tests for usability of nsTLiteralString in constant expressions. static_assert(u""_ns.IsEmpty()); constexpr auto testStringA = u"a"_ns; static_assert(!testStringA.IsEmpty()); static_assert(!testStringA.IsVoid()); static_assert(testStringA.IsLiteral()); static_assert(testStringA.IsTerminated()); static_assert(testStringA.GetDataFlags() == (nsLiteralString::DataFlags::LITERAL | nsLiteralString::DataFlags::TERMINATED)); static_assert(*static_cast(testStringA.Data()) == 'a'); static_assert(1 == testStringA.Length()); static_assert(testStringA.CharAt(0) == 'a'); static_assert(testStringA[0] == 'a'); static_assert(*testStringA.BeginReading() == 'a'); static_assert(*testStringA.EndReading() == 0); static_assert(testStringA.EndReading() - testStringA.BeginReading() == 1); } // namespace TestStrings