| //===-- Unittests for string_view -----------------------------------------===// |
| // |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| // See https://llvm.org/LICENSE.txt for license information. |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #include "src/__support/CPP/string_view.h" |
| #include "src/__support/CPP/type_traits.h" |
| #include "src/string/memory_utils/inline_memcpy.h" |
| #include "test/UnitTest/Test.h" |
| |
| using TestCharTypes = LIBC_NAMESPACE::testing::TypeList<char, wchar_t>; |
| |
| template <typename CharT> |
| const CharT *chooseLiteral(const char *CharStr, const wchar_t *WCharStr) { |
| if constexpr (LIBC_NAMESPACE::cpp::is_same_v<CharT, char>) |
| return CharStr; |
| else { |
| static_assert(LIBC_NAMESPACE::cpp::is_same_v<CharT, wchar_t>); |
| return WCharStr; |
| } |
| } |
| |
| template <typename CharT> |
| CharT chooseLiteral(char CharValue, wchar_t WCharValue) { |
| if constexpr (LIBC_NAMESPACE::cpp::is_same_v<CharT, char>) |
| return CharValue; |
| else { |
| static_assert(LIBC_NAMESPACE::cpp::is_same_v<CharT, wchar_t>); |
| return WCharValue; |
| } |
| } |
| |
| #define ENCODED(CharT, S) chooseLiteral<CharT>(S, L##S) |
| |
| TYPED_TEST(LlvmLibcStringViewTest, InitializeCheck, TestCharTypes) { |
| using CharT = ParamType; |
| using StringView = LIBC_NAMESPACE::cpp::basic_string_view<CharT>; |
| |
| StringView S; |
| ASSERT_EQ(S.size(), size_t(0)); |
| ASSERT_TRUE(S.data() == nullptr); |
| |
| S = StringView(ENCODED(CharT, "")); |
| ASSERT_EQ(S.size(), size_t(0)); |
| ASSERT_TRUE(S.data() != nullptr); |
| |
| S = StringView(ENCODED(CharT, "abc"), 0); |
| ASSERT_EQ(S.size(), size_t(0)); |
| ASSERT_TRUE(S.data() != nullptr); |
| |
| S = StringView(ENCODED(CharT, "123456789")); |
| ASSERT_EQ(S.size(), size_t(9)); |
| |
| S = StringView(ENCODED(CharT, "123456789"), 5); |
| ASSERT_EQ(S.size(), size_t(5)); |
| } |
| |
| TYPED_TEST(LlvmLibcStringViewTest, Equals, TestCharTypes) { |
| using CharT = ParamType; |
| using StringView = LIBC_NAMESPACE::cpp::basic_string_view<CharT>; |
| |
| StringView S(ENCODED(CharT, "abc")); |
| ASSERT_EQ(S, StringView(ENCODED(CharT, "abc"))); |
| ASSERT_NE(S, StringView()); |
| ASSERT_NE(S, StringView(ENCODED(CharT, ""))); |
| ASSERT_NE(S, StringView(ENCODED(CharT, "123"))); |
| ASSERT_NE(S, StringView(ENCODED(CharT, "abd"))); |
| ASSERT_NE(S, StringView(ENCODED(CharT, "aaa"))); |
| ASSERT_NE(S, StringView(ENCODED(CharT, "abcde"))); |
| } |
| |
| TYPED_TEST(LlvmLibcStringViewTest, startsWith, TestCharTypes) { |
| using CharT = ParamType; |
| using StringView = LIBC_NAMESPACE::cpp::basic_string_view<CharT>; |
| |
| StringView S(ENCODED(CharT, "abc")); |
| ASSERT_TRUE(S.starts_with(ENCODED(CharT, 'a'))); |
| ASSERT_TRUE(S.starts_with(StringView(ENCODED(CharT, "a")))); |
| ASSERT_TRUE(S.starts_with(StringView(ENCODED(CharT, "ab")))); |
| ASSERT_TRUE(S.starts_with(StringView(ENCODED(CharT, "abc")))); |
| ASSERT_TRUE(S.starts_with(StringView())); |
| ASSERT_TRUE(S.starts_with(StringView(ENCODED(CharT, "")))); |
| ASSERT_FALSE(S.starts_with(ENCODED(CharT, '1'))); |
| ASSERT_FALSE(S.starts_with(StringView(ENCODED(CharT, "123")))); |
| ASSERT_FALSE(S.starts_with(StringView(ENCODED(CharT, "abd")))); |
| ASSERT_FALSE(S.starts_with(StringView(ENCODED(CharT, "aaa")))); |
| ASSERT_FALSE(S.starts_with(StringView(ENCODED(CharT, "abcde")))); |
| } |
| |
| TYPED_TEST(LlvmLibcStringViewTest, endsWith, TestCharTypes) { |
| using CharT = ParamType; |
| using StringView = LIBC_NAMESPACE::cpp::basic_string_view<CharT>; |
| |
| StringView S(ENCODED(CharT, "abc")); |
| ASSERT_TRUE(S.ends_with(ENCODED(CharT, 'c'))); |
| ASSERT_TRUE(S.ends_with(StringView(ENCODED(CharT, "c")))); |
| ASSERT_TRUE(S.ends_with(StringView(ENCODED(CharT, "bc")))); |
| ASSERT_TRUE(S.ends_with(StringView(ENCODED(CharT, "abc")))); |
| ASSERT_TRUE(S.ends_with(StringView())); |
| ASSERT_TRUE(S.ends_with(StringView(ENCODED(CharT, "")))); |
| ASSERT_FALSE(S.ends_with(ENCODED(CharT, '1'))); |
| ASSERT_FALSE(S.ends_with(StringView(ENCODED(CharT, "123")))); |
| ASSERT_FALSE(S.ends_with(StringView(ENCODED(CharT, "abd")))); |
| ASSERT_FALSE(S.ends_with(StringView(ENCODED(CharT, "aaa")))); |
| ASSERT_FALSE(S.ends_with(StringView(ENCODED(CharT, "abcde")))); |
| } |
| |
| TYPED_TEST(LlvmLibcStringViewTest, RemovePrefix, TestCharTypes) { |
| using CharT = ParamType; |
| using StringView = LIBC_NAMESPACE::cpp::basic_string_view<CharT>; |
| |
| StringView A(ENCODED(CharT, "123456789")); |
| A.remove_prefix(0); |
| ASSERT_EQ(A.size(), size_t(9)); |
| ASSERT_TRUE(A == ENCODED(CharT, "123456789")); |
| |
| StringView B(ENCODED(CharT, "123456789")); |
| B.remove_prefix(4); |
| ASSERT_EQ(B.size(), size_t(5)); |
| ASSERT_TRUE(B == ENCODED(CharT, "56789")); |
| |
| StringView C(ENCODED(CharT, "123456789")); |
| C.remove_prefix(9); |
| ASSERT_EQ(C.size(), size_t(0)); |
| } |
| |
| TYPED_TEST(LlvmLibcStringViewTest, RemoveSuffix, TestCharTypes) { |
| using CharT = ParamType; |
| using StringView = LIBC_NAMESPACE::cpp::basic_string_view<CharT>; |
| |
| StringView A(ENCODED(CharT, "123456789")); |
| A.remove_suffix(0); |
| ASSERT_EQ(A.size(), size_t(9)); |
| ASSERT_TRUE(A == ENCODED(CharT, "123456789")); |
| |
| StringView B(ENCODED(CharT, "123456789")); |
| B.remove_suffix(4); |
| ASSERT_EQ(B.size(), size_t(5)); |
| ASSERT_TRUE(B == ENCODED(CharT, "12345")); |
| |
| StringView C(ENCODED(CharT, "123456789")); |
| C.remove_suffix(9); |
| ASSERT_EQ(C.size(), size_t(0)); |
| } |
| |
| TYPED_TEST(LlvmLibcStringViewTest, Observer, TestCharTypes) { |
| using CharT = ParamType; |
| using StringView = LIBC_NAMESPACE::cpp::basic_string_view<CharT>; |
| |
| StringView ABC(ENCODED(CharT, "abc")); |
| ASSERT_EQ(ABC.size(), size_t(3)); |
| ASSERT_FALSE(ABC.empty()); |
| ASSERT_EQ(ABC.front(), ENCODED(CharT, 'a')); |
| ASSERT_EQ(ABC.back(), ENCODED(CharT, 'c')); |
| } |
| |
| TYPED_TEST(LlvmLibcStringViewTest, FindFirstOf, TestCharTypes) { |
| using CharT = ParamType; |
| using StringView = LIBC_NAMESPACE::cpp::basic_string_view<CharT>; |
| |
| StringView Tmp(ENCODED(CharT, "abca")); |
| ASSERT_TRUE(Tmp.find_first_of(ENCODED(CharT, 'a')) == 0); |
| ASSERT_TRUE(Tmp.find_first_of(ENCODED(CharT, 'd')) == StringView::npos); |
| ASSERT_TRUE(Tmp.find_first_of(ENCODED(CharT, 'b')) == 1); |
| ASSERT_TRUE(Tmp.find_first_of(ENCODED(CharT, 'a'), 0) == 0); |
| ASSERT_TRUE(Tmp.find_first_of(ENCODED(CharT, 'b'), 1) == 1); |
| ASSERT_TRUE(Tmp.find_first_of(ENCODED(CharT, 'a'), 1) == 3); |
| ASSERT_TRUE(Tmp.find_first_of(ENCODED(CharT, 'a'), 42) == StringView::npos); |
| ASSERT_FALSE(Tmp.find_first_of(ENCODED(CharT, 'c')) == 1); |
| ASSERT_FALSE(Tmp.find_first_of(ENCODED(CharT, 'c'), 0) == 1); |
| ASSERT_FALSE(Tmp.find_first_of(ENCODED(CharT, 'c'), 1) == 1); |
| } |
| |
| TYPED_TEST(LlvmLibcStringViewTest, FindLastOf, TestCharTypes) { |
| using CharT = ParamType; |
| using StringView = LIBC_NAMESPACE::cpp::basic_string_view<CharT>; |
| |
| StringView Tmp(ENCODED(CharT, "abada")); |
| |
| ASSERT_EQ(Tmp.find_last_of(ENCODED(CharT, 'a')), size_t(4)); |
| ASSERT_EQ(Tmp.find_last_of(ENCODED(CharT, 'a'), 123), size_t(4)); |
| ASSERT_EQ(Tmp.find_last_of(ENCODED(CharT, 'a'), 5), size_t(4)); |
| ASSERT_EQ(Tmp.find_last_of(ENCODED(CharT, 'a'), 4), size_t(4)); |
| ASSERT_EQ(Tmp.find_last_of(ENCODED(CharT, 'a'), 3), size_t(2)); |
| ASSERT_EQ(Tmp.find_last_of(ENCODED(CharT, 'a'), 2), size_t(2)); |
| ASSERT_EQ(Tmp.find_last_of(ENCODED(CharT, 'a'), 1), size_t(0)); |
| ASSERT_EQ(Tmp.find_last_of(ENCODED(CharT, 'a'), 0), size_t(0)); |
| |
| ASSERT_EQ(Tmp.find_last_of(ENCODED(CharT, 'b')), size_t(1)); |
| ASSERT_EQ(Tmp.find_last_of(ENCODED(CharT, 'b'), 123), size_t(1)); |
| ASSERT_EQ(Tmp.find_last_of(ENCODED(CharT, 'b'), 5), size_t(1)); |
| ASSERT_EQ(Tmp.find_last_of(ENCODED(CharT, 'b'), 4), size_t(1)); |
| ASSERT_EQ(Tmp.find_last_of(ENCODED(CharT, 'b'), 3), size_t(1)); |
| ASSERT_EQ(Tmp.find_last_of(ENCODED(CharT, 'b'), 2), size_t(1)); |
| ASSERT_EQ(Tmp.find_last_of(ENCODED(CharT, 'b'), 1), size_t(1)); |
| ASSERT_EQ(Tmp.find_last_of(ENCODED(CharT, 'b'), 0), StringView::npos); |
| |
| ASSERT_EQ(Tmp.find_last_of(ENCODED(CharT, 'd')), size_t(3)); |
| ASSERT_EQ(Tmp.find_last_of(ENCODED(CharT, 'd'), 123), size_t(3)); |
| ASSERT_EQ(Tmp.find_last_of(ENCODED(CharT, 'd'), 5), size_t(3)); |
| ASSERT_EQ(Tmp.find_last_of(ENCODED(CharT, 'd'), 4), size_t(3)); |
| ASSERT_EQ(Tmp.find_last_of(ENCODED(CharT, 'd'), 3), size_t(3)); |
| ASSERT_EQ(Tmp.find_last_of(ENCODED(CharT, 'd'), 2), StringView::npos); |
| ASSERT_EQ(Tmp.find_last_of(ENCODED(CharT, 'd'), 1), StringView::npos); |
| ASSERT_EQ(Tmp.find_last_of(ENCODED(CharT, 'd'), 0), StringView::npos); |
| |
| ASSERT_EQ(Tmp.find_last_of(ENCODED(CharT, 'e')), StringView::npos); |
| ASSERT_EQ(Tmp.find_last_of(ENCODED(CharT, 'e'), 123), StringView::npos); |
| ASSERT_EQ(Tmp.find_last_of(ENCODED(CharT, 'e'), 5), StringView::npos); |
| ASSERT_EQ(Tmp.find_last_of(ENCODED(CharT, 'e'), 4), StringView::npos); |
| ASSERT_EQ(Tmp.find_last_of(ENCODED(CharT, 'e'), 3), StringView::npos); |
| ASSERT_EQ(Tmp.find_last_of(ENCODED(CharT, 'e'), 2), StringView::npos); |
| ASSERT_EQ(Tmp.find_last_of(ENCODED(CharT, 'e'), 1), StringView::npos); |
| ASSERT_EQ(Tmp.find_last_of(ENCODED(CharT, 'e'), 0), StringView::npos); |
| |
| StringView Empty; |
| ASSERT_EQ(Empty.find_last_of(ENCODED(CharT, 'a')), StringView::npos); |
| ASSERT_EQ(Empty.find_last_of(ENCODED(CharT, 'a'), 0), StringView::npos); |
| ASSERT_EQ(Empty.find_last_of(ENCODED(CharT, 'a'), 123), StringView::npos); |
| |
| StringView Empty1(ENCODED(CharT, "")); |
| ASSERT_EQ(Empty1.find_last_of(ENCODED(CharT, 'a')), StringView::npos); |
| ASSERT_EQ(Empty1.find_last_of(ENCODED(CharT, 'a'), 0), StringView::npos); |
| ASSERT_EQ(Empty1.find_last_of(ENCODED(CharT, 'a'), 123), StringView::npos); |
| } |
| |
| TYPED_TEST(LlvmLibcStringViewTest, FindFirstNotOf, TestCharTypes) { |
| using CharT = ParamType; |
| using StringView = LIBC_NAMESPACE::cpp::basic_string_view<CharT>; |
| |
| StringView Tmp(ENCODED(CharT, "abada")); |
| |
| EXPECT_EQ(Tmp.find_first_not_of(ENCODED(CharT, 'a')), size_t(1)); |
| EXPECT_EQ(Tmp.find_first_not_of(ENCODED(CharT, 'a'), 123), StringView::npos); |
| EXPECT_EQ(Tmp.find_first_not_of(ENCODED(CharT, 'a'), 5), StringView::npos); |
| EXPECT_EQ(Tmp.find_first_not_of(ENCODED(CharT, 'a'), 4), StringView::npos); |
| EXPECT_EQ(Tmp.find_first_not_of(ENCODED(CharT, 'a'), 3), size_t(3)); |
| EXPECT_EQ(Tmp.find_first_not_of(ENCODED(CharT, 'a'), 2), size_t(3)); |
| EXPECT_EQ(Tmp.find_first_not_of(ENCODED(CharT, 'a'), 1), size_t(1)); |
| EXPECT_EQ(Tmp.find_first_not_of(ENCODED(CharT, 'a'), 0), size_t(1)); |
| |
| EXPECT_EQ(Tmp.find_first_not_of(ENCODED(CharT, 'b')), size_t(0)); |
| EXPECT_EQ(Tmp.find_first_not_of(ENCODED(CharT, 'b'), 123), StringView::npos); |
| EXPECT_EQ(Tmp.find_first_not_of(ENCODED(CharT, 'b'), 5), StringView::npos); |
| EXPECT_EQ(Tmp.find_first_not_of(ENCODED(CharT, 'b'), 4), size_t(4)); |
| EXPECT_EQ(Tmp.find_first_not_of(ENCODED(CharT, 'b'), 3), size_t(3)); |
| EXPECT_EQ(Tmp.find_first_not_of(ENCODED(CharT, 'b'), 2), size_t(2)); |
| EXPECT_EQ(Tmp.find_first_not_of(ENCODED(CharT, 'b'), 1), size_t(2)); |
| EXPECT_EQ(Tmp.find_first_not_of(ENCODED(CharT, 'b'), 0), size_t(0)); |
| |
| EXPECT_EQ(Tmp.find_first_not_of(ENCODED(CharT, 'd')), size_t(0)); |
| EXPECT_EQ(Tmp.find_first_not_of(ENCODED(CharT, 'd'), 123), StringView::npos); |
| EXPECT_EQ(Tmp.find_first_not_of(ENCODED(CharT, 'd'), 5), StringView::npos); |
| EXPECT_EQ(Tmp.find_first_not_of(ENCODED(CharT, 'd'), 4), size_t(4)); |
| EXPECT_EQ(Tmp.find_first_not_of(ENCODED(CharT, 'd'), 3), size_t(4)); |
| EXPECT_EQ(Tmp.find_first_not_of(ENCODED(CharT, 'd'), 2), size_t(2)); |
| EXPECT_EQ(Tmp.find_first_not_of(ENCODED(CharT, 'd'), 1), size_t(1)); |
| EXPECT_EQ(Tmp.find_first_not_of(ENCODED(CharT, 'd'), 0), size_t(0)); |
| |
| EXPECT_EQ(Tmp.find_first_not_of(ENCODED(CharT, 'e')), size_t(0)); |
| EXPECT_EQ(Tmp.find_first_not_of(ENCODED(CharT, 'e'), 123), StringView::npos); |
| EXPECT_EQ(Tmp.find_first_not_of(ENCODED(CharT, 'e'), 5), StringView::npos); |
| EXPECT_EQ(Tmp.find_first_not_of(ENCODED(CharT, 'e'), 4), size_t(4)); |
| EXPECT_EQ(Tmp.find_first_not_of(ENCODED(CharT, 'e'), 3), size_t(3)); |
| EXPECT_EQ(Tmp.find_first_not_of(ENCODED(CharT, 'e'), 2), size_t(2)); |
| EXPECT_EQ(Tmp.find_first_not_of(ENCODED(CharT, 'e'), 1), size_t(1)); |
| EXPECT_EQ(Tmp.find_first_not_of(ENCODED(CharT, 'e'), 0), size_t(0)); |
| |
| StringView Empty; |
| EXPECT_EQ(Empty.find_first_not_of(ENCODED(CharT, 'a')), StringView::npos); |
| EXPECT_EQ(Empty.find_first_not_of(ENCODED(CharT, 'a'), 0), StringView::npos); |
| EXPECT_EQ(Empty.find_first_not_of(ENCODED(CharT, 'a'), 123), |
| StringView::npos); |
| |
| StringView Empty1(ENCODED(CharT, "")); |
| EXPECT_EQ(Empty1.find_first_not_of(ENCODED(CharT, 'a')), StringView::npos); |
| EXPECT_EQ(Empty1.find_first_not_of(ENCODED(CharT, 'a'), 0), StringView::npos); |
| EXPECT_EQ(Empty1.find_first_not_of(ENCODED(CharT, 'a'), 123), |
| StringView::npos); |
| |
| StringView Full(ENCODED(CharT, "aaaaaaa")); |
| EXPECT_EQ(Full.find_first_not_of(ENCODED(CharT, 'a')), StringView::npos); |
| EXPECT_EQ(Full.find_first_not_of(ENCODED(CharT, 'a'), 0), StringView::npos); |
| EXPECT_EQ(Full.find_first_not_of(ENCODED(CharT, 'a'), 123), StringView::npos); |
| |
| EXPECT_EQ(Full.find_first_not_of(ENCODED(CharT, 'b')), size_t(0)); |
| EXPECT_EQ(Full.find_first_not_of(ENCODED(CharT, 'b'), 0), size_t(0)); |
| EXPECT_EQ(Full.find_first_not_of(ENCODED(CharT, 'b'), 123), StringView::npos); |
| } |
| |
| TYPED_TEST(LlvmLibcStringViewTest, Contains, TestCharTypes) { |
| using CharT = ParamType; |
| using StringView = LIBC_NAMESPACE::cpp::basic_string_view<CharT>; |
| |
| StringView Empty; |
| EXPECT_FALSE(Empty.contains(ENCODED(CharT, 'a'))); |
| EXPECT_FALSE(Empty.contains(ENCODED(CharT, 'g'))); |
| EXPECT_FALSE(Empty.contains(ENCODED(CharT, 'q'))); |
| |
| StringView S = ENCODED(CharT, "abada"); |
| EXPECT_TRUE(S.contains(ENCODED(CharT, 'a'))); |
| EXPECT_TRUE(S.contains(ENCODED(CharT, 'b'))); |
| EXPECT_FALSE(S.contains(ENCODED(CharT, 'c'))); |
| EXPECT_TRUE(S.contains(ENCODED(CharT, 'd'))); |
| EXPECT_FALSE(S.contains(ENCODED(CharT, 'e'))); |
| } |
| |
| TYPED_TEST(LlvmLibcStringViewTest, Substr, TestCharTypes) { |
| using CharT = ParamType; |
| using StringView = LIBC_NAMESPACE::cpp::basic_string_view<CharT>; |
| |
| StringView S = ENCODED(CharT, "abada"); |
| EXPECT_EQ(S.substr(0), StringView(ENCODED(CharT, "abada"))); |
| EXPECT_EQ(S.substr(1), StringView(ENCODED(CharT, "bada"))); |
| EXPECT_EQ(S.substr(3), StringView(ENCODED(CharT, "da"))); |
| EXPECT_EQ(S.substr(5), StringView(ENCODED(CharT, ""))); |
| EXPECT_EQ(S.substr(1, 3), StringView(ENCODED(CharT, "bad"))); |
| EXPECT_EQ(S.substr(3, 1), StringView(ENCODED(CharT, "d"))); |
| } |
| |
| TEST(LlvmLibcStringViewTest, WideCharacterComparison) { |
| // Check that wide character comparison is lexicographic by character and not |
| // equivalent to memcmp, which would be incorrect on little endian. |
| char BytesA[] = {1, 2, 3, 4}; |
| char BytesB[] = {4, 3, 2, 1}; |
| char32_t CharA; |
| char32_t CharB; |
| LIBC_NAMESPACE::inline_memcpy(&CharA, BytesA, sizeof(CharA)); |
| LIBC_NAMESPACE::inline_memcpy(&CharB, BytesB, sizeof(CharB)); |
| |
| LIBC_NAMESPACE::cpp::basic_string_view<char32_t> StringViewA(&CharA, 1); |
| LIBC_NAMESPACE::cpp::basic_string_view<char32_t> StringViewB(&CharB, 1); |
| |
| EXPECT_EQ(StringViewA < StringViewB, CharA < CharB); |
| } |