Run clang-tidy; improve types.hpp, added subheaders

This commit is contained in:
S David 2024-03-15 18:37:30 -04:00
parent cf9f791de1
commit 8ed2a666f8
31 changed files with 465 additions and 394 deletions

View File

@ -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
View File

@ -56,4 +56,7 @@ release/*
*-build/
*debug/
docs/*
*.bak

View File

@ -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 :

View File

@ -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 :

View File

@ -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 :

View File

@ -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();

View File

@ -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;
};
}

View File

@ -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

View 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 :

View File

@ -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[]);

View File

@ -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 :)

View File

@ -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 :

View 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 :

View 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 :

View File

@ -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
View 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 :

View File

@ -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 :

View File

@ -3,7 +3,7 @@
set(MDML_SOURCES
libmdml.cpp
exception.cpp
Exception.cpp
debuginfo.cpp
Application.cpp
CgiApplication.cpp

View File

@ -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 :

View File

@ -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

View File

@ -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 :

View File

@ -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;
}

View File

@ -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 :

View File

@ -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")
{

View File

@ -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 :

View File

@ -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 :

View File

@ -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 :

View File

@ -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 :

View File

@ -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 :

View File

@ -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 :

View File

@ -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 :