16#include <gtest/gtest.h>
18#include <kcenon/common/di/service_container.h>
19#include <kcenon/common/interfaces/database_interface.h>
20#include <kcenon/database/config/feature_flags.h>
22#if KCENON_HAS_COMMON_SYSTEM
24#include <kcenon/database/di/service_registration.h>
32using namespace kcenon::common::di;
33using namespace kcenon::database::di;
34using namespace kcenon::common::interfaces;
39class DatabaseServiceRegistrationTest :
public ::testing::Test
42 service_container container_;
44 void TearDown()
override { container_.clear(); }
49TEST_F(DatabaseServiceRegistrationTest, RegisterDatabaseServices_DefaultConfig_Succeeds)
51 auto result = register_database_services(container_);
53 EXPECT_TRUE(result.is_ok());
54 EXPECT_TRUE(container_.is_registered<IDatabase>());
57TEST_F(DatabaseServiceRegistrationTest, RegisterDatabaseServices_CustomConfig_Succeeds)
59 database_registration_config config;
61 config.lifetime = service_lifetime::singleton;
63 auto result = register_database_services(container_, config);
65 EXPECT_TRUE(result.is_ok());
66 EXPECT_TRUE(container_.is_registered<IDatabase>());
69TEST_F(DatabaseServiceRegistrationTest, RegisterDatabaseServices_TransientLifetime_Succeeds)
71 database_registration_config config;
72 config.lifetime = service_lifetime::transient;
74 auto result = register_database_services(container_, config);
76 EXPECT_TRUE(result.is_ok());
77 EXPECT_TRUE(container_.is_registered<IDatabase>());
80TEST_F(DatabaseServiceRegistrationTest, RegisterDatabaseServices_Duplicate_Fails)
82 auto result1 = register_database_services(container_);
85 auto result2 = register_database_services(container_);
86 EXPECT_TRUE(result2.is_err());
89TEST_F(DatabaseServiceRegistrationTest, RegisterAllDatabaseServices_Succeeds)
91 auto result = register_all_database_services(container_);
93 EXPECT_TRUE(result.is_ok());
94 EXPECT_TRUE(container_.is_registered<IDatabase>());
97TEST_F(DatabaseServiceRegistrationTest, RegisterAllDatabaseServices_Duplicate_Fails)
99 auto result1 = register_all_database_services(container_);
102 auto result2 = register_all_database_services(container_);
103 EXPECT_TRUE(result2.is_err());
108TEST_F(DatabaseServiceRegistrationTest, Resolve_DefaultSingleton_ReturnsSameInstance)
110 register_database_services(container_);
112 auto result1 = container_.resolve<IDatabase>();
113 auto result2 = container_.resolve<IDatabase>();
119 EXPECT_EQ(result1.value(), result2.value());
122TEST_F(DatabaseServiceRegistrationTest, Resolve_Transient_ReturnsDifferentInstances)
124 database_registration_config config;
125 config.lifetime = service_lifetime::transient;
127 register_database_services(container_, config);
129 auto result1 = container_.resolve<IDatabase>();
130 auto result2 = container_.resolve<IDatabase>();
135 EXPECT_NE(result1.value(), result2.value());
138TEST_F(DatabaseServiceRegistrationTest, Resolve_ReturnsValidIDatabase)
140 register_database_services(container_);
142 auto result = container_.resolve<IDatabase>();
145 EXPECT_NE(result.value(),
nullptr);
148 EXPECT_FALSE(result.value()->is_connected());
151TEST_F(DatabaseServiceRegistrationTest, ResolveOrNull_Unregistered_ReturnsNull)
153 auto ptr = container_.resolve_or_null<IDatabase>();
155 EXPECT_EQ(ptr,
nullptr);
158TEST_F(DatabaseServiceRegistrationTest, ResolveOrNull_Registered_ReturnsInstance)
160 register_database_services(container_);
162 auto ptr = container_.resolve_or_null<IDatabase>();
164 EXPECT_NE(ptr,
nullptr);
169TEST_F(DatabaseServiceRegistrationTest, RegisterInstance_Succeeds)
171 auto manager = std::make_shared<::database::database_manager>(
172 std::make_shared<::database::database_context>());
174 auto result = register_database_instance(container_, manager);
176 EXPECT_TRUE(result.is_ok());
177 EXPECT_TRUE(container_.is_registered<IDatabase>());
180TEST_F(DatabaseServiceRegistrationTest, RegisterInstance_NullManager_Fails)
182 auto result = register_database_instance(container_,
nullptr);
184 EXPECT_TRUE(result.is_err());
187TEST_F(DatabaseServiceRegistrationTest, RegisterInstance_ResolveReturnsSameAdapter)
189 auto manager = std::make_shared<::database::database_manager>(
190 std::make_shared<::database::database_context>());
192 register_database_instance(container_, manager);
194 auto result1 = container_.resolve<IDatabase>();
195 auto result2 = container_.resolve<IDatabase>();
201 EXPECT_EQ(result1.value(), result2.value());
206TEST_F(DatabaseServiceRegistrationTest, UnregisterDatabaseServices_Succeeds)
208 register_database_services(container_);
209 EXPECT_TRUE(container_.is_registered<IDatabase>());
211 auto result = unregister_database_services(container_);
212 EXPECT_TRUE(result.is_ok());
213 EXPECT_FALSE(container_.is_registered<IDatabase>());
216TEST_F(DatabaseServiceRegistrationTest, UnregisterDatabaseServices_NotRegistered_Fails)
218 auto result = unregister_database_services(container_);
219 EXPECT_TRUE(result.is_err());
224TEST_F(DatabaseServiceRegistrationTest, GetUnderlyingManager_FactoryRegistered_ReturnsManager)
226 register_database_services(container_);
228 auto db_result = container_.resolve<IDatabase>();
231 auto manager = get_underlying_database_manager(db_result.value());
232 EXPECT_NE(manager,
nullptr);
235TEST_F(DatabaseServiceRegistrationTest, GetUnderlyingManager_InstanceRegistered_ReturnsOriginal)
237 auto original_manager = std::make_shared<::database::database_manager>(
238 std::make_shared<::database::database_context>());
240 register_database_instance(container_, original_manager);
242 auto db_result = container_.resolve<IDatabase>();
245 auto retrieved_manager = get_underlying_database_manager(db_result.value());
246 EXPECT_EQ(retrieved_manager, original_manager);
251TEST_F(DatabaseServiceRegistrationTest, Clear_RemovesRegistration)
253 register_database_services(container_);
254 EXPECT_TRUE(container_.is_registered<IDatabase>());
258 EXPECT_FALSE(container_.is_registered<IDatabase>());
260 auto result = container_.resolve<IDatabase>();
261 EXPECT_TRUE(result.is_err());
266TEST_F(DatabaseServiceRegistrationTest, Freeze_PreventsRegistration)
268 register_database_services(container_);
271 EXPECT_TRUE(container_.is_frozen());
274 auto result = container_.register_simple_factory<IDatabase>(
275 []() -> std::shared_ptr<IDatabase> {
return nullptr; },
276 service_lifetime::singleton);
278 EXPECT_TRUE(result.is_err());
281TEST_F(DatabaseServiceRegistrationTest, Freeze_AllowsResolution)
283 register_database_services(container_);
286 auto result = container_.resolve<IDatabase>();
287 EXPECT_TRUE(result.is_ok());
288 EXPECT_NE(result.value(),
nullptr);
293TEST_F(DatabaseServiceRegistrationTest, ConcurrentResolve_Singleton_ThreadSafe)
295 register_database_services(container_);
297 const int num_threads = 8;
298 std::vector<std::thread> threads;
299 std::vector<std::shared_ptr<IDatabase>> results(num_threads);
301 for (
int i = 0; i < num_threads; ++i)
303 threads.emplace_back(
304 [
this, &results, i]()
306 auto result = container_.resolve<IDatabase>();
309 results[i] = result.value();
314 for (
auto& t : threads)
320 EXPECT_NE(results[0],
nullptr);
321 for (
int i = 1; i < num_threads; ++i)
323 EXPECT_EQ(results[0], results[i]);
327TEST_F(DatabaseServiceRegistrationTest, ConcurrentResolve_Transient_ThreadSafe)
329 database_registration_config config;
330 config.lifetime = service_lifetime::transient;
331 register_database_services(container_, config);
333 const int num_threads = 8;
334 const int ops_per_thread = 50;
335 std::vector<std::thread> threads;
336 std::atomic<int> success_count{0};
338 for (
int i = 0; i < num_threads; ++i)
340 threads.emplace_back(
341 [
this, &success_count, ops_per_thread]()
343 for (
int j = 0; j < ops_per_thread; ++j)
345 auto result = container_.resolve<IDatabase>();
354 for (
auto& t : threads)
359 EXPECT_EQ(success_count.load(), num_threads * ops_per_thread);
364TEST_F(DatabaseServiceRegistrationTest, RegisteredServices_ReturnsDescriptors)
366 register_database_services(container_);
368 auto services = container_.registered_services();
369 EXPECT_GE(services.size(), 1u);
374TEST_F(DatabaseServiceRegistrationTest, ScopedContainer_InheritsRegistration)
376 register_database_services(container_);
378 auto scope = container_.create_scope();
379 ASSERT_NE(scope,
nullptr);
381 EXPECT_TRUE(scope->is_registered<IDatabase>());
383 auto result = scope->resolve<IDatabase>();
384 EXPECT_TRUE(result.is_ok());
385 EXPECT_NE(result.value(),
nullptr);
@ sqlite
Indicates a SQLite database.
TEST_F(AsyncResultTest, ConstructsFromFuture)
#define ASSERT_TRUE(condition, message)