use std::time::Duration; use assert_matches::assert_matches; use rmpv::Value; use serde::{Deserialize, Serialize}; use tarantool_rs::{errors::Error, Connection, Executor, ExecutorExt}; use tracing_test::traced_test; use crate::common::{TarantoolTestContainer, TarantoolTestContainerExt}; mod common; #[derive(Debug, Deserialize, PartialEq, Serialize)] struct CrewMember { id: u32, name: String, rank: String, occupation: String, } #[tokio::test] #[traced_test] async fn image_test() -> Result<(), anyhow::Error> { let container = TarantoolTestContainer::new_with_test_data(); let conn = container.create_conn().await?; conn.ping().await?; Ok(()) } #[tokio::test] #[traced_test] async fn auth_ok() -> Result<(), anyhow::Error> { let container = TarantoolTestContainer::new_with_test_data(); let conn = Connection::builder() .auth("Sisko", Some("A-4-7-1")) .build(format!("127.0.0.1:{}", container.connect_port())) .await?; conn.ping().await?; Ok(()) } #[tokio::test] #[traced_test] async fn auth_err() -> Result<(), anyhow::Error> { let container = TarantoolTestContainer::new_with_test_data(); assert_matches!( Connection::builder() .auth("Quark", Some("Q-0-0-0")) .build(format!("127.0.0.1:{}", container.connect_port())) .await .map(drop), Err(Error::Auth(_)) ); Ok(()) } #[tokio::test] #[traced_test] async fn eval() -> Result<(), anyhow::Error> { let container = TarantoolTestContainer::new_with_test_data(); let conn = container.create_conn().await?; let res: u32 = conn.eval("return ...", (42,)).await?.decode_result()?; assert_eq!(res, 42); Ok(()) } #[tokio::test] #[traced_test] async fn call() -> Result<(), anyhow::Error> { let container = TarantoolTestContainer::new_with_test_data(); let conn = container.create_conn().await?; let res: String = conn.call("station_name", (false,)).await?.decode_first()?; assert_eq!(res, "Deep Space 9"); Ok(()) } #[tokio::test] #[traced_test] async fn retrieve_schema() -> Result<(), anyhow::Error> { let container = TarantoolTestContainer::new_with_test_data(); let conn = container.create_conn().await?; let space = conn .space("ds9_crew") .await? .expect("Space 'ds9_crew' found"); assert_eq!( space.metadata().id(), 512, "First user space expected to have id 512" ); assert_eq!(space.metadata().name(), "ds9_crew"); let index_count = space.indices().count(); assert!(index_count > 1, "There should be multiple indices"); Ok(()) } #[tokio::test] #[traced_test] async fn select_all() -> Result<(), anyhow::Error> { let container = TarantoolTestContainer::new_with_test_data(); let conn: Connection = container.create_conn().await?; let space = conn .space("ds9_crew") .await? .expect("Space 'ds9_crew' found"); let members: Vec = space .select(None, None, Some(tarantool_rs::IteratorType::All), ()) .await?; assert_eq!(members.len(), 7); assert_eq!( members[1], CrewMember { id: 2, name: "Kira Nerys".into(), rank: "Major".into(), occupation: "First officer".into() } ); Ok(()) } #[tokio::test] #[traced_test] async fn select_limits() -> Result<(), anyhow::Error> { let container = TarantoolTestContainer::new_with_test_data(); let conn: Connection = container.create_conn().await?; let space = conn .space("ds9_crew") .await? .expect("Space 'ds9_crew' found"); let members: Vec = space .select(Some(2), Some(2), Some(tarantool_rs::IteratorType::All), ()) .await?; assert_eq!(members.len(), 2); assert_eq!( members[1], CrewMember { id: 4, name: "Julian Bashir".into(), rank: "Lieutenant".into(), occupation: "Chief medical officer".into() } ); Ok(()) } #[tokio::test] #[traced_test] async fn select_by_key() -> Result<(), anyhow::Error> { let container = TarantoolTestContainer::new_with_test_data(); let conn: Connection = container.create_conn().await?; let space = conn .space("ds9_crew") .await? .expect("Space 'ds9_crew' found"); let rank_idx = space.index("idx_rank").expect("Rank index present"); let members: Vec = rank_idx .select(None, None, None, ("Lieutenant Commander",)) .await?; assert_eq!(members.len(), 2); assert_eq!( members[0], CrewMember { id: 3, name: "Jadzia Dax".into(), rank: "Lieutenant Commander".into(), occupation: "Science officer".into() } ); Ok(()) } #[tokio::test] #[traced_test] async fn timeout() -> Result<(), anyhow::Error> { let container = TarantoolTestContainer::new_with_test_data(); let conn = Connection::builder() .timeout(Duration::from_millis(100)) .build(format!("127.0.0.1:{}", container.connect_port())) .await?; assert_matches!( conn.eval("require('fiber').sleep(1)", ()).await, Err(tarantool_rs::Error::Timeout) ); Ok(()) } #[tokio::test] #[traced_test] async fn dmo() -> Result<(), anyhow::Error> { let container = TarantoolTestContainer::new_with_test_data(); let conn = Connection::builder() .timeout(Duration::from_millis(100)) .build(format!("127.0.0.1:{}", container.connect_port())) .await?; let tx = conn.transaction().await?; let space = tx.space("ds9_crew").await?.expect("Space 'ds9_crew' found"); let name_idx = space.index("idx_name").unwrap(); // update let new_value: CrewMember = name_idx .update( ("Benjamin Sisko",), (Value::Array(vec!["=".into(), 2.into(), "Captain".into()]),), ) .await? .decode()?; assert_eq!( new_value, CrewMember { id: 1, name: "Benjamin Sisko".into(), rank: "Captain".into(), occupation: "Commanding officer".into() } ); // delete let _: CrewMember = name_idx.delete(("Jadzia Dax",)).await?.decode()?; // insert let _: CrewMember = space .insert((None::<()>, "Ezri Dax", "Ensign", "Counselor")) .await? .decode()?; tx.commit().await?; Ok(()) }