use std::{ rc::Rc, sync::RwLock, }; use static_assertions::assert_impl_all; use postgres::{ Client, NoTls, }; use serde_json::{ Map, Value, }; use cqrs_es2::{ EventEnvelope, IAggregate, IEventStore, }; use cqrs_es2_sql::{ get_cqrs, EventStore, }; use super::common_one::*; assert_impl_all!( EventStore::: IEventStore:: ); fn test_store() -> EventStore { let conn = Client::connect(CONNECTION_STRING, NoTls).unwrap(); EventStore::::new(conn) } #[test] fn test_valid_cqrs_framework() { let view_events: Rc>>> = Default::default(); let query = TestQuery::new(view_events); let conn = Client::connect(CONNECTION_STRING, NoTls).unwrap(); let _ps = get_cqrs(conn, vec![Box::new(query)]); } #[test] fn commit_and_load_events() { let mut event_store = test_store(); let id = uuid::Uuid::new_v4().to_string(); assert_eq!(0, event_store.load(id.as_str()).len()); let context = event_store.load_aggregate(id.as_str()); event_store .commit( vec![ TestEvent::Created(Created { id: "test_event_A".to_string(), }), TestEvent::Tested(Tested { test_name: "test A".to_string(), }), ], context, metadata(), ) .unwrap(); assert_eq!(2, event_store.load(id.as_str()).len()); let context = event_store.load_aggregate(id.as_str()); event_store .commit( vec![TestEvent::Tested(Tested { test_name: "test B".to_string(), })], context, metadata(), ) .unwrap(); assert_eq!(3, event_store.load(id.as_str()).len()); } // #[test] // TODO: test no longer valid, is there a way to cover this // elsewhere? #[allow(dead_code)] fn optimistic_lock_error() { let mut event_store = test_store(); let id = uuid::Uuid::new_v4().to_string(); assert_eq!(0, event_store.load(id.as_str()).len()); let context = event_store.load_aggregate(id.as_str()); event_store .commit( vec![TestEvent::Created(Created { id: "test_event_A".to_string(), })], context, metadata(), ) .unwrap(); let context = event_store.load_aggregate(id.as_str()); let result = event_store.commit( vec![TestEvent::Tested(Tested { test_name: "test B".to_string(), })], context, metadata(), ); match result { Ok(_) => { panic!("expected an optimistic lock error") }, Err(e) => { assert_eq!( e, cqrs_es2::AggregateError::TechnicalError( "optimistic lock error".to_string() ) ); }, }; } #[test] fn test_event_breakout_type() { let event = TestEvent::Created(Created { id: "test_event_A".to_string(), }); let (event_type, value) = serialize_event::(&event); println!("{} - {}", &event_type, &value); let test_event: TestEvent = deserialize_event::( event_type.as_str(), value, ); assert_eq!(test_event, event); } fn serialize_event( event: &A::Event ) -> (String, Value) { let val = serde_json::to_value(event).unwrap(); match &val { Value::Object(object) => { for key in object.keys() { let value = object.get(key).unwrap(); return (key.to_string(), value.clone()); } panic!("{:?} not a domain event", val); }, _ => { panic!("{:?} not an object", val); }, } } fn deserialize_event( event_type: &str, value: Value, ) -> A::Event { let mut new_val_map = Map::with_capacity(1); new_val_map.insert(event_type.to_string(), value); let new_event_val = Value::Object(new_val_map); serde_json::from_value(new_event_val).unwrap() } #[test] fn thread_safe_test() { // TODO: use R2D2 for sync/send // https://github.com/sfackler/r2d2-postgres // fn is_sync() {} // is_sync::>(); fn is_send() {} is_send::>(); }