TestCharacterDataBuffer.cpp (24098B)
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* This Source Code Form is subject to the terms of the Mozilla Public 3 * License, v. 2.0. If a copy of the MPL was not distributed with this 4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 5 6 #include "gtest/gtest.h" 7 #include "mozilla/BasePrincipal.h" 8 #include "mozilla/OriginAttributes.h" 9 #include "mozilla/dom/CharacterDataBuffer.h" 10 #include "mozilla/dom/Document.h" 11 #include "nsCOMPtr.h" 12 #include "nsIURI.h" 13 #include "nsNetUtil.h" 14 #include "nsString.h" 15 #include "nsTextNode.h" 16 17 namespace mozilla::dom { 18 19 using WhitespaceOption = CharacterDataBuffer::WhitespaceOption; 20 using WhitespaceOptions = CharacterDataBuffer::WhitespaceOptions; 21 22 static already_AddRefed<Document> CreateHTMLDoc() { 23 nsCOMPtr<nsIURI> uri; 24 NS_NewURI(getter_AddRefs(uri), "data:text/html,"); 25 26 RefPtr<BasePrincipal> principal = 27 BasePrincipal::CreateContentPrincipal(uri, OriginAttributes()); 28 MOZ_RELEASE_ASSERT(principal); 29 30 nsCOMPtr<mozilla::dom::Document> doc; 31 MOZ_ALWAYS_SUCCEEDS(NS_NewDOMDocument(getter_AddRefs(doc), 32 u""_ns, // aNamespaceURI 33 u""_ns, // aQualifiedName 34 nullptr, // aDoctype 35 uri, uri, principal, 36 LoadedAsData::No, // aLoadedAsData 37 nullptr, // aEventObject 38 DocumentFlavor::HTML)); 39 MOZ_RELEASE_ASSERT(doc); 40 return doc.forget(); 41 } 42 43 struct TestData { 44 TestData(const char16_t* aData, const char16_t* aScanData, 45 uint32_t aStartOffset, uint32_t aExpectedOffset) 46 : mData(aData), 47 mScanData(aScanData), 48 mStartOffset(aStartOffset), 49 mExpectedOffset(aExpectedOffset) {} 50 51 friend std::ostream& operator<<(std::ostream& aStream, 52 const TestData& aData) { 53 return aStream << "Scan \"" << NS_ConvertUTF16toUTF8(aData.mScanData).get() 54 << "\" in \"" << NS_ConvertUTF16toUTF8(aData.mData).get() 55 << "\" starting from " << aData.mStartOffset; 56 } 57 58 const char16_t* const mData; 59 const char16_t* const mScanData; 60 const uint32_t mStartOffset; 61 const uint32_t mExpectedOffset; 62 }; 63 64 TEST(CharacterDataBufferTest, FindChar1b) 65 { 66 const RefPtr<Document> doc = CreateHTMLDoc(); 67 const RefPtr<nsTextNode> textNode = doc->CreateTextNode(EmptyString()); 68 MOZ_RELEASE_ASSERT(textNode); 69 const CharacterDataBuffer& characterDataBuffer = textNode->DataBuffer(); 70 71 for (const auto& testData : { 72 TestData(u"", u"a", 0, CharacterDataBuffer::kNotFound), 73 TestData(u"abc", u"a", 0, 0), 74 TestData(u"abc", u"A", 0, CharacterDataBuffer::kNotFound), 75 TestData(u"abc", u"b", 0, 1), 76 TestData(u"abc", u"c", 0, 2), 77 TestData(u"abc", u"a", 1, CharacterDataBuffer::kNotFound), 78 TestData(u"abc", u"b", 1, 1), 79 TestData(u"abc", u"c", 2, 2), 80 TestData(u"a\u00A0b", u"\u00A0", 0, 1), 81 }) { 82 textNode->SetData(nsDependentString(testData.mData), IgnoreErrors()); 83 MOZ_ASSERT(!characterDataBuffer.Is2b()); 84 const uint32_t ret = characterDataBuffer.FindChar(testData.mScanData[0], 85 testData.mStartOffset); 86 EXPECT_EQ(ret, testData.mExpectedOffset) << testData; 87 } 88 } 89 90 TEST(CharacterDataBufferTest, FindChar2b) 91 { 92 const RefPtr<Document> doc = CreateHTMLDoc(); 93 const RefPtr<nsTextNode> textNode = doc->CreateTextNode(EmptyString()); 94 MOZ_RELEASE_ASSERT(textNode); 95 textNode->MarkAsMaybeModifiedFrequently(); 96 const CharacterDataBuffer& characterDataBuffer = textNode->DataBuffer(); 97 98 for (const auto& testData : { 99 TestData(u"abc", u"a", 0, 0), 100 TestData(u"abc", u"A", 0, CharacterDataBuffer::kNotFound), 101 TestData(u"abc", u"b", 0, 1), 102 TestData(u"abc", u"c", 0, 2), 103 TestData(u"abc", u"a", 1, CharacterDataBuffer::kNotFound), 104 TestData(u"abc", u"b", 1, 1), 105 TestData(u"abc", u"c", 2, 2), 106 TestData(u"a\u00A0b", u"\u00A0", 0, 1), 107 }) { 108 textNode->SetData(nsDependentString(testData.mData), IgnoreErrors()); 109 MOZ_ASSERT(characterDataBuffer.Is2b()); 110 const uint32_t ret = characterDataBuffer.FindChar(testData.mScanData[0], 111 testData.mStartOffset); 112 EXPECT_EQ(ret, testData.mExpectedOffset) << testData; 113 } 114 } 115 116 TEST(CharacterDataBufferTest, RFindChar1b) 117 { 118 const RefPtr<Document> doc = CreateHTMLDoc(); 119 const RefPtr<nsTextNode> textNode = doc->CreateTextNode(EmptyString()); 120 MOZ_RELEASE_ASSERT(textNode); 121 const CharacterDataBuffer& characterDataBuffer = textNode->DataBuffer(); 122 123 for (const auto& testData : { 124 TestData(u"", u"a", UINT32_MAX, CharacterDataBuffer::kNotFound), 125 TestData(u"abc", u"a", UINT32_MAX, 0), 126 TestData(u"abc", u"A", UINT32_MAX, CharacterDataBuffer::kNotFound), 127 TestData(u"abc", u"b", UINT32_MAX, 1), 128 TestData(u"abc", u"c", UINT32_MAX, 2), 129 TestData(u"abca", u"a", UINT32_MAX, 3), 130 TestData(u"abc", u"a", 0, 0), 131 TestData(u"abc", u"c", 2, 2), 132 TestData(u"a\u00A0b", u"\u00A0", UINT32_MAX, 1), 133 }) { 134 textNode->SetData(nsDependentString(testData.mData), IgnoreErrors()); 135 MOZ_ASSERT(!characterDataBuffer.Is2b()); 136 const uint32_t ret = characterDataBuffer.RFindChar(testData.mScanData[0], 137 testData.mStartOffset); 138 EXPECT_EQ(ret, testData.mExpectedOffset) << testData; 139 } 140 } 141 142 TEST(CharacterDataBufferTest, RFindChar2b) 143 { 144 const RefPtr<Document> doc = CreateHTMLDoc(); 145 const RefPtr<nsTextNode> textNode = doc->CreateTextNode(EmptyString()); 146 MOZ_RELEASE_ASSERT(textNode); 147 textNode->MarkAsMaybeModifiedFrequently(); 148 const CharacterDataBuffer& characterDataBuffer = textNode->DataBuffer(); 149 150 for (const auto& testData : { 151 TestData(u"abc", u"a", UINT32_MAX, 0), 152 TestData(u"abc", u"A", UINT32_MAX, CharacterDataBuffer::kNotFound), 153 TestData(u"abc", u"b", UINT32_MAX, 1), 154 TestData(u"abc", u"c", UINT32_MAX, 2), 155 TestData(u"abca", u"a", UINT32_MAX, 3), 156 TestData(u"abc", u"a", 0, 0), 157 TestData(u"abc", u"c", 2, 2), 158 TestData(u"a\u00A0b", u"\u00A0", UINT32_MAX, 1), 159 }) { 160 textNode->SetData(nsDependentString(testData.mData), IgnoreErrors()); 161 MOZ_ASSERT(characterDataBuffer.Is2b()); 162 const uint32_t ret = characterDataBuffer.RFindChar(testData.mScanData[0], 163 testData.mStartOffset); 164 EXPECT_EQ(ret, testData.mExpectedOffset) << testData; 165 } 166 } 167 168 TEST(CharacterDataBufferTest, FindFirstDifferentCharOffsetIn1b) 169 { 170 const RefPtr<Document> doc = CreateHTMLDoc(); 171 const RefPtr<nsTextNode> textNode = doc->CreateTextNode(EmptyString()); 172 MOZ_RELEASE_ASSERT(textNode); 173 const CharacterDataBuffer& characterDataBuffer = textNode->DataBuffer(); 174 175 for (const auto& testData : { 176 TestData(u"abcdef", u"abc", 0, CharacterDataBuffer::kNotFound), 177 TestData(u"abcdef", u"Abc", 0, 0), 178 TestData(u"abcdef", u"aBc", 0, 1), 179 TestData(u"abcdef", u"abC", 0, 2), 180 TestData(u"abcdef", u"def", 3, CharacterDataBuffer::kNotFound), 181 TestData(u"abcdef", u"Def", 3, 3), 182 TestData(u"abcdef", u"dEf", 3, 4), 183 TestData(u"abcdef", u"deF", 3, 5), 184 }) { 185 textNode->SetData(nsDependentString(testData.mData), IgnoreErrors()); 186 MOZ_ASSERT(!characterDataBuffer.Is2b()); 187 const uint32_t ret = characterDataBuffer.FindFirstDifferentCharOffset( 188 NS_ConvertUTF16toUTF8(testData.mScanData), testData.mStartOffset); 189 EXPECT_EQ(ret, testData.mExpectedOffset) << testData; 190 } 191 } 192 193 TEST(CharacterDataBufferTest, FindFirstDifferentCharOffsetIn2b) 194 { 195 const RefPtr<Document> doc = CreateHTMLDoc(); 196 const RefPtr<nsTextNode> textNode = doc->CreateTextNode(EmptyString()); 197 MOZ_RELEASE_ASSERT(textNode); 198 textNode->MarkAsMaybeModifiedFrequently(); 199 const CharacterDataBuffer& characterDataBuffer = textNode->DataBuffer(); 200 201 for (const auto& testData : { 202 TestData(u"abcdef", u"abc", 0, CharacterDataBuffer::kNotFound), 203 TestData(u"abcdef", u"Abc", 0, 0), 204 TestData(u"abcdef", u"aBc", 0, 1), 205 TestData(u"abcdef", u"abC", 0, 2), 206 TestData(u"abcdef", u"def", 3, CharacterDataBuffer::kNotFound), 207 TestData(u"abcdef", u"Def", 3, 3), 208 TestData(u"abcdef", u"dEf", 3, 4), 209 TestData(u"abcdef", u"deF", 3, 5), 210 }) { 211 textNode->SetData(nsDependentString(testData.mData), IgnoreErrors()); 212 MOZ_ASSERT(characterDataBuffer.Is2b()); 213 const uint32_t ret = characterDataBuffer.FindFirstDifferentCharOffset( 214 NS_ConvertUTF16toUTF8(testData.mScanData), testData.mStartOffset); 215 EXPECT_EQ(ret, testData.mExpectedOffset) << testData; 216 } 217 } 218 219 TEST(CharacterDataBufferTest, RFindFirstDifferentCharOffsetIn1b) 220 { 221 const RefPtr<Document> doc = CreateHTMLDoc(); 222 const RefPtr<nsTextNode> textNode = doc->CreateTextNode(EmptyString()); 223 MOZ_RELEASE_ASSERT(textNode); 224 const CharacterDataBuffer& characterDataBuffer = textNode->DataBuffer(); 225 226 for (const auto& testData : { 227 TestData(u"abcdef", u"abc", 3, CharacterDataBuffer::kNotFound), 228 TestData(u"abcdef", u"Abc", 3, 0), 229 TestData(u"abcdef", u"aBc", 3, 1), 230 TestData(u"abcdef", u"abC", 3, 2), 231 TestData(u"abcdef", u"def", 6, CharacterDataBuffer::kNotFound), 232 TestData(u"abcdef", u"Def", 6, 3), 233 TestData(u"abcdef", u"dEf", 6, 4), 234 TestData(u"abcdef", u"deF", 6, 5), 235 }) { 236 textNode->SetData(nsDependentString(testData.mData), IgnoreErrors()); 237 MOZ_ASSERT(!characterDataBuffer.Is2b()); 238 const uint32_t ret = characterDataBuffer.RFindFirstDifferentCharOffset( 239 NS_ConvertUTF16toUTF8(testData.mScanData), testData.mStartOffset); 240 EXPECT_EQ(ret, testData.mExpectedOffset) << testData; 241 } 242 } 243 244 TEST(CharacterDataBufferTest, RFindFirstDifferentCharOffsetIn2b) 245 { 246 const RefPtr<Document> doc = CreateHTMLDoc(); 247 const RefPtr<nsTextNode> textNode = doc->CreateTextNode(EmptyString()); 248 MOZ_RELEASE_ASSERT(textNode); 249 textNode->MarkAsMaybeModifiedFrequently(); 250 const CharacterDataBuffer& characterDataBuffer = textNode->DataBuffer(); 251 252 for (const auto& testData : { 253 TestData(u"abcdef", u"abc", 3, CharacterDataBuffer::kNotFound), 254 TestData(u"abcdef", u"Abc", 3, 0), 255 TestData(u"abcdef", u"aBc", 3, 1), 256 TestData(u"abcdef", u"abC", 3, 2), 257 TestData(u"abcdef", u"def", 6, CharacterDataBuffer::kNotFound), 258 TestData(u"abcdef", u"Def", 6, 3), 259 TestData(u"abcdef", u"dEf", 6, 4), 260 TestData(u"abcdef", u"deF", 6, 5), 261 }) { 262 textNode->SetData(nsDependentString(testData.mData), IgnoreErrors()); 263 MOZ_ASSERT(characterDataBuffer.Is2b()); 264 const uint32_t ret = characterDataBuffer.RFindFirstDifferentCharOffset( 265 NS_ConvertUTF16toUTF8(testData.mScanData), testData.mStartOffset); 266 EXPECT_EQ(ret, testData.mExpectedOffset) << testData; 267 } 268 } 269 270 struct TestDataForFindNonWhitespace { 271 TestDataForFindNonWhitespace(const char16_t* aData, uint32_t aOffset, 272 const WhitespaceOptions& aOptions, 273 uint32_t aExpectedOffset) 274 : mData(aData), 275 mOffset(aOffset), 276 mExpectedOffset(aExpectedOffset), 277 mOptions(aOptions) {} 278 279 friend std::ostream& operator<<(std::ostream& aStream, 280 const TestDataForFindNonWhitespace& aData) { 281 aStream << "Scan with options={"; 282 bool isFirstOption = true; 283 if (aData.mOptions.contains(WhitespaceOption::FormFeedIsSignificant)) { 284 aStream << "WhitespaceOption::FormFeedIsSignificant"; 285 isFirstOption = false; 286 } 287 if (aData.mOptions.contains(WhitespaceOption::NewLineIsSignificant)) { 288 if (!isFirstOption) { 289 aStream << ", "; 290 } 291 aStream << "WhitespaceOption::NewLineIsSignificant"; 292 isFirstOption = false; 293 } 294 if (aData.mOptions.contains(WhitespaceOption::TreatNBSPAsCollapsible)) { 295 if (!isFirstOption) { 296 aStream << ", "; 297 } 298 aStream << "WhitespaceOption::TreatNBSPAsCollapsible"; 299 isFirstOption = false; 300 } 301 return aStream << "} in \"" << aData.FormatUTF8Data().get() 302 << "\" starting from " << aData.mOffset; 303 } 304 305 nsAutoCString FormatUTF8Data() const { 306 nsAutoString data(mData); 307 data.ReplaceSubstring(u"\n"_ns, u"\\n"_ns); 308 data.ReplaceSubstring(u"\t"_ns, u"\\t"_ns); 309 data.ReplaceSubstring(u"\r"_ns, u"\\r"_ns); 310 data.ReplaceSubstring(u"\f"_ns, u"\\f"_ns); 311 data.ReplaceSubstring(u"\u00A0"_ns, u" "_ns); 312 return NS_ConvertUTF16toUTF8(data); 313 } 314 315 const char16_t* const mData; 316 const uint32_t mOffset; 317 const uint32_t mExpectedOffset; 318 const WhitespaceOptions mOptions; 319 }; 320 321 TEST(CharacterDataBufferTest, FindNonWhitespaceIn1b) 322 { 323 const RefPtr<Document> doc = CreateHTMLDoc(); 324 const RefPtr<nsTextNode> textNode = doc->CreateTextNode(EmptyString()); 325 MOZ_RELEASE_ASSERT(textNode); 326 const CharacterDataBuffer& characterDataBuffer = textNode->DataBuffer(); 327 328 for (const auto& testData : { 329 TestDataForFindNonWhitespace(u"", 0, {}, 330 CharacterDataBuffer::kNotFound), 331 TestDataForFindNonWhitespace(u" ", 0, {}, 332 CharacterDataBuffer::kNotFound), 333 TestDataForFindNonWhitespace(u" ", 0, {}, 334 CharacterDataBuffer::kNotFound), 335 TestDataForFindNonWhitespace(u"\t\n\r\f", 0, {}, 336 CharacterDataBuffer::kNotFound), 337 TestDataForFindNonWhitespace(u" \t\n\r\f", 0, {}, 338 CharacterDataBuffer::kNotFound), 339 TestDataForFindNonWhitespace(u"a", 0, {}, 0), 340 TestDataForFindNonWhitespace(u" a", 0, {}, 1), 341 TestDataForFindNonWhitespace(u"\u00A0", 0, {}, 0), 342 TestDataForFindNonWhitespace(u" \u00A0", 0, {}, 1), 343 TestDataForFindNonWhitespace(u"a b", 1, {}, 2), 344 TestDataForFindNonWhitespace(u"a b", 2, {}, 2), 345 TestDataForFindNonWhitespace( 346 u"\fa", 0, {WhitespaceOption::FormFeedIsSignificant}, 0), 347 TestDataForFindNonWhitespace( 348 u" \fa", 0, {WhitespaceOption::FormFeedIsSignificant}, 1), 349 TestDataForFindNonWhitespace( 350 u"\n", 0, {WhitespaceOption::NewLineIsSignificant}, 0), 351 TestDataForFindNonWhitespace( 352 u" \n", 0, {WhitespaceOption::NewLineIsSignificant}, 1), 353 TestDataForFindNonWhitespace( 354 u"\u00A0", 0, {WhitespaceOption::TreatNBSPAsCollapsible}, 355 CharacterDataBuffer::kNotFound), 356 TestDataForFindNonWhitespace( 357 u" \u00A0", 0, {WhitespaceOption::TreatNBSPAsCollapsible}, 358 CharacterDataBuffer::kNotFound), 359 }) { 360 textNode->SetData(nsDependentString(testData.mData), IgnoreErrors()); 361 MOZ_ASSERT(!characterDataBuffer.Is2b()); 362 const uint32_t ret = characterDataBuffer.FindNonWhitespaceChar( 363 testData.mOptions, testData.mOffset); 364 EXPECT_EQ(ret, testData.mExpectedOffset) << testData; 365 } 366 } 367 368 TEST(CharacterDataBufferTest, FindNonWhitespaceIn2b) 369 { 370 const RefPtr<Document> doc = CreateHTMLDoc(); 371 const RefPtr<nsTextNode> textNode = doc->CreateTextNode(EmptyString()); 372 MOZ_RELEASE_ASSERT(textNode); 373 textNode->MarkAsMaybeModifiedFrequently(); 374 const CharacterDataBuffer& characterDataBuffer = textNode->DataBuffer(); 375 376 for (const auto& testData : { 377 TestDataForFindNonWhitespace(u" ", 0, {}, 378 CharacterDataBuffer::kNotFound), 379 TestDataForFindNonWhitespace(u" ", 0, {}, 380 CharacterDataBuffer::kNotFound), 381 TestDataForFindNonWhitespace(u"\t\n\r\f", 0, {}, 382 CharacterDataBuffer::kNotFound), 383 TestDataForFindNonWhitespace(u" \t\n\r\f", 0, {}, 384 CharacterDataBuffer::kNotFound), 385 TestDataForFindNonWhitespace(u"a", 0, {}, 0), 386 TestDataForFindNonWhitespace(u" a", 0, {}, 1), 387 TestDataForFindNonWhitespace(u"\u00A0", 0, {}, 0), 388 TestDataForFindNonWhitespace(u" \u00A0", 0, {}, 1), 389 TestDataForFindNonWhitespace(u"a b", 1, {}, 2), 390 TestDataForFindNonWhitespace(u"a b", 2, {}, 2), 391 TestDataForFindNonWhitespace( 392 u"\fa", 0, {WhitespaceOption::FormFeedIsSignificant}, 0), 393 TestDataForFindNonWhitespace( 394 u" \fa", 0, {WhitespaceOption::FormFeedIsSignificant}, 1), 395 TestDataForFindNonWhitespace( 396 u"\n", 0, {WhitespaceOption::NewLineIsSignificant}, 0), 397 TestDataForFindNonWhitespace( 398 u" \n", 0, {WhitespaceOption::NewLineIsSignificant}, 1), 399 TestDataForFindNonWhitespace( 400 u"\u00A0", 0, {WhitespaceOption::TreatNBSPAsCollapsible}, 401 CharacterDataBuffer::kNotFound), 402 TestDataForFindNonWhitespace( 403 u" \u00A0", 0, {WhitespaceOption::TreatNBSPAsCollapsible}, 404 CharacterDataBuffer::kNotFound), 405 }) { 406 textNode->SetData(nsDependentString(testData.mData), IgnoreErrors()); 407 MOZ_ASSERT(characterDataBuffer.Is2b()); 408 const uint32_t ret = characterDataBuffer.FindNonWhitespaceChar( 409 testData.mOptions, testData.mOffset); 410 EXPECT_EQ(ret, testData.mExpectedOffset) << testData; 411 } 412 } 413 414 TEST(CharacterDataBufferTest, RFindNonWhitespaceIn1b) 415 { 416 const RefPtr<Document> doc = CreateHTMLDoc(); 417 const RefPtr<nsTextNode> textNode = doc->CreateTextNode(EmptyString()); 418 MOZ_RELEASE_ASSERT(textNode); 419 const CharacterDataBuffer& characterDataBuffer = textNode->DataBuffer(); 420 421 for (const auto& testData : { 422 TestDataForFindNonWhitespace(u"", UINT32_MAX, {}, 423 CharacterDataBuffer::kNotFound), 424 TestDataForFindNonWhitespace(u" ", UINT32_MAX, {}, 425 CharacterDataBuffer::kNotFound), 426 TestDataForFindNonWhitespace(u" ", UINT32_MAX, {}, 427 CharacterDataBuffer::kNotFound), 428 TestDataForFindNonWhitespace(u"\t\n\r\f", UINT32_MAX, {}, 429 CharacterDataBuffer::kNotFound), 430 TestDataForFindNonWhitespace(u"\t\n\r\f ", UINT32_MAX, {}, 431 CharacterDataBuffer::kNotFound), 432 TestDataForFindNonWhitespace(u"a", UINT32_MAX, {}, 0), 433 TestDataForFindNonWhitespace(u"a ", UINT32_MAX, {}, 0), 434 TestDataForFindNonWhitespace(u"ab", UINT32_MAX, {}, 1), 435 TestDataForFindNonWhitespace(u"ab ", UINT32_MAX, {}, 1), 436 TestDataForFindNonWhitespace(u"a\u00A0", UINT32_MAX, {}, 1), 437 TestDataForFindNonWhitespace(u"a\u00A0 ", UINT32_MAX, {}, 1), 438 TestDataForFindNonWhitespace(u"a b", 1, {}, 0), 439 TestDataForFindNonWhitespace(u"a b", 0, {}, 0), 440 TestDataForFindNonWhitespace( 441 u"a\f", UINT32_MAX, {WhitespaceOption::FormFeedIsSignificant}, 442 1), 443 TestDataForFindNonWhitespace( 444 u"a\f ", UINT32_MAX, {WhitespaceOption::FormFeedIsSignificant}, 445 1), 446 TestDataForFindNonWhitespace( 447 u"a\n", UINT32_MAX, {WhitespaceOption::NewLineIsSignificant}, 1), 448 TestDataForFindNonWhitespace( 449 u"a\n ", UINT32_MAX, {WhitespaceOption::NewLineIsSignificant}, 450 1), 451 TestDataForFindNonWhitespace( 452 u"a\u00A0", UINT32_MAX, 453 {WhitespaceOption::TreatNBSPAsCollapsible}, 0), 454 TestDataForFindNonWhitespace( 455 u"a\u00A0 ", UINT32_MAX, 456 {WhitespaceOption::TreatNBSPAsCollapsible}, 0), 457 }) { 458 textNode->SetData(nsDependentString(testData.mData), IgnoreErrors()); 459 MOZ_ASSERT(!characterDataBuffer.Is2b()); 460 const uint32_t ret = characterDataBuffer.RFindNonWhitespaceChar( 461 testData.mOptions, testData.mOffset); 462 EXPECT_EQ(ret, testData.mExpectedOffset) << testData; 463 } 464 } 465 466 TEST(CharacterDataBufferTest, RFindNonWhitespaceIn2b) 467 { 468 const RefPtr<Document> doc = CreateHTMLDoc(); 469 const RefPtr<nsTextNode> textNode = doc->CreateTextNode(EmptyString()); 470 MOZ_RELEASE_ASSERT(textNode); 471 textNode->MarkAsMaybeModifiedFrequently(); 472 const CharacterDataBuffer& characterDataBuffer = textNode->DataBuffer(); 473 474 for (const auto& testData : { 475 TestDataForFindNonWhitespace(u" ", UINT32_MAX, {}, 476 CharacterDataBuffer::kNotFound), 477 TestDataForFindNonWhitespace(u" ", UINT32_MAX, {}, 478 CharacterDataBuffer::kNotFound), 479 TestDataForFindNonWhitespace(u"\t\n\r\f", UINT32_MAX, {}, 480 CharacterDataBuffer::kNotFound), 481 TestDataForFindNonWhitespace(u"\t\n\r\f ", UINT32_MAX, {}, 482 CharacterDataBuffer::kNotFound), 483 TestDataForFindNonWhitespace(u"a", UINT32_MAX, {}, 0), 484 TestDataForFindNonWhitespace(u"a ", UINT32_MAX, {}, 0), 485 TestDataForFindNonWhitespace(u"ab", UINT32_MAX, {}, 1), 486 TestDataForFindNonWhitespace(u"ab ", UINT32_MAX, {}, 1), 487 TestDataForFindNonWhitespace(u"a\u00A0", UINT32_MAX, {}, 1), 488 TestDataForFindNonWhitespace(u"a\u00A0 ", UINT32_MAX, {}, 1), 489 TestDataForFindNonWhitespace(u"a b", 1, {}, 0), 490 TestDataForFindNonWhitespace(u"a b", 0, {}, 0), 491 TestDataForFindNonWhitespace( 492 u"a\f", UINT32_MAX, {WhitespaceOption::FormFeedIsSignificant}, 493 1), 494 TestDataForFindNonWhitespace( 495 u"a\f ", UINT32_MAX, {WhitespaceOption::FormFeedIsSignificant}, 496 1), 497 TestDataForFindNonWhitespace( 498 u"a\n", UINT32_MAX, {WhitespaceOption::NewLineIsSignificant}, 1), 499 TestDataForFindNonWhitespace( 500 u"a\n ", UINT32_MAX, {WhitespaceOption::NewLineIsSignificant}, 501 1), 502 TestDataForFindNonWhitespace( 503 u"a\u00A0", UINT32_MAX, 504 {WhitespaceOption::TreatNBSPAsCollapsible}, 0), 505 TestDataForFindNonWhitespace( 506 u"a\u00A0 ", UINT32_MAX, 507 {WhitespaceOption::TreatNBSPAsCollapsible}, 0), 508 }) { 509 textNode->SetData(nsDependentString(testData.mData), IgnoreErrors()); 510 MOZ_ASSERT(characterDataBuffer.Is2b()); 511 const uint32_t ret = characterDataBuffer.RFindNonWhitespaceChar( 512 testData.mOptions, testData.mOffset); 513 EXPECT_EQ(ret, testData.mExpectedOffset) << testData; 514 } 515 } 516 517 TEST(CharacterDataBufferTest, SafeAPIsChar1b) 518 { 519 const RefPtr<Document> doc = CreateHTMLDoc(); 520 const RefPtr<nsTextNode> textNode = doc->CreateTextNode(EmptyString()); 521 MOZ_RELEASE_ASSERT(textNode); 522 const CharacterDataBuffer& characterDataBuffer = textNode->DataBuffer(); 523 524 // Test empty data buffer. 525 EXPECT_EQ(characterDataBuffer.SafeFirstChar(), u'\0'); 526 EXPECT_EQ(characterDataBuffer.SafeLastChar(), u'\0'); 527 EXPECT_EQ(characterDataBuffer.SafeCharAt(100), u'\0'); 528 529 // Test non-empty data buffer. 530 const char16_t* testStr = u"abcdef"; 531 textNode->SetData(nsDependentString(testStr), IgnoreErrors()); 532 MOZ_ASSERT(!characterDataBuffer.Is2b()); 533 534 EXPECT_EQ(characterDataBuffer.SafeFirstChar(), u'a'); 535 EXPECT_EQ(characterDataBuffer.SafeLastChar(), u'f'); 536 EXPECT_EQ(characterDataBuffer.SafeCharAt(2), u'c'); 537 EXPECT_EQ(characterDataBuffer.SafeCharAt(100), u'\0'); 538 } 539 540 }; // namespace mozilla::dom