scf_core/manager/default/
mod.rs

1use std::collections::HashMap;
2use std::fmt;
3use std::sync::{Arc, RwLock};
4use std::time::*;
5
6use lang_extension::any::*;
7use lang_extension::fmt::*;
8
9use super::*;
10use crate::property::default::*;
11
12#[derive(Clone)]
13pub struct DefaultConfigurationManagerConfig {
14    name: String,
15    sources: Arc<Vec<Box<dyn ConfigurationSource>>>,
16    task_executor: ConsumerRef<Box<dyn Fn()>>,
17}
18
19impl PartialEq for DefaultConfigurationManagerConfig {
20    fn eq(&self, other: &Self) -> bool {
21        self.sources
22            .as_ref()
23            .reference_equals(other.sources.as_ref())
24    }
25}
26
27impl Eq for DefaultConfigurationManagerConfig {}
28
29impl fmt::Debug for DefaultConfigurationManagerConfig {
30    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
31        write!(
32            f,
33            "{} {{\n\tname: {},\n\tsources: {:?},\n\ttask_executor:\n\t{}\n}}",
34            self.type_name(),
35            self.name,
36            self.sources,
37            self.task_executor.as_ref().to_instance_string()
38        )
39    }
40}
41
42unsafe impl Sync for DefaultConfigurationManagerConfig {}
43unsafe impl Send for DefaultConfigurationManagerConfig {}
44
45impl ConfigurationManagerConfig for DefaultConfigurationManagerConfig {
46    fn get_name(&self) -> &str {
47        self.name.as_str()
48    }
49
50    fn get_sources(&self) -> &Vec<Box<dyn ConfigurationSource>> {
51        self.sources.as_ref()
52    }
53
54    fn get_task_executor(&self) -> &dyn Fn(&Box<dyn Fn()>) {
55        self.task_executor.as_ref().as_ref()
56    }
57
58    as_boxed!(impl ConfigurationManagerConfig);
59}
60
61pub struct DefaultConfigurationManagerConfigBuilder {
62    name: Option<String>,
63    sources: HashMap<i32, Box<dyn ConfigurationSource>>,
64    task_executor: Option<ConsumerRef<Box<dyn Fn()>>>,
65}
66
67impl DefaultConfigurationManagerConfigBuilder {
68    pub fn new() -> Self {
69        Self {
70            name: None,
71            sources: HashMap::new(),
72            task_executor: Some(arc_boxed!(Self::execute)),
73        }
74    }
75
76    fn execute(action: &Box<dyn Fn()>) {
77        action()
78    }
79}
80
81impl ConfigurationManagerConfigBuilder for DefaultConfigurationManagerConfigBuilder {
82    fn set_name(&mut self, name: &str) -> &mut dyn ConfigurationManagerConfigBuilder {
83        self.name = Some(name.to_owned());
84        self
85    }
86
87    fn add_source(
88        &mut self,
89        priority: i32,
90        source: Box<dyn ConfigurationSource>,
91    ) -> &mut dyn ConfigurationManagerConfigBuilder {
92        if self.sources.contains_key(&priority) {
93            panic!("a source with priority {} exists", priority);
94        }
95        self.sources.insert(priority, source);
96        self
97    }
98
99    fn add_sources(
100        &mut self,
101        sources: HashMap<i32, Box<dyn ConfigurationSource>>,
102    ) -> &mut dyn ConfigurationManagerConfigBuilder {
103        for (k, v) in sources.into_iter() {
104            self.sources.insert(k, v);
105        }
106        self
107    }
108
109    fn set_task_executor(
110        &mut self,
111        task_executor: ConsumerRef<Box<dyn Fn()>>,
112    ) -> &mut dyn ConfigurationManagerConfigBuilder {
113        self.task_executor = Some(task_executor);
114        self
115    }
116
117    fn build(&self) -> Box<dyn ConfigurationManagerConfig> {
118        Box::new(DefaultConfigurationManagerConfig {
119            name: self.name.as_ref().unwrap().to_owned(),
120            sources: Arc::new({
121                let mut keys: Vec<_> = self
122                    .sources
123                    .keys()
124                    .collect::<Vec<&i32>>()
125                    .iter()
126                    .map(|v| **v)
127                    .collect();
128                keys.sort();
129                keys.reverse();
130                let mut sources = Vec::new();
131                for k in keys {
132                    sources.push(ConfigurationSource::clone_boxed(
133                        self.sources.get(&k).unwrap().as_ref(),
134                    ));
135                }
136                sources
137            }),
138            task_executor: self.task_executor.as_ref().unwrap().clone(),
139        })
140    }
141}
142
143#[derive(Clone)]
144pub struct DefaultConfigurationManager {
145    config: Arc<Box<dyn ConfigurationManagerConfig>>,
146    properties: Arc<RwLock<HashMap<ImmutableKey, Box<dyn RawProperty>>>>,
147    change_listeners: Arc<RwLock<Vec<RawPropertyChangeListener>>>,
148}
149
150impl DefaultConfigurationManager {
151    pub fn new(config: Box<dyn ConfigurationManagerConfig>) -> DefaultConfigurationManager {
152        let manager = DefaultConfigurationManager {
153            config: Arc::new(config),
154            properties: Arc::new(RwLock::new(HashMap::new())),
155            change_listeners: Arc::new(RwLock::new(Vec::new())),
156        };
157        let clone = manager.clone();
158        let source_change_listener: ConfigurationSourceChangeListener =
159            Arc::new(Box::new(move |e| clone.on_source_change(e)));
160        for s in manager.config.get_sources() {
161            s.add_change_listener(source_change_listener.clone());
162        }
163        manager
164    }
165
166    fn on_source_change(&self, _event: &dyn ConfigurationSourceChangeEvent) {
167        let properties = self.properties.read().unwrap();
168        for property in properties.values() {
169            let (new_value, source) = self.do_get_property_value(property.get_raw_config());
170            let old_value = property.get_raw_value();
171            if new_value != old_value {
172                if property.get_raw_config().is_static() {
173                    warn!(
174                        "ignore dynamic change for static property, \
175                        dynamic change for static property will be applied when app restart, \
176                        static:\n\t{:?},\n\tdynamic:\n\t{:?},\n\tproperty: {:?}",
177                        old_value,
178                        new_value,
179                        property.get_raw_config().get_raw_key()
180                    );
181
182                    continue;
183                }
184
185                if new_value.is_none() && property.get_raw_config().is_required() {
186                    error!(
187                        "ignore dynamic change for required property, \
188                        required property cannot be changed to None, \
189                        now keep its current value, you should fix the invalid change at once, \
190                        or app will panic when next app restart, property:\n\t{:?}",
191                        property.get_raw_config().get_raw_key()
192                    );
193
194                    continue;
195                }
196
197                let pe = DefaultRawPropertyChangeEvent::new(
198                    Arc::new(RawProperty::clone_boxed(property.as_ref())),
199                    old_value.map(|v| ImmutableValue::wrap(v)),
200                    new_value.as_ref().map(|v| ImmutableValue::wrap(v.clone())),
201                    SystemTime::now()
202                        .duration_since(UNIX_EPOCH)
203                        .unwrap()
204                        .as_millis(),
205                );
206                let raw_property = property.as_ref();
207                let default_raw_property = raw_property
208                    .as_any_ref()
209                    .downcast_ref::<DefaultRawProperty>()
210                    .unwrap()
211                    .clone();
212                default_raw_property.update(new_value, source);
213                let pe_clone = pe.clone();
214                let mut action: Box<dyn Fn()> =
215                    Box::new(move || default_raw_property.raise_change_event(&pe_clone));
216                self.config.get_task_executor()(&action);
217                let manager = self.clone();
218                action = Box::new(move || manager.raise_change_event(&pe));
219                self.config.get_task_executor()(&action);
220            }
221        }
222    }
223
224    fn do_get_property_value(
225        &self,
226        config: &dyn RawPropertyConfig,
227    ) -> (Option<Box<dyn Value>>, Option<Box<dyn ConfigurationSource>>) {
228        for source in self.config.get_sources().iter() {
229            let value = source.get_property_value(config);
230            let new_value = self.apply_value_filter(config, source.get_config().get_name(), value);
231            if new_value.is_some() {
232                return (new_value, Some(source.clone()));
233            }
234        }
235
236        (config.get_raw_default_value(), None)
237    }
238
239    fn apply_value_filter(
240        &self,
241        config: &dyn RawPropertyConfig,
242        source: &str,
243        value: Option<Box<dyn Value>>,
244    ) -> Option<Box<dyn Value>> {
245        if value.is_none() {
246            return None;
247        }
248
249        if config.get_value_filter().is_none() {
250            return value;
251        }
252
253        let new_value = config
254            .get_value_filter()
255            .unwrap()
256            .filter_raw(value.clone().unwrap());
257        if new_value.is_some() {
258            if new_value != value {
259                warn!(
260                    "property value in config source {:?}\n\tchanged by property filter, \
261                    from: {:?},\n\tto: {:?},\n\tproperty: {:?}",
262                    source,
263                    value.as_ref().unwrap(),
264                    new_value.as_ref().unwrap(),
265                    config
266                );
267            }
268
269            info!(
270                "use property value in config source {:?},\n\tvalue: {:?},\n\tproperty: {:?}",
271                source,
272                new_value.as_ref().unwrap(),
273                config.get_raw_key()
274            );
275            return new_value;
276        } else {
277            error!(
278                "property value in source {:?}\n\tignored by property filter, probably not valid, \
279                value: {:?},\n\tproperty: {:?}",
280                source,
281                value.unwrap(),
282                config
283            );
284            None
285        }
286    }
287
288    fn check_required(&self, config: &dyn RawPropertyConfig, value: Option<&Box<dyn Value>>) {
289        if config.is_required() && value.is_none() {
290            panic!(
291                "None is got for required property, forgot to config it?\n\
292                Property: {:?}",
293                config
294            );
295        }
296    }
297
298    fn raise_change_event(&self, event: &dyn RawPropertyChangeEvent) {
299        let listeners = self.change_listeners.read().unwrap();
300        for listener in listeners.iter() {
301            listener(event);
302        }
303    }
304}
305
306impl ConfigurationManager for DefaultConfigurationManager {
307    fn get_config(&self) -> &dyn ConfigurationManagerConfig {
308        self.config.as_ref().as_ref()
309    }
310
311    fn get_properties(&self) -> Vec<Box<dyn RawProperty>> {
312        let lock = self.properties.read().unwrap();
313        let mut properties = Vec::<Box<dyn RawProperty>>::new();
314        for (_, p) in lock.iter() {
315            properties.push(p.clone());
316        }
317
318        properties
319    }
320
321    fn get_property(&self, config: &dyn RawPropertyConfig) -> Box<dyn RawProperty> {
322        let key = ImmutableKey::wrap(config.get_raw_key());
323        let mut opt_property = self
324            .properties
325            .read()
326            .unwrap()
327            .get(&key)
328            .map(|p| RawProperty::clone_boxed(p.as_ref()));
329        if opt_property.is_none() {
330            let mut map = self.properties.write().unwrap();
331            opt_property = match map.get(&key) {
332                Some(p) => Some(RawProperty::clone_boxed(p.as_ref())),
333                None => {
334                    let (value, source) = self.do_get_property_value(config);
335                    self.check_required(config, value.as_ref());
336                    let property = DefaultRawProperty::new(config);
337                    property.update(value, source);
338                    map.insert(key.clone(), RawProperty::clone_boxed(&property));
339                    Some(Box::new(property))
340                }
341            };
342        }
343
344        let property = opt_property.unwrap();
345        if !config.equals(property.get_raw_config().as_any_ref()) {
346            panic!(
347                "make sure using same config for property: {:?},\n\tprevious config: {:?},\n\t\
348                current config: {:?}",
349                config.get_raw_key(),
350                property.get_raw_config(),
351                config
352            );
353        }
354
355        property
356    }
357
358    fn get_property_value(&self, config: &dyn RawPropertyConfig) -> Option<Box<dyn Value>> {
359        let (value, _) = self.do_get_property_value(config);
360        self.check_required(config, value.as_ref());
361        value
362    }
363
364    fn add_raw_change_listener(&self, listener: RawPropertyChangeListener) {
365        self.change_listeners.write().unwrap().push(listener);
366    }
367
368    as_boxed!(impl ConfigurationManager);
369}
370
371impl PartialEq for DefaultConfigurationManager {
372    fn eq(&self, other: &Self) -> bool {
373        self.properties
374            .as_ref()
375            .reference_equals(other.properties.as_ref())
376    }
377}
378
379impl Eq for DefaultConfigurationManager {}
380
381impl fmt::Debug for DefaultConfigurationManager {
382    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
383        write!(
384            f,
385            "{} {{\n\tconfig: {:?},\n\tproperties: {:?}\n}}",
386            self.type_name(),
387            self.get_config(),
388            self.get_properties()
389        )
390    }
391}
392
393unsafe impl Sync for DefaultConfigurationManager {}
394unsafe impl Send for DefaultConfigurationManager {}
395
396#[cfg(test)]
397mod test {
398    use super::*;
399    use crate::source::default::*;
400    use crate::tests::init_log;
401    use lang_extension::convert::*;
402    use std::sync::atomic::*;
403    use std::thread;
404
405    fn new_source() -> DefaultConfigurationSource {
406        DefaultConfigurationSource::new(
407            DefaultConfigurationSourceConfigBuilder::new()
408                .set_name("test")
409                .build(),
410            Arc::new(Box::new(move |o| -> Option<Box<dyn Value>> {
411                let x = if Key::as_trait_ref(&"key_ok".to_string()).equals(o.as_any_ref()) {
412                    Some(Value::to_boxed("10".to_string()))
413                } else if Key::as_trait_ref(&"key_error".to_string()).equals(o.as_any_ref()) {
414                    Some(Value::to_boxed("error".to_string()))
415                } else {
416                    None
417                };
418                println!("raw_value: {:?}", x);
419                x
420            })),
421        )
422    }
423
424    fn new_value_converter() -> DefaultTypeConverter<String, i32> {
425        DefaultTypeConverter::<String, i32>::new(Box::new(|s| match s.parse::<i32>() {
426            Ok(v) => {
427                println!("parse value: {}", v);
428                Ok(Box::new(v))
429            }
430            Err(e) => {
431                println!("parse error: {}", e);
432                Err(Box::new(e.to_string()))
433            }
434        }))
435    }
436
437    fn new_property_config(
438        value_converter: &dyn TypeConverter<String, i32>,
439    ) -> Box<dyn PropertyConfig<String, i32>> {
440        DefaultPropertyConfigBuilder::<String, i32>::new()
441            .set_key(Box::new("key_ok".to_string()))
442            .add_value_converter(RawTypeConverter::clone_boxed(value_converter))
443            .set_value_filter(Box::new(DefaultValueFilter::<i32>::new(Box::new(|v| {
444                if *v == 10 { Some(Box::new(5)) } else { Some(v) }
445            }))))
446            .set_doc("for test")
447            .build()
448    }
449
450    fn new_property_config2(
451        value_converter: &dyn TypeConverter<String, i32>,
452    ) -> Box<dyn PropertyConfig<String, i32>> {
453        DefaultPropertyConfigBuilder::<String, i32>::new()
454            .set_key(Box::new("key_error".to_string()))
455            .add_value_converter(RawTypeConverter::clone_boxed(value_converter))
456            .build()
457    }
458
459    fn new_property_config3(
460        key: &str,
461        value_converter: &dyn TypeConverter<String, i32>,
462    ) -> Box<dyn PropertyConfig<String, i32>> {
463        DefaultPropertyConfigBuilder::<String, i32>::new()
464            .set_key(Box::new(key.to_string()))
465            .add_value_converter(RawTypeConverter::clone_boxed(value_converter))
466            .set_required(true)
467            .build()
468    }
469
470    fn new_property_config4(
471        key: &str,
472        value_converter: &dyn TypeConverter<String, i32>,
473    ) -> Box<dyn PropertyConfig<String, i32>> {
474        DefaultPropertyConfigBuilder::<String, i32>::new()
475            .set_key(Box::new(key.to_string()))
476            .add_value_converter(RawTypeConverter::clone_boxed(value_converter))
477            .set_static(true)
478            .build()
479    }
480
481    #[test]
482    fn manager_config_test() {
483        let source = new_source();
484        let config = DefaultConfigurationManagerConfigBuilder::new()
485            .set_name("test")
486            .add_source(1, Box::new(source))
487            .build();
488        println!("manager config: {:?}", config);
489
490        assert_eq!("test", config.get_name());
491
492        assert_eq!(1, config.get_sources().len());
493
494        let action: Box<dyn Fn()> = Box::new(|| {
495            println!("task executed");
496        });
497        config.get_task_executor()(&action);
498
499        assert_eq!(&config, &config.clone());
500    }
501
502    #[test]
503    fn manager_test() {
504        init_log();
505
506        let source = ConfigurationSource::to_boxed(new_source());
507        let config = DefaultConfigurationManagerConfigBuilder::new()
508            .set_name("test")
509            .add_source(1, source.clone())
510            .build();
511        let manager = DefaultConfigurationManager::new(config);
512        println!("manager: {:?}", manager);
513        assert_eq!("test", manager.get_config().get_name());
514
515        let value_converter = new_value_converter();
516        let config = new_property_config(&value_converter);
517        let property = manager.get_property(RawPropertyConfig::as_trait_ref(config.as_ref()));
518        assert_eq!(Some(Value::to_boxed(5)), property.get_raw_value());
519        assert_eq!(Some(source.clone()), property.get_source());
520        let config2 = new_property_config2(&value_converter);
521        let property2 = manager.get_property(RawPropertyConfig::as_trait_ref(config2.as_ref()));
522        assert_eq!(None, property2.get_raw_value());
523        assert_eq!(None, property2.get_source());
524
525        let value = manager.get_property_value(RawPropertyConfig::as_trait_ref(config.as_ref()));
526        assert_eq!(Some(Value::to_boxed(5)), value);
527        let value2 = manager.get_property_value(RawPropertyConfig::as_trait_ref(config2.as_ref()));
528        assert_eq!(None, value2);
529
530        let manager_clone = manager.clone();
531        let config_clone = config.clone();
532        let handle = thread::spawn(move || {
533            let property =
534                manager_clone.get_property(RawPropertyConfig::as_trait_ref(config_clone.as_ref()));
535            assert_eq!(Some(Value::to_boxed(5)), property.get_raw_value());
536        });
537        handle.join().unwrap();
538    }
539
540    #[test]
541    fn dynamic_test() {
542        init_log();
543
544        let mut builder = DefaultConfigurationSourceConfigBuilder::new();
545        let source_config = builder.set_name("test").build();
546        let property_provider: PropertyProvider = Arc::new(Box::new(|k| {
547            if k.equals("key_ok".to_string().as_any_ref()) {
548                Some(Value::to_boxed(20))
549            } else {
550                None
551            }
552        }));
553        let source0: Box<dyn ConfigurationSource> = Box::new(DefaultConfigurationSource::new(
554            source_config,
555            property_provider,
556        ));
557
558        let memory_map = Arc::new(RwLock::new(HashMap::<String, String>::new()));
559        memory_map
560            .write()
561            .unwrap()
562            .insert("key_ok".to_string(), "10".to_string());
563        memory_map
564            .write()
565            .unwrap()
566            .insert("key_error".to_string(), "error".to_string());
567        let memory_map2 = memory_map.clone();
568        let source = DefaultConfigurationSource::new(
569            DefaultConfigurationSourceConfigBuilder::new()
570                .set_name("test")
571                .build(),
572            Arc::new(Box::new(move |o| -> Option<Box<dyn Value>> {
573                match o.as_any_ref().downcast_ref::<String>() {
574                    Some(k) => memory_map2
575                        .read()
576                        .unwrap()
577                        .get(k)
578                        .map(|v| Value::clone_boxed(v)),
579                    None => None,
580                }
581            })),
582        );
583        let source_boxed = ConfigurationSource::clone_boxed(&source);
584        let config = DefaultConfigurationManagerConfigBuilder::new()
585            .set_name("test")
586            .add_source(0, source0.clone())
587            .add_source(1, source_boxed.clone())
588            .build();
589        let manager = DefaultConfigurationManager::new(config);
590
591        let value_converter = new_value_converter();
592        let config = new_property_config(&value_converter);
593        let property = manager.get_property(RawPropertyConfig::as_trait_ref(config.as_ref()));
594        assert_eq!(Some(Value::to_boxed(5)), property.get_raw_value());
595        assert_eq!(Some(source_boxed.clone()), property.get_source());
596        let config2 = new_property_config2(&value_converter);
597        let property2 = manager.get_property(RawPropertyConfig::as_trait_ref(config2.as_ref()));
598        assert_eq!(None, property2.get_raw_value());
599        assert_eq!(None, property2.get_source());
600
601        let value = manager.get_property_value(RawPropertyConfig::as_trait_ref(config.as_ref()));
602        assert_eq!(Some(Value::to_boxed(5)), value);
603        let value2 = manager.get_property_value(RawPropertyConfig::as_trait_ref(config2.as_ref()));
604        assert_eq!(None, value2);
605
606        memory_map
607            .write()
608            .unwrap()
609            .insert("key_ok".to_string(), "11".to_string());
610        source.raise_change_event();
611        assert_eq!(Some(Value::to_boxed(11)), property.get_raw_value());
612        let value2 = manager.get_property_value(RawPropertyConfig::as_trait_ref(config2.as_ref()));
613        assert_eq!(None, value2);
614
615        let value = manager.get_property_value(RawPropertyConfig::as_trait_ref(config.as_ref()));
616        assert_eq!(Some(Value::to_boxed(11)), value);
617        let value2 = manager.get_property_value(RawPropertyConfig::as_trait_ref(config2.as_ref()));
618        assert_eq!(None, value2);
619
620        let property = DefaultProperty::<String, i32>::from_raw(property.as_ref());
621        let changed = Arc::new(AtomicBool::new(false));
622        let changed_clone = changed.clone();
623        property.add_change_listener(Arc::new(Box::new(move |e| {
624            println!("changed: {:?}", e);
625            changed_clone.swap(true, Ordering::Relaxed);
626        })));
627        memory_map
628            .write()
629            .unwrap()
630            .insert("key_ok".to_string(), "12".to_string());
631        source.raise_change_event();
632        assert_eq!(Some(Box::new(12)), property.get_value());
633        assert_eq!(Some(source_boxed.clone()), property.get_source());
634        assert_eq!(Some(Value::to_boxed(12)), property.get_raw_value());
635        let value = manager.get_property_value(RawPropertyConfig::as_trait_ref(config.as_ref()));
636        assert_eq!(Some(Value::to_boxed(12)), value);
637        assert!(changed.fetch_and(true, Ordering::Relaxed));
638
639        memory_map.write().unwrap().remove(&"key_ok".to_string());
640        source.raise_change_event();
641        assert_eq!(Some(Box::new(20)), property.get_value());
642        assert_eq!(Some(source0.clone()), property.get_source());
643        memory_map
644            .write()
645            .unwrap()
646            .insert("key_error".to_string(), "1".to_string());
647        source.raise_change_event();
648        assert_eq!(Some(Value::to_boxed(1)), property2.get_raw_value());
649    }
650
651    #[test]
652    fn required_property() {
653        init_log();
654
655        let source = new_source();
656        let config = DefaultConfigurationManagerConfigBuilder::new()
657            .set_name("test")
658            .add_source(1, Box::new(source))
659            .build();
660        let manager = DefaultConfigurationManager::new(config);
661
662        let value_converter = new_value_converter();
663        let config = new_property_config3("key_ok", &value_converter);
664        manager.get_property(RawPropertyConfig::as_trait_ref(config.as_ref()));
665        manager.get_property_value(RawPropertyConfig::as_trait_ref(config.as_ref()));
666    }
667
668    #[should_panic]
669    #[test]
670    fn required_property2() {
671        init_log();
672
673        let source = new_source();
674        let config = DefaultConfigurationManagerConfigBuilder::new()
675            .set_name("test")
676            .add_source(1, Box::new(source))
677            .build();
678        let manager = DefaultConfigurationManager::new(config);
679
680        let value_converter = new_value_converter();
681        let config = new_property_config3("key_none", &value_converter);
682        manager.get_property(RawPropertyConfig::as_trait_ref(config.as_ref()));
683    }
684
685    #[should_panic]
686    #[test]
687    fn required_property3() {
688        init_log();
689
690        let source = new_source();
691        let config = DefaultConfigurationManagerConfigBuilder::new()
692            .set_name("test")
693            .add_source(1, Box::new(source))
694            .build();
695        let manager = DefaultConfigurationManager::new(config);
696
697        let value_converter = new_value_converter();
698        let config = new_property_config3("key_none", &value_converter);
699        manager.get_property_value(RawPropertyConfig::as_trait_ref(config.as_ref()));
700    }
701
702    #[test]
703    fn required_property_dynamic() {
704        init_log();
705
706        let memory_map = Arc::new(RwLock::new(HashMap::<String, String>::new()));
707        memory_map
708            .write()
709            .unwrap()
710            .insert("key_ok".to_string(), "20".to_string());
711        memory_map
712            .write()
713            .unwrap()
714            .insert("key_required".to_string(), "30".to_string());
715        let memory_map2 = memory_map.clone();
716        let source = DefaultConfigurationSource::new(
717            DefaultConfigurationSourceConfigBuilder::new()
718                .set_name("test")
719                .build(),
720            Arc::new(Box::new(move |o| -> Option<Box<dyn Value>> {
721                match o.as_any_ref().downcast_ref::<String>() {
722                    Some(k) => memory_map2
723                        .read()
724                        .unwrap()
725                        .get(k)
726                        .map(|v| Value::clone_boxed(v)),
727                    None => None,
728                }
729            })),
730        );
731        let config = DefaultConfigurationManagerConfigBuilder::new()
732            .set_name("test")
733            .add_source(1, Box::new(source.clone()))
734            .build();
735        let manager = DefaultConfigurationManager::new(config);
736
737        let value_converter = new_value_converter();
738        let config = new_property_config(&value_converter);
739        let property = manager.get_property(RawPropertyConfig::as_trait_ref(config.as_ref()));
740        assert_eq!(Some(Value::to_boxed(20)), property.get_raw_value());
741
742        memory_map.write().unwrap().remove(&"key_ok".to_string());
743        source.raise_change_event();
744        assert_eq!(None, property.get_raw_value());
745
746        let config = new_property_config3("key_required", &value_converter);
747        let property = manager.get_property(RawPropertyConfig::as_trait_ref(config.as_ref()));
748        assert_eq!(Some(Value::to_boxed(30)), property.get_raw_value());
749
750        memory_map
751            .write()
752            .unwrap()
753            .remove(&"key_required".to_string());
754        source.raise_change_event();
755        assert_eq!(Some(Value::to_boxed(30)), property.get_raw_value());
756    }
757
758    #[test]
759    fn static_property() {
760        init_log();
761
762        let memory_map = Arc::new(RwLock::new(HashMap::<String, String>::new()));
763        memory_map
764            .write()
765            .unwrap()
766            .insert("key_ok".to_string(), "20".to_string());
767        let memory_map2 = memory_map.clone();
768        let source = DefaultConfigurationSource::new(
769            DefaultConfigurationSourceConfigBuilder::new()
770                .set_name("test")
771                .build(),
772            Arc::new(Box::new(move |o| -> Option<Box<dyn Value>> {
773                match o.as_any_ref().downcast_ref::<String>() {
774                    Some(k) => memory_map2
775                        .read()
776                        .unwrap()
777                        .get(k)
778                        .map(|v| Value::clone_boxed(v)),
779                    None => None,
780                }
781            })),
782        );
783        let config = DefaultConfigurationManagerConfigBuilder::new()
784            .set_name("test")
785            .add_source(1, Box::new(source.clone()))
786            .build();
787        let manager = DefaultConfigurationManager::new(config);
788
789        let value_converter = new_value_converter();
790        let config = new_property_config4("key_ok", &value_converter);
791        let property = manager.get_property(RawPropertyConfig::as_trait_ref(config.as_ref()));
792        assert_eq!(Some(Value::to_boxed(20)), property.get_raw_value());
793
794        memory_map
795            .write()
796            .unwrap()
797            .insert("key_ok".to_string(), "30".to_string());
798        source.raise_change_event();
799        assert_eq!(Some(Value::to_boxed(20)), property.get_raw_value());
800
801        memory_map.write().unwrap().remove(&"key_ok".to_string());
802        source.raise_change_event();
803        assert_eq!(Some(Value::to_boxed(20)), property.get_raw_value());
804    }
805}