142 lines
4.4 KiB
C++
142 lines
4.4 KiB
C++
#include "config/config_manager.h"
|
|
#include "config/yaml_parser.h"
|
|
#include <gtest/gtest.h>
|
|
#include <chrono>
|
|
#include <filesystem>
|
|
#include <fstream>
|
|
#include <thread>
|
|
|
|
using namespace radiantwave::config;
|
|
|
|
TEST(YamlParserTest, ParseBasicYaml) {
|
|
std::string yaml = R"(
|
|
license_key: "KEY-12345"
|
|
email_address: "test@example.com"
|
|
provisioning_status: "READY"
|
|
|
|
audio:
|
|
volume: 95
|
|
output_device: "hdmi"
|
|
|
|
proclamation:
|
|
scroll_speed: 2.5
|
|
font_size: 40
|
|
)";
|
|
|
|
YamlNode root = parseYaml(yaml);
|
|
EXPECT_TRUE(root.hasChild("license_key"));
|
|
EXPECT_EQ(root.getChild("license_key").asString(), "KEY-12345");
|
|
EXPECT_EQ(root.getChild("email_address").asString(), "test@example.com");
|
|
|
|
EXPECT_TRUE(root.hasChild("audio"));
|
|
EXPECT_EQ(root.getChild("audio").getChild("volume").asInt(), 95);
|
|
EXPECT_EQ(root.getChild("audio").getChild("output_device").asString(), "hdmi");
|
|
|
|
EXPECT_TRUE(root.hasChild("proclamation"));
|
|
EXPECT_FLOAT_EQ(root.getChild("proclamation").getChild("scroll_speed").asFloat(), 2.5f);
|
|
EXPECT_EQ(root.getChild("proclamation").getChild("font_size").asInt(), 40);
|
|
}
|
|
|
|
TEST(YamlParserTest, ConfigRoundTrip) {
|
|
AppConfig original;
|
|
original.license_key = "RW-TEST-99";
|
|
original.email_address = "admin@radiantwave.com";
|
|
original.audio.volume = 60;
|
|
original.audio.dynamic_audio = false;
|
|
original.proclamation.scroll_speed = 1.8f;
|
|
original.proclamation.schedule_active = true;
|
|
|
|
std::string serialized = serializeConfigToYaml(original);
|
|
AppConfig parsed = parseConfigFromYaml(serialized);
|
|
|
|
EXPECT_EQ(parsed.license_key, original.license_key);
|
|
EXPECT_EQ(parsed.email_address, original.email_address);
|
|
EXPECT_EQ(parsed.audio.volume, original.audio.volume);
|
|
EXPECT_EQ(parsed.audio.dynamic_audio, original.audio.dynamic_audio);
|
|
EXPECT_FLOAT_EQ(parsed.proclamation.scroll_speed, original.proclamation.scroll_speed);
|
|
EXPECT_TRUE(parsed.proclamation.schedule_active);
|
|
}
|
|
|
|
TEST(ConfigManagerTest, DefaultGeneration) {
|
|
std::string temp_path = (std::filesystem::temp_directory_path() / "test_rw_config1.yaml").string();
|
|
if (std::filesystem::exists(temp_path)) {
|
|
std::filesystem::remove(temp_path);
|
|
}
|
|
|
|
ConfigManager manager;
|
|
EXPECT_TRUE(manager.initialize(temp_path));
|
|
|
|
AppConfig cfg = manager.get();
|
|
EXPECT_EQ(cfg.audio.volume, 80);
|
|
EXPECT_EQ(cfg.audio.dynamic_audio, true);
|
|
EXPECT_EQ(cfg.proclamation.font_size, 32);
|
|
EXPECT_FALSE(cfg.proclamation.schedule_active);
|
|
|
|
EXPECT_TRUE(std::filesystem::exists(temp_path));
|
|
std::filesystem::remove(temp_path);
|
|
}
|
|
|
|
TEST(ConfigManagerTest, MergePreservesExistingValues) {
|
|
std::string temp_path = (std::filesystem::temp_directory_path() / "test_rw_config2.yaml").string();
|
|
|
|
// Write partial config
|
|
{
|
|
std::ofstream file(temp_path);
|
|
file << "license_key: \"MY-LICENSE\"\n";
|
|
file << "audio:\n";
|
|
file << " volume: 42\n";
|
|
}
|
|
|
|
ConfigManager manager;
|
|
EXPECT_TRUE(manager.initialize(temp_path));
|
|
|
|
AppConfig cfg = manager.get();
|
|
// Preserved custom values
|
|
EXPECT_EQ(cfg.license_key, "MY-LICENSE");
|
|
EXPECT_EQ(cfg.audio.volume, 42);
|
|
|
|
// Default values populated for missing fields
|
|
EXPECT_EQ(cfg.proclamation.font_size, 32);
|
|
|
|
std::filesystem::remove(temp_path);
|
|
}
|
|
|
|
TEST(ConfigManagerTest, HotReloadWatcher) {
|
|
std::string temp_path = (std::filesystem::temp_directory_path() / "test_rw_config3.yaml").string();
|
|
if (std::filesystem::exists(temp_path)) {
|
|
std::filesystem::remove(temp_path);
|
|
}
|
|
|
|
ConfigManager manager;
|
|
EXPECT_TRUE(manager.initialize(temp_path));
|
|
|
|
std::atomic<bool> reloaded{false};
|
|
int new_font_size = 0;
|
|
|
|
manager.onChanged([&](const AppConfig& new_cfg) {
|
|
new_font_size = new_cfg.proclamation.font_size;
|
|
reloaded = true;
|
|
});
|
|
|
|
// Pause briefly then write modified config to disk
|
|
std::this_thread::sleep_for(std::chrono::milliseconds(600));
|
|
|
|
{
|
|
std::ofstream file(temp_path, std::ios::out | std::ios::trunc);
|
|
file << "proclamation:\n";
|
|
file << " font_size: 48\n";
|
|
}
|
|
|
|
// Wait for file watcher thread to pick up change
|
|
for (int i = 0; i < 20; ++i) {
|
|
if (reloaded) break;
|
|
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
|
}
|
|
|
|
EXPECT_TRUE(reloaded);
|
|
EXPECT_EQ(new_font_size, 48);
|
|
|
|
manager.shutdown();
|
|
std::filesystem::remove(temp_path);
|
|
}
|