diff --git a/examples/fetch_state.rs b/examples/fetch_state.rs index 7a47029..64ea98b 100644 --- a/examples/fetch_state.rs +++ b/examples/fetch_state.rs @@ -12,8 +12,8 @@ async fn main() -> Result<(), MpvError> { let playlist = mpv.get_playlist().await?; println!("playlist: {:?}", playlist); - let playback_time: f64 = mpv.get_property("playback-time").await?; - println!("playback-time: {}", playback_time); + let playback_time: Option = mpv.get_property("playback-time").await?; + println!("playback-time: {:?}", playback_time); Ok(()) } diff --git a/src/core_api.rs b/src/core_api.rs index 92e7fee..49636a2 100644 --- a/src/core_api.rs +++ b/src/core_api.rs @@ -134,18 +134,22 @@ impl IntoRawCommandPart for SeekOptions { pub trait GetPropertyTypeHandler: Sized { // TODO: fix this #[allow(async_fn_in_trait)] - async fn get_property_generic(instance: &Mpv, property: &str) -> Result; + async fn get_property_generic(instance: &Mpv, property: &str) + -> Result, MpvError>; } impl GetPropertyTypeHandler for T where T: TypeHandler, { - async fn get_property_generic(instance: &Mpv, property: &str) -> Result { + async fn get_property_generic(instance: &Mpv, property: &str) -> Result, MpvError> { instance .get_property_value(property) .await - .and_then(T::get_value) + .and_then(|value| match value { + Some(v) => T::get_value(v).map(|v| Some(v)), + None => Ok(None), + }) } } @@ -172,7 +176,7 @@ where instance .command_sender .send(( - MpvIpcCommand::SetProperty(property.to_owned(), value), + MpvIpcCommand::SetProperty(property.to_owned(), value.to_owned()), res_tx, )) .await @@ -277,7 +281,7 @@ impl Mpv { command: &str, args: &[&str], ) -> Result, MpvError> { - let command = Vec::from( + let command_vec = Vec::from( [command] .iter() .chain(args.iter()) @@ -287,7 +291,7 @@ impl Mpv { ); let (res_tx, res_rx) = oneshot::channel(); self.command_sender - .send((MpvIpcCommand::Command(command), res_tx)) + .send((MpvIpcCommand::Command(command_vec.clone()), res_tx)) .await .map_err(|err| MpvError::InternalConnectionError(err.to_string()))?; @@ -462,7 +466,7 @@ impl Mpv { pub async fn get_property( &self, property: &str, - ) -> Result { + ) -> Result, MpvError> { T::get_property_generic(self, property).await } @@ -487,7 +491,7 @@ impl Mpv { /// Ok(()) /// } /// ``` - pub async fn get_property_value(&self, property: &str) -> Result { + pub async fn get_property_value(&self, property: &str) -> Result, MpvError> { let (res_tx, res_rx) = oneshot::channel(); self.command_sender .send((MpvIpcCommand::GetProperty(property.to_owned()), res_tx)) @@ -495,9 +499,7 @@ impl Mpv { .map_err(|err| MpvError::InternalConnectionError(err.to_string()))?; match res_rx.await { - Ok(MpvIpcResponse(response)) => { - response.and_then(|value| value.ok_or(MpvError::MissingMpvData)) - } + Ok(MpvIpcResponse(response)) => response, Err(err) => Err(MpvError::InternalConnectionError(err.to_string())), } } @@ -526,11 +528,10 @@ impl Mpv { /// Ok(()) /// } /// ``` - pub async fn set_property>( - &self, - property: &str, - value: T, - ) -> Result<(), MpvError> { - T::set_property_generic(self, property, value).await + pub async fn set_property(&self, property: &str, value: T) -> Result<(), MpvError> + where + T: SetPropertyTypeHandler + Clone + fmt::Debug, + { + T::set_property_generic(self, property, value.clone()).await } } diff --git a/src/error.rs b/src/error.rs index 7adb07e..6426f8c 100644 --- a/src/error.rs +++ b/src/error.rs @@ -46,3 +46,48 @@ pub enum MpvError { #[error("Unknown error: {0}")] Other(String), } + +impl PartialEq for MpvError { + fn eq(&self, other: &Self) -> bool { + match (self, other) { + (Self::MpvError(l0), Self::MpvError(r0)) => l0 == r0, + (Self::MpvSocketConnectionError(l0), Self::MpvSocketConnectionError(r0)) => l0 == r0, + (Self::InternalConnectionError(l0), Self::InternalConnectionError(r0)) => l0 == r0, + (Self::JsonParseError(l0), Self::JsonParseError(r0)) => { + l0.to_string() == r0.to_string() + } + ( + Self::ValueContainsUnexpectedType { + expected_type: l_expected_type, + received: l_received, + }, + Self::ValueContainsUnexpectedType { + expected_type: r_expected_type, + received: r_received, + }, + ) => l_expected_type == r_expected_type && l_received == r_received, + ( + Self::DataContainsUnexpectedType { + expected_type: l_expected_type, + received: l_received, + }, + Self::DataContainsUnexpectedType { + expected_type: r_expected_type, + received: r_received, + }, + ) => l_expected_type == r_expected_type && l_received == r_received, + ( + Self::MissingKeyInObject { + key: l_key, + map: l_map, + }, + Self::MissingKeyInObject { + key: r_key, + map: r_map, + }, + ) => l_key == r_key && l_map == r_map, + + _ => core::mem::discriminant(self) == core::mem::discriminant(other), + } + } +} diff --git a/src/event_property_parser.rs b/src/event_property_parser.rs index bfab40a..5250772 100644 --- a/src/event_property_parser.rs +++ b/src/event_property_parser.rs @@ -129,14 +129,19 @@ pub fn parse_event_property(event: Event) -> Result<(usize, Property), MpvError> }; Ok((id, Property::Metadata(metadata))) } - // "playlist" => { - // let playlist = match data { - // MpvDataType::Array(a) => json_array_to_playlist(&a), - // MpvDataType::Null => Vec::new(), - // _ => return Err(Error(ErrorCode::ValueDoesNotContainPlaylist)), - // }; - // Ok((id, Property::Playlist(playlist))) - // } + "playlist" => { + let playlist = match data { + Some(MpvDataType::Array(a)) => mpv_array_to_playlist(&a)?, + None => Vec::new(), + Some(data) => { + return Err(MpvError::DataContainsUnexpectedType { + expected_type: "Array".to_owned(), + received: data, + }) + } + }; + Ok((id, Property::Playlist(playlist))) + } "playlist-pos" => { let playlist_pos = match data { Some(MpvDataType::Usize(u)) => Some(u), @@ -246,3 +251,59 @@ pub fn parse_event_property(event: Event) -> Result<(usize, Property), MpvError> _ => Ok((id, Property::Unknown { name, data })), } } + +fn mpv_data_to_playlist_entry( + map: &HashMap, +) -> Result { + let filename = match map.get("filename") { + Some(MpvDataType::String(s)) => s.to_string(), + Some(data) => { + return Err(MpvError::DataContainsUnexpectedType { + expected_type: "String".to_owned(), + received: data.clone(), + }) + } + None => return Err(MpvError::MissingMpvData), + }; + let title = match map.get("title") { + Some(MpvDataType::String(s)) => s.to_string(), + Some(data) => { + return Err(MpvError::DataContainsUnexpectedType { + expected_type: "String".to_owned(), + received: data.clone(), + }) + } + None => return Err(MpvError::MissingMpvData), + }; + let current = match map.get("current") { + Some(MpvDataType::Bool(b)) => *b, + Some(data) => { + return Err(MpvError::DataContainsUnexpectedType { + expected_type: "bool".to_owned(), + received: data.clone(), + }) + } + None => return Err(MpvError::MissingMpvData), + }; + Ok(PlaylistEntry { + id: 0, + filename, + title, + current, + }) +} + +fn mpv_array_to_playlist(array: &[MpvDataType]) -> Result, MpvError> { + array + .iter() + .map(|value| match value { + MpvDataType::HashMap(map) => mpv_data_to_playlist_entry(map), + _ => Err(MpvError::DataContainsUnexpectedType { + expected_type: "HashMap".to_owned(), + received: value.clone(), + }), + }) + .enumerate() + .map(|(id, entry)| entry.map(|entry| PlaylistEntry { id, ..entry })) + .collect() +} diff --git a/src/highlevel_api_extension.rs b/src/highlevel_api_extension.rs index 4d7a4c0..255f53e 100644 --- a/src/highlevel_api_extension.rs +++ b/src/highlevel_api_extension.rs @@ -141,12 +141,15 @@ pub trait MpvExt { impl MpvExt for Mpv { async fn get_metadata(&self) -> Result, MpvError> { - self.get_property("metadata").await + self.get_property("metadata") + .await? + .ok_or(MpvError::MissingMpvData) } async fn get_playlist(&self) -> Result { self.get_property::>("playlist") - .await + .await? + .ok_or(MpvError::MissingMpvData) .map(Playlist) } @@ -174,15 +177,15 @@ impl MpvExt for Mpv { let enabled = match option { Switch::On => "yes", Switch::Off => "no", - Switch::Toggle => { - self.get_property::("pause") - .await - .map(|s| match s.as_str() { - "yes" => "no", - "no" => "yes", - _ => "no", - })? - } + Switch::Toggle => self + .get_property::("pause") + .await? + .ok_or(MpvError::MissingMpvData) + .map(|s| match s.as_str() { + "yes" => "no", + "no" => "yes", + _ => "no", + })?, }; self.set_property("pause", enabled).await } @@ -238,16 +241,16 @@ impl MpvExt for Mpv { } async fn playlist_play_next(&self, id: usize) -> Result<(), MpvError> { - match self.get_property::("playlist-pos").await { - Ok(current_id) => { - self.run_command(MpvCommand::PlaylistMove { - from: id, - to: current_id + 1, - }) - .await - } - Err(msg) => Err(msg), - } + let current_id = self + .get_property::("playlist-pos") + .await? + .ok_or(MpvError::MissingMpvData)?; + + self.run_command(MpvCommand::PlaylistMove { + from: id, + to: current_id + 1, + }) + .await } async fn playlist_remove_id(&self, id: usize) -> Result<(), MpvError> { @@ -266,15 +269,15 @@ impl MpvExt for Mpv { let enabled = match option { Switch::On => "inf", Switch::Off => "no", - Switch::Toggle => { - self.get_property::("loop-file") - .await - .map(|s| match s.as_str() { - "inf" => "no", - "no" => "inf", - _ => "no", - })? - } + Switch::Toggle => self + .get_property::("loop-file") + .await? + .ok_or(MpvError::MissingMpvData) + .map(|s| match s.as_str() { + "inf" => "no", + "no" => "inf", + _ => "no", + })?, }; self.set_property("loop-file", enabled).await } @@ -283,32 +286,32 @@ impl MpvExt for Mpv { let enabled = match option { Switch::On => "inf", Switch::Off => "no", - Switch::Toggle => { - self.get_property::("loop-playlist") - .await - .map(|s| match s.as_str() { - "inf" => "no", - "no" => "inf", - _ => "no", - })? - } + Switch::Toggle => self + .get_property::("loop-playlist") + .await? + .ok_or(MpvError::MissingMpvData) + .map(|s| match s.as_str() { + "inf" => "no", + "no" => "inf", + _ => "no", + })?, }; - self.set_property("loo-playlist", enabled).await + self.set_property("loop-playlist", enabled).await } async fn set_mute(&self, option: Switch) -> Result<(), MpvError> { let enabled = match option { Switch::On => "yes", Switch::Off => "no", - Switch::Toggle => { - self.get_property::("mute") - .await - .map(|s| match s.as_str() { - "yes" => "no", - "no" => "yes", - _ => "no", - })? - } + Switch::Toggle => self + .get_property::("mute") + .await? + .ok_or(MpvError::MissingMpvData) + .map(|s| match s.as_str() { + "yes" => "no", + "no" => "yes", + _ => "no", + })?, }; self.set_property("mute", enabled).await } @@ -318,19 +321,15 @@ impl MpvExt for Mpv { input_speed: f64, option: NumberChangeOptions, ) -> Result<(), MpvError> { - match self.get_property::("speed").await { - Ok(speed) => match option { - NumberChangeOptions::Increase => { - self.set_property("speed", speed + input_speed).await - } + let speed = self + .get_property::("speed") + .await? + .ok_or(MpvError::MissingMpvData)?; - NumberChangeOptions::Decrease => { - self.set_property("speed", speed - input_speed).await - } - - NumberChangeOptions::Absolute => self.set_property("speed", input_speed).await, - }, - Err(msg) => Err(msg), + match option { + NumberChangeOptions::Increase => self.set_property("speed", speed + input_speed).await, + NumberChangeOptions::Decrease => self.set_property("speed", speed - input_speed).await, + NumberChangeOptions::Absolute => self.set_property("speed", input_speed).await, } } @@ -339,19 +338,19 @@ impl MpvExt for Mpv { input_volume: f64, option: NumberChangeOptions, ) -> Result<(), MpvError> { - match self.get_property::("volume").await { - Ok(volume) => match option { - NumberChangeOptions::Increase => { - self.set_property("volume", volume + input_volume).await - } + let volume = self + .get_property::("volume") + .await? + .ok_or(MpvError::MissingMpvData)?; - NumberChangeOptions::Decrease => { - self.set_property("volume", volume - input_volume).await - } - - NumberChangeOptions::Absolute => self.set_property("volume", input_volume).await, - }, - Err(msg) => Err(msg), + match option { + NumberChangeOptions::Increase => { + self.set_property("volume", volume + input_volume).await + } + NumberChangeOptions::Decrease => { + self.set_property("volume", volume - input_volume).await + } + NumberChangeOptions::Absolute => self.set_property("volume", input_volume).await, } } diff --git a/src/message_parser.rs b/src/message_parser.rs index 3a652ba..3955082 100644 --- a/src/message_parser.rs +++ b/src/message_parser.rs @@ -109,7 +109,7 @@ impl TypeHandler for Vec { expected_type: "Array".to_string(), received: value.clone(), }) - .map(|array| json_array_to_playlist(array)) + .and_then(|array| json_array_to_playlist(array)) } fn as_string(&self) -> String { @@ -155,29 +155,65 @@ pub(crate) fn json_array_to_vec(array: &[Value]) -> Result, Mpv array.iter().map(json_to_value).collect() } -pub(crate) fn json_array_to_playlist(array: &[Value]) -> Vec { - let mut output: Vec = Vec::new(); - for (id, entry) in array.iter().enumerate() { - let mut filename: String = String::new(); - let mut title: String = String::new(); - let mut current: bool = false; - if let Value::String(ref f) = entry["filename"] { - filename = f.to_string(); +fn json_map_to_playlist_entry( + map: &serde_json::map::Map, +) -> Result { + let filename = match map.get("filename") { + Some(Value::String(s)) => s.to_string(), + Some(data) => { + return Err(MpvError::ValueContainsUnexpectedType { + expected_type: "String".to_owned(), + received: data.clone(), + }) } - if let Value::String(ref t) = entry["title"] { - title = t.to_string(); + None => return Err(MpvError::MissingMpvData), + }; + let title = match map.get("title") { + Some(Value::String(s)) => s.to_string(), + Some(data) => { + return Err(MpvError::ValueContainsUnexpectedType { + expected_type: "String".to_owned(), + received: data.clone(), + }) } - if let Value::Bool(ref b) = entry["current"] { - current = *b; + None => return Err(MpvError::MissingMpvData), + }; + let current = match map.get("current") { + Some(Value::Bool(b)) => *b, + Some(data) => { + return Err(MpvError::ValueContainsUnexpectedType { + expected_type: "bool".to_owned(), + received: data.clone(), + }) } - output.push(PlaylistEntry { - id, - filename, - title, - current, - }); - } - output + None => return Err(MpvError::MissingMpvData), + }; + Ok(PlaylistEntry { + id: 0, + filename, + title, + current, + }) +} + +pub(crate) fn json_array_to_playlist(array: &[Value]) -> Result, MpvError> { + array + .iter() + .map(|entry| match entry { + Value::Object(map) => json_map_to_playlist_entry(map), + data => Err(MpvError::ValueContainsUnexpectedType { + expected_type: "Map".to_owned(), + received: data.clone(), + }), + }) + .enumerate() + .map(|(id, entry)| { + entry.map(|mut entry| { + entry.id = id; + entry + }) + }) + .collect() } #[cfg(test)] @@ -277,7 +313,7 @@ mod test { } #[test] - fn test_json_array_to_playlist() { + fn test_json_array_to_playlist() -> Result<(), MpvError> { let json = json!([ { "filename": "file1", @@ -306,6 +342,8 @@ mod test { }, ]; - assert_eq!(json_array_to_playlist(json.as_array().unwrap()), expected); + assert_eq!(json_array_to_playlist(json.as_array().unwrap())?, expected); + + Ok(()) } } diff --git a/tests/integration_tests/misc.rs b/tests/integration_tests/misc.rs index 13d110b..4f3a56f 100644 --- a/tests/integration_tests/misc.rs +++ b/tests/integration_tests/misc.rs @@ -1,26 +1,30 @@ -use mpvipc::MpvExt; +use mpvipc::{MpvError, MpvExt}; use super::*; #[tokio::test] #[cfg(target_family = "unix")] -async fn test_get_mpv_version() { +async fn test_get_mpv_version() -> Result<(), MpvError> { let (mut proc, mpv) = spawn_headless_mpv().await.unwrap(); - let version: String = mpv.get_property("mpv-version").await.unwrap(); + let version: String = mpv.get_property("mpv-version").await?.unwrap(); assert!(version.starts_with("mpv")); mpv.kill().await.unwrap(); proc.kill().await.unwrap(); + + Ok(()) } #[tokio::test] #[cfg(target_family = "unix")] -async fn test_set_property() { +async fn test_set_property() -> Result<(), MpvError> { let (mut proc, mpv) = spawn_headless_mpv().await.unwrap(); mpv.set_property("pause", true).await.unwrap(); - let paused: bool = mpv.get_property("pause").await.unwrap(); + let paused: bool = mpv.get_property("pause").await?.unwrap(); assert!(paused); mpv.kill().await.unwrap(); proc.kill().await.unwrap(); + + Ok(()) } diff --git a/tests/mock_socket_tests/get_property.rs b/tests/mock_socket_tests/get_property.rs index 815e89a..1ce44e4 100644 --- a/tests/mock_socket_tests/get_property.rs +++ b/tests/mock_socket_tests/get_property.rs @@ -22,73 +22,77 @@ fn test_socket(answers: Vec) -> (UnixStream, JoinHandle Result<(), MpvError> { let (server, join_handle) = test_socket(vec![ json!({ "data": 100.0, "request_id": 0, "error": "success" }).to_string(), ]); - let mpv = Mpv::connect_socket(server).await.unwrap(); - let volume: f64 = mpv.get_property("volume").await.unwrap(); + let mpv = Mpv::connect_socket(server).await?; + let volume: Option = mpv.get_property("volume").await?; - assert_eq!(volume, 100.0); + assert_eq!(volume, Some(100.0)); join_handle.await.unwrap().unwrap(); + + Ok(()) } #[test(tokio::test)] -async fn test_get_property_broken_pipe() { +async fn test_get_property_broken_pipe() -> Result<(), MpvError> { let (server, join_handle) = test_socket(vec![]); let mpv = Mpv::connect_socket(server).await.unwrap(); let maybe_volume = mpv.get_property::("volume").await; - match maybe_volume { - Err(MpvError::MpvSocketConnectionError(err)) => { - assert_eq!(err.to_string(), "Broken pipe (os error 32)"); - } - _ => panic!("Unexpected result: {:?}", maybe_volume), - } + assert_eq!( + maybe_volume, + Err(MpvError::MpvSocketConnectionError( + "Broken pipe (os error 32)".to_string() + )) + ); + join_handle.await.unwrap().unwrap(); + + Ok(()) } #[test(tokio::test)] -async fn test_get_property_wrong_type() { +async fn test_get_property_wrong_type() -> Result<(), MpvError> { let (server, join_handle) = test_socket(vec![ json!({ "data": 100.0, "request_id": 0, "error": "success" }).to_string(), ]); - let mpv = Mpv::connect_socket(server).await.unwrap(); + let mpv = Mpv::connect_socket(server).await?; let maybe_volume = mpv.get_property::("volume").await; - match maybe_volume { + assert_eq!( + maybe_volume, Err(MpvError::ValueContainsUnexpectedType { - expected_type, - received, - }) => { - assert_eq!(expected_type, "bool"); - assert_eq!(received, json!(100.0)); - } - _ => panic!("Unexpected result: {:?}", maybe_volume), - } + expected_type: "bool".to_string(), + received: json!(100.0) + }) + ); join_handle.await.unwrap().unwrap(); + + Ok(()) } #[test(tokio::test)] -async fn test_get_property_error() { +async fn test_get_property_error() -> Result<(), MpvError> { let (server, join_handle) = test_socket(vec![ json!({ "error": "property unavailable", "request_id": 0 }).to_string(), ]); - let mpv = Mpv::connect_socket(server).await.unwrap(); + let mpv = Mpv::connect_socket(server).await?; let maybe_volume = mpv.get_property::("volume").await; - match maybe_volume { - Err(MpvError::MpvError(err)) => { - assert_eq!(err, "property unavailable"); - } - _ => panic!("Unexpected result: {:?}", maybe_volume), - } + assert_eq!( + maybe_volume, + Err(MpvError::MpvError("property unavailable".to_string())) + ); join_handle.await.unwrap().unwrap(); + + Ok(()) } #[test(tokio::test)] @@ -130,8 +134,8 @@ async fn test_get_property_simultaneous_requests() { let mpv_clone_1 = mpv.clone(); let mpv_poller_1 = tokio::spawn(async move { loop { - let volume: f64 = mpv_clone_1.get_property("volume").await.unwrap(); - assert_eq!(volume, 100.0); + let volume: Option = mpv_clone_1.get_property("volume").await.unwrap(); + assert_eq!(volume, Some(100.0)); } }); @@ -139,8 +143,8 @@ async fn test_get_property_simultaneous_requests() { let mpv_poller_2 = tokio::spawn(async move { loop { tokio::time::sleep(Duration::from_millis(1)).await; - let paused: bool = mpv_clone_2.get_property("pause").await.unwrap(); - assert!(paused); + let paused: Option = mpv_clone_2.get_property("pause").await.unwrap(); + assert_eq!(paused, Some(true)); } }); @@ -173,7 +177,7 @@ async fn test_get_property_simultaneous_requests() { } #[test(tokio::test)] -async fn test_get_playlist() { +async fn test_get_playlist() -> Result<(), MpvError> { let expected = Playlist(vec![ PlaylistEntry { id: 0, @@ -208,22 +212,26 @@ async fn test_get_playlist() { }) .to_string()]); - let mpv = Mpv::connect_socket(server).await.unwrap(); - let playlist = mpv.get_playlist().await.unwrap(); + let mpv = Mpv::connect_socket(server).await?; + let playlist = mpv.get_playlist().await?; assert_eq!(playlist, expected); join_handle.await.unwrap().unwrap(); + + Ok(()) } #[test(tokio::test)] -async fn test_get_playlist_empty() { +async fn test_get_playlist_empty() -> Result<(), MpvError> { let (server, join_handle) = test_socket(vec![ json!({ "data": [], "request_id": 0, "error": "success" }).to_string(), ]); - let mpv = Mpv::connect_socket(server).await.unwrap(); - let playlist = mpv.get_playlist().await.unwrap(); + let mpv = Mpv::connect_socket(server).await?; + let playlist = mpv.get_playlist().await?; assert_eq!(playlist, Playlist(vec![])); join_handle.await.unwrap().unwrap(); + + Ok(()) } diff --git a/tests/mock_socket_tests/set_property.rs b/tests/mock_socket_tests/set_property.rs index 79b1a51..55bf1d6 100644 --- a/tests/mock_socket_tests/set_property.rs +++ b/tests/mock_socket_tests/set_property.rs @@ -1,7 +1,7 @@ use std::{panic, time::Duration}; use futures::{stream::FuturesUnordered, SinkExt, StreamExt}; -use mpvipc::{Mpv, MpvError, MpvExt, Playlist, PlaylistEntry}; +use mpvipc::{Mpv, MpvError}; use serde_json::{json, Value}; use test_log::test; use tokio::{net::UnixStream, task::JoinHandle}; @@ -22,69 +22,76 @@ fn test_socket(answers: Vec) -> (UnixStream, JoinHandle Result<(), MpvError> { let (server, join_handle) = test_socket(vec![ json!({ "data": null, "request_id": 0, "error": "success" }).to_string(), ]); - let mpv = Mpv::connect_socket(server).await.unwrap(); - let volume = mpv.set_property("volume", 64.0).await; + let mpv = Mpv::connect_socket(server).await?; + mpv.set_property("volume", 64.0).await?; - assert!(volume.is_ok()); join_handle.await.unwrap().unwrap(); + + Ok(()) } #[test(tokio::test)] -async fn test_set_property_broken_pipe() { +async fn test_set_property_broken_pipe() -> Result<(), MpvError> { let (server, join_handle) = test_socket(vec![]); - let mpv = Mpv::connect_socket(server).await.unwrap(); + let mpv = Mpv::connect_socket(server).await?; let maybe_set_volume = mpv.set_property("volume", 64.0).await; - match maybe_set_volume { - Err(MpvError::MpvSocketConnectionError(err)) => { - assert_eq!(err.to_string(), "Broken pipe (os error 32)"); - } - _ => panic!("Unexpected result: {:?}", maybe_set_volume), - } + assert_eq!( + maybe_set_volume, + Err(MpvError::MpvSocketConnectionError( + "Broken pipe (os error 32)".to_string() + )) + ); + join_handle.await.unwrap().unwrap(); + + Ok(()) } #[test(tokio::test)] -async fn test_set_property_wrong_type() { +async fn test_set_property_wrong_type() -> Result<(), MpvError> { let (server, join_handle) = test_socket(vec![ json!({"request_id":0,"error":"unsupported format for accessing property"}).to_string(), ]); - let mpv = Mpv::connect_socket(server).await.unwrap(); + let mpv = Mpv::connect_socket(server).await?; let maybe_volume = mpv.set_property::("volume", true).await; - match maybe_volume { - Err(MpvError::MpvError(err)) => { - assert_eq!(err, "unsupported format for accessing property"); - } - _ => panic!("Unexpected result: {:?}", maybe_volume), - } + assert_eq!( + maybe_volume, + Err(MpvError::MpvError( + "unsupported format for accessing property".to_string() + )) + ); + join_handle.await.unwrap().unwrap(); + + Ok(()) } #[test(tokio::test)] -async fn test_get_property_error() { +async fn test_get_property_error() -> Result<(), MpvError> { let (server, join_handle) = test_socket(vec![ json!({"request_id":0,"error":"property not found"}).to_string(), ]); - let mpv = Mpv::connect_socket(server).await.unwrap(); + let mpv = Mpv::connect_socket(server).await?; let maybe_volume = mpv.set_property("nonexistent", true).await; - match maybe_volume { - Err(MpvError::MpvError(err)) => { - assert_eq!(err, "property not found"); - } - _ => panic!("Unexpected result: {:?}", maybe_volume), - } + assert_eq!( + maybe_volume, + Err(MpvError::MpvError("property not found".to_string())) + ); join_handle.await.unwrap().unwrap(); + + Ok(()) } #[test(tokio::test)] @@ -175,59 +182,3 @@ async fn test_set_property_simultaneous_requests() { panic!("One of the pollers quit unexpectedly"); }; } - -#[test(tokio::test)] -async fn test_get_playlist() { - let expected = Playlist(vec![ - PlaylistEntry { - id: 0, - filename: "file1".to_string(), - title: "title1".to_string(), - current: false, - }, - PlaylistEntry { - id: 1, - filename: "file2".to_string(), - title: "title2".to_string(), - current: true, - }, - PlaylistEntry { - id: 2, - filename: "file3".to_string(), - title: "title3".to_string(), - current: false, - }, - ]); - - let (server, join_handle) = test_socket(vec![json!({ - "data": expected.0.iter().map(|entry| { - json!({ - "filename": entry.filename, - "title": entry.title, - "current": entry.current - }) - }).collect::>(), - "request_id": 0, - "error": "success" - }) - .to_string()]); - - let mpv = Mpv::connect_socket(server).await.unwrap(); - let playlist = mpv.get_playlist().await.unwrap(); - - assert_eq!(playlist, expected); - join_handle.await.unwrap().unwrap(); -} - -#[test(tokio::test)] -async fn test_get_playlist_empty() { - let (server, join_handle) = test_socket(vec![ - json!({ "data": [], "request_id": 0, "error": "success" }).to_string(), - ]); - - let mpv = Mpv::connect_socket(server).await.unwrap(); - let playlist = mpv.get_playlist().await.unwrap(); - - assert_eq!(playlist, Playlist(vec![])); - join_handle.await.unwrap().unwrap(); -}