// Exact Rust translations of LibreMetaverse.Tests/AppearanceLiveTests.cs. // Source SHA-256: 9f4ec256d11290cbad70e209d2f9043d4c6afb18255796c09c4cb26415f971a6 use libremetaverse::GridClient; use libremetaverse::appearance::CurrentOutfitFolder; use libremetaverse_compat_tests::{LiveTestRuntime, login_live_grid, logout_live_grid}; use libremetaverse_types::{UUID, WearableType}; use std::sync::Arc; use std::time::{Duration, Instant}; struct LiveAppearance { client: Arc, cof: CurrentOutfitFolder, runtime: LiveTestRuntime, } impl LiveAppearance { fn login() -> Self { let runtime = LiveTestRuntime::new(); let mut client = GridClient::new().expect("GridClient constructor"); login_live_grid( &runtime, &mut client, "Unit Test Framework", "admin@radegast.life", ); let client = Arc::new(client); let cof = CurrentOutfitFolder::new(Some(Arc::clone(&client))) .expect("CurrentOutfitFolder constructor"); Self { client, cof, runtime, } } } impl Drop for LiveAppearance { fn drop(&mut self) { let _ = self.cof.dispose(); if let Some(client) = Arc::get_mut(&mut self.client) { logout_live_grid(&self.runtime, client); } } } // parity-case: LibreMetaverse.Tests/AppearanceLiveTests.cs::AppearanceLiveTests.COF_IsInitializedAfterLogin::test 7029854dc6f4e03016e2ea274140cd9adbbad6b8c11b58cf9e728d9a4cf37f81 ignored-live #[test] #[cfg_attr( not(live_grid_credentials), ignore = "requires GRID_USER, GRID_PASSWORD, and GRID_LOGIN_URL in the environment or workspace .env" )] fn cof_is_initialized_after_login() { let live = LiveAppearance::login(); live.runtime .block_on(live.cof.get_current_outfit_links(None)) .unwrap(); let folder = live.cof.cof().expect("COF folder is null"); assert_ne!(folder.base.uuid(), UUID::zero()); } // parity-case: LibreMetaverse.Tests/AppearanceLiveTests.cs::AppearanceLiveTests.COF_HasExpectedFolderName::test 9a8cee3c3958b8631921aaa6b43f69dc430eee9bd3544c8f667aa8f5e858b8ac ignored-live #[test] #[cfg_attr( not(live_grid_credentials), ignore = "requires GRID_USER, GRID_PASSWORD, and GRID_LOGIN_URL in the environment or workspace .env" )] fn cof_has_expected_folder_name() { let live = LiveAppearance::login(); live.runtime .block_on(live.cof.get_current_outfit_links(None)) .unwrap(); let folder = live.cof.cof().expect("COF folder is null"); assert!(folder.base.name().eq_ignore_ascii_case("Current Outfit")); } // parity-case: LibreMetaverse.Tests/AppearanceLiveTests.cs::AppearanceLiveTests.GetCurrentOutfitLinksAsync_ReturnsLinks::test a1a1c9f926a8b9f4cc4287ab751c4eb70d25a83c1024ef76e53f95c351db8a35 ignored-live #[test] #[cfg_attr( not(live_grid_credentials), ignore = "requires GRID_USER, GRID_PASSWORD, and GRID_LOGIN_URL in the environment or workspace .env" )] fn get_current_outfit_links_returns_links() { let live = LiveAppearance::login(); let links = live .runtime .block_on(live.cof.get_current_outfit_links(None)) .unwrap(); for link in links { assert!(link.is_link().unwrap(), "returned COF item is not a link"); } } // parity-case: LibreMetaverse.Tests/AppearanceLiveTests.cs::AppearanceLiveTests.GetCurrentOutfitLinksAsync_ContainsAtLeastOneLink::test ef91dfaf7b75f61c97c3957b4dac006a153c7f2d167d6732a9a6dceee08883f2 ignored-live #[test] #[cfg_attr( not(live_grid_credentials), ignore = "requires GRID_USER, GRID_PASSWORD, and GRID_LOGIN_URL in the environment or workspace .env" )] fn get_current_outfit_links_contains_at_least_one_link() { let live = LiveAppearance::login(); let links = live .runtime .block_on(live.cof.get_current_outfit_links(None)) .unwrap(); assert!( !links.is_empty(), "COF returned zero links; the dedicated account must wear at least its default shape" ); } // parity-case: LibreMetaverse.Tests/AppearanceLiveTests.cs::AppearanceLiveTests.GetWornAt_Shape_ReturnsAtLeastOne::test abc01e346371910610312ff9352ee05c0d317a7c677c0fa8cb398d3b0522c3bf ignored-live #[test] #[cfg_attr( not(live_grid_credentials), ignore = "requires GRID_USER, GRID_PASSWORD, and GRID_LOGIN_URL in the environment or workspace .env" )] fn get_worn_at_shape_returns_at_least_one() { let live = LiveAppearance::login(); let worn = live .runtime .block_on(live.cof.get_worn_at(WearableType::Shape, None)) .unwrap(); assert!( !worn.is_empty(), "GetWornAtAsync(Shape) returned no items for the dedicated account" ); } // parity-case: LibreMetaverse.Tests/AppearanceLiveTests.cs::AppearanceLiveTests.LastUpdateReceivedCOFVersion_AdvancesAfterLogin::test 5371df8b02df9da20b413f4155f63967184dad23f57708beb56a2c6559e78520 ignored-live #[test] #[cfg_attr( not(live_grid_credentials), ignore = "requires GRID_USER, GRID_PASSWORD, and GRID_LOGIN_URL in the environment or workspace .env" )] fn last_update_received_cof_version_advances_after_login() { let live = LiveAppearance::login(); let deadline = Instant::now() + Duration::from_secs(25); let mut version = -1; while Instant::now() < deadline { version = live.client.appearance().last_update_received_cof_version(); if version > -1 { break; } std::thread::sleep(Duration::from_millis(500)); } assert!( version > -1, "the OpenSim simulator did not send AvatarAppearance for self within 25 seconds" ); } // parity-case: LibreMetaverse.Tests/AppearanceLiveTests.cs::AppearanceLiveTests.RequestOwnAvatarTextures_DoesNotThrow_AndMaintainsVersionGuard::test ee8420690fc9714411450beb5be5755b82ddf7ed0d69e9da88b3184339bea744 ignored-live #[test] #[cfg_attr( not(live_grid_credentials), ignore = "requires GRID_USER, GRID_PASSWORD, and GRID_LOGIN_URL in the environment or workspace .env" )] fn request_own_avatar_textures_does_not_throw_and_maintains_version_guard() { let live = LiveAppearance::login(); let before = live.client.appearance().last_update_received_cof_version(); live.client.avatars().request_own_avatar_textures().unwrap(); let deadline = Instant::now() + Duration::from_secs(15); let mut after = before; while Instant::now() < deadline { after = live.client.appearance().last_update_received_cof_version(); if after > before { break; } std::thread::sleep(Duration::from_millis(500)); } assert!( after >= before, "COF version regressed from {before} to {after}" ); } // parity-case: LibreMetaverse.Tests/AppearanceLiveTests.cs::AppearanceLiveTests.COF_MaxClothingLayers_Is60::test aac1292781cb0a4cbf710535036fa6464065f72d1b2c5214a9b7dc918513e8cd ignored-live #[test] #[cfg_attr( not(live_grid_credentials), ignore = "requires GRID_USER, GRID_PASSWORD, and GRID_LOGIN_URL in the environment or workspace .env" )] fn cof_max_clothing_layers_is_60() { assert_eq!(LiveAppearance::login().cof.max_clothing_layers(), 60); }