Run clang-tidy; improve types.hpp, added subheaders
This commit is contained in:
parent
cf9f791de1
commit
8ed2a666f8
@ -35,9 +35,9 @@ CheckOptions:
|
||||
- { key: readability-identifier-naming.EnumIgnoredRegexp, value: '^.*_t$' }
|
||||
|
||||
# Abstract Class Name
|
||||
# - { key: readability-identifier-naming.AbstractClassPrefix,value: 'I' }
|
||||
# - { key: readability-identifier-naming.AbstractClassIgnoredRegexp,
|
||||
# value: '^.*able$|^.*Base$|^Abstract.*|^Component$' }
|
||||
- { key: readability-identifier-naming.AbstractClassPrefix, value: 'I' }
|
||||
- { key: readability-identifier-naming.AbstractClassIgnoredRegexp,
|
||||
value: '^.*able$|^.*Base$|^Abstract.*|^Component$' }
|
||||
|
||||
# Template Parameters
|
||||
- { key: readability-identifier-naming.TypeTemplateParameterPrefix,
|
||||
|
3
.gitignore
vendored
3
.gitignore
vendored
@ -56,4 +56,7 @@ release/*
|
||||
|
||||
*-build/
|
||||
*debug/
|
||||
|
||||
|
||||
docs/*
|
||||
*.bak
|
||||
|
@ -67,4 +67,4 @@ main(int argc, const char* argv[], const char* envp[])
|
||||
}
|
||||
|
||||
// clang-format off
|
||||
// vim: set foldmethod=marker foldmarker=#region,#endregion textwidth=80 ts=8 sts=0 sw=8 noexpandtab ft=cpp.doxygen :
|
||||
// vim: set foldmethod=marker foldmarker=@{,@} textwidth=80 ts=8 sts=0 sw=8 noexpandtab ft=cpp.doxygen :
|
||||
|
@ -16,36 +16,33 @@
|
||||
|
||||
namespace mdml {
|
||||
|
||||
// NOLINTNEXTLINE(readability-identifier-naming)
|
||||
class Application {
|
||||
public:
|
||||
Application(int argc, c::const_string argv[], c::const_string env[]);
|
||||
virtual ~Application() = default;
|
||||
|
||||
// @{ Disabled constructors and operators
|
||||
Application(Application&&) = delete;
|
||||
Application(const Application&) = delete;
|
||||
Application& operator=(const Application&) = delete;
|
||||
auto operator=(const Application&) -> Application& = delete;
|
||||
auto operator=(Application&&) -> Application& = delete;
|
||||
// @}
|
||||
|
||||
inline static Application& GetInstance() { return *instance_ptr; };
|
||||
virtual ~Application();
|
||||
|
||||
// #region Getters
|
||||
inline const std::vector<std::string>& Arguments()
|
||||
// Getters
|
||||
auto getArguments() -> const std::vector<std::string>&
|
||||
{
|
||||
return this->arguments;
|
||||
}
|
||||
inline const Dictionary<const std::string>& Environment()
|
||||
auto getEnvironment() -> const Dictionary<const std::string>&
|
||||
{
|
||||
return this->environment_variables;
|
||||
}
|
||||
|
||||
inline const std::string& GetEnv(const std::string& key)
|
||||
{
|
||||
return this->environment_variables[key];
|
||||
} /* #endregion */
|
||||
|
||||
private:
|
||||
static count_t instance_count;
|
||||
static Application* instance_ptr;
|
||||
virtual auto run() -> int = 0;
|
||||
|
||||
protected:
|
||||
Application(int argc, c::const_string argv[], c::const_string env[]);
|
||||
|
||||
void parse_arguments(int argc, c::const_string argv[]);
|
||||
void create_env_dictionary(c::const_string envp[]);
|
||||
|
||||
@ -55,4 +52,4 @@ class Application {
|
||||
}
|
||||
|
||||
// clang-format off
|
||||
// vim: set foldmethod=marker foldmarker=#region,#endregion textwidth=81 ts=8 sts=0 sw=8 noexpandtab ft=cpp.doxygen :
|
||||
// vim: set foldmethod=marker foldmarker=@{,@} textwidth=81 ts=8 sts=0 sw=8 noexpandtab ft=cpp.doxygen :
|
||||
|
@ -23,22 +23,26 @@ class IRouteHandler;
|
||||
class CgiApplication : public Application {
|
||||
|
||||
public:
|
||||
using RouteDictionary = Dictionary<route::ptr<IRouteHandler>>;
|
||||
using RouteDictionary = Dictionary<std::shared_ptr<IRouteHandler>>;
|
||||
|
||||
CgiApplication(int argc, c::const_string argv[], c::const_string env[]);
|
||||
virtual ~CgiApplication();
|
||||
~CgiApplication() override;
|
||||
|
||||
Result<std::string> ProcessRequest();
|
||||
|
||||
inline void ImportRoutes(RouteDictionary& route_collection)
|
||||
{
|
||||
this->Routes = std::move(route_collection);
|
||||
}
|
||||
// Disabled copy and assignment operators @{
|
||||
CgiApplication(const CgiApplication&) = delete;
|
||||
CgiApplication(CgiApplication&&) = delete;
|
||||
auto operator=(const CgiApplication&) -> CgiApplication& = delete;
|
||||
auto operator=(CgiApplication&&) -> CgiApplication& = delete;
|
||||
// @}
|
||||
|
||||
auto run() -> int override;
|
||||
auto processRequest() -> Result<std::string>;
|
||||
|
||||
/// \todo make this private, and have the unit test inspect it with a
|
||||
/// helper friend class.
|
||||
RouteDictionary Routes;
|
||||
};
|
||||
|
||||
}
|
||||
// clang-format off
|
||||
// vim: set foldmethod=marker foldmarker=#region,#endregion textwidth=81 ts=8 sts=0 sw=8 noexpandtab ft=cpp.doxygen :
|
||||
// vim: set foldmethod=marker foldmarker=@{,@} textwidth=81 ts=8 sts=0 sw=8 noexpandtab ft=cpp.doxygen :
|
||||
|
@ -12,30 +12,25 @@
|
||||
#include "private/debuginfo.hpp"
|
||||
#include "types.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <exception>
|
||||
#include <optional>
|
||||
#include <sstream>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
|
||||
namespace mdml {
|
||||
|
||||
class exception : public std::exception {
|
||||
namespace messages {
|
||||
constexpr auto kExceptionDefault = "An exception has ocurred!";
|
||||
}
|
||||
|
||||
class Exception : public std::exception {
|
||||
|
||||
public:
|
||||
exception(c::const_string _message = default_error);
|
||||
exception(const std::string& message);
|
||||
Exception(c::const_string _message = messages::kExceptionDefault);
|
||||
Exception(const std::string& message);
|
||||
|
||||
exception(const mdml::exception& other) = default;
|
||||
exception(const std::exception& inner);
|
||||
Exception(const mdml::Exception& other) = default;
|
||||
Exception(const std::exception& inner);
|
||||
|
||||
exception& operator=(const exception&) = delete;
|
||||
auto operator=(const Exception&) -> Exception& = delete;
|
||||
|
||||
virtual const char* what() const noexcept override;
|
||||
const std::string& stacktrace() const noexcept;
|
||||
|
||||
constexpr static auto default_error = "An exception has ocurred!";
|
||||
auto what() const noexcept -> const char* override;
|
||||
auto stacktrace() const noexcept -> const std::string&;
|
||||
|
||||
private:
|
||||
void build_what_message();
|
@ -16,9 +16,9 @@
|
||||
namespace mdml {
|
||||
struct IRouteHandler {
|
||||
virtual ~IRouteHandler() = default;
|
||||
virtual Result<std::string> Process(
|
||||
virtual auto process(
|
||||
const std::string& name, const std::string& request_uri
|
||||
) = 0;
|
||||
) -> Result<std::string> = 0;
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -31,31 +31,31 @@ class MarkdownRouteHandler : public IRouteHandler {
|
||||
, OutputStream()
|
||||
{
|
||||
}*/
|
||||
virtual ~MarkdownRouteHandler();
|
||||
~MarkdownRouteHandler() override;
|
||||
|
||||
void LoadTemplate(const fs::path& template_name);
|
||||
void LoadMarkdown(const fs::path& markdown_page_name);
|
||||
void loadTemplate(const fs::path& template_name);
|
||||
void loadMarkdown(const fs::path& markdown_page_name);
|
||||
|
||||
virtual Result<std::string> Process(
|
||||
const std::string& name, const std::string& request_uri
|
||||
);
|
||||
auto process(const std::string& name, const std::string& request_uri)
|
||||
-> Result<std::string> override;
|
||||
|
||||
std::string& GetHtmlData() { return html_data; }
|
||||
std::string& GetMarkdownData() { return markdown_data; }
|
||||
auto getHtmlData() -> std::string& { return html_data; }
|
||||
auto getMarkdownData() -> std::string& { return markdown_data; }
|
||||
|
||||
static Dictionary<route::ptr<IRouteHandler>> GenerateRoutes(MarkdownRouteHandler& ref,
|
||||
std::filesystem::path content_dir,
|
||||
// NOLINTNEXTLINE(readability-identifier-naming)
|
||||
static auto GenerateRoutes(
|
||||
MarkdownRouteHandler& ref, std::filesystem::path content_dir,
|
||||
std::filesystem::path main_template
|
||||
);
|
||||
) -> Dictionary<std::shared_ptr<IRouteHandler>>;
|
||||
|
||||
std::reference_wrapper<std::ostream> OutputStream;
|
||||
|
||||
const fs::path& getWorkingDir() { return this->work_dir; }
|
||||
auto getWorkingDir() -> const fs::path& { return this->work_dir; }
|
||||
|
||||
protected:
|
||||
std::string render_document(
|
||||
auto render_document(
|
||||
const std::string& title, const std::string& request_uri
|
||||
);
|
||||
) -> std::string;
|
||||
|
||||
static void load_document(
|
||||
const fs::path& document_path, std::string& out_document
|
||||
|
46
include/private/assert.hpp
Normal file
46
include/private/assert.hpp
Normal file
@ -0,0 +1,46 @@
|
||||
/* assert.hpp
|
||||
* Copyright © 2024 Saul D. Beniquez
|
||||
* License: Mozilla Public License v. 2.0
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public License,
|
||||
* v.2.0. If a copy of the MPL was not distributed with this file, You can
|
||||
* obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "types/ctypes.hpp"
|
||||
|
||||
#include "Exception.hpp"
|
||||
|
||||
#include <sstream>
|
||||
|
||||
#define ASSERT(condition) \
|
||||
if (condition == false) { \
|
||||
mdml::assert_impl(#condition); \
|
||||
}
|
||||
|
||||
#define ASSERT_MSG(condition, msg) \
|
||||
if (condition == false) { \
|
||||
mdml::assert_impl(#condition, msg); \
|
||||
}
|
||||
|
||||
namespace mdml {
|
||||
|
||||
inline void
|
||||
assert_impl(c::const_string failed_condition, c::const_string assert_reason = "")
|
||||
{
|
||||
std::stringstream assert_buffer;
|
||||
assert_buffer << failed_condition << " is false!";
|
||||
|
||||
if (std::strlen(assert_reason) > 0) {
|
||||
assert_buffer << std::endl
|
||||
<< "\tassert_resion: " << assert_reason;
|
||||
}
|
||||
assert_buffer << std::flush;
|
||||
throw Exception(assert_buffer.str());
|
||||
}
|
||||
}
|
||||
|
||||
// clang-format off
|
||||
// vim: set foldmethod=syntax foldminlines=10 textwidth=80 ts=8 sts=0 sw=8 noexpandtab ft=cpp.doxygen :
|
@ -20,7 +20,7 @@
|
||||
|
||||
namespace mdml {
|
||||
|
||||
std::string generate_stacktrace(unsigned short framesToRemove = 1);
|
||||
auto generate_stacktrace(unsigned short framesToRemove = 1) -> std::string;
|
||||
|
||||
void print_cmdline(int argc, const char* argv[]);
|
||||
|
||||
|
@ -14,17 +14,17 @@ struct Platform {
|
||||
#ifdef __linux__
|
||||
static constexpr bool LINUX = true;
|
||||
#else
|
||||
static constexpr bool LINUX = false;
|
||||
static constexpr bool kLinux = false;
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
static constexpr bool WINDOWS = true;
|
||||
#else
|
||||
static constexpr bool WINDOWS = false;
|
||||
static constexpr bool kWindows = false;
|
||||
#endif
|
||||
|
||||
#ifdef __APPLE__
|
||||
static constexpr bool MACOS = true;
|
||||
static constexpr bool kMacos = true;
|
||||
#else
|
||||
static constexpr bool MACOS = false;
|
||||
#endif
|
||||
@ -32,7 +32,7 @@ struct Platform {
|
||||
#ifdef __FreeBSD__
|
||||
static constexpr bool FREEBSD = true;
|
||||
#else
|
||||
static constexpr bool FREEBSD = false;
|
||||
static constexpr bool kFreebsd = false;
|
||||
#endif
|
||||
|
||||
// I don't own any AIX, Solaris, HP-UX, or pure Darwin systems, sorry :)
|
||||
|
@ -9,50 +9,11 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <functional>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
namespace mdml {
|
||||
namespace c {
|
||||
using string = char*;
|
||||
using const_string = const char*;
|
||||
}
|
||||
|
||||
namespace route {
|
||||
template<typename T>
|
||||
using ptr = std::shared_ptr<T>;
|
||||
template<typename T>
|
||||
inline static ptr<T>
|
||||
make_ptr()
|
||||
{
|
||||
return std::make_shared<T>();
|
||||
}
|
||||
}
|
||||
|
||||
enum error_t : bool { NO_ERROR = false, ERROR = true };
|
||||
using count_t = size_t;
|
||||
|
||||
template<typename T>
|
||||
using reference = std::reference_wrapper<T>;
|
||||
|
||||
template<typename T>
|
||||
using optional_reference = std::optional<std::reference_wrapper<T>>;
|
||||
|
||||
template<typename T>
|
||||
using const_reference = std::reference_wrapper<const T>;
|
||||
|
||||
template<typename T>
|
||||
using opt_const_reference = std::optional<const_reference<const T>>;
|
||||
|
||||
template<typename value_t>
|
||||
using Dictionary = std::map<const std::string, value_t>;
|
||||
}
|
||||
|
||||
#include "types/Result.hpp"
|
||||
#include "types/ctypes.hpp"
|
||||
|
||||
#include "types/Collections.hpp"
|
||||
#include "types/References.hpp"
|
||||
|
||||
// clang-format off
|
||||
// vim: set foldmethod=marker foldmarker=#region,#endregion textwidth=80 ts=8 sts=0 sw=8 noexpandtab ft=cpp.doxygen :
|
||||
|
20
include/types/Collections.hpp
Normal file
20
include/types/Collections.hpp
Normal file
@ -0,0 +1,20 @@
|
||||
/* Collections.hpp
|
||||
* Copyright © 2024 Saul D. Beniquez
|
||||
* License: Mozilla Public License v. 2.0
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public License,
|
||||
* v.2.0. If a copy of the MPL was not distributed with this file, You can
|
||||
* obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <map>
|
||||
|
||||
namespace mdml {
|
||||
template<typename TValue>
|
||||
using Dictionary = std::map<const std::string, TValue>;
|
||||
}
|
||||
|
||||
// clang-format off
|
||||
// vim: set foldmethod=syntax foldminlines=10 textwidth=80 ts=8 sts=0 sw=8 noexpandtab ft=cpp.doxygen :
|
30
include/types/References.hpp
Normal file
30
include/types/References.hpp
Normal file
@ -0,0 +1,30 @@
|
||||
/* ReferenTypes.hpp
|
||||
* Copyright © 2024 Saul D. Beniquez
|
||||
* License: Mozilla Public License v. 2.0
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public License,
|
||||
* v.2.0. If a copy of the MPL was not distributed with this file, You can
|
||||
* obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <functional>
|
||||
|
||||
namespace mdml {
|
||||
|
||||
template<typename T>
|
||||
using Reference = std::reference_wrapper<T>;
|
||||
|
||||
template<typename T>
|
||||
using OptionalReference = std::optional<std::reference_wrapper<T>>;
|
||||
|
||||
template<typename T>
|
||||
using ConstReference = std::reference_wrapper<const T>;
|
||||
|
||||
template<typename T>
|
||||
using OptConstReference = std::optional<ConstReference<const T>>;
|
||||
|
||||
}
|
||||
// clang-format off
|
||||
// vim: set foldmethod=syntax foldminlines=10 textwidth=80 ts=8 sts=0 sw=8 noexpandtab ft=cpp.doxygen :
|
@ -8,35 +8,39 @@
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "types.hpp"
|
||||
#include <utility>
|
||||
|
||||
namespace mdml {
|
||||
|
||||
enum error_t : bool { NoError = false, Error = true };
|
||||
|
||||
template<typename T>
|
||||
struct Result {
|
||||
|
||||
inline Result(const error_t& error_flag, const T error_data)
|
||||
: val(error_flag, error_data)
|
||||
Result(const error_t& error_flag, const T kErrorData)
|
||||
: val(error_flag, kErrorData)
|
||||
, IsError(this->val.first)
|
||||
, ErrorData(this->val.second)
|
||||
{
|
||||
}
|
||||
inline Result(const bool& error_flag, const T error_data)
|
||||
: val(error_t(error_flag), error_data)
|
||||
Result(bool error_flag, const T kErrorData)
|
||||
: val(static_cast<error_t>(error_flag), kErrorData)
|
||||
, IsError(this->val.first)
|
||||
, ErrorData(this->val.second)
|
||||
{
|
||||
}
|
||||
|
||||
// @{ Copy Constructors and assignment operator
|
||||
virtual ~Result() = default;
|
||||
Result(const Result& other) = default;
|
||||
inline Result& operator=(const Result& other)
|
||||
Result(Result&& other) = default;
|
||||
auto operator=(const Result& other) -> Result&
|
||||
{
|
||||
this->val = other.val;
|
||||
this->IsError = this->val.first;
|
||||
this->ErrorData = this->val.data;
|
||||
}
|
||||
//@}
|
||||
error_t& IsError;
|
||||
T& ErrorData;
|
||||
|
||||
@ -46,4 +50,4 @@ struct Result {
|
||||
|
||||
}
|
||||
// clang-format off
|
||||
// vim: set foldmethod=marker foldmarker=#region,#endregion textwidth=80 ts=8 sts=0 sw=8 noexpandtab ft=cpp.doxygen :
|
||||
// vim: set foldmethod=marker foldmarker=@{,@} textwidth=80 ts=8 sts=0 sw=8 noexpandtab ft=cpp.doxygen :
|
||||
|
24
include/types/ctypes.hpp
Normal file
24
include/types/ctypes.hpp
Normal file
@ -0,0 +1,24 @@
|
||||
/* ctypes.hpp
|
||||
* Copyright © 2024 Saul D. Beniquez
|
||||
* License: Mozilla Public License v. 2.0
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public License,
|
||||
* v.2.0. If a copy of the MPL was not distributed with this file, You can
|
||||
* obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
namespace mdml {
|
||||
using count_t = std::size_t;
|
||||
|
||||
namespace c {
|
||||
using string = char*;
|
||||
using const_string = const char*;
|
||||
}
|
||||
}
|
||||
|
||||
// clang-format off
|
||||
// vim: set foldmethod=syntax foldminlines=10 textwidth=80 ts=8 sts=0 sw=8 noexpandtab ft=cpp.doxygen :
|
@ -8,55 +8,30 @@
|
||||
*/
|
||||
|
||||
#include "Application.hpp"
|
||||
#include "exception.hpp"
|
||||
#include "Exception.hpp"
|
||||
|
||||
#include "types.hpp"
|
||||
|
||||
#include "private/assert.hpp"
|
||||
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <vector>
|
||||
|
||||
using namespace mdml;
|
||||
|
||||
count_t Application::instance_count = 0;
|
||||
Application* Application::instance_ptr = nullptr;
|
||||
|
||||
Application::Application(int argc, c::const_string argv[], c::const_string env[])
|
||||
: arguments(), environment_variables()
|
||||
{
|
||||
if (Application::instance_count != 0) {
|
||||
std::stringstream buffer;
|
||||
buffer << this->instance_count;
|
||||
|
||||
auto fatal_exception = std::logic_error(
|
||||
"Cannot instantiate more than one "
|
||||
"mdml::Application class at a time.\n"
|
||||
" instance_count = " +
|
||||
buffer.str()
|
||||
ASSERT_MSG(
|
||||
argv != nullptr, "Application constructor has null argv parameter"
|
||||
);
|
||||
ASSERT_MSG(
|
||||
env != nullptr, "Application constructor has null env parameter"
|
||||
);
|
||||
throw mdml::exception(fatal_exception);
|
||||
}
|
||||
|
||||
if (argv == nullptr || env == nullptr) {
|
||||
std::string problem = (argv == nullptr) ? "argv " : "envp ";
|
||||
auto message = "Cannot instantiate the application class "
|
||||
"with null " +
|
||||
problem + "parameter";
|
||||
|
||||
auto fatal_exception = std::logic_error(message);
|
||||
throw mdml::exception(fatal_exception);
|
||||
}
|
||||
|
||||
++(Application::instance_count);
|
||||
this->parse_arguments(argc, argv);
|
||||
this->create_env_dictionary(env);
|
||||
|
||||
Application::instance_ptr = this;
|
||||
}
|
||||
|
||||
Application::~Application()
|
||||
{
|
||||
--(Application::instance_count);
|
||||
Application::instance_ptr = nullptr;
|
||||
}
|
||||
|
||||
void
|
||||
@ -93,4 +68,4 @@ Application::create_env_dictionary(c::const_string envp[])
|
||||
}
|
||||
|
||||
// clang-format off
|
||||
// vim: set foldmethod=marker foldmarker=#region,#endregion textwidth=80 ts=8 sts=0 sw=8 noexpandtab ft=cpp.doxygen :
|
||||
// vim: set foldmethod=marker foldmarker=@{,@} textwidth=80 ts=8 sts=0 sw=8 noexpandtab ft=cpp.doxygen :
|
||||
|
@ -3,7 +3,7 @@
|
||||
|
||||
set(MDML_SOURCES
|
||||
libmdml.cpp
|
||||
exception.cpp
|
||||
Exception.cpp
|
||||
debuginfo.cpp
|
||||
Application.cpp
|
||||
CgiApplication.cpp
|
||||
|
@ -7,20 +7,21 @@
|
||||
* obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
#include "Application.hpp"
|
||||
#include "CgiApplication.hpp"
|
||||
#include "Application.hpp"
|
||||
#include "IRouteHandler.hpp"
|
||||
#include "exception.hpp"
|
||||
|
||||
#include "Exception.hpp"
|
||||
#include "types.hpp"
|
||||
|
||||
#include "private/assert.hpp"
|
||||
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
|
||||
using namespace mdml;
|
||||
|
||||
struct MarkdownTemplateRequestHandler : public IRouteHandler {};
|
||||
|
||||
CgiApplication::CgiApplication(
|
||||
int argc, c::const_string argv[], c::const_string env[]
|
||||
)
|
||||
@ -40,55 +41,67 @@ CgiApplication::~CgiApplication()
|
||||
}
|
||||
}
|
||||
|
||||
Result<std::string>
|
||||
CgiApplication::ProcessRequest()
|
||||
auto
|
||||
CgiApplication::run() -> int
|
||||
{
|
||||
|
||||
auto result = processRequest();
|
||||
return result.IsError;
|
||||
}
|
||||
|
||||
auto
|
||||
CgiApplication::processRequest() -> Result<std::string>
|
||||
{
|
||||
try {
|
||||
auto& environment = Application::environment_variables;
|
||||
auto dictionary_pair = environment.find("REQUEST_URI");
|
||||
|
||||
// Check if REQUEST_URI is in the environment map
|
||||
if (environment.find("REQUEST_URI") == environment.end()) {
|
||||
throw mdml::exception("No REQUEST_URI in Environment!");
|
||||
}
|
||||
ASSERT_MSG(
|
||||
dictionary_pair != environment.end(),
|
||||
"No REQUEST_URI in Environment!"
|
||||
)
|
||||
|
||||
try {
|
||||
/* Parse REQUEST_URI to get the route's basename */
|
||||
auto request_URI = environment["REQUEST_URI"];
|
||||
auto question_pos = request_URI.find('?');
|
||||
auto ampersand_pos = request_URI.find('&');
|
||||
auto page_name = request_URI;
|
||||
auto not_found = std::string::npos;
|
||||
auto request_uri = dictionary_pair->second;
|
||||
auto question_pos = request_uri.find('?');
|
||||
auto ampersand_pos = request_uri.find('&');
|
||||
auto page_name = request_uri;
|
||||
|
||||
if (question_pos == not_found) {
|
||||
if (ampersand_pos != not_found) {
|
||||
const auto kNotFound = std::string::npos;
|
||||
|
||||
/** \todo Make this make sense. Maybe create an array of parameters,
|
||||
* and ignore whether it starts with a ? or &. */
|
||||
if (question_pos == kNotFound) {
|
||||
if (ampersand_pos != kNotFound) {
|
||||
question_pos = ampersand_pos;
|
||||
}
|
||||
}
|
||||
if (question_pos != not_found) {
|
||||
page_name = request_URI.substr(0, question_pos);
|
||||
if (question_pos != kNotFound) {
|
||||
page_name = request_uri.substr(0, question_pos);
|
||||
}
|
||||
|
||||
if (Routes.find(page_name) != Routes.end()) {
|
||||
auto route_handler = Routes[page_name];
|
||||
auto result =
|
||||
route_handler->Process(page_name, request_URI);
|
||||
route_handler->process(page_name, request_uri);
|
||||
|
||||
/*
|
||||
if (result.IsError) {
|
||||
auto except =
|
||||
mdml::exception(result.ErrorData.c_str());
|
||||
throw except;
|
||||
Exception(result.ErrorData.c_str()); throw except;
|
||||
}
|
||||
*/
|
||||
|
||||
return result;
|
||||
} else {
|
||||
std::stringstream buffer;
|
||||
buffer << "Unknown route: " << page_name << std::endl;
|
||||
return { ERROR, buffer.str() };
|
||||
// throw mdml::exception(buffer.str().c_str());
|
||||
return { Error, buffer.str() };
|
||||
}
|
||||
} catch (const mdml::exception& except) {
|
||||
throw except;
|
||||
} catch (const std::exception& except) {
|
||||
throw mdml::exception(except);
|
||||
} catch (std::exception& stdexcept) {
|
||||
throw Exception(stdexcept);
|
||||
}
|
||||
}
|
||||
|
||||
// clang-format off
|
||||
// vim: set foldmethod=marker foldmarker=#region,#endregion textwidth=80 ts=8 sts=0 sw=8 noexpandtab ft=cpp.doxygen :
|
||||
// vim: set foldmethod=marker foldmarker=@{,@} textwidth=80 ts=8 sts=0 sw=8 noexpandtab ft=cpp.doxygen :
|
||||
|
@ -7,7 +7,7 @@
|
||||
file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
#include "exception.hpp"
|
||||
#include "Exception.hpp"
|
||||
|
||||
#include "private/debuginfo.hpp"
|
||||
#include "types.hpp"
|
||||
@ -20,75 +20,75 @@
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
|
||||
using mdml::exception;
|
||||
using namespace mdml;
|
||||
|
||||
constexpr unsigned DEFAULT_STACKFRAMES_TO_STRIP = 3;
|
||||
constexpr unsigned kDefaultStackframesToStrip = 3;
|
||||
|
||||
// Helper classes and functions. #region
|
||||
// Helper classes and functions. @{
|
||||
|
||||
exception::exception(c::const_string error_message)
|
||||
Exception::Exception(c::const_string error_message)
|
||||
: std::exception()
|
||||
, error_message(error_message)
|
||||
, what_message()
|
||||
, stack_trace(mdml::generate_stacktrace(DEFAULT_STACKFRAMES_TO_STRIP))
|
||||
, stack_trace(mdml::generate_stacktrace(kDefaultStackframesToStrip))
|
||||
, inner_exception_ptr()
|
||||
{
|
||||
build_what_message();
|
||||
}
|
||||
|
||||
exception::exception(const std::string& error_message)
|
||||
Exception::Exception(const std::string& error_message)
|
||||
: std::exception()
|
||||
, error_message(error_message)
|
||||
, what_message()
|
||||
, stack_trace(mdml::generate_stacktrace(DEFAULT_STACKFRAMES_TO_STRIP))
|
||||
, stack_trace(mdml::generate_stacktrace(kDefaultStackframesToStrip))
|
||||
, inner_exception_ptr()
|
||||
{
|
||||
build_what_message();
|
||||
}
|
||||
|
||||
exception::exception(const std::exception& inner)
|
||||
Exception::Exception(const std::exception& inner)
|
||||
: std::exception(inner)
|
||||
, error_message(inner.what())
|
||||
, what_message()
|
||||
, inner_exception_ptr(std::make_exception_ptr(&inner))
|
||||
, stack_trace(mdml::generate_stacktrace(DEFAULT_STACKFRAMES_TO_STRIP))
|
||||
, stack_trace(mdml::generate_stacktrace(kDefaultStackframesToStrip))
|
||||
{
|
||||
build_what_message();
|
||||
}
|
||||
|
||||
const char*
|
||||
exception::what() const noexcept
|
||||
auto
|
||||
Exception::what() const noexcept -> const char*
|
||||
{
|
||||
return this->what_message.c_str();
|
||||
}
|
||||
|
||||
const std::string&
|
||||
exception::stacktrace() const noexcept
|
||||
auto
|
||||
Exception::stacktrace() const noexcept -> const std::string&
|
||||
{
|
||||
return this->stack_trace;
|
||||
}
|
||||
|
||||
std::string
|
||||
prepend_tabs_to_lines(const std::string& input)
|
||||
auto
|
||||
prepend_tabs_to_lines(const std::string& input) -> std::string
|
||||
{
|
||||
std::ostringstream results_buffer;
|
||||
std::istringstream input_buffer(input);
|
||||
|
||||
// Function to add a tab character before each line
|
||||
auto addTabBeforeLine = [&results_buffer](const std::string& line) {
|
||||
auto add_tab_before_line = [&results_buffer](const std::string& line) {
|
||||
results_buffer << '\t' << line << '\n';
|
||||
};
|
||||
|
||||
// Process each line and add a tab character before it
|
||||
std::string line;
|
||||
while (std::getline(input_buffer, line)) {
|
||||
addTabBeforeLine(line);
|
||||
add_tab_before_line(line);
|
||||
}
|
||||
|
||||
return results_buffer.str();
|
||||
}
|
||||
void
|
||||
exception::build_what_message()
|
||||
Exception::build_what_message()
|
||||
{
|
||||
std::stringstream buffer;
|
||||
|
||||
@ -97,7 +97,7 @@ exception::build_what_message()
|
||||
std::string indented_stacktrace =
|
||||
prepend_tabs_to_lines(this->stack_trace);
|
||||
|
||||
buffer << "mdml::exception::what(): { " << std::endl
|
||||
buffer << "mdml::Exception::what(): { " << std::endl
|
||||
<< "\terror: " << error_message.c_str() << std::endl
|
||||
<< "\tstack_trace: " << std::endl
|
||||
<< indented_stacktrace << std::endl
|
@ -7,10 +7,10 @@
|
||||
* obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
#include "Application.hpp"
|
||||
#include "IRouteHandler.hpp"
|
||||
#include "MarkdownRouteHandler.hpp"
|
||||
#include "exception.hpp"
|
||||
#include "Application.hpp"
|
||||
#include "Exception.hpp"
|
||||
#include "IRouteHandler.hpp"
|
||||
#include "types.hpp"
|
||||
|
||||
#include "cmark.h"
|
||||
@ -23,8 +23,10 @@
|
||||
|
||||
using namespace mdml;
|
||||
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
namespace {
|
||||
const auto NOT_FOUND = std::string::npos;
|
||||
const auto kNotFound = std::string::npos;
|
||||
|
||||
void
|
||||
string_replace(
|
||||
@ -33,9 +35,9 @@ string_replace(
|
||||
)
|
||||
{
|
||||
for (auto pattern_pos = out_buffer.find(pattern);
|
||||
pattern_pos != NOT_FOUND;
|
||||
pattern_pos != kNotFound;
|
||||
pattern_pos = out_buffer.find(pattern)) {
|
||||
if (pattern_pos != NOT_FOUND) {
|
||||
if (pattern_pos != kNotFound) {
|
||||
out_buffer.replace(
|
||||
pattern_pos, pattern.length(), replacement
|
||||
);
|
||||
@ -44,7 +46,6 @@ string_replace(
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
MarkdownRouteHandler::MarkdownRouteHandler(fs::path working_dir)
|
||||
: IRouteHandler(), OutputStream(std::cout), work_dir(working_dir)
|
||||
{
|
||||
@ -53,7 +54,7 @@ MarkdownRouteHandler::MarkdownRouteHandler(fs::path working_dir)
|
||||
MarkdownRouteHandler::~MarkdownRouteHandler() {}
|
||||
|
||||
void
|
||||
MarkdownRouteHandler::LoadTemplate(const fs::path& template_filename)
|
||||
MarkdownRouteHandler::loadTemplate(const fs::path& template_filename)
|
||||
{
|
||||
fs::path full_html_path;
|
||||
|
||||
@ -66,7 +67,7 @@ MarkdownRouteHandler::LoadTemplate(const fs::path& template_filename)
|
||||
}
|
||||
|
||||
void
|
||||
MarkdownRouteHandler::LoadMarkdown(const fs::path& markdown_filename)
|
||||
MarkdownRouteHandler::loadMarkdown(const fs::path& markdown_filename)
|
||||
{
|
||||
fs::path full_md_path;
|
||||
|
||||
@ -79,31 +80,30 @@ MarkdownRouteHandler::LoadMarkdown(const fs::path& markdown_filename)
|
||||
this->load_document(full_md_path, this->markdown_data);
|
||||
}
|
||||
|
||||
Result<std::string>
|
||||
MarkdownRouteHandler::Process(
|
||||
auto
|
||||
MarkdownRouteHandler::process(
|
||||
const std::string& name, const std::string& request_uri
|
||||
)
|
||||
) -> Result<std::string>
|
||||
{
|
||||
auto document = render_document(name, request_uri);
|
||||
auto& out = OutputStream.get();
|
||||
|
||||
out << document << std::flush;
|
||||
|
||||
return { NO_ERROR, document };
|
||||
return { NoError, document };
|
||||
}
|
||||
|
||||
Dictionary<route::ptr<IRouteHandler>>
|
||||
MarkdownRouteHandler::GenerateRoutes(MarkdownRouteHandler& ref,
|
||||
std::filesystem::path content_dir, std::filesystem::path main_template
|
||||
)
|
||||
auto
|
||||
MarkdownRouteHandler::GenerateRoutes(
|
||||
MarkdownRouteHandler& ref, fs::path content_dir, fs::path main_template
|
||||
) -> Dictionary<std::shared_ptr<IRouteHandler>>
|
||||
{
|
||||
if (content_dir.is_relative()) {
|
||||
content_dir = ref.work_dir / content_dir;
|
||||
}
|
||||
Dictionary<route::ptr<IRouteHandler>> results;
|
||||
Dictionary<std::shared_ptr<IRouteHandler>> results;
|
||||
|
||||
for (const auto& entry :
|
||||
std::filesystem::directory_iterator(content_dir)) {
|
||||
for (const auto& entry : fs::directory_iterator(content_dir)) {
|
||||
if (entry.is_regular_file()) {
|
||||
auto filename = entry.path().filename().string();
|
||||
auto routename = entry.path().stem().string();
|
||||
@ -112,16 +112,17 @@ MarkdownRouteHandler::GenerateRoutes(MarkdownRouteHandler& ref,
|
||||
// Check if the file has a .md extension and a specific
|
||||
// name pattern
|
||||
if (extension == ".md") {
|
||||
auto& routeHandler = ref;
|
||||
auto& route_handler = ref;
|
||||
|
||||
// Load template and document
|
||||
routeHandler.LoadTemplate(
|
||||
route_handler.loadTemplate(
|
||||
(ref.work_dir / main_template).string()
|
||||
);
|
||||
routeHandler.LoadMarkdown(entry.path().string());
|
||||
route_handler.loadMarkdown(entry.path().string()
|
||||
);
|
||||
|
||||
// Move the routeHandler into the vector
|
||||
results.emplace(routename, &routeHandler);
|
||||
results.emplace(routename, &route_handler);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -136,17 +137,17 @@ MarkdownRouteHandler::load_document(
|
||||
{
|
||||
if (!fs::exists(document_path) || !fs::is_regular_file(document_path)) {
|
||||
auto error = "File not found: " + document_path.string();
|
||||
throw mdml::exception(error);
|
||||
throw Exception(error);
|
||||
}
|
||||
|
||||
try {
|
||||
std::ifstream file(document_path);
|
||||
if (file.is_open()) {
|
||||
std::string htmlContent(
|
||||
std::string html_content(
|
||||
(std::istreambuf_iterator<char>(file)),
|
||||
std::istreambuf_iterator<char>()
|
||||
);
|
||||
out_document = htmlContent;
|
||||
out_document = html_content;
|
||||
} else {
|
||||
auto error_message =
|
||||
(std::stringstream()
|
||||
@ -154,19 +155,19 @@ MarkdownRouteHandler::load_document(
|
||||
<< document_path.filename() << "', at path "
|
||||
<< document_path.parent_path() << ". ")
|
||||
.str();
|
||||
throw mdml::exception(error_message);
|
||||
throw Exception(error_message);
|
||||
}
|
||||
} catch (const mdml::exception& e) {
|
||||
} catch (const Exception& e) {
|
||||
throw e;
|
||||
} catch (const std::exception& e) {
|
||||
throw mdml::exception(e);
|
||||
throw Exception(e);
|
||||
}
|
||||
}
|
||||
|
||||
std::string
|
||||
auto
|
||||
MarkdownRouteHandler::render_document(
|
||||
const std::string& title, const std::string& request_uri
|
||||
)
|
||||
) -> std::string
|
||||
{
|
||||
std::string result = this->html_data;
|
||||
std::string token = "%content%";
|
||||
@ -183,4 +184,4 @@ MarkdownRouteHandler::render_document(
|
||||
return result;
|
||||
}
|
||||
// clang-format off
|
||||
// vim: set foldmethod=marker foldmarker=#region,#endregion textwidth=80 ts=8 sts=0 sw=8 noexpandtab ft=cpp.doxygen :
|
||||
// vim: set foldmethod=marker foldmarker=@{,@} textwidth=80 ts=8 sts=0 sw=8 noexpandtab ft=cpp.doxygen :
|
||||
|
@ -27,26 +27,26 @@ namespace mdml {
|
||||
namespace {
|
||||
|
||||
// Extracts the mangled symbol from a string like <func_name+0x34>
|
||||
std::string
|
||||
extract_mangled_symbol(const std::string& input)
|
||||
auto
|
||||
extract_mangled_symbol(const std::string& input) -> std::string
|
||||
{
|
||||
std::string result;
|
||||
bool insideAngleBrackets = false;
|
||||
bool inside_angle_brackets = false;
|
||||
|
||||
for (char c : input) {
|
||||
if (c == '<') {
|
||||
insideAngleBrackets = true;
|
||||
inside_angle_brackets = true;
|
||||
continue;
|
||||
}
|
||||
if (c == '>') {
|
||||
insideAngleBrackets = false;
|
||||
inside_angle_brackets = false;
|
||||
continue;
|
||||
}
|
||||
if (c == '+') {
|
||||
break;
|
||||
}
|
||||
|
||||
if (insideAngleBrackets) {
|
||||
if (inside_angle_brackets) {
|
||||
result += c;
|
||||
}
|
||||
}
|
||||
@ -57,8 +57,8 @@ extract_mangled_symbol(const std::string& input)
|
||||
|
||||
// There are a lot of C and platform-specific hacks contained within
|
||||
// I am sorry. 🤡
|
||||
std::string
|
||||
generate_stacktrace(unsigned short framesToRemove)
|
||||
auto
|
||||
generate_stacktrace(unsigned short framesToRemove) -> std::string
|
||||
{
|
||||
std::stringstream buffer;
|
||||
#ifndef BOOST_STACKTRACER
|
||||
@ -69,9 +69,9 @@ generate_stacktrace(unsigned short framesToRemove)
|
||||
size_t columns_to_print = 0;
|
||||
|
||||
// preconfigure column length for certain platforms
|
||||
if (Platform::FREEBSD) {
|
||||
if (Platform::kFreebsd) {
|
||||
columns_to_print = 2;
|
||||
} else if (Platform::MACOS) {
|
||||
} else if (Platform::kMacos) {
|
||||
columns_to_print = 4;
|
||||
}
|
||||
|
||||
|
@ -14,4 +14,4 @@ some_function()
|
||||
}
|
||||
|
||||
// clang-format off
|
||||
// vim: set foldmethod=marker foldmarker=#region,#endregion textwidth=80 ts=8 sts=0 sw=8 noexpandtab ft=cpp.doxygen :
|
||||
// vim: set foldmethod=marker foldmarker=@{,@} textwidth=80 ts=8 sts=0 sw=8 noexpandtab ft=cpp.doxygen :
|
||||
|
@ -7,7 +7,7 @@
|
||||
* obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
#include "exception.hpp"
|
||||
#include "Exception.hpp"
|
||||
#include "tests-common.hpp"
|
||||
|
||||
#include "Application.hpp"
|
||||
@ -15,33 +15,49 @@
|
||||
#include <functional>
|
||||
#include <optional>
|
||||
|
||||
struct simulated_launch {
|
||||
struct LaunchParameters {
|
||||
static const char* argv[];
|
||||
static const char* env[];
|
||||
};
|
||||
inline const char* simulated_launch::argv[] = { "param1", "param2", "param3" };
|
||||
inline const char* simulated_launch::env[] = { "PATH=/usr/bin",
|
||||
inline const char* LaunchParameters::argv[] = { "param1", "param2", "param3" };
|
||||
inline const char* LaunchParameters::env[] = {
|
||||
"PATH=/usr/bin",
|
||||
"VAR2=TWO",
|
||||
nullptr };
|
||||
|
||||
template<typename T>
|
||||
using opt_reference = std::optional<std::reference_wrapper<T>>;
|
||||
};
|
||||
|
||||
BEGIN_TEST_SUITE("Application-test")
|
||||
{
|
||||
using namespace mdml;
|
||||
|
||||
struct DerivedApplication : public mdml::Application {
|
||||
DerivedApplication(
|
||||
int argc = 0, c::const_string argv[] = {},
|
||||
c::const_string env[] = {}
|
||||
)
|
||||
: Application(argc, argv, env)
|
||||
{
|
||||
}
|
||||
auto run() -> int override { return 0; }
|
||||
};
|
||||
struct TestFixture {
|
||||
TestFixture() : derived_app() {}
|
||||
|
||||
DerivedApplication derived_app;
|
||||
};
|
||||
|
||||
TEST("Application Class construction")
|
||||
{
|
||||
auto simple_construction = []() {
|
||||
auto test_object = mdml::Application(
|
||||
3, simulated_launch::argv, simulated_launch::env
|
||||
auto test_object = DerivedApplication(
|
||||
3, LaunchParameters::argv, LaunchParameters::env
|
||||
);
|
||||
};
|
||||
auto double_construction = []() {
|
||||
auto test_object = mdml::Application(
|
||||
3, simulated_launch::argv, simulated_launch::env
|
||||
auto test_object = DerivedApplication(
|
||||
3, LaunchParameters::argv, LaunchParameters::env
|
||||
);
|
||||
auto throws_errors = mdml::Application(
|
||||
3, simulated_launch::argv, simulated_launch::env
|
||||
auto throws_errors = DerivedApplication(
|
||||
3, LaunchParameters::argv, LaunchParameters::env
|
||||
);
|
||||
};
|
||||
|
||||
@ -49,51 +65,29 @@ BEGIN_TEST_SUITE("Application-test")
|
||||
{
|
||||
REQUIRE_NOTHROW(simple_construction());
|
||||
}
|
||||
SECTION("Double construction")
|
||||
{
|
||||
REQUIRE_THROWS_AS(
|
||||
double_construction(), mdml::exception
|
||||
);
|
||||
}
|
||||
SECTION("Get existing instance")
|
||||
{
|
||||
opt_reference<mdml::Application> app;
|
||||
try {
|
||||
auto test_object = mdml::Application(
|
||||
3,
|
||||
simulated_launch::argv,
|
||||
simulated_launch::env
|
||||
);
|
||||
app = test_object;
|
||||
} catch (const mdml::exception& e) {
|
||||
app = mdml::Application::GetInstance();
|
||||
}
|
||||
}
|
||||
auto incorrect_construction = []() {
|
||||
mdml::Application obj(0, nullptr, nullptr);
|
||||
};
|
||||
|
||||
SECTION("Incorrect parameters")
|
||||
{
|
||||
REQUIRE_THROWS_AS(
|
||||
incorrect_construction(), mdml::exception
|
||||
);
|
||||
auto incorrect_construction = []() {
|
||||
DerivedApplication obj(0, nullptr, nullptr);
|
||||
};
|
||||
|
||||
REQUIRE_THROWS_AS(incorrect_construction(), Exception);
|
||||
}
|
||||
}
|
||||
|
||||
TEST("Application Parameter capture")
|
||||
{
|
||||
SECTION("Arguments are captured in vector")
|
||||
SECTION("getArguments are captured in vector")
|
||||
{
|
||||
auto correct_construction = []() {
|
||||
auto test_object = mdml::Application(
|
||||
auto correct_construction = [&]() {
|
||||
auto test_object = DerivedApplication(
|
||||
3,
|
||||
simulated_launch::argv,
|
||||
simulated_launch::env
|
||||
LaunchParameters::argv,
|
||||
LaunchParameters::env
|
||||
);
|
||||
auto args_list = test_object.Arguments();
|
||||
auto args_list = test_object.getArguments();
|
||||
|
||||
SECTION("Argument verification")
|
||||
SECTION("getArgument verification")
|
||||
{
|
||||
REQUIRE(args_list[0] == "param1");
|
||||
REQUIRE(args_list[1] == "param2");
|
||||
@ -103,13 +97,13 @@ BEGIN_TEST_SUITE("Application-test")
|
||||
}
|
||||
SECTION("Environemnt variables are catpured in map")
|
||||
{
|
||||
auto correct_construction = []() {
|
||||
auto test_object = mdml::Application(
|
||||
auto correct_construction = [&]() {
|
||||
auto test_object = DerivedApplication(
|
||||
3,
|
||||
simulated_launch::argv,
|
||||
simulated_launch::env
|
||||
LaunchParameters::argv,
|
||||
LaunchParameters::env
|
||||
);
|
||||
auto environ = test_object.Environment();
|
||||
auto environ = test_object.getEnvironment();
|
||||
|
||||
SECTION("Varaible verification")
|
||||
{
|
||||
|
@ -8,50 +8,49 @@
|
||||
*/
|
||||
|
||||
#include "CgiApplication.hpp"
|
||||
#include "Exception.hpp"
|
||||
#include "IRouteHandler.hpp"
|
||||
#include "exception.hpp"
|
||||
|
||||
#include "tests-common.hpp"
|
||||
#include <catch2/matchers/catch_matchers_string.hpp>
|
||||
|
||||
|
||||
BEGIN_TEST_SUITE("CgiApplication")
|
||||
{
|
||||
struct simulated_launch {
|
||||
using namespace mdml;
|
||||
struct SimulatedLaunch {
|
||||
static const char* argv[];
|
||||
static const char* env[];
|
||||
};
|
||||
inline const char* simulated_launch::argv[] = { "param1", "param2", "param3" };
|
||||
inline const char* simulated_launch::env[] = {
|
||||
};
|
||||
inline const char* SimulatedLaunch::argv[] = { "param1",
|
||||
"param2",
|
||||
"param3" };
|
||||
inline const char* SimulatedLaunch::env[] = {
|
||||
"PATH=/usr/bin",
|
||||
"VAR2=TWO",
|
||||
"REQUEST_URI=markdown?msg=hello-world",
|
||||
nullptr
|
||||
};
|
||||
};
|
||||
|
||||
// Define a test oute handler for the "/markdown" route
|
||||
class ExampleRouteHandler : public mdml::IRouteHandler {
|
||||
// Define a test oute handler for the "/markdown" route
|
||||
class ExampleRouteHandler : public mdml::IRouteHandler {
|
||||
public:
|
||||
virtual mdml::Result<std::string> Process(
|
||||
auto process(
|
||||
const std::string& name, const std::string& request_uri
|
||||
) override
|
||||
) -> mdml::Result<std::string> override
|
||||
{
|
||||
// Implement test logic for the route
|
||||
// handler
|
||||
return { mdml::NO_ERROR, "Processed" };
|
||||
return { mdml::NoError, "processed" };
|
||||
}
|
||||
virtual ~ExampleRouteHandler() = default;
|
||||
};
|
||||
~ExampleRouteHandler() override = default;
|
||||
};
|
||||
|
||||
|
||||
|
||||
using namespace mdml;
|
||||
struct TestFixture {
|
||||
const char* envp[4] = { "PATH=/usr/bin",
|
||||
"VAR2=TWO",
|
||||
"REQUEST_URI=markdown?msg=hello-world",
|
||||
nullptr };
|
||||
TestFixture() : cgi_app(1, simulated_launch::argv, envp) {}
|
||||
TestFixture() : cgi_app(1, SimulatedLaunch::argv, envp) {}
|
||||
|
||||
CgiApplication cgi_app;
|
||||
};
|
||||
@ -60,15 +59,15 @@ class ExampleRouteHandler : public mdml::IRouteHandler {
|
||||
{
|
||||
|
||||
CgiApplication test(
|
||||
1, simulated_launch::argv, simulated_launch::env
|
||||
1, SimulatedLaunch::argv, SimulatedLaunch::env
|
||||
);
|
||||
};
|
||||
|
||||
TEST("CgiApplication RegisterRoutes Test")
|
||||
{
|
||||
|
||||
CgiApplication test(
|
||||
1, simulated_launch::argv, simulated_launch::env
|
||||
CgiApplication test_app(
|
||||
1, SimulatedLaunch::argv, SimulatedLaunch::env
|
||||
);
|
||||
|
||||
mdml::CgiApplication::RouteDictionary routes;
|
||||
@ -76,40 +75,42 @@ class ExampleRouteHandler : public mdml::IRouteHandler {
|
||||
routes.emplace("test2", new ExampleRouteHandler());
|
||||
routes.emplace("fasdfdshjk", new ExampleRouteHandler());
|
||||
|
||||
test.ImportRoutes(routes);
|
||||
test_app.Routes = std::move(routes);
|
||||
|
||||
REQUIRE(routes.size() < 1);
|
||||
|
||||
REQUIRE(test.Routes.size() == 3);
|
||||
REQUIRE(test.Routes.at("test") != nullptr);
|
||||
REQUIRE(test_app.Routes.size() == 3);
|
||||
REQUIRE(test_app.Routes.at("test") != nullptr);
|
||||
};
|
||||
|
||||
TEST("CgiApplication::ProcessRequest no REQUEST_URI variable")
|
||||
TEST("CgiApplication::processRequest no REQUEST_URI variable")
|
||||
{
|
||||
const char* no_request_env[] = { "PATH=/usr/bin",
|
||||
"VAR2=TWO",
|
||||
nullptr };
|
||||
CgiApplication test(1, simulated_launch::argv, no_request_env);
|
||||
CgiApplication test_app(
|
||||
1, SimulatedLaunch::argv, no_request_env
|
||||
);
|
||||
REQUIRE_THROWS_AS(
|
||||
[&]() { test.ProcessRequest(); }(), mdml::exception
|
||||
[&]() { test_app.processRequest(); }(), mdml::Exception
|
||||
);
|
||||
}
|
||||
|
||||
FIXTURE_TEST("CgiApplication ProcessRequest with valid route")
|
||||
FIXTURE_TEST("CgiApplication processRequest with valid route")
|
||||
{
|
||||
|
||||
// Add the test route handler to the Routes dictionary
|
||||
auto handler = mdml::route::make_ptr<ExampleRouteHandler>();
|
||||
auto handler = std::make_shared<ExampleRouteHandler>();
|
||||
cgi_app.Routes["markdown"] = handler;
|
||||
|
||||
auto result = cgi_app.ProcessRequest();
|
||||
auto result = cgi_app.processRequest();
|
||||
|
||||
// Add assertions to check the result
|
||||
CHECK(result.ErrorData == "Processed");
|
||||
CHECK(result.ErrorData == "processed");
|
||||
REQUIRE(result.IsError == false);
|
||||
}
|
||||
|
||||
FIXTURE_TEST("CgiApplication ProcessRequest with unknown route")
|
||||
FIXTURE_TEST("CgiApplication processRequest with unknown route")
|
||||
{
|
||||
|
||||
// Remove the "markdown" route from the Routes
|
||||
@ -121,36 +122,35 @@ class ExampleRouteHandler : public mdml::IRouteHandler {
|
||||
cgi_app.Routes.erase(key);
|
||||
}
|
||||
|
||||
auto result = cgi_app.ProcessRequest();
|
||||
auto result = cgi_app.processRequest();
|
||||
|
||||
// Add assertions to check the result
|
||||
CHECK(result.ErrorData != "Success");
|
||||
REQUIRE(result.IsError == true);
|
||||
}
|
||||
|
||||
FIXTURE_TEST("CgiApplication ProcessRequest Route throws exception")
|
||||
FIXTURE_TEST("CgiApplication processRequest Route throws exception")
|
||||
{
|
||||
// Define a test oute handler for the "/markdown" route
|
||||
class BadRouteHandler : public IRouteHandler {
|
||||
public:
|
||||
virtual Result<std::string> Process(
|
||||
auto process(
|
||||
const std::string& name,
|
||||
const std::string& request_uri
|
||||
) override
|
||||
) -> Result<std::string> override
|
||||
{
|
||||
throw std::runtime_error("ERROR");
|
||||
return { mdml::ERROR,
|
||||
throw std::runtime_error("Error");
|
||||
return { mdml::Error,
|
||||
"This line never executes" };
|
||||
}
|
||||
virtual ~BadRouteHandler() = default;
|
||||
~BadRouteHandler() override = default;
|
||||
};
|
||||
auto handler = mdml::route::make_ptr<BadRouteHandler>();
|
||||
auto handler = std::make_shared<BadRouteHandler>();
|
||||
cgi_app.Routes["markdown"] = handler;
|
||||
|
||||
REQUIRE_THROWS_AS(
|
||||
[&]() { cgi_app.ProcessRequest(); }(), mdml::exception
|
||||
);
|
||||
REQUIRE_THROWS_AS(cgi_app.processRequest(), mdml::Exception);
|
||||
// REQUIRE(cgi_app.processRequest().IsError);
|
||||
}
|
||||
}
|
||||
// clang-format off
|
||||
// vim: set foldmethod=marker foldmarker=#region,#endregion textwidth=80 ts=8 sts=0 sw=8 noexpandtab ft=cpp.doxygen :
|
||||
// vim: set foldmethod=marker foldmarker=@{,@} textwidth=80 ts=8 sts=0 sw=8 noexpandtab ft=cpp.doxygen :
|
||||
|
@ -118,4 +118,4 @@ BEGIN_TEST_SUITE("MarkdownRouteHandler Unit Tests")
|
||||
}
|
||||
}
|
||||
// clang-format off
|
||||
// vim: set foldmethod=marker foldmarker=#region,#endregion textwidth=80 ts=8 sts=0 sw=8 noexpandtab ft=cpp.doxygen :
|
||||
// vim: set foldmethod=marker foldmarker=@{,@} textwidth=80 ts=8 sts=0 sw=8 noexpandtab ft=cpp.doxygen :
|
||||
|
@ -12,6 +12,8 @@
|
||||
#include "types.hpp"
|
||||
#include "types/Result.hpp"
|
||||
|
||||
#include <string>
|
||||
|
||||
BEGIN_TEST_SUITE("mdml::Result")
|
||||
{
|
||||
TEST("Construction of Result object")
|
||||
@ -19,14 +21,15 @@ BEGIN_TEST_SUITE("mdml::Result")
|
||||
SECTION("Using bool to initialize")
|
||||
{
|
||||
REQUIRE_NOTHROW([]() {
|
||||
mdml::Result test{ false, "Success" };
|
||||
mdml::Result<std::string> test{ false,
|
||||
"Success" };
|
||||
}());
|
||||
}
|
||||
|
||||
SECTION("Using error_t to initialize")
|
||||
{
|
||||
REQUIRE_NOTHROW([]() {
|
||||
mdml::Result test{ mdml::NO_ERROR, "Success" };
|
||||
mdml::Result test{ mdml::NoError, "Success" };
|
||||
}());
|
||||
}
|
||||
}
|
||||
@ -60,4 +63,4 @@ BEGIN_TEST_SUITE("mdml::Result")
|
||||
}
|
||||
|
||||
// clang-format off
|
||||
// vim: set foldmethod=marker foldmarker=#region,#endregion textwidth=80 ts=8 sts=0 sw=8 noexpandtab ft=cpp.doxygen :
|
||||
// vim: set foldmethod=marker foldmarker=@{,@} textwidth=80 ts=8 sts=0 sw=8 noexpandtab ft=cpp.doxygen :
|
||||
|
@ -33,5 +33,5 @@
|
||||
#endif
|
||||
|
||||
// clang-format off
|
||||
// vim: set foldmethod=marker foldmarker=#region,#endregion textwidth=80 ts=8 sts=0 sw=8 noexpandtab ft=cpp.doxygen :
|
||||
// vim: set foldmethod=marker foldmarker=@{,@} textwidth=80 ts=8 sts=0 sw=8 noexpandtab ft=cpp.doxygen :
|
||||
|
||||
|
@ -7,7 +7,7 @@
|
||||
* obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
#include "exception.hpp"
|
||||
#include "Exception.hpp"
|
||||
|
||||
#include "tests-common.hpp"
|
||||
|
||||
@ -28,13 +28,15 @@ throw_local_exception()
|
||||
auto local = std::logic_error("This is a stack variable");
|
||||
|
||||
// Stack variables should not be used outside their stack frames.
|
||||
throw mdml::exception(local);
|
||||
throw mdml::Exception(local);
|
||||
}
|
||||
|
||||
BEGIN_TEST_SUITE("mdml::exception")
|
||||
BEGIN_TEST_SUITE("Exception")
|
||||
{
|
||||
using namespace mdml;
|
||||
|
||||
auto throw_an_exception = []() {
|
||||
throw mdml::exception("An error occurred!!");
|
||||
throw Exception("An error occurred!!");
|
||||
};
|
||||
|
||||
TEST("TEST: Can throw new exception type")
|
||||
@ -46,20 +48,20 @@ BEGIN_TEST_SUITE("mdml::exception")
|
||||
{
|
||||
SECTION("1. Blank constructor")
|
||||
{
|
||||
mdml::exception obj;
|
||||
Exception obj;
|
||||
}
|
||||
SECTION("2a. With cstring parameter")
|
||||
{
|
||||
mdml::exception obj("Sample Error");
|
||||
Exception obj("Sample Error");
|
||||
}
|
||||
SECTION("2b. With std::string parameter")
|
||||
{
|
||||
mdml::exception obj(std::string("Sample Error"));
|
||||
Exception obj(std::string("Sample Error"));
|
||||
}
|
||||
|
||||
SECTION("3. With STL exception")
|
||||
{
|
||||
mdml::exception obj(std::runtime_error("Sample Error"));
|
||||
Exception obj(std::runtime_error("Sample Error"));
|
||||
}
|
||||
SECTION("4. With destroyed stack")
|
||||
{
|
||||
@ -84,22 +86,21 @@ BEGIN_TEST_SUITE("mdml::exception")
|
||||
|
||||
SECTION("1. Unspecified error or exception")
|
||||
{
|
||||
mdml::exception obj;
|
||||
Exception obj;
|
||||
|
||||
REQUIRE_THAT(
|
||||
obj.what(),
|
||||
Match::ContainsSubstring(
|
||||
mdml::exception::default_error,
|
||||
CaseSensitive::Yes
|
||||
messages::kExceptionDefault, CaseSensitive::Yes
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
SECTION("2. custom error or exception")
|
||||
{
|
||||
constexpr auto test_message = "This is a test.";
|
||||
mdml::exception test_object_one(test_message);
|
||||
mdml::exception test_object_two(
|
||||
constexpr auto kTestMessage = "This is a test.";
|
||||
Exception test_object_one(kTestMessage);
|
||||
Exception test_object_two(
|
||||
std::logic_error("Makes no sense")
|
||||
);
|
||||
SECTION(" a: what() does not contain default message")
|
||||
@ -107,7 +108,7 @@ BEGIN_TEST_SUITE("mdml::exception")
|
||||
REQUIRE_THAT(
|
||||
test_object_one.what(),
|
||||
!Match::ContainsSubstring(
|
||||
mdml::exception::default_error
|
||||
messages::kExceptionDefault
|
||||
)
|
||||
);
|
||||
}
|
||||
@ -115,7 +116,7 @@ BEGIN_TEST_SUITE("mdml::exception")
|
||||
{
|
||||
REQUIRE_THAT(
|
||||
test_object_one.what(),
|
||||
Match::ContainsSubstring(test_message)
|
||||
Match::ContainsSubstring(kTestMessage)
|
||||
);
|
||||
}
|
||||
SECTION(" c: what() contains inner exception message")
|
||||
@ -130,7 +131,7 @@ BEGIN_TEST_SUITE("mdml::exception")
|
||||
|
||||
TEST("TEST: what() contains stacktrace with Catch2 runtime methods")
|
||||
{
|
||||
mdml::exception test_object("Test");
|
||||
Exception test_object("Test");
|
||||
SECTION(" a: what() does not contain default message")
|
||||
{
|
||||
REQUIRE_THAT(
|
||||
@ -143,4 +144,4 @@ BEGIN_TEST_SUITE("mdml::exception")
|
||||
}
|
||||
|
||||
// clang-format off
|
||||
// vim: set foldmethod=marker foldmarker=#region,#endregion textwidth=80 ts=4 sts=0 sw=4 noexpandtab ft=cpp.doxygen :
|
||||
// vim: set foldmethod=marker foldmarker=@{,@} textwidth=80 ts=4 sts=0 sw=4 noexpandtab ft=cpp.doxygen :
|
||||
|
@ -7,7 +7,7 @@
|
||||
* obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
#include "exception.hpp"
|
||||
#include "Exception.hpp"
|
||||
|
||||
#include "tests-common.hpp"
|
||||
|
||||
@ -26,7 +26,7 @@ BEGIN_TEST_SUITE("Catch2")
|
||||
TEST("Basic Functionality")
|
||||
{
|
||||
auto throw_something = []() {
|
||||
throw std::runtime_error("ERROR");
|
||||
throw std::runtime_error("Error");
|
||||
};
|
||||
try {
|
||||
CHECK_THROWS(throw_something());
|
||||
@ -47,4 +47,4 @@ BEGIN_TEST_SUITE("Catch2")
|
||||
}
|
||||
|
||||
// clang-format off
|
||||
// vim: set foldmethod=marker foldmarker=#region,#endregion textwidth=80 ts=8 sts=0 sw=8 noexpandtab ft=cpp.doxygen :
|
||||
// vim: set foldmethod=marker foldmarker=@{,@} textwidth=80 ts=8 sts=0 sw=8 noexpandtab ft=cpp.doxygen :
|
||||
|
@ -33,5 +33,5 @@
|
||||
#endif
|
||||
|
||||
// clang-format off
|
||||
// vim: set foldmethod=marker foldmarker=#region,#endregion textwidth=80 ts=8 sts=0 sw=8 noexpandtab ft=cpp.doxygen :
|
||||
// vim: set foldmethod=marker foldmarker=@{,@} textwidth=80 ts=8 sts=0 sw=8 noexpandtab ft=cpp.doxygen :
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user