/* -*- 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 <stdio.h>
#include <stdlib.h>
#include "nsASCIIMask.h"
#include "nsCharSeparatedTokenizer.h"
#include "nsPrintfCString.h"
#include "nsString.h"
#include "mozilla/StringBuffer.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;
using mozilla::StringBuffer;
#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 <
typename T>
struct EnableTest {
template <
typename Q = T,
typename EnableIfChar16 = mozilla::Char16OnlyT<Q>>
bool IsChar16() {
return true;
}
template <
typename Q = T,
typename EnableIfChar = mozilla::CharOnlyT<Q>>
bool IsChar16(
int dummy = 42) {
return false;
}
template <
typename Q = T,
typename EnableIfChar16 = mozilla::Char16OnlyT<Q>>
bool IsChar() {
return false;
}
template <
typename Q = T,
typename EnableIfChar = mozilla::CharOnlyT<Q>>
bool IsChar(
int dummy = 42) {
return true;
}
};
TEST_F(Strings, IsChar) {
EnableTest<
char> charTest;
EXPECT_TRUE(charTest.IsChar());
EXPECT_FALSE(charTest.IsChar16());
EnableTest<char16_t> 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<StringBuffer> buf;
buf = StringBuffer::Alloc(
sizeof(kData));
EXPECT_TRUE(!!buf);
buf = StringBuffer::Alloc(
sizeof(kData));
EXPECT_TRUE(!!buf);
char* data = (
char*)buf->Data();
memcpy(data, kData,
sizeof(kData));
nsCString str;
str.Assign(buf,
sizeof(kData) - 1);
StringBuffer* buf2 = str.GetStringBuffer();
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);
}
}
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<nsCString> 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<
float> 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<
float> 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<
double> 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<
double> 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<nsCString, 0>{}));
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<nsString, 0>{}));
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<
int, 0>{}, 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<
int, 0>{}, 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 <
typename T>
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<nsCString>(); }
TEST_F(Strings, CompressWhitespaceW) {
CompressWhitespaceHelper<nsString>();
nsString str, result;
str.AssignLiteral(u
"\u263A is\r\n ;-)");
result.AssignLiteral(u
"\u263A is ;-)");
str.CompressWhitespace(
true,
true);
EXPECT_TRUE(str == result);
}
template <
typename T>
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<nsCString>(); }
TEST_F(Strings, StripCRLFW) {
StripCRLFHelper<nsString>();
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;
--> --------------------
--> maximum size reached
--> --------------------