blob: d8c2e03a4e9b2847214af367566f38ced2478f29 [file]
//===-- 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);
}