Translate social and marketplace parity tests

This commit is contained in:
2026-08-08 21:46:59 +02:00
parent cdb392643c
commit 1604822689
11 changed files with 2349 additions and 1163 deletions

View File

@@ -2,70 +2,6 @@
// Source: LibreMetaverse 2aa70bb68513b39795da5d13c88f31b86e85a3ba
// Pending cases are catalog entries, not fake executable Rust tests.
// pending-parity-case: LibreMetaverse.Tests/ConstructorNullArgumentTests.cs::ConstructorNullArgumentTests.AppearanceManager_Null_Throws::test a3c872805bc924b5a1a9441d5c9eb61ed6d6e9477e4bb411131359290b144ab4
// pending-parity-case: LibreMetaverse.Tests/ConstructorNullArgumentTests.cs::ConstructorNullArgumentTests.AvatarManager_Null_Throws::test 54f23cbf0ba87b0525c2914e78d75808e93fd1c460fc0bec4d15f09575b1431c
// pending-parity-case: LibreMetaverse.Tests/MarketplaceFolderClassifierTests.cs::MarketplaceFolderClassifierTests.GetRole_ListingsRootFolder_ReturnsListingsRoot::test a3c21e19f21924bffbbafe1199a4b942b545bdb278c3362b2a1ec98b35d672cf
// pending-parity-case: LibreMetaverse.Tests/MarketplaceFolderClassifierTests.cs::MarketplaceFolderClassifierTests.GetRole_ListingFolder_ReturnsListing::test c08d860a4506254d9ac831e91894f2fc34d840c100468ee7e39b505690302368
// pending-parity-case: LibreMetaverse.Tests/MarketplaceFolderClassifierTests.cs::MarketplaceFolderClassifierTests.GetRole_VersionFolder_ReturnsVersion::test 90d792d6858c6a253b9ddf80d3f5e7244570490fa4ef68c1914b342db05c7aa2
// pending-parity-case: LibreMetaverse.Tests/MarketplaceFolderClassifierTests.cs::MarketplaceFolderClassifierTests.GetRole_StockFolder_ReturnsStock::test 330a418b3a7b534a60d4e84610af1cd51bb9e6ee77b603c45576d3416972cb75
// pending-parity-case: LibreMetaverse.Tests/MarketplaceFolderClassifierTests.cs::MarketplaceFolderClassifierTests.GetRole_ContentFolder_ReturnsContent::test 43f487b7be01edcdbf3b05c5ab8b50b6aec6722ae1e3dae0c44f1dea93fb72bd
// pending-parity-case: LibreMetaverse.Tests/MarketplaceFolderClassifierTests.cs::MarketplaceFolderClassifierTests.GetRole_UnknownUUID_ReturnsNone::test 06958bff71d6248d23b9508a11059ab150cc558cf81efbee86ba04f38446a534
// pending-parity-case: LibreMetaverse.Tests/MarketplaceFolderClassifierTests.cs::MarketplaceFolderClassifierTests.GetRole_RegularFolderOutsideMarketplace_ReturnsNone::test da102792d7adc232b8af6b43c03196c579474e63cb3139a38cabab957efc27dc
// pending-parity-case: LibreMetaverse.Tests/MarketplaceFolderClassifierTests.cs::MarketplaceFolderClassifierTests.IsMarketplaceFolder_ListingFolder_ReturnsTrue::test a759b5be1acf6fa627ad1cacbfdee7b5387b66dbd456d1296a9ccca1b9d21d2a
// pending-parity-case: LibreMetaverse.Tests/MarketplaceFolderClassifierTests.cs::MarketplaceFolderClassifierTests.IsMarketplaceFolder_VersionFolder_ReturnsTrue::test bdcf12d6e0c50d7ccb5dc2a219490fd63099726569fd212878bdc8d762b3e769
// pending-parity-case: LibreMetaverse.Tests/MarketplaceFolderClassifierTests.cs::MarketplaceFolderClassifierTests.IsMarketplaceFolder_RegularFolderOutsideMarketplace_ReturnsFalse::test bbfeeeb783208c1dd6056f180a3f1d350dff15a7ddf7866fd71d2e9a350db5bf
// pending-parity-case: LibreMetaverse.Tests/MarketplaceFolderClassifierTests.cs::MarketplaceFolderClassifierTests.IsMarketplaceFolder_UnknownUUID_ReturnsFalse::test 33b914bdccd2c7b1f134bf9be6fa3baf55f93801f0de86e64a7aa0d376837706
// pending-parity-case: LibreMetaverse.Tests/MarketplaceFolderClassifierTests.cs::MarketplaceFolderClassifierTests.GetListingsRoot_HasMarketplaceListingsFolder_ReturnsItsUUID::test bae93f760f1a2cc97608a487b98d44e40a552a3698b71f27014ae12bc2ab08d0
// pending-parity-case: LibreMetaverse.Tests/MarketplaceFolderClassifierTests.cs::MarketplaceFolderClassifierTests.GetListingsRoot_NoMarketplaceListingsFolder_ReturnsZero::test 68eaa338235b510b202dbf067902999b38f52aef0040edb3d7539ae24f884b25
// pending-parity-case: LibreMetaverse.Tests/MarketplaceFolderClassifierTests.cs::MarketplaceFolderClassifierTests.GetListingsRoot_NoRootFolder_ReturnsZero::test e23c43ed9179d62b38e290a47711bae64fd9c9ff7c7445b5ad065187af740367
// pending-parity-case: LibreMetaverse.Tests/MarketplaceFolderClassifierTests.cs::MarketplaceFolderClassifierTests.GetListingFolder_CalledOnListingFolder_ReturnsSelf::test 6761009b4891640dfeb44dd361f02cefa968df503ebca6d8b5f3defe86ec803f
// pending-parity-case: LibreMetaverse.Tests/MarketplaceFolderClassifierTests.cs::MarketplaceFolderClassifierTests.GetListingFolder_CalledOnVersionFolder_ReturnsListingFolder::test ae3e668b09cda08f558ad654132bda1acdaa3bce08a832b08465ad9302cd6773
// pending-parity-case: LibreMetaverse.Tests/MarketplaceFolderClassifierTests.cs::MarketplaceFolderClassifierTests.GetListingFolder_CalledOnStockFolder_ReturnsListingFolder::test 2af63c64992155da9343b273ec7e80984bf3233d5391625e61317d60e976bccf
// pending-parity-case: LibreMetaverse.Tests/MarketplaceFolderClassifierTests.cs::MarketplaceFolderClassifierTests.GetListingFolder_CalledOnListingsRoot_ReturnsZero::test 8921bd854b48d34916e3329640fb758e6d5ac6bc099f3b79dbdbde63529886db
// pending-parity-case: LibreMetaverse.Tests/MarketplaceFolderClassifierTests.cs::MarketplaceFolderClassifierTests.GetListingFolder_CalledOnUnknownFolder_ReturnsZero::test db0ccbbbcd06e502abdb1db6ebc351c7c202c68ee01e0e17143a0f28dec1ec12
// pending-parity-case: LibreMetaverse.Tests/MarketplaceFolderClassifierTests.cs::MarketplaceFolderClassifierTests.GetVersionFolder_ListingHasVersionFolder_ReturnsVersionUUID::test a5f816a37538eed4ae5eedfbe5c357c8aa296bad0c734de50ce8f286d8785084
// pending-parity-case: LibreMetaverse.Tests/MarketplaceFolderClassifierTests.cs::MarketplaceFolderClassifierTests.GetVersionFolder_ListingHasNoVersionFolder_ReturnsZero::test f35acb3a9edd8e0554d2e1c6c87723804a447060135a29fbd39cd07e7e092467
// pending-parity-case: LibreMetaverse.Tests/MarketplaceFolderClassifierTests.cs::MarketplaceFolderClassifierTests.GetStockCount_VersionFolderWithOneItem_ReturnsOne::test d6dadccb9d8c19814038262f376b09ce05201a165634721ad1fd70213a53462d
// pending-parity-case: LibreMetaverse.Tests/MarketplaceFolderClassifierTests.cs::MarketplaceFolderClassifierTests.GetStockCount_VersionFolderWithOnlySubfolders_ReturnsZero::test 27dc9e58e342db51b5a400bf9785a77c62fe8011b4cabba3bbf69a7ea6aec6c8
// pending-parity-case: LibreMetaverse.Tests/MarketplaceFolderClassifierTests.cs::MarketplaceFolderClassifierTests.GetStockCount_ZeroUUID_ReturnsZero::test bd1fdd59481aae5b8e443a55dc8300ac50956c5c4ded3289dbbc4d863a7a9042
// pending-parity-case: LibreMetaverse.Tests/MarketplaceFolderClassifierTests.cs::MarketplaceFolderClassifierTests.GetStockCount_MultipleItems_ReturnsCorrectCount::test d0ff960d09e791672000e5c63423181e70fc28437eb1cb26538fa175ce4d75f1
// pending-parity-case: LibreMetaverse.Tests/MarketplaceFolderClassifierTests.cs::MarketplaceFolderClassifierTests.GetAllListingFolderIds_SingleListingFolder_ReturnsOne::test bc49aaa674206f0b4b5f625260090ec2f7ee59ad053881141890271f2f9369e1
// pending-parity-case: LibreMetaverse.Tests/MarketplaceFolderClassifierTests.cs::MarketplaceFolderClassifierTests.GetAllListingFolderIds_TwoListingFolders_ReturnsBoth::test 4cf174ea092dbbd6741a9cec7ab0caca5da7e41ab5283e88c427d2f7057dd9ff
// pending-parity-case: LibreMetaverse.Tests/MarketplaceFolderClassifierTests.cs::MarketplaceFolderClassifierTests.GetAllListingFolderIds_NoMarketplaceRoot_ReturnsEmpty::test fedc2c585ea3fdaae8bf14eb56ccbdcfbb0d2d8a790bb7137a6dd0a02a6ef2c8
// pending-parity-case: LibreMetaverse.Tests/MarketplaceFolderClassifierTests.cs::MarketplaceFolderClassifierTests.ValidateListing_WellFormedListing_ReturnsValid::test b15ac0ff131da6764651ccb24a87771f8e9f955c389e813e9c1b50865b472b16
// pending-parity-case: LibreMetaverse.Tests/MarketplaceFolderClassifierTests.cs::MarketplaceFolderClassifierTests.ValidateListing_NoVersionFolder_ReturnsMissingVersionFolder::test 5becd6939ba410c0e6c7cfb42234b1c513a6e69f827080b7f4301da3da6dfab8
// pending-parity-case: LibreMetaverse.Tests/MarketplaceFolderClassifierTests.cs::MarketplaceFolderClassifierTests.ValidateListing_MultipleVersionFolders_ReturnsMultipleVersionFolders::test f10ec95540212b4c47035928de4472cdd268cb4946dc1b73f2e65cff32881142
// pending-parity-case: LibreMetaverse.Tests/MarketplaceFolderClassifierTests.cs::MarketplaceFolderClassifierTests.ValidateListing_EmptyVersionFolder_ReturnsEmptyListing::test 1443157d7ab29ffe2ea45f38ea43e121262abb89f2264e141c750c7e7689e2c8
// pending-parity-case: LibreMetaverse.Tests/MarketplaceFolderClassifierTests.cs::MarketplaceFolderClassifierTests.ValidateListing_UnknownUUID_ReturnsInvalidStructure::test 9ee13dc32219883b7847c2f71de03a42e80681e5916e86d6723bda11fd8223ab
// pending-parity-case: LibreMetaverse.Tests/MarketplaceFolderClassifierTests.cs::MarketplaceFolderClassifierTests.ValidateListing_ValidFlags_AreBitmaskComposable::test dcdb7dfcdbcf003c4698e7a2a580046db610a1b8ab3ed7ad7cbe8e2aa36eace4
// pending-parity-case: LibreMetaverse.Tests/MarketplaceManagerTests.cs::MarketplaceManagerTests.FetchListingsAsync_ListingsArrayResponse_PopulatesBothCaches::test 1ec347288488be26f8a4b923d304ae9598d1d4f40423356012c353b3527ae089
// pending-parity-case: LibreMetaverse.Tests/MarketplaceManagerTests.cs::MarketplaceManagerTests.FetchListingsAsync_UnlistedEntry_ParsesAsUnlisted::test 3e5b22da9fcc6a38ddec3ffb215367320df035aed33c9c0690461fdce786b37d
// pending-parity-case: LibreMetaverse.Tests/MarketplaceManagerTests.cs::MarketplaceManagerTests.FetchListingsAsync_FiresListingsSyncedEvent::test ec70956ce5eb51fe650a6e2e77924ec21051b0c06396bce7c9c82a277f6aa82a
// pending-parity-case: LibreMetaverse.Tests/MarketplaceManagerTests.cs::MarketplaceManagerTests.FetchListingsAsync_HttpError_FiresErrorEventAndLeavesEmptyCache::test 0a71f4db07be054bf77752f07223268bd25b673a9c5c8cfe8a5f78ee36b4a463
// pending-parity-case: LibreMetaverse.Tests/MarketplaceManagerTests.cs::MarketplaceManagerTests.FetchListingsAsync_EmptyListingsArray_ResultsInEmptyCache::test 79ab6108d67cba54f55a8603f3929f1329cbe84ce3b591717d4b4712c2bbe0a2
// pending-parity-case: LibreMetaverse.Tests/MarketplaceManagerTests.cs::MarketplaceManagerTests.FetchListingsAsync_SecondCall_ReplacesCacheWithNewData::test 2327332d62529d276a8e1e074b20c3a37a47b5c820910644e6562317fdd4651b
// pending-parity-case: LibreMetaverse.Tests/MarketplaceManagerTests.cs::MarketplaceManagerTests.CreateListingAsync_SendsNestedInventoryInfoNotFlatUuidField::test efda655bf20ec6157df4738df4cf4ddcc1ee9e1ade01f1f0177630659b54b1d6
// pending-parity-case: LibreMetaverse.Tests/MarketplaceManagerTests.cs::MarketplaceManagerTests.CreateListingAsync_FiresListingChangedEvent::test 242073ff6fbae379c518d047cd63e1ad368ff37ffc2cad379b8c007fb725b74e
// pending-parity-case: LibreMetaverse.Tests/MarketplaceManagerTests.cs::MarketplaceManagerTests.CreateListingAsync_HttpError_ReturnsNullAndFiresErrorEvent::test fa999c4cce5bee688ef3bb6342e276867268ab9f32571eff25646cb1384bcece
// pending-parity-case: LibreMetaverse.Tests/MarketplaceManagerTests.cs::MarketplaceManagerTests.DeleteListingAsync_UsesSingularListingRoute::test aea0672be109f05632df326a0c2caf7b7d14d23cf0d66e6ab867902351ebb554
// pending-parity-case: LibreMetaverse.Tests/MarketplaceManagerTests.cs::MarketplaceManagerTests.DeleteListingAsync_HttpError_ReturnsFalseAndFiresErrorEvent::test 52976e09904483e7f33dbe016d695e380646f75b2fdd1b1f744c3fc69dd9d192
// pending-parity-case: LibreMetaverse.Tests/MarketplaceManagerTests.cs::MarketplaceManagerTests.ActivateListingAsync_SendsIsListedTrueAndCachedInventoryInfoToSingularRoute::test 4b6daed0e333c504a7aed8666980152990c37d81830d08f3a31faf39dbbc706f
// pending-parity-case: LibreMetaverse.Tests/MarketplaceManagerTests.cs::MarketplaceManagerTests.ActivateListingAsync_NoCachedListing_ReturnsFalseWithoutSendingRequest::test 1c4d407a29ba139b13e868882f1721327cfdd64dc2d2e9a32a0c71678905bb65
// pending-parity-case: LibreMetaverse.Tests/MarketplaceManagerTests.cs::MarketplaceManagerTests.ActivateListingAsync_HttpError_ReturnsFalse::test 1f7b39a95adfd13cf159fbadac9d157a70ebbdcb360a1cf1cf4d21b891bd61d6
// pending-parity-case: LibreMetaverse.Tests/MarketplaceManagerTests.cs::MarketplaceManagerTests.DeactivateListingAsync_SendsIsListedFalse::test 1fa6eb4bfc86fb9a5fe746b18e43568b9dcc1a723e3a667b1bc57a1ebb66fb50
// pending-parity-case: LibreMetaverse.Tests/MarketplaceManagerTests.cs::MarketplaceManagerTests.TryGetByFolder_AfterFetch_ReturnsMatchingListing::test cb0b2a301f9096a238ba078739f0b6488a4dcc20fecdd59d51c930f7ea28902c
// pending-parity-case: LibreMetaverse.Tests/MarketplaceManagerTests.cs::MarketplaceManagerTests.TryGetByFolder_MissingUUID_ReturnsFalse::test 86fe3e33c410412e829efbc4e775b164492b2dd14d82421478552e9a01c35ef8
// pending-parity-case: LibreMetaverse.Tests/MarketplaceManagerTests.cs::MarketplaceManagerTests.TryGetById_EmptyCache_ReturnsFalse::test 8d49aeaf5444d8d2d2098f932df01dac6e6942a86b105287c5f40cb54e501dcc
// pending-parity-case: LibreMetaverse.Tests/MarketplaceManagerTests.cs::MarketplaceManagerTests.MarketplaceListingsSyncedEventArgs_StoresListings::test c0744e6b9f9282613692f7be962009e9129c234e3ca863ab40b581baa90a6a68
// pending-parity-case: LibreMetaverse.Tests/MarketplaceManagerTests.cs::MarketplaceManagerTests.MarketplaceListingChangedEventArgs_StoresListingIdAndListing::test 874578d97b250b4667e3cb0c28626948ede80fba14e9ae9add153e2dfddc1902
// pending-parity-case: LibreMetaverse.Tests/MarketplaceManagerTests.cs::MarketplaceManagerTests.MarketplaceListingChangedEventArgs_NullListing_IsValidForDeleteScenario::test 6a4fadad3a00e0e17977506badf7e08a53278f7c89fc4c7597a502164257f50d
// pending-parity-case: LibreMetaverse.Tests/MarketplaceManagerTests.cs::MarketplaceManagerTests.MarketplaceErrorEventArgs_StoresMessageAndException::test cb0213208ab6b63f32a950f1771354fae4b6904c72720b1705ddf5b8355ffc7d
// pending-parity-case: LibreMetaverse.Tests/MarketplaceManagerTests.cs::MarketplaceManagerTests.MarketplaceErrorEventArgs_WithoutException_HasNullException::test de7c8addfb291cba5dee890a98ac8b5f27b192d0b75894c4102303a49785de47
// pending-parity-case: LibreMetaverse.Tests/MarketplaceManagerTests.cs::MarketplaceManagerTests.MarketplaceListing_DefaultValues_AreCorrect::test 70a29163581702fdc32c54a398ad4cefa608da8b1bc9d54a4e9e191e95398fb7
// pending-parity-case: LibreMetaverse.Tests/OfflineMessagesTests.cs::OfflineMessagesTests.RetrieveInstantMessagesAsync_BareArrayOfArraysResponse_RaisesInstantMessage::test d51f69e0fa1e1e59a5cedec7d60315d1f590848672a9f4f0c5e21d2abff5c372
// pending-parity-case: LibreMetaverse.Tests/OfflineMessagesTests.cs::OfflineMessagesTests.RetrieveInstantMessagesAsync_MessagesMapResponse_RaisesInstantMessage::test dbce6320d57d12ca5557cfba65257e15be314cde947b20dd21bc386819fcb3ce
// pending-parity-case: LibreMetaverse.Tests/ProductInfoRequestMessageTests.cs::ProductInfoRequestMessageTests.Deserialize_BareArray_ReadsSkuNameDescription::test 5d51fdbb1bec1ff74df59778d214413e78fb650679d36e7c44be92d1b2e3205f
// pending-parity-case: LibreMetaverse.Tests/ProductInfoRequestMessageTests.cs::ProductInfoRequestMessageTests.SerializeDeserialize_RoundTrips::test 5cb54bed4150cf13f815b223d6b7e35e7427004a12e98c7328c7674b6fe6309b
// pending-parity-case: LibreMetaverse.Tests/RLV/Commands/AdjustHeightCommandTests.cs::AdjustHeightCommandTests.AdjustHeight::test fb3adb86988b10b2d3fe9223324f8a3c1ba7b8c2ea909ee6b57b38c590fed372
// pending-parity-case: LibreMetaverse.Tests/RLV/Commands/AdjustHeightCommandTests.cs::AdjustHeightCommandTests.AdjustHeight_WithDelta::test 1f37a125fd9df8585740d37c711888dfcd92460d86c19077f771d7f3fab54264
// pending-parity-case: LibreMetaverse.Tests/RLV/Commands/AttachAllCommandTests.cs::AttachAllCommandTests.AttachForce_Recursive::case:eee2b1b757fc196e 17a84542635b76f4f806126ab170d43441ad00b9b91650aa1164909de9692671

