From 9acd185d4432995ce60e67ecaf43d83e1fb8a9a9 Mon Sep 17 00:00:00 2001 From: Simon Rozman Date: Thu, 8 Feb 2024 15:18:42 +0100 Subject: [PATCH] UnitTest: redesing to avoid #include ".cpp" in Xcode Each unit test .cpp file is not a separate compilation unit in Xcode project like it is in Visual Studio. Hopefully, Visual Studio test tool still likes this arrangement. Signed-off-by: Simon Rozman --- UnitTests/UnitTests.xcodeproj/project.pbxproj | 22 + UnitTests/hash.cpp | 52 +- UnitTests/main.cpp | 11 - UnitTests/math.cpp | 52 +- UnitTests/parser.cpp | 926 +++++++++--------- UnitTests/pch.hpp | 83 +- UnitTests/pool.cpp | 44 +- UnitTests/ring.cpp | 68 +- UnitTests/sgml.cpp | 90 +- UnitTests/stream.cpp | 247 +++-- UnitTests/string.cpp | 40 +- UnitTests/unicode.cpp | 148 ++- UnitTests/watchdog.cpp | 30 +- UnitTests/zlib.cpp | 40 +- 14 files changed, 951 insertions(+), 902 deletions(-) diff --git a/UnitTests/UnitTests.xcodeproj/project.pbxproj b/UnitTests/UnitTests.xcodeproj/project.pbxproj index 15bb1f75f..b0349f19c 100644 --- a/UnitTests/UnitTests.xcodeproj/project.pbxproj +++ b/UnitTests/UnitTests.xcodeproj/project.pbxproj @@ -17,6 +17,17 @@ F421D4802B750EAE004ECBB0 /* trees.c in Sources */ = {isa = PBXBuildFile; fileRef = F421D4792B750EAE004ECBB0 /* trees.c */; settings = {COMPILER_FLAGS = "-w"; }; }; F421D4812B750EAE004ECBB0 /* inftrees.c in Sources */ = {isa = PBXBuildFile; fileRef = F421D47A2B750EAE004ECBB0 /* inftrees.c */; settings = {COMPILER_FLAGS = "-w"; }; }; F421D4822B750EAE004ECBB0 /* uncompr.c in Sources */ = {isa = PBXBuildFile; fileRef = F421D47B2B750EAE004ECBB0 /* uncompr.c */; settings = {COMPILER_FLAGS = "-w"; }; }; + F421D4832B7511FA004ECBB0 /* hash.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F437AA902AC1BB64001E2230 /* hash.cpp */; }; + F421D4842B7514B5004ECBB0 /* math.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F4C07F4E2AB059300044EDC0 /* math.cpp */; }; + F421D4852B751551004ECBB0 /* parser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F4C07F562AB08E690044EDC0 /* parser.cpp */; }; + F421D4862B751707004ECBB0 /* pool.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F4CCA3B72B73B940007B857B /* pool.cpp */; }; + F421D4872B751739004ECBB0 /* ring.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F4C07F592AB08E690044EDC0 /* ring.cpp */; }; + F421D4882B751774004ECBB0 /* sgml.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F4C07F582AB08E690044EDC0 /* sgml.cpp */; }; + F421D4892B751777004ECBB0 /* stream.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F4C07F5A2AB08E690044EDC0 /* stream.cpp */; }; + F421D48A2B75177B004ECBB0 /* string.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F4CCA3B82B73D2E2007B857B /* string.cpp */; }; + F421D48B2B75177E004ECBB0 /* unicode.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F4C07F572AB08E690044EDC0 /* unicode.cpp */; }; + F421D48C2B751780004ECBB0 /* watchdog.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F4CCA3B62B73B912007B857B /* watchdog.cpp */; }; + F421D48D2B751783004ECBB0 /* zlib.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F421D46B2B750BFD004ECBB0 /* zlib.cpp */; }; F4C07F522AB059580044EDC0 /* pch.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F4C07F512AB059580044EDC0 /* pch.cpp */; }; F4C07F552AB05B5B0044EDC0 /* main.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F4C07F542AB05B5B0044EDC0 /* main.cpp */; }; /* End PBXBuildFile section */ @@ -231,17 +242,28 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + F421D4892B751777004ECBB0 /* stream.cpp in Sources */, + F421D48B2B75177E004ECBB0 /* unicode.cpp in Sources */, F421D47F2B750EAE004ECBB0 /* zutil.c in Sources */, F4C07F552AB05B5B0044EDC0 /* main.cpp in Sources */, + F421D4882B751774004ECBB0 /* sgml.cpp in Sources */, F4C07F522AB059580044EDC0 /* pch.cpp in Sources */, + F421D4862B751707004ECBB0 /* pool.cpp in Sources */, F421D4802B750EAE004ECBB0 /* trees.c in Sources */, + F421D48D2B751783004ECBB0 /* zlib.cpp in Sources */, F421D47D2B750EAE004ECBB0 /* deflate.c in Sources */, F421D4702B750E0F004ECBB0 /* adler32.c in Sources */, F421D4822B750EAE004ECBB0 /* uncompr.c in Sources */, F421D4742B750E21004ECBB0 /* crc32.c in Sources */, F421D47E2B750EAE004ECBB0 /* inffast.c in Sources */, F421D4722B750E18004ECBB0 /* compress.c in Sources */, + F421D4872B751739004ECBB0 /* ring.cpp in Sources */, + F421D4852B751551004ECBB0 /* parser.cpp in Sources */, F421D4812B750EAE004ECBB0 /* inftrees.c in Sources */, + F421D4842B7514B5004ECBB0 /* math.cpp in Sources */, + F421D4832B7511FA004ECBB0 /* hash.cpp in Sources */, + F421D48A2B75177B004ECBB0 /* string.cpp in Sources */, + F421D48C2B751780004ECBB0 /* watchdog.cpp in Sources */, F421D47C2B750EAE004ECBB0 /* inflate.c in Sources */, ); runOnlyForDeploymentPostprocessing = 0; diff --git a/UnitTests/hash.cpp b/UnitTests/hash.cpp index 99634adb2..a1b4e8a23 100644 --- a/UnitTests/hash.cpp +++ b/UnitTests/hash.cpp @@ -1,4 +1,4 @@ -/* +/* SPDX-License-Identifier: MIT Copyright © 2023-2024 Amebis */ @@ -34,34 +34,30 @@ namespace Microsoft { namespace UnitTests { - TEST_CLASS(hash) + void hash::crc32() { - public: - TEST_METHOD(crc32) - { - stdex::crc32_hash h; - static const char data[] = "This is a test."; - h.hash(data, sizeof(data) - sizeof(*data)); - h.finalize(); - Assert::AreEqual(0xc6c3c95d, h); - } + stdex::crc32_hash h; + static const char data[] = "This is a test."; + h.hash(data, sizeof(data) - sizeof(*data)); + h.finalize(); + Assert::AreEqual(0xc6c3c95d, h); + } - TEST_METHOD(md5) - { - stdex::md5_hash h; - static const char data[] = "This is a test."; - h.hash(data, sizeof(data) - sizeof(*data)); - h.finalize(); - Assert::AreEqual({0x12,0x0e,0xa8,0xa2,0x5e,0x5d,0x48,0x7b,0xf6,0x8b,0x5f,0x70,0x96,0x44,0x00,0x19}, h); - } + void hash::md5() + { + stdex::md5_hash h; + static const char data[] = "This is a test."; + h.hash(data, sizeof(data) - sizeof(*data)); + h.finalize(); + Assert::AreEqual({0x12,0x0e,0xa8,0xa2,0x5e,0x5d,0x48,0x7b,0xf6,0x8b,0x5f,0x70,0x96,0x44,0x00,0x19}, h); + } - TEST_METHOD(sha1) - { - stdex::sha1_hash h; - static const char data[] = "This is a test."; - h.hash(data, sizeof(data) - sizeof(*data)); - h.finalize(); - Assert::AreEqual({0xaf,0xa6,0xc8,0xb3,0xa2,0xfa,0xe9,0x57,0x85,0xdc,0x7d,0x96,0x85,0xa5,0x78,0x35,0xd7,0x03,0xac,0x88}, h); - } - }; + void hash::sha1() + { + stdex::sha1_hash h; + static const char data[] = "This is a test."; + h.hash(data, sizeof(data) - sizeof(*data)); + h.finalize(); + Assert::AreEqual({0xaf,0xa6,0xc8,0xb3,0xa2,0xfa,0xe9,0x57,0x85,0xdc,0x7d,0x96,0x85,0xa5,0x78,0x35,0xd7,0x03,0xac,0x88}, h); + } } diff --git a/UnitTests/main.cpp b/UnitTests/main.cpp index 12e69063e..b01fb7050 100644 --- a/UnitTests/main.cpp +++ b/UnitTests/main.cpp @@ -4,17 +4,6 @@ */ #include "pch.hpp" -#include "hash.cpp" -#include "math.cpp" -#include "pool.cpp" -#include "parser.cpp" -#include "ring.cpp" -#include "sgml.cpp" -#include "stream.cpp" -#include "string.cpp" -#include "unicode.cpp" -#include "watchdog.cpp" -#include "zlib.cpp" #include int main(int argc, const char * argv[]) diff --git a/UnitTests/math.cpp b/UnitTests/math.cpp index 12328c240..c4768b6b6 100644 --- a/UnitTests/math.cpp +++ b/UnitTests/math.cpp @@ -1,4 +1,4 @@ -/* +/* SPDX-License-Identifier: MIT Copyright © 2023-2024 Amebis */ @@ -12,33 +12,29 @@ using namespace Microsoft::VisualStudio::CppUnitTestFramework; namespace UnitTests { - TEST_CLASS(math) + void math::mul() { - public: - TEST_METHOD(mul) - { - Assert::AreEqual(10, stdex::mul(2, 5)); - Assert::AreEqual(10, stdex::mul(5, 2)); - Assert::AreEqual(0, stdex::mul(0, 10)); - Assert::AreEqual(0, stdex::mul(10, 0)); - Assert::AreEqual(0, stdex::mul(SIZE_MAX, 0)); - Assert::AreEqual(0, stdex::mul(0, SIZE_MAX)); - Assert::AreEqual(SIZE_MAX, stdex::mul(SIZE_MAX, 1)); - Assert::AreEqual(SIZE_MAX, stdex::mul(1, SIZE_MAX)); - Assert::ExpectException([] { stdex::mul(SIZE_MAX, 2); }); - Assert::ExpectException([] { stdex::mul(2, SIZE_MAX); }); - } + Assert::AreEqual(10, stdex::mul(2, 5)); + Assert::AreEqual(10, stdex::mul(5, 2)); + Assert::AreEqual(0, stdex::mul(0, 10)); + Assert::AreEqual(0, stdex::mul(10, 0)); + Assert::AreEqual(0, stdex::mul(SIZE_MAX, 0)); + Assert::AreEqual(0, stdex::mul(0, SIZE_MAX)); + Assert::AreEqual(SIZE_MAX, stdex::mul(SIZE_MAX, 1)); + Assert::AreEqual(SIZE_MAX, stdex::mul(1, SIZE_MAX)); + Assert::ExpectException([] { stdex::mul(SIZE_MAX, 2); }); + Assert::ExpectException([] { stdex::mul(2, SIZE_MAX); }); + } - TEST_METHOD(add) - { - Assert::AreEqual(7, stdex::add(2, 5)); - Assert::AreEqual(7, stdex::add(5, 2)); - Assert::AreEqual(10, stdex::add(0, 10)); - Assert::AreEqual(10, stdex::add(10, 0)); - Assert::AreEqual(SIZE_MAX, stdex::add(SIZE_MAX, 0)); - Assert::AreEqual(SIZE_MAX, stdex::add(0, SIZE_MAX)); - Assert::ExpectException([] { stdex::add(SIZE_MAX, 1); }); - Assert::ExpectException([] { stdex::add(1, SIZE_MAX); }); - } - }; + void math::add() + { + Assert::AreEqual(7, stdex::add(2, 5)); + Assert::AreEqual(7, stdex::add(5, 2)); + Assert::AreEqual(10, stdex::add(0, 10)); + Assert::AreEqual(10, stdex::add(10, 0)); + Assert::AreEqual(SIZE_MAX, stdex::add(SIZE_MAX, 0)); + Assert::AreEqual(SIZE_MAX, stdex::add(0, SIZE_MAX)); + Assert::ExpectException([] { stdex::add(SIZE_MAX, 1); }); + Assert::ExpectException([] { stdex::add(1, SIZE_MAX); }); + } } diff --git a/UnitTests/parser.cpp b/UnitTests/parser.cpp index b8e6209a9..e5db86b49 100644 --- a/UnitTests/parser.cpp +++ b/UnitTests/parser.cpp @@ -6,15 +6,17 @@ #include "pch.hpp" using namespace std; +using namespace stdex; +using namespace parser; #ifdef _WIN32 using namespace Microsoft::VisualStudio::CppUnitTestFramework; namespace Microsoft { namespace VisualStudio { namespace CppUnitTestFramework { - static wstring ToString(const stdex::interval& q) + static wstring ToString(const interval& q) { - return stdex::sprintf(L"<%zu, %zu>", nullptr, q.start, q.end); + return sprintf(L"<%zu, %zu>", nullptr, q.start, q.end); } } } @@ -23,477 +25,473 @@ namespace Microsoft { namespace UnitTests { - TEST_CLASS(parser) + void parser::wtest() { - public: - TEST_METHOD(wtest) + static const wchar_t text[] = L"This is a test.\nSecond line."; + { - static const wchar_t text[] = L"This is a test.\nSecond line."; - - { - stdex::parser::wnoop p; - Assert::IsTrue(p.match(text)); - Assert::AreEqual((size_t)0, p.interval.start); - Assert::AreEqual((size_t)0, p.interval.end); - } - - { - stdex::parser::wcu p(L't'); - Assert::IsFalse(p.match(text)); - Assert::IsTrue(p.match(text, 0, _countof(text), stdex::parser::match_case_insensitive)); - Assert::AreEqual((size_t)0, p.interval.start); - Assert::AreEqual((size_t)1, p.interval.end); - } - - { - stdex::parser::wspace_cu p; - Assert::IsFalse(p.match(text)); - Assert::IsTrue(p.match(text, 4)); - Assert::AreEqual((size_t)4, p.interval.start); - Assert::AreEqual((size_t)5, p.interval.end); - } - - { - stdex::parser::wpunct_cu p; - Assert::IsFalse(p.match(text)); - Assert::IsTrue(p.match(text, 14)); - Assert::AreEqual((size_t)14, p.interval.start); - Assert::AreEqual((size_t)15, p.interval.end); - } - - { - stdex::parser::wspace_or_punct_cu p; - Assert::IsFalse(p.match(text)); - Assert::IsTrue(p.match(text, 4)); - Assert::AreEqual((size_t)4, p.interval.start); - Assert::AreEqual((size_t)5, p.interval.end); - Assert::IsTrue(p.match(text, 14)); - Assert::AreEqual((size_t)14, p.interval.start); - Assert::AreEqual((size_t)15, p.interval.end); - } - - { - stdex::parser::wbol p; - Assert::IsTrue(p.match(text)); - Assert::AreEqual((size_t)0, p.interval.start); - Assert::AreEqual((size_t)0, p.interval.end); - Assert::IsFalse(p.match(text, 1)); - Assert::IsFalse(p.match(text, 15)); - Assert::IsTrue(p.match(text, 16)); - Assert::AreEqual((size_t)16, p.interval.start); - Assert::AreEqual((size_t)16, p.interval.end); - } - - { - stdex::parser::weol p; - Assert::IsFalse(p.match(text)); - Assert::IsFalse(p.match(text, 1)); - Assert::IsTrue(p.match(text, 15)); - Assert::AreEqual((size_t)15, p.interval.start); - Assert::AreEqual((size_t)15, p.interval.end); - Assert::IsFalse(p.match(text, 16)); - } - - { - stdex::parser::wcu_set p(L"abcD"); - Assert::IsFalse(p.match(text)); - Assert::IsTrue(p.match(text, 8)); - Assert::AreEqual((size_t)8, p.interval.start); - Assert::AreEqual((size_t)9, p.interval.end); - Assert::AreEqual((size_t)0, p.hit_offset); - Assert::IsFalse(p.match(text, 21)); - Assert::IsTrue(p.match(text, 21, _countof(text), stdex::parser::match_case_insensitive)); - Assert::AreEqual((size_t)21, p.interval.start); - Assert::AreEqual((size_t)22, p.interval.end); - Assert::AreEqual((size_t)3, p.hit_offset); - } - - { - stdex::parser::wstring p(L"this"); - Assert::IsFalse(p.match(text)); - Assert::IsTrue(p.match(text, 0, sizeof(text), stdex::parser::match_case_insensitive)); - Assert::AreEqual((size_t)0, p.interval.start); - Assert::AreEqual((size_t)4, p.interval.end); - } - - { - stdex::parser::wany_cu chr; - stdex::parser::witerations p(stdex::make_shared_no_delete(&chr), 1, 5); - Assert::IsTrue(p.match(text)); - Assert::AreEqual((size_t)0, p.interval.start); - Assert::AreEqual((size_t)5, p.interval.end); - } - - { - stdex::parser::wspace_cu nospace(true); - stdex::parser::witerations p(stdex::make_shared_no_delete(&nospace), 1); - Assert::IsTrue(p.match(text)); - Assert::AreEqual((size_t)0, p.interval.start); - Assert::AreEqual((size_t)4, p.interval.end); - } - - { - stdex::parser::wcu chr_t(L't'), chr_h(L'h'), chr_i(L'i'), chr_s(L's'); - stdex::parser::wspace_cu space; - stdex::parser::wsequence p({ - stdex::make_shared_no_delete(&chr_t), - stdex::make_shared_no_delete(&chr_h), - stdex::make_shared_no_delete(&chr_i), - stdex::make_shared_no_delete(&chr_s), - stdex::make_shared_no_delete(&space) }); - Assert::IsFalse(p.match(text)); - Assert::IsTrue(p.match(text, 0, _countof(text), stdex::parser::match_case_insensitive)); - Assert::AreEqual((size_t)0, p.interval.start); - Assert::AreEqual((size_t)5, p.interval.end); - } - - { - stdex::parser::wstring apple(L"apple"), orange(L"orange"), _this(L"this"); - stdex::parser::wspace_cu space; - stdex::parser::wbranch p({ - stdex::make_shared_no_delete(&apple), - stdex::make_shared_no_delete(&orange), - stdex::make_shared_no_delete(&_this), - stdex::make_shared_no_delete(&space) }); - Assert::IsFalse(p.match(text)); - Assert::IsTrue(p.match(text, 0, _countof(text), stdex::parser::match_case_insensitive)); - Assert::AreEqual((size_t)2, p.hit_offset); - Assert::AreEqual((size_t)0, p.interval.start); - Assert::AreEqual((size_t)4, p.interval.end); - } - - { - stdex::parser::wstring_branch p(L"apple", L"orange", L"this", nullptr); - Assert::IsFalse(p.match(text)); - Assert::IsTrue(p.match(text, 0, _countof(text), stdex::parser::match_case_insensitive)); - Assert::AreEqual((size_t)2, p.hit_offset); - Assert::AreEqual((size_t)0, p.interval.start); - Assert::AreEqual((size_t)4, p.interval.end); - } - - { - stdex::parser::wcu chr_s(L's'), chr_h(L'h'), chr_i(L'i'), chr_t(L't'); - stdex::parser::wpermutation p({ - stdex::make_shared_no_delete(&chr_s), - stdex::make_shared_no_delete(&chr_h), - stdex::make_shared_no_delete(&chr_i), - stdex::make_shared_no_delete(&chr_t) }); - Assert::IsFalse(p.match(text)); - Assert::IsTrue(p.match(text, 0, _countof(text), stdex::parser::match_case_insensitive)); - Assert::AreEqual((size_t)0, p.interval.start); - Assert::AreEqual((size_t)4, p.interval.end); - } - - { - std::locale locale_slSI("sl_SI"); - stdex::parser::wspace_cu space(false, locale_slSI); - stdex::parser::wiban p(stdex::make_shared_no_delete(&space), locale_slSI); - Assert::IsTrue(p.match(L"SI56023120015226972", 0, SIZE_MAX)); - Assert::IsTrue(p.is_valid); - Assert::AreEqual(L"SI", p.country); - Assert::AreEqual(L"56", p.check_digits); - Assert::AreEqual(L"023120015226972", p.bban); - Assert::IsTrue(p.match(L"SI56 0231 2001 5226 972", 0, SIZE_MAX)); - Assert::IsTrue(p.is_valid); - Assert::AreEqual(L"SI", p.country); - Assert::AreEqual(L"56", p.check_digits); - Assert::AreEqual(L"023120015226972", p.bban); - Assert::IsFalse(p.match(L"si56 0231 2001 5226 972", 0, SIZE_MAX)); - Assert::IsFalse(p.is_valid); - Assert::IsTrue(p.match(L"si56 0231 2001 5226 972", 0, SIZE_MAX, stdex::parser::match_case_insensitive)); - Assert::IsTrue(p.is_valid); - Assert::IsTrue(p.match(L"SI56 0231 2001 5226 9720", 0, SIZE_MAX)); - Assert::AreEqual(stdex::interval(0, 23), p.interval); - Assert::IsTrue(p.is_valid); - Assert::IsTrue(p.match(L"...SI56 0231 2001 5226 972...", 3, SIZE_MAX)); - Assert::IsTrue(p.is_valid); - Assert::IsTrue(p.match(L"SI56 0231 2001 5226 972", 0, SIZE_MAX)); // no-break space - Assert::IsTrue(p.is_valid); - - Assert::IsTrue(p.match(L"BE71 0961 2345 6769", 0, SIZE_MAX)); - Assert::IsTrue(p.is_valid); - Assert::IsTrue(p.match(L"BR15 0000 0000 0000 1093 2840 814 P2", 0, SIZE_MAX)); - Assert::IsTrue(p.is_valid); - Assert::IsTrue(p.match(L"CR99 0000 0000 0000 8888 88", 0, SIZE_MAX)); - Assert::IsFalse(p.is_valid); - Assert::IsTrue(p.match(L"FR76 3000 6000 0112 3456 7890 189", 0, SIZE_MAX)); - Assert::IsTrue(p.is_valid); - Assert::IsTrue(p.match(L"IE12 BOFI 9000 0112 3456 78", 0, SIZE_MAX)); - Assert::IsFalse(p.is_valid); - Assert::IsTrue(p.match(L"DE91 1000 0000 0123 4567 89", 0, SIZE_MAX)); - Assert::IsTrue(p.is_valid); - Assert::IsTrue(p.match(L"GR96 0810 0010 0000 0123 4567 890", 0, SIZE_MAX)); - Assert::IsTrue(p.is_valid); - Assert::IsTrue(p.match(L"MU43 BOMM 0101 1234 5678 9101 000 MUR", 0, SIZE_MAX)); - Assert::IsTrue(p.is_valid); - Assert::IsTrue(p.match(L"PK70 BANK 0000 1234 5678 9000", 0, SIZE_MAX)); - Assert::IsTrue(p.is_valid); - Assert::IsTrue(p.match(L"PL10 1050 0099 7603 1234 5678 9123", 0, SIZE_MAX)); - Assert::IsTrue(p.is_valid); - Assert::IsTrue(p.match(L"RO09 BCYP 0000 0012 3456 7890", 0, SIZE_MAX)); - Assert::IsTrue(p.is_valid); - Assert::IsTrue(p.match(L"LC14 BOSL 1234 5678 9012 3456 7890 1234", 0, SIZE_MAX)); - Assert::IsTrue(p.is_valid); - Assert::IsTrue(p.match(L"SA44 2000 0001 2345 6789 1234", 0, SIZE_MAX)); - Assert::IsTrue(p.is_valid); - Assert::IsTrue(p.match(L"ES79 2100 0813 6101 2345 6789", 0, SIZE_MAX)); - Assert::IsTrue(p.is_valid); - Assert::IsTrue(p.match(L"SE87 3000 0000 0101 2345 6789", 0, SIZE_MAX)); - Assert::IsFalse(p.is_valid); - Assert::IsTrue(p.match(L"CH56 0483 5012 3456 7800 9", 0, SIZE_MAX)); - Assert::IsTrue(p.is_valid); - Assert::IsTrue(p.match(L"GB98 MIDL 0700 9312 3456 78", 0, SIZE_MAX)); - Assert::IsTrue(p.is_valid); - } - - { - std::locale locale_slSI("sl_SI"); - stdex::parser::wspace_cu space(false, locale_slSI); - stdex::parser::wcreditor_reference p(stdex::make_shared_no_delete(&space), locale_slSI); - Assert::IsTrue(p.match(L"RF18539007547034", 0, SIZE_MAX)); - Assert::IsTrue(p.is_valid); - Assert::AreEqual(L"18", p.check_digits); - Assert::AreEqual(L"000000000539007547034", p.reference); - Assert::IsTrue(p.match(L"RF18 5390 0754 7034", 0, SIZE_MAX)); - Assert::IsTrue(p.is_valid); - Assert::AreEqual(L"18", p.check_digits); - Assert::AreEqual(L"000000000539007547034", p.reference); - Assert::IsFalse(p.match(L"rf18 5390 0754 7034", 0, SIZE_MAX)); - Assert::IsFalse(p.is_valid); - Assert::IsTrue(p.match(L"rf18 5390 0754 7034", 0, SIZE_MAX, stdex::parser::match_case_insensitive)); - Assert::IsTrue(p.is_valid); - Assert::IsTrue(p.match(L"RF18 5390 0754 70340", 0, SIZE_MAX)); - Assert::IsFalse(p.is_valid); - Assert::IsTrue(p.match(L"...RF18 5390 0754 7034...", 3, SIZE_MAX)); - Assert::IsTrue(p.is_valid); - Assert::IsTrue(p.match(L"RF18 5390 0754 7034", 0, SIZE_MAX)); // no-break space - Assert::IsTrue(p.is_valid); - } - - { - std::locale locale_slSI("sl_SI"); - stdex::parser::wspace_cu space(false, locale_slSI); - stdex::parser::wsi_reference p(stdex::make_shared_no_delete(&space), locale_slSI); - Assert::IsTrue(p.match(L"SI121234567890120", 0, SIZE_MAX)); - Assert::IsTrue(p.is_valid); - Assert::AreEqual(L"12", p.model); - Assert::AreEqual(stdex::interval(4, 17), p.part1.interval); - Assert::IsTrue(p.match(L"SI12 1234567890120", 0, SIZE_MAX)); - Assert::IsTrue(p.is_valid); - Assert::AreEqual(L"12", p.model); - Assert::AreEqual(stdex::interval(5, 18), p.part1.interval); - Assert::IsFalse(p.match(L"si12 1234567890120", 0, SIZE_MAX)); - Assert::IsTrue(p.match(L"si12 1234567890120", 0, SIZE_MAX, stdex::parser::match_case_insensitive)); - Assert::IsTrue(p.match(L"...SI12 1234567890120...", 3, SIZE_MAX)); - Assert::IsTrue(p.match(L"SI12 1234567890120", 0, SIZE_MAX)); // no-break space - } + wnoop p; + Assert::IsTrue(p.match(text)); + Assert::AreEqual((size_t)0, p.interval.start); + Assert::AreEqual((size_t)0, p.interval.end); + } + + { + wcu p(L't'); + Assert::IsFalse(p.match(text)); + Assert::IsTrue(p.match(text, 0, _countof(text), match_case_insensitive)); + Assert::AreEqual((size_t)0, p.interval.start); + Assert::AreEqual((size_t)1, p.interval.end); + } + + { + wspace_cu p; + Assert::IsFalse(p.match(text)); + Assert::IsTrue(p.match(text, 4)); + Assert::AreEqual((size_t)4, p.interval.start); + Assert::AreEqual((size_t)5, p.interval.end); + } + + { + wpunct_cu p; + Assert::IsFalse(p.match(text)); + Assert::IsTrue(p.match(text, 14)); + Assert::AreEqual((size_t)14, p.interval.start); + Assert::AreEqual((size_t)15, p.interval.end); + } + + { + wspace_or_punct_cu p; + Assert::IsFalse(p.match(text)); + Assert::IsTrue(p.match(text, 4)); + Assert::AreEqual((size_t)4, p.interval.start); + Assert::AreEqual((size_t)5, p.interval.end); + Assert::IsTrue(p.match(text, 14)); + Assert::AreEqual((size_t)14, p.interval.start); + Assert::AreEqual((size_t)15, p.interval.end); + } + + { + wbol p; + Assert::IsTrue(p.match(text)); + Assert::AreEqual((size_t)0, p.interval.start); + Assert::AreEqual((size_t)0, p.interval.end); + Assert::IsFalse(p.match(text, 1)); + Assert::IsFalse(p.match(text, 15)); + Assert::IsTrue(p.match(text, 16)); + Assert::AreEqual((size_t)16, p.interval.start); + Assert::AreEqual((size_t)16, p.interval.end); + } + + { + weol p; + Assert::IsFalse(p.match(text)); + Assert::IsFalse(p.match(text, 1)); + Assert::IsTrue(p.match(text, 15)); + Assert::AreEqual((size_t)15, p.interval.start); + Assert::AreEqual((size_t)15, p.interval.end); + Assert::IsFalse(p.match(text, 16)); + } + + { + wcu_set p(L"abcD"); + Assert::IsFalse(p.match(text)); + Assert::IsTrue(p.match(text, 8)); + Assert::AreEqual((size_t)8, p.interval.start); + Assert::AreEqual((size_t)9, p.interval.end); + Assert::AreEqual((size_t)0, p.hit_offset); + Assert::IsFalse(p.match(text, 21)); + Assert::IsTrue(p.match(text, 21, _countof(text), match_case_insensitive)); + Assert::AreEqual((size_t)21, p.interval.start); + Assert::AreEqual((size_t)22, p.interval.end); + Assert::AreEqual((size_t)3, p.hit_offset); + } + + { + stdex::parser::wstring p(L"this"); + Assert::IsFalse(p.match(text)); + Assert::IsTrue(p.match(text, 0, sizeof(text), match_case_insensitive)); + Assert::AreEqual((size_t)0, p.interval.start); + Assert::AreEqual((size_t)4, p.interval.end); + } + + { + wany_cu chr; + witerations p(make_shared_no_delete(&chr), 1, 5); + Assert::IsTrue(p.match(text)); + Assert::AreEqual((size_t)0, p.interval.start); + Assert::AreEqual((size_t)5, p.interval.end); + } + + { + wspace_cu nospace(true); + witerations p(make_shared_no_delete(&nospace), 1); + Assert::IsTrue(p.match(text)); + Assert::AreEqual((size_t)0, p.interval.start); + Assert::AreEqual((size_t)4, p.interval.end); + } + + { + wcu chr_t(L't'), chr_h(L'h'), chr_i(L'i'), chr_s(L's'); + wspace_cu space; + wsequence p({ + make_shared_no_delete(&chr_t), + make_shared_no_delete(&chr_h), + make_shared_no_delete(&chr_i), + make_shared_no_delete(&chr_s), + make_shared_no_delete(&space) }); + Assert::IsFalse(p.match(text)); + Assert::IsTrue(p.match(text, 0, _countof(text), match_case_insensitive)); + Assert::AreEqual((size_t)0, p.interval.start); + Assert::AreEqual((size_t)5, p.interval.end); + } + + { + stdex::parser::wstring apple(L"apple"), orange(L"orange"), _this(L"this"); + wspace_cu space; + wbranch p({ + make_shared_no_delete(&apple), + make_shared_no_delete(&orange), + make_shared_no_delete(&_this), + make_shared_no_delete(&space) }); + Assert::IsFalse(p.match(text)); + Assert::IsTrue(p.match(text, 0, _countof(text), match_case_insensitive)); + Assert::AreEqual((size_t)2, p.hit_offset); + Assert::AreEqual((size_t)0, p.interval.start); + Assert::AreEqual((size_t)4, p.interval.end); + } + + { + wstring_branch p(L"apple", L"orange", L"this", nullptr); + Assert::IsFalse(p.match(text)); + Assert::IsTrue(p.match(text, 0, _countof(text), match_case_insensitive)); + Assert::AreEqual((size_t)2, p.hit_offset); + Assert::AreEqual((size_t)0, p.interval.start); + Assert::AreEqual((size_t)4, p.interval.end); + } + + { + wcu chr_s(L's'), chr_h(L'h'), chr_i(L'i'), chr_t(L't'); + wpermutation p({ + make_shared_no_delete(&chr_s), + make_shared_no_delete(&chr_h), + make_shared_no_delete(&chr_i), + make_shared_no_delete(&chr_t) }); + Assert::IsFalse(p.match(text)); + Assert::IsTrue(p.match(text, 0, _countof(text), match_case_insensitive)); + Assert::AreEqual((size_t)0, p.interval.start); + Assert::AreEqual((size_t)4, p.interval.end); } - TEST_METHOD(sgml_test) { std::locale locale_slSI("sl_SI"); - static const char text[] = "V kožuščku zlobnega mizarja stopiclja fant\nin kliče 1234567890."; + wspace_cu space(false, locale_slSI); + wiban p(make_shared_no_delete(&space), locale_slSI); + Assert::IsTrue(p.match(L"SI56023120015226972", 0, SIZE_MAX)); + Assert::IsTrue(p.is_valid); + Assert::AreEqual(L"SI", p.country); + Assert::AreEqual(L"56", p.check_digits); + Assert::AreEqual(L"023120015226972", p.bban); + Assert::IsTrue(p.match(L"SI56 0231 2001 5226 972", 0, SIZE_MAX)); + Assert::IsTrue(p.is_valid); + Assert::AreEqual(L"SI", p.country); + Assert::AreEqual(L"56", p.check_digits); + Assert::AreEqual(L"023120015226972", p.bban); + Assert::IsFalse(p.match(L"si56 0231 2001 5226 972", 0, SIZE_MAX)); + Assert::IsFalse(p.is_valid); + Assert::IsTrue(p.match(L"si56 0231 2001 5226 972", 0, SIZE_MAX, match_case_insensitive)); + Assert::IsTrue(p.is_valid); + Assert::IsTrue(p.match(L"SI56 0231 2001 5226 9720", 0, SIZE_MAX)); + Assert::AreEqual(interval(0, 23), p.interval); + Assert::IsTrue(p.is_valid); + Assert::IsTrue(p.match(L"...SI56 0231 2001 5226 972...", 3, SIZE_MAX)); + Assert::IsTrue(p.is_valid); + Assert::IsTrue(p.match(L"SI56 0231 2001 5226 972", 0, SIZE_MAX)); // no-break space + Assert::IsTrue(p.is_valid); - { - stdex::parser::sgml_noop p; - Assert::IsTrue(p.match(text)); - Assert::AreEqual((size_t)0, p.interval.start); - Assert::AreEqual((size_t)0, p.interval.end); - } - - { - stdex::parser::sgml_cp p("v"); - Assert::IsFalse(p.match(text)); - Assert::IsTrue(p.match(text, 0, _countof(text), stdex::parser::match_case_insensitive)); - Assert::AreEqual((size_t)0, p.interval.start); - Assert::AreEqual((size_t)1, p.interval.end); - } - - { - stdex::parser::sgml_cp p("Ž", SIZE_MAX, false, locale_slSI); - Assert::IsFalse(p.match(text, 4)); - Assert::IsTrue(p.match(text, 4, _countof(text), stdex::parser::match_case_insensitive)); - Assert::AreEqual((size_t)4, p.interval.start); - Assert::AreEqual((size_t)12, p.interval.end); - } - - { - stdex::parser::sgml_space_cp p(false, locale_slSI); - Assert::IsFalse(p.match(text)); - Assert::IsTrue(p.match(text, 1)); - Assert::AreEqual((size_t)1, p.interval.start); - Assert::AreEqual((size_t)2, p.interval.end); - Assert::IsTrue(p.match(text, 79)); - Assert::AreEqual((size_t)79, p.interval.start); - Assert::AreEqual((size_t)85, p.interval.end); - } - - { - stdex::parser::sgml_string_branch p(locale_slSI, "apple", "orange", "KoŽuŠčKu", nullptr); - Assert::IsFalse(p.match(text, 2)); - Assert::IsTrue(p.match(text, 2, _countof(text), stdex::parser::match_case_insensitive)); - Assert::AreEqual((size_t)2, p.hit_offset); - Assert::AreEqual((size_t)2, p.interval.start); - Assert::AreEqual((size_t)31, p.interval.end); - } - - { - stdex::parser::sgml_space_cp space(false, locale_slSI); - stdex::parser::sgml_iban p(stdex::make_shared_no_delete(&space), locale_slSI); - Assert::IsTrue(p.match("SI56023120015226972", 0, SIZE_MAX)); - Assert::IsTrue(p.is_valid); - Assert::AreEqual("SI", p.country); - Assert::AreEqual("56", p.check_digits); - Assert::AreEqual("023120015226972", p.bban); - Assert::IsTrue(p.match("SI56 0231 2001 5226 972", 0, SIZE_MAX)); - Assert::IsTrue(p.is_valid); - Assert::AreEqual("SI", p.country); - Assert::AreEqual("56", p.check_digits); - Assert::AreEqual("023120015226972", p.bban); - Assert::IsFalse(p.match("si56 0231 2001 5226 972", 0, SIZE_MAX)); - Assert::IsFalse(p.is_valid); - Assert::IsTrue(p.match("si56 0231 2001 5226 972", 0, SIZE_MAX, stdex::parser::match_case_insensitive)); - Assert::IsTrue(p.is_valid); - Assert::IsTrue(p.match("SI56 0231 2001 5226 9720", 0, SIZE_MAX)); - Assert::AreEqual(stdex::interval(0, 23), p.interval); - Assert::IsTrue(p.is_valid); - Assert::IsTrue(p.match("...SI56 0231 2001 5226 972...", 3, SIZE_MAX)); - Assert::IsTrue(p.is_valid); - Assert::IsTrue(p.match("SI56 0231 2001 5226 972", 0, SIZE_MAX)); - Assert::IsTrue(p.is_valid); - } - - { - stdex::parser::sgml_space_cp space(false, locale_slSI); - stdex::parser::sgml_creditor_reference p(stdex::make_shared_no_delete(&space), locale_slSI); - Assert::IsTrue(p.match("RF18539007547034", 0, SIZE_MAX)); - Assert::IsTrue(p.is_valid); - Assert::AreEqual("18", p.check_digits); - Assert::AreEqual("000000000539007547034", p.reference); - Assert::IsTrue(p.match("RF18 5390 0754 7034", 0, SIZE_MAX)); - Assert::IsTrue(p.is_valid); - Assert::AreEqual("18", p.check_digits); - Assert::AreEqual("000000000539007547034", p.reference); - Assert::IsFalse(p.match("rf18 5390 0754 7034", 0, SIZE_MAX)); - Assert::IsFalse(p.is_valid); - Assert::IsTrue(p.match("rf18 5390 0754 7034", 0, SIZE_MAX, stdex::parser::match_case_insensitive)); - Assert::IsTrue(p.is_valid); - Assert::IsTrue(p.match("RF18 5390 0754 70340", 0, SIZE_MAX)); - Assert::IsFalse(p.is_valid); - Assert::IsTrue(p.match("...RF18 5390 0754 7034...", 3, SIZE_MAX)); - Assert::IsTrue(p.is_valid); - Assert::IsTrue(p.match("RF18 5390 0754 7034", 0, SIZE_MAX)); - Assert::IsTrue(p.is_valid); - } - - { - stdex::parser::sgml_space_cp space(false, locale_slSI); - stdex::parser::sgml_si_reference p(stdex::make_shared_no_delete(&space), locale_slSI); - Assert::IsTrue(p.match("SI121234567890120", 0, SIZE_MAX)); - Assert::IsTrue(p.is_valid); - Assert::AreEqual("12", p.model); - Assert::AreEqual(stdex::interval(4, 17), p.part1.interval); - Assert::IsTrue(p.match("SI12 1234567890120", 0, SIZE_MAX)); - Assert::IsTrue(p.is_valid); - Assert::AreEqual("12", p.model); - Assert::AreEqual(stdex::interval(5, 18), p.part1.interval); - Assert::IsFalse(p.match("si12 1234567890120", 0, SIZE_MAX)); - Assert::IsTrue(p.match("si12 1234567890120", 0, SIZE_MAX, stdex::parser::match_case_insensitive)); - Assert::IsTrue(p.match("...SI12 1234567890120...", 3, SIZE_MAX)); - Assert::IsTrue(p.match("SI12 1234567890120", 0, SIZE_MAX)); - } + Assert::IsTrue(p.match(L"BE71 0961 2345 6769", 0, SIZE_MAX)); + Assert::IsTrue(p.is_valid); + Assert::IsTrue(p.match(L"BR15 0000 0000 0000 1093 2840 814 P2", 0, SIZE_MAX)); + Assert::IsTrue(p.is_valid); + Assert::IsTrue(p.match(L"CR99 0000 0000 0000 8888 88", 0, SIZE_MAX)); + Assert::IsFalse(p.is_valid); + Assert::IsTrue(p.match(L"FR76 3000 6000 0112 3456 7890 189", 0, SIZE_MAX)); + Assert::IsTrue(p.is_valid); + Assert::IsTrue(p.match(L"IE12 BOFI 9000 0112 3456 78", 0, SIZE_MAX)); + Assert::IsFalse(p.is_valid); + Assert::IsTrue(p.match(L"DE91 1000 0000 0123 4567 89", 0, SIZE_MAX)); + Assert::IsTrue(p.is_valid); + Assert::IsTrue(p.match(L"GR96 0810 0010 0000 0123 4567 890", 0, SIZE_MAX)); + Assert::IsTrue(p.is_valid); + Assert::IsTrue(p.match(L"MU43 BOMM 0101 1234 5678 9101 000 MUR", 0, SIZE_MAX)); + Assert::IsTrue(p.is_valid); + Assert::IsTrue(p.match(L"PK70 BANK 0000 1234 5678 9000", 0, SIZE_MAX)); + Assert::IsTrue(p.is_valid); + Assert::IsTrue(p.match(L"PL10 1050 0099 7603 1234 5678 9123", 0, SIZE_MAX)); + Assert::IsTrue(p.is_valid); + Assert::IsTrue(p.match(L"RO09 BCYP 0000 0012 3456 7890", 0, SIZE_MAX)); + Assert::IsTrue(p.is_valid); + Assert::IsTrue(p.match(L"LC14 BOSL 1234 5678 9012 3456 7890 1234", 0, SIZE_MAX)); + Assert::IsTrue(p.is_valid); + Assert::IsTrue(p.match(L"SA44 2000 0001 2345 6789 1234", 0, SIZE_MAX)); + Assert::IsTrue(p.is_valid); + Assert::IsTrue(p.match(L"ES79 2100 0813 6101 2345 6789", 0, SIZE_MAX)); + Assert::IsTrue(p.is_valid); + Assert::IsTrue(p.match(L"SE87 3000 0000 0101 2345 6789", 0, SIZE_MAX)); + Assert::IsFalse(p.is_valid); + Assert::IsTrue(p.match(L"CH56 0483 5012 3456 7800 9", 0, SIZE_MAX)); + Assert::IsTrue(p.is_valid); + Assert::IsTrue(p.match(L"GB98 MIDL 0700 9312 3456 78", 0, SIZE_MAX)); + Assert::IsTrue(p.is_valid); } - TEST_METHOD(http_test) { - static const std::locale locale("en_US.UTF-8"); - static const char request[] = - "GET / HTTP/2\r\n" - "Host: stackoverflow.com\r\n" - "User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/110.0\r\n" - "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8\r\n" - "Accept-Language: sl,en-US;q=0.8,en;q=0.6,de-DE;q=0.4,de;q=0.2\r\n" - "Accept-Encoding: gzip, deflate, br\r\n" - "DNT: 1\r\n" - "Connection: keep-alive\r\n" - "Cookie: prov=00000000-0000-0000-0000-000000000000; acct=t=00000000000000000%2f%2f0000%2b0000%2b000&s=00000000000000000000000000000000; OptanonConsent=isGpcEnabled=0&datestamp=Fri+Feb+03+2023+11%3A11%3A08+GMT%2B0100+(Srednjeevropski+standardni+%C4%8Das)&version=6.37.0&isIABGlobal=false&hosts=&consentId=00000000-0000-0000-0000-000000000000&interactionCount=1&landingPath=NotLandingPage&groups=00000%3A0%2C00000%3A0%2C00000%3A0%2C00000%3A0; OptanonAlertBoxClosed=2023-02-03T10:11:08.683Z\r\n" - "Upgrade-Insecure-Requests: 1\r\n" - "Sec-Fetch-Dest: document\r\n" - "Sec-Fetch-Mode: navigate\r\n" - "Sec-Fetch-Site: none\r\n" - "Sec-Fetch-User: ?1\r\n" - "Pragma: no-cache\r\n" - "Cache-Control: no-cache\r\n" - "\r\n"; - - { - stdex::parser::http_request p(locale); - Assert::IsTrue(p.match(request)); - Assert::AreEqual((size_t)0, p.interval.start); - Assert::AreEqual((size_t)14, p.interval.end); - Assert::AreEqual((size_t)0, p.verb.start); - Assert::AreEqual((size_t)3, p.verb.end); - Assert::AreEqual((size_t)4, p.url.interval.start); - Assert::AreEqual((size_t)5, p.url.interval.end); - Assert::AreEqual((size_t)6, p.protocol.interval.start); - Assert::AreEqual((size_t)12, p.protocol.interval.end); - Assert::AreEqual((uint16_t)0x200, p.protocol.version); - } - - { - list hdrs; - size_t offset = 14; - for (;;) { - stdex::parser::http_header h; - if (h.match(request, offset)) { - offset = h.interval.end; - hdrs.push_back(std::move(h)); - } - else - break; - } - Assert::AreEqual((size_t)15, hdrs.size()); - stdex::parser::http_weighted_collection> langs; - for (const auto& h : hdrs) - if (stdex::strnicmp(request + h.name.start, h.name.size(), "Accept-Language", SIZE_MAX, locale) == 0) - langs.insert(request, h.value.start, h.value.end); - Assert::IsTrue(!langs.empty()); - { - const vector control = { - "sl", "en-US", "en", "de-DE", "de" - }; - auto c = control.cbegin(); - auto l = langs.cbegin(); - for (; c != control.cend() && l != langs.cend(); ++c, ++l) - Assert::IsTrue(stdex::strnicmp(request + l->value.interval.start, l->value.interval.size(), c->c_str(), c->size(), locale) == 0); - Assert::IsTrue(c == control.cend()); - Assert::IsTrue(l == langs.cend()); - } - } - - //static const char response[] = - // "HTTP/2 200 OK\r\n" - // "cache-control: private\r\n" - // "content-type: text/html; charset=utf-8\r\n" - // "content-encoding: gzip\r\n" - // "strict-transport-security: max-age=15552000\r\n" - // "x-frame-options: SAMEORIGIN\r\n" - // "set-cookie: acct=t=00000000000000000%2f%2f0000%2b0000%2b000&s=00000000000000000000000000000000; expires=Sat, 16 Sep 2023 10:23:00 GMT; domain=.stackoverflow.com; path=/; secure; samesite=none; httponly\r\n" - // "set-cookie: prov_tgt=; expires=Tue, 14 Mar 2023 10:23:00 GMT; domain=.stackoverflow.com; path=/; secure; samesite=none; httponly\r\n" - // "x-request-guid: a6536a49-b473-4c6f-b313-c1e7c0d8f600\r\n" - // "feature-policy: microphone 'none'; speaker 'none'\r\n" - // "content-security-policy: upgrade-insecure-requests; frame-ancestors 'self' https://stackexchange.com\r\n" - // "accept-ranges: bytes\r\n" - // "date: Thu, 16 Mar 2023 10:23:00 GMT\r\n" - // "via: 1.1 varnish\r\n" - // "x-served-by: cache-vie6354-VIE\r\n" - // "x-cache: MISS\r\n" - // "x-cache-hits: 0\r\n" - // "x-timer: S1678962181.533907,VS0,VE144\r\n" - // "vary: Accept-Encoding,Fastly-SSL\r\n" - // "x-dns-prefetch-control: off\r\n" - // "X-Firefox-Spdy: h2\r\n" - // "\r\n"; + std::locale locale_slSI("sl_SI"); + wspace_cu space(false, locale_slSI); + wcreditor_reference p(make_shared_no_delete(&space), locale_slSI); + Assert::IsTrue(p.match(L"RF18539007547034", 0, SIZE_MAX)); + Assert::IsTrue(p.is_valid); + Assert::AreEqual(L"18", p.check_digits); + Assert::AreEqual(L"000000000539007547034", p.reference); + Assert::IsTrue(p.match(L"RF18 5390 0754 7034", 0, SIZE_MAX)); + Assert::IsTrue(p.is_valid); + Assert::AreEqual(L"18", p.check_digits); + Assert::AreEqual(L"000000000539007547034", p.reference); + Assert::IsFalse(p.match(L"rf18 5390 0754 7034", 0, SIZE_MAX)); + Assert::IsFalse(p.is_valid); + Assert::IsTrue(p.match(L"rf18 5390 0754 7034", 0, SIZE_MAX, match_case_insensitive)); + Assert::IsTrue(p.is_valid); + Assert::IsTrue(p.match(L"RF18 5390 0754 70340", 0, SIZE_MAX)); + Assert::IsFalse(p.is_valid); + Assert::IsTrue(p.match(L"...RF18 5390 0754 7034...", 3, SIZE_MAX)); + Assert::IsTrue(p.is_valid); + Assert::IsTrue(p.match(L"RF18 5390 0754 7034", 0, SIZE_MAX)); // no-break space + Assert::IsTrue(p.is_valid); } - }; + + { + std::locale locale_slSI("sl_SI"); + wspace_cu space(false, locale_slSI); + wsi_reference p(make_shared_no_delete(&space), locale_slSI); + Assert::IsTrue(p.match(L"SI121234567890120", 0, SIZE_MAX)); + Assert::IsTrue(p.is_valid); + Assert::AreEqual(L"12", p.model); + Assert::AreEqual(interval(4, 17), p.part1.interval); + Assert::IsTrue(p.match(L"SI12 1234567890120", 0, SIZE_MAX)); + Assert::IsTrue(p.is_valid); + Assert::AreEqual(L"12", p.model); + Assert::AreEqual(interval(5, 18), p.part1.interval); + Assert::IsFalse(p.match(L"si12 1234567890120", 0, SIZE_MAX)); + Assert::IsTrue(p.match(L"si12 1234567890120", 0, SIZE_MAX, match_case_insensitive)); + Assert::IsTrue(p.match(L"...SI12 1234567890120...", 3, SIZE_MAX)); + Assert::IsTrue(p.match(L"SI12 1234567890120", 0, SIZE_MAX)); // no-break space + } + } + + void parser::sgml_test() + { + std::locale locale_slSI("sl_SI"); + static const char text[] = "V kožuščku zlobnega mizarja stopiclja fant\nin kliče 1234567890."; + + { + sgml_noop p; + Assert::IsTrue(p.match(text)); + Assert::AreEqual((size_t)0, p.interval.start); + Assert::AreEqual((size_t)0, p.interval.end); + } + + { + sgml_cp p("v"); + Assert::IsFalse(p.match(text)); + Assert::IsTrue(p.match(text, 0, _countof(text), match_case_insensitive)); + Assert::AreEqual((size_t)0, p.interval.start); + Assert::AreEqual((size_t)1, p.interval.end); + } + + { + sgml_cp p("Ž", SIZE_MAX, false, locale_slSI); + Assert::IsFalse(p.match(text, 4)); + Assert::IsTrue(p.match(text, 4, _countof(text), match_case_insensitive)); + Assert::AreEqual((size_t)4, p.interval.start); + Assert::AreEqual((size_t)12, p.interval.end); + } + + { + sgml_space_cp p(false, locale_slSI); + Assert::IsFalse(p.match(text)); + Assert::IsTrue(p.match(text, 1)); + Assert::AreEqual((size_t)1, p.interval.start); + Assert::AreEqual((size_t)2, p.interval.end); + Assert::IsTrue(p.match(text, 79)); + Assert::AreEqual((size_t)79, p.interval.start); + Assert::AreEqual((size_t)85, p.interval.end); + } + + { + sgml_string_branch p(locale_slSI, "apple", "orange", "KoŽuŠčKu", nullptr); + Assert::IsFalse(p.match(text, 2)); + Assert::IsTrue(p.match(text, 2, _countof(text), match_case_insensitive)); + Assert::AreEqual((size_t)2, p.hit_offset); + Assert::AreEqual((size_t)2, p.interval.start); + Assert::AreEqual((size_t)31, p.interval.end); + } + + { + sgml_space_cp space(false, locale_slSI); + sgml_iban p(make_shared_no_delete(&space), locale_slSI); + Assert::IsTrue(p.match("SI56023120015226972", 0, SIZE_MAX)); + Assert::IsTrue(p.is_valid); + Assert::AreEqual("SI", p.country); + Assert::AreEqual("56", p.check_digits); + Assert::AreEqual("023120015226972", p.bban); + Assert::IsTrue(p.match("SI56 0231 2001 5226 972", 0, SIZE_MAX)); + Assert::IsTrue(p.is_valid); + Assert::AreEqual("SI", p.country); + Assert::AreEqual("56", p.check_digits); + Assert::AreEqual("023120015226972", p.bban); + Assert::IsFalse(p.match("si56 0231 2001 5226 972", 0, SIZE_MAX)); + Assert::IsFalse(p.is_valid); + Assert::IsTrue(p.match("si56 0231 2001 5226 972", 0, SIZE_MAX, match_case_insensitive)); + Assert::IsTrue(p.is_valid); + Assert::IsTrue(p.match("SI56 0231 2001 5226 9720", 0, SIZE_MAX)); + Assert::AreEqual(interval(0, 23), p.interval); + Assert::IsTrue(p.is_valid); + Assert::IsTrue(p.match("...SI56 0231 2001 5226 972...", 3, SIZE_MAX)); + Assert::IsTrue(p.is_valid); + Assert::IsTrue(p.match("SI56 0231 2001 5226 972", 0, SIZE_MAX)); + Assert::IsTrue(p.is_valid); + } + + { + sgml_space_cp space(false, locale_slSI); + sgml_creditor_reference p(make_shared_no_delete(&space), locale_slSI); + Assert::IsTrue(p.match("RF18539007547034", 0, SIZE_MAX)); + Assert::IsTrue(p.is_valid); + Assert::AreEqual("18", p.check_digits); + Assert::AreEqual("000000000539007547034", p.reference); + Assert::IsTrue(p.match("RF18 5390 0754 7034", 0, SIZE_MAX)); + Assert::IsTrue(p.is_valid); + Assert::AreEqual("18", p.check_digits); + Assert::AreEqual("000000000539007547034", p.reference); + Assert::IsFalse(p.match("rf18 5390 0754 7034", 0, SIZE_MAX)); + Assert::IsFalse(p.is_valid); + Assert::IsTrue(p.match("rf18 5390 0754 7034", 0, SIZE_MAX, match_case_insensitive)); + Assert::IsTrue(p.is_valid); + Assert::IsTrue(p.match("RF18 5390 0754 70340", 0, SIZE_MAX)); + Assert::IsFalse(p.is_valid); + Assert::IsTrue(p.match("...RF18 5390 0754 7034...", 3, SIZE_MAX)); + Assert::IsTrue(p.is_valid); + Assert::IsTrue(p.match("RF18 5390 0754 7034", 0, SIZE_MAX)); + Assert::IsTrue(p.is_valid); + } + + { + sgml_space_cp space(false, locale_slSI); + sgml_si_reference p(make_shared_no_delete(&space), locale_slSI); + Assert::IsTrue(p.match("SI121234567890120", 0, SIZE_MAX)); + Assert::IsTrue(p.is_valid); + Assert::AreEqual("12", p.model); + Assert::AreEqual(interval(4, 17), p.part1.interval); + Assert::IsTrue(p.match("SI12 1234567890120", 0, SIZE_MAX)); + Assert::IsTrue(p.is_valid); + Assert::AreEqual("12", p.model); + Assert::AreEqual(interval(5, 18), p.part1.interval); + Assert::IsFalse(p.match("si12 1234567890120", 0, SIZE_MAX)); + Assert::IsTrue(p.match("si12 1234567890120", 0, SIZE_MAX, match_case_insensitive)); + Assert::IsTrue(p.match("...SI12 1234567890120...", 3, SIZE_MAX)); + Assert::IsTrue(p.match("SI12 1234567890120", 0, SIZE_MAX)); + } + } + + void parser::http_test() + { + static const std::locale locale("en_US.UTF-8"); + static const char request[] = + "GET / HTTP/2\r\n" + "Host: stackoverflow.com\r\n" + "User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/110.0\r\n" + "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8\r\n" + "Accept-Language: sl,en-US;q=0.8,en;q=0.6,de-DE;q=0.4,de;q=0.2\r\n" + "Accept-Encoding: gzip, deflate, br\r\n" + "DNT: 1\r\n" + "Connection: keep-alive\r\n" + "Cookie: prov=00000000-0000-0000-0000-000000000000; acct=t=00000000000000000%2f%2f0000%2b0000%2b000&s=00000000000000000000000000000000; OptanonConsent=isGpcEnabled=0&datestamp=Fri+Feb+03+2023+11%3A11%3A08+GMT%2B0100+(Srednjeevropski+standardni+%C4%8Das)&version=6.37.0&isIABGlobal=false&hosts=&consentId=00000000-0000-0000-0000-000000000000&interactionCount=1&landingPath=NotLandingPage&groups=00000%3A0%2C00000%3A0%2C00000%3A0%2C00000%3A0; OptanonAlertBoxClosed=2023-02-03T10:11:08.683Z\r\n" + "Upgrade-Insecure-Requests: 1\r\n" + "Sec-Fetch-Dest: document\r\n" + "Sec-Fetch-Mode: navigate\r\n" + "Sec-Fetch-Site: none\r\n" + "Sec-Fetch-User: ?1\r\n" + "Pragma: no-cache\r\n" + "Cache-Control: no-cache\r\n" + "\r\n"; + + { + http_request p(locale); + Assert::IsTrue(p.match(request)); + Assert::AreEqual((size_t)0, p.interval.start); + Assert::AreEqual((size_t)14, p.interval.end); + Assert::AreEqual((size_t)0, p.verb.start); + Assert::AreEqual((size_t)3, p.verb.end); + Assert::AreEqual((size_t)4, p.url.interval.start); + Assert::AreEqual((size_t)5, p.url.interval.end); + Assert::AreEqual((size_t)6, p.protocol.interval.start); + Assert::AreEqual((size_t)12, p.protocol.interval.end); + Assert::AreEqual((uint16_t)0x200, p.protocol.version); + } + + { + list hdrs; + size_t offset = 14; + for (;;) { + http_header h; + if (h.match(request, offset)) { + offset = h.interval.end; + hdrs.push_back(std::move(h)); + } + else + break; + } + Assert::AreEqual((size_t)15, hdrs.size()); + http_weighted_collection> langs; + for (const auto& h : hdrs) + if (strnicmp(request + h.name.start, h.name.size(), "Accept-Language", SIZE_MAX, locale) == 0) + langs.insert(request, h.value.start, h.value.end); + Assert::IsTrue(!langs.empty()); + { + const vector control = { + "sl", "en-US", "en", "de-DE", "de" + }; + auto c = control.cbegin(); + auto l = langs.cbegin(); + for (; c != control.cend() && l != langs.cend(); ++c, ++l) + Assert::IsTrue(strnicmp(request + l->value.interval.start, l->value.interval.size(), c->c_str(), c->size(), locale) == 0); + Assert::IsTrue(c == control.cend()); + Assert::IsTrue(l == langs.cend()); + } + } + + //static const char response[] = + // "HTTP/2 200 OK\r\n" + // "cache-control: private\r\n" + // "content-type: text/html; charset=utf-8\r\n" + // "content-encoding: gzip\r\n" + // "strict-transport-security: max-age=15552000\r\n" + // "x-frame-options: SAMEORIGIN\r\n" + // "set-cookie: acct=t=00000000000000000%2f%2f0000%2b0000%2b000&s=00000000000000000000000000000000; expires=Sat, 16 Sep 2023 10:23:00 GMT; domain=.stackoverflow.com; path=/; secure; samesite=none; httponly\r\n" + // "set-cookie: prov_tgt=; expires=Tue, 14 Mar 2023 10:23:00 GMT; domain=.stackoverflow.com; path=/; secure; samesite=none; httponly\r\n" + // "x-request-guid: a6536a49-b473-4c6f-b313-c1e7c0d8f600\r\n" + // "feature-policy: microphone 'none'; speaker 'none'\r\n" + // "content-security-policy: upgrade-insecure-requests; frame-ancestors 'self' https://stackexchange.com\r\n" + // "accept-ranges: bytes\r\n" + // "date: Thu, 16 Mar 2023 10:23:00 GMT\r\n" + // "via: 1.1 varnish\r\n" + // "x-served-by: cache-vie6354-VIE\r\n" + // "x-cache: MISS\r\n" + // "x-cache-hits: 0\r\n" + // "x-timer: S1678962181.533907,VS0,VE144\r\n" + // "vary: Accept-Encoding,Fastly-SSL\r\n" + // "x-dns-prefetch-control: off\r\n" + // "X-Firefox-Spdy: h2\r\n" + // "\r\n"; + } } diff --git a/UnitTests/pch.hpp b/UnitTests/pch.hpp index 0aafb1134..2895583c9 100644 --- a/UnitTests/pch.hpp +++ b/UnitTests/pch.hpp @@ -1,4 +1,4 @@ -/* +/* SPDX-License-Identifier: MIT Copyright © 2023-2024 Amebis */ @@ -39,3 +39,84 @@ #include #include #include + +namespace UnitTests +{ + TEST_CLASS(hash) + { + public: + TEST_METHOD(crc32); + TEST_METHOD(md5); + TEST_METHOD(sha1); + }; + + TEST_CLASS(math) + { + public: + TEST_METHOD(mul); + TEST_METHOD(add); + }; + + TEST_CLASS(parser) + { + public: + TEST_METHOD(wtest); + TEST_METHOD(sgml_test); + TEST_METHOD(http_test); + }; + + TEST_CLASS(pool) + { + public: + TEST_METHOD(test); + }; + + TEST_CLASS(ring) + { + public: + TEST_METHOD(test); + }; + + TEST_CLASS(sgml) + { + public: + TEST_METHOD(sgml2str); + TEST_METHOD(str2sgml); + }; + + TEST_CLASS(stream) + { + public: + TEST_METHOD(async); + TEST_METHOD(replicator); + TEST_METHOD(open_close); + TEST_METHOD(file_stat); + }; + + TEST_CLASS(string) + { + public: + TEST_METHOD(sprintf); + }; + + TEST_CLASS(unicode) + { + public: + TEST_METHOD(str2wstr); + TEST_METHOD(wstr2str); + TEST_METHOD(charset_encoder); + TEST_METHOD(normalize); + }; + + TEST_CLASS(watchdog) + { + public: + TEST_METHOD(test); + }; + + TEST_CLASS(zlib) + { + public: + TEST_METHOD(test); + }; +} diff --git a/UnitTests/pool.cpp b/UnitTests/pool.cpp index e59dba2d6..2eb186272 100644 --- a/UnitTests/pool.cpp +++ b/UnitTests/pool.cpp @@ -12,31 +12,25 @@ using namespace Microsoft::VisualStudio::CppUnitTestFramework; namespace UnitTests { - constexpr size_t pool_capacity = 50; - - TEST_CLASS(pool) + void pool::test() { - public: - TEST_METHOD(test) - { - using worker_t = unique_ptr; - using pool_t = stdex::pool; - pool_t pool; - list workers; - for (auto n = thread::hardware_concurrency(); n--; ) { - workers.push_back(thread([](_Inout_ pool_t& pool) - { - for (size_t n = 10000; n--; ) { - worker_t el = pool.pop(); - if (!el) - el.reset(new int(1)); - pool.push(std::move(el)); - } - }, ref(pool))); - } - - for (auto& w : workers) - w.join(); + using worker_t = unique_ptr; + using pool_t = stdex::pool; + pool_t pool; + list workers; + for (auto n = thread::hardware_concurrency(); n--; ) { + workers.push_back(thread([](_Inout_ pool_t& pool) + { + for (size_t n = 10000; n--; ) { + worker_t el = pool.pop(); + if (!el) + el.reset(new int(1)); + pool.push(std::move(el)); + } + }, ref(pool))); } - }; + + for (auto& w : workers) + w.join(); + } } diff --git a/UnitTests/ring.cpp b/UnitTests/ring.cpp index 35dca3c6f..1f42db7fa 100644 --- a/UnitTests/ring.cpp +++ b/UnitTests/ring.cpp @@ -14,44 +14,40 @@ namespace UnitTests { constexpr size_t ring_capacity = 50; - TEST_CLASS(ring) + void ring::test() { - public: - TEST_METHOD(test) - { - using ring_t = stdex::ring; - ring_t ring; - thread writer([](_Inout_ ring_t& ring) - { - int seed = 0; - for (size_t retries = 1000; retries--;) { - for (auto to_write = static_cast(static_cast(::rand()) * ring_capacity / 5 / RAND_MAX); to_write;) { - int* ptr; size_t num_write; - tie(ptr, num_write) = ring.back(); - if (to_write < num_write) - num_write = to_write; - for (size_t i = 0; i < num_write; i++) - ptr[i] = seed++; - ring.push(num_write); - to_write -= num_write; - } + using ring_t = stdex::ring; + ring_t ring; + thread writer([](_Inout_ ring_t& ring) + { + int seed = 0; + for (size_t retries = 1000; retries--;) { + for (auto to_write = static_cast(static_cast(::rand()) * ring_capacity / 5 / RAND_MAX); to_write;) { + int* ptr; size_t num_write; + tie(ptr, num_write) = ring.back(); + if (to_write < num_write) + num_write = to_write; + for (size_t i = 0; i < num_write; i++) + ptr[i] = seed++; + ring.push(num_write); + to_write -= num_write; } - ring.quit(); - }, ref(ring)); + } + ring.quit(); + }, ref(ring)); - int seed = 0; - for (;;) { - int* ptr; size_t num_read; - tie(ptr, num_read) = ring.front(); - if (!ptr) _Unlikely_ - break; - if (num_read > 7) - num_read = 7; - for (size_t i = 0; i < num_read; ++i) - Assert::AreEqual(seed++, ptr[i]); - ring.pop(num_read); - } - writer.join(); + int seed = 0; + for (;;) { + int* ptr; size_t num_read; + tie(ptr, num_read) = ring.front(); + if (!ptr) _Unlikely_ + break; + if (num_read > 7) + num_read = 7; + for (size_t i = 0; i < num_read; ++i) + Assert::AreEqual(seed++, ptr[i]); + ring.pop(num_read); } - }; + writer.join(); + } } diff --git a/UnitTests/sgml.cpp b/UnitTests/sgml.cpp index ac13a3616..02d3e808c 100644 --- a/UnitTests/sgml.cpp +++ b/UnitTests/sgml.cpp @@ -1,4 +1,4 @@ -/* +/* SPDX-License-Identifier: MIT Copyright © 2023-2024 Amebis */ @@ -12,56 +12,52 @@ using namespace Microsoft::VisualStudio::CppUnitTestFramework; namespace UnitTests { - TEST_CLASS(sgml) + void sgml::sgml2str() { - public: - TEST_METHOD(sgml2str) - { - Assert::AreEqual(L"This is a test.", stdex::sgml2str("This is a test.", SIZE_MAX).c_str()); - Assert::AreEqual(L"Th\u00ed\u0161 i\u22c5 a te\u0073\u0304t.&unknown;😀😅", stdex::sgml2str("Thíš i⋅ a te&smacr;t.&unknown;😀😅", SIZE_MAX).c_str()); - Assert::AreEqual(L"This", stdex::sgml2str("This is a test.", 4).c_str()); - Assert::AreEqual(L"T\u0068\u0301", stdex::sgml2str("T&hacute;is is a test.", 9).c_str()); - Assert::AreEqual(L"T&hac", stdex::sgml2str("T&hacute;is is a test.", 5).c_str()); - Assert::AreEqual(L"The "quoted" & text.", stdex::sgml2str("The "quoted" & text.", SIZE_MAX, stdex::sgml_c).c_str()); + Assert::AreEqual(L"This is a test.", stdex::sgml2str("This is a test.", SIZE_MAX).c_str()); + Assert::AreEqual(L"Th\u00ed\u0161 i\u22c5 a te\u0073\u0304t.&unknown;😀😅", stdex::sgml2str("Thíš i⋅ a te&smacr;t.&unknown;😀😅", SIZE_MAX).c_str()); + Assert::AreEqual(L"This", stdex::sgml2str("This is a test.", 4).c_str()); + Assert::AreEqual(L"T\u0068\u0301", stdex::sgml2str("T&hacute;is is a test.", 9).c_str()); + Assert::AreEqual(L"T&hac", stdex::sgml2str("T&hacute;is is a test.", 5).c_str()); + Assert::AreEqual(L"The "quoted" & text.", stdex::sgml2str("The "quoted" & text.", SIZE_MAX, stdex::sgml_c).c_str()); - stdex::mapping_vector map; - constexpr size_t i = 0; - constexpr size_t j = 0; - stdex::sgml2str("Thíš i⋅ a te&smacr;t.&unknown;😀😅", SIZE_MAX, 0, stdex::mapping(i, j), &map); - Assert::IsTrue(stdex::mapping_vector{ - { i + 2, j + 2 }, - { i + 10, j + 3 }, - { i + 10, j + 3 }, - { i + 18, j + 4 }, - { i + 20, j + 6 }, - { i + 26, j + 7 }, - { i + 27, j + 8 }, - { i + 32, j + 9 }, - { i + 35, j + 12 }, - { i + 42, j + 14 }, - { i + 53, j + 25 }, + stdex::mapping_vector map; + constexpr size_t i = 0; + constexpr size_t j = 0; + stdex::sgml2str("Thíš i⋅ a te&smacr;t.&unknown;😀😅", SIZE_MAX, 0, stdex::mapping(i, j), &map); + Assert::IsTrue(stdex::mapping_vector{ + { i + 2, j + 2 }, + { i + 10, j + 3 }, + { i + 10, j + 3 }, + { i + 18, j + 4 }, + { i + 20, j + 6 }, + { i + 26, j + 7 }, + { i + 27, j + 8 }, + { i + 32, j + 9 }, + { i + 35, j + 12 }, + { i + 42, j + 14 }, + { i + 53, j + 25 }, #ifdef _WIN32 // wchar_t* is UTF-16 - { i + 62, j + 27 }, - { i + 62, j + 27 }, - { i + 71, j + 29 }, + { i + 62, j + 27 }, + { i + 62, j + 27 }, + { i + 71, j + 29 }, #else // wchar_t* is UTF-32 - { i + 62, j + 26 }, - { i + 62, j + 26 }, - { i + 71, j + 27 }, + { i + 62, j + 26 }, + { i + 62, j + 26 }, + { i + 71, j + 27 }, #endif - } == map); - } + } == map); + } - TEST_METHOD(str2sgml) - { - Assert::AreEqual("This is a test.", stdex::str2sgml(L"This is a test.", SIZE_MAX).c_str()); - Assert::AreEqual("Thíš i⋅ a te&smacr;t.&unknown;😀😅", stdex::str2sgml(L"Th\u00ed\u0161 i\u22c5 a te\u0073\u0304t.&unknown;😀😅", SIZE_MAX).c_str()); - Assert::AreEqual("This", stdex::str2sgml(L"This is a test.", 4, 0).c_str()); - Assert::AreEqual("te&smacr;", stdex::str2sgml(L"te\u0073\u0304t", 4, 0).c_str()); - Assert::AreEqual("tes", stdex::str2sgml(L"te\u0073\u0304t", 3, 0).c_str()); - Assert::AreEqual("⌘‰͢", stdex::str2sgml(L"⌘‰͢", SIZE_MAX).c_str()); - Assert::AreEqual("$\"<>&", stdex::str2sgml(L"$\"<>&", SIZE_MAX).c_str()); - Assert::AreEqual("$"<>&", stdex::str2sgml(L"$\"<>&", SIZE_MAX, stdex::sgml_c).c_str()); - } - }; + void sgml::str2sgml() + { + Assert::AreEqual("This is a test.", stdex::str2sgml(L"This is a test.", SIZE_MAX).c_str()); + Assert::AreEqual("Thíš i⋅ a te&smacr;t.&unknown;😀😅", stdex::str2sgml(L"Th\u00ed\u0161 i\u22c5 a te\u0073\u0304t.&unknown;😀😅", SIZE_MAX).c_str()); + Assert::AreEqual("This", stdex::str2sgml(L"This is a test.", 4, 0).c_str()); + Assert::AreEqual("te&smacr;", stdex::str2sgml(L"te\u0073\u0304t", 4, 0).c_str()); + Assert::AreEqual("tes", stdex::str2sgml(L"te\u0073\u0304t", 3, 0).c_str()); + Assert::AreEqual("⌘‰͢", stdex::str2sgml(L"⌘‰͢", SIZE_MAX).c_str()); + Assert::AreEqual("$\"<>&", stdex::str2sgml(L"$\"<>&", SIZE_MAX).c_str()); + Assert::AreEqual("$"<>&", stdex::str2sgml(L"$\"<>&", SIZE_MAX, stdex::sgml_c).c_str()); + } } diff --git a/UnitTests/stream.cpp b/UnitTests/stream.cpp index 26690b2c3..48498e638 100644 --- a/UnitTests/stream.cpp +++ b/UnitTests/stream.cpp @@ -6,154 +6,151 @@ #include "pch.hpp" using namespace std; +using namespace stdex; +using namespace stdex::stream; #ifdef _WIN32 using namespace Microsoft::VisualStudio::CppUnitTestFramework; #endif +static stdex::sstring temp_path() +{ +#ifdef _WIN32 + TCHAR temp_path[MAX_PATH]; + Assert::IsTrue(ExpandEnvironmentStrings(_T("%TEMP%\\"), temp_path, _countof(temp_path)) < MAX_PATH); + return temp_path; +#else + return "/tmp/"; +#endif +} + namespace UnitTests { - TEST_CLASS(stream) + void stream::async() { - public: - TEST_METHOD(async) + constexpr uint32_t total = 1000; + memory_file source(stdex::mul(total, sizeof(uint32_t))); { - constexpr uint32_t total = 1000; - stdex::stream::memory_file source(stdex::mul(total, sizeof(uint32_t))); - { - stdex::stream::async_writer<70> writer(source); - for (uint32_t i = 0; i < total; ++i) { - Assert::IsTrue(writer.ok()); - writer << i; - } + async_writer<70> writer(source); + for (uint32_t i = 0; i < total; ++i) { + Assert::IsTrue(writer.ok()); + writer << i; } - Assert::AreEqual(0, source.seekbeg(0)); - { - stdex::stream::async_reader<50> reader(source); - uint32_t x; - for (uint32_t i = 0; i < total; ++i) { - reader >> x; - Assert::IsTrue(reader.ok()); - Assert::AreEqual(i, x); - } + } + Assert::AreEqual(0, source.seekbeg(0)); + { + async_reader<50> reader(source); + uint32_t x; + for (uint32_t i = 0; i < total; ++i) { reader >> x; - Assert::IsFalse(reader.ok()); + Assert::IsTrue(reader.ok()); + Assert::AreEqual(i, x); + } + reader >> x; + Assert::IsFalse(reader.ok()); + } + } + + void stream::replicator() + { + constexpr uint32_t total = 1000; + + memory_file f1(stdex::mul(total, sizeof(uint32_t))); + + stdex::sstring filename2, filename3; + filename2 = filename3 = temp_path(); + filename2 += _T("stdex-stream-replicator-2.tmp"); + file f2( + filename2.c_str(), + mode_for_reading | mode_for_writing | mode_create | mode_binary); + + filename3 += _T("stdex-stream-replicator-3.tmp"); + cached_file f3( + filename3.c_str(), + mode_for_reading | mode_for_writing | mode_create | mode_binary, + 128); + + { + stdex::stream::replicator writer; + buffer f2_buf(f2, 0, 32); + writer.push_back(&f1); + writer.push_back(&f2_buf); + writer.push_back(&f3); + for (uint32_t i = 0; i < total; ++i) { + Assert::IsTrue(writer.ok()); + writer << i; } } - TEST_METHOD(replicator) + f1.seekbeg(0); + f2.seekbeg(0); + f3.seekbeg(0); { - constexpr uint32_t total = 1000; - - stdex::stream::memory_file f1(stdex::mul(total, sizeof(uint32_t))); - - stdex::sstring filename2, filename3; - filename2 = filename3 = temp_path(); - filename2 += _T("stdex-stream-replicator-2.tmp"); - stdex::stream::file f2( - filename2.c_str(), - stdex::stream::mode_for_reading | stdex::stream::mode_for_writing | stdex::stream::mode_create | stdex::stream::mode_binary); - - filename3 += _T("stdex-stream-replicator-3.tmp"); - stdex::stream::cached_file f3( - filename3.c_str(), - stdex::stream::mode_for_reading | stdex::stream::mode_for_writing | stdex::stream::mode_create | stdex::stream::mode_binary, - 128); - - { - stdex::stream::replicator writer; - stdex::stream::buffer f2_buf(f2, 0, 32); - writer.push_back(&f1); - writer.push_back(&f2_buf); - writer.push_back(&f3); - for (uint32_t i = 0; i < total; ++i) { - Assert::IsTrue(writer.ok()); - writer << i; - } - } - - f1.seekbeg(0); - f2.seekbeg(0); - f3.seekbeg(0); - { - stdex::stream::buffer f2_buf(f2, 64, 0); - uint32_t x; - for (uint32_t i = 0; i < total; ++i) { - f1 >> x; - Assert::IsTrue(f1.ok()); - Assert::AreEqual(i, x); - f2_buf >> x; - Assert::IsTrue(f2_buf.ok()); - Assert::AreEqual(i, x); - f3 >> x; - Assert::IsTrue(f3.ok()); - Assert::AreEqual(i, x); - } + buffer f2_buf(f2, 64, 0); + uint32_t x; + for (uint32_t i = 0; i < total; ++i) { f1 >> x; - Assert::IsFalse(f1.ok()); + Assert::IsTrue(f1.ok()); + Assert::AreEqual(i, x); f2_buf >> x; - Assert::IsFalse(f2_buf.ok()); + Assert::IsTrue(f2_buf.ok()); + Assert::AreEqual(i, x); f3 >> x; - Assert::IsFalse(f3.ok()); + Assert::IsTrue(f3.ok()); + Assert::AreEqual(i, x); } - - f2.close(); - std::filesystem::remove(filename2); - f3.close(); - std::filesystem::remove(filename3); + f1 >> x; + Assert::IsFalse(f1.ok()); + f2_buf >> x; + Assert::IsFalse(f2_buf.ok()); + f3 >> x; + Assert::IsFalse(f3.ok()); } - TEST_METHOD(open_close) - { - stdex::stream::cached_file dat(stdex::invalid_handle, stdex::stream::state_t::fail, 4096); - const stdex::sstring filepath = temp_path(); - constexpr uint32_t count = 3; - stdex::sstring filename[count]; - stdex::stream::fpos_t start[count]; - for (uint32_t i = 0; i < count; ++i) { - filename[i] = filepath + stdex::sprintf(_T("stdex-stream-open_close%u.tmp"), NULL, i); - dat.open(filename[i].c_str(), stdex::stream::mode_for_reading | stdex::stream::mode_for_writing | stdex::stream::share_none | stdex::stream::mode_preserve_existing | stdex::stream::mode_binary); + f2.close(); + std::filesystem::remove(filename2); + f3.close(); + std::filesystem::remove(filename3); + } + + void stream::open_close() + { + cached_file dat(stdex::invalid_handle, state_t::fail, 4096); + const stdex::sstring filepath = temp_path(); + constexpr uint32_t count = 3; + stdex::sstring filename[count]; + stdex::stream::fpos_t start[count]; + for (uint32_t i = 0; i < count; ++i) { + filename[i] = filepath + stdex::sprintf(_T("stdex-stream-open_close%u.tmp"), NULL, i); + dat.open(filename[i].c_str(), mode_for_reading | mode_for_writing | share_none | mode_preserve_existing | mode_binary); + Assert::IsTrue(dat.ok()); + start[i] = dat.tell(); + Assert::AreNotEqual(fpos_max, start[i]); + for (uint32_t j = 0; j < 31 + 11 * i; ++j) { + dat << j * count + i; Assert::IsTrue(dat.ok()); - start[i] = dat.tell(); - Assert::AreNotEqual(stdex::stream::fpos_max, start[i]); - for (uint32_t j = 0; j < 31 + 11 * i; ++j) { - dat << j * count + i; - Assert::IsTrue(dat.ok()); - } - dat.close(); - } - for (uint32_t i = 0; i < count; ++i) { - dat.open(filename[i].c_str(), stdex::stream::mode_for_reading | stdex::stream::mode_open_existing | stdex::stream::share_none | stdex::stream::mode_binary); - Assert::IsTrue(dat.ok()); - for (;;) { - uint32_t x; - dat >> x; - if (!dat.ok()) - break; - Assert::AreEqual(i, x % count); - } } dat.close(); - for (uint32_t i = 0; i < count; ++i) - std::filesystem::remove(filename[i]); } + for (uint32_t i = 0; i < count; ++i) { + dat.open(filename[i].c_str(), mode_for_reading | mode_open_existing | share_none | mode_binary); + Assert::IsTrue(dat.ok()); + for (;;) { + uint32_t x; + dat >> x; + if (!dat.ok()) + break; + Assert::AreEqual(i, x % count); + } + } + dat.close(); + for (uint32_t i = 0; i < count; ++i) + std::filesystem::remove(filename[i]); + } - TEST_METHOD(file_stat) - { - stdex::sstring path(temp_path()); - Assert::IsTrue(stdex::stream::file::exists(path)); - Assert::IsFalse(stdex::stream::file::readonly(path)); - } - - protected: - static stdex::sstring temp_path() - { -#ifdef _WIN32 - TCHAR temp_path[MAX_PATH]; - Assert::IsTrue(ExpandEnvironmentStrings(_T("%TEMP%\\"), temp_path, _countof(temp_path)) < MAX_PATH); - return temp_path; -#else - return "/tmp/"; -#endif - } - }; + void stream::file_stat() + { + stdex::sstring path(temp_path()); + Assert::IsTrue(file::exists(path)); + Assert::IsFalse(file::readonly(path)); + } } diff --git a/UnitTests/string.cpp b/UnitTests/string.cpp index ab2612c19..3485645e6 100644 --- a/UnitTests/string.cpp +++ b/UnitTests/string.cpp @@ -12,31 +12,27 @@ using namespace Microsoft::VisualStudio::CppUnitTestFramework; namespace UnitTests { - TEST_CLASS(string) + void string::sprintf() { - public: - TEST_METHOD(sprintf) - { - stdex::locale locale(stdex::create_locale(LC_ALL, "en_US.UTF-8")); + stdex::locale locale(stdex::create_locale(LC_ALL, "en_US.UTF-8")); - Assert::AreEqual(L"This is a test.", stdex::sprintf(L"This is %ls.", locale, L"a test").c_str()); - Assert::AreEqual(15, stdex::sprintf(L"This is %ls.", locale, L"a test").size()); - Assert::AreEqual("This is a test.", stdex::sprintf("This is %s.", locale, "a test").c_str()); - Assert::AreEqual(15, stdex::sprintf("This is %s.", locale, "a test").size()); + Assert::AreEqual(L"This is a test.", stdex::sprintf(L"This is %ls.", locale, L"a test").c_str()); + Assert::AreEqual(15, stdex::sprintf(L"This is %ls.", locale, L"a test").size()); + Assert::AreEqual("This is a test.", stdex::sprintf("This is %s.", locale, "a test").c_str()); + Assert::AreEqual(15, stdex::sprintf("This is %s.", locale, "a test").size()); - Assert::AreEqual(L"This is a 🐔Test🐮.", stdex::sprintf(L"This is %ls.", locale, L"a 🐔Test🐮").c_str()); - Assert::AreEqual("This is a 🐔Test🐮.", stdex::sprintf("This is %s.", locale, "a 🐔Test🐮").c_str()); + Assert::AreEqual(L"This is a 🐔Test🐮.", stdex::sprintf(L"This is %ls.", locale, L"a 🐔Test🐮").c_str()); + Assert::AreEqual("This is a 🐔Test🐮.", stdex::sprintf("This is %s.", locale, "a 🐔Test🐮").c_str()); - wstring wstr; - std::string str; - for (size_t i = 0; i < 200; i++) { - wstr += L"🐔Test🐮\r\n"; - str += "🐔Test🐮\r\n"; - } - Assert::AreEqual(wstr.c_str(), stdex::sprintf(L"%ls", locale, wstr.data()).c_str()); - Assert::AreEqual(wstr.size(), stdex::sprintf(L"%ls", locale, wstr.data()).size()); - Assert::AreEqual(str.c_str(), stdex::sprintf("%s", locale, str.data()).c_str()); - Assert::AreEqual(str.size(), stdex::sprintf("%s", locale, str.data()).size()); + wstring wstr; + std::string str; + for (size_t i = 0; i < 200; i++) { + wstr += L"🐔Test🐮\r\n"; + str += "🐔Test🐮\r\n"; } - }; + Assert::AreEqual(wstr.c_str(), stdex::sprintf(L"%ls", locale, wstr.data()).c_str()); + Assert::AreEqual(wstr.size(), stdex::sprintf(L"%ls", locale, wstr.data()).size()); + Assert::AreEqual(str.c_str(), stdex::sprintf("%s", locale, str.data()).c_str()); + Assert::AreEqual(str.size(), stdex::sprintf("%s", locale, str.data()).size()); + } } diff --git a/UnitTests/unicode.cpp b/UnitTests/unicode.cpp index a0200ad7b..f37e29b90 100644 --- a/UnitTests/unicode.cpp +++ b/UnitTests/unicode.cpp @@ -1,4 +1,4 @@ -/* +/* SPDX-License-Identifier: MIT Copyright © 2023-2024 Amebis */ @@ -16,91 +16,87 @@ using namespace Microsoft::VisualStudio::CppUnitTestFramework; namespace UnitTests { - TEST_CLASS(unicode) + void unicode::str2wstr() { - public: - TEST_METHOD(str2wstr) - { - Assert::AreEqual( - L"This is a test.", - stdex::str2wstr("This is a test.", stdex::charset_id::utf8).c_str()); - Assert::AreEqual( - L"Th\u00ed\u0161 i\u22c5 a te\u0073\u0304t. 😀😅", - stdex::str2wstr("Thíš i⋅ a tes̄t. 😀😅", stdex::charset_id::utf8).c_str()); - std::string src; - std::wstring dst; - for (size_t i = 0; i < 2000; i++) { - src += "🐔Test🐮\r\n"; - dst += L"🐔Test🐮\r\n"; - } - Assert::AreEqual(dst.c_str(), stdex::str2wstr(src, stdex::charset_id::utf8).c_str()); - Assert::AreEqual( - L"", - stdex::str2wstr("test", 0, stdex::charset_id::utf8).c_str()); - Assert::AreEqual( - L"", - stdex::str2wstr(nullptr, 0, stdex::charset_id::utf8).c_str()); + Assert::AreEqual( + L"This is a test.", + stdex::str2wstr("This is a test.", stdex::charset_id::utf8).c_str()); + Assert::AreEqual( + L"Th\u00ed\u0161 i\u22c5 a te\u0073\u0304t. 😀😅", + stdex::str2wstr("Thíš i⋅ a tes̄t. 😀😅", stdex::charset_id::utf8).c_str()); + std::string src; + std::wstring dst; + for (size_t i = 0; i < 2000; i++) { + src += "🐔Test🐮\r\n"; + dst += L"🐔Test🐮\r\n"; } + Assert::AreEqual(dst.c_str(), stdex::str2wstr(src, stdex::charset_id::utf8).c_str()); + Assert::AreEqual( + L"", + stdex::str2wstr("test", 0, stdex::charset_id::utf8).c_str()); + Assert::AreEqual( + L"", + stdex::str2wstr(nullptr, 0, stdex::charset_id::utf8).c_str()); + } - TEST_METHOD(wstr2str) - { - Assert::AreEqual( - "This is a test.", - stdex::wstr2str(L"This is a test.", stdex::charset_id::utf8).c_str()); - Assert::AreEqual( - "Th\xc3\xad\xc5\xa1 i\xe2\x8b\x85 a tes\xcc\x84t. \xf0\x9f\x98\x80\xf0\x9f\x98\x85", - stdex::wstr2str(L"Thíš i⋅ a tes̄t. 😀😅", stdex::charset_id::utf8).c_str()); - std::wstring src; - std::string dst; - for (size_t i = 0; i < 2000; i++) { - src += L"🐔Test🐮\r\n"; - dst += "🐔Test🐮\r\n"; - } - Assert::AreEqual(dst.c_str(), stdex::wstr2str(src, stdex::charset_id::utf8).c_str()); - Assert::AreEqual( - "", - stdex::wstr2str(L"test", 0, stdex::charset_id::utf8).c_str()); - Assert::AreEqual( - "", - stdex::wstr2str(nullptr, 0, stdex::charset_id::utf8).c_str()); + void unicode::wstr2str() + { + Assert::AreEqual( + "This is a test.", + stdex::wstr2str(L"This is a test.", stdex::charset_id::utf8).c_str()); + Assert::AreEqual( + "Th\xc3\xad\xc5\xa1 i\xe2\x8b\x85 a tes\xcc\x84t. \xf0\x9f\x98\x80\xf0\x9f\x98\x85", + stdex::wstr2str(L"Thíš i⋅ a tes̄t. 😀😅", stdex::charset_id::utf8).c_str()); + std::wstring src; + std::string dst; + for (size_t i = 0; i < 2000; i++) { + src += L"🐔Test🐮\r\n"; + dst += "🐔Test🐮\r\n"; } + Assert::AreEqual(dst.c_str(), stdex::wstr2str(src, stdex::charset_id::utf8).c_str()); + Assert::AreEqual( + "", + stdex::wstr2str(L"test", 0, stdex::charset_id::utf8).c_str()); + Assert::AreEqual( + "", + stdex::wstr2str(nullptr, 0, stdex::charset_id::utf8).c_str()); + } - TEST_METHOD(charset_encoder) - { - stdex::charset_encoder win1250_to_utf8(stdex::charset_id::windows1250, stdex::charset_id::utf8); + void unicode::charset_encoder() + { + stdex::charset_encoder win1250_to_utf8(stdex::charset_id::windows1250, stdex::charset_id::utf8); - Assert::AreEqual( - "This is a test.", - win1250_to_utf8.convert("This is a test.").c_str()); - Assert::AreEqual( - "Thíš i· a teşt.", - win1250_to_utf8.convert("Th\xed\x9a i\xb7 a te\xbat.").c_str()); - std::string src, dst; - for (size_t i = 0; i < 1000; i++) { - src += "V ko\x9eu\x9a\xe8ku zlobnega mizarja stopiclja fant in kli\xe8" "e 0123456789.\r\n"; - dst += "V kožuščku zlobnega mizarja stopiclja fant in kliče 0123456789.\r\n"; - } - Assert::AreEqual(dst.c_str(), win1250_to_utf8.convert(src).c_str()); - Assert::AreEqual( - "", - win1250_to_utf8.convert("test", 0).c_str()); - Assert::AreEqual( - "", - win1250_to_utf8.convert(nullptr, 0).c_str()); + Assert::AreEqual( + "This is a test.", + win1250_to_utf8.convert("This is a test.").c_str()); + Assert::AreEqual( + "Thíš i· a teşt.", + win1250_to_utf8.convert("Th\xed\x9a i\xb7 a te\xbat.").c_str()); + std::string src, dst; + for (size_t i = 0; i < 1000; i++) { + src += "V ko\x9eu\x9a\xe8ku zlobnega mizarja stopiclja fant in kli\xe8" "e 0123456789.\r\n"; + dst += "V kožuščku zlobnega mizarja stopiclja fant in kliče 0123456789.\r\n"; } + Assert::AreEqual(dst.c_str(), win1250_to_utf8.convert(src).c_str()); + Assert::AreEqual( + "", + win1250_to_utf8.convert("test", 0).c_str()); + Assert::AreEqual( + "", + win1250_to_utf8.convert(nullptr, 0).c_str()); + } - TEST_METHOD(normalize) - { + void unicode::normalize() + { #ifdef _WIN32 - Assert::AreEqual( - L"tést", - stdex::normalize(L"tést").c_str()); - Assert::AreEqual( - L"", - stdex::normalize(nullptr, 0).c_str()); + Assert::AreEqual( + L"tést", + stdex::normalize(L"tést").c_str()); + Assert::AreEqual( + L"", + stdex::normalize(nullptr, 0).c_str()); #endif - } - }; + } } #ifdef __GNUC__ diff --git a/UnitTests/watchdog.cpp b/UnitTests/watchdog.cpp index d3ea30c52..a0a2d1e1c 100644 --- a/UnitTests/watchdog.cpp +++ b/UnitTests/watchdog.cpp @@ -1,4 +1,4 @@ -/* +/* SPDX-License-Identifier: MIT Copyright © 2023-2024 Amebis */ @@ -12,21 +12,17 @@ using namespace Microsoft::VisualStudio::CppUnitTestFramework; namespace UnitTests { - TEST_CLASS(watchdog) + void watchdog::test() { - public: - TEST_METHOD(test) - { - volatile bool wd_called = false; - stdex::watchdog wd( - std::chrono::milliseconds(100), [&] { wd_called = true; }); - for (int i = 0; i < 100; ++i) { - std::this_thread::sleep_for(std::chrono::milliseconds(10)); - Assert::IsFalse(wd_called); - wd.reset(); - } - std::this_thread::sleep_for(std::chrono::milliseconds(300)); - Assert::IsTrue(wd_called); + volatile bool wd_called = false; + stdex::watchdog wd( + std::chrono::milliseconds(100), [&] { wd_called = true; }); + for (int i = 0; i < 100; ++i) { + std::this_thread::sleep_for(std::chrono::milliseconds(10)); + Assert::IsFalse(wd_called); + wd.reset(); } - }; -} \ No newline at end of file + std::this_thread::sleep_for(std::chrono::milliseconds(300)); + Assert::IsTrue(wd_called); + } +} diff --git a/UnitTests/zlib.cpp b/UnitTests/zlib.cpp index 505112781..119688296 100644 --- a/UnitTests/zlib.cpp +++ b/UnitTests/zlib.cpp @@ -12,29 +12,25 @@ using namespace Microsoft::VisualStudio::CppUnitTestFramework; namespace UnitTests { - TEST_CLASS(zlib) + void zlib::test() { - public: - TEST_METHOD(test) + static const char inflated[] = "This is a test."; + stdex::stream::memory_file dat_deflated; { - static const char inflated[] = "This is a test."; - stdex::stream::memory_file dat_deflated; - { - stdex::zlib_writer zlib(dat_deflated, 9, 4); - zlib.write(inflated, sizeof(inflated) - sizeof(*inflated)); - } - static const uint8_t deflated[] = { 0x78, 0xda, 0x0b, 0xc9, 0xc8, 0x2c, 0x56, 0x00, 0xa2, 0x44, 0x85, 0x92, 0xd4, 0xe2, 0x12, 0x3d, 0x00, 0x29, 0x97, 0x05, 0x24 }; - Assert::AreEqual(sizeof(deflated), dat_deflated.size()); - Assert::AreEqual(0, memcmp(deflated, dat_deflated.data(), sizeof(deflated))); - - dat_deflated.seekbeg(0); - stdex::stream::memory_file dat_inflated; - { - stdex::zlib_reader zlib(dat_deflated, 3); - dat_inflated.write_stream(zlib); - } - Assert::AreEqual(sizeof(inflated) - sizeof(*inflated), dat_inflated.size()); - Assert::AreEqual(0, memcmp(inflated, dat_inflated.data(), sizeof(inflated) - sizeof(*inflated))); + stdex::zlib_writer zlib(dat_deflated, 9, 4); + zlib.write(inflated, sizeof(inflated) - sizeof(*inflated)); } - }; + static const uint8_t deflated[] = { 0x78, 0xda, 0x0b, 0xc9, 0xc8, 0x2c, 0x56, 0x00, 0xa2, 0x44, 0x85, 0x92, 0xd4, 0xe2, 0x12, 0x3d, 0x00, 0x29, 0x97, 0x05, 0x24 }; + Assert::AreEqual(sizeof(deflated), dat_deflated.size()); + Assert::AreEqual(0, memcmp(deflated, dat_deflated.data(), sizeof(deflated))); + + dat_deflated.seekbeg(0); + stdex::stream::memory_file dat_inflated; + { + stdex::zlib_reader zlib(dat_deflated, 3); + dat_inflated.write_stream(zlib); + } + Assert::AreEqual(sizeof(inflated) - sizeof(*inflated), dat_inflated.size()); + Assert::AreEqual(0, memcmp(inflated, dat_inflated.data(), sizeof(inflated) - sizeof(*inflated))); + } }