Files
MetaCrate/tests/compat/tests/appearance_visual_semantics.rs

206 lines
8.2 KiB
Rust

// Exact Rust translations of LibreMetaverse.Tests/AppearanceTests.cs.
// Source SHA-256: 3d1f6a43127ee2c678284fd68572c0e81d1825766cc88e17136111fe8b3b7a86
use libremetaverse::{
AppearanceFlags, Avatar, AvatarAppearanceEventArgs, PrimitiveTextureEntryFace, VisualParam,
VisualParams,
};
use libremetaverse_types::{UUID, Utils};
use std::collections::HashSet;
fn group0_params() -> Vec<VisualParam> {
let mut params = VisualParams::params();
VisualParams::group0_param_ids()
.into_iter()
.filter_map(|id| params.0.remove(&id))
.collect()
}
fn appearance_args(visual_params: Vec<u8>) -> AvatarAppearanceEventArgs {
AvatarAppearanceEventArgs::new(
None,
UUID::zero(),
false,
PrimitiveTextureEntryFace::new(None).unwrap(),
Vec::new(),
visual_params,
1,
0,
AppearanceFlags::NONE,
0,
)
.unwrap()
}
// parity-case: LibreMetaverse.Tests/AppearanceTests.cs::AppearanceTests.DecodeVisualParams_EmptyArray_ReturnsEmptyDictionary::test 644f412b90d429032a9273d24e89333a1694dc88eec3429a98acf00588315ec5 translated
#[test]
fn decode_visual_params_empty_array_returns_empty_dictionary() {
let mut avatar = Avatar::new().unwrap();
avatar.visual_parameters = Vec::new();
let decoded = avatar.decode_visual_params().unwrap();
assert_eq!(decoded.len(), 0);
}
// parity-case: LibreMetaverse.Tests/AppearanceTests.cs::AppearanceTests.DecodeVisualParams_CountMatchesGroup0ParamCount::test 6a9acc7130e3394476392b86334a0ce1cb82253bea2b37ac33cf90a426c7af40 translated
#[test]
fn decode_visual_params_count_matches_group0_param_count() {
let group0 = group0_params();
let mut avatar = Avatar::new().unwrap();
avatar.visual_parameters = vec![0; group0.len()];
let decoded = avatar.decode_visual_params().unwrap();
assert!(decoded.len() >= group0.len());
}
// parity-case: LibreMetaverse.Tests/AppearanceTests.cs::AppearanceTests.DecodeVisualParams_RoundTrip_DefaultValues::test a0c0727a50b414522f875709240f4056547cb699c6ec1981fbef15488784daf5 translated
#[test]
fn decode_visual_params_round_trip_default_values() {
let params = VisualParams::params();
let ids = VisualParams::group0_param_ids();
let bytes = ids
.iter()
.map(|id| {
params.0.get(id).map_or(0, |vp| {
Utils::float_to_byte(vp.default_value, vp.min_value, vp.max_value).unwrap()
})
})
.collect();
let mut avatar = Avatar::new().unwrap();
avatar.visual_parameters = bytes;
let decoded = avatar.decode_visual_params().unwrap();
let driven_targets: HashSet<i32> = params
.0
.values()
.filter_map(|param| param.driven_params.as_ref())
.flatten()
.map(|driven| driven.param_id)
.collect();
for id in ids {
let Some(vp) = params.0.get(&id) else {
continue;
};
assert!(
decoded.contains_key(&id),
"ParamID {id} ({}) missing",
vp.name
);
if driven_targets.contains(&id) {
continue;
}
let encoded = Utils::float_to_byte(vp.default_value, vp.min_value, vp.max_value).unwrap();
let expected =
Utils::byte_to_float_with_byte_single_single(encoded, vp.min_value, vp.max_value)
.unwrap();
assert!(
(decoded[&id] - expected).abs() <= 1e-5,
"ParamID {id} ({})",
vp.name
);
}
}
// parity-case: LibreMetaverse.Tests/AppearanceTests.cs::AppearanceTests.DecodeVisualParams_KeysAreGroup0ParamIDs::test fc4fd3059b01a319af2946ea0c289120a4c2609e7e9a96ac26c039c5042b8b4c translated
#[test]
fn decode_visual_params_keys_are_group0_param_ids() {
let group0 = group0_params();
let mut avatar = Avatar::new().unwrap();
avatar.visual_parameters = vec![0; group0.len()];
let decoded = avatar.decode_visual_params().unwrap();
let expected: HashSet<i32> = group0.iter().map(|param| param.param_id).collect();
assert!(expected.iter().all(|id| decoded.contains_key(id)));
}
// parity-case: LibreMetaverse.Tests/AppearanceTests.cs::AppearanceTests.DecodeVisualParams_TruncatedArray_ReturnsPartialResult::test b017127549e186b3cf85b9fe0cc09811ea1d00efa44e3d863292033cb0691d13 translated
#[test]
fn decode_visual_params_truncated_array_returns_partial_result() {
let mut avatar = Avatar::new().unwrap();
avatar.visual_parameters = vec![0; 10];
let decoded = avatar.decode_visual_params().unwrap();
assert!(decoded.len() >= 10);
assert!(decoded.len() < VisualParams::group0_param_ids().len());
}
// parity-case: LibreMetaverse.Tests/AppearanceTests.cs::AppearanceTests.DecodeVisualParams_MinValue_DecodesNearParamMin::test 80e0fd97979f91c879add1fc3142a0b619a405e4977120db1d5f42a11a71f3f5 translated
#[test]
fn decode_visual_params_min_value_decodes_near_param_min() {
let group0 = group0_params();
let mut avatar = Avatar::new().unwrap();
avatar.visual_parameters = vec![0; group0.len()];
let decoded = avatar.decode_visual_params().unwrap();
for vp in group0 {
let upper = vp.min_value + (vp.max_value - vp.min_value) / 255.0 + 1e-5;
assert!(
decoded[&vp.param_id] <= upper,
"ParamID {} ({})",
vp.param_id,
vp.name
);
}
}
// parity-case: LibreMetaverse.Tests/AppearanceTests.cs::AppearanceTests.DecodeVisualParams_MaxValue_DecodesNearParamMax::test 31937bc9080b18be4aa98ea44bf73f929ba7862b621406b03c16a4651542f302 translated
#[test]
fn decode_visual_params_max_value_decodes_near_param_max() {
let group0 = group0_params();
let mut avatar = Avatar::new().unwrap();
avatar.visual_parameters = vec![0xff; group0.len()];
let decoded = avatar.decode_visual_params().unwrap();
for vp in group0 {
let lower = vp.max_value - (vp.max_value - vp.min_value) / 255.0 - 1e-5;
assert!(
decoded[&vp.param_id] >= lower,
"ParamID {} ({})",
vp.param_id,
vp.name
);
}
}
// parity-case: LibreMetaverse.Tests/AppearanceTests.cs::AppearanceTests.AvatarAppearanceEventArgs_DecodeVisualParams_EmptyList_ReturnsEmptyDictionary::test af99909259d531024895ce7ea325b49927a12daa886a35eab3d52e3f8fc76921 translated
#[test]
fn appearance_event_args_decode_visual_params_empty_list_returns_empty_dictionary() {
let decoded = appearance_args(Vec::new()).decode_visual_params().unwrap();
assert_eq!(decoded.len(), 0);
}
// parity-case: LibreMetaverse.Tests/AppearanceTests.cs::AppearanceTests.AvatarAppearanceEventArgs_DecodeVisualParams_RoundTrip_DefaultValues::test 0aec57fab35764525195e6c0e08a63ff10a467be684295381731c04e836539b5 translated
#[test]
fn appearance_event_args_decode_visual_params_round_trip_default_values() {
let params = VisualParams::params();
let ids = VisualParams::group0_param_ids();
let bytes = ids
.iter()
.map(|id| {
params.0.get(id).map_or(0, |vp| {
Utils::float_to_byte(vp.default_value, vp.min_value, vp.max_value).unwrap()
})
})
.collect();
let decoded = appearance_args(bytes).decode_visual_params().unwrap();
assert!(decoded.len() >= ids.len());
for id in ids {
if params.0.contains_key(&id) {
assert!(decoded.contains_key(&id));
}
}
}
// parity-case: LibreMetaverse.Tests/AppearanceTests.cs::AppearanceTests.AvatarAppearanceEventArgs_DecodeVisualParams_MatchesAvatarDecodeVisualParams::test ff87dd3a506027ad248006b3b55d85a18b0810bc5b4e3a72eb81d31ebbe4184a translated
#[test]
fn appearance_event_args_decode_visual_params_matches_avatar_decode_visual_params() {
let group0 = group0_params();
let bytes: Vec<u8> = group0
.iter()
.map(|vp| Utils::float_to_byte(vp.default_value, vp.min_value, vp.max_value).unwrap())
.collect();
let mut avatar = Avatar::new().unwrap();
avatar.visual_parameters = bytes.clone();
let from_avatar = avatar.decode_visual_params().unwrap();
let from_args = appearance_args(bytes).decode_visual_params().unwrap();
assert_eq!(from_args.len(), from_avatar.len());
for (id, expected) in from_avatar {
assert!(from_args.contains_key(&id));
assert!((from_args[&id] - expected).abs() <= 1e-5);
}
}