aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStefan Boberg <[email protected]>2023-04-24 15:53:30 +0200
committerStefan Boberg <[email protected]>2023-04-24 15:53:30 +0200
commit9ee1a686c29b7ab18207c2963497337532f441cb (patch)
tree17d2681767e92603b7199d88235a775e5ca354ab
parentadded changelog comment (diff)
parentfixed dashboard file serving bug (#255) (diff)
downloadzen-9ee1a686c29b7ab18207c2963497337532f441cb.tar.xz
zen-9ee1a686c29b7ab18207c2963497337532f441cb.zip
Merge branch 'main' of https://github.com/EpicGames/zen
-rw-r--r--xmake.lua2
-rw-r--r--zen/zen.cpp2
-rw-r--r--zencore/include/zencore/testing.h54
-rw-r--r--zencore/testing.cpp52
-rw-r--r--zenhttp/httpasio.cpp5
-rw-r--r--zenhttp/httpsys.cpp13
-rw-r--r--zenhttp/include/zenhttp/httpserver.h2
-rw-r--r--zenserver-test/zenserver-test.cpp42
-rw-r--r--zenserver/frontend/frontend.cpp2
-rw-r--r--zenserver/zenserver.cpp2
-rw-r--r--zenutil/include/zenutil/zenserverprocess.h14
-rw-r--r--zenutil/zenserverprocess.cpp24
12 files changed, 177 insertions, 37 deletions
diff --git a/xmake.lua b/xmake.lua
index 1b6724044..cc9458bdd 100644
--- a/xmake.lua
+++ b/xmake.lua
@@ -111,6 +111,8 @@ if is_os("windows") then
set_description("Enable http.sys server")
option_end()
add_define_by_config("ZEN_WITH_HTTPSYS", "httpsys")
+else
+ add_defines("ZEN_WITH_HTTPSYS=0")
end
option("compute")
diff --git a/zen/zen.cpp b/zen/zen.cpp
index 5a34ffa80..9754f4434 100644
--- a/zen/zen.cpp
+++ b/zen/zen.cpp
@@ -27,7 +27,7 @@
#include <zenhttp/httpcommon.h>
#if ZEN_WITH_TESTS
-# define ZEN_TEST_WITH_RUNNER
+# define ZEN_TEST_WITH_RUNNER 1
# include <zencore/testing.h>
#endif
diff --git a/zencore/include/zencore/testing.h b/zencore/include/zencore/testing.h
index bd55524aa..a00ee3166 100644
--- a/zencore/include/zencore/testing.h
+++ b/zencore/include/zencore/testing.h
@@ -4,24 +4,64 @@
#include <zencore/zencore.h>
-#ifdef ZEN_TEST_WITH_RUNNER
-# define CATCH_CONFIG_RUNNER
+#include <memory>
+
+#ifndef ZEN_TEST_WITH_RUNNER
+# define ZEN_TEST_WITH_RUNNER 0
+#endif
+
+#if ZEN_TEST_WITH_RUNNER
# define DOCTEST_CONFIG_IMPLEMENT
#endif
#if ZEN_WITH_TESTS
# include <doctest/doctest.h>
-# define ZEN_RUN_TESTS(argC, argV) doctest::Context(argc, argv).run()
inline auto
Approx(auto Value)
{
return doctest::Approx(Value);
}
-#else
-# define ZEN_RUN_TESTS(argC, argV)
#endif
-#ifdef ZEN_TEST_WITH_RUNNER
-# undef CATCH_CONFIG_RUNNER
+/**
+ * Test runner helper
+ *
+ * This acts as a thin layer between the test app and the test
+ * framework, which is used to customize configuration logic
+ * and to set up logging.
+ *
+ * If you don't want to implement custom setup then the
+ * ZEN_RUN_TESTS macro can be used instead.
+ */
+
+#if ZEN_WITH_TESTS
+namespace zen::testing {
+
+class TestRunner
+{
+public:
+ TestRunner();
+ ~TestRunner();
+
+ int ApplyCommandLine(int argc, char const* const* argv);
+ int Run();
+
+private:
+ struct Impl;
+
+ std::unique_ptr<Impl> m_Impl;
+};
+
+# define ZEN_RUN_TESTS(argC, argV) \
+ [&] { \
+ zen::testing::TestRunner Runner; \
+ Runner.ApplyCommandLine(argC, argV); \
+ return Runner.Run(); \
+ }()
+
+} // namespace zen::testing
+#endif
+
+#if ZEN_TEST_WITH_RUNNER
# undef DOCTEST_CONFIG_IMPLEMENT
#endif
diff --git a/zencore/testing.cpp b/zencore/testing.cpp
new file mode 100644
index 000000000..15be4b716
--- /dev/null
+++ b/zencore/testing.cpp
@@ -0,0 +1,52 @@
+#include "zencore/testing.h"
+#include "zencore/logging.h"
+
+#if ZEN_WITH_TESTS
+
+namespace zen::testing {
+
+using namespace std::literals;
+
+struct TestRunner::Impl
+{
+ doctest::Context Session;
+};
+
+TestRunner::TestRunner()
+{
+ m_Impl = std::make_unique<Impl>();
+}
+
+TestRunner::~TestRunner()
+{
+}
+
+int
+TestRunner::ApplyCommandLine(int argc, char const* const* argv)
+{
+ m_Impl->Session.applyCommandLine(argc, argv);
+
+ for (int i = 1; i < argc; ++i)
+ {
+ if (argv[i] == "--debug"sv)
+ {
+ spdlog::set_level(spdlog::level::debug);
+ }
+ }
+
+ return 0;
+}
+
+int
+TestRunner::Run()
+{
+ int Rv = 0;
+
+ m_Impl->Session.run();
+
+ return Rv;
+}
+
+} // namespace zen::testing
+
+#endif
diff --git a/zenhttp/httpasio.cpp b/zenhttp/httpasio.cpp
index f270c9d2b..510b349f9 100644
--- a/zenhttp/httpasio.cpp
+++ b/zenhttp/httpasio.cpp
@@ -1077,8 +1077,9 @@ HttpAsioServerRequest::HttpAsioServerRequest(asio_http::HttpRequest& Request, Ht
std::string_view Uri = Request.Url();
Uri.remove_prefix(std::min(PrefixLength, static_cast<int>(Uri.size())));
- m_Uri = Uri;
- m_QueryString = Request.QueryString();
+ m_Uri = Uri;
+ m_UriWithExtension = Uri;
+ m_QueryString = Request.QueryString();
m_Verb = Request.RequestVerb();
m_ContentLength = Request.Body().Size();
diff --git a/zenhttp/httpsys.cpp b/zenhttp/httpsys.cpp
index 16ec135cd..0f4fe0a6d 100644
--- a/zenhttp/httpsys.cpp
+++ b/zenhttp/httpsys.cpp
@@ -1232,6 +1232,9 @@ HttpSysServerRequest::HttpSysServerRequest(HttpSysTransaction& Tx, HttpService&
std::string_view UriSuffix8{m_UriUtf8};
+ m_UriWithExtension = UriSuffix8; // Retain URI with extension for user access
+ m_Uri = UriSuffix8;
+
const size_t LastComponentIndex = UriSuffix8.find_last_of('/');
if (LastComponentIndex != std::string_view::npos)
@@ -1244,22 +1247,18 @@ HttpSysServerRequest::HttpSysServerRequest(HttpSysTransaction& Tx, HttpService&
if (LastDotIndex != std::string_view::npos)
{
UriSuffix8.remove_prefix(LastDotIndex + 1);
+ m_Uri.remove_suffix(UriSuffix8.size() + 1);
AcceptContentType = ParseContentType(UriSuffix8);
-
- if (AcceptContentType != HttpContentType::kUnknownContentType)
- {
- m_UriUtf8.RemoveSuffix((uint32_t)(UriSuffix8.size() + 1));
- }
}
}
else
{
m_UriUtf8.Reset();
+ m_Uri = {};
+ m_UriWithExtension = {};
}
- m_Uri = std::string_view(m_UriUtf8);
-
if (uint16_t QueryStringLength = HttpRequestPtr->CookedUrl.QueryStringLength)
{
--QueryStringLength; // We skip the leading question mark
diff --git a/zenhttp/include/zenhttp/httpserver.h b/zenhttp/include/zenhttp/httpserver.h
index 451a47b4a..3b9fa50b4 100644
--- a/zenhttp/include/zenhttp/httpserver.h
+++ b/zenhttp/include/zenhttp/httpserver.h
@@ -34,6 +34,7 @@ public:
// Synchronous operations
[[nodiscard]] inline std::string_view RelativeUri() const { return m_Uri; } // Returns URI without service prefix
+ [[nodiscard]] std::string_view RelativeUriWithExtension() const { return m_UriWithExtension; }
[[nodiscard]] inline std::string_view QueryString() const { return m_QueryString; }
struct QueryParams
@@ -118,6 +119,7 @@ protected:
HttpContentType m_AcceptType = HttpContentType::kUnknownContentType;
uint64_t m_ContentLength = ~0ull;
std::string_view m_Uri;
+ std::string_view m_UriWithExtension;
std::string_view m_QueryString;
mutable uint32_t m_RequestId = ~uint32_t(0);
mutable Oid m_SessionId = Oid::Zero;
diff --git a/zenserver-test/zenserver-test.cpp b/zenserver-test/zenserver-test.cpp
index 1f320f2f6..3195181d1 100644
--- a/zenserver-test/zenserver-test.cpp
+++ b/zenserver-test/zenserver-test.cpp
@@ -300,7 +300,7 @@ main()
return 0;
}
#elif 0
-//#include <restinio/all.hpp>
+// #include <restinio/all.hpp>
int
main()
@@ -317,6 +317,8 @@ zen::ZenServerEnvironment TestEnv;
int
main(int argc, char** argv)
{
+ using namespace std::literals;
+
# if ZEN_USE_MIMALLOC
mi_version();
# endif
@@ -333,11 +335,31 @@ main(int argc, char** argv)
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);
+ // This is pretty janky because we're passing most of the options through to the test
+ // framework, so we can't just use cxxopts (I think). This should ideally be cleaned up
+ // somehow in the future
+
+ std::string ServerClass;
+
+ for (int i = 1; i < argc; ++i)
+ {
+ if (argv[i] == "--http"sv)
+ {
+ if ((i + 1) < argc)
+ {
+ ServerClass = argv[++i];
+ }
+ }
+ }
+
+ TestEnv.InitializeForTest(ProgramBaseDir, TestBaseDir, ServerClass);
ZEN_INFO("Running tests...(base dir: '{}')", TestBaseDir);
- return ZEN_RUN_TESTS(argc, argv);
+ zen::testing::TestRunner Runner;
+ Runner.ApplyCommandLine(argc, argv);
+
+ return Runner.Run();
}
namespace zen::tests {
@@ -454,7 +476,7 @@ TEST_CASE("project.basic")
ZenServerInstance Instance1(TestEnv);
Instance1.SetTestDir(TestDir);
- Instance1.SpawnServer(PortNumber, "--http asio");
+ Instance1.SpawnServer(PortNumber);
Instance1.WaitUntilReady();
std::atomic<uint64_t> RequestCount{0};
@@ -1711,19 +1733,17 @@ TEST_CASE("zcache.failing.upstream")
using namespace std::literals;
using namespace utils;
- const uint16_t Upstream1PortNumber = 13338;
- ZenConfig Upstream1Cfg = ZenConfig::New(Upstream1PortNumber);
- Upstream1Cfg.Args += (" --http asio");
+ const uint16_t Upstream1PortNumber = 13338;
+ ZenConfig Upstream1Cfg = ZenConfig::New(Upstream1PortNumber);
ZenServerInstance Upstream1Server(TestEnv);
- const uint16_t Upstream2PortNumber = 13339;
- ZenConfig Upstream2Cfg = ZenConfig::New(Upstream2PortNumber);
- Upstream2Cfg.Args += (" --http asio");
+ const uint16_t Upstream2PortNumber = 13339;
+ ZenConfig Upstream2Cfg = ZenConfig::New(Upstream2PortNumber);
ZenServerInstance Upstream2Server(TestEnv);
std::vector<std::uint16_t> UpstreamPorts = {Upstream1PortNumber, Upstream2PortNumber};
ZenConfig LocalCfg = ZenConfig::NewWithThreadedUpstreams(UpstreamPorts, false);
- LocalCfg.Args += (" --http asio --upstream-thread-count 2");
+ LocalCfg.Args += (" --upstream-thread-count 2");
ZenServerInstance LocalServer(TestEnv);
const uint16_t LocalPortNumber = 13337;
const auto LocalUri = fmt::format("http://localhost:{}/z$", LocalPortNumber);
diff --git a/zenserver/frontend/frontend.cpp b/zenserver/frontend/frontend.cpp
index e0b27ac55..149d97924 100644
--- a/zenserver/frontend/frontend.cpp
+++ b/zenserver/frontend/frontend.cpp
@@ -75,7 +75,7 @@ HttpFrontendService::HandleRequest(zen::HttpServerRequest& Request)
{
using namespace std::literals;
- std::string_view Uri = Request.RelativeUri();
+ std::string_view Uri = Request.RelativeUriWithExtension();
for (; Uri[0] == '/'; Uri = Uri.substr(1))
;
if (Uri.empty())
diff --git a/zenserver/zenserver.cpp b/zenserver/zenserver.cpp
index 443bb627e..5b861f1bc 100644
--- a/zenserver/zenserver.cpp
+++ b/zenserver/zenserver.cpp
@@ -50,7 +50,7 @@ ZEN_THIRD_PARTY_INCLUDES_END
// in some shared code into the executable
#if ZEN_WITH_TESTS
-# define ZEN_TEST_WITH_RUNNER
+# define ZEN_TEST_WITH_RUNNER 1
# include <zencore/testing.h>
#endif
diff --git a/zenutil/include/zenutil/zenserverprocess.h b/zenutil/include/zenutil/zenserverprocess.h
index 3ec4b19b0..1c204c144 100644
--- a/zenutil/include/zenutil/zenserverprocess.h
+++ b/zenutil/include/zenutil/zenserverprocess.h
@@ -20,19 +20,21 @@ public:
~ZenServerEnvironment();
void Initialize(std::filesystem::path ProgramBaseDir);
- void InitializeForTest(std::filesystem::path ProgramBaseDir, std::filesystem::path TestBaseDir);
+ void InitializeForTest(std::filesystem::path ProgramBaseDir, std::filesystem::path TestBaseDir, std::string_view ServerClass = "");
- std::filesystem::path CreateNewTestDir();
- std::filesystem::path ProgramBaseDir() const { return m_ProgramBaseDir; }
- std::filesystem::path GetTestRootDir(std::string_view Path);
- inline bool IsInitialized() const { return m_IsInitialized; }
- inline bool IsTestEnvironment() const { return m_IsTestInstance; }
+ std::filesystem::path CreateNewTestDir();
+ std::filesystem::path ProgramBaseDir() const { return m_ProgramBaseDir; }
+ std::filesystem::path GetTestRootDir(std::string_view Path);
+ inline bool IsInitialized() const { return m_IsInitialized; }
+ inline bool IsTestEnvironment() const { return m_IsTestInstance; }
+ inline std::string_view GetServerClass() const { return m_ServerClass; }
private:
std::filesystem::path m_ProgramBaseDir;
std::filesystem::path m_TestBaseDir;
bool m_IsInitialized = false;
bool m_IsTestInstance = false;
+ std::string m_ServerClass;
};
struct ZenServerInstance
diff --git a/zenutil/zenserverprocess.cpp b/zenutil/zenserverprocess.cpp
index 659eb665b..5ecde343b 100644
--- a/zenutil/zenserverprocess.cpp
+++ b/zenutil/zenserverprocess.cpp
@@ -397,8 +397,12 @@ ZenServerEnvironment::Initialize(std::filesystem::path ProgramBaseDir)
}
void
-ZenServerEnvironment::InitializeForTest(std::filesystem::path ProgramBaseDir, std::filesystem::path TestBaseDir)
+ZenServerEnvironment::InitializeForTest(std::filesystem::path ProgramBaseDir,
+ std::filesystem::path TestBaseDir,
+ std::string_view ServerClass)
{
+ using namespace std::literals;
+
m_ProgramBaseDir = ProgramBaseDir;
m_TestBaseDir = TestBaseDir;
@@ -408,6 +412,19 @@ ZenServerEnvironment::InitializeForTest(std::filesystem::path ProgramBaseDir, st
m_IsTestInstance = true;
m_IsInitialized = true;
+
+ if (ServerClass.empty())
+ {
+#if ZEN_WITH_HTTPSYS
+ m_ServerClass = "httpsys"sv;
+#else
+ m_ServerClass = "asio"sv;
+#endif
+ }
+ else
+ {
+ m_ServerClass = ServerClass;
+ }
}
std::filesystem::path
@@ -516,6 +533,11 @@ ZenServerInstance::SpawnServer(int BasePort, std::string_view AdditionalServerAr
CommandLine << " --child-id " << ChildEventName;
+ if (std::string_view ServerClass = m_Env.GetServerClass(); ServerClass.empty() == false)
+ {
+ CommandLine << " --http " << ServerClass;
+ }
+
if (BasePort)
{
CommandLine << " --port " << BasePort;