194 lines
5.1 KiB
C++
194 lines
5.1 KiB
C++
/**
|
|
* @file basic_test.cpp
|
|
* @brief Minimal unit tests using standard library assert() only.
|
|
*
|
|
* Tests each module: Logger, ConfigManager, DataManager, Utils,
|
|
* DataProcessor, and CommandLineAdapter.
|
|
*/
|
|
|
|
#include <cassert>
|
|
#include <iostream>
|
|
#include <string>
|
|
#include <memory>
|
|
#include <sstream>
|
|
|
|
// Include all module headers
|
|
#include "logger.hpp"
|
|
#include "configmanager.hpp"
|
|
#include "datamanager.hpp"
|
|
#include "utils.hpp"
|
|
#include "processor.hpp"
|
|
#include "adapter.hpp"
|
|
|
|
/// @brief Test the Logger module.
|
|
static void test_logger() {
|
|
Logger logger(LogLevel::DEBUG);
|
|
assert(logger.level() == LogLevel::DEBUG);
|
|
|
|
// Changing level should work
|
|
logger.setLevel(LogLevel::WARN);
|
|
assert(logger.level() == LogLevel::WARN);
|
|
|
|
// Logging at a lower level should not crash; we just test no throw
|
|
logger.debug("this should be suppressed");
|
|
logger.info("this should be suppressed");
|
|
logger.warn("this should appear");
|
|
logger.error("this should appear");
|
|
|
|
std::cout << "[PASS] test_logger\n";
|
|
}
|
|
|
|
/// @brief Test the ConfigManager module.
|
|
static void test_configmanager() {
|
|
// Create a temporary config file in memory using stringstream
|
|
// We'll use loadFrom with a real file path; write a small tmp file
|
|
{
|
|
std::ofstream tmp("test_config.txt");
|
|
tmp << "# Comment line\n"
|
|
<< "app.name = MyApp\n"
|
|
<< "log.level = 2\n"
|
|
<< "enable.cache = true\n"
|
|
<< " empty.value = \n";
|
|
}
|
|
|
|
ConfigManager cfg;
|
|
bool ok = cfg.loadFrom("test_config.txt");
|
|
assert(ok);
|
|
|
|
assert(cfg.getString("app.name") == "MyApp");
|
|
assert(cfg.getInt("log.level") == 2);
|
|
assert(cfg.getBool("enable.cache") == true);
|
|
assert(cfg.hasKey("app.name"));
|
|
assert(!cfg.hasKey("nonexistent"));
|
|
|
|
// Test default values
|
|
assert(cfg.getString("missing", "default") == "default");
|
|
assert(cfg.getInt("missing", 42) == 42);
|
|
assert(cfg.getBool("missing", true) == true);
|
|
|
|
// Clean up
|
|
std::remove("test_config.txt");
|
|
std::cout << "[PASS] test_configmanager\n";
|
|
}
|
|
|
|
/// @brief Test the DataManager module.
|
|
static void test_datamanager() {
|
|
DataManager dm;
|
|
assert(dm.size() == 0);
|
|
|
|
dm.store("key1", std::any(42));
|
|
assert(dm.exists("key1"));
|
|
assert(dm.size() == 1);
|
|
|
|
auto val = dm.load("key1");
|
|
assert(val != nullptr);
|
|
assert(std::any_cast<int>(*val) == 42);
|
|
|
|
bool removed = dm.remove("key1");
|
|
assert(removed);
|
|
assert(!dm.exists("key1"));
|
|
assert(dm.size() == 0);
|
|
|
|
dm.clear();
|
|
assert(dm.size() == 0);
|
|
|
|
std::cout << "[PASS] test_datamanager\n";
|
|
}
|
|
|
|
/// @brief Test the Utils module.
|
|
static void test_utils() {
|
|
std::string s = " hello world ";
|
|
utils::trim(s);
|
|
assert(s == "hello world");
|
|
|
|
auto parts = utils::split("a,b,c", ',');
|
|
assert(parts.size() == 3);
|
|
assert(parts[0] == "a");
|
|
assert(parts[1] == "b");
|
|
assert(parts[2] == "c");
|
|
|
|
std::string mixed = "HeLLo";
|
|
utils::toLower(mixed);
|
|
assert(mixed == "hello");
|
|
|
|
assert(!utils::currentTimestamp().empty());
|
|
|
|
assert(utils::fileName("/path/to/file.txt") == "file.txt");
|
|
assert(utils::fileExtension("/path/to/file.txt") == "txt");
|
|
assert(utils::fileExtension("noext") == "");
|
|
|
|
std::cout << "[PASS] test_utils\n";
|
|
}
|
|
|
|
/// @brief Test the DataProcessor module.
|
|
static void test_processor() {
|
|
auto logger = std::make_shared<Logger>(LogLevel::ERROR);
|
|
DataProcessor proc(logger);
|
|
|
|
ProcessResult res = proc.process(std::any(123));
|
|
assert(res.success);
|
|
assert(res.code == 0);
|
|
|
|
// Ensure output_data contains the input pass-through
|
|
assert(std::any_cast<int>(res.output_data) == 123);
|
|
|
|
std::cout << "[PASS] test_processor\n";
|
|
}
|
|
|
|
/// @brief Test the CommandLineAdapter module.
|
|
static void test_adapter() {
|
|
{
|
|
const char* argv[] = {"app", "--help"};
|
|
CommandLineAdapter a(2, const_cast<char**>(argv));
|
|
CommandLineArgs args = a.parse();
|
|
assert(args.show_help);
|
|
assert(!args.show_version);
|
|
assert(!args.has_errors);
|
|
}
|
|
|
|
{
|
|
const char* argv[] = {"app", "--version"};
|
|
CommandLineAdapter a(2, const_cast<char**>(argv));
|
|
CommandLineArgs args = a.parse();
|
|
assert(args.show_version);
|
|
assert(!args.show_help);
|
|
assert(!args.has_errors);
|
|
}
|
|
|
|
{
|
|
const char* argv[] = {"app", "--config", "my.cfg"};
|
|
CommandLineAdapter a(3, const_cast<char**>(argv));
|
|
CommandLineArgs args = a.parse();
|
|
assert(!args.has_errors);
|
|
assert(args.config_path == "my.cfg");
|
|
}
|
|
|
|
{
|
|
const char* argv[] = {"app", "--unknown"};
|
|
CommandLineAdapter a(2, const_cast<char**>(argv));
|
|
CommandLineArgs args = a.parse();
|
|
assert(args.has_errors);
|
|
assert(!args.error_msg.empty());
|
|
}
|
|
|
|
std::cout << "[PASS] test_adapter\n";
|
|
}
|
|
|
|
/**
|
|
* @brief Main test runner.
|
|
* @return 0 on success, 1 on any assertion failure.
|
|
*/
|
|
int main() {
|
|
std::cout << "=== Running ModularApp Unit Tests ===\n";
|
|
|
|
test_logger();
|
|
test_configmanager();
|
|
test_datamanager();
|
|
test_utils();
|
|
test_processor();
|
|
test_adapter();
|
|
|
|
std::cout << "=== ALL TESTS PASSED ===\n";
|
|
return 0;
|
|
}
|