Monitoring System 0.1.0
System resource monitoring with pluggable collectors and alerting
Loading...
Searching...
No Matches
test_di_container.cpp File Reference

Unit tests for monitoring_system DI container integration. More...

#include <gtest/gtest.h>
#include <kcenon/common/di/service_container.h>
#include <atomic>
#include <chrono>
#include <memory>
#include <stdexcept>
#include <string>
#include <thread>
#include <vector>
Include dependency graph for test_di_container.cpp:

Go to the source code of this file.

Classes

class  IService
 
class  ServiceA
 
class  ServiceB
 
class  DIContainerTest
 

Functions

 TEST_F (DIContainerTest, RegisterAndResolveTransient)
 
 TEST_F (DIContainerTest, RegisterAndResolveSingleton)
 
 TEST_F (DIContainerTest, RegisterSingletonInstance)
 
 TEST_F (DIContainerTest, ServiceWithDependencies)
 
 TEST_F (DIContainerTest, ScopedContainer)
 
 TEST_F (DIContainerTest, ResolveUnregisteredService)
 
 TEST_F (DIContainerTest, ResolveOrNullUnregistered)
 
 TEST_F (DIContainerTest, ClearContainer)
 
 TEST_F (DIContainerTest, UnregisterService)
 
 TEST_F (DIContainerTest, DuplicateRegistrationFails)
 
 TEST_F (DIContainerTest, ThreadSafety)
 
 TEST_F (DIContainerTest, RegisteredServicesDescriptors)
 
 TEST_F (DIContainerTest, FreezePreventsRegistration)
 
 TEST_F (DIContainerTest, FreezeAllowsResolution)
 

Detailed Description

Unit tests for monitoring_system DI container integration.

Tests validate that monitoring_system types work correctly with common_system's service_container, covering registration, resolution, lifetime management, dependency injection, scoping, and thread safety.

Part of kcenon/common_system#368

Definition in file test_di_container.cpp.

Function Documentation

◆ TEST_F() [1/14]

TEST_F ( DIContainerTest ,
ClearContainer  )

Test clear functionality

Definition at line 247 of file test_di_container.cpp.

248{
249 container_.register_simple_factory<IService>(
250 []() { return std::make_shared<ServiceA>(); }, service_lifetime::singleton);
251
252 EXPECT_TRUE(container_.is_registered<IService>());
253
254 container_.clear();
255
256 EXPECT_FALSE(container_.is_registered<IService>());
257
258 auto resolve_result = container_.resolve<IService>();
259 EXPECT_TRUE(resolve_result.is_err());
260}

◆ TEST_F() [2/14]

TEST_F ( DIContainerTest ,
DuplicateRegistrationFails  )

Test duplicate registration fails

Definition at line 280 of file test_di_container.cpp.

281{
282 auto result1 = container_.register_simple_factory<IService>(
283 []() { return std::make_shared<ServiceA>(); }, service_lifetime::singleton);
284 ASSERT_TRUE(result1.is_ok());
285
286 auto result2 = container_.register_simple_factory<IService>(
287 []() { return std::make_shared<ServiceA>(); }, service_lifetime::singleton);
288 EXPECT_TRUE(result2.is_err());
289}

◆ TEST_F() [3/14]

TEST_F ( DIContainerTest ,
FreezeAllowsResolution  )

Test freeze still allows resolution

Definition at line 370 of file test_di_container.cpp.

371{
372 container_.register_simple_factory<IService>(
373 []() { return std::make_shared<ServiceA>(); }, service_lifetime::singleton);
374
375 container_.freeze();
376
377 auto result = container_.resolve<IService>();
378 EXPECT_TRUE(result.is_ok());
379 EXPECT_NE(result.value(), nullptr);
380}

◆ TEST_F() [4/14]

TEST_F ( DIContainerTest ,
FreezePreventsRegistration  )

Test freeze prevents new registrations

Definition at line 353 of file test_di_container.cpp.

354{
355 container_.register_simple_factory<IService>(
356 []() { return std::make_shared<ServiceA>(); }, service_lifetime::singleton);
357
358 container_.freeze();
359 EXPECT_TRUE(container_.is_frozen());
360
361 auto result = container_.register_simple_factory<ServiceA>(
362 []() { return std::make_shared<ServiceA>(); }, service_lifetime::transient);
363
364 EXPECT_TRUE(result.is_err());
365}

