aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorDan Engelbrecht <[email protected]>2024-03-14 16:33:17 +0100
committerGitHub Enterprise <[email protected]>2024-03-14 16:33:17 +0100
commit45bfc721dd049193abf3b2be2aa7b097466ddbe9 (patch)
treeabb6cf119aa148972aabad730ed384c115177cf1 /src
parentchange code owners for Enterprise github user names (#7) (diff)
downloadzen-45bfc721dd049193abf3b2be2aa7b097466ddbe9.tar.xz
zen-45bfc721dd049193abf3b2be2aa7b097466ddbe9.zip
clean up test linking (#4)
- Improvement: Add zenhttp-test and zenutil-test - Improvement: Moved cachepolicy test to cachepolicy.cpp - Improvement: Renamed cachestore tests from z$ to cachestore - Improvement: Moved test linking so test for a lib is linked by <lib>-test - Improvement: Removed HttpRequestParseRelativeUri in httpstructuredcache.cpp and use the one in cacherequests.h instead
Diffstat (limited to 'src')
-rw-r--r--src/zencore-test/zencore-test.cpp11
-rw-r--r--src/zenhttp-test/xmake.lua15
-rw-r--r--src/zenhttp-test/zenhttp-test.cpp34
-rw-r--r--src/zennet-test/zennet-test.cpp24
-rw-r--r--src/zennet-test/zennet-test.h5
-rw-r--r--src/zenserver-test/cachepolicy-tests.cpp153
-rw-r--r--src/zenserver-test/zenserver-test.cpp21
-rw-r--r--src/zenserver/cache/httpstructuredcache.cpp280
-rw-r--r--src/zenserver/cache/httpstructuredcache.h2
-rw-r--r--src/zenserver/main.cpp10
-rw-r--r--src/zenserver/zenserver.cpp10
-rw-r--r--src/zenserver/zenserver.h2
-rw-r--r--src/zenstore-test/zenstore-test.cpp16
-rw-r--r--src/zenstore/cache/cacherpc.cpp52
-rw-r--r--src/zenstore/cache/structuredcachestore.cpp20
-rw-r--r--src/zenstore/zenstore.cpp2
-rw-r--r--src/zenutil-test/xmake.lua9
-rw-r--r--src/zenutil-test/zenutil-test.cpp34
-rw-r--r--src/zenutil/cache/cachepolicy.cpp144
-rw-r--r--src/zenutil/cache/cacherequests.cpp189
-rw-r--r--src/zenutil/include/zenutil/cache/cachepolicy.h2
-rw-r--r--src/zenutil/include/zenutil/cache/cacherequests.h6
-rw-r--r--src/zenutil/zenutil.cpp3
23 files changed, 412 insertions, 632 deletions
diff --git a/src/zencore-test/zencore-test.cpp b/src/zencore-test/zencore-test.cpp
index 53413fb25..64df746e4 100644
--- a/src/zencore-test/zencore-test.cpp
+++ b/src/zencore-test/zencore-test.cpp
@@ -3,9 +3,16 @@
// zencore-test.cpp : Defines the entry point for the console application.
//
+#include <zencore/filesystem.h>
#include <zencore/logging.h>
#include <zencore/zencore.h>
+#if ZEN_USE_MIMALLOC
+ZEN_THIRD_PARTY_INCLUDES_START
+# include <mimalloc-new-delete.h>
+ZEN_THIRD_PARTY_INCLUDES_END
+#endif
+
#if ZEN_WITH_TESTS
# define ZEN_TEST_WITH_RUNNER 1
# include <zencore/testing.h>
@@ -14,10 +21,14 @@
int
main([[maybe_unused]] int argc, [[maybe_unused]] char* argv[])
{
+#if ZEN_USE_MIMALLOC
+ mi_version();
+#endif
#if ZEN_WITH_TESTS
zen::zencore_forcelinktests();
zen::logging::InitializeLogging();
+ zen::MaximizeOpenFileCount();
return ZEN_RUN_TESTS(argc, argv);
#else
diff --git a/src/zenhttp-test/xmake.lua b/src/zenhttp-test/xmake.lua
new file mode 100644
index 000000000..a6163e506
--- /dev/null
+++ b/src/zenhttp-test/xmake.lua
@@ -0,0 +1,15 @@
+-- Copyright Epic Games, Inc. All Rights Reserved.
+
+target("zenhttp-test")
+ set_kind("binary")
+ set_group("tests")
+ add_headerfiles("**.h")
+ add_files("*.cpp")
+ add_deps("zenhttp", "zencore")
+ add_packages("vcpkg::doctest")
+
+ if is_plat("macosx") then
+ add_ldflags("-framework CoreFoundation")
+ add_ldflags("-framework Security")
+ add_ldflags("-framework SystemConfiguration")
+ end
diff --git a/src/zenhttp-test/zenhttp-test.cpp b/src/zenhttp-test/zenhttp-test.cpp
new file mode 100644
index 000000000..440e85a9f
--- /dev/null
+++ b/src/zenhttp-test/zenhttp-test.cpp
@@ -0,0 +1,34 @@
+// Copyright Epic Games, Inc. All Rights Reserved.
+
+#include <zencore/filesystem.h>
+#include <zencore/logging.h>
+#include <zenhttp/zenhttp.h>
+
+#if ZEN_USE_MIMALLOC
+ZEN_THIRD_PARTY_INCLUDES_START
+# include <mimalloc-new-delete.h>
+ZEN_THIRD_PARTY_INCLUDES_END
+#endif
+
+#if ZEN_WITH_TESTS
+# define ZEN_TEST_WITH_RUNNER 1
+# include <zencore/testing.h>
+#endif
+
+int
+main([[maybe_unused]] int argc, [[maybe_unused]] char* argv[])
+{
+#if ZEN_USE_MIMALLOC
+ mi_version();
+#endif
+#if ZEN_WITH_TESTS
+ zen::zenhttp_forcelinktests();
+
+ zen::logging::InitializeLogging();
+ zen::MaximizeOpenFileCount();
+
+ return ZEN_RUN_TESTS(argc, argv);
+#else
+ return 0;
+#endif
+}
diff --git a/src/zennet-test/zennet-test.cpp b/src/zennet-test/zennet-test.cpp
index b133f246c..f7f54e6ad 100644
--- a/src/zennet-test/zennet-test.cpp
+++ b/src/zennet-test/zennet-test.cpp
@@ -1,49 +1,31 @@
// Copyright Epic Games, Inc. All Rights Reserved.
-#include "zennet-test.h"
-#include <zencore/fmtutils.h>
+#include <zencore/filesystem.h>
#include <zencore/logging.h>
-#include <zencore/timer.h>
#include <zennet/zennet.h>
-#include <zenutil/zenserverprocess.h>
#if ZEN_USE_MIMALLOC
ZEN_THIRD_PARTY_INCLUDES_START
-# include <mimalloc.h>
+# include <mimalloc-new-delete.h>
ZEN_THIRD_PARTY_INCLUDES_END
#endif
-//////////////////////////////////////////////////////////////////////////
-
#if ZEN_WITH_TESTS
# define ZEN_TEST_WITH_RUNNER 1
# include <zencore/testing.h>
#endif
-//////////////////////////////////////////////////////////////////////////
-
-using namespace std::literals;
-
-zen::ZenServerEnvironment TestEnv;
-
int
main([[maybe_unused]] int argc, [[maybe_unused]] char** argv)
{
#if ZEN_USE_MIMALLOC
mi_version();
#endif
-
#if ZEN_WITH_TESTS
zen::zennet_forcelinktests();
zen::logging::InitializeLogging();
-
- std::filesystem::path ProgramBaseDir = std::filesystem::path(argv[0]).parent_path();
- std::filesystem::path TestBaseDir = ProgramBaseDir.parent_path().parent_path() / ".test";
-
- TestEnv.InitializeForTest(ProgramBaseDir, TestBaseDir);
-
- ZEN_INFO("Running tests...(base dir: '{}')", TestBaseDir);
+ zen::MaximizeOpenFileCount();
return ZEN_RUN_TESTS(argc, argv);
#else
diff --git a/src/zennet-test/zennet-test.h b/src/zennet-test/zennet-test.h
deleted file mode 100644
index f84fd52ce..000000000
--- a/src/zennet-test/zennet-test.h
+++ /dev/null
@@ -1,5 +0,0 @@
-// Copyright Epic Games, Inc. All Rights Reserved.
-
-#include <zenutil/zenserverprocess.h>
-
-extern zen::ZenServerEnvironment TestEnv;
diff --git a/src/zenserver-test/cachepolicy-tests.cpp b/src/zenserver-test/cachepolicy-tests.cpp
deleted file mode 100644
index 79d78e522..000000000
--- a/src/zenserver-test/cachepolicy-tests.cpp
+++ /dev/null
@@ -1,153 +0,0 @@
-// Copyright Epic Games, Inc. All Rights Reserved.
-
-#include <zencore/zencore.h>
-
-#if ZEN_WITH_TESTS
-
-# include <zencore/compactbinary.h>
-# include <zencore/compactbinarybuilder.h>
-# include <zencore/string.h>
-# include <zencore/testing.h>
-# include <zencore/uid.h>
-# include <zenutil/cache/cachepolicy.h>
-
-namespace zen::tests {
-
-using namespace std::literals;
-
-TEST_CASE("cachepolicy")
-{
- SUBCASE("atomics serialization")
- {
- CachePolicy SomeAtomics[] = {CachePolicy::None,
- CachePolicy::QueryLocal,
- CachePolicy::StoreRemote,
- CachePolicy::SkipData,
- CachePolicy::KeepAlive};
- for (CachePolicy Atomic : SomeAtomics)
- {
- CHECK(ParseCachePolicy(WriteToString<128>(Atomic)) == Atomic);
- }
- // Also verify that we ignore unrecognized bits
- for (CachePolicy Atomic : SomeAtomics)
- {
- CHECK(ParseCachePolicy(WriteToString<128>(Atomic | (CachePolicy)0x10000000)) == Atomic);
- }
- }
- SUBCASE("aliases serialization")
- {
- CachePolicy SomeAliases[] = {CachePolicy::Query, CachePolicy::Local};
- for (CachePolicy Alias : SomeAliases)
- {
- CHECK(ParseCachePolicy(WriteToString<128>(Alias)) == Alias);
- }
- // Also verify that we ignore unrecognized bits
- for (CachePolicy Alias : SomeAliases)
- {
- CHECK(ParseCachePolicy(WriteToString<128>(Alias | (CachePolicy)0x10000000)) == Alias);
- }
- }
- SUBCASE("aliases take priority over atomics")
- {
- CHECK(WriteToString<128>(CachePolicy::Default).ToView() == "Default"sv);
- CHECK(WriteToString<128>(CachePolicy::Query).ToView() == "Query"sv);
- CHECK(WriteToString<128>(CachePolicy::Local).ToView() == "Local"sv);
- }
- SUBCASE("policies requiring multiple strings work")
- {
- char Delimiter = ',';
- CachePolicy Combination = CachePolicy::SkipData | CachePolicy::QueryLocal;
- CHECK(WriteToString<128>(Combination).ToView().find(Delimiter) != std::string_view::npos);
- CHECK(ParseCachePolicy(WriteToString<128>(Combination)) == Combination);
- }
- SUBCASE("parsing invalid text")
- {
- CHECK(ParseCachePolicy(",,,") == CachePolicy::None);
- CHECK(ParseCachePolicy("fee,fie,foo,fum") == CachePolicy::None);
- CHECK(ParseCachePolicy("fee,KeepAlive,foo,fum") == CachePolicy::KeepAlive);
- }
-}
-
-TEST_CASE("cacherecordpolicy")
-{
- SUBCASE("policy with no values")
- {
- CachePolicy Policy = CachePolicy::SkipData | CachePolicy::QueryLocal | CachePolicy::PartialRecord;
- CachePolicy ValuePolicy = Policy & CacheValuePolicy::PolicyMask;
- CacheRecordPolicy RecordPolicy;
- CacheRecordPolicyBuilder Builder(Policy);
- RecordPolicy = Builder.Build();
- SUBCASE("construct")
- {
- CHECK(RecordPolicy.IsUniform());
- CHECK(RecordPolicy.GetRecordPolicy() == Policy);
- CHECK(RecordPolicy.GetBasePolicy() == Policy);
- CHECK(RecordPolicy.GetValuePolicy(Oid::NewOid()) == ValuePolicy);
- CHECK(RecordPolicy.GetValuePolicies().size() == 0);
- }
- SUBCASE("saveload")
- {
- CbWriter Writer;
- RecordPolicy.Save(Writer);
- CbObject Saved = Writer.Save()->AsObject();
- CacheRecordPolicy Loaded = CacheRecordPolicy::Load(Saved).Get();
- CHECK(Loaded.IsUniform());
- CHECK(Loaded.GetRecordPolicy() == Policy);
- CHECK(Loaded.GetBasePolicy() == Policy);
- CHECK(Loaded.GetValuePolicy(Oid::NewOid()) == ValuePolicy);
- CHECK(Loaded.GetValuePolicies().size() == 0);
- }
- }
-
- SUBCASE("policy with values")
- {
- CachePolicy DefaultPolicy = CachePolicy::StoreRemote | CachePolicy::QueryLocal | CachePolicy::PartialRecord;
- CachePolicy DefaultValuePolicy = DefaultPolicy & CacheValuePolicy::PolicyMask;
- CachePolicy PartialOverlap = CachePolicy::StoreRemote;
- CachePolicy NoOverlap = CachePolicy::QueryRemote;
- CachePolicy UnionPolicy = DefaultPolicy | PartialOverlap | NoOverlap | CachePolicy::PartialRecord;
-
- CacheRecordPolicy RecordPolicy;
- CacheRecordPolicyBuilder Builder(DefaultPolicy);
- Oid PartialOid = Oid::NewOid();
- Oid NoOverlapOid = Oid::NewOid();
- Oid OtherOid = Oid::NewOid();
- Builder.AddValuePolicy(PartialOid, PartialOverlap);
- Builder.AddValuePolicy(NoOverlapOid, NoOverlap);
- RecordPolicy = Builder.Build();
- SUBCASE("construct")
- {
- CHECK(!RecordPolicy.IsUniform());
- CHECK(RecordPolicy.GetRecordPolicy() == UnionPolicy);
- CHECK(RecordPolicy.GetBasePolicy() == DefaultPolicy);
- CHECK(RecordPolicy.GetValuePolicy(PartialOid) == PartialOverlap);
- CHECK(RecordPolicy.GetValuePolicy(NoOverlapOid) == NoOverlap);
- CHECK(RecordPolicy.GetValuePolicy(OtherOid) == DefaultValuePolicy);
- CHECK(RecordPolicy.GetValuePolicies().size() == 2);
- }
- SUBCASE("saveload")
- {
- CbWriter Writer;
- RecordPolicy.Save(Writer);
- CbObject Saved = Writer.Save()->AsObject();
- CacheRecordPolicy Loaded = CacheRecordPolicy::Load(Saved).Get();
- CHECK(!RecordPolicy.IsUniform());
- CHECK(RecordPolicy.GetRecordPolicy() == UnionPolicy);
- CHECK(RecordPolicy.GetBasePolicy() == DefaultPolicy);
- CHECK(RecordPolicy.GetValuePolicy(PartialOid) == PartialOverlap);
- CHECK(RecordPolicy.GetValuePolicy(NoOverlapOid) == NoOverlap);
- CHECK(RecordPolicy.GetValuePolicy(OtherOid) == DefaultValuePolicy);
- CHECK(RecordPolicy.GetValuePolicies().size() == 2);
- }
- }
-
- SUBCASE("parsing invalid text")
- {
- OptionalCacheRecordPolicy Loaded = CacheRecordPolicy::Load(CbObject());
- CHECK(Loaded.IsNull());
- }
-}
-
-} // namespace zen::tests
-
-#endif
diff --git a/src/zenserver-test/zenserver-test.cpp b/src/zenserver-test/zenserver-test.cpp
index 9074485b6..4a368c992 100644
--- a/src/zenserver-test/zenserver-test.cpp
+++ b/src/zenserver-test/zenserver-test.cpp
@@ -27,12 +27,6 @@
#include <zenutil/packageformat.h>
#include <zenutil/zenserverprocess.h>
-#if ZEN_USE_MIMALLOC
-ZEN_THIRD_PARTY_INCLUDES_START
-# include <mimalloc.h>
-ZEN_THIRD_PARTY_INCLUDES_END
-#endif
-
#include <http_parser.h>
#if ZEN_PLATFORM_WINDOWS
@@ -59,6 +53,12 @@ ZEN_THIRD_PARTY_INCLUDES_END
# include <process.h>
#endif
+#if ZEN_USE_MIMALLOC
+ZEN_THIRD_PARTY_INCLUDES_START
+# include <mimalloc-new-delete.h>
+ZEN_THIRD_PARTY_INCLUDES_END
+#endif
+
//////////////////////////////////////////////////////////////////////////
#include "projectclient.h"
@@ -100,16 +100,11 @@ zen::ZenServerEnvironment TestEnv;
int
main(int argc, char** argv)
{
- using namespace std::literals;
- using namespace zen;
-
# if ZEN_USE_MIMALLOC
mi_version();
# endif
-
- zencore_forcelinktests();
- zenhttp_forcelinktests();
- cacherequests_forcelink();
+ using namespace std::literals;
+ using namespace zen;
zen::logging::InitializeLogging();
diff --git a/src/zenserver/cache/httpstructuredcache.cpp b/src/zenserver/cache/httpstructuredcache.cpp
index 4cf7c9a01..f64b9c5a5 100644
--- a/src/zenserver/cache/httpstructuredcache.cpp
+++ b/src/zenserver/cache/httpstructuredcache.cpp
@@ -39,11 +39,6 @@
#include <cpr/cpr.h>
#include <gsl/gsl-lite.hpp>
-#if ZEN_WITH_TESTS
-# include <zencore/testing.h>
-# include <zencore/testutils.h>
-#endif
-
namespace zen {
using namespace std::literals;
@@ -64,64 +59,6 @@ namespace {
static constinit std::string_view HttpZCacheUtilReplayRecording = "exec$/replay-recording"sv;
static constinit std::string_view HttpZCacheDetailsPrefix = "details$"sv;
- constinit AsciiSet ValidNamespaceNameCharactersSet{"abcdefghijklmnopqrstuvwxyz0123456789-_.ABCDEFGHIJKLMNOPQRSTUVWXYZ"};
- constinit AsciiSet ValidBucketNameCharactersSet{"abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"};
-
- std::optional<std::string> GetValidNamespaceName(std::string_view Name)
- {
- if (Name.empty())
- {
- ZEN_WARN("Namespace is invalid, empty namespace is not allowed");
- return {};
- }
-
- if (Name.length() > 64)
- {
- ZEN_WARN("Namespace '{}' is invalid, length exceeds 64 characters", Name);
- return {};
- }
-
- if (!AsciiSet::HasOnly(Name, ValidNamespaceNameCharactersSet))
- {
- ZEN_WARN("Namespace '{}' is invalid, invalid characters detected", Name);
- return {};
- }
-
- return ToLower(Name);
- }
-
- std::optional<std::string> GetValidBucketName(std::string_view Name)
- {
- if (Name.empty())
- {
- ZEN_WARN("Bucket name is invalid, empty bucket name is not allowed");
- return {};
- }
-
- if (!AsciiSet::HasOnly(Name, ValidBucketNameCharactersSet))
- {
- ZEN_WARN("Bucket name '{}' is invalid, invalid characters detected", Name);
- return {};
- }
-
- return ToLower(Name);
- }
-
- std::optional<IoHash> GetValidIoHash(std::string_view Hash)
- {
- if (Hash.length() != IoHash::StringLength)
- {
- return {};
- }
-
- IoHash KeyHash;
- if (!ParseHexBytes(Hash.data(), Hash.size(), KeyHash.Hash))
- {
- return {};
- }
- return KeyHash;
- }
-
struct HttpRequestData
{
std::optional<std::string> Namespace;
@@ -130,117 +67,6 @@ namespace {
std::optional<IoHash> ValueContentId;
};
- bool HttpRequestParseRelativeUri(std::string_view Key, HttpRequestData& Data)
- {
- std::vector<std::string_view> Tokens;
- uint32_t TokenCount = ForEachStrTok(Key, '/', [&](const std::string_view& Token) {
- Tokens.push_back(Token);
- return true;
- });
-
- switch (TokenCount)
- {
- case 0:
- return true;
- case 1:
- Data.Namespace = GetValidNamespaceName(Tokens[0]);
- return Data.Namespace.has_value();
- case 2:
- {
- std::optional<IoHash> PossibleHashKey = GetValidIoHash(Tokens[1]);
- if (PossibleHashKey.has_value())
- {
- // Legacy bucket/key request
- Data.Bucket = GetValidBucketName(Tokens[0]);
- if (!Data.Bucket.has_value())
- {
- return false;
- }
- Data.HashKey = PossibleHashKey;
- Data.Namespace = ZenCacheStore::DefaultNamespace;
- return true;
- }
- Data.Namespace = GetValidNamespaceName(Tokens[0]);
- if (!Data.Namespace.has_value())
- {
- return false;
- }
- Data.Bucket = GetValidBucketName(Tokens[1]);
- if (!Data.Bucket.has_value())
- {
- return false;
- }
- return true;
- }
- case 3:
- {
- std::optional<IoHash> PossibleHashKey = GetValidIoHash(Tokens[1]);
- if (PossibleHashKey.has_value())
- {
- // Legacy bucket/key/valueid request
- Data.Bucket = GetValidBucketName(Tokens[0]);
- if (!Data.Bucket.has_value())
- {
- return false;
- }
- Data.HashKey = PossibleHashKey;
- Data.ValueContentId = GetValidIoHash(Tokens[2]);
- if (!Data.ValueContentId.has_value())
- {
- return false;
- }
- Data.Namespace = ZenCacheStore::DefaultNamespace;
- return true;
- }
- Data.Namespace = GetValidNamespaceName(Tokens[0]);
- if (!Data.Namespace.has_value())
- {
- return false;
- }
- Data.Bucket = GetValidBucketName(Tokens[1]);
- if (!Data.Bucket.has_value())
- {
- return false;
- }
- Data.HashKey = GetValidIoHash(Tokens[2]);
- if (!Data.HashKey)
- {
- return false;
- }
- return true;
- }
- case 4:
- {
- Data.Namespace = GetValidNamespaceName(Tokens[0]);
- if (!Data.Namespace.has_value())
- {
- return false;
- }
-
- Data.Bucket = GetValidBucketName(Tokens[1]);
- if (!Data.Bucket.has_value())
- {
- return false;
- }
-
- Data.HashKey = GetValidIoHash(Tokens[2]);
- if (!Data.HashKey.has_value())
- {
- return false;
- }
-
- Data.ValueContentId = GetValidIoHash(Tokens[3]);
- if (!Data.ValueContentId.has_value())
- {
- return false;
- }
- return true;
- }
- default:
- return false;
- }
- }
-
} // namespace
//////////////////////////////////////////////////////////////////////////
@@ -614,8 +440,8 @@ HttpStructuredCacheService::HandleRequest(HttpServerRequest& Request)
return;
}
- HttpRequestData RequestData;
- if (!HttpRequestParseRelativeUri(Key, RequestData))
+ cacherequests::HttpRequestData RequestData;
+ if (!cacherequests::HttpRequestParseRelativeUri(Key, ZenCacheStore::DefaultNamespace, RequestData))
{
m_CacheStats.BadRequestCount++;
return Request.WriteResponse(HttpResponseCode::BadRequest); // invalid URL
@@ -1968,106 +1794,4 @@ HttpStructuredCacheService::AreDiskWritesAllowed() const
return (m_DiskWriteBlocker == nullptr || m_DiskWriteBlocker->AreDiskWritesAllowed());
}
-#if ZEN_WITH_TESTS
-
-TEST_CASE("z$service.parse.relative.Uri")
-{
- HttpRequestData RootRequest;
- CHECK(HttpRequestParseRelativeUri("", RootRequest));
- CHECK(!RootRequest.Namespace.has_value());
- CHECK(!RootRequest.Bucket.has_value());
- CHECK(!RootRequest.HashKey.has_value());
- CHECK(!RootRequest.ValueContentId.has_value());
-
- RootRequest = {};
- CHECK(HttpRequestParseRelativeUri("/", RootRequest));
- CHECK(!RootRequest.Namespace.has_value());
- CHECK(!RootRequest.Bucket.has_value());
- CHECK(!RootRequest.HashKey.has_value());
- CHECK(!RootRequest.ValueContentId.has_value());
-
- HttpRequestData LegacyBucketRequestBecomesNamespaceRequest;
- CHECK(HttpRequestParseRelativeUri("test", LegacyBucketRequestBecomesNamespaceRequest));
- CHECK(LegacyBucketRequestBecomesNamespaceRequest.Namespace == "test"sv);
- CHECK(!LegacyBucketRequestBecomesNamespaceRequest.Bucket.has_value());
- CHECK(!LegacyBucketRequestBecomesNamespaceRequest.HashKey.has_value());
- CHECK(!LegacyBucketRequestBecomesNamespaceRequest.ValueContentId.has_value());
-
- HttpRequestData LegacyHashKeyRequest;
- CHECK(HttpRequestParseRelativeUri("test/0123456789abcdef12340123456789abcdef1234", LegacyHashKeyRequest));
- CHECK(LegacyHashKeyRequest.Namespace == ZenCacheStore::DefaultNamespace);
- CHECK(LegacyHashKeyRequest.Bucket == "test"sv);
- CHECK(LegacyHashKeyRequest.HashKey == IoHash::FromHexString("0123456789abcdef12340123456789abcdef1234"sv));
- CHECK(!LegacyHashKeyRequest.ValueContentId.has_value());
-
- HttpRequestData LegacyValueContentIdRequest;
- CHECK(HttpRequestParseRelativeUri("test/0123456789abcdef12340123456789abcdef1234/56789abcdef12345678956789abcdef123456789",
- LegacyValueContentIdRequest));
- CHECK(LegacyValueContentIdRequest.Namespace == ZenCacheStore::DefaultNamespace);
- CHECK(LegacyValueContentIdRequest.Bucket == "test"sv);
- CHECK(LegacyValueContentIdRequest.HashKey == IoHash::FromHexString("0123456789abcdef12340123456789abcdef1234"sv));
- CHECK(LegacyValueContentIdRequest.ValueContentId == IoHash::FromHexString("56789abcdef12345678956789abcdef123456789"sv));
-
- HttpRequestData V2DefaultNamespaceRequest;
- CHECK(HttpRequestParseRelativeUri("ue4.ddc", V2DefaultNamespaceRequest));
- CHECK(V2DefaultNamespaceRequest.Namespace == "ue4.ddc");
- CHECK(!V2DefaultNamespaceRequest.Bucket.has_value());
- CHECK(!V2DefaultNamespaceRequest.HashKey.has_value());
- CHECK(!V2DefaultNamespaceRequest.ValueContentId.has_value());
-
- HttpRequestData V2NamespaceRequest;
- CHECK(HttpRequestParseRelativeUri("nicenamespace", V2NamespaceRequest));
- CHECK(V2NamespaceRequest.Namespace == "nicenamespace"sv);
- CHECK(!V2NamespaceRequest.Bucket.has_value());
- CHECK(!V2NamespaceRequest.HashKey.has_value());
- CHECK(!V2NamespaceRequest.ValueContentId.has_value());
-
- HttpRequestData V2BucketRequestWithDefaultNamespace;
- CHECK(HttpRequestParseRelativeUri("ue4.ddc/test", V2BucketRequestWithDefaultNamespace));
- CHECK(V2BucketRequestWithDefaultNamespace.Namespace == "ue4.ddc");
- CHECK(V2BucketRequestWithDefaultNamespace.Bucket == "test"sv);
- CHECK(!V2BucketRequestWithDefaultNamespace.HashKey.has_value());
- CHECK(!V2BucketRequestWithDefaultNamespace.ValueContentId.has_value());
-
- HttpRequestData V2BucketRequestWithNamespace;
- CHECK(HttpRequestParseRelativeUri("nicenamespace/test", V2BucketRequestWithNamespace));
- CHECK(V2BucketRequestWithNamespace.Namespace == "nicenamespace"sv);
- CHECK(V2BucketRequestWithNamespace.Bucket == "test"sv);
- CHECK(!V2BucketRequestWithNamespace.HashKey.has_value());
- CHECK(!V2BucketRequestWithNamespace.ValueContentId.has_value());
-
- HttpRequestData V2HashKeyRequest;
- CHECK(HttpRequestParseRelativeUri("test/0123456789abcdef12340123456789abcdef1234", V2HashKeyRequest));
- CHECK(V2HashKeyRequest.Namespace == ZenCacheStore::DefaultNamespace);
- CHECK(V2HashKeyRequest.Bucket == "test");
- CHECK(V2HashKeyRequest.HashKey == IoHash::FromHexString("0123456789abcdef12340123456789abcdef1234"sv));
- CHECK(!V2HashKeyRequest.ValueContentId.has_value());
-
- HttpRequestData V2ValueContentIdRequest;
- CHECK(
- HttpRequestParseRelativeUri("nicenamespace/test/0123456789abcdef12340123456789abcdef1234/56789abcdef12345678956789abcdef123456789",
- V2ValueContentIdRequest));
- CHECK(V2ValueContentIdRequest.Namespace == "nicenamespace"sv);
- CHECK(V2ValueContentIdRequest.Bucket == "test"sv);
- CHECK(V2ValueContentIdRequest.HashKey == IoHash::FromHexString("0123456789abcdef12340123456789abcdef1234"sv));
- CHECK(V2ValueContentIdRequest.ValueContentId == IoHash::FromHexString("56789abcdef12345678956789abcdef123456789"sv));
-
- HttpRequestData Invalid;
- CHECK(!HttpRequestParseRelativeUri("bad\2_namespace", Invalid));
- CHECK(!HttpRequestParseRelativeUri("nice/\2\1bucket", Invalid));
- CHECK(!HttpRequestParseRelativeUri("namespace/bucket/0123456789a", Invalid));
- CHECK(!HttpRequestParseRelativeUri("namespace/bucket/0123456789abcdef12340123456789abcdef1234/56789abcdef1234", Invalid));
- CHECK(!HttpRequestParseRelativeUri("namespace/bucket/pppppppp89abcdef12340123456789abcdef1234", Invalid));
- CHECK(!HttpRequestParseRelativeUri("namespace/bucket/0123456789abcdef12340123456789abcdef1234/56789abcd", Invalid));
- CHECK(!HttpRequestParseRelativeUri("namespace/bucket/0123456789abcdef12340123456789abcdef1234/ppppppppdef12345678956789abcdef123456789",
- Invalid));
-}
-
-#endif
-
-void
-z$service_forcelink()
-{
-}
-
} // namespace zen
diff --git a/src/zenserver/cache/httpstructuredcache.h b/src/zenserver/cache/httpstructuredcache.h
index da4bdd63c..7dc8c4c21 100644
--- a/src/zenserver/cache/httpstructuredcache.h
+++ b/src/zenserver/cache/httpstructuredcache.h
@@ -136,6 +136,4 @@ private:
std::unique_ptr<cache::IRpcRequestRecorder> m_RequestRecorder;
};
-void z$service_forcelink();
-
} // namespace zen
diff --git a/src/zenserver/main.cpp b/src/zenserver/main.cpp
index 8faefca88..4a5b98e8e 100644
--- a/src/zenserver/main.cpp
+++ b/src/zenserver/main.cpp
@@ -23,7 +23,6 @@
#if ZEN_USE_MIMALLOC
ZEN_THIRD_PARTY_INCLUDES_START
# include <mimalloc-new-delete.h>
-# include <mimalloc.h>
ZEN_THIRD_PARTY_INCLUDES_END
#endif
@@ -293,11 +292,7 @@ ZenWindowsService::Run()
int
test_main(int argc, char** argv)
{
- zen::zencore_forcelinktests();
- zen::zenhttp_forcelinktests();
- zen::zenstore_forcelinktests();
- zen::zenutil_forcelinktests();
- zen::z$service_forcelink();
+ zen::zenserver_forcelinktests();
zen::logging::InitializeLogging();
zen::logging::SetLogLevel(zen::logging::level::Debug);
@@ -311,11 +306,10 @@ test_main(int argc, char** argv)
int
main(int argc, char* argv[])
{
- using namespace zen;
-
#if ZEN_USE_MIMALLOC
mi_version();
#endif
+ using namespace zen;
if (argc >= 2)
{
diff --git a/src/zenserver/zenserver.cpp b/src/zenserver/zenserver.cpp
index 3f3762dbf..6b0760343 100644
--- a/src/zenserver/zenserver.cpp
+++ b/src/zenserver/zenserver.cpp
@@ -944,4 +944,14 @@ ZenServer::ToString(ServerState Value)
}
}
+#if ZEN_WITH_TESTS
+
+void
+zenserver_forcelinktests()
+{
+ zen::prj_forcelink();
+}
+
+#endif
+
} // namespace zen
diff --git a/src/zenserver/zenserver.h b/src/zenserver/zenserver.h
index 6ff13cfff..cdd7c17a7 100644
--- a/src/zenserver/zenserver.h
+++ b/src/zenserver/zenserver.h
@@ -143,4 +143,6 @@ private:
std::string m_StartupScrubOptions;
};
+void zenserver_forcelinktests();
+
} // namespace zen
diff --git a/src/zenstore-test/zenstore-test.cpp b/src/zenstore-test/zenstore-test.cpp
index c301c04a3..3ad9e620b 100644
--- a/src/zenstore-test/zenstore-test.cpp
+++ b/src/zenstore-test/zenstore-test.cpp
@@ -2,15 +2,12 @@
#include <zencore/filesystem.h>
#include <zencore/logging.h>
-#include <zencore/zencore.h>
-#include <zenstore/cache/structuredcachestore.h>
#include <zenstore/zenstore.h>
-#include <zenutil/zenutil.h>
-#if ZEN_PLATFORM_LINUX || ZEN_PLATFORM_MAC
-# include <sys/time.h>
-# include <sys/resource.h>
-# include <zencore/except.h>
+#if ZEN_USE_MIMALLOC
+ZEN_THIRD_PARTY_INCLUDES_START
+# include <mimalloc-new-delete.h>
+ZEN_THIRD_PARTY_INCLUDES_END
#endif
#if ZEN_WITH_TESTS
@@ -21,10 +18,11 @@
int
main([[maybe_unused]] int argc, [[maybe_unused]] char* argv[])
{
+#if ZEN_USE_MIMALLOC
+ mi_version();
+#endif
#if ZEN_WITH_TESTS
zen::zenstore_forcelinktests();
- zen::zenutil_forcelinktests();
- zen::structured_cachestore_forcelink();
zen::logging::InitializeLogging();
zen::MaximizeOpenFileCount();
diff --git a/src/zenstore/cache/cacherpc.cpp b/src/zenstore/cache/cacherpc.cpp
index 5acb2b8c9..e6ba6629d 100644
--- a/src/zenstore/cache/cacherpc.cpp
+++ b/src/zenstore/cache/cacherpc.cpp
@@ -14,55 +14,9 @@
#include <zenstore/cache/structuredcachestore.h>
#include <zenstore/cache/upstreamcacheclient.h>
#include <zenstore/cidstore.h>
+#include <zenutil/cache/cacherequests.h>
#include <zenutil/packageformat.h>
-namespace zen { namespace {
-
- constinit AsciiSet ValidNamespaceNameCharactersSet{"abcdefghijklmnopqrstuvwxyz0123456789-_.ABCDEFGHIJKLMNOPQRSTUVWXYZ"};
- constinit AsciiSet ValidBucketNameCharactersSet{"abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"};
-
- std::optional<std::string> GetValidNamespaceName(std::string_view Name)
- {
- if (Name.empty())
- {
- ZEN_WARN("Namespace is invalid, empty namespace is not allowed");
- return {};
- }
-
- if (Name.length() > 64)
- {
- ZEN_WARN("Namespace '{}' is invalid, length exceeds 64 characters", Name);
- return {};
- }
-
- if (!AsciiSet::HasOnly(Name, ValidNamespaceNameCharactersSet))
- {
- ZEN_WARN("Namespace '{}' is invalid, invalid characters detected", Name);
- return {};
- }
-
- return ToLower(Name);
- }
-
- std::optional<std::string> GetValidBucketName(std::string_view Name)
- {
- if (Name.empty())
- {
- ZEN_WARN("Bucket name is invalid, empty bucket name is not allowed");
- return {};
- }
-
- if (!AsciiSet::HasOnly(Name, ValidBucketNameCharactersSet))
- {
- ZEN_WARN("Bucket name '{}' is invalid, invalid characters detected", Name);
- return {};
- }
-
- return ToLower(Name);
- }
-
-}} // namespace zen::
-
//////////////////////////////////////////////////////////////////////////
namespace zen {
@@ -86,7 +40,7 @@ GetRpcRequestNamespace(const CbObjectView Params)
{
return {};
}
- return GetValidNamespaceName(NamespaceField.AsString());
+ return cacherequests::GetValidNamespaceName(NamespaceField.AsString());
}
bool
@@ -101,7 +55,7 @@ GetRpcRequestCacheKey(const CbObjectView& KeyView, CacheKey& Key)
{
return false;
}
- std::optional<std::string> Bucket = GetValidBucketName(BucketField.AsString());
+ std::optional<std::string> Bucket = cacherequests::GetValidBucketName(BucketField.AsString());
if (!Bucket.has_value())
{
return false;
diff --git a/src/zenstore/cache/structuredcachestore.cpp b/src/zenstore/cache/structuredcachestore.cpp
index 7ef290cf5..daa628f77 100644
--- a/src/zenstore/cache/structuredcachestore.cpp
+++ b/src/zenstore/cache/structuredcachestore.cpp
@@ -873,7 +873,7 @@ namespace testutils {
} // namespace testutils
-TEST_CASE("z$.store")
+TEST_CASE("cachestore.store")
{
ScopedTemporaryDirectory TempDir;
@@ -914,7 +914,7 @@ TEST_CASE("z$.store")
}
}
-TEST_CASE("z$.size")
+TEST_CASE("cachestore.size")
{
auto JobQueue = MakeJobQueue(1, "testqueue");
@@ -1029,7 +1029,7 @@ TEST_CASE("z$.size")
}
}
-TEST_CASE("z$.gc")
+TEST_CASE("cachestore.gc")
{
using namespace testutils;
@@ -1208,7 +1208,7 @@ TEST_CASE("z$.gc")
}
}
-TEST_CASE_TEMPLATE("z$.threadedinsert", GCV2, FalseType, TrueType) // * doctest::skip(true))
+TEST_CASE_TEMPLATE("cachestore.threadedinsert", GCV2, FalseType, TrueType) // * doctest::skip(true))
{
// for (uint32_t i = 0; i < 100; ++i)
{
@@ -1482,7 +1482,7 @@ TEST_CASE_TEMPLATE("z$.threadedinsert", GCV2, FalseType, TrueType) // * doctest:
}
}
-TEST_CASE("z$.namespaces")
+TEST_CASE("cachestore.namespaces")
{
using namespace testutils;
@@ -1550,7 +1550,7 @@ TEST_CASE("z$.namespaces")
}
}
-TEST_CASE("z$.drop.bucket")
+TEST_CASE("cachestore.drop.bucket")
{
using namespace testutils;
@@ -1625,7 +1625,7 @@ TEST_CASE("z$.drop.bucket")
}
}
-TEST_CASE("z$.drop.namespace")
+TEST_CASE("cachestore.drop.namespace")
{
using namespace testutils;
@@ -1715,7 +1715,7 @@ TEST_CASE("z$.drop.namespace")
}
}
-TEST_CASE("z$.blocked.disklayer.put")
+TEST_CASE("cachestore.blocked.disklayer.put")
{
ScopedTemporaryDirectory TempDir;
@@ -1768,7 +1768,7 @@ TEST_CASE("z$.blocked.disklayer.put")
CHECK(memcmp(NewView.GetData(), Buffer2.GetData(), NewView.GetSize()) == 0);
}
-TEST_CASE("z$.scrub")
+TEST_CASE("cachestore.scrub")
{
ScopedTemporaryDirectory TempDir;
@@ -1862,7 +1862,7 @@ TEST_CASE("z$.scrub")
CHECK(ScrubCtx.BadCids().GetSize() == 0);
}
-TEST_CASE("z$.newgc.basics")
+TEST_CASE("cachestore.newgc.basics")
{
using namespace testutils;
diff --git a/src/zenstore/zenstore.cpp b/src/zenstore/zenstore.cpp
index 60dabe31f..038c6bdc7 100644
--- a/src/zenstore/zenstore.cpp
+++ b/src/zenstore/zenstore.cpp
@@ -5,6 +5,7 @@
#if ZEN_WITH_TESTS
# include <zenstore/blockstore.h>
+# include <zenstore/cache/structuredcachestore.h>
# include <zenstore/gc.h>
# include <zenstore/hashkeyset.h>
@@ -23,6 +24,7 @@ zenstore_forcelinktests()
compactcas_forcelink();
gc_forcelink();
hashkeyset_forcelink();
+ structured_cachestore_forcelink();
}
} // namespace zen
diff --git a/src/zenutil-test/xmake.lua b/src/zenutil-test/xmake.lua
new file mode 100644
index 000000000..61a828f1c
--- /dev/null
+++ b/src/zenutil-test/xmake.lua
@@ -0,0 +1,9 @@
+-- Copyright Epic Games, Inc. All Rights Reserved.
+
+target("zenutil-test")
+ set_kind("binary")
+ set_group("tests")
+ add_headerfiles("**.h")
+ add_files("*.cpp")
+ add_deps("zenutil", "zencore")
+ add_packages("vcpkg::doctest")
diff --git a/src/zenutil-test/zenutil-test.cpp b/src/zenutil-test/zenutil-test.cpp
new file mode 100644
index 000000000..f95b7e888
--- /dev/null
+++ b/src/zenutil-test/zenutil-test.cpp
@@ -0,0 +1,34 @@
+// Copyright Epic Games, Inc. All Rights Reserved.
+
+#include <zencore/filesystem.h>
+#include <zencore/logging.h>
+#include <zenutil/zenutil.h>
+
+#if ZEN_USE_MIMALLOC
+ZEN_THIRD_PARTY_INCLUDES_START
+# include <mimalloc-new-delete.h>
+ZEN_THIRD_PARTY_INCLUDES_END
+#endif
+
+#if ZEN_WITH_TESTS
+# define ZEN_TEST_WITH_RUNNER 1
+# include <zencore/testing.h>
+#endif
+
+int
+main([[maybe_unused]] int argc, [[maybe_unused]] char* argv[])
+{
+#if ZEN_USE_MIMALLOC
+ mi_version();
+#endif
+#if ZEN_WITH_TESTS
+ zen::zenutil_forcelinktests();
+
+ zen::logging::InitializeLogging();
+ zen::MaximizeOpenFileCount();
+
+ return ZEN_RUN_TESTS(argc, argv);
+#else
+ return 0;
+#endif
+}
diff --git a/src/zenutil/cache/cachepolicy.cpp b/src/zenutil/cache/cachepolicy.cpp
index 3bca363bb..0bdfd87ce 100644
--- a/src/zenutil/cache/cachepolicy.cpp
+++ b/src/zenutil/cache/cachepolicy.cpp
@@ -10,6 +10,10 @@
#include <algorithm>
#include <unordered_map>
+#if ZEN_WITH_TESTS
+# include <zencore/testing.h>
+#endif
+
namespace zen::Private {
class CacheRecordPolicyShared;
}
@@ -279,4 +283,144 @@ CacheRecordPolicyBuilder::Build()
return Policy;
}
+#if ZEN_WITH_TESTS
+TEST_CASE("cachepolicy")
+{
+ SUBCASE("atomics serialization")
+ {
+ CachePolicy SomeAtomics[] = {CachePolicy::None,
+ CachePolicy::QueryLocal,
+ CachePolicy::StoreRemote,
+ CachePolicy::SkipData,
+ CachePolicy::KeepAlive};
+ for (CachePolicy Atomic : SomeAtomics)
+ {
+ CHECK(ParseCachePolicy(WriteToString<128>(Atomic)) == Atomic);
+ }
+ // Also verify that we ignore unrecognized bits
+ for (CachePolicy Atomic : SomeAtomics)
+ {
+ CHECK(ParseCachePolicy(WriteToString<128>(Atomic | (CachePolicy)0x10000000)) == Atomic);
+ }
+ }
+ SUBCASE("aliases serialization")
+ {
+ CachePolicy SomeAliases[] = {CachePolicy::Query, CachePolicy::Local};
+ for (CachePolicy Alias : SomeAliases)
+ {
+ CHECK(ParseCachePolicy(WriteToString<128>(Alias)) == Alias);
+ }
+ // Also verify that we ignore unrecognized bits
+ for (CachePolicy Alias : SomeAliases)
+ {
+ CHECK(ParseCachePolicy(WriteToString<128>(Alias | (CachePolicy)0x10000000)) == Alias);
+ }
+ }
+ SUBCASE("aliases take priority over atomics")
+ {
+ CHECK(WriteToString<128>(CachePolicy::Default).ToView() == "Default"sv);
+ CHECK(WriteToString<128>(CachePolicy::Query).ToView() == "Query"sv);
+ CHECK(WriteToString<128>(CachePolicy::Local).ToView() == "Local"sv);
+ }
+ SUBCASE("policies requiring multiple strings work")
+ {
+ char Delimiter = ',';
+ CachePolicy Combination = CachePolicy::SkipData | CachePolicy::QueryLocal;
+ CHECK(WriteToString<128>(Combination).ToView().find(Delimiter) != std::string_view::npos);
+ CHECK(ParseCachePolicy(WriteToString<128>(Combination)) == Combination);
+ }
+ SUBCASE("parsing invalid text")
+ {
+ CHECK(ParseCachePolicy(",,,") == CachePolicy::None);
+ CHECK(ParseCachePolicy("fee,fie,foo,fum") == CachePolicy::None);
+ CHECK(ParseCachePolicy("fee,KeepAlive,foo,fum") == CachePolicy::KeepAlive);
+ }
+}
+
+TEST_CASE("cacherecordpolicy")
+{
+ SUBCASE("policy with no values")
+ {
+ CachePolicy Policy = CachePolicy::SkipData | CachePolicy::QueryLocal | CachePolicy::PartialRecord;
+ CachePolicy ValuePolicy = Policy & CacheValuePolicy::PolicyMask;
+ CacheRecordPolicy RecordPolicy;
+ CacheRecordPolicyBuilder Builder(Policy);
+ RecordPolicy = Builder.Build();
+ SUBCASE("construct")
+ {
+ CHECK(RecordPolicy.IsUniform());
+ CHECK(RecordPolicy.GetRecordPolicy() == Policy);
+ CHECK(RecordPolicy.GetBasePolicy() == Policy);
+ CHECK(RecordPolicy.GetValuePolicy(Oid::NewOid()) == ValuePolicy);
+ CHECK(RecordPolicy.GetValuePolicies().size() == 0);
+ }
+ SUBCASE("saveload")
+ {
+ CbWriter Writer;
+ RecordPolicy.Save(Writer);
+ CbObject Saved = Writer.Save()->AsObject();
+ CacheRecordPolicy Loaded = CacheRecordPolicy::Load(Saved).Get();
+ CHECK(Loaded.IsUniform());
+ CHECK(Loaded.GetRecordPolicy() == Policy);
+ CHECK(Loaded.GetBasePolicy() == Policy);
+ CHECK(Loaded.GetValuePolicy(Oid::NewOid()) == ValuePolicy);
+ CHECK(Loaded.GetValuePolicies().size() == 0);
+ }
+ }
+
+ SUBCASE("policy with values")
+ {
+ CachePolicy DefaultPolicy = CachePolicy::StoreRemote | CachePolicy::QueryLocal | CachePolicy::PartialRecord;
+ CachePolicy DefaultValuePolicy = DefaultPolicy & CacheValuePolicy::PolicyMask;
+ CachePolicy PartialOverlap = CachePolicy::StoreRemote;
+ CachePolicy NoOverlap = CachePolicy::QueryRemote;
+ CachePolicy UnionPolicy = DefaultPolicy | PartialOverlap | NoOverlap | CachePolicy::PartialRecord;
+
+ CacheRecordPolicy RecordPolicy;
+ CacheRecordPolicyBuilder Builder(DefaultPolicy);
+ Oid PartialOid = Oid::NewOid();
+ Oid NoOverlapOid = Oid::NewOid();
+ Oid OtherOid = Oid::NewOid();
+ Builder.AddValuePolicy(PartialOid, PartialOverlap);
+ Builder.AddValuePolicy(NoOverlapOid, NoOverlap);
+ RecordPolicy = Builder.Build();
+ SUBCASE("construct")
+ {
+ CHECK(!RecordPolicy.IsUniform());
+ CHECK(RecordPolicy.GetRecordPolicy() == UnionPolicy);
+ CHECK(RecordPolicy.GetBasePolicy() == DefaultPolicy);
+ CHECK(RecordPolicy.GetValuePolicy(PartialOid) == PartialOverlap);
+ CHECK(RecordPolicy.GetValuePolicy(NoOverlapOid) == NoOverlap);
+ CHECK(RecordPolicy.GetValuePolicy(OtherOid) == DefaultValuePolicy);
+ CHECK(RecordPolicy.GetValuePolicies().size() == 2);
+ }
+ SUBCASE("saveload")
+ {
+ CbWriter Writer;
+ RecordPolicy.Save(Writer);
+ CbObject Saved = Writer.Save()->AsObject();
+ CacheRecordPolicy Loaded = CacheRecordPolicy::Load(Saved).Get();
+ CHECK(!RecordPolicy.IsUniform());
+ CHECK(RecordPolicy.GetRecordPolicy() == UnionPolicy);
+ CHECK(RecordPolicy.GetBasePolicy() == DefaultPolicy);
+ CHECK(RecordPolicy.GetValuePolicy(PartialOid) == PartialOverlap);
+ CHECK(RecordPolicy.GetValuePolicy(NoOverlapOid) == NoOverlap);
+ CHECK(RecordPolicy.GetValuePolicy(OtherOid) == DefaultValuePolicy);
+ CHECK(RecordPolicy.GetValuePolicies().size() == 2);
+ }
+ }
+
+ SUBCASE("parsing invalid text")
+ {
+ OptionalCacheRecordPolicy Loaded = CacheRecordPolicy::Load(CbObject());
+ CHECK(Loaded.IsNull());
+ }
+}
+#endif
+
+void
+cachepolicy_forcelink()
+{
+}
+
} // namespace zen
diff --git a/src/zenutil/cache/cacherequests.cpp b/src/zenutil/cache/cacherequests.cpp
index 51fb61c27..f4de6bacd 100644
--- a/src/zenutil/cache/cacherequests.cpp
+++ b/src/zenutil/cache/cacherequests.cpp
@@ -24,67 +24,67 @@ namespace cacherequests {
namespace {
constinit AsciiSet ValidNamespaceNameCharactersSet{"abcdefghijklmnopqrstuvwxyz0123456789-_.ABCDEFGHIJKLMNOPQRSTUVWXYZ"};
constinit AsciiSet ValidBucketNameCharactersSet{"abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"};
+ } // namespace
- std::optional<std::string> GetValidNamespaceName(std::string_view Name)
+ std::optional<std::string> GetValidNamespaceName(std::string_view Name)
+ {
+ if (Name.empty())
{
- if (Name.empty())
- {
- ZEN_WARN("Namespace is invalid, empty namespace is not allowed");
- return {};
- }
-
- if (Name.length() > 64)
- {
- ZEN_WARN("Namespace '{}' is invalid, length exceeds 64 characters", Name);
- return {};
- }
-
- if (!AsciiSet::HasOnly(Name, ValidNamespaceNameCharactersSet))
- {
- ZEN_WARN("Namespace '{}' is invalid, invalid characters detected", Name);
- return {};
- }
+ ZEN_WARN("Namespace is invalid, empty namespace is not allowed");
+ return {};
+ }
- return ToLower(Name);
+ if (Name.length() > 64)
+ {
+ ZEN_WARN("Namespace '{}' is invalid, length exceeds 64 characters", Name);
+ return {};
}
- std::optional<std::string> GetValidBucketName(std::string_view Name)
+ if (!AsciiSet::HasOnly(Name, ValidNamespaceNameCharactersSet))
{
- if (Name.empty())
- {
- ZEN_WARN("Bucket name is invalid, empty bucket name is not allowed");
- return {};
- }
+ ZEN_WARN("Namespace '{}' is invalid, invalid characters detected", Name);
+ return {};
+ }
- if (!AsciiSet::HasOnly(Name, ValidBucketNameCharactersSet))
- {
- ZEN_WARN("Bucket name '{}' is invalid, invalid characters detected", Name);
- return {};
- }
+ return ToLower(Name);
+ }
- return ToLower(Name);
+ std::optional<std::string> GetValidBucketName(std::string_view Name)
+ {
+ if (Name.empty())
+ {
+ ZEN_WARN("Bucket name is invalid, empty bucket name is not allowed");
+ return {};
}
- std::optional<IoHash> GetValidIoHash(std::string_view Hash)
+ if (!AsciiSet::HasOnly(Name, ValidBucketNameCharactersSet))
{
- if (Hash.length() != IoHash::StringLength)
- {
- return {};
- }
+ ZEN_WARN("Bucket name '{}' is invalid, invalid characters detected", Name);
+ return {};
+ }
- IoHash KeyHash;
- if (!ParseHexBytes(Hash.data(), Hash.size(), KeyHash.Hash))
- {
- return {};
- }
- return KeyHash;
+ return ToLower(Name);
+ }
+
+ std::optional<IoHash> GetValidIoHash(std::string_view Hash)
+ {
+ if (Hash.length() != IoHash::StringLength)
+ {
+ return {};
}
- std::optional<CacheRecordPolicy> Convert(const OptionalCacheRecordPolicy& Policy)
+ IoHash KeyHash;
+ if (!ParseHexBytes(Hash.data(), Hash.size(), KeyHash.Hash))
{
- return Policy.IsValid() ? Policy.Get() : std::optional<CacheRecordPolicy>{};
- };
- } // namespace
+ return {};
+ }
+ return KeyHash;
+ }
+
+ std::optional<CacheRecordPolicy> Convert(const OptionalCacheRecordPolicy& Policy)
+ {
+ return Policy.IsValid() ? Policy.Get() : std::optional<CacheRecordPolicy>{};
+ };
std::optional<std::string> GetRequestNamespace(const CbObjectView& Params)
{
@@ -923,16 +923,18 @@ namespace cacherequests {
return true;
}
- bool HttpRequestParseRelativeUri(std::string_view Key, HttpRequestData& Data)
+ bool HttpRequestParseRelativeUri(std::string_view Key, std::string_view DefaultNamespace, HttpRequestData& Data)
{
std::vector<std::string_view> Tokens;
- uint32_t TokenCount = zen::ForEachStrTok(Key, '/', [&](const std::string_view& Token) {
+ uint32_t TokenCount = ForEachStrTok(Key, '/', [&](const std::string_view& Token) {
Tokens.push_back(Token);
return true;
});
switch (TokenCount)
{
+ case 0:
+ return true;
case 1:
Data.Namespace = GetValidNamespaceName(Tokens[0]);
return Data.Namespace.has_value();
@@ -947,7 +949,8 @@ namespace cacherequests {
{
return false;
}
- Data.HashKey = PossibleHashKey;
+ Data.HashKey = PossibleHashKey;
+ Data.Namespace = DefaultNamespace;
return true;
}
Data.Namespace = GetValidNamespaceName(Tokens[0]);
@@ -979,6 +982,7 @@ namespace cacherequests {
{
return false;
}
+ Data.Namespace = DefaultNamespace;
return true;
}
Data.Namespace = GetValidNamespaceName(Tokens[0]);
@@ -1552,85 +1556,104 @@ namespace cacherequests {
CHECK(FullResult == FullResultCopy);
}
- TEST_CASE("z$service.parse.relative.Uri")
+ TEST_CASE("cachrequests.parse.relative.Uri")
{
+ using namespace std::literals;
+
+ HttpRequestData RootRequest;
+ CHECK(HttpRequestParseRelativeUri("", "!default!", RootRequest));
+ CHECK(!RootRequest.Namespace.has_value());
+ CHECK(!RootRequest.Bucket.has_value());
+ CHECK(!RootRequest.HashKey.has_value());
+ CHECK(!RootRequest.ValueContentId.has_value());
+
+ RootRequest = {};
+ CHECK(HttpRequestParseRelativeUri("/", "!default!", RootRequest));
+ CHECK(!RootRequest.Namespace.has_value());
+ CHECK(!RootRequest.Bucket.has_value());
+ CHECK(!RootRequest.HashKey.has_value());
+ CHECK(!RootRequest.ValueContentId.has_value());
+
HttpRequestData LegacyBucketRequestBecomesNamespaceRequest;
- CHECK(HttpRequestParseRelativeUri("test", LegacyBucketRequestBecomesNamespaceRequest));
- CHECK(LegacyBucketRequestBecomesNamespaceRequest.Namespace == "test");
+ CHECK(HttpRequestParseRelativeUri("test", "!default!", LegacyBucketRequestBecomesNamespaceRequest));
+ CHECK(LegacyBucketRequestBecomesNamespaceRequest.Namespace == "test"sv);
CHECK(!LegacyBucketRequestBecomesNamespaceRequest.Bucket.has_value());
CHECK(!LegacyBucketRequestBecomesNamespaceRequest.HashKey.has_value());
CHECK(!LegacyBucketRequestBecomesNamespaceRequest.ValueContentId.has_value());
HttpRequestData LegacyHashKeyRequest;
- CHECK(HttpRequestParseRelativeUri("test/0123456789abcdef12340123456789abcdef1234", LegacyHashKeyRequest));
- CHECK(!LegacyHashKeyRequest.Namespace);
- CHECK(LegacyHashKeyRequest.Bucket == "test");
- CHECK(LegacyHashKeyRequest.HashKey == IoHash::FromHexString("0123456789abcdef12340123456789abcdef1234"));
+ CHECK(HttpRequestParseRelativeUri("test/0123456789abcdef12340123456789abcdef1234", "!default!", LegacyHashKeyRequest));
+ CHECK(LegacyHashKeyRequest.Namespace == "!default!");
+ CHECK(LegacyHashKeyRequest.Bucket == "test"sv);
+ CHECK(LegacyHashKeyRequest.HashKey == IoHash::FromHexString("0123456789abcdef12340123456789abcdef1234"sv));
CHECK(!LegacyHashKeyRequest.ValueContentId.has_value());
HttpRequestData LegacyValueContentIdRequest;
CHECK(HttpRequestParseRelativeUri("test/0123456789abcdef12340123456789abcdef1234/56789abcdef12345678956789abcdef123456789",
+ "!default!",
LegacyValueContentIdRequest));
- CHECK(!LegacyValueContentIdRequest.Namespace);
- CHECK(LegacyValueContentIdRequest.Bucket == "test");
- CHECK(LegacyValueContentIdRequest.HashKey == IoHash::FromHexString("0123456789abcdef12340123456789abcdef1234"));
- CHECK(LegacyValueContentIdRequest.ValueContentId == IoHash::FromHexString("56789abcdef12345678956789abcdef123456789"));
+ CHECK(LegacyValueContentIdRequest.Namespace == "!default!");
+ CHECK(LegacyValueContentIdRequest.Bucket == "test"sv);
+ CHECK(LegacyValueContentIdRequest.HashKey == IoHash::FromHexString("0123456789abcdef12340123456789abcdef1234"sv));
+ CHECK(LegacyValueContentIdRequest.ValueContentId == IoHash::FromHexString("56789abcdef12345678956789abcdef123456789"sv));
HttpRequestData V2DefaultNamespaceRequest;
- CHECK(HttpRequestParseRelativeUri("ue4.ddc", V2DefaultNamespaceRequest));
+ CHECK(HttpRequestParseRelativeUri("ue4.ddc", "!default!", V2DefaultNamespaceRequest));
CHECK(V2DefaultNamespaceRequest.Namespace == "ue4.ddc");
CHECK(!V2DefaultNamespaceRequest.Bucket.has_value());
CHECK(!V2DefaultNamespaceRequest.HashKey.has_value());
CHECK(!V2DefaultNamespaceRequest.ValueContentId.has_value());
HttpRequestData V2NamespaceRequest;
- CHECK(HttpRequestParseRelativeUri("nicenamespace", V2NamespaceRequest));
- CHECK(V2NamespaceRequest.Namespace == "nicenamespace");
+ CHECK(HttpRequestParseRelativeUri("nicenamespace", "!default!", V2NamespaceRequest));
+ CHECK(V2NamespaceRequest.Namespace == "nicenamespace"sv);
CHECK(!V2NamespaceRequest.Bucket.has_value());
CHECK(!V2NamespaceRequest.HashKey.has_value());
CHECK(!V2NamespaceRequest.ValueContentId.has_value());
HttpRequestData V2BucketRequestWithDefaultNamespace;
- CHECK(HttpRequestParseRelativeUri("ue4.ddc/test", V2BucketRequestWithDefaultNamespace));
+ CHECK(HttpRequestParseRelativeUri("ue4.ddc/test", "!default!", V2BucketRequestWithDefaultNamespace));
CHECK(V2BucketRequestWithDefaultNamespace.Namespace == "ue4.ddc");
- CHECK(V2BucketRequestWithDefaultNamespace.Bucket == "test");
+ CHECK(V2BucketRequestWithDefaultNamespace.Bucket == "test"sv);
CHECK(!V2BucketRequestWithDefaultNamespace.HashKey.has_value());
CHECK(!V2BucketRequestWithDefaultNamespace.ValueContentId.has_value());
HttpRequestData V2BucketRequestWithNamespace;
- CHECK(HttpRequestParseRelativeUri("nicenamespace/test", V2BucketRequestWithNamespace));
- CHECK(V2BucketRequestWithNamespace.Namespace == "nicenamespace");
- CHECK(V2BucketRequestWithNamespace.Bucket == "test");
+ CHECK(HttpRequestParseRelativeUri("nicenamespace/test", "!default!", V2BucketRequestWithNamespace));
+ CHECK(V2BucketRequestWithNamespace.Namespace == "nicenamespace"sv);
+ CHECK(V2BucketRequestWithNamespace.Bucket == "test"sv);
CHECK(!V2BucketRequestWithNamespace.HashKey.has_value());
CHECK(!V2BucketRequestWithNamespace.ValueContentId.has_value());
HttpRequestData V2HashKeyRequest;
- CHECK(HttpRequestParseRelativeUri("test/0123456789abcdef12340123456789abcdef1234", V2HashKeyRequest));
- CHECK(!V2HashKeyRequest.Namespace);
+ CHECK(HttpRequestParseRelativeUri("test/0123456789abcdef12340123456789abcdef1234", "!default!", V2HashKeyRequest));
+ CHECK(V2HashKeyRequest.Namespace == "!default!");
CHECK(V2HashKeyRequest.Bucket == "test");
- CHECK(V2HashKeyRequest.HashKey == IoHash::FromHexString("0123456789abcdef12340123456789abcdef1234"));
+ CHECK(V2HashKeyRequest.HashKey == IoHash::FromHexString("0123456789abcdef12340123456789abcdef1234"sv));
CHECK(!V2HashKeyRequest.ValueContentId.has_value());
HttpRequestData V2ValueContentIdRequest;
CHECK(HttpRequestParseRelativeUri(
"nicenamespace/test/0123456789abcdef12340123456789abcdef1234/56789abcdef12345678956789abcdef123456789",
+ "!default!",
V2ValueContentIdRequest));
- CHECK(V2ValueContentIdRequest.Namespace == "nicenamespace");
- CHECK(V2ValueContentIdRequest.Bucket == "test");
- CHECK(V2ValueContentIdRequest.HashKey == IoHash::FromHexString("0123456789abcdef12340123456789abcdef1234"));
- CHECK(V2ValueContentIdRequest.ValueContentId == IoHash::FromHexString("56789abcdef12345678956789abcdef123456789"));
+ CHECK(V2ValueContentIdRequest.Namespace == "nicenamespace"sv);
+ CHECK(V2ValueContentIdRequest.Bucket == "test"sv);
+ CHECK(V2ValueContentIdRequest.HashKey == IoHash::FromHexString("0123456789abcdef12340123456789abcdef1234"sv));
+ CHECK(V2ValueContentIdRequest.ValueContentId == IoHash::FromHexString("56789abcdef12345678956789abcdef123456789"sv));
HttpRequestData Invalid;
- CHECK(!HttpRequestParseRelativeUri("", Invalid));
- CHECK(!HttpRequestParseRelativeUri("/", Invalid));
- CHECK(!HttpRequestParseRelativeUri("bad\2_namespace", Invalid));
- CHECK(!HttpRequestParseRelativeUri("nice/\2\1bucket", Invalid));
- CHECK(!HttpRequestParseRelativeUri("namespace/bucket/0123456789a", Invalid));
- CHECK(!HttpRequestParseRelativeUri("namespace/bucket/0123456789abcdef12340123456789abcdef1234/56789abcdef1234", Invalid));
- CHECK(!HttpRequestParseRelativeUri("namespace/bucket/pppppppp89abcdef12340123456789abcdef1234", Invalid));
- CHECK(!HttpRequestParseRelativeUri("namespace/bucket/0123456789abcdef12340123456789abcdef1234/56789abcd", Invalid));
+ CHECK(!HttpRequestParseRelativeUri("bad\2_namespace", "!default!", Invalid));
+ CHECK(!HttpRequestParseRelativeUri("nice/\2\1bucket", "!default!", Invalid));
+ CHECK(!HttpRequestParseRelativeUri("namespace/bucket/0123456789a", "!default!", Invalid));
+ CHECK(!HttpRequestParseRelativeUri("namespace/bucket/0123456789abcdef12340123456789abcdef1234/56789abcdef1234",
+ "!default!",
+ Invalid));
+ CHECK(!HttpRequestParseRelativeUri("namespace/bucket/pppppppp89abcdef12340123456789abcdef1234", "!default!", Invalid));
+ CHECK(!HttpRequestParseRelativeUri("namespace/bucket/0123456789abcdef12340123456789abcdef1234/56789abcd", "!default!", Invalid));
CHECK(!HttpRequestParseRelativeUri(
"namespace/bucket/0123456789abcdef12340123456789abcdef1234/ppppppppdef12345678956789abcdef123456789",
+ "!default!",
Invalid));
}
#endif
diff --git a/src/zenutil/include/zenutil/cache/cachepolicy.h b/src/zenutil/include/zenutil/cache/cachepolicy.h
index c9c9e78a4..7773cd3d1 100644
--- a/src/zenutil/include/zenutil/cache/cachepolicy.h
+++ b/src/zenutil/include/zenutil/cache/cachepolicy.h
@@ -224,4 +224,6 @@ public:
inline void Reset() { *this = OptionalCacheRecordPolicy(); }
};
+void cachepolicy_forcelink();
+
} // namespace zen
diff --git a/src/zenutil/include/zenutil/cache/cacherequests.h b/src/zenutil/include/zenutil/cache/cacherequests.h
index f1999ebfe..abc5a3c13 100644
--- a/src/zenutil/include/zenutil/cache/cacherequests.h
+++ b/src/zenutil/include/zenutil/cache/cacherequests.h
@@ -240,6 +240,10 @@ namespace cacherequests {
//////////////////////////////////////////////////////////////////////////
+ std::optional<std::string> GetValidNamespaceName(std::string_view Name);
+ std::optional<std::string> GetValidBucketName(std::string_view Name);
+ std::optional<IoHash> GetValidIoHash(std::string_view Hash);
+
struct HttpRequestData
{
std::optional<std::string> Namespace;
@@ -248,7 +252,7 @@ namespace cacherequests {
std::optional<IoHash> ValueContentId;
};
- bool HttpRequestParseRelativeUri(std::string_view Key, HttpRequestData& Data);
+ bool HttpRequestParseRelativeUri(std::string_view Key, std::string_view DefaultNamespace, HttpRequestData& Data);
// Temporarily public
std::optional<std::string> GetRequestNamespace(const CbObjectView& Params);
diff --git a/src/zenutil/zenutil.cpp b/src/zenutil/zenutil.cpp
index 8544f3401..97ebeb01d 100644
--- a/src/zenutil/zenutil.cpp
+++ b/src/zenutil/zenutil.cpp
@@ -5,6 +5,7 @@
#if ZEN_WITH_TESTS
# include <zenutil/basicfile.h>
+# include <zenutil/cache/cacherequests.h>
# include <zenutil/cache/rpcrecording.h>
# include <zenutil/packageformat.h>
@@ -14,8 +15,10 @@ void
zenutil_forcelinktests()
{
basicfile_forcelink();
+ cachepolicy_forcelink();
cache::rpcrecord_forcelink();
forcelink_packageformat();
+ cacherequests_forcelink();
}
} // namespace zen