reactive_graph_std_arithmetic/behaviour/entity/
counter.rs

1use reactive_graph_behaviour_model_api::behaviour_validator;
2use reactive_graph_behaviour_model_api::prelude::*;
3use reactive_graph_behaviour_model_impl::entity_behaviour;
4use reactive_graph_graph::prelude::*;
5use reactive_graph_reactive_model_impl::ReactiveEntity;
6use serde_json::Value;
7use serde_json::json;
8use uuid::Uuid;
9
10use reactive_graph_runtime_model::ActionProperties::TRIGGER;
11use reactive_graph_std_result_model::ResultNumberU64Properties::RESULT;
12
13entity_behaviour!(Counter, CounterFactory, CounterFsm, CounterBehaviourTransitions, CounterValidator);
14
15behaviour_validator!(CounterValidator, Uuid, ReactiveEntity, TRIGGER.as_ref(), RESULT.as_ref());
16
17impl BehaviourInit<Uuid, ReactiveEntity> for CounterBehaviourTransitions {}
18
19impl BehaviourConnect<Uuid, ReactiveEntity> for CounterBehaviourTransitions {
20    fn connect(&self) -> Result<(), BehaviourConnectFailed> {
21        // let counter = crate::model_arithmetic::Counter::from(self.reactive_instance.clone());
22        let reactive_instance = self.reactive_instance.clone();
23        self.property_observers.observe_with_handle(TRIGGER.as_ref(), move |trigger: &Value| {
24            if !trigger.as_bool().unwrap_or(false) {
25                return;
26            }
27            match reactive_instance.get(RESULT).and_then(|v| v.as_i64()) {
28                Some(current_value) => {
29                    reactive_instance.set(RESULT, json!(current_value + 1));
30                }
31                None => {
32                    reactive_instance.set(RESULT, json!(0));
33                }
34            }
35        });
36        Ok(())
37    }
38}
39
40impl BehaviourShutdown<Uuid, ReactiveEntity> for CounterBehaviourTransitions {}
41impl BehaviourTransitions<Uuid, ReactiveEntity> for CounterBehaviourTransitions {}
42
43#[cfg(test)]
44mod tests {
45    use super::*;
46    use serde_json::json;
47
48    use crate::behaviour::entity::counter::CounterFactory;
49    use reactive_graph_reactive_model_api::ReactiveInstanceContainer;
50    use reactive_graph_reactive_model_impl::ReactiveProperties;
51    use reactive_graph_runtime_model::ActionProperties::TRIGGER;
52    use reactive_graph_std_arithmetic_model::BEHAVIOUR_COUNTER;
53    use reactive_graph_std_arithmetic_model::Counter1;
54    use reactive_graph_std_arithmetic_model::ENTITY_TYPE_COUNTER;
55    use reactive_graph_std_result_model::ResultNumberU64Properties::RESULT;
56
57    // TODO: This test should be moved to the reactive model
58    #[cfg(feature = "rustc_nightly")]
59    #[test]
60    fn rx_counter_test() {
61        let id = Uuid::new_v4();
62        let properties = PropertyInstances::new().property(RESULT, json!(0)).property(TRIGGER, json!(false));
63
64        let reactive_instance = ReactiveEntity::builder()
65            .ty(ENTITY_TYPE_COUNTER.clone())
66            .id(id)
67            .properties(ReactiveProperties::new_with_id_from_properties(id, properties))
68            .build();
69
70        let counter = Counter1::from(reactive_instance.clone());
71
72        let factory = CounterFactory::new(BEHAVIOUR_COUNTER.clone());
73        {
74            let behaviour = factory.create(reactive_instance.clone()).expect("Failed to create behaviour");
75            assert_eq!(BehaviourState::Connected, behaviour.get_state(), "The behaviour should be connected!");
76
77            assert_eq!(0, counter.result, "The counter should have the default value!");
78            (counter.trigger)(true);
79            assert_eq!(1, counter.result, "The counter should have been increased!");
80            (counter.trigger)(true);
81            assert_eq!(2, counter.result, "The counter should have been increased!");
82            (counter.trigger)(true);
83            assert_eq!(3, counter.result, "The counter should have been increased!");
84        }
85
86        (counter.trigger)(true);
87        assert_eq!(3, counter.result, "The behaviour should have been dropped.");
88    }
89
90    #[cfg(feature = "rustc_nightly")]
91    #[test]
92    fn rx_counter_2_test() {
93        let counter = Counter1::new(false, 0u64);
94        // let reactive_entity = counter.result.get_reactive_instance();
95
96        let factory = CounterFactory::new(BEHAVIOUR_COUNTER.clone());
97        {
98            let behaviour = factory
99                .create(counter.result.get_reactive_instance().clone())
100                .expect("Failed to create behaviour");
101            assert_eq!(BehaviourState::Connected, behaviour.get_state(), "The behaviour should be connected!");
102
103            assert_eq!(0, counter.result, "The counter should have the default value!");
104            (counter.trigger)(true);
105            assert_eq!(1, counter.result, "The counter should have been increased!");
106            (counter.trigger)(true);
107            assert_eq!(2, counter.result, "The counter should have been increased!");
108            (counter.trigger)(true);
109            assert_eq!(3, counter.result, "The counter should have been increased!");
110        }
111
112        (counter.trigger)(true);
113        assert_eq!(3, counter.result, "The behaviour should have been dropped.");
114    }
115}