From 4e37a51c2c839ecae652049ec8cda1ef57d07db8 Mon Sep 17 00:00:00 2001 From: Krzysztof Kowalczyk Date: Wed, 29 May 2024 13:04:00 +0200 Subject: [PATCH] move StrVec tests to StrVec_ut.cpp --- src/tools/test_util.cpp | 1 + src/utils/tests/StrUtil_ut.cpp | 314 ------------------------- src/utils/tests/StrVec_ut.cpp | 323 ++++++++++++++++++++++++++ vs2022/SumatraPDF-dll.vcxproj | 10 + vs2022/SumatraPDF-dll.vcxproj.filters | 3 + vs2022/SumatraPDF.vcxproj | 10 + vs2022/SumatraPDF.vcxproj.filters | 3 + vs2022/test_util.vcxproj | 1 + vs2022/test_util.vcxproj.filters | 3 + 9 files changed, 354 insertions(+), 314 deletions(-) create mode 100644 src/utils/tests/StrVec_ut.cpp diff --git a/src/tools/test_util.cpp b/src/tools/test_util.cpp index e50d65c9d32..2a2c530adc8 100644 --- a/src/tools/test_util.cpp +++ b/src/tools/test_util.cpp @@ -28,6 +28,7 @@ extern void TrivialHtmlParser_UnitTests(); extern void VecTest(); extern void WinUtilTest(); extern void StrFormatTest(); +extern void StrVecTest(); int main(int, char**) { printf("Running unit tests\n"); diff --git a/src/utils/tests/StrUtil_ut.cpp b/src/utils/tests/StrUtil_ut.cpp index 5b6e11a33f1..95aa9b8309d 100644 --- a/src/utils/tests/StrUtil_ut.cpp +++ b/src/utils/tests/StrUtil_ut.cpp @@ -225,314 +225,6 @@ void strWStrTest() { } } -static void assertStrEq(const char* s1, const char* s2) { - bool ok = str::Eq(s1, s2); - utassert(ok); -} - -static void CheckRemoveAt(StrVec& v) { - while (v.Size() > 0) { - int n = v.Size(); - int idx = v.Size() / 2; - auto exp = v[idx]; - char* got; - if (n % 2 == 0) { - got = v.RemoveAt(idx); - } else { - got = v.RemoveAtFast(idx); - } - utassert(exp == got); // should be exact same pointer value - utassert(v.Size() == n - 1); - } -} - -static void StrVecCheckIter(StrVec& v, const char** strings, int start = 0) { - int i = 0; - for (char* s : v) { - if (i < start) { - i++; - continue; - } - char* s2 = v[i]; - utassert(str::Eq(s, s2)); - if (strings) { - const char* s3 = strings[i - start]; - utassert(str::Eq(s, s3)); - } - i++; - } - if (!strings) { - return; - } - - // test iterator + operator - auto it = v.begin() + start; - auto end = v.end(); - i = 0; - for (; it != end; it++, i++) { - char* s = *it; - const char* s2 = strings[i]; - utassert(str::Eq(s, s2)); - } -} - -static void AppendStrings(StrVec& v, const char** strings, int nStrings) { - int initialSize = v.Size(); - for (int i = 0; i < nStrings; i++) { - v.Append(strings[i]); - utassert(v.Size() == initialSize + i + 1); - } - StrVecCheckIter(v, strings, initialSize); -} - -const char* strs[] = {"foo", "bar", "Blast", nullptr, "this is a large string, my friend"}; - -static void StrVecTest() { - { - StrVec v; - const char* s = "lolda"; - v.InsertAt(0, s); - utassert(v.Size() == 1); - utassert(str::Eq(v.At(0), s)); - } - // order in strs - int unsortedOrder[] = {0, 1, 2, 3, 4}; - int sortedOrder[]{3, 2, 1, 0, 4}; - int sortedNoCaseOrder[]{3, 1, 2, 0, 4}; - - int n = dimofi(strs); - StrVec v; - utassert(v.Size() == 0); - AppendStrings(v, strs, n); - StrVecCheckIter(v, strs, 0); - - StrVec sortedView = v; - Sort(sortedView); - - for (int i = 0; i < n; i++) { - char* got = sortedView.At(i); - auto exp = strs[sortedOrder[i]]; - assertStrEq(got, exp); - } - - // allocate a bunch to test allocating - for (int i = 0; i < 1024; i++) { - v.Append(strs[4]); - } - utassert(v.Size() == 1024 + n); - - for (int i = 0; i < n; i++) { - auto got = v.At(i); - auto exp = strs[unsortedOrder[i]]; - assertStrEq(got, exp); - } - - for (int i = 0; i < 1024; i++) { - auto got = v.At(i + n); - auto exp = strs[4]; - assertStrEq(got, exp); - } - SortNoCase(sortedView); - - for (int i = 0; i < n; i++) { - auto got = sortedView.At(i); - auto exp = strs[sortedNoCaseOrder[i]]; - assertStrEq(got, exp); - } - - Sort(v); - for (int i = 0; i < n; i++) { - char* got = v.At(i); - auto exp = strs[sortedOrder[i]]; - assertStrEq(got, exp); - } - StrVecCheckIter(v, nullptr); - SortNoCase(v); - for (int i = 0; i < n; i++) { - char* got = v.At(i); - auto exp = strs[sortedNoCaseOrder[i]]; - assertStrEq(got, exp); - } - v.SetAt(3, nullptr); - utassert(nullptr == v[3]); - CheckRemoveAt(v); -} - -static void StrVecTest2() { - StrVec v; - v.Append("foo"); - v.Append("bar"); - char* s = Join(v); - utassert(v.Size() == 2); - utassert(str::Eq("foobar", s)); - str::Free(s); - - s = Join(v, ";"); - utassert(v.Size() == 2); - utassert(str::Eq("foo;bar", s)); - str::Free(s); - - v.Append(nullptr); - utassert(v.Size() == 3); - - v.Append("glee"); - s = JoinTemp(v, "_ _"); - utassert(v.Size() == 4); - utassert(str::Eq("foo_ _bar_ _glee", s)); - - StrVecCheckIter(v, nullptr); - Sort(v); - const char* strsSorted[] = {nullptr, "bar", "foo", "glee"}; - StrVecCheckIter(v, strsSorted); - - s = Join(v, "++"); - utassert(v.Size() == 4); - utassert(str::Eq("bar++foo++glee", s)); - str::Free(s); - - s = Join(v); - utassert(str::Eq("barfooglee", s)); - str::Free(s); - - { - StrVec v2(v); - utassert(str::Eq(v2.At(2), "foo")); - v2.Append("nobar"); - utassert(str::Eq(v2.At(4), "nobar")); - v2 = v; - utassert(v2.Size() == 4); - // copies should be same values but at different addresses - utassert(v2.At(1) != v.At(1)); - utassert(str::Eq(v2.At(1), v.At(1))); - s = v2.At(2); - utassert(str::Eq(s, "foo")); - CheckRemoveAt(v2); - } - - { - StrVec v2; - size_t count = Split(v2, "a,b,,c,", ","); - utassert(count == 5 && v2.Find("c") == 3); - utassert(v2.Find("") == 2); - utassert(v2.Find("", 3) == 4); - utassert(v2.Find("", 5) == -1); - utassert(v2.Find("B") == -1 && v2.FindI("B") == 1); - TempStr joined = JoinTemp(v2, ";"); - utassert(str::Eq(joined, "a;b;;c;")); - CheckRemoveAt(v2); - } - - { - StrVec v2; - size_t count = Split(v2, "a,b,,c,", ",", true); - utassert(count == 3 && v2.Find("c") == 2); - TempStr joined = JoinTemp(v2, ";"); - utassert(str::Eq(joined, "a;b;c")); - StrVecCheckIter(v2, nullptr); - -#if 0 - AutoFreeWStr last(v2.Pop()); - utassert(v2.size() == 2 && str::Eq(last, L"c")); -#endif - CheckRemoveAt(v2); - } - CheckRemoveAt(v); -} - -static void StrVecTest3() { - StrVec v; - utassert(v.Size() == 0); - v.Append("one"); - v.Append("two"); - v.Append("One"); - utassert(v.Size() == 3); - utassert(str::Eq(v.At(0), "one")); - utassert(str::EqI(v.At(2), "one")); - utassert(v.Find("One") == 2); - utassert(v.FindI("One") == 0); - utassert(v.Find("Two") == -1); - StrVecCheckIter(v, nullptr); - CheckRemoveAt(v); -} - -static void StrVecTest4() { - StrVec v; - AppendStrings(v, strs, dimofi(strs)); - - int idx = 2; - - utassert(str::Eq(strs[idx], v[idx])); - auto s = "new value of string, should be large to get results faster"; - // StrVec: tests adding where can allocate new value inside a page - v.SetAt(idx, s); - utassert(str::Eq(s, v[idx])); - v.SetAt(idx, nullptr); - utassert(str::Eq(nullptr, v[idx])); - v.SetAt(idx, ""); - utassert(str::Eq("", v[idx])); - // StrVec: force allocating in side strings - // first page is 256 bytes so this should force allocation in sideStrings - int n = 256 / str::Leni(s); - for (int i = 0; i < n; i++) { - v.SetAt(idx, s); - } - utassert(str::Eq(s, v[idx])); - - auto prevAtIdx = strs[idx]; - defer { - strs[idx] = prevAtIdx; - }; - strs[idx] = s; - StrVecCheckIter(v, strs); - - auto s2 = v.RemoveAt(idx); - utassert(str::Eq(s, s2)); - - // should be replaced by next value - s2 = v.At(idx); - utassert(str::Eq(s2, strs[idx + 1])); - - // StrVec: test multiple side strings - n = v.Size(); - for (int i = 0; i < n; i++) { - v.SetAt(i, s); - } - for (auto it = v.begin(); it != v.end(); it++) { - s2 = *it; - utassert(str::Eq(s, s2)); - } - auto s3 = "hello"; - v.SetAt(n / 2, s3); - s2 = v[n / 2]; - utassert(str::Eq(s3, s2)); - while (v.Size() > 0) { - n = v.Size(); - s2 = v[0]; - if (n % 2 == 0) { - s3 = v.RemoveAtFast(0); - } else { - s3 = v.RemoveAt(0); - } - utassert(str::Eq(s2, s3)); - } -} - -static void StrVecTest5() { - StrVec v; - AppendStrings(v, strs, dimofi(strs)); - const char* s = "first"; - v.InsertAt(0, s); - auto s2 = v.At(0); - utassert(str::Eq(s, s2)); - s = strs[0]; - s2 = v.At(1); - utassert(str::Eq(s2, s)); - s = "middle"; - v.InsertAt(3, s); - s2 = v.At(3); - utassert(str::Eq(s2, s)); -} - void StrTest() { WCHAR buf[32]; const WCHAR* str = L"a string"; @@ -959,10 +651,4 @@ void StrTest() { StrConvTest(); StrUrlExtractTest(); // ParseUntilTest(); - - StrVecTest(); - StrVecTest2(); - StrVecTest3(); - StrVecTest4(); - StrVecTest5(); } diff --git a/src/utils/tests/StrVec_ut.cpp b/src/utils/tests/StrVec_ut.cpp new file mode 100644 index 00000000000..30137f9ad66 --- /dev/null +++ b/src/utils/tests/StrVec_ut.cpp @@ -0,0 +1,323 @@ +/* Copyright 2022 the SumatraPDF project authors (see AUTHORS file). +License: Simplified BSD (see COPYING.BSD) */ + +#include "utils/BaseUtil.h" + +// must be last due to assert() over-write +#include "utils/UtAssert.h" + +static void strEq(const char* s1, const char* s2) { + bool ok = str::Eq(s1, s2); + utassert(ok); +} + +static void CheckRemoveAt(StrVec& v) { + while (v.Size() > 0) { + int n = v.Size(); + int idx = v.Size() / 2; + auto exp = v[idx]; + char* got; + if (n % 2 == 0) { + got = v.RemoveAt(idx); + } else { + got = v.RemoveAtFast(idx); + } + utassert(exp == got); // should be exact same pointer value + utassert(v.Size() == n - 1); + } +} + +static void StrVecCheckIter(StrVec& v, const char** strings, int start = 0) { + int i = 0; + for (char* s : v) { + if (i < start) { + i++; + continue; + } + char* s2 = v[i]; + utassert(str::Eq(s, s2)); + if (strings) { + const char* s3 = strings[i - start]; + utassert(str::Eq(s, s3)); + } + i++; + } + if (!strings) { + return; + } + + // test iterator + operator + auto it = v.begin() + start; + auto end = v.end(); + i = 0; + for (; it != end; it++, i++) { + char* s = *it; + const char* s2 = strings[i]; + utassert(str::Eq(s, s2)); + } +} + +static void AppendStrings(StrVec& v, const char** strings, int nStrings) { + int initialSize = v.Size(); + for (int i = 0; i < nStrings; i++) { + v.Append(strings[i]); + utassert(v.Size() == initialSize + i + 1); + } + StrVecCheckIter(v, strings, initialSize); +} + +const char* strs[] = {"foo", "bar", "Blast", nullptr, "this is a large string, my friend"}; + +static void StrVecTest1() { + { + StrVec v; + const char* s = "lolda"; + v.InsertAt(0, s); + utassert(v.Size() == 1); + utassert(str::Eq(v.At(0), s)); + } + // order in strs + int unsortedOrder[] = {0, 1, 2, 3, 4}; + int sortedOrder[]{3, 2, 1, 0, 4}; + int sortedNoCaseOrder[]{3, 1, 2, 0, 4}; + + int n = dimofi(strs); + StrVec v; + utassert(v.Size() == 0); + AppendStrings(v, strs, n); + StrVecCheckIter(v, strs, 0); + + StrVec sortedView = v; + Sort(sortedView); + + for (int i = 0; i < n; i++) { + char* got = sortedView.At(i); + auto exp = strs[sortedOrder[i]]; + strEq(got, exp); + } + + // allocate a bunch to test allocating + for (int i = 0; i < 1024; i++) { + v.Append(strs[4]); + } + utassert(v.Size() == 1024 + n); + + for (int i = 0; i < n; i++) { + auto got = v.At(i); + auto exp = strs[unsortedOrder[i]]; + strEq(got, exp); + } + + for (int i = 0; i < 1024; i++) { + auto got = v.At(i + n); + auto exp = strs[4]; + strEq(got, exp); + } + SortNoCase(sortedView); + + for (int i = 0; i < n; i++) { + auto got = sortedView.At(i); + auto exp = strs[sortedNoCaseOrder[i]]; + strEq(got, exp); + } + + Sort(v); + for (int i = 0; i < n; i++) { + char* got = v.At(i); + auto exp = strs[sortedOrder[i]]; + strEq(got, exp); + } + StrVecCheckIter(v, nullptr); + SortNoCase(v); + for (int i = 0; i < n; i++) { + char* got = v.At(i); + auto exp = strs[sortedNoCaseOrder[i]]; + strEq(got, exp); + } + v.SetAt(3, nullptr); + utassert(nullptr == v[3]); + CheckRemoveAt(v); +} + +static void StrVecTest2() { + StrVec v; + v.Append("foo"); + v.Append("bar"); + char* s = Join(v); + utassert(v.Size() == 2); + utassert(str::Eq("foobar", s)); + str::Free(s); + + s = Join(v, ";"); + utassert(v.Size() == 2); + utassert(str::Eq("foo;bar", s)); + str::Free(s); + + v.Append(nullptr); + utassert(v.Size() == 3); + + v.Append("glee"); + s = JoinTemp(v, "_ _"); + utassert(v.Size() == 4); + utassert(str::Eq("foo_ _bar_ _glee", s)); + + StrVecCheckIter(v, nullptr); + Sort(v); + const char* strsSorted[] = {nullptr, "bar", "foo", "glee"}; + StrVecCheckIter(v, strsSorted); + + s = Join(v, "++"); + utassert(v.Size() == 4); + utassert(str::Eq("bar++foo++glee", s)); + str::Free(s); + + s = Join(v); + utassert(str::Eq("barfooglee", s)); + str::Free(s); + + { + StrVec v2(v); + utassert(str::Eq(v2.At(2), "foo")); + v2.Append("nobar"); + utassert(str::Eq(v2.At(4), "nobar")); + v2 = v; + utassert(v2.Size() == 4); + // copies should be same values but at different addresses + utassert(v2.At(1) != v.At(1)); + utassert(str::Eq(v2.At(1), v.At(1))); + s = v2.At(2); + utassert(str::Eq(s, "foo")); + CheckRemoveAt(v2); + } + + { + StrVec v2; + size_t count = Split(v2, "a,b,,c,", ","); + utassert(count == 5 && v2.Find("c") == 3); + utassert(v2.Find("") == 2); + utassert(v2.Find("", 3) == 4); + utassert(v2.Find("", 5) == -1); + utassert(v2.Find("B") == -1 && v2.FindI("B") == 1); + TempStr joined = JoinTemp(v2, ";"); + utassert(str::Eq(joined, "a;b;;c;")); + CheckRemoveAt(v2); + } + + { + StrVec v2; + size_t count = Split(v2, "a,b,,c,", ",", true); + utassert(count == 3 && v2.Find("c") == 2); + TempStr joined = JoinTemp(v2, ";"); + utassert(str::Eq(joined, "a;b;c")); + StrVecCheckIter(v2, nullptr); + + #if 0 + AutoFreeWStr last(v2.Pop()); + utassert(v2.size() == 2 && str::Eq(last, L"c")); + #endif + CheckRemoveAt(v2); + } + CheckRemoveAt(v); +} + +static void StrVecTest3() { + StrVec v; + utassert(v.Size() == 0); + v.Append("one"); + v.Append("two"); + v.Append("One"); + utassert(v.Size() == 3); + utassert(str::Eq(v.At(0), "one")); + utassert(str::EqI(v.At(2), "one")); + utassert(v.Find("One") == 2); + utassert(v.FindI("One") == 0); + utassert(v.Find("Two") == -1); + StrVecCheckIter(v, nullptr); + CheckRemoveAt(v); +} + +static void StrVecTest4() { + StrVec v; + AppendStrings(v, strs, dimofi(strs)); + + int idx = 2; + + utassert(str::Eq(strs[idx], v[idx])); + auto s = "new value of string, should be large to get results faster"; + // StrVec: tests adding where can allocate new value inside a page + v.SetAt(idx, s); + utassert(str::Eq(s, v[idx])); + v.SetAt(idx, nullptr); + utassert(str::Eq(nullptr, v[idx])); + v.SetAt(idx, ""); + utassert(str::Eq("", v[idx])); + // StrVec: force allocating in side strings + // first page is 256 bytes so this should force allocation in sideStrings + int n = 256 / str::Leni(s); + for (int i = 0; i < n; i++) { + v.SetAt(idx, s); + } + utassert(str::Eq(s, v[idx])); + + auto prevAtIdx = strs[idx]; + defer { + strs[idx] = prevAtIdx; + }; + strs[idx] = s; + StrVecCheckIter(v, strs); + + auto s2 = v.RemoveAt(idx); + utassert(str::Eq(s, s2)); + + // should be replaced by next value + s2 = v.At(idx); + utassert(str::Eq(s2, strs[idx + 1])); + + // StrVec: test multiple side strings + n = v.Size(); + for (int i = 0; i < n; i++) { + v.SetAt(i, s); + } + for (auto it = v.begin(); it != v.end(); it++) { + s2 = *it; + utassert(str::Eq(s, s2)); + } + auto s3 = "hello"; + v.SetAt(n / 2, s3); + s2 = v[n / 2]; + utassert(str::Eq(s3, s2)); + while (v.Size() > 0) { + n = v.Size(); + s2 = v[0]; + if (n % 2 == 0) { + s3 = v.RemoveAtFast(0); + } else { + s3 = v.RemoveAt(0); + } + utassert(str::Eq(s2, s3)); + } +} + +static void StrVecTest5() { + StrVec v; + AppendStrings(v, strs, dimofi(strs)); + const char* s = "first"; + v.InsertAt(0, s); + auto s2 = v.At(0); + utassert(str::Eq(s, s2)); + s = strs[0]; + s2 = v.At(1); + utassert(str::Eq(s2, s)); + s = "middle"; + v.InsertAt(3, s); + s2 = v.At(3); + utassert(str::Eq(s2, s)); +} + +void StrVecTest() { + StrVecTest1(); + StrVecTest2(); + StrVecTest3(); + StrVecTest4(); + StrVecTest5(); +} diff --git a/vs2022/SumatraPDF-dll.vcxproj b/vs2022/SumatraPDF-dll.vcxproj index 9f33701d570..bb7a761f35f 100644 --- a/vs2022/SumatraPDF-dll.vcxproj +++ b/vs2022/SumatraPDF-dll.vcxproj @@ -1339,6 +1339,16 @@ true true + + true + true + true + true + true + true + true + true + true true diff --git a/vs2022/SumatraPDF-dll.vcxproj.filters b/vs2022/SumatraPDF-dll.vcxproj.filters index 5a70a0e29a4..b59096ddcbe 100644 --- a/vs2022/SumatraPDF-dll.vcxproj.filters +++ b/vs2022/SumatraPDF-dll.vcxproj.filters @@ -524,6 +524,9 @@ src\utils\tests + + src\utils\tests + src\utils\tests diff --git a/vs2022/SumatraPDF.vcxproj b/vs2022/SumatraPDF.vcxproj index bd56c1e6c7f..3f57ad58ea8 100644 --- a/vs2022/SumatraPDF.vcxproj +++ b/vs2022/SumatraPDF.vcxproj @@ -1290,6 +1290,16 @@ true true + + true + true + true + true + true + true + true + true + true true diff --git a/vs2022/SumatraPDF.vcxproj.filters b/vs2022/SumatraPDF.vcxproj.filters index 85392340d17..cb9327e89d6 100644 --- a/vs2022/SumatraPDF.vcxproj.filters +++ b/vs2022/SumatraPDF.vcxproj.filters @@ -521,6 +521,9 @@ src\utils\tests + + src\utils\tests + src\utils\tests diff --git a/vs2022/test_util.vcxproj b/vs2022/test_util.vcxproj index 5c3a5b79a2c..a95efecb7f3 100644 --- a/vs2022/test_util.vcxproj +++ b/vs2022/test_util.vcxproj @@ -891,6 +891,7 @@ + diff --git a/vs2022/test_util.vcxproj.filters b/vs2022/test_util.vcxproj.filters index 48e20beedf3..2cdd2af2977 100644 --- a/vs2022/test_util.vcxproj.filters +++ b/vs2022/test_util.vcxproj.filters @@ -237,6 +237,9 @@ utils\tests + + utils\tests + utils\tests