verdure_ioc/component/
factory.rs1use std::any::{Any, TypeId};
7use std::sync::Arc;
8
9pub trait ComponentFactory {
38 fn get_component_by_type_id(&self, type_id: TypeId) -> Option<Arc<dyn Any + Send + Sync>>;
51
52 fn get_component<T: Any + Send + Sync>(&self) -> Option<Arc<T>>;
88}
89
90#[cfg(test)]
91mod tests {
92 use super::*;
93 use std::collections::HashMap;
94
95 #[derive(Debug, PartialEq)]
96 struct TestComponent {
97 value: i32,
98 }
99
100 #[derive(Debug, PartialEq)]
101 struct AnotherComponent {
102 name: String,
103 }
104
105 struct MockComponentFactory {
106 components: HashMap<TypeId, Arc<dyn Any + Send + Sync>>,
107 }
108
109 impl MockComponentFactory {
110 fn new() -> Self {
111 Self {
112 components: HashMap::new(),
113 }
114 }
115
116 fn register<T: Any + Send + Sync>(&mut self, component: T) {
117 self.components
118 .insert(TypeId::of::<T>(), Arc::new(component));
119 }
120 }
121
122 impl ComponentFactory for MockComponentFactory {
123 fn get_component_by_type_id(&self, type_id: TypeId) -> Option<Arc<dyn Any + Send + Sync>> {
124 self.components.get(&type_id).cloned()
125 }
126
127 fn get_component<T: Any + Send + Sync>(&self) -> Option<Arc<T>> {
128 let component_any = self.get_component_by_type_id(TypeId::of::<T>())?;
129 component_any.downcast().ok()
130 }
131 }
132
133 #[test]
134 fn test_component_factory_get_component() {
135 let mut factory = MockComponentFactory::new();
136
137 let test_component = TestComponent { value: 42 };
138 factory.register(test_component);
139
140 let retrieved: Option<Arc<TestComponent>> = factory.get_component();
141 assert!(retrieved.is_some());
142 assert_eq!(retrieved.unwrap().value, 42);
143 }
144
145 #[test]
146 fn test_component_factory_get_component_by_type_id() {
147 let mut factory = MockComponentFactory::new();
148
149 let test_component = TestComponent { value: 100 };
150 factory.register(test_component);
151
152 let type_id = TypeId::of::<TestComponent>();
153 let retrieved = factory.get_component_by_type_id(type_id);
154 assert!(retrieved.is_some());
155
156 let downcasted = retrieved.unwrap().downcast::<TestComponent>();
157 assert!(downcasted.is_ok());
158 assert_eq!(downcasted.unwrap().value, 100);
159 }
160
161 #[test]
162 fn test_component_factory_multiple_components() {
163 let mut factory = MockComponentFactory::new();
164
165 factory.register(TestComponent { value: 123 });
166 factory.register(AnotherComponent {
167 name: "test".to_string(),
168 });
169
170 let test_comp: Option<Arc<TestComponent>> = factory.get_component();
171 let another_comp: Option<Arc<AnotherComponent>> = factory.get_component();
172
173 assert!(test_comp.is_some());
174 assert!(another_comp.is_some());
175
176 assert_eq!(test_comp.unwrap().value, 123);
177 assert_eq!(another_comp.unwrap().name, "test");
178 }
179
180 #[test]
181 fn test_component_factory_nonexistent_component() {
182 let factory = MockComponentFactory::new();
183
184 let result: Option<Arc<TestComponent>> = factory.get_component();
185 assert!(result.is_none());
186
187 let result_by_type_id = factory.get_component_by_type_id(TypeId::of::<TestComponent>());
188 assert!(result_by_type_id.is_none());
189 }
190
191 #[test]
192 fn test_component_factory_downcast_failure() {
193 let mut factory = MockComponentFactory::new();
194 factory.register(TestComponent { value: 42 });
195
196 let type_id = TypeId::of::<TestComponent>();
198 let component_any = factory.get_component_by_type_id(type_id).unwrap();
199
200 let wrong_downcast = component_any.downcast::<AnotherComponent>();
201 assert!(wrong_downcast.is_err());
202 }
203
204 #[test]
205 fn test_component_factory_trait_object() {
206 let mut factory = MockComponentFactory::new();
207 factory.register(TestComponent { value: 999 });
208
209 let component: Option<Arc<TestComponent>> = factory.get_component();
211
212 assert!(component.is_some());
213 assert_eq!(component.unwrap().value, 999);
214
215 let type_id = TypeId::of::<TestComponent>();
217 let component_any = factory.get_component_by_type_id(type_id);
218 assert!(component_any.is_some());
219
220 let downcasted = component_any.unwrap().downcast::<TestComponent>().unwrap();
221 assert_eq!(downcasted.value, 999);
222 }
223}