View File

@@ -0,0 +1,530 @@
// Exact Rust translation of LibreMetaverse.Tests/MarketplaceFolderClassifierTests.cs.
// Source SHA-256: 4679b5c685e35e73122b7857b77ea4a5b2b83345ad176aeee32239feb528fd9b
use libremetaverse::marketplace::{
MarketplaceFolderClassifier as Classifier, MarketplaceFolderRole as Role,
MarketplaceValidationFlags as Flags,
};
use libremetaverse::{GridClient, Inventory, InventoryFolder, InventoryItem};
use libremetaverse_types::{FolderType, UUID};
use std::sync::Arc;
fn uuid() -> UUID {
UUID::random().expect("UUID Random")
}
fn folder(id: UUID, name: &str, parent: UUID, preferred: Option<FolderType>) -> InventoryFolder {
let mut folder = InventoryFolder::new(id).expect("InventoryFolder constructor");
folder.base.set_name(name.into());
folder.base.set_parent_uuid(parent);
if let Some(preferred) = preferred {
folder.set_preferred_type(preferred);
}
folder
}
fn item(id: UUID, name: &str, parent: UUID) -> InventoryItem {
let mut item = InventoryItem::new_with_uuid(id).expect("InventoryItem constructor");
item.base.set_name(name.into());
item.base.set_parent_uuid(parent);
item
}
struct Fixture {
client: Arc<GridClient>,
inventory: Inventory,
root: UUID,
listings_root: UUID,
listing: UUID,
version: UUID,
stock: UUID,
content: UUID,
}
impl Fixture {
fn new() -> Self {
let client = Arc::new(GridClient::new().expect("GridClient constructor"));
let mut inventory = Inventory::new_with_grid_client_uuid(Arc::clone(&client), uuid())
.expect("Inventory constructor");
let root = uuid();
inventory.set_root_folder(Some(folder(root, "My Inventory", UUID::zero(), None)));
let listings_root = uuid();
inventory
.update_node_for(&folder(
listings_root,
"Marketplace Listings",
root,
Some(FolderType::MarketplaceListings),
))
.unwrap();
let listing = uuid();
inventory
.update_node_for(&folder(listing, "My Listing", listings_root, None))
.unwrap();
let version = uuid();
inventory
.update_node_for(&folder(
version,
"Version 1",
listing,
Some(FolderType::MarketplaceVersion),
))
.unwrap();
let stock = uuid();
inventory
.update_node_for(&folder(
stock,
"Stock",
version,
Some(FolderType::MarketplaceStock),
))
.unwrap();
let content = uuid();
inventory
.update_node_for(&folder(content, "Content", version, None))
.unwrap();
inventory
.update_node_for(&item(uuid(), "Product", version))
.unwrap();
Self {
client,
inventory,
root,
listings_root,
listing,
version,
stock,
content,
}
}
}
impl Drop for Fixture {
fn drop(&mut self) {
let _ = self.client.dispose_with_method();
}
}
fn empty_inventory() -> (Arc<GridClient>, Inventory) {
let client = Arc::new(GridClient::new().expect("GridClient constructor"));
let inventory = Inventory::new_with_grid_client_uuid(Arc::clone(&client), uuid())
.expect("Inventory constructor");
(client, inventory)
}
// parity-case: LibreMetaverse.Tests/MarketplaceFolderClassifierTests.cs::MarketplaceFolderClassifierTests.GetRole_ListingsRootFolder_ReturnsListingsRoot::test a3c21e19f21924bffbbafe1199a4b942b545bdb278c3362b2a1ec98b35d672cf translated
#[test]
fn get_role_listings_root_folder_returns_listings_root() {
let f = Fixture::new();
assert_eq!(
Classifier::get_role(f.listings_root, &f.inventory).unwrap(),
Role::ListingsRoot
);
}
// parity-case: LibreMetaverse.Tests/MarketplaceFolderClassifierTests.cs::MarketplaceFolderClassifierTests.GetRole_ListingFolder_ReturnsListing::test c08d860a4506254d9ac831e91894f2fc34d840c100468ee7e39b505690302368 translated
#[test]
fn get_role_listing_folder_returns_listing() {
let f = Fixture::new();
assert_eq!(
Classifier::get_role(f.listing, &f.inventory).unwrap(),
Role::Listing
);
}
// parity-case: LibreMetaverse.Tests/MarketplaceFolderClassifierTests.cs::MarketplaceFolderClassifierTests.GetRole_VersionFolder_ReturnsVersion::test 90d792d6858c6a253b9ddf80d3f5e7244570490fa4ef68c1914b342db05c7aa2 translated
#[test]
fn get_role_version_folder_returns_version() {
let f = Fixture::new();
assert_eq!(
Classifier::get_role(f.version, &f.inventory).unwrap(),
Role::Version
);
}
// parity-case: LibreMetaverse.Tests/MarketplaceFolderClassifierTests.cs::MarketplaceFolderClassifierTests.GetRole_StockFolder_ReturnsStock::test 330a418b3a7b534a60d4e84610af1cd51bb9e6ee77b603c45576d3416972cb75 translated
#[test]
fn get_role_stock_folder_returns_stock() {
let f = Fixture::new();
assert_eq!(
Classifier::get_role(f.stock, &f.inventory).unwrap(),
Role::Stock
);
}
// parity-case: LibreMetaverse.Tests/MarketplaceFolderClassifierTests.cs::MarketplaceFolderClassifierTests.GetRole_ContentFolder_ReturnsContent::test 43f487b7be01edcdbf3b05c5ab8b50b6aec6722ae1e3dae0c44f1dea93fb72bd translated
#[test]
fn get_role_content_folder_returns_content() {
let f = Fixture::new();
assert_eq!(
Classifier::get_role(f.content, &f.inventory).unwrap(),
Role::Content
);
}
// parity-case: LibreMetaverse.Tests/MarketplaceFolderClassifierTests.cs::MarketplaceFolderClassifierTests.GetRole_UnknownUUID_ReturnsNone::test 06958bff71d6248d23b9508a11059ab150cc558cf81efbee86ba04f38446a534 translated
#[test]
fn get_role_unknown_uuid_returns_none() {
let f = Fixture::new();
assert_eq!(
Classifier::get_role(uuid(), &f.inventory).unwrap(),
Role::None
);
}
// parity-case: LibreMetaverse.Tests/MarketplaceFolderClassifierTests.cs::MarketplaceFolderClassifierTests.GetRole_RegularFolderOutsideMarketplace_ReturnsNone::test da102792d7adc232b8af6b43c03196c579474e63cb3139a38cabab957efc27dc translated
#[test]
fn get_role_regular_folder_outside_marketplace_returns_none() {
let f = Fixture::new();
let regular = uuid();
f.inventory
.update_node_for(&folder(regular, "Objects", f.root, None))
.unwrap();
assert_eq!(
Classifier::get_role(regular, &f.inventory).unwrap(),
Role::None
);
}
// parity-case: LibreMetaverse.Tests/MarketplaceFolderClassifierTests.cs::MarketplaceFolderClassifierTests.IsMarketplaceFolder_ListingFolder_ReturnsTrue::test a759b5be1acf6fa627ad1cacbfdee7b5387b66dbd456d1296a9ccca1b9d21d2a translated
#[test]
fn is_marketplace_folder_listing_returns_true() {
let f = Fixture::new();
assert!(Classifier::is_marketplace_folder(f.listing, &f.inventory).unwrap());
}
// parity-case: LibreMetaverse.Tests/MarketplaceFolderClassifierTests.cs::MarketplaceFolderClassifierTests.IsMarketplaceFolder_VersionFolder_ReturnsTrue::test bdcf12d6e0c50d7ccb5dc2a219490fd63099726569fd212878bdc8d762b3e769 translated
#[test]
fn is_marketplace_folder_version_returns_true() {
let f = Fixture::new();
assert!(Classifier::is_marketplace_folder(f.version, &f.inventory).unwrap());
}
// parity-case: LibreMetaverse.Tests/MarketplaceFolderClassifierTests.cs::MarketplaceFolderClassifierTests.IsMarketplaceFolder_RegularFolderOutsideMarketplace_ReturnsFalse::test bbfeeeb783208c1dd6056f180a3f1d350dff15a7ddf7866fd71d2e9a350db5bf translated
#[test]
fn is_marketplace_folder_regular_returns_false() {
let f = Fixture::new();
let regular = uuid();
f.inventory
.update_node_for(&folder(regular, "Objects", f.root, None))
.unwrap();
assert!(!Classifier::is_marketplace_folder(regular, &f.inventory).unwrap());
}
// parity-case: LibreMetaverse.Tests/MarketplaceFolderClassifierTests.cs::MarketplaceFolderClassifierTests.IsMarketplaceFolder_UnknownUUID_ReturnsFalse::test 33b914bdccd2c7b1f134bf9be6fa3baf55f93801f0de86e64a7aa0d376837706 translated
#[test]
fn is_marketplace_folder_unknown_returns_false() {
let f = Fixture::new();
assert!(!Classifier::is_marketplace_folder(uuid(), &f.inventory).unwrap());
}
// parity-case: LibreMetaverse.Tests/MarketplaceFolderClassifierTests.cs::MarketplaceFolderClassifierTests.GetListingsRoot_HasMarketplaceListingsFolder_ReturnsItsUUID::test bae93f760f1a2cc97608a487b98d44e40a552a3698b71f27014ae12bc2ab08d0 translated
#[test]
fn get_listings_root_returns_marketplace_folder() {
let f = Fixture::new();
assert_eq!(
Classifier::get_listings_root(&f.inventory).unwrap(),
f.listings_root
);
}
// parity-case: LibreMetaverse.Tests/MarketplaceFolderClassifierTests.cs::MarketplaceFolderClassifierTests.GetListingsRoot_NoMarketplaceListingsFolder_ReturnsZero::test 68eaa338235b510b202dbf067902999b38f52aef0040edb3d7539ae24f884b25 translated
#[test]
fn get_listings_root_without_marketplace_folder_returns_zero() {
let (client, mut inventory) = empty_inventory();
let root = uuid();
inventory.set_root_folder(Some(folder(root, "My Inventory", UUID::zero(), None)));
inventory
.update_node_for(&folder(uuid(), "Objects", root, None))
.unwrap();
assert_eq!(
Classifier::get_listings_root(&inventory).unwrap(),
UUID::zero()
);
let _ = client.dispose_with_method();
}
// parity-case: LibreMetaverse.Tests/MarketplaceFolderClassifierTests.cs::MarketplaceFolderClassifierTests.GetListingsRoot_NoRootFolder_ReturnsZero::test e23c43ed9179d62b38e290a47711bae64fd9c9ff7c7445b5ad065187af740367 translated
#[test]
fn get_listings_root_without_root_returns_zero() {
let (client, inventory) = empty_inventory();
assert_eq!(
Classifier::get_listings_root(&inventory).unwrap(),
UUID::zero()
);
let _ = client.dispose_with_method();
}
// parity-case: LibreMetaverse.Tests/MarketplaceFolderClassifierTests.cs::MarketplaceFolderClassifierTests.GetListingFolder_CalledOnListingFolder_ReturnsSelf::test 6761009b4891640dfeb44dd361f02cefa968df503ebca6d8b5f3defe86ec803f translated
#[test]
fn get_listing_folder_on_listing_returns_self() {
let f = Fixture::new();
assert_eq!(
Classifier::get_listing_folder(f.listing, &f.inventory).unwrap(),
f.listing
);
}
// parity-case: LibreMetaverse.Tests/MarketplaceFolderClassifierTests.cs::MarketplaceFolderClassifierTests.GetListingFolder_CalledOnVersionFolder_ReturnsListingFolder::test ae3e668b09cda08f558ad654132bda1acdaa3bce08a832b08465ad9302cd6773 translated
#[test]
fn get_listing_folder_on_version_returns_listing() {
let f = Fixture::new();
assert_eq!(
Classifier::get_listing_folder(f.version, &f.inventory).unwrap(),
f.listing
);
}
// parity-case: LibreMetaverse.Tests/MarketplaceFolderClassifierTests.cs::MarketplaceFolderClassifierTests.GetListingFolder_CalledOnStockFolder_ReturnsListingFolder::test 2af63c64992155da9343b273ec7e80984bf3233d5391625e61317d60e976bccf translated
#[test]
fn get_listing_folder_on_stock_returns_listing() {
let f = Fixture::new();
assert_eq!(
Classifier::get_listing_folder(f.stock, &f.inventory).unwrap(),
f.listing
);
}
// parity-case: LibreMetaverse.Tests/MarketplaceFolderClassifierTests.cs::MarketplaceFolderClassifierTests.GetListingFolder_CalledOnListingsRoot_ReturnsZero::test 8921bd854b48d34916e3329640fb758e6d5ac6bc099f3b79dbdbde63529886db translated
#[test]
fn get_listing_folder_on_root_returns_zero() {
let f = Fixture::new();
assert_eq!(
Classifier::get_listing_folder(f.listings_root, &f.inventory).unwrap(),
UUID::zero()
);
}
// parity-case: LibreMetaverse.Tests/MarketplaceFolderClassifierTests.cs::MarketplaceFolderClassifierTests.GetListingFolder_CalledOnUnknownFolder_ReturnsZero::test db0ccbbbcd06e502abdb1db6ebc351c7c202c68ee01e0e17143a0f28dec1ec12 translated
#[test]
fn get_listing_folder_on_unknown_returns_zero() {
let f = Fixture::new();
assert_eq!(
Classifier::get_listing_folder(uuid(), &f.inventory).unwrap(),
UUID::zero()
);
}
// parity-case: LibreMetaverse.Tests/MarketplaceFolderClassifierTests.cs::MarketplaceFolderClassifierTests.GetVersionFolder_ListingHasVersionFolder_ReturnsVersionUUID::test a5f816a37538eed4ae5eedfbe5c357c8aa296bad0c734de50ce8f286d8785084 translated
#[test]
fn get_version_folder_returns_version() {
let f = Fixture::new();
assert_eq!(
Classifier::get_version_folder(f.listing, &f.inventory).unwrap(),
f.version
);
}
// parity-case: LibreMetaverse.Tests/MarketplaceFolderClassifierTests.cs::MarketplaceFolderClassifierTests.GetVersionFolder_ListingHasNoVersionFolder_ReturnsZero::test f35acb3a9edd8e0554d2e1c6c87723804a447060135a29fbd39cd07e7e092467 translated
#[test]
fn get_version_folder_without_version_returns_zero() {
let f = Fixture::new();
let listing = uuid();
f.inventory
.update_node_for(&folder(listing, "Empty Listing", f.listings_root, None))
.unwrap();
assert_eq!(
Classifier::get_version_folder(listing, &f.inventory).unwrap(),
UUID::zero()
);
}
// parity-case: LibreMetaverse.Tests/MarketplaceFolderClassifierTests.cs::MarketplaceFolderClassifierTests.GetStockCount_VersionFolderWithOneItem_ReturnsOne::test d6dadccb9d8c19814038262f376b09ce05201a165634721ad1fd70213a53462d translated
#[test]
fn get_stock_count_one_item_returns_one() {
let f = Fixture::new();
assert_eq!(
Classifier::get_stock_count(f.version, &f.inventory).unwrap(),
1
);
}
// parity-case: LibreMetaverse.Tests/MarketplaceFolderClassifierTests.cs::MarketplaceFolderClassifierTests.GetStockCount_VersionFolderWithOnlySubfolders_ReturnsZero::test 27dc9e58e342db51b5a400bf9785a77c62fe8011b4cabba3bbf69a7ea6aec6c8 translated
#[test]
fn get_stock_count_only_subfolders_returns_zero() {
let f = Fixture::new();
let version = uuid();
f.inventory
.update_node_for(&folder(
version,
"Version Empty",
f.listing,
Some(FolderType::MarketplaceVersion),
))
.unwrap();
f.inventory
.update_node_for(&folder(uuid(), "SubFolder", version, None))
.unwrap();
assert_eq!(
Classifier::get_stock_count(version, &f.inventory).unwrap(),
0
);
}
// parity-case: LibreMetaverse.Tests/MarketplaceFolderClassifierTests.cs::MarketplaceFolderClassifierTests.GetStockCount_ZeroUUID_ReturnsZero::test bd1fdd59481aae5b8e443a55dc8300ac50956c5c4ded3289dbbc4d863a7a9042 translated
#[test]
fn get_stock_count_zero_uuid_returns_zero() {
let f = Fixture::new();
assert_eq!(
Classifier::get_stock_count(UUID::zero(), &f.inventory).unwrap(),
0
);
}
// parity-case: LibreMetaverse.Tests/MarketplaceFolderClassifierTests.cs::MarketplaceFolderClassifierTests.GetStockCount_MultipleItems_ReturnsCorrectCount::test d0ff960d09e791672000e5c63423181e70fc28437eb1cb26538fa175ce4d75f1 translated
#[test]
fn get_stock_count_multiple_items_returns_three() {
let f = Fixture::new();
let version = uuid();
f.inventory
.update_node_for(&folder(
version,
"Version Multi",
f.listing,
Some(FolderType::MarketplaceVersion),
))
.unwrap();
for name in ["Item A", "Item B", "Item C"] {
f.inventory
.update_node_for(&item(uuid(), name, version))
.unwrap();
}
assert_eq!(
Classifier::get_stock_count(version, &f.inventory).unwrap(),
3
);
}
// parity-case: LibreMetaverse.Tests/MarketplaceFolderClassifierTests.cs::MarketplaceFolderClassifierTests.GetAllListingFolderIds_SingleListingFolder_ReturnsOne::test bc49aaa674206f0b4b5f625260090ec2f7ee59ad053881141890271f2f9369e1 translated
#[test]
fn get_all_listing_folder_ids_returns_single_listing() {
let f = Fixture::new();
let ids = Classifier::get_all_listing_folder_ids(&f.inventory).unwrap();
assert_eq!(ids.len(), 1);
assert!(ids.contains(&f.listing));
}
// parity-case: LibreMetaverse.Tests/MarketplaceFolderClassifierTests.cs::MarketplaceFolderClassifierTests.GetAllListingFolderIds_TwoListingFolders_ReturnsBoth::test 4cf174ea092dbbd6741a9cec7ab0caca5da7e41ab5283e88c427d2f7057dd9ff translated
#[test]
fn get_all_listing_folder_ids_returns_both() {
let f = Fixture::new();
let second = uuid();
f.inventory
.update_node_for(&folder(second, "Second Listing", f.listings_root, None))
.unwrap();
let ids = Classifier::get_all_listing_folder_ids(&f.inventory).unwrap();
assert_eq!(ids.len(), 2);
assert!(ids.contains(&f.listing));
assert!(ids.contains(&second));
}
// parity-case: LibreMetaverse.Tests/MarketplaceFolderClassifierTests.cs::MarketplaceFolderClassifierTests.GetAllListingFolderIds_NoMarketplaceRoot_ReturnsEmpty::test fedc2c585ea3fdaae8bf14eb56ccbdcfbb0d2d8a790bb7137a6dd0a02a6ef2c8 translated
#[test]
fn get_all_listing_folder_ids_without_marketplace_root_returns_empty() {
let (client, inventory) = empty_inventory();
assert!(
Classifier::get_all_listing_folder_ids(&inventory)
.unwrap()
.is_empty()
);
let _ = client.dispose_with_method();
}
// parity-case: LibreMetaverse.Tests/MarketplaceFolderClassifierTests.cs::MarketplaceFolderClassifierTests.ValidateListing_WellFormedListing_ReturnsValid::test b15ac0ff131da6764651ccb24a87771f8e9f955c389e813e9c1b50865b472b16 translated
#[test]
fn validate_listing_well_formed_returns_valid() {
let f = Fixture::new();
assert_eq!(
Classifier::validate_listing(f.listing, &f.inventory).unwrap(),
Flags::VALID
);
}
// parity-case: LibreMetaverse.Tests/MarketplaceFolderClassifierTests.cs::MarketplaceFolderClassifierTests.ValidateListing_NoVersionFolder_ReturnsMissingVersionFolder::test 5becd6939ba410c0e6c7cfb42234b1c513a6e69f827080b7f4301da3da6dfab8 translated
#[test]
fn validate_listing_without_version_returns_missing_version() {
let f = Fixture::new();
let listing = uuid();
f.inventory
.update_node_for(&folder(
listing,
"No Version Listing",
f.listings_root,
None,
))
.unwrap();
assert_eq!(
Classifier::validate_listing(listing, &f.inventory).unwrap(),
Flags::MISSING_VERSION_FOLDER
);
}
// parity-case: LibreMetaverse.Tests/MarketplaceFolderClassifierTests.cs::MarketplaceFolderClassifierTests.ValidateListing_MultipleVersionFolders_ReturnsMultipleVersionFolders::test f10ec95540212b4c47035928de4472cdd268cb4946dc1b73f2e65cff32881142 translated
#[test]
fn validate_listing_multiple_versions_returns_multiple_versions() {
let f = Fixture::new();
let listing = uuid();
f.inventory
.update_node_for(&folder(
listing,
"Multi-Version Listing",
f.listings_root,
None,
))
.unwrap();
for name in ["Version A", "Version B"] {
f.inventory
.update_node_for(&folder(
uuid(),
name,
listing,
Some(FolderType::MarketplaceVersion),
))
.unwrap();
}
assert_eq!(
Classifier::validate_listing(listing, &f.inventory).unwrap(),
Flags::MULTIPLE_VERSION_FOLDERS
);
}
// parity-case: LibreMetaverse.Tests/MarketplaceFolderClassifierTests.cs::MarketplaceFolderClassifierTests.ValidateListing_EmptyVersionFolder_ReturnsEmptyListing::test 1443157d7ab29ffe2ea45f38ea43e121262abb89f2264e141c750c7e7689e2c8 translated
#[test]
fn validate_listing_empty_version_returns_empty_listing() {
let f = Fixture::new();
let listing = uuid();
f.inventory
.update_node_for(&folder(listing, "Empty Listing", f.listings_root, None))
.unwrap();
f.inventory
.update_node_for(&folder(
uuid(),
"Version 1",
listing,
Some(FolderType::MarketplaceVersion),
))
.unwrap();
assert_eq!(
Classifier::validate_listing(listing, &f.inventory).unwrap(),
Flags::EMPTY_LISTING
);
}
// parity-case: LibreMetaverse.Tests/MarketplaceFolderClassifierTests.cs::MarketplaceFolderClassifierTests.ValidateListing_UnknownUUID_ReturnsInvalidStructure::test 9ee13dc32219883b7847c2f71de03a42e80681e5916e86d6723bda11fd8223ab translated
#[test]
fn validate_listing_unknown_returns_invalid_structure() {
let f = Fixture::new();
assert_eq!(
Classifier::validate_listing(uuid(), &f.inventory).unwrap(),
Flags::INVALID_STRUCTURE
);
}
// parity-case: LibreMetaverse.Tests/MarketplaceFolderClassifierTests.cs::MarketplaceFolderClassifierTests.ValidateListing_ValidFlags_AreBitmaskComposable::test dcdb7dfcdbcf003c4698e7a2a580046db610a1b8ab3ed7ad7cbe8e2aa36eace4 translated
#[test]
fn validation_flags_are_bitmask_composable() {
let combined = Flags(Flags::MISSING_VERSION_FOLDER.0 | Flags::EMPTY_LISTING.0);
assert_ne!(combined.0 & Flags::MISSING_VERSION_FOLDER.0, 0);
assert_ne!(combined.0 & Flags::EMPTY_LISTING.0, 0);
assert_eq!(combined.0 & Flags::MULTIPLE_VERSION_FOLDERS.0, 0);
}

