Skip to content

Commit

Permalink
fix: Drop illegal VibrateCmd feature descriptions on protocol downgrade
Browse files Browse the repository at this point in the history
Fixes #608
  • Loading branch information
blackspherefollower authored and qdot committed Mar 2, 2024
1 parent df2f128 commit 9a759a1
Show file tree
Hide file tree
Showing 2 changed files with 160 additions and 1 deletion.
Expand Up @@ -392,7 +392,8 @@ impl From<ClientDeviceMessageAttributes> 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()
Expand Down
158 changes: 158 additions & 0 deletions buttplug/tests/test_message_downgrades.rs
Expand Up @@ -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<ButtplugSerializedMessage> = 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<ButtplugSerializedMessage> = 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<ButtplugSerializedMessage> = 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
);
}

0 comments on commit 9a759a1

Please sign in to comment.