Skip to main content

litellm_rs/utils/sys/
di.rs

1//! Dependency injection utilities for better service management
2//!
3//! This module provides a lightweight dependency injection system
4//! that follows Rust best practices and improves testability.
5
6#![allow(dead_code)] // Tool module - functions may be used in the future
7
8use crate::utils::error::{GatewayError, Result};
9use parking_lot::RwLock;
10use std::any::{Any, TypeId};
11use std::collections::HashMap;
12use std::sync::Arc;
13
14/// A trait for services that can be injected
15pub trait Injectable: Send + Sync + 'static {
16    /// Get the type name for debugging
17    fn type_name(&self) -> &'static str {
18        std::any::type_name::<Self>()
19    }
20}
21
22/// Automatic implementation for types that meet the requirements
23impl<T> Injectable for T where T: Send + Sync + 'static {}
24
25/// A service container for dependency injection
26#[derive(Default)]
27pub struct ServiceContainer {
28    services: RwLock<HashMap<TypeId, Arc<dyn Any + Send + Sync>>>,
29    singletons: RwLock<HashMap<TypeId, Arc<dyn Any + Send + Sync>>>,
30}
31
32impl ServiceContainer {
33    /// Create a new service container
34    pub fn new() -> Self {
35        Self::default()
36    }
37
38    /// Register a service instance
39    pub fn register<T>(&self, service: T) -> Result<()>
40    where
41        T: Injectable,
42    {
43        let type_id = TypeId::of::<T>();
44        let service = Arc::new(service);
45
46        let mut services = self.services.write();
47        if services.contains_key(&type_id) {
48            return Err(GatewayError::Config(format!(
49                "Service {} is already registered",
50                std::any::type_name::<T>()
51            )));
52        }
53
54        services.insert(type_id, service);
55        Ok(())
56    }
57
58    /// Register a singleton service
59    pub fn register_singleton<T>(&self, service: T) -> Result<()>
60    where
61        T: Injectable,
62    {
63        let type_id = TypeId::of::<T>();
64        let service = Arc::new(service);
65
66        let mut singletons = self.singletons.write();
67        if singletons.contains_key(&type_id) {
68            return Err(GatewayError::Config(format!(
69                "Singleton {} is already registered",
70                std::any::type_name::<T>()
71            )));
72        }
73
74        singletons.insert(type_id, service);
75        Ok(())
76    }
77
78    /// Register a service factory
79    pub fn register_factory<T, F>(&self, factory: F) -> Result<()>
80    where
81        T: Injectable,
82        F: Fn() -> T + Send + Sync + 'static,
83    {
84        let service = factory();
85        self.register(service)
86    }
87
88    /// Get a service instance
89    pub fn get<T>(&self) -> Result<Arc<T>>
90    where
91        T: Injectable,
92    {
93        let type_id = TypeId::of::<T>();
94
95        // First check singletons
96        {
97            let singletons = self.singletons.read();
98            if let Some(service) = singletons.get(&type_id) {
99                return service.clone().downcast::<T>().map_err(|_| {
100                    GatewayError::Internal(format!(
101                        "Failed to downcast singleton service {}",
102                        std::any::type_name::<T>()
103                    ))
104                });
105            }
106        }
107
108        // Then check regular services
109        {
110            let services = self.services.read();
111            if let Some(service) = services.get(&type_id) {
112                return service.clone().downcast::<T>().map_err(|_| {
113                    GatewayError::Internal(format!(
114                        "Failed to downcast service {}",
115                        std::any::type_name::<T>()
116                    ))
117                });
118            }
119        }
120
121        Err(GatewayError::Config(format!(
122            "Service {} is not registered",
123            std::any::type_name::<T>()
124        )))
125    }
126
127    /// Try to get a service instance (returns None if not found)
128    pub fn try_get<T>(&self) -> Option<Arc<T>>
129    where
130        T: Injectable,
131    {
132        self.get().ok()
133    }
134
135    /// Check if a service is registered
136    pub fn contains<T>(&self) -> bool
137    where
138        T: Injectable,
139    {
140        let type_id = TypeId::of::<T>();
141        let singletons = self.singletons.read();
142        let services = self.services.read();
143
144        singletons.contains_key(&type_id) || services.contains_key(&type_id)
145    }
146
147    /// Remove a service
148    pub fn remove<T>(&self) -> Result<()>
149    where
150        T: Injectable,
151    {
152        let type_id = TypeId::of::<T>();
153
154        {
155            let mut singletons = self.singletons.write();
156            if singletons.remove(&type_id).is_some() {
157                return Ok(());
158            }
159        }
160
161        {
162            let mut services = self.services.write();
163            if services.remove(&type_id).is_some() {
164                return Ok(());
165            }
166        }
167
168        Err(GatewayError::Config(format!(
169            "Service {} is not registered",
170            std::any::type_name::<T>()
171        )))
172    }
173
174    /// Clear all services
175    pub fn clear(&self) {
176        self.services.write().clear();
177        self.singletons.write().clear();
178    }
179
180    /// Get the number of registered services
181    pub fn service_count(&self) -> usize {
182        let services = self.services.read();
183        let singletons = self.singletons.read();
184        services.len() + singletons.len()
185    }
186}
187
188/// A builder for setting up service dependencies
189pub struct ServiceBuilder {
190    container: ServiceContainer,
191}
192
193impl ServiceBuilder {
194    /// Create a new service builder
195    pub fn new() -> Self {
196        Self {
197            container: ServiceContainer::new(),
198        }
199    }
200
201    /// Add a service
202    pub fn add_service<T>(self, service: T) -> Result<Self>
203    where
204        T: Injectable,
205    {
206        self.container.register(service)?;
207        Ok(self)
208    }
209
210    /// Add a singleton service
211    pub fn add_singleton<T>(self, service: T) -> Result<Self>
212    where
213        T: Injectable,
214    {
215        self.container.register_singleton(service)?;
216        Ok(self)
217    }
218
219    /// Add a service factory
220    pub fn add_factory<T, F>(self, factory: F) -> Result<Self>
221    where
222        T: Injectable,
223        F: Fn() -> T + Send + Sync + 'static,
224    {
225        self.container.register_factory(factory)?;
226        Ok(self)
227    }
228
229    /// Build the service container
230    pub fn build(self) -> ServiceContainer {
231        self.container
232    }
233}
234
235impl Default for ServiceBuilder {
236    fn default() -> Self {
237        Self::new()
238    }
239}
240
241/// A trait for types that can be configured with dependencies
242pub trait WithDependencies {
243    /// Configure the type with dependencies from the container
244    fn with_dependencies(self, container: &ServiceContainer) -> Result<Self>
245    where
246        Self: Sized;
247}
248
249// Note: Macros removed for simplicity - use direct method calls instead
250
251/// Global service container for application-wide services
252use once_cell::sync::Lazy;
253
254static GLOBAL_CONTAINER: Lazy<ServiceContainer> = Lazy::new(ServiceContainer::new);
255
256/// Get the global service container
257pub fn global_container() -> &'static ServiceContainer {
258    &GLOBAL_CONTAINER
259}
260
261/// Register a service globally
262pub fn register_global<T>(service: T) -> Result<()>
263where
264    T: Injectable,
265{
266    global_container().register(service)
267}
268
269/// Register a singleton service globally
270pub fn register_global_singleton<T>(service: T) -> Result<()>
271where
272    T: Injectable,
273{
274    global_container().register_singleton(service)
275}
276
277/// Get a service from the global container
278pub fn get_global<T>() -> Result<Arc<T>>
279where
280    T: Injectable,
281{
282    global_container().get()
283}
284
285#[cfg(test)]
286mod tests {
287    use super::*;
288
289    // Test service types
290    #[derive(Debug, Clone, PartialEq)]
291    struct TestService {
292        value: String,
293    }
294
295    #[derive(Debug, Clone, PartialEq)]
296    struct AnotherService {
297        number: i32,
298    }
299
300    #[derive(Debug, Clone)]
301    struct CounterService {
302        count: Arc<RwLock<i32>>,
303    }
304
305    impl CounterService {
306        fn new() -> Self {
307            Self {
308                count: Arc::new(RwLock::new(0)),
309            }
310        }
311
312        fn increment(&self) {
313            *self.count.write() += 1;
314        }
315
316        fn get_count(&self) -> i32 {
317            *self.count.read()
318        }
319    }
320
321    // Tests for Injectable trait
322    #[test]
323    fn test_injectable_type_name() {
324        let service = TestService {
325            value: "test".to_string(),
326        };
327        let type_name = service.type_name();
328        assert!(type_name.contains("TestService"));
329    }
330
331    // Tests for ServiceContainer::new
332    #[test]
333    fn test_container_new() {
334        let container = ServiceContainer::new();
335        assert_eq!(container.service_count(), 0);
336    }
337
338    #[test]
339    fn test_container_default() {
340        let container = ServiceContainer::default();
341        assert_eq!(container.service_count(), 0);
342    }
343
344    // Tests for ServiceContainer::register
345    #[test]
346    fn test_register_service() {
347        let container = ServiceContainer::new();
348        let service = TestService {
349            value: "test".to_string(),
350        };
351
352        let result = container.register(service);
353        assert!(result.is_ok());
354        assert_eq!(container.service_count(), 1);
355    }
356
357    #[test]
358    fn test_register_duplicate_service_fails() {
359        let container = ServiceContainer::new();
360        let service1 = TestService {
361            value: "test1".to_string(),
362        };
363        let service2 = TestService {
364            value: "test2".to_string(),
365        };
366
367        container.register(service1).unwrap();
368        let result = container.register(service2);
369
370        assert!(result.is_err());
371        if let Err(GatewayError::Config(msg)) = result {
372            assert!(msg.contains("already registered"));
373        } else {
374            panic!("Expected Config error");
375        }
376    }
377
378    #[test]
379    fn test_register_different_services() {
380        let container = ServiceContainer::new();
381        let service1 = TestService {
382            value: "test".to_string(),
383        };
384        let service2 = AnotherService { number: 42 };
385
386        container.register(service1).unwrap();
387        container.register(service2).unwrap();
388
389        assert_eq!(container.service_count(), 2);
390    }
391
392    // Tests for ServiceContainer::register_singleton
393    #[test]
394    fn test_register_singleton() {
395        let container = ServiceContainer::new();
396        let service = TestService {
397            value: "singleton".to_string(),
398        };
399
400        let result = container.register_singleton(service);
401        assert!(result.is_ok());
402        assert_eq!(container.service_count(), 1);
403    }
404
405    #[test]
406    fn test_register_duplicate_singleton_fails() {
407        let container = ServiceContainer::new();
408        let service1 = TestService {
409            value: "singleton1".to_string(),
410        };
411        let service2 = TestService {
412            value: "singleton2".to_string(),
413        };
414
415        container.register_singleton(service1).unwrap();
416        let result = container.register_singleton(service2);
417
418        assert!(result.is_err());
419        if let Err(GatewayError::Config(msg)) = result {
420            assert!(msg.contains("already registered"));
421        } else {
422            panic!("Expected Config error");
423        }
424    }
425
426    #[test]
427    fn test_singleton_returns_same_instance() {
428        let container = ServiceContainer::new();
429        let service = CounterService::new();
430        container.register_singleton(service).unwrap();
431
432        let instance1: Arc<CounterService> = container.get().unwrap();
433        instance1.increment();
434
435        let instance2: Arc<CounterService> = container.get().unwrap();
436        assert_eq!(instance2.get_count(), 1);
437
438        instance2.increment();
439        assert_eq!(instance1.get_count(), 2);
440    }
441
442    // Tests for ServiceContainer::register_factory
443    #[test]
444    fn test_register_factory() {
445        let container = ServiceContainer::new();
446        let factory = || TestService {
447            value: "from_factory".to_string(),
448        };
449
450        let result = container.register_factory(factory);
451        assert!(result.is_ok());
452        assert_eq!(container.service_count(), 1);
453    }
454
455    #[test]
456    fn test_factory_creates_service() {
457        let container = ServiceContainer::new();
458        let factory = || TestService {
459            value: "factory_value".to_string(),
460        };
461
462        container.register_factory(factory).unwrap();
463        let service: Arc<TestService> = container.get().unwrap();
464        assert_eq!(service.value, "factory_value");
465    }
466
467    // Tests for ServiceContainer::get
468    #[test]
469    fn test_get_service() {
470        let container = ServiceContainer::new();
471        let service = TestService {
472            value: "get_test".to_string(),
473        };
474
475        container.register(service).unwrap();
476        let retrieved: Arc<TestService> = container.get().unwrap();
477        assert_eq!(retrieved.value, "get_test");
478    }
479
480    #[test]
481    fn test_get_singleton() {
482        let container = ServiceContainer::new();
483        let service = TestService {
484            value: "singleton_get".to_string(),
485        };
486
487        container.register_singleton(service).unwrap();
488        let retrieved: Arc<TestService> = container.get().unwrap();
489        assert_eq!(retrieved.value, "singleton_get");
490    }
491
492    #[test]
493    fn test_get_unregistered_service_fails() {
494        let container = ServiceContainer::new();
495        let result: Result<Arc<TestService>> = container.get();
496
497        assert!(result.is_err());
498        if let Err(GatewayError::Config(msg)) = result {
499            assert!(msg.contains("not registered"));
500        } else {
501            panic!("Expected Config error");
502        }
503    }
504
505    #[test]
506    fn test_get_prefers_singleton_over_service() {
507        let container = ServiceContainer::new();
508
509        // Register as regular service first
510        let service = TestService {
511            value: "regular".to_string(),
512        };
513        container.register(service).unwrap();
514
515        // Then register another instance as singleton
516        // (This is a bit contrived but tests the priority)
517        let container2 = ServiceContainer::new();
518        let singleton = AnotherService { number: 100 };
519        container2.register_singleton(singleton).unwrap();
520
521        let retrieved: Arc<AnotherService> = container2.get().unwrap();
522        assert_eq!(retrieved.number, 100);
523    }
524
525    // Tests for ServiceContainer::try_get
526    #[test]
527    fn test_try_get_existing_service() {
528        let container = ServiceContainer::new();
529        let service = TestService {
530            value: "try_get_test".to_string(),
531        };
532
533        container.register(service).unwrap();
534        let retrieved: Option<Arc<TestService>> = container.try_get();
535        assert!(retrieved.is_some());
536        assert_eq!(retrieved.unwrap().value, "try_get_test");
537    }
538
539    #[test]
540    fn test_try_get_nonexistent_service() {
541        let container = ServiceContainer::new();
542        let retrieved: Option<Arc<TestService>> = container.try_get();
543        assert!(retrieved.is_none());
544    }
545
546    // Tests for ServiceContainer::contains
547    #[test]
548    fn test_contains_registered_service() {
549        let container = ServiceContainer::new();
550        let service = TestService {
551            value: "contains_test".to_string(),
552        };
553
554        container.register(service).unwrap();
555        assert!(container.contains::<TestService>());
556    }
557
558    #[test]
559    fn test_contains_registered_singleton() {
560        let container = ServiceContainer::new();
561        let service = TestService {
562            value: "singleton_contains".to_string(),
563        };
564
565        container.register_singleton(service).unwrap();
566        assert!(container.contains::<TestService>());
567    }
568
569    #[test]
570    fn test_contains_unregistered_service() {
571        let container = ServiceContainer::new();
572        assert!(!container.contains::<TestService>());
573    }
574
575    // Tests for ServiceContainer::remove
576    #[test]
577    fn test_remove_service() {
578        let container = ServiceContainer::new();
579        let service = TestService {
580            value: "remove_test".to_string(),
581        };
582
583        container.register(service).unwrap();
584        assert_eq!(container.service_count(), 1);
585
586        let result = container.remove::<TestService>();
587        assert!(result.is_ok());
588        assert_eq!(container.service_count(), 0);
589        assert!(!container.contains::<TestService>());
590    }
591
592    #[test]
593    fn test_remove_singleton() {
594        let container = ServiceContainer::new();
595        let service = TestService {
596            value: "remove_singleton".to_string(),
597        };
598
599        container.register_singleton(service).unwrap();
600        assert_eq!(container.service_count(), 1);
601
602        let result = container.remove::<TestService>();
603        assert!(result.is_ok());
604        assert_eq!(container.service_count(), 0);
605    }
606
607    #[test]
608    fn test_remove_unregistered_service_fails() {
609        let container = ServiceContainer::new();
610        let result = container.remove::<TestService>();
611
612        assert!(result.is_err());
613        if let Err(GatewayError::Config(msg)) = result {
614            assert!(msg.contains("not registered"));
615        } else {
616            panic!("Expected Config error");
617        }
618    }
619
620    // Tests for ServiceContainer::clear
621    #[test]
622    fn test_clear_empty_container() {
623        let container = ServiceContainer::new();
624        container.clear();
625        assert_eq!(container.service_count(), 0);
626    }
627
628    #[test]
629    fn test_clear_services() {
630        let container = ServiceContainer::new();
631        container
632            .register(TestService {
633                value: "test1".to_string(),
634            })
635            .unwrap();
636        container.register(AnotherService { number: 42 }).unwrap();
637
638        assert_eq!(container.service_count(), 2);
639        container.clear();
640        assert_eq!(container.service_count(), 0);
641        assert!(!container.contains::<TestService>());
642        assert!(!container.contains::<AnotherService>());
643    }
644
645    #[test]
646    fn test_clear_singletons() {
647        let container = ServiceContainer::new();
648        container
649            .register_singleton(TestService {
650                value: "singleton".to_string(),
651            })
652            .unwrap();
653
654        container.clear();
655        assert_eq!(container.service_count(), 0);
656    }
657
658    #[test]
659    fn test_clear_mixed_services() {
660        let container = ServiceContainer::new();
661        container
662            .register(TestService {
663                value: "regular".to_string(),
664            })
665            .unwrap();
666        container
667            .register_singleton(AnotherService { number: 100 })
668            .unwrap();
669
670        assert_eq!(container.service_count(), 2);
671        container.clear();
672        assert_eq!(container.service_count(), 0);
673    }
674
675    // Tests for ServiceContainer::service_count
676    #[test]
677    fn test_service_count_empty() {
678        let container = ServiceContainer::new();
679        assert_eq!(container.service_count(), 0);
680    }
681
682    #[test]
683    fn test_service_count_with_services() {
684        let container = ServiceContainer::new();
685        container
686            .register(TestService {
687                value: "test".to_string(),
688            })
689            .unwrap();
690        assert_eq!(container.service_count(), 1);
691
692        container.register(AnotherService { number: 42 }).unwrap();
693        assert_eq!(container.service_count(), 2);
694    }
695
696    #[test]
697    fn test_service_count_with_singletons() {
698        let container = ServiceContainer::new();
699        container
700            .register_singleton(TestService {
701                value: "singleton".to_string(),
702            })
703            .unwrap();
704        assert_eq!(container.service_count(), 1);
705    }
706
707    #[test]
708    fn test_service_count_mixed() {
709        let container = ServiceContainer::new();
710        container
711            .register(TestService {
712                value: "regular".to_string(),
713            })
714            .unwrap();
715        container
716            .register_singleton(AnotherService { number: 100 })
717            .unwrap();
718        assert_eq!(container.service_count(), 2);
719    }
720
721    // Tests for ServiceBuilder
722    #[test]
723    fn test_builder_new() {
724        let builder = ServiceBuilder::new();
725        let container = builder.build();
726        assert_eq!(container.service_count(), 0);
727    }
728
729    #[test]
730    fn test_builder_default() {
731        let builder = ServiceBuilder::default();
732        let container = builder.build();
733        assert_eq!(container.service_count(), 0);
734    }
735
736    #[test]
737    fn test_builder_add_service() {
738        let service = TestService {
739            value: "builder_test".to_string(),
740        };
741
742        let container = ServiceBuilder::new().add_service(service).unwrap().build();
743
744        assert_eq!(container.service_count(), 1);
745        assert!(container.contains::<TestService>());
746    }
747
748    #[test]
749    fn test_builder_add_singleton() {
750        let service = TestService {
751            value: "builder_singleton".to_string(),
752        };
753
754        let container = ServiceBuilder::new()
755            .add_singleton(service)
756            .unwrap()
757            .build();
758
759        assert_eq!(container.service_count(), 1);
760        let retrieved: Arc<TestService> = container.get().unwrap();
761        assert_eq!(retrieved.value, "builder_singleton");
762    }
763
764    #[test]
765    fn test_builder_add_factory() {
766        let factory = || TestService {
767            value: "builder_factory".to_string(),
768        };
769
770        let container = ServiceBuilder::new().add_factory(factory).unwrap().build();
771
772        assert_eq!(container.service_count(), 1);
773        let retrieved: Arc<TestService> = container.get().unwrap();
774        assert_eq!(retrieved.value, "builder_factory");
775    }
776
777    #[test]
778    fn test_builder_chaining() {
779        let container = ServiceBuilder::new()
780            .add_service(TestService {
781                value: "test".to_string(),
782            })
783            .unwrap()
784            .add_singleton(AnotherService { number: 42 })
785            .unwrap()
786            .build();
787
788        assert_eq!(container.service_count(), 2);
789        assert!(container.contains::<TestService>());
790        assert!(container.contains::<AnotherService>());
791    }
792
793    #[test]
794    fn test_builder_duplicate_service_fails() {
795        let result = ServiceBuilder::new()
796            .add_service(TestService {
797                value: "first".to_string(),
798            })
799            .unwrap()
800            .add_service(TestService {
801                value: "second".to_string(),
802            });
803
804        assert!(result.is_err());
805    }
806
807    // Tests for global container functions
808    #[test]
809    fn test_global_container_exists() {
810        let container = global_container();
811        // Just verify it exists and can be called
812        let _ = container.service_count();
813    }
814
815    // Note: Testing global functions is tricky because they share state
816    // These tests demonstrate usage but may interfere with each other
817    #[test]
818    fn test_register_and_get_global() {
819        // Use a unique type for this test to avoid conflicts
820        #[derive(Debug, Clone)]
821        struct UniqueGlobalService1 {
822            value: String,
823        }
824
825        let service = UniqueGlobalService1 {
826            value: "global_test".to_string(),
827        };
828
829        // Clear might not work across tests, so we handle both cases
830        let register_result = register_global(service);
831        if register_result.is_ok() {
832            let retrieved: Result<Arc<UniqueGlobalService1>> = get_global();
833            assert!(retrieved.is_ok());
834            assert_eq!(retrieved.unwrap().value, "global_test");
835        }
836        // If already registered from another test, that's okay
837    }
838
839    #[test]
840    fn test_register_global_singleton() {
841        #[derive(Debug, Clone)]
842        struct UniqueGlobalService2 {
843            value: String,
844        }
845
846        let service = UniqueGlobalService2 {
847            value: "global_singleton".to_string(),
848        };
849
850        let register_result = register_global_singleton(service);
851        if register_result.is_ok() {
852            let retrieved: Result<Arc<UniqueGlobalService2>> = get_global();
853            assert!(retrieved.is_ok());
854        }
855    }
856
857    // Concurrency tests
858    #[test]
859    fn test_concurrent_get() {
860        use std::thread;
861
862        let container = Arc::new(ServiceContainer::new());
863        container
864            .register(TestService {
865                value: "concurrent".to_string(),
866            })
867            .unwrap();
868
869        let handles: Vec<_> = (0..10)
870            .map(|_| {
871                let container = Arc::clone(&container);
872                thread::spawn(move || {
873                    let service: Arc<TestService> = container.get().unwrap();
874                    assert_eq!(service.value, "concurrent");
875                })
876            })
877            .collect();
878
879        for handle in handles {
880            handle.join().unwrap();
881        }
882    }
883
884    #[test]
885    fn test_concurrent_singleton_access() {
886        use std::thread;
887
888        let container = Arc::new(ServiceContainer::new());
889        let counter = CounterService::new();
890        container.register_singleton(counter).unwrap();
891
892        let handles: Vec<_> = (0..10)
893            .map(|_| {
894                let container = Arc::clone(&container);
895                thread::spawn(move || {
896                    let service: Arc<CounterService> = container.get().unwrap();
897                    service.increment();
898                })
899            })
900            .collect();
901
902        for handle in handles {
903            handle.join().unwrap();
904        }
905
906        let final_service: Arc<CounterService> = container.get().unwrap();
907        assert_eq!(final_service.get_count(), 10);
908    }
909
910    // Edge case tests
911    #[test]
912    fn test_service_with_arc_sharing() {
913        let container = ServiceContainer::new();
914        let service = TestService {
915            value: "shared".to_string(),
916        };
917
918        container.register(service).unwrap();
919        let instance1: Arc<TestService> = container.get().unwrap();
920        let instance2: Arc<TestService> = container.get().unwrap();
921
922        // Both should point to the same underlying data
923        assert_eq!(instance1.value, instance2.value);
924        assert_eq!(Arc::strong_count(&instance1), Arc::strong_count(&instance2));
925    }
926
927    #[test]
928    fn test_multiple_service_types() {
929        let container = ServiceContainer::new();
930
931        container
932            .register(TestService {
933                value: "test".to_string(),
934            })
935            .unwrap();
936        container.register(AnotherService { number: 42 }).unwrap();
937        container.register(CounterService::new()).unwrap();
938
939        assert_eq!(container.service_count(), 3);
940        assert!(container.contains::<TestService>());
941        assert!(container.contains::<AnotherService>());
942        assert!(container.contains::<CounterService>());
943    }
944}