View File

@@ -0,0 +1,464 @@
// Exact Rust translation of LibreMetaverse.Tests/MarketplaceManagerTests.cs.
// Source SHA-256: 059a0cf2c190954fb6a52aed1c63ca286aa22a7eca72a6a5e9f18e3054f55f38
use libremetaverse::marketplace::{
MarketplaceErrorEventArgs, MarketplaceListing, MarketplaceListingChangedEventArgs,
MarketplaceListingStatus, MarketplaceListingsSyncedEventArgs, MarketplaceManager,
};
use libremetaverse::{GridClient, HttpCapsClient, Simulator};
use libremetaverse_compat_tests::block_on;
use libremetaverse_types::UUID;
use libremetaverse_types::compat::{
ExternalError, HttpMessageHandler, HttpRequest, HttpResponse, Uri,
};
use std::collections::{BTreeMap, VecDeque};
use std::sync::{Arc, Mutex};
use std::time::SystemTime;
const CAP_BASE: &str = "http://test.invalid/direct-delivery";
const SEED: &str = "http://test.invalid/seed";
const FOLDER_1: &str = "11111111-1111-1111-1111-111111111111";
const VERSION_1: &str = "22222222-2222-2222-2222-222222222222";
const FOLDER_2: &str = "33333333-3333-3333-3333-333333333333";
const VERSION_2: &str = "44444444-4444-4444-4444-444444444444";
fn uuid(text: &str) -> UUID {
UUID::new_with_string(text.into()).expect("UUID string constructor")
}
fn random_uuid() -> UUID {
UUID::random().expect("UUID Random")
}
fn response(status: u16, body: &str) -> HttpResponse {
HttpResponse {
status_code: status,
headers: BTreeMap::new(),
content_type: Some("application/json".into()),
body: body.as_bytes().to_vec(),
}
}
struct Harness {
manager: MarketplaceManager,
requests: Arc<Mutex<Vec<HttpRequest>>>,
responses: Arc<Mutex<VecDeque<(String, HttpResponse)>>>,
}
impl Harness {
fn new() -> Self {
let requests = Arc::new(Mutex::new(Vec::new()));
let responses = Arc::new(Mutex::new(VecDeque::new()));
let captured = Arc::clone(&requests);
let queued = Arc::clone(&responses);
let handler = HttpMessageHandler::new(move |request, _| {
let reply = if request.uri.0 == SEED {
HttpResponse {
status_code: 200,
headers: BTreeMap::new(),
content_type: Some("application/llsd+xml".into()),
body: format!(
"<llsd><map><key>DirectDelivery</key><uri>{CAP_BASE}</uri></map></llsd>"
)
.into_bytes(),
}
} else {
let uri = request.uri.0.clone();
captured.lock().unwrap().push(request);
let mut queued = queued.lock().unwrap();
let index = queued
.iter()
.position(|(expected, _)| expected == &uri)
.expect("queued response for request URI");
queued.remove(index).unwrap().1
};
async move { reply }
});
let mut client = GridClient::new().expect("GridClient constructor");
client.set_http_caps_client(HttpCapsClient::new(handler.clone()).unwrap());
let mut simulator_client = GridClient::new().expect("simulator GridClient constructor");
simulator_client.set_http_caps_client(HttpCapsClient::new(handler).unwrap());
let simulator = Simulator::new(
simulator_client,
"127.0.0.1:13".parse().unwrap(),
0,
None,
None,
)
.expect("Simulator constructor");
simulator
.set_seed_caps(Some(Uri(SEED.into())), Some(true))
.unwrap();
let mut network = client.network();
network.set_current_sim(Some(simulator));
client.set_network(network);
Self {
manager: MarketplaceManager::new(client).expect("MarketplaceManager constructor"),
requests,
responses,
}
}
fn add(&self, path: &str, status: u16, body: &str) {
self.responses
.lock()
.unwrap()
.push_back((format!("{CAP_BASE}/{path}"), response(status, body)));
}
fn requests(&self) -> Vec<HttpRequest> {
self.requests.lock().unwrap().clone()
}
fn last_request(&self) -> HttpRequest {
self.requests().last().expect("captured request").clone()
}
fn seed_listing(&self, id: i32, folder: &str, version: &str, count: i32) {
self.add(
"listings",
200,
&format!(
"{{\"listings\":[{{\"id\":{id},\"is_listed\":false,\"inventory_info\":{{\"listing_folder_id\":\"{folder}\",\"version_folder_id\":\"{version}\",\"count_on_hand\":{count}}}}}]}}"
),
);
block_on(self.manager.fetch_listings(None)).unwrap();
}
}
fn listing_json(id: i32, folder: &str) -> String {
format!(
"{{\"listings\":[{{\"id\":{id},\"inventory_info\":{{\"listing_folder_id\":\"{folder}\"}}}}]}}"
)
}
// parity-case: LibreMetaverse.Tests/MarketplaceManagerTests.cs::MarketplaceManagerTests.FetchListingsAsync_ListingsArrayResponse_PopulatesBothCaches::test 1ec347288488be26f8a4b923d304ae9598d1d4f40423356012c353b3527ae089 translated
#[test]
fn fetch_listings_populates_both_caches() {
let h = Harness::new();
h.add("listings", 200, &format!("{{\"listings\":[{{\"id\":101,\"is_listed\":true,\"edit_url\":\"http://mp.sl.com/edit/101\",\"inventory_info\":{{\"listing_folder_id\":\"{FOLDER_1}\",\"version_folder_id\":\"{VERSION_1}\",\"count_on_hand\":3}}}}]}}"));
block_on(h.manager.fetch_listings(None)).unwrap();
let by_id = h.manager.listings_by_id();
let by_folder = h.manager.listings_by_folder();
assert!(by_id.contains_key(&101));
assert!(by_folder.contains_key(&uuid(FOLDER_1)));
let listing = &by_id[&101];
assert_eq!(listing.status(), MarketplaceListingStatus::Listed);
assert_eq!(listing.stock_count(), 3);
assert_eq!(listing.version_folder_uuid(), uuid(VERSION_1));
assert_eq!(
listing.edit_url().as_deref(),
Some("http://mp.sl.com/edit/101")
);
}
// parity-case: LibreMetaverse.Tests/MarketplaceManagerTests.cs::MarketplaceManagerTests.FetchListingsAsync_UnlistedEntry_ParsesAsUnlisted::test 3e5b22da9fcc6a38ddec3ffb215367320df035aed33c9c0690461fdce786b37d translated
#[test]
fn fetch_listings_parses_unlisted_entry() {
let h = Harness::new();
h.add("listings", 200, &format!("{{\"listings\":[{{\"id\":102,\"is_listed\":false,\"inventory_info\":{{\"listing_folder_id\":\"{FOLDER_2}\"}}}}]}}"));
block_on(h.manager.fetch_listings(None)).unwrap();
assert_eq!(
h.manager.listings_by_id()[&102].status(),
MarketplaceListingStatus::Unlisted
);
}
// parity-case: LibreMetaverse.Tests/MarketplaceManagerTests.cs::MarketplaceManagerTests.FetchListingsAsync_FiresListingsSyncedEvent::test ec70956ce5eb51fe650a6e2e77924ec21051b0c06396bce7c9c82a277f6aa82a translated
#[test]
fn fetch_listings_fires_synced_event() {
let h = Harness::new();
h.add("listings", 200, &listing_json(101, FOLDER_1));
let raised = Arc::new(Mutex::new(None));
let captured = Arc::clone(&raised);
let _subscription = h.manager.subscribe_listings_synced(Arc::new(move |args| {
let listings = args.listings();
*captured.lock().unwrap() = Some((listings.len(), listings[0].listing_id()));
}));
block_on(h.manager.fetch_listings(None)).unwrap();
assert_eq!(*raised.lock().unwrap(), Some((1, 101)));
}
// parity-case: LibreMetaverse.Tests/MarketplaceManagerTests.cs::MarketplaceManagerTests.FetchListingsAsync_HttpError_FiresErrorEventAndLeavesEmptyCache::test 0a71f4db07be054bf77752f07223268bd25b673a9c5c8cfe8a5f78ee36b4a463 translated
#[test]
fn fetch_listings_http_error_fires_error_and_leaves_empty_cache() {
let h = Harness::new();
h.add("listings", 500, "");
let error = Arc::new(Mutex::new(None));
let captured = Arc::clone(&error);
let _subscription = h.manager.subscribe_error(Arc::new(move |args| {
*captured.lock().unwrap() = Some(args.message());
}));
block_on(h.manager.fetch_listings(None)).unwrap();
assert!(
error
.lock()
.unwrap()
.as_ref()
.is_some_and(|message| !message.is_empty())
);
assert!(h.manager.listings_by_id().is_empty());
}
// parity-case: LibreMetaverse.Tests/MarketplaceManagerTests.cs::MarketplaceManagerTests.FetchListingsAsync_EmptyListingsArray_ResultsInEmptyCache::test 79ab6108d67cba54f55a8603f3929f1329cbe84ce3b591717d4b4712c2bbe0a2 translated
#[test]
fn fetch_listings_empty_array_results_in_empty_cache() {
let h = Harness::new();
h.add("listings", 200, "{\"listings\":[]}");
block_on(h.manager.fetch_listings(None)).unwrap();
assert!(h.manager.listings_by_id().is_empty());
}
// parity-case: LibreMetaverse.Tests/MarketplaceManagerTests.cs::MarketplaceManagerTests.FetchListingsAsync_SecondCall_ReplacesCacheWithNewData::test 2327332d62529d276a8e1e074b20c3a37a47b5c820910644e6562317fdd4651b translated
#[test]
fn fetch_listings_second_call_replaces_cache() {
let h = Harness::new();
h.add("listings", 200, &listing_json(101, FOLDER_1));
block_on(h.manager.fetch_listings(None)).unwrap();
assert!(h.manager.listings_by_id().contains_key(&101));
h.add("listings", 200, &listing_json(202, FOLDER_2));
block_on(h.manager.fetch_listings(None)).unwrap();
let listings = h.manager.listings_by_id();
assert!(!listings.contains_key(&101));
assert!(listings.contains_key(&202));
}
// parity-case: LibreMetaverse.Tests/MarketplaceManagerTests.cs::MarketplaceManagerTests.CreateListingAsync_SendsNestedInventoryInfoNotFlatUuidField::test efda655bf20ec6157df4738df4cf4ddcc1ee9e1ade01f1f0177630659b54b1d6 translated
#[test]
fn create_listing_sends_nested_inventory_info() {
let h = Harness::new();
h.add("listings", 200, &listing_json(202, FOLDER_2));
let result = block_on(h.manager.create_listing(
uuid(FOLDER_2),
uuid(VERSION_2),
"My Listing".into(),
Some(5),
None,
))
.unwrap()
.expect("created listing");
assert_eq!(result.listing_id(), 202);
let request = h.last_request();
assert_eq!(request.method, "POST");
assert_eq!(request.uri.0, format!("{CAP_BASE}/listings"));
let body = String::from_utf8(request.body).unwrap();
assert!(body.contains("\"name\":\"My Listing\""));
assert!(body.contains(&format!("\"listing_folder_id\":\"{FOLDER_2}\"")));
assert!(body.contains(&format!("\"version_folder_id\":\"{VERSION_2}\"")));
assert!(body.contains("\"count_on_hand\":5"));
assert!(!body.contains("listing_folder_uuid"));
}
// parity-case: LibreMetaverse.Tests/MarketplaceManagerTests.cs::MarketplaceManagerTests.CreateListingAsync_FiresListingChangedEvent::test 242073ff6fbae379c518d047cd63e1ad368ff37ffc2cad379b8c007fb725b74e translated
#[test]
fn create_listing_fires_changed_event() {
let h = Harness::new();
h.add("listings", 200, &listing_json(202, FOLDER_2));
let changed = Arc::new(Mutex::new(None));
let captured = Arc::clone(&changed);
let _subscription = h.manager.subscribe_listing_changed(Arc::new(move |args| {
let listing = args.listing().expect("changed listing");
*captured.lock().unwrap() = Some((args.listing_id(), listing.listing_folder_uuid()));
}));
block_on(
h.manager
.create_listing(uuid(FOLDER_2), uuid(VERSION_2), "Name".into(), None, None),
)
.unwrap();
assert_eq!(*changed.lock().unwrap(), Some((202, uuid(FOLDER_2))));
}
// parity-case: LibreMetaverse.Tests/MarketplaceManagerTests.cs::MarketplaceManagerTests.CreateListingAsync_HttpError_ReturnsNullAndFiresErrorEvent::test fa999c4cce5bee688ef3bb6342e276867268ab9f32571eff25646cb1384bcece translated
#[test]
fn create_listing_http_error_returns_none_and_fires_error() {
let h = Harness::new();
h.add("listings", 400, "");
let fired = Arc::new(Mutex::new(false));
let captured = Arc::clone(&fired);
let _subscription = h
.manager
.subscribe_error(Arc::new(move |_| *captured.lock().unwrap() = true));
let result =
block_on(
h.manager
.create_listing(random_uuid(), random_uuid(), "Name".into(), None, None),
)
.unwrap();
assert!(result.is_none());
assert!(*fired.lock().unwrap());
}
// parity-case: LibreMetaverse.Tests/MarketplaceManagerTests.cs::MarketplaceManagerTests.DeleteListingAsync_UsesSingularListingRoute::test aea0672be109f05632df326a0c2caf7b7d14d23cf0d66e6ab867902351ebb554 translated
#[test]
fn delete_listing_uses_singular_route_and_evicts_caches() {
let h = Harness::new();
h.add("listings", 200, &listing_json(101, FOLDER_1));
block_on(h.manager.fetch_listings(None)).unwrap();
let mut listing = None;
assert!(h.manager.try_get_by_id(101, &mut listing));
h.add("listing/101", 200, "");
assert!(block_on(h.manager.delete_listing(101, None)).unwrap());
assert!(!h.manager.try_get_by_id(101, &mut None));
assert!(!h.manager.try_get_by_folder(uuid(FOLDER_1), &mut None));
assert_eq!(h.last_request().uri.0, format!("{CAP_BASE}/listing/101"));
}
// parity-case: LibreMetaverse.Tests/MarketplaceManagerTests.cs::MarketplaceManagerTests.DeleteListingAsync_HttpError_ReturnsFalseAndFiresErrorEvent::test 52976e09904483e7f33dbe016d695e380646f75b2fdd1b1f744c3fc69dd9d192 translated
#[test]
fn delete_listing_http_error_returns_false_and_fires_error() {
let h = Harness::new();
h.add("listing/999", 404, "");
let fired = Arc::new(Mutex::new(false));
let captured = Arc::clone(&fired);
let _subscription = h
.manager
.subscribe_error(Arc::new(move |_| *captured.lock().unwrap() = true));
assert!(!block_on(h.manager.delete_listing(999, None)).unwrap());
assert!(*fired.lock().unwrap());
}
// parity-case: LibreMetaverse.Tests/MarketplaceManagerTests.cs::MarketplaceManagerTests.ActivateListingAsync_SendsIsListedTrueAndCachedInventoryInfoToSingularRoute::test 4b6daed0e333c504a7aed8666980152990c37d81830d08f3a31faf39dbbc706f translated
#[test]
fn activate_listing_sends_full_cached_inventory_info() {
let h = Harness::new();
h.seed_listing(101, FOLDER_1, VERSION_1, 7);
h.add("listing/101", 200, &format!("{{\"listings\":[{{\"id\":101,\"is_listed\":true,\"inventory_info\":{{\"listing_folder_id\":\"{FOLDER_1}\",\"version_folder_id\":\"{VERSION_1}\",\"count_on_hand\":7}}}}]}}"));
assert!(block_on(h.manager.activate_listing(101, None)).unwrap());
let request = h.last_request();
assert_eq!(request.method, "PUT");
assert_eq!(request.uri.0, format!("{CAP_BASE}/listing/101"));
let body = String::from_utf8(request.body).unwrap();
for expected in [
"\"is_listed\":true",
"\"id\":101",
&format!("\"listing_folder_id\":\"{FOLDER_1}\""),
&format!("\"version_folder_id\":\"{VERSION_1}\""),
"\"count_on_hand\":7",
] {
assert!(body.contains(expected));
}
let mut listing = None;
assert!(h.manager.try_get_by_id(101, &mut listing));
assert_eq!(listing.unwrap().status(), MarketplaceListingStatus::Listed);
}
// parity-case: LibreMetaverse.Tests/MarketplaceManagerTests.cs::MarketplaceManagerTests.ActivateListingAsync_NoCachedListing_ReturnsFalseWithoutSendingRequest::test 1c4d407a29ba139b13e868882f1721327cfdd64dc2d2e9a32a0c71678905bb65 translated
#[test]
fn activate_listing_without_cached_listing_sends_nothing() {
let h = Harness::new();
assert!(!block_on(h.manager.activate_listing(999, None)).unwrap());
assert!(h.requests().is_empty());
}
// parity-case: LibreMetaverse.Tests/MarketplaceManagerTests.cs::MarketplaceManagerTests.ActivateListingAsync_HttpError_ReturnsFalse::test 1f7b39a95adfd13cf159fbadac9d157a70ebbdcb360a1cf1cf4d21b891bd61d6 translated
#[test]
fn activate_listing_http_error_returns_false() {
let h = Harness::new();
h.seed_listing(101, FOLDER_1, VERSION_1, 0);
h.add("listing/101", 400, "");
assert!(!block_on(h.manager.activate_listing(101, None)).unwrap());
}
// parity-case: LibreMetaverse.Tests/MarketplaceManagerTests.cs::MarketplaceManagerTests.DeactivateListingAsync_SendsIsListedFalse::test 1fa6eb4bfc86fb9a5fe746b18e43568b9dcc1a723e3a667b1bc57a1ebb66fb50 translated
#[test]
fn deactivate_listing_sends_is_listed_false() {
let h = Harness::new();
h.seed_listing(101, FOLDER_1, VERSION_1, 0);
h.add("listing/101", 200, &format!("{{\"listings\":[{{\"id\":101,\"is_listed\":false,\"inventory_info\":{{\"listing_folder_id\":\"{FOLDER_1}\"}}}}]}}"));
block_on(h.manager.deactivate_listing(101, None)).unwrap();
assert!(
String::from_utf8(h.last_request().body)
.unwrap()
.contains("\"is_listed\":false")
);
let mut listing = None;
assert!(h.manager.try_get_by_id(101, &mut listing));
assert_eq!(
listing.unwrap().status(),
MarketplaceListingStatus::Unlisted
);
}
// parity-case: LibreMetaverse.Tests/MarketplaceManagerTests.cs::MarketplaceManagerTests.TryGetByFolder_AfterFetch_ReturnsMatchingListing::test cb0b2a301f9096a238ba078739f0b6488a4dcc20fecdd59d51c930f7ea28902c translated
#[test]
fn try_get_by_folder_returns_matching_listing() {
let h = Harness::new();
h.add("listings", 200, &listing_json(101, FOLDER_1));
block_on(h.manager.fetch_listings(None)).unwrap();
let mut listing = None;
assert!(h.manager.try_get_by_folder(uuid(FOLDER_1), &mut listing));
assert_eq!(listing.unwrap().listing_id(), 101);
}
// parity-case: LibreMetaverse.Tests/MarketplaceManagerTests.cs::MarketplaceManagerTests.TryGetByFolder_MissingUUID_ReturnsFalse::test 86fe3e33c410412e829efbc4e775b164492b2dd14d82421478552e9a01c35ef8 translated
#[test]
fn try_get_by_folder_missing_uuid_returns_false() {
let h = Harness::new();
h.add("listings", 200, "{\"listings\":[]}");
block_on(h.manager.fetch_listings(None)).unwrap();
assert!(!h.manager.try_get_by_folder(random_uuid(), &mut None));
}
// parity-case: LibreMetaverse.Tests/MarketplaceManagerTests.cs::MarketplaceManagerTests.TryGetById_EmptyCache_ReturnsFalse::test 8d49aeaf5444d8d2d2098f932df01dac6e6942a86b105287c5f40cb54e501dcc translated
#[test]
fn try_get_by_id_empty_cache_returns_false() {
let h = Harness::new();
assert!(!h.manager.try_get_by_id(9999, &mut None));
}
// parity-case: LibreMetaverse.Tests/MarketplaceManagerTests.cs::MarketplaceManagerTests.MarketplaceListingsSyncedEventArgs_StoresListings::test c0744e6b9f9282613692f7be962009e9129c234e3ca863ab40b581baa90a6a68 translated
#[test]
fn listings_synced_event_args_store_listings() {
let mut listing = MarketplaceListing::new().unwrap();
listing.set_listing_id(1);
let args = MarketplaceListingsSyncedEventArgs::new(vec![listing]).unwrap();
let listings = args.listings();
assert_eq!(listings.len(), 1);
assert_eq!(listings[0].listing_id(), 1);
}
// parity-case: LibreMetaverse.Tests/MarketplaceManagerTests.cs::MarketplaceManagerTests.MarketplaceListingChangedEventArgs_StoresListingIdAndListing::test 874578d97b250b4667e3cb0c28626948ede80fba14e9ae9add153e2dfddc1902 translated
#[test]
fn listing_changed_event_args_store_same_listing() {
let mut listing = MarketplaceListing::new().unwrap();
listing.set_listing_id(42);
let listing = Arc::new(listing);
let args = MarketplaceListingChangedEventArgs::new(42, Some(Arc::clone(&listing))).unwrap();
assert_eq!(args.listing_id(), 42);
assert!(Arc::ptr_eq(&args.listing().unwrap(), &listing));
}
// parity-case: LibreMetaverse.Tests/MarketplaceManagerTests.cs::MarketplaceManagerTests.MarketplaceListingChangedEventArgs_NullListing_IsValidForDeleteScenario::test 6a4fadad3a00e0e17977506badf7e08a53278f7c89fc4c7597a502164257f50d translated
#[test]
fn listing_changed_event_args_allow_none_for_delete() {
let args = MarketplaceListingChangedEventArgs::new(99, None).unwrap();
assert_eq!(args.listing_id(), 99);
assert!(args.listing().is_none());
}
// parity-case: LibreMetaverse.Tests/MarketplaceManagerTests.cs::MarketplaceManagerTests.MarketplaceErrorEventArgs_StoresMessageAndException::test cb0213208ab6b63f32a950f1771354fae4b6904c72720b1705ddf5b8355ffc7d translated
#[test]
fn error_event_args_store_same_message_and_exception() {
let error = Arc::new(ExternalError("inner error".into()));
let args = MarketplaceErrorEventArgs::new("Something failed.".into(), Some(Arc::clone(&error)))
.unwrap();
assert_eq!(args.message(), "Something failed.");
assert!(Arc::ptr_eq(&args.exception().unwrap(), &error));
}
// parity-case: LibreMetaverse.Tests/MarketplaceManagerTests.cs::MarketplaceManagerTests.MarketplaceErrorEventArgs_WithoutException_HasNullException::test de7c8addfb291cba5dee890a98ac8b5f27b192d0b75894c4102303a49785de47 translated
#[test]
fn error_event_args_without_exception_has_none() {
let args = MarketplaceErrorEventArgs::new("No exception here.".into(), None).unwrap();
assert_eq!(args.message(), "No exception here.");
assert!(args.exception().is_none());
}
// parity-case: LibreMetaverse.Tests/MarketplaceManagerTests.cs::MarketplaceManagerTests.MarketplaceListing_DefaultValues_AreCorrect::test 70a29163581702fdc32c54a398ad4cefa608da8b1bc9d54a4e9e191e95398fb7 translated
#[test]
fn marketplace_listing_defaults_are_correct() {
let listing = MarketplaceListing::new().unwrap();
assert_eq!(listing.status(), MarketplaceListingStatus::Unknown);
assert_eq!(listing.last_sync_utc(), SystemTime::UNIX_EPOCH);
assert!(listing.edit_url().is_none());
}

View File

@@ -0,0 +1,20 @@
// Exact Rust translations of the remaining manager cases in
// LibreMetaverse.Tests/ConstructorNullArgumentTests.cs.
// Source SHA-256: 28deea0bf4d9353a2424842c6184abab8fe82746ceb12e093912728a247f21bc
use libremetaverse::{AppearanceManager, AvatarManager, Error};
// parity-case: LibreMetaverse.Tests/ConstructorNullArgumentTests.cs::ConstructorNullArgumentTests.AppearanceManager_Null_Throws::test a3c872805bc924b5a1a9441d5c9eb61ed6d6e9477e4bb411131359290b144ab4 translated
#[test]
fn appearance_manager_null_throws() {
assert!(matches!(
AppearanceManager::new(None),
Err(Error::ArgumentNull)
));
}
// parity-case: LibreMetaverse.Tests/ConstructorNullArgumentTests.cs::ConstructorNullArgumentTests.AvatarManager_Null_Throws::test 54f23cbf0ba87b0525c2914e78d75808e93fd1c460fc0bec4d15f09575b1431c translated
#[test]
fn avatar_manager_null_throws() {
assert!(matches!(AvatarManager::new(None), Err(Error::ArgumentNull)));
}

View File

@@ -0,0 +1,159 @@
// Exact Rust translations of LibreMetaverse.Tests/OfflineMessagesTests.cs and
// LibreMetaverse.Tests/ProductInfoRequestMessageTests.cs.
// Source SHA-256: ad649e9efb2b60b8a323d3d457be568fda9cc5ecb80b8999f6066d0b7f5a6527
// Source SHA-256: fabdc141e6f616b88d998ceca16f1884d4c3aa6efc5152060e8840a4ef0d6db7
use libremetaverse::messages::linden::{
ProductInfoRequestMessage, ProductInfoRequestMessageProductInfo,
};
use libremetaverse::{GridClient, HttpCapsClient, Simulator};
use libremetaverse_compat_tests::block_on;
use libremetaverse_structured_data::{OSD, OSDMap};
use libremetaverse_types::compat::{HttpMessageHandler, HttpResponse, Uri};
use std::collections::{BTreeMap, HashMap};
use std::sync::{Arc, Mutex};
const CAP: &str = "http://test.invalid/read-offline-msgs";
const SEED: &str = "http://test.invalid/seed";
fn response(body: &str) -> HttpResponse {
HttpResponse {
status_code: 200,
headers: BTreeMap::new(),
content_type: Some("application/json".into()),
body: body.as_bytes().to_vec(),
}
}
fn offline_client(body: &str) -> GridClient {
let body = body.to_owned();
let handler = HttpMessageHandler::new(move |request, _| {
let reply = if request.uri.0 == SEED {
HttpResponse {
status_code: 200,
headers: BTreeMap::new(),
content_type: Some("application/llsd+xml".into()),
body: format!(
"<llsd><map><key>ReadOfflineMsgs</key><uri>{CAP}</uri><key>AcceptFriendship</key><uri>http://test.invalid/accept-friendship</uri><key>AcceptGroupInvite</key><uri>http://test.invalid/accept-group-invite</uri></map></llsd>"
)
.into_bytes(),
}
} else {
response(&body)
};
async move { reply }
});
let mut client = GridClient::new().expect("GridClient constructor");
client.set_http_caps_client(HttpCapsClient::new(handler.clone()).unwrap());
let mut simulator_client = GridClient::new().expect("simulator GridClient constructor");
simulator_client.set_http_caps_client(HttpCapsClient::new(handler).unwrap());
let simulator = Simulator::new(
simulator_client,
"127.0.0.1:13".parse().unwrap(),
0,
None,
None,
)
.expect("Simulator constructor");
simulator
.set_seed_caps(Some(Uri(SEED.into())), Some(true))
.unwrap();
let mut network = client.network();
network.set_current_sim(Some(simulator));
client.set_network(network);
client
}
fn message_json(from_name: &str, text: &str) -> String {
format!(
"{{\"from_agent_id\":\"11111111-1111-1111-1111-111111111111\",\"from_agent_name\":\"{from_name}\",\"to_agent_id\":\"22222222-2222-2222-2222-222222222222\",\"region_id\":\"33333333-3333-3333-3333-333333333333\",\"dialog\":0,\"transaction-id\":\"44444444-4444-4444-4444-444444444444\",\"timestamp\":0,\"message\":\"{text}\",\"local_x\":1.0,\"local_y\":2.0,\"local_z\":3.0}}"
)
}
fn retrieve(body: &str) -> Vec<(String, String)> {
let mut client = offline_client(body);
let received = Arc::new(Mutex::new(Vec::new()));
let captured = Arc::clone(&received);
let agent = client.self_();
let _subscription = agent.subscribe_im(Arc::new(move |args| {
let message = args.im();
captured
.lock()
.unwrap()
.push((message.message, message.from_agent_name));
}));
block_on(agent.retrieve_instant_messages(None)).unwrap();
received.lock().unwrap().clone()
}
fn map(entries: impl IntoIterator<Item = (&'static str, OSD)>) -> OSDMap {
OSDMap::new_with_dictionary(
entries
.into_iter()
.map(|(key, value)| (key.into(), value))
.collect(),
)
.expect("OSDMap dictionary constructor")
}
// parity-case: LibreMetaverse.Tests/OfflineMessagesTests.cs::OfflineMessagesTests.RetrieveInstantMessagesAsync_BareArrayOfArraysResponse_RaisesInstantMessage::test d51f69e0fa1e1e59a5cedec7d60315d1f590848672a9f4f0c5e21d2abff5c372 translated
#[test]
fn retrieve_offline_messages_bare_array_raises_instant_message() {
let received = retrieve(&format!("[[{}]]", message_json("Jim", "hello")));
assert_eq!(received.len(), 1);
assert_eq!(received[0].0, "hello");
assert_eq!(received[0].1, "Jim");
}
// parity-case: LibreMetaverse.Tests/OfflineMessagesTests.cs::OfflineMessagesTests.RetrieveInstantMessagesAsync_MessagesMapResponse_RaisesInstantMessage::test dbce6320d57d12ca5557cfba65257e15be314cde947b20dd21bc386819fcb3ce translated
#[test]
fn retrieve_offline_messages_map_raises_instant_message() {
let received = retrieve(&format!(
"{{\"messages\":[{}]}}",
message_json("Jim", "hello via map")
));
assert_eq!(received.len(), 1);
assert_eq!(received[0].0, "hello via map");
}
// parity-case: LibreMetaverse.Tests/ProductInfoRequestMessageTests.cs::ProductInfoRequestMessageTests.Deserialize_BareArray_ReadsSkuNameDescription::test 5d51fdbb1bec1ff74df59778d214413e78fb650679d36e7c44be92d1b2e3205f translated
#[test]
fn product_info_deserialize_bare_array_reads_fields() {
let product = OSD::Map(HashMap::from([
("sku".into(), OSD::String("023".into())),
("name".into(), OSD::String("Homestead".into())),
(
"description".into(),
OSD::String("A Homestead region".into()),
),
]));
let mut message =
ProductInfoRequestMessage::new().expect("ProductInfoRequestMessage constructor");
message
.deserialize(map([("products", OSD::Array(vec![product]))]))
.unwrap();
assert_eq!(message.products.len(), 1);
assert_eq!(message.products[0].sku, "023");
assert_eq!(message.products[0].name, "Homestead");
assert_eq!(message.products[0].description, "A Homestead region");
}
// parity-case: LibreMetaverse.Tests/ProductInfoRequestMessageTests.cs::ProductInfoRequestMessageTests.SerializeDeserialize_RoundTrips::test 5cb54bed4150cf13f815b223d6b7e35e7427004a12e98c7328c7674b6fe6309b translated
#[test]
fn product_info_serialize_deserialize_round_trips() {
let mut product = ProductInfoRequestMessageProductInfo::new().expect("ProductInfo constructor");
product.sku = "001".into();
product.name = "Full Region".into();
product.description = "A full region".into();
let mut message =
ProductInfoRequestMessage::new().expect("ProductInfoRequestMessage constructor");
message.products.push(product);
let encoded = message.serialize().unwrap();
let mut decoded =
ProductInfoRequestMessage::new().expect("ProductInfoRequestMessage constructor");
decoded.deserialize(encoded).unwrap();
assert_eq!(decoded.products.len(), 1);
assert_eq!(decoded.products[0].sku, "001");
assert_eq!(decoded.products[0].name, "Full Region");
assert_eq!(decoded.products[0].description, "A full region");
}