Translate complete RLV test suite

This commit is contained in:
2026-08-08 23:21:40 +02:00
parent 1604822689
commit 3140e65dc7
31 changed files with 14434 additions and 4938 deletions

View File

@@ -0,0 +1,383 @@
//! Exact Rust translations of the non-inventory RLV command tests.
use libremetaverse_compat_tests::block_on;
use libremetaverse_compat_tests::rlv_support::{RlvHarness, TeleportCall, guid};
const OBJECT: &str = "00000000-0000-4000-8000-000000000000";
const OTHER_SENDER: &str = "aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaaa";
fn harness() -> RlvHarness {
RlvHarness::new().expect("RlvService constructor")
}
// parity-case: LibreMetaverse.Tests/RLV/Commands/AdjustHeightCommandTests.cs::AdjustHeightCommandTests.AdjustHeight::test fb3adb86988b10b2d3fe9223324f8a3c1ba7b8c2ea909ee6b57b38c590fed372 translated
#[test]
fn adjust_height() {
let h = harness();
block_on(h.process("@adjustheight:4.3;1.25=force")).unwrap();
assert_eq!(
h.actions.lock().unwrap().adjusted_heights,
vec![(4.3, 1.25, 0.0)]
);
}
// parity-case: LibreMetaverse.Tests/RLV/Commands/AdjustHeightCommandTests.cs::AdjustHeightCommandTests.AdjustHeight_WithDelta::test 1f37a125fd9df8585740d37c711888dfcd92460d86c19077f771d7f3fab54264 translated
#[test]
fn adjust_height_with_delta() {
let h = harness();
block_on(h.process("@adjustheight:4.3;1.25;12.34=force")).unwrap();
assert_eq!(
h.actions.lock().unwrap().adjusted_heights,
vec![(4.3, 1.25, 12.34)]
);
}
fn seed_clear(h: &RlvHarness) {
block_on(h.process("@tploc=n")).unwrap();
block_on(h.process("@tplm=n")).unwrap();
block_on(h.process("@unsit=n")).unwrap();
block_on(h.process("@fly=n")).unwrap();
}
// parity-case: LibreMetaverse.Tests/RLV/Commands/ClearCommandTests.cs::ClearCommandTests.Clear::test 865d022233930e9582fec5b0e99063f15506a339c430755aba83706b594182ad translated
#[test]
fn clear() {
let h = harness();
seed_clear(&h);
block_on(h.process("@clear")).unwrap();
assert!(
h.service
.restrictions()
.find_restrictions(None, None)
.unwrap()
.is_empty()
);
}
// parity-case: LibreMetaverse.Tests/RLV/Commands/ClearCommandTests.cs::ClearCommandTests.Clear_CaseInSensitive::test b70296f9d2b6c9eb8c6dd6e560056ab8320d746a991fafec858812fc2ebb3141 translated
#[test]
fn clear_is_case_insensitive() {
let h = harness();
seed_clear(&h);
block_on(h.process("@cLEaR")).unwrap();
assert!(
h.service
.restrictions()
.find_restrictions(None, None)
.unwrap()
.is_empty()
);
}
// parity-case: LibreMetaverse.Tests/RLV/Commands/ClearCommandTests.cs::ClearCommandTests.Clear_SenderBased::test 1ae70737411e18626227c0b15181572c1c623eefce0a8fa1a874b2229c44c38e translated
#[test]
fn clear_is_sender_based() {
let h = harness();
block_on(h.process("@tploc=n")).unwrap();
block_on(h.process("@tplm=n")).unwrap();
block_on(h.process_from("@unsit=n", OTHER_SENDER, "Sender 2")).unwrap();
block_on(h.process_from("@fly=n", OTHER_SENDER, "Sender 2")).unwrap();
block_on(h.process_from("@clear", OTHER_SENDER, "Sender 2")).unwrap();
let permissions = h.service.permissions();
assert_eq!(
[
permissions.can_tp_loc().unwrap(),
permissions.can_tp_lm().unwrap(),
permissions.can_unsit().unwrap(),
permissions.can_fly().unwrap()
],
[false, false, true, true]
);
}
// parity-case: LibreMetaverse.Tests/RLV/Commands/ClearCommandTests.cs::ClearCommandTests.Clear_Filtered::test e0f0b5a42c3baf92fef6a8d4fc2c60dbd6963db6f844fed55b06968f0c9e543f translated
#[test]
fn clear_is_filtered() {
let h = harness();
seed_clear(&h);
block_on(h.process("@clear=tp")).unwrap();
let permissions = h.service.permissions();
assert_eq!(
[
permissions.can_tp_loc().unwrap(),
permissions.can_tp_lm().unwrap(),
permissions.can_unsit().unwrap(),
permissions.can_fly().unwrap()
],
[true, true, false, false]
);
}
fn set_debug(setting: &str, value: &str) -> Vec<(String, String)> {
let h = harness();
block_on(h.process(&format!("@setdebug_{setting}:{value}=force"))).unwrap();
h.actions.lock().unwrap().debug_settings.clone()
}
// parity-case: LibreMetaverse.Tests/RLV/Commands/SetDebugCommandTests.cs::SetDebugCommandTests.SetDebug_Default::case:fa77559e30768d15 abcee425068df326a3258ab4d881218e6eee52523fa5d306b191308e85dfff3d translated
#[test]
fn set_debug_known_setting() {
assert_eq!(
set_debug("RenderResolutionDivisor", "RenderResolutionDivisor Success"),
vec![(
"renderresolutiondivisor".into(),
"RenderResolutionDivisor Success".into()
)]
);
}
// parity-case: LibreMetaverse.Tests/RLV/Commands/SetDebugCommandTests.cs::SetDebugCommandTests.SetDebug_Default::case:55694f25ed879d95 abcee425068df326a3258ab4d881218e6eee52523fa5d306b191308e85dfff3d translated
#[test]
fn set_debug_unknown_setting() {
assert_eq!(
set_debug("Unknown Setting", "Unknown Setting Success"),
vec![("unknown setting".into(), "Unknown Setting Success".into())]
);
}
// parity-case: LibreMetaverse.Tests/RLV/Commands/SetDebugCommandTests.cs::SetDebugCommandTests.SetDebug_Invalid::test 2e0595319ba8e2c9a8280c5b034363ad7998eb740cb6b7fff3d75bb0167c6464 translated
#[test]
fn set_debug_rejects_empty_name() {
let h = harness();
assert!(!block_on(h.process("@setdebug_:42=force")).unwrap());
assert!(h.actions.lock().unwrap().debug_settings.is_empty());
}
fn set_env(setting: &str, value: &str) -> Vec<(String, String)> {
let h = harness();
block_on(h.process(&format!("@setenv_{setting}:{value}=force"))).unwrap();
h.actions.lock().unwrap().environment_settings.clone()
}
// parity-case: LibreMetaverse.Tests/RLV/Commands/SetEnvCommandTests.cs::SetEnvCommandTests.SetEnv_Default::case:f656b648d00a6d91 836c1332ca9c4f645e5c9dca8b4a2b967d55fd8148901b05ce5d741e665ab7e1 translated
#[test]
fn set_environment_known_setting() {
assert_eq!(
set_env("Daytime", "Daytime Success"),
vec![("daytime".into(), "Daytime Success".into())]
);
}
// parity-case: LibreMetaverse.Tests/RLV/Commands/SetEnvCommandTests.cs::SetEnvCommandTests.SetEnv_Default::case:55694f25ed879d95 836c1332ca9c4f645e5c9dca8b4a2b967d55fd8148901b05ce5d741e665ab7e1 translated
#[test]
fn set_environment_unknown_setting() {
assert_eq!(
set_env("Unknown Setting", "Unknown Setting Success"),
vec![("unknown setting".into(), "Unknown Setting Success".into())]
);
}
// parity-case: LibreMetaverse.Tests/RLV/Commands/SetGroupCommandTests.cs::SetGroupCommandTests.SetGroup_ByName::test fae27e58cd981f5471f4c2b8356bb07aa5e76a57aaf0882d0dbfb86360e077e3 translated
#[test]
fn set_group_by_name() {
let h = harness();
block_on(h.process("@setgroup:Group Name=force")).unwrap();
assert_eq!(
h.actions.lock().unwrap().group_names,
vec![("Group Name".into(), None)]
);
}
// parity-case: LibreMetaverse.Tests/RLV/Commands/SetGroupCommandTests.cs::SetGroupCommandTests.SetGroup_ByNameAndRole::test 408442b86bb8259eb9bbb4cf8a5d3b0830c7ba9357fa04cb6e851511a7a24df1 translated
#[test]
fn set_group_by_name_and_role() {
let h = harness();
block_on(h.process("@setgroup:Group Name;Admin Role=force")).unwrap();
assert_eq!(
h.actions.lock().unwrap().group_names,
vec![("Group Name".into(), Some("Admin Role".into()))]
);
}
// parity-case: LibreMetaverse.Tests/RLV/Commands/SetGroupCommandTests.cs::SetGroupCommandTests.SetGroup_ById::test 27f13c52c8c5e2e4298fee3f4322f9906d5f82e900aa5f46c9a8ffac3a6dfae7 translated
#[test]
fn set_group_by_id() {
let h = harness();
block_on(h.process(&format!("@setgroup:{OBJECT}=force"))).unwrap();
assert_eq!(
h.actions.lock().unwrap().group_ids,
vec![(guid(OBJECT), None)]
);
}
// parity-case: LibreMetaverse.Tests/RLV/Commands/SetGroupCommandTests.cs::SetGroupCommandTests.SetGroup_ByIdAndRole::test e18fd0c318ebd4f9a189418449568b3a34b8f7d3a0097f100a7253c4d5a31bde translated
#[test]
fn set_group_by_id_and_role() {
let h = harness();
block_on(h.process(&format!("@setgroup:{OBJECT};Admin Role=force"))).unwrap();
assert_eq!(
h.actions.lock().unwrap().group_ids,
vec![(guid(OBJECT), Some("Admin Role".into()))]
);
}
// parity-case: LibreMetaverse.Tests/RLV/Commands/SetRotCommandTests.cs::SetRotCommandTests.SetRot::test c3302d63cdda9d72b85dad2749e2684cc26d51c72ddc6ace8275911f8ba67ef4 translated
#[test]
fn set_rotation() {
let h = harness();
block_on(h.process("@setrot:1.5=force")).unwrap();
assert_eq!(h.actions.lock().unwrap().rotations, vec![1.5]);
}
fn sit_harness(is_sitting: bool, exists: bool) -> RlvHarness {
let h = harness();
h.queries.lock().unwrap().is_sitting = is_sitting;
h.queries
.lock()
.unwrap()
.object_exists
.insert(guid(OBJECT), exists);
h
}
// parity-case: LibreMetaverse.Tests/RLV/Commands/SitCommandTests.cs::SitCommandTests.ForceSit_Default::test 24e45ba898cb8ed0919369d07a39d0b21982fa4fc4c41eb4835ba765c05e2469 translated
#[test]
fn force_sit() {
let h = sit_harness(false, true);
block_on(h.process(&format!("@sit:{OBJECT}=force"))).unwrap();
assert_eq!(h.actions.lock().unwrap().sits, vec![guid(OBJECT)]);
}
// parity-case: LibreMetaverse.Tests/RLV/Commands/SitCommandTests.cs::SitCommandTests.ForceSit_RestrictedUnsit_WhileStanding::test 8d179277f6a7f98ead813de7bd02ab5146b46ce240d1d5e4a69037885e5f626a translated
#[test]
fn force_sit_with_unsit_restricted_while_standing() {
let h = sit_harness(false, true);
block_on(h.process("@unsit=n")).unwrap();
block_on(h.process(&format!("@sit:{OBJECT}=force"))).unwrap();
assert_eq!(h.actions.lock().unwrap().sits, vec![guid(OBJECT)]);
}
// parity-case: LibreMetaverse.Tests/RLV/Commands/SitCommandTests.cs::SitCommandTests.ForceSit_RestrictedUnsit_WhileSeated::test 1f2debd6e644c86698577e1c04db96d6aac43267ceae8de9f28435b62ff92817 translated
#[test]
fn force_sit_rejects_unsit_restriction_while_seated() {
let h = sit_harness(true, true);
block_on(h.process("@unsit=n")).unwrap();
assert!(!block_on(h.process(&format!("@sit:{OBJECT}=force"))).unwrap());
assert!(h.actions.lock().unwrap().sits.is_empty());
}
// parity-case: LibreMetaverse.Tests/RLV/Commands/SitCommandTests.cs::SitCommandTests.ForceSit_RestrictedSit::test 8ac0964fc07bb5e860123ce8de1102c2254ffde28f246896d81f7524c3c87021 translated
#[test]
fn force_sit_rejects_sit_restriction() {
let h = sit_harness(true, true);
block_on(h.process("@sit=n")).unwrap();
assert!(!block_on(h.process(&format!("@sit:{OBJECT}=force"))).unwrap());
assert!(h.actions.lock().unwrap().sits.is_empty());
}
// parity-case: LibreMetaverse.Tests/RLV/Commands/SitCommandTests.cs::SitCommandTests.ForceSit_RestrictedStandTp::test bc0c259477ef5f1e5a76b1081f604ba421c82340f738e37fd52b91a421037cf6 translated
#[test]
fn force_sit_rejects_standtp_restriction() {
let h = sit_harness(true, true);
block_on(h.process("@standtp=n")).unwrap();
assert!(!block_on(h.process(&format!("@sit:{OBJECT}=force"))).unwrap());
assert!(h.actions.lock().unwrap().sits.is_empty());
}
// parity-case: LibreMetaverse.Tests/RLV/Commands/SitCommandTests.cs::SitCommandTests.ForceSit_InvalidObject::test 787bfe6fefe3895b4bcb5da027ffeac70bf67c3c7a295dbbf7e1526156290040 translated
#[test]
fn force_sit_rejects_invalid_object() {
let h = sit_harness(false, false);
assert!(!block_on(h.process(&format!("@sit:{OBJECT}=force"))).unwrap());
assert!(h.actions.lock().unwrap().sits.is_empty());
}
// parity-case: LibreMetaverse.Tests/RLV/Commands/SitGroundCommandTests.cs::SitGroundCommandTests.ForceSitGround::test 2319cd49aaae5ac824bc5ffd4f33a5e4f3f684ebec1dc1f1732071eb44ee1cb8 translated
#[test]
fn force_sit_ground() {
let h = harness();
assert!(block_on(h.process("@sitground=force")).unwrap());
}
// parity-case: LibreMetaverse.Tests/RLV/Commands/SitGroundCommandTests.cs::SitGroundCommandTests.ForceSitGround_RestrictedSit::test 5ac661e9f7fa93cf6ca76aa69f6d84ac61ebd22f26620203f084777010b6de4d translated
#[test]
fn force_sit_ground_rejects_sit_restriction() {
let h = harness();
block_on(h.process("@sit=n")).unwrap();
assert!(!block_on(h.process("@sitground=force")).unwrap());
}
fn teleport(command: &str) -> Vec<TeleportCall> {
let h = harness();
block_on(h.process(command)).unwrap();
h.actions.lock().unwrap().teleports.clone()
}
// parity-case: LibreMetaverse.Tests/RLV/Commands/TpToCommandTests.cs::TpToCommandTests.TpTo_Default::test 1613e723da60f84dfb54a7345b96566a055a9b7a017e66b0929d6f37c04b62a3 translated
#[test]
fn teleport_default() {
assert_eq!(
teleport("@tpto:1.5/2.5/3.5=force"),
vec![TeleportCall {
x: 1.5,
y: 2.5,
z: 3.5,
region: None,
look_at: None
}]
);
}
// parity-case: LibreMetaverse.Tests/RLV/Commands/TpToCommandTests.cs::TpToCommandTests.TpTo_WithRegion::test 50c5f63c5cb0da221846fd7c0c7f2d471bef2aa2ab203a9b5bdb4eceeb3d97bf translated
#[test]
fn teleport_with_region() {
assert_eq!(
teleport("@tpto:Region Name/1.5/2.5/3.5=force"),
vec![TeleportCall {
x: 1.5,
y: 2.5,
z: 3.5,
region: Some("Region Name".into()),
look_at: None
}]
);
}
// parity-case: LibreMetaverse.Tests/RLV/Commands/TpToCommandTests.cs::TpToCommandTests.TpTo_WithRegionAndLookAt::test c9030189de7acdad0db5c8f83e49ee0433ec0588a35436ab39cdcf40a4fd4d36 translated
#[test]
#[allow(clippy::approx_constant)] // Exact C# fixture literal, not a PI approximation.
fn teleport_with_region_and_look_at() {
assert_eq!(
teleport("@tpto:Region Name/1.5/2.5/3.5;3.1415=force"),
vec![TeleportCall {
x: 1.5,
y: 2.5,
z: 3.5,
region: Some("Region Name".into()),
look_at: Some(Some(3.1415))
}]
);
}
// parity-case: LibreMetaverse.Tests/RLV/Commands/TpToCommandTests.cs::TpToCommandTests.TpTo_RestrictedUnsit::test 4dc00a1048593f7468271a4262cf311a3516ea4a53e288eeca69d1297dafc9f2 translated
#[test]
fn teleport_rejects_unsit_restriction() {
let h = harness();
block_on(h.process("@unsit=n")).unwrap();
assert!(!block_on(h.process("@tpto:1.5/2.5/3.5=force")).unwrap());
assert!(h.actions.lock().unwrap().teleports.is_empty());
}
// parity-case: LibreMetaverse.Tests/RLV/Commands/TpToCommandTests.cs::TpToCommandTests.TpTo_RestrictedTpLoc::test 3e1ecc1d04973a496edf9d156e52ba76a93ff431181a3ece93c0e4f82884895a translated
#[test]
fn teleport_rejects_tploc_restriction() {
let h = harness();
block_on(h.process("@tploc=n")).unwrap();
assert!(!block_on(h.process("@tpto:1.5/2.5/3.5=force")).unwrap());
assert!(h.actions.lock().unwrap().teleports.is_empty());
}
// parity-case: LibreMetaverse.Tests/RLV/Commands/UnsitCommandTests.cs::UnsitCommandTests.ForceUnSit::test 2f91e1112e1c4e97b79a4dc7bcd4d4a85f13125bd636f81147ce5b396366ebed translated
#[test]
fn force_unsit() {
let h = harness();
assert!(block_on(h.process("@unsit=force")).unwrap());
}
// parity-case: LibreMetaverse.Tests/RLV/Commands/UnsitCommandTests.cs::UnsitCommandTests.ForceUnSit_RestrictedUnsit::test 2ecf210dc83b06018cdcf44cb44bdf43f1040133e7523542a2e1126d6d98004f translated
#[test]
fn force_unsit_rejects_unsit_restriction() {
let h = harness();
block_on(h.process("@unsit=n")).unwrap();
assert!(!block_on(h.process("@unsit=force")).unwrap());
}