153 строки
4.9 KiB
C++
153 строки
4.9 KiB
C++
/*
|
|
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
*
|
|
* This source code is licensed under the MIT license found in the
|
|
* LICENSE file in the root directory of this source tree.
|
|
*/
|
|
|
|
#include "hermes/VM/StringView.h"
|
|
#include "hermes/VM/Runtime.h"
|
|
|
|
#include "TestHelpers.h"
|
|
|
|
#include "gtest/gtest.h"
|
|
|
|
using namespace hermes::vm;
|
|
|
|
namespace {
|
|
|
|
using StringViewTest = RuntimeTestFixture;
|
|
|
|
TEST_F(StringViewTest, Construction) {
|
|
// Test createStringView
|
|
UTF16Ref str1 = createUTF16Ref(u"abcdef\x100");
|
|
auto strPrim1 = StringPrimitive::createNoThrow(runtime, str1);
|
|
StringView view1 = StringPrimitive::createStringView(runtime, strPrim1);
|
|
EXPECT_TRUE(!view1.isASCII());
|
|
EXPECT_EQ(view1.length(), 7u);
|
|
|
|
// Test getUTF16Ref and copyUTF16String.
|
|
SmallU16String<8> storage;
|
|
UTF16Ref ref1 = view1.getUTF16Ref(storage);
|
|
// Does not need to use storage.
|
|
EXPECT_TRUE(storage.empty());
|
|
EXPECT_EQ(ref1.data(), view1.castToChar16Ptr());
|
|
|
|
// After copy, storage should now contain data.
|
|
view1.appendUTF16String(storage);
|
|
EXPECT_EQ(storage.size(), 7u);
|
|
}
|
|
|
|
TEST_F(StringViewTest, Comparison) {
|
|
auto strPrim1 =
|
|
StringPrimitive::createNoThrow(runtime, createUTF16Ref(u"abcde"));
|
|
auto view1 = StringPrimitive::createStringView(runtime, strPrim1);
|
|
|
|
auto strPrim2 =
|
|
StringPrimitive::createNoThrow(runtime, createUTF16Ref(u"abcdefg"));
|
|
auto view2 = StringPrimitive::createStringView(runtime, strPrim2);
|
|
|
|
EXPECT_FALSE(view1.equals(view2));
|
|
EXPECT_FALSE(view2.equals(view1));
|
|
|
|
auto strPrim3 =
|
|
StringPrimitive::createNoThrow(runtime, createUTF16Ref(u"abc"));
|
|
auto view3 = StringPrimitive::createStringView(runtime, strPrim3);
|
|
|
|
EXPECT_FALSE(view1.equals(view3));
|
|
EXPECT_FALSE(view3.equals(view1));
|
|
|
|
auto strPrim4 =
|
|
StringPrimitive::createNoThrow(runtime, createUTF16Ref(u"defgh"));
|
|
auto view4 = StringPrimitive::createStringView(runtime, strPrim4);
|
|
EXPECT_FALSE(view1.equals(view4));
|
|
EXPECT_FALSE(view4.equals(view1));
|
|
|
|
llvh::StringRef str = "abcde";
|
|
auto strPrim5 = StringPrimitive::createNoThrow(runtime, str);
|
|
auto view5 = StringPrimitive::createStringView(runtime, strPrim5);
|
|
EXPECT_TRUE(view1.equals(view5));
|
|
EXPECT_TRUE(view1.equals(view5));
|
|
|
|
// Test copy ctor and operator=.
|
|
StringView tmp = view1;
|
|
EXPECT_TRUE(tmp.equals(view1));
|
|
tmp = view2;
|
|
EXPECT_FALSE(tmp.equals(view1));
|
|
tmp = view1;
|
|
EXPECT_TRUE(tmp.equals(view1));
|
|
}
|
|
|
|
TEST_F(StringViewTest, HandleHandling) {
|
|
// StringView conditionally holds onto a handle.
|
|
// This verifies that we correctly perform handle book-keeping in ctors and
|
|
// operator=. It has no assertions; it relies on GCScope to check its handle
|
|
// count in its dtor.
|
|
GCScope scope1{runtime, "StringViewTest.HandleHandling1"};
|
|
|
|
auto strPrim1 = StringPrimitive::createNoThrow(
|
|
runtime, createUTF16Ref(u"I have a handle"));
|
|
StringView scope1View1 = StringPrimitive::createStringView(runtime, strPrim1);
|
|
StringView scope1View2 = StringPrimitive::createStringView(runtime, strPrim1);
|
|
StringView scope1View3 = StringPrimitive::createStringView(runtime, strPrim1);
|
|
(void)scope1View3;
|
|
|
|
GCScope scope2{runtime, "StringViewTest.HandleHandling2"};
|
|
auto strPrim2 = StringPrimitive::createNoThrow(
|
|
runtime, createUTF16Ref(u"I also have a handle"));
|
|
StringView scope2View1 = StringPrimitive::createStringView(runtime, strPrim2);
|
|
|
|
// This assignment requires us to change the GCScope associated with the
|
|
// handle in scope1.
|
|
StringView tmp1 = scope2View1;
|
|
tmp1 = scope1View1;
|
|
|
|
// This ctor ensures we bump the handle count in scope1 and decrement it
|
|
// scope2.
|
|
StringView tmp2 = scope1View1;
|
|
(void)tmp2;
|
|
|
|
// Same but with moves ctor and operator=.
|
|
StringView tmp3 = std::move(scope1View2);
|
|
(void)tmp3;
|
|
StringView tmp4 = scope2View1;
|
|
tmp4 = std::move(scope1View2);
|
|
}
|
|
|
|
TEST_F(StringViewTest, Iteration) {
|
|
auto str1 = createUTF16Ref(u"abcdefghijklmnopqrstuvwxyz");
|
|
auto strPrim1 = StringPrimitive::createNoThrow(runtime, str1);
|
|
auto view1 = StringPrimitive::createStringView(runtime, strPrim1);
|
|
uint32_t index = 0;
|
|
for (const char16_t c : view1) {
|
|
EXPECT_EQ(c, str1[index++]);
|
|
}
|
|
}
|
|
|
|
TEST_F(StringViewTest, Slice) {
|
|
auto str = createUTF16Ref(u"abcdefgh");
|
|
auto strPrim1 = StringPrimitive::createNoThrow(runtime, str);
|
|
auto view = StringPrimitive::createStringView(runtime, strPrim1);
|
|
auto itr = view.begin();
|
|
for (uint32_t i = 0; i < 8; ++i, ++itr) {
|
|
EXPECT_TRUE(view.slice(i).equals(str.slice(i)));
|
|
EXPECT_TRUE(view.slice(i, 8 - i).equals(str.slice(i, 8 - i)));
|
|
EXPECT_TRUE(view.slice(itr, view.end()).equals(str.slice(i)));
|
|
}
|
|
}
|
|
|
|
TEST_F(StringViewTest, Output) {
|
|
auto str = createUTF16Ref(u"abcd");
|
|
llvh::SmallVector<char, 32> result{};
|
|
llvh::raw_svector_ostream os{result};
|
|
auto strPrim = StringPrimitive::createNoThrow(runtime, str);
|
|
auto view = StringPrimitive::createStringView(runtime, strPrim);
|
|
os << view;
|
|
EXPECT_EQ('a', result[0]);
|
|
EXPECT_EQ('b', result[1]);
|
|
EXPECT_EQ('c', result[2]);
|
|
EXPECT_EQ('d', result[3]);
|
|
}
|
|
|
|
} // namespace
|