#include #include "settings.hpp" #include "apikey.hpp" #include using namespace svapi; TEST(Settings, DefaultsAndRoundTrip) { Settings s = Settings::fromJson(nlohmann::json::object()); EXPECT_EQ(s.openaiApiBase, "https://api.openai.com"); EXPECT_EQ(s.defaultEmbeddingModel, "text-embedding-3-small"); EXPECT_EQ(s.sessionTtlMinutes, 720u); EXPECT_TRUE(s.webuiEnabled); EXPECT_EQ(s.defaultProject, "default"); EXPECT_EQ(Settings::fromJson(s.toJson()).toJson(), s.toJson()); } TEST(Settings, EmbeddingTimeoutDefaults) { Settings s = Settings::fromJson(nlohmann::json::object()); EXPECT_EQ(s.embeddingConnectTimeoutSec, 10u); EXPECT_EQ(s.embeddingReadTimeoutSec, 60u); } TEST(Settings, EmbeddingTimeoutRoundTrip) { nlohmann::json j{{"embedding_connect_timeout_sec", 30}, {"embedding_read_timeout_sec", 120}}; Settings s = Settings::fromJson(j); EXPECT_EQ(s.embeddingConnectTimeoutSec, 30u); EXPECT_EQ(s.embeddingReadTimeoutSec, 120u); // round-trip: toJson → fromJson preserves values Settings s2 = Settings::fromJson(s.toJson()); EXPECT_EQ(s2.embeddingConnectTimeoutSec, 30u); EXPECT_EQ(s2.embeddingReadTimeoutSec, 120u); } TEST(ApiKey, JsonRoundTripAndPublicMasks) { ApiKey k = ApiKey::fromJson(nlohmann::json::parse( R"({"key":"abcdef0123456789","label":"n8n","projects":["p1","p2"],"admin":false,"created_at":7})")); EXPECT_EQ(k.key, "abcdef0123456789"); EXPECT_EQ(k.projects.size(), 2u); EXPECT_FALSE(k.admin); EXPECT_EQ(k.createdAt, 7u); EXPECT_EQ(ApiKey::fromJson(k.toJson()).toJson(), k.toJson()); auto pub = k.toPublicJson(); EXPECT_FALSE(pub.contains("key")); // secret not exposed EXPECT_EQ(pub["label"], "n8n"); EXPECT_EQ(pub["projects"].size(), 2u); EXPECT_TRUE(pub.contains("key_prefix")); // short hint only } TEST(ApiKey, CanAccess) { ApiKey adminK; adminK.admin = true; EXPECT_TRUE(adminK.canAccess("anything")); ApiKey star; star.projects = {"*"}; EXPECT_TRUE(star.canAccess("anything")); ApiKey scoped; scoped.projects = {"p1", "p2"}; EXPECT_TRUE(scoped.canAccess("p1")); EXPECT_FALSE(scoped.canAccess("p3")); } TEST(ApiKey, GenerateIsHexAndUnique) { std::string a = generateApiKey(), b = generateApiKey(); EXPECT_GE(a.size(), 32u); EXPECT_NE(a, b); for (char c : a) EXPECT_TRUE(std::isxdigit(static_cast(c))); }