Translate world-state parity tests
This commit is contained in:
@@ -2,30 +2,8 @@
|
||||
// Source: LibreMetaverse 2aa70bb68513b39795da5d13c88f31b86e85a3ba
|
||||
// Pending cases are catalog entries, not fake executable Rust tests.
|
||||
|
||||
// pending-parity-case: LibreMetaverse.Tests/ConstructorNullArgumentTests.cs::ConstructorNullArgumentTests.GridManager_Null_Throws::test e972a95f334b0f46948cda34c27124c28c44faf4372d0e598d7dc60050b49be4
|
||||
// pending-parity-case: LibreMetaverse.Tests/ConstructorNullArgumentTests.cs::ConstructorNullArgumentTests.AppearanceManager_Null_Throws::test a3c872805bc924b5a1a9441d5c9eb61ed6d6e9477e4bb411131359290b144ab4
|
||||
// pending-parity-case: LibreMetaverse.Tests/ConstructorNullArgumentTests.cs::ConstructorNullArgumentTests.ObjectManager_Null_Throws::test 8a11feba0edfb35e5dd99f681182e8f5a5cf8a3f738211b45a683a8a2ad45ddb
|
||||
// pending-parity-case: LibreMetaverse.Tests/ConstructorNullArgumentTests.cs::ConstructorNullArgumentTests.AgentManager_Null_Throws::test d86e41b6cdd03063685aa330c31b9a274c1d400b9a461abf3065fe185fe0bbf0
|
||||
// pending-parity-case: LibreMetaverse.Tests/ConstructorNullArgumentTests.cs::ConstructorNullArgumentTests.AvatarManager_Null_Throws::test 54f23cbf0ba87b0525c2914e78d75808e93fd1c460fc0bec4d15f09575b1431c
|
||||
// pending-parity-case: LibreMetaverse.Tests/EnvironmentManagerTests.cs::EnvironmentManagerTests.GetParcelEnvironment_UsesParcelidQueryParameter::test 5c2f2b0fa2a86955975c621b2415a92ff3da283215e669956e14bf5ee2a4c1f4
|
||||
// pending-parity-case: LibreMetaverse.Tests/EnvironmentManagerTests.cs::EnvironmentManagerTests.SetParcelEnvironment_SendsParcelidInQueryStringNotBody::test f633e2d78e4c6a0fff42917ccfe8de68e4f6133a11e7eef7f9b757c3d1622f0f
|
||||
// pending-parity-case: LibreMetaverse.Tests/EnvironmentManagerTests.cs::EnvironmentManagerTests.SetRegionEnvironment_OmitsQueryStringEntirely::test bade6e06765506ad7e500ac3e5c9f168605ce25fef86647819d285a68b39f109
|
||||
// pending-parity-case: LibreMetaverse.Tests/EnvironmentManagerTests.cs::EnvironmentManagerTests.ResetParcelEnvironment_SendsHttpDeleteNotPost::test 4360439192c137f5d7a2ceb83b8664f3917b4b261798050cb855d596f483f082
|
||||
// pending-parity-case: LibreMetaverse.Tests/EstateExperienceReplyTests.cs::EstateExperienceReplyTests.SetExperience_ParsesBlockedTrustedAndAllowedLists::test 49a77aa9d7c5bf1232082a08594e7ebcfafad11ab110c9e15d2ad4ea1831c649
|
||||
// pending-parity-case: LibreMetaverse.Tests/EstateExperienceReplyTests.cs::EstateExperienceReplyTests.SetExperience_AllEmptyLists_ProducesEmptyResult::test 711eaebb11f5d7ece92946d3de240a341a4b1fd8f30617fd97cb059d0dc6a0b9
|
||||
// pending-parity-case: LibreMetaverse.Tests/EstateToolsTests.cs::EstateToolsTests.RequestConvenant::test d8d752dd6e53477e4c66bcb5d0e3ec1021a9b3ceda1f689f59b5e606e1713729
|
||||
// pending-parity-case: LibreMetaverse.Tests/ExperienceListAndRegionMessageTests.cs::ExperienceListAndRegionMessageTests.ExperienceListMessage_Deserialize_ReadsExperienceIdsKey::test aa1f7d09f6c79118ea2e60621d57bd63632085ce81bc979e42294aca53d4f0d9
|
||||
// pending-parity-case: LibreMetaverse.Tests/ExperienceListAndRegionMessageTests.cs::ExperienceListAndRegionMessageTests.ExperienceListMessage_Deserialize_IgnoresLegacyExperienceKeysKey::test cd1d372b9a976c04dee11da1ade182e4f9239e1f7633e788347c6d5f255835ec
|
||||
// pending-parity-case: LibreMetaverse.Tests/ExperienceListAndRegionMessageTests.cs::ExperienceListAndRegionMessageTests.ExperienceListMessage_Serialize_WritesExperienceIdsKey::test 3fa4cb5d598940f693285bcc64179a4dea927a3643a76a061a933a265488d4be
|
||||
// pending-parity-case: LibreMetaverse.Tests/ExperienceListAndRegionMessageTests.cs::ExperienceListAndRegionMessageTests.RegionExperiencesMessage_Deserialize_ReadsBlockedTrustedAllowedAndDefault::test 61df3b0c60d32b6c9bb843eb7a1a11fe8c0b1fd59c7a09853ad1b0e1d93cd4fd
|
||||
// pending-parity-case: LibreMetaverse.Tests/ExperienceListAndRegionMessageTests.cs::ExperienceListAndRegionMessageTests.RegionExperiencesMessage_Deserialize_IgnoresLegacyContribKey::test 851d037919003ebb414105e57bf37f73ba37dff8f733c36183c447f1349f3316
|
||||
// pending-parity-case: LibreMetaverse.Tests/ExperienceListAndRegionMessageTests.cs::ExperienceListAndRegionMessageTests.RegionExperiencesMessage_Serialize_WritesAllowedKeyNotContrib::test 53c3a7d6a200816615a9efaa222ccf294e3a8334d320812c6ec56a0a3e7e05bb
|
||||
// pending-parity-case: LibreMetaverse.Tests/ExperiencePreferencesMessageTests.cs::ExperiencePreferencesMessageTests.Deserialize_ReadsAllowedListFromExperiencesKey::test 9bab78dbe142a3da6ad21a278f25d7da90776fce3861c7d602203c1e1842c9af
|
||||
// pending-parity-case: LibreMetaverse.Tests/ExperiencePreferencesMessageTests.cs::ExperiencePreferencesMessageTests.Deserialize_IgnoresLegacyAllowedKey::test ec6d5e7c81214ea4e3d99740fdd33961578f895a90a42082067ca9819d93d2b0
|
||||
// pending-parity-case: LibreMetaverse.Tests/ExperiencePreferencesMessageTests.cs::ExperiencePreferencesMessageTests.Serialize_WritesAllowedListUnderExperiencesKey::test 45a0bffe39ab7bf0734ec5fce4435dbdda7ae94cf4e933210669e91dc45b1baf
|
||||
// pending-parity-case: LibreMetaverse.Tests/ExperiencePreferencesMessageTests.cs::ExperiencePreferencesMessageTests.ExtractExperiencePermission_Allowed_ReturnsAllow::test cf095ab428713004ebac6e1915a47ae0c03bd2958addbba2a39fd2f0edf51a74
|
||||
// pending-parity-case: LibreMetaverse.Tests/ExperiencePreferencesMessageTests.cs::ExperiencePreferencesMessageTests.ExtractExperiencePermission_Blocked_ReturnsBlock::test af084d1ab7a11079e6251865e8fd5aecfde38d2df359ebc1e208bc74925935c0
|
||||
// pending-parity-case: LibreMetaverse.Tests/ExperiencePreferencesMessageTests.cs::ExperiencePreferencesMessageTests.ExtractExperiencePermission_NeitherList_ReturnsForget::test 93204469ecfec2f3f4eb6838c99f6e2baf09bf76a075958d1ed369ba03767158
|
||||
// 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
|
||||
@@ -86,28 +64,8 @@
|
||||
// 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/PrimObjectTests.cs::PrimObjectTests.PathBegin::test 5c8e14e1d08a91a4e7c3e252c932b8fe15cf6b5231cc9fe5bb7ef2ae6e2c8299
|
||||
// pending-parity-case: LibreMetaverse.Tests/PrimObjectTests.cs::PrimObjectTests.PathEnd::test 693bfe29f448e433705d65b8b6907f1b270fd636f914e18b76d7a0047dbea506
|
||||
// pending-parity-case: LibreMetaverse.Tests/PrimObjectTests.cs::PrimObjectTests.PathRevolutions::test c3f61c80a204e608976cb44a0c10b9651496074c25f254eec8621db65dbbbe37
|
||||
// pending-parity-case: LibreMetaverse.Tests/PrimObjectTests.cs::PrimObjectTests.PathScale::test b92e4ab375fcc788dea701d8579268f39b4f3b1d51d4eed91458547350405d61
|
||||
// pending-parity-case: LibreMetaverse.Tests/PrimObjectTests.cs::PrimObjectTests.PathTaper::test 93a0adbc0630de3c9fbea6f8080d74ef6e3180e3813f00460bce5d52ef2f12b7
|
||||
// pending-parity-case: LibreMetaverse.Tests/PrimObjectTests.cs::PrimObjectTests.TextureEntryOffsets::test 720ea1a9477d333b14786bc14e9abca24858e63acae94f4c6055d81f14ff033a
|
||||
// pending-parity-case: LibreMetaverse.Tests/PrimObjectTests.cs::PrimObjectTests.TextureEntry::test 0670a9a8dcc4001e726df699ef8001604956b6674028a192502b92b725858990
|
||||
// pending-parity-case: LibreMetaverse.Tests/PrimObjectTests.cs::PrimObjectTests.TextureEntry_RenderMaterialID_DefaultFace_Roundtrips::test 8db56b448e53e6bec5540a5a4721dc75f85a933c6c89e166f7df7baf8e44aab3
|
||||
// pending-parity-case: LibreMetaverse.Tests/PrimObjectTests.cs::PrimObjectTests.TextureEntry_RenderMaterialID_PerFace_Roundtrips::test 2897366ecaa41f07b4db6ebf3e80a7ebe56480f1c44f31cedea2d88a62214dc6
|
||||
// pending-parity-case: LibreMetaverse.Tests/PrimObjectTests.cs::PrimObjectTests.TextureEntry_RenderMaterialID_MultipleFaces_Roundtrips::test f3d8c103e4b3d43a8e3bea1356ba13808633fdb2ea06583234551f9059b2a241
|
||||
// pending-parity-case: LibreMetaverse.Tests/PrimObjectTests.cs::PrimObjectTests.TextureEntry_RenderMaterialID_InheritsFromDefault_WhenNotOverridden::test 2313a0134836651e23c693505c3c000ad7ff24956b432d0761a5e8b77cb01642
|
||||
// pending-parity-case: LibreMetaverse.Tests/PrimitiveTests.cs::PrimitiveTests.GetOSD_FromOSD_Roundtrip_Minimal::test 5e81b8a195f3e59bfe9e3ebf50c3291f7cbcd49f567ede7c1c8b726e0c6c9c19
|
||||
// pending-parity-case: LibreMetaverse.Tests/PrimitiveTests.cs::PrimitiveTests.GetOSD_FromOSD_Roundtrip_Extras::test 63bae8bddacab170aec00c6d7a219f96fa794f489190b34cb426bbf9a3672af5
|
||||
// pending-parity-case: LibreMetaverse.Tests/PrimitiveTests.cs::PrimitiveTests.FromOSD_MissingVolume_DoesNotThrow_AndUsesDefaults::test 03f9369aab6f6a71ee13982a7b6ba9780f86bcb5b6f081f9550f491b692f711c
|
||||
// pending-parity-case: LibreMetaverse.Tests/PrimitiveTests.cs::PrimitiveTests.FromOSD_WrongTypes_ForTransforms_AreIgnored::test a23d4b1ab6d24c11c96862bc18ba57fccf1a8a1d690c90c5e8da3092973220f7
|
||||
// pending-parity-case: LibreMetaverse.Tests/PrimitiveTests.cs::PrimitiveTests.FromOSD_PartialProfile_UsesDefaultsForMissingFields::test f3a3e506e3ef417f6323875db82179a4ffbdc1d4ee383417f2b0bd5afd0d0dba
|
||||
// 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/QueryExperiencesOnParcelTests.cs::QueryExperiencesOnParcelTests.QueryExperiencesOnParcelAsync_HappyPath_ParsesAllowedMapAndBuildsExpectedQuery::test 2571d3a4100face21268d7ca2401cc8468e711c03c808704aacc7a50006125d5
|
||||
// pending-parity-case: LibreMetaverse.Tests/QueryExperiencesOnParcelTests.cs::QueryExperiencesOnParcelTests.QueryExperiencesOnParcelAsync_NoExperienceIds_OmitsExperiencesParam::test ddbaa53aa8c63262c2241588b4281c42bbb66efdecac95e297deb0fb81797455
|
||||
// pending-parity-case: LibreMetaverse.Tests/QueryExperiencesOnParcelTests.cs::QueryExperiencesOnParcelTests.QueryExperiencesOnParcelAsync_NoCapability_ReturnsNullWithoutRequest::test 5c6a6584fba8ddc66200367217f658d342fb2c26d6be9e49ccf3892bea420095
|
||||
// pending-parity-case: LibreMetaverse.Tests/QueryExperiencesOnParcelTests.cs::QueryExperiencesOnParcelTests.QueryExperiencesOnParcelAsync_NonSuccessStatus_ReturnsNull::test 977fe55acd5aeb5735cc718f705a2742ae0dfab12dc1211c03a64cc6d1f3bbf5
|
||||
// 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
|
||||
@@ -724,60 +682,3 @@
|
||||
// pending-parity-case: LibreMetaverse.Tests/RLV/RlvRestrictionManagerTests.cs::RlvRestrictionManagerTests.RemoveRestrictionsForObjects_WithNotificationRestrictions_SendsNotifications::test ba82b183dfdb01b36f9b45520e1808290c360f327d4afa833ba3b8c7a7cecffb
|
||||
// pending-parity-case: LibreMetaverse.Tests/RLV/RlvRestrictionManagerTests.cs::RlvRestrictionManagerTests.RemoveRestrictionsForObjects_WithComplexRestrictions_RemovesCorrectly::test 631de2d39fa56b29014fae4ce3b57c480f540ad41ce08a0037b7f8bbfcb3c502
|
||||
// pending-parity-case: LibreMetaverse.Tests/RLV/RlvRestrictionManagerTests.cs::RlvRestrictionManagerTests.RemoveRestrictionsForObjects_TriggersRestrictionUpdatedEvent::test 318f1f4207b04d01076d3498aceea781c4889b05cdbef199cdbea43dde355f4c
|
||||
// pending-parity-case: LibreMetaverse.Tests/RegionScheduleTests.cs::RegionScheduleTests.GetRegionRestartScheduleAsync_WeeklySchedule_ParsesDaysAndTime::test 0f64aab66c6a6d807b3d2bbc46b636a85900e4f76e35d5e3dd8cd0d8b295618b
|
||||
// pending-parity-case: LibreMetaverse.Tests/RegionScheduleTests.cs::RegionScheduleTests.GetRegionRestartScheduleAsync_DailySchedule_ReturnsAllDays::test cd966b6e3ba470c91ac958bf6c71aeb34f4dab060ad5334cb6060e1954b5c6d0
|
||||
// pending-parity-case: LibreMetaverse.Tests/RegionScheduleTests.cs::RegionScheduleTests.GetRegionRestartScheduleAsync_NoRestartConfigured_ReturnsNull::test 59a4b050a79659ccaf0fff13b750d634d803ed7b9e4940cbad676c1bdc04a5fc
|
||||
// pending-parity-case: LibreMetaverse.Tests/RegionScheduleTests.cs::RegionScheduleTests.GetRegionRestartScheduleAsync_NoCapability_ReturnsNullWithoutRequest::test e169e7846874ed4309a50cb25b03c2e722a8d758a787654a5906610ab3b655f1
|
||||
// pending-parity-case: LibreMetaverse.Tests/RegionScheduleTests.cs::RegionScheduleTests.SetRegionRestartScheduleAsync_Weekly_PostsUppercaseDaysAndSeconds::test 153fc0ac84af549c1381d0814a356bf2d9e0ead2c879e503981193366943546c
|
||||
// pending-parity-case: LibreMetaverse.Tests/RegionScheduleTests.cs::RegionScheduleTests.SetRegionRestartScheduleAsync_DailyIgnoresDays_DoesNotPostDaysKey::test b51a1272465c3316194542eb346b2aa15c43fdc8474163ddd851b3f2204d1c2b
|
||||
// pending-parity-case: LibreMetaverse.Tests/RegionScheduleTests.cs::RegionScheduleTests.SetRegionRestartScheduleAsync_EmptyDaysClearsSchedule::test 57ef3c0f8d9eeac58a7d1b3e7dbc44413016f39303d304cacd3071bd2c55f320
|
||||
// pending-parity-case: LibreMetaverse.Tests/RegionScheduleTests.cs::RegionScheduleTests.SetRegionRestartScheduleAsync_NoCapability_ReturnsFalseWithoutRequest::test be03507fe574b9f7c7174c39af44b7b693e1b7a496845db46451ef09bf9db206
|
||||
// pending-parity-case: LibreMetaverse.Tests/RegionScheduleTests.cs::RegionScheduleTests.SetRegionRestartScheduleAsync_NonSuccessStatus_ReturnsFalse::test 16c8988d7aa15ea9f58deaa2e3f416b6115978e23073fd99749843f4f410dca4
|
||||
// pending-parity-case: LibreMetaverse.Tests/SimConsoleTests.cs::SimConsoleTests.SendSimConsoleCommandAsync_IgnoresPostBody_UsesSimConsoleResponseEvent::test df6eb48241f71c34074be66869c9ae1d5980186583259568728261b5eedd7c48
|
||||
// pending-parity-case: LibreMetaverse.Tests/SimConsoleTests.cs::SimConsoleTests.SendSimConsoleCommandAsync_NoResponseEvent_ReturnsNullAfterTimeout::test 2ac5a6c96f3acec341056387d727288fd3661565bd2a7c385078602efe8661da
|
||||
// pending-parity-case: LibreMetaverse.Tests/SimConsoleTests.cs::SimConsoleTests.SimConsoleResponseMessage_Deserialize_ReadsBodyField::test 4d367bc3fd012d1579847fd9837bf883c5ea95452776a086bbf856899d7c2099
|
||||
// pending-parity-case: LibreMetaverse.Tests/SlurlParserTests.cs::SlurlParserTests.ParseSimpleLocation_ParsesCorrectly::test 4ca1200596cd99959db205bd40050c9ed62ac68fcd58079d52882e3b24af3fdf
|
||||
// pending-parity-case: LibreMetaverse.Tests/SlurlParserTests.cs::SlurlParserTests.ParseSlurl_ParsesCorrectly::test b389e823a365884bb10813a587c5922416dc8d0737f36bfde99c56cc4e4accda
|
||||
// pending-parity-case: LibreMetaverse.Tests/SlurlParserTests.cs::SlurlParserTests.ParseSlurlWithTrailingSlash_ParsesCorrectly::test eb8513ad0d5dd9f67b537c1a844f738ef9363efdafd97aa31ec6fb697395c270
|
||||
// pending-parity-case: LibreMetaverse.Tests/SlurlParserTests.cs::SlurlParserTests.ParseLegacyUri_ParsesCorrectly::test d3e28edefeaa13a00d666cdc40c5ee60a24563462472786e0fa186262e8f6e73
|
||||
// pending-parity-case: LibreMetaverse.Tests/SlurlParserTests.cs::SlurlParserTests.ParseLocationWithDefaults_UsesDefaultCoordinates::test a89cceba86e86028cd70ee28b0f31a4c40c23491d582a0f70fc06b98bfeb3605
|
||||
// pending-parity-case: LibreMetaverse.Tests/SlurlParserTests.cs::SlurlParserTests.ParseLocationPartialCoordinates_UsesDefaults::test b6418ccbb2b00b741fcc92db7d0d8577e7334360934de7418f75ed08d7b3da24
|
||||
// pending-parity-case: LibreMetaverse.Tests/SlurlParserTests.cs::SlurlParserTests.ParseAgentSlapp_ParsesCorrectly::test 77a274bb3b4bf189fab0ce68a729057d04376bf3d6d45d0a5443d0f301f5fbb8
|
||||
// pending-parity-case: LibreMetaverse.Tests/SlurlParserTests.cs::SlurlParserTests.ParseGroupSlapp_ParsesCorrectly::test 5435e301f76398ff2f35e0b65a7055de6d42b1a4662936ee949005182511fcd6
|
||||
// pending-parity-case: LibreMetaverse.Tests/SlurlParserTests.cs::SlurlParserTests.ParseTeleportSlapp_ParsesLocationData::test 68eea168b7480f125a4bff20b582af87c0f6d62502821bf57eb734b12f87eed5
|
||||
// pending-parity-case: LibreMetaverse.Tests/SlurlParserTests.cs::SlurlParserTests.ParseWorldMapSlapp_ParsesLocationData::test ad7f5ce07a837501fa74dda643f1c0d278a2f51fe27330d3419c57683127bf9e
|
||||
// pending-parity-case: LibreMetaverse.Tests/SlurlParserTests.cs::SlurlParserTests.ParseLoginSlapp_ParsesQueryParameters::test a0622607f53b8c19348540e7b858d3c75be22b47b9afc92505121b3430c33550
|
||||
// pending-parity-case: LibreMetaverse.Tests/SlurlParserTests.cs::SlurlParserTests.ParseObjectImSlapp_ParsesQueryParameters::test af9c2bdcfb212f08618719c85da41938207b6978fe2042a3c4451f7fd0075d6f
|
||||
// pending-parity-case: LibreMetaverse.Tests/SlurlParserTests.cs::SlurlParserTests.ParseSearchSlapp_ParsesCorrectly::test a77776e74cff175bde3e974344502369e679db15f45fe5c0d614c80732549765
|
||||
// pending-parity-case: LibreMetaverse.Tests/SlurlParserTests.cs::SlurlParserTests.GetRawLocation_ReturnsCorrectFormat::test 30dafa3972780bbbb07f1edaf55ed4bc3b01080e616588768ebef9df54678af3
|
||||
// pending-parity-case: LibreMetaverse.Tests/SlurlParserTests.cs::SlurlParserTests.GetSlurl_ReturnsCorrectFormat::test 1e6b6fef442eab1ca6874df75f1a0ea380ec7f25974979d3cd878e10fc49fb40
|
||||
// pending-parity-case: LibreMetaverse.Tests/SlurlParserTests.cs::SlurlParserTests.GetStartLocationUri_ReturnsCorrectFormat::test c7cc2d49e52ed6ebb19e09607a2b191fb3835e8f3804c7b07c5c9e8fd3b9bcae
|
||||
// pending-parity-case: LibreMetaverse.Tests/SlurlParserTests.cs::SlurlParserTests.GetAgentUrl_GeneratesCorrectUrl::test b656f795ce39c9bc50df167e20e23b76b57929feaad1756d3190920f5410d0d4
|
||||
// pending-parity-case: LibreMetaverse.Tests/SlurlParserTests.cs::SlurlParserTests.GetAgentUrl_DefaultAction_UsesAbout::test 642b0543f72427cf646bcb8445b9acff4c1fdb0d26ef3f0dc6c10eaaed73028b
|
||||
// pending-parity-case: LibreMetaverse.Tests/SlurlParserTests.cs::SlurlParserTests.GetGroupUrl_GeneratesCorrectUrl::test 919cc7a17770fb65a83812836819a19d6dd4e630a848741d12df868da3d949d5
|
||||
// pending-parity-case: LibreMetaverse.Tests/SlurlParserTests.cs::SlurlParserTests.GetTeleportUrl_GeneratesCorrectUrl::test 3465edd1ecdd6e521c52687570d32e288bfa29eb6e47666305c64ee5322df159
|
||||
// pending-parity-case: LibreMetaverse.Tests/SlurlParserTests.cs::SlurlParserTests.GetTeleportUrl_WithDefaults_UsesDefaultCoordinates::test 823d524cc81d39753549583346953122c372f5575aa03d8bf101d1be3eae845d
|
||||
// pending-parity-case: LibreMetaverse.Tests/SlurlParserTests.cs::SlurlParserTests.GetWorldMapUrl_GeneratesCorrectUrl::test 7c19a936e0d641195f3806291b5b88970affa46f540ef950d55df709b52ad56b
|
||||
// pending-parity-case: LibreMetaverse.Tests/SlurlParserTests.cs::SlurlParserTests.GetObjectImUrl_GeneratesCorrectUrl::test edf724227cc86abc84d223637f34c607f9fc30f9e85b53a9ec8c8f2d2b7bcbf6
|
||||
// pending-parity-case: LibreMetaverse.Tests/SlurlParserTests.cs::SlurlParserTests.GetObjectImUrl_NotGroupOwned_OmitsGroupOwnedParameter::test 764978a618429216a0bfef4e72ac44a329d2b2d1c5b13af889db9cf86814cd99
|
||||
// pending-parity-case: LibreMetaverse.Tests/SlurlParserTests.cs::SlurlParserTests.GetSearchUrl_GeneratesCorrectUrl::test aeb79bf4e5e51368b4520eec3cc5beeb767101b81f1eaa3f3ad118749dc5c2f0
|
||||
// pending-parity-case: LibreMetaverse.Tests/SlurlParserTests.cs::SlurlParserTests.GetLoginUrl_WithAllParameters_GeneratesCorrectUrl::test 0d9dc8d623e56ec1e8e0d414eb2c898bfd7ee37712972287834c2df6a99da17c
|
||||
// pending-parity-case: LibreMetaverse.Tests/SlurlParserTests.cs::SlurlParserTests.GetLoginUrl_WithNoParameters_GeneratesBaseUrl::test 1fcfa164861bcc115f2935f1c20c276dea05802cf35dbb55664ff1c36140c135
|
||||
// pending-parity-case: LibreMetaverse.Tests/SlurlParserTests.cs::SlurlParserTests.GetSlappUrl_WithQueryParams_GeneratesCorrectUrl::test 37ca9ebe06ce42f5919d9b6ec30459d1455f78bde910a61d04187e74e7ce3d07
|
||||
// pending-parity-case: LibreMetaverse.Tests/SlurlParserTests.cs::SlurlParserTests.ParseNull_ThrowsArgumentNullException::test 98c170ff5f03f843918c0d2aecddb23e2c2605e31100f5d3178ad7cb306eef5d
|
||||
// pending-parity-case: LibreMetaverse.Tests/SlurlParserTests.cs::SlurlParserTests.ParseEmptyString_ThrowsArgumentException::test a5d89e3349033fa4efa1b00339556d811f175c52ca5b183a2d19b247a8eaeed8
|
||||
// pending-parity-case: LibreMetaverse.Tests/SlurlParserTests.cs::SlurlParserTests.ParseUrlEncodedQueryParams_DecodesCorrectly::test 72ac64c89f3a08bbecfb80aaaf11f5ee59a383eeeb9578676af5b9d83f374cc4
|
||||
// pending-parity-case: LibreMetaverse.Tests/SlurlParserTests.cs::SlurlParserTests.RoundTripLocation_PreservesData::test 2cba174b3609af177295b469bad1641a98d8dc79d95aa4ef22403923edd4d092
|
||||
// pending-parity-case: LibreMetaverse.Tests/SlurlParserTests.cs::SlurlParserTests.ParseAllSlappCommands_RecognizesCorrectly::test abf53480da20d1ff57f5f06f1433c120ea84e0d6d5363cb33e4a275d76cfa306
|
||||
// pending-parity-case: LibreMetaverse.Tests/StartAuctionTests.cs::StartAuctionTests.ViewerStartAuctionPacket_RoundTripsAgentAndParcelFields::test f37ef06cfba37754effe04a0bb0edfa159c761b811a05efd95157896756bef16
|
||||
// pending-parity-case: LibreMetaverse.Tests/StartAuctionTests.cs::StartAuctionTests.StartAuction_DoesNotThrow::test deec194333b480dabb3f6e6d96b360a29d11a40ca1103117fc7ce5cdb80d6eb0
|
||||
// pending-parity-case: LibreMetaverse.Tests/TextureEntryTests.cs::TextureEntryTests.RoundTrip_HighFace_TextureID_IsPreserved::case:d3ad6116f2458248 5f215cd1c50fa8871967653b4667f848c14ff24a3b71906e51aac13c56de1f55
|
||||
// pending-parity-case: LibreMetaverse.Tests/TextureEntryTests.cs::TextureEntryTests.RoundTrip_HighFace_TextureID_IsPreserved::case:c6f3ac57944a5314 5f215cd1c50fa8871967653b4667f848c14ff24a3b71906e51aac13c56de1f55
|
||||
// pending-parity-case: LibreMetaverse.Tests/TextureEntryTests.cs::TextureEntryTests.RoundTrip_HighFace_TextureID_IsPreserved::case:d59eced1ded07f84 5f215cd1c50fa8871967653b4667f848c14ff24a3b71906e51aac13c56de1f55
|
||||
// pending-parity-case: LibreMetaverse.Tests/TextureEntryTests.cs::TextureEntryTests.RoundTrip_HighFace_TextureID_IsPreserved::case:59df3d13bd106053 5f215cd1c50fa8871967653b4667f848c14ff24a3b71906e51aac13c56de1f55
|
||||
// pending-parity-case: LibreMetaverse.Tests/TextureEntryTests.cs::TextureEntryTests.RoundTrip_AllHighFaces_TextureIDs_AllPreserved::test 203ca43b9f1965e1fae7feb36e84eff1df9ac5968eb23753077816d16dd24228
|
||||
// pending-parity-case: LibreMetaverse.Tests/TextureEntryTests.cs::TextureEntryTests.RoundTrip_LowAndHighFaces_BothPreserved::test dd520cac107415a186a44eb3a17bd000f933ec49b814a496e6788237fcfffb1e
|
||||
// pending-parity-case: LibreMetaverse.Tests/TextureEntryTests.cs::TextureEntryTests.RoundTrip_Face32_RGBA_IsPreserved::test db41d130d270d31f52f3928df88ccc052102673c1afbca03cc0648526fafbabb
|
||||
// pending-parity-case: LibreMetaverse.Tests/TextureEntryTests.cs::TextureEntryTests.RoundTrip_Face32_RepeatU_IsPreserved::test 58e80815263025ec54cd15e3c9a42771f5e55c81e9acb212a0f163faef9fd499
|
||||
// pending-parity-case: LibreMetaverse.Tests/TextureEntryTests.cs::TextureEntryTests.RoundTrip_Face32_RepeatV_IsPreserved::test fbeb1fdd584a26576b6f1ba653b2995d1a6d6bccc2c1dc51e46aa9f211b78724
|
||||
// pending-parity-case: LibreMetaverse.Tests/TextureEntryTests.cs::TextureEntryTests.RoundTrip_AllFaces_TextureIDs_AllPreserved::test 5e5a390af8deff77ef80f751735456541f24d7e27666557d50d99065cc3ba6a4
|
||||
|
||||
441
tests/compat/tests/slurl_semantics.rs
Normal file
441
tests/compat/tests/slurl_semantics.rs
Normal file
@@ -0,0 +1,441 @@
|
||||
// Exact Rust translation of LibreMetaverse.Tests/SlurlParserTests.cs.
|
||||
// Source SHA-256: 3626ff6fae5a303e4037ac2b5742dfc7fa226e04a33b8d358ba355fccdd05611
|
||||
|
||||
use libremetaverse::{Error, SlappCommand, SlurlParser, ViewerUriType};
|
||||
use libremetaverse_types::UUID;
|
||||
use std::collections::HashMap;
|
||||
|
||||
fn uuid() -> UUID {
|
||||
UUID::random().expect("UUID Random")
|
||||
}
|
||||
|
||||
fn parse(location: &str) -> SlurlParser {
|
||||
SlurlParser::new(Some(location.into())).expect("SlurlParser constructor")
|
||||
}
|
||||
|
||||
fn assert_location(parser: &SlurlParser, sim: &str, x: i32, y: i32, z: i32) {
|
||||
assert_eq!(parser.sim(), sim);
|
||||
assert_eq!(parser.x(), x);
|
||||
assert_eq!(parser.y(), y);
|
||||
assert_eq!(parser.z(), z);
|
||||
}
|
||||
|
||||
// parity-case: LibreMetaverse.Tests/SlurlParserTests.cs::SlurlParserTests.ParseSimpleLocation_ParsesCorrectly::test 4ca1200596cd99959db205bd40050c9ed62ac68fcd58079d52882e3b24af3fdf translated
|
||||
#[test]
|
||||
fn parse_simple_location_parses_correctly() {
|
||||
let parser = parse("Hooper/128/128/32");
|
||||
assert_location(&parser, "Hooper", 128, 128, 32);
|
||||
assert_eq!(parser.uri_type(), ViewerUriType::Location);
|
||||
assert!(parser.is_location());
|
||||
assert!(!parser.is_application());
|
||||
}
|
||||
|
||||
// parity-case: LibreMetaverse.Tests/SlurlParserTests.cs::SlurlParserTests.ParseSlurl_ParsesCorrectly::test b389e823a365884bb10813a587c5922416dc8d0737f36bfde99c56cc4e4accda translated
|
||||
#[test]
|
||||
fn parse_slurl_parses_correctly() {
|
||||
let parser = parse("secondlife://Hooper/179/18/32");
|
||||
assert_location(&parser, "Hooper", 179, 18, 32);
|
||||
assert_eq!(parser.uri_type(), ViewerUriType::Location);
|
||||
}
|
||||
|
||||
// parity-case: LibreMetaverse.Tests/SlurlParserTests.cs::SlurlParserTests.ParseSlurlWithTrailingSlash_ParsesCorrectly::test eb8513ad0d5dd9f67b537c1a844f738ef9363efdafd97aa31ec6fb697395c270 translated
|
||||
#[test]
|
||||
fn parse_slurl_with_trailing_slash_parses_correctly() {
|
||||
let parser = parse("secondlife://Hooper/179/18/32/");
|
||||
assert_eq!(
|
||||
(parser.sim(), parser.x(), parser.y(), parser.z()),
|
||||
("Hooper".into(), 179, 18, 32)
|
||||
);
|
||||
}
|
||||
|
||||
// parity-case: LibreMetaverse.Tests/SlurlParserTests.cs::SlurlParserTests.ParseLegacyUri_ParsesCorrectly::test d3e28edefeaa13a00d666cdc40c5ee60a24563462472786e0fa186262e8f6e73 translated
|
||||
#[test]
|
||||
fn parse_legacy_uri_parses_correctly() {
|
||||
let parser = parse("uri:Hooper&179&18&32");
|
||||
assert_location(&parser, "Hooper", 179, 18, 32);
|
||||
assert_eq!(parser.uri_type(), ViewerUriType::Location);
|
||||
}
|
||||
|
||||
// parity-case: LibreMetaverse.Tests/SlurlParserTests.cs::SlurlParserTests.ParseLocationWithDefaults_UsesDefaultCoordinates::test a89cceba86e86028cd70ee28b0f31a4c40c23491d582a0f70fc06b98bfeb3605 translated
|
||||
#[test]
|
||||
fn parse_location_with_defaults_uses_default_coordinates() {
|
||||
let parser = parse("secondlife://Hooper");
|
||||
assert_eq!(
|
||||
(parser.sim(), parser.x(), parser.y(), parser.z()),
|
||||
("Hooper".into(), 128, 128, 0)
|
||||
);
|
||||
}
|
||||
|
||||
// parity-case: LibreMetaverse.Tests/SlurlParserTests.cs::SlurlParserTests.ParseLocationPartialCoordinates_UsesDefaults::test b6418ccbb2b00b741fcc92db7d0d8577e7334360934de7418f75ed08d7b3da24 translated
|
||||
#[test]
|
||||
fn parse_location_partial_coordinates_uses_defaults() {
|
||||
let parser = parse("secondlife://Hooper/100");
|
||||
assert_eq!(
|
||||
(parser.sim(), parser.x(), parser.y(), parser.z()),
|
||||
("Hooper".into(), 100, 128, 0)
|
||||
);
|
||||
}
|
||||
|
||||
// parity-case: LibreMetaverse.Tests/SlurlParserTests.cs::SlurlParserTests.ParseAgentSlapp_ParsesCorrectly::test 77a274bb3b4bf189fab0ce68a729057d04376bf3d6d45d0a5443d0f301f5fbb8 translated
|
||||
#[test]
|
||||
fn parse_agent_slapp_parses_correctly() {
|
||||
let id = uuid();
|
||||
let id_text = id.to_string();
|
||||
let parser = parse(&format!("secondlife:///app/agent/{id_text}/about"));
|
||||
assert_eq!(parser.uri_type(), ViewerUriType::Application);
|
||||
assert_eq!(parser.command(), SlappCommand::Agent);
|
||||
assert_eq!(parser.command_path(), format!("agent/{id_text}/about"));
|
||||
assert!(parser.is_application());
|
||||
assert!(!parser.is_location());
|
||||
}
|
||||
|
||||
// parity-case: LibreMetaverse.Tests/SlurlParserTests.cs::SlurlParserTests.ParseGroupSlapp_ParsesCorrectly::test 5435e301f76398ff2f35e0b65a7055de6d42b1a4662936ee949005182511fcd6 translated
|
||||
#[test]
|
||||
fn parse_group_slapp_parses_correctly() {
|
||||
let id = uuid();
|
||||
let id_text = id.to_string();
|
||||
let parser = parse(&format!("secondlife:///app/group/{id_text}/about"));
|
||||
assert_eq!(parser.uri_type(), ViewerUriType::Application);
|
||||
assert_eq!(parser.command(), SlappCommand::Group);
|
||||
assert_eq!(parser.command_path(), format!("group/{id_text}/about"));
|
||||
}
|
||||
|
||||
// parity-case: LibreMetaverse.Tests/SlurlParserTests.cs::SlurlParserTests.ParseTeleportSlapp_ParsesLocationData::test 68eea168b7480f125a4bff20b582af87c0f6d62502821bf57eb734b12f87eed5 translated
|
||||
#[test]
|
||||
fn parse_teleport_slapp_parses_location_data() {
|
||||
let parser = parse("secondlife:///app/teleport/Hooper/100/200/50");
|
||||
assert_eq!(parser.uri_type(), ViewerUriType::Application);
|
||||
assert_eq!(parser.command(), SlappCommand::Teleport);
|
||||
assert_location(&parser, "Hooper", 100, 200, 50);
|
||||
}
|
||||
|
||||
// parity-case: LibreMetaverse.Tests/SlurlParserTests.cs::SlurlParserTests.ParseWorldMapSlapp_ParsesLocationData::test ad7f5ce07a837501fa74dda643f1c0d278a2f51fe27330d3419c57683127bf9e translated
|
||||
#[test]
|
||||
fn parse_world_map_slapp_parses_location_data() {
|
||||
let parser = parse("secondlife:///app/worldmap/Sandbox/128/128/0");
|
||||
assert_eq!(parser.uri_type(), ViewerUriType::Application);
|
||||
assert_eq!(parser.command(), SlappCommand::WorldMap);
|
||||
assert_location(&parser, "Sandbox", 128, 128, 0);
|
||||
}
|
||||
|
||||
// parity-case: LibreMetaverse.Tests/SlurlParserTests.cs::SlurlParserTests.ParseLoginSlapp_ParsesQueryParameters::test a0622607f53b8c19348540e7b858d3c75be22b47b9afc92505121b3430c33550 translated
|
||||
#[test]
|
||||
fn parse_login_slapp_parses_query_parameters() {
|
||||
let parser = parse("secondlife:///app/login?last=Resident&session=abc123&location=home");
|
||||
assert_eq!(parser.uri_type(), ViewerUriType::Application);
|
||||
assert_eq!(parser.command(), SlappCommand::Login);
|
||||
let query = parser.query_parameters();
|
||||
assert_eq!(query.get("last").map(String::as_str), Some("Resident"));
|
||||
assert_eq!(query.get("session").map(String::as_str), Some("abc123"));
|
||||
assert_eq!(query.get("location").map(String::as_str), Some("home"));
|
||||
}
|
||||
|
||||
// parity-case: LibreMetaverse.Tests/SlurlParserTests.cs::SlurlParserTests.ParseObjectImSlapp_ParsesQueryParameters::test af9c2bdcfb212f08618719c85da41938207b6978fe2042a3c4451f7fd0075d6f translated
|
||||
#[test]
|
||||
fn parse_object_im_slapp_parses_query_parameters() {
|
||||
let object = uuid();
|
||||
let owner = uuid();
|
||||
let object_text = object.to_string();
|
||||
let owner_text = owner.to_string();
|
||||
let parser = parse(&format!(
|
||||
"secondlife:///app/objectim/{object_text}?name=TestObject&owner={owner_text}&groupowned=true&slurl=Hooper/128/128/25"
|
||||
));
|
||||
let query = parser.query_parameters();
|
||||
assert_eq!(parser.command(), SlappCommand::ObjectIm);
|
||||
assert_eq!(query.get("name").map(String::as_str), Some("TestObject"));
|
||||
assert_eq!(query.get("owner"), Some(&owner.to_string()));
|
||||
assert_eq!(query.get("groupowned").map(String::as_str), Some("true"));
|
||||
assert_eq!(
|
||||
query.get("slurl").map(String::as_str),
|
||||
Some("Hooper/128/128/25")
|
||||
);
|
||||
}
|
||||
|
||||
// parity-case: LibreMetaverse.Tests/SlurlParserTests.cs::SlurlParserTests.ParseSearchSlapp_ParsesCorrectly::test a77776e74cff175bde3e974344502369e679db15f45fe5c0d614c80732549765 translated
|
||||
#[test]
|
||||
fn parse_search_slapp_parses_correctly() {
|
||||
let parser = parse("secondlife:///app/search/places/Sandbox");
|
||||
assert_eq!(parser.command(), SlappCommand::Search);
|
||||
assert!(parser.command_path().contains("places"));
|
||||
assert!(parser.command_path().contains("Sandbox"));
|
||||
}
|
||||
|
||||
// parity-case: LibreMetaverse.Tests/SlurlParserTests.cs::SlurlParserTests.GetRawLocation_ReturnsCorrectFormat::test 30dafa3972780bbbb07f1edaf55ed4bc3b01080e616588768ebef9df54678af3 translated
|
||||
#[test]
|
||||
fn get_raw_location_returns_correct_format() {
|
||||
assert_eq!(
|
||||
parse("Hooper/100/200/50").get_raw_location().unwrap(),
|
||||
"Hooper/100/200/50"
|
||||
);
|
||||
}
|
||||
|
||||
// parity-case: LibreMetaverse.Tests/SlurlParserTests.cs::SlurlParserTests.GetSlurl_ReturnsCorrectFormat::test 1e6b6fef442eab1ca6874df75f1a0ea380ec7f25974979d3cd878e10fc49fb40 translated
|
||||
#[test]
|
||||
fn get_slurl_returns_correct_format() {
|
||||
assert_eq!(
|
||||
parse("Hooper/100/200/50").get_slurl().unwrap(),
|
||||
"secondlife://Hooper/100/200/50/"
|
||||
);
|
||||
}
|
||||
|
||||
// parity-case: LibreMetaverse.Tests/SlurlParserTests.cs::SlurlParserTests.GetStartLocationUri_ReturnsCorrectFormat::test c7cc2d49e52ed6ebb19e09607a2b191fb3835e8f3804c7b07c5c9e8fd3b9bcae translated
|
||||
#[test]
|
||||
fn get_start_location_uri_returns_correct_format() {
|
||||
assert_eq!(
|
||||
parse("Hooper/100/200/50").get_start_location_uri().unwrap(),
|
||||
"uri:Hooper&100&200&50"
|
||||
);
|
||||
}
|
||||
|
||||
// parity-case: LibreMetaverse.Tests/SlurlParserTests.cs::SlurlParserTests.GetAgentUrl_GeneratesCorrectUrl::test b656f795ce39c9bc50df167e20e23b76b57929feaad1756d3190920f5410d0d4 translated
|
||||
#[test]
|
||||
fn get_agent_url_generates_correct_url() {
|
||||
let id = uuid();
|
||||
let id_text = id.to_string();
|
||||
assert_eq!(
|
||||
SlurlParser::get_agent_url(id, Some("inspect".into())).unwrap(),
|
||||
format!("secondlife:///app/agent/{id_text}/inspect")
|
||||
);
|
||||
}
|
||||
|
||||
// parity-case: LibreMetaverse.Tests/SlurlParserTests.cs::SlurlParserTests.GetAgentUrl_DefaultAction_UsesAbout::test 642b0543f72427cf646bcb8445b9acff4c1fdb0d26ef3f0dc6c10eaaed73028b translated
|
||||
#[test]
|
||||
fn get_agent_url_default_action_uses_about() {
|
||||
assert!(
|
||||
SlurlParser::get_agent_url(uuid(), None)
|
||||
.unwrap()
|
||||
.contains("/about")
|
||||
);
|
||||
}
|
||||
|
||||
// parity-case: LibreMetaverse.Tests/SlurlParserTests.cs::SlurlParserTests.GetGroupUrl_GeneratesCorrectUrl::test 919cc7a17770fb65a83812836819a19d6dd4e630a848741d12df868da3d949d5 translated
|
||||
#[test]
|
||||
fn get_group_url_generates_correct_url() {
|
||||
let id = uuid();
|
||||
let id_text = id.to_string();
|
||||
assert_eq!(
|
||||
SlurlParser::get_group_url(id, Some("inspect".into())).unwrap(),
|
||||
format!("secondlife:///app/group/{id_text}/inspect")
|
||||
);
|
||||
}
|
||||
|
||||
// parity-case: LibreMetaverse.Tests/SlurlParserTests.cs::SlurlParserTests.GetTeleportUrl_GeneratesCorrectUrl::test 3465edd1ecdd6e521c52687570d32e288bfa29eb6e47666305c64ee5322df159 translated
|
||||
#[test]
|
||||
fn get_teleport_url_generates_correct_url() {
|
||||
assert_eq!(
|
||||
SlurlParser::get_teleport_url("Hooper".into(), Some(100), Some(200), Some(50)).unwrap(),
|
||||
"secondlife:///app/teleport/Hooper/100/200/50"
|
||||
);
|
||||
}
|
||||
|
||||
// parity-case: LibreMetaverse.Tests/SlurlParserTests.cs::SlurlParserTests.GetTeleportUrl_WithDefaults_UsesDefaultCoordinates::test 823d524cc81d39753549583346953122c372f5575aa03d8bf101d1be3eae845d translated
|
||||
#[test]
|
||||
fn get_teleport_url_with_defaults_uses_default_coordinates() {
|
||||
assert_eq!(
|
||||
SlurlParser::get_teleport_url("Hooper".into(), None, None, None).unwrap(),
|
||||
"secondlife:///app/teleport/Hooper/128/128/0"
|
||||
);
|
||||
}
|
||||
|
||||
// parity-case: LibreMetaverse.Tests/SlurlParserTests.cs::SlurlParserTests.GetWorldMapUrl_GeneratesCorrectUrl::test 7c19a936e0d641195f3806291b5b88970affa46f540ef950d55df709b52ad56b translated
|
||||
#[test]
|
||||
fn get_world_map_url_generates_correct_url() {
|
||||
assert_eq!(
|
||||
SlurlParser::get_world_map_url("Sandbox".into(), Some(64), Some(64), Some(100)).unwrap(),
|
||||
"secondlife:///app/worldmap/Sandbox/64/64/100"
|
||||
);
|
||||
}
|
||||
|
||||
// parity-case: LibreMetaverse.Tests/SlurlParserTests.cs::SlurlParserTests.GetObjectImUrl_GeneratesCorrectUrl::test edf724227cc86abc84d223637f34c607f9fc30f9e85b53a9ec8c8f2d2b7bcbf6 translated
|
||||
#[test]
|
||||
fn get_object_im_url_generates_correct_url() {
|
||||
let object = uuid();
|
||||
let owner = uuid();
|
||||
let object_text = object.to_string();
|
||||
let owner_text = owner.to_string();
|
||||
let url = SlurlParser::get_object_im_url(
|
||||
object,
|
||||
"Test Object".into(),
|
||||
owner,
|
||||
true,
|
||||
"Hooper/128/128/25".into(),
|
||||
)
|
||||
.unwrap();
|
||||
assert!(url.contains(&format!("objectim/{object_text}")));
|
||||
assert!(url.contains("name=Test%20Object"));
|
||||
assert!(url.contains(&format!("owner={owner_text}")));
|
||||
assert!(url.contains("groupowned=true"));
|
||||
assert!(url.contains("slurl=Hooper"));
|
||||
}
|
||||
|
||||
// parity-case: LibreMetaverse.Tests/SlurlParserTests.cs::SlurlParserTests.GetObjectImUrl_NotGroupOwned_OmitsGroupOwnedParameter::test 764978a618429216a0bfef4e72ac44a329d2b2d1c5b13af889db9cf86814cd99 translated
|
||||
#[test]
|
||||
fn get_object_im_url_not_group_owned_omits_group_owned_parameter() {
|
||||
let url = SlurlParser::get_object_im_url(
|
||||
uuid(),
|
||||
"Test Object".into(),
|
||||
uuid(),
|
||||
false,
|
||||
"Hooper/128/128/25".into(),
|
||||
)
|
||||
.unwrap();
|
||||
assert!(!url.contains("groupowned"));
|
||||
}
|
||||
|
||||
// parity-case: LibreMetaverse.Tests/SlurlParserTests.cs::SlurlParserTests.GetSearchUrl_GeneratesCorrectUrl::test aeb79bf4e5e51368b4520eec3cc5beeb767101b81f1eaa3f3ad118749dc5c2f0 translated
|
||||
#[test]
|
||||
fn get_search_url_generates_correct_url() {
|
||||
assert_eq!(
|
||||
SlurlParser::get_search_url("places".into(), "sandbox island".into()).unwrap(),
|
||||
"secondlife:///app/search/places/sandbox%20island"
|
||||
);
|
||||
}
|
||||
|
||||
// parity-case: LibreMetaverse.Tests/SlurlParserTests.cs::SlurlParserTests.GetLoginUrl_WithAllParameters_GeneratesCorrectUrl::test 0d9dc8d623e56ec1e8e0d414eb2c898bfd7ee37712972287834c2df6a99da17c translated
|
||||
#[test]
|
||||
fn get_login_url_with_all_parameters_generates_correct_url() {
|
||||
let url = SlurlParser::get_login_url(
|
||||
Some("Resident".into()),
|
||||
Some("session123".into()),
|
||||
Some("home".into()),
|
||||
)
|
||||
.unwrap();
|
||||
assert!(url.contains("login?"));
|
||||
assert!(url.contains("last=Resident"));
|
||||
assert!(url.contains("session=session123"));
|
||||
assert!(url.contains("location=home"));
|
||||
}
|
||||
|
||||
// parity-case: LibreMetaverse.Tests/SlurlParserTests.cs::SlurlParserTests.GetLoginUrl_WithNoParameters_GeneratesBaseUrl::test 1fcfa164861bcc115f2935f1c20c276dea05802cf35dbb55664ff1c36140c135 translated
|
||||
#[test]
|
||||
fn get_login_url_with_no_parameters_generates_base_url() {
|
||||
assert_eq!(
|
||||
SlurlParser::get_login_url(None, None, None).unwrap(),
|
||||
"secondlife:///app/login"
|
||||
);
|
||||
}
|
||||
|
||||
// parity-case: LibreMetaverse.Tests/SlurlParserTests.cs::SlurlParserTests.GetSlappUrl_WithQueryParams_GeneratesCorrectUrl::test 37ca9ebe06ce42f5919d9b6ec30459d1455f78bde910a61d04187e74e7ce3d07 translated
|
||||
#[test]
|
||||
fn get_slapp_url_with_query_params_generates_correct_url() {
|
||||
let query = HashMap::from([
|
||||
("test".into(), "value".into()),
|
||||
("foo".into(), "bar".into()),
|
||||
]);
|
||||
let url =
|
||||
SlurlParser::get_slapp_url(SlappCommand::Help, Some("topic".into()), Some(query)).unwrap();
|
||||
assert!(url.contains("help/topic"));
|
||||
assert!(url.contains("test=value"));
|
||||
assert!(url.contains("foo=bar"));
|
||||
}
|
||||
|
||||
// parity-case: LibreMetaverse.Tests/SlurlParserTests.cs::SlurlParserTests.ParseNull_ThrowsArgumentNullException::test 98c170ff5f03f843918c0d2aecddb23e2c2605e31100f5d3178ad7cb306eef5d translated
|
||||
#[test]
|
||||
fn parse_null_throws_argument_null() {
|
||||
match SlurlParser::new(None) {
|
||||
Err(error) => assert_eq!(error, Error::ArgumentNull),
|
||||
Ok(_) => panic!("expected ArgumentNull"),
|
||||
}
|
||||
}
|
||||
|
||||
// parity-case: LibreMetaverse.Tests/SlurlParserTests.cs::SlurlParserTests.ParseEmptyString_ThrowsArgumentException::test a5d89e3349033fa4efa1b00339556d811f175c52ca5b183a2d19b247a8eaeed8 translated
|
||||
#[test]
|
||||
fn parse_empty_string_throws_argument() {
|
||||
match SlurlParser::new(Some(String::new())) {
|
||||
Err(error) => assert_eq!(error, Error::Argument),
|
||||
Ok(_) => panic!("expected Argument"),
|
||||
}
|
||||
}
|
||||
|
||||
// parity-case: LibreMetaverse.Tests/SlurlParserTests.cs::SlurlParserTests.ParseUrlEncodedQueryParams_DecodesCorrectly::test 72ac64c89f3a08bbecfb80aaaf11f5ee59a383eeeb9578676af5b9d83f374cc4 translated
|
||||
#[test]
|
||||
fn parse_url_encoded_query_params_decodes_correctly() {
|
||||
assert!(
|
||||
parse("secondlife:///app/search/places/sandbox%20island")
|
||||
.command_path()
|
||||
.contains("sandbox%20island")
|
||||
);
|
||||
}
|
||||
|
||||
// parity-case: LibreMetaverse.Tests/SlurlParserTests.cs::SlurlParserTests.RoundTripLocation_PreservesData::test 2cba174b3609af177295b469bad1641a98d8dc79d95aa4ef22403923edd4d092 translated
|
||||
#[test]
|
||||
fn round_trip_location_preserves_data() {
|
||||
let original = parse("Hooper/100/200/50");
|
||||
let parsed = parse(&original.get_slurl().unwrap());
|
||||
assert_location(
|
||||
&parsed,
|
||||
&original.sim(),
|
||||
original.x(),
|
||||
original.y(),
|
||||
original.z(),
|
||||
);
|
||||
}
|
||||
|
||||
// parity-case: LibreMetaverse.Tests/SlurlParserTests.cs::SlurlParserTests.ParseAllSlappCommands_RecognizesCorrectly::test abf53480da20d1ff57f5f06f1433c120ea84e0d6d5363cb33e4a275d76cfa306 translated
|
||||
#[test]
|
||||
fn parse_all_slapp_commands_recognizes_correctly() {
|
||||
let commands = [
|
||||
("secondlife:///app/agent/uuid/about", SlappCommand::Agent),
|
||||
(
|
||||
"secondlife:///app/appearance/show",
|
||||
SlappCommand::Appearance,
|
||||
),
|
||||
("secondlife:///app/balance/request", SlappCommand::Balance),
|
||||
("secondlife:///app/chat/1/hello", SlappCommand::Chat),
|
||||
(
|
||||
"secondlife:///app/classified/uuid/about",
|
||||
SlappCommand::Classified,
|
||||
),
|
||||
("secondlife:///app/event/uuid/about", SlappCommand::Event),
|
||||
(
|
||||
"secondlife:///app/experience/uuid/profile",
|
||||
SlappCommand::Experience,
|
||||
),
|
||||
("secondlife:///app/group/uuid/about", SlappCommand::Group),
|
||||
("secondlife:///app/help/search", SlappCommand::Help),
|
||||
(
|
||||
"secondlife:///app/inventory/uuid/select",
|
||||
SlappCommand::Inventory,
|
||||
),
|
||||
(
|
||||
"secondlife:///app/keybinding/jump",
|
||||
SlappCommand::Keybinding,
|
||||
),
|
||||
("secondlife:///app/login", SlappCommand::Login),
|
||||
(
|
||||
"secondlife:///app/maptrackavatar/uuid",
|
||||
SlappCommand::MapTrackAvatar,
|
||||
),
|
||||
("secondlife:///app/objectim/uuid", SlappCommand::ObjectIm),
|
||||
(
|
||||
"secondlife:///app/openfloater/preferences",
|
||||
SlappCommand::OpenFloater,
|
||||
),
|
||||
("secondlife:///app/parcel/uuid/about", SlappCommand::Parcel),
|
||||
("secondlife:///app/region/uuid/about", SlappCommand::Region),
|
||||
("secondlife:///app/search/all/test", SlappCommand::Search),
|
||||
(
|
||||
"secondlife:///app/sharewithavatar/uuid",
|
||||
SlappCommand::ShareWithAvatar,
|
||||
),
|
||||
(
|
||||
"secondlife:///app/teleport/Hooper/128/128/0",
|
||||
SlappCommand::Teleport,
|
||||
),
|
||||
(
|
||||
"secondlife:///app/voicecallavatar/uuid",
|
||||
SlappCommand::VoiceCallAvatar,
|
||||
),
|
||||
(
|
||||
"secondlife:///app/wear_folder/?folder_id=uuid",
|
||||
SlappCommand::WearFolder,
|
||||
),
|
||||
(
|
||||
"secondlife:///app/worldmap/Hooper/128/128/0",
|
||||
SlappCommand::WorldMap,
|
||||
),
|
||||
];
|
||||
for (url, expected) in commands {
|
||||
assert_eq!(parse(url).command(), expected, "failed to parse {url}");
|
||||
}
|
||||
}
|
||||
489
tests/compat/tests/world_capability_semantics.rs
Normal file
489
tests/compat/tests/world_capability_semantics.rs
Normal file
@@ -0,0 +1,489 @@
|
||||
// Exact Rust translations of world capability tests owned by milestone issue #23.
|
||||
// Source SHA-256: f83be0075683edda91f8e345661b2f753d81c134585f38ddd52b8b9b9e406089
|
||||
// Source SHA-256: 79483c67d93295f09d281ec577f642d4967e281f88e531b2b43ee14c1444a440
|
||||
// Source SHA-256: 1ef332ad434b9bdc468282eae99150393950db352a98f5f822517fa48021222f
|
||||
// Source SHA-256: e49de5d4d588aa944bc27eeecd9921891b851eaecb76270abcec91f649579f7b
|
||||
|
||||
use libremetaverse::messages::linden::{EnvironmentData, SimConsoleResponseMessage};
|
||||
use libremetaverse::{
|
||||
GridClient, HttpCapsClient, RegionRestartDays, RegionRestartSchedule, Simulator,
|
||||
};
|
||||
use libremetaverse_compat_tests::block_on;
|
||||
use libremetaverse_structured_data::{OSD, OSDParser};
|
||||
use libremetaverse_types::UUID;
|
||||
use libremetaverse_types::compat::{HttpMessageHandler, HttpRequest, HttpResponse, Uri};
|
||||
use std::collections::BTreeMap;
|
||||
use std::sync::{Arc, Mutex};
|
||||
use std::time::Duration;
|
||||
|
||||
const CAP: &str = "http://test.invalid/capability";
|
||||
const SEED: &str = "http://test.invalid/seed";
|
||||
|
||||
#[derive(Clone)]
|
||||
struct Recording(Arc<Mutex<Vec<HttpRequest>>>);
|
||||
|
||||
impl Recording {
|
||||
fn requests(&self) -> Vec<HttpRequest> {
|
||||
self.0.lock().unwrap().clone()
|
||||
}
|
||||
}
|
||||
|
||||
fn response(status: u16, content_type: &str, body: &str) -> HttpResponse {
|
||||
HttpResponse {
|
||||
status_code: status,
|
||||
headers: BTreeMap::new(),
|
||||
content_type: Some(content_type.into()),
|
||||
body: body.as_bytes().to_vec(),
|
||||
}
|
||||
}
|
||||
|
||||
fn client_with_cap(
|
||||
cap_name: &str,
|
||||
expose_capability: bool,
|
||||
cap_response: HttpResponse,
|
||||
) -> (GridClient, Recording) {
|
||||
let requests = Arc::new(Mutex::new(Vec::new()));
|
||||
let captured = Arc::clone(&requests);
|
||||
let cap_reply = Mutex::new(Some(cap_response));
|
||||
let seed = if expose_capability {
|
||||
format!("<llsd><map><key>{cap_name}</key><uri>{CAP}</uri></map></llsd>")
|
||||
} else {
|
||||
"<llsd><map></map></llsd>".into()
|
||||
};
|
||||
let handler = HttpMessageHandler::new(move |request, _| {
|
||||
let reply = if request.uri.0 == SEED {
|
||||
response(200, "application/llsd+xml", &seed)
|
||||
} else {
|
||||
captured.lock().unwrap().push(request);
|
||||
cap_reply
|
||||
.lock()
|
||||
.unwrap()
|
||||
.take()
|
||||
.unwrap_or_else(|| response(404, "application/octet-stream", ""))
|
||||
};
|
||||
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,
|
||||
)
|
||||
.unwrap();
|
||||
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, Recording(requests))
|
||||
}
|
||||
|
||||
fn only_request(recording: &Recording) -> HttpRequest {
|
||||
let requests = recording.requests();
|
||||
assert_eq!(requests.len(), 1);
|
||||
requests.into_iter().next().unwrap()
|
||||
}
|
||||
|
||||
fn uuid() -> UUID {
|
||||
UUID::random().expect("UUID Random")
|
||||
}
|
||||
|
||||
// parity-case: LibreMetaverse.Tests/EnvironmentManagerTests.cs::EnvironmentManagerTests.GetParcelEnvironment_UsesParcelidQueryParameter::test 5c2f2b0fa2a86955975c621b2415a92ff3da283215e669956e14bf5ee2a4c1f4 translated
|
||||
#[test]
|
||||
fn get_parcel_environment_uses_parcelid_query_parameter() {
|
||||
let (client, recording) = client_with_cap(
|
||||
"ExtEnvironment",
|
||||
true,
|
||||
response(
|
||||
200,
|
||||
"application/llsd+xml",
|
||||
"<llsd><map><key>success</key><boolean>true</boolean></map></llsd>",
|
||||
),
|
||||
);
|
||||
block_on(client.environment().get_parcel_environment(42, None)).unwrap();
|
||||
let request = only_request(&recording);
|
||||
assert_eq!(request.method, "GET");
|
||||
assert!(request.uri.0.contains("parcelid=42"));
|
||||
assert!(!request.uri.0.contains("parcel_id"));
|
||||
}
|
||||
|
||||
// parity-case: LibreMetaverse.Tests/EnvironmentManagerTests.cs::EnvironmentManagerTests.SetParcelEnvironment_SendsParcelidInQueryStringNotBody::test f633e2d78e4c6a0fff42917ccfe8de68e4f6133a11e7eef7f9b757c3d1622f0f translated
|
||||
#[test]
|
||||
fn set_parcel_environment_sends_parcelid_in_query_not_body() {
|
||||
let (client, recording) = client_with_cap(
|
||||
"ExtEnvironment",
|
||||
true,
|
||||
response(
|
||||
200,
|
||||
"application/llsd+xml",
|
||||
"<llsd><map><key>success</key><boolean>true</boolean></map></llsd>",
|
||||
),
|
||||
);
|
||||
let mut environment = EnvironmentData::new().expect("EnvironmentData constructor");
|
||||
environment.set_day_length(7200);
|
||||
block_on(
|
||||
client
|
||||
.environment()
|
||||
.set_parcel_environment(7, environment, None),
|
||||
)
|
||||
.unwrap();
|
||||
let request = only_request(&recording);
|
||||
assert_eq!(request.method, "POST");
|
||||
assert!(request.uri.0.contains("parcelid=7"));
|
||||
let OSD::Map(body) = OSDParser::deserialize_with_bytes(request.body).unwrap() else {
|
||||
panic!("ExtEnvironment POST body is not an LLSD map")
|
||||
};
|
||||
assert!(!body.contains_key("parcel_id"));
|
||||
let Some(OSD::Map(environment)) = body.get("environment") else {
|
||||
panic!("environment map missing")
|
||||
};
|
||||
assert_eq!(
|
||||
environment.get("day_length").unwrap().as_integer().unwrap(),
|
||||
7200
|
||||
);
|
||||
assert!(!environment.contains_key("sky_track"));
|
||||
}
|
||||
|
||||
// parity-case: LibreMetaverse.Tests/EnvironmentManagerTests.cs::EnvironmentManagerTests.SetRegionEnvironment_OmitsQueryStringEntirely::test bade6e06765506ad7e500ac3e5c9f168605ce25fef86647819d285a68b39f109 translated
|
||||
#[test]
|
||||
fn set_region_environment_omits_query_string_entirely() {
|
||||
let (client, recording) = client_with_cap(
|
||||
"ExtEnvironment",
|
||||
true,
|
||||
response(
|
||||
200,
|
||||
"application/llsd+xml",
|
||||
"<llsd><map><key>success</key><boolean>true</boolean></map></llsd>",
|
||||
),
|
||||
);
|
||||
let environment = EnvironmentData::new().expect("EnvironmentData constructor");
|
||||
block_on(
|
||||
client
|
||||
.environment()
|
||||
.set_region_environment_with_environment_data_cancellation_token(environment, None),
|
||||
)
|
||||
.unwrap();
|
||||
let request = only_request(&recording);
|
||||
assert_eq!(request.method, "POST");
|
||||
assert_eq!(request.uri.0, CAP);
|
||||
}
|
||||
|
||||
// parity-case: LibreMetaverse.Tests/EnvironmentManagerTests.cs::EnvironmentManagerTests.ResetParcelEnvironment_SendsHttpDeleteNotPost::test 4360439192c137f5d7a2ceb83b8664f3917b4b261798050cb855d596f483f082 translated
|
||||
#[test]
|
||||
fn reset_parcel_environment_sends_delete_not_post() {
|
||||
let (client, recording) = client_with_cap(
|
||||
"ExtEnvironment",
|
||||
true,
|
||||
response(
|
||||
200,
|
||||
"application/llsd+xml",
|
||||
"<llsd><map><key>success</key><boolean>true</boolean></map></llsd>",
|
||||
),
|
||||
);
|
||||
assert!(block_on(client.environment().reset_parcel_environment(3, None)).unwrap());
|
||||
let request = only_request(&recording);
|
||||
assert_eq!(request.method, "DELETE");
|
||||
assert!(request.uri.0.contains("parcelid=3"));
|
||||
}
|
||||
|
||||
// parity-case: LibreMetaverse.Tests/QueryExperiencesOnParcelTests.cs::QueryExperiencesOnParcelTests.QueryExperiencesOnParcelAsync_HappyPath_ParsesAllowedMapAndBuildsExpectedQuery::test 2571d3a4100face21268d7ca2401cc8468e711c03c808704aacc7a50006125d5 translated
|
||||
#[test]
|
||||
fn query_experiences_on_parcel_happy_path() {
|
||||
let first = uuid();
|
||||
let second = uuid();
|
||||
let first_text = first.to_string();
|
||||
let second_text = second.to_string();
|
||||
let body = format!(r#"{{"experiences":{{"{first_text}":true,"{second_text}":false}}}}"#);
|
||||
let (mut client, recording) = client_with_cap(
|
||||
"ExperienceQuery",
|
||||
true,
|
||||
response(200, "application/json", &body),
|
||||
);
|
||||
let result = block_on(client.self_().query_experiences_on_parcel(
|
||||
42,
|
||||
Box::new([first, second].into_iter()),
|
||||
None,
|
||||
))
|
||||
.unwrap()
|
||||
.expect("experience result");
|
||||
assert_eq!(result.get(&first), Some(&true));
|
||||
assert_eq!(result.get(&second), Some(&false));
|
||||
let request = only_request(&recording);
|
||||
assert!(request.uri.0.contains("parcelid=42"));
|
||||
assert!(
|
||||
request
|
||||
.uri
|
||||
.0
|
||||
.contains(&format!("experiences={first_text},{second_text}"))
|
||||
);
|
||||
}
|
||||
|
||||
// parity-case: LibreMetaverse.Tests/QueryExperiencesOnParcelTests.cs::QueryExperiencesOnParcelTests.QueryExperiencesOnParcelAsync_NoExperienceIds_OmitsExperiencesParam::test ddbaa53aa8c63262c2241588b4281c42bbb66efdecac95e297deb0fb81797455 translated
|
||||
#[test]
|
||||
fn query_experiences_on_parcel_no_ids_omits_parameter() {
|
||||
let (mut client, recording) = client_with_cap(
|
||||
"ExperienceQuery",
|
||||
true,
|
||||
response(200, "application/json", r#"{"experiences":{}}"#),
|
||||
);
|
||||
let result = block_on(client.self_().query_experiences_on_parcel(
|
||||
7,
|
||||
Box::new(std::iter::empty()),
|
||||
None,
|
||||
))
|
||||
.unwrap()
|
||||
.expect("experience result");
|
||||
assert!(result.is_empty());
|
||||
let request = only_request(&recording);
|
||||
assert!(request.uri.0.contains("parcelid=7"));
|
||||
assert!(!request.uri.0.contains("experiences"));
|
||||
}
|
||||
|
||||
// parity-case: LibreMetaverse.Tests/QueryExperiencesOnParcelTests.cs::QueryExperiencesOnParcelTests.QueryExperiencesOnParcelAsync_NoCapability_ReturnsNullWithoutRequest::test 5c6a6584fba8ddc66200367217f658d342fb2c26d6be9e49ccf3892bea420095 translated
|
||||
#[test]
|
||||
fn query_experiences_on_parcel_no_capability_returns_none_without_request() {
|
||||
let (mut client, recording) = client_with_cap(
|
||||
"ExperienceQuery",
|
||||
false,
|
||||
response(404, "application/json", ""),
|
||||
);
|
||||
let result = block_on(client.self_().query_experiences_on_parcel(
|
||||
1,
|
||||
Box::new([uuid()].into_iter()),
|
||||
None,
|
||||
))
|
||||
.unwrap();
|
||||
assert!(result.is_none());
|
||||
assert!(recording.requests().is_empty());
|
||||
}
|
||||
|
||||
// parity-case: LibreMetaverse.Tests/QueryExperiencesOnParcelTests.cs::QueryExperiencesOnParcelTests.QueryExperiencesOnParcelAsync_NonSuccessStatus_ReturnsNull::test 977fe55acd5aeb5735cc718f705a2742ae0dfab12dc1211c03a64cc6d1f3bbf5 translated
|
||||
#[test]
|
||||
fn query_experiences_on_parcel_non_success_returns_none() {
|
||||
let (mut client, _) = client_with_cap(
|
||||
"ExperienceQuery",
|
||||
true,
|
||||
response(500, "application/json", ""),
|
||||
);
|
||||
assert!(
|
||||
block_on(client.self_().query_experiences_on_parcel(
|
||||
1,
|
||||
Box::new([uuid()].into_iter()),
|
||||
None
|
||||
))
|
||||
.unwrap()
|
||||
.is_none()
|
||||
);
|
||||
}
|
||||
|
||||
// parity-case: LibreMetaverse.Tests/RegionScheduleTests.cs::RegionScheduleTests.GetRegionRestartScheduleAsync_WeeklySchedule_ParsesDaysAndTime::test 0f64aab66c6a6d807b3d2bbc46b636a85900e4f76e35d5e3dd8cd0d8b295618b translated
|
||||
#[test]
|
||||
fn get_region_restart_schedule_weekly_parses_days_and_time() {
|
||||
let (client, _) = client_with_cap(
|
||||
"RegionSchedule",
|
||||
true,
|
||||
response(
|
||||
200,
|
||||
"application/json",
|
||||
r#"{"restart":{"type":"W","days":"TR","time":7200}}"#,
|
||||
),
|
||||
);
|
||||
let schedule = block_on(client.estate().get_region_restart_schedule(None))
|
||||
.unwrap()
|
||||
.expect("restart schedule");
|
||||
assert!(!schedule.is_daily());
|
||||
assert_eq!(
|
||||
schedule.days(),
|
||||
RegionRestartDays(RegionRestartDays::TUESDAY.0 | RegionRestartDays::THURSDAY.0)
|
||||
);
|
||||
assert_eq!(schedule.time(), Duration::from_secs(2 * 60 * 60));
|
||||
}
|
||||
|
||||
// parity-case: LibreMetaverse.Tests/RegionScheduleTests.cs::RegionScheduleTests.GetRegionRestartScheduleAsync_DailySchedule_ReturnsAllDays::test cd966b6e3ba470c91ac958bf6c71aeb34f4dab060ad5334cb6060e1954b5c6d0 translated
|
||||
#[test]
|
||||
fn get_region_restart_schedule_daily_returns_all_days() {
|
||||
let (client, _) = client_with_cap(
|
||||
"RegionSchedule",
|
||||
true,
|
||||
response(
|
||||
200,
|
||||
"application/json",
|
||||
r#"{"restart":{"type":"D","time":3600}}"#,
|
||||
),
|
||||
);
|
||||
let schedule = block_on(client.estate().get_region_restart_schedule(None))
|
||||
.unwrap()
|
||||
.expect("restart schedule");
|
||||
assert!(schedule.is_daily());
|
||||
assert_eq!(schedule.days(), RegionRestartDays::ALL);
|
||||
assert_eq!(schedule.time(), Duration::from_secs(60 * 60));
|
||||
}
|
||||
|
||||
// parity-case: LibreMetaverse.Tests/RegionScheduleTests.cs::RegionScheduleTests.GetRegionRestartScheduleAsync_NoRestartConfigured_ReturnsNull::test 59a4b050a79659ccaf0fff13b750d634d803ed7b9e4940cbad676c1bdc04a5fc translated
|
||||
#[test]
|
||||
fn get_region_restart_schedule_no_restart_returns_none() {
|
||||
let (client, _) = client_with_cap(
|
||||
"RegionSchedule",
|
||||
true,
|
||||
response(200, "application/json", "{}"),
|
||||
);
|
||||
assert!(
|
||||
block_on(client.estate().get_region_restart_schedule(None))
|
||||
.unwrap()
|
||||
.is_none()
|
||||
);
|
||||
}
|
||||
|
||||
// parity-case: LibreMetaverse.Tests/RegionScheduleTests.cs::RegionScheduleTests.GetRegionRestartScheduleAsync_NoCapability_ReturnsNullWithoutRequest::test e169e7846874ed4309a50cb25b03c2e722a8d758a787654a5906610ab3b655f1 translated
|
||||
#[test]
|
||||
fn get_region_restart_schedule_no_capability_returns_none_without_request() {
|
||||
let (client, recording) = client_with_cap(
|
||||
"RegionSchedule",
|
||||
false,
|
||||
response(404, "application/json", ""),
|
||||
);
|
||||
assert!(
|
||||
block_on(client.estate().get_region_restart_schedule(None))
|
||||
.unwrap()
|
||||
.is_none()
|
||||
);
|
||||
assert!(recording.requests().is_empty());
|
||||
}
|
||||
|
||||
fn schedule(daily: bool, days: RegionRestartDays, time: Duration) -> RegionRestartSchedule {
|
||||
let mut schedule = RegionRestartSchedule::new().expect("RegionRestartSchedule constructor");
|
||||
schedule.set_is_daily(daily);
|
||||
schedule.set_days(days);
|
||||
schedule.set_time(time);
|
||||
schedule
|
||||
}
|
||||
|
||||
// parity-case: LibreMetaverse.Tests/RegionScheduleTests.cs::RegionScheduleTests.SetRegionRestartScheduleAsync_Weekly_PostsUppercaseDaysAndSeconds::test 153fc0ac84af549c1381d0814a356bf2d9e0ead2c879e503981193366943546c translated
|
||||
#[test]
|
||||
fn set_region_restart_schedule_weekly_posts_uppercase_days_and_seconds() {
|
||||
let (client, recording) = client_with_cap(
|
||||
"RegionSchedule",
|
||||
true,
|
||||
response(200, "application/json", ""),
|
||||
);
|
||||
let days = RegionRestartDays(
|
||||
RegionRestartDays::MONDAY.0 | RegionRestartDays::WEDNESDAY.0 | RegionRestartDays::FRIDAY.0,
|
||||
);
|
||||
assert!(
|
||||
block_on(
|
||||
client.estate().set_region_restart_schedule(
|
||||
schedule(false, days, Duration::from_secs(5400)),
|
||||
None
|
||||
)
|
||||
)
|
||||
.unwrap()
|
||||
);
|
||||
let body = String::from_utf8(only_request(&recording).body).unwrap();
|
||||
assert!(body.contains("<key>type</key>"));
|
||||
assert!(body.contains('W'));
|
||||
assert!(body.contains("MWF"));
|
||||
assert!(body.contains("5400"));
|
||||
}
|
||||
|
||||
// parity-case: LibreMetaverse.Tests/RegionScheduleTests.cs::RegionScheduleTests.SetRegionRestartScheduleAsync_DailyIgnoresDays_DoesNotPostDaysKey::test b51a1272465c3316194542eb346b2aa15c43fdc8474163ddd851b3f2204d1c2b translated
|
||||
#[test]
|
||||
fn set_region_restart_schedule_daily_omits_days() {
|
||||
let (client, recording) = client_with_cap(
|
||||
"RegionSchedule",
|
||||
true,
|
||||
response(200, "application/json", ""),
|
||||
);
|
||||
assert!(
|
||||
block_on(client.estate().set_region_restart_schedule(
|
||||
schedule(
|
||||
true,
|
||||
RegionRestartDays::NONE,
|
||||
Duration::from_secs(3 * 60 * 60)
|
||||
),
|
||||
None
|
||||
))
|
||||
.unwrap()
|
||||
);
|
||||
assert!(
|
||||
!String::from_utf8(only_request(&recording).body)
|
||||
.unwrap()
|
||||
.contains("<key>days</key>")
|
||||
);
|
||||
}
|
||||
|
||||
// parity-case: LibreMetaverse.Tests/RegionScheduleTests.cs::RegionScheduleTests.SetRegionRestartScheduleAsync_EmptyDaysClearsSchedule::test 57ef3c0f8d9eeac58a7d1b3e7dbc44413016f39303d304cacd3071bd2c55f320 translated
|
||||
#[test]
|
||||
fn set_region_restart_schedule_empty_days_clears_schedule() {
|
||||
let (client, recording) = client_with_cap(
|
||||
"RegionSchedule",
|
||||
true,
|
||||
response(200, "application/json", ""),
|
||||
);
|
||||
assert!(
|
||||
block_on(client.estate().set_region_restart_schedule(
|
||||
schedule(false, RegionRestartDays::NONE, Duration::ZERO),
|
||||
None
|
||||
))
|
||||
.unwrap()
|
||||
);
|
||||
let body = String::from_utf8(only_request(&recording).body).unwrap();
|
||||
assert!(body.contains("<key>days</key>"));
|
||||
assert!(body.contains("<string />") || body.contains("<string></string>"));
|
||||
}
|
||||
|
||||
// parity-case: LibreMetaverse.Tests/RegionScheduleTests.cs::RegionScheduleTests.SetRegionRestartScheduleAsync_NoCapability_ReturnsFalseWithoutRequest::test be03507fe574b9f7c7174c39af44b7b693e1b7a496845db46451ef09bf9db206 translated
|
||||
#[test]
|
||||
fn set_region_restart_schedule_no_capability_returns_false_without_request() {
|
||||
let (client, recording) = client_with_cap(
|
||||
"RegionSchedule",
|
||||
false,
|
||||
response(404, "application/json", ""),
|
||||
);
|
||||
assert!(
|
||||
!block_on(client.estate().set_region_restart_schedule(
|
||||
schedule(true, RegionRestartDays::NONE, Duration::ZERO),
|
||||
None
|
||||
))
|
||||
.unwrap()
|
||||
);
|
||||
assert!(recording.requests().is_empty());
|
||||
}
|
||||
|
||||
// parity-case: LibreMetaverse.Tests/RegionScheduleTests.cs::RegionScheduleTests.SetRegionRestartScheduleAsync_NonSuccessStatus_ReturnsFalse::test 16c8988d7aa15ea9f58deaa2e3f416b6115978e23073fd99749843f4f410dca4 translated
|
||||
#[test]
|
||||
fn set_region_restart_schedule_non_success_returns_false() {
|
||||
let (client, _) = client_with_cap(
|
||||
"RegionSchedule",
|
||||
true,
|
||||
response(500, "application/json", ""),
|
||||
);
|
||||
assert!(
|
||||
!block_on(client.estate().set_region_restart_schedule(
|
||||
schedule(true, RegionRestartDays::NONE, Duration::ZERO),
|
||||
None
|
||||
))
|
||||
.unwrap()
|
||||
);
|
||||
}
|
||||
|
||||
// parity-case: LibreMetaverse.Tests/SimConsoleTests.cs::SimConsoleTests.SimConsoleResponseMessage_Deserialize_ReadsBodyField::test 4d367bc3fd012d1579847fd9837bf883c5ea95452776a086bbf856899d7c2099 translated
|
||||
#[test]
|
||||
fn sim_console_response_message_deserialize_reads_body_field() {
|
||||
let map = libremetaverse_structured_data::OSDMap::new_with_dictionary(
|
||||
std::collections::HashMap::from([(
|
||||
"body".into(),
|
||||
OSD::String("console output text".into()),
|
||||
)]),
|
||||
)
|
||||
.unwrap();
|
||||
let mut message =
|
||||
SimConsoleResponseMessage::new().expect("SimConsoleResponseMessage constructor");
|
||||
message.deserialize(map).unwrap();
|
||||
assert_eq!(message.body, "console output text");
|
||||
}
|
||||
23
tests/compat/tests/world_constructor_semantics.rs
Normal file
23
tests/compat/tests/world_constructor_semantics.rs
Normal file
@@ -0,0 +1,23 @@
|
||||
// Exact Rust translations of the world-manager cases in
|
||||
// LibreMetaverse.Tests/ConstructorNullArgumentTests.cs.
|
||||
// Source SHA-256: 28deea0bf4d9353a2424842c6184abab8fe82746ceb12e093912728a247f21bc
|
||||
|
||||
use libremetaverse::{AgentManager, Error, GridManager, ObjectManager};
|
||||
|
||||
// parity-case: LibreMetaverse.Tests/ConstructorNullArgumentTests.cs::ConstructorNullArgumentTests.GridManager_Null_Throws::test e972a95f334b0f46948cda34c27124c28c44faf4372d0e598d7dc60050b49be4 translated
|
||||
#[test]
|
||||
fn grid_manager_null_throws() {
|
||||
assert!(matches!(GridManager::new(None), Err(Error::ArgumentNull)));
|
||||
}
|
||||
|
||||
// parity-case: LibreMetaverse.Tests/ConstructorNullArgumentTests.cs::ConstructorNullArgumentTests.ObjectManager_Null_Throws::test 8a11feba0edfb35e5dd99f681182e8f5a5cf8a3f738211b45a683a8a2ad45ddb translated
|
||||
#[test]
|
||||
fn object_manager_null_throws() {
|
||||
assert!(matches!(ObjectManager::new(None), Err(Error::ArgumentNull)));
|
||||
}
|
||||
|
||||
// parity-case: LibreMetaverse.Tests/ConstructorNullArgumentTests.cs::ConstructorNullArgumentTests.AgentManager_Null_Throws::test d86e41b6cdd03063685aa330c31b9a274c1d400b9a461abf3065fe185fe0bbf0 translated
|
||||
#[test]
|
||||
fn agent_manager_null_throws() {
|
||||
assert!(matches!(AgentManager::new(None), Err(Error::ArgumentNull)));
|
||||
}
|
||||
81
tests/compat/tests/world_live_semantics.rs
Normal file
81
tests/compat/tests/world_live_semantics.rs
Normal file
@@ -0,0 +1,81 @@
|
||||
// Exact Rust translation of LibreMetaverse.Tests/EstateToolsTests.cs.
|
||||
// Source SHA-256: 2f1867304e21e72d20fbeed98e7705528797947eb3115f84f80aa6adc2f3f88e
|
||||
|
||||
use libremetaverse::{GridClient, NetworkManager};
|
||||
use libremetaverse_compat_tests::{block_on, live_grid_credentials};
|
||||
use libremetaverse_types::UUID;
|
||||
use std::sync::mpsc;
|
||||
use std::time::Duration;
|
||||
|
||||
struct LiveEstate {
|
||||
client: GridClient,
|
||||
}
|
||||
|
||||
impl LiveEstate {
|
||||
fn login() -> Self {
|
||||
let mut client = GridClient::new().expect("GridClient constructor");
|
||||
client.settings().timing().login_timeout = 30_000;
|
||||
let network = client.network();
|
||||
let (first, last, password, login_url) = live_grid_credentials();
|
||||
let start = NetworkManager::start_location("Hooper".into(), 179, 18, 32)
|
||||
.expect("NetworkManager StartLocation");
|
||||
let mut login = network
|
||||
.default_login_params(
|
||||
first,
|
||||
last,
|
||||
password,
|
||||
"Unit Test Framework".into(),
|
||||
"admin@radegast.life".into(),
|
||||
)
|
||||
.expect("NetworkManager DefaultLoginParams");
|
||||
login.start = start;
|
||||
login.uri = login_url;
|
||||
let logged_in = block_on(network.login_with_login_params_cancellation_token(login, None))
|
||||
.expect("NetworkManager LoginAsync");
|
||||
assert!(
|
||||
logged_in,
|
||||
"client failed to login: {}",
|
||||
network.login_message()
|
||||
);
|
||||
assert!(network.connected(), "client is not connected to the grid");
|
||||
let current = network.current_sim().expect("CurrentSim after login");
|
||||
if !current.name.is_empty() && !current.name.eq_ignore_ascii_case("Hooper") {
|
||||
eprintln!(
|
||||
"logged in to {} instead of Hooper; covenant request remains read-only",
|
||||
current.name
|
||||
);
|
||||
}
|
||||
Self { client }
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for LiveEstate {
|
||||
fn drop(&mut self) {
|
||||
let _ = self.client.network().logout_with_method();
|
||||
let _ = self.client.dispose_with_method();
|
||||
}
|
||||
}
|
||||
|
||||
// parity-case: LibreMetaverse.Tests/EstateToolsTests.cs::EstateToolsTests.RequestConvenant::test d8d752dd6e53477e4c66bcb5d0e3ec1021a9b3ceda1f689f59b5e606e1713729 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; performs only a reversible read-only covenant request"
|
||||
)]
|
||||
fn request_covenant() {
|
||||
let live = LiveEstate::login();
|
||||
let estate = live.client.estate();
|
||||
let (sender, receiver) = mpsc::sync_channel(1);
|
||||
let _subscription = estate.subscribe_estate_covenant_reply(std::sync::Arc::new(move |reply| {
|
||||
let _ = sender.send((reply.estate_name(), reply.covenant_id()));
|
||||
}));
|
||||
estate
|
||||
.request_covenant()
|
||||
.expect("EstateTools RequestCovenant");
|
||||
let Ok((name, covenant)) = receiver.recv_timeout(Duration::from_secs(10)) else {
|
||||
eprintln!("timeout waiting for estate covenant reply after 10 seconds");
|
||||
return;
|
||||
};
|
||||
assert!(!name.is_empty());
|
||||
assert_ne!(covenant, UUID::zero());
|
||||
}
|
||||
150
tests/compat/tests/world_message_semantics.rs
Normal file
150
tests/compat/tests/world_message_semantics.rs
Normal file
@@ -0,0 +1,150 @@
|
||||
// Exact Rust translations of LibreMetaverse.Tests/ExperienceListAndRegionMessageTests.cs and
|
||||
// LibreMetaverse.Tests/ExperiencePreferencesMessageTests.cs public message cases.
|
||||
// Source SHA-256: b023ec7ac43124fcd47b15474a9d66d1fca522d1166dc0d5c21b8c82189051f2
|
||||
// Source SHA-256: 7b67b72c2ad652626126d0e4eda7e8c26fc94c28f0f915238b2925f80a3d4af2
|
||||
|
||||
use libremetaverse::messages::linden::{
|
||||
ExperienceListMessage, ExperiencePreferencesMessage, RegionExperiencesMessage,
|
||||
};
|
||||
use libremetaverse_structured_data::{OSD, OSDMap};
|
||||
use libremetaverse_types::UUID;
|
||||
|
||||
fn uuid() -> UUID {
|
||||
UUID::random().expect("UUID Random")
|
||||
}
|
||||
|
||||
fn map(entries: impl IntoIterator<Item = (&'static str, OSD)>) -> OSDMap {
|
||||
OSDMap::new_with_dictionary(
|
||||
entries
|
||||
.into_iter()
|
||||
.map(|(key, value)| (key.to_owned(), value))
|
||||
.collect(),
|
||||
)
|
||||
.expect("OSDMap dictionary constructor")
|
||||
}
|
||||
|
||||
fn ids(values: impl IntoIterator<Item = UUID>) -> OSD {
|
||||
OSD::Array(values.into_iter().map(OSD::UUID).collect())
|
||||
}
|
||||
|
||||
// parity-case: LibreMetaverse.Tests/ExperienceListAndRegionMessageTests.cs::ExperienceListAndRegionMessageTests.ExperienceListMessage_Deserialize_ReadsExperienceIdsKey::test aa1f7d09f6c79118ea2e60621d57bd63632085ce81bc979e42294aca53d4f0d9 translated
|
||||
#[test]
|
||||
fn experience_list_deserialize_reads_experience_ids_key() {
|
||||
let id = uuid();
|
||||
let mut message = ExperienceListMessage::new().expect("ExperienceListMessage constructor");
|
||||
message
|
||||
.deserialize(map([("experience_ids", ids([id]))]))
|
||||
.unwrap();
|
||||
assert_eq!(message.experience_i_ds, vec![id]);
|
||||
}
|
||||
|
||||
// parity-case: LibreMetaverse.Tests/ExperienceListAndRegionMessageTests.cs::ExperienceListAndRegionMessageTests.ExperienceListMessage_Deserialize_IgnoresLegacyExperienceKeysKey::test cd1d372b9a976c04dee11da1ade182e4f9239e1f7633e788347c6d5f255835ec translated
|
||||
#[test]
|
||||
fn experience_list_deserialize_ignores_legacy_experience_keys_key() {
|
||||
let mut message = ExperienceListMessage::new().expect("ExperienceListMessage constructor");
|
||||
message
|
||||
.deserialize(map([("experience_keys", ids([uuid()]))]))
|
||||
.unwrap();
|
||||
assert!(message.experience_i_ds.is_empty());
|
||||
}
|
||||
|
||||
// parity-case: LibreMetaverse.Tests/ExperienceListAndRegionMessageTests.cs::ExperienceListAndRegionMessageTests.ExperienceListMessage_Serialize_WritesExperienceIdsKey::test 3fa4cb5d598940f693285bcc64179a4dea927a3643a76a061a933a265488d4be translated
|
||||
#[test]
|
||||
fn experience_list_serialize_writes_experience_ids_key() {
|
||||
let mut message = ExperienceListMessage::new().expect("ExperienceListMessage constructor");
|
||||
message.experience_i_ds.push(uuid());
|
||||
let encoded = message.serialize().unwrap();
|
||||
assert!(encoded.contains_key("experience_ids".into()).unwrap());
|
||||
assert!(!encoded.contains_key("experience_keys".into()).unwrap());
|
||||
}
|
||||
|
||||
// parity-case: LibreMetaverse.Tests/ExperienceListAndRegionMessageTests.cs::ExperienceListAndRegionMessageTests.RegionExperiencesMessage_Deserialize_ReadsBlockedTrustedAllowedAndDefault::test 61df3b0c60d32b6c9bb843eb7a1a11fe8c0b1fd59c7a09853ad1b0e1d93cd4fd translated
|
||||
#[test]
|
||||
fn region_experiences_deserialize_reads_all_lists_and_default() {
|
||||
let blocked = uuid();
|
||||
let trusted = uuid();
|
||||
let allowed = uuid();
|
||||
let default_experience = uuid();
|
||||
let mut message =
|
||||
RegionExperiencesMessage::new().expect("RegionExperiencesMessage constructor");
|
||||
message
|
||||
.deserialize(map([
|
||||
("blocked", ids([blocked])),
|
||||
("trusted", ids([trusted])),
|
||||
("allowed", ids([allowed])),
|
||||
("default", OSD::UUID(default_experience)),
|
||||
]))
|
||||
.unwrap();
|
||||
assert_eq!(message.blocked, vec![blocked]);
|
||||
assert_eq!(message.trusted, vec![trusted]);
|
||||
assert_eq!(message.allowed, vec![allowed]);
|
||||
assert_eq!(message.default, default_experience);
|
||||
}
|
||||
|
||||
// parity-case: LibreMetaverse.Tests/ExperienceListAndRegionMessageTests.cs::ExperienceListAndRegionMessageTests.RegionExperiencesMessage_Deserialize_IgnoresLegacyContribKey::test 851d037919003ebb414105e57bf37f73ba37dff8f733c36183c447f1349f3316 translated
|
||||
#[test]
|
||||
fn region_experiences_deserialize_ignores_legacy_contrib_key() {
|
||||
let mut message =
|
||||
RegionExperiencesMessage::new().expect("RegionExperiencesMessage constructor");
|
||||
message
|
||||
.deserialize(map([
|
||||
("blocked", OSD::Array(Vec::new())),
|
||||
("trusted", OSD::Array(Vec::new())),
|
||||
("contrib", ids([uuid()])),
|
||||
]))
|
||||
.unwrap();
|
||||
assert!(message.allowed.is_empty());
|
||||
}
|
||||
|
||||
// parity-case: LibreMetaverse.Tests/ExperienceListAndRegionMessageTests.cs::ExperienceListAndRegionMessageTests.RegionExperiencesMessage_Serialize_WritesAllowedKeyNotContrib::test 53c3a7d6a200816615a9efaa222ccf294e3a8334d320812c6ec56a0a3e7e05bb translated
|
||||
#[test]
|
||||
fn region_experiences_serialize_writes_allowed_not_contrib() {
|
||||
let mut message =
|
||||
RegionExperiencesMessage::new().expect("RegionExperiencesMessage constructor");
|
||||
message.allowed.push(uuid());
|
||||
let encoded = message.serialize().unwrap();
|
||||
assert!(encoded.contains_key("allowed".into()).unwrap());
|
||||
assert!(!encoded.contains_key("contrib".into()).unwrap());
|
||||
}
|
||||
|
||||
// parity-case: LibreMetaverse.Tests/ExperiencePreferencesMessageTests.cs::ExperiencePreferencesMessageTests.Deserialize_ReadsAllowedListFromExperiencesKey::test 9bab78dbe142a3da6ad21a278f25d7da90776fce3861c7d602203c1e1842c9af translated
|
||||
#[test]
|
||||
fn experience_preferences_deserialize_reads_experiences_and_blocked() {
|
||||
let allowed = uuid();
|
||||
let blocked = uuid();
|
||||
let mut message =
|
||||
ExperiencePreferencesMessage::new().expect("ExperiencePreferencesMessage constructor");
|
||||
message
|
||||
.deserialize(map([
|
||||
("experiences", ids([allowed])),
|
||||
("blocked", ids([blocked])),
|
||||
]))
|
||||
.unwrap();
|
||||
assert_eq!(message.allowed, vec![allowed]);
|
||||
assert_eq!(message.blocked, vec![blocked]);
|
||||
}
|
||||
|
||||
// parity-case: LibreMetaverse.Tests/ExperiencePreferencesMessageTests.cs::ExperiencePreferencesMessageTests.Deserialize_IgnoresLegacyAllowedKey::test ec6d5e7c81214ea4e3d99740fdd33961578f895a90a42082067ca9819d93d2b0 translated
|
||||
#[test]
|
||||
fn experience_preferences_deserialize_ignores_legacy_allowed_key() {
|
||||
let mut message =
|
||||
ExperiencePreferencesMessage::new().expect("ExperiencePreferencesMessage constructor");
|
||||
message
|
||||
.deserialize(map([
|
||||
("allowed", ids([uuid()])),
|
||||
("blocked", OSD::Array(Vec::new())),
|
||||
]))
|
||||
.unwrap();
|
||||
assert!(message.allowed.is_empty());
|
||||
}
|
||||
|
||||
// parity-case: LibreMetaverse.Tests/ExperiencePreferencesMessageTests.cs::ExperiencePreferencesMessageTests.Serialize_WritesAllowedListUnderExperiencesKey::test 45a0bffe39ab7bf0734ec5fce4435dbdda7ae94cf4e933210669e91dc45b1baf translated
|
||||
#[test]
|
||||
fn experience_preferences_serialize_writes_experiences_not_allowed() {
|
||||
let mut message =
|
||||
ExperiencePreferencesMessage::new().expect("ExperiencePreferencesMessage constructor");
|
||||
message.allowed.push(uuid());
|
||||
let encoded = message.serialize().unwrap();
|
||||
assert!(encoded.contains_key("experiences".into()).unwrap());
|
||||
assert!(!encoded.contains_key("allowed".into()).unwrap());
|
||||
}
|
||||
652
tests/compat/tests/world_object_semantics.rs
Normal file
652
tests/compat/tests/world_object_semantics.rs
Normal file
@@ -0,0 +1,652 @@
|
||||
// Exact Rust translations of object and texture tests owned by milestone issue #23.
|
||||
// Source SHA-256: 1a9d986c5e2d7526e95a7bb5b870ebee13ddf9f4e8c3fd69c34b7a7f22375916
|
||||
// Source SHA-256: b444ada9b4d09944dbdf7668c0c8105de66fb590bee1d6d1f284b30700ee5284
|
||||
// Source SHA-256: f9a33efa0e88e4a7d86bf7beda56c0f45757ff66f0cdc161da384ad5a31467a6
|
||||
|
||||
#![allow(clippy::float_cmp)]
|
||||
|
||||
use libremetaverse::{
|
||||
Bumpiness, Helpers, MappingType, Primitive, PrimitiveConstructionData, PrimitiveFlexibleData,
|
||||
PrimitiveLightData, PrimitiveLightImage, PrimitiveObjectProperties, PrimitiveSculptData,
|
||||
PrimitiveTextureEntry, Shininess,
|
||||
};
|
||||
use libremetaverse_structured_data::OSD;
|
||||
use libremetaverse_types::{
|
||||
Color4, HoleType, Material, PCode, PathCurve, PrimFlags, ProfileCurve, Quaternion, SculptType,
|
||||
UUID, Vector3,
|
||||
};
|
||||
use std::collections::HashMap;
|
||||
|
||||
fn uuid() -> UUID {
|
||||
UUID::random().expect("UUID Random")
|
||||
}
|
||||
|
||||
fn round_trip(entry: &PrimitiveTextureEntry) -> PrimitiveTextureEntry {
|
||||
let bytes = entry.get_bytes().expect("TextureEntry GetBytes");
|
||||
let length = i32::try_from(bytes.len()).expect("TextureEntry length fits Int32");
|
||||
PrimitiveTextureEntry::new_with_bytes_int32_int32(bytes, 0, length)
|
||||
.expect("TextureEntry byte constructor")
|
||||
}
|
||||
|
||||
fn face(entry: &PrimitiveTextureEntry, index: usize) -> &libremetaverse::PrimitiveTextureEntryFace {
|
||||
entry.face_textures[index].as_ref().expect("per-face entry")
|
||||
}
|
||||
|
||||
fn assert_vector(actual: Vector3, expected: Vector3) {
|
||||
assert_eq!(
|
||||
(actual.x, actual.y, actual.z),
|
||||
(expected.x, expected.y, expected.z)
|
||||
);
|
||||
}
|
||||
|
||||
fn assert_quaternion(actual: Quaternion, expected: Quaternion) {
|
||||
assert_eq!(
|
||||
(actual.x, actual.y, actual.z, actual.w),
|
||||
(expected.x, expected.y, expected.z, expected.w)
|
||||
);
|
||||
}
|
||||
|
||||
// parity-case: LibreMetaverse.Tests/PrimObjectTests.cs::PrimObjectTests.PathBegin::test 5c8e14e1d08a91a4e7c3e252c932b8fe15cf6b5231cc9fe5bb7ef2ae6e2c8299 translated
|
||||
#[test]
|
||||
fn path_begin() {
|
||||
for value in 0_u16..u16::from(u8::MAX) {
|
||||
let unpacked = Primitive::unpack_begin_cut(value).unwrap();
|
||||
assert_eq!(
|
||||
Primitive::pack_begin_cut(unpacked).unwrap(),
|
||||
value,
|
||||
"started with {value}, float value was {unpacked}"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// parity-case: LibreMetaverse.Tests/PrimObjectTests.cs::PrimObjectTests.PathEnd::test 693bfe29f448e433705d65b8b6907f1b270fd636f914e18b76d7a0047dbea506 translated
|
||||
#[test]
|
||||
fn path_end() {
|
||||
for value in 0_u16..u16::from(u8::MAX) {
|
||||
let unpacked = Primitive::unpack_end_cut(value).unwrap();
|
||||
assert_eq!(
|
||||
Primitive::pack_end_cut(unpacked).unwrap(),
|
||||
value,
|
||||
"started with {value}, float value was {unpacked}"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// parity-case: LibreMetaverse.Tests/PrimObjectTests.cs::PrimObjectTests.PathRevolutions::test c3f61c80a204e608976cb44a0c10b9651496074c25f254eec8621db65dbbbe37 translated
|
||||
#[test]
|
||||
fn path_revolutions() {
|
||||
for value in 0_u8..u8::MAX {
|
||||
let unpacked = Primitive::unpack_path_revolutions(value).unwrap();
|
||||
assert_eq!(
|
||||
Primitive::pack_path_revolutions(unpacked).unwrap(),
|
||||
value,
|
||||
"started with {value}, float value was {unpacked}"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// parity-case: LibreMetaverse.Tests/PrimObjectTests.cs::PrimObjectTests.PathScale::test b92e4ab375fcc788dea701d8579268f39b4f3b1d51d4eed91458547350405d61 translated
|
||||
#[test]
|
||||
fn path_scale() {
|
||||
for value in 0_u8..u8::MAX {
|
||||
let unpacked = Primitive::unpack_path_scale(value).unwrap();
|
||||
assert_eq!(
|
||||
Primitive::pack_path_scale(unpacked).unwrap(),
|
||||
value,
|
||||
"started with {value}, float value was {unpacked}"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// parity-case: LibreMetaverse.Tests/PrimObjectTests.cs::PrimObjectTests.PathTaper::test 93a0adbc0630de3c9fbea6f8080d74ef6e3180e3813f00460bce5d52ef2f12b7 translated
|
||||
#[test]
|
||||
fn path_taper() {
|
||||
for value in i8::MIN..i8::MAX {
|
||||
let unpacked = Primitive::unpack_path_taper(value).unwrap();
|
||||
assert_eq!(
|
||||
Primitive::pack_path_taper(unpacked).unwrap(),
|
||||
value,
|
||||
"started with {value}, float value was {unpacked}"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// parity-case: LibreMetaverse.Tests/PrimObjectTests.cs::PrimObjectTests.TextureEntryOffsets::test 720ea1a9477d333b14786bc14e9abca24858e63acae94f4c6055d81f14ff033a translated
|
||||
#[test]
|
||||
fn texture_entry_offsets() {
|
||||
let mut value = -1.0_f32;
|
||||
while value <= 1.0 {
|
||||
value = (value * 1000.0).round() / 1000.0;
|
||||
let packed = Helpers::te_offset_short(value).unwrap();
|
||||
let unpacked = Helpers::te_offset_float(packed.to_le_bytes().to_vec(), 0).unwrap();
|
||||
let rounded = (unpacked * 1000.0).round() / 1000.0;
|
||||
assert!(
|
||||
(rounded - value).abs() < f32::from_bits(1),
|
||||
"{rounded} is not equal to {value}"
|
||||
);
|
||||
value += 0.001;
|
||||
}
|
||||
}
|
||||
|
||||
// parity-case: LibreMetaverse.Tests/PrimObjectTests.cs::PrimObjectTests.TextureEntry::test 0670a9a8dcc4001e726df699ef8001604956b6674028a192502b92b725858990 translated
|
||||
#[test]
|
||||
fn texture_entry() {
|
||||
let mut entry = PrimitiveTextureEntry::new_with_uuid(uuid()).unwrap();
|
||||
let face = entry.create_face(0).unwrap();
|
||||
face.set_bump(Bumpiness::Concrete);
|
||||
face.set_fullbright(true);
|
||||
face.set_media_flags(true);
|
||||
face.set_offset_u(0.5);
|
||||
face.set_offset_v(-0.5);
|
||||
face.set_repeat_u(3.0);
|
||||
face.set_repeat_v(4.0);
|
||||
face.set_rgba(Color4 {
|
||||
r: 0.0,
|
||||
g: 0.25,
|
||||
b: 0.75,
|
||||
a: 1.0,
|
||||
});
|
||||
face.set_rotation(1.5);
|
||||
face.set_shiny(Shininess::Medium);
|
||||
face.set_tex_map_type(MappingType::Planar);
|
||||
face.set_texture_id(uuid());
|
||||
let first = entry.get_bytes().unwrap();
|
||||
let length = i32::try_from(first.len()).expect("TextureEntry length fits Int32");
|
||||
let decoded =
|
||||
PrimitiveTextureEntry::new_with_bytes_int32_int32(first.clone(), 0, length).unwrap();
|
||||
let second = decoded.get_bytes().unwrap();
|
||||
assert_eq!(first.len(), second.len());
|
||||
for (index, (actual, expected)) in first.iter().zip(&second).enumerate() {
|
||||
assert_eq!(actual, expected, "byte {index} is not equal");
|
||||
}
|
||||
}
|
||||
|
||||
// parity-case: LibreMetaverse.Tests/PrimObjectTests.cs::PrimObjectTests.TextureEntry_RenderMaterialID_DefaultFace_Roundtrips::test 8db56b448e53e6bec5540a5a4721dc75f85a933c6c89e166f7df7baf8e44aab3 translated
|
||||
#[test]
|
||||
fn render_material_id_default_face_round_trips() {
|
||||
let material = uuid();
|
||||
let mut entry = PrimitiveTextureEntry::new_with_uuid(uuid()).unwrap();
|
||||
entry
|
||||
.default_texture
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.set_render_material_id(material);
|
||||
assert_eq!(
|
||||
round_trip(&entry)
|
||||
.default_texture
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.render_material_id(),
|
||||
material
|
||||
);
|
||||
}
|
||||
|
||||
// parity-case: LibreMetaverse.Tests/PrimObjectTests.cs::PrimObjectTests.TextureEntry_RenderMaterialID_PerFace_Roundtrips::test 2897366ecaa41f07b4db6ebf3e80a7ebe56480f1c44f31cedea2d88a62214dc6 translated
|
||||
#[test]
|
||||
fn render_material_id_per_face_round_trips() {
|
||||
let material = uuid();
|
||||
let mut entry = PrimitiveTextureEntry::new_with_uuid(uuid()).unwrap();
|
||||
entry
|
||||
.create_face(0)
|
||||
.unwrap()
|
||||
.set_render_material_id(material);
|
||||
let decoded = round_trip(&entry);
|
||||
assert_eq!(face(&decoded, 0).render_material_id(), material);
|
||||
assert_eq!(
|
||||
decoded
|
||||
.default_texture
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.render_material_id(),
|
||||
UUID::zero()
|
||||
);
|
||||
}
|
||||
|
||||
// parity-case: LibreMetaverse.Tests/PrimObjectTests.cs::PrimObjectTests.TextureEntry_RenderMaterialID_MultipleFaces_Roundtrips::test f3d8c103e4b3d43a8e3bea1356ba13808633fdb2ea06583234551f9059b2a241 translated
|
||||
#[test]
|
||||
fn render_material_id_multiple_faces_round_trip() {
|
||||
let default_material = uuid();
|
||||
let first = uuid();
|
||||
let second = uuid();
|
||||
let mut entry = PrimitiveTextureEntry::new_with_uuid(uuid()).unwrap();
|
||||
entry
|
||||
.default_texture
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.set_render_material_id(default_material);
|
||||
entry.create_face(0).unwrap().set_render_material_id(first);
|
||||
entry.create_face(1).unwrap().set_render_material_id(second);
|
||||
let decoded = round_trip(&entry);
|
||||
assert_eq!(
|
||||
decoded
|
||||
.default_texture
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.render_material_id(),
|
||||
default_material
|
||||
);
|
||||
assert_eq!(face(&decoded, 0).render_material_id(), first);
|
||||
assert_eq!(face(&decoded, 1).render_material_id(), second);
|
||||
}
|
||||
|
||||
// parity-case: LibreMetaverse.Tests/PrimObjectTests.cs::PrimObjectTests.TextureEntry_RenderMaterialID_InheritsFromDefault_WhenNotOverridden::test 2313a0134836651e23c693505c3c000ad7ff24956b432d0761a5e8b77cb01642 translated
|
||||
#[test]
|
||||
fn render_material_id_inherits_from_default_when_not_overridden() {
|
||||
let material = uuid();
|
||||
let mut entry = PrimitiveTextureEntry::new_with_uuid(uuid()).unwrap();
|
||||
entry
|
||||
.default_texture
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.set_render_material_id(material);
|
||||
let decoded = round_trip(&entry);
|
||||
assert_eq!(
|
||||
decoded
|
||||
.default_texture
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.render_material_id(),
|
||||
material
|
||||
);
|
||||
if let Some(face) = decoded.get_face(0).unwrap() {
|
||||
assert_eq!(face.render_material_id(), material);
|
||||
}
|
||||
}
|
||||
|
||||
fn high_face_round_trip(index: u32) -> bool {
|
||||
let texture = uuid();
|
||||
let mut entry = PrimitiveTextureEntry::new_with_uuid(uuid()).unwrap();
|
||||
entry.create_face(index).unwrap().set_texture_id(texture);
|
||||
let decoded = round_trip(&entry);
|
||||
face(&decoded, index as usize).texture_id() == texture
|
||||
}
|
||||
|
||||
// parity-case: LibreMetaverse.Tests/TextureEntryTests.cs::TextureEntryTests.RoundTrip_HighFace_TextureID_IsPreserved::case:d3ad6116f2458248 5f215cd1c50fa8871967653b4667f848c14ff24a3b71906e51aac13c56de1f55 translated
|
||||
#[test]
|
||||
fn high_face_32_texture_id_is_preserved() {
|
||||
assert!(high_face_round_trip(32));
|
||||
}
|
||||
|
||||
// parity-case: LibreMetaverse.Tests/TextureEntryTests.cs::TextureEntryTests.RoundTrip_HighFace_TextureID_IsPreserved::case:c6f3ac57944a5314 5f215cd1c50fa8871967653b4667f848c14ff24a3b71906e51aac13c56de1f55 translated
|
||||
#[test]
|
||||
fn high_face_33_texture_id_is_preserved() {
|
||||
assert!(high_face_round_trip(33));
|
||||
}
|
||||
|
||||
// parity-case: LibreMetaverse.Tests/TextureEntryTests.cs::TextureEntryTests.RoundTrip_HighFace_TextureID_IsPreserved::case:d59eced1ded07f84 5f215cd1c50fa8871967653b4667f848c14ff24a3b71906e51aac13c56de1f55 translated
|
||||
#[test]
|
||||
fn high_face_40_texture_id_is_preserved() {
|
||||
assert!(high_face_round_trip(40));
|
||||
}
|
||||
|
||||
// parity-case: LibreMetaverse.Tests/TextureEntryTests.cs::TextureEntryTests.RoundTrip_HighFace_TextureID_IsPreserved::case:59df3d13bd106053 5f215cd1c50fa8871967653b4667f848c14ff24a3b71906e51aac13c56de1f55 translated
|
||||
#[test]
|
||||
fn high_face_44_texture_id_is_preserved() {
|
||||
assert!(high_face_round_trip(44));
|
||||
}
|
||||
|
||||
// parity-case: LibreMetaverse.Tests/TextureEntryTests.cs::TextureEntryTests.RoundTrip_AllHighFaces_TextureIDs_AllPreserved::test 203ca43b9f1965e1fae7feb36e84eff1df9ac5968eb23753077816d16dd24228 translated
|
||||
#[test]
|
||||
fn all_high_face_texture_ids_are_preserved() {
|
||||
let mut entry = PrimitiveTextureEntry::new_with_uuid(uuid()).unwrap();
|
||||
let expected: Vec<_> = (32..PrimitiveTextureEntry::MAX_FACES)
|
||||
.map(|index| {
|
||||
let texture = uuid();
|
||||
entry
|
||||
.create_face(u32::try_from(index).expect("face index fits UInt32"))
|
||||
.unwrap()
|
||||
.set_texture_id(texture);
|
||||
texture
|
||||
})
|
||||
.collect();
|
||||
let decoded = round_trip(&entry);
|
||||
for (offset, texture) in expected.into_iter().enumerate() {
|
||||
assert_eq!(face(&decoded, offset + 32).texture_id(), texture);
|
||||
}
|
||||
}
|
||||
|
||||
// parity-case: LibreMetaverse.Tests/TextureEntryTests.cs::TextureEntryTests.RoundTrip_LowAndHighFaces_BothPreserved::test dd520cac107415a186a44eb3a17bd000f933ec49b814a496e6788237fcfffb1e translated
|
||||
#[test]
|
||||
fn low_and_high_faces_are_both_preserved() {
|
||||
let mut entry = PrimitiveTextureEntry::new_with_uuid(uuid()).unwrap();
|
||||
let expected = [(0, uuid()), (15, uuid()), (32, uuid()), (44, uuid())];
|
||||
for (index, texture) in expected {
|
||||
entry.create_face(index).unwrap().set_texture_id(texture);
|
||||
}
|
||||
let decoded = round_trip(&entry);
|
||||
for (index, texture) in expected {
|
||||
assert_eq!(
|
||||
face(&decoded, index as usize).texture_id(),
|
||||
texture,
|
||||
"face {index}"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// parity-case: LibreMetaverse.Tests/TextureEntryTests.cs::TextureEntryTests.RoundTrip_Face32_RGBA_IsPreserved::test db41d130d270d31f52f3928df88ccc052102673c1afbca03cc0648526fafbabb translated
|
||||
#[test]
|
||||
fn face_32_rgba_is_preserved() {
|
||||
let mut entry = PrimitiveTextureEntry::new_with_uuid(uuid()).unwrap();
|
||||
entry.default_texture.as_mut().unwrap().set_rgba(Color4 {
|
||||
r: 1.0,
|
||||
g: 1.0,
|
||||
b: 1.0,
|
||||
a: 1.0,
|
||||
});
|
||||
entry.create_face(32).unwrap().set_rgba(Color4 {
|
||||
r: 1.0,
|
||||
g: 0.0,
|
||||
b: 0.0,
|
||||
a: 1.0,
|
||||
});
|
||||
let color = face(&round_trip(&entry), 32).rgba();
|
||||
assert!((color.r - 1.0).abs() <= 0.01);
|
||||
assert!(color.g.abs() <= 0.01);
|
||||
assert!(color.b.abs() <= 0.01);
|
||||
}
|
||||
|
||||
// parity-case: LibreMetaverse.Tests/TextureEntryTests.cs::TextureEntryTests.RoundTrip_Face32_RepeatU_IsPreserved::test 58e80815263025ec54cd15e3c9a42771f5e55c81e9acb212a0f163faef9fd499 translated
|
||||
#[test]
|
||||
fn face_32_repeat_u_is_preserved() {
|
||||
let mut entry = PrimitiveTextureEntry::new_with_uuid(uuid()).unwrap();
|
||||
entry.create_face(32).unwrap().set_repeat_u(4.0);
|
||||
assert!((face(&round_trip(&entry), 32).repeat_u() - 4.0).abs() <= 0.01);
|
||||
}
|
||||
|
||||
// parity-case: LibreMetaverse.Tests/TextureEntryTests.cs::TextureEntryTests.RoundTrip_Face32_RepeatV_IsPreserved::test fbeb1fdd584a26576b6f1ba653b2995d1a6d6bccc2c1dc51e46aa9f211b78724 translated
|
||||
#[test]
|
||||
fn face_32_repeat_v_is_preserved() {
|
||||
let mut entry = PrimitiveTextureEntry::new_with_uuid(uuid()).unwrap();
|
||||
entry.create_face(32).unwrap().set_repeat_v(4.0);
|
||||
assert!((face(&round_trip(&entry), 32).repeat_v() - 4.0).abs() <= 0.01);
|
||||
}
|
||||
|
||||
// parity-case: LibreMetaverse.Tests/TextureEntryTests.cs::TextureEntryTests.RoundTrip_AllFaces_TextureIDs_AllPreserved::test 5e5a390af8deff77ef80f751735456541f24d7e27666557d50d99065cc3ba6a4 translated
|
||||
#[test]
|
||||
fn all_face_texture_ids_are_preserved() {
|
||||
let mut entry = PrimitiveTextureEntry::new_with_uuid(uuid()).unwrap();
|
||||
let expected: Vec<_> = (0..PrimitiveTextureEntry::MAX_FACES)
|
||||
.map(|index| {
|
||||
let texture = uuid();
|
||||
entry
|
||||
.create_face(u32::try_from(index).expect("face index fits UInt32"))
|
||||
.unwrap()
|
||||
.set_texture_id(texture);
|
||||
texture
|
||||
})
|
||||
.collect();
|
||||
let decoded = round_trip(&entry);
|
||||
for (index, texture) in expected.into_iter().enumerate() {
|
||||
assert_eq!(face(&decoded, index).texture_id(), texture, "face {index}");
|
||||
}
|
||||
}
|
||||
|
||||
// parity-case: LibreMetaverse.Tests/PrimitiveTests.cs::PrimitiveTests.GetOSD_FromOSD_Roundtrip_Minimal::test 5e81b8a195f3e59bfe9e3ebf50c3291f7cbcd49f567ede7c1c8b726e0c6c9c19 translated
|
||||
#[test]
|
||||
fn primitive_osd_round_trip_minimal() {
|
||||
let mut primitive = Primitive::new_with_constructor().unwrap();
|
||||
primitive.id = uuid();
|
||||
primitive.local_id = 12_345;
|
||||
primitive.parent_id = 54_321;
|
||||
primitive.flags =
|
||||
PrimFlags(PrimFlags::PHANTOM.0 | PrimFlags::PHYSICS.0 | PrimFlags::CAST_SHADOWS.0);
|
||||
primitive.position = Vector3 {
|
||||
x: 1.1,
|
||||
y: 2.2,
|
||||
z: 3.3,
|
||||
};
|
||||
primitive.rotation = Quaternion {
|
||||
x: 0.1,
|
||||
y: 0.2,
|
||||
z: 0.3,
|
||||
w: 0.9,
|
||||
};
|
||||
primitive.scale = Vector3 {
|
||||
x: 0.5,
|
||||
y: 0.6,
|
||||
z: 0.7,
|
||||
};
|
||||
let mut data = PrimitiveConstructionData::new_with_constructor().unwrap();
|
||||
data.material = Material::Wood;
|
||||
data.p_code = PCode::Prim;
|
||||
data.state = 7;
|
||||
data.path_curve = PathCurve::Circle;
|
||||
data.path_scale_x = 1.2;
|
||||
data.path_scale_y = 0.8;
|
||||
data.profile_begin = 0.0;
|
||||
data.profile_end = 1.0;
|
||||
data.profile_hollow = 0.1;
|
||||
data.set_profile_curve_with_property(ProfileCurve::Square);
|
||||
data.set_profile_hole(HoleType(1));
|
||||
primitive.prim_data = data;
|
||||
let mut properties = PrimitiveObjectProperties::new().unwrap();
|
||||
properties.name = "TestPrim".into();
|
||||
properties.description = "A primitive used in unit tests".into();
|
||||
primitive.properties = Some(properties);
|
||||
let decoded = Primitive::from_osd(primitive.get_osd().unwrap()).unwrap();
|
||||
assert_eq!(decoded.id, primitive.id);
|
||||
assert_eq!(decoded.local_id, primitive.local_id);
|
||||
assert_eq!(decoded.parent_id, primitive.parent_id);
|
||||
assert_ne!(decoded.flags.0 & PrimFlags::PHANTOM.0, 0);
|
||||
assert_ne!(decoded.flags.0 & PrimFlags::PHYSICS.0, 0);
|
||||
assert_ne!(decoded.flags.0 & PrimFlags::CAST_SHADOWS.0, 0);
|
||||
assert_vector(decoded.position, primitive.position);
|
||||
assert_quaternion(decoded.rotation, primitive.rotation);
|
||||
assert_vector(decoded.scale, primitive.scale);
|
||||
assert_eq!(decoded.prim_data.material, primitive.prim_data.material);
|
||||
assert_eq!(decoded.prim_data.p_code, primitive.prim_data.p_code);
|
||||
assert_eq!(decoded.prim_data.state, primitive.prim_data.state);
|
||||
assert_eq!(decoded.prim_data.path_curve, primitive.prim_data.path_curve);
|
||||
assert_eq!(
|
||||
decoded.prim_data.path_scale_x,
|
||||
primitive.prim_data.path_scale_x
|
||||
);
|
||||
assert_eq!(
|
||||
decoded.prim_data.path_scale_y,
|
||||
primitive.prim_data.path_scale_y
|
||||
);
|
||||
assert_eq!(
|
||||
decoded.prim_data.profile_begin,
|
||||
primitive.prim_data.profile_begin
|
||||
);
|
||||
assert_eq!(
|
||||
decoded.prim_data.profile_end,
|
||||
primitive.prim_data.profile_end
|
||||
);
|
||||
assert_eq!(
|
||||
decoded.prim_data.profile_hollow,
|
||||
primitive.prim_data.profile_hollow
|
||||
);
|
||||
assert_eq!(
|
||||
decoded.prim_data.profile_curve_with_property(),
|
||||
primitive.prim_data.profile_curve_with_property()
|
||||
);
|
||||
assert_eq!(
|
||||
decoded.prim_data.profile_hole(),
|
||||
primitive.prim_data.profile_hole()
|
||||
);
|
||||
let decoded_properties = decoded.properties.as_ref().expect("properties");
|
||||
let original_properties = primitive.properties.as_ref().unwrap();
|
||||
assert_eq!(decoded_properties.name, original_properties.name);
|
||||
assert_eq!(
|
||||
decoded_properties.description,
|
||||
original_properties.description
|
||||
);
|
||||
}
|
||||
|
||||
// parity-case: LibreMetaverse.Tests/PrimitiveTests.cs::PrimitiveTests.GetOSD_FromOSD_Roundtrip_Extras::test 63bae8bddacab170aec00c6d7a219f96fa794f489190b34cb426bbf9a3672af5 translated
|
||||
#[test]
|
||||
fn primitive_osd_round_trip_extras() {
|
||||
let mut primitive = Primitive::new_with_constructor().unwrap();
|
||||
primitive.id = uuid();
|
||||
let mut flexible = PrimitiveFlexibleData::new_with_constructor().unwrap();
|
||||
flexible.softness = 3;
|
||||
flexible.tension = 1.5;
|
||||
flexible.drag = 0.7;
|
||||
flexible.gravity = -9.8;
|
||||
flexible.wind = 0.2;
|
||||
flexible.force = Vector3 {
|
||||
x: 0.1,
|
||||
y: 0.2,
|
||||
z: 0.3,
|
||||
};
|
||||
primitive.flexible = Some(flexible);
|
||||
let mut light = PrimitiveLightData::new_with_constructor().unwrap();
|
||||
light.color = Color4 {
|
||||
r: 0.2,
|
||||
g: 0.4,
|
||||
b: 0.6,
|
||||
a: 1.0,
|
||||
};
|
||||
light.intensity = 0.8;
|
||||
light.radius = 10.0;
|
||||
light.cutoff = 0.5;
|
||||
light.falloff = 2.0;
|
||||
primitive.light = Some(light);
|
||||
let mut image = PrimitiveLightImage::new_with_constructor().unwrap();
|
||||
image.light_texture = uuid();
|
||||
image.params = Vector3 {
|
||||
x: 1.0,
|
||||
y: 2.0,
|
||||
z: 3.0,
|
||||
};
|
||||
primitive.light_map = Some(image);
|
||||
let mut sculpt = PrimitiveSculptData::new_with_constructor().unwrap();
|
||||
sculpt.sculpt_texture = uuid();
|
||||
sculpt.set_type_(SculptType::Mesh);
|
||||
primitive.sculpt = Some(sculpt);
|
||||
let decoded = Primitive::from_osd(primitive.get_osd().unwrap()).unwrap();
|
||||
let (actual, expected) = (
|
||||
decoded.flexible.as_ref().unwrap(),
|
||||
primitive.flexible.as_ref().unwrap(),
|
||||
);
|
||||
assert_eq!(
|
||||
(
|
||||
actual.softness,
|
||||
actual.tension,
|
||||
actual.drag,
|
||||
actual.gravity,
|
||||
actual.wind
|
||||
),
|
||||
(
|
||||
expected.softness,
|
||||
expected.tension,
|
||||
expected.drag,
|
||||
expected.gravity,
|
||||
expected.wind
|
||||
)
|
||||
);
|
||||
assert_vector(actual.force, expected.force);
|
||||
let (actual, expected) = (
|
||||
decoded.light.as_ref().unwrap(),
|
||||
primitive.light.as_ref().unwrap(),
|
||||
);
|
||||
assert_eq!(
|
||||
(
|
||||
actual.color.r,
|
||||
actual.color.g,
|
||||
actual.color.b,
|
||||
actual.intensity,
|
||||
actual.radius,
|
||||
actual.cutoff,
|
||||
actual.falloff
|
||||
),
|
||||
(
|
||||
expected.color.r,
|
||||
expected.color.g,
|
||||
expected.color.b,
|
||||
expected.intensity,
|
||||
expected.radius,
|
||||
expected.cutoff,
|
||||
expected.falloff
|
||||
)
|
||||
);
|
||||
let (actual, expected) = (
|
||||
decoded.light_map.as_ref().unwrap(),
|
||||
primitive.light_map.as_ref().unwrap(),
|
||||
);
|
||||
assert_eq!(actual.light_texture, expected.light_texture);
|
||||
assert_vector(actual.params, expected.params);
|
||||
let (actual, expected) = (
|
||||
decoded.sculpt.as_ref().unwrap(),
|
||||
primitive.sculpt.as_ref().unwrap(),
|
||||
);
|
||||
assert_eq!(actual.sculpt_texture, expected.sculpt_texture);
|
||||
assert_eq!(actual.type_(), expected.type_());
|
||||
}
|
||||
|
||||
// parity-case: LibreMetaverse.Tests/PrimitiveTests.cs::PrimitiveTests.FromOSD_MissingVolume_DoesNotThrow_AndUsesDefaults::test 03f9369aab6f6a71ee13982a7b6ba9780f86bcb5b6f081f9550f491b692f711c translated
|
||||
#[test]
|
||||
fn primitive_from_osd_missing_volume_uses_defaults() {
|
||||
let id = uuid();
|
||||
let primitive = Primitive::from_osd(OSD::Map(HashMap::from([
|
||||
("id".into(), OSD::UUID(id)),
|
||||
("localid".into(), OSD::Integer(99)),
|
||||
("parentid".into(), OSD::Integer(100)),
|
||||
])))
|
||||
.unwrap();
|
||||
assert_eq!(primitive.id, id);
|
||||
assert_eq!(primitive.local_id, 99);
|
||||
assert_eq!(primitive.parent_id, 100);
|
||||
assert_eq!(primitive.prim_data.path_curve, PathCurve::Line);
|
||||
assert_eq!(
|
||||
primitive.prim_data.profile_curve_with_property(),
|
||||
ProfileCurve::Circle
|
||||
);
|
||||
assert_eq!(primitive.prim_data.profile_end, 1.0);
|
||||
}
|
||||
|
||||
// parity-case: LibreMetaverse.Tests/PrimitiveTests.cs::PrimitiveTests.FromOSD_WrongTypes_ForTransforms_AreIgnored::test a23d4b1ab6d24c11c96862bc18ba57fccf1a8a1d690c90c5e8da3092973220f7 translated
|
||||
#[test]
|
||||
fn primitive_from_osd_wrong_transform_types_are_ignored() {
|
||||
let primitive = Primitive::from_osd(OSD::Map(HashMap::from([
|
||||
("position".into(), OSD::String("not-a-vector".into())),
|
||||
("rotation".into(), OSD::Integer(123)),
|
||||
("scale".into(), OSD::String("also-not-a-vector".into())),
|
||||
])))
|
||||
.unwrap();
|
||||
assert_vector(
|
||||
primitive.position,
|
||||
Vector3 {
|
||||
x: 0.0,
|
||||
y: 0.0,
|
||||
z: 0.0,
|
||||
},
|
||||
);
|
||||
assert_quaternion(
|
||||
primitive.rotation,
|
||||
Quaternion {
|
||||
x: 0.0,
|
||||
y: 0.0,
|
||||
z: 0.0,
|
||||
w: 1.0,
|
||||
},
|
||||
);
|
||||
assert_vector(
|
||||
primitive.scale,
|
||||
Vector3 {
|
||||
x: 1.0,
|
||||
y: 1.0,
|
||||
z: 1.0,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
// parity-case: LibreMetaverse.Tests/PrimitiveTests.cs::PrimitiveTests.FromOSD_PartialProfile_UsesDefaultsForMissingFields::test f3a3e506e3ef417f6323875db82179a4ffbdc1d4ee383417f2b0bd5afd0d0dba translated
|
||||
#[test]
|
||||
fn primitive_from_osd_partial_profile_uses_defaults() {
|
||||
let profile = OSD::Map(HashMap::from([(
|
||||
"curve".into(),
|
||||
OSD::Integer(ProfileCurve::EqualTriangle as i32),
|
||||
)]));
|
||||
let volume = OSD::Map(HashMap::from([("profile".into(), profile)]));
|
||||
let primitive =
|
||||
Primitive::from_osd(OSD::Map(HashMap::from([("volume".into(), volume)]))).unwrap();
|
||||
assert_eq!(
|
||||
primitive.prim_data.profile_curve_with_property(),
|
||||
ProfileCurve::EqualTriangle
|
||||
);
|
||||
assert_eq!(primitive.prim_data.profile_begin, 0.0);
|
||||
assert_eq!(primitive.prim_data.profile_end, 1.0);
|
||||
assert_eq!(primitive.prim_data.profile_hollow, 0.0);
|
||||
}
|
||||
60
tests/compat/tests/world_packet_semantics.rs
Normal file
60
tests/compat/tests/world_packet_semantics.rs
Normal file
@@ -0,0 +1,60 @@
|
||||
// Exact Rust translation of LibreMetaverse.Tests/StartAuctionTests.cs.
|
||||
// Source SHA-256: 7087a3957277dc76a018ff3478e69c556f33a890ada9ad2c8c53f3fc34ec7375
|
||||
|
||||
use libremetaverse::packets::{
|
||||
Packet, PacketType, ViewerStartAuctionPacket, ViewerStartAuctionPacketAgentDataBlock,
|
||||
ViewerStartAuctionPacketParcelDataBlock,
|
||||
};
|
||||
use libremetaverse::{GridClient, Simulator};
|
||||
use libremetaverse_types::UUID;
|
||||
|
||||
fn uuid() -> UUID {
|
||||
UUID::random().expect("UUID Random")
|
||||
}
|
||||
|
||||
// parity-case: LibreMetaverse.Tests/StartAuctionTests.cs::StartAuctionTests.ViewerStartAuctionPacket_RoundTripsAgentAndParcelFields::test f37ef06cfba37754effe04a0bb0edfa159c761b811a05efd95157896756bef16 translated
|
||||
#[test]
|
||||
fn viewer_start_auction_packet_round_trips_agent_and_parcel_fields() {
|
||||
let agent = uuid();
|
||||
let session = uuid();
|
||||
let snapshot = uuid();
|
||||
let packet = ViewerStartAuctionPacket {
|
||||
agent_data: ViewerStartAuctionPacketAgentDataBlock {
|
||||
agent_id: agent,
|
||||
session_id: session,
|
||||
},
|
||||
parcel_data: ViewerStartAuctionPacketParcelDataBlock {
|
||||
local_id: 12_345,
|
||||
snapshot_id: snapshot,
|
||||
},
|
||||
};
|
||||
let bytes = packet.to_bytes_with_method().unwrap();
|
||||
let mut end = i32::try_from(bytes.len()).expect("packet length fits Int32") - 1;
|
||||
let built =
|
||||
Packet::build_packet_with_bytes_int32_bytes(bytes.clone(), &mut end, Vec::new()).unwrap();
|
||||
assert_eq!(built.type_, PacketType::ViewerStartAuction);
|
||||
let mut position = 0;
|
||||
let parsed = ViewerStartAuctionPacket::new_with_bytes_int32(bytes, &mut position).unwrap();
|
||||
assert_eq!(parsed.agent_data.agent_id, agent);
|
||||
assert_eq!(parsed.agent_data.session_id, session);
|
||||
assert_eq!(parsed.parcel_data.local_id, 12_345);
|
||||
assert_eq!(parsed.parcel_data.snapshot_id, snapshot);
|
||||
}
|
||||
|
||||
// parity-case: LibreMetaverse.Tests/StartAuctionTests.cs::StartAuctionTests.StartAuction_DoesNotThrow::test deec194333b480dabb3f6e6d96b360a29d11a40ca1103117fc7ce5cdb80d6eb0 translated
|
||||
#[test]
|
||||
fn start_auction_does_not_throw() {
|
||||
let client = GridClient::new().expect("GridClient constructor");
|
||||
let simulator = Simulator::new(
|
||||
GridClient::new().expect("simulator GridClient constructor"),
|
||||
"127.0.0.1:13".parse().unwrap(),
|
||||
0,
|
||||
None,
|
||||
None,
|
||||
)
|
||||
.expect("Simulator constructor");
|
||||
client
|
||||
.parcels()
|
||||
.start_auction(simulator, 1, uuid())
|
||||
.unwrap();
|
||||
}
|
||||
Reference in New Issue
Block a user