summaryrefslogtreecommitdiff
path: root/test/test_string.cpp
diff options
context:
space:
mode:
authorDominick Allen <djallen@librehumanitas.org>2024-09-23 07:36:16 -0500
committerDominick Allen <djallen@librehumanitas.org>2024-09-23 07:36:16 -0500
commit0b860bb5dd6d2007db605291d239a6a9d41f57d1 (patch)
treefab140e03a3665236503d1405de9d33ba58ccc4a /test/test_string.cpp
parent7da829d48f9059c83ab9cada2c850621e8bbd3f3 (diff)
Installable library.
Diffstat (limited to 'test/test_string.cpp')
-rw-r--r--test/test_string.cpp296
1 files changed, 296 insertions, 0 deletions
diff --git a/test/test_string.cpp b/test/test_string.cpp
new file mode 100644
index 0000000..3b8c3aa
--- /dev/null
+++ b/test/test_string.cpp
@@ -0,0 +1,296 @@
+/*
+ * libfud
+ * Copyright 2024 Dominick Allen
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "fud_array.hpp"
+#include "fud_string.hpp"
+#include "test_common.hpp"
+
+#include "gtest/gtest.h"
+
+namespace fud {
+
+TEST(FudString, CStringLength)
+{
+ ASSERT_EQ(cStringLength(nullptr), -1);
+ ASSERT_EQ(cStringLength(""), 0);
+ ASSERT_EQ(cStringLength("a"), 1);
+ ASSERT_EQ(cStringLength(MULTI_BYTE_LITERAL), sizeof(MULTI_BYTE_LITERAL) - 1);
+ ASSERT_EQ(cStringLength(MULTI_BYTE_LITERAL), sizeof(MULTI_BYTE_LITERAL) - 1);
+}
+
+TEST(FudString, BasicStringOps)
+{
+ const Array<utf8, 2> invalid{0xFF, 0x00};
+ ASSERT_FALSE(Ascii::valid(invalid[0]));
+ const Array<utf8, 2> invalid2{0xFF, 0x00};
+ String fudString{invalid2.data()};
+ ASSERT_EQ(fudString.length(), 1);
+ ASSERT_EQ(fudString.data()[0], invalid[0]);
+ ASSERT_FALSE(Ascii::valid(fudString.data()[0]));
+ ASSERT_FALSE(fudString.utf8Valid());
+
+ fudString = String{"TEST"};
+ ASSERT_TRUE(fudString.utf8Valid());
+
+ StringView view1{};
+ ASSERT_FALSE(view1.utf8Valid());
+ StringView view2{fudString};
+ ASSERT_TRUE(view2.utf8Valid());
+ ASSERT_TRUE(view2.nullTerminated());
+}
+
+#if 0
+TEST(FudString, FindSubstringCxx)
+{
+ Array<uint8_t, sizeof(CHQUOTE)> basis{};
+ ASSERT_EQ(ExtCopyMem(basis.data(), basis.size(), CHQUOTE, sizeof(CHQUOTE)), ExtSuccess);
+ String fudString{basis.size() - 1, basis.size(), basis.data()};
+
+ StringView haystack{extString};
+ ASSERT_NE(haystack.length, 0);
+ ASSERT_NE(haystack.data, nullptr);
+
+ Array<uint8_t, sizeof("learning")> subBasis{};
+ ASSERT_EQ(ExtCopyMem(subBasis.data(), subBasis.size(), "learning", sizeof("learning")), ExtSuccess);
+ FudStringView needle{subBasis.size() - 1, subBasis.data()};
+
+ FudStringView stringView{};
+ auto findStatus = ext_string_find_substring(haystack, needle, &stringView);
+ ASSERT_EQ(findStatus, ExtSuccess);
+ // NOLINTBEGIN(cppcoreguidelines-pro-type-reinterpret-cast)
+ ASSERT_EQ(
+ ext_string_get_c_string(&extString) + sizeof("why waste time"),
+ reinterpret_cast<const char*>(stringView.data));
+ // NOLINTEND(cppcoreguidelines-pro-type-reinterpret-cast)
+}
+
+TEST(TestFudString, StringBuffer)
+{
+ Result<FixedStringBuffer<1>, ExtStatus> bufferResult{FixedStringBuffer<1>::fromLiteral(nullptr)};
+ ASSERT_TRUE(bufferResult.isError());
+ ASSERT_EQ(bufferResult.getError(), ExtNullPointer);
+
+ Array<uint8_t, 1> data1{};
+ bufferResult = FixedStringBuffer<1>::fromArray(data1);
+ ASSERT_TRUE(bufferResult.isOkay());
+ FixedStringBuffer<1> buffer1{std::move(bufferResult.getOkay())};
+ ASSERT_EQ(buffer1.m_string.m_data[0], '\0');
+ ASSERT_EQ(buffer1.m_string.m_length, 0);
+ ASSERT_EQ(buffer1.m_string.m_size, 1);
+
+ bufferResult = FixedStringBuffer<1>::fromLiteral("a");
+ ASSERT_TRUE(bufferResult.isError());
+ ASSERT_EQ(bufferResult.getError(), ExtInvalidInput);
+
+ data1[0] = 'a';
+ bufferResult = FixedStringBuffer<1>::fromArray(data1);
+ ASSERT_TRUE(bufferResult.isError());
+ ASSERT_EQ(bufferResult.getError(), ExtInvalidInput);
+
+ bufferResult = FixedStringBuffer<1>::fromLiteral("");
+ ASSERT_TRUE(bufferResult.isOkay());
+ buffer1 = {bufferResult.getOkay()};
+ ASSERT_EQ(buffer1.m_string.m_data[0], '\0');
+ ASSERT_EQ(buffer1.m_string.m_length, 0);
+ ASSERT_EQ(buffer1.m_string.m_size, 1);
+
+ StringView view1{buffer1};
+ ASSERT_EQ(buffer1.append(view1), ExtInvalidInput);
+
+ ASSERT_EQ(buffer1, buffer1);
+ const auto buffer2{buffer1};
+ ASSERT_EQ(buffer1, buffer2);
+ const auto buffer3{buffer2}; // NOLINT(performance-unnecessary-copy-initialization)
+ ASSERT_EQ(buffer1, buffer3);
+ auto buffer4 = buffer3; // NOLINT(performance-unnecessary-copy-initialization)
+ ASSERT_EQ(buffer1, buffer4);
+
+ Array<uint8_t, sizeof("test")> data2{"test"};
+ auto bufferResult2{FixedStringBuffer<data2.size()>::fromArray(data2)};
+ ASSERT_TRUE(bufferResult2.isOkay());
+ FixedStringBuffer<data2.size()> bufferTest{std::move(bufferResult2.getOkay())};
+ ASSERT_EQ(bufferTest.m_string.m_data[0], 't');
+ ASSERT_EQ(bufferTest.m_string.m_data[4], '\0');
+ ASSERT_EQ(bufferTest.m_string.m_length, data2.size() - 1);
+ ASSERT_EQ(bufferTest.m_string.m_size, data2.size());
+
+ const StringView view2{bufferTest};
+ FixedStringBuffer<data2.size()> bufferTest2{};
+ ASSERT_EQ(bufferTest2.append(view2), ExtSuccess);
+ ASSERT_EQ(bufferTest2.append(view2), ExtFull);
+ ASSERT_EQ(bufferTest2.remainingLength(), 0);
+ bufferTest2.m_string.m_length++;
+ ASSERT_EQ(bufferTest2.remainingLength(), 0);
+ bufferTest2.clear();
+ ASSERT_EQ(bufferTest2.remainingLength(), data2.size() - 1);
+
+ bufferTest2.m_string.m_length = 0;
+ bufferTest2.m_memory.clear();
+ buffer1.m_string.m_data[0] = 'a';
+ view1.length = 1;
+ ASSERT_EQ(bufferTest2.append(view1), FudStringInvalid);
+ ASSERT_TRUE(bufferTest2.m_memory.pushBack('\0'));
+ ASSERT_EQ(bufferTest2.append(view1), ExtSuccess);
+
+ ASSERT_NE(bufferTest2, bufferTest);
+ bufferTest2.clear();
+ ASSERT_EQ(bufferTest2.append(view2), ExtSuccess);
+ ASSERT_EQ(bufferTest, bufferTest2);
+ bufferTest.data()[3] = 'a';
+ ASSERT_NE(bufferTest, bufferTest2);
+}
+
+TEST(FudString, SpanCxx)
+{
+ Array<uint8_t, sizeof(CHQUOTE)> basis{};
+ ASSERT_EQ(ExtCopyMem(basis.data(), basis.size(), CHQUOTE, sizeof(CHQUOTE)), ExtSuccess);
+ String fudString{basis.size(), basis.size() - 1, basis.data()};
+
+ StringView inputView{extString};
+ ASSERT_NE(inputView.length, 0);
+ ASSERT_EQ(inputView.length, sizeof(CHQUOTE) - 1);
+ ASSERT_NE(inputView.data, nullptr);
+
+ constexpr Array<uint8_t, charSetSize + 1> charArray{CHARACTER_SET};
+ Array<Utf8, charSetSize> utf8Array{};
+ for (auto idx = 0; idx < utf8Array.size(); ++idx) {
+ utf8Array[idx] = Utf8{Ascii{charArray[idx]}};
+ }
+
+ static_assert(!ext_lib::hasDuplicates(charArray));
+ auto temp = utf8Array[0];
+ utf8Array[0] = utf8Array[1];
+ auto characterSetResult{Utf8Set<charSetSize>::make(utf8Array)};
+ ASSERT_TRUE(characterSetResult.isError());
+ utf8Array[0] = temp;
+ characterSetResult = Utf8Set<charSetSize>::make(utf8Array);
+ ASSERT_TRUE(characterSetResult.isOkay());
+ auto characterSet = characterSetResult.getOkay();
+
+ FudStringView result{};
+ EXPECT_EQ(ext_string_span_set(inputView, nullptr, nullptr), ExtNullPointer);
+ ASSERT_EQ(ext_string_span_set(inputView, &characterSet, &result), ExtSuccess);
+
+ ASSERT_EQ(result.length, sizeof(", when ignorance is instantaneous?") - 1);
+ std::vector<char> resString(result.length + 1);
+ ASSERT_EQ(ExtCopyMem(resString.data(), resString.size(), result.data, result.length), ExtSuccess);
+ ASSERT_EQ(std::string(resString.data()), std::string(", when ignorance is instantaneous?"));
+
+ Array<uint8_t, 2> ex2{'l'};
+ StringView setView2{};
+ setView2.length = sizeof(ex2) - 1;
+ setView2.data = ex2.data();
+ StringView setView3{setView2};
+ int difference = -1;
+ ASSERT_EQ(ExtCompareMem(&setView2, sizeof(setView2), &setView3, sizeof(setView3), &difference), ExtSuccess);
+ ASSERT_EQ(difference, 0);
+
+ Array<ExtUtf8Impl, 1> setArray{{Utf8{Ascii{'l'}}}};
+ Utf8Set<1> charSet{setArray};
+ ASSERT_FALSE(charSet.isEmptySet());
+ ASSERT_TRUE(static_cast<ExtUtf8Set*>(&charSet)->contains(Utf8{Ascii{'l'}}));
+ ASSERT_TRUE(static_cast<ExtUtf8Set*>(&charSet)->contains(setArray[0]));
+
+ EXPECT_EQ(ext_string_c_span_set(inputView, nullptr, nullptr), ExtNullPointer);
+ ASSERT_EQ(ext_string_c_span_set(inputView, &charSet, &result), ExtSuccess);
+
+ ASSERT_EQ(result.length, sizeof("learning, when ignorance is instantaneous?") - 1);
+ StringView resultView{result};
+ ASSERT_TRUE(resultView.nullTerminated());
+ resString.resize(result.length + 1);
+ ASSERT_EQ(ExtCopyMem(resString.data(), resString.size(), result.data, result.length), ExtSuccess);
+ ASSERT_EQ(std::string(resString.data()), std::string("learning, when ignorance is instantaneous?"));
+}
+
+TEST(FudString, SpanSetInvalid)
+{
+ constexpr Array<uint8_t, charSetSize + 1> charArray{CHARACTER_SET};
+ Array<Utf8, charSetSize> utf8Array{};
+ for (auto idx = 0; idx < utf8Array.size(); ++idx) {
+ utf8Array[idx] = Utf8{Ascii{charArray[idx]}};
+ }
+ utf8Array[0] = Utf8{Ascii{0xFF}}; // NOLINT(readability-magic-numbers)
+
+ static_assert(!ext_lib::hasDuplicates(charArray));
+ auto characterSetResult{Utf8Set<charSetSize>::make(utf8Array)};
+ ASSERT_TRUE(characterSetResult.isOkay());
+ auto characterSet{characterSetResult.getOkay()};
+
+ Array<uint8_t, sizeof(CHQUOTE)> backing{CHQUOTE};
+ auto fudString{FudString::withBacking(backing)};
+
+ StringView inputView{extString};
+
+ Array<uint8_t, sizeof(CHARACTER_SET)> setBacking{CHARACTER_SET};
+ setBacking[0] = ExtUtf8::invalidAsciiCode.character();
+
+ FudStringView result{};
+ ASSERT_EQ(ext_string_span_set(inputView, &characterSet, &result), ExtUtf8Invalid);
+ ASSERT_EQ(ext_string_c_span_set(inputView, &characterSet, &result), ExtUtf8Invalid);
+}
+
+TEST(FudString, SpanSetInputInvalid)
+{
+ constexpr Array<uint8_t, charSetSize + 1> charArray{CHARACTER_SET};
+ Array<Utf8, charSetSize> utf8Array{};
+ for (auto idx = 0; idx < utf8Array.size(); ++idx) {
+ utf8Array[idx] = Utf8{Ascii{charArray[idx]}};
+ }
+
+ static_assert(!ext_lib::hasDuplicates(charArray));
+ auto characterSetResult{Utf8Set<charSetSize>::make(utf8Array)};
+ ASSERT_TRUE(characterSetResult.isOkay());
+ auto characterSet{characterSetResult.getOkay()};
+
+ Array<uint8_t, sizeof(CHQUOTE)> backing{CHQUOTE};
+ backing[0] = ExtUtf8::invalidAsciiCode.character();
+ auto fudString{FudString::withBacking(backing)};
+
+ StringView inputView{extString};
+
+ Array<uint8_t, sizeof(CHARACTER_SET)> setBacking{CHARACTER_SET};
+
+ FudStringView result{};
+ ASSERT_EQ(ext_string_span_set(inputView, &characterSet, &result), ExtUtf8Invalid);
+ ASSERT_EQ(ext_string_c_span_set(inputView, &characterSet, &result), ExtUtf8Invalid);
+}
+
+TEST(FudString, SpanSetNotFound)
+{
+ constexpr Array<uint8_t, sizeof("QZ")> setBacking{"QZ"};
+ Array<Utf8, sizeof(setBacking) - 1> utf8Array{};
+ for (auto idx = 0; idx < utf8Array.size(); ++idx) {
+ utf8Array[idx] = Utf8{Ascii{setBacking[idx]}};
+ }
+
+ static_assert(!ext_lib::hasDuplicates(setBacking));
+ auto characterSetResult{Utf8Set<utf8Array.size()>::make(utf8Array)};
+ ASSERT_TRUE(characterSetResult.isOkay());
+ auto characterSet{characterSetResult.getOkay()};
+
+ Array<uint8_t, sizeof(CHQUOTE)> backing{CHQUOTE};
+ auto fudString{FudString::withBacking(backing)};
+
+ StringView inputView{extString};
+
+ FudStringView result{};
+ ASSERT_EQ(ext_string_span_set(inputView, &characterSet, &result), ExtNotFound);
+ ASSERT_EQ(ext_string_c_span_set(inputView, &characterSet, &result), ExtNotFound);
+}
+
+#endif
+} // namespace fud