Create Application class that handles parameters & environment.
Some checks failed
buildbot/mdml-cgi-linux-podman-builder Build done.
buildbot/mdml-cgi-darwin-macos-builder Build done.
buildbot/mdml-cgi-freebsd-jail-builder Build done.

Close #16
This commit is contained in:
S David 2023-10-23 21:01:47 -04:00
parent d8173aae98
commit 0a072ce286
6 changed files with 193 additions and 20 deletions

View File

@ -8,6 +8,7 @@
*/
#include "Application.hpp"
#include "types.hpp"
#include <iomanip>
#include <iostream>
@ -15,9 +16,9 @@
#include <string>
int
main(int argc, char** argv, char** envp)
main(int argc, const char** argv, const char** envp)
{
mdml::Application app(argc, argv, envp);
for (int i = 0; i < argc; ++i) {
std::cout << argv[i] << std::endl;
}

View File

@ -15,6 +15,12 @@
#include <string>
namespace mdml {
namespace c {
using string = char*;
using const_string = const char*;
}
using count_t = size_t;
template<typename T>
using reference = std::reference_wrapper<T>;
@ -29,7 +35,7 @@ template<typename T>
using opt_const_reference = std::optional<const_reference<const T>>;
template<typename value_t>
using Dictionary = std::map<std::string, value_t>;
using Dictionary = std::map<const std::string, value_t>;
}
// clang-format off

View File

@ -8,6 +8,7 @@
*/
#include "Application.hpp"
#include "exception.hpp"
#include <map>
#include <string>
@ -15,16 +16,37 @@
using namespace mdml;
Application::Application(int argc, char* argv[], char* env[])
count_t Application::instance_count = 0;
Application::Application(int argc, c::const_string argv[], c::const_string env[])
: arguments(), environment_variables()
{
if (Application::instance_count != 0) {
auto fatal_exception =
std::logic_error("Cannot instantiate more than one "
"mdml::Application class at a time");
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);
}
/* For future use, in case the default constructor is not good enough
Application::~Application()
{
} */
(Application::instance_count)--;
}
const std::string&
Application::GetEnv(const std::string& key)
@ -33,18 +55,34 @@ Application::GetEnv(const std::string& key)
}
void
Application::create_env_dictionary(char* env[])
Application::parse_arguments(int argc, c::const_string argv[])
{
for (auto** current = env; (*current) != 0; ++current) {
auto encoded_pair = std::string_view(*env);
std::string key, value;
for (count_t index = 0; index < argc; ++index) {
this->arguments.push_back(argv[index]);
}
}
void
Application::create_env_dictionary(c::const_string envp[])
{
for (count_t num = 0; envp[num] != nullptr; ++num) {
auto encoded_pair = std::string_view(envp[num]);
size_t equal_character_pos;
auto not_found = encoded_pair.npos;
equal_character_pos = encoded_pair.find('=');
if (equal_character_pos != encoded_pair.npos) {
key = encoded_pair.substr(0, equal_character_pos);
value = encoded_pair.substr(equal_character_pos + 1);
this->environment_variables[key] = value;
if (equal_character_pos != not_found) {
auto key = std::string(
encoded_pair.substr(0, equal_character_pos)
);
auto val = std::string(
encoded_pair.substr(equal_character_pos + 1)
);
this->environment_variables.insert(
std::make_pair(key, val)
);
}
}
}

View File

@ -17,14 +17,32 @@ namespace mdml {
class Application {
public:
explicit Application(int argc, char* argv[], char* env[]);
virtual ~Application() = default;
Application(int argc, c::const_string argv[], c::const_string env[]);
Application(const Application&) = delete;
Application& operator=(const Application&) = delete;
virtual ~Application();
inline const std::vector<const std::string>& ArgumentsVector()
{
return this->arguments;
}
inline const Dictionary<const std::string>& EnvironDictionary()
{
return this->environment_variables;
}
const std::string& GetEnv(const std::string& key);
private:
void create_env_dictionary(char* env[]);
Dictionary<std::string> environment_variables;
static count_t instance_count;
void parse_arguments(int argc, c::const_string argv[]);
void create_env_dictionary(c::const_string envp[]);
std::vector<const std::string> arguments;
Dictionary<const std::string> environment_variables;
};
}

106
tests/Application-test.cpp Normal file
View File

@ -0,0 +1,106 @@
/* Application-test.cpp
* Copyright © 2023 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/.
*/
#include "exception.hpp"
#include "tests-common.hpp"
#include "Application.hpp"
struct invoke_data {
static const char* argv[];
static const char* env[];
};
inline const char* invoke_data::argv[] = { "param1", "param2", "param3" };
inline const char* invoke_data::env[] = { "PATH=/usr/bin", "VAR2=TWO", nullptr };
BEGIN_TEST_SUITE("Application-test")
{
TEST("Class construction")
{
auto simple_construction = []() {
auto test_object = mdml::Application(
3, invoke_data::argv, invoke_data::env
);
};
auto double_construction = []() {
auto test_object = mdml::Application(
3, invoke_data::argv, invoke_data::env
);
auto throws_errors = mdml::Application(
3, invoke_data::argv, invoke_data::env
);
};
SECTION("First construction")
{
REQUIRE_NOTHROW(simple_construction());
}
SECTION("Double construction")
{
REQUIRE_THROWS_AS(
double_construction(), mdml::exception
);
}
SECTION("Double construction")
{
REQUIRE_THROWS_AS(
double_construction(), mdml::exception
);
}
auto incorrect_construction = []() {
mdml::Application obj(0, nullptr, nullptr);
};
SECTION("Incorrect parameters")
{
REQUIRE_THROWS_AS(
incorrect_construction(), mdml::exception
);
}
}
TEST("Parameter capture")
{
SECTION("Arguments are captured in vector")
{
auto correct_construction = []() {
auto test_object = mdml::Application(
3, invoke_data::argv, invoke_data::env
);
auto args_list = test_object.ArgumentsVector();
SECTION("Argument verification")
{
REQUIRE(args_list[0] == "param1");
REQUIRE(args_list[1] == "param2");
}
};
REQUIRE_NOTHROW(correct_construction());
}
SECTION("Environemnt variables are catpured in map")
{
auto correct_construction = []() {
auto test_object = mdml::Application(
3, invoke_data::argv, invoke_data::env
);
auto environ = test_object.EnvironDictionary();
SECTION("Varaible verification")
{
REQUIRE(environ["PATH"] == "/usr/bin");
REQUIRE(environ["VAR2"] == "TWO");
}
};
REQUIRE_NOTHROW(correct_construction());
}
}
}
// clang-format off
// vim: set foldmethod=marker foldmarker=#region,#endregion textwidth=80 ts=8 sts=0 sw=8 noexpandtab ft=cpp.doxygen :

View File

@ -1,6 +1,10 @@
# Add the test executable
add_executable(mdml-tests exception-test.cpp)
add_executable(mdml-tests
exception-test.cpp
Application-test.cpp
)
set_target_properties(mdml-tests PROPERTIES
RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/artifacts/tests"