◆ TEST_F() [5/14]

TEST_F ( DIContainerTest ,
RegisterAndResolveSingleton  )

Test singleton lifetime

Definition at line 125 of file test_di_container.cpp.

126{
127 auto result = container_.register_simple_factory<IService>(
128 []() { return std::make_shared<ServiceA>(); }, service_lifetime::singleton);
129
130 ASSERT_TRUE(result.is_ok());
131
132 // Resolve multiple times
133 auto service1_result = container_.resolve<IService>();
134 auto service2_result = container_.resolve<IService>();
135
136 ASSERT_TRUE(service1_result.is_ok());
137 ASSERT_TRUE(service2_result.is_ok());
138
139 auto service1 = service1_result.value();
140 auto service2 = service2_result.value();
141
142 // Singleton services should be the same instance
143 EXPECT_EQ(service1, service2);
144 EXPECT_EQ(ServiceA::get_instance_count(), 1);
145 EXPECT_EQ(service1->get_name(), "ServiceA_1");
146 EXPECT_EQ(service2->get_name(), "ServiceA_1");
147}
static int get_instance_count()

References ServiceA::get_instance_count().

Here is the call graph for this function:

◆ TEST_F() [6/14]

TEST_F ( DIContainerTest ,
RegisterAndResolveTransient  )

Test basic service registration and resolution with transient lifetime

Definition at line 96 of file test_di_container.cpp.

97{
98 auto result = container_.register_simple_factory<IService>(
99 []() { return std::make_shared<ServiceA>(); }, service_lifetime::transient);
100
101 ASSERT_TRUE(result.is_ok());
102 EXPECT_TRUE(container_.is_registered<IService>());
103
104 // Resolve service multiple times
105 auto service1_result = container_.resolve<IService>();
106 ASSERT_TRUE(service1_result.is_ok());
107 auto service1 = service1_result.value();
108 EXPECT_NE(service1, nullptr);
109 EXPECT_EQ(service1->get_name(), "ServiceA_1");
110
111 auto service2_result = container_.resolve<IService>();
112 ASSERT_TRUE(service2_result.is_ok());
113 auto service2 = service2_result.value();
114 EXPECT_NE(service2, nullptr);
115 EXPECT_EQ(service2->get_name(), "ServiceA_2");
116
117 // Transient services should be different instances
118 EXPECT_NE(service1, service2);
119 EXPECT_EQ(ServiceA::get_instance_count(), 2);
120}

References ServiceA::get_instance_count().

Here is the call graph for this function:

◆ TEST_F() [7/14]

TEST_F ( DIContainerTest ,
RegisteredServicesDescriptors  )

Test registered_services returns descriptors

Definition at line 338 of file test_di_container.cpp.

339{
340 container_.register_simple_factory<IService>(
341 []() { return std::make_shared<ServiceA>(); }, service_lifetime::singleton);
342
343 container_.register_simple_factory<ServiceA>(
344 []() { return std::make_shared<ServiceA>(); }, service_lifetime::transient);
345
346 auto services = container_.registered_services();
347 EXPECT_GE(services.size(), 2u);
348}

◆ TEST_F() [8/14]

TEST_F ( DIContainerTest ,
RegisterSingletonInstance  )

Test direct instance registration

Definition at line 152 of file test_di_container.cpp.

153{
154 auto instance = std::make_shared<ServiceA>();
155 auto initial_name = instance->get_name();
156
157 auto result = container_.register_instance<IService>(instance);
158 ASSERT_TRUE(result.is_ok());
159
160 // Resolve should return the same instance
161 auto resolved_result = container_.resolve<IService>();
162 ASSERT_TRUE(resolved_result.is_ok());
163 auto resolved = resolved_result.value();
164
165 EXPECT_EQ(resolved, instance);
166 EXPECT_EQ(resolved->get_name(), initial_name);
167}
@ resolved
Alert condition cleared.

◆ TEST_F() [9/14]

TEST_F ( DIContainerTest ,
ResolveOrNullUnregistered  )

Test resolve_or_null for unregistered service returns nullptr

Definition at line 238 of file test_di_container.cpp.

239{
240 auto ptr = container_.resolve_or_null<IService>();
241 EXPECT_EQ(ptr, nullptr);
242}

◆ TEST_F() [10/14]

TEST_F ( DIContainerTest ,
ResolveUnregisteredService  )

Test error handling - resolve unregistered service

Definition at line 229 of file test_di_container.cpp.

230{
231 auto result = container_.resolve<IService>();
232 EXPECT_TRUE(result.is_err());
233}

◆ TEST_F() [11/14]

TEST_F ( DIContainerTest ,
ScopedContainer  )

Test scoped container

Definition at line 207 of file test_di_container.cpp.

208{
209 // Register singleton in root container
210 container_.register_simple_factory<IService>(
211 []() { return std::make_shared<ServiceA>(); }, service_lifetime::singleton);
212
213 // Create scoped container
214 auto scope = container_.create_scope();
215 ASSERT_NE(scope, nullptr);
216
217 // Scoped container should inherit parent registrations
218 EXPECT_TRUE(scope->is_registered<IService>());
219
220 // Resolve in scope should work
221 auto service_result = scope->resolve<IService>();
222 ASSERT_TRUE(service_result.is_ok());
223 EXPECT_NE(service_result.value(), nullptr);
224}

◆ TEST_F() [12/14]

TEST_F ( DIContainerTest ,
ServiceWithDependencies  )

Test service with dependencies resolved through the container

Definition at line 172 of file test_di_container.cpp.

173{
174 // Register dependency as singleton
175 container_.register_simple_factory<ServiceA>(
176 []() { return std::make_shared<ServiceA>(); }, service_lifetime::singleton);
177
178 // Register service that depends on ServiceA, using container to resolve
179 container_.register_factory<ServiceB>(
180 [](IServiceContainer& c) {
181 auto dep_result = c.resolve<ServiceA>();
182 if (dep_result.is_err()) {
183 throw std::runtime_error("Failed to resolve dependency");
184 }
185 return std::make_shared<ServiceB>(dep_result.value());
186 },
187 service_lifetime::transient);
188
189 // Resolve service with dependencies
190 auto service_result = container_.resolve<ServiceB>();
191 ASSERT_TRUE(service_result.is_ok());
192 auto service = service_result.value();
193
194 EXPECT_NE(service, nullptr);
195 auto dependency = service->get_dependency();
196 EXPECT_NE(dependency, nullptr);
197
198 // Dependency should be the same singleton
199 auto dep_result = container_.resolve<ServiceA>();
200 ASSERT_TRUE(dep_result.is_ok());
201 EXPECT_EQ(dependency, dep_result.value());
202}

◆ TEST_F() [13/14]

TEST_F ( DIContainerTest ,
ThreadSafety  )

Test thread safety of singleton resolution

Definition at line 294 of file test_di_container.cpp.

295{
296 container_.register_simple_factory<IService>(
297 []() {
298 std::this_thread::sleep_for(std::chrono::milliseconds(1));
299 return std::make_shared<ServiceA>();
300 },
301 service_lifetime::singleton);
302
303 // Resolve from multiple threads
304 const int num_threads = 10;
305 std::vector<std::thread> threads;
306 std::vector<std::shared_ptr<IService>> results(num_threads);
307
308 for (int i = 0; i < num_threads; ++i) {
309 threads.emplace_back(
310 [this, &results, i]()
311 {
312 auto result = container_.resolve<IService>();
313 if (result.is_ok()) {
314 results[i] = result.value();
315 }
316 });
317 }
318
319 for (auto& t : threads) {
320 t.join();
321 }
322
323 // All threads should get the same singleton instance
324 auto first = results[0];
325 EXPECT_NE(first, nullptr);
326
327 for (const auto& result : results) {
328 EXPECT_EQ(result, first);
329 }
330
331 // Only one instance should have been created
332 EXPECT_EQ(ServiceA::get_instance_count(), 1);
333}

References ServiceA::get_instance_count().

Here is the call graph for this function:

◆ TEST_F() [14/14]

TEST_F ( DIContainerTest ,
UnregisterService  )

Test unregister specific service

Definition at line 265 of file test_di_container.cpp.

266{
267 container_.register_simple_factory<IService>(
268 []() { return std::make_shared<ServiceA>(); }, service_lifetime::singleton);
269
270 EXPECT_TRUE(container_.is_registered<IService>());
271
272 auto result = container_.unregister<IService>();
273 EXPECT_TRUE(result.is_ok());
274 EXPECT_FALSE(container_.is_registered<IService>());
275}