From 9a759a1d7137d40c3bd39c7262c400b8fde369eb Mon Sep 17 00:00:00 2001 From: blackspherefollower Date: Mon, 5 Feb 2024 15:51:05 +0000 Subject: [PATCH] fix: Drop illegal VibrateCmd feature descriptions on protocol downgrade Fixes #608 --- .../client_device_message_attributes.rs | 3 +- buttplug/tests/test_message_downgrades.rs | 158 ++++++++++++++++++ 2 files changed, 160 insertions(+), 1 deletion(-) diff --git a/buttplug/src/core/message/client_device_message_attributes.rs b/buttplug/src/core/message/client_device_message_attributes.rs index 521c5ed90..f710d9182 100644 --- a/buttplug/src/core/message/client_device_message_attributes.rs +++ b/buttplug/src/core/message/client_device_message_attributes.rs @@ -392,7 +392,8 @@ impl From for ClientDeviceMessageAttributesV2 { vibrate_cmd: other .scalar_cmd() .as_ref() - .map(|x| GenericDeviceMessageAttributesV2::vibrate_cmd_from_scalar_cmd(x)), + .map(|x| GenericDeviceMessageAttributesV2::vibrate_cmd_from_scalar_cmd(x)) + .filter(|x| x.feature_count != 0), rotate_cmd: other .rotate_cmd() .as_ref() diff --git a/buttplug/tests/test_message_downgrades.rs b/buttplug/tests/test_message_downgrades.rs index a3e473a6e..4fe17a6fe 100644 --- a/buttplug/tests/test_message_downgrades.rs +++ b/buttplug/tests/test_message_downgrades.rs @@ -169,3 +169,161 @@ async fn test_version0_singlemotorvibratecmd() { HardwareCommand::Write(HardwareWriteCmd::new(Endpoint::Tx, vec![0xF1, 64], false)), ); } + +#[tokio::test] +async fn test_version1_singlemotorvibratecmd() { + let (server, mut device) = test_server_with_device("Massage Demo", false).await; + let recv = server.event_stream(); + pin_mut!(recv); + let serializer = ButtplugServerJSONSerializer::default(); + let rsi = + r#"[{"RequestServerInfo":{"Id": 1, "ClientName": "Test Client", "MessageVersion": 1}}]"#; + let output = server + .parse_message( + serializer + .deserialize(&rsi.to_owned().into()) + .expect("Test, assuming infallible.")[0] + .clone(), + ) + .await + .expect("Test, assuming infallible."); + assert_eq!( + serializer.serialize(&vec!(output)), + r#"[{"ServerInfo":{"Id":1,"MajorVersion":0,"MinorVersion":0,"BuildVersion":0,"MessageVersion":1,"MaxPingTime":0,"ServerName":"Buttplug Server"}}]"#.to_owned().into(), + ); + // Skip JSON parsing here, we aren't converting versions. + let reply = server + .parse_message(message::StartScanning::default().into()) + .await; + assert!(reply.is_ok(), "Should get back ok: {:?}", reply); + // Check that we got an event back about scanning finishing. + let mut msg = recv.next().await.expect("Test, assuming infallible."); + let mut smsg = serializer.serialize(&vec![msg]); + // We should receive ScanningFinished and DeviceAdded, but the order may change. + let possible_messages: Vec = vec![r#"[{"ScanningFinished":{"Id":0}}]"#.to_owned().into(), r#"[{"DeviceAdded":{"Id":0,"DeviceIndex":0,"DeviceName":"Aneros Vivi","DeviceMessages":{"VibrateCmd":{"FeatureCount":2},"stop_device_cmd":{},"single_motor_vibrate_cmd":{}}}}]"#.to_owned().into()]; + assert!( + possible_messages.contains(&smsg), + "We should receive ScanningFinished and DeviceAdded, but the order may change. Got {:?}", + smsg + ); + msg = recv.next().await.expect("Test, assuming infallible."); + smsg = serializer.serialize(&vec![msg]); + // We should get back an aneros with only SingleMotorVibrateCmd + assert!( + possible_messages.contains(&smsg), + "We should receive ScanningFinished and DeviceAdded, but the order may change. Got {:?}", + smsg + ); + let output2 = server + .parse_message( + serializer + .deserialize( + &r#"[{"VibrateCmd": { "Id": 2, "DeviceIndex": 0, "Speeds": [{ "Index": 0, "Speed": 0.5 }]}}]"# + .to_owned() + .into(), + ) + .expect("Test, assuming infallible.")[0] + .clone(), + ) + .await + .expect("Test, assuming infallible."); + assert_eq!( + serializer.serialize(&vec!(output2)), + r#"[{"Ok":{"Id":2}}]"#.to_owned().into() + ); + check_test_recv_value( + &mut device, + HardwareCommand::Write(HardwareWriteCmd::new(Endpoint::Tx, vec![0xF1, 64], false)), + ); +} + +#[tokio::test] +async fn test_version0_oscilatoronly() { + let (server, mut _device) = test_server_with_device("Xone", false).await; + let recv = server.event_stream(); + pin_mut!(recv); + let serializer = ButtplugServerJSONSerializer::default(); + let rsi = r#"[{"RequestServerInfo":{"Id": 1, "ClientName": "Test Client"}}]"#; + let output = server + .parse_message( + serializer + .deserialize(&rsi.to_owned().into()) + .expect("Test, assuming infallible.")[0] + .clone(), + ) + .await + .expect("Test, assuming infallible."); + assert_eq!( + serializer.serialize(&vec!(output)), + r#"[{"ServerInfo":{"Id":1,"MajorVersion":0,"MinorVersion":0,"BuildVersion":0,"MessageVersion":0,"MaxPingTime":0,"ServerName":"Buttplug Server"}}]"#.to_owned().into(), + ); + // Skip JSON parsing here, we aren't converting versions. + let reply = server + .parse_message(message::StartScanning::default().into()) + .await; + assert!(reply.is_ok(), "Should get back ok: {:?}", reply); + // Check that we got an event back about scanning finishing. + let mut msg = recv.next().await.expect("Test, assuming infallible."); + let mut smsg = serializer.serialize(&vec![msg]); + // We should receive ScanningFinished and DeviceAdded, but the order may change. + let possible_messages: Vec = vec![r#"[{"ScanningFinished":{"Id":0}}]"#.to_owned().into(), r#"[{"DeviceAdded":{"Id":0,"DeviceIndex":0,"DeviceName":"MagicMotion Xone","DeviceMessages":["StopDeviceCmd"]}}]"#.to_owned().into()]; + assert!( + possible_messages.contains(&smsg), + "We should receive ScanningFinished and DeviceAdded, but the order may change. Got {:?}", + smsg + ); + msg = recv.next().await.expect("Test, assuming infallible."); + smsg = serializer.serialize(&vec![msg]); + // We should get back an MagicMotion Xone with no actuators + assert!( + possible_messages.contains(&smsg), + "We should receive ScanningFinished and DeviceAdded, but the order may change. Got {:?}", + smsg + ); +} + +#[tokio::test] +async fn test_version1_oscilatoronly() { + let (server, mut _device) = test_server_with_device("Xone", false).await; + let recv = server.event_stream(); + pin_mut!(recv); + let serializer = ButtplugServerJSONSerializer::default(); + let rsi = + r#"[{"RequestServerInfo":{"Id": 1, "ClientName": "Test Client", "MessageVersion": 1}}]"#; + let output = server + .parse_message( + serializer + .deserialize(&rsi.to_owned().into()) + .expect("Test, assuming infallible.")[0] + .clone(), + ) + .await + .expect("Test, assuming infallible."); + assert_eq!( + serializer.serialize(&vec!(output)), + r#"[{"ServerInfo":{"Id":1,"MajorVersion":0,"MinorVersion":0,"BuildVersion":0,"MessageVersion":1,"MaxPingTime":0,"ServerName":"Buttplug Server"}}]"#.to_owned().into(), + ); + // Skip JSON parsing here, we aren't converting versions. + let reply = server + .parse_message(message::StartScanning::default().into()) + .await; + assert!(reply.is_ok(), "Should get back ok: {:?}", reply); + // Check that we got an event back about scanning finishing. + let mut msg = recv.next().await.expect("Test, assuming infallible."); + let mut smsg = serializer.serialize(&vec![msg]); + // We should receive ScanningFinished and DeviceAdded, but the order may change. + let possible_messages: Vec = vec![r#"[{"ScanningFinished":{"Id":0}}]"#.to_owned().into(), r#"[{"DeviceAdded":{"Id":0,"DeviceIndex":0,"DeviceName":"MagicMotion Xone","DeviceMessages":{"stop_device_cmd":{}}}}]"#.to_owned().into()]; + assert!( + possible_messages.contains(&smsg), + "We should receive ScanningFinished and DeviceAdded, but the order may change. Got {:?}", + smsg + ); + msg = recv.next().await.expect("Test, assuming infallible."); + smsg = serializer.serialize(&vec![msg]); + // We should get back an MagicMotion Xone with no actuators + assert!( + possible_messages.contains(&smsg), + "We should receive ScanningFinished and DeviceAdded, but the order may change. Got {:?}", + smsg + ); +}