Create Application class that handles parameters & environment.
Close #16
This commit is contained in:
parent
d8173aae98
commit
0a072ce286
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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
106
tests/Application-test.cpp
Normal 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 :
|
@ -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"
|
||||
|
Loading…
Reference in New Issue
Block a user