From 39da0872ea2e1bdd805d447ad9b5db3104bf394c Mon Sep 17 00:00:00 2001 From: Mike Dickson Date: Wed, 24 Apr 2024 15:52:57 -0400 Subject: [PATCH] Remove tests as they are non functional. We will add them back in later. Remove some funkiness with copying of DLLs for System.Drawing. We're pulling the v6.0 version from Nuget which is bad enough but at least this way its pinned or replaced in code. --- .../Tests/FetchInventory2HandlerTests.cs | 170 -- .../FetchInventoryDescendents2HandlerTests.cs | 303 ---- .../Tests/GetTextureHandlerTests.cs | 64 - ...OpenSim.Capabilities.Handlers.Tests.csproj | 5 +- .../OpenSim.Capabilities.Handlers.csproj | 5 +- OpenSim/Data/Tests/AssetTests.cs | 220 --- OpenSim/Data/Tests/BasicDataServiceTest.cs | 271 ---- OpenSim/Data/Tests/DataTestUtil.cs | 88 - OpenSim/Data/Tests/DefaultTestConns.cs | 90 -- OpenSim/Data/Tests/EstateTests.cs | 511 ------ OpenSim/Data/Tests/InventoryTests.cs | 369 ----- OpenSim/Data/Tests/OpenSim.Data.Tests.csproj | 42 - .../Data/Tests/PropertyCompareConstraint.cs | 413 ----- OpenSim/Data/Tests/PropertyScrambler.cs | 184 --- OpenSim/Data/Tests/RegionTests.cs | 1145 ------------- .../Tests/Resources/TestDataConnections.ini | 24 - OpenSim/Framework/OpenSim.Framework.csproj | 5 +- .../Tests/LandDataSerializerTests.cs | 166 -- ...enSim.Framework.Serialization.Tests.csproj | 32 - .../Tests/RegionSettingsSerializerTests.cs | 142 -- .../OpenSim.Framework.Servers.Tests.csproj | 19 - .../Servers/Tests/VersionInfoTests.cs | 45 - .../Framework/Tests/AgentCircuitDataTest.cs | 351 ---- .../Tests/AgentCircuitManagerTests.cs | 199 --- OpenSim/Framework/Tests/AnimationTests.cs | 91 -- OpenSim/Framework/Tests/AssetBaseTest.cs | 72 - OpenSim/Framework/Tests/CacheTests.cs | 125 -- OpenSim/Framework/Tests/LocationTest.cs | 90 -- .../Framework/Tests/MundaneFrameworkTests.cs | 289 ---- .../Tests/OpenSim.Framework.Tests.csproj | 39 - .../Framework/Tests/PrimeNumberHelperTests.cs | 144 -- OpenSim/Framework/Tests/UtilTest.cs | 360 ----- OpenSim/Region/Application/Application.cs | 43 +- .../Caps/EventQueue/Tests/EventQueueTests.cs | 201 --- .../Caps/Tests/WebFetchInvDescModuleTests.cs | 161 -- .../Linden/UDP/Tests/BasicCircuitTests.cs | 273 ---- .../Linden/UDP/Tests/LLImageManagerTests.cs | 174 -- ....Region.ClientStack.LindenUDP.Tests.csproj | 36 - .../Linden/UDP/Tests/PacketHandlerTests.cs | 104 -- .../Linden/UDP/Tests/Resources/4-tile2.jp2 | Bin 24410 -> 0 bytes .../Linden/UDP/Tests/ThrottleTests.cs | 432 ----- .../Asset/Tests/FlotsamAssetCacheTests.cs | 127 -- .../Tests/AttachmentsModuleTests.cs | 1030 ------------ .../Tests/AvatarFactoryModuleTests.cs | 197 --- .../Avatar/Chat/Tests/ChatModuleTests.cs | 320 ---- .../Avatar/Friends/Tests/FriendModuleTests.cs | 209 --- .../Tests/InventoryArchiveLoadPathTests.cs | 360 ----- .../Tests/InventoryArchiveLoadTests.cs | 192 --- .../Tests/InventoryArchiveSaveTests.cs | 422 ----- .../Tests/InventoryArchiveTestCase.cs | 176 -- .../Tests/InventoryTransferModuleTests.cs | 448 ------ .../Tests/HGAssetMapperTests.cs | 148 -- .../Tests/InventoryAccessModuleTests.cs | 177 -- .../Tests/HGUserManagementModuleTests.cs | 75 - .../OpenSim.Region.CoreModules.Tests.csproj | 5 +- .../OpenSim.Region.CoreModules.csproj | 3 - .../Tests/ScriptsHttpRequestsTests.cs | 199 --- .../Tests/VectorRenderModuleTests.cs | 321 ---- .../Asset/Tests/AssetConnectorTests.cs | 174 -- .../Grid/Tests/GridConnectorsTests.cs | 201 --- .../Presence/Tests/PresenceConnectorsTests.cs | 116 -- .../World/Archiver/Tests/ArchiverTests.cs | 1056 ------------ .../Archiver/Tests/Resources/test-sound.wav | Bin 211648 -> 0 bytes .../Land/Tests/LandManagementModuleTests.cs | 266 --- .../World/Land/Tests/PrimCountModuleTests.cs | 382 ----- .../World/Media/Moap/Tests/MoapTests.cs | 102 -- .../World/Serialiser/Tests/SerialiserTests.cs | 884 ---------- .../World/Terrain/Tests/TerrainModuleTests.cs | 75 - .../World/Terrain/Tests/TerrainTest.cs | 119 -- .../OpenSim.Region.Framework.Tests.csproj | 5 +- .../Framework/OpenSim.Region.Framework.csproj | 5 +- .../Scenes/Tests/EntityManagerTests.cs | 177 -- .../Framework/Scenes/Tests/SceneGraphTests.cs | 91 -- .../Scenes/Tests/SceneManagerTests.cs | 56 - .../Scenes/Tests/SceneObjectBasicTests.cs | 244 --- .../Scenes/Tests/SceneObjectCopyTests.cs | 348 ---- .../Scenes/Tests/SceneObjectCrossingTests.cs | 287 ---- .../Scenes/Tests/SceneObjectDeRezTests.cs | 260 --- .../Scenes/Tests/SceneObjectLinkingTests.cs | 373 ----- .../Scenes/Tests/SceneObjectResizeTests.cs | 102 -- .../Scenes/Tests/SceneObjectScriptTests.cs | 74 - .../Tests/SceneObjectSerializationTests.cs | 135 -- .../Scenes/Tests/SceneObjectSpatialTests.cs | 153 -- .../Scenes/Tests/SceneObjectStatusTests.cs | 242 --- .../Scenes/Tests/SceneObjectUndoRedoTests.cs | 184 --- .../Scenes/Tests/SceneObjectUserGroupTests.cs | 83 - .../Scenes/Tests/ScenePresenceAgentTests.cs | 291 ---- .../Tests/ScenePresenceAnimationTests.cs | 68 - .../Tests/ScenePresenceAutopilotTests.cs | 131 -- .../Tests/ScenePresenceCapabilityTests.cs | 88 - .../Tests/ScenePresenceCrossingTests.cs | 247 --- .../Scenes/Tests/ScenePresenceSitTests.cs | 251 --- .../Tests/ScenePresenceTeleportTests.cs | 694 -------- .../Scenes/Tests/SceneStatisticsTests.cs | 69 - .../Scenes/Tests/SceneTelehubTests.cs | 118 -- .../Framework/Scenes/Tests/SceneTests.cs | 107 -- .../Scenes/Tests/SharedRegionModuleTests.cs | 249 --- .../Scenes/Tests/TaskInventoryTests.cs | 175 -- .../Scenes/Tests/UserInventoryTests.cs | 200 --- .../Scenes/Tests/UuidGathererTests.cs | 160 -- .../XmlRpcGroups/Tests/GroupsModuleTests.cs | 276 ---- .../OpenSim.Region.OptionalModules.csproj | 5 +- .../Tests/JsonStoreScriptModuleTests.cs | 900 ----------- .../World/NPC/Tests/NPCModuleTests.cs | 486 ------ .../BulletS/Tests/BasicVehicles.cs | 152 -- .../BulletS/Tests/BulletSimTests.cs | 50 - .../BulletS/Tests/BulletSimTestsUtil.cs | 111 -- .../BulletS/Tests/HullCreation.cs | 205 --- ....Region.PhysicsModule.BulletS.Tests.csproj | 33 - .../PhysicsModules/BulletS/Tests/Raycast.cs | 126 -- ...penSim.Region.PhysicsModule.Meshing.csproj | 5 +- ...m.Region.PhysicsModule.ubOdeMeshing.csproj | 5 +- ...nSim.Region.ScriptEngine.Shared.Api.csproj | 5 +- .../Shared/Tests/LSL_ApiAvatarTests.cs | 165 -- .../Shared/Tests/LSL_ApiHttpTests.cs | 253 --- .../Shared/Tests/LSL_ApiInventoryTests.cs | 300 ---- .../Shared/Tests/LSL_ApiLinkingTests.cs | 192 --- .../Shared/Tests/LSL_ApiListTests.cs | 139 -- .../Shared/Tests/LSL_ApiNotecardTests.cs | 269 ---- .../Shared/Tests/LSL_ApiObjectTests.cs | 399 ----- .../ScriptEngine/Shared/Tests/LSL_ApiTest.cs | 278 ---- .../Shared/Tests/LSL_ApiUserTests.cs | 157 -- .../Shared/Tests/LSL_TypesTestLSLFloat.cs | 661 -------- .../Shared/Tests/LSL_TypesTestLSLInteger.cs | 150 -- .../Shared/Tests/LSL_TypesTestLSLString.cs | 144 -- .../Shared/Tests/LSL_TypesTestList.cs | 295 ---- .../Shared/Tests/LSL_TypesTestVector3.cs | 63 - .../Shared/Tests/OSSL_ApiAppearanceTest.cs | 167 -- .../Shared/Tests/OSSL_ApiAttachmentTests.cs | 234 --- .../Shared/Tests/OSSL_ApiNpcTests.cs | 354 ---- .../Tests/AssetServerPostHandlerTests.cs | 109 -- OpenSim/Server/ServerMain.cs | 43 +- .../OpenSim.Services.Connectors.csproj | 5 +- ...Sim.Services.InventoryService.Tests.csproj | 50 - .../Tests/XInventoryServiceTests.cs | 175 -- .../OpenSim.Services.SimulationService.csproj | 5 +- OpenSim/Tests/Clients/Assets/AssetsClient.cs | 124 -- .../OpenSim.Tests.Clients.AssetClient.csproj | 30 - OpenSim/Tests/Clients/Grid/GridClient.cs | 205 --- .../Common/ANumericalToleranceConstraint.cs | 56 - OpenSim/Tests/Common/DatabaseTestAttribute.cs | 44 - .../Tests/Common/DoubleToleranceConstraint.cs | 77 - OpenSim/Tests/Common/Helpers/AssetHelpers.cs | 168 -- .../Helpers/BaseRequestHandlerHelpers.cs | 75 - .../Common/Helpers/ClientStackHelpers.cs | 95 -- .../Common/Helpers/EntityTransferHelpers.cs | 123 -- OpenSim/Tests/Common/Helpers/SceneHelpers.cs | 739 --------- .../Common/Helpers/TaskInventoryHelpers.cs | 210 --- .../Common/Helpers/UserAccountHelpers.cs | 160 -- .../Common/Helpers/UserInventoryHelpers.cs | 374 ----- OpenSim/Tests/Common/LongRunningAttribute.cs | 49 - .../Tests/Common/Mock/BaseAssetRepository.cs | 62 - .../Tests/Common/Mock/MockAssetDataPlugin.cs | 70 - .../Mock/MockGroupsServicesConnector.cs | 436 ----- .../Tests/Common/Mock/MockRegionDataPlugin.cs | 375 ----- OpenSim/Tests/Common/Mock/MockScriptEngine.cs | 294 ---- OpenSim/Tests/Common/Mock/TestClient.cs | 1419 ----------------- .../Common/Mock/TestEventQueueGetModule.cs | 237 --- .../Tests/Common/Mock/TestGroupsDataPlugin.cs | 339 ---- .../Common/Mock/TestHttpClientContext.cs | 112 -- OpenSim/Tests/Common/Mock/TestHttpRequest.cs | 175 -- OpenSim/Tests/Common/Mock/TestHttpResponse.cs | 173 -- .../Common/Mock/TestInventoryDataPlugin.cs | 219 --- OpenSim/Tests/Common/Mock/TestLLUDPServer.cs | 171 -- OpenSim/Tests/Common/Mock/TestLandChannel.cs | 130 -- .../Tests/Common/Mock/TestOSHttpRequest.cs | 192 --- .../Tests/Common/Mock/TestOSHttpResponse.cs | 139 -- OpenSim/Tests/Common/Mock/TestScene.cs | 77 - .../Common/Mock/TestXInventoryDataPlugin.cs | 172 -- .../Tests/Common/OpenSim.Tests.Common.csproj | 56 - OpenSim/Tests/Common/OpenSimTestCase.cs | 55 - .../Common/QuaternionToleranceConstraint.cs | 82 - OpenSim/Tests/Common/TestHelpers.cs | 164 -- OpenSim/Tests/Common/TestLogging.cs | 46 - OpenSim/Tests/Common/TestsAssetCache.cs | 145 -- .../Tests/Common/VectorToleranceConstraint.cs | 81 - OpenSim/Tests/ConfigurationLoaderTest.cs | 150 -- OpenSim/Tests/OpenSim.Tests.csproj | 81 - .../Tests/Performance/NPCPerformanceTests.cs | 189 --- .../Performance/ObjectPerformanceTests.cs | 174 -- .../OpenSim.Tests.Performance.csproj | 46 - .../Performance/ScriptPerformanceTests.cs | 169 -- OpenSim/Tests/Permissions/Common.cs | 374 ----- .../Tests/Permissions/DirectTransferTests.cs | 153 -- .../Permissions/IndirectTransferTests.cs | 132 -- .../OpenSim.Tests.Permissions.csproj | 36 - .../Tests/Robust/Clients/Grid/GridClient.cs | 133 -- .../Tests/Robust/Clients/Grid/GridForm.html | 11 - .../Robust/Clients/InstantMessage/IMClient.cs | 58 - .../Clients/Inventory/InventoryClient.cs | 205 --- .../Robust/Clients/Presence/PresenceClient.cs | 81 - .../UserAccounts/UserAccountsClient.cs | 86 - OpenSim/Tests/Robust/Robust.Tests.csproj | 37 - OpenSim/Tests/Robust/Server/DemonServer.cs | 69 - .../Tests/Stress/OpenSim.Tests.Stress.csproj | 46 - .../Stress/VectorRenderModuleStressTests.cs | 130 -- bin/Robust.Tests.dll.config | 43 - bin/Robust.Tests.ini | 468 ------ bin/System.Drawing.Common.dll.linux | Bin 427112 -> 0 bytes bin/System.Drawing.Common.dll.win | Bin 454248 -> 0 bytes bin/prebuild.dll | Bin 245760 -> 0 bytes 201 files changed, 56 insertions(+), 38679 deletions(-) delete mode 100644 OpenSim/Capabilities/Handlers/FetchInventory/Tests/FetchInventory2HandlerTests.cs delete mode 100644 OpenSim/Capabilities/Handlers/FetchInventory/Tests/FetchInventoryDescendents2HandlerTests.cs delete mode 100644 OpenSim/Capabilities/Handlers/GetTexture/Tests/GetTextureHandlerTests.cs delete mode 100644 OpenSim/Data/Tests/AssetTests.cs delete mode 100644 OpenSim/Data/Tests/BasicDataServiceTest.cs delete mode 100644 OpenSim/Data/Tests/DataTestUtil.cs delete mode 100644 OpenSim/Data/Tests/DefaultTestConns.cs delete mode 100644 OpenSim/Data/Tests/EstateTests.cs delete mode 100644 OpenSim/Data/Tests/InventoryTests.cs delete mode 100644 OpenSim/Data/Tests/OpenSim.Data.Tests.csproj delete mode 100644 OpenSim/Data/Tests/PropertyCompareConstraint.cs delete mode 100644 OpenSim/Data/Tests/PropertyScrambler.cs delete mode 100644 OpenSim/Data/Tests/RegionTests.cs delete mode 100644 OpenSim/Data/Tests/Resources/TestDataConnections.ini delete mode 100644 OpenSim/Framework/Serialization/Tests/LandDataSerializerTests.cs delete mode 100644 OpenSim/Framework/Serialization/Tests/OpenSim.Framework.Serialization.Tests.csproj delete mode 100644 OpenSim/Framework/Serialization/Tests/RegionSettingsSerializerTests.cs delete mode 100644 OpenSim/Framework/Servers/Tests/OpenSim.Framework.Servers.Tests.csproj delete mode 100644 OpenSim/Framework/Servers/Tests/VersionInfoTests.cs delete mode 100644 OpenSim/Framework/Tests/AgentCircuitDataTest.cs delete mode 100644 OpenSim/Framework/Tests/AgentCircuitManagerTests.cs delete mode 100644 OpenSim/Framework/Tests/AnimationTests.cs delete mode 100644 OpenSim/Framework/Tests/AssetBaseTest.cs delete mode 100644 OpenSim/Framework/Tests/CacheTests.cs delete mode 100644 OpenSim/Framework/Tests/LocationTest.cs delete mode 100644 OpenSim/Framework/Tests/MundaneFrameworkTests.cs delete mode 100644 OpenSim/Framework/Tests/OpenSim.Framework.Tests.csproj delete mode 100644 OpenSim/Framework/Tests/PrimeNumberHelperTests.cs delete mode 100644 OpenSim/Framework/Tests/UtilTest.cs delete mode 100644 OpenSim/Region/ClientStack/Linden/Caps/EventQueue/Tests/EventQueueTests.cs delete mode 100644 OpenSim/Region/ClientStack/Linden/Caps/Tests/WebFetchInvDescModuleTests.cs delete mode 100644 OpenSim/Region/ClientStack/Linden/UDP/Tests/BasicCircuitTests.cs delete mode 100644 OpenSim/Region/ClientStack/Linden/UDP/Tests/LLImageManagerTests.cs delete mode 100644 OpenSim/Region/ClientStack/Linden/UDP/Tests/OpenSim.Region.ClientStack.LindenUDP.Tests.csproj delete mode 100644 OpenSim/Region/ClientStack/Linden/UDP/Tests/PacketHandlerTests.cs delete mode 100644 OpenSim/Region/ClientStack/Linden/UDP/Tests/Resources/4-tile2.jp2 delete mode 100644 OpenSim/Region/ClientStack/Linden/UDP/Tests/ThrottleTests.cs delete mode 100644 OpenSim/Region/CoreModules/Asset/Tests/FlotsamAssetCacheTests.cs delete mode 100644 OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs delete mode 100644 OpenSim/Region/CoreModules/Avatar/AvatarFactory/Tests/AvatarFactoryModuleTests.cs delete mode 100644 OpenSim/Region/CoreModules/Avatar/Chat/Tests/ChatModuleTests.cs delete mode 100644 OpenSim/Region/CoreModules/Avatar/Friends/Tests/FriendModuleTests.cs delete mode 100644 OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveLoadPathTests.cs delete mode 100644 OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveLoadTests.cs delete mode 100644 OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveSaveTests.cs delete mode 100644 OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveTestCase.cs delete mode 100644 OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/Tests/InventoryTransferModuleTests.cs delete mode 100644 OpenSim/Region/CoreModules/Framework/InventoryAccess/Tests/HGAssetMapperTests.cs delete mode 100644 OpenSim/Region/CoreModules/Framework/InventoryAccess/Tests/InventoryAccessModuleTests.cs delete mode 100644 OpenSim/Region/CoreModules/Framework/UserManagement/Tests/HGUserManagementModuleTests.cs delete mode 100644 OpenSim/Region/CoreModules/Scripting/HttpRequest/Tests/ScriptsHttpRequestsTests.cs delete mode 100644 OpenSim/Region/CoreModules/Scripting/VectorRender/Tests/VectorRenderModuleTests.cs delete mode 100644 OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/Tests/AssetConnectorTests.cs delete mode 100644 OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/Tests/GridConnectorsTests.cs delete mode 100644 OpenSim/Region/CoreModules/ServiceConnectorsOut/Presence/Tests/PresenceConnectorsTests.cs delete mode 100644 OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs delete mode 100755 OpenSim/Region/CoreModules/World/Archiver/Tests/Resources/test-sound.wav delete mode 100644 OpenSim/Region/CoreModules/World/Land/Tests/LandManagementModuleTests.cs delete mode 100644 OpenSim/Region/CoreModules/World/Land/Tests/PrimCountModuleTests.cs delete mode 100644 OpenSim/Region/CoreModules/World/Media/Moap/Tests/MoapTests.cs delete mode 100644 OpenSim/Region/CoreModules/World/Serialiser/Tests/SerialiserTests.cs delete mode 100644 OpenSim/Region/CoreModules/World/Terrain/Tests/TerrainModuleTests.cs delete mode 100644 OpenSim/Region/CoreModules/World/Terrain/Tests/TerrainTest.cs delete mode 100644 OpenSim/Region/Framework/Scenes/Tests/EntityManagerTests.cs delete mode 100644 OpenSim/Region/Framework/Scenes/Tests/SceneGraphTests.cs delete mode 100644 OpenSim/Region/Framework/Scenes/Tests/SceneManagerTests.cs delete mode 100644 OpenSim/Region/Framework/Scenes/Tests/SceneObjectBasicTests.cs delete mode 100644 OpenSim/Region/Framework/Scenes/Tests/SceneObjectCopyTests.cs delete mode 100644 OpenSim/Region/Framework/Scenes/Tests/SceneObjectCrossingTests.cs delete mode 100644 OpenSim/Region/Framework/Scenes/Tests/SceneObjectDeRezTests.cs delete mode 100644 OpenSim/Region/Framework/Scenes/Tests/SceneObjectLinkingTests.cs delete mode 100644 OpenSim/Region/Framework/Scenes/Tests/SceneObjectResizeTests.cs delete mode 100644 OpenSim/Region/Framework/Scenes/Tests/SceneObjectScriptTests.cs delete mode 100644 OpenSim/Region/Framework/Scenes/Tests/SceneObjectSerializationTests.cs delete mode 100644 OpenSim/Region/Framework/Scenes/Tests/SceneObjectSpatialTests.cs delete mode 100644 OpenSim/Region/Framework/Scenes/Tests/SceneObjectStatusTests.cs delete mode 100644 OpenSim/Region/Framework/Scenes/Tests/SceneObjectUndoRedoTests.cs delete mode 100644 OpenSim/Region/Framework/Scenes/Tests/SceneObjectUserGroupTests.cs delete mode 100644 OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAgentTests.cs delete mode 100644 OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAnimationTests.cs delete mode 100644 OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAutopilotTests.cs delete mode 100644 OpenSim/Region/Framework/Scenes/Tests/ScenePresenceCapabilityTests.cs delete mode 100644 OpenSim/Region/Framework/Scenes/Tests/ScenePresenceCrossingTests.cs delete mode 100644 OpenSim/Region/Framework/Scenes/Tests/ScenePresenceSitTests.cs delete mode 100644 OpenSim/Region/Framework/Scenes/Tests/ScenePresenceTeleportTests.cs delete mode 100644 OpenSim/Region/Framework/Scenes/Tests/SceneStatisticsTests.cs delete mode 100644 OpenSim/Region/Framework/Scenes/Tests/SceneTelehubTests.cs delete mode 100644 OpenSim/Region/Framework/Scenes/Tests/SceneTests.cs delete mode 100644 OpenSim/Region/Framework/Scenes/Tests/SharedRegionModuleTests.cs delete mode 100644 OpenSim/Region/Framework/Scenes/Tests/TaskInventoryTests.cs delete mode 100644 OpenSim/Region/Framework/Scenes/Tests/UserInventoryTests.cs delete mode 100644 OpenSim/Region/Framework/Scenes/Tests/UuidGathererTests.cs delete mode 100644 OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/Tests/GroupsModuleTests.cs delete mode 100644 OpenSim/Region/OptionalModules/Scripting/JsonStore/Tests/JsonStoreScriptModuleTests.cs delete mode 100644 OpenSim/Region/OptionalModules/World/NPC/Tests/NPCModuleTests.cs delete mode 100644 OpenSim/Region/PhysicsModules/BulletS/Tests/BasicVehicles.cs delete mode 100644 OpenSim/Region/PhysicsModules/BulletS/Tests/BulletSimTests.cs delete mode 100644 OpenSim/Region/PhysicsModules/BulletS/Tests/BulletSimTestsUtil.cs delete mode 100644 OpenSim/Region/PhysicsModules/BulletS/Tests/HullCreation.cs delete mode 100644 OpenSim/Region/PhysicsModules/BulletS/Tests/OpenSim.Region.PhysicsModule.BulletS.Tests.csproj delete mode 100755 OpenSim/Region/PhysicsModules/BulletS/Tests/Raycast.cs delete mode 100644 OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiAvatarTests.cs delete mode 100644 OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiHttpTests.cs delete mode 100644 OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiInventoryTests.cs delete mode 100644 OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiLinkingTests.cs delete mode 100644 OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiListTests.cs delete mode 100644 OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiNotecardTests.cs delete mode 100644 OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiObjectTests.cs delete mode 100644 OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiTest.cs delete mode 100644 OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiUserTests.cs delete mode 100644 OpenSim/Region/ScriptEngine/Shared/Tests/LSL_TypesTestLSLFloat.cs delete mode 100644 OpenSim/Region/ScriptEngine/Shared/Tests/LSL_TypesTestLSLInteger.cs delete mode 100644 OpenSim/Region/ScriptEngine/Shared/Tests/LSL_TypesTestLSLString.cs delete mode 100644 OpenSim/Region/ScriptEngine/Shared/Tests/LSL_TypesTestList.cs delete mode 100644 OpenSim/Region/ScriptEngine/Shared/Tests/LSL_TypesTestVector3.cs delete mode 100644 OpenSim/Region/ScriptEngine/Shared/Tests/OSSL_ApiAppearanceTest.cs delete mode 100644 OpenSim/Region/ScriptEngine/Shared/Tests/OSSL_ApiAttachmentTests.cs delete mode 100644 OpenSim/Region/ScriptEngine/Shared/Tests/OSSL_ApiNpcTests.cs delete mode 100644 OpenSim/Server/Handlers/Asset/Tests/AssetServerPostHandlerTests.cs delete mode 100644 OpenSim/Services/InventoryService/Tests/OpenSim.Services.InventoryService.Tests.csproj delete mode 100644 OpenSim/Services/InventoryService/Tests/XInventoryServiceTests.cs delete mode 100644 OpenSim/Tests/Clients/Assets/AssetsClient.cs delete mode 100644 OpenSim/Tests/Clients/Assets/OpenSim.Tests.Clients.AssetClient.csproj delete mode 100644 OpenSim/Tests/Clients/Grid/GridClient.cs delete mode 100644 OpenSim/Tests/Common/ANumericalToleranceConstraint.cs delete mode 100644 OpenSim/Tests/Common/DatabaseTestAttribute.cs delete mode 100644 OpenSim/Tests/Common/DoubleToleranceConstraint.cs delete mode 100644 OpenSim/Tests/Common/Helpers/AssetHelpers.cs delete mode 100644 OpenSim/Tests/Common/Helpers/BaseRequestHandlerHelpers.cs delete mode 100644 OpenSim/Tests/Common/Helpers/ClientStackHelpers.cs delete mode 100644 OpenSim/Tests/Common/Helpers/EntityTransferHelpers.cs delete mode 100644 OpenSim/Tests/Common/Helpers/SceneHelpers.cs delete mode 100644 OpenSim/Tests/Common/Helpers/TaskInventoryHelpers.cs delete mode 100644 OpenSim/Tests/Common/Helpers/UserAccountHelpers.cs delete mode 100644 OpenSim/Tests/Common/Helpers/UserInventoryHelpers.cs delete mode 100644 OpenSim/Tests/Common/LongRunningAttribute.cs delete mode 100644 OpenSim/Tests/Common/Mock/BaseAssetRepository.cs delete mode 100644 OpenSim/Tests/Common/Mock/MockAssetDataPlugin.cs delete mode 100644 OpenSim/Tests/Common/Mock/MockGroupsServicesConnector.cs delete mode 100644 OpenSim/Tests/Common/Mock/MockRegionDataPlugin.cs delete mode 100644 OpenSim/Tests/Common/Mock/MockScriptEngine.cs delete mode 100755 OpenSim/Tests/Common/Mock/TestClient.cs delete mode 100644 OpenSim/Tests/Common/Mock/TestEventQueueGetModule.cs delete mode 100644 OpenSim/Tests/Common/Mock/TestGroupsDataPlugin.cs delete mode 100644 OpenSim/Tests/Common/Mock/TestHttpClientContext.cs delete mode 100644 OpenSim/Tests/Common/Mock/TestHttpRequest.cs delete mode 100644 OpenSim/Tests/Common/Mock/TestHttpResponse.cs delete mode 100644 OpenSim/Tests/Common/Mock/TestInventoryDataPlugin.cs delete mode 100644 OpenSim/Tests/Common/Mock/TestLLUDPServer.cs delete mode 100644 OpenSim/Tests/Common/Mock/TestLandChannel.cs delete mode 100644 OpenSim/Tests/Common/Mock/TestOSHttpRequest.cs delete mode 100644 OpenSim/Tests/Common/Mock/TestOSHttpResponse.cs delete mode 100644 OpenSim/Tests/Common/Mock/TestScene.cs delete mode 100644 OpenSim/Tests/Common/Mock/TestXInventoryDataPlugin.cs delete mode 100644 OpenSim/Tests/Common/OpenSim.Tests.Common.csproj delete mode 100644 OpenSim/Tests/Common/OpenSimTestCase.cs delete mode 100644 OpenSim/Tests/Common/QuaternionToleranceConstraint.cs delete mode 100644 OpenSim/Tests/Common/TestHelpers.cs delete mode 100644 OpenSim/Tests/Common/TestLogging.cs delete mode 100644 OpenSim/Tests/Common/TestsAssetCache.cs delete mode 100644 OpenSim/Tests/Common/VectorToleranceConstraint.cs delete mode 100644 OpenSim/Tests/ConfigurationLoaderTest.cs delete mode 100644 OpenSim/Tests/OpenSim.Tests.csproj delete mode 100644 OpenSim/Tests/Performance/NPCPerformanceTests.cs delete mode 100644 OpenSim/Tests/Performance/ObjectPerformanceTests.cs delete mode 100644 OpenSim/Tests/Performance/OpenSim.Tests.Performance.csproj delete mode 100644 OpenSim/Tests/Performance/ScriptPerformanceTests.cs delete mode 100644 OpenSim/Tests/Permissions/Common.cs delete mode 100644 OpenSim/Tests/Permissions/DirectTransferTests.cs delete mode 100644 OpenSim/Tests/Permissions/IndirectTransferTests.cs delete mode 100644 OpenSim/Tests/Permissions/OpenSim.Tests.Permissions.csproj delete mode 100644 OpenSim/Tests/Robust/Clients/Grid/GridClient.cs delete mode 100644 OpenSim/Tests/Robust/Clients/Grid/GridForm.html delete mode 100644 OpenSim/Tests/Robust/Clients/InstantMessage/IMClient.cs delete mode 100644 OpenSim/Tests/Robust/Clients/Inventory/InventoryClient.cs delete mode 100644 OpenSim/Tests/Robust/Clients/Presence/PresenceClient.cs delete mode 100644 OpenSim/Tests/Robust/Clients/UserAccounts/UserAccountsClient.cs delete mode 100644 OpenSim/Tests/Robust/Robust.Tests.csproj delete mode 100644 OpenSim/Tests/Robust/Server/DemonServer.cs delete mode 100644 OpenSim/Tests/Stress/OpenSim.Tests.Stress.csproj delete mode 100644 OpenSim/Tests/Stress/VectorRenderModuleStressTests.cs delete mode 100644 bin/Robust.Tests.dll.config delete mode 100644 bin/Robust.Tests.ini delete mode 100644 bin/System.Drawing.Common.dll.linux delete mode 100644 bin/System.Drawing.Common.dll.win delete mode 100644 bin/prebuild.dll diff --git a/OpenSim/Capabilities/Handlers/FetchInventory/Tests/FetchInventory2HandlerTests.cs b/OpenSim/Capabilities/Handlers/FetchInventory/Tests/FetchInventory2HandlerTests.cs deleted file mode 100644 index 94c2c89f450..00000000000 --- a/OpenSim/Capabilities/Handlers/FetchInventory/Tests/FetchInventory2HandlerTests.cs +++ /dev/null @@ -1,170 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Net; -using System.Text.RegularExpressions; -using log4net; -using log4net.Config; -using NUnit.Framework; -using OpenMetaverse; -using OpenSim.Capabilities.Handlers; -using OpenSim.Framework; -using OpenSim.Framework.Servers.HttpServer; -using OpenSim.Region.Framework.Scenes; -using OpenSim.Services.Interfaces; -using OpenSim.Tests.Common; - -namespace OpenSim.Capabilities.Handlers.FetchInventory.Tests -{ - [TestFixture] - public class FetchInventory2HandlerTests : OpenSimTestCase - { - private UUID m_userID = UUID.Random(); - private Scene m_scene; - private UUID m_rootFolderID; - private UUID m_notecardsFolder; - private UUID m_objectsFolder; - - private void Init() - { - // Create an inventory that looks like this: - // - // /My Inventory - // - // /Objects - // Object 1 - // Object 2 - // Object 3 - // /Notecards - // Notecard 1 - // Notecard 2 - // Notecard 3 - // Notecard 4 - // Notecard 5 - - m_scene = new SceneHelpers().SetupScene(); - - m_scene.InventoryService.CreateUserInventory(m_userID); - - m_rootFolderID = m_scene.InventoryService.GetRootFolder(m_userID).ID; - - InventoryFolderBase of = m_scene.InventoryService.GetFolderForType(m_userID, FolderType.Object); - m_objectsFolder = of.ID; - - // Add 3 objects - InventoryItemBase item; - for (int i = 1; i <= 3; i++) - { - item = new InventoryItemBase(new UUID("b0000000-0000-0000-0000-0000000000b" + i), m_userID); - item.AssetID = UUID.Random(); - item.AssetType = (int)AssetType.Object; - item.Folder = m_objectsFolder; - item.Name = "Object " + i; - m_scene.InventoryService.AddItem(item); - } - - InventoryFolderBase ncf = m_scene.InventoryService.GetFolderForType(m_userID, FolderType.Notecard); - m_notecardsFolder = ncf.ID; - - // Add 5 notecards - for (int i = 1; i <= 5; i++) - { - item = new InventoryItemBase(new UUID("10000000-0000-0000-0000-00000000000" + i), m_userID); - item.AssetID = UUID.Random(); - item.AssetType = (int)AssetType.Notecard; - item.Folder = m_notecardsFolder; - item.Name = "Notecard " + i; - m_scene.InventoryService.AddItem(item); - } - - } - - [Test] - public void Test_001_RequestOne() - { - TestHelpers.InMethod(); - - Init(); - - FetchInventory2Handler handler = new FetchInventory2Handler(m_scene.InventoryService, m_userID); - TestOSHttpRequest req = new TestOSHttpRequest(); - TestOSHttpResponse resp = new TestOSHttpResponse(); - - string request = "itemsitem_id"; - request += "10000000-0000-0000-0000-000000000001"; // Notecard 1 - request += ""; - - string llsdresponse = handler.FetchInventoryRequest(request, "/FETCH", string.Empty, req, resp); - - Assert.That(llsdresponse != null, Is.True, "Incorrect null response"); - Assert.That(llsdresponse != string.Empty, Is.True, "Incorrect empty response"); - Assert.That(llsdresponse.Contains(m_userID.ToString()), Is.True, "Response should contain userID"); - - Assert.That(llsdresponse.Contains("10000000-0000-0000-0000-000000000001"), Is.True, "Response does not contain item uuid"); - Assert.That(llsdresponse.Contains("Notecard 1"), Is.True, "Response does not contain item Name"); - Console.WriteLine(llsdresponse); - } - - [Test] - public void Test_002_RequestMany() - { - TestHelpers.InMethod(); - - Init(); - - FetchInventory2Handler handler = new FetchInventory2Handler(m_scene.InventoryService, m_userID); - TestOSHttpRequest req = new TestOSHttpRequest(); - TestOSHttpResponse resp = new TestOSHttpResponse(); - - string request = "items"; - request += "item_id10000000-0000-0000-0000-000000000001"; // Notecard 1 - request += "item_id10000000-0000-0000-0000-000000000002"; // Notecard 2 - request += "item_id10000000-0000-0000-0000-000000000003"; // Notecard 3 - request += "item_id10000000-0000-0000-0000-000000000004"; // Notecard 4 - request += "item_id10000000-0000-0000-0000-000000000005"; // Notecard 5 - request += ""; - - string llsdresponse = handler.FetchInventoryRequest(request, "/FETCH", string.Empty, req, resp); - - Assert.That(llsdresponse != null, Is.True, "Incorrect null response"); - Assert.That(llsdresponse != string.Empty, Is.True, "Incorrect empty response"); - Assert.That(llsdresponse.Contains(m_userID.ToString()), Is.True, "Response should contain userID"); - - Console.WriteLine(llsdresponse); - Assert.That(llsdresponse.Contains("10000000-0000-0000-0000-000000000001"), Is.True, "Response does not contain notecard 1"); - Assert.That(llsdresponse.Contains("10000000-0000-0000-0000-000000000002"), Is.True, "Response does not contain notecard 2"); - Assert.That(llsdresponse.Contains("10000000-0000-0000-0000-000000000003"), Is.True, "Response does not contain notecard 3"); - Assert.That(llsdresponse.Contains("10000000-0000-0000-0000-000000000004"), Is.True, "Response does not contain notecard 4"); - Assert.That(llsdresponse.Contains("10000000-0000-0000-0000-000000000005"), Is.True, "Response does not contain notecard 5"); - } - - } - -} \ No newline at end of file diff --git a/OpenSim/Capabilities/Handlers/FetchInventory/Tests/FetchInventoryDescendents2HandlerTests.cs b/OpenSim/Capabilities/Handlers/FetchInventory/Tests/FetchInventoryDescendents2HandlerTests.cs deleted file mode 100644 index d8fe9732aa9..00000000000 --- a/OpenSim/Capabilities/Handlers/FetchInventory/Tests/FetchInventoryDescendents2HandlerTests.cs +++ /dev/null @@ -1,303 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections.Generic; -using System.Linq; -using System.IO; -using System.Text.RegularExpressions; -using log4net; -using log4net.Config; -using NUnit.Framework; -using OpenMetaverse; -using OpenSim.Capabilities.Handlers; -using OpenSim.Framework; -using OpenSim.Framework.Servers.HttpServer; -using OpenSim.Region.Framework.Scenes; -using OpenSim.Services.Interfaces; -using OpenSim.Tests.Common; - -namespace OpenSim.Capabilities.Handlers.FetchInventory.Tests -{ - [TestFixture] - public class FetchInventoryDescendents2HandlerTests : OpenSimTestCase - { - private UUID m_userID = new UUID("00000000-0000-0000-0000-000000000001"); - private Scene m_scene; - private UUID m_rootFolderID; - private int m_rootDescendents; - private UUID m_notecardsFolder; - private UUID m_objectsFolder; - - private void Init() - { - // Create an inventory that looks like this: - // - // /My Inventory - // - // /Objects - // Some Object - // /Notecards - // Notecard 1 - // Notecard 2 - // /Test Folder - // Link to notecard -> /Notecards/Notecard 2 - // Link to Objects folder -> /Objects - - m_scene = new SceneHelpers().SetupScene(); - - m_scene.InventoryService.CreateUserInventory(m_userID); - - m_rootFolderID = m_scene.InventoryService.GetRootFolder(m_userID).ID; - - InventoryFolderBase of = m_scene.InventoryService.GetFolderForType(m_userID, FolderType.Object); - m_objectsFolder = of.ID; - - // Add an object - InventoryItemBase item = new InventoryItemBase(new UUID("b0000000-0000-0000-0000-00000000000b"), m_userID); - item.AssetID = UUID.Random(); - item.AssetType = (int)AssetType.Object; - item.Folder = m_objectsFolder; - item.Name = "Some Object"; - m_scene.InventoryService.AddItem(item); - - InventoryFolderBase ncf = m_scene.InventoryService.GetFolderForType(m_userID, FolderType.Notecard); - m_notecardsFolder = ncf.ID; - - // Add a notecard - item = new InventoryItemBase(new UUID("10000000-0000-0000-0000-000000000001"), m_userID); - item.AssetID = UUID.Random(); - item.AssetType = (int)AssetType.Notecard; - item.Folder = m_notecardsFolder; - item.Name = "Test Notecard 1"; - m_scene.InventoryService.AddItem(item); - // Add another notecard - item.ID = new UUID("20000000-0000-0000-0000-000000000002"); - item.AssetID = new UUID("a0000000-0000-0000-0000-00000000000a"); - item.Name = "Test Notecard 2"; - m_scene.InventoryService.AddItem(item); - - // Add a folder - InventoryFolderBase folder = new InventoryFolderBase(new UUID("f0000000-0000-0000-0000-00000000000f"), "Test Folder", m_userID, m_rootFolderID); - folder.Type = (short)FolderType.None; - m_scene.InventoryService.AddFolder(folder); - - // Add a link to notecard 2 in Test Folder - item.AssetID = item.ID; // use item ID of notecard 2 - item.ID = new UUID("40000000-0000-0000-0000-000000000004"); - item.AssetType = (int)AssetType.Link; - item.Folder = folder.ID; - item.Name = "Link to notecard"; - m_scene.InventoryService.AddItem(item); - - // Add a link to the Objects folder in Test Folder - item.AssetID = m_scene.InventoryService.GetFolderForType(m_userID, FolderType.Object).ID; // use item ID of Objects folder - item.ID = new UUID("50000000-0000-0000-0000-000000000005"); - item.AssetType = (int)AssetType.LinkFolder; - item.Folder = folder.ID; - item.Name = "Link to Objects folder"; - m_scene.InventoryService.AddItem(item); - - InventoryCollection coll = m_scene.InventoryService.GetFolderContent(m_userID, m_rootFolderID); - m_rootDescendents = coll.Items.Count + coll.Folders.Count; - Console.WriteLine("Number of descendents: " + m_rootDescendents); - } - - private string dorequest(FetchInvDescHandler handler, string request) - { - TestOSHttpRequest req = new TestOSHttpRequest(); - TestOSHttpResponse resp = new TestOSHttpResponse(); - using(ExpiringKey bad = new ExpiringKey(5000)) // bad but this is test - using (MemoryStream ms = new MemoryStream(Utils.StringToBytes(request), false)) - { - req.InputStream = ms; - handler.FetchInventoryDescendentsRequest(req, resp, bad); - } - return Util.UTF8.GetString(resp.RawBuffer); - } - - [Test] - public void Test_001_SimpleFolder() - { - TestHelpers.InMethod(); - - Init(); - - FetchInvDescHandler handler = new FetchInvDescHandler(m_scene.InventoryService, null, m_scene); - - string request = "foldersfetch_folders1fetch_items1folder_id"; - request += m_rootFolderID; - request += "owner_id"; - request += m_userID.ToString(); - request += "sort_order1"; - - string llsdresponse = dorequest(handler, request); - - Assert.That(llsdresponse != null, Is.True, "Incorrect null response"); - Assert.That(llsdresponse != string.Empty, Is.True, "Incorrect empty response"); - Assert.That(llsdresponse.Contains(m_userID.ToString()), Is.True, "Response should contain userID"); - - string descendents = "descendents" + m_rootDescendents + ""; - Assert.That(llsdresponse.Contains(descendents), Is.True, "Incorrect number of descendents"); - Console.WriteLine(llsdresponse); - } - - [Test] - public void Test_002_MultipleFolders() - { - TestHelpers.InMethod(); - - FetchInvDescHandler handler = new FetchInvDescHandler(m_scene.InventoryService, null, m_scene); - - string request = "folders"; - request += "fetch_folders1fetch_items1folder_id"; - request += m_rootFolderID; - request += "owner_id00000000-0000-0000-0000-000000000001sort_order1"; - request += "fetch_folders1fetch_items1folder_id"; - request += m_notecardsFolder; - request += "owner_id00000000-0000-0000-0000-000000000001sort_order1"; - request += ""; - - string llsdresponse = dorequest(handler, request); - Console.WriteLine(llsdresponse); - - string descendents = "descendents" + m_rootDescendents + ""; - Assert.That(llsdresponse.Contains(descendents), Is.True, "Incorrect number of descendents for root folder"); - descendents = "descendents2"; - Assert.That(llsdresponse.Contains(descendents), Is.True, "Incorrect number of descendents for Notecard folder"); - - Assert.That(llsdresponse.Contains("10000000-0000-0000-0000-000000000001"), Is.True, "Notecard 1 is missing from response"); - Assert.That(llsdresponse.Contains("20000000-0000-0000-0000-000000000002"), Is.True, "Notecard 2 is missing from response"); - } - - [Test] - public void Test_003_Links() - { - TestHelpers.InMethod(); - - FetchInvDescHandler handler = new FetchInvDescHandler(m_scene.InventoryService, null, m_scene); - - string request = "foldersfetch_folders1fetch_items1folder_id"; - request += "f0000000-0000-0000-0000-00000000000f"; - request += "owner_id00000000-0000-0000-0000-000000000001sort_order1"; - - string llsdresponse = dorequest(handler, request); - Console.WriteLine(llsdresponse); - - string descendents = "descendents2"; - Assert.That(llsdresponse.Contains(descendents), Is.True, "Incorrect number of descendents for Test Folder"); - - // Make sure that the note card link is included - Assert.That(llsdresponse.Contains("Link to notecard"), Is.True, "Link to notecard is missing"); - - //Make sure the notecard item itself is included - Assert.That(llsdresponse.Contains("Test Notecard 2"), Is.True, "Notecard 2 item (the source) is missing"); - - // Make sure that the source item is before the link item - int pos1 = llsdresponse.IndexOf("Test Notecard 2"); - int pos2 = llsdresponse.IndexOf("Link to notecard"); - Assert.Less(pos1, pos2, "Source of link is after link"); - - // Make sure the folder link is included - Assert.That(llsdresponse.Contains("Link to Objects folder"), Is.True, "Link to Objects folder is missing"); - -/* contents of link folder are not supposed to be listed - // Make sure the objects inside the Objects folder are included - // Note: I'm not entirely sure this is needed, but that's what I found in the implementation - Assert.That(llsdresponse.Contains("Some Object"), Is.True, "Some Object item (contents of the source) is missing"); -*/ - // Make sure that the source item is before the link item - pos1 = llsdresponse.IndexOf("Some Object"); - pos2 = llsdresponse.IndexOf("Link to Objects folder"); - Assert.Less(pos1, pos2, "Contents of source of folder link is after folder link"); - } - - [Test] - public void Test_004_DuplicateFolders() - { - TestHelpers.InMethod(); - - FetchInvDescHandler handler = new FetchInvDescHandler(m_scene.InventoryService, null, m_scene); - - string request = "folders"; - request += "fetch_folders1fetch_items1folder_id"; - request += m_rootFolderID; - request += "owner_id00000000-0000-0000-0000-000000000000sort_order1"; - request += "fetch_folders1fetch_items1folder_id"; - request += m_notecardsFolder; - request += "owner_id00000000-0000-0000-0000-000000000000sort_order1"; - request += "fetch_folders1fetch_items1folder_id"; - request += m_rootFolderID; - request += "owner_id00000000-0000-0000-0000-000000000000sort_order1"; - request += "fetch_folders1fetch_items1folder_id"; - request += m_notecardsFolder; - request += "owner_id00000000-0000-0000-0000-000000000000sort_order1"; - request += ""; - - string llsdresponse = dorequest(handler, request); - Console.WriteLine(llsdresponse); - - string root_folder = "folder_id" + m_rootFolderID + ""; - string notecards_folder = "folder_id" + m_notecardsFolder + ""; - string notecards_category = "category_id" + m_notecardsFolder + ""; - - Assert.That(llsdresponse.Contains(root_folder), "Missing root folder"); - Assert.That(llsdresponse.Contains(notecards_folder), "Missing notecards folder"); - int count = Regex.Matches(llsdresponse, root_folder).Count; - Assert.AreEqual(1, count, "More than 1 root folder in response"); - count = Regex.Matches(llsdresponse, notecards_folder).Count; - Assert.AreEqual(1, count, "More than 1 notecards folder in response"); - count = Regex.Matches(llsdresponse, notecards_category).Count; - Assert.AreEqual(1, count, "More than 1 notecards folder in response"); // Notecards will also be a category on root - } - - [Test] - public void Test_005_FolderZero() - { - - TestHelpers.InMethod(); - - Init(); - - FetchInvDescHandler handler = new FetchInvDescHandler(m_scene.InventoryService, null, m_scene); - - string request = "foldersfetch_folders1fetch_items1folder_id"; - request += UUID.Zero; - request += "owner_id00000000-0000-0000-0000-000000000000sort_order1"; - - string llsdresponse = dorequest(handler, request); - - Assert.That(llsdresponse != null, Is.True, "Incorrect null response"); - Assert.That(llsdresponse != string.Empty, Is.True, "Incorrect empty response"); - // we do return a answer now - //Assert.That(llsdresponse.Contains("bad_folders00000000-0000-0000-0000-000000000000"), Is.True, "Folder Zero should be a bad folder"); - - Console.WriteLine(llsdresponse); - } - } - -} \ No newline at end of file diff --git a/OpenSim/Capabilities/Handlers/GetTexture/Tests/GetTextureHandlerTests.cs b/OpenSim/Capabilities/Handlers/GetTexture/Tests/GetTextureHandlerTests.cs deleted file mode 100644 index 61aa689045e..00000000000 --- a/OpenSim/Capabilities/Handlers/GetTexture/Tests/GetTextureHandlerTests.cs +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections.Generic; -using System.Net; -using log4net; -using log4net.Config; -using NUnit.Framework; -using OpenMetaverse; -using OpenSim.Capabilities.Handlers; -using OpenSim.Framework; -using OpenSim.Framework.Servers.HttpServer; -using OpenSim.Region.Framework.Scenes; -using OpenSim.Tests.Common; - -/* -namespace OpenSim.Capabilities.Handlers.GetTexture.Tests -{ - [TestFixture] - public class GetTextureHandlerTests : OpenSimTestCase - { - [Test] - public void TestTextureNotFound() - { - TestHelpers.InMethod(); - - // Overkill - we only really need the asset service, not a whole scene. - Scene scene = new SceneHelpers().SetupScene(); - - GetTextureHandler handler = new GetTextureHandler("/gettexture", scene.AssetService, "TestGetTexture", null, null); - TestOSHttpRequest req = new TestOSHttpRequest(); - TestOSHttpResponse resp = new TestOSHttpResponse(); - req.Url = new Uri("http://localhost/?texture_id=00000000-0000-1111-9999-000000000012"); - handler.Handle(null, null, req, resp); - Assert.That(resp.StatusCode, Is.EqualTo((int)System.Net.HttpStatusCode.NotFound)); - } - } -} -*/ diff --git a/OpenSim/Capabilities/Handlers/OpenSim.Capabilities.Handlers.Tests.csproj b/OpenSim/Capabilities/Handlers/OpenSim.Capabilities.Handlers.Tests.csproj index 64248bb2b58..2a34b485357 100644 --- a/OpenSim/Capabilities/Handlers/OpenSim.Capabilities.Handlers.Tests.csproj +++ b/OpenSim/Capabilities/Handlers/OpenSim.Capabilities.Handlers.Tests.csproj @@ -23,9 +23,6 @@ ..\..\..\bin\OpenMetaverseTypes.dll False - - False - False @@ -62,4 +59,4 @@ - \ No newline at end of file + diff --git a/OpenSim/Capabilities/Handlers/OpenSim.Capabilities.Handlers.csproj b/OpenSim/Capabilities/Handlers/OpenSim.Capabilities.Handlers.csproj index 177692b4bcc..085a93c8198 100644 --- a/OpenSim/Capabilities/Handlers/OpenSim.Capabilities.Handlers.csproj +++ b/OpenSim/Capabilities/Handlers/OpenSim.Capabilities.Handlers.csproj @@ -27,9 +27,6 @@ ..\..\..\bin\OpenMetaverseTypes.dll False - - False - False @@ -53,4 +50,4 @@ - \ No newline at end of file + diff --git a/OpenSim/Data/Tests/AssetTests.cs b/OpenSim/Data/Tests/AssetTests.cs deleted file mode 100644 index cf1ef6ecffb..00000000000 --- a/OpenSim/Data/Tests/AssetTests.cs +++ /dev/null @@ -1,220 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System.Collections.Generic; -using NUnit.Framework; -using OpenMetaverse; -using OpenSim.Framework; -using OpenSim.Tests.Common; -using System.Data.Common; - -// DBMS-specific: -using OpenSim.Data.MySQL; - -using System.Data.SQLite; -using OpenSim.Data.SQLite; -using MySqlConnector; - -namespace OpenSim.Data.Tests -{ - [TestFixture(Description = "Asset store tests (SQLite)")] - public class SQLiteAssetTests : AssetTests - { - } - - [TestFixture(Description = "Asset store tests (MySQL)")] - public class MySqlAssetTests : AssetTests - { - } - - public class AssetTests : BasicDataServiceTest - where TConn : DbConnection, new() - where TAssetData : AssetDataBase, new() - { - TAssetData m_db; - - public UUID uuid1 = UUID.Random(); - public UUID uuid2 = UUID.Random(); - public UUID uuid3 = UUID.Random(); - - public string critter1 = UUID.Random().ToString(); - public string critter2 = UUID.Random().ToString(); - public string critter3 = UUID.Random().ToString(); - - public byte[] data1 = new byte[100]; - - PropertyScrambler scrambler = new PropertyScrambler() - .DontScramble(x => x.ID) - .DontScramble(x => x.Type) - .DontScramble(x => x.FullID) - .DontScramble(x => x.Metadata.ID) - .DontScramble(x => x.Metadata.CreatorID) - .DontScramble(x => x.Metadata.ContentType) - .DontScramble(x => x.Metadata.FullID) - .DontScramble(x => x.Data); - - protected override void InitService(object service) - { - ClearDB(); - m_db = (TAssetData)service; - m_db.Initialise(m_connStr); - } - - private void ClearDB() - { - DropTables("assets"); - ResetMigrations("AssetStore"); - } - - - [Test] - public void T001_LoadEmpty() - { - TestHelpers.InMethod(); - - bool[] exist = m_db.AssetsExist(new[] { uuid1, uuid2, uuid3 }); - Assert.IsFalse(exist[0]); - Assert.IsFalse(exist[1]); - Assert.IsFalse(exist[2]); - } - - [Test] - public void T010_StoreReadVerifyAssets() - { - TestHelpers.InMethod(); - - AssetBase a1 = new AssetBase(uuid1, "asset one", (sbyte)AssetType.Texture, critter1.ToString()); - AssetBase a2 = new AssetBase(uuid2, "asset two", (sbyte)AssetType.Texture, critter2.ToString()); - AssetBase a3 = new AssetBase(uuid3, "asset three", (sbyte)AssetType.Texture, critter3.ToString()); - a1.Data = data1; - a2.Data = data1; - a3.Data = data1; - - scrambler.Scramble(a1); - scrambler.Scramble(a2); - scrambler.Scramble(a3); - - m_db.StoreAsset(a1); - m_db.StoreAsset(a2); - m_db.StoreAsset(a3); - a1.UploadAttempts = 0; - a2.UploadAttempts = 0; - a3.UploadAttempts = 0; - - AssetBase a1a = m_db.GetAsset(uuid1); - a1a.UploadAttempts = 0; - Assert.That(a1a, Constraints.PropertyCompareConstraint(a1)); - - AssetBase a2a = m_db.GetAsset(uuid2); - a2a.UploadAttempts = 0; - Assert.That(a2a, Constraints.PropertyCompareConstraint(a2)); - - AssetBase a3a = m_db.GetAsset(uuid3); - a3a.UploadAttempts = 0; - Assert.That(a3a, Constraints.PropertyCompareConstraint(a3)); - - scrambler.Scramble(a1a); - scrambler.Scramble(a2a); - scrambler.Scramble(a3a); - - m_db.StoreAsset(a1a); - m_db.StoreAsset(a2a); - m_db.StoreAsset(a3a); - a1a.UploadAttempts = 0; - a2a.UploadAttempts = 0; - a3a.UploadAttempts = 0; - - AssetBase a1b = m_db.GetAsset(uuid1); - a1b.UploadAttempts = 0; - Assert.That(a1b, Constraints.PropertyCompareConstraint(a1a)); - - AssetBase a2b = m_db.GetAsset(uuid2); - a2b.UploadAttempts = 0; - Assert.That(a2b, Constraints.PropertyCompareConstraint(a2a)); - - AssetBase a3b = m_db.GetAsset(uuid3); - a3b.UploadAttempts = 0; - Assert.That(a3b, Constraints.PropertyCompareConstraint(a3a)); - - bool[] exist = m_db.AssetsExist(new[] { uuid1, uuid2, uuid3 }); - Assert.IsTrue(exist[0]); - Assert.IsTrue(exist[1]); - Assert.IsTrue(exist[2]); - - List metadatas = m_db.FetchAssetMetadataSet(0, 1000); - - Assert.That(metadatas.Count >= 3, "FetchAssetMetadataSet() should have returned at least 3 assets!"); - - // It is possible that the Asset table is filled with data, in which case we don't try to find "our" - // assets there: - if (metadatas.Count < 1000) - { - AssetMetadata metadata = metadatas.Find(x => x.FullID == uuid1); - Assert.That(metadata.Name, Is.EqualTo(a1b.Name)); - Assert.That(metadata.Description, Is.EqualTo(a1b.Description)); - Assert.That(metadata.Type, Is.EqualTo(a1b.Type)); - Assert.That(metadata.Temporary, Is.EqualTo(a1b.Temporary)); - Assert.That(metadata.FullID, Is.EqualTo(a1b.FullID)); - } - } - - [Test] - public void T020_CheckForWeirdCreatorID() - { - TestHelpers.InMethod(); - - // It is expected that eventually the CreatorID might be an arbitrary string (an URI) - // rather than a valid UUID (?). This test is to make sure that the database layer does not - // attempt to convert CreatorID to GUID, but just passes it both ways as a string. - AssetBase a1 = new AssetBase(uuid1, "asset one", (sbyte)AssetType.Texture, critter1); - AssetBase a2 = new AssetBase(uuid2, "asset two", (sbyte)AssetType.Texture, "This is not a GUID!"); - AssetBase a3 = new AssetBase(uuid3, "asset three", (sbyte)AssetType.Texture, ""); - a1.Data = data1; - a2.Data = data1; - a3.Data = data1; - - m_db.StoreAsset(a1); - a1.UploadAttempts = 0; - m_db.StoreAsset(a2); - a2.UploadAttempts = 0; - m_db.StoreAsset(a3); - a3.UploadAttempts = 0; - - AssetBase a1a = m_db.GetAsset(uuid1); - a1a.UploadAttempts = 0; - Assert.That(a1a, Constraints.PropertyCompareConstraint(a1)); - - AssetBase a2a = m_db.GetAsset(uuid2); - a2a.UploadAttempts = 0; - Assert.That(a2a, Constraints.PropertyCompareConstraint(a2)); - - AssetBase a3a = m_db.GetAsset(uuid3); - a3a.UploadAttempts = 0; - Assert.That(a3a, Constraints.PropertyCompareConstraint(a3)); - } - } -} \ No newline at end of file diff --git a/OpenSim/Data/Tests/BasicDataServiceTest.cs b/OpenSim/Data/Tests/BasicDataServiceTest.cs deleted file mode 100644 index 264f7bafbec..00000000000 --- a/OpenSim/Data/Tests/BasicDataServiceTest.cs +++ /dev/null @@ -1,271 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.IO; -using System.Collections.Generic; -using log4net.Config; -using NUnit.Framework; -using NUnit.Framework.Constraints; -using OpenMetaverse; -using OpenSim.Framework; -using OpenSim.Tests.Common; -using log4net; -using System.Data; -using System.Data.Common; -using System.Reflection; - -namespace OpenSim.Data.Tests -{ - /// This is a base class for testing any Data service for any DBMS. - /// Requires NUnit 2.5 or better (to support the generics). - /// - /// - /// FIXME: Should extend OpenSimTestCase but compile on mono 2.4.3 currently fails with - /// AssetTests`2 : System.MemberAccessException : Cannot create an instance of OpenSim.Data.Tests.AssetTests`2[TConn,TAssetData] because Type.ContainsGenericParameters is true. - /// and similar on EstateTests, InventoryTests and RegionTests. - /// Runs fine with mono 2.10.8.1, so easiest thing is to wait until min Mono version uplifts. - /// - /// - /// - public class BasicDataServiceTest - where TConn : DbConnection, new() - where TService : class, new() - { - protected string m_connStr; - private TService m_service; - private string m_file; - - // TODO: Is this in the right place here? - // Later: apparently it's not, but does it matter here? -// protected static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - - protected ILog m_log; // doesn't matter here that it's not static, init to correct type in instance .ctor - - public BasicDataServiceTest() - : this("") - { - } - - public BasicDataServiceTest(string conn) - { - m_connStr = !String.IsNullOrEmpty(conn) ? conn : DefaultTestConns.Get(typeof(TConn)); - - m_log = LogManager.GetLogger(this.GetType()); - TestLogging.LogToConsole(); // TODO: Is that right? - } - - /// - /// To be overridden in derived classes. Do whatever init with the m_service, like setting the conn string to it. - /// You'd probably want to to cast the 'service' to a more specific type and store it in a member var. - /// This framework takes care of disposing it, if it's disposable. - /// - /// The service being tested - protected virtual void InitService(object service) - { - } - - [OneTimeSetUp] - public void Init() - { - // Sorry, some SQLite-specific stuff goes here (not a big deal, as its just some file ops) - if (typeof(TConn).Name.StartsWith("Sqlite")) - { - // SQLite doesn't work on power or z linux - if (Directory.Exists("/proc/ppc64") || Directory.Exists("/proc/dasd")) - Assert.Ignore(); - - if (Util.IsWindows()) - Util.LoadArchSpecificWindowsDll("sqlite3.dll"); - - // for SQLite, if no explicit conn string is specified, use a temp file - if (String.IsNullOrEmpty(m_connStr)) - { - m_file = Path.GetTempFileName() + ".db"; - m_connStr = "URI=file:" + m_file + ",version=3"; - } - } - - if (String.IsNullOrEmpty(m_connStr)) - { - string msg = String.Format("Connection string for {0} is not defined, ignoring tests", typeof(TConn).Name); - m_log.Warn(msg); - Assert.Ignore(msg); - } - - // Try the connection, ignore tests if Open() fails - using (TConn conn = new TConn()) - { - conn.ConnectionString = m_connStr; - try - { - conn.Open(); - conn.Close(); - } - catch - { - string msg = String.Format("{0} is unable to connect to the database, ignoring tests", typeof(TConn).Name); - m_log.Warn(msg); - Assert.Ignore(msg); - } - } - - // If we manage to connect to the database with the user - // and password above it is our test database, and run - // these tests. If anything goes wrong, ignore these - // tests. - try - { - m_service = new TService(); - InitService(m_service); - } - catch (Exception e) - { - m_log.Error(e.ToString()); - Assert.Ignore(); - } - } - - [OneTimeTearDown] - public void Cleanup() - { - if (m_service != null) - { - if (m_service is IDisposable) - ((IDisposable)m_service).Dispose(); - m_service = null; - } - - if (!String.IsNullOrEmpty(m_file) && File.Exists(m_file)) - File.Delete(m_file); - } - - protected virtual DbConnection Connect() - { - DbConnection cnn = new TConn(); - cnn.ConnectionString = m_connStr; - cnn.Open(); - return cnn; - } - - protected virtual void ExecuteSql(string sql) - { - using (DbConnection dbcon = Connect()) - { - using (DbCommand cmd = dbcon.CreateCommand()) - { - cmd.CommandText = sql; - cmd.ExecuteNonQuery(); - } - } - } - - protected delegate bool ProcessRow(IDataReader reader); - - protected virtual int ExecQuery(string sql, bool bSingleRow, ProcessRow action) - { - int nRecs = 0; - using (DbConnection dbcon = Connect()) - { - using (DbCommand cmd = dbcon.CreateCommand()) - { - cmd.CommandText = sql; - CommandBehavior cb = bSingleRow ? CommandBehavior.SingleRow : CommandBehavior.Default; - using (DbDataReader rdr = cmd.ExecuteReader(cb)) - { - while (rdr.Read()) - { - nRecs++; - if (!action(rdr)) - break; - } - } - } - } - return nRecs; - } - - /// Drop tables (listed as parameters). There is no "DROP IF EXISTS" syntax common for all - /// databases, so we just DROP and ignore an exception. - /// - /// - protected virtual void DropTables(params string[] tables) - { - foreach (string tbl in tables) - { - try - { - ExecuteSql("DROP TABLE " + tbl + ";"); - }catch - { - } - } - } - - /// Clear tables listed as parameters (without dropping them). - /// - /// - protected virtual void ResetMigrations(params string[] stores) - { - string lst = ""; - foreach (string store in stores) - { - string s = "'" + store + "'"; - if (lst.Length == 0) - lst = s; - else - lst += ", " + s; - } - - string sCond = stores.Length > 1 ? ("in (" + lst + ")") : ("=" + lst); - try - { - ExecuteSql("DELETE FROM migrations where name " + sCond); - } - catch - { - } - } - - /// Clear tables listed as parameters (without dropping them). - /// - /// - protected virtual void ClearTables(params string[] tables) - { - foreach (string tbl in tables) - { - try - { - ExecuteSql("DELETE FROM " + tbl + ";"); - } - catch - { - } - } - } - } -} diff --git a/OpenSim/Data/Tests/DataTestUtil.cs b/OpenSim/Data/Tests/DataTestUtil.cs deleted file mode 100644 index 5393529592d..00000000000 --- a/OpenSim/Data/Tests/DataTestUtil.cs +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections.Generic; -using System.Text; -using OpenMetaverse; -using NUnit.Framework; - -namespace OpenSim.Data.Tests -{ - /// - /// Shared constants and methods for database unit tests. - /// - public class DataTestUtil - { - public const uint UNSIGNED_INTEGER_MIN = uint.MinValue; - //public const uint UNSIGNED_INTEGER_MAX = uint.MaxValue; - public const uint UNSIGNED_INTEGER_MAX = INTEGER_MAX; - - public const int INTEGER_MIN = int.MinValue + 1; // Postgresql requires +1 to .NET int.MinValue - public const int INTEGER_MAX = int.MaxValue; - - public const float FLOAT_MIN = float.MinValue * (1 - FLOAT_PRECISSION); - public const float FLOAT_MAX = float.MaxValue * (1 - FLOAT_PRECISSION); - public const float FLOAT_ACCURATE = 1.234567890123456789012f; - public const float FLOAT_PRECISSION = 1E-5f; // Native MySQL is severly limited with floating accuracy - - public const double DOUBLE_MIN = -1E52 * (1 - DOUBLE_PRECISSION); - public const double DOUBLE_MAX = 1E52 * (1 - DOUBLE_PRECISSION); - public const double DOUBLE_ACCURATE = 1.2345678901234567890123456789012345678901234567890123f; - public const double DOUBLE_PRECISSION = 1E-14; // Native MySQL is severly limited with double accuracy - - public const string STRING_MIN = ""; - public static string STRING_MAX(int length) - { - StringBuilder stringBuilder = new StringBuilder(); - for (int i = 0; i < length; i++) - { - stringBuilder.Append(i % 10); - } - return stringBuilder.ToString(); - } - - public static UUID UUID_MIN = new UUID("00000000-0000-0000-0000-000000000000"); - public static UUID UUID_MAX = new UUID("ffffffff-ffff-ffff-ffff-ffffffffffff"); - - public const bool BOOLEAN_MIN = false; - public const bool BOOLEAN_MAX = true; - - public static void AssertFloatEqualsWithTolerance(float expectedValue, float actualValue) - { - Assert.GreaterOrEqual(actualValue, expectedValue - Math.Abs(expectedValue) * FLOAT_PRECISSION); - Assert.LessOrEqual(actualValue, expectedValue + Math.Abs(expectedValue) * FLOAT_PRECISSION); - } - - public static void AssertDoubleEqualsWithTolerance(double expectedValue, double actualValue) - { - Assert.GreaterOrEqual(actualValue, expectedValue - Math.Abs(expectedValue) * DOUBLE_PRECISSION); - Assert.LessOrEqual(actualValue, expectedValue + Math.Abs(expectedValue) * DOUBLE_PRECISSION); - } - } -} - diff --git a/OpenSim/Data/Tests/DefaultTestConns.cs b/OpenSim/Data/Tests/DefaultTestConns.cs deleted file mode 100644 index 87b346e33f9..00000000000 --- a/OpenSim/Data/Tests/DefaultTestConns.cs +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Reflection; -using System.IO; -using Nini.Config; - -namespace OpenSim.Data.Tests -{ - /// This static class looks for TestDataConnections.ini file in the /bin directory to obtain - /// a connection string for testing one of the supported databases. - /// The connections must be in the section [TestConnections] with names matching the connection class - /// name for the specific database, e.g.: - /// - /// [TestConnections] - /// MySqlConnection="..." - /// SqlConnection="..." - /// SQLiteConnection="..." - /// - /// Note that the conn string may also be set explicitly in the [TestCase()] attribute of test classes - /// based on BasicDataServiceTest.cs. - /// - - static class DefaultTestConns - { - private static Dictionary conns = new Dictionary(); - - public static string Get(Type connType) - { - string sConn; - - if (conns.TryGetValue(connType, out sConn)) - return sConn; - - Assembly asm = Assembly.GetExecutingAssembly(); - string sType = connType.Name; - - // Note: when running from NUnit, the DLL is located in some temp dir, so how do we get - // to the INI file? Ok, so put it into the resources! - // string iniName = Path.Combine(Path.GetDirectoryName(asm.Location), "TestDataConnections.ini"); - - string[] allres = asm.GetManifestResourceNames(); - string sResFile = Array.Find(allres, s => s.Contains("TestDataConnections.ini")); - - if (String.IsNullOrEmpty(sResFile)) - throw new Exception(String.Format("Please add resource TestDataConnections.ini, with section [TestConnections] and settings like {0}=\"...\"", - sType)); - - using (Stream resource = asm.GetManifestResourceStream(sResFile)) - { - IConfigSource source = new IniConfigSource(resource); - var cfg = source.Configs["TestConnections"]; - sConn = cfg.Get(sType, ""); - } - - if (!String.IsNullOrEmpty(sConn)) - conns[connType] = sConn; - - return sConn; - } - } -} diff --git a/OpenSim/Data/Tests/EstateTests.cs b/OpenSim/Data/Tests/EstateTests.cs deleted file mode 100644 index 4bfdc64f1da..00000000000 --- a/OpenSim/Data/Tests/EstateTests.cs +++ /dev/null @@ -1,511 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using NUnit.Framework; -using OpenMetaverse; -using OpenSim.Framework; -using OpenSim.Tests.Common; -using System.Data.Common; - -// DBMS-specific: -using OpenSim.Data.MySQL; - -using System.Data.SQLite; -using OpenSim.Data.SQLite; -using MySqlConnector; - -namespace OpenSim.Data.Tests -{ - [TestFixture(Description = "Estate store tests (SQLite)")] - public class SQLiteEstateTests : EstateTests - { - } - - [TestFixture(Description = "Estate store tests (MySQL)")] - public class MySqlEstateTests : EstateTests - { - } - - public class EstateTests : BasicDataServiceTest - where TConn : DbConnection, new() - where TEstateStore : class, IEstateDataStore, new() - { - public IEstateDataStore db; - - public static UUID REGION_ID = new UUID("250d214e-1c7e-4f9b-a488-87c5e53feed7"); - - public static UUID USER_ID_1 = new UUID("250d214e-1c7e-4f9b-a488-87c5e53feed1"); - public static UUID USER_ID_2 = new UUID("250d214e-1c7e-4f9b-a488-87c5e53feed2"); - - public static UUID MANAGER_ID_1 = new UUID("250d214e-1c7e-4f9b-a488-87c5e53feed3"); - public static UUID MANAGER_ID_2 = new UUID("250d214e-1c7e-4f9b-a488-87c5e53feed4"); - - public static UUID GROUP_ID_1 = new UUID("250d214e-1c7e-4f9b-a488-87c5e53feed5"); - public static UUID GROUP_ID_2 = new UUID("250d214e-1c7e-4f9b-a488-87c5e53feed6"); - - protected override void InitService(object service) - { - ClearDB(); - db = (IEstateDataStore)service; - db.Initialise(m_connStr); - } - - private void ClearDB() - { - // if a new table is added, it has to be dropped here - DropTables( - "estate_managers", - "estate_groups", - "estate_users", - "estateban", - "estate_settings", - "estate_map" - ); - ResetMigrations("EstateStore"); - } - - #region 0Tests - - [Test] - public void T010_EstateSettingsSimpleStorage_MinimumParameterSet() - { - TestHelpers.InMethod(); - - EstateSettingsSimpleStorage( - REGION_ID, - DataTestUtil.STRING_MIN, - DataTestUtil.UNSIGNED_INTEGER_MIN, - DataTestUtil.FLOAT_MIN, - DataTestUtil.INTEGER_MIN, - DataTestUtil.INTEGER_MIN, - DataTestUtil.INTEGER_MIN, - DataTestUtil.BOOLEAN_MIN, - DataTestUtil.BOOLEAN_MIN, - DataTestUtil.DOUBLE_MIN, - DataTestUtil.BOOLEAN_MIN, - DataTestUtil.BOOLEAN_MIN, - DataTestUtil.BOOLEAN_MIN, - DataTestUtil.BOOLEAN_MIN, - DataTestUtil.BOOLEAN_MIN, - DataTestUtil.BOOLEAN_MIN, - DataTestUtil.BOOLEAN_MIN, - DataTestUtil.BOOLEAN_MIN, - DataTestUtil.BOOLEAN_MIN, - DataTestUtil.BOOLEAN_MIN, - DataTestUtil.BOOLEAN_MIN, - DataTestUtil.BOOLEAN_MIN, - DataTestUtil.STRING_MIN, - DataTestUtil.UUID_MIN - ); - } - - [Test] - public void T011_EstateSettingsSimpleStorage_MaximumParameterSet() - { - TestHelpers.InMethod(); - - EstateSettingsSimpleStorage( - REGION_ID, - DataTestUtil.STRING_MAX(64), - DataTestUtil.UNSIGNED_INTEGER_MAX, - DataTestUtil.FLOAT_MAX, - DataTestUtil.INTEGER_MAX, - DataTestUtil.INTEGER_MAX, - DataTestUtil.INTEGER_MAX, - DataTestUtil.BOOLEAN_MAX, - DataTestUtil.BOOLEAN_MAX, - DataTestUtil.DOUBLE_MAX, - DataTestUtil.BOOLEAN_MAX, - DataTestUtil.BOOLEAN_MAX, - DataTestUtil.BOOLEAN_MAX, - DataTestUtil.BOOLEAN_MAX, - DataTestUtil.BOOLEAN_MAX, - DataTestUtil.BOOLEAN_MAX, - DataTestUtil.BOOLEAN_MAX, - DataTestUtil.BOOLEAN_MAX, - DataTestUtil.BOOLEAN_MAX, - DataTestUtil.BOOLEAN_MAX, - DataTestUtil.BOOLEAN_MAX, - DataTestUtil.BOOLEAN_MAX, - DataTestUtil.STRING_MAX(255), - DataTestUtil.UUID_MAX - ); - } - - [Test] - public void T012_EstateSettingsSimpleStorage_AccurateParameterSet() - { - TestHelpers.InMethod(); - - EstateSettingsSimpleStorage( - REGION_ID, - DataTestUtil.STRING_MAX(1), - DataTestUtil.UNSIGNED_INTEGER_MIN, - DataTestUtil.FLOAT_ACCURATE, - DataTestUtil.INTEGER_MIN, - DataTestUtil.INTEGER_MIN, - DataTestUtil.INTEGER_MIN, - DataTestUtil.BOOLEAN_MIN, - DataTestUtil.BOOLEAN_MIN, - DataTestUtil.DOUBLE_ACCURATE, - DataTestUtil.BOOLEAN_MIN, - DataTestUtil.BOOLEAN_MIN, - DataTestUtil.BOOLEAN_MIN, - DataTestUtil.BOOLEAN_MIN, - DataTestUtil.BOOLEAN_MIN, - DataTestUtil.BOOLEAN_MIN, - DataTestUtil.BOOLEAN_MIN, - DataTestUtil.BOOLEAN_MIN, - DataTestUtil.BOOLEAN_MIN, - DataTestUtil.BOOLEAN_MIN, - DataTestUtil.BOOLEAN_MIN, - DataTestUtil.BOOLEAN_MIN, - DataTestUtil.STRING_MAX(1), - DataTestUtil.UUID_MIN - ); - } - - [Test] - public void T012_EstateSettingsRandomStorage() - { - TestHelpers.InMethod(); - - // Letting estate store generate rows to database for us - EstateSettings originalSettings = db.LoadEstateSettings(REGION_ID, true); - new PropertyScrambler() - .DontScramble(x=>x.EstateID) - .Scramble(originalSettings); - - // Saving settings. - db.StoreEstateSettings(originalSettings); - - // Loading settings to another instance variable. - EstateSettings loadedSettings = db.LoadEstateSettings(REGION_ID, true); - - // Checking that loaded values are correct. - Assert.That(loadedSettings, Constraints.PropertyCompareConstraint(originalSettings)); - } - - [Test] - public void T020_EstateSettingsManagerList() - { - TestHelpers.InMethod(); - - // Letting estate store generate rows to database for us - EstateSettings originalSettings = db.LoadEstateSettings(REGION_ID, true); - - originalSettings.EstateManagers = new UUID[] { MANAGER_ID_1, MANAGER_ID_2 }; - - // Saving settings. - db.StoreEstateSettings(originalSettings); - - // Loading settings to another instance variable. - EstateSettings loadedSettings = db.LoadEstateSettings(REGION_ID, true); - - Assert.AreEqual(2, loadedSettings.EstateManagers.Length); - Assert.AreEqual(MANAGER_ID_1, loadedSettings.EstateManagers[0]); - Assert.AreEqual(MANAGER_ID_2, loadedSettings.EstateManagers[1]); - } - - [Test] - public void T021_EstateSettingsUserList() - { - TestHelpers.InMethod(); - - // Letting estate store generate rows to database for us - EstateSettings originalSettings = db.LoadEstateSettings(REGION_ID, true); - - originalSettings.EstateAccess = new UUID[] { USER_ID_1, USER_ID_2 }; - - // Saving settings. - db.StoreEstateSettings(originalSettings); - - // Loading settings to another instance variable. - EstateSettings loadedSettings = db.LoadEstateSettings(REGION_ID, true); - - Assert.AreEqual(2, loadedSettings.EstateAccess.Length); - Assert.AreEqual(USER_ID_1, loadedSettings.EstateAccess[0]); - Assert.AreEqual(USER_ID_2, loadedSettings.EstateAccess[1]); - } - - [Test] - public void T022_EstateSettingsGroupList() - { - TestHelpers.InMethod(); - - // Letting estate store generate rows to database for us - EstateSettings originalSettings = db.LoadEstateSettings(REGION_ID, true); - - originalSettings.EstateGroups = new UUID[] { GROUP_ID_1, GROUP_ID_2 }; - - // Saving settings. - db.StoreEstateSettings(originalSettings); - - // Loading settings to another instance variable. - EstateSettings loadedSettings = db.LoadEstateSettings(REGION_ID, true); - - Assert.AreEqual(2, loadedSettings.EstateAccess.Length); - Assert.AreEqual(GROUP_ID_1, loadedSettings.EstateGroups[0]); - Assert.AreEqual(GROUP_ID_2, loadedSettings.EstateGroups[1]); - } - - [Test] - public void T022_EstateSettingsBanList() - { - TestHelpers.InMethod(); - - // Letting estate store generate rows to database for us - EstateSettings originalSettings = db.LoadEstateSettings(REGION_ID, true); - - EstateBan estateBan1 = new EstateBan(); - estateBan1.BannedUserID = DataTestUtil.UUID_MIN; - - EstateBan estateBan2 = new EstateBan(); - estateBan2.BannedUserID = DataTestUtil.UUID_MAX; - - originalSettings.EstateBans = new EstateBan[] { estateBan1, estateBan2 }; - - // Saving settings. - db.StoreEstateSettings(originalSettings); - - // Loading settings to another instance variable. - EstateSettings loadedSettings = db.LoadEstateSettings(REGION_ID, true); - - Assert.AreEqual(2, loadedSettings.EstateBans.Length); - Assert.AreEqual(DataTestUtil.UUID_MIN, loadedSettings.EstateBans[0].BannedUserID); - - Assert.AreEqual(DataTestUtil.UUID_MAX, loadedSettings.EstateBans[1].BannedUserID); - - } - - #endregion - - #region Parametrizable Test Implementations - - private void EstateSettingsSimpleStorage( - UUID regionId, - string estateName, - uint parentEstateID, - float billableFactor, - int pricePerMeter, - int redirectGridX, - int redirectGridY, - bool useGlobalTime, - bool fixedSun, - double sunPosition, - bool allowVoice, - bool allowDirectTeleport, - bool resetHomeOnTeleport, - bool denyAnonymous, - bool denyIdentified, - bool denyTransacted, - bool denyMinors, - bool abuseEmailToEstateOwner, - bool blockDwell, - bool estateSkipScripts, - bool taxFree, - bool publicAccess, - string abuseEmail, - UUID estateOwner - ) - { - - // Letting estate store generate rows to database for us - EstateSettings originalSettings = db.LoadEstateSettings(regionId, true); - - SetEstateSettings(originalSettings, - estateName, - parentEstateID, - billableFactor, - pricePerMeter, - redirectGridX, - redirectGridY, - useGlobalTime, - fixedSun, - sunPosition, - allowVoice, - allowDirectTeleport, - resetHomeOnTeleport, - denyAnonymous, - denyIdentified, - denyTransacted, - denyMinors, - abuseEmailToEstateOwner, - blockDwell, - estateSkipScripts, - taxFree, - publicAccess, - abuseEmail, - estateOwner - ); - - // Saving settings. - db.StoreEstateSettings(originalSettings); - - // Loading settings to another instance variable. - EstateSettings loadedSettings = db.LoadEstateSettings(regionId, true); - - // Checking that loaded values are correct. - ValidateEstateSettings(loadedSettings, - estateName, - parentEstateID, - billableFactor, - pricePerMeter, - redirectGridX, - redirectGridY, - useGlobalTime, - fixedSun, - sunPosition, - allowVoice, - allowDirectTeleport, - resetHomeOnTeleport, - denyAnonymous, - denyIdentified, - denyTransacted, - denyMinors, - abuseEmailToEstateOwner, - blockDwell, - estateSkipScripts, - taxFree, - publicAccess, - abuseEmail, - estateOwner - ); - - } - - #endregion - - #region EstateSetting Initialization and Validation Methods - - private void SetEstateSettings( - EstateSettings estateSettings, - string estateName, - uint parentEstateID, - float billableFactor, - int pricePerMeter, - int redirectGridX, - int redirectGridY, - bool useGlobalTime, - bool fixedSun, - double sunPosition, - bool allowVoice, - bool allowDirectTeleport, - bool resetHomeOnTeleport, - bool denyAnonymous, - bool denyIdentified, - bool denyTransacted, - bool denyMinors, - bool abuseEmailToEstateOwner, - bool blockDwell, - bool estateSkipScripts, - bool taxFree, - bool publicAccess, - string abuseEmail, - UUID estateOwner - ) - { - estateSettings.EstateName = estateName; - estateSettings.ParentEstateID = parentEstateID; - estateSettings.BillableFactor = billableFactor; - estateSettings.PricePerMeter = pricePerMeter; - estateSettings.RedirectGridX = redirectGridX; - estateSettings.RedirectGridY = redirectGridY; - estateSettings.UseGlobalTime = useGlobalTime; - estateSettings.FixedSun = fixedSun; - estateSettings.SunPosition = sunPosition; - estateSettings.AllowVoice = allowVoice; - estateSettings.AllowDirectTeleport = allowDirectTeleport; - estateSettings.ResetHomeOnTeleport = resetHomeOnTeleport; - estateSettings.DenyAnonymous = denyAnonymous; - estateSettings.DenyIdentified = denyIdentified; - estateSettings.DenyTransacted = denyTransacted; - estateSettings.DenyMinors = denyMinors; - estateSettings.AbuseEmailToEstateOwner = abuseEmailToEstateOwner; - estateSettings.BlockDwell = blockDwell; - estateSettings.EstateSkipScripts = estateSkipScripts; - estateSettings.TaxFree = taxFree; - estateSettings.PublicAccess = publicAccess; - estateSettings.AbuseEmail = abuseEmail; - estateSettings.EstateOwner = estateOwner; - } - - private void ValidateEstateSettings( - EstateSettings estateSettings, - string estateName, - uint parentEstateID, - float billableFactor, - int pricePerMeter, - int redirectGridX, - int redirectGridY, - bool useGlobalTime, - bool fixedSun, - double sunPosition, - bool allowVoice, - bool allowDirectTeleport, - bool resetHomeOnTeleport, - bool denyAnonymous, - bool denyIdentified, - bool denyTransacted, - bool denyMinors, - bool abuseEmailToEstateOwner, - bool blockDwell, - bool estateSkipScripts, - bool taxFree, - bool publicAccess, - string abuseEmail, - UUID estateOwner - ) - { - Assert.AreEqual(estateName, estateSettings.EstateName); - Assert.AreEqual(parentEstateID, estateSettings.ParentEstateID); - - DataTestUtil.AssertFloatEqualsWithTolerance(billableFactor, estateSettings.BillableFactor); - - Assert.AreEqual(pricePerMeter, estateSettings.PricePerMeter); - Assert.AreEqual(redirectGridX, estateSettings.RedirectGridX); - Assert.AreEqual(redirectGridY, estateSettings.RedirectGridY); - - Assert.AreEqual(allowVoice, estateSettings.AllowVoice); - Assert.AreEqual(allowDirectTeleport, estateSettings.AllowDirectTeleport); - Assert.AreEqual(resetHomeOnTeleport, estateSettings.ResetHomeOnTeleport); - Assert.AreEqual(denyAnonymous, estateSettings.DenyAnonymous); - Assert.AreEqual(denyIdentified, estateSettings.DenyIdentified); - Assert.AreEqual(denyTransacted, estateSettings.DenyTransacted); - Assert.AreEqual(denyMinors, estateSettings.DenyMinors); - Assert.AreEqual(abuseEmailToEstateOwner, estateSettings.AbuseEmailToEstateOwner); - Assert.AreEqual(blockDwell, estateSettings.BlockDwell); - Assert.AreEqual(estateSkipScripts, estateSettings.EstateSkipScripts); - Assert.AreEqual(taxFree, estateSettings.TaxFree); - Assert.AreEqual(publicAccess, estateSettings.PublicAccess); - Assert.AreEqual(abuseEmail, estateSettings.AbuseEmail); - Assert.AreEqual(estateOwner, estateSettings.EstateOwner); - } - - #endregion - } -} \ No newline at end of file diff --git a/OpenSim/Data/Tests/InventoryTests.cs b/OpenSim/Data/Tests/InventoryTests.cs deleted file mode 100644 index dc99bf1a5a3..00000000000 --- a/OpenSim/Data/Tests/InventoryTests.cs +++ /dev/null @@ -1,369 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using NUnit.Framework; -using OpenMetaverse; -using OpenSim.Framework; -using OpenSim.Tests.Common; -using System.Data.Common; - -// DBMS-specific: -using OpenSim.Data.MySQL; -using MySqlConnector; - -namespace OpenSim.Data.Tests -{ - [TestFixture(Description = "Inventory store tests (MySQL)")] - public class MySqlInventoryTests : InventoryTests - { - } - - public class InventoryTests : BasicDataServiceTest - where TConn : DbConnection, new() - where TInvStore : class, IInventoryDataPlugin, new() - { - public IInventoryDataPlugin db; - - public UUID zero = UUID.Zero; - - public UUID folder1 = UUID.Random(); - public UUID folder2 = UUID.Random(); - public UUID folder3 = UUID.Random(); - public UUID owner1 = UUID.Random(); - public UUID owner2 = UUID.Random(); - public UUID owner3 = UUID.Random(); - - public UUID item1 = UUID.Random(); - public UUID item2 = UUID.Random(); - public UUID item3 = UUID.Random(); - public UUID asset1 = UUID.Random(); - public UUID asset2 = UUID.Random(); - public UUID asset3 = UUID.Random(); - - public string name1; - public string name2 = "First Level folder"; - public string name3 = "First Level folder 2"; - public string niname1 = "My Shirt"; - public string iname1 = "Shirt"; - public string iname2 = "Text Board"; - public string iname3 = "No Pants Barrel"; - - public InventoryTests(string conn) : base(conn) - { - name1 = "Root Folder for " + owner1.ToString(); - } - public InventoryTests() : this("") { } - - protected override void InitService(object service) - { - ClearDB(); - db = (IInventoryDataPlugin)service; - db.Initialise(m_connStr); - } - - private void ClearDB() - { - DropTables("inventoryitems", "inventoryfolders"); - ResetMigrations("InventoryStore"); - } - - [Test] - public void T001_LoadEmpty() - { - TestHelpers.InMethod(); - - Assert.That(db.getInventoryFolder(zero), Is.Null); - Assert.That(db.getInventoryFolder(folder1), Is.Null); - Assert.That(db.getInventoryFolder(folder2), Is.Null); - Assert.That(db.getInventoryFolder(folder3), Is.Null); - - Assert.That(db.getInventoryItem(zero), Is.Null); - Assert.That(db.getInventoryItem(item1), Is.Null); - Assert.That(db.getInventoryItem(item2), Is.Null); - Assert.That(db.getInventoryItem(item3), Is.Null); - - Assert.That(db.getUserRootFolder(zero), Is.Null); - Assert.That(db.getUserRootFolder(owner1), Is.Null); - } - - // 01x - folder tests - [Test] - public void T010_FolderNonParent() - { - TestHelpers.InMethod(); - - InventoryFolderBase f1 = NewFolder(folder2, folder1, owner1, name2); - // the folder will go in - db.addInventoryFolder(f1); - InventoryFolderBase f1a = db.getUserRootFolder(owner1); - Assert.That(f1a, Is.Null); - } - - [Test] - public void T011_FolderCreate() - { - TestHelpers.InMethod(); - - InventoryFolderBase f1 = NewFolder(folder1, zero, owner1, name1); - // TODO: this is probably wrong behavior, but is what we have - // db.updateInventoryFolder(f1); - // InventoryFolderBase f1a = db.getUserRootFolder(owner1); - // Assert.That(uuid1, Is.EqualTo(f1a.ID)) - // Assert.That(name1, Text.Matches(f1a.Name), "Assert.That(name1, Text.Matches(f1a.Name))"); - // Assert.That(db.getUserRootFolder(owner1), Is.Null); - - // succeed with true - db.addInventoryFolder(f1); - InventoryFolderBase f1a = db.getUserRootFolder(owner1); - Assert.That(folder1, Is.EqualTo(f1a.ID), "Assert.That(folder1, Is.EqualTo(f1a.ID))"); - Assert.That(name1, Does.Match(f1a.Name), "Assert.That(name1, Text.Matches(f1a.Name))"); - } - - // we now have the following tree - // folder1 - // +--- folder2 - // +--- folder3 - - [Test] - public void T012_FolderList() - { - TestHelpers.InMethod(); - - InventoryFolderBase f2 = NewFolder(folder3, folder1, owner1, name3); - db.addInventoryFolder(f2); - - Assert.That(db.getInventoryFolders(zero).Count, Is.EqualTo(1), "Assert.That(db.getInventoryFolders(zero).Count, Is.EqualTo(1))"); - Assert.That(db.getInventoryFolders(folder1).Count, Is.EqualTo(2), "Assert.That(db.getInventoryFolders(folder1).Count, Is.EqualTo(2))"); - Assert.That(db.getInventoryFolders(folder2).Count, Is.EqualTo(0), "Assert.That(db.getInventoryFolders(folder2).Count, Is.EqualTo(0))"); - Assert.That(db.getInventoryFolders(folder3).Count, Is.EqualTo(0), "Assert.That(db.getInventoryFolders(folder3).Count, Is.EqualTo(0))"); - Assert.That(db.getInventoryFolders(UUID.Random()).Count, Is.EqualTo(0), "Assert.That(db.getInventoryFolders(UUID.Random()).Count, Is.EqualTo(0))"); - - } - - [Test] - public void T013_FolderHierarchy() - { - TestHelpers.InMethod(); - - int n = db.getFolderHierarchy(zero).Count; // (for dbg - easier to see what's returned) - Assert.That(n, Is.EqualTo(0), "Assert.That(db.getFolderHierarchy(zero).Count, Is.EqualTo(0))"); - n = db.getFolderHierarchy(folder1).Count; - Assert.That(n, Is.EqualTo(2), "Assert.That(db.getFolderHierarchy(folder1).Count, Is.EqualTo(2))"); - Assert.That(db.getFolderHierarchy(folder2).Count, Is.EqualTo(0), "Assert.That(db.getFolderHierarchy(folder2).Count, Is.EqualTo(0))"); - Assert.That(db.getFolderHierarchy(folder3).Count, Is.EqualTo(0), "Assert.That(db.getFolderHierarchy(folder3).Count, Is.EqualTo(0))"); - Assert.That(db.getFolderHierarchy(UUID.Random()).Count, Is.EqualTo(0), "Assert.That(db.getFolderHierarchy(UUID.Random()).Count, Is.EqualTo(0))"); - } - - - [Test] - public void T014_MoveFolder() - { - TestHelpers.InMethod(); - - InventoryFolderBase f2 = db.getInventoryFolder(folder2); - f2.ParentID = folder3; - db.moveInventoryFolder(f2); - - Assert.That(db.getInventoryFolders(zero).Count, Is.EqualTo(1), "Assert.That(db.getInventoryFolders(zero).Count, Is.EqualTo(1))"); - Assert.That(db.getInventoryFolders(folder1).Count, Is.EqualTo(1), "Assert.That(db.getInventoryFolders(folder1).Count, Is.EqualTo(1))"); - Assert.That(db.getInventoryFolders(folder2).Count, Is.EqualTo(0), "Assert.That(db.getInventoryFolders(folder2).Count, Is.EqualTo(0))"); - Assert.That(db.getInventoryFolders(folder3).Count, Is.EqualTo(1), "Assert.That(db.getInventoryFolders(folder3).Count, Is.EqualTo(1))"); - Assert.That(db.getInventoryFolders(UUID.Random()).Count, Is.EqualTo(0), "Assert.That(db.getInventoryFolders(UUID.Random()).Count, Is.EqualTo(0))"); - } - - [Test] - public void T015_FolderHierarchy() - { - TestHelpers.InMethod(); - - Assert.That(db.getFolderHierarchy(zero).Count, Is.EqualTo(0), "Assert.That(db.getFolderHierarchy(zero).Count, Is.EqualTo(0))"); - Assert.That(db.getFolderHierarchy(folder1).Count, Is.EqualTo(2), "Assert.That(db.getFolderHierarchy(folder1).Count, Is.EqualTo(2))"); - Assert.That(db.getFolderHierarchy(folder2).Count, Is.EqualTo(0), "Assert.That(db.getFolderHierarchy(folder2).Count, Is.EqualTo(0))"); - Assert.That(db.getFolderHierarchy(folder3).Count, Is.EqualTo(1), "Assert.That(db.getFolderHierarchy(folder3).Count, Is.EqualTo(1))"); - Assert.That(db.getFolderHierarchy(UUID.Random()).Count, Is.EqualTo(0), "Assert.That(db.getFolderHierarchy(UUID.Random()).Count, Is.EqualTo(0))"); - } - - // Item tests - [Test] - public void T100_NoItems() - { - TestHelpers.InMethod(); - - Assert.That(db.getInventoryInFolder(zero).Count, Is.EqualTo(0), "Assert.That(db.getInventoryInFolder(zero).Count, Is.EqualTo(0))"); - Assert.That(db.getInventoryInFolder(folder1).Count, Is.EqualTo(0), "Assert.That(db.getInventoryInFolder(folder1).Count, Is.EqualTo(0))"); - Assert.That(db.getInventoryInFolder(folder2).Count, Is.EqualTo(0), "Assert.That(db.getInventoryInFolder(folder2).Count, Is.EqualTo(0))"); - Assert.That(db.getInventoryInFolder(folder3).Count, Is.EqualTo(0), "Assert.That(db.getInventoryInFolder(folder3).Count, Is.EqualTo(0))"); - } - - // TODO: Feeding a bad inventory item down the data path will - // crash the system. This is largely due to the builder - // routines. That should be fixed and tested for. - [Test] - public void T101_CreatItems() - { - TestHelpers.InMethod(); - - db.addInventoryItem(NewItem(item1, folder3, owner1, iname1, asset1)); - db.addInventoryItem(NewItem(item2, folder3, owner1, iname2, asset2)); - db.addInventoryItem(NewItem(item3, folder3, owner1, iname3, asset3)); - Assert.That(db.getInventoryInFolder(folder3).Count, Is.EqualTo(3), "Assert.That(db.getInventoryInFolder(folder3).Count, Is.EqualTo(3))"); - } - - [Test] - public void T102_CompareItems() - { - TestHelpers.InMethod(); - - InventoryItemBase i1 = db.getInventoryItem(item1); - InventoryItemBase i2 = db.getInventoryItem(item2); - InventoryItemBase i3 = db.getInventoryItem(item3); - Assert.That(i1.Name, Is.EqualTo(iname1), "Assert.That(i1.Name, Is.EqualTo(iname1))"); - Assert.That(i2.Name, Is.EqualTo(iname2), "Assert.That(i2.Name, Is.EqualTo(iname2))"); - Assert.That(i3.Name, Is.EqualTo(iname3), "Assert.That(i3.Name, Is.EqualTo(iname3))"); - Assert.That(i1.Owner, Is.EqualTo(owner1), "Assert.That(i1.Owner, Is.EqualTo(owner1))"); - Assert.That(i2.Owner, Is.EqualTo(owner1), "Assert.That(i2.Owner, Is.EqualTo(owner1))"); - Assert.That(i3.Owner, Is.EqualTo(owner1), "Assert.That(i3.Owner, Is.EqualTo(owner1))"); - Assert.That(i1.AssetID, Is.EqualTo(asset1), "Assert.That(i1.AssetID, Is.EqualTo(asset1))"); - Assert.That(i2.AssetID, Is.EqualTo(asset2), "Assert.That(i2.AssetID, Is.EqualTo(asset2))"); - Assert.That(i3.AssetID, Is.EqualTo(asset3), "Assert.That(i3.AssetID, Is.EqualTo(asset3))"); - } - - [Test] - public void T103_UpdateItem() - { - TestHelpers.InMethod(); - - // TODO: probably shouldn't have the ability to have an - // owner of an item in a folder not owned by the user - - InventoryItemBase i1 = db.getInventoryItem(item1); - i1.Name = niname1; - i1.Description = niname1; - i1.Owner = owner2; - db.updateInventoryItem(i1); - - i1 = db.getInventoryItem(item1); - Assert.That(i1.Name, Is.EqualTo(niname1), "Assert.That(i1.Name, Is.EqualTo(niname1))"); - Assert.That(i1.Description, Is.EqualTo(niname1), "Assert.That(i1.Description, Is.EqualTo(niname1))"); - Assert.That(i1.Owner, Is.EqualTo(owner2), "Assert.That(i1.Owner, Is.EqualTo(owner2))"); - } - - [Test] - public void T104_RandomUpdateItem() - { - TestHelpers.InMethod(); - - PropertyScrambler folderScrambler = - new PropertyScrambler() - .DontScramble(x => x.Owner) - .DontScramble(x => x.ParentID) - .DontScramble(x => x.ID); - UUID owner = UUID.Random(); - UUID folder = UUID.Random(); - UUID rootId = UUID.Random(); - UUID rootAsset = UUID.Random(); - InventoryFolderBase f1 = NewFolder(folder, zero, owner, name1); - folderScrambler.Scramble(f1); - - db.addInventoryFolder(f1); - InventoryFolderBase f1a = db.getUserRootFolder(owner); - Assert.That(f1a, Constraints.PropertyCompareConstraint(f1)); - - folderScrambler.Scramble(f1a); - - db.updateInventoryFolder(f1a); - - InventoryFolderBase f1b = db.getUserRootFolder(owner); - Assert.That(f1b, Constraints.PropertyCompareConstraint(f1a)); - - //Now we have a valid folder to insert into, we can insert the item. - PropertyScrambler inventoryScrambler = - new PropertyScrambler() - .DontScramble(x => x.ID) - .DontScramble(x => x.AssetID) - .DontScramble(x => x.Owner) - .DontScramble(x => x.Folder); - InventoryItemBase root = NewItem(rootId, folder, owner, iname1, rootAsset); - inventoryScrambler.Scramble(root); - db.addInventoryItem(root); - - InventoryItemBase expected = db.getInventoryItem(rootId); - Assert.That(expected, Constraints.PropertyCompareConstraint(root) - .IgnoreProperty(x => x.InvType) - .IgnoreProperty(x => x.CreatorIdAsUuid) - .IgnoreProperty(x => x.Description) - .IgnoreProperty(x => x.CreatorIdentification) - .IgnoreProperty(x => x.CreatorData)); - - inventoryScrambler.Scramble(expected); - db.updateInventoryItem(expected); - - InventoryItemBase actual = db.getInventoryItem(rootId); - Assert.That(actual, Constraints.PropertyCompareConstraint(expected) - .IgnoreProperty(x => x.InvType) - .IgnoreProperty(x => x.CreatorIdAsUuid) - .IgnoreProperty(x => x.Description) - .IgnoreProperty(x => x.CreatorIdentification) - .IgnoreProperty(x => x.CreatorData)); - } - - [Test] - public void T999_StillNull() - { - TestHelpers.InMethod(); - - // After all tests are run, these should still return no results - Assert.That(db.getInventoryFolder(zero), Is.Null); - Assert.That(db.getInventoryItem(zero), Is.Null); - Assert.That(db.getUserRootFolder(zero), Is.Null); - Assert.That(db.getInventoryInFolder(zero).Count, Is.EqualTo(0), "Assert.That(db.getInventoryInFolder(zero).Count, Is.EqualTo(0))"); - } - - private InventoryItemBase NewItem(UUID id, UUID parent, UUID owner, string name, UUID asset) - { - InventoryItemBase i = new InventoryItemBase(); - i.ID = id; - i.Folder = parent; - i.Owner = owner; - i.CreatorId = owner.ToString(); - i.Name = name; - i.Description = name; - i.AssetID = asset; - return i; - } - - private InventoryFolderBase NewFolder(UUID id, UUID parent, UUID owner, string name) - { - InventoryFolderBase f = new InventoryFolderBase(); - f.ID = id; - f.ParentID = parent; - f.Owner = owner; - f.Name = name; - return f; - } - } -} diff --git a/OpenSim/Data/Tests/OpenSim.Data.Tests.csproj b/OpenSim/Data/Tests/OpenSim.Data.Tests.csproj deleted file mode 100644 index 18a0723e094..00000000000 --- a/OpenSim/Data/Tests/OpenSim.Data.Tests.csproj +++ /dev/null @@ -1,42 +0,0 @@ - - - net8.0 - - - - ..\..\..\bin\Nini.dll - False - - - ..\..\..\bin\OpenMetaverse.dll - False - - - ..\..\..\bin\OpenMetaverseTypes.dll - False - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/OpenSim/Data/Tests/PropertyCompareConstraint.cs b/OpenSim/Data/Tests/PropertyCompareConstraint.cs deleted file mode 100644 index b99525a74a3..00000000000 --- a/OpenSim/Data/Tests/PropertyCompareConstraint.cs +++ /dev/null @@ -1,413 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections; -using System.Collections.Generic; -using System.Drawing; -using System.Linq; -using System.Linq.Expressions; -using System.Reflection; -using NUnit.Framework; -using NUnit.Framework.Constraints; -using OpenMetaverse; -using OpenSim.Framework; -using OpenSim.Tests.Common; - -namespace OpenSim.Data.Tests -{ - public static class Constraints - { - //This is here because C# has a gap in the language, you can't infer type from a constructor - public static PropertyCompareConstraint PropertyCompareConstraint(T expected) - { - return new PropertyCompareConstraint(expected); - } - } - - public class PropertyCompareConstraint : NUnit.Framework.Constraints.Constraint - { - private readonly object _expected; - //the reason everywhere uses propertyNames.Reverse().ToArray() is because the stack is backwards of the order we want to display the properties in. - private string failingPropertyName = string.Empty; - private object failingExpected; - private object failingActual; - - public PropertyCompareConstraint(T expected) - { - _expected = expected; - } - - public override bool Matches(object actual) - { - return ObjectCompare(_expected, actual, new Stack()); - } - - private bool ObjectCompare(object expected, object actual, Stack propertyNames) - { - //If they are both null, they are equal - if (actual == null && expected == null) - return true; - - //If only one is null, then they aren't - if (actual == null || expected == null) - { - failingPropertyName = string.Join(".", propertyNames.Reverse().ToArray()); - failingActual = actual; - failingExpected = expected; - return false; - } - - //prevent loops... - if (propertyNames.Count > 50) - { - failingPropertyName = string.Join(".", propertyNames.Reverse().ToArray()); - failingActual = actual; - failingExpected = expected; - return false; - } - - if (actual.GetType() != expected.GetType()) - { - propertyNames.Push("GetType()"); - failingPropertyName = string.Join(".", propertyNames.Reverse().ToArray()); - propertyNames.Pop(); - failingActual = actual.GetType(); - failingExpected = expected.GetType(); - return false; - } - - if (actual.GetType() == typeof(Color)) - { - Color actualColor = (Color) actual; - Color expectedColor = (Color) expected; - if (actualColor.R != expectedColor.R) - { - propertyNames.Push("R"); - failingPropertyName = string.Join(".", propertyNames.Reverse().ToArray()); - propertyNames.Pop(); - failingActual = actualColor.R; - failingExpected = expectedColor.R; - return false; - } - if (actualColor.G != expectedColor.G) - { - propertyNames.Push("G"); - failingPropertyName = string.Join(".", propertyNames.Reverse().ToArray()); - propertyNames.Pop(); - failingActual = actualColor.G; - failingExpected = expectedColor.G; - return false; - } - if (actualColor.B != expectedColor.B) - { - propertyNames.Push("B"); - failingPropertyName = string.Join(".", propertyNames.Reverse().ToArray()); - propertyNames.Pop(); - failingActual = actualColor.B; - failingExpected = expectedColor.B; - return false; - } - if (actualColor.A != expectedColor.A) - { - propertyNames.Push("A"); - failingPropertyName = string.Join(".", propertyNames.Reverse().ToArray()); - propertyNames.Pop(); - failingActual = actualColor.A; - failingExpected = expectedColor.A; - return false; - } - return true; - } - - IComparable comp = actual as IComparable; - if (comp != null) - { - if (comp.CompareTo(expected) != 0) - { - failingPropertyName = string.Join(".", propertyNames.Reverse().ToArray()); - failingActual = actual; - failingExpected = expected; - return false; - } - return true; - } - - //Now try the much more annoying IComparable - Type icomparableInterface = actual.GetType().GetInterface("IComparable`1"); - if (icomparableInterface != null) - { - int result = (int)icomparableInterface.GetMethod("CompareTo").Invoke(actual, new[] { expected }); - if (result != 0) - { - failingPropertyName = string.Join(".", propertyNames.Reverse().ToArray()); - failingActual = actual; - failingExpected = expected; - return false; - } - return true; - } - - IEnumerable arr = actual as IEnumerable; - if (arr != null) - { - List actualList = arr.Cast().ToList(); - List expectedList = ((IEnumerable)expected).Cast().ToList(); - if (actualList.Count != expectedList.Count) - { - propertyNames.Push("Count"); - failingPropertyName = string.Join(".", propertyNames.Reverse().ToArray()); - failingActual = actualList.Count; - failingExpected = expectedList.Count; - propertyNames.Pop(); - return false; - } - //actualList and expectedList should be the same size. - for (int i = 0; i < actualList.Count; i++) - { - propertyNames.Push("[" + i + "]"); - if (!ObjectCompare(expectedList[i], actualList[i], propertyNames)) - return false; - propertyNames.Pop(); - } - //Everything seems okay... - return true; - } - - //Skip static properties. I had a nasty problem comparing colors because of all of the public static colors. - PropertyInfo[] properties = expected.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance); - foreach (var property in properties) - { - if (ignores.Contains(property.Name)) - continue; - - object actualValue = property.GetValue(actual, null); - object expectedValue = property.GetValue(expected, null); - - propertyNames.Push(property.Name); - if (!ObjectCompare(expectedValue, actualValue, propertyNames)) - return false; - propertyNames.Pop(); - } - - return true; - } - - public override void WriteDescriptionTo(MessageWriter writer) - { - writer.WriteExpectedValue(failingExpected); - } - - public override void WriteActualValueTo(MessageWriter writer) - { - writer.WriteActualValue(failingActual); - writer.WriteLine(); - writer.Write(" On Property: " + failingPropertyName); - } - - //These notes assume the lambda: (x=>x.Parent.Value) - //ignores should really contain like a fully dotted version of the property name, but I'm starting with small steps - readonly List ignores = new List(); - public PropertyCompareConstraint IgnoreProperty(Expression> func) - { - Expression express = func.Body; - PullApartExpression(express); - - return this; - } - - private void PullApartExpression(Expression express) - { - //This deals with any casts... like implicit casts to object. Not all UnaryExpression are casts, but this is a first attempt. - if (express is UnaryExpression) - PullApartExpression(((UnaryExpression)express).Operand); - if (express is MemberExpression) - { - //If the inside of the lambda is the access to x, we've hit the end of the chain. - // We should track by the fully scoped parameter name, but this is the first rev of doing this. - ignores.Add(((MemberExpression)express).Member.Name); - } - } - } - - [TestFixture] - public class PropertyCompareConstraintTest : OpenSimTestCase - { - public class HasInt - { - public int TheValue { get; set; } - } - - [Test] - public void IntShouldMatch() - { - HasInt actual = new HasInt { TheValue = 5 }; - HasInt expected = new HasInt { TheValue = 5 }; - var constraint = Constraints.PropertyCompareConstraint(expected); - - Assert.That(constraint.Matches(actual), Is.True); - } - - [Test] - public void IntShouldNotMatch() - { - HasInt actual = new HasInt { TheValue = 5 }; - HasInt expected = new HasInt { TheValue = 4 }; - var constraint = Constraints.PropertyCompareConstraint(expected); - - Assert.That(constraint.Matches(actual), Is.False); - } - - - [Test] - public void IntShouldIgnore() - { - HasInt actual = new HasInt { TheValue = 5 }; - HasInt expected = new HasInt { TheValue = 4 }; - var constraint = Constraints.PropertyCompareConstraint(expected).IgnoreProperty(x => x.TheValue); - - Assert.That(constraint.Matches(actual), Is.True); - } - - [Test] - public void AssetShouldMatch() - { - UUID uuid1 = UUID.Random(); - AssetBase actual = new AssetBase(uuid1, "asset one", (sbyte)AssetType.Texture, UUID.Zero.ToString()); - AssetBase expected = new AssetBase(uuid1, "asset one", (sbyte)AssetType.Texture, UUID.Zero.ToString()); - - var constraint = Constraints.PropertyCompareConstraint(expected); - - Assert.That(constraint.Matches(actual), Is.True); - } - - [Test] - public void AssetShouldNotMatch() - { - UUID uuid1 = UUID.Random(); - AssetBase actual = new AssetBase(uuid1, "asset one", (sbyte)AssetType.Texture, UUID.Zero.ToString()); - AssetBase expected = new AssetBase(UUID.Random(), "asset one", (sbyte)AssetType.Texture, UUID.Zero.ToString()); - - var constraint = Constraints.PropertyCompareConstraint(expected); - - Assert.That(constraint.Matches(actual), Is.False); - } - - [Test] - public void AssetShouldNotMatch2() - { - UUID uuid1 = UUID.Random(); - AssetBase actual = new AssetBase(uuid1, "asset one", (sbyte)AssetType.Texture, UUID.Zero.ToString()); - AssetBase expected = new AssetBase(uuid1, "asset two", (sbyte)AssetType.Texture, UUID.Zero.ToString()); - - var constraint = Constraints.PropertyCompareConstraint(expected); - - Assert.That(constraint.Matches(actual), Is.False); - } - - [Test] - public void UUIDShouldMatch() - { - UUID uuid1 = UUID.Random(); - UUID uuid2 = UUID.Parse(uuid1.ToString()); - - var constraint = Constraints.PropertyCompareConstraint(uuid1); - - Assert.That(constraint.Matches(uuid2), Is.True); - } - - [Test] - public void UUIDShouldNotMatch() - { - UUID uuid1 = UUID.Random(); - UUID uuid2 = UUID.Random(); - - var constraint = Constraints.PropertyCompareConstraint(uuid1); - - Assert.That(constraint.Matches(uuid2), Is.False); - } - - [Test] - public void TestColors() - { - Color actual = Color.Red; - Color expected = Color.FromArgb(actual.A, actual.R, actual.G, actual.B); - - var constraint = Constraints.PropertyCompareConstraint(expected); - - Assert.That(constraint.Matches(actual), Is.True); - } - - [Test] - public void ShouldCompareLists() - { - List expected = new List { 1, 2, 3 }; - List actual = new List { 1, 2, 3 }; - - var constraint = Constraints.PropertyCompareConstraint(expected); - Assert.That(constraint.Matches(actual), Is.True); - } - - - [Test] - public void ShouldFailToCompareListsThatAreDifferent() - { - List expected = new List { 1, 2, 3 }; - List actual = new List { 1, 2, 4 }; - - var constraint = Constraints.PropertyCompareConstraint(expected); - Assert.That(constraint.Matches(actual), Is.False); - } - - [Test] - public void ShouldFailToCompareListsThatAreDifferentLengths() - { - List expected = new List { 1, 2, 3 }; - List actual = new List { 1, 2 }; - - var constraint = Constraints.PropertyCompareConstraint(expected); - Assert.That(constraint.Matches(actual), Is.False); - } - - public class Recursive - { - public Recursive Other { get; set; } - } - - [Test] - public void ErrorsOutOnRecursive() - { - Recursive parent = new Recursive(); - Recursive child = new Recursive(); - parent.Other = child; - child.Other = parent; - - var constraint = Constraints.PropertyCompareConstraint(child); - Assert.That(constraint.Matches(child), Is.False); - } - } -} \ No newline at end of file diff --git a/OpenSim/Data/Tests/PropertyScrambler.cs b/OpenSim/Data/Tests/PropertyScrambler.cs deleted file mode 100644 index 0d291df0b32..00000000000 --- a/OpenSim/Data/Tests/PropertyScrambler.cs +++ /dev/null @@ -1,184 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections; -using System.Collections.Generic; -using System.Linq.Expressions; -using System.Reflection; -using System.Text; -using NUnit.Framework; -using OpenMetaverse; -using OpenSim.Framework; -using OpenSim.Tests.Common; - -namespace OpenSim.Data.Tests -{ - //This is generic so that the lambda expressions will work right in IDEs. - public class PropertyScrambler - { - readonly System.Collections.Generic.List membersToNotScramble = new List(); - - private void AddExpressionToNotScrableList(Expression expression) - { - UnaryExpression unaryExpression = expression as UnaryExpression; - if (unaryExpression != null) - { - AddExpressionToNotScrableList(unaryExpression.Operand); - return; - } - - MemberExpression memberExpression = expression as MemberExpression; - if (memberExpression != null) - { - if (!(memberExpression.Member is PropertyInfo)) - { - throw new NotImplementedException("I don't know how deal with a MemberExpression that is a " + expression.Type); - } - membersToNotScramble.Add(memberExpression.Member.Name); - return; - } - - throw new NotImplementedException("I don't know how to parse a " + expression.Type); - } - - public PropertyScrambler DontScramble(Expression> expression) - { - AddExpressionToNotScrableList(expression.Body); - return this; - } - - public void Scramble(T obj) - { - internalScramble(obj); - } - - private void internalScramble(object obj) - { - PropertyInfo[] properties = obj.GetType().GetProperties(); - foreach (var property in properties) - { - //Skip indexers of classes. We will assume that everything that has an indexer - // is also IEnumberable. May not always be true, but should be true normally. - if (property.GetIndexParameters().Length > 0) - continue; - - RandomizeProperty(obj, property, null); - } - //Now if it implments IEnumberable, it's probably some kind of list, so we should randomize - // everything inside of it. - IEnumerable enumerable = obj as IEnumerable; - if (enumerable != null) - { - foreach (object value in enumerable) - { - internalScramble(value); - } - } - } - - private readonly Random random = new Random(); - private void RandomizeProperty(object obj, PropertyInfo property, object[] index) - {//I'd like a better way to compare, but I had lots of problems with InventoryFolderBase because the ID is inherited. - if (membersToNotScramble.Contains(property.Name)) - return; - Type t = property.PropertyType; - if (!property.CanWrite) - return; - object value = property.GetValue(obj, index); - if (value == null) - return; - - if (t == typeof(string)) - property.SetValue(obj, RandomName(), index); - else if (t == typeof(UUID)) - property.SetValue(obj, UUID.Random(), index); - else if (t == typeof(sbyte)) - property.SetValue(obj, (sbyte)random.Next(sbyte.MinValue, sbyte.MaxValue), index); - else if (t == typeof(short)) - property.SetValue(obj, (short)random.Next(short.MinValue, short.MaxValue), index); - else if (t == typeof(int)) - property.SetValue(obj, random.Next(), index); - else if (t == typeof(long)) - property.SetValue(obj, random.Next() * int.MaxValue, index); - else if (t == typeof(byte)) - property.SetValue(obj, (byte)random.Next(byte.MinValue, byte.MaxValue), index); - else if (t == typeof(ushort)) - property.SetValue(obj, (ushort)random.Next(ushort.MinValue, ushort.MaxValue), index); - else if (t == typeof(uint)) - property.SetValue(obj, Convert.ToUInt32(random.Next()), index); - else if (t == typeof(ulong)) - property.SetValue(obj, Convert.ToUInt64(random.Next()) * Convert.ToUInt64(UInt32.MaxValue), index); - else if (t == typeof(bool)) - property.SetValue(obj, true, index); - else if (t == typeof(byte[])) - { - byte[] bytes = new byte[30]; - random.NextBytes(bytes); - property.SetValue(obj, bytes, index); - } - else - internalScramble(value); - } - - private string RandomName() - { - StringBuilder name = new StringBuilder(); - int size = random.Next(5, 12); - for (int i = 0; i < size; i++) - { - char ch = Convert.ToChar(Convert.ToInt32(Math.Floor(26 * random.NextDouble() + 65))); - name.Append(ch); - } - return name.ToString(); - } - } - - [TestFixture] - public class PropertyScramblerTests : OpenSimTestCase - { - [Test] - public void TestScramble() - { - AssetBase actual = new AssetBase(UUID.Random(), "asset one", (sbyte)AssetType.Texture, UUID.Zero.ToString()); - new PropertyScrambler().Scramble(actual); - } - - [Test] - public void DontScramble() - { - UUID uuid = UUID.Random(); - AssetBase asset = new AssetBase(uuid, "asset", (sbyte)AssetType.Texture, UUID.Zero.ToString()); - new PropertyScrambler() - .DontScramble(x => x.Metadata) - .DontScramble(x => x.FullID) - .DontScramble(x => x.ID) - .Scramble(asset); - Assert.That(asset.FullID, Is.EqualTo(uuid)); - } - } -} \ No newline at end of file diff --git a/OpenSim/Data/Tests/RegionTests.cs b/OpenSim/Data/Tests/RegionTests.cs deleted file mode 100644 index 75d644aa0af..00000000000 --- a/OpenSim/Data/Tests/RegionTests.cs +++ /dev/null @@ -1,1145 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections.Generic; -using System.Drawing; -using System.Text; -using NUnit.Framework; -using OpenMetaverse; -using OpenSim.Framework; -using OpenSim.Region.Framework.Interfaces; -using OpenSim.Region.Framework.Scenes; -using OpenSim.Tests.Common; -using System.Data.Common; -using System.Threading; - -// DBMS-specific: -using OpenSim.Data.MySQL; - -using System.Data.SQLite; -using OpenSim.Data.SQLite; -using MySqlConnector; - -namespace OpenSim.Data.Tests -{ - [TestFixture(Description = "Region store tests (SQLite)")] - public class SQLiteRegionTests : RegionTests - { - } - - [TestFixture(Description = "Region store tests (MySQL)")] - public class MySqlRegionTests : RegionTests - { - } - - public class RegionTests : BasicDataServiceTest - where TConn : DbConnection, new() - where TRegStore : class, ISimulationDataStore, new() - { - bool m_rebuildDB; - - public ISimulationDataStore db; - public UUID zero = UUID.Zero; - public UUID region1 = UUID.Random(); - public UUID region2 = UUID.Random(); - public UUID region3 = UUID.Random(); - public UUID region4 = UUID.Random(); - public UUID prim1 = UUID.Random(); - public UUID prim2 = UUID.Random(); - public UUID prim3 = UUID.Random(); - public UUID prim4 = UUID.Random(); - public UUID prim5 = UUID.Random(); - public UUID prim6 = UUID.Random(); - public UUID item1 = UUID.Random(); - public UUID item2 = UUID.Random(); - public UUID item3 = UUID.Random(); - - public static Random random = new Random(); - - public string itemname1 = "item1"; - - public uint localID = 1; - - public double height1 = 20; - public double height2 = 100; - - public RegionTests(string conn, bool rebuild) - : base(conn) - { - m_rebuildDB = rebuild; - } - - public RegionTests() : this("", true) { } - public RegionTests(string conn) : this(conn, true) {} - public RegionTests(bool rebuild): this("", rebuild) {} - - - protected override void InitService(object service) - { - ClearDB(); - db = (ISimulationDataStore)service; - db.Initialise(m_connStr); - } - - private void ClearDB() - { - string[] reg_tables = new string[] { - "prims", "primshapes", "primitems", "terrain", "land", "landaccesslist", "regionban", "regionsettings" - }; - - if (m_rebuildDB) - { - DropTables(reg_tables); - ResetMigrations("RegionStore"); - } - else - { - ClearTables(reg_tables); - } - } - - // Test Plan - // Prims - // - empty test - 001 - // - store / retrieve basic prims (most minimal we can make) - 010, 011 - // - store / retrieve parts in a scenegroup 012 - // - store a prim with complete information for consistency check 013 - // - update existing prims, make sure it sticks - 014 - // - tests empty inventory - 020 - // - add inventory items to prims make - 021 - // - retrieves the added item - 022 - // - update inventory items to prims - 023 - // - remove inventory items make sure it sticks - 024 - // - checks if all parameters are persistent - 025 - // - adds many items and see if it is handled correctly - 026 - - [Test] - public void T001_LoadEmpty() - { - TestHelpers.InMethod(); - - List objs = db.LoadObjects(region1); - List objs3 = db.LoadObjects(region3); - List land = db.LoadLandObjects(region1); - - Assert.That(objs.Count, Is.EqualTo(0), "Assert.That(objs.Count, Is.EqualTo(0))"); - Assert.That(objs3.Count, Is.EqualTo(0), "Assert.That(objs3.Count, Is.EqualTo(0))"); - Assert.That(land.Count, Is.EqualTo(0), "Assert.That(land.Count, Is.EqualTo(0))"); - } - - // SOG round trips - // * store objects, make sure they save - // * update - - [Test] - public void T010_StoreSimpleObject() - { - TestHelpers.InMethod(); - - SceneObjectGroup sog = NewSOG("object1", prim1, region1); - SceneObjectGroup sog2 = NewSOG("object2", prim2, region1); - - // in case the objects don't store - try - { - db.StoreObject(sog, region1); - } - catch (Exception e) - { - m_log.Error(e.ToString()); - Assert.Fail(); - } - - try - { - db.StoreObject(sog2, region1); - } - catch (Exception e) - { - m_log.Error(e.ToString()); - Assert.Fail(); - } - - // This tests the ADO.NET driver - List objs = db.LoadObjects(region1); - - Assert.That(objs.Count, Is.EqualTo(2), "Assert.That(objs.Count, Is.EqualTo(2))"); - } - - [Test] - public void T011_ObjectNames() - { - TestHelpers.InMethod(); - - List objs = db.LoadObjects(region1); - foreach (SceneObjectGroup sog in objs) - { - SceneObjectPart p = sog.RootPart; - Assert.That("", Is.Not.EqualTo(p.Name), "Assert.That(\"\", Is.Not.EqualTo(p.Name))"); - Assert.That(p.Name, Is.EqualTo(p.Description), "Assert.That(p.Name, Is.EqualTo(p.Description))"); - } - } - - [Test] - public void T012_SceneParts() - { - TestHelpers.InMethod(); - - UUID tmp0 = UUID.Random(); - UUID tmp1 = UUID.Random(); - UUID tmp2 = UUID.Random(); - UUID tmp3 = UUID.Random(); - UUID newregion = UUID.Random(); - SceneObjectPart p1 = NewSOP("SoP 1",tmp1); - SceneObjectPart p2 = NewSOP("SoP 2",tmp2); - SceneObjectPart p3 = NewSOP("SoP 3",tmp3); - SceneObjectGroup sog = NewSOG("Sop 0", tmp0, newregion); - sog.AddPart(p1); - sog.AddPart(p2); - sog.AddPart(p3); - - SceneObjectPart[] parts = sog.Parts; - Assert.That(parts.Length,Is.EqualTo(4), "Assert.That(parts.Length,Is.EqualTo(4))"); - - db.StoreObject(sog, newregion); - List sogs = db.LoadObjects(newregion); - Assert.That(sogs.Count,Is.EqualTo(1), "Assert.That(sogs.Count,Is.EqualTo(1))"); - SceneObjectGroup newsog = sogs[0]; - - SceneObjectPart[] newparts = newsog.Parts; - Assert.That(newparts.Length,Is.EqualTo(4), "Assert.That(newparts.Length,Is.EqualTo(4))"); - - Assert.That(newsog.ContainsPart(tmp0), "Assert.That(newsog.ContainsPart(tmp0))"); - Assert.That(newsog.ContainsPart(tmp1), "Assert.That(newsog.ContainsPart(tmp1))"); - Assert.That(newsog.ContainsPart(tmp2), "Assert.That(newsog.ContainsPart(tmp2))"); - Assert.That(newsog.ContainsPart(tmp3), "Assert.That(newsog.ContainsPart(tmp3))"); - } - - [Test] - public void T013_DatabasePersistency() - { - TestHelpers.InMethod(); - - // Sets all ScenePart parameters, stores and retrieves them, then check for consistency with initial data - // The commented Asserts are the ones that are unchangeable (when storing on the database, their "Set" values are ignored - // The ObjectFlags is an exception, if it is entered incorrectly, the object IS REJECTED on the database silently. - UUID creator,uuid = new UUID(); - creator = UUID.Random(); - uint iserial = (uint)random.Next(); - TaskInventoryDictionary dic = new TaskInventoryDictionary(); - uint objf = (uint) random.Next() & (uint)~(PrimFlags.Touch | PrimFlags.Money | PrimFlags.AllowInventoryDrop); - uuid = prim4; - uint localid = localID+1; - localID = localID + 1; - string name = "Adam West"; - byte material = (byte) random.Next((int)SOPMaterialData.MaxMaterial); - ulong regionh = (ulong)random.NextDouble() * (ulong)random.Next(); - int pin = random.Next(); - Byte[] partsys = new byte[8]; - Byte[] textani = new byte[8]; - random.NextBytes(textani); - random.NextBytes(partsys); - DateTime expires = new DateTime(2008, 12, 20); - DateTime rezzed = new DateTime(2009, 07, 15); - Vector3 groupos = new Vector3(random.Next(100000),random.Next(100000),random.Next(100000)); - Vector3 offset = new Vector3(random.Next(100000),random.Next(100000),random.Next(100000)); - Quaternion rotoff = new Quaternion(random.Next(1),random.Next(1),random.Next(1),random.Next(1)); - rotoff.Normalize(); - Vector3 velocity = new Vector3(random.Next(100000),random.Next(100000),random.Next(100000)); - Vector3 angvelo = new Vector3(random.Next(100000),random.Next(100000),random.Next(100000)); - Vector3 accel = new Vector3(random.Next(100000),random.Next(100000),random.Next(100000)); - string description = name; - Color color = Color.FromArgb(255, 165, 50, 100); - string text = "All Your Base Are Belong to Us"; - string sitname = "SitName"; - string touchname = "TouchName"; - int linknum = random.Next(); - byte clickaction = (byte) random.Next(127); - PrimitiveBaseShape pbshap = new PrimitiveBaseShape(); - pbshap = PrimitiveBaseShape.Default; - pbshap.PathBegin = ushort.MaxValue; - pbshap.PathEnd = ushort.MaxValue; - pbshap.ProfileBegin = ushort.MaxValue; - pbshap.ProfileEnd = ushort.MaxValue; - pbshap.ProfileHollow = ushort.MaxValue; - Vector3 scale = new Vector3(random.Next(100000),random.Next(100000),random.Next(100000)); - - RegionInfo regionInfo = new RegionInfo() - { - RegionID = region3, - RegionLocX = 0, - RegionLocY = 0 - }; - - SceneObjectPart sop = new SceneObjectPart(); - SceneObjectGroup sog = new SceneObjectGroup(sop); - - sop.RegionHandle = regionh; - sop.UUID = uuid; - sop.LocalId = localid; - sop.Shape = pbshap; - sop.GroupPosition = groupos; - sop.RotationOffset = rotoff; - sop.CreatorID = creator; - sop.InventorySerial = iserial; - sop.TaskInventory = dic; - sop.Flags = (PrimFlags)objf; - sop.Name = name; - sop.Material = material; - sop.ScriptAccessPin = pin; - sop.TextureAnimation = textani; - sop.ParticleSystem = partsys; - sop.Expires = expires; - sop.Rezzed = rezzed; - sop.OffsetPosition = offset; - sop.Velocity = velocity; - sop.AngularVelocity = angvelo; - sop.Acceleration = accel; - sop.Description = description; - sop.Color = color; - sop.Text = text; - sop.SitName = sitname; - sop.TouchName = touchname; - sop.LinkNum = linknum; - sop.ClickAction = clickaction; - sop.Scale = scale; - - //Tests if local part accepted the parameters: - Assert.That(regionh,Is.EqualTo(sop.RegionHandle), "Assert.That(regionh,Is.EqualTo(sop.RegionHandle))"); - Assert.That(localid,Is.EqualTo(sop.LocalId), "Assert.That(localid,Is.EqualTo(sop.LocalId))"); - Assert.That(groupos,Is.EqualTo(sop.GroupPosition), "Assert.That(groupos,Is.EqualTo(sop.GroupPosition))"); - Assert.That(name,Is.EqualTo(sop.Name), "Assert.That(name,Is.EqualTo(sop.Name))"); - Assert.That(rotoff, new QuaternionToleranceConstraint(sop.RotationOffset, 0.001), "Assert.That(rotoff,Is.EqualTo(sop.RotationOffset))"); - Assert.That(uuid,Is.EqualTo(sop.UUID), "Assert.That(uuid,Is.EqualTo(sop.UUID))"); - Assert.That(creator,Is.EqualTo(sop.CreatorID), "Assert.That(creator,Is.EqualTo(sop.CreatorID))"); - // Modified in-class - // Assert.That(iserial,Is.EqualTo(sop.InventorySerial), "Assert.That(iserial,Is.EqualTo(sop.InventorySerial))"); - Assert.That(dic,Is.EqualTo(sop.TaskInventory), "Assert.That(dic,Is.EqualTo(sop.TaskInventory))"); - Assert.That(objf, Is.EqualTo((uint)sop.Flags), "Assert.That(objf,Is.EqualTo(sop.Flags))"); - Assert.That(name,Is.EqualTo(sop.Name), "Assert.That(name,Is.EqualTo(sop.Name))"); - Assert.That(material,Is.EqualTo(sop.Material), "Assert.That(material,Is.EqualTo(sop.Material))"); - Assert.That(pin,Is.EqualTo(sop.ScriptAccessPin), "Assert.That(pin,Is.EqualTo(sop.ScriptAccessPin))"); - Assert.That(textani,Is.EqualTo(sop.TextureAnimation), "Assert.That(textani,Is.EqualTo(sop.TextureAnimation))"); - Assert.That(partsys,Is.EqualTo(sop.ParticleSystem), "Assert.That(partsys,Is.EqualTo(sop.ParticleSystem))"); - Assert.That(expires,Is.EqualTo(sop.Expires), "Assert.That(expires,Is.EqualTo(sop.Expires))"); - Assert.That(rezzed,Is.EqualTo(sop.Rezzed), "Assert.That(rezzed,Is.EqualTo(sop.Rezzed))"); - Assert.That(offset,Is.EqualTo(sop.OffsetPosition), "Assert.That(offset,Is.EqualTo(sop.OffsetPosition))"); - Assert.That(velocity,Is.EqualTo(sop.Velocity), "Assert.That(velocity,Is.EqualTo(sop.Velocity))"); - Assert.That(angvelo,Is.EqualTo(sop.AngularVelocity), "Assert.That(angvelo,Is.EqualTo(sop.AngularVelocity))"); - Assert.That(accel,Is.EqualTo(sop.Acceleration), "Assert.That(accel,Is.EqualTo(sop.Acceleration))"); - Assert.That(description,Is.EqualTo(sop.Description), "Assert.That(description,Is.EqualTo(sop.Description))"); - Assert.That(color,Is.EqualTo(sop.Color), "Assert.That(color,Is.EqualTo(sop.Color))"); - Assert.That(text,Is.EqualTo(sop.Text), "Assert.That(text,Is.EqualTo(sop.Text))"); - Assert.That(sitname,Is.EqualTo(sop.SitName), "Assert.That(sitname,Is.EqualTo(sop.SitName))"); - Assert.That(touchname,Is.EqualTo(sop.TouchName), "Assert.That(touchname,Is.EqualTo(sop.TouchName))"); - Assert.That(linknum,Is.EqualTo(sop.LinkNum), "Assert.That(linknum,Is.EqualTo(sop.LinkNum))"); - Assert.That(clickaction,Is.EqualTo(sop.ClickAction), "Assert.That(clickaction,Is.EqualTo(sop.ClickAction))"); - Assert.That(scale,Is.EqualTo(sop.Scale), "Assert.That(scale,Is.EqualTo(sop.Scale))"); - - // This is necessary or object will not be inserted in DB - sop.Flags = PrimFlags.None; - - // Inserts group in DB - db.StoreObject(sog,region3); - List sogs = db.LoadObjects(region3); - Assert.That(sogs.Count, Is.EqualTo(1), "Assert.That(sogs.Count, Is.EqualTo(1))"); - // Makes sure there are no double insertions: - db.StoreObject(sog,region3); - sogs = db.LoadObjects(region3); - Assert.That(sogs.Count, Is.EqualTo(1), "Assert.That(sogs.Count, Is.EqualTo(1))"); - - - // Tests if the parameters were inserted correctly - SceneObjectPart p = sogs[0].RootPart; - Assert.That(regionh,Is.EqualTo(p.RegionHandle), "Assert.That(regionh,Is.EqualTo(p.RegionHandle))"); - //Assert.That(localid,Is.EqualTo(p.LocalId), "Assert.That(localid,Is.EqualTo(p.LocalId))"); - Assert.That(groupos, Is.EqualTo(p.GroupPosition), "Assert.That(groupos,Is.EqualTo(p.GroupPosition))"); - Assert.That(name,Is.EqualTo(p.Name), "Assert.That(name,Is.EqualTo(p.Name))"); - Assert.That(rotoff, Is.EqualTo(p.RotationOffset), "Assert.That(rotoff,Is.EqualTo(p.RotationOffset))"); - Assert.That(uuid,Is.EqualTo(p.UUID), "Assert.That(uuid,Is.EqualTo(p.UUID))"); - Assert.That(creator,Is.EqualTo(p.CreatorID), "Assert.That(creator,Is.EqualTo(p.CreatorID))"); - //Assert.That(iserial,Is.EqualTo(p.InventorySerial), "Assert.That(iserial,Is.EqualTo(p.InventorySerial))"); - Assert.That(dic,Is.EqualTo(p.TaskInventory), "Assert.That(dic,Is.EqualTo(p.TaskInventory))"); - //Assert.That(objf, Is.EqualTo((uint)p.Flags), "Assert.That(objf,Is.EqualTo(p.Flags))"); - Assert.That(name,Is.EqualTo(p.Name), "Assert.That(name,Is.EqualTo(p.Name))"); - Assert.That(material,Is.EqualTo(p.Material), "Assert.That(material,Is.EqualTo(p.Material))"); - Assert.That(pin,Is.EqualTo(p.ScriptAccessPin), "Assert.That(pin,Is.EqualTo(p.ScriptAccessPin))"); - Assert.That(textani,Is.EqualTo(p.TextureAnimation), "Assert.That(textani,Is.EqualTo(p.TextureAnimation))"); - Assert.That(partsys,Is.EqualTo(p.ParticleSystem), "Assert.That(partsys,Is.EqualTo(p.ParticleSystem))"); - //Assert.That(expires,Is.EqualTo(p.Expires), "Assert.That(expires,Is.EqualTo(p.Expires))"); - //Assert.That(rezzed,Is.EqualTo(p.Rezzed), "Assert.That(rezzed,Is.EqualTo(p.Rezzed))"); - Assert.That(offset,Is.EqualTo(p.OffsetPosition), "Assert.That(offset,Is.EqualTo(p.OffsetPosition))"); - Assert.That(velocity,Is.EqualTo(p.Velocity), "Assert.That(velocity,Is.EqualTo(p.Velocity))"); - Assert.That(angvelo,Is.EqualTo(p.AngularVelocity), "Assert.That(angvelo,Is.EqualTo(p.AngularVelocity))"); - Assert.That(accel,Is.EqualTo(p.Acceleration), "Assert.That(accel,Is.EqualTo(p.Acceleration))"); - Assert.That(description,Is.EqualTo(p.Description), "Assert.That(description,Is.EqualTo(p.Description))"); - Assert.That(color,Is.EqualTo(p.Color), "Assert.That(color,Is.EqualTo(p.Color))"); - Assert.That(text,Is.EqualTo(p.Text), "Assert.That(text,Is.EqualTo(p.Text))"); - Assert.That(sitname,Is.EqualTo(p.SitName), "Assert.That(sitname,Is.EqualTo(p.SitName))"); - Assert.That(touchname,Is.EqualTo(p.TouchName), "Assert.That(touchname,Is.EqualTo(p.TouchName))"); - //Assert.That(linknum,Is.EqualTo(p.LinkNum), "Assert.That(linknum,Is.EqualTo(p.LinkNum))"); - Assert.That(clickaction,Is.EqualTo(p.ClickAction), "Assert.That(clickaction,Is.EqualTo(p.ClickAction))"); - Assert.That(scale,Is.EqualTo(p.Scale), "Assert.That(scale,Is.EqualTo(p.Scale))"); - - //Assert.That(updatef,Is.EqualTo(p.UpdateFlag), "Assert.That(updatef,Is.EqualTo(p.UpdateFlag))"); - - Assert.That(pbshap.PathBegin, Is.EqualTo(p.Shape.PathBegin), "Assert.That(pbshap.PathBegin, Is.EqualTo(p.Shape.PathBegin))"); - Assert.That(pbshap.PathEnd, Is.EqualTo(p.Shape.PathEnd), "Assert.That(pbshap.PathEnd, Is.EqualTo(p.Shape.PathEnd))"); - Assert.That(pbshap.ProfileBegin, Is.EqualTo(p.Shape.ProfileBegin), "Assert.That(pbshap.ProfileBegin, Is.EqualTo(p.Shape.ProfileBegin))"); - Assert.That(pbshap.ProfileEnd, Is.EqualTo(p.Shape.ProfileEnd), "Assert.That(pbshap.ProfileEnd, Is.EqualTo(p.Shape.ProfileEnd))"); - Assert.That(pbshap.ProfileHollow, Is.EqualTo(p.Shape.ProfileHollow), "Assert.That(pbshap.ProfileHollow, Is.EqualTo(p.Shape.ProfileHollow))"); - } - - [Test] - public void T014_UpdateObject() - { - TestHelpers.InMethod(); - - string text1 = "object1 text"; - SceneObjectGroup sog = FindSOG("object1", region1); - sog.RootPart.Text = text1; - db.StoreObject(sog, region1); - - sog = FindSOG("object1", region1); - Assert.That(text1, Is.EqualTo(sog.RootPart.Text), "Assert.That(text1, Is.EqualTo(sog.RootPart.Text))"); - - // Creates random values - UUID creator = new UUID(); - creator = UUID.Random(); - TaskInventoryDictionary dic = new TaskInventoryDictionary(); - localID = localID + 1; - string name = "West Adam"; - byte material = (byte) random.Next((int)SOPMaterialData.MaxMaterial); - ulong regionh = (ulong)random.NextDouble() * (ulong)random.Next(); - int pin = random.Next(); - Byte[] partsys = new byte[8]; - Byte[] textani = new byte[8]; - random.NextBytes(textani); - random.NextBytes(partsys); - DateTime expires = new DateTime(2010, 12, 20); - DateTime rezzed = new DateTime(2005, 07, 15); - Vector3 groupos = new Vector3(random.Next(100000),random.Next(100000),random.Next(100000)); - Vector3 offset = new Vector3(random.Next(100000),random.Next(100000),random.Next(100000)); - Quaternion rotoff = new Quaternion(random.Next(100),random.Next(100),random.Next(100),random.Next(100)); - rotoff.Normalize(); - Vector3 velocity = new Vector3(random.Next(100000),random.Next(100000),random.Next(100000)); - Vector3 angvelo = new Vector3(random.Next(100000),random.Next(100000),random.Next(100000)); - Vector3 accel = new Vector3(random.Next(100000),random.Next(100000),random.Next(100000)); - string description = name; - Color color = Color.FromArgb(255, 255, 255, 0); - string text = "What You Say?{]\vz~"; - string sitname = RandomName(); - string touchname = RandomName(); - int linknum = random.Next(); - byte clickaction = (byte) random.Next(127); - PrimitiveBaseShape pbshap = new PrimitiveBaseShape(); - pbshap = PrimitiveBaseShape.Default; - Vector3 scale = new Vector3(random.Next(),random.Next(),random.Next()); - - // Updates the region with new values - SceneObjectGroup sog2 = FindSOG("Adam West", region3); - Assert.That(sog2,Is.Not.Null); - sog2.RootPart.RegionHandle = regionh; - sog2.RootPart.Shape = pbshap; - sog2.RootPart.GroupPosition = groupos; - sog2.RootPart.RotationOffset = rotoff; - sog2.RootPart.CreatorID = creator; - sog2.RootPart.TaskInventory = dic; - sog2.RootPart.Name = name; - sog2.RootPart.Material = material; - sog2.RootPart.ScriptAccessPin = pin; - sog2.RootPart.TextureAnimation = textani; - sog2.RootPart.ParticleSystem = partsys; - sog2.RootPart.Expires = expires; - sog2.RootPart.Rezzed = rezzed; - sog2.RootPart.OffsetPosition = offset; - sog2.RootPart.Velocity = velocity; - sog2.RootPart.AngularVelocity = angvelo; - sog2.RootPart.Acceleration = accel; - sog2.RootPart.Description = description; - sog2.RootPart.Color = color; - sog2.RootPart.Text = text; - sog2.RootPart.SitName = sitname; - sog2.RootPart.TouchName = touchname; - sog2.RootPart.LinkNum = linknum; - sog2.RootPart.ClickAction = clickaction; - sog2.RootPart.Scale = scale; - - db.StoreObject(sog2, region3); - List sogs = db.LoadObjects(region3); - Assert.That(sogs.Count, Is.EqualTo(1), "Assert.That(sogs.Count, Is.EqualTo(1))"); - - SceneObjectGroup retsog = FindSOG("West Adam", region3); - Assert.That(retsog,Is.Not.Null); - SceneObjectPart p = retsog.RootPart; - Assert.That(regionh,Is.EqualTo(p.RegionHandle), "Assert.That(regionh,Is.EqualTo(p.RegionHandle))"); - Assert.That(groupos,Is.EqualTo(p.GroupPosition), "Assert.That(groupos,Is.EqualTo(p.GroupPosition))"); - Assert.That(name,Is.EqualTo(p.Name), "Assert.That(name,Is.EqualTo(p.Name))"); - Assert.That(rotoff, new QuaternionToleranceConstraint(p.RotationOffset, 0.001), "Assert.That(rotoff,Is.EqualTo(p.RotationOffset))"); - Assert.That(creator,Is.EqualTo(p.CreatorID), "Assert.That(creator,Is.EqualTo(p.CreatorID))"); - Assert.That(dic,Is.EqualTo(p.TaskInventory), "Assert.That(dic,Is.EqualTo(p.TaskInventory))"); - Assert.That(name,Is.EqualTo(p.Name), "Assert.That(name,Is.EqualTo(p.Name))"); - Assert.That(material,Is.EqualTo(p.Material), "Assert.That(material,Is.EqualTo(p.Material))"); - Assert.That(pin,Is.EqualTo(p.ScriptAccessPin), "Assert.That(pin,Is.EqualTo(p.ScriptAccessPin))"); - Assert.That(textani,Is.EqualTo(p.TextureAnimation), "Assert.That(textani,Is.EqualTo(p.TextureAnimation))"); - Assert.That(partsys,Is.EqualTo(p.ParticleSystem), "Assert.That(partsys,Is.EqualTo(p.ParticleSystem))"); - Assert.That(offset,Is.EqualTo(p.OffsetPosition), "Assert.That(offset,Is.EqualTo(p.OffsetPosition))"); - Assert.That(velocity,Is.EqualTo(p.Velocity), "Assert.That(velocity,Is.EqualTo(p.Velocity))"); - Assert.That(angvelo,Is.EqualTo(p.AngularVelocity), "Assert.That(angvelo,Is.EqualTo(p.AngularVelocity))"); - Assert.That(accel,Is.EqualTo(p.Acceleration), "Assert.That(accel,Is.EqualTo(p.Acceleration))"); - Assert.That(description,Is.EqualTo(p.Description), "Assert.That(description,Is.EqualTo(p.Description))"); - Assert.That(color,Is.EqualTo(p.Color), "Assert.That(color,Is.EqualTo(p.Color))"); - Assert.That(text,Is.EqualTo(p.Text), "Assert.That(text,Is.EqualTo(p.Text))"); - Assert.That(sitname,Is.EqualTo(p.SitName), "Assert.That(sitname,Is.EqualTo(p.SitName))"); - Assert.That(touchname,Is.EqualTo(p.TouchName), "Assert.That(touchname,Is.EqualTo(p.TouchName))"); - Assert.That(clickaction,Is.EqualTo(p.ClickAction), "Assert.That(clickaction,Is.EqualTo(p.ClickAction))"); - Assert.That(scale,Is.EqualTo(p.Scale), "Assert.That(scale,Is.EqualTo(p.Scale))"); - } - - /// - /// Test storage and retrieval of a scene object with a large number of parts. - /// - [Test] - public void T015_LargeSceneObjects() - { - TestHelpers.InMethod(); - - UUID id = UUID.Random(); - Dictionary mydic = new Dictionary(); - SceneObjectGroup sog = NewSOG("Test SOG", id, region4); - mydic.Add(sog.RootPart.UUID,sog.RootPart); - for (int i = 0; i < 30; i++) - { - UUID tmp = UUID.Random(); - SceneObjectPart sop = NewSOP(("Test SOP " + i.ToString()),tmp); - Vector3 groupos = new Vector3(random.Next(100000),random.Next(100000),random.Next(100000)); - Vector3 offset = new Vector3(random.Next(100000),random.Next(100000),random.Next(100000)); - Quaternion rotoff = new Quaternion(random.Next(1000),random.Next(1000),random.Next(1000),random.Next(1000)); - rotoff.Normalize(); - Vector3 velocity = new Vector3(random.Next(100000),random.Next(100000),random.Next(100000)); - Vector3 angvelo = new Vector3(random.Next(100000),random.Next(100000),random.Next(100000)); - Vector3 accel = new Vector3(random.Next(100000),random.Next(100000),random.Next(100000)); - - sop.GroupPosition = groupos; - sop.RotationOffset = rotoff; - sop.OffsetPosition = offset; - sop.Velocity = velocity; - sop.AngularVelocity = angvelo; - sop.Acceleration = accel; - - mydic.Add(tmp,sop); - sog.AddPart(sop); - } - - db.StoreObject(sog, region4); - SceneObjectGroup retsog = FindSOG("Test SOG", region4); - SceneObjectPart[] parts = retsog.Parts; - for (int i = 0; i < 30; i++) - { - SceneObjectPart cursop = mydic[parts[i].UUID]; - Assert.That(cursop.GroupPosition,Is.EqualTo(parts[i].GroupPosition), "Assert.That(cursop.GroupPosition,Is.EqualTo(parts[i].GroupPosition))"); - Assert.That(cursop.RotationOffset, new QuaternionToleranceConstraint(parts[i].RotationOffset, 0.001), "Assert.That(rotoff,Is.EqualTo(p.RotationOffset))"); - Assert.That(cursop.OffsetPosition,Is.EqualTo(parts[i].OffsetPosition), "Assert.That(cursop.OffsetPosition,Is.EqualTo(parts[i].OffsetPosition))"); - Assert.That(cursop.Velocity,Is.EqualTo(parts[i].Velocity), "Assert.That(cursop.Velocity,Is.EqualTo(parts[i].Velocity))"); - Assert.That(cursop.AngularVelocity,Is.EqualTo(parts[i].AngularVelocity), "Assert.That(cursop.AngularVelocity,Is.EqualTo(parts[i].AngularVelocity))"); - Assert.That(cursop.Acceleration,Is.EqualTo(parts[i].Acceleration), "Assert.That(cursop.Acceleration,Is.EqualTo(parts[i].Acceleration))"); - } - } - - //[Test] - public void T016_RandomSogWithSceneParts() - { - TestHelpers.InMethod(); - - PropertyScrambler scrambler = - new PropertyScrambler() - .DontScramble(x => x.UUID); - UUID tmpSog = UUID.Random(); - UUID tmp1 = UUID.Random(); - UUID tmp2 = UUID.Random(); - UUID tmp3 = UUID.Random(); - UUID newregion = UUID.Random(); - SceneObjectPart p1 = new SceneObjectPart(); - SceneObjectPart p2 = new SceneObjectPart(); - SceneObjectPart p3 = new SceneObjectPart(); - p1.Shape = PrimitiveBaseShape.Default; - p2.Shape = PrimitiveBaseShape.Default; - p3.Shape = PrimitiveBaseShape.Default; - p1.UUID = tmp1; - p2.UUID = tmp2; - p3.UUID = tmp3; - scrambler.Scramble(p1); - scrambler.Scramble(p2); - scrambler.Scramble(p3); - - SceneObjectGroup sog = NewSOG("Sop 0", tmpSog, newregion); - PropertyScrambler sogScrambler = - new PropertyScrambler() - .DontScramble(x => x.UUID); - sogScrambler.Scramble(sog); - sog.UUID = tmpSog; - sog.AddPart(p1); - sog.AddPart(p2); - sog.AddPart(p3); - - SceneObjectPart[] parts = sog.Parts; - Assert.That(parts.Length, Is.EqualTo(4), "Assert.That(parts.Length,Is.EqualTo(4))"); - - db.StoreObject(sog, newregion); - List sogs = db.LoadObjects(newregion); - Assert.That(sogs.Count, Is.EqualTo(1), "Assert.That(sogs.Count,Is.EqualTo(1))"); - SceneObjectGroup newsog = sogs[0]; - - SceneObjectPart[] newparts = newsog.Parts; - Assert.That(newparts.Length, Is.EqualTo(4), "Assert.That(newparts.Length,Is.EqualTo(4))"); - - Assert.That(newsog, Constraints.PropertyCompareConstraint(sog) - .IgnoreProperty(x=>x.LocalId) - .IgnoreProperty(x=>x.HasGroupChanged) - .IgnoreProperty(x=>x.IsSelected) - .IgnoreProperty(x=>x.RegionHandle) - .IgnoreProperty(x=>x.RegionUUID) - .IgnoreProperty(x=>x.Scene) - .IgnoreProperty(x=>x.Parts) - .IgnoreProperty(x=>x.RootPart)); - } - - - private SceneObjectGroup GetMySOG(string name) - { - SceneObjectGroup sog = FindSOG(name, region1); - if (sog == null) - { - sog = NewSOG(name, prim1, region1); - db.StoreObject(sog, region1); - } - return sog; - } - - // NOTE: it is a bad practice to rely on some of the previous tests having been run before. - // If the tests are run manually, one at a time, each starts with full class init (DB cleared). - // Even when all tests are run, NUnit 2.5+ no longer guarantee a specific test order. - // We shouldn't expect to find anything in the DB if we haven't put it there *in the same test*! - - [Test] - public void T020_PrimInventoryEmpty() - { -/* - TestHelpers.InMethod(); - - SceneObjectGroup sog = GetMySOG("object1"); - TaskInventoryItem t = sog.GetInventoryItem(sog.RootPart.LocalId, item1); - Assert.That(t, Is.Null); -*/ - } - - // TODO: Is there any point to call StorePrimInventory on a list, rather than on the prim itself? - - private void StoreInventory(SceneObjectGroup sog) - { - List list = new List(); - // TODO: seriously??? this is the way we need to loop to get this? - foreach (UUID uuid in sog.RootPart.Inventory.GetInventoryList()) - { - list.Add(sog.GetInventoryItem(sog.RootPart.LocalId, uuid)); - } - - db.StorePrimInventory(sog.RootPart.UUID, list); - } - - [Test] - public void T021_PrimInventoryBasic() - { -/* - TestHelpers.InMethod(); - - SceneObjectGroup sog = GetMySOG("object1"); - InventoryItemBase i = NewItem(item1, zero, zero, itemname1, zero); - - Assert.That(sog.AddInventoryItem(zero, sog.RootPart.LocalId, i, zero), Is.True); - TaskInventoryItem t = sog.GetInventoryItem(sog.RootPart.LocalId, item1); - Assert.That(t.Name, Is.EqualTo(itemname1), "Assert.That(t.Name, Is.EqualTo(itemname1))"); - - StoreInventory(sog); - - SceneObjectGroup sog1 = FindSOG("object1", region1); - Assert.That(sog1, Is.Not.Null); - - TaskInventoryItem t1 = sog1.GetInventoryItem(sog1.RootPart.LocalId, item1); - Assert.That(t1, Is.Not.Null); - Assert.That(t1.Name, Is.EqualTo(itemname1), "Assert.That(t.Name, Is.EqualTo(itemname1))"); - - // Updating inventory - t1.Name = "My New Name"; - sog1.UpdateInventoryItem(t1); - - StoreInventory(sog1); - - SceneObjectGroup sog2 = FindSOG("object1", region1); - TaskInventoryItem t2 = sog2.GetInventoryItem(sog2.RootPart.LocalId, item1); - Assert.That(t2.Name, Is.EqualTo("My New Name"), "Assert.That(t.Name, Is.EqualTo(\"My New Name\"))"); - - // Removing inventory - List list = new List(); - db.StorePrimInventory(prim1, list); - - sog = FindSOG("object1", region1); - t = sog.GetInventoryItem(sog.RootPart.LocalId, item1); - Assert.That(t, Is.Null); -*/ - } - - [Test] - public void T025_PrimInventoryPersistency() - { -/* - TestHelpers.InMethod(); - - InventoryItemBase i = new InventoryItemBase(); - UUID id = UUID.Random(); - i.ID = id; - UUID folder = UUID.Random(); - i.Folder = folder; - UUID owner = UUID.Random(); - i.Owner = owner; - UUID creator = UUID.Random(); - i.CreatorId = creator.ToString(); - string name = RandomName(); - i.Name = name; - i.Description = name; - UUID assetid = UUID.Random(); - i.AssetID = assetid; - int invtype = random.Next(); - i.InvType = invtype; - uint nextperm = (uint) random.Next(); - i.NextPermissions = nextperm; - uint curperm = (uint) random.Next(); - i.CurrentPermissions = curperm; - uint baseperm = (uint) random.Next(); - i.BasePermissions = baseperm; - uint eoperm = (uint) random.Next(); - i.EveryOnePermissions = eoperm; - int assettype = random.Next(); - i.AssetType = assettype; - UUID groupid = UUID.Random(); - i.GroupID = groupid; - bool groupown = true; - i.GroupOwned = groupown; - int saleprice = random.Next(); - i.SalePrice = saleprice; - byte saletype = (byte) random.Next(127); - i.SaleType = saletype; - uint flags = (uint) random.Next(); - i.Flags = flags; - int creationd = random.Next(); - i.CreationDate = creationd; - - SceneObjectGroup sog = GetMySOG("object1"); - Assert.That(sog.AddInventoryItem(zero, sog.RootPart.LocalId, i, zero), Is.True); - TaskInventoryItem t = sog.GetInventoryItem(sog.RootPart.LocalId, id); - - Assert.That(t.Name, Is.EqualTo(name), "Assert.That(t.Name, Is.EqualTo(name))"); - Assert.That(t.AssetID,Is.EqualTo(assetid), "Assert.That(t.AssetID,Is.EqualTo(assetid))"); - Assert.That(t.BasePermissions,Is.EqualTo(baseperm), "Assert.That(t.BasePermissions,Is.EqualTo(baseperm))"); - Assert.That(t.CreationDate,Is.EqualTo(creationd), "Assert.That(t.CreationDate,Is.EqualTo(creationd))"); - Assert.That(t.CreatorID,Is.EqualTo(creator), "Assert.That(t.CreatorID,Is.EqualTo(creator))"); - Assert.That(t.Description,Is.EqualTo(name), "Assert.That(t.Description,Is.EqualTo(name))"); - Assert.That(t.EveryonePermissions,Is.EqualTo(eoperm), "Assert.That(t.EveryonePermissions,Is.EqualTo(eoperm))"); - Assert.That(t.Flags,Is.EqualTo(flags), "Assert.That(t.Flags,Is.EqualTo(flags))"); - Assert.That(t.GroupID,Is.EqualTo(sog.RootPart.GroupID), "Assert.That(t.GroupID,Is.EqualTo(sog.RootPart.GroupID))"); - // Where is this group permissions?? - // Assert.That(t.GroupPermissions,Is.EqualTo(), "Assert.That(t.GroupPermissions,Is.EqualTo())"); - Assert.That(t.Type,Is.EqualTo(assettype), "Assert.That(t.Type,Is.EqualTo(assettype))"); - Assert.That(t.InvType, Is.EqualTo(invtype), "Assert.That(t.InvType, Is.EqualTo(invtype))"); - Assert.That(t.ItemID, Is.EqualTo(id), "Assert.That(t.ItemID, Is.EqualTo(id))"); - Assert.That(t.LastOwnerID, Is.EqualTo(sog.RootPart.LastOwnerID), "Assert.That(t.LastOwnerID, Is.EqualTo(sog.RootPart.LastOwnerID))"); - Assert.That(t.NextPermissions, Is.EqualTo(nextperm), "Assert.That(t.NextPermissions, Is.EqualTo(nextperm))"); - // Ownership changes when you drop an object into an object - // owned by someone else - Assert.That(t.OwnerID,Is.EqualTo(sog.RootPart.OwnerID), "Assert.That(t.OwnerID,Is.EqualTo(sog.RootPart.OwnerID))"); -// Assert.That(t.CurrentPermissions, Is.EqualTo(curperm | 16), "Assert.That(t.CurrentPermissions, Is.EqualTo(curperm | 8))"); - Assert.That(t.ParentID,Is.EqualTo(sog.RootPart.FolderID), "Assert.That(t.ParentID,Is.EqualTo(sog.RootPart.FolderID))"); - Assert.That(t.ParentPartID,Is.EqualTo(sog.RootPart.UUID), "Assert.That(t.ParentPartID,Is.EqualTo(sog.RootPart.UUID))"); -*/ - } -/* - [Test] - [ExpectedException(typeof(ArgumentException))] - public void T026_PrimInventoryMany() - { - - TestHelpers.InMethod(); - - UUID i1,i2,i3,i4; - i1 = UUID.Random(); - i2 = UUID.Random(); - i3 = UUID.Random(); - i4 = i3; - InventoryItemBase ib1 = NewItem(i1, zero, zero, RandomName(), zero); - InventoryItemBase ib2 = NewItem(i2, zero, zero, RandomName(), zero); - InventoryItemBase ib3 = NewItem(i3, zero, zero, RandomName(), zero); - InventoryItemBase ib4 = NewItem(i4, zero, zero, RandomName(), zero); - - SceneObjectGroup sog = FindSOG("object1", region1); - - Assert.That(sog.AddInventoryItem(zero, sog.RootPart.LocalId, ib1, zero), Is.True); - Assert.That(sog.AddInventoryItem(zero, sog.RootPart.LocalId, ib2, zero), Is.True); - Assert.That(sog.AddInventoryItem(zero, sog.RootPart.LocalId, ib3, zero), Is.True); - Assert.That(sog.AddInventoryItem(zero, sog.RootPart.LocalId, ib4, zero), Is.True); - - TaskInventoryItem t1 = sog.GetInventoryItem(sog.RootPart.LocalId, i1); - Assert.That(t1.Name, Is.EqualTo(ib1.Name), "Assert.That(t1.Name, Is.EqualTo(ib1.Name))"); - TaskInventoryItem t2 = sog.GetInventoryItem(sog.RootPart.LocalId, i2); - Assert.That(t2.Name, Is.EqualTo(ib2.Name), "Assert.That(t2.Name, Is.EqualTo(ib2.Name))"); - TaskInventoryItem t3 = sog.GetInventoryItem(sog.RootPart.LocalId, i3); - Assert.That(t3.Name, Is.EqualTo(ib3.Name), "Assert.That(t3.Name, Is.EqualTo(ib3.Name))"); - TaskInventoryItem t4 = sog.GetInventoryItem(sog.RootPart.LocalId, i4); - Assert.That(t4, Is.Null); - - } -*/ - [Test] - public void T052_RemoveObject() - { - TestHelpers.InMethod(); - - db.RemoveObject(prim1, region1); - SceneObjectGroup sog = FindSOG("object1", region1); - Assert.That(sog, Is.Null); - } - - [Test] - public void T100_DefaultRegionInfo() - { - TestHelpers.InMethod(); - - RegionSettings r1 = db.LoadRegionSettings(region1); - Assert.That(r1.RegionUUID, Is.EqualTo(region1), "Assert.That(r1.RegionUUID, Is.EqualTo(region1))"); - - RegionSettings r2 = db.LoadRegionSettings(region2); - Assert.That(r2.RegionUUID, Is.EqualTo(region2), "Assert.That(r2.RegionUUID, Is.EqualTo(region2))"); - } - - [Test] - public void T101_UpdateRegionInfo() - { - TestHelpers.InMethod(); - - int agentlimit = random.Next(); - double objectbonus = random.Next(); - int maturity = random.Next(); - UUID tertex1 = UUID.Random(); - UUID tertex2 = UUID.Random(); - UUID tertex3 = UUID.Random(); - UUID tertex4 = UUID.Random(); - double elev1nw = 1000; - double elev2nw = 1001; - double elev1ne = 1002; - double elev2ne = 1003; - double elev1se = 1004; - double elev2se = 1425; - double elev1sw = 352; - double elev2sw = 774; - double waterh = 125; - double terrainraise = 74; - double terrainlower = -79; - Vector3 sunvector = new Vector3((float)Math.Round(random.NextDouble(),5),(float)Math.Round(random.NextDouble(),5),(float)Math.Round(random.NextDouble(),5)); - UUID terimgid = UUID.Random(); - UUID cov = UUID.Random(); - - RegionSettings r1 = db.LoadRegionSettings(region1); - r1.BlockTerraform = true; - r1.BlockFly = true; - r1.AllowDamage = true; - r1.RestrictPushing = true; - r1.AllowLandResell = false; - r1.AllowLandJoinDivide = false; - r1.BlockShowInSearch = true; - r1.AgentLimit = agentlimit; - r1.ObjectBonus = objectbonus; - r1.Maturity = maturity; - r1.DisableScripts = true; - r1.DisableCollisions = true; - r1.DisablePhysics = true; - r1.TerrainTexture1 = tertex1; - r1.TerrainTexture2 = tertex2; - r1.TerrainTexture3 = tertex3; - r1.TerrainTexture4 = tertex4; - r1.Elevation1NW = elev1nw; - r1.Elevation2NW = elev2nw; - r1.Elevation1NE = elev1ne; - r1.Elevation2NE = elev2ne; - r1.Elevation1SE = elev1se; - r1.Elevation2SE = elev2se; - r1.Elevation1SW = elev1sw; - r1.Elevation2SW = elev2sw; - r1.WaterHeight = waterh; - r1.TerrainRaiseLimit = terrainraise; - r1.TerrainLowerLimit = terrainlower; - r1.UseEstateSun = false; - r1.Sandbox = true; - r1.TerrainImageID = terimgid; - r1.FixedSun = true; - r1.Covenant = cov; - - db.StoreRegionSettings(r1); - - RegionSettings r1a = db.LoadRegionSettings(region1); - Assert.That(r1a.RegionUUID, Is.EqualTo(region1), "Assert.That(r1a.RegionUUID, Is.EqualTo(region1))"); - Assert.That(r1a.BlockTerraform,Is.True); - Assert.That(r1a.BlockFly,Is.True); - Assert.That(r1a.AllowDamage,Is.True); - Assert.That(r1a.RestrictPushing,Is.True); - Assert.That(r1a.AllowLandResell,Is.False); - Assert.That(r1a.AllowLandJoinDivide,Is.False); - Assert.That(r1a.BlockShowInSearch,Is.True); - Assert.That(r1a.AgentLimit,Is.EqualTo(agentlimit), "Assert.That(r1a.AgentLimit,Is.EqualTo(agentlimit))"); - Assert.That(r1a.ObjectBonus,Is.EqualTo(objectbonus), "Assert.That(r1a.ObjectBonus,Is.EqualTo(objectbonus))"); - Assert.That(r1a.Maturity,Is.EqualTo(maturity), "Assert.That(r1a.Maturity,Is.EqualTo(maturity))"); - Assert.That(r1a.DisableScripts,Is.True); - Assert.That(r1a.DisableCollisions,Is.True); - Assert.That(r1a.DisablePhysics,Is.True); - Assert.That(r1a.TerrainTexture1,Is.EqualTo(tertex1), "Assert.That(r1a.TerrainTexture1,Is.EqualTo(tertex1))"); - Assert.That(r1a.TerrainTexture2,Is.EqualTo(tertex2), "Assert.That(r1a.TerrainTexture2,Is.EqualTo(tertex2))"); - Assert.That(r1a.TerrainTexture3,Is.EqualTo(tertex3), "Assert.That(r1a.TerrainTexture3,Is.EqualTo(tertex3))"); - Assert.That(r1a.TerrainTexture4,Is.EqualTo(tertex4), "Assert.That(r1a.TerrainTexture4,Is.EqualTo(tertex4))"); - Assert.That(r1a.Elevation1NW,Is.EqualTo(elev1nw), "Assert.That(r1a.Elevation1NW,Is.EqualTo(elev1nw))"); - Assert.That(r1a.Elevation2NW,Is.EqualTo(elev2nw), "Assert.That(r1a.Elevation2NW,Is.EqualTo(elev2nw))"); - Assert.That(r1a.Elevation1NE,Is.EqualTo(elev1ne), "Assert.That(r1a.Elevation1NE,Is.EqualTo(elev1ne))"); - Assert.That(r1a.Elevation2NE,Is.EqualTo(elev2ne), "Assert.That(r1a.Elevation2NE,Is.EqualTo(elev2ne))"); - Assert.That(r1a.Elevation1SE,Is.EqualTo(elev1se), "Assert.That(r1a.Elevation1SE,Is.EqualTo(elev1se))"); - Assert.That(r1a.Elevation2SE,Is.EqualTo(elev2se), "Assert.That(r1a.Elevation2SE,Is.EqualTo(elev2se))"); - Assert.That(r1a.Elevation1SW,Is.EqualTo(elev1sw), "Assert.That(r1a.Elevation1SW,Is.EqualTo(elev1sw))"); - Assert.That(r1a.Elevation2SW,Is.EqualTo(elev2sw), "Assert.That(r1a.Elevation2SW,Is.EqualTo(elev2sw))"); - Assert.That(r1a.WaterHeight,Is.EqualTo(waterh), "Assert.That(r1a.WaterHeight,Is.EqualTo(waterh))"); - Assert.That(r1a.TerrainRaiseLimit,Is.EqualTo(terrainraise), "Assert.That(r1a.TerrainRaiseLimit,Is.EqualTo(terrainraise))"); - Assert.That(r1a.TerrainLowerLimit,Is.EqualTo(terrainlower), "Assert.That(r1a.TerrainLowerLimit,Is.EqualTo(terrainlower))"); - Assert.That(r1a.Sandbox,Is.True); - //Assert.That(r1a.TerrainImageID,Is.EqualTo(terimgid), "Assert.That(r1a.TerrainImageID,Is.EqualTo(terimgid))"); - Assert.That(r1a.Covenant, Is.EqualTo(cov), "Assert.That(r1a.Covenant, Is.EqualTo(cov))"); - } - - [Test] - public void T300_NoTerrain() - { - TestHelpers.InMethod(); - - Assert.That(db.LoadTerrain(zero), Is.Null); - Assert.That(db.LoadTerrain(region1), Is.Null); - Assert.That(db.LoadTerrain(region2), Is.Null); - Assert.That(db.LoadTerrain(UUID.Random()), Is.Null); - } - - [Test] - public void T301_CreateTerrain() - { - TestHelpers.InMethod(); - - double[,] t1 = GenTerrain(height1); - db.StoreTerrain(t1, region1); - - // store terrain is async - Thread.Sleep(500); - - Assert.That(db.LoadTerrain(zero), Is.Null); - Assert.That(db.LoadTerrain(region1), Is.Not.Null); - Assert.That(db.LoadTerrain(region2), Is.Null); - Assert.That(db.LoadTerrain(UUID.Random()), Is.Null); - } - - [Test] - public void T302_FetchTerrain() - { - TestHelpers.InMethod(); - - double[,] baseterrain1 = GenTerrain(height1); - double[,] baseterrain2 = GenTerrain(height2); - double[,] t1 = db.LoadTerrain(region1); - Assert.That(CompareTerrain(t1, baseterrain1), Is.True); - Assert.That(CompareTerrain(t1, baseterrain2), Is.False); - } - - [Test] - public void T303_UpdateTerrain() - { - TestHelpers.InMethod(); - - double[,] baseterrain1 = GenTerrain(height1); - double[,] baseterrain2 = GenTerrain(height2); - db.StoreTerrain(baseterrain2, region1); - - // store terrain is async - Thread.Sleep(500); - - double[,] t1 = db.LoadTerrain(region1); - Assert.That(CompareTerrain(t1, baseterrain1), Is.False); - Assert.That(CompareTerrain(t1, baseterrain2), Is.True); - } - - [Test] - public void T400_EmptyLand() - { - TestHelpers.InMethod(); - - Assert.That(db.LoadLandObjects(zero).Count, Is.EqualTo(0), "Assert.That(db.LoadLandObjects(zero).Count, Is.EqualTo(0))"); - Assert.That(db.LoadLandObjects(region1).Count, Is.EqualTo(0), "Assert.That(db.LoadLandObjects(region1).Count, Is.EqualTo(0))"); - Assert.That(db.LoadLandObjects(region2).Count, Is.EqualTo(0), "Assert.That(db.LoadLandObjects(region2).Count, Is.EqualTo(0))"); - Assert.That(db.LoadLandObjects(UUID.Random()).Count, Is.EqualTo(0), "Assert.That(db.LoadLandObjects(UUID.Random()).Count, Is.EqualTo(0))"); - } - - // TODO: we should have real land tests, but Land is so - // intermingled with scene that you can't test it without a - // valid scene. That requires some disagregation. - - - //************************************************************************************// - // Extra private methods - - private double[,] GenTerrain(double value) - { - double[,] terret = new double[Constants.RegionSize, Constants.RegionSize]; - terret.Initialize(); - for (int x = 0; x < Constants.RegionSize; x++) - for (int y = 0; y < Constants.RegionSize; y++) - terret[x,y] = value; - - return terret; - } - - private bool CompareTerrain(double[,] one, double[,] two) - { - for (int x = 0; x < Constants.RegionSize; x++) - for (int y = 0; y < Constants.RegionSize; y++) - if (one[x,y] != two[x,y]) - return false; - - return true; - } - - private SceneObjectGroup FindSOG(string name, UUID r) - { - List objs = db.LoadObjects(r); - foreach (SceneObjectGroup sog in objs) - if (sog.Name == name) - return sog; - - return null; - } - - // This builds a minimalistic Prim, 1 SOG with 1 root SOP. A - // common failure case is people adding new fields that aren't - // initialized, but have non-null db constraints. We should - // honestly be passing more and more null things in here. - // - // Please note that in Sqlite.BuildPrim there is a commented out inline version - // of this so you can debug and step through the build process and check the fields - // - // Real World Value: Tests for situation where extending a SceneObjectGroup/SceneObjectPart - // causes the application to crash at the database layer because of null values - // in NOT NULL fields - // - private SceneObjectGroup NewSOG(string name, UUID uuid, UUID regionId) - { - RegionInfo regionInfo = new RegionInfo - { - RegionID = regionId, - RegionLocX = 0, - RegionLocY = 0 - }; - - SceneObjectPart sop = new SceneObjectPart - { - Name = name, - Description = name, - Text = RandomName(), - SitName = RandomName(), - TouchName = RandomName(), - UUID = uuid, - Shape = PrimitiveBaseShape.Default - }; - - SceneObjectGroup sog = new SceneObjectGroup(sop); - - return sog; - } - - private SceneObjectPart NewSOP(string name, UUID uuid) - { - SceneObjectPart sop = new SceneObjectPart - { - Name = name, - Description = name, - Text = RandomName(), - SitName = RandomName(), - TouchName = RandomName(), - UUID = uuid, - Shape = PrimitiveBaseShape.Default - }; - return sop; - } - - // These are copied from the Inventory Item tests - - private InventoryItemBase NewItem(UUID id, UUID parent, UUID owner, string name, UUID asset) - { - InventoryItemBase i = new InventoryItemBase - { - ID = id, - Folder = parent, - Owner = owner, - CreatorId = owner.ToString(), - Name = name, - Description = name, - AssetID = asset - }; - return i; - } - - private static string RandomName() - { - StringBuilder name = new StringBuilder(); - int size = random.Next(5,12); - char ch ; - for (int i=0; i..\..\bin\OpenMetaverseTypes.dll False - - False - False @@ -209,4 +206,4 @@ VersionInfo.tt - \ No newline at end of file + diff --git a/OpenSim/Framework/Serialization/Tests/LandDataSerializerTests.cs b/OpenSim/Framework/Serialization/Tests/LandDataSerializerTests.cs deleted file mode 100644 index e81cb78cfd2..00000000000 --- a/OpenSim/Framework/Serialization/Tests/LandDataSerializerTests.cs +++ /dev/null @@ -1,166 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections.Generic; -using OpenMetaverse; -using OpenMetaverse.StructuredData; -using NUnit.Framework; -using OpenSim.Framework; -using OpenSim.Framework.Serialization.External; -using OpenSim.Tests.Common; - -namespace OpenSim.Framework.Serialization.Tests -{ - [TestFixture] - public class LandDataSerializerTest : OpenSimTestCase - { - private LandData land; - private LandData landWithParcelAccessList; - -// private static string preSerialized = "\n\n 128\n 0\n 00000000-0000-0000-0000-000000000000\n 10\n 0\n 0\n 54ff9641-dd40-4a2c-b1f1-47dd3af24e50\n d740204e-bbbf-44aa-949d-02c7d739f6a5\n False\n AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=\n land data to test LandDataSerializer\n 536870944\n 2\n LandDataSerializerTest Land\n 0\n 0\n 1\n d4452578-2f25-4b97-a81b-819af559cfd7\n http://videos.opensimulator.org/bumblebee.mp4\n \n 1b8eedf9-6d15-448b-8015-24286f1756bf\n \n 0\n 0\n 0\n 00000000-0000-0000-0000-000000000000\n <0, 0, 0>\n <0, 0, 0>\n 0\n 0\n"; - private static string preSerializedWithParcelAccessList - = "\n\n 128\n 0\n 00000000-0000-0000-0000-000000000000\n 10\n 0\n 0\n 54ff9641-dd40-4a2c-b1f1-47dd3af24e50\n d740204e-bbbf-44aa-949d-02c7d739f6a5\n False\n AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=\n land data to test LandDataSerializer\n 536870944\n 2\n LandDataSerializerTest Land\n 0\n 0\n 1\n d4452578-2f25-4b97-a81b-819af559cfd7\n http://videos.opensimulator.org/bumblebee.mp4\n \n 1b8eedf9-6d15-448b-8015-24286f1756bf\n \n \n 62d65d45-c91a-4f77-862c-46557d978b6c\n \n 2\n \n \n ec2a8d18-2378-4fe0-8b68-2a31b57c481e\n \n 1\n \n \n 0\n 0\n 0\n 00000000-0000-0000-0000-000000000000\n <0, 0, 0>\n <0, 0, 0>\n 0\n 0\n"; - - [SetUp] - public void setup() - { - // setup LandData object - this.land = new LandData(); - this.land.AABBMax = new Vector3(1, 2, 3); - this.land.AABBMin = new Vector3(129, 130, 131); - this.land.Area = 128; - this.land.AuctionID = 4; - this.land.AuthBuyerID = new UUID("7176df0c-6c50-45db-8a37-5e78be56a0cd"); - this.land.Category = ParcelCategory.Residential; - this.land.ClaimDate = 1; - this.land.ClaimPrice = 2; - this.land.GlobalID = new UUID("54ff9641-dd40-4a2c-b1f1-47dd3af24e50"); - this.land.GroupID = new UUID("d740204e-bbbf-44aa-949d-02c7d739f6a5"); - this.land.Description = "land data to test LandDataSerializer"; - this.land.Flags = (uint)(ParcelFlags.AllowDamage | ParcelFlags.AllowVoiceChat); - this.land.LandingType = (byte)LandingType.Direct; - this.land.Name = "LandDataSerializerTest Land"; - this.land.Status = ParcelStatus.Leased; - this.land.LocalID = 1; - this.land.MediaAutoScale = (byte)0x01; - this.land.MediaID = new UUID("d4452578-2f25-4b97-a81b-819af559cfd7"); - this.land.MediaURL = "http://videos.opensimulator.org/bumblebee.mp4"; - this.land.OwnerID = new UUID("1b8eedf9-6d15-448b-8015-24286f1756bf"); - - this.landWithParcelAccessList = this.land.Copy(); - this.landWithParcelAccessList.ParcelAccessList.Clear(); - - LandAccessEntry pae0 = new LandAccessEntry(); - pae0.AgentID = new UUID("62d65d45-c91a-4f77-862c-46557d978b6c"); - pae0.Flags = AccessList.Ban; - pae0.Expires = 0; - this.landWithParcelAccessList.ParcelAccessList.Add(pae0); - - LandAccessEntry pae1 = new LandAccessEntry(); - pae1.AgentID = new UUID("ec2a8d18-2378-4fe0-8b68-2a31b57c481e"); - pae1.Flags = AccessList.Access; - pae1.Expires = 0; - this.landWithParcelAccessList.ParcelAccessList.Add(pae1); - } - - /// - /// Test the LandDataSerializer.Serialize() method - /// -// [Test] -// public void LandDataSerializerSerializeTest() -// { -// TestHelpers.InMethod(); -// -// string serialized = LandDataSerializer.Serialize(this.land).Replace("\r\n", "\n"); -// Assert.That(serialized.Length > 0, "Serialize(LandData) returned empty string"); -// -// // adding a simple boolean variable because resharper nUnit integration doesn't like this -// // XML data in the Assert.That statement. Not sure why. -// bool result = (serialized == preSerialized); -// Assert.That(result, "result of Serialize LandData does not match expected result"); -// -// string serializedWithParcelAccessList = LandDataSerializer.Serialize(this.landWithParcelAccessList).Replace("\r\n", "\n"); -// Assert.That(serializedWithParcelAccessList.Length > 0, -// "Serialize(LandData) returned empty string for LandData object with ParcelAccessList"); -// result = (serializedWithParcelAccessList == preSerializedWithParcelAccessList); -// Assert.That(result, -// "result of Serialize(LandData) does not match expected result (pre-serialized with parcel access list"); -// } - - /// - /// Test the LandDataSerializer.Deserialize() method - /// - [Test] - public void TestLandDataDeserializeNoAccessLists() - { - TestHelpers.InMethod(); -// log4net.Config.XmlConfigurator.Configure(); - - Dictionary options = new Dictionary(); - LandData ld = LandDataSerializer.Deserialize(LandDataSerializer.Serialize(this.land, options)); - Assert.That(ld, Is.Not.Null, "Deserialize(string) returned null"); -// Assert.That(ld.AABBMax, Is.EqualTo(land.AABBMax)); -// Assert.That(ld.AABBMin, Is.EqualTo(land.AABBMin)); - Assert.That(ld.Area, Is.EqualTo(land.Area)); - Assert.That(ld.AuctionID, Is.EqualTo(land.AuctionID)); - Assert.That(ld.AuthBuyerID, Is.EqualTo(land.AuthBuyerID)); - Assert.That(ld.Category, Is.EqualTo(land.Category)); - Assert.That(ld.ClaimDate, Is.EqualTo(land.ClaimDate)); - Assert.That(ld.ClaimPrice, Is.EqualTo(land.ClaimPrice)); - Assert.That(ld.GlobalID, Is.EqualTo(land.GlobalID), "Reified LandData.GlobalID != original LandData.GlobalID"); - Assert.That(ld.GroupID, Is.EqualTo(land.GroupID)); - Assert.That(ld.Description, Is.EqualTo(land.Description)); - Assert.That(ld.Flags, Is.EqualTo(land.Flags)); - Assert.That(ld.LandingType, Is.EqualTo(land.LandingType)); - Assert.That(ld.Name, Is.EqualTo(land.Name), "Reified LandData.Name != original LandData.Name"); - Assert.That(ld.Status, Is.EqualTo(land.Status)); - Assert.That(ld.LocalID, Is.EqualTo(land.LocalID)); - Assert.That(ld.MediaAutoScale, Is.EqualTo(land.MediaAutoScale)); - Assert.That(ld.MediaID, Is.EqualTo(land.MediaID)); - Assert.That(ld.MediaURL, Is.EqualTo(land.MediaURL)); - Assert.That(ld.OwnerID, Is.EqualTo(land.OwnerID)); - } - - [Test] - public void TestLandDataDeserializeWithAccessLists() - { - TestHelpers.InMethod(); -// log4net.Config.XmlConfigurator.Configure(); - - LandData ld = LandDataSerializer.Deserialize(LandDataSerializerTest.preSerializedWithParcelAccessList); - Assert.That(ld != null, - "Deserialize(string) returned null (pre-serialized with parcel access list)"); - Assert.That(ld.GlobalID == this.landWithParcelAccessList.GlobalID, - "Reified LandData.GlobalID != original LandData.GlobalID (pre-serialized with parcel access list)"); - Assert.That(ld.Name == this.landWithParcelAccessList.Name, - "Reified LandData.Name != original LandData.Name (pre-serialized with parcel access list)"); - Assert.That(ld.ParcelAccessList.Count, Is.EqualTo(2)); - Assert.That(ld.ParcelAccessList[0].AgentID, Is.EqualTo(UUID.Parse("62d65d45-c91a-4f77-862c-46557d978b6c"))); - } - } -} diff --git a/OpenSim/Framework/Serialization/Tests/OpenSim.Framework.Serialization.Tests.csproj b/OpenSim/Framework/Serialization/Tests/OpenSim.Framework.Serialization.Tests.csproj deleted file mode 100644 index 78d84809fa2..00000000000 --- a/OpenSim/Framework/Serialization/Tests/OpenSim.Framework.Serialization.Tests.csproj +++ /dev/null @@ -1,32 +0,0 @@ - - - net8.0 - - - - - - - - - - ..\..\..\..\bin\OpenMetaverse.dll - False - - - ..\..\..\..\bin\OpenMetaverse.StructuredData.dll - False - - - ..\..\..\..\bin\OpenMetaverseTypes.dll - False - - - - - - - - - - \ No newline at end of file diff --git a/OpenSim/Framework/Serialization/Tests/RegionSettingsSerializerTests.cs b/OpenSim/Framework/Serialization/Tests/RegionSettingsSerializerTests.cs deleted file mode 100644 index 4f3f2ddde31..00000000000 --- a/OpenSim/Framework/Serialization/Tests/RegionSettingsSerializerTests.cs +++ /dev/null @@ -1,142 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections.Generic; -using OpenMetaverse; -using OpenMetaverse.StructuredData; -using NUnit.Framework; -using OpenSim.Framework; -using OpenSim.Framework.Serialization.External; -using OpenSim.Tests.Common; - -namespace OpenSim.Framework.Serialization.Tests -{ - [TestFixture] - public class RegionSettingsSerializerTests : OpenSimTestCase - { - private string m_serializedRs = @" - - - True - True - True - True - True - True - True - True - True - 1 - True - 40 - 1.4 - - - 00000000-0000-0000-0000-000000000020 - 00000000-0000-0000-0000-000000000040 - 00000000-0000-0000-0000-000000000060 - 00000000-0000-0000-0000-000000000080 - 1.9 - 15.9 - 49 - 45.3 - 2.1 - 4.5 - 9.2 - 19.2 - - - 23 - 17.9 - 0.4 - True - true - 12 - - - 00000000-0000-0000-0000-111111111111 - 1,-2,0.33 - -"; - - private RegionSettings m_rs; - - [SetUp] - public void Setup() - { - m_rs = new RegionSettings(); - m_rs.AgentLimit = 17; - m_rs.AllowDamage = true; - m_rs.AllowLandJoinDivide = true; - m_rs.AllowLandResell = true; - m_rs.BlockFly = true; - m_rs.BlockShowInSearch = true; - m_rs.BlockTerraform = true; - m_rs.DisableCollisions = true; - m_rs.DisablePhysics = true; - m_rs.DisableScripts = true; - m_rs.Elevation1NW = 15.9; - m_rs.Elevation1NE = 45.3; - m_rs.Elevation1SE = 49; - m_rs.Elevation1SW = 1.9; - m_rs.Elevation2NW = 4.5; - m_rs.Elevation2NE = 19.2; - m_rs.Elevation2SE = 9.2; - m_rs.Elevation2SW = 2.1; - m_rs.FixedSun = true; - m_rs.SunPosition = 12.0; - m_rs.ObjectBonus = 1.4; - m_rs.RestrictPushing = true; - m_rs.TerrainLowerLimit = 0.4; - m_rs.TerrainRaiseLimit = 17.9; - m_rs.TerrainTexture1 = UUID.Parse("00000000-0000-0000-0000-000000000020"); - m_rs.TerrainTexture2 = UUID.Parse("00000000-0000-0000-0000-000000000040"); - m_rs.TerrainTexture3 = UUID.Parse("00000000-0000-0000-0000-000000000060"); - m_rs.TerrainTexture4 = UUID.Parse("00000000-0000-0000-0000-000000000080"); - m_rs.UseEstateSun = true; - m_rs.WaterHeight = 23; - m_rs.TelehubObject = UUID.Parse("00000000-0000-0000-0000-111111111111"); - m_rs.AddSpawnPoint(SpawnPoint.Parse("1,-2,0.33")); - } - - [Test] - public void TestRegionSettingsDeserialize() - { - TestHelpers.InMethod(); -// log4net.Config.XmlConfigurator.Configure(); - - RegionSettings deserRs = RegionSettingsSerializer.Deserialize(m_serializedRs, out ViewerEnvironment dummy, new EstateSettings()); - Assert.That(deserRs, Is.Not.Null); - Assert.That(deserRs.TerrainTexture2, Is.EqualTo(m_rs.TerrainTexture2)); - Assert.That(deserRs.DisablePhysics, Is.EqualTo(m_rs.DisablePhysics)); - Assert.That(deserRs.TerrainLowerLimit, Is.EqualTo(m_rs.TerrainLowerLimit)); - Assert.That(deserRs.TelehubObject, Is.EqualTo(m_rs.TelehubObject)); - Assert.That(deserRs.SpawnPoints()[0].ToString(), Is.EqualTo(m_rs.SpawnPoints()[0].ToString())); - } - } -} diff --git a/OpenSim/Framework/Servers/Tests/OpenSim.Framework.Servers.Tests.csproj b/OpenSim/Framework/Servers/Tests/OpenSim.Framework.Servers.Tests.csproj deleted file mode 100644 index f5f6d7bec52..00000000000 --- a/OpenSim/Framework/Servers/Tests/OpenSim.Framework.Servers.Tests.csproj +++ /dev/null @@ -1,19 +0,0 @@ - - - net8.0 - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/OpenSim/Framework/Servers/Tests/VersionInfoTests.cs b/OpenSim/Framework/Servers/Tests/VersionInfoTests.cs deleted file mode 100644 index 68a1c78aa4b..00000000000 --- a/OpenSim/Framework/Servers/Tests/VersionInfoTests.cs +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections.Generic; -using System.Text; -using NUnit.Framework; -using OpenSim.Tests.Common; - -namespace OpenSim.Framework.Servers.Tests -{ - [TestFixture] - public class VersionInfoTests : OpenSimTestCase - { - [Test] - public void TestVersionLength() - { - Assert.AreEqual(VersionInfo.VERSIONINFO_VERSION_LENGTH, VersionInfo.Version.Length," VersionInfo.Version string not " + VersionInfo.VERSIONINFO_VERSION_LENGTH + " chars."); - } - } -} diff --git a/OpenSim/Framework/Tests/AgentCircuitDataTest.cs b/OpenSim/Framework/Tests/AgentCircuitDataTest.cs deleted file mode 100644 index c8eb57dd591..00000000000 --- a/OpenSim/Framework/Tests/AgentCircuitDataTest.cs +++ /dev/null @@ -1,351 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System.Collections.Generic; -using OpenMetaverse; -using OpenMetaverse.StructuredData; -using NUnit.Framework; -using OpenSim.Tests.Common; - -namespace OpenSim.Framework.Tests -{ - [TestFixture] - public class AgentCircuitDataTest : OpenSimTestCase - { - private UUID AgentId; - private AvatarAppearance AvAppearance; - private byte[] VisualParams; - private UUID BaseFolder; - private string CapsPath; - private Dictionary ChildrenCapsPaths; - private uint circuitcode = 0949030; - private string firstname; - private string lastname; - private UUID SecureSessionId; - private UUID SessionId; - private Vector3 StartPos; - - - [SetUp] - public void setup() - { - AgentId = UUID.Random(); - BaseFolder = UUID.Random(); - CapsPath = "http://www.opensimulator.org/Caps/Foo"; - ChildrenCapsPaths = new Dictionary(); - ChildrenCapsPaths.Add(ulong.MaxValue, "http://www.opensimulator.org/Caps/Foo2"); - firstname = "CoolAvatarTest"; - lastname = "test"; - StartPos = new Vector3(5,23,125); - - SecureSessionId = UUID.Random(); - SessionId = UUID.Random(); - - AvAppearance = new AvatarAppearance(); - VisualParams = new byte[218]; - - //body - VisualParams[(int)AvatarAppearance.VPElement.SHAPE_HEIGHT] = 155; - VisualParams[(int)AvatarAppearance.VPElement.SHAPE_THICKNESS] = 00; - VisualParams[(int)AvatarAppearance.VPElement.SHAPE_BODY_FAT] = 0; - - //Torso - VisualParams[(int)AvatarAppearance.VPElement.SHAPE_TORSO_MUSCLES] = 48; - VisualParams[(int)AvatarAppearance.VPElement.SHAPE_NECK_THICKNESS] = 43; - VisualParams[(int)AvatarAppearance.VPElement.SHAPE_NECK_LENGTH] = 255; - VisualParams[(int)AvatarAppearance.VPElement.SHAPE_SHOULDERS] = 94; - VisualParams[(int)AvatarAppearance.VPElement.SHAPE_CHEST_MALE_NO_PECS] = 199; - VisualParams[(int)AvatarAppearance.VPElement.SHAPE_ARM_LENGTH] = 255; - VisualParams[(int)AvatarAppearance.VPElement.SHAPE_HAND_SIZE] = 33; - VisualParams[(int)AvatarAppearance.VPElement.SHAPE_TORSO_LENGTH] = 240; - VisualParams[(int)AvatarAppearance.VPElement.SHAPE_LOVE_HANDLES] = 0; - VisualParams[(int)AvatarAppearance.VPElement.SHAPE_BELLY_SIZE] = 0; - - // legs - VisualParams[(int)AvatarAppearance.VPElement.SHAPE_LEG_MUSCLES] = 82; - VisualParams[(int)AvatarAppearance.VPElement.SHAPE_LEG_LENGTH] = 255; - VisualParams[(int)AvatarAppearance.VPElement.SHAPE_HIP_WIDTH] = 84; - VisualParams[(int)AvatarAppearance.VPElement.SHAPE_HIP_LENGTH] = 166; - VisualParams[(int)AvatarAppearance.VPElement.SHAPE_BUTT_SIZE] = 64; - VisualParams[(int)AvatarAppearance.VPElement.SHAPE_SADDLEBAGS] = 89; - VisualParams[(int)AvatarAppearance.VPElement.SHAPE_BOWED_LEGS] = 127; - VisualParams[(int)AvatarAppearance.VPElement.SHAPE_FOOT_SIZE] = 45; - - - // head - VisualParams[(int)AvatarAppearance.VPElement.SHAPE_HEAD_SIZE] = 255; - VisualParams[(int)AvatarAppearance.VPElement.SHAPE_SQUASH_STRETCH_HEAD] = 0; // head stretch - VisualParams[(int)AvatarAppearance.VPElement.SHAPE_HEAD_SHAPE] = 155; - VisualParams[(int)AvatarAppearance.VPElement.SHAPE_EGG_HEAD] = 127; - VisualParams[(int)AvatarAppearance.VPElement.SHAPE_POINTY_EARS] = 255; - VisualParams[(int)AvatarAppearance.VPElement.SHAPE_HEAD_LENGTH] = 45; - VisualParams[(int)AvatarAppearance.VPElement.SHAPE_FACE_SHEAR] = 127; - VisualParams[(int)AvatarAppearance.VPElement.SHAPE_FOREHEAD_ANGLE] = 104; - VisualParams[(int)AvatarAppearance.VPElement.SHAPE_BIG_BROW] = 94; - VisualParams[(int)AvatarAppearance.VPElement.SHAPE_PUFFY_UPPER_CHEEKS] = 0; // upper cheeks - VisualParams[(int)AvatarAppearance.VPElement.SHAPE_DOUBLE_CHIN] = 122; // lower cheeks - VisualParams[(int)AvatarAppearance.VPElement.SHAPE_HIGH_CHEEK_BONES] = 130; - - - - // eyes - VisualParams[(int)AvatarAppearance.VPElement.SHAPE_EYE_SIZE] = 105; - VisualParams[(int)AvatarAppearance.VPElement.SHAPE_WIDE_EYES] = 135; - VisualParams[(int)AvatarAppearance.VPElement.SHAPE_EYE_SPACING] = 184; - VisualParams[(int)AvatarAppearance.VPElement.SHAPE_EYELID_CORNER_UP] = 230; - VisualParams[(int)AvatarAppearance.VPElement.SHAPE_EYELID_INNER_CORNER_UP] = 120; - VisualParams[(int)AvatarAppearance.VPElement.SHAPE_EYE_DEPTH] = 158; - VisualParams[(int)AvatarAppearance.VPElement.SHAPE_UPPER_EYELID_FOLD] = 69; - VisualParams[(int)AvatarAppearance.VPElement.SHAPE_BAGGY_EYES] = 38; - VisualParams[(int)AvatarAppearance.VPElement.SHAPE_EYELASHES_LONG] = 127; - VisualParams[(int)AvatarAppearance.VPElement.SHAPE_POP_EYE] = 127; - - VisualParams[(int)AvatarAppearance.VPElement.EYES_EYE_COLOR] = 25; - VisualParams[(int)AvatarAppearance.VPElement.EYES_EYE_LIGHTNESS] = 127; - - // ears - VisualParams[(int)AvatarAppearance.VPElement.SHAPE_BIG_EARS] = 255; - VisualParams[(int)AvatarAppearance.VPElement.SHAPE_EARS_OUT] = 127; - VisualParams[(int)AvatarAppearance.VPElement.SHAPE_ATTACHED_EARLOBES] = 127; - VisualParams[(int)AvatarAppearance.VPElement.SHAPE_POINTY_EARS] = 255; - - // nose - VisualParams[(int)AvatarAppearance.VPElement.SHAPE_NOSE_BIG_OUT] = 79; - VisualParams[(int)AvatarAppearance.VPElement.SHAPE_WIDE_NOSE] = 35; - VisualParams[(int)AvatarAppearance.VPElement.SHAPE_BROAD_NOSTRILS] = 86; - VisualParams[(int)AvatarAppearance.VPElement.SHAPE_LOW_SEPTUM_NOSE] = 112; // nostril division - VisualParams[(int)AvatarAppearance.VPElement.SHAPE_BULBOUS_NOSE] = 25; - VisualParams[(int)AvatarAppearance.VPElement.SHAPE_NOBLE_NOSE_BRIDGE] = 25; // upper bridge - VisualParams[(int)AvatarAppearance.VPElement.SHAPE_LOWER_BRIDGE_NOSE] = 25; // lower bridge - VisualParams[(int)AvatarAppearance.VPElement.SHAPE_WIDE_NOSE_BRIDGE] = 25; - VisualParams[(int)AvatarAppearance.VPElement.SHAPE_UPTURNED_NOSE_TIP] = 107; - VisualParams[(int)AvatarAppearance.VPElement.SHAPE_BULBOUS_NOSE_TIP] = 25; - VisualParams[(int)AvatarAppearance.VPElement.SHAPE_CROOKED_NOSE] = 127; - - - // Mouth - VisualParams[(int)AvatarAppearance.VPElement.SHAPE_LIP_WIDTH] = 122; - VisualParams[(int)AvatarAppearance.VPElement.SHAPE_TALL_LIPS] = 10; // lip fullness - VisualParams[(int)AvatarAppearance.VPElement.SHAPE_LIP_THICKNESS] = 112; - VisualParams[(int)AvatarAppearance.VPElement.SHAPE_LIP_RATIO] = 137; - VisualParams[(int)AvatarAppearance.VPElement.SHAPE_MOUTH_HEIGHT] = 176; - VisualParams[(int)AvatarAppearance.VPElement.SHAPE_MOUTH_CORNER] = 140; // Sad --> happy - VisualParams[(int)AvatarAppearance.VPElement.SHAPE_LIP_CLEFT_DEEP] = 84; - VisualParams[(int)AvatarAppearance.VPElement.SHAPE_WIDE_LIP_CLEFT] = 84; - VisualParams[(int)AvatarAppearance.VPElement.SHAPE_SHIFT_MOUTH] = 127; - - - // chin - VisualParams[(int)AvatarAppearance.VPElement.SHAPE_WEAK_CHIN] = 119; - VisualParams[(int)AvatarAppearance.VPElement.SHAPE_SQUARE_JAW] = 5; - VisualParams[(int)AvatarAppearance.VPElement.SHAPE_DEEP_CHIN] = 132; - VisualParams[(int)AvatarAppearance.VPElement.SHAPE_JAW_ANGLE] = 153; - VisualParams[(int)AvatarAppearance.VPElement.SHAPE_JAW_JUT] = 100; - VisualParams[(int)AvatarAppearance.VPElement.SHAPE_JOWLS] = 38; - VisualParams[(int)AvatarAppearance.VPElement.SHAPE_CLEFT_CHIN] = 89; - VisualParams[(int)AvatarAppearance.VPElement.SHAPE_CLEFT_CHIN_UPPER] = 89; - VisualParams[(int)AvatarAppearance.VPElement.SHAPE_DOUBLE_CHIN] = 0; - - - // hair color - VisualParams[(int)AvatarAppearance.VPElement.HAIR_WHITE_HAIR] = 0; - VisualParams[(int)AvatarAppearance.VPElement.HAIR_RAINBOW_COLOR_39] = 0; - VisualParams[(int)AvatarAppearance.VPElement.HAIR_BLONDE_HAIR] = 24; - VisualParams[(int)AvatarAppearance.VPElement.HAIR_RED_HAIR] = 0; - - // hair style - VisualParams[(int)AvatarAppearance.VPElement.HAIR_HAIR_VOLUME] = 160; - VisualParams[(int)AvatarAppearance.VPElement.HAIR_HAIR_FRONT] = 153; - VisualParams[(int)AvatarAppearance.VPElement.HAIR_HAIR_SIDES] = 153; - VisualParams[(int)AvatarAppearance.VPElement.HAIR_HAIR_BACK] = 170; - VisualParams[(int)AvatarAppearance.VPElement.HAIR_HAIR_BIG_FRONT] = 0; - VisualParams[(int)AvatarAppearance.VPElement.HAIR_HAIR_BIG_TOP] = 117; - VisualParams[(int)AvatarAppearance.VPElement.HAIR_HAIR_BIG_BACK] = 170; - VisualParams[(int)AvatarAppearance.VPElement.HAIR_FRONT_FRINGE] = 0; - VisualParams[(int)AvatarAppearance.VPElement.HAIR_SIDE_FRINGE] = 142; - VisualParams[(int)AvatarAppearance.VPElement.HAIR_BACK_FRINGE] = 0; - VisualParams[(int)AvatarAppearance.VPElement.HAIR_HAIR_SIDES_FULL] = 146; - VisualParams[(int)AvatarAppearance.VPElement.HAIR_HAIR_SWEEP] = 0; - VisualParams[(int)AvatarAppearance.VPElement.HAIR_HAIR_SHEAR_FRONT] = 0; - VisualParams[(int)AvatarAppearance.VPElement.HAIR_HAIR_SHEAR_BACK] = 0; - VisualParams[(int)AvatarAppearance.VPElement.HAIR_HAIR_TAPER_FRONT] = 0; - VisualParams[(int)AvatarAppearance.VPElement.HAIR_HAIR_TAPER_BACK] = 0; - VisualParams[(int)AvatarAppearance.VPElement.HAIR_HAIR_RUMPLED] = 0; - VisualParams[(int)AvatarAppearance.VPElement.HAIR_PIGTAILS] = 0; - VisualParams[(int)AvatarAppearance.VPElement.HAIR_PONYTAIL] = 0; - VisualParams[(int)AvatarAppearance.VPElement.HAIR_HAIR_SPIKED] = 0; - VisualParams[(int)AvatarAppearance.VPElement.HAIR_HAIR_TILT] = 0; - VisualParams[(int)AvatarAppearance.VPElement.HAIR_HAIR_PART_MIDDLE] = 0; - VisualParams[(int)AvatarAppearance.VPElement.HAIR_HAIR_PART_RIGHT] = 0; - VisualParams[(int)AvatarAppearance.VPElement.HAIR_HAIR_PART_LEFT] = 0; - VisualParams[(int)AvatarAppearance.VPElement.HAIR_BANGS_PART_MIDDLE] = 155; - - //Eyebrows - VisualParams[(int)AvatarAppearance.VPElement.HAIR_EYEBROW_SIZE] = 20; - VisualParams[(int)AvatarAppearance.VPElement.HAIR_EYEBROW_DENSITY] = 140; - VisualParams[(int)AvatarAppearance.VPElement.HAIR_LOWER_EYEBROWS] = 200; // eyebrow height - VisualParams[(int)AvatarAppearance.VPElement.HAIR_ARCED_EYEBROWS] = 124; - VisualParams[(int)AvatarAppearance.VPElement.HAIR_POINTY_EYEBROWS] = 65; - - //Facial hair - VisualParams[(int)AvatarAppearance.VPElement.HAIR_HAIR_THICKNESS] = 65; - VisualParams[(int)AvatarAppearance.VPElement.HAIR_SIDEBURNS] = 235; - VisualParams[(int)AvatarAppearance.VPElement.HAIR_MOUSTACHE] = 75; - VisualParams[(int)AvatarAppearance.VPElement.HAIR_CHIN_CURTAINS] = 140; - VisualParams[(int)AvatarAppearance.VPElement.HAIR_SOULPATCH] = 0; - - AvAppearance.VisualParams = VisualParams; - - AvAppearance.SetAppearance(AvAppearance.Texture, (byte[])VisualParams.Clone()); - } - - /// - /// Test to ensure that the serialization format is the same and the underlying types don't change without notice - /// oldSerialization is just a json serialization of the OSDMap packed for the AgentCircuitData. - /// The idea is that if the current json serializer cannot parse the old serialization, then the underlying types - /// have changed and are incompatible. - /// - [Test] - public void HistoricalAgentCircuitDataOSDConversion() - { - string oldSerialization = "{\"agent_id\":\"522675bd-8214-40c1-b3ca-9c7f7fd170be\",\"base_folder\":\"c40b5f5f-476f-496b-bd69-b5a539c434d8\",\"caps_path\":\"http://www.opensimulator.org/Caps/Foo\",\"children_seeds\":[{\"handle\":\"18446744073709551615\",\"seed\":\"http://www.opensimulator.org/Caps/Foo2\"}],\"child\":false,\"circuit_code\":\"949030\",\"first_name\":\"CoolAvatarTest\",\"last_name\":\"test\",\"inventory_folder\":\"c40b5f5f-476f-496b-bd69-b5a539c434d8\",\"secure_session_id\":\"1e608e2b-0ddb-41f6-be0f-926f61cd3e0a\",\"session_id\":\"aa06f798-9d70-4bdb-9bbf-012a02ee2baf\",\"start_pos\":\"<5, 23, 125>\"}"; - AgentCircuitData Agent1Data = new AgentCircuitData(); - Agent1Data.AgentID = new UUID("522675bd-8214-40c1-b3ca-9c7f7fd170be"); - Agent1Data.Appearance = AvAppearance; - Agent1Data.BaseFolder = new UUID("c40b5f5f-476f-496b-bd69-b5a539c434d8"); - Agent1Data.CapsPath = CapsPath; - Agent1Data.child = false; - Agent1Data.ChildrenCapSeeds = ChildrenCapsPaths; - Agent1Data.circuitcode = circuitcode; - Agent1Data.firstname = firstname; - Agent1Data.InventoryFolder = new UUID("c40b5f5f-476f-496b-bd69-b5a539c434d8"); - Agent1Data.lastname = lastname; - Agent1Data.SecureSessionID = new UUID("1e608e2b-0ddb-41f6-be0f-926f61cd3e0a"); - Agent1Data.SessionID = new UUID("aa06f798-9d70-4bdb-9bbf-012a02ee2baf"); - Agent1Data.startpos = StartPos; - - - OSDMap map2; - try - { - map2 = (OSDMap) OSDParser.DeserializeJson(oldSerialization); - - - AgentCircuitData Agent2Data = new AgentCircuitData(); - Agent2Data.UnpackAgentCircuitData(map2); - - Assert.That((Agent1Data.AgentID == Agent2Data.AgentID)); - Assert.That((Agent1Data.BaseFolder == Agent2Data.BaseFolder)); - - Assert.That((Agent1Data.CapsPath == Agent2Data.CapsPath)); - Assert.That((Agent1Data.child == Agent2Data.child)); - Assert.That((Agent1Data.ChildrenCapSeeds.Count == Agent2Data.ChildrenCapSeeds.Count)); - Assert.That((Agent1Data.circuitcode == Agent2Data.circuitcode)); - Assert.That((Agent1Data.firstname == Agent2Data.firstname)); - Assert.That((Agent1Data.InventoryFolder == Agent2Data.InventoryFolder)); - Assert.That((Agent1Data.lastname == Agent2Data.lastname)); - Assert.That((Agent1Data.SecureSessionID == Agent2Data.SecureSessionID)); - Assert.That((Agent1Data.SessionID == Agent2Data.SessionID)); - Assert.That((Agent1Data.startpos == Agent2Data.startpos)); - } - catch (LitJson.JsonException) - { - //intermittant litjson errors :P - Assert.That(1 == 1); - } - /* - Enable this once VisualParams go in the packing method - for (int i=0;i<208;i++) - Assert.That((Agent1Data.Appearance.VisualParams[i] == Agent2Data.Appearance.VisualParams[i])); - */ - } - - /// - /// Test to ensure that the packing and unpacking methods work. - /// - [Test] - public void TestAgentCircuitDataOSDConversion() - { - AgentCircuitData Agent1Data = new AgentCircuitData(); - Agent1Data.AgentID = AgentId; - Agent1Data.Appearance = AvAppearance; - Agent1Data.BaseFolder = BaseFolder; - Agent1Data.CapsPath = CapsPath; - Agent1Data.child = false; - Agent1Data.ChildrenCapSeeds = ChildrenCapsPaths; - Agent1Data.circuitcode = circuitcode; - Agent1Data.firstname = firstname; - Agent1Data.InventoryFolder = BaseFolder; - Agent1Data.lastname = lastname; - Agent1Data.SecureSessionID = SecureSessionId; - Agent1Data.SessionID = SessionId; - Agent1Data.startpos = StartPos; - - EntityTransferContext ctx = new EntityTransferContext(); - OSDMap map2; - OSDMap map = Agent1Data.PackAgentCircuitData(ctx); - try - { - string str = OSDParser.SerializeJsonString(map); - //System.Console.WriteLine(str); - map2 = (OSDMap) OSDParser.DeserializeJson(str); - } - catch (System.NullReferenceException) - { - //spurious litjson errors :P - map2 = map; - Assert.That(1==1); - return; - } - - AgentCircuitData Agent2Data = new AgentCircuitData(); - Agent2Data.UnpackAgentCircuitData(map2); - - Assert.That((Agent1Data.AgentID == Agent2Data.AgentID)); - Assert.That((Agent1Data.BaseFolder == Agent2Data.BaseFolder)); - - Assert.That((Agent1Data.CapsPath == Agent2Data.CapsPath)); - Assert.That((Agent1Data.child == Agent2Data.child)); - Assert.That((Agent1Data.ChildrenCapSeeds.Count == Agent2Data.ChildrenCapSeeds.Count)); - Assert.That((Agent1Data.circuitcode == Agent2Data.circuitcode)); - Assert.That((Agent1Data.firstname == Agent2Data.firstname)); - Assert.That((Agent1Data.InventoryFolder == Agent2Data.InventoryFolder)); - Assert.That((Agent1Data.lastname == Agent2Data.lastname)); - Assert.That((Agent1Data.SecureSessionID == Agent2Data.SecureSessionID)); - Assert.That((Agent1Data.SessionID == Agent2Data.SessionID)); - Assert.That((Agent1Data.startpos == Agent2Data.startpos)); - - /* - Enable this once VisualParams go in the packing method - for (int i = 0; i < 208; i++) - Assert.That((Agent1Data.Appearance.VisualParams[i] == Agent2Data.Appearance.VisualParams[i])); - */ - - - } - } -} diff --git a/OpenSim/Framework/Tests/AgentCircuitManagerTests.cs b/OpenSim/Framework/Tests/AgentCircuitManagerTests.cs deleted file mode 100644 index 2558f300385..00000000000 --- a/OpenSim/Framework/Tests/AgentCircuitManagerTests.cs +++ /dev/null @@ -1,199 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -using System.Collections.Generic; -using OpenMetaverse; -using NUnit.Framework; -using System; - -namespace OpenSim.Framework.Tests -{ - [TestFixture] - public class AgentCircuitManagerTests - { - private AgentCircuitData m_agentCircuitData1; - private AgentCircuitData m_agentCircuitData2; - private UUID AgentId1; - private UUID AgentId2; - private uint circuitcode1; - private uint circuitcode2; - - private UUID SessionId1; - private UUID SessionId2; - private Random rnd = new Random(Environment.TickCount); - - [SetUp] - public void setup() - { - - AgentId1 = UUID.Random(); - AgentId2 = UUID.Random(); - circuitcode1 = (uint) rnd.Next((int)uint.MinValue, int.MaxValue); - circuitcode2 = (uint) rnd.Next((int)uint.MinValue, int.MaxValue); - SessionId1 = UUID.Random(); - SessionId2 = UUID.Random(); - UUID BaseFolder = UUID.Random(); - string CapsPath = "http://www.opensimulator.org/Caps/Foo"; - Dictionary ChildrenCapsPaths = new Dictionary(); - ChildrenCapsPaths.Add(ulong.MaxValue, "http://www.opensimulator.org/Caps/Foo2"); - string firstname = "CoolAvatarTest"; - string lastname = "test"; - Vector3 StartPos = new Vector3(5, 23, 125); - - UUID SecureSessionId = UUID.Random(); - // TODO: unused: UUID SessionId = UUID.Random(); - - m_agentCircuitData1 = new AgentCircuitData(); - m_agentCircuitData1.AgentID = AgentId1; - m_agentCircuitData1.Appearance = new AvatarAppearance(); - m_agentCircuitData1.BaseFolder = BaseFolder; - m_agentCircuitData1.CapsPath = CapsPath; - m_agentCircuitData1.child = false; - m_agentCircuitData1.ChildrenCapSeeds = ChildrenCapsPaths; - m_agentCircuitData1.circuitcode = circuitcode1; - m_agentCircuitData1.firstname = firstname; - m_agentCircuitData1.InventoryFolder = BaseFolder; - m_agentCircuitData1.lastname = lastname; - m_agentCircuitData1.SecureSessionID = SecureSessionId; - m_agentCircuitData1.SessionID = SessionId1; - m_agentCircuitData1.startpos = StartPos; - - m_agentCircuitData2 = new AgentCircuitData(); - m_agentCircuitData2.AgentID = AgentId2; - m_agentCircuitData2.Appearance = new AvatarAppearance(); - m_agentCircuitData2.BaseFolder = BaseFolder; - m_agentCircuitData2.CapsPath = CapsPath; - m_agentCircuitData2.child = false; - m_agentCircuitData2.ChildrenCapSeeds = ChildrenCapsPaths; - m_agentCircuitData2.circuitcode = circuitcode2; - m_agentCircuitData2.firstname = firstname; - m_agentCircuitData2.InventoryFolder = BaseFolder; - m_agentCircuitData2.lastname = lastname; - m_agentCircuitData2.SecureSessionID = SecureSessionId; - m_agentCircuitData2.SessionID = SessionId2; - m_agentCircuitData2.startpos = StartPos; - } - - /// - /// Validate that adding the circuit works appropriately - /// - [Test] - public void AddAgentCircuitTest() - { - AgentCircuitManager agentCircuitManager = new AgentCircuitManager(); - agentCircuitManager.AddNewCircuit(circuitcode1,m_agentCircuitData1); - agentCircuitManager.AddNewCircuit(circuitcode2, m_agentCircuitData2); - AgentCircuitData agent = agentCircuitManager.GetAgentCircuitData(circuitcode1); - - Assert.That((m_agentCircuitData1.AgentID == agent.AgentID)); - Assert.That((m_agentCircuitData1.BaseFolder == agent.BaseFolder)); - - Assert.That((m_agentCircuitData1.CapsPath == agent.CapsPath)); - Assert.That((m_agentCircuitData1.child == agent.child)); - Assert.That((m_agentCircuitData1.ChildrenCapSeeds.Count == agent.ChildrenCapSeeds.Count)); - Assert.That((m_agentCircuitData1.circuitcode == agent.circuitcode)); - Assert.That((m_agentCircuitData1.firstname == agent.firstname)); - Assert.That((m_agentCircuitData1.InventoryFolder == agent.InventoryFolder)); - Assert.That((m_agentCircuitData1.lastname == agent.lastname)); - Assert.That((m_agentCircuitData1.SecureSessionID == agent.SecureSessionID)); - Assert.That((m_agentCircuitData1.SessionID == agent.SessionID)); - Assert.That((m_agentCircuitData1.startpos == agent.startpos)); - } - - /// - /// Validate that removing the circuit code removes it appropriately - /// - [Test] - public void RemoveAgentCircuitTest() - { - AgentCircuitManager agentCircuitManager = new AgentCircuitManager(); - agentCircuitManager.AddNewCircuit(circuitcode1, m_agentCircuitData1); - agentCircuitManager.AddNewCircuit(circuitcode2, m_agentCircuitData2); - agentCircuitManager.RemoveCircuit(circuitcode2); - - AgentCircuitData agent = agentCircuitManager.GetAgentCircuitData(circuitcode2); - Assert.That(agent == null); - - } - - /// - /// Validate that changing the circuit code works - /// - [Test] - public void ChangeAgentCircuitCodeTest() - { - AgentCircuitManager agentCircuitManager = new AgentCircuitManager(); - agentCircuitManager.AddNewCircuit(circuitcode1, m_agentCircuitData1); - agentCircuitManager.AddNewCircuit(circuitcode2, m_agentCircuitData2); - bool result = false; - - result = agentCircuitManager.TryChangeCircuitCode(circuitcode1, 393930); - - AgentCircuitData agent = agentCircuitManager.GetAgentCircuitData(393930); - AgentCircuitData agent2 = agentCircuitManager.GetAgentCircuitData(circuitcode1); - Assert.That(agent != null); - Assert.That(agent2 == null); - Assert.That(result); - - } - - /// - /// Validates that the login authentication scheme is working - /// First one should be authorized - /// Rest should not be authorized - /// - [Test] - public void ValidateLoginTest() - { - AgentCircuitManager agentCircuitManager = new AgentCircuitManager(); - agentCircuitManager.AddNewCircuit(circuitcode1, m_agentCircuitData1); - agentCircuitManager.AddNewCircuit(circuitcode2, m_agentCircuitData2); - - // should be authorized - AuthenticateResponse resp = agentCircuitManager.AuthenticateSession(SessionId1, AgentId1, circuitcode1); - Assert.That(resp.Authorised); - - - //should not be authorized - resp = agentCircuitManager.AuthenticateSession(SessionId1, UUID.Random(), circuitcode1); - Assert.That(!resp.Authorised); - - resp = agentCircuitManager.AuthenticateSession(UUID.Random(), AgentId1, circuitcode1); - Assert.That(!resp.Authorised); - - resp = agentCircuitManager.AuthenticateSession(SessionId1, AgentId1, circuitcode2); - Assert.That(!resp.Authorised); - - resp = agentCircuitManager.AuthenticateSession(SessionId2, AgentId1, circuitcode2); - Assert.That(!resp.Authorised); - - agentCircuitManager.RemoveCircuit(circuitcode2); - - resp = agentCircuitManager.AuthenticateSession(SessionId2, AgentId2, circuitcode2); - Assert.That(!resp.Authorised); - } - } -} diff --git a/OpenSim/Framework/Tests/AnimationTests.cs b/OpenSim/Framework/Tests/AnimationTests.cs deleted file mode 100644 index daf86118755..00000000000 --- a/OpenSim/Framework/Tests/AnimationTests.cs +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Reflection; -using NUnit.Framework; -using OpenMetaverse; -using OpenMetaverse.StructuredData; -using OpenSim.Framework; -using OpenSim.Tests.Common; -using Animation = OpenSim.Framework.Animation; - -namespace OpenSim.Framework.Tests -{ - [TestFixture] - public class AnimationTests : OpenSimTestCase - { - private Animation anim1 = null; - private Animation anim2 = null; - private UUID animUUID1 = UUID.Zero; - private UUID objUUID1 = UUID.Zero; - private UUID animUUID2 = UUID.Zero; - private UUID objUUID2 = UUID.Zero; - - [SetUp] - public void Setup() - { - animUUID1 = UUID.Random(); - animUUID2 = UUID.Random(); - objUUID1 = UUID.Random(); - objUUID2 = UUID.Random(); - - anim1 = new Animation(animUUID1, 1, objUUID1); - anim2 = new Animation(animUUID2, 1, objUUID2); - } - - [Test] - public void AnimationOSDTest() - { - Assert.That(anim1.AnimID==animUUID1 && anim1.ObjectID == objUUID1 && anim1.SequenceNum ==1, "The Animation Constructor didn't set the fields correctly"); - OSD updateMessage = anim1.PackUpdateMessage(); - Assert.That(updateMessage is OSDMap, "Packed UpdateMessage isn't an OSDMap"); - OSDMap updateMap = (OSDMap) updateMessage; - Assert.That(updateMap.ContainsKey("animation"), "Packed Message doesn't contain an animation element"); - Assert.That(updateMap.ContainsKey("object_id"), "Packed Message doesn't contain an object_id element"); - Assert.That(updateMap.ContainsKey("seq_num"), "Packed Message doesn't contain a seq_num element"); - Assert.That(updateMap["animation"].AsUUID() == animUUID1); - Assert.That(updateMap["object_id"].AsUUID() == objUUID1); - Assert.That(updateMap["seq_num"].AsInteger() == 1); - - Animation anim3 = new Animation(updateMap); - - Assert.That(anim3.ObjectID == anim1.ObjectID && anim3.AnimID == anim1.AnimID && anim3.SequenceNum == anim1.SequenceNum, "OSDMap Constructor failed to set the properties correctly."); - - anim3.UnpackUpdateMessage(anim2.PackUpdateMessage()); - - Assert.That(anim3.ObjectID == objUUID2 && anim3.AnimID == animUUID2 && anim3.SequenceNum == 1, "Animation.UnpackUpdateMessage failed to set the properties correctly."); - - Animation anim4 = new Animation(); - anim4.AnimID = anim2.AnimID; - anim4.ObjectID = anim2.ObjectID; - anim4.SequenceNum = anim2.SequenceNum; - - Assert.That(anim4.ObjectID == objUUID2 && anim4.AnimID == animUUID2 && anim4.SequenceNum == 1, "void constructor and manual field population failed to set the properties correctly."); - } - } -} \ No newline at end of file diff --git a/OpenSim/Framework/Tests/AssetBaseTest.cs b/OpenSim/Framework/Tests/AssetBaseTest.cs deleted file mode 100644 index 1975a4df7e5..00000000000 --- a/OpenSim/Framework/Tests/AssetBaseTest.cs +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections.Generic; -using System.Text; -using NUnit.Framework; -using OpenMetaverse; -using OpenSim.Tests.Common; - -namespace OpenSim.Framework.Tests -{ - [TestFixture] - public class AssetBaseTest : OpenSimTestCase - { - [Test] - public void TestContainsReferences() - { - CheckContainsReferences(AssetType.Bodypart, true); - CheckContainsReferences(AssetType.Clothing, true); - - CheckContainsReferences(AssetType.Animation, false); - CheckContainsReferences(AssetType.CallingCard, false); - CheckContainsReferences(AssetType.Folder , false); - CheckContainsReferences(AssetType.Gesture , false); - CheckContainsReferences(AssetType.ImageJPEG , false); - CheckContainsReferences(AssetType.ImageTGA , false); - CheckContainsReferences(AssetType.Landmark , false); - CheckContainsReferences(AssetType.LSLBytecode, false); - CheckContainsReferences(AssetType.LSLText, false); - CheckContainsReferences(AssetType.Notecard, false); - CheckContainsReferences(AssetType.Object, false); - CheckContainsReferences(AssetType.Simstate, false); - CheckContainsReferences(AssetType.Sound, false); - CheckContainsReferences(AssetType.SoundWAV, false); - CheckContainsReferences(AssetType.Texture, false); - CheckContainsReferences(AssetType.TextureTGA, false); - CheckContainsReferences(AssetType.Unknown, false); - } - - private void CheckContainsReferences(AssetType assetType, bool expected) - { - AssetBase asset = new AssetBase(UUID.Zero, String.Empty, (sbyte)assetType, UUID.Zero.ToString()); - bool actual = asset.ContainsReferences; - Assert.AreEqual(expected, actual, "Expected "+assetType+".ContainsReferences to be "+expected+" but was "+actual+"."); - } - } -} diff --git a/OpenSim/Framework/Tests/CacheTests.cs b/OpenSim/Framework/Tests/CacheTests.cs deleted file mode 100644 index fc7df692b97..00000000000 --- a/OpenSim/Framework/Tests/CacheTests.cs +++ /dev/null @@ -1,125 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using NUnit.Framework; -using OpenMetaverse; -using OpenSim.Tests.Common; - -namespace OpenSim.Framework.Tests -{ - [TestFixture] - public class CacheTests : OpenSimTestCase - { - private Cache cache; - private UUID cacheItemUUID; - [SetUp] - public void Build() - { - cache = new Cache(); - cache = new Cache(CacheMedium.Memory,CacheStrategy.Aggressive,CacheFlags.AllowUpdate); - cacheItemUUID = UUID.Random(); - MemoryCacheItem cachedItem = new MemoryCacheItem(cacheItemUUID.ToString(),DateTime.Now + TimeSpan.FromDays(1)); - byte[] foo = new byte[1]; - foo[0] = 255; - cachedItem.Store(foo); - cache.Store(cacheItemUUID.ToString(), cachedItem); - } - [Test] - public void TestRetreive() - { - CacheItemBase citem = (CacheItemBase)cache.Get(cacheItemUUID.ToString()); - byte[] data = (byte[]) citem.Retrieve(); - Assert.That(data.Length == 1, "Cached Item should have one byte element"); - Assert.That(data[0] == 255, "Cached Item element should be 255"); - } - - [Test] - public void TestNotInCache() - { - UUID randomNotIn = UUID.Random(); - while (randomNotIn == cacheItemUUID) - { - randomNotIn = UUID.Random(); - } - object citem = cache.Get(randomNotIn.ToString()); - Assert.That(citem == null, "Item should not be in Cache"); - } - - - [Test] - public void ExpireItemManually() - { - UUID ImmediateExpiryUUID = UUID.Random(); - MemoryCacheItem cachedItem = new MemoryCacheItem(ImmediateExpiryUUID.ToString(), TimeSpan.FromDays(1)); - byte[] foo = new byte[1]; - foo[0] = 1; - cachedItem.Store(foo); - cache.Store(cacheItemUUID.ToString(), cachedItem); - cache.Invalidate(cacheItemUUID.ToString()); - cache.Get(cacheItemUUID.ToString()); - object citem = cache.Get(cacheItemUUID.ToString()); - Assert.That(citem == null, "Item should not be in Cache because we manually invalidated it"); - } - - [Test] - public void ClearCacheTest() - { - UUID ImmediateExpiryUUID = UUID.Random(); - MemoryCacheItem cachedItem = new MemoryCacheItem(ImmediateExpiryUUID.ToString(), DateTime.Now - TimeSpan.FromDays(1)); - byte[] foo = new byte[1]; - foo[0] = 1; - cachedItem.Store(foo); - cache.Store(cacheItemUUID.ToString(), cachedItem); - cache.Clear(); - - object citem = cache.Get(cacheItemUUID.ToString()); - Assert.That(citem == null, "Item should not be in Cache because we manually invalidated it"); - } - - [Test] - public void CacheItemMundane() - { - UUID Random1 = UUID.Random(); - UUID Random2 = UUID.Random(); - byte[] data = Array.Empty(); - CacheItemBase cb1 = new CacheItemBase(Random1.ToString(), DateTime.Now + TimeSpan.FromDays(1)); - CacheItemBase cb2 = new CacheItemBase(Random2.ToString(), DateTime.Now + TimeSpan.FromDays(1)); - CacheItemBase cb3 = new CacheItemBase(Random1.ToString(), DateTime.Now + TimeSpan.FromDays(1)); - - cb1.Store(data); - - Assert.That(cb1.Equals(cb3), "cb1 should equal cb3, their uuids are the same"); - Assert.That(!cb2.Equals(cb1), "cb2 should not equal cb1, their uuids are NOT the same"); - Assert.That(cb1.IsLocked() == false, "CacheItemBase default is false"); - Assert.That(cb1.Retrieve() == null, "Virtual Retrieve method should return null"); - - - } - - } -} diff --git a/OpenSim/Framework/Tests/LocationTest.cs b/OpenSim/Framework/Tests/LocationTest.cs deleted file mode 100644 index 5e84026708a..00000000000 --- a/OpenSim/Framework/Tests/LocationTest.cs +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using NUnit.Framework; -using OpenSim.Tests.Common; - -namespace OpenSim.Framework.Tests -{ - [TestFixture] - public class LocationTest : OpenSimTestCase - { - [Test] - public void locationRegionHandleRegionHandle() - { - //1099511628032000 - // 256000 - // 256000 - Location TestLocation1 = new Location(1099511628032000); - Location TestLocation2 = new Location(1099511628032000); - Assert.That(TestLocation1 == TestLocation2); - - TestLocation1 = new Location(1099511628032001); - TestLocation2 = new Location(1099511628032000); - Assert.That(TestLocation1 != TestLocation2); - } - - [Test] - public void locationXYRegionHandle() - { - Location TestLocation1 = new Location(255000,256000); - Location TestLocation2 = new Location(1095216660736000); - Assert.That(TestLocation1 == TestLocation2); - - Assert.That(TestLocation1.X == 255000 && TestLocation1.Y == 256000, "Test xy location doesn't match position in the constructor"); - Assert.That(TestLocation2.X == 255000 && TestLocation2.Y == 256000, "Test xy location doesn't match regionhandle provided"); - - Assert.That(TestLocation2.RegionHandle == 1095216660736000, - "Location RegionHandle Property didn't match regionhandle provided in constructor"); - - ulong RegionHandle = TestLocation1.RegionHandle; - Assert.That(RegionHandle.Equals(1095216660736000), "Equals(regionhandle) failed to match the position in the constructor"); - - TestLocation2 = new Location(RegionHandle); - Assert.That(TestLocation2.Equals(255000, 256000), "Decoded regionhandle failed to match the original position in the constructor"); - - - TestLocation1 = new Location(255001, 256001); - TestLocation2 = new Location(1095216660736000); - Assert.That(TestLocation1 != TestLocation2); - - Assert.That(TestLocation1.Equals(255001, 256001), "Equals(x,y) failed to match the position in the constructor"); - - Assert.That(TestLocation2.GetHashCode() == (TestLocation2.X.GetHashCode() ^ TestLocation2.Y.GetHashCode()), "GetHashCode failed to produce the expected hashcode"); - - Location TestLocation3; - object cln = TestLocation2.Clone(); - TestLocation3 = (Location) cln; - Assert.That(TestLocation3.X == TestLocation2.X && TestLocation3.Y == TestLocation2.Y, - "Cloned Location values do not match"); - - Assert.That(TestLocation2.Equals(cln), "Cloned object failed .Equals(obj) Test"); - - } - - } -} diff --git a/OpenSim/Framework/Tests/MundaneFrameworkTests.cs b/OpenSim/Framework/Tests/MundaneFrameworkTests.cs deleted file mode 100644 index 3d99c412246..00000000000 --- a/OpenSim/Framework/Tests/MundaneFrameworkTests.cs +++ /dev/null @@ -1,289 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using NUnit.Framework; -using OpenSim.Framework; -using OpenMetaverse; -using OpenMetaverse.StructuredData; -using System; -using System.Globalization; -using System.Threading; -using OpenSim.Tests.Common; - -namespace OpenSim.Framework.Tests -{ - [TestFixture] - public class MundaneFrameworkTests : OpenSimTestCase - { - private bool m_RegionSettingsOnSaveEventFired; - - [Test] - public void ChildAgentDataUpdate01() - { - // code coverage - ChildAgentDataUpdate cadu = new ChildAgentDataUpdate(); - Assert.IsFalse(cadu.alwaysrun, "Default is false"); - } - - [Test] - public void AgentPositionTest01() - { - UUID AgentId1 = UUID.Random(); - UUID SessionId1 = UUID.Random(); - uint CircuitCode1 = uint.MinValue; - Vector3 Size1 = Vector3.UnitZ; - Vector3 Position1 = Vector3.UnitX; - Vector3 LeftAxis1 = Vector3.UnitY; - Vector3 UpAxis1 = Vector3.UnitZ; - Vector3 AtAxis1 = Vector3.UnitX; - - ulong RegionHandle1 = ulong.MinValue; - byte[] Throttles1 = new byte[] {0, 1, 0}; - - Vector3 Velocity1 = Vector3.Zero; - float Far1 = 256; - - bool ChangedGrid1 = false; - Vector3 Center1 = Vector3.Zero; - - AgentPosition position1 = new AgentPosition(); - position1.AgentID = AgentId1; - position1.SessionID = SessionId1; - position1.CircuitCode = CircuitCode1; - position1.Size = Size1; - position1.Position = Position1; - position1.LeftAxis = LeftAxis1; - position1.UpAxis = UpAxis1; - position1.AtAxis = AtAxis1; - position1.RegionHandle = RegionHandle1; - position1.Throttles = Throttles1; - position1.Velocity = Velocity1; - position1.Far = Far1; - position1.ChangedGrid = ChangedGrid1; - position1.Center = Center1; - - ChildAgentDataUpdate cadu = new ChildAgentDataUpdate(); - cadu.AgentID = AgentId1.Guid; - cadu.ActiveGroupID = UUID.Zero.Guid; - cadu.throttles = Throttles1; - cadu.drawdistance = Far1; - cadu.Position = Position1; - cadu.Velocity = Velocity1; - cadu.regionHandle = RegionHandle1; - cadu.cameraPosition = Center1; - cadu.AVHeight = Size1.Z; - - AgentPosition position2 = new AgentPosition(); - position2.CopyFrom(cadu, position1.SessionID); - - Assert.IsTrue( - position2.AgentID == position1.AgentID - && position2.Size == position1.Size - && position2.Position == position1.Position - && position2.Velocity == position1.Velocity - && position2.Center == position1.Center - && position2.RegionHandle == position1.RegionHandle - && position2.Far == position1.Far - - ,"Copy From ChildAgentDataUpdate failed"); - - position2 = new AgentPosition(); - - Assert.IsFalse(position2.AgentID == position1.AgentID, "Test Error, position2 should be a blank uninitialized AgentPosition"); - EntityTransferContext ctx = new EntityTransferContext(); - position2.Unpack(position1.Pack(ctx), null, ctx); - - Assert.IsTrue(position2.AgentID == position1.AgentID, "Agent ID didn't unpack the same way it packed"); - Assert.IsTrue(position2.Position == position1.Position, "Position didn't unpack the same way it packed"); - Assert.IsTrue(position2.Velocity == position1.Velocity, "Velocity didn't unpack the same way it packed"); - Assert.IsTrue(position2.SessionID == position1.SessionID, "SessionID didn't unpack the same way it packed"); - Assert.IsTrue(position2.CircuitCode == position1.CircuitCode, "CircuitCode didn't unpack the same way it packed"); - Assert.IsTrue(position2.LeftAxis == position1.LeftAxis, "LeftAxis didn't unpack the same way it packed"); - Assert.IsTrue(position2.UpAxis == position1.UpAxis, "UpAxis didn't unpack the same way it packed"); - Assert.IsTrue(position2.AtAxis == position1.AtAxis, "AtAxis didn't unpack the same way it packed"); - Assert.IsTrue(position2.RegionHandle == position1.RegionHandle, "RegionHandle didn't unpack the same way it packed"); - Assert.IsTrue(position2.ChangedGrid == position1.ChangedGrid, "ChangedGrid didn't unpack the same way it packed"); - Assert.IsTrue(position2.Center == position1.Center, "Center didn't unpack the same way it packed"); - Assert.IsTrue(position2.Size == position1.Size, "Size didn't unpack the same way it packed"); - - } - - [Test] - public void RegionSettingsTest01() - { - RegionSettings settings = new RegionSettings(); - settings.OnSave += RegionSaveFired; - settings.Save(); - settings.OnSave -= RegionSaveFired; - -// string str = settings.LoadedCreationDate; -// int dt = settings.LoadedCreationDateTime; -// string id = settings.LoadedCreationID; -// string time = settings.LoadedCreationTime; - - Assert.That(m_RegionSettingsOnSaveEventFired, "RegionSettings Save Event didn't Fire"); - - } - public void RegionSaveFired(RegionSettings settings) - { - m_RegionSettingsOnSaveEventFired = true; - } - - [Test] - public void InventoryItemBaseConstructorTest01() - { - InventoryItemBase b1 = new InventoryItemBase(); - Assert.That(b1.ID == UUID.Zero, "void constructor should create an inventory item with ID = UUID.Zero"); - Assert.That(b1.Owner == UUID.Zero, "void constructor should create an inventory item with Owner = UUID.Zero"); - - UUID ItemID = UUID.Random(); - UUID OwnerID = UUID.Random(); - - InventoryItemBase b2 = new InventoryItemBase(ItemID); - Assert.That(b2.ID == ItemID, "ID constructor should create an inventory item with ID = ItemID"); - Assert.That(b2.Owner == UUID.Zero, "ID constructor should create an inventory item with Owner = UUID.Zero"); - - InventoryItemBase b3 = new InventoryItemBase(ItemID,OwnerID); - Assert.That(b3.ID == ItemID, "ID,OwnerID constructor should create an inventory item with ID = ItemID"); - Assert.That(b3.Owner == OwnerID, "ID,OwnerID constructor should create an inventory item with Owner = OwnerID"); - - } - - [Test] - public void AssetMetaDataNonNullContentTypeTest01() - { - AssetMetadata assetMetadata = new AssetMetadata(); - assetMetadata.ContentType = "image/jp2"; - Assert.That(assetMetadata.Type == (sbyte)AssetType.Texture, "Content type should be AssetType.Texture"); - Assert.That(assetMetadata.ContentType == "image/jp2", "Text of content type should be image/jp2"); - UUID rndID = UUID.Random(); - assetMetadata.ID = rndID.ToString(); - Assert.That(assetMetadata.ID.ToLower() == rndID.ToString().ToLower(), "assetMetadata.ID Setter/Getter not Consistent"); - DateTime fixedTime = DateTime.Now; - assetMetadata.CreationDate = fixedTime; - } - - [Test] - public void EstateSettingsMundateTests() - { - EstateSettings es = new EstateSettings(); - es.AddBan(null); - UUID bannedUserId = UUID.Random(); - es.AddBan(new EstateBan() - { BannedHostAddress = string.Empty, - BannedHostIPMask = string.Empty, - BannedHostNameMask = string.Empty, - BannedUserID = bannedUserId} - ); - Assert.IsTrue(es.IsBanned(bannedUserId, 32), "User Should be banned but is not."); - Assert.IsFalse(es.IsBanned(UUID.Zero, 32), "User Should not be banned but is."); - - es.RemoveBan(bannedUserId); - - Assert.IsFalse(es.IsBanned(bannedUserId, 32), "User Should not be banned but is."); - - es.AddEstateManager(UUID.Zero); - - es.AddEstateManager(bannedUserId); - Assert.IsTrue(es.IsEstateManagerOrOwner(bannedUserId), "bannedUserId should be EstateManager but isn't."); - - es.RemoveEstateManager(bannedUserId); - Assert.IsFalse(es.IsEstateManagerOrOwner(bannedUserId), "bannedUserID is estateManager but shouldn't be"); - - Assert.IsFalse(es.HasAccess(bannedUserId), "bannedUserID has access but shouldn't"); - - es.AddEstateUser(bannedUserId); - - Assert.IsTrue(es.HasAccess(bannedUserId), "bannedUserID doesn't have access but should"); - es.RemoveEstateUser(bannedUserId); - - es.AddEstateManager(bannedUserId); - - Assert.IsTrue(es.HasAccess(bannedUserId), "bannedUserID doesn't have access but should"); - - Assert.That(es.EstateGroups.Length == 0, "No Estate Groups Added.. so the array should be 0 length"); - - es.AddEstateGroup(bannedUserId); - - Assert.That(es.EstateGroups.Length == 1, "1 Estate Groups Added.. so the array should be 1 length"); - - Assert.That(es.EstateGroups[0] == bannedUserId,"User ID should be in EstateGroups"); - - } - - [Test] - public void InventoryFolderBaseConstructorTest01() - { - UUID uuid1 = UUID.Random(); - UUID uuid2 = UUID.Random(); - - InventoryFolderBase fld = new InventoryFolderBase(uuid1); - Assert.That(fld.ID == uuid1, "ID constructor failed to save value in ID field."); - - fld = new InventoryFolderBase(uuid1, uuid2); - Assert.That(fld.ID == uuid1, "ID,Owner constructor failed to save value in ID field."); - Assert.That(fld.Owner == uuid2, "ID,Owner constructor failed to save value in ID field."); - } - - [Test] - public void AsssetBaseConstructorTest01() - { - AssetBase abase = new AssetBase(); - Assert.IsNotNull(abase.Metadata, "void constructor of AssetBase should have created a MetaData element but didn't."); - UUID itemID = UUID.Random(); - UUID creatorID = UUID.Random(); - abase = new AssetBase(itemID.ToString(), "test item", (sbyte) AssetType.Texture, creatorID.ToString()); - - Assert.IsNotNull(abase.Metadata, "string,string,sbyte,string constructor of AssetBase should have created a MetaData element but didn't."); - Assert.That(abase.ID == itemID.ToString(), "string,string,sbyte,string constructor failed to set ID property"); - Assert.That(abase.Metadata.CreatorID == creatorID.ToString(), "string,string,sbyte,string constructor failed to set Creator ID"); - - - abase = new AssetBase(itemID.ToString(), "test item", -1, creatorID.ToString()); - Assert.IsNotNull(abase.Metadata, "string,string,sbyte,string constructor of AssetBase with unknown type should have created a MetaData element but didn't."); - Assert.That(abase.Metadata.Type == -1, "Unknown Type passed to string,string,sbyte,string constructor and was a known type when it came out again"); - - AssetMetadata metts = new AssetMetadata(); - metts.FullID = itemID; - metts.ID = string.Empty; - metts.Name = "test item"; - abase.Metadata = metts; - - Assert.That(abase.ToString() == itemID.ToString(), "ToString is overriden to be fullID.ToString()"); - Assert.That(abase.ID == itemID.ToString(),"ID should be MetaData.FullID.ToString() when string.empty or null is provided to the ID property"); - } - - [Test] - public void CultureSetCultureTest01() - { - CultureInfo ci = new CultureInfo("en-US", false); - Culture.SetCurrentCulture(); - Assert.That(Thread.CurrentThread.CurrentCulture.Name == ci.Name, "SetCurrentCulture failed to set thread culture to en-US"); - - } - } -} diff --git a/OpenSim/Framework/Tests/OpenSim.Framework.Tests.csproj b/OpenSim/Framework/Tests/OpenSim.Framework.Tests.csproj deleted file mode 100644 index c172f760a7d..00000000000 --- a/OpenSim/Framework/Tests/OpenSim.Framework.Tests.csproj +++ /dev/null @@ -1,39 +0,0 @@ - - - net8.0 - - - - - - - - - - ..\..\..\bin\Nini.dll - False - - - ..\..\..\bin\OpenMetaverse.dll - False - - - ..\..\..\bin\OpenMetaverse.StructuredData.dll - False - - - ..\..\..\bin\OpenMetaverseTypes.dll - False - - - ..\..\..\bin\XMLRPC.dll - False - - - - - - - - - \ No newline at end of file diff --git a/OpenSim/Framework/Tests/PrimeNumberHelperTests.cs b/OpenSim/Framework/Tests/PrimeNumberHelperTests.cs deleted file mode 100644 index cc30fb97d6a..00000000000 --- a/OpenSim/Framework/Tests/PrimeNumberHelperTests.cs +++ /dev/null @@ -1,144 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Reflection; -using NUnit.Framework; -using OpenMetaverse; -using OpenMetaverse.StructuredData; -using OpenSim.Framework; -using OpenSim.Tests.Common; - -namespace OpenSim.Framework.Tests -{ - [TestFixture] - public class PrimeNumberHelperTests : OpenSimTestCase - { - [Test] - public void TestGetPrime() - { - int prime1 = PrimeNumberHelper.GetPrime(7919); - Assert.That(prime1 == 8419, "Prime Number Get Prime Failed, 7919 is prime"); - Assert.That(PrimeNumberHelper.IsPrime(prime1),"Prime1 should be prime"); - Assert.That(PrimeNumberHelper.IsPrime(7919), "7919 is prime but is falsely failing the prime test"); - prime1 = PrimeNumberHelper.GetPrime(Int32.MaxValue - 1); - Assert.That(prime1 == -1, "prime1 should have been -1 since there are no primes between Int32.MaxValue-1 and Int32.MaxValue"); - - } - - [Test] - public void Test1000SmallPrimeNumbers() - { - int[] primes = { - 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, - 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191 - , 193, 197, 199, 211, 223, 227, 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 283, - 293, 307, 311, 313, 317, 331, 337, 347, 349, 353, 359, 367, 373, 379, 383, 389, 397, 401, - 409, 419, 421, 431, 433, 439, 443, 449, 457, 461, 463, 467, 479, 487, 491, 499, 503, 509, - 521, 523, 541, 547, 557, 563, 569, 571, 577, 587, 593, 599, 601, 607, 613, 617, 619, 631, - 641, 643, 647, 653, 659, 661, 673, 677, 683, 691, 701, 709, 719, 727, 733, 739, 743, 751, - 757, 761, 769, 773, 787, 797, 809, 811, 821, 823, 827, 829, 839, 853, 857, 859, 863, 877, - 881, 883, 887, 907, 911, 919, 929, 937, 941, 947, 953, 967, 971, 977, 983, 991, 997, 1009, - 1013, 1019, 1021, 1031, 1033, 1039, 1049, 1051, 1061, 1063, 1069, 1087, 1091, 1093, 1097, - 1103, 1109, 1117, 1123, 1129, 1151, 1153, 1163, 1171, 1181, 1187, 1193, 1201, 1213, 1217, - 1223, 1229, 1231, 1237, 1249, 1259, 1277, 1279, 1283, 1289, 1291, 1297, 1301, 1303, 1307, - 1319, 1321, 1327, 1361, 1367, 1373, 1381, 1399, 1409, 1423, 1427, 1429, 1433, 1439, 1447, - 1451, 1453, 1459, 1471, 1481, 1483, 1487, 1489, 1493, 1499, 1511, 1523, 1531, 1543, 1549, - 1553, 1559, 1567, 1571, 1579, 1583, 1597, 1601, 1607, 1609, 1613, 1619, 1621, 1627, 1637, - 1657, 1663, 1667, 1669, 1693, 1697, 1699, 1709, 1721, 1723, 1733, 1741, 1747, 1753, 1759, - 1777, 1783, 1787, 1789, 1801, 1811, 1823, 1831, 1847, 1861, 1867, 1871, 1873, 1877, 1879, - 1889, 1901, 1907, 1913, 1931, 1933, 1949, 1951, 1973, 1979, 1987, 1993, 1997, 1999, 2003, - 2011, 2017, 2027, 2029, 2039, 2053, 2063, 2069, 2081, 2083, 2087, 2089, 2099, 2111, 2113, - 2129, 2131, 2137, 2141, 2143, 2153, 2161, 2179, 2203, 2207, 2213, 2221, 2237, 2239, 2243, - 2251, 2267, 2269, 2273, 2281, 2287, 2293, 2297, 2309, 2311, 2333, 2339, 2341, 2347, 2351, - 2357, 2371, 2377, 2381, 2383, 2389, 2393, 2399, 2411, 2417, 2423, 2437, 2441, 2447, 2459, - 2467, 2473, 2477, 2503, 2521, 2531, 2539, 2543, 2549, 2551, 2557, 2579, 2591, 2593, 2609, - 2617, 2621, 2633, 2647, 2657, 2659, 2663, 2671, 2677, 2683, 2687, 2689, 2693, 2699, 2707, - 2711, 2713, 2719, 2729, 2731, 2741, 2749, 2753, 2767, 2777, 2789, 2791, 2797, 2801, 2803, - 2819, 2833, 2837, 2843, 2851, 2857, 2861, 2879, 2887, 2897, 2903, 2909, 2917, 2927, 2939, - 2953, 2957, 2963, 2969, 2971, 2999, 3001, 3011, 3019, 3023, 3037, 3041, 3049, 3061, 3067, - 3079, 3083, 3089, 3109, 3119, 3121, 3137, 3163, 3167, 3169, 3181, 3187, 3191, 3203, 3209, - 3217, 3221, 3229, 3251, 3253, 3257, 3259, 3271, 3299, 3301, 3307, 3313, 3319, 3323, 3329, - 3331, 3343, 3347, 3359, 3361, 3371, 3373, 3389, 3391, 3407, 3413, 3433, 3449, 3457, 3461, - 3463, 3467, 3469, 3491, 3499, 3511, 3517, 3527, 3529, 3533, 3539, 3541, 3547, 3557, 3559, - 3571, 3581, 3583, 3593, 3607, 3613, 3617, 3623, 3631, 3637, 3643, 3659, 3671, 3673, 3677, - 3691, 3697, 3701, 3709, 3719, 3727, 3733, 3739, 3761, 3767, 3769, 3779, 3793, 3797, 3803, - 3821, 3823, 3833, 3847, 3851, 3853, 3863, 3877, 3881, 3889, 3907, 3911, 3917, 3919, 3923, - 3929, 3931, 3943, 3947, 3967, 3989, 4001, 4003, 4007, 4013, 4019, 4021, 4027, 4049, 4051, - 4057, 4073, 4079, 4091, 4093, 4099, 4111, 4127, 4129, 4133, 4139, 4153, 4157, 4159, 4177, - 4201, 4211, 4217, 4219, 4229, 4231, 4241, 4243, 4253, 4259, 4261, 4271, 4273, 4283, 4289, - 4297, 4327, 4337, 4339, 4349, 4357, 4363, 4373, 4391, 4397, 4409, 4421, 4423, 4441, 4447, - 4451, 4457, 4463, 4481, 4483, 4493, 4507, 4513, 4517, 4519, 4523, 4547, 4549, 4561, 4567, - 4583, 4591, 4597, 4603, 4621, 4637, 4639, 4643, 4649, 4651, 4657, 4663, 4673, 4679, 4691, - 4703, 4721, 4723, 4729, 4733, 4751, 4759, 4783, 4787, 4789, 4793, 4799, 4801, 4813, 4817, - 4831, 4861, 4871, 4877, 4889, 4903, 4909, 4919, 4931, 4933, 4937, 4943, 4951, 4957, 4967, - 4969, 4973, 4987, 4993, 4999, 5003, 5009, 5011, 5021, 5023, 5039, 5051, 5059, 5077, 5081, - 5087, 5099, 5101, 5107, 5113, 5119, 5147, 5153, 5167, 5171, 5179, 5189, 5197, 5209, 5227, - 5231, 5233, 5237, 5261, 5273, 5279, 5281, 5297, 5303, 5309, 5323, 5333, 5347, 5351, 5381, - 5387, 5393, 5399, 5407, 5413, 5417, 5419, 5431, 5437, 5441, 5443, 5449, 5471, 5477, 5479, - 5483, 5501, 5503, 5507, 5519, 5521, 5527, 5531, 5557, 5563, 5569, 5573, 5581, 5591, 5623, - 5639, 5641, 5647, 5651, 5653, 5657, 5659, 5669, 5683, 5689, 5693, 5701, 5711, 5717, 5737, - 5741, 5743, 5749, 5779, 5783, 5791, 5801, 5807, 5813, 5821, 5827, 5839, 5843, 5849, 5851, - 5857, 5861, 5867, 5869, 5879, 5881, 5897, 5903, 5923, 5927, 5939, 5953, 5981, 5987, 6007, - 6011, 6029, 6037, 6043, 6047, 6053, 6067, 6073, 6079, 6089, 6091, 6101, 6113, 6121, 6131, - 6133, 6143, 6151, 6163, 6173, 6197, 6199, 6203, 6211, 6217, 6221, 6229, 6247, 6257, 6263, - 6269, 6271, 6277, 6287, 6299, 6301, 6311, 6317, 6323, 6329, 6337, 6343, 6353, 6359, 6361, - 6367, 6373, 6379, 6389, 6397, 6421, 6427, 6449, 6451, 6469, 6473, 6481, 6491, 6521, 6529, - 6547, 6551, 6553, 6563, 6569, 6571, 6577, 6581, 6599, 6607, 6619, 6637, 6653, 6659, 6661, - 6673, 6679, 6689, 6691, 6701, 6703, 6709, 6719, 6733, 6737, 6761, 6763, 6779, 6781, 6791, - 6793, 6803, 6823, 6827, 6829, 6833, 6841, 6857, 6863, 6869, 6871, 6883, 6899, 6907, 6911, - 6917, 6947, 6949, 6959, 6961, 6967, 6971, 6977, 6983, 6991, 6997, 7001, 7013, 7019, 7027, - 7039, 7043, 7057, 7069, 7079, 7103, 7109, 7121, 7127, 7129, 7151, 7159, 7177, 7187, 7193, - 7207, 7211, 7213, 7219, 7229, 7237, 7243, 7247, 7253, 7283, 7297, 7307, 7309, 7321, 7331, - 7333, 7349, 7351, 7369, 7393, 7411, 7417, 7433, 7451, 7457, 7459, 7477, 7481, 7487, 7489, - 7499, 7507, 7517, 7523, 7529, 7537, 7541, 7547, 7549, 7559, 7561, 7573, 7577, 7583, 7589, - 7591, 7603, 7607, 7621, 7639, 7643, 7649, 7669, 7673, 7681, 7687, 7691, 7699, 7703, 7717, - 7723, 7727, 7741, 7753, 7757, 7759, 7789, 7793, 7817, 7823, 7829, 7841, 7853, 7867, 7873, - 7877, 7879, 7883, 7901, 7907, 7919 - }; - for (int i = 0; i < primes.Length; i++) - { - Assert.That(PrimeNumberHelper.IsPrime(primes[i]),primes[i] + " is prime but is erroniously failing the prime test"); - } - - int[] nonprimes = { - 4, 6, 8, 10, 14, 16, 18, 22, 28, 30, 36, 40, 42, 46, 52, 58, 60, 66, 70, 72, 78, 82, 88, - 96, 366, 372, 378, 382, 388, 396, 400, 408, 418, 420, 430, 432, 438, 442, 448, 456, 460, 462, - 466, 478, 486, 490, 498, 502, 508, 856, 858, 862, 876, 880, 882, 886, 906, 910, 918, 928, 936, - 940, 946, 952, 966, 970, 976, 982, 990, 996, 1008, 1740, 1746, 1752, 1758, 4650, 4656, 4662, - 4672, 4678, 4690, 7740, 7752, 7756, 7758, 7788, 7792, 7816, 7822, 7828, 7840, 7852, 7866, 7872, - 7876, 7878, 7882, 7900, 7906, 7918 - }; - for (int i = 0; i < nonprimes.Length; i++) - { - Assert.That(!PrimeNumberHelper.IsPrime(nonprimes[i]), nonprimes[i] + " is not prime but is erroniously passing the prime test"); - } - - Assert.That(PrimeNumberHelper.IsPrime(3)); - } - } -} \ No newline at end of file diff --git a/OpenSim/Framework/Tests/UtilTest.cs b/OpenSim/Framework/Tests/UtilTest.cs deleted file mode 100644 index b3d79eec971..00000000000 --- a/OpenSim/Framework/Tests/UtilTest.cs +++ /dev/null @@ -1,360 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using NUnit.Framework; -using OpenMetaverse; -using OpenSim.Tests.Common; - -namespace OpenSim.Framework.Tests -{ - [TestFixture] - public class UtilTests : OpenSimTestCase - { - [Test] - public void VectorOperationTests() - { - Vector3 v1, v2; - double expectedDistance; - double expectedMagnitude; - double lowPrecisionTolerance = 0.001; - - //Lets test a simple case of <0,0,0> and <5,5,5> - { - v1 = new Vector3(0, 0, 0); - v2 = new Vector3(5, 5, 5); - expectedDistance = 8.66; - Assert.That(Util.GetDistanceTo(v1, v2), - new DoubleToleranceConstraint(expectedDistance, lowPrecisionTolerance), - "Calculated distance between two vectors was not within tolerances."); - - expectedMagnitude = 0; - Assert.That(Util.GetMagnitude(v1), Is.EqualTo(0), "Magnitude of null vector was not zero."); - - expectedMagnitude = 8.66; - Assert.That(Util.GetMagnitude(v2), - new DoubleToleranceConstraint(expectedMagnitude, lowPrecisionTolerance), - "Magnitude of vector was incorrect."); -/* - TestDelegate d = delegate() { Util.GetNormalizedVector(v1); }; - bool causesArgumentException = TestHelpers.AssertThisDelegateCausesArgumentException(d); - Assert.That(causesArgumentException, Is.True, - "Getting magnitude of null vector did not cause argument exception."); -*/ - Vector3 expectedNormalizedVector = new Vector3(.577f, .577f, .577f); - double expectedNormalizedMagnitude = 1; - Vector3 normalizedVector = Util.GetNormalizedVector(v2); - Assert.That(normalizedVector, - new VectorToleranceConstraint(expectedNormalizedVector, lowPrecisionTolerance), - "Normalized vector generated from vector was not what was expected."); - Assert.That(Util.GetMagnitude(normalizedVector), - new DoubleToleranceConstraint(expectedNormalizedMagnitude, lowPrecisionTolerance), - "Normalized vector generated from vector does not have magnitude of 1."); - } - - //Lets test a simple case of <0,0,0> and <0,0,0> - { - v1 = new Vector3(0, 0, 0); - v2 = new Vector3(0, 0, 0); - expectedDistance = 0; - Assert.That(Util.GetDistanceTo(v1, v2), - new DoubleToleranceConstraint(expectedDistance, lowPrecisionTolerance), - "Calculated distance between two vectors was not within tolerances."); - - expectedMagnitude = 0; - Assert.That(Util.GetMagnitude(v1), Is.EqualTo(0), "Magnitude of null vector was not zero."); - - expectedMagnitude = 0; - Assert.That(Util.GetMagnitude(v2), - new DoubleToleranceConstraint(expectedMagnitude, lowPrecisionTolerance), - "Magnitude of vector was incorrect."); -/* - TestDelegate d = delegate() { Util.GetNormalizedVector(v1); }; - bool causesArgumentException = TestHelpers.AssertThisDelegateCausesArgumentException(d); - Assert.That(causesArgumentException, Is.True, - "Getting magnitude of null vector did not cause argument exception."); - - d = delegate() { Util.GetNormalizedVector(v2); }; - causesArgumentException = TestHelpers.AssertThisDelegateCausesArgumentException(d); - Assert.That(causesArgumentException, Is.True, - "Getting magnitude of null vector did not cause argument exception."); -*/ - } - - //Lets test a simple case of <0,0,0> and <-5,-5,-5> - { - v1 = new Vector3(0, 0, 0); - v2 = new Vector3(-5, -5, -5); - expectedDistance = 8.66; - Assert.That(Util.GetDistanceTo(v1, v2), - new DoubleToleranceConstraint(expectedDistance, lowPrecisionTolerance), - "Calculated distance between two vectors was not within tolerances."); - - expectedMagnitude = 0; - Assert.That(Util.GetMagnitude(v1), Is.EqualTo(0), "Magnitude of null vector was not zero."); - - expectedMagnitude = 8.66; - Assert.That(Util.GetMagnitude(v2), - new DoubleToleranceConstraint(expectedMagnitude, lowPrecisionTolerance), - "Magnitude of vector was incorrect."); -/* - TestDelegate d = delegate() { Util.GetNormalizedVector(v1); }; - bool causesArgumentException = TestHelpers.AssertThisDelegateCausesArgumentException(d); - Assert.That(causesArgumentException, Is.True, - "Getting magnitude of null vector did not cause argument exception."); -*/ - Vector3 expectedNormalizedVector = new Vector3(-.577f, -.577f, -.577f); - double expectedNormalizedMagnitude = 1; - Vector3 normalizedVector = Util.GetNormalizedVector(v2); - Assert.That(normalizedVector, - new VectorToleranceConstraint(expectedNormalizedVector, lowPrecisionTolerance), - "Normalized vector generated from vector was not what was expected."); - Assert.That(Util.GetMagnitude(normalizedVector), - new DoubleToleranceConstraint(expectedNormalizedMagnitude, lowPrecisionTolerance), - "Normalized vector generated from vector does not have magnitude of 1."); - } - } - - [Test] - public void UUIDTests() - { - Assert.IsTrue(Util.isUUID("01234567-89ab-Cdef-0123-456789AbCdEf"), - "A correct UUID wasn't recognized."); - Assert.IsFalse(Util.isUUID("FOOBAR67-89ab-Cdef-0123-456789AbCdEf"), - "UUIDs with non-hex characters are recognized as correct UUIDs."); - Assert.IsFalse(Util.isUUID("01234567"), - "Too short UUIDs are recognized as correct UUIDs."); - Assert.IsFalse(Util.isUUID("01234567-89ab-Cdef-0123-456789AbCdEf0"), - "Too long UUIDs are recognized as correct UUIDs."); - Assert.IsFalse(Util.isUUID("01234567-89ab-Cdef-0123+456789AbCdEf"), - "UUIDs with wrong format are recognized as correct UUIDs."); - } - - [Test] - public void GetHashGuidTests() - { - string string1 = "This is one string"; - string string2 = "This is another"; - - // Two consecutive runs should equal the same - Assert.AreEqual(Util.GetHashGuid(string1, "secret1"), Util.GetHashGuid(string1, "secret1")); - Assert.AreEqual(Util.GetHashGuid(string2, "secret1"), Util.GetHashGuid(string2, "secret1")); - - // Varying data should not eqal the same - Assert.AreNotEqual(Util.GetHashGuid(string1, "secret1"), Util.GetHashGuid(string2, "secret1")); - - // Varying secrets should not eqal the same - Assert.AreNotEqual(Util.GetHashGuid(string1, "secret1"), Util.GetHashGuid(string1, "secret2")); - } - - [Test] - public void SLUtilTypeConvertTests() - { - int[] assettypes = new int[]{-1,0,1,2,3,5,6,7,8,10,11,12,13,17,18,19,20,21,22 - ,24,25}; - string[] contenttypes = new string[] - { - "application/octet-stream", - "image/x-j2c", - "audio/ogg", - "application/vnd.ll.callingcard", - "application/vnd.ll.landmark", - "application/vnd.ll.clothing", - "application/vnd.ll.primitive", - "application/vnd.ll.notecard", - "application/vnd.ll.folder", - "application/vnd.ll.lsltext", - "application/vnd.ll.lslbyte", - "image/tga", - "application/vnd.ll.bodypart", - "audio/x-wav", - "image/tga", - "image/jpeg", - "application/vnd.ll.animation", - "application/vnd.ll.gesture", - "application/x-metaverse-simstate", - "application/vnd.ll.link", - "application/vnd.ll.linkfolder", - }; - for (int i=0;i - /// Test an attempt to put a message on the queue of a user that is not in the region. - /// - [Test] - public void TestEnqueueMessageNoUser() - { - TestHelpers.InMethod(); - TestHelpers.EnableLogging(); - - string messageName = "TestMessage"; - - m_eqgMod.Enqueue(m_eqgMod.BuildEvent(messageName, new OSDMap()), TestHelpers.ParseTail(0x1)); - - Hashtable eventsResponse = m_eqgMod.GetEvents(UUID.Zero, TestHelpers.ParseTail(0x1)); - - Assert.That((int)eventsResponse["int_response_code"], Is.EqualTo((int)HttpStatusCode.NotFound)); - } - - /// - /// NPCs do not currently have an event queue but a caller may try to send a message anyway, so check behaviour. - /// - [Test] - public void TestEnqueueMessageToNpc() - { - TestHelpers.InMethod(); -// TestHelpers.EnableLogging(); - - UUID npcId - = m_npcMod.CreateNPC( - "John", "Smith", new Vector3(128, 128, 30), UUID.Zero, true, m_scene, new AvatarAppearance()); - - ScenePresence npc = m_scene.GetScenePresence(npcId); - - string messageName = "TestMessage"; - - m_eqgMod.Enqueue(m_eqgMod.BuildEvent(messageName, new OSDMap()), npc.UUID); - - Hashtable eventsResponse = m_eqgMod.GetEvents(UUID.Zero, npc.UUID); - - Assert.That((int)eventsResponse["int_response_code"], Is.EqualTo((int)HttpStatusCode.NotFound)); - } - } -} diff --git a/OpenSim/Region/ClientStack/Linden/Caps/Tests/WebFetchInvDescModuleTests.cs b/OpenSim/Region/ClientStack/Linden/Caps/Tests/WebFetchInvDescModuleTests.cs deleted file mode 100644 index 050b779887a..00000000000 --- a/OpenSim/Region/ClientStack/Linden/Caps/Tests/WebFetchInvDescModuleTests.cs +++ /dev/null @@ -1,161 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections; -using System.Collections.Generic; -using System.IO; -using System.Net; -using System.Text; -using OSHttpServer; -using log4net.Config; -using Nini.Config; -using NUnit.Framework; -using OpenMetaverse; -using OpenMetaverse.Packets; -using OpenMetaverse.StructuredData; -using OpenSim.Framework; -using OpenSim.Framework.Capabilities; -using OpenSim.Framework.Servers; -using OpenSim.Framework.Servers.HttpServer; -using OpenSim.Region.ClientStack.Linden; -using OpenSim.Region.CoreModules.Framework; -using OpenSim.Region.Framework.Scenes; -using OpenSim.Services.Interfaces; -using OpenSim.Tests.Common; -using OSDArray = OpenMetaverse.StructuredData.OSDArray; -using OSDMap = OpenMetaverse.StructuredData.OSDMap; - -namespace OpenSim.Region.ClientStack.Linden.Caps.Tests -{ - /* - [TestFixture] - public class WebFetchInvDescModuleTests : OpenSimTestCase - { - [TestFixtureSetUp] - public void TestFixtureSetUp() - { - // Don't allow tests to be bamboozled by asynchronous events. Execute everything on the same thread. - Util.FireAndForgetMethod = FireAndForgetMethod.RegressionTest; - } - - [TestFixtureTearDown] - public void TestFixureTearDown() - { - // We must set this back afterwards, otherwise later tests will fail since they're expecting multiple - // threads. Possibly, later tests should be rewritten so none of them require async stuff (which regression - // tests really shouldn't). - Util.FireAndForgetMethod = Util.DefaultFireAndForgetMethod; - } - - [SetUp] - public override void SetUp() - { - base.SetUp(); - - // This is an unfortunate bit of clean up we have to do because MainServer manages things through static - // variables and the VM is not restarted between tests. - uint port = 9999; - MainServer.RemoveHttpServer(port); - - BaseHttpServer server = new BaseHttpServer(port, false, 0, ""); - MainServer.AddHttpServer(server); - MainServer.Instance = server; - - server.Start(false); - } - - [Test] - public void TestInventoryDescendentsFetch() - { - TestHelpers.InMethod(); - TestHelpers.EnableLogging(); - - BaseHttpServer httpServer = MainServer.Instance; - Scene scene = new SceneHelpers().SetupScene(); - - CapabilitiesModule capsModule = new CapabilitiesModule(); - WebFetchInvDescModule wfidModule = new WebFetchInvDescModule(false); - - IConfigSource config = new IniConfigSource(); - config.AddConfig("ClientStack.LindenCaps"); - config.Configs["ClientStack.LindenCaps"].Set("Cap_FetchInventoryDescendents2", "localhost"); - - SceneHelpers.SetupSceneModules(scene, config, capsModule, wfidModule); - - UserAccount ua = UserAccountHelpers.CreateUserWithInventory(scene, TestHelpers.ParseTail(0x1)); - - // We need a user present to have any capabilities set up - SceneHelpers.AddScenePresence(scene, ua.PrincipalID); - - TestHttpRequest req = new TestHttpRequest(); - OpenSim.Framework.Capabilities.Caps userCaps = capsModule.GetCapsForUser(ua.PrincipalID); - PollServiceEventArgs pseArgs; - userCaps.TryGetPollHandler("FetchInventoryDescendents2", out pseArgs); - req.UriPath = pseArgs.Url; - req.Uri = new Uri("file://" + req.UriPath); - - // Retrieve root folder details directly so that we can request - InventoryFolderBase folder = scene.InventoryService.GetRootFolder(ua.PrincipalID); - - OSDMap osdFolder = new OSDMap(); - osdFolder["folder_id"] = folder.ID; - osdFolder["owner_id"] = ua.PrincipalID; - osdFolder["fetch_folders"] = true; - osdFolder["fetch_items"] = true; - osdFolder["sort_order"] = 0; - - OSDArray osdFoldersArray = new OSDArray(); - osdFoldersArray.Add(osdFolder); - - OSDMap osdReqMap = new OSDMap(); - osdReqMap["folders"] = osdFoldersArray; - - req.Body = new MemoryStream(OSDParser.SerializeLLSDXmlBytes(osdReqMap)); - - TestHttpClientContext context = new TestHttpClientContext(false); - - // WARNING: This results in a caught exception, because queryString is null - MainServer.Instance.OnRequest(context, new RequestEventArgs(req)); - - // Drive processing of the queued inventory request synchronously. - wfidModule.WaitProcessQueuedInventoryRequest(); - MainServer.Instance.PollServiceRequestManager.WaitPerformResponse(); - -// System.Threading.Thread.Sleep(10000); - - OSDMap responseOsd = (OSDMap)OSDParser.DeserializeLLSDXml(context.ResponseBody); - OSDArray foldersOsd = (OSDArray)responseOsd["folders"]; - OSDMap folderOsd = (OSDMap)foldersOsd[0]; - - // A sanity check that the response has the expected number of descendents for a default inventory - // TODO: Need a more thorough check. - Assert.That((int)folderOsd["descendents"], Is.EqualTo(16)); - } - } - */ -} \ No newline at end of file diff --git a/OpenSim/Region/ClientStack/Linden/UDP/Tests/BasicCircuitTests.cs b/OpenSim/Region/ClientStack/Linden/UDP/Tests/BasicCircuitTests.cs deleted file mode 100644 index c61ea2104db..00000000000 --- a/OpenSim/Region/ClientStack/Linden/UDP/Tests/BasicCircuitTests.cs +++ /dev/null @@ -1,273 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Net; -using log4net.Config; -using Nini.Config; -using NUnit.Framework; -using OpenMetaverse; -using OpenMetaverse.Packets; -using OpenSim.Framework; -using OpenSim.Framework.Monitoring; -using OpenSim.Region.Framework.Scenes; -using OpenSim.Tests.Common; - -namespace OpenSim.Region.ClientStack.LindenUDP.Tests -{ - /// - /// This will contain basic tests for the LindenUDP client stack - /// - [TestFixture] - public class BasicCircuitTests : OpenSimTestCase - { - private Scene m_scene; - - [OneTimeSetUp] - public void FixtureInit() - { - // Don't allow tests to be bamboozled by asynchronous events. Execute everything on the same thread. - Util.FireAndForgetMethod = FireAndForgetMethod.RegressionTest; - } - - [OneTimeTearDown] - public void TearDown() - { - // We must set this back afterwards, otherwise later tests will fail since they're expecting multiple - // threads. Possibly, later tests should be rewritten so none of them require async stuff (which regression - // tests really shouldn't). - Util.FireAndForgetMethod = Util.DefaultFireAndForgetMethod; - } - - [SetUp] - public override void SetUp() - { - base.SetUp(); - m_scene = new SceneHelpers().SetupScene(); - StatsManager.SimExtraStats = new SimExtraStatsCollector(); - } - -// /// -// /// Build an object name packet for test purposes -// /// -// /// -// /// -// private ObjectNamePacket BuildTestObjectNamePacket(uint objectLocalId, string objectName) -// { -// ObjectNamePacket onp = new ObjectNamePacket(); -// ObjectNamePacket.ObjectDataBlock odb = new ObjectNamePacket.ObjectDataBlock(); -// odb.LocalID = objectLocalId; -// odb.Name = Utils.StringToBytes(objectName); -// onp.ObjectData = new ObjectNamePacket.ObjectDataBlock[] { odb }; -// onp.Header.Zerocoded = false; -// -// return onp; -// } -// - /// - /// Test adding a client to the stack - /// -/* - [Test] - public void TestAddClient() - { - TestHelpers.InMethod(); -// TestHelpers.EnableLogging(); - - TestLLUDPServer udpServer = ClientStackHelpers.AddUdpServer(m_scene); - - UUID myAgentUuid = TestHelpers.ParseTail(0x1); - UUID mySessionUuid = TestHelpers.ParseTail(0x2); - uint myCircuitCode = 123456; - IPEndPoint testEp = new IPEndPoint(IPAddress.Loopback, 999); - - UseCircuitCodePacket uccp = new UseCircuitCodePacket(); - - UseCircuitCodePacket.CircuitCodeBlock uccpCcBlock - = new UseCircuitCodePacket.CircuitCodeBlock(); - uccpCcBlock.Code = myCircuitCode; - uccpCcBlock.ID = myAgentUuid; - uccpCcBlock.SessionID = mySessionUuid; - uccp.CircuitCode = uccpCcBlock; - - byte[] uccpBytes = uccp.ToBytes(); - UDPPacketBuffer upb = new UDPPacketBuffer(testEp, uccpBytes.Length); - upb.DataLength = uccpBytes.Length; // God knows why this isn't set by the constructor. - Buffer.BlockCopy(uccpBytes, 0, upb.Data, 0, uccpBytes.Length); - - udpServer.PacketReceived(upb); - - // Presence shouldn't exist since the circuit manager doesn't know about this circuit for authentication yet - Assert.That(m_scene.GetScenePresence(myAgentUuid), Is.Null); - - AgentCircuitData acd = new AgentCircuitData(); - acd.AgentID = myAgentUuid; - acd.SessionID = mySessionUuid; - - m_scene.AuthenticateHandler.AddNewCircuit(myCircuitCode, acd); - - udpServer.PacketReceived(upb); - - // Should succeed now - ScenePresence sp = m_scene.GetScenePresence(myAgentUuid); - Assert.That(sp.UUID, Is.EqualTo(myAgentUuid)); - - Assert.That(udpServer.PacketsSent.Count, Is.EqualTo(1)); - - Packet packet = udpServer.PacketsSent[0]; - Assert.That(packet, Is.InstanceOf(typeof(PacketAckPacket))); - - PacketAckPacket ackPacket = packet as PacketAckPacket; - Assert.That(ackPacket.Packets.Length, Is.EqualTo(1)); - Assert.That(ackPacket.Packets[0].ID, Is.EqualTo(0)); - } - - [Test] - public void TestLogoutClientDueToAck() - { - TestHelpers.InMethod(); -// TestHelpers.EnableLogging(); - - IniConfigSource ics = new IniConfigSource(); - IConfig config = ics.AddConfig("ClientStack.LindenUDP"); - config.Set("AckTimeout", -1); - TestLLUDPServer udpServer = ClientStackHelpers.AddUdpServer(m_scene, ics); - - ScenePresence sp - = ClientStackHelpers.AddChildClient( - m_scene, udpServer, TestHelpers.ParseTail(0x1), TestHelpers.ParseTail(0x2), 123456); - - udpServer.ClientOutgoingPacketHandler(sp.ControllingClient, true, false, false); - - ScenePresence spAfterAckTimeout = m_scene.GetScenePresence(sp.UUID); - Assert.That(spAfterAckTimeout, Is.Null); - } -*/ -// /// -// /// Test removing a client from the stack -// /// -// [Test] -// public void TestRemoveClient() -// { -// TestHelper.InMethod(); -// -// uint myCircuitCode = 123457; -// -// TestLLUDPServer testLLUDPServer; -// TestLLPacketServer testLLPacketServer; -// AgentCircuitManager acm; -// SetupStack(new MockScene(), out testLLUDPServer, out testLLPacketServer, out acm); -// AddClient(myCircuitCode, new IPEndPoint(IPAddress.Loopback, 1000), testLLUDPServer, acm); -// -// testLLUDPServer.RemoveClientCircuit(myCircuitCode); -// Assert.IsFalse(testLLUDPServer.HasCircuit(myCircuitCode)); -// -// // Check that removing a non-existent circuit doesn't have any bad effects -// testLLUDPServer.RemoveClientCircuit(101); -// Assert.IsFalse(testLLUDPServer.HasCircuit(101)); -// } -// -// /// -// /// Make sure that the client stack reacts okay to malformed packets -// /// -// [Test] -// public void TestMalformedPacketSend() -// { -// TestHelper.InMethod(); -// -// uint myCircuitCode = 123458; -// EndPoint testEp = new IPEndPoint(IPAddress.Loopback, 1001); -// MockScene scene = new MockScene(); -// -// TestLLUDPServer testLLUDPServer; -// TestLLPacketServer testLLPacketServer; -// AgentCircuitManager acm; -// SetupStack(scene, out testLLUDPServer, out testLLPacketServer, out acm); -// AddClient(myCircuitCode, testEp, testLLUDPServer, acm); -// -// byte[] data = new byte[] { 0x01, 0x02, 0x03, 0x04 }; -// -// // Send two garbled 'packets' in succession -// testLLUDPServer.LoadReceive(data, testEp); -// testLLUDPServer.LoadReceive(data, testEp); -// testLLUDPServer.ReceiveData(null); -// -// // Check that we are still here -// Assert.IsTrue(testLLUDPServer.HasCircuit(myCircuitCode)); -// Assert.That(testLLPacketServer.GetTotalPacketsReceived(), Is.EqualTo(0)); -// -// // Check that sending a valid packet to same circuit still succeeds -// Assert.That(scene.ObjectNameCallsReceived, Is.EqualTo(0)); -// -// testLLUDPServer.LoadReceive(BuildTestObjectNamePacket(1, "helloooo"), testEp); -// testLLUDPServer.ReceiveData(null); -// -// Assert.That(testLLPacketServer.GetTotalPacketsReceived(), Is.EqualTo(1)); -// Assert.That(testLLPacketServer.GetPacketsReceivedFor(PacketType.ObjectName), Is.EqualTo(1)); -// } -// -// /// -// /// Test that the stack continues to work even if some client has caused a -// /// SocketException on Socket.BeginReceive() -// /// -// [Test] -// public void TestExceptionOnBeginReceive() -// { -// TestHelper.InMethod(); -// -// MockScene scene = new MockScene(); -// -// uint circuitCodeA = 130000; -// EndPoint epA = new IPEndPoint(IPAddress.Loopback, 1300); -// UUID agentIdA = UUID.Parse("00000000-0000-0000-0000-000000001300"); -// UUID sessionIdA = UUID.Parse("00000000-0000-0000-0000-000000002300"); -// -// uint circuitCodeB = 130001; -// EndPoint epB = new IPEndPoint(IPAddress.Loopback, 1301); -// UUID agentIdB = UUID.Parse("00000000-0000-0000-0000-000000001301"); -// UUID sessionIdB = UUID.Parse("00000000-0000-0000-0000-000000002301"); -// -// TestLLUDPServer testLLUDPServer; -// TestLLPacketServer testLLPacketServer; -// AgentCircuitManager acm; -// SetupStack(scene, out testLLUDPServer, out testLLPacketServer, out acm); -// AddClient(circuitCodeA, epA, agentIdA, sessionIdA, testLLUDPServer, acm); -// AddClient(circuitCodeB, epB, agentIdB, sessionIdB, testLLUDPServer, acm); -// -// testLLUDPServer.LoadReceive(BuildTestObjectNamePacket(1, "packet1"), epA); -// testLLUDPServer.LoadReceive(BuildTestObjectNamePacket(1, "packet2"), epB); -// testLLUDPServer.LoadReceiveWithBeginException(epA); -// testLLUDPServer.LoadReceive(BuildTestObjectNamePacket(2, "packet3"), epB); -// testLLUDPServer.ReceiveData(null); -// -// Assert.IsFalse(testLLUDPServer.HasCircuit(circuitCodeA)); -// -// Assert.That(testLLPacketServer.GetTotalPacketsReceived(), Is.EqualTo(3)); -// Assert.That(testLLPacketServer.GetPacketsReceivedFor(PacketType.ObjectName), Is.EqualTo(3)); -// } - } -} diff --git a/OpenSim/Region/ClientStack/Linden/UDP/Tests/LLImageManagerTests.cs b/OpenSim/Region/ClientStack/Linden/UDP/Tests/LLImageManagerTests.cs deleted file mode 100644 index 2e8aacefd36..00000000000 --- a/OpenSim/Region/ClientStack/Linden/UDP/Tests/LLImageManagerTests.cs +++ /dev/null @@ -1,174 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.IO; -using System.Net; -using System.Reflection; -using System.Threading; -using log4net.Config; -using Nini.Config; -using NUnit.Framework; -using OpenMetaverse; -using OpenMetaverse.Packets; -using OpenSim.Framework; -using OpenSim.Region.CoreModules.Agent.TextureSender; -using OpenSim.Region.Framework.Scenes; -using OpenSim.Tests.Common; - -namespace OpenSim.Region.ClientStack.LindenUDP.Tests -{ - [TestFixture] - public class LLImageManagerTests : OpenSimTestCase - { - private AssetBase m_testImageAsset; - private Scene scene; - private LLImageManager llim; - private TestClient tc; - - [OneTimeSetUp] - public void FixtureInit() - { - // Don't allow tests to be bamboozled by asynchronous events. Execute everything on the same thread. - Util.FireAndForgetMethod = FireAndForgetMethod.None; - - using ( - Stream resource - = GetType().Assembly.GetManifestResourceStream( - "OpenSim.Region.ClientStack.LindenUDP.Tests.Resources.4-tile2.jp2")) - { - using (BinaryReader br = new BinaryReader(resource)) - { - m_testImageAsset - = new AssetBase( - TestHelpers.ParseTail(0x1), - "Test Image", - (sbyte)AssetType.Texture, - TestHelpers.ParseTail(0x2).ToString()); - - m_testImageAsset.Data = br.ReadBytes(99999999); - } - } - } - - [OneTimeTearDown] - public void TearDown() - { - // We must set this back afterwards, otherwise later tests will fail since they're expecting multiple - // threads. Possibly, later tests should be rewritten not to worry about such things. - Util.FireAndForgetMethod = Util.DefaultFireAndForgetMethod; - } - - [SetUp] - public override void SetUp() - { - base.SetUp(); - - UUID userId = TestHelpers.ParseTail(0x3); - - J2KDecoderModule j2kdm = new J2KDecoderModule(); - - SceneHelpers sceneHelpers = new SceneHelpers(); - scene = sceneHelpers.SetupScene(); - SceneHelpers.SetupSceneModules(scene, j2kdm); - - tc = new TestClient(SceneHelpers.GenerateAgentData(userId), scene); - llim = new LLImageManager(tc, scene.AssetService, j2kdm); - } - - [Test] - public void TestSendImage() - { - TestHelpers.InMethod(); -// XmlConfigurator.Configure(); - - scene.AssetService.Store(m_testImageAsset); - - TextureRequestArgs args = new TextureRequestArgs(); - args.RequestedAssetID = m_testImageAsset.FullID; - args.DiscardLevel = 0; - args.PacketNumber = 1; - args.Priority = 5; - args.requestSequence = 1; - - llim.EnqueueReq(args); - llim.ProcessImageQueue(20); - - Assert.That(tc.SentImageDataPackets.Count, Is.EqualTo(1)); - } - - [Test] - public void TestDiscardImage() - { - TestHelpers.InMethod(); -// XmlConfigurator.Configure(); - - scene.AssetService.Store(m_testImageAsset); - - TextureRequestArgs args = new TextureRequestArgs(); - args.RequestedAssetID = m_testImageAsset.FullID; - args.DiscardLevel = 0; - args.PacketNumber = 1; - args.Priority = 5; - args.requestSequence = 1; - llim.EnqueueReq(args); - - // Now create a discard request - TextureRequestArgs discardArgs = new TextureRequestArgs(); - discardArgs.RequestedAssetID = m_testImageAsset.FullID; - discardArgs.DiscardLevel = -1; - discardArgs.PacketNumber = 1; - discardArgs.Priority = 0; - discardArgs.requestSequence = 2; - llim.EnqueueReq(discardArgs); - - llim.ProcessImageQueue(20); - - Assert.That(tc.SentImageDataPackets.Count, Is.EqualTo(0)); - } - - [Test] - public void TestMissingImage() - { - TestHelpers.InMethod(); -// XmlConfigurator.Configure(); - - TextureRequestArgs args = new TextureRequestArgs(); - args.RequestedAssetID = m_testImageAsset.FullID; - args.DiscardLevel = 0; - args.PacketNumber = 1; - args.Priority = 5; - args.requestSequence = 1; - - llim.EnqueueReq(args); - llim.ProcessImageQueue(20); - - Assert.That(tc.SentImageDataPackets.Count, Is.EqualTo(0)); - Assert.That(tc.SentImageNotInDatabasePackets.Count, Is.EqualTo(1)); - } - } -} \ No newline at end of file diff --git a/OpenSim/Region/ClientStack/Linden/UDP/Tests/OpenSim.Region.ClientStack.LindenUDP.Tests.csproj b/OpenSim/Region/ClientStack/Linden/UDP/Tests/OpenSim.Region.ClientStack.LindenUDP.Tests.csproj deleted file mode 100644 index 7a8310a3ab6..00000000000 --- a/OpenSim/Region/ClientStack/Linden/UDP/Tests/OpenSim.Region.ClientStack.LindenUDP.Tests.csproj +++ /dev/null @@ -1,36 +0,0 @@ - - - net8.0 - - - - ..\..\..\..\..\..\bin\Nini.dll - False - - - ..\..\..\..\..\..\bin\OpenMetaverse.dll - False - - - ..\..\..\..\..\..\bin\OpenMetaverseTypes.dll - False - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/OpenSim/Region/ClientStack/Linden/UDP/Tests/PacketHandlerTests.cs b/OpenSim/Region/ClientStack/Linden/UDP/Tests/PacketHandlerTests.cs deleted file mode 100644 index 1731aa97b04..00000000000 --- a/OpenSim/Region/ClientStack/Linden/UDP/Tests/PacketHandlerTests.cs +++ /dev/null @@ -1,104 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using Nini.Config; -using NUnit.Framework; -using OpenMetaverse; -using OpenMetaverse.Packets; -using OpenSim.Framework; -using OpenSim.Tests.Common; - -namespace OpenSim.Region.ClientStack.LindenUDP.Tests -{ - /// - /// Tests for the LL packet handler - /// - [TestFixture] - public class PacketHandlerTests : OpenSimTestCase - { -// [Test] -// /// -// /// More a placeholder, really -// /// -// public void InPacketTest() -// { -// TestHelper.InMethod(); -// -// AgentCircuitData agent = new AgentCircuitData(); -// agent.AgentID = UUID.Random(); -// agent.firstname = "testfirstname"; -// agent.lastname = "testlastname"; -// agent.SessionID = UUID.Zero; -// agent.SecureSessionID = UUID.Zero; -// agent.circuitcode = 123; -// agent.BaseFolder = UUID.Zero; -// agent.InventoryFolder = UUID.Zero; -// agent.startpos = Vector3.Zero; -// agent.CapsPath = "http://wibble.com"; -// -// TestLLUDPServer testLLUDPServer; -// TestLLPacketServer testLLPacketServer; -// AgentCircuitManager acm; -// IScene scene = new MockScene(); -// SetupStack(scene, out testLLUDPServer, out testLLPacketServer, out acm); -// -// TestClient testClient = new TestClient(agent, scene); -// -// LLPacketHandler packetHandler -// = new LLPacketHandler(testClient, testLLPacketServer, new ClientStackUserSettings()); -// -// packetHandler.InPacket(new AgentAnimationPacket()); -// LLQueItem receivedPacket = packetHandler.PacketQueue.Dequeue(); -// -// Assert.That(receivedPacket, Is.Not.Null); -// Assert.That(receivedPacket.Incoming, Is.True); -// Assert.That(receivedPacket.Packet, Is.TypeOf(typeof(AgentAnimationPacket))); -// } -// -// /// -// /// Add a client for testing -// /// -// /// -// /// -// /// -// /// Agent circuit manager used in setting up the stack -// protected void SetupStack( -// IScene scene, out TestLLUDPServer testLLUDPServer, out TestLLPacketServer testPacketServer, -// out AgentCircuitManager acm) -// { -// IConfigSource configSource = new IniConfigSource(); -// ClientStackUserSettings userSettings = new ClientStackUserSettings(); -// testLLUDPServer = new TestLLUDPServer(); -// acm = new AgentCircuitManager(); -// -// uint port = 666; -// testLLUDPServer.Initialise(null, ref port, 0, false, configSource, acm); -// testPacketServer = new TestLLPacketServer(testLLUDPServer, userSettings); -// testLLUDPServer.LocalScene = scene; -// } - } -} diff --git a/OpenSim/Region/ClientStack/Linden/UDP/Tests/Resources/4-tile2.jp2 b/OpenSim/Region/ClientStack/Linden/UDP/Tests/Resources/4-tile2.jp2 deleted file mode 100644 index 8c631046e877a1532c045abc845ab23fb9f78557..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 24410 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 h=nDeX#3 - /// Test throttle setttings where max client throttle has been limited server side. - /// - [Test] - public void TestSingleClientThrottleRegionLimited() - { - TestHelpers.InMethod(); - // TestHelpers.EnableLogging(); - - int resendBytes = 6000; - int landBytes = 8000; - int windBytes = 10000; - int cloudBytes = 12000; - int taskBytes = 14000; - int textureBytes = 16000; - int assetBytes = 18000; - int totalBytes - = (int)((resendBytes + landBytes + windBytes + cloudBytes + taskBytes + textureBytes + assetBytes) / 2); - - Scene scene = new SceneHelpers().SetupScene(); - TestLLUDPServer udpServer = ClientStackHelpers.AddUdpServer(scene); - udpServer.Throttle.RequestedDripRate = totalBytes; - - ScenePresence sp1 - = ClientStackHelpers.AddChildClient( - scene, udpServer, TestHelpers.ParseTail(0x1), TestHelpers.ParseTail(0x2), 123456); - - LLUDPClient udpClient1 = ((LLClientView)sp1.ControllingClient).UDPClient; - - SetThrottles( - udpClient1, resendBytes, landBytes, windBytes, cloudBytes, taskBytes, textureBytes, assetBytes); - - AssertThrottles( - udpClient1, - resendBytes / 2, landBytes / 2, windBytes / 2, cloudBytes / 2, taskBytes / 2, - textureBytes / 2, assetBytes / 2, totalBytes, 0, 0); - - // Test: Now add another client - ScenePresence sp2 - = ClientStackHelpers.AddChildClient( - scene, udpServer, TestHelpers.ParseTail(0x10), TestHelpers.ParseTail(0x20), 123457); - - LLUDPClient udpClient2 = ((LLClientView)sp2.ControllingClient).UDPClient; - // udpClient.ThrottleDebugLevel = 1; - - SetThrottles( - udpClient2, resendBytes, landBytes, windBytes, cloudBytes, taskBytes, textureBytes, assetBytes); - - AssertThrottles( - udpClient1, - resendBytes / 4, landBytes / 4, windBytes / 4, cloudBytes / 4, taskBytes / 4, - textureBytes / 4, assetBytes / 4, totalBytes / 2, 0, 0); - - AssertThrottles( - udpClient2, - resendBytes / 4, landBytes / 4, windBytes / 4, cloudBytes / 4, taskBytes / 4, - textureBytes / 4, assetBytes / 4, totalBytes / 2, 0, 0); - } - - /// - /// Test throttle setttings where max client throttle has been limited server side. - /// - [Test] - public void TestClientThrottlePerClientLimited() - { - TestHelpers.InMethod(); - // TestHelpers.EnableLogging(); - - int resendBytes = 4000; - int landBytes = 6000; - int windBytes = 8000; - int cloudBytes = 10000; - int taskBytes = 12000; - int textureBytes = 14000; - int assetBytes = 16000; - int totalBytes - = (int)((resendBytes + landBytes + windBytes + cloudBytes + taskBytes + textureBytes + assetBytes) / 2); - - Scene scene = new SceneHelpers().SetupScene(); - TestLLUDPServer udpServer = ClientStackHelpers.AddUdpServer(scene); - udpServer.ThrottleRates.Total = totalBytes; - - ScenePresence sp - = ClientStackHelpers.AddChildClient( - scene, udpServer, TestHelpers.ParseTail(0x1), TestHelpers.ParseTail(0x2), 123456); - - LLUDPClient udpClient = ((LLClientView)sp.ControllingClient).UDPClient; - // udpClient.ThrottleDebugLevel = 1; - - SetThrottles( - udpClient, resendBytes, landBytes, windBytes, cloudBytes, taskBytes, textureBytes, assetBytes); - - AssertThrottles( - udpClient, - resendBytes / 2, landBytes / 2, windBytes / 2, cloudBytes / 2, taskBytes / 2, - textureBytes / 2, assetBytes / 2, totalBytes, 0, totalBytes); - } - - [Test] - public void TestClientThrottlePerClientAndRegionLimited() - { - TestHelpers.InMethod(); - //TestHelpers.EnableLogging(); - - int resendBytes = 4000; - int landBytes = 6000; - int windBytes = 8000; - int cloudBytes = 10000; - int taskBytes = 12000; - int textureBytes = 14000; - int assetBytes = 16000; - - // current total 70000 - int totalBytes = resendBytes + landBytes + windBytes + cloudBytes + taskBytes + textureBytes + assetBytes; - - Scene scene = new SceneHelpers().SetupScene(); - TestLLUDPServer udpServer = ClientStackHelpers.AddUdpServer(scene); - udpServer.ThrottleRates.Total = (int)(totalBytes * 1.1); - udpServer.Throttle.RequestedDripRate = (int)(totalBytes * 1.5); - - ScenePresence sp1 - = ClientStackHelpers.AddChildClient( - scene, udpServer, TestHelpers.ParseTail(0x1), TestHelpers.ParseTail(0x2), 123456); - - LLUDPClient udpClient1 = ((LLClientView)sp1.ControllingClient).UDPClient; - udpClient1.ThrottleDebugLevel = 1; - - SetThrottles( - udpClient1, resendBytes, landBytes, windBytes, cloudBytes, taskBytes, textureBytes, assetBytes); - - AssertThrottles( - udpClient1, - resendBytes, landBytes, windBytes, cloudBytes, taskBytes, - textureBytes, assetBytes, totalBytes, 0, totalBytes * 1.1); - - // Now add another client - ScenePresence sp2 - = ClientStackHelpers.AddChildClient( - scene, udpServer, TestHelpers.ParseTail(0x10), TestHelpers.ParseTail(0x20), 123457); - - LLUDPClient udpClient2 = ((LLClientView)sp2.ControllingClient).UDPClient; - udpClient2.ThrottleDebugLevel = 1; - - SetThrottles( - udpClient2, resendBytes, landBytes, windBytes, cloudBytes, taskBytes, textureBytes, assetBytes); - - AssertThrottles( - udpClient1, - resendBytes * 0.75, landBytes * 0.75, windBytes * 0.75, cloudBytes * 0.75, taskBytes * 0.75, - textureBytes * 0.75, assetBytes * 0.75, totalBytes * 0.75, 0, totalBytes * 1.1); - - AssertThrottles( - udpClient2, - resendBytes * 0.75, landBytes * 0.75, windBytes * 0.75, cloudBytes * 0.75, taskBytes * 0.75, - textureBytes * 0.75, assetBytes * 0.75, totalBytes * 0.75, 0, totalBytes * 1.1); - } - - private void AssertThrottles( - LLUDPClient udpClient, - double resendBytes, double landBytes, double windBytes, double cloudBytes, double taskBytes, double textureBytes, double assetBytes, - double totalBytes, double targetBytes, double maxBytes) - { - ClientInfo ci = udpClient.GetClientInfo(); - -// Console.WriteLine( -// "Resend={0}, Land={1}, Wind={2}, Cloud={3}, Task={4}, Texture={5}, Asset={6}, TOTAL = {7}", -// ci.resendThrottle, ci.landThrottle, ci.windThrottle, ci.cloudThrottle, ci.taskThrottle, ci.textureThrottle, ci.assetThrottle, ci.totalThrottle); - - Assert.AreEqual((int)resendBytes, ci.resendThrottle, "Resend"); - Assert.AreEqual((int)landBytes, ci.landThrottle, "Land"); - Assert.AreEqual((int)windBytes, ci.windThrottle, "Wind"); - Assert.AreEqual((int)cloudBytes, ci.cloudThrottle, "Cloud"); - Assert.AreEqual((int)taskBytes, ci.taskThrottle, "Task"); - Assert.AreEqual((int)textureBytes, ci.textureThrottle, "Texture"); - Assert.AreEqual((int)assetBytes, ci.assetThrottle, "Asset"); - Assert.AreEqual((int)totalBytes, ci.totalThrottle, "Total"); - Assert.AreEqual((int)targetBytes, ci.targetThrottle, "Target"); - Assert.AreEqual((int)maxBytes, ci.maxThrottle, "Max"); - } - - private void SetThrottles( - LLUDPClient udpClient, int resendBytes, int landBytes, int windBytes, int cloudBytes, int taskBytes, int textureBytes, int assetBytes) - { - byte[] throttles = new byte[28]; - - Array.Copy(BitConverter.GetBytes((float)resendBytes * 8), 0, throttles, 0, 4); - Array.Copy(BitConverter.GetBytes((float)landBytes * 8), 0, throttles, 4, 4); - Array.Copy(BitConverter.GetBytes((float)windBytes * 8), 0, throttles, 8, 4); - Array.Copy(BitConverter.GetBytes((float)cloudBytes * 8), 0, throttles, 12, 4); - Array.Copy(BitConverter.GetBytes((float)taskBytes * 8), 0, throttles, 16, 4); - Array.Copy(BitConverter.GetBytes((float)textureBytes * 8), 0, throttles, 20, 4); - Array.Copy(BitConverter.GetBytes((float)assetBytes * 8), 0, throttles, 24, 4); - - udpClient.SetThrottles(throttles); - } - } - */ -} \ No newline at end of file diff --git a/OpenSim/Region/CoreModules/Asset/Tests/FlotsamAssetCacheTests.cs b/OpenSim/Region/CoreModules/Asset/Tests/FlotsamAssetCacheTests.cs deleted file mode 100644 index dbb794142e6..00000000000 --- a/OpenSim/Region/CoreModules/Asset/Tests/FlotsamAssetCacheTests.cs +++ /dev/null @@ -1,127 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections.Generic; -using System.IO; -using System.Reflection; -using System.Threading; -using log4net.Config; -using Nini.Config; -using NUnit.Framework; -using OpenMetaverse; -using OpenMetaverse.Assets; -using OpenSim.Framework; -using OpenSim.Region.Framework.Scenes; -using OpenSim.Region.Framework.Scenes.Serialization; -using OpenSim.Tests.Common; - -namespace OpenSim.Region.CoreModules.Asset.Tests -{ - /// - /// At the moment we're only test the in-memory part of the FlotsamAssetCache. This is a considerable weakness. - /// - [TestFixture] - public class FlotsamAssetCacheTests : OpenSimTestCase - { - protected TestScene m_scene; - protected FlotsamAssetCache m_cache; - - [SetUp] - public override void SetUp() - { - base.SetUp(); - - IConfigSource config = new IniConfigSource(); - - config.AddConfig("Modules"); - config.Configs["Modules"].Set("AssetCaching", "FlotsamAssetCache"); - config.AddConfig("AssetCache"); - config.Configs["AssetCache"].Set("FileCacheEnabled", "false"); - config.Configs["AssetCache"].Set("MemoryCacheEnabled", "true"); - - m_cache = new FlotsamAssetCache(); - m_scene = new SceneHelpers().SetupScene(); - SceneHelpers.SetupSceneModules(m_scene, config, m_cache); - } - - [Test] - public void TestCacheAsset() - { - TestHelpers.InMethod(); -// log4net.Config.XmlConfigurator.Configure(); - - AssetBase asset = AssetHelpers.CreateNotecardAsset(); - asset.ID = TestHelpers.ParseTail(0x1).ToString(); - - // Check we don't get anything before the asset is put in the cache - AssetBase retrievedAsset = m_cache.Get(asset.ID.ToString()); - Assert.That(retrievedAsset, Is.Null); - - m_cache.Store(asset); - - // Check that asset is now in cache - retrievedAsset = m_cache.Get(asset.ID.ToString()); - Assert.That(retrievedAsset, Is.Not.Null); - Assert.That(retrievedAsset.ID, Is.EqualTo(asset.ID)); - } - - [Test] - public void TestExpireAsset() - { - TestHelpers.InMethod(); -// log4net.Config.XmlConfigurator.Configure(); - - AssetBase asset = AssetHelpers.CreateNotecardAsset(); - asset.ID = TestHelpers.ParseTail(0x2).ToString(); - - m_cache.Store(asset); - - m_cache.Expire(asset.ID); - - AssetBase retrievedAsset = m_cache.Get(asset.ID.ToString()); - Assert.That(retrievedAsset, Is.Null); - } - - [Test] - public void TestClearCache() - { - TestHelpers.InMethod(); -// log4net.Config.XmlConfigurator.Configure(); - - AssetBase asset = AssetHelpers.CreateNotecardAsset(); - asset.ID = TestHelpers.ParseTail(0x2).ToString(); - - m_cache.Store(asset); - - m_cache.Clear(); - - AssetBase retrievedAsset = m_cache.Get(asset.ID.ToString()); - Assert.That(retrievedAsset, Is.Null); - } - } -} \ No newline at end of file diff --git a/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs b/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs deleted file mode 100644 index 941853c947a..00000000000 --- a/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs +++ /dev/null @@ -1,1030 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections.Generic; -using System.Reflection; -using System.Text; -using System.Threading; -using System.Timers; -using System.Xml; -using Timer=System.Timers.Timer; -using Nini.Config; -using NUnit.Framework; -using OpenMetaverse; -using OpenSim.Framework; -using OpenSim.Framework.Servers; -using OpenSim.Framework.Servers.HttpServer; -using OpenSim.Region.CoreModules.Avatar.Attachments; -using OpenSim.Region.CoreModules.Framework; -using OpenSim.Region.CoreModules.Framework.EntityTransfer; -using OpenSim.Region.CoreModules.Framework.InventoryAccess; -using OpenSim.Region.CoreModules.Scripting.WorldComm; -using OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation; -using OpenSim.Region.CoreModules.World.Serialiser; -using OpenSim.Region.Framework.Scenes; -using OpenSim.Region.Framework.Interfaces; -using OpenSim.Region.ScriptEngine.Interfaces; -using OpenSim.Region.ScriptEngine.XEngine; -using OpenSim.Services.Interfaces; -using OpenSim.Tests.Common; - -namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests -{ -/* - /// - /// Attachment tests - /// - [TestFixture] - public class AttachmentsModuleTests : OpenSimTestCase - { - private AutoResetEvent m_chatEvent = new AutoResetEvent(false); -// private OSChatMessage m_osChatMessageReceived; - - // Used to test whether the operations have fired the attach event. Must be reset after each test. - private int m_numberOfAttachEventsFired; - - [TestFixtureSetUp] - public void FixtureInit() - { - // Don't allow tests to be bamboozled by asynchronous events. Execute everything on the same thread. - Util.FireAndForgetMethod = FireAndForgetMethod.None; - } - - [TestFixtureTearDown] - public void TearDown() - { - // We must set this back afterwards, otherwise later tests will fail since they're expecting multiple - // threads. Possibly, later tests should be rewritten not to worry about such things. - Util.FireAndForgetMethod = Util.DefaultFireAndForgetMethod; - } - - private void OnChatFromWorld(object sender, OSChatMessage oscm) - { -// Console.WriteLine("Got chat [{0}]", oscm.Message); - -// m_osChatMessageReceived = oscm; - m_chatEvent.Set(); - } - - private Scene CreateTestScene() - { - IConfigSource config = new IniConfigSource(); - List modules = new List(); - - AddCommonConfig(config, modules); - - Scene scene - = new SceneHelpers().SetupScene( - "attachments-test-scene", TestHelpers.ParseTail(999), 1000, 1000, config); - SceneHelpers.SetupSceneModules(scene, config, modules.ToArray()); - - scene.EventManager.OnAttach += (localID, itemID, avatarID) => m_numberOfAttachEventsFired++; - - return scene; - } - - private Scene CreateScriptingEnabledTestScene() - { - IConfigSource config = new IniConfigSource(); - List modules = new List(); - - AddCommonConfig(config, modules); - AddScriptingConfig(config, modules); - - Scene scene - = new SceneHelpers().SetupScene( - "attachments-test-scene", TestHelpers.ParseTail(999), 1000, 1000, config); - SceneHelpers.SetupSceneModules(scene, config, modules.ToArray()); - - scene.StartScripts(); - - return scene; - } - - private void AddCommonConfig(IConfigSource config, List modules) - { - config.AddConfig("Modules"); - config.Configs["Modules"].Set("InventoryAccessModule", "BasicInventoryAccessModule"); - - AttachmentsModule attMod = new AttachmentsModule(); - attMod.DebugLevel = 1; - modules.Add(attMod); - modules.Add(new BasicInventoryAccessModule()); - } - - private void AddScriptingConfig(IConfigSource config, List modules) - { - IConfig startupConfig = config.AddConfig("Startup"); - startupConfig.Set("DefaultScriptEngine", "XEngine"); - - IConfig xEngineConfig = config.AddConfig("XEngine"); - xEngineConfig.Set("Enabled", "true"); - xEngineConfig.Set("StartDelay", "0"); - - // These tests will not run with AppDomainLoading = true, at least on mono. For unknown reasons, the call - // to AssemblyResolver.OnAssemblyResolve fails. - xEngineConfig.Set("AppDomainLoading", "false"); - - modules.Add(new XEngine()); - - // Necessary to stop serialization complaining - // FIXME: Stop this being necessary if at all possible -// modules.Add(new WorldCommModule()); - } - - /// - /// Creates an attachment item in the given user's inventory. Does not attach. - /// - /// - /// A user with the given ID and an inventory must already exist. - /// - /// - /// The attachment item. - /// - /// - /// - /// - /// - /// - private InventoryItemBase CreateAttachmentItem( - Scene scene, UUID userId, string attName, int rawItemId, int rawAssetId) - { - return UserInventoryHelpers.CreateInventoryItem( - scene, - attName, - TestHelpers.ParseTail(rawItemId), - TestHelpers.ParseTail(rawAssetId), - userId, - InventoryType.Object); - } - - [Test] - public void TestAddAttachmentFromGround() - { - TestHelpers.InMethod(); -// TestHelpers.EnableLogging(); - - m_numberOfAttachEventsFired = 0; - - Scene scene = CreateTestScene(); - UserAccount ua1 = UserAccountHelpers.CreateUserWithInventory(scene, 0x1); - ScenePresence sp = SceneHelpers.AddScenePresence(scene, ua1); - - string attName = "att"; - - SceneObjectGroup so = SceneHelpers.AddSceneObject(scene, attName, sp.UUID); - Assert.That(so.Backup, Is.True); - - m_numberOfAttachEventsFired = 0; - scene.AttachmentsModule.AttachObject(sp, so, (uint)AttachmentPoint.Chest, false, true, false); - - // Check status on scene presence - Assert.That(sp.HasAttachments(), Is.True); - List attachments = sp.GetAttachments(); - Assert.That(attachments.Count, Is.EqualTo(1)); - SceneObjectGroup attSo = attachments[0]; - Assert.That(attSo.Name, Is.EqualTo(attName)); - Assert.That(attSo.AttachmentPoint, Is.EqualTo((byte)AttachmentPoint.Chest)); - Assert.That(attSo.IsAttachment); - Assert.That(attSo.UsesPhysics, Is.False); - Assert.That(attSo.IsTemporary, Is.False); - Assert.That(attSo.Backup, Is.False); - - // Check item status -// Assert.That( -// sp.Appearance.GetAttachpoint(attSo.FromItemID), -// Is.EqualTo((int)AttachmentPoint.Chest)); - - InventoryItemBase attachmentItem = scene.InventoryService.GetItem(sp.UUID, attSo.FromItemID); - Assert.That(attachmentItem, Is.Not.Null); - Assert.That(attachmentItem.Name, Is.EqualTo(attName)); - - InventoryFolderBase targetFolder = scene.InventoryService.GetFolderForType(sp.UUID, FolderType.Object); - Assert.That(attachmentItem.Folder, Is.EqualTo(targetFolder.ID)); - - Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(1)); - - // Check events - Assert.That(m_numberOfAttachEventsFired, Is.EqualTo(1)); - } - - [Test] - public void TestWearAttachmentFromGround() - { - TestHelpers.InMethod(); -// TestHelpers.EnableLogging(); - - Scene scene = CreateTestScene(); - UserAccount ua1 = UserAccountHelpers.CreateUserWithInventory(scene, 0x1); - ScenePresence sp = SceneHelpers.AddScenePresence(scene, ua1); - - SceneObjectGroup so2 = SceneHelpers.AddSceneObject(scene, "att2", sp.UUID); - - { - SceneObjectGroup so = SceneHelpers.AddSceneObject(scene, "att1", sp.UUID); - - m_numberOfAttachEventsFired = 0; - scene.AttachmentsModule.AttachObject(sp, so, (uint)AttachmentPoint.Default, false, true, false); - - // Check status on scene presence - Assert.That(sp.HasAttachments(), Is.True); - List attachments = sp.GetAttachments(); - Assert.That(attachments.Count, Is.EqualTo(1)); - SceneObjectGroup attSo = attachments[0]; - Assert.That(attSo.Name, Is.EqualTo(so.Name)); - Assert.That(attSo.AttachmentPoint, Is.EqualTo((byte)AttachmentPoint.LeftHand)); - Assert.That(attSo.IsAttachment); - Assert.That(attSo.UsesPhysics, Is.False); - Assert.That(attSo.IsTemporary, Is.False); - - // Check item status -// Assert.That( -// sp.Appearance.GetAttachpoint(attSo.FromItemID), -// Is.EqualTo((int)AttachmentPoint.LeftHand)); - - InventoryItemBase attachmentItem = scene.InventoryService.GetItem(sp.UUID, attSo.FromItemID); - Assert.That(attachmentItem, Is.Not.Null); - Assert.That(attachmentItem.Name, Is.EqualTo(so.Name)); - - InventoryFolderBase targetFolder = scene.InventoryService.GetFolderForType(sp.UUID, FolderType.Object); - Assert.That(attachmentItem.Folder, Is.EqualTo(targetFolder.ID)); - - Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(2)); - - // Check events - Assert.That(m_numberOfAttachEventsFired, Is.EqualTo(1)); - } - - // Test wearing a different attachment from the ground. - { - scene.AttachmentsModule.AttachObject(sp, so2, (uint)AttachmentPoint.Default, false, true, false); - - // Check status on scene presence - Assert.That(sp.HasAttachments(), Is.True); - List attachments = sp.GetAttachments(); - Assert.That(attachments.Count, Is.EqualTo(1)); - SceneObjectGroup attSo = attachments[0]; - Assert.That(attSo.Name, Is.EqualTo(so2.Name)); - Assert.That(attSo.AttachmentPoint, Is.EqualTo((byte)AttachmentPoint.LeftHand)); - Assert.That(attSo.IsAttachment); - Assert.That(attSo.UsesPhysics, Is.False); - Assert.That(attSo.IsTemporary, Is.False); - - // Check item status -// Assert.That( -// sp.Appearance.GetAttachpoint(attSo.FromItemID), -// Is.EqualTo((int)AttachmentPoint.LeftHand)); - - InventoryItemBase attachmentItem = scene.InventoryService.GetItem(sp.UUID, attSo.FromItemID); - Assert.That(attachmentItem, Is.Not.Null); - Assert.That(attachmentItem.Name, Is.EqualTo(so2.Name)); - - InventoryFolderBase targetFolder = scene.InventoryService.GetFolderForType(sp.UUID, FolderType.Object); - Assert.That(attachmentItem.Folder, Is.EqualTo(targetFolder.ID)); - - Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(1)); - - // Check events - Assert.That(m_numberOfAttachEventsFired, Is.EqualTo(3)); - } - - // Test rewearing an already worn attachment from ground. Nothing should happen. - { - scene.AttachmentsModule.AttachObject(sp, so2, (uint)AttachmentPoint.Default, false, true, false); - - // Check status on scene presence - Assert.That(sp.HasAttachments(), Is.True); - List attachments = sp.GetAttachments(); - Assert.That(attachments.Count, Is.EqualTo(1)); - SceneObjectGroup attSo = attachments[0]; - Assert.That(attSo.Name, Is.EqualTo(so2.Name)); - Assert.That(attSo.AttachmentPoint, Is.EqualTo((byte)AttachmentPoint.LeftHand)); - Assert.That(attSo.IsAttachment); - Assert.That(attSo.UsesPhysics, Is.False); - Assert.That(attSo.IsTemporary, Is.False); - - // Check item status -// Assert.That( -// sp.Appearance.GetAttachpoint(attSo.FromItemID), -// Is.EqualTo((int)AttachmentPoint.LeftHand)); - - InventoryItemBase attachmentItem = scene.InventoryService.GetItem(sp.UUID, attSo.FromItemID); - Assert.That(attachmentItem, Is.Not.Null); - Assert.That(attachmentItem.Name, Is.EqualTo(so2.Name)); - - InventoryFolderBase targetFolder = scene.InventoryService.GetFolderForType(sp.UUID, FolderType.Object); - Assert.That(attachmentItem.Folder, Is.EqualTo(targetFolder.ID)); - - Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(1)); - - // Check events - Assert.That(m_numberOfAttachEventsFired, Is.EqualTo(3)); - } - } - - /// - /// Test that we do not attempt to attach an in-world object that someone else is sitting on. - /// - [Test] - public void TestAddSatOnAttachmentFromGround() - { - TestHelpers.InMethod(); -// TestHelpers.EnableLogging(); - - m_numberOfAttachEventsFired = 0; - - Scene scene = CreateTestScene(); - UserAccount ua1 = UserAccountHelpers.CreateUserWithInventory(scene, 0x1); - ScenePresence sp = SceneHelpers.AddScenePresence(scene, ua1); - - string attName = "att"; - - SceneObjectGroup so = SceneHelpers.AddSceneObject(scene, attName, sp.UUID); - - UserAccount ua2 = UserAccountHelpers.CreateUserWithInventory(scene, 0x2); - ScenePresence sp2 = SceneHelpers.AddScenePresence(scene, ua2); - - // Put avatar within 10m of the prim so that sit doesn't fail. - sp2.AbsolutePosition = new Vector3(0, 0, 0); - sp2.HandleAgentRequestSit(sp2.ControllingClient, sp2.UUID, so.UUID, Vector3.Zero); - - scene.AttachmentsModule.AttachObject(sp, so, (uint)AttachmentPoint.Chest, false, true, false); - - Assert.That(sp.HasAttachments(), Is.False); - Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(1)); - - // Check events - Assert.That(m_numberOfAttachEventsFired, Is.EqualTo(0)); - } - - [Test] - public void TestRezAttachmentFromInventory() - { - TestHelpers.InMethod(); -// TestHelpers.EnableLogging(); - - Scene scene = CreateTestScene(); - UserAccount ua1 = UserAccountHelpers.CreateUserWithInventory(scene, 0x1); - ScenePresence sp = SceneHelpers.AddScenePresence(scene, ua1.PrincipalID); - - InventoryItemBase attItem = CreateAttachmentItem(scene, ua1.PrincipalID, "att", 0x10, 0x20); - - { - scene.AttachmentsModule.RezSingleAttachmentFromInventory( - sp, attItem.ID, (uint)AttachmentPoint.Chest); - - // Check scene presence status - Assert.That(sp.HasAttachments(), Is.True); - List attachments = sp.GetAttachments(); - Assert.That(attachments.Count, Is.EqualTo(1)); - SceneObjectGroup attSo = attachments[0]; - Assert.That(attSo.Name, Is.EqualTo(attItem.Name)); - Assert.That(attSo.AttachmentPoint, Is.EqualTo((byte)AttachmentPoint.Chest)); - Assert.That(attSo.IsAttachment); - Assert.That(attSo.UsesPhysics, Is.False); - Assert.That(attSo.IsTemporary, Is.False); - Assert.IsFalse(attSo.Backup); - - // Check appearance status -// Assert.That(sp.Appearance.GetAttachments().Count, Is.EqualTo(1)); -// Assert.That(sp.Appearance.GetAttachpoint(attItem.ID), Is.EqualTo((int)AttachmentPoint.Chest)); - Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(1)); - - // Check events - Assert.That(m_numberOfAttachEventsFired, Is.EqualTo(1)); - } - - // Test attaching an already attached attachment - { - scene.AttachmentsModule.RezSingleAttachmentFromInventory( - sp, attItem.ID, (uint)AttachmentPoint.Chest); - - // Check scene presence status - Assert.That(sp.HasAttachments(), Is.True); - List attachments = sp.GetAttachments(); - Assert.That(attachments.Count, Is.EqualTo(1)); - SceneObjectGroup attSo = attachments[0]; - Assert.That(attSo.Name, Is.EqualTo(attItem.Name)); - Assert.That(attSo.AttachmentPoint, Is.EqualTo((byte)AttachmentPoint.Chest)); - Assert.That(attSo.IsAttachment); - Assert.That(attSo.UsesPhysics, Is.False); - Assert.That(attSo.IsTemporary, Is.False); - - // Check appearance status -// Assert.That(sp.Appearance.GetAttachments().Count, Is.EqualTo(1)); -// Assert.That(sp.Appearance.GetAttachpoint(attItem.ID), Is.EqualTo((int)AttachmentPoint.Chest)); - Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(1)); - - // Check events - Assert.That(m_numberOfAttachEventsFired, Is.EqualTo(1)); - } - } - - /// - /// Test wearing an attachment from inventory, as opposed to explicit choosing the rez point - /// - [Test] - public void TestWearAttachmentFromInventory() - { - TestHelpers.InMethod(); -// TestHelpers.EnableLogging(); - - Scene scene = CreateTestScene(); - UserAccount ua1 = UserAccountHelpers.CreateUserWithInventory(scene, 0x1); - ScenePresence sp = SceneHelpers.AddScenePresence(scene, ua1.PrincipalID); - - InventoryItemBase attItem1 = CreateAttachmentItem(scene, ua1.PrincipalID, "att1", 0x10, 0x20); - InventoryItemBase attItem2 = CreateAttachmentItem(scene, ua1.PrincipalID, "att2", 0x11, 0x21); - - { - m_numberOfAttachEventsFired = 0; - scene.AttachmentsModule.RezSingleAttachmentFromInventory(sp, attItem1.ID, (uint)AttachmentPoint.Default); - - // default attachment point is currently the left hand. - Assert.That(sp.HasAttachments(), Is.True); - List attachments = sp.GetAttachments(); - Assert.That(attachments.Count, Is.EqualTo(1)); - SceneObjectGroup attSo = attachments[0]; - Assert.That(attSo.Name, Is.EqualTo(attItem1.Name)); - Assert.That(attSo.AttachmentPoint, Is.EqualTo((byte)AttachmentPoint.LeftHand)); - Assert.That(attSo.IsAttachment); - - // Check appearance status -// Assert.That(sp.Appearance.GetAttachments().Count, Is.EqualTo(1)); -// Assert.That(sp.Appearance.GetAttachpoint(attItem1.ID), Is.EqualTo((int)AttachmentPoint.LeftHand)); - Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(1)); - - // Check events - Assert.That(m_numberOfAttachEventsFired, Is.EqualTo(1)); - } - - // Test wearing a second attachment at the same position - // Until multiple attachments at one point is implemented, this will remove the first attachment - // This test relies on both attachments having the same default attachment point (in this case LeftHand - // since none other has been set). - { - scene.AttachmentsModule.RezSingleAttachmentFromInventory(sp, attItem2.ID, (uint)AttachmentPoint.Default); - - // default attachment point is currently the left hand. - Assert.That(sp.HasAttachments(), Is.True); - List attachments = sp.GetAttachments(); - Assert.That(attachments.Count, Is.EqualTo(1)); - SceneObjectGroup attSo = attachments[0]; - Assert.That(attSo.Name, Is.EqualTo(attItem2.Name)); - Assert.That(attSo.AttachmentPoint, Is.EqualTo((byte)AttachmentPoint.LeftHand)); - Assert.That(attSo.IsAttachment); - - // Check appearance status -// Assert.That(sp.Appearance.GetAttachments().Count, Is.EqualTo(1)); -// Assert.That(sp.Appearance.GetAttachpoint(attItem2.ID), Is.EqualTo((int)AttachmentPoint.LeftHand)); - Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(1)); - - // Check events - Assert.That(m_numberOfAttachEventsFired, Is.EqualTo(3)); - } - - // Test wearing an already attached attachment - { - scene.AttachmentsModule.RezSingleAttachmentFromInventory(sp, attItem2.ID, (uint)AttachmentPoint.Default); - - // default attachment point is currently the left hand. - Assert.That(sp.HasAttachments(), Is.True); - List attachments = sp.GetAttachments(); - Assert.That(attachments.Count, Is.EqualTo(1)); - SceneObjectGroup attSo = attachments[0]; - Assert.That(attSo.Name, Is.EqualTo(attItem2.Name)); - Assert.That(attSo.AttachmentPoint, Is.EqualTo((byte)AttachmentPoint.LeftHand)); - Assert.That(attSo.IsAttachment); - - // Check appearance status -// Assert.That(sp.Appearance.GetAttachments().Count, Is.EqualTo(1)); -// Assert.That(sp.Appearance.GetAttachpoint(attItem2.ID), Is.EqualTo((int)AttachmentPoint.LeftHand)); - Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(1)); - - // Check events - Assert.That(m_numberOfAttachEventsFired, Is.EqualTo(3)); - } - } - - /// - /// Test specific conditions associated with rezzing a scripted attachment from inventory. - /// - [Test] - public void TestRezScriptedAttachmentFromInventory() - { - TestHelpers.InMethod(); - - Scene scene = CreateScriptingEnabledTestScene(); - UserAccount ua1 = UserAccountHelpers.CreateUserWithInventory(scene, 0x1); - ScenePresence sp = SceneHelpers.AddScenePresence(scene, ua1); - - SceneObjectGroup so = SceneHelpers.CreateSceneObject(1, sp.UUID, "att-name", 0x10); - TaskInventoryItem scriptItem - = TaskInventoryHelpers.AddScript( - scene.AssetService, - so.RootPart, - "scriptItem", - "default { attach(key id) { if (id != NULL_KEY) { llSay(0, \"Hello World\"); } } }"); - - InventoryItemBase userItem = UserInventoryHelpers.AddInventoryItem(scene, so, 0x100, 0x1000); - - // FIXME: Right now, we have to do a tricksy chat listen to make sure we know when the script is running. - // In the future, we need to be able to do this programatically more predicably. - scene.EventManager.OnChatFromWorld += OnChatFromWorld; - - m_chatEvent.Reset(); - scene.AttachmentsModule.RezSingleAttachmentFromInventory(sp, userItem.ID, (uint)AttachmentPoint.Chest); - - m_chatEvent.WaitOne(60000); - - // TODO: Need to have a test that checks the script is actually started but this involves a lot more - // plumbing of the script engine and either pausing for events or more infrastructure to turn off various - // script engine delays/asychronicity that isn't helpful in an automated regression testing context. - SceneObjectGroup attSo = scene.GetSceneObjectGroup(so.Name); - Assert.That(attSo.ContainsScripts(), Is.True); - - TaskInventoryItem reRezzedScriptItem = attSo.RootPart.Inventory.GetInventoryItem(scriptItem.Name); - IScriptModule xengine = scene.RequestModuleInterface(); - Assert.That(xengine.GetScriptState(reRezzedScriptItem.ItemID), Is.True); - } - - [Test] - public void TestDetachAttachmentToGround() - { - TestHelpers.InMethod(); -// log4net.Config.XmlConfigurator.Configure(); - - Scene scene = CreateTestScene(); - UserAccount ua1 = UserAccountHelpers.CreateUserWithInventory(scene, 0x1); - ScenePresence sp = SceneHelpers.AddScenePresence(scene, ua1.PrincipalID); - - InventoryItemBase attItem = CreateAttachmentItem(scene, ua1.PrincipalID, "att", 0x10, 0x20); - - ISceneEntity so - = scene.AttachmentsModule.RezSingleAttachmentFromInventory( - sp, attItem.ID, (uint)AttachmentPoint.Chest); - - m_numberOfAttachEventsFired = 0; - scene.AttachmentsModule.DetachSingleAttachmentToGround(sp, so.LocalId); - - // Check scene presence status - Assert.That(sp.HasAttachments(), Is.False); - List attachments = sp.GetAttachments(); - Assert.That(attachments.Count, Is.EqualTo(0)); - - // Check appearance status -// Assert.That(sp.Appearance.GetAttachments().Count, Is.EqualTo(0)); - - // Check item status - Assert.That(scene.InventoryService.GetItem(sp.UUID, attItem.ID), Is.Null); - - // Check object in scene - SceneObjectGroup soInScene = scene.GetSceneObjectGroup("att"); - Assert.That(soInScene, Is.Not.Null); - Assert.IsTrue(soInScene.Backup); - - // Check events - Assert.That(m_numberOfAttachEventsFired, Is.EqualTo(1)); - } - - [Test] - public void TestDetachAttachmentToInventory() - { - TestHelpers.InMethod(); - - Scene scene = CreateTestScene(); - UserAccount ua1 = UserAccountHelpers.CreateUserWithInventory(scene, 0x1); - ScenePresence sp = SceneHelpers.AddScenePresence(scene, ua1.PrincipalID); - - InventoryItemBase attItem = CreateAttachmentItem(scene, ua1.PrincipalID, "att", 0x10, 0x20); - - SceneObjectGroup so - = (SceneObjectGroup)scene.AttachmentsModule.RezSingleAttachmentFromInventory( - sp, attItem.ID, (uint)AttachmentPoint.Chest); - - m_numberOfAttachEventsFired = 0; - scene.AttachmentsModule.DetachSingleAttachmentToInv(sp, so); - - // Check status on scene presence - Assert.That(sp.HasAttachments(), Is.False); - List attachments = sp.GetAttachments(); - Assert.That(attachments.Count, Is.EqualTo(0)); - - // Check item status -// Assert.That(sp.Appearance.GetAttachpoint(attItem.ID), Is.EqualTo(0)); - - Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(0)); - - // Check events - Assert.That(m_numberOfAttachEventsFired, Is.EqualTo(1)); - } - - /// - /// Test specific conditions associated with detaching a scripted attachment from inventory. - /// - [Test] - public void TestDetachScriptedAttachmentToInventory() - { - TestHelpers.InMethod(); -// TestHelpers.EnableLogging(); - - Scene scene = CreateScriptingEnabledTestScene(); - UserAccount ua1 = UserAccountHelpers.CreateUserWithInventory(scene, 0x1); - ScenePresence sp = SceneHelpers.AddScenePresence(scene, ua1); - - SceneObjectGroup so = SceneHelpers.CreateSceneObject(1, sp.UUID, "att-name", 0x10); - TaskInventoryItem scriptTaskItem - = TaskInventoryHelpers.AddScript( - scene.AssetService, - so.RootPart, - "scriptItem", - "default { attach(key id) { if (id != NULL_KEY) { llSay(0, \"Hello World\"); } } }"); - - InventoryItemBase userItem = UserInventoryHelpers.AddInventoryItem(scene, so, 0x100, 0x1000); - - // FIXME: Right now, we have to do a tricksy chat listen to make sure we know when the script is running. - // In the future, we need to be able to do this programatically more predicably. - scene.EventManager.OnChatFromWorld += OnChatFromWorld; - - m_chatEvent.Reset(); - SceneObjectGroup rezzedSo - = (SceneObjectGroup)(scene.AttachmentsModule.RezSingleAttachmentFromInventory(sp, userItem.ID, (uint)AttachmentPoint.Chest)); - - // Wait for chat to signal rezzed script has been started. - m_chatEvent.WaitOne(60000); - - scene.AttachmentsModule.DetachSingleAttachmentToInv(sp, rezzedSo); - - InventoryItemBase userItemUpdated = scene.InventoryService.GetItem(userItem.Owner, userItem.ID); - AssetBase asset = scene.AssetService.Get(userItemUpdated.AssetID.ToString()); - - // TODO: It would probably be better here to check script state via the saving and retrieval of state - // information at a higher level, rather than having to inspect the serialization. - XmlDocument soXml = new XmlDocument(); - soXml.LoadXml(Encoding.UTF8.GetString(asset.Data)); - - XmlNodeList scriptStateNodes = soXml.GetElementsByTagName("ScriptState"); - Assert.That(scriptStateNodes.Count, Is.EqualTo(1)); - - // Re-rez the attachment to check script running state - SceneObjectGroup reRezzedSo = (SceneObjectGroup)(scene.AttachmentsModule.RezSingleAttachmentFromInventory(sp, userItem.ID, (uint)AttachmentPoint.Chest)); - - // Wait for chat to signal rezzed script has been started. - m_chatEvent.WaitOne(60000); - - TaskInventoryItem reRezzedScriptItem = reRezzedSo.RootPart.Inventory.GetInventoryItem(scriptTaskItem.Name); - IScriptModule xengine = scene.RequestModuleInterface(); - Assert.That(xengine.GetScriptState(reRezzedScriptItem.ItemID), Is.True); - -// Console.WriteLine(soXml.OuterXml); - } - - /// - /// Test that attachments don't hang about in the scene when the agent is closed - /// - [Test] - public void TestRemoveAttachmentsOnAvatarExit() - { - TestHelpers.InMethod(); -// log4net.Config.XmlConfigurator.Configure(); - - Scene scene = CreateTestScene(); - UserAccount ua1 = UserAccountHelpers.CreateUserWithInventory(scene, 0x1); - InventoryItemBase attItem = CreateAttachmentItem(scene, ua1.PrincipalID, "att", 0x10, 0x20); - - AgentCircuitData acd = SceneHelpers.GenerateAgentData(ua1.PrincipalID); - acd.Appearance = new AvatarAppearance(); - acd.Appearance.SetAttachment((int)AttachmentPoint.Chest, attItem.ID, attItem.AssetID); - ScenePresence presence = SceneHelpers.AddScenePresence(scene, acd); - - UUID rezzedAttID = presence.GetAttachments()[0].UUID; - - m_numberOfAttachEventsFired = 0; - scene.CloseAgent(presence.UUID, false); - - // Check that we can't retrieve this attachment from the scene. - Assert.That(scene.GetSceneObjectGroup(rezzedAttID), Is.Null); - - // Check events - Assert.That(m_numberOfAttachEventsFired, Is.EqualTo(0)); - } - - [Test] - public void TestRezAttachmentsOnAvatarEntrance() - { - TestHelpers.InMethod(); -// TestHelpers.EnableLogging(); - - Scene scene = CreateTestScene(); - UserAccount ua1 = UserAccountHelpers.CreateUserWithInventory(scene, 0x1); - InventoryItemBase attItem = CreateAttachmentItem(scene, ua1.PrincipalID, "att", 0x10, 0x20); - - AgentCircuitData acd = SceneHelpers.GenerateAgentData(ua1.PrincipalID); - acd.Appearance = new AvatarAppearance(); - acd.Appearance.SetAttachment((int)AttachmentPoint.Chest, attItem.ID, attItem.AssetID); - - m_numberOfAttachEventsFired = 0; - ScenePresence presence = SceneHelpers.AddScenePresence(scene, acd); - - Assert.That(presence.HasAttachments(), Is.True); - List attachments = presence.GetAttachments(); - - Assert.That(attachments.Count, Is.EqualTo(1)); - SceneObjectGroup attSo = attachments[0]; - Assert.That(attSo.Name, Is.EqualTo(attItem.Name)); - Assert.That(attSo.AttachmentPoint, Is.EqualTo((byte)AttachmentPoint.Chest)); - Assert.That(attSo.IsAttachment); - Assert.That(attSo.UsesPhysics, Is.False); - Assert.That(attSo.IsTemporary, Is.False); - Assert.IsFalse(attSo.Backup); - - // Check appearance status - List retreivedAttachments = presence.Appearance.GetAttachments(); - Assert.That(retreivedAttachments.Count, Is.EqualTo(1)); - Assert.That(retreivedAttachments[0].AttachPoint, Is.EqualTo((int)AttachmentPoint.Chest)); - Assert.That(retreivedAttachments[0].ItemID, Is.EqualTo(attItem.ID)); - Assert.That(retreivedAttachments[0].AssetID, Is.EqualTo(attItem.AssetID)); - Assert.That(presence.Appearance.GetAttachpoint(attItem.ID), Is.EqualTo((int)AttachmentPoint.Chest)); - - Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(1)); - - // Check events. We expect OnAttach to fire on login. - Assert.That(m_numberOfAttachEventsFired, Is.EqualTo(1)); - } - - [Test] - public void TestUpdateAttachmentPosition() - { - TestHelpers.InMethod(); - - Scene scene = CreateTestScene(); - UserAccount ua1 = UserAccountHelpers.CreateUserWithInventory(scene, 0x1); - InventoryItemBase attItem = CreateAttachmentItem(scene, ua1.PrincipalID, "att", 0x10, 0x20); - - AgentCircuitData acd = SceneHelpers.GenerateAgentData(ua1.PrincipalID); - acd.Appearance = new AvatarAppearance(); - acd.Appearance.SetAttachment((int)AttachmentPoint.Chest, attItem.ID, attItem.AssetID); - ScenePresence sp = SceneHelpers.AddScenePresence(scene, acd); - - SceneObjectGroup attSo = sp.GetAttachments()[0]; - - Vector3 newPosition = new Vector3(1, 2, 4); - - m_numberOfAttachEventsFired = 0; - scene.SceneGraph.UpdatePrimGroupPosition(attSo.LocalId, newPosition, sp.ControllingClient); - - Assert.That(attSo.AbsolutePosition, Is.EqualTo(sp.AbsolutePosition)); - Assert.That(attSo.RootPart.AttachedPos, Is.EqualTo(newPosition)); - - // Check events - Assert.That(m_numberOfAttachEventsFired, Is.EqualTo(0)); - } - - - [Test] - public void TestSameSimulatorNeighbouringRegionsTeleportV1() - { - TestHelpers.InMethod(); -// TestHelpers.EnableLogging(); - - BaseHttpServer httpServer = new BaseHttpServer(99999); - MainServer.AddHttpServer(httpServer); - MainServer.Instance = httpServer; - - AttachmentsModule attModA = new AttachmentsModule(); - AttachmentsModule attModB = new AttachmentsModule(); - EntityTransferModule etmA = new EntityTransferModule(); - EntityTransferModule etmB = new EntityTransferModule(); - LocalSimulationConnectorModule lscm = new LocalSimulationConnectorModule(); - - IConfigSource config = new IniConfigSource(); - IConfig modulesConfig = config.AddConfig("Modules"); - modulesConfig.Set("EntityTransferModule", etmA.Name); - modulesConfig.Set("SimulationServices", lscm.Name); - IConfig entityTransferConfig = config.AddConfig("EntityTransfer"); - - // In order to run a single threaded regression test we do not want the entity transfer module waiting - // for a callback from the destination scene before removing its avatar data. - entityTransferConfig.Set("wait_for_callback", false); - - modulesConfig.Set("InventoryAccessModule", "BasicInventoryAccessModule"); - - SceneHelpers sh = new SceneHelpers(); - TestScene sceneA = sh.SetupScene("sceneA", TestHelpers.ParseTail(0x100), 1000, 1000); - TestScene sceneB = sh.SetupScene("sceneB", TestHelpers.ParseTail(0x200), 1001, 1000); - - SceneHelpers.SetupSceneModules(new Scene[] { sceneA, sceneB }, config, lscm); - SceneHelpers.SetupSceneModules( - sceneA, config, new CapabilitiesModule(), etmA, attModA, new BasicInventoryAccessModule()); - SceneHelpers.SetupSceneModules( - sceneB, config, new CapabilitiesModule(), etmB, attModB, new BasicInventoryAccessModule()); - - // FIXME: Hack - this is here temporarily to revert back to older entity transfer behaviour - //lscm.ServiceVersion = 0.1f; - - UserAccount ua1 = UserAccountHelpers.CreateUserWithInventory(sceneA, 0x1); - - AgentCircuitData acd = SceneHelpers.GenerateAgentData(ua1.PrincipalID); - TestClient tc = new TestClient(acd, sceneA); - List destinationTestClients = new List(); - EntityTransferHelpers.SetupInformClientOfNeighbourTriggersNeighbourClientCreate(tc, destinationTestClients); - - ScenePresence beforeTeleportSp = SceneHelpers.AddScenePresence(sceneA, tc, acd); - beforeTeleportSp.AbsolutePosition = new Vector3(30, 31, 32); - - InventoryItemBase attItem = CreateAttachmentItem(sceneA, ua1.PrincipalID, "att", 0x10, 0x20); - - sceneA.AttachmentsModule.RezSingleAttachmentFromInventory( - beforeTeleportSp, attItem.ID, (uint)AttachmentPoint.Chest); - - Vector3 teleportPosition = new Vector3(10, 11, 12); - Vector3 teleportLookAt = new Vector3(20, 21, 22); - - m_numberOfAttachEventsFired = 0; - sceneA.RequestTeleportLocation( - beforeTeleportSp.ControllingClient, - sceneB.RegionInfo.RegionHandle, - teleportPosition, - teleportLookAt, - (uint)TeleportFlags.ViaLocation); - - destinationTestClients[0].CompleteMovement(); - - // Check attachments have made it into sceneB - ScenePresence afterTeleportSceneBSp = sceneB.GetScenePresence(ua1.PrincipalID); - - // This is appearance data, as opposed to actually rezzed attachments - List sceneBAttachments = afterTeleportSceneBSp.Appearance.GetAttachments(); - Assert.That(sceneBAttachments.Count, Is.EqualTo(1)); - Assert.That(sceneBAttachments[0].AttachPoint, Is.EqualTo((int)AttachmentPoint.Chest)); - Assert.That(sceneBAttachments[0].ItemID, Is.EqualTo(attItem.ID)); - Assert.That(sceneBAttachments[0].AssetID, Is.EqualTo(attItem.AssetID)); - Assert.That(afterTeleportSceneBSp.Appearance.GetAttachpoint(attItem.ID), Is.EqualTo((int)AttachmentPoint.Chest)); - - // This is the actual attachment - List actualSceneBAttachments = afterTeleportSceneBSp.GetAttachments(); - Assert.That(actualSceneBAttachments.Count, Is.EqualTo(1)); - SceneObjectGroup actualSceneBAtt = actualSceneBAttachments[0]; - Assert.That(actualSceneBAtt.Name, Is.EqualTo(attItem.Name)); - Assert.That(actualSceneBAtt.AttachmentPoint, Is.EqualTo((uint)AttachmentPoint.Chest)); - Assert.IsFalse(actualSceneBAtt.Backup); - - Assert.That(sceneB.GetSceneObjectGroups().Count, Is.EqualTo(1)); - - // Check attachments have been removed from sceneA - ScenePresence afterTeleportSceneASp = sceneA.GetScenePresence(ua1.PrincipalID); - - // Since this is appearance data, it is still present on the child avatar! - List sceneAAttachments = afterTeleportSceneASp.Appearance.GetAttachments(); - Assert.That(sceneAAttachments.Count, Is.EqualTo(1)); - Assert.That(afterTeleportSceneASp.Appearance.GetAttachpoint(attItem.ID), Is.EqualTo((int)AttachmentPoint.Chest)); - - // This is the actual attachment, which should no longer exist - List actualSceneAAttachments = afterTeleportSceneASp.GetAttachments(); - Assert.That(actualSceneAAttachments.Count, Is.EqualTo(0)); - - Assert.That(sceneA.GetSceneObjectGroups().Count, Is.EqualTo(0)); - - // Check events - Assert.That(m_numberOfAttachEventsFired, Is.EqualTo(0)); - } - - - [Test] - public void TestSameSimulatorNeighbouringRegionsTeleportV2() - { - TestHelpers.InMethod(); -// TestHelpers.EnableLogging(); - - BaseHttpServer httpServer = new BaseHttpServer(99999); - MainServer.AddHttpServer(httpServer); - MainServer.Instance = httpServer; - - AttachmentsModule attModA = new AttachmentsModule(); - AttachmentsModule attModB = new AttachmentsModule(); - EntityTransferModule etmA = new EntityTransferModule(); - EntityTransferModule etmB = new EntityTransferModule(); - LocalSimulationConnectorModule lscm = new LocalSimulationConnectorModule(); - - IConfigSource config = new IniConfigSource(); - IConfig modulesConfig = config.AddConfig("Modules"); - modulesConfig.Set("EntityTransferModule", etmA.Name); - modulesConfig.Set("SimulationServices", lscm.Name); - - modulesConfig.Set("InventoryAccessModule", "BasicInventoryAccessModule"); - - SceneHelpers sh = new SceneHelpers(); - TestScene sceneA = sh.SetupScene("sceneA", TestHelpers.ParseTail(0x100), 1000, 1000); - TestScene sceneB = sh.SetupScene("sceneB", TestHelpers.ParseTail(0x200), 1001, 1000); - - SceneHelpers.SetupSceneModules(new Scene[] { sceneA, sceneB }, config, lscm); - SceneHelpers.SetupSceneModules( - sceneA, config, new CapabilitiesModule(), etmA, attModA, new BasicInventoryAccessModule()); - SceneHelpers.SetupSceneModules( - sceneB, config, new CapabilitiesModule(), etmB, attModB, new BasicInventoryAccessModule()); - - UserAccount ua1 = UserAccountHelpers.CreateUserWithInventory(sceneA, 0x1); - - AgentCircuitData acd = SceneHelpers.GenerateAgentData(ua1.PrincipalID); - TestClient tc = new TestClient(acd, sceneA); - List destinationTestClients = new List(); - EntityTransferHelpers.SetupInformClientOfNeighbourTriggersNeighbourClientCreate(tc, destinationTestClients); - - ScenePresence beforeTeleportSp = SceneHelpers.AddScenePresence(sceneA, tc, acd); - beforeTeleportSp.AbsolutePosition = new Vector3(30, 31, 32); - - Assert.That(destinationTestClients.Count, Is.EqualTo(1)); - Assert.That(destinationTestClients[0], Is.Not.Null); - - InventoryItemBase attItem = CreateAttachmentItem(sceneA, ua1.PrincipalID, "att", 0x10, 0x20); - - sceneA.AttachmentsModule.RezSingleAttachmentFromInventory( - beforeTeleportSp, attItem.ID, (uint)AttachmentPoint.Chest); - - Vector3 teleportPosition = new Vector3(10, 11, 12); - Vector3 teleportLookAt = new Vector3(20, 21, 22); - - // Here, we need to make clientA's receipt of SendRegionTeleport trigger clientB's CompleteMovement(). This - // is to operate the teleport V2 mechanism where the EntityTransferModule will first request the client to - // CompleteMovement to the region and then call UpdateAgent to the destination region to confirm the receipt - // Both these operations will occur on different threads and will wait for each other. - // We have to do this via ThreadPool directly since FireAndForget has been switched to sync for the V1 - // test protocol, where we are trying to avoid unpredictable async operations in regression tests. - tc.OnTestClientSendRegionTeleport - += (regionHandle, simAccess, regionExternalEndPoint, locationID, flags, capsURL) - => ThreadPool.UnsafeQueueUserWorkItem(o => destinationTestClients[0].CompleteMovement(), null); - - m_numberOfAttachEventsFired = 0; - sceneA.RequestTeleportLocation( - beforeTeleportSp.ControllingClient, - sceneB.RegionInfo.RegionHandle, - teleportPosition, - teleportLookAt, - (uint)TeleportFlags.ViaLocation); - - // Check attachments have made it into sceneB - ScenePresence afterTeleportSceneBSp = sceneB.GetScenePresence(ua1.PrincipalID); - - // This is appearance data, as opposed to actually rezzed attachments - List sceneBAttachments = afterTeleportSceneBSp.Appearance.GetAttachments(); - Assert.That(sceneBAttachments.Count, Is.EqualTo(1)); - Assert.That(sceneBAttachments[0].AttachPoint, Is.EqualTo((int)AttachmentPoint.Chest)); - Assert.That(sceneBAttachments[0].ItemID, Is.EqualTo(attItem.ID)); - Assert.That(sceneBAttachments[0].AssetID, Is.EqualTo(attItem.AssetID)); - Assert.That(afterTeleportSceneBSp.Appearance.GetAttachpoint(attItem.ID), Is.EqualTo((int)AttachmentPoint.Chest)); - - // This is the actual attachment - List actualSceneBAttachments = afterTeleportSceneBSp.GetAttachments(); - Assert.That(actualSceneBAttachments.Count, Is.EqualTo(1)); - SceneObjectGroup actualSceneBAtt = actualSceneBAttachments[0]; - Assert.That(actualSceneBAtt.Name, Is.EqualTo(attItem.Name)); - Assert.That(actualSceneBAtt.AttachmentPoint, Is.EqualTo((uint)AttachmentPoint.Chest)); - Assert.IsFalse(actualSceneBAtt.Backup); - - Assert.That(sceneB.GetSceneObjectGroups().Count, Is.EqualTo(1)); - - // Check attachments have been removed from sceneA - ScenePresence afterTeleportSceneASp = sceneA.GetScenePresence(ua1.PrincipalID); - - // Since this is appearance data, it is still present on the child avatar! - List sceneAAttachments = afterTeleportSceneASp.Appearance.GetAttachments(); - Assert.That(sceneAAttachments.Count, Is.EqualTo(1)); - Assert.That(afterTeleportSceneASp.Appearance.GetAttachpoint(attItem.ID), Is.EqualTo((int)AttachmentPoint.Chest)); - - // This is the actual attachment, which should no longer exist - List actualSceneAAttachments = afterTeleportSceneASp.GetAttachments(); - Assert.That(actualSceneAAttachments.Count, Is.EqualTo(0)); - - Assert.That(sceneA.GetSceneObjectGroups().Count, Is.EqualTo(0)); - - // Check events - Assert.That(m_numberOfAttachEventsFired, Is.EqualTo(0)); - } - } -*/ -} diff --git a/OpenSim/Region/CoreModules/Avatar/AvatarFactory/Tests/AvatarFactoryModuleTests.cs b/OpenSim/Region/CoreModules/Avatar/AvatarFactory/Tests/AvatarFactoryModuleTests.cs deleted file mode 100644 index f55baa83cf4..00000000000 --- a/OpenSim/Region/CoreModules/Avatar/AvatarFactory/Tests/AvatarFactoryModuleTests.cs +++ /dev/null @@ -1,197 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections.Generic; -using Nini.Config; -using NUnit.Framework; -using OpenMetaverse; -using OpenSim.Framework; -using OpenSim.Region.CoreModules.Asset; -using OpenSim.Region.Framework.Scenes; -using OpenSim.Tests.Common; - -namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory -{ - [TestFixture] - public class AvatarFactoryModuleTests : OpenSimTestCase - { - /// - /// Only partial right now since we don't yet test that it's ended up in the avatar appearance service. - /// - [Test] - public void TestSetAppearance() - { - TestHelpers.InMethod(); -// TestHelpers.EnableLogging(); - - UUID userId = TestHelpers.ParseTail(0x1); - UUID bakedTextureID = TestHelpers.ParseTail(0x2); - - // We need an asset cache because otherwise the LocalAssetServiceConnector will short-circuit directly - // to the AssetService, which will then store temporary and local assets permanently - TestsAssetCache assetCache = new TestsAssetCache(); - - AvatarFactoryModule afm = new AvatarFactoryModule(); - TestScene scene = new SceneHelpers(assetCache).SetupScene(); - SceneHelpers.SetupSceneModules(scene, afm); - ScenePresence sp = SceneHelpers.AddScenePresence(scene, userId); - - // TODO: Use the actual BunchOfCaps functionality once we slot in the CapabilitiesModules - AssetBase bakedTextureAsset; - bakedTextureAsset - = new AssetBase( - bakedTextureID, "Test Baked Texture", (sbyte)AssetType.Texture, userId.ToString()); - bakedTextureAsset.Data = new byte[] { 2 }; // Not necessary to have a genuine JPEG2000 asset here yet - bakedTextureAsset.Temporary = true; - bakedTextureAsset.Local = true; - scene.AssetService.Store(bakedTextureAsset); - - byte[] visualParams = new byte[AvatarAppearance.VISUALPARAM_COUNT]; - for (byte i = 0; i < visualParams.Length; i++) - visualParams[i] = i; - - Primitive.TextureEntry bakedTextureEntry = new Primitive.TextureEntry(TestHelpers.ParseTail(0x10)); - uint eyesFaceIndex = (uint)AppearanceManager.BakeTypeToAgentTextureIndex(BakeType.Eyes); - Primitive.TextureEntryFace eyesFace = bakedTextureEntry.CreateFace(eyesFaceIndex); - - int rebakeRequestsReceived = 0; - ((TestClient)sp.ControllingClient).OnReceivedSendRebakeAvatarTextures += id => rebakeRequestsReceived++; - - // This is the alpha texture - eyesFace.TextureID = bakedTextureID; - afm.SetAppearance(sp, bakedTextureEntry, visualParams, null); - - Assert.That(rebakeRequestsReceived, Is.EqualTo(0)); - - AssetBase eyesBake = scene.AssetService.Get(bakedTextureID.ToString()); - Assert.That(eyesBake, Is.Not.Null); - Assert.That(eyesBake.Temporary, Is.True); - Assert.That(eyesBake.Local, Is.True); - } - - /// - /// Test appearance setting where the baked texture UUID are library alpha textures. - /// - /// - /// For a mesh avatar, it appears these 'baked textures' are used. So these should not trigger a request to - /// rebake. - /// - [Test] - public void TestSetAppearanceAlphaBakedTextures() - { - TestHelpers.InMethod(); -// TestHelpers.EnableLogging(); - - UUID userId = TestHelpers.ParseTail(0x1); - UUID alphaTextureID = new UUID("3a367d1c-bef1-6d43-7595-e88c1e3aadb3"); - - // We need an asset cache because otherwise the LocalAssetServiceConnector will short-circuit directly - // to the AssetService, which will then store temporary and local assets permanently - TestsAssetCache assetCache = new TestsAssetCache(); - - AvatarFactoryModule afm = new AvatarFactoryModule(); - TestScene scene = new SceneHelpers(assetCache).SetupScene(); - SceneHelpers.SetupSceneModules(scene, afm); - ScenePresence sp = SceneHelpers.AddScenePresence(scene, userId); - - AssetBase libraryAsset; - libraryAsset - = new AssetBase( - alphaTextureID, "Default Alpha Layer Texture", (sbyte)AssetType.Texture, userId.ToString()); - libraryAsset.Data = new byte[] { 2 }; // Not necessary to have a genuine JPEG2000 asset here yet - libraryAsset.Temporary = false; - libraryAsset.Local = false; - scene.AssetService.Store(libraryAsset); - - byte[] visualParams = new byte[AvatarAppearance.VISUALPARAM_COUNT]; - for (byte i = 0; i < visualParams.Length; i++) - visualParams[i] = i; - - Primitive.TextureEntry bakedTextureEntry = new Primitive.TextureEntry(TestHelpers.ParseTail(0x10)); - uint eyesFaceIndex = (uint)AppearanceManager.BakeTypeToAgentTextureIndex(BakeType.Eyes); - Primitive.TextureEntryFace eyesFace = bakedTextureEntry.CreateFace(eyesFaceIndex); - - int rebakeRequestsReceived = 0; - ((TestClient)sp.ControllingClient).OnReceivedSendRebakeAvatarTextures += id => rebakeRequestsReceived++; - - // This is the alpha texture - eyesFace.TextureID = alphaTextureID; - afm.SetAppearance(sp, bakedTextureEntry, visualParams, null); - - Assert.That(rebakeRequestsReceived, Is.EqualTo(0)); - } - - [Test] - public void TestSaveBakedTextures() - { - TestHelpers.InMethod(); -// log4net.Config.XmlConfigurator.Configure(); - - UUID userId = TestHelpers.ParseTail(0x1); - UUID eyesTextureId = TestHelpers.ParseTail(0x2); - - // We need an asset cache because otherwise the LocalAssetServiceConnector will short-circuit directly - // to the AssetService, which will then store temporary and local assets permanently - TestsAssetCache assetCache = new TestsAssetCache(); - - AvatarFactoryModule afm = new AvatarFactoryModule(); - TestScene scene = new SceneHelpers(assetCache).SetupScene(); - SceneHelpers.SetupSceneModules(scene, afm); - ScenePresence sp = SceneHelpers.AddScenePresence(scene, userId); - - // TODO: Use the actual BunchOfCaps functionality once we slot in the CapabilitiesModules - AssetBase uploadedAsset; - uploadedAsset = new AssetBase(eyesTextureId, "Baked Texture", (sbyte)AssetType.Texture, userId.ToString()); - uploadedAsset.Data = new byte[] { 2 }; - uploadedAsset.Temporary = true; - uploadedAsset.Local = true; // Local assets aren't persisted, non-local are - scene.AssetService.Store(uploadedAsset); - - byte[] visualParams = new byte[AvatarAppearance.VISUALPARAM_COUNT]; - for (byte i = 0; i < visualParams.Length; i++) - visualParams[i] = i; - - Primitive.TextureEntry bakedTextureEntry = new Primitive.TextureEntry(TestHelpers.ParseTail(0x10)); - uint eyesFaceIndex = (uint)AppearanceManager.BakeTypeToAgentTextureIndex(BakeType.Eyes); - Primitive.TextureEntryFace eyesFace = bakedTextureEntry.CreateFace(eyesFaceIndex); - eyesFace.TextureID = eyesTextureId; - - afm.SetAppearance(sp, bakedTextureEntry, visualParams, new WearableCacheItem[0]); - afm.SaveBakedTextures(userId); -// Dictionary bakedTextures = afm.GetBakedTextureFaces(userId); - - // We should also inpsect the asset data store layer directly, but this is difficult to get at right now. - assetCache.Clear(); - - AssetBase eyesBake = scene.AssetService.Get(eyesTextureId.ToString()); - Assert.That(eyesBake, Is.Not.Null); - Assert.That(eyesBake.Temporary, Is.False); - Assert.That(eyesBake.Local, Is.False); - } - } -} \ No newline at end of file diff --git a/OpenSim/Region/CoreModules/Avatar/Chat/Tests/ChatModuleTests.cs b/OpenSim/Region/CoreModules/Avatar/Chat/Tests/ChatModuleTests.cs deleted file mode 100644 index 2813c11d487..00000000000 --- a/OpenSim/Region/CoreModules/Avatar/Chat/Tests/ChatModuleTests.cs +++ /dev/null @@ -1,320 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections.Generic; -using log4net.Config; -using Nini.Config; -using NUnit.Framework; -using OpenMetaverse; -using OpenSim.Framework; -using OpenSim.Framework.Servers; -using OpenSim.Framework.Servers.HttpServer; -using OpenSim.Region.CoreModules.Avatar.Chat; -using OpenSim.Region.CoreModules.Framework; -using OpenSim.Region.CoreModules.Framework.EntityTransfer; -using OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation; -using OpenSim.Region.Framework.Scenes; -using OpenSim.Services.Interfaces; -using OpenSim.Tests.Common; -using System.Threading; - -namespace OpenSim.Region.CoreModules.Avatar.Chat.Tests -{ - [TestFixture] - public class ChatModuleTests : OpenSimTestCase - { - [OneTimeSetUp] - public void FixtureInit() - { - // Don't allow tests to be bamboozled by asynchronous events. Execute everything on the same thread. - // We must do this here so that child agent positions are updated in a predictable manner. - Util.FireAndForgetMethod = FireAndForgetMethod.RegressionTest; - } - - [OneTimeTearDown] - public void TearDown() - { - // We must set this back afterwards, otherwise later tests will fail since they're expecting multiple - // threads. Possibly, later tests should be rewritten so none of them require async stuff (which regression - // tests really shouldn't). - Util.FireAndForgetMethod = Util.DefaultFireAndForgetMethod; - } - - private void SetupNeighbourRegions(TestScene sceneA, TestScene sceneB) - { - // XXX: HTTP server is not (and should not be) necessary for this test, though it's absence makes the - // CapabilitiesModule complain when it can't set up HTTP endpoints. - BaseHttpServer httpServer = new BaseHttpServer(99999); - MainServer.AddHttpServer(httpServer); - MainServer.Instance = httpServer; - - // We need entity transfer modules so that when sp2 logs into the east region, the region calls - // EntityTransferModuleto set up a child agent on the west region. - // XXX: However, this is not an entity transfer so is misleading. - EntityTransferModule etmA = new EntityTransferModule(); - EntityTransferModule etmB = new EntityTransferModule(); - LocalSimulationConnectorModule lscm = new LocalSimulationConnectorModule(); - - IConfigSource config = new IniConfigSource(); - config.AddConfig("Chat"); - IConfig modulesConfig = config.AddConfig("Modules"); - modulesConfig.Set("EntityTransferModule", etmA.Name); - modulesConfig.Set("SimulationServices", lscm.Name); - - SceneHelpers.SetupSceneModules(new Scene[] { sceneA, sceneB }, config, lscm); - SceneHelpers.SetupSceneModules(sceneA, config, new CapabilitiesModule(), etmA, new ChatModule()); - SceneHelpers.SetupSceneModules(sceneB, config, new CapabilitiesModule(), etmB, new ChatModule()); - } - - /// - /// Tests chat between neighbour regions on the east-west axis - /// - /// - /// Really, this is a combination of a child agent position update test and a chat range test. These need - /// to be separated later on. - /// - [Test] - public void TestInterRegionChatDistanceEastWest() - { - TestHelpers.InMethod(); -// TestHelpers.EnableLogging(); - - UUID sp1Uuid = TestHelpers.ParseTail(0x11); - UUID sp2Uuid = TestHelpers.ParseTail(0x12); - - Vector3 sp1Position = new Vector3(6, 128, 20); - Vector3 sp2Position = new Vector3(250, 128, 20); - - SceneHelpers sh = new SceneHelpers(); - TestScene sceneWest = sh.SetupScene("sceneWest", TestHelpers.ParseTail(0x1), 1000, 1000); - TestScene sceneEast = sh.SetupScene("sceneEast", TestHelpers.ParseTail(0x2), 1001, 1000); - - SetupNeighbourRegions(sceneWest, sceneEast); - - ScenePresence sp1 = SceneHelpers.AddScenePresence(sceneEast, sp1Uuid); - TestClient sp1Client = (TestClient)sp1.ControllingClient; - - // If we don't set agents to flying, test will go wrong as they instantly fall to z = 0. - // TODO: May need to create special complete no-op test physics module rather than basic physics, since - // physics is irrelevant to this test. - sp1.Flying = true; - - // When sp1 logs in to sceneEast, it sets up a child agent in sceneWest and informs the sp2 client to - // make the connection. For this test, will simplify this chain by making the connection directly. - ScenePresence sp1Child = SceneHelpers.AddChildScenePresence(sceneWest, sp1Uuid); - TestClient sp1ChildClient = (TestClient)sp1Child.ControllingClient; - - sp1.AbsolutePosition = sp1Position; - - ScenePresence sp2 = SceneHelpers.AddScenePresence(sceneWest, sp2Uuid); - TestClient sp2Client = (TestClient)sp2.ControllingClient; - sp2.Flying = true; - - ScenePresence sp2Child = SceneHelpers.AddChildScenePresence(sceneEast, sp2Uuid); - TestClient sp2ChildClient = (TestClient)sp2Child.ControllingClient; - - sp2.AbsolutePosition = sp2Position; - - // We must update the scenes in order to make the root new root agents trigger position updates in their - // children. - for (int i = 0; i < 6; ++i) - { - sceneWest.Update(1); - sceneEast.Update(1); - } - sp1.DrawDistance += 64; - sp2.DrawDistance += 64; - for (int i = 0; i < 6; ++i) - { - sceneWest.Update(1); - sceneEast.Update(1); - } - - // Check child positions are correct. - Assert.AreEqual( - new Vector3(sp1Position.X + sceneEast.RegionInfo.RegionSizeX, sp1Position.Y, sp1Position.Z), - sp1ChildClient.SceneAgent.AbsolutePosition); - - Assert.AreEqual( - new Vector3(sp2Position.X - sceneWest.RegionInfo.RegionSizeX, sp2Position.Y, sp2Position.Z), - sp2ChildClient.SceneAgent.AbsolutePosition); - - string receivedSp1ChatMessage = ""; - string receivedSp2ChatMessage = ""; - - sp1ChildClient.OnReceivedChatMessage - += (message, type, fromPos, fromName, fromAgentID, ownerID, source, audible) => receivedSp1ChatMessage = message; - sp2ChildClient.OnReceivedChatMessage - += (message, type, fromPos, fromName, fromAgentID, ownerID, source, audible) => receivedSp2ChatMessage = message; - - TestUserInRange(sp1Client, "ello darling", ref receivedSp2ChatMessage); - TestUserInRange(sp2Client, "fantastic cats", ref receivedSp1ChatMessage); - - sp1Position = new Vector3(30, 128, 20); - sp1.AbsolutePosition = sp1Position; - for (int i = 0; i < 2; ++i) - { - sceneWest.Update(1); - sceneEast.Update(1); - } - Thread.Sleep(12000); // child updates are now time limited - for (int i = 0; i < 6; ++i) - { - sceneWest.Update(1); - sceneEast.Update(1); - } - - // Check child position is correct. - Assert.AreEqual( - new Vector3(sp1Position.X + sceneEast.RegionInfo.RegionSizeX, sp1Position.Y, sp1Position.Z), - sp1ChildClient.SceneAgent.AbsolutePosition); - - TestUserOutOfRange(sp1Client, "beef", ref receivedSp2ChatMessage); - TestUserOutOfRange(sp2Client, "lentils", ref receivedSp1ChatMessage); - } - - /// - /// Tests chat between neighbour regions on the north-south axis - /// - /// - /// Really, this is a combination of a child agent position update test and a chat range test. These need - /// to be separated later on. - /// - [Test] - public void TestInterRegionChatDistanceNorthSouth() - { - TestHelpers.InMethod(); - // TestHelpers.EnableLogging(); - - UUID sp1Uuid = TestHelpers.ParseTail(0x11); - UUID sp2Uuid = TestHelpers.ParseTail(0x12); - - Vector3 sp1Position = new Vector3(128, 250, 20); - Vector3 sp2Position = new Vector3(128, 6, 20); - - SceneHelpers sh = new SceneHelpers(); - TestScene sceneNorth = sh.SetupScene("sceneNorth", TestHelpers.ParseTail(0x1), 1000, 1000); - TestScene sceneSouth = sh.SetupScene("sceneSouth", TestHelpers.ParseTail(0x2), 1000, 1001); - - SetupNeighbourRegions(sceneNorth, sceneSouth); - - ScenePresence sp1 = SceneHelpers.AddScenePresence(sceneNorth, sp1Uuid); - TestClient sp1Client = (TestClient)sp1.ControllingClient; - - // If we don't set agents to flying, test will go wrong as they instantly fall to z = 0. - // TODO: May need to create special complete no-op test physics module rather than basic physics, since - // physics is irrelevant to this test. - sp1.Flying = true; - - // When sp1 logs in to sceneEast, it sets up a child agent in sceneNorth and informs the sp2 client to - // make the connection. For this test, will simplify this chain by making the connection directly. - ScenePresence sp1Child = SceneHelpers.AddChildScenePresence(sceneSouth, sp1Uuid); - TestClient sp1ChildClient = (TestClient)sp1Child.ControllingClient; - - sp1.AbsolutePosition = sp1Position; - - ScenePresence sp2 = SceneHelpers.AddScenePresence(sceneSouth, sp2Uuid); - TestClient sp2Client = (TestClient)sp2.ControllingClient; - sp2.Flying = true; - - ScenePresence sp2Child = SceneHelpers.AddChildScenePresence(sceneNorth, sp2Uuid); - TestClient sp2ChildClient = (TestClient)sp2Child.ControllingClient; - - sp2.AbsolutePosition = sp2Position; - - // We must update the scenes in order to make the root new root agents trigger position updates in their - // children. - for (int i = 0; i < 6; ++i) - { - sceneNorth.Update(1); - sceneSouth.Update(1); - } - sp1.DrawDistance += 64; - sp2.DrawDistance += 64; - for (int i = 0; i < 6; ++i) - { - sceneNorth.Update(1); - sceneSouth.Update(1); - } - - // Check child positions are correct. - Assert.AreEqual( - new Vector3(sp1Position.X, sp1Position.Y - sceneNorth.RegionInfo.RegionSizeY, sp1Position.Z), - sp1ChildClient.SceneAgent.AbsolutePosition); - - Assert.AreEqual( - new Vector3(sp2Position.X, sp2Position.Y + sceneSouth.RegionInfo.RegionSizeY, sp2Position.Z), - sp2ChildClient.SceneAgent.AbsolutePosition); - - string receivedSp1ChatMessage = ""; - string receivedSp2ChatMessage = ""; - - sp1ChildClient.OnReceivedChatMessage - += (message, type, fromPos, fromName, fromAgentID, ownerID, source, audible) => receivedSp1ChatMessage = message; - sp2ChildClient.OnReceivedChatMessage - += (message, type, fromPos, fromName, fromAgentID, ownerID, source, audible) => receivedSp2ChatMessage = message; - - TestUserInRange(sp1Client, "ello darling", ref receivedSp2ChatMessage); - TestUserInRange(sp2Client, "fantastic cats", ref receivedSp1ChatMessage); - - sp1Position = new Vector3(30, 128, 20); - sp1.AbsolutePosition = sp1Position; - sceneNorth.Update(6); - sceneSouth.Update(6); - Thread.Sleep(12000); // child updates are now time limited - sceneNorth.Update(6); - sceneSouth.Update(6); - - // Check child position is correct. - Assert.AreEqual( - new Vector3(sp1Position.X, sp1Position.Y - sceneNorth.RegionInfo.RegionSizeY, sp1Position.Z), - sp1ChildClient.SceneAgent.AbsolutePosition); - - TestUserOutOfRange(sp1Client, "beef", ref receivedSp2ChatMessage); - TestUserOutOfRange(sp2Client, "lentils", ref receivedSp1ChatMessage); - } - - private void TestUserInRange(TestClient speakClient, string testMessage, ref string receivedMessage) - { - receivedMessage = ""; - - speakClient.Chat(0, ChatTypeEnum.Say, testMessage); - - Assert.AreEqual(testMessage, receivedMessage); - } - - private void TestUserOutOfRange(TestClient speakClient, string testMessage, ref string receivedMessage) - { - receivedMessage = ""; - - speakClient.Chat(0, ChatTypeEnum.Say, testMessage); - - Assert.AreNotEqual(testMessage, receivedMessage); - } - } -} \ No newline at end of file diff --git a/OpenSim/Region/CoreModules/Avatar/Friends/Tests/FriendModuleTests.cs b/OpenSim/Region/CoreModules/Avatar/Friends/Tests/FriendModuleTests.cs deleted file mode 100644 index d79d6504443..00000000000 --- a/OpenSim/Region/CoreModules/Avatar/Friends/Tests/FriendModuleTests.cs +++ /dev/null @@ -1,209 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections.Generic; -using Nini.Config; -using NUnit.Framework; -using OpenMetaverse; -using OpenSim.Data.Null; -using OpenSim.Framework; -using OpenSim.Region.CoreModules.Avatar.Friends; -using OpenSim.Region.Framework.Scenes; -using OpenSim.Tests.Common; - -namespace OpenSim.Region.CoreModules.Avatar.Friends.Tests -{ - [TestFixture] - public class FriendsModuleTests : OpenSimTestCase - { - private FriendsModule m_fm; - private TestScene m_scene; - - [OneTimeSetUp] - public void FixtureInit() - { - // Don't allow tests to be bamboozled by asynchronous events. Execute everything on the same thread. - Util.FireAndForgetMethod = FireAndForgetMethod.RegressionTest; - } - - [OneTimeTearDown] - public void TearDown() - { - // We must set this back afterwards, otherwise later tests will fail since they're expecting multiple - // threads. Possibly, later tests should be rewritten so none of them require async stuff (which regression - // tests really shouldn't). - Util.FireAndForgetMethod = Util.DefaultFireAndForgetMethod; - } - - [SetUp] - public void Init() - { - // We must clear friends data between tests since Data.Null holds it in static properties. This is necessary - // so that different services and simulator can share the data in standalone mode. This is pretty horrible - // effectively the statics are global variables. - NullFriendsData.Clear(); - - IConfigSource config = new IniConfigSource(); - config.AddConfig("Modules"); - // Not strictly necessary since FriendsModule assumes it is the default (!) - config.Configs["Modules"].Set("FriendsModule", "FriendsModule"); - config.AddConfig("Friends"); - config.Configs["Friends"].Set("Connector", "OpenSim.Services.FriendsService.dll"); - config.AddConfig("FriendsService"); - config.Configs["FriendsService"].Set("StorageProvider", "OpenSim.Data.Null.dll"); - - m_scene = new SceneHelpers().SetupScene(); - m_fm = new FriendsModule(); - SceneHelpers.SetupSceneModules(m_scene, config, m_fm); - } - - [Test] - public void TestLoginWithNoFriends() - { - TestHelpers.InMethod(); -// log4net.Config.XmlConfigurator.Configure(); - - UUID userId = TestHelpers.ParseTail(0x1); - - ScenePresence sp = SceneHelpers.AddScenePresence(m_scene, userId); - - Assert.That(((TestClient)sp.ControllingClient).ReceivedOfflineNotifications.Count, Is.EqualTo(0)); - Assert.That(((TestClient)sp.ControllingClient).ReceivedOnlineNotifications.Count, Is.EqualTo(0)); - } - - [Test] - public void TestLoginWithOfflineFriends() - { - TestHelpers.InMethod(); -// log4net.Config.XmlConfigurator.Configure(); - - UUID user1Id = TestHelpers.ParseTail(0x1); - UUID user2Id = TestHelpers.ParseTail(0x2); - -// UserAccountHelpers.CreateUserWithInventory(m_scene, user1Id); -// UserAccountHelpers.CreateUserWithInventory(m_scene, user2Id); -// -// m_fm.AddFriendship(user1Id, user2Id); - - ScenePresence sp1 = SceneHelpers.AddScenePresence(m_scene, user1Id); - ScenePresence sp2 = SceneHelpers.AddScenePresence(m_scene, user2Id); - - m_fm.AddFriendship(sp1.ControllingClient, user2Id); - - // Not necessary for this test. CanSeeOnline is automatically granted. -// m_fm.GrantRights(sp1.ControllingClient, user2Id, (int)FriendRights.CanSeeOnline); - - // We must logout from the client end so that the presence service is correctly updated by the presence - // detector. This is listening to the OnConnectionClosed event on the client. - ((TestClient)sp1.ControllingClient).Logout(); - ((TestClient)sp2.ControllingClient).Logout(); -// m_scene.RemoveClient(sp1.UUID, true); -// m_scene.RemoveClient(sp2.UUID, true); - - ScenePresence sp1Redux = SceneHelpers.AddScenePresence(m_scene, user1Id); - - // We don't expect to receive notifications of offline friends on login, just online. - Assert.That(((TestClient)sp1Redux.ControllingClient).ReceivedOfflineNotifications.Count, Is.EqualTo(0)); - Assert.That(((TestClient)sp1Redux.ControllingClient).ReceivedOnlineNotifications.Count, Is.EqualTo(0)); - } - - [Test] - public void TestLoginWithOnlineFriends() - { - TestHelpers.InMethod(); -// log4net.Config.XmlConfigurator.Configure(); - - UUID user1Id = TestHelpers.ParseTail(0x1); - UUID user2Id = TestHelpers.ParseTail(0x2); - -// UserAccountHelpers.CreateUserWithInventory(m_scene, user1Id); -// UserAccountHelpers.CreateUserWithInventory(m_scene, user2Id); -// -// m_fm.AddFriendship(user1Id, user2Id); - - ScenePresence sp1 = SceneHelpers.AddScenePresence(m_scene, user1Id); - ScenePresence sp2 = SceneHelpers.AddScenePresence(m_scene, user2Id); - - m_fm.AddFriendship(sp1.ControllingClient, user2Id); - - // Not necessary for this test. CanSeeOnline is automatically granted. -// m_fm.GrantRights(sp1.ControllingClient, user2Id, (int)FriendRights.CanSeeOnline); - - // We must logout from the client end so that the presence service is correctly updated by the presence - // detector. This is listening to the OnConnectionClosed event on the client. -// ((TestClient)sp1.ControllingClient).Logout(); - ((TestClient)sp2.ControllingClient).Logout(); -// m_scene.RemoveClient(user2Id, true); - - ScenePresence sp2Redux = SceneHelpers.AddScenePresence(m_scene, user2Id); - - Assert.That(((TestClient)sp2Redux.ControllingClient).ReceivedOfflineNotifications.Count, Is.EqualTo(0)); - Assert.That(((TestClient)sp2Redux.ControllingClient).ReceivedOnlineNotifications.Count, Is.EqualTo(1)); - } - - [Test] - public void TestAddFriendshipWhileOnline() - { - TestHelpers.InMethod(); -// log4net.Config.XmlConfigurator.Configure(); - - UUID userId = TestHelpers.ParseTail(0x1); - UUID user2Id = TestHelpers.ParseTail(0x2); - - ScenePresence sp = SceneHelpers.AddScenePresence(m_scene, userId); - SceneHelpers.AddScenePresence(m_scene, user2Id); - - // This fiendship is two-way but without a connector, only the first user will receive the online - // notification. - m_fm.AddFriendship(sp.ControllingClient, user2Id); - - Assert.That(((TestClient)sp.ControllingClient).ReceivedOfflineNotifications.Count, Is.EqualTo(0)); - Assert.That(((TestClient)sp.ControllingClient).ReceivedOnlineNotifications.Count, Is.EqualTo(1)); - } - - [Test] - public void TestRemoveFriendshipWhileOnline() - { - TestHelpers.InMethod(); -// log4net.Config.XmlConfigurator.Configure(); - - UUID user1Id = TestHelpers.ParseTail(0x1); - UUID user2Id = TestHelpers.ParseTail(0x2); - - ScenePresence sp = SceneHelpers.AddScenePresence(m_scene, user1Id); - SceneHelpers.AddScenePresence(m_scene, user2Id); - - m_fm.AddFriendship(sp.ControllingClient, user2Id); - m_fm.RemoveFriendship(sp.ControllingClient, user2Id); - - TestClient user1Client = sp.ControllingClient as TestClient; - Assert.That(user1Client.ReceivedFriendshipTerminations.Count, Is.EqualTo(1)); - Assert.That(user1Client.ReceivedFriendshipTerminations[0], Is.EqualTo(user2Id)); - } - } -} \ No newline at end of file diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveLoadPathTests.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveLoadPathTests.cs deleted file mode 100644 index 86eca17d3b2..00000000000 --- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveLoadPathTests.cs +++ /dev/null @@ -1,360 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections.Generic; -using System.IO; -using System.Reflection; -using System.Threading; -using NUnit.Framework; -using OpenMetaverse; -using OpenSim.Data; -using OpenSim.Framework; -using OpenSim.Framework.Serialization; -using OpenSim.Framework.Serialization.External; -using OpenSim.Region.CoreModules.Avatar.Inventory.Archiver; -using OpenSim.Region.CoreModules.World.Serialiser; -using OpenSim.Region.Framework.Scenes; -using OpenSim.Region.Framework.Scenes.Serialization; -using OpenSim.Services.Interfaces; -using OpenSim.Tests.Common; - -namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests -{ - [TestFixture] - public class InventoryArchiveLoadPathTests : InventoryArchiveTestCase - { - /// - /// Test loading an IAR to various different inventory paths. - /// - [Test] - public void TestLoadIarToInventoryPaths() - { - TestHelpers.InMethod(); -// log4net.Config.XmlConfigurator.Configure(); - - SerialiserModule serialiserModule = new SerialiserModule(); - InventoryArchiverModule archiverModule = new InventoryArchiverModule(); - - // Annoyingly, we have to set up a scene even though inventory loading has nothing to do with a scene - Scene scene = new SceneHelpers().SetupScene(); - - SceneHelpers.SetupSceneModules(scene, serialiserModule, archiverModule); - - UserAccountHelpers.CreateUserWithInventory(scene, m_uaMT, "meowfood"); - UserAccountHelpers.CreateUserWithInventory(scene, m_uaLL1, "hampshire"); - - archiverModule.DearchiveInventory(UUID.Random(), m_uaMT.FirstName, m_uaMT.LastName, "/", "meowfood", m_iarStream); - InventoryItemBase foundItem1 - = InventoryArchiveUtils.FindItemByPath(scene.InventoryService, m_uaMT.PrincipalID, m_item1Name); - - Assert.That(foundItem1, Is.Not.Null, "Didn't find loaded item 1"); - - // Now try loading to a root child folder - UserInventoryHelpers.CreateInventoryFolder(scene.InventoryService, m_uaMT.PrincipalID, "xA", false); - MemoryStream archiveReadStream = new MemoryStream(m_iarStream.ToArray()); - archiverModule.DearchiveInventory(UUID.Random(), m_uaMT.FirstName, m_uaMT.LastName, "xA", "meowfood", archiveReadStream); - - InventoryItemBase foundItem2 - = InventoryArchiveUtils.FindItemByPath(scene.InventoryService, m_uaMT.PrincipalID, "xA/" + m_item1Name); - Assert.That(foundItem2, Is.Not.Null, "Didn't find loaded item 2"); - - // Now try loading to a more deeply nested folder - UserInventoryHelpers.CreateInventoryFolder(scene.InventoryService, m_uaMT.PrincipalID, "xB/xC", false); - archiveReadStream = new MemoryStream(archiveReadStream.ToArray()); - archiverModule.DearchiveInventory(UUID.Random(), m_uaMT.FirstName, m_uaMT.LastName, "xB/xC", "meowfood", archiveReadStream); - - InventoryItemBase foundItem3 - = InventoryArchiveUtils.FindItemByPath(scene.InventoryService, m_uaMT.PrincipalID, "xB/xC/" + m_item1Name); - Assert.That(foundItem3, Is.Not.Null, "Didn't find loaded item 3"); - } - - /// - /// Test that things work when the load path specified starts with a slash - /// - [Test] - public void TestLoadIarPathStartsWithSlash() - { - TestHelpers.InMethod(); -// log4net.Config.XmlConfigurator.Configure(); - - SerialiserModule serialiserModule = new SerialiserModule(); - InventoryArchiverModule archiverModule = new InventoryArchiverModule(); - Scene scene = new SceneHelpers().SetupScene(); - SceneHelpers.SetupSceneModules(scene, serialiserModule, archiverModule); - - UserAccountHelpers.CreateUserWithInventory(scene, m_uaMT, "password"); - archiverModule.DearchiveInventory(UUID.Random(), m_uaMT.FirstName, m_uaMT.LastName, "/Objects", "password", m_iarStream); - - InventoryItemBase foundItem1 - = InventoryArchiveUtils.FindItemByPath( - scene.InventoryService, m_uaMT.PrincipalID, "/Objects/" + m_item1Name); - - Assert.That(foundItem1, Is.Not.Null, "Didn't find loaded item 1 in TestLoadIarFolderStartsWithSlash()"); - } - - [Test] - public void TestLoadIarPathWithEscapedChars() - { - TestHelpers.InMethod(); -// log4net.Config.XmlConfigurator.Configure(); - - string itemName = "You & you are a mean/man/"; - string humanEscapedItemName = @"You & you are a mean\/man\/"; - string userPassword = "meowfood"; - - InventoryArchiverModule archiverModule = new InventoryArchiverModule(); - - Scene scene = new SceneHelpers().SetupScene(); - SceneHelpers.SetupSceneModules(scene, archiverModule); - - // Create user - string userFirstName = "Jock"; - string userLastName = "Stirrup"; - UUID userId = UUID.Parse("00000000-0000-0000-0000-000000000020"); - UserAccountHelpers.CreateUserWithInventory(scene, userFirstName, userLastName, userId, "meowfood"); - - // Create asset - SceneObjectGroup object1; - SceneObjectPart part1; - { - string partName = "part name"; - UUID ownerId = UUID.Parse("00000000-0000-0000-0000-000000000040"); - PrimitiveBaseShape shape = PrimitiveBaseShape.CreateSphere(); - Vector3 groupPosition = new Vector3(10, 20, 30); - Quaternion rotationOffset = new Quaternion(20, 30, 40, 50); - Vector3 offsetPosition = new Vector3(5, 10, 15); - - part1 - = new SceneObjectPart( - ownerId, shape, groupPosition, rotationOffset, offsetPosition); - part1.Name = partName; - - object1 = new SceneObjectGroup(part1); - scene.AddNewSceneObject(object1, false); - } - - UUID asset1Id = UUID.Parse("00000000-0000-0000-0000-000000000060"); - AssetBase asset1 = AssetHelpers.CreateAsset(asset1Id, object1); - scene.AssetService.Store(asset1); - - // Create item - UUID item1Id = UUID.Parse("00000000-0000-0000-0000-000000000080"); - InventoryItemBase item1 = new InventoryItemBase(); - item1.Name = itemName; - item1.AssetID = asset1.FullID; - item1.ID = item1Id; - InventoryFolderBase objsFolder - = InventoryArchiveUtils.FindFoldersByPath(scene.InventoryService, userId, "Objects")[0]; - item1.Folder = objsFolder.ID; - scene.AddInventoryItem(item1); - - MemoryStream archiveWriteStream = new MemoryStream(); - archiverModule.OnInventoryArchiveSaved += SaveCompleted; - - mre.Reset(); - archiverModule.ArchiveInventory( - UUID.Random(), userFirstName, userLastName, "Objects", userPassword, archiveWriteStream); - mre.WaitOne(60000, false); - - // LOAD ITEM - MemoryStream archiveReadStream = new MemoryStream(archiveWriteStream.ToArray()); - - archiverModule.DearchiveInventory(UUID.Random(), userFirstName, userLastName, "Scripts", userPassword, archiveReadStream); - - InventoryItemBase foundItem1 - = InventoryArchiveUtils.FindItemByPath( - scene.InventoryService, userId, "Scripts/Objects/" + humanEscapedItemName); - - Assert.That(foundItem1, Is.Not.Null, "Didn't find loaded item 1"); -// Assert.That( -// foundItem1.CreatorId, Is.EqualTo(userUuid), -// "Loaded item non-uuid creator doesn't match that of the loading user"); - Assert.That( - foundItem1.Name, Is.EqualTo(itemName), - "Loaded item name doesn't match saved name"); - } - - /// - /// Test replication of an archive path to the user's inventory. - /// - [Test] - public void TestNewIarPath() - { - TestHelpers.InMethod(); -// log4net.Config.XmlConfigurator.Configure(); - - Scene scene = new SceneHelpers().SetupScene(); - UserAccount ua1 = UserAccountHelpers.CreateUserWithInventory(scene); - - Dictionary foldersCreated = new Dictionary(); - Dictionary nodesLoaded = new Dictionary(); - - string folder1Name = "1"; - string folder2aName = "2a"; - string folder2bName = "2b"; - - string folder1ArchiveName = InventoryArchiveWriteRequest.CreateArchiveFolderName(folder1Name, UUID.Random()); - string folder2aArchiveName = InventoryArchiveWriteRequest.CreateArchiveFolderName(folder2aName, UUID.Random()); - string folder2bArchiveName = InventoryArchiveWriteRequest.CreateArchiveFolderName(folder2bName, UUID.Random()); - - string iarPath1 = string.Join("", new string[] { folder1ArchiveName, folder2aArchiveName }); - string iarPath2 = string.Join("", new string[] { folder1ArchiveName, folder2bArchiveName }); - - { - // Test replication of path1 - new InventoryArchiveReadRequest(UUID.Random(), null, scene.InventoryService, scene.AssetService, scene.UserAccountService, ua1, null, (Stream)null, false) - .ReplicateArchivePathToUserInventory( - iarPath1, scene.InventoryService.GetRootFolder(ua1.PrincipalID), - foldersCreated, nodesLoaded); - - List folder1Candidates - = InventoryArchiveUtils.FindFoldersByPath(scene.InventoryService, ua1.PrincipalID, folder1Name); - Assert.That(folder1Candidates.Count, Is.EqualTo(1)); - - InventoryFolderBase folder1 = folder1Candidates[0]; - List folder2aCandidates - = InventoryArchiveUtils.FindFoldersByPath(scene.InventoryService, folder1, folder2aName); - Assert.That(folder2aCandidates.Count, Is.EqualTo(1)); - } - - { - // Test replication of path2 - new InventoryArchiveReadRequest(UUID.Random(), null, scene.InventoryService, scene.AssetService, scene.UserAccountService, ua1, null, (Stream)null, false) - .ReplicateArchivePathToUserInventory( - iarPath2, scene.InventoryService.GetRootFolder(ua1.PrincipalID), - foldersCreated, nodesLoaded); - - List folder1Candidates - = InventoryArchiveUtils.FindFoldersByPath(scene.InventoryService, ua1.PrincipalID, folder1Name); - Assert.That(folder1Candidates.Count, Is.EqualTo(1)); - - InventoryFolderBase folder1 = folder1Candidates[0]; - - List folder2aCandidates - = InventoryArchiveUtils.FindFoldersByPath(scene.InventoryService, folder1, folder2aName); - Assert.That(folder2aCandidates.Count, Is.EqualTo(1)); - - List folder2bCandidates - = InventoryArchiveUtils.FindFoldersByPath(scene.InventoryService, folder1, folder2bName); - Assert.That(folder2bCandidates.Count, Is.EqualTo(1)); - } - } - - /// - /// Test replication of a partly existing archive path to the user's inventory. This should create - /// a duplicate path without the merge option. - /// - [Test] - public void TestPartExistingIarPath() - { - TestHelpers.InMethod(); - //log4net.Config.XmlConfigurator.Configure(); - - Scene scene = new SceneHelpers().SetupScene(); - UserAccount ua1 = UserAccountHelpers.CreateUserWithInventory(scene); - - string folder1ExistingName = "a"; - string folder2Name = "b"; - - InventoryFolderBase folder1 - = UserInventoryHelpers.CreateInventoryFolder( - scene.InventoryService, ua1.PrincipalID, folder1ExistingName, false); - - string folder1ArchiveName = InventoryArchiveWriteRequest.CreateArchiveFolderName(folder1ExistingName, UUID.Random()); - string folder2ArchiveName = InventoryArchiveWriteRequest.CreateArchiveFolderName(folder2Name, UUID.Random()); - - string itemArchivePath = string.Join("", new string[] { folder1ArchiveName, folder2ArchiveName }); - - new InventoryArchiveReadRequest(UUID.Random(), null, scene.InventoryService, scene.AssetService, scene.UserAccountService, ua1, null, (Stream)null, false) - .ReplicateArchivePathToUserInventory( - itemArchivePath, scene.InventoryService.GetRootFolder(ua1.PrincipalID), - new Dictionary(), new Dictionary()); - - List folder1PostCandidates - = InventoryArchiveUtils.FindFoldersByPath(scene.InventoryService, ua1.PrincipalID, folder1ExistingName); - Assert.That(folder1PostCandidates.Count, Is.EqualTo(2)); - - // FIXME: Temporarily, we're going to do something messy to make sure we pick up the created folder. - InventoryFolderBase folder1Post = null; - foreach (InventoryFolderBase folder in folder1PostCandidates) - { - if (folder.ID != folder1.ID) - { - folder1Post = folder; - break; - } - } -// Assert.That(folder1Post.ID, Is.EqualTo(folder1.ID)); - - List folder2PostCandidates - = InventoryArchiveUtils.FindFoldersByPath(scene.InventoryService, folder1Post, "b"); - Assert.That(folder2PostCandidates.Count, Is.EqualTo(1)); - } - - /// - /// Test replication of a partly existing archive path to the user's inventory. This should create - /// a merged path. - /// - [Test] - public void TestMergeIarPath() - { - TestHelpers.InMethod(); -// log4net.Config.XmlConfigurator.Configure(); - - Scene scene = new SceneHelpers().SetupScene(); - UserAccount ua1 = UserAccountHelpers.CreateUserWithInventory(scene); - - string folder1ExistingName = "a"; - string folder2Name = "b"; - - InventoryFolderBase folder1 - = UserInventoryHelpers.CreateInventoryFolder( - scene.InventoryService, ua1.PrincipalID, folder1ExistingName, false); - - string folder1ArchiveName = InventoryArchiveWriteRequest.CreateArchiveFolderName(folder1ExistingName, UUID.Random()); - string folder2ArchiveName = InventoryArchiveWriteRequest.CreateArchiveFolderName(folder2Name, UUID.Random()); - - string itemArchivePath = string.Join("", new string[] { folder1ArchiveName, folder2ArchiveName }); - - new InventoryArchiveReadRequest(UUID.Random(), null, scene.InventoryService, scene.AssetService, scene.UserAccountService, ua1, folder1ExistingName, (Stream)null, true) - .ReplicateArchivePathToUserInventory( - itemArchivePath, scene.InventoryService.GetRootFolder(ua1.PrincipalID), - new Dictionary(), new Dictionary()); - - List folder1PostCandidates - = InventoryArchiveUtils.FindFoldersByPath(scene.InventoryService, ua1.PrincipalID, folder1ExistingName); - Assert.That(folder1PostCandidates.Count, Is.EqualTo(1)); - Assert.That(folder1PostCandidates[0].ID, Is.EqualTo(folder1.ID)); - - List folder2PostCandidates - = InventoryArchiveUtils.FindFoldersByPath(scene.InventoryService, folder1PostCandidates[0], "b"); - Assert.That(folder2PostCandidates.Count, Is.EqualTo(1)); - } - } -} - diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveLoadTests.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveLoadTests.cs deleted file mode 100644 index d0bdc91a12f..00000000000 --- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveLoadTests.cs +++ /dev/null @@ -1,192 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections.Generic; -using System.IO; -using System.Reflection; -using System.Threading; -using NUnit.Framework; -using OpenMetaverse; -using OpenSim.Data; -using OpenSim.Framework; -using OpenSim.Framework.Serialization; -using OpenSim.Framework.Serialization.External; -using OpenSim.Region.CoreModules.Avatar.Inventory.Archiver; -using OpenSim.Region.CoreModules.World.Serialiser; -using OpenSim.Region.Framework.Scenes; -using OpenSim.Region.Framework.Scenes.Serialization; -using OpenSim.Services.Interfaces; -using OpenSim.Tests.Common; - -namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests -{ - [TestFixture] - public class InventoryArchiveLoadTests : InventoryArchiveTestCase - { - protected TestScene m_scene; - protected InventoryArchiverModule m_archiverModule; - - [SetUp] - public override void SetUp() - { - base.SetUp(); - - SerialiserModule serialiserModule = new SerialiserModule(); - m_archiverModule = new InventoryArchiverModule(); - - m_scene = new SceneHelpers().SetupScene(); - SceneHelpers.SetupSceneModules(m_scene, serialiserModule, m_archiverModule); - } - - [Test] - public void TestLoadCoalesecedItem() - { - TestHelpers.InMethod(); -// TestHelpers.EnableLogging(); - - UserAccountHelpers.CreateUserWithInventory(m_scene, m_uaLL1, "password"); - m_archiverModule.DearchiveInventory(UUID.Random(), m_uaLL1.FirstName, m_uaLL1.LastName, "/", "password", m_iarStream); - - InventoryItemBase coaItem - = InventoryArchiveUtils.FindItemByPath(m_scene.InventoryService, m_uaLL1.PrincipalID, m_coaItemName); - - Assert.That(coaItem, Is.Not.Null, "Didn't find loaded item 1"); - - string assetXml = AssetHelpers.ReadAssetAsString(m_scene.AssetService, coaItem.AssetID); - - CoalescedSceneObjects coa; - bool readResult = CoalescedSceneObjectsSerializer.TryFromXml(assetXml, out coa); - - Assert.That(readResult, Is.True); - Assert.That(coa.Count, Is.EqualTo(2)); - - List coaObjects = coa.Objects; - Assert.That(coaObjects[0].UUID, Is.EqualTo(UUID.Parse("00000000-0000-0000-0000-000000000120"))); - Assert.That(coaObjects[0].AbsolutePosition, Is.EqualTo(new Vector3(15, 30, 45))); - - Assert.That(coaObjects[1].UUID, Is.EqualTo(UUID.Parse("00000000-0000-0000-0000-000000000140"))); - Assert.That(coaObjects[1].AbsolutePosition, Is.EqualTo(new Vector3(25, 50, 75))); - } - - /// - /// Test case where a creator account exists for the creator UUID embedded in item metadata and serialized - /// objects. - /// - [Test] - public void TestLoadIarCreatorAccountPresent() - { - TestHelpers.InMethod(); -// log4net.Config.XmlConfigurator.Configure(); - - UserAccountHelpers.CreateUserWithInventory(m_scene, m_uaLL1, "meowfood"); - - m_archiverModule.DearchiveInventory(UUID.Random(), m_uaLL1.FirstName, m_uaLL1.LastName, "/", "meowfood", m_iarStream); - InventoryItemBase foundItem1 - = InventoryArchiveUtils.FindItemByPath(m_scene.InventoryService, m_uaLL1.PrincipalID, m_item1Name); - - Assert.That( - foundItem1.CreatorId, Is.EqualTo(m_uaLL1.PrincipalID.ToString()), - "Loaded item non-uuid creator doesn't match original"); - Assert.That( - foundItem1.CreatorIdAsUuid, Is.EqualTo(m_uaLL1.PrincipalID), - "Loaded item uuid creator doesn't match original"); - Assert.That(foundItem1.Owner, Is.EqualTo(m_uaLL1.PrincipalID), - "Loaded item owner doesn't match inventory reciever"); - - AssetBase asset1 = m_scene.AssetService.Get(foundItem1.AssetID.ToString()); - string xmlData = Utils.BytesToString(asset1.Data); - SceneObjectGroup sog1 = SceneObjectSerializer.FromOriginalXmlFormat(xmlData); - - Assert.That(sog1.RootPart.CreatorID, Is.EqualTo(m_uaLL1.PrincipalID)); - } - -// /// -// /// Test loading a V0.1 OpenSim Inventory Archive (subject to change since there is no fixed format yet) where -// /// an account exists with the same name as the creator, though not the same id. -// /// -// [Test] -// public void TestLoadIarV0_1SameNameCreator() -// { -// TestHelpers.InMethod(); -// TestHelpers.EnableLogging(); -// -// UserAccountHelpers.CreateUserWithInventory(m_scene, m_uaMT, "meowfood"); -// UserAccountHelpers.CreateUserWithInventory(m_scene, m_uaLL2, "hampshire"); -// -// m_archiverModule.DearchiveInventory(m_uaMT.FirstName, m_uaMT.LastName, "/", "meowfood", m_iarStream); -// InventoryItemBase foundItem1 -// = InventoryArchiveUtils.FindItemByPath(m_scene.InventoryService, m_uaMT.PrincipalID, m_item1Name); -// -// Assert.That( -// foundItem1.CreatorId, Is.EqualTo(m_uaLL2.PrincipalID.ToString()), -// "Loaded item non-uuid creator doesn't match original"); -// Assert.That( -// foundItem1.CreatorIdAsUuid, Is.EqualTo(m_uaLL2.PrincipalID), -// "Loaded item uuid creator doesn't match original"); -// Assert.That(foundItem1.Owner, Is.EqualTo(m_uaMT.PrincipalID), -// "Loaded item owner doesn't match inventory reciever"); -// -// AssetBase asset1 = m_scene.AssetService.Get(foundItem1.AssetID.ToString()); -// string xmlData = Utils.BytesToString(asset1.Data); -// SceneObjectGroup sog1 = SceneObjectSerializer.FromOriginalXmlFormat(xmlData); -// -// Assert.That(sog1.RootPart.CreatorID, Is.EqualTo(m_uaLL2.PrincipalID)); -// } - - /// - /// Test loading a V0.1 OpenSim Inventory Archive (subject to change since there is no fixed format yet) where - /// the creator or an account with the creator's name does not exist within the system. - /// - [Test] - public void TestLoadIarV0_1AbsentCreator() - { - TestHelpers.InMethod(); -// log4net.Config.XmlConfigurator.Configure(); - - UserAccountHelpers.CreateUserWithInventory(m_scene, m_uaMT, "password"); - m_archiverModule.DearchiveInventory(UUID.Random(), m_uaMT.FirstName, m_uaMT.LastName, "/", "password", m_iarStream); - - InventoryItemBase foundItem1 - = InventoryArchiveUtils.FindItemByPath(m_scene.InventoryService, m_uaMT.PrincipalID, m_item1Name); - - Assert.That(foundItem1, Is.Not.Null, "Didn't find loaded item 1"); - Assert.That( - foundItem1.CreatorId, Is.EqualTo(m_uaMT.PrincipalID.ToString()), - "Loaded item non-uuid creator doesn't match that of the loading user"); - Assert.That( - foundItem1.CreatorIdAsUuid, Is.EqualTo(m_uaMT.PrincipalID), - "Loaded item uuid creator doesn't match that of the loading user"); - - AssetBase asset1 = m_scene.AssetService.Get(foundItem1.AssetID.ToString()); - string xmlData = Utils.BytesToString(asset1.Data); - SceneObjectGroup sog1 = SceneObjectSerializer.FromOriginalXmlFormat(xmlData); - - Assert.That(sog1.RootPart.CreatorID, Is.EqualTo(m_uaMT.PrincipalID)); - } - } -} \ No newline at end of file diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveSaveTests.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveSaveTests.cs deleted file mode 100644 index bd112b43782..00000000000 --- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveSaveTests.cs +++ /dev/null @@ -1,422 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections.Generic; -using System.IO; -using System.Reflection; -using System.Threading; -using NUnit.Framework; -using OpenMetaverse; -using OpenSim.Data; -using OpenSim.Framework; -using OpenSim.Framework.Serialization; -using OpenSim.Framework.Serialization.External; -using OpenSim.Region.CoreModules.Avatar.Inventory.Archiver; -using OpenSim.Region.CoreModules.World.Serialiser; -using OpenSim.Region.Framework.Scenes; -using OpenSim.Region.Framework.Scenes.Serialization; -using OpenSim.Services.Interfaces; -using OpenSim.Tests.Common; - -namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests -{ - [TestFixture] - public class InventoryArchiveSaveTests : InventoryArchiveTestCase - { - protected TestScene m_scene; - protected InventoryArchiverModule m_archiverModule; - - [SetUp] - public override void SetUp() - { - base.SetUp(); - - SerialiserModule serialiserModule = new SerialiserModule(); - m_archiverModule = new InventoryArchiverModule(); - - m_scene = new SceneHelpers().SetupScene(); - SceneHelpers.SetupSceneModules(m_scene, serialiserModule, m_archiverModule); - } - - /// - /// Test that the IAR has the required files in the right order. - /// - /// - /// At the moment, the only thing that matters is that the control file is the very first one. - /// - [Test] - public void TestOrder() - { - TestHelpers.InMethod(); -// log4net.Config.XmlConfigurator.Configure(); - - MemoryStream archiveReadStream = new MemoryStream(m_iarStreamBytes); - TarArchiveReader tar = new TarArchiveReader(archiveReadStream); - string filePath; - TarArchiveReader.TarEntryType tarEntryType; - - byte[] data = tar.ReadEntry(out filePath, out tarEntryType); - Assert.That(filePath, Is.EqualTo(ArchiveConstants.CONTROL_FILE_PATH)); - - InventoryArchiveReadRequest iarr - = new InventoryArchiveReadRequest(UUID.Random(), null, null, null, null, null, null, (Stream)null, false); - iarr.LoadControlFile(filePath, data); - - Assert.That(iarr.ControlFileLoaded, Is.True); - } - - [Test] - public void TestSaveRootFolderToIar() - { - TestHelpers.InMethod(); -// TestHelpers.EnableLogging(); - - string userFirstName = "Jock"; - string userLastName = "Stirrup"; - string userPassword = "troll"; - UUID userId = TestHelpers.ParseTail(0x20); - - UserAccountHelpers.CreateUserWithInventory(m_scene, userFirstName, userLastName, userId, userPassword); - - MemoryStream archiveWriteStream = new MemoryStream(); - m_archiverModule.OnInventoryArchiveSaved += SaveCompleted; - - mre.Reset(); - m_archiverModule.ArchiveInventory( - UUID.Random(), userFirstName, userLastName, "/", userPassword, archiveWriteStream); - mre.WaitOne(60000, false); - - // Test created iar - byte[] archive = archiveWriteStream.ToArray(); - MemoryStream archiveReadStream = new MemoryStream(archive); - TarArchiveReader tar = new TarArchiveReader(archiveReadStream); - -// InventoryArchiveUtils. - bool gotObjectsFolder = false; - - string objectsFolderName - = string.Format( - "{0}{1}", - ArchiveConstants.INVENTORY_PATH, - InventoryArchiveWriteRequest.CreateArchiveFolderName( - UserInventoryHelpers.GetInventoryFolder(m_scene.InventoryService, userId, "Objects"))); - - string filePath; - TarArchiveReader.TarEntryType tarEntryType; - - while (tar.ReadEntry(out filePath, out tarEntryType) != null) - { -// Console.WriteLine("Got {0}", filePath); - - // Lazily, we only bother to look for the system objects folder created when we call CreateUserWithInventory() - // XXX: But really we need to stop all that stuff being created in tests or check for such folders - // more thoroughly - if (filePath == objectsFolderName) - gotObjectsFolder = true; - } - - Assert.That(gotObjectsFolder, Is.True); - } - - [Test] - public void TestSaveNonRootFolderToIar() - { - TestHelpers.InMethod(); -// TestHelpers.EnableLogging(); - - string userFirstName = "Jock"; - string userLastName = "Stirrup"; - string userPassword = "troll"; - UUID userId = TestHelpers.ParseTail(0x20); - - UserAccountHelpers.CreateUserWithInventory(m_scene, userFirstName, userLastName, userId, userPassword); - - // Create base folder - InventoryFolderBase f1 - = UserInventoryHelpers.CreateInventoryFolder(m_scene.InventoryService, userId, "f1", true); - - // Create item1 - SceneObjectGroup so1 = SceneHelpers.CreateSceneObject(1, userId, "My Little Dog Object", 0x5); - InventoryItemBase i1 = UserInventoryHelpers.AddInventoryItem(m_scene, so1, 0x50, 0x60, "f1"); - - // Create embedded folder - InventoryFolderBase f1_1 - = UserInventoryHelpers.CreateInventoryFolder(m_scene.InventoryService, userId, "f1/f1.1", true); - - // Create embedded item - SceneObjectGroup so1_1 = SceneHelpers.CreateSceneObject(1, userId, "My Little Cat Object", 0x6); - InventoryItemBase i2 = UserInventoryHelpers.AddInventoryItem(m_scene, so1_1, 0x500, 0x600, "f1/f1.1"); - - MemoryStream archiveWriteStream = new MemoryStream(); - m_archiverModule.OnInventoryArchiveSaved += SaveCompleted; - - mre.Reset(); - m_archiverModule.ArchiveInventory( - UUID.Random(), userFirstName, userLastName, "f1", userPassword, archiveWriteStream); - mre.WaitOne(60000, false); - - // Test created iar - byte[] archive = archiveWriteStream.ToArray(); - MemoryStream archiveReadStream = new MemoryStream(archive); - TarArchiveReader tar = new TarArchiveReader(archiveReadStream); - -// InventoryArchiveUtils. - bool gotf1 = false, gotf1_1 = false, gotso1 = false, gotso2 = false; - - string f1FileName - = string.Format("{0}{1}", ArchiveConstants.INVENTORY_PATH, InventoryArchiveWriteRequest.CreateArchiveFolderName(f1)); - string f1_1FileName - = string.Format("{0}{1}", f1FileName, InventoryArchiveWriteRequest.CreateArchiveFolderName(f1_1)); - string so1FileName - = string.Format("{0}{1}", f1FileName, InventoryArchiveWriteRequest.CreateArchiveItemName(i1)); - string so2FileName - = string.Format("{0}{1}", f1_1FileName, InventoryArchiveWriteRequest.CreateArchiveItemName(i2)); - - string filePath; - TarArchiveReader.TarEntryType tarEntryType; - - while (tar.ReadEntry(out filePath, out tarEntryType) != null) - { -// Console.WriteLine("Got {0}", filePath); - - if (filePath == f1FileName) - gotf1 = true; - else if (filePath == f1_1FileName) - gotf1_1 = true; - else if (filePath == so1FileName) - gotso1 = true; - else if (filePath == so2FileName) - gotso2 = true; - } - -// Assert.That(gotControlFile, Is.True, "No control file in archive"); - Assert.That(gotf1, Is.True); - Assert.That(gotf1_1, Is.True); - Assert.That(gotso1, Is.True); - Assert.That(gotso2, Is.True); - - // TODO: Test presence of more files and contents of files. - } - - /// - /// Test saving a single inventory item to an IAR - /// (subject to change since there is no fixed format yet). - /// - [Test] - public void TestSaveItemToIar() - { - TestHelpers.InMethod(); -// log4net.Config.XmlConfigurator.Configure(); - - // Create user - string userFirstName = "Jock"; - string userLastName = "Stirrup"; - string userPassword = "troll"; - UUID userId = UUID.Parse("00000000-0000-0000-0000-000000000020"); - UserAccountHelpers.CreateUserWithInventory(m_scene, userFirstName, userLastName, userId, userPassword); - - // Create asset - UUID ownerId = UUID.Parse("00000000-0000-0000-0000-000000000040"); - SceneObjectGroup object1 = SceneHelpers.CreateSceneObject(1, ownerId, "My Little Dog Object", 0x50); - - UUID asset1Id = UUID.Parse("00000000-0000-0000-0000-000000000060"); - AssetBase asset1 = AssetHelpers.CreateAsset(asset1Id, object1); - m_scene.AssetService.Store(asset1); - - // Create item - UUID item1Id = UUID.Parse("00000000-0000-0000-0000-000000000080"); - string item1Name = "My Little Dog"; - InventoryItemBase item1 = new InventoryItemBase(); - item1.Name = item1Name; - item1.AssetID = asset1.FullID; - item1.ID = item1Id; - InventoryFolderBase objsFolder - = InventoryArchiveUtils.FindFoldersByPath(m_scene.InventoryService, userId, "Objects")[0]; - item1.Folder = objsFolder.ID; - m_scene.AddInventoryItem(item1); - - MemoryStream archiveWriteStream = new MemoryStream(); - m_archiverModule.OnInventoryArchiveSaved += SaveCompleted; - - mre.Reset(); - m_archiverModule.ArchiveInventory( - UUID.Random(), userFirstName, userLastName, "Objects/" + item1Name, userPassword, archiveWriteStream); - mre.WaitOne(60000, false); - - byte[] archive = archiveWriteStream.ToArray(); - MemoryStream archiveReadStream = new MemoryStream(archive); - TarArchiveReader tar = new TarArchiveReader(archiveReadStream); - - //bool gotControlFile = false; - bool gotObject1File = false; - //bool gotObject2File = false; - string expectedObject1FileName = InventoryArchiveWriteRequest.CreateArchiveItemName(item1); - string expectedObject1FilePath = string.Format( - "{0}{1}", - ArchiveConstants.INVENTORY_PATH, - expectedObject1FileName); - - string filePath; - TarArchiveReader.TarEntryType tarEntryType; - -// Console.WriteLine("Reading archive"); - - while (tar.ReadEntry(out filePath, out tarEntryType) != null) - { - Console.WriteLine("Got {0}", filePath); - -// if (ArchiveConstants.CONTROL_FILE_PATH == filePath) -// { -// gotControlFile = true; -// } - - if (filePath.StartsWith(ArchiveConstants.INVENTORY_PATH) && filePath.EndsWith(".xml")) - { -// string fileName = filePath.Remove(0, "Objects/".Length); -// -// if (fileName.StartsWith(part1.Name)) -// { - Assert.That(expectedObject1FilePath, Is.EqualTo(filePath)); - gotObject1File = true; -// } -// else if (fileName.StartsWith(part2.Name)) -// { -// Assert.That(fileName, Is.EqualTo(expectedObject2FileName)); -// gotObject2File = true; -// } - } - } - -// Assert.That(gotControlFile, Is.True, "No control file in archive"); - Assert.That(gotObject1File, Is.True, "No item1 file in archive"); -// Assert.That(gotObject2File, Is.True, "No object2 file in archive"); - - // TODO: Test presence of more files and contents of files. - } - - /// - /// Test saving a single inventory item to an IAR without its asset - /// - [Test] - public void TestSaveItemToIarNoAssets() - { - TestHelpers.InMethod(); -// log4net.Config.XmlConfigurator.Configure(); - - // Create user - string userFirstName = "Jock"; - string userLastName = "Stirrup"; - string userPassword = "troll"; - UUID userId = UUID.Parse("00000000-0000-0000-0000-000000000020"); - UserAccountHelpers.CreateUserWithInventory(m_scene, userFirstName, userLastName, userId, userPassword); - - // Create asset - UUID ownerId = UUID.Parse("00000000-0000-0000-0000-000000000040"); - SceneObjectGroup object1 = SceneHelpers.CreateSceneObject(1, ownerId, "My Little Dog Object", 0x50); - - UUID asset1Id = UUID.Parse("00000000-0000-0000-0000-000000000060"); - AssetBase asset1 = AssetHelpers.CreateAsset(asset1Id, object1); - m_scene.AssetService.Store(asset1); - - // Create item - UUID item1Id = UUID.Parse("00000000-0000-0000-0000-000000000080"); - string item1Name = "My Little Dog"; - InventoryItemBase item1 = new InventoryItemBase(); - item1.Name = item1Name; - item1.AssetID = asset1.FullID; - item1.ID = item1Id; - InventoryFolderBase objsFolder - = InventoryArchiveUtils.FindFoldersByPath(m_scene.InventoryService, userId, "Objects")[0]; - item1.Folder = objsFolder.ID; - m_scene.AddInventoryItem(item1); - - MemoryStream archiveWriteStream = new MemoryStream(); - - Dictionary options = new Dictionary(); - options.Add("noassets", true); - - // When we're not saving assets, archiving is being done synchronously. - m_archiverModule.ArchiveInventory( - UUID.Random(), userFirstName, userLastName, "Objects/" + item1Name, userPassword, archiveWriteStream, options); - - byte[] archive = archiveWriteStream.ToArray(); - MemoryStream archiveReadStream = new MemoryStream(archive); - TarArchiveReader tar = new TarArchiveReader(archiveReadStream); - - //bool gotControlFile = false; - bool gotObject1File = false; - //bool gotObject2File = false; - string expectedObject1FileName = InventoryArchiveWriteRequest.CreateArchiveItemName(item1); - string expectedObject1FilePath = string.Format( - "{0}{1}", - ArchiveConstants.INVENTORY_PATH, - expectedObject1FileName); - - string filePath; - TarArchiveReader.TarEntryType tarEntryType; - -// Console.WriteLine("Reading archive"); - - while (tar.ReadEntry(out filePath, out tarEntryType) != null) - { - Console.WriteLine("Got {0}", filePath); - -// if (ArchiveConstants.CONTROL_FILE_PATH == filePath) -// { -// gotControlFile = true; -// } - - if (filePath.StartsWith(ArchiveConstants.INVENTORY_PATH) && filePath.EndsWith(".xml")) - { -// string fileName = filePath.Remove(0, "Objects/".Length); -// -// if (fileName.StartsWith(part1.Name)) -// { - Assert.That(expectedObject1FilePath, Is.EqualTo(filePath)); - gotObject1File = true; -// } -// else if (fileName.StartsWith(part2.Name)) -// { -// Assert.That(fileName, Is.EqualTo(expectedObject2FileName)); -// gotObject2File = true; -// } - } - else if (filePath.StartsWith(ArchiveConstants.ASSETS_PATH)) - { - Assert.Fail("Found asset path in TestSaveItemToIarNoAssets()"); - } - } - -// Assert.That(gotControlFile, Is.True, "No control file in archive"); - Assert.That(gotObject1File, Is.True, "No item1 file in archive"); -// Assert.That(gotObject2File, Is.True, "No object2 file in archive"); - - // TODO: Test presence of more files and contents of files. - } - } -} \ No newline at end of file diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveTestCase.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveTestCase.cs deleted file mode 100644 index ec36e3e4ff6..00000000000 --- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveTestCase.cs +++ /dev/null @@ -1,176 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections.Generic; -using System.IO; -using System.Reflection; -using System.Threading; -using NUnit.Framework; -using OpenMetaverse; -using OpenSim.Data; -using OpenSim.Framework; -using OpenSim.Framework.Serialization; -using OpenSim.Framework.Serialization.External; -using OpenSim.Region.CoreModules.Avatar.Inventory.Archiver; -using OpenSim.Region.CoreModules.World.Serialiser; -using OpenSim.Region.Framework.Scenes; -using OpenSim.Region.Framework.Scenes.Serialization; -using OpenSim.Services.Interfaces; -using OpenSim.Tests.Common; - -namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests -{ - [TestFixture] - public class InventoryArchiveTestCase : OpenSimTestCase - { - protected ManualResetEvent mre = new ManualResetEvent(false); - - /// - /// A raw array of bytes that we'll use to create an IAR memory stream suitable for isolated use in each test. - /// - protected byte[] m_iarStreamBytes; - - /// - /// Stream of data representing a common IAR for load tests. - /// - protected MemoryStream m_iarStream; - - protected UserAccount m_uaMT - = new UserAccount { - PrincipalID = UUID.Parse("00000000-0000-0000-0000-000000000555"), - FirstName = "Mr", - LastName = "Tiddles" }; - - protected UserAccount m_uaLL1 - = new UserAccount { - PrincipalID = UUID.Parse("00000000-0000-0000-0000-000000000666"), - FirstName = "Lord", - LastName = "Lucan" }; - - protected UserAccount m_uaLL2 - = new UserAccount { - PrincipalID = UUID.Parse("00000000-0000-0000-0000-000000000777"), - FirstName = "Lord", - LastName = "Lucan" }; - - protected string m_item1Name = "Ray Gun Item"; - protected string m_coaItemName = "Coalesced Item"; - - [OneTimeSetUp] - public void FixtureSetup() - { - // Don't allow tests to be bamboozled by asynchronous events. Execute everything on the same thread. - Util.FireAndForgetMethod = FireAndForgetMethod.RegressionTest; - - ConstructDefaultIarBytesForTestLoad(); - } - - [OneTimeTearDown] - public void TearDown() - { - // We must set this back afterwards, otherwise later tests will fail since they're expecting multiple - // threads. Possibly, later tests should be rewritten so none of them require async stuff (which regression - // tests really shouldn't). - Util.FireAndForgetMethod = Util.DefaultFireAndForgetMethod; - } - - [SetUp] - public override void SetUp() - { - base.SetUp(); - m_iarStream = new MemoryStream(m_iarStreamBytes); - } - - protected void ConstructDefaultIarBytesForTestLoad() - { -// log4net.Config.XmlConfigurator.Configure(); - - InventoryArchiverModule archiverModule = new InventoryArchiverModule(); - Scene scene = new SceneHelpers().SetupScene(); - SceneHelpers.SetupSceneModules(scene, archiverModule); - - UserAccountHelpers.CreateUserWithInventory(scene, m_uaLL1, "hampshire"); - - MemoryStream archiveWriteStream = new MemoryStream(); - - // Create scene object asset - UUID ownerId = UUID.Parse("00000000-0000-0000-0000-000000000040"); - SceneObjectGroup object1 = SceneHelpers.CreateSceneObject(1, ownerId, "Ray Gun Object", 0x50); - - UUID asset1Id = UUID.Parse("00000000-0000-0000-0000-000000000060"); - AssetBase asset1 = AssetHelpers.CreateAsset(asset1Id, object1); - scene.AssetService.Store(asset1); - - // Create scene object item - InventoryItemBase item1 = new InventoryItemBase(); - item1.Name = m_item1Name; - item1.ID = UUID.Parse("00000000-0000-0000-0000-000000000020"); - item1.AssetID = asset1.FullID; - item1.GroupID = UUID.Random(); - item1.CreatorId = m_uaLL1.PrincipalID.ToString(); - item1.Owner = m_uaLL1.PrincipalID; - item1.Folder = scene.InventoryService.GetRootFolder(m_uaLL1.PrincipalID).ID; - scene.AddInventoryItem(item1); - - // Create coalesced objects asset - SceneObjectGroup cobj1 = SceneHelpers.CreateSceneObject(1, m_uaLL1.PrincipalID, "Object1", 0x120); - cobj1.AbsolutePosition = new Vector3(15, 30, 45); - - SceneObjectGroup cobj2 = SceneHelpers.CreateSceneObject(1, m_uaLL1.PrincipalID, "Object2", 0x140); - cobj2.AbsolutePosition = new Vector3(25, 50, 75); - - CoalescedSceneObjects coa = new CoalescedSceneObjects(m_uaLL1.PrincipalID, cobj1, cobj2); - - AssetBase coaAsset = AssetHelpers.CreateAsset(0x160, coa); - scene.AssetService.Store(coaAsset); - - // Create coalesced objects inventory item - InventoryItemBase coaItem = new InventoryItemBase(); - coaItem.Name = m_coaItemName; - coaItem.ID = UUID.Parse("00000000-0000-0000-0000-000000000180"); - coaItem.AssetID = coaAsset.FullID; - coaItem.GroupID = UUID.Random(); - coaItem.CreatorId = m_uaLL1.PrincipalID.ToString(); - coaItem.Owner = m_uaLL1.PrincipalID; - coaItem.Folder = scene.InventoryService.GetRootFolder(m_uaLL1.PrincipalID).ID; - scene.AddInventoryItem(coaItem); - - archiverModule.ArchiveInventory( - UUID.Random(), m_uaLL1.FirstName, m_uaLL1.LastName, "/*", "hampshire", archiveWriteStream); - - m_iarStreamBytes = archiveWriteStream.ToArray(); - } - - protected void SaveCompleted( - UUID id, bool succeeded, UserAccount userInfo, string invPath, Stream saveStream, - Exception reportedException, int SaveCount, int FilterCount) - { - mre.Set(); - } - } -} \ No newline at end of file diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/Tests/InventoryTransferModuleTests.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/Tests/InventoryTransferModuleTests.cs deleted file mode 100644 index 82ed0918aa1..00000000000 --- a/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/Tests/InventoryTransferModuleTests.cs +++ /dev/null @@ -1,448 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections.Generic; -using System.Reflection; -using log4net.Config; -using Nini.Config; -using NUnit.Framework; -using OpenMetaverse; -using OpenMetaverse.Assets; -using OpenSim.Framework; -using OpenSim.Region.CoreModules.Avatar.Inventory.Transfer; -using OpenSim.Region.Framework.Interfaces; -using OpenSim.Region.Framework.Scenes; -using OpenSim.Services.Interfaces; -using OpenSim.Tests.Common; - -namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer.Tests -{ - [TestFixture] - public class InventoryTransferModuleTests : OpenSimTestCase - { - protected TestScene m_scene; - - [SetUp] - public override void SetUp() - { - base.SetUp(); - - IConfigSource config = new IniConfigSource(); - config.AddConfig("Messaging"); - config.Configs["Messaging"].Set("InventoryTransferModule", "InventoryTransferModule"); - - m_scene = new SceneHelpers().SetupScene(); - SceneHelpers.SetupSceneModules(m_scene, config, new InventoryTransferModule()); - } - - [Test] - public void TestAcceptGivenItem() - { -// TestHelpers.EnableLogging(); - - UUID initialSessionId = TestHelpers.ParseTail(0x10); - UUID itemId = TestHelpers.ParseTail(0x100); - UUID assetId = TestHelpers.ParseTail(0x200); - - UserAccount ua1 - = UserAccountHelpers.CreateUserWithInventory(m_scene, "User", "One", TestHelpers.ParseTail(0x1), "pw"); - UserAccount ua2 - = UserAccountHelpers.CreateUserWithInventory(m_scene, "User", "Two", TestHelpers.ParseTail(0x2), "pw"); - - ScenePresence giverSp = SceneHelpers.AddScenePresence(m_scene, ua1); - TestClient giverClient = (TestClient)giverSp.ControllingClient; - - ScenePresence receiverSp = SceneHelpers.AddScenePresence(m_scene, ua2); - TestClient receiverClient = (TestClient)receiverSp.ControllingClient; - - // Create the object to test give - InventoryItemBase originalItem - = UserInventoryHelpers.CreateInventoryItem( - m_scene, "givenObj", itemId, assetId, giverSp.UUID, InventoryType.Object); - - byte[] giveImBinaryBucket = new byte[17]; - byte[] itemIdBytes = itemId.GetBytes(); - Array.Copy(itemIdBytes, 0, giveImBinaryBucket, 1, itemIdBytes.Length); - - GridInstantMessage giveIm - = new GridInstantMessage( - m_scene, - giverSp.UUID, - giverSp.Name, - receiverSp.UUID, - (byte)InstantMessageDialog.InventoryOffered, - false, - "inventory offered msg", - initialSessionId, - false, - Vector3.Zero, - giveImBinaryBucket, - true); - - giverClient.HandleImprovedInstantMessage(giveIm); - - // These details might not all be correct. - GridInstantMessage acceptIm - = new GridInstantMessage( - m_scene, - receiverSp.UUID, - receiverSp.Name, - giverSp.UUID, - (byte)InstantMessageDialog.InventoryAccepted, - false, - "inventory accepted msg", - initialSessionId, - false, - Vector3.Zero, - null, - true); - - receiverClient.HandleImprovedInstantMessage(acceptIm); - - // Test for item remaining in the giver's inventory (here we assume a copy item) - // TODO: Test no-copy items. - InventoryItemBase originalItemAfterGive - = UserInventoryHelpers.GetInventoryItem(m_scene.InventoryService, giverSp.UUID, "Objects/givenObj"); - - Assert.That(originalItemAfterGive, Is.Not.Null); - Assert.That(originalItemAfterGive.ID, Is.EqualTo(originalItem.ID)); - - // Test for item successfully making it into the receiver's inventory - InventoryItemBase receivedItem - = UserInventoryHelpers.GetInventoryItem(m_scene.InventoryService, receiverSp.UUID, "Objects/givenObj"); - - Assert.That(receivedItem, Is.Not.Null); - Assert.That(receivedItem.ID, Is.Not.EqualTo(originalItem.ID)); - - // Test that on a delete, item still exists and is accessible for the giver. - m_scene.InventoryService.DeleteItems(receiverSp.UUID, new List() { receivedItem.ID }); - - InventoryItemBase originalItemAfterDelete - = UserInventoryHelpers.GetInventoryItem(m_scene.InventoryService, giverSp.UUID, "Objects/givenObj"); - - Assert.That(originalItemAfterDelete, Is.Not.Null); - - // TODO: Test scenario where giver deletes their item first. - } - - /// - /// Test user rejection of a given item. - /// - /// - /// A rejected item still ends up in the user's trash folder. - /// - [Test] - public void TestRejectGivenItem() - { -// TestHelpers.EnableLogging(); - - UUID initialSessionId = TestHelpers.ParseTail(0x10); - UUID itemId = TestHelpers.ParseTail(0x100); - UUID assetId = TestHelpers.ParseTail(0x200); - - UserAccount ua1 - = UserAccountHelpers.CreateUserWithInventory(m_scene, "User", "One", TestHelpers.ParseTail(0x1), "pw"); - UserAccount ua2 - = UserAccountHelpers.CreateUserWithInventory(m_scene, "User", "Two", TestHelpers.ParseTail(0x2), "pw"); - - ScenePresence giverSp = SceneHelpers.AddScenePresence(m_scene, ua1); - TestClient giverClient = (TestClient)giverSp.ControllingClient; - - ScenePresence receiverSp = SceneHelpers.AddScenePresence(m_scene, ua2); - TestClient receiverClient = (TestClient)receiverSp.ControllingClient; - - // Create the object to test give - InventoryItemBase originalItem - = UserInventoryHelpers.CreateInventoryItem( - m_scene, "givenObj", itemId, assetId, giverSp.UUID, InventoryType.Object); - - GridInstantMessage receivedIm = null; - receiverClient.OnReceivedInstantMessage += im => receivedIm = im; - - byte[] giveImBinaryBucket = new byte[17]; - byte[] itemIdBytes = itemId.GetBytes(); - Array.Copy(itemIdBytes, 0, giveImBinaryBucket, 1, itemIdBytes.Length); - - GridInstantMessage giveIm - = new GridInstantMessage( - m_scene, - giverSp.UUID, - giverSp.Name, - receiverSp.UUID, - (byte)InstantMessageDialog.InventoryOffered, - false, - "inventory offered msg", - initialSessionId, - false, - Vector3.Zero, - giveImBinaryBucket, - true); - - giverClient.HandleImprovedInstantMessage(giveIm); - - // These details might not all be correct. - // Session ID is now the created item ID (!) - GridInstantMessage rejectIm - = new GridInstantMessage( - m_scene, - receiverSp.UUID, - receiverSp.Name, - giverSp.UUID, - (byte)InstantMessageDialog.InventoryDeclined, - false, - "inventory declined msg", - new UUID(receivedIm.imSessionID), - false, - Vector3.Zero, - null, - true); - - receiverClient.HandleImprovedInstantMessage(rejectIm); - - // Test for item remaining in the giver's inventory (here we assume a copy item) - // TODO: Test no-copy items. - InventoryItemBase originalItemAfterGive - = UserInventoryHelpers.GetInventoryItem(m_scene.InventoryService, giverSp.UUID, "Objects/givenObj"); - - Assert.That(originalItemAfterGive, Is.Not.Null); - Assert.That(originalItemAfterGive.ID, Is.EqualTo(originalItem.ID)); - - // Test for item successfully making it into the receiver's inventory - InventoryItemBase receivedItem - = UserInventoryHelpers.GetInventoryItem(m_scene.InventoryService, receiverSp.UUID, "Trash/givenObj"); - - InventoryFolderBase trashFolder - = m_scene.InventoryService.GetFolderForType(receiverSp.UUID, FolderType.Trash); - - Assert.That(receivedItem, Is.Not.Null); - Assert.That(receivedItem.ID, Is.Not.EqualTo(originalItem.ID)); - Assert.That(receivedItem.Folder, Is.EqualTo(trashFolder.ID)); - - // Test that on a delete, item still exists and is accessible for the giver. - m_scene.InventoryService.PurgeFolder(trashFolder); - - InventoryItemBase originalItemAfterDelete - = UserInventoryHelpers.GetInventoryItem(m_scene.InventoryService, giverSp.UUID, "Objects/givenObj"); - - Assert.That(originalItemAfterDelete, Is.Not.Null); - } - - [Test] - public void TestAcceptGivenFolder() - { - TestHelpers.InMethod(); -// TestHelpers.EnableLogging(); - - UUID initialSessionId = TestHelpers.ParseTail(0x10); - UUID folderId = TestHelpers.ParseTail(0x100); - - UserAccount ua1 - = UserAccountHelpers.CreateUserWithInventory(m_scene, "User", "One", TestHelpers.ParseTail(0x1), "pw"); - UserAccount ua2 - = UserAccountHelpers.CreateUserWithInventory(m_scene, "User", "Two", TestHelpers.ParseTail(0x2), "pw"); - - ScenePresence giverSp = SceneHelpers.AddScenePresence(m_scene, ua1); - TestClient giverClient = (TestClient)giverSp.ControllingClient; - - ScenePresence receiverSp = SceneHelpers.AddScenePresence(m_scene, ua2); - TestClient receiverClient = (TestClient)receiverSp.ControllingClient; - - InventoryFolderBase originalFolder - = UserInventoryHelpers.CreateInventoryFolder( - m_scene.InventoryService, giverSp.UUID, folderId, "f1", true); - - byte[] giveImBinaryBucket = new byte[17]; - giveImBinaryBucket[0] = (byte)AssetType.Folder; - byte[] itemIdBytes = folderId.GetBytes(); - Array.Copy(itemIdBytes, 0, giveImBinaryBucket, 1, itemIdBytes.Length); - - GridInstantMessage giveIm - = new GridInstantMessage( - m_scene, - giverSp.UUID, - giverSp.Name, - receiverSp.UUID, - (byte)InstantMessageDialog.InventoryOffered, - false, - "inventory offered msg", - initialSessionId, - false, - Vector3.Zero, - giveImBinaryBucket, - true); - - giverClient.HandleImprovedInstantMessage(giveIm); - - // These details might not all be correct. - GridInstantMessage acceptIm - = new GridInstantMessage( - m_scene, - receiverSp.UUID, - receiverSp.Name, - giverSp.UUID, - (byte)InstantMessageDialog.InventoryAccepted, - false, - "inventory accepted msg", - initialSessionId, - false, - Vector3.Zero, - null, - true); - - receiverClient.HandleImprovedInstantMessage(acceptIm); - - // Test for item remaining in the giver's inventory (here we assume a copy item) - // TODO: Test no-copy items. - InventoryFolderBase originalFolderAfterGive - = UserInventoryHelpers.GetInventoryFolder(m_scene.InventoryService, giverSp.UUID, "f1"); - - Assert.That(originalFolderAfterGive, Is.Not.Null); - Assert.That(originalFolderAfterGive.ID, Is.EqualTo(originalFolder.ID)); - - // Test for item successfully making it into the receiver's inventory - InventoryFolderBase receivedFolder - = UserInventoryHelpers.GetInventoryFolder(m_scene.InventoryService, receiverSp.UUID, "f1"); - - Assert.That(receivedFolder, Is.Not.Null); - Assert.That(receivedFolder.ID, Is.Not.EqualTo(originalFolder.ID)); - - // Test that on a delete, item still exists and is accessible for the giver. - m_scene.InventoryService.DeleteFolders(receiverSp.UUID, new List() { receivedFolder.ID }); - - InventoryFolderBase originalFolderAfterDelete - = UserInventoryHelpers.GetInventoryFolder(m_scene.InventoryService, giverSp.UUID, "f1"); - - Assert.That(originalFolderAfterDelete, Is.Not.Null); - - // TODO: Test scenario where giver deletes their item first. - } - - /// - /// Test user rejection of a given item. - /// - /// - /// A rejected item still ends up in the user's trash folder. - /// - [Test] - public void TestRejectGivenFolder() - { - TestHelpers.InMethod(); -// TestHelpers.EnableLogging(); - - UUID initialSessionId = TestHelpers.ParseTail(0x10); - UUID folderId = TestHelpers.ParseTail(0x100); - - UserAccount ua1 - = UserAccountHelpers.CreateUserWithInventory(m_scene, "User", "One", TestHelpers.ParseTail(0x1), "pw"); - UserAccount ua2 - = UserAccountHelpers.CreateUserWithInventory(m_scene, "User", "Two", TestHelpers.ParseTail(0x2), "pw"); - - ScenePresence giverSp = SceneHelpers.AddScenePresence(m_scene, ua1); - TestClient giverClient = (TestClient)giverSp.ControllingClient; - - ScenePresence receiverSp = SceneHelpers.AddScenePresence(m_scene, ua2); - TestClient receiverClient = (TestClient)receiverSp.ControllingClient; - - // Create the folder to test give - InventoryFolderBase originalFolder - = UserInventoryHelpers.CreateInventoryFolder( - m_scene.InventoryService, giverSp.UUID, folderId, "f1", true); - - GridInstantMessage receivedIm = null; - receiverClient.OnReceivedInstantMessage += im => receivedIm = im; - - byte[] giveImBinaryBucket = new byte[17]; - giveImBinaryBucket[0] = (byte)AssetType.Folder; - byte[] itemIdBytes = folderId.GetBytes(); - Array.Copy(itemIdBytes, 0, giveImBinaryBucket, 1, itemIdBytes.Length); - - GridInstantMessage giveIm - = new GridInstantMessage( - m_scene, - giverSp.UUID, - giverSp.Name, - receiverSp.UUID, - (byte)InstantMessageDialog.InventoryOffered, - false, - "inventory offered msg", - initialSessionId, - false, - Vector3.Zero, - giveImBinaryBucket, - true); - - giverClient.HandleImprovedInstantMessage(giveIm); - - // These details might not all be correct. - // Session ID is now the created item ID (!) - GridInstantMessage rejectIm - = new GridInstantMessage( - m_scene, - receiverSp.UUID, - receiverSp.Name, - giverSp.UUID, - (byte)InstantMessageDialog.InventoryDeclined, - false, - "inventory declined msg", - new UUID(receivedIm.imSessionID), - false, - Vector3.Zero, - null, - true); - - receiverClient.HandleImprovedInstantMessage(rejectIm); - - // Test for item remaining in the giver's inventory (here we assume a copy item) - // TODO: Test no-copy items. - InventoryFolderBase originalFolderAfterGive - = UserInventoryHelpers.GetInventoryFolder(m_scene.InventoryService, giverSp.UUID, "f1"); - - Assert.That(originalFolderAfterGive, Is.Not.Null); - Assert.That(originalFolderAfterGive.ID, Is.EqualTo(originalFolder.ID)); - - // Test for folder successfully making it into the receiver's inventory - InventoryFolderBase receivedFolder - = UserInventoryHelpers.GetInventoryFolder(m_scene.InventoryService, receiverSp.UUID, "Trash/f1"); - - InventoryFolderBase trashFolder - = m_scene.InventoryService.GetFolderForType(receiverSp.UUID, FolderType.Trash); - - Assert.That(receivedFolder, Is.Not.Null); - Assert.That(receivedFolder.ID, Is.Not.EqualTo(originalFolder.ID)); - Assert.That(receivedFolder.ParentID, Is.EqualTo(trashFolder.ID)); - - // Test that on a delete, item still exists and is accessible for the giver. - m_scene.InventoryService.PurgeFolder(trashFolder); - - InventoryFolderBase originalFolderAfterDelete - = UserInventoryHelpers.GetInventoryFolder(m_scene.InventoryService, giverSp.UUID, "f1"); - - Assert.That(originalFolderAfterDelete, Is.Not.Null); - } - } -} \ No newline at end of file diff --git a/OpenSim/Region/CoreModules/Framework/InventoryAccess/Tests/HGAssetMapperTests.cs b/OpenSim/Region/CoreModules/Framework/InventoryAccess/Tests/HGAssetMapperTests.cs deleted file mode 100644 index 7515e0edd0d..00000000000 --- a/OpenSim/Region/CoreModules/Framework/InventoryAccess/Tests/HGAssetMapperTests.cs +++ /dev/null @@ -1,148 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Threading; -using System.Xml; -using Nini.Config; -using NUnit.Framework; -using OpenMetaverse; -using OpenSim.Framework; -using OpenSim.Region.CoreModules.Framework.InventoryAccess; -using OpenSim.Region.Framework.Scenes; -//using OpenSim.Region.ScriptEngine.XEngine; -using OpenSim.Services.Interfaces; -using OpenSim.Tests.Common; - -namespace OpenSim.Region.CoreModules.Framework.InventoryAccess.Tests -{ - [TestFixture] - public class HGAssetMapperTests : OpenSimTestCase - { - /* - [Test] - public void TestPostAssetRewrite() - { - TestHelpers.InMethod(); -// TestHelpers.EnableLogging(); - - XEngine xengine = new XEngine(); - xengine.DebugLevel = 1; - - IniConfigSource configSource = new IniConfigSource(); - - IConfig startupConfig = configSource.AddConfig("Startup"); - startupConfig.Set("DefaultScriptEngine", "XEngine"); - - IConfig xEngineConfig = configSource.AddConfig("XEngine"); - xEngineConfig.Set("Enabled", "true"); - xEngineConfig.Set("StartDelay", "0"); - xEngineConfig.Set("AppDomainLoading", "false"); - - string homeUrl = "http://hg.HomeTestPostAssetRewriteGrid.com"; - string foreignUrl = "http://hg.ForeignTestPostAssetRewriteGrid.com"; - int soIdTail = 0x1; - UUID assetId = TestHelpers.ParseTail(0x10); - UUID userId = TestHelpers.ParseTail(0x100); - UUID sceneId = TestHelpers.ParseTail(0x1000); - string userFirstName = "TestPostAsset"; - string userLastName = "Rewrite"; - int soPartsCount = 3; - - Scene scene = new SceneHelpers().SetupScene("TestPostAssetRewriteScene", sceneId, 1000, 1000, configSource); - SceneHelpers.SetupSceneModules(scene, configSource, xengine); - scene.StartScripts(); - - HGAssetMapper hgam = new HGAssetMapper(scene, homeUrl); - UserAccount ua - = UserAccountHelpers.CreateUserWithInventory(scene, userFirstName, userLastName, userId, "password"); - - SceneObjectGroup so = SceneHelpers.AddSceneObject(scene, soPartsCount, ua.PrincipalID, "part", soIdTail); - RezScript( - scene, so.UUID, "default { state_entry() { llSay(0, \"Hello World\"); } }", "item1", ua.PrincipalID); - - AssetBase asset = AssetHelpers.CreateAsset(assetId, so); - asset.CreatorID = foreignUrl; - hgam.PostAsset(foreignUrl, asset); - - // Check transformed asset. - AssetBase ncAssetGet = scene.AssetService.Get(assetId.ToString()); - Assert.AreEqual(foreignUrl, ncAssetGet.CreatorID); - string xmlData = Utils.BytesToString(ncAssetGet.Data); - XmlDocument ncAssetGetXmlDoc = new XmlDocument(); - ncAssetGetXmlDoc.LoadXml(xmlData); - - // Console.WriteLine(ncAssetGetXmlDoc.OuterXml); - - XmlNodeList creatorDataNodes = ncAssetGetXmlDoc.GetElementsByTagName("CreatorData"); - - Assert.AreEqual(soPartsCount, creatorDataNodes.Count); - //Console.WriteLine("creatorDataNodes {0}", creatorDataNodes.Count); - - foreach (XmlNode creatorDataNode in creatorDataNodes) - { - Assert.AreEqual( - string.Format("{0};{1} {2}", homeUrl, ua.FirstName, ua.LastName), creatorDataNode.InnerText); - } - - // Check that saved script nodes have attributes - XmlNodeList savedScriptStateNodes = ncAssetGetXmlDoc.GetElementsByTagName("SavedScriptState"); - - Assert.AreEqual(1, savedScriptStateNodes.Count); - Assert.AreEqual(1, savedScriptStateNodes[0].Attributes.Count); - XmlNode uuidAttribute = savedScriptStateNodes[0].Attributes.GetNamedItem("UUID"); - Assert.NotNull(uuidAttribute); - // XXX: To check the actual UUID attribute we would have to do some work to retreive the UUID of the task - // item created earlier. - } - - private void RezScript(Scene scene, UUID soId, string script, string itemName, UUID userId) - { - InventoryItemBase itemTemplate = new InventoryItemBase(); - // itemTemplate.ID = itemId; - itemTemplate.Name = itemName; - itemTemplate.Folder = soId; - itemTemplate.InvType = (int)InventoryType.LSL; - - // XXX: Ultimately it would be better to be able to directly manipulate the script engine to rez a script - // immediately for tests rather than chunter through it's threaded mechanisms. - AutoResetEvent chatEvent = new AutoResetEvent(false); - - scene.EventManager.OnChatFromWorld += (s, c) => - { -// Console.WriteLine("Got chat [{0}]", c.Message); - chatEvent.Set(); - }; - - scene.RezNewScript(userId, itemTemplate, script); - -// Console.WriteLine("HERE"); - Assert.IsTrue(chatEvent.WaitOne(60000), "Chat event in HGAssetMapperTests.RezScript not received"); - } - } - */ -} \ No newline at end of file diff --git a/OpenSim/Region/CoreModules/Framework/InventoryAccess/Tests/InventoryAccessModuleTests.cs b/OpenSim/Region/CoreModules/Framework/InventoryAccess/Tests/InventoryAccessModuleTests.cs deleted file mode 100644 index de29ae9441f..00000000000 --- a/OpenSim/Region/CoreModules/Framework/InventoryAccess/Tests/InventoryAccessModuleTests.cs +++ /dev/null @@ -1,177 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections.Generic; -using System.IO; -using System.Reflection; -using System.Threading; -using Nini.Config; -using NUnit.Framework; -using OpenMetaverse; -using OpenSim.Data; -using OpenSim.Framework; -using OpenSim.Framework.Serialization; -using OpenSim.Framework.Serialization.External; -using OpenSim.Region.CoreModules.Avatar.Inventory.Archiver; -using OpenSim.Region.CoreModules.Framework.InventoryAccess; -using OpenSim.Region.Framework.Scenes; -using OpenSim.Region.Framework.Scenes.Serialization; -using OpenSim.Services.Interfaces; -using OpenSim.Tests.Common; - -namespace OpenSim.Region.CoreModules.Framework.InventoryAccess.Tests -{ - [TestFixture] - public class InventoryAccessModuleTests : OpenSimTestCase - { - protected TestScene m_scene; - protected BasicInventoryAccessModule m_iam; - protected UUID m_userId = UUID.Parse("00000000-0000-0000-0000-000000000020"); - protected TestClient m_tc; - - [SetUp] - public override void SetUp() - { - base.SetUp(); - - m_iam = new BasicInventoryAccessModule(); - - IConfigSource config = new IniConfigSource(); - config.AddConfig("Modules"); - config.Configs["Modules"].Set("InventoryAccessModule", "BasicInventoryAccessModule"); - - SceneHelpers sceneHelpers = new SceneHelpers(); - m_scene = sceneHelpers.SetupScene(); - SceneHelpers.SetupSceneModules(m_scene, config, m_iam); - - // Create user - string userFirstName = "Jock"; - string userLastName = "Stirrup"; - string userPassword = "troll"; - UserAccountHelpers.CreateUserWithInventory(m_scene, userFirstName, userLastName, m_userId, userPassword); - - AgentCircuitData acd = new AgentCircuitData(); - acd.AgentID = m_userId; - m_tc = new TestClient(acd, m_scene); - } - - [Test] - public void TestRezCoalescedObject() - { -/* - TestHelpers.InMethod(); -// log4net.Config.XmlConfigurator.Configure(); - - // Create asset - SceneObjectGroup object1 = SceneHelpers.CreateSceneObject(1, m_userId, "Object1", 0x20); - object1.AbsolutePosition = new Vector3(15, 30, 45); - - SceneObjectGroup object2 = SceneHelpers.CreateSceneObject(1, m_userId, "Object2", 0x40); - object2.AbsolutePosition = new Vector3(25, 50, 75); - - CoalescedSceneObjects coa = new CoalescedSceneObjects(m_userId, object1, object2); - - UUID asset1Id = UUID.Parse("00000000-0000-0000-0000-000000000060"); - AssetBase asset1 = AssetHelpers.CreateAsset(asset1Id, coa); - m_scene.AssetService.Store(asset1); - - // Create item - UUID item1Id = UUID.Parse("00000000-0000-0000-0000-000000000080"); - string item1Name = "My Little Dog"; - InventoryItemBase item1 = new InventoryItemBase(); - item1.Name = item1Name; - item1.AssetID = asset1.FullID; - item1.ID = item1Id; - InventoryFolderBase objsFolder - = InventoryArchiveUtils.FindFoldersByPath(m_scene.InventoryService, m_userId, "Objects")[0]; - item1.Folder = objsFolder.ID; - item1.Flags |= (uint)InventoryItemFlags.ObjectHasMultipleItems; - m_scene.AddInventoryItem(item1); - - SceneObjectGroup so - = m_iam.RezObject( - m_tc, item1Id, new Vector3(100, 100, 100), Vector3.Zero, UUID.Zero, 1, false, false, false, UUID.Zero, false); - - Assert.That(so, Is.Not.Null); - - Assert.That(m_scene.SceneGraph.GetTotalObjectsCount(), Is.EqualTo(2)); - - SceneObjectPart retrievedObj1Part = m_scene.GetSceneObjectPart(object1.Name); - Assert.That(retrievedObj1Part, Is.Null); - - retrievedObj1Part = m_scene.GetSceneObjectPart(item1.Name); - Assert.That(retrievedObj1Part, Is.Not.Null); - Assert.That(retrievedObj1Part.Name, Is.EqualTo(item1.Name)); - - // Bottom of coalescence is placed on ground, hence we end up with 100.5 rather than 85 since the bottom - // object is unit square. - Assert.That(retrievedObj1Part.AbsolutePosition, Is.EqualTo(new Vector3(95, 90, 100.5f))); - - SceneObjectPart retrievedObj2Part = m_scene.GetSceneObjectPart(object2.Name); - Assert.That(retrievedObj2Part, Is.Not.Null); - Assert.That(retrievedObj2Part.Name, Is.EqualTo(object2.Name)); - Assert.That(retrievedObj2Part.AbsolutePosition, Is.EqualTo(new Vector3(105, 110, 130.5f))); -*/ - } - - [Test] - public void TestRezObject() - { - TestHelpers.InMethod(); -// log4net.Config.XmlConfigurator.Configure(); - - // Create asset - SceneObjectGroup object1 = SceneHelpers.CreateSceneObject(1, m_userId, "My Little Dog Object", 0x40); - - UUID asset1Id = UUID.Parse("00000000-0000-0000-0000-000000000060"); - AssetBase asset1 = AssetHelpers.CreateAsset(asset1Id, object1); - m_scene.AssetService.Store(asset1); - - // Create item - UUID item1Id = UUID.Parse("00000000-0000-0000-0000-000000000080"); - string item1Name = "My Little Dog"; - InventoryItemBase item1 = new InventoryItemBase(); - item1.Name = item1Name; - item1.AssetID = asset1.FullID; - item1.ID = item1Id; - InventoryFolderBase objsFolder - = InventoryArchiveUtils.FindFoldersByPath(m_scene.InventoryService, m_userId, "Objects")[0]; - item1.Folder = objsFolder.ID; - m_scene.AddInventoryItem(item1); - - SceneObjectGroup so - = m_iam.RezObject( - m_tc, item1Id, UUID.Zero, Vector3.Zero, Vector3.Zero, UUID.Zero, 1, false, false, false, UUID.Zero, false); - - Assert.That(so, Is.Not.Null); - - SceneObjectPart retrievedPart = m_scene.GetSceneObjectPart(so.UUID); - Assert.That(retrievedPart, Is.Not.Null); - } - } -} \ No newline at end of file diff --git a/OpenSim/Region/CoreModules/Framework/UserManagement/Tests/HGUserManagementModuleTests.cs b/OpenSim/Region/CoreModules/Framework/UserManagement/Tests/HGUserManagementModuleTests.cs deleted file mode 100644 index 8d07ffe2284..00000000000 --- a/OpenSim/Region/CoreModules/Framework/UserManagement/Tests/HGUserManagementModuleTests.cs +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using Nini.Config; -using NUnit.Framework; -using OpenMetaverse; -using OpenSim.Framework; -using OpenSim.Region.CoreModules.Framework.UserManagement; -using OpenSim.Tests.Common; - -namespace OpenSim.Region.CoreModules.Framework.UserManagement.Tests -{ - [TestFixture] - public class HGUserManagementModuleTests : OpenSimTestCase - { - /// - /// Test that a new HG agent (i.e. one without a user account) has their name cached in the UMM upon creation. - /// - [Test] - public void TestCachedUserNameForNewAgent() - { - TestHelpers.InMethod(); -// TestHelpers.EnableLogging(); - - HGUserManagementModule hgumm = new HGUserManagementModule(); - UUID userId = TestHelpers.ParseStem("11"); - string firstName = "Fred"; - string lastName = "Astaire"; - string homeUri = "example.com:8002"; - - IConfigSource config = new IniConfigSource(); - config.AddConfig("Modules"); - config.Configs["Modules"].Set("UserManagementModule", hgumm.Name); - - SceneHelpers sceneHelpers = new SceneHelpers(); - TestScene scene = sceneHelpers.SetupScene(); - SceneHelpers.SetupSceneModules(scene, config, hgumm); - - AgentCircuitData acd = SceneHelpers.GenerateAgentData(userId); - acd.firstname = firstName; - acd.lastname = lastName; - acd.ServiceURLs["HomeURI"] = "http://" + homeUri; - - SceneHelpers.AddScenePresence(scene, acd); - - string name = hgumm.GetUserName(userId); - Assert.That(name, Is.EqualTo(string.Format("{0}.{1} @{2}", firstName, lastName, homeUri))); - } - } -} \ No newline at end of file diff --git a/OpenSim/Region/CoreModules/OpenSim.Region.CoreModules.Tests.csproj b/OpenSim/Region/CoreModules/OpenSim.Region.CoreModules.Tests.csproj index b2634cfa259..16012e023d6 100644 --- a/OpenSim/Region/CoreModules/OpenSim.Region.CoreModules.Tests.csproj +++ b/OpenSim/Region/CoreModules/OpenSim.Region.CoreModules.Tests.csproj @@ -19,9 +19,6 @@ ..\..\..\bin\OpenMetaverseTypes.dll False - - False - ..\..\..\bin\XMLRPC.dll False @@ -279,4 +276,4 @@ - \ No newline at end of file + diff --git a/OpenSim/Region/CoreModules/OpenSim.Region.CoreModules.csproj b/OpenSim/Region/CoreModules/OpenSim.Region.CoreModules.csproj index cc03502c1b5..57f37faf737 100644 --- a/OpenSim/Region/CoreModules/OpenSim.Region.CoreModules.csproj +++ b/OpenSim/Region/CoreModules/OpenSim.Region.CoreModules.csproj @@ -35,9 +35,6 @@ ..\..\..\bin\OpenMetaverseTypes.dll False - - False - False diff --git a/OpenSim/Region/CoreModules/Scripting/HttpRequest/Tests/ScriptsHttpRequestsTests.cs b/OpenSim/Region/CoreModules/Scripting/HttpRequest/Tests/ScriptsHttpRequestsTests.cs deleted file mode 100644 index 7e223d70c5b..00000000000 --- a/OpenSim/Region/CoreModules/Scripting/HttpRequest/Tests/ScriptsHttpRequestsTests.cs +++ /dev/null @@ -1,199 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections.Generic; -using System.IO; -using System.Net; -using System.Reflection; -using System.Runtime.Serialization; -using System.Text; -using System.Threading; -using log4net.Config; -using NUnit.Framework; -using OpenMetaverse; -using OpenMetaverse.Assets; -using OpenSim.Framework; -using OpenSim.Region.CoreModules.Scripting.HttpRequest; -using OpenSim.Region.Framework.Scenes; -using OpenSim.Tests.Common; - -namespace OpenSim.Region.CoreModules.Scripting.HttpRequest.Tests -{ - class TestWebRequestCreate : IWebRequestCreate - { - public TestWebRequest NextRequest { get; set; } - - public WebRequest Create(Uri uri) - { -// NextRequest.RequestUri = uri; - - return NextRequest; - -// return new TestWebRequest(new SerializationInfo(typeof(TestWebRequest), new FormatterConverter()), new StreamingContext()); - } - } - - class TestWebRequest : WebRequest - { - public override string ContentType { get; set; } - public override string Method { get; set; } - - public Func OnEndGetResponse { get; set; } - - public TestWebRequest() : base() - { -// Console.WriteLine("created"); - } - -// public TestWebRequest(SerializationInfo serializationInfo, StreamingContext streamingContext) -// : base(serializationInfo, streamingContext) -// { -// Console.WriteLine("created"); -// } - - public override IAsyncResult BeginGetResponse(AsyncCallback callback, object state) - { -// Console.WriteLine("bish"); - TestAsyncResult tasr = new TestAsyncResult(); - callback(tasr); - - return tasr; - } - - public override WebResponse EndGetResponse(IAsyncResult asyncResult) - { -// Console.WriteLine("bosh"); - return OnEndGetResponse(asyncResult); - } - } - - class TestHttpWebResponse : HttpWebResponse - { - public string Response { get; set; } - -#pragma warning disable 0618 - public TestHttpWebResponse(SerializationInfo serializationInfo, StreamingContext streamingContext) - : base(serializationInfo, streamingContext) {} -#pragma warning restore 0618 - - public override Stream GetResponseStream() - { - return new MemoryStream(Encoding.UTF8.GetBytes(Response)); - } - } - - class TestAsyncResult : IAsyncResult - { - WaitHandle m_wh = new ManualResetEvent(true); - - object IAsyncResult.AsyncState - { - get { - throw new System.NotImplementedException (); - } - } - - WaitHandle IAsyncResult.AsyncWaitHandle - { - get { return m_wh; } - } - - bool IAsyncResult.CompletedSynchronously - { - get { return false; } - } - - bool IAsyncResult.IsCompleted - { - get { return true; } - } - } - - /// - /// Test script http request code. - /// - /// - /// This class uses some very hacky workarounds in order to mock HttpWebResponse which are Mono dependent (though - /// alternative code can be written to make this work for Windows). However, the value of being able to - /// regression test this kind of code is very high. - /// - [TestFixture] - public class ScriptsHttpRequestsTests : OpenSimTestCase - { - /// - /// Test what happens when we get a 404 response from a call. - /// -// [Test] - public void Test404Response() - { - TestHelpers.InMethod(); - TestHelpers.EnableLogging(); - - if (!Util.IsPlatformMono) - Assert.Ignore("Ignoring test since can only currently run on Mono"); - - string rawResponse = "boom"; - - TestWebRequestCreate twrc = new TestWebRequestCreate(); - - TestWebRequest twr = new TestWebRequest(); - //twr.OnEndGetResponse += ar => new TestHttpWebResponse(null, new StreamingContext()); - twr.OnEndGetResponse += ar => - { - SerializationInfo si = new SerializationInfo(typeof(HttpWebResponse), new FormatterConverter()); - StreamingContext sc = new StreamingContext(); -// WebHeaderCollection headers = new WebHeaderCollection(); -// si.AddValue("m_HttpResponseHeaders", headers); - si.AddValue("uri", new Uri("test://arrg")); -// si.AddValue("m_Certificate", null); - si.AddValue("version", HttpVersion.Version11); - si.AddValue("statusCode", HttpStatusCode.NotFound); - si.AddValue("contentLength", 0); - si.AddValue("method", "GET"); - si.AddValue("statusDescription", "Not Found"); - si.AddValue("contentType", null); - si.AddValue("cookieCollection", new CookieCollection()); - - TestHttpWebResponse thwr = new TestHttpWebResponse(si, sc); - thwr.Response = rawResponse; - - throw new WebException("no message", null, WebExceptionStatus.ProtocolError, thwr); - }; - - twrc.NextRequest = twr; - - WebRequest.RegisterPrefix("test", twrc); - HttpRequestClass hr = new HttpRequestClass(); - hr.Url = "test://something"; - hr.SendRequest(); - - Assert.That(hr.Status, Is.EqualTo((int)HttpStatusCode.NotFound)); - Assert.That(hr.ResponseBody, Is.EqualTo(rawResponse)); - } - } -} \ No newline at end of file diff --git a/OpenSim/Region/CoreModules/Scripting/VectorRender/Tests/VectorRenderModuleTests.cs b/OpenSim/Region/CoreModules/Scripting/VectorRender/Tests/VectorRenderModuleTests.cs deleted file mode 100644 index 726e808c17a..00000000000 --- a/OpenSim/Region/CoreModules/Scripting/VectorRender/Tests/VectorRenderModuleTests.cs +++ /dev/null @@ -1,321 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections.Generic; -using System.IO; -using System.Reflection; -using System.Threading; -using log4net.Config; -using NUnit.Framework; -using OpenMetaverse; -using OpenMetaverse.Assets; -using OpenSim.Framework; -using OpenSim.Region.CoreModules.Scripting.DynamicTexture; -using OpenSim.Region.CoreModules.Scripting.VectorRender; -using OpenSim.Region.Framework.Scenes; -using OpenSim.Region.Framework.Scenes.Serialization; -using OpenSim.Tests.Common; - -namespace OpenSim.Region.CoreModules.Scripting.VectorRender.Tests -{ - [TestFixture] - public class VectorRenderModuleTests : OpenSimTestCase - { - Scene m_scene; - DynamicTextureModule m_dtm; - VectorRenderModule m_vrm; - - private void SetupScene(bool reuseTextures) - { - - TestsAssetCache cache = new TestsAssetCache(); - m_scene = new SceneHelpers(cache).SetupScene(); - - m_dtm = new DynamicTextureModule(); - m_dtm.ReuseTextures = reuseTextures; -// m_dtm.ReuseLowDataTextures = reuseTextures; - - m_vrm = new VectorRenderModule(); - - SceneHelpers.SetupSceneModules(m_scene, m_dtm, m_vrm); - } - - [Test] - public void TestDraw() - { - TestHelpers.InMethod(); - - SetupScene(false); - SceneObjectGroup so = SceneHelpers.AddSceneObject(m_scene); - UUID originalTextureID = so.RootPart.Shape.Textures.GetFace(0).TextureID; - - m_dtm.AddDynamicTextureData( - m_scene.RegionInfo.RegionID, - so.UUID, - m_vrm.GetContentType(), - "PenColour BLACK; MoveTo 40,220; FontSize 32; Text Hello World;", - ""); - - Assert.That(originalTextureID, Is.Not.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID)); - } - - [Test] - public void TestRepeatSameDraw() - { - TestHelpers.InMethod(); - - string dtText = "PenColour BLACK; MoveTo 40,220; FontSize 32; Text Hello World;"; - - SetupScene(false); - SceneObjectGroup so = SceneHelpers.AddSceneObject(m_scene); - - m_dtm.AddDynamicTextureData( - m_scene.RegionInfo.RegionID, - so.UUID, - m_vrm.GetContentType(), - dtText, - ""); - - UUID firstDynamicTextureID = so.RootPart.Shape.Textures.GetFace(0).TextureID; - - m_dtm.AddDynamicTextureData( - m_scene.RegionInfo.RegionID, - so.UUID, - m_vrm.GetContentType(), - dtText, - ""); - - Assert.That(firstDynamicTextureID, Is.Not.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID)); - } - - [Test] - public void TestRepeatSameDrawDifferentExtraParams() - { - TestHelpers.InMethod(); - - string dtText = "PenColour BLACK; MoveTo 40,220; FontSize 32; Text Hello World;"; - - SetupScene(false); - SceneObjectGroup so = SceneHelpers.AddSceneObject(m_scene); - - m_dtm.AddDynamicTextureData( - m_scene.RegionInfo.RegionID, - so.UUID, - m_vrm.GetContentType(), - dtText, - ""); - - UUID firstDynamicTextureID = so.RootPart.Shape.Textures.GetFace(0).TextureID; - - m_dtm.AddDynamicTextureData( - m_scene.RegionInfo.RegionID, - so.UUID, - m_vrm.GetContentType(), - dtText, - "alpha:250"); - - Assert.That(firstDynamicTextureID, Is.Not.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID)); - } - - [Test] - public void TestRepeatSameDrawContainingImage() - { - TestHelpers.InMethod(); - - string dtText - = "PenColour BLACK; MoveTo 40,220; FontSize 32; Text Hello World; Image http://0.0.0.0/shouldnotexist.png"; - - SetupScene(false); - SceneObjectGroup so = SceneHelpers.AddSceneObject(m_scene); - - m_dtm.AddDynamicTextureData( - m_scene.RegionInfo.RegionID, - so.UUID, - m_vrm.GetContentType(), - dtText, - ""); - - UUID firstDynamicTextureID = so.RootPart.Shape.Textures.GetFace(0).TextureID; - - m_dtm.AddDynamicTextureData( - m_scene.RegionInfo.RegionID, - so.UUID, - m_vrm.GetContentType(), - dtText, - ""); - - Assert.That(firstDynamicTextureID, Is.Not.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID)); - } - - [Test] - public void TestDrawReusingTexture() - { - TestHelpers.InMethod(); - - SetupScene(true); - SceneObjectGroup so = SceneHelpers.AddSceneObject(m_scene); - UUID originalTextureID = so.RootPart.Shape.Textures.GetFace(0).TextureID; - - m_dtm.AddDynamicTextureData( - m_scene.RegionInfo.RegionID, - so.UUID, - m_vrm.GetContentType(), - "PenColour BLACK; MoveTo 40,220; FontSize 32; Text Hello World;", - ""); - - Assert.That(originalTextureID, Is.Not.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID)); - } - - [Test] - public void TestRepeatSameDrawReusingTexture() - { - TestHelpers.InMethod(); -// TestHelpers.EnableLogging(); - - string dtText = "PenColour BLACK; MoveTo 40,220; FontSize 32; Text Hello World;"; - - SetupScene(true); - SceneObjectGroup so = SceneHelpers.AddSceneObject(m_scene); - - m_dtm.AddDynamicTextureData( - m_scene.RegionInfo.RegionID, - so.UUID, - m_vrm.GetContentType(), - dtText, - ""); - - UUID firstDynamicTextureID = so.RootPart.Shape.Textures.GetFace(0).TextureID; - - m_dtm.AddDynamicTextureData( - m_scene.RegionInfo.RegionID, - so.UUID, - m_vrm.GetContentType(), - dtText, - ""); - - Assert.That(firstDynamicTextureID, Is.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID)); - } - - /// - /// Test a low data dynamically generated texture such that it is treated as a low data texture that causes - /// problems for current viewers. - /// - /// - /// As we do not set DynamicTextureModule.ReuseLowDataTextures = true in this test, it should not reuse the - /// texture - /// - [Test] - public void TestRepeatSameDrawLowDataTexture() - { - TestHelpers.InMethod(); -// TestHelpers.EnableLogging(); - - string dtText = "PenColour BLACK; MoveTo 40,220; FontSize 32; Text Hello World;"; - - SetupScene(true); - SceneObjectGroup so = SceneHelpers.AddSceneObject(m_scene); - - m_dtm.AddDynamicTextureData( - m_scene.RegionInfo.RegionID, - so.UUID, - m_vrm.GetContentType(), - dtText, - "1024"); - - UUID firstDynamicTextureID = so.RootPart.Shape.Textures.GetFace(0).TextureID; - - m_dtm.AddDynamicTextureData( - m_scene.RegionInfo.RegionID, - so.UUID, - m_vrm.GetContentType(), - dtText, - "1024"); - - Assert.That(firstDynamicTextureID, Is.Not.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID)); - } - - [Test] - public void TestRepeatSameDrawDifferentExtraParamsReusingTexture() - { - TestHelpers.InMethod(); - - string dtText = "PenColour BLACK; MoveTo 40,220; FontSize 32; Text Hello World;"; - - SetupScene(true); - SceneObjectGroup so = SceneHelpers.AddSceneObject(m_scene); - - m_dtm.AddDynamicTextureData( - m_scene.RegionInfo.RegionID, - so.UUID, - m_vrm.GetContentType(), - dtText, - ""); - - UUID firstDynamicTextureID = so.RootPart.Shape.Textures.GetFace(0).TextureID; - - m_dtm.AddDynamicTextureData( - m_scene.RegionInfo.RegionID, - so.UUID, - m_vrm.GetContentType(), - dtText, - "alpha:250"); - - Assert.That(firstDynamicTextureID, Is.Not.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID)); - } - - [Test] - public void TestRepeatSameDrawContainingImageReusingTexture() - { - TestHelpers.InMethod(); - - string dtText - = "PenColour BLACK; MoveTo 40,220; FontSize 32; Text Hello World; Image http://0.0.0.0/shouldnotexist.png"; - - SetupScene(true); - SceneObjectGroup so = SceneHelpers.AddSceneObject(m_scene); - - m_dtm.AddDynamicTextureData( - m_scene.RegionInfo.RegionID, - so.UUID, - m_vrm.GetContentType(), - dtText, - ""); - - UUID firstDynamicTextureID = so.RootPart.Shape.Textures.GetFace(0).TextureID; - - m_dtm.AddDynamicTextureData( - m_scene.RegionInfo.RegionID, - so.UUID, - m_vrm.GetContentType(), - dtText, - ""); - - Assert.That(firstDynamicTextureID, Is.Not.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID)); - } - } -} \ No newline at end of file diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/Tests/AssetConnectorTests.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/Tests/AssetConnectorTests.cs deleted file mode 100644 index 4f75191cf29..00000000000 --- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/Tests/AssetConnectorTests.cs +++ /dev/null @@ -1,174 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections.Generic; -using System.IO; -using System.Reflection; -using System.Threading; -using log4net.Config; -using Nini.Config; -using NUnit.Framework; -using OpenMetaverse; -using OpenSim.Framework; -using OpenSim.Region.Framework.Scenes; -using OpenSim.Region.CoreModules.ServiceConnectorsOut.Asset; -using OpenSim.Tests.Common; - -namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Asset.Tests -{ - [TestFixture] - public class AssetConnectorTests : OpenSimTestCase - { - [Test] - public void TestAddAsset() - { - TestHelpers.InMethod(); -// TestHelpers.EnableLogging(); - - IConfigSource config = new IniConfigSource(); - config.AddConfig("Modules"); - config.Configs["Modules"].Set("AssetServices", "LocalAssetServicesConnector"); - config.AddConfig("AssetService"); - config.Configs["AssetService"].Set("LocalServiceModule", "OpenSim.Services.AssetService.dll:AssetService"); - config.Configs["AssetService"].Set("StorageProvider", "OpenSim.Tests.Common.dll"); - - LocalAssetServicesConnector lasc = new LocalAssetServicesConnector(); - lasc.Initialise(config); - - AssetBase a1 = AssetHelpers.CreateNotecardAsset(); - lasc.Store(a1); - - AssetBase retreivedA1 = lasc.Get(a1.ID); - Assert.That(retreivedA1.ID, Is.EqualTo(a1.ID)); - Assert.That(retreivedA1.Metadata.ID, Is.EqualTo(a1.Metadata.ID)); - Assert.That(retreivedA1.Data.Length, Is.EqualTo(a1.Data.Length)); - - AssetMetadata retrievedA1Metadata = lasc.GetMetadata(a1.ID); - Assert.That(retrievedA1Metadata.ID, Is.EqualTo(a1.ID)); - - byte[] retrievedA1Data = lasc.GetData(a1.ID); - Assert.That(retrievedA1Data.Length, Is.EqualTo(a1.Data.Length)); - - // TODO: Add cache and check that this does receive a copy of the asset - } - - public void TestAddTemporaryAsset() - { - TestHelpers.InMethod(); -// TestHelpers.EnableLogging(); - - IConfigSource config = new IniConfigSource(); - config.AddConfig("Modules"); - config.Configs["Modules"].Set("AssetServices", "LocalAssetServicesConnector"); - config.AddConfig("AssetService"); - config.Configs["AssetService"].Set("LocalServiceModule", "OpenSim.Services.AssetService.dll:AssetService"); - config.Configs["AssetService"].Set("StorageProvider", "OpenSim.Tests.Common.dll"); - - LocalAssetServicesConnector lasc = new LocalAssetServicesConnector(); - lasc.Initialise(config); - - // If it is remote, it should be stored - AssetBase a2 = AssetHelpers.CreateNotecardAsset(); - a2.Local = false; - a2.Temporary = true; - - lasc.Store(a2); - - AssetBase retreivedA2 = lasc.Get(a2.ID); - Assert.That(retreivedA2.ID, Is.EqualTo(a2.ID)); - Assert.That(retreivedA2.Metadata.ID, Is.EqualTo(a2.Metadata.ID)); - Assert.That(retreivedA2.Data.Length, Is.EqualTo(a2.Data.Length)); - - AssetMetadata retrievedA2Metadata = lasc.GetMetadata(a2.ID); - Assert.That(retrievedA2Metadata.ID, Is.EqualTo(a2.ID)); - - byte[] retrievedA2Data = lasc.GetData(a2.ID); - Assert.That(retrievedA2Data.Length, Is.EqualTo(a2.Data.Length)); - - // TODO: Add cache and check that this does receive a copy of the asset - } - - [Test] - public void TestAddLocalAsset() - { - TestHelpers.InMethod(); -// TestHelpers.EnableLogging(); - - IConfigSource config = new IniConfigSource(); - config.AddConfig("Modules"); - config.Configs["Modules"].Set("AssetServices", "LocalAssetServicesConnector"); - config.AddConfig("AssetService"); - config.Configs["AssetService"].Set("LocalServiceModule", "OpenSim.Services.AssetService.dll:AssetService"); - config.Configs["AssetService"].Set("StorageProvider", "OpenSim.Tests.Common.dll"); - - LocalAssetServicesConnector lasc = new LocalAssetServicesConnector(); - lasc.Initialise(config); - - AssetBase a1 = AssetHelpers.CreateNotecardAsset(); - a1.Local = true; - - lasc.Store(a1); - - Assert.That(lasc.Get(a1.ID), Is.Null); - Assert.That(lasc.GetData(a1.ID), Is.Null); - Assert.That(lasc.GetMetadata(a1.ID), Is.Null); - - // TODO: Add cache and check that this does receive a copy of the asset - } - - [Test] - public void TestAddTemporaryLocalAsset() - { - TestHelpers.InMethod(); -// TestHelpers.EnableLogging(); - - IConfigSource config = new IniConfigSource(); - config.AddConfig("Modules"); - config.Configs["Modules"].Set("AssetServices", "LocalAssetServicesConnector"); - config.AddConfig("AssetService"); - config.Configs["AssetService"].Set("LocalServiceModule", "OpenSim.Services.AssetService.dll:AssetService"); - config.Configs["AssetService"].Set("StorageProvider", "OpenSim.Tests.Common.dll"); - - LocalAssetServicesConnector lasc = new LocalAssetServicesConnector(); - lasc.Initialise(config); - - // If it is local, it should not be stored - AssetBase a1 = AssetHelpers.CreateNotecardAsset(); - a1.Local = true; - a1.Temporary = true; - - lasc.Store(a1); - - Assert.That(lasc.Get(a1.ID), Is.Null); - Assert.That(lasc.GetData(a1.ID), Is.Null); - Assert.That(lasc.GetMetadata(a1.ID), Is.Null); - - // TODO: Add cache and check that this does receive a copy of the asset - } - } -} \ No newline at end of file diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/Tests/GridConnectorsTests.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/Tests/GridConnectorsTests.cs deleted file mode 100644 index d76c98de008..00000000000 --- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/Tests/GridConnectorsTests.cs +++ /dev/null @@ -1,201 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections.Generic; -using System.IO; -using System.Reflection; -using System.Threading; -using log4net.Config; -using Nini.Config; -using NUnit.Framework; -using OpenMetaverse; - -using OpenSim.Framework; -using OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid; -using OpenSim.Region.Framework.Scenes; -using GridRegion = OpenSim.Services.Interfaces.GridRegion; -using OpenSim.Tests.Common; - -namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid.Tests -{ - [TestFixture] - public class GridConnectorsTests : OpenSimTestCase - { - RegionGridServicesConnector m_LocalConnector; - - [SetUp] - public override void SetUp() - { - base.SetUp(); - - IConfigSource config = new IniConfigSource(); - config.AddConfig("Modules"); - config.AddConfig("GridService"); - config.Configs["Modules"].Set("GridServices", "RegionGridServicesConnector"); - config.Configs["GridService"].Set("LocalServiceModule", "OpenSim.Services.GridService.dll:GridService"); - config.Configs["GridService"].Set("StorageProvider", "OpenSim.Data.Null.dll"); - config.Configs["GridService"].Set("Region_Test_Region_1", "DefaultRegion"); - config.Configs["GridService"].Set("Region_Test_Region_2", "FallbackRegion"); - config.Configs["GridService"].Set("Region_Test_Region_3", "FallbackRegion"); - config.Configs["GridService"].Set("Region_Other_Region_4", "FallbackRegion"); - - m_LocalConnector = new RegionGridServicesConnector(config); - } - - /// - /// Test region registration. - /// - [Test] - public void TestRegisterRegion() - { - TestHelpers.InMethod(); -// log4net.Config.XmlConfigurator.Configure(); - - // Create 4 regions - GridRegion r1 = new GridRegion(); - r1.RegionName = "Test Region 1"; - r1.RegionID = new UUID(1); - r1.RegionLocX = 1000 * (int)Constants.RegionSize; - r1.RegionLocY = 1000 * (int)Constants.RegionSize; - r1.ExternalHostName = "127.0.0.1"; - r1.HttpPort = 9001; - r1.InternalEndPoint = new System.Net.IPEndPoint(System.Net.IPAddress.Parse("0.0.0.0"), 0); - Scene s = new Scene(new RegionInfo()); - s.RegionInfo.RegionID = r1.RegionID; - m_LocalConnector.AddRegion(s); - - GridRegion r2 = new GridRegion(); - r2.RegionName = "Test Region 2"; - r2.RegionID = new UUID(2); - r2.RegionLocX = 1001 * (int)Constants.RegionSize; - r2.RegionLocY = 1000 * (int)Constants.RegionSize; - r2.ExternalHostName = "127.0.0.1"; - r2.HttpPort = 9002; - r2.InternalEndPoint = new System.Net.IPEndPoint(System.Net.IPAddress.Parse("0.0.0.0"), 0); - s = new Scene(new RegionInfo()); - s.RegionInfo.RegionID = r2.RegionID; - m_LocalConnector.AddRegion(s); - - GridRegion r3 = new GridRegion(); - r3.RegionName = "Test Region 3"; - r3.RegionID = new UUID(3); - r3.RegionLocX = 1005 * (int)Constants.RegionSize; - r3.RegionLocY = 1000 * (int)Constants.RegionSize; - r3.ExternalHostName = "127.0.0.1"; - r3.HttpPort = 9003; - r3.InternalEndPoint = new System.Net.IPEndPoint(System.Net.IPAddress.Parse("0.0.0.0"), 0); - s = new Scene(new RegionInfo()); - s.RegionInfo.RegionID = r3.RegionID; - m_LocalConnector.AddRegion(s); - - GridRegion r4 = new GridRegion(); - r4.RegionName = "Other Region 4"; - r4.RegionID = new UUID(4); - r4.RegionLocX = 1004 * (int)Constants.RegionSize; - r4.RegionLocY = 1002 * (int)Constants.RegionSize; - r4.ExternalHostName = "127.0.0.1"; - r4.HttpPort = 9004; - r4.InternalEndPoint = new System.Net.IPEndPoint(System.Net.IPAddress.Parse("0.0.0.0"), 0); - s = new Scene(new RegionInfo()); - s.RegionInfo.RegionID = r4.RegionID; - m_LocalConnector.AddRegion(s); - - m_LocalConnector.RegisterRegion(UUID.Zero, r1); - - GridRegion result = m_LocalConnector.GetRegionByName(UUID.Zero, "Test"); - Assert.IsNull(result, "Retrieved GetRegionByName \"Test\" is not null"); - - result = m_LocalConnector.GetRegionByName(UUID.Zero, "Test Region 1"); - Assert.IsNotNull(result, "Retrieved GetRegionByName is null"); - Assert.That(result.RegionName, Is.EqualTo("Test Region 1"), "Retrieved region's name does not match"); - - m_LocalConnector.RegisterRegion(UUID.Zero, r2); - m_LocalConnector.RegisterRegion(UUID.Zero, r3); - m_LocalConnector.RegisterRegion(UUID.Zero, r4); - - result = m_LocalConnector.GetRegionByUUID(UUID.Zero, new UUID(1)); - Assert.IsNotNull(result, "Retrieved GetRegionByUUID is null"); - Assert.That(result.RegionID, Is.EqualTo(new UUID(1)), "Retrieved region's UUID does not match"); - - result = m_LocalConnector.GetRegionByPosition(UUID.Zero, (int)Util.RegionToWorldLoc(1000), (int)Util.RegionToWorldLoc(1000)); - Assert.IsNotNull(result, "Retrieved GetRegionByPosition is null"); - Assert.That(result.RegionLocX, Is.EqualTo(1000 * (int)Constants.RegionSize), "Retrieved region's position does not match"); - - List results = m_LocalConnector.GetNeighbours(UUID.Zero, new UUID(1)); - Assert.IsNotNull(results, "Retrieved neighbours list is null"); - Assert.That(results.Count, Is.EqualTo(1), "Retrieved neighbour collection is greater than expected"); - Assert.That(results[0].RegionID, Is.EqualTo(new UUID(2)), "Retrieved region's UUID does not match"); - - results = m_LocalConnector.GetRegionsByName(UUID.Zero, "Test", 10); - Assert.IsNotNull(results, "Retrieved GetRegionsByName collection is null"); - Assert.That(results.Count, Is.EqualTo(3), "Retrieved neighbour collection is less than expected"); - - results = m_LocalConnector.GetRegionRange(UUID.Zero, 900 * (int)Constants.RegionSize, 1002 * (int)Constants.RegionSize, - 900 * (int)Constants.RegionSize, 1100 * (int)Constants.RegionSize); - Assert.IsNotNull(results, "Retrieved GetRegionRange collection is null"); - Assert.That(results.Count, Is.EqualTo(2), "Retrieved neighbour collection is not the number expected"); - - results = m_LocalConnector.GetDefaultRegions(UUID.Zero); - Assert.IsNotNull(results, "Retrieved GetDefaultRegions collection is null"); - Assert.That(results.Count, Is.EqualTo(1), "Retrieved default regions collection has not the expected size"); - Assert.That(results[0].RegionID, Is.EqualTo(new UUID(1)), "Retrieved default region's UUID does not match"); - - results = m_LocalConnector.GetFallbackRegions(UUID.Zero, r1.RegionLocX, r1.RegionLocY); - Assert.IsNotNull(results, "Retrieved GetFallbackRegions collection for region 1 is null"); - Assert.That(results.Count, Is.EqualTo(3), "Retrieved fallback regions collection for region 1 has not the expected size"); - Assert.That(results[0].RegionID, Is.EqualTo(new UUID(2)), "Retrieved fallback regions for default region are not in the expected order 2-4-3"); - Assert.That(results[1].RegionID, Is.EqualTo(new UUID(4)), "Retrieved fallback regions for default region are not in the expected order 2-4-3"); - Assert.That(results[2].RegionID, Is.EqualTo(new UUID(3)), "Retrieved fallback regions for default region are not in the expected order 2-4-3"); - - results = m_LocalConnector.GetFallbackRegions(UUID.Zero, r2.RegionLocX, r2.RegionLocY); - Assert.IsNotNull(results, "Retrieved GetFallbackRegions collection for region 2 is null"); - Assert.That(results.Count, Is.EqualTo(3), "Retrieved fallback regions collection for region 2 has not the expected size"); - Assert.That(results[0].RegionID, Is.EqualTo(new UUID(2)), "Retrieved fallback regions are not in the expected order 2-4-3"); - Assert.That(results[1].RegionID, Is.EqualTo(new UUID(4)), "Retrieved fallback regions are not in the expected order 2-4-3"); - Assert.That(results[2].RegionID, Is.EqualTo(new UUID(3)), "Retrieved fallback regions are not in the expected order 2-4-3"); - - results = m_LocalConnector.GetFallbackRegions(UUID.Zero, r3.RegionLocX, r3.RegionLocY); - Assert.IsNotNull(results, "Retrieved GetFallbackRegions collection for region 3 is null"); - Assert.That(results.Count, Is.EqualTo(3), "Retrieved fallback regions collection for region 3 has not the expected size"); - Assert.That(results[0].RegionID, Is.EqualTo(new UUID(3)), "Retrieved fallback regions are not in the expected order 3-4-2"); - Assert.That(results[1].RegionID, Is.EqualTo(new UUID(4)), "Retrieved fallback regions are not in the expected order 3-4-2"); - Assert.That(results[2].RegionID, Is.EqualTo(new UUID(2)), "Retrieved fallback regions are not in the expected order 3-4-2"); - - results = m_LocalConnector.GetFallbackRegions(UUID.Zero, r4.RegionLocX, r4.RegionLocY); - Assert.IsNotNull(results, "Retrieved GetFallbackRegions collection for region 4 is null"); - Assert.That(results.Count, Is.EqualTo(3), "Retrieved fallback regions collection for region 4 has not the expected size"); - Assert.That(results[0].RegionID, Is.EqualTo(new UUID(4)), "Retrieved fallback regions are not in the expected order 4-3-2"); - Assert.That(results[1].RegionID, Is.EqualTo(new UUID(3)), "Retrieved fallback regions are not in the expected order 4-3-2"); - Assert.That(results[2].RegionID, Is.EqualTo(new UUID(2)), "Retrieved fallback regions are not in the expected order 4-3-2"); - - results = m_LocalConnector.GetHyperlinks(UUID.Zero); - Assert.IsNotNull(results, "Retrieved GetHyperlinks list is null"); - Assert.That(results.Count, Is.EqualTo(0), "Retrieved linked regions collection is not the number expected"); - } - } -} diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Presence/Tests/PresenceConnectorsTests.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Presence/Tests/PresenceConnectorsTests.cs deleted file mode 100644 index 7838d123e8a..00000000000 --- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Presence/Tests/PresenceConnectorsTests.cs +++ /dev/null @@ -1,116 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections.Generic; -using System.IO; -using System.Reflection; -using System.Threading; -using log4net.Config; -using NUnit.Framework; -using OpenMetaverse; -using OpenSim.Framework; -using Nini.Config; -using OpenSim.Region.CoreModules.ServiceConnectorsOut.Presence; -using OpenSim.Region.Framework.Scenes; -using PresenceInfo = OpenSim.Services.Interfaces.PresenceInfo; -using OpenSim.Tests.Common; - -namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Presence.Tests -{ - [TestFixture] - public class PresenceConnectorsTests : OpenSimTestCase - { - LocalPresenceServicesConnector m_LocalConnector; - - public override void SetUp() - { - base.SetUp(); - - IConfigSource config = new IniConfigSource(); - config.AddConfig("Modules"); - config.AddConfig("PresenceService"); - config.Configs["Modules"].Set("PresenceServices", "LocalPresenceServicesConnector"); - config.Configs["PresenceService"].Set("LocalServiceModule", "OpenSim.Services.PresenceService.dll:PresenceService"); - config.Configs["PresenceService"].Set("StorageProvider", "OpenSim.Data.Null.dll"); - - m_LocalConnector = new LocalPresenceServicesConnector(); - m_LocalConnector.Initialise(config); - - // Let's stick in a test presence - m_LocalConnector.m_PresenceService.LoginAgent(UUID.Zero.ToString(), UUID.Zero, UUID.Zero); - } - - /// - /// Test OpenSim Presence. - /// - [Test] - public void TestPresenceV0_1() - { - SetUp(); - - // Let's stick in a test presence - /* - PresenceData p = new PresenceData(); - p.SessionID = UUID.Zero; - p.UserID = UUID.Zero.ToString(); - p.Data = new Dictionary(); - p.Data["Online"] = true.ToString(); - m_presenceData.Add(UUID.Zero, p); - */ - - string user1 = UUID.Zero.ToString(); - UUID session1 = UUID.Zero; - - // this is not implemented by this connector - //m_LocalConnector.LoginAgent(user1, session1, UUID.Zero); - PresenceInfo result = m_LocalConnector.GetAgent(session1); - Assert.IsNotNull(result, "Retrieved GetAgent is null"); - Assert.That(result.UserID, Is.EqualTo(user1), "Retrieved userID does not match"); - - UUID region1 = UUID.Random(); - bool r = m_LocalConnector.ReportAgent(session1, region1); - Assert.IsTrue(r, "First ReportAgent returned false"); - result = m_LocalConnector.GetAgent(session1); - Assert.That(result.RegionID, Is.EqualTo(region1), "Agent is not in the right region (region1)"); - - UUID region2 = UUID.Random(); - r = m_LocalConnector.ReportAgent(session1, region2); - Assert.IsTrue(r, "Second ReportAgent returned false"); - result = m_LocalConnector.GetAgent(session1); - Assert.That(result.RegionID, Is.EqualTo(region2), "Agent is not in the right region (region2)"); - - r = m_LocalConnector.LogoutAgent(session1); - Assert.IsTrue(r, "LogoutAgent returned false"); - result = m_LocalConnector.GetAgent(session1); - Assert.IsNull(result, "Agent session is still stored after logout"); - - r = m_LocalConnector.ReportAgent(session1, region1); - Assert.IsFalse(r, "ReportAgent of non-logged in user returned true"); - } - } -} diff --git a/OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs b/OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs deleted file mode 100644 index 35427dc679f..00000000000 --- a/OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs +++ /dev/null @@ -1,1056 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections.Generic; -using System.IO; -using System.Reflection; -using System.Threading; -using log4net.Config; -using Nini.Config; -using NUnit.Framework; -using OpenMetaverse; -using OpenMetaverse.Assets; -using OpenSim.Framework; -using OpenSim.Framework.Serialization; -using OpenSim.Framework.Serialization.External; -using OpenSim.Region.CoreModules.World.Land; -using OpenSim.Region.CoreModules.World.Serialiser; -using OpenSim.Region.CoreModules.World.Terrain; -using OpenSim.Region.Framework.Scenes; -using OpenSim.Region.Framework.Scenes.Serialization; -using OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups; -using OpenSim.Tests.Common; -using ArchiveConstants = OpenSim.Framework.Serialization.ArchiveConstants; -using TarArchiveReader = OpenSim.Framework.Serialization.TarArchiveReader; -using TarArchiveWriter = OpenSim.Framework.Serialization.TarArchiveWriter; -using RegionSettings = OpenSim.Framework.RegionSettings; -using OpenSim.Region.Framework.Interfaces; - -namespace OpenSim.Region.CoreModules.World.Archiver.Tests -{ - [TestFixture] - public class ArchiverTests : OpenSimTestCase - { - private Guid m_lastRequestId; - private string m_lastErrorMessage; - - protected SceneHelpers m_sceneHelpers; - protected TestScene m_scene; - protected ArchiverModule m_archiverModule; - protected SerialiserModule m_serialiserModule; - - protected TaskInventoryItem m_soundItem; - - private AutoResetEvent m_oarEvent = new AutoResetEvent(false); - - [SetUp] - public override void SetUp() - { - base.SetUp(); - - m_archiverModule = new ArchiverModule(); - m_serialiserModule = new SerialiserModule(); - TerrainModule terrainModule = new TerrainModule(); - - m_sceneHelpers = new SceneHelpers(); - m_scene = m_sceneHelpers.SetupScene(); - SceneHelpers.SetupSceneModules(m_scene, m_archiverModule, m_serialiserModule, terrainModule); - } - - private void LoadCompleted(Guid requestId, List loadedScenes, string errorMessage) - { - lock (this) - { - m_lastRequestId = requestId; - m_lastErrorMessage = errorMessage; - Console.WriteLine("About to pulse ArchiverTests on LoadCompleted"); - m_oarEvent.Set(); - } - } - - private void SaveCompleted(Guid requestId, string errorMessage) - { - lock (this) - { - m_lastRequestId = requestId; - m_lastErrorMessage = errorMessage; - Console.WriteLine("About to pulse ArchiverTests on SaveCompleted"); - m_oarEvent.Set(); - } - } - - protected SceneObjectPart CreateSceneObjectPart1() - { - string partName = "My Little Pony"; - UUID ownerId = UUID.Parse("00000000-0000-0000-0000-000000000015"); - PrimitiveBaseShape shape = PrimitiveBaseShape.CreateSphere(); - Vector3 groupPosition = new Vector3(10, 20, 30); - Quaternion rotationOffset = new Quaternion(20, 30, 40, 50); - rotationOffset.Normalize(); -// Vector3 offsetPosition = new Vector3(5, 10, 15); - - return new SceneObjectPart(ownerId, shape, groupPosition, rotationOffset, Vector3.Zero) { Name = partName }; - } - - protected SceneObjectPart CreateSceneObjectPart2() - { - string partName = "Action Man"; - UUID ownerId = UUID.Parse("00000000-0000-0000-0000-000000000016"); - PrimitiveBaseShape shape = PrimitiveBaseShape.CreateCylinder(); - Vector3 groupPosition = new Vector3(90, 80, 70); - Quaternion rotationOffset = new Quaternion(60, 70, 80, 90); - rotationOffset.Normalize(); - Vector3 offsetPosition = new Vector3(20, 25, 30); - - return new SceneObjectPart(ownerId, shape, groupPosition, rotationOffset, offsetPosition) { Name = partName }; - } - - private void CreateTestObjects(Scene scene, out SceneObjectGroup sog1, out SceneObjectGroup sog2, out UUID ncAssetUuid) - { - SceneObjectPart part1 = CreateSceneObjectPart1(); - sog1 = new SceneObjectGroup(part1); - scene.AddNewSceneObject(sog1, false); - - AssetNotecard nc = new AssetNotecard(); - nc.BodyText = "Hello World!"; - nc.Encode(); - ncAssetUuid = UUID.Random(); - UUID ncItemUuid = UUID.Random(); - AssetBase ncAsset - = AssetHelpers.CreateAsset(ncAssetUuid, AssetType.Notecard, nc.AssetData, UUID.Zero); - m_scene.AssetService.Store(ncAsset); - - TaskInventoryItem ncItem - = new TaskInventoryItem { Name = "ncItem", AssetID = ncAssetUuid, ItemID = ncItemUuid }; - SceneObjectPart part2 = CreateSceneObjectPart2(); - sog2 = new SceneObjectGroup(part2); - part2.Inventory.AddInventoryItem(ncItem, true); - - scene.AddNewSceneObject(sog2, false); - } - - private static void CreateSoundAsset(TarArchiveWriter tar, Assembly assembly, string soundDataResourceName, out byte[] soundData, out UUID soundUuid) - { - using (Stream resource = assembly.GetManifestResourceStream(soundDataResourceName)) - { - using (BinaryReader br = new BinaryReader(resource)) - { - // FIXME: Use the inspector instead - soundData = br.ReadBytes(99999999); - soundUuid = UUID.Parse("00000000-0000-0000-0000-000000000001"); - string soundAssetFileName - = ArchiveConstants.ASSETS_PATH + soundUuid - + ArchiveConstants.ASSET_TYPE_TO_EXTENSION[(sbyte)AssetType.SoundWAV]; - tar.WriteFile(soundAssetFileName, soundData); - - /* - AssetBase soundAsset = AssetHelpers.CreateAsset(soundUuid, soundData); - scene.AssetService.Store(soundAsset); - asset1FileName = ArchiveConstants.ASSETS_PATH + soundUuid + ".wav"; - */ - } - } - } - - /// - /// Test saving an OpenSim Region Archive. - /// - [Test] - public void TestSaveOar() - { - TestHelpers.InMethod(); -// log4net.Config.XmlConfigurator.Configure(); - - SceneObjectGroup sog1; - SceneObjectGroup sog2; - UUID ncAssetUuid; - CreateTestObjects(m_scene, out sog1, out sog2, out ncAssetUuid); - - MemoryStream archiveWriteStream = new MemoryStream(); - m_scene.EventManager.OnOarFileSaved += SaveCompleted; - - Guid requestId = new Guid("00000000-0000-0000-0000-808080808080"); - - m_oarEvent.Reset(); - m_archiverModule.ArchiveRegion(archiveWriteStream, requestId); - //AssetServerBase assetServer = (AssetServerBase)scene.CommsManager.AssetCache.AssetServer; - //while (assetServer.HasWaitingRequests()) - // assetServer.ProcessNextRequest(); - - m_oarEvent.WaitOne(60000); - - Assert.That(m_lastRequestId, Is.EqualTo(requestId)); - - byte[] archive = archiveWriteStream.ToArray(); - MemoryStream archiveReadStream = new MemoryStream(archive); - TarArchiveReader tar = new TarArchiveReader(archiveReadStream); - - bool gotNcAssetFile = false; - - string expectedNcAssetFileName = string.Format("{0}_{1}", ncAssetUuid, "notecard.txt"); - - List foundPaths = new List(); - List expectedPaths = new List(); - expectedPaths.Add(ArchiveHelpers.CreateObjectPath(sog1)); - expectedPaths.Add(ArchiveHelpers.CreateObjectPath(sog2)); - - string filePath; - TarArchiveReader.TarEntryType tarEntryType; - - byte[] data = tar.ReadEntry(out filePath, out tarEntryType); - Assert.That(filePath, Is.EqualTo(ArchiveConstants.CONTROL_FILE_PATH)); - - Dictionary archiveOptions = new Dictionary(); - ArchiveReadRequest arr = new ArchiveReadRequest(m_scene, (Stream)null, Guid.Empty, archiveOptions); - arr.LoadControlFile(filePath, data, new DearchiveScenesInfo()); - - Assert.That(arr.ControlFileLoaded, Is.True); - - while (tar.ReadEntry(out filePath, out tarEntryType) != null) - { - if (filePath.StartsWith(ArchiveConstants.ASSETS_PATH)) - { - string fileName = filePath.Remove(0, ArchiveConstants.ASSETS_PATH.Length); - - Assert.That(fileName, Is.EqualTo(expectedNcAssetFileName)); - gotNcAssetFile = true; - } - else if (filePath.StartsWith(ArchiveConstants.OBJECTS_PATH)) - { - foundPaths.Add(filePath); - } - } - - Assert.That(gotNcAssetFile, Is.True, "No notecard asset file in archive"); - Assert.That(foundPaths, Is.EquivalentTo(expectedPaths)); - - // TODO: Test presence of more files and contents of files. - } - - /// - /// Test saving an OpenSim Region Archive with the no assets option - /// - [Test] - public void TestSaveOarNoAssets() - { - TestHelpers.InMethod(); -// log4net.Config.XmlConfigurator.Configure(); - - SceneObjectPart part1 = CreateSceneObjectPart1(); - SceneObjectGroup sog1 = new SceneObjectGroup(part1); - m_scene.AddNewSceneObject(sog1, false); - - SceneObjectPart part2 = CreateSceneObjectPart2(); - - AssetNotecard nc = new AssetNotecard(); - nc.BodyText = "Hello World!"; - nc.Encode(); - UUID ncAssetUuid = new UUID("00000000-0000-0000-1000-000000000000"); - UUID ncItemUuid = new UUID("00000000-0000-0000-1100-000000000000"); - AssetBase ncAsset - = AssetHelpers.CreateAsset(ncAssetUuid, AssetType.Notecard, nc.AssetData, UUID.Zero); - m_scene.AssetService.Store(ncAsset); - SceneObjectGroup sog2 = new SceneObjectGroup(part2); - TaskInventoryItem ncItem - = new TaskInventoryItem { Name = "ncItem", AssetID = ncAssetUuid, ItemID = ncItemUuid }; - part2.Inventory.AddInventoryItem(ncItem, true); - - m_scene.AddNewSceneObject(sog2, false); - - MemoryStream archiveWriteStream = new MemoryStream(); - - Guid requestId = new Guid("00000000-0000-0000-0000-808080808080"); - - Dictionary options = new Dictionary(); - options.Add("noassets", true); - - m_archiverModule.ArchiveRegion(archiveWriteStream, requestId, options); - - // Don't wait for completion - with --noassets save oar happens synchronously -// Monitor.Wait(this, 60000); - - Assert.That(m_lastRequestId, Is.EqualTo(requestId)); - - byte[] archive = archiveWriteStream.ToArray(); - MemoryStream archiveReadStream = new MemoryStream(archive); - TarArchiveReader tar = new TarArchiveReader(archiveReadStream); - - List foundPaths = new List(); - List expectedPaths = new List(); - expectedPaths.Add(ArchiveHelpers.CreateObjectPath(sog1)); - expectedPaths.Add(ArchiveHelpers.CreateObjectPath(sog2)); - - string filePath; - TarArchiveReader.TarEntryType tarEntryType; - - byte[] data = tar.ReadEntry(out filePath, out tarEntryType); - Assert.That(filePath, Is.EqualTo(ArchiveConstants.CONTROL_FILE_PATH)); - - Dictionary archiveOptions = new Dictionary(); - ArchiveReadRequest arr = new ArchiveReadRequest(m_scene, (Stream)null, Guid.Empty, archiveOptions); - arr.LoadControlFile(filePath, data, new DearchiveScenesInfo()); - - Assert.That(arr.ControlFileLoaded, Is.True); - - while (tar.ReadEntry(out filePath, out tarEntryType) != null) - { - if (filePath.StartsWith(ArchiveConstants.ASSETS_PATH)) - { - Assert.Fail("Asset was found in saved oar of TestSaveOarNoAssets()"); - } - else if (filePath.StartsWith(ArchiveConstants.OBJECTS_PATH)) - { - foundPaths.Add(filePath); - } - } - - Assert.That(foundPaths, Is.EquivalentTo(expectedPaths)); - - // TODO: Test presence of more files and contents of files. - } - - /// - /// Test loading an OpenSim Region Archive. - /// - [Test] - public void TestLoadOar() - { - TestHelpers.InMethod(); -// log4net.Config.XmlConfigurator.Configure(); - - MemoryStream archiveWriteStream = new MemoryStream(); - TarArchiveWriter tar = new TarArchiveWriter(archiveWriteStream); - - // Put in a random blank directory to check that this doesn't upset the load process - tar.WriteDir("ignoreme"); - - // Also check that direct entries which will also have a file entry containing that directory doesn't - // upset load - tar.WriteDir(ArchiveConstants.TERRAINS_PATH); - - tar.WriteFile( - ArchiveConstants.CONTROL_FILE_PATH, - new ArchiveWriteRequest(m_scene, (Stream)null, Guid.Empty).CreateControlFile(new ArchiveScenesGroup())); - SceneObjectPart part1 = CreateSceneObjectPart1(); - - part1.SitTargetOrientation = new Quaternion(0.2f, 0.3f, 0.4f, 0.5f); - part1.SitTargetPosition = new Vector3(1, 2, 3); - - SceneObjectGroup object1 = new SceneObjectGroup(part1); - - // Let's put some inventory items into our object - string soundItemName = "sound-item1"; - UUID soundItemUuid = UUID.Parse("00000000-0000-0000-0000-000000000002"); - Type type = GetType(); - Assembly assembly = type.Assembly; - string soundDataResourceName = null; - string[] names = assembly.GetManifestResourceNames(); - foreach (string name in names) - { - if (name.EndsWith(".Resources.test-sound.wav")) - soundDataResourceName = name; - } - Assert.That(soundDataResourceName, Is.Not.Null); - - byte[] soundData; - UUID soundUuid; - CreateSoundAsset(tar, assembly, soundDataResourceName, out soundData, out soundUuid); - - TaskInventoryItem item1 - = new TaskInventoryItem { AssetID = soundUuid, ItemID = soundItemUuid, Name = soundItemName }; - part1.Inventory.AddInventoryItem(item1, true); - m_scene.AddNewSceneObject(object1, false); - - string object1FileName = string.Format( - "{0}_{1:000}-{2:000}-{3:000}__{4}.xml", - part1.Name, - Math.Round(part1.GroupPosition.X), Math.Round(part1.GroupPosition.Y), Math.Round(part1.GroupPosition.Z), - part1.UUID); - tar.WriteFile(ArchiveConstants.OBJECTS_PATH + object1FileName, SceneObjectSerializer.ToXml2Format(object1)); - - tar.Close(); - - MemoryStream archiveReadStream = new MemoryStream(archiveWriteStream.ToArray()); - - m_scene.EventManager.OnOarFileLoaded += LoadCompleted; - m_oarEvent.Reset(); - m_archiverModule.DearchiveRegion(archiveReadStream); - - m_oarEvent.WaitOne(60000); - - Assert.That(m_lastErrorMessage, Is.Null); - - TestLoadedRegion(part1, soundItemName, soundData); - } - - /// - /// Test loading an OpenSim Region Archive where the scene object parts are not ordered by link number (e.g. - /// 2 can come after 3). - /// - [Test] - public void TestLoadOarUnorderedParts() - { - TestHelpers.InMethod(); - - UUID ownerId = TestHelpers.ParseTail(0xaaaa); - - MemoryStream archiveWriteStream = new MemoryStream(); - TarArchiveWriter tar = new TarArchiveWriter(archiveWriteStream); - - tar.WriteFile( - ArchiveConstants.CONTROL_FILE_PATH, - new ArchiveWriteRequest(m_scene, (Stream)null, Guid.Empty).CreateControlFile(new ArchiveScenesGroup())); - - SceneObjectGroup sog1 = SceneHelpers.CreateSceneObject(1, ownerId, "obj1-", 0x11); - SceneObjectPart sop2 - = SceneHelpers.CreateSceneObjectPart("obj1-Part2", TestHelpers.ParseTail(0x12), ownerId); - SceneObjectPart sop3 - = SceneHelpers.CreateSceneObjectPart("obj1-Part3", TestHelpers.ParseTail(0x13), ownerId); - - // Add the parts so they will be written out in reverse order to the oar - sog1.AddPart(sop3); - sop3.LinkNum = 3; - sog1.AddPart(sop2); - sop2.LinkNum = 2; - - tar.WriteFile( - ArchiveConstants.CreateOarObjectPath(sog1.Name, sog1.UUID, sog1.AbsolutePosition), - SceneObjectSerializer.ToXml2Format(sog1)); - - tar.Close(); - - MemoryStream archiveReadStream = new MemoryStream(archiveWriteStream.ToArray()); - - m_scene.EventManager.OnOarFileLoaded += LoadCompleted; - m_oarEvent.Reset(); - m_archiverModule.DearchiveRegion(archiveReadStream); - - m_oarEvent.WaitOne(60000); - - Assert.That(m_lastErrorMessage, Is.Null); - - SceneObjectPart part2 = m_scene.GetSceneObjectPart("obj1-Part2"); - Assert.That(part2.LinkNum, Is.EqualTo(2)); - - SceneObjectPart part3 = m_scene.GetSceneObjectPart("obj1-Part3"); - Assert.That(part3.LinkNum, Is.EqualTo(3)); - } - - /// - /// Test loading an OpenSim Region Archive saved with the --publish option. - /// - [Test] - public void TestLoadPublishedOar() - { - TestHelpers.InMethod(); -// log4net.Config.XmlConfigurator.Configure(); - - SceneObjectPart part1 = CreateSceneObjectPart1(); - SceneObjectGroup sog1 = new SceneObjectGroup(part1); - m_scene.AddNewSceneObject(sog1, false); - - SceneObjectPart part2 = CreateSceneObjectPart2(); - - AssetNotecard nc = new AssetNotecard(); - nc.BodyText = "Hello World!"; - nc.Encode(); - UUID ncAssetUuid = new UUID("00000000-0000-0000-1000-000000000000"); - UUID ncItemUuid = new UUID("00000000-0000-0000-1100-000000000000"); - AssetBase ncAsset - = AssetHelpers.CreateAsset(ncAssetUuid, AssetType.Notecard, nc.AssetData, UUID.Zero); - m_scene.AssetService.Store(ncAsset); - SceneObjectGroup sog2 = new SceneObjectGroup(part2); - TaskInventoryItem ncItem - = new TaskInventoryItem { Name = "ncItem", AssetID = ncAssetUuid, ItemID = ncItemUuid }; - part2.Inventory.AddInventoryItem(ncItem, true); - - m_scene.AddNewSceneObject(sog2, false); - - MemoryStream archiveWriteStream = new MemoryStream(); - m_scene.EventManager.OnOarFileSaved += SaveCompleted; - - Guid requestId = new Guid("00000000-0000-0000-0000-808080808080"); - - m_oarEvent.Reset(); - m_archiverModule.ArchiveRegion( - archiveWriteStream, requestId, new Dictionary() { { "wipe-owners", Boolean.TrueString } }); - - m_oarEvent.WaitOne(60000); - - Assert.That(m_lastRequestId, Is.EqualTo(requestId)); - - byte[] archive = archiveWriteStream.ToArray(); - MemoryStream archiveReadStream = new MemoryStream(archive); - - { - UUID estateOwner = TestHelpers.ParseTail(0x4747); - UUID objectOwner = TestHelpers.ParseTail(0x15); - - // Reload to new scene - ArchiverModule archiverModule = new ArchiverModule(); - SerialiserModule serialiserModule = new SerialiserModule(); - TerrainModule terrainModule = new TerrainModule(); - - SceneHelpers m_sceneHelpers2 = new SceneHelpers(); - TestScene scene2 = m_sceneHelpers2.SetupScene(); - SceneHelpers.SetupSceneModules(scene2, archiverModule, serialiserModule, terrainModule); - - // Make sure there's a valid owner for the owner we saved (this should have been wiped if the code is - // behaving correctly - UserAccountHelpers.CreateUserWithInventory(scene2, objectOwner); - - scene2.RegionInfo.EstateSettings.EstateOwner = estateOwner; - - scene2.EventManager.OnOarFileLoaded += LoadCompleted; - m_oarEvent.Reset(); - archiverModule.DearchiveRegion(archiveReadStream); - - m_oarEvent.WaitOne(60000); - - Assert.That(m_lastErrorMessage, Is.Null); - - SceneObjectGroup loadedSog = scene2.GetSceneObjectGroup(part1.Name); - Assert.That(loadedSog.OwnerID, Is.EqualTo(estateOwner)); - Assert.That(loadedSog.LastOwnerID, Is.EqualTo(estateOwner)); - } - } - - /// - /// Test OAR loading where the land parcel is group deeded. - /// - /// - /// In this situation, the owner ID is set to the group ID. - /// - [Test] - public void TestLoadOarDeededLand() - { - TestHelpers.InMethod(); -// TestHelpers.EnableLogging(); - - UUID landID = TestHelpers.ParseTail(0x10); - - MockGroupsServicesConnector groupsService = new MockGroupsServicesConnector(); - - IConfigSource configSource = new IniConfigSource(); - IConfig config = configSource.AddConfig("Groups"); - config.Set("Enabled", true); - config.Set("Module", "GroupsModule"); - config.Set("DebugEnabled", true); - SceneHelpers.SetupSceneModules( - m_scene, configSource, new object[] { new GroupsModule(), groupsService, new LandManagementModule() }); - - // Create group in scene for loading - // FIXME: For now we'll put up with the issue that we'll get a group ID that varies across tests. - UUID groupID - = groupsService.CreateGroup(UUID.Zero, "group1", "", true, UUID.Zero, 3, true, true, true, UUID.Zero); - - // Construct OAR - MemoryStream oarStream = new MemoryStream(); - TarArchiveWriter tar = new TarArchiveWriter(oarStream); - - tar.WriteDir(ArchiveConstants.LANDDATA_PATH); - tar.WriteFile( - ArchiveConstants.CONTROL_FILE_PATH, - new ArchiveWriteRequest(m_scene, (Stream)null, Guid.Empty).CreateControlFile(new ArchiveScenesGroup())); - - LandObject lo = new LandObject(groupID, true, m_scene); - lo.SetLandBitmap(lo.BasicFullRegionLandBitmap()); - LandData ld = lo.LandData; - ld.GlobalID = landID; - - string ldPath = ArchiveConstants.CreateOarLandDataPath(ld); - Dictionary options = new Dictionary(); - tar.WriteFile(ldPath, LandDataSerializer.Serialize(ld, options)); - tar.Close(); - - oarStream = new MemoryStream(oarStream.ToArray()); - - // Load OAR - m_scene.EventManager.OnOarFileLoaded += LoadCompleted; - m_oarEvent.Reset(); - m_archiverModule.DearchiveRegion(oarStream); - - m_oarEvent.WaitOne(60000); - - ILandObject rLo = m_scene.LandChannel.GetLandObject(16, 16); - LandData rLd = rLo.LandData; - - Assert.That(rLd.GlobalID, Is.EqualTo(landID)); - Assert.That(rLd.OwnerID, Is.EqualTo(groupID)); - Assert.That(rLd.GroupID, Is.EqualTo(groupID)); - Assert.That(rLd.IsGroupOwned, Is.EqualTo(true)); - } - - /// - /// Test loading the region settings of an OpenSim Region Archive. - /// - [Test] - public void TestLoadOarRegionSettings() - { - TestHelpers.InMethod(); - //log4net.Config.XmlConfigurator.Configure(); - - MemoryStream archiveWriteStream = new MemoryStream(); - TarArchiveWriter tar = new TarArchiveWriter(archiveWriteStream); - - tar.WriteDir(ArchiveConstants.TERRAINS_PATH); - tar.WriteFile( - ArchiveConstants.CONTROL_FILE_PATH, - new ArchiveWriteRequest(m_scene, (Stream)null, Guid.Empty).CreateControlFile(new ArchiveScenesGroup())); - - RegionSettings rs = new RegionSettings(); - rs.AgentLimit = 17; - rs.AllowDamage = true; - rs.AllowLandJoinDivide = true; - rs.AllowLandResell = true; - rs.BlockFly = true; - rs.BlockShowInSearch = true; - rs.BlockTerraform = true; - rs.DisableCollisions = true; - rs.DisablePhysics = true; - rs.DisableScripts = true; - rs.Elevation1NW = 15.9; - rs.Elevation1NE = 45.3; - rs.Elevation1SE = 49; - rs.Elevation1SW = 1.9; - rs.Elevation2NW = 4.5; - rs.Elevation2NE = 19.2; - rs.Elevation2SE = 9.2; - rs.Elevation2SW = 2.1; - rs.FixedSun = true; - rs.SunPosition = 12.0; - rs.ObjectBonus = 1.4; - rs.RestrictPushing = true; - rs.TerrainLowerLimit = -17.9; - rs.TerrainRaiseLimit = 17.9; - rs.TerrainTexture1 = UUID.Parse("00000000-0000-0000-0000-000000000020"); - rs.TerrainTexture2 = UUID.Parse("00000000-0000-0000-0000-000000000040"); - rs.TerrainTexture3 = UUID.Parse("00000000-0000-0000-0000-000000000060"); - rs.TerrainTexture4 = UUID.Parse("00000000-0000-0000-0000-000000000080"); - rs.UseEstateSun = true; - rs.WaterHeight = 23; - rs.TelehubObject = UUID.Parse("00000000-0000-0000-0000-111111111111"); - rs.AddSpawnPoint(SpawnPoint.Parse("1,-2,0.33")); - - tar.WriteFile(ArchiveConstants.SETTINGS_PATH + "region1.xml", RegionSettingsSerializer.Serialize(rs, null, new EstateSettings())); - - tar.Close(); - - MemoryStream archiveReadStream = new MemoryStream(archiveWriteStream.ToArray()); - - m_scene.EventManager.OnOarFileLoaded += LoadCompleted; - m_oarEvent.Reset(); - m_archiverModule.DearchiveRegion(archiveReadStream); - - m_oarEvent.WaitOne(60000); - - Assert.That(m_lastErrorMessage, Is.Null); - RegionSettings loadedRs = m_scene.RegionInfo.RegionSettings; - - Assert.That(loadedRs.AgentLimit, Is.EqualTo(17)); - Assert.That(loadedRs.AllowDamage, Is.True); - Assert.That(loadedRs.AllowLandJoinDivide, Is.True); - Assert.That(loadedRs.AllowLandResell, Is.True); - Assert.That(loadedRs.BlockFly, Is.True); - Assert.That(loadedRs.BlockShowInSearch, Is.True); - Assert.That(loadedRs.BlockTerraform, Is.True); - Assert.That(loadedRs.DisableCollisions, Is.True); - Assert.That(loadedRs.DisablePhysics, Is.True); - Assert.That(loadedRs.DisableScripts, Is.True); - Assert.That(loadedRs.Elevation1NW, Is.EqualTo(15.9)); - Assert.That(loadedRs.Elevation1NE, Is.EqualTo(45.3)); - Assert.That(loadedRs.Elevation1SE, Is.EqualTo(49)); - Assert.That(loadedRs.Elevation1SW, Is.EqualTo(1.9)); - Assert.That(loadedRs.Elevation2NW, Is.EqualTo(4.5)); - Assert.That(loadedRs.Elevation2NE, Is.EqualTo(19.2)); - Assert.That(loadedRs.Elevation2SE, Is.EqualTo(9.2)); - Assert.That(loadedRs.Elevation2SW, Is.EqualTo(2.1)); - Assert.That(loadedRs.ObjectBonus, Is.EqualTo(1.4)); - Assert.That(loadedRs.RestrictPushing, Is.True); - Assert.That(loadedRs.TerrainLowerLimit, Is.EqualTo(-17.9)); - Assert.That(loadedRs.TerrainRaiseLimit, Is.EqualTo(17.9)); - Assert.That(loadedRs.TerrainTexture1, Is.EqualTo(UUID.Parse("00000000-0000-0000-0000-000000000020"))); - Assert.That(loadedRs.TerrainTexture2, Is.EqualTo(UUID.Parse("00000000-0000-0000-0000-000000000040"))); - Assert.That(loadedRs.TerrainTexture3, Is.EqualTo(UUID.Parse("00000000-0000-0000-0000-000000000060"))); - Assert.That(loadedRs.TerrainTexture4, Is.EqualTo(UUID.Parse("00000000-0000-0000-0000-000000000080"))); - Assert.That(loadedRs.WaterHeight, Is.EqualTo(23)); - Assert.AreEqual(UUID.Zero, loadedRs.TelehubObject); // because no object was found with the original UUID - Assert.AreEqual(0, loadedRs.SpawnPoints().Count); - } - - /// - /// Test merging an OpenSim Region Archive into an existing scene - /// - //[Test] - public void TestMergeOar() - { - TestHelpers.InMethod(); - //XmlConfigurator.Configure(); - - MemoryStream archiveWriteStream = new MemoryStream(); - -// string part2Name = "objectMerge"; -// PrimitiveBaseShape part2Shape = PrimitiveBaseShape.CreateCylinder(); -// Vector3 part2GroupPosition = new Vector3(90, 80, 70); -// Quaternion part2RotationOffset = new Quaternion(60, 70, 80, 90); -// Vector3 part2OffsetPosition = new Vector3(20, 25, 30); - - SceneObjectPart part2 = CreateSceneObjectPart2(); - - // Create an oar file that we can use for the merge - { - ArchiverModule archiverModule = new ArchiverModule(); - SerialiserModule serialiserModule = new SerialiserModule(); - TerrainModule terrainModule = new TerrainModule(); - - Scene scene = m_sceneHelpers.SetupScene(); - SceneHelpers.SetupSceneModules(scene, archiverModule, serialiserModule, terrainModule); - - m_scene.AddNewSceneObject(new SceneObjectGroup(part2), false); - - // Write out this scene - - scene.EventManager.OnOarFileSaved += SaveCompleted; - m_oarEvent.Reset(); - m_archiverModule.ArchiveRegion(archiveWriteStream); - - m_oarEvent.WaitOne(60000); - } - - { - SceneObjectPart part1 = CreateSceneObjectPart1(); - m_scene.AddNewSceneObject(new SceneObjectGroup(part1), false); - - // Merge in the archive we created earlier - byte[] archive = archiveWriteStream.ToArray(); - MemoryStream archiveReadStream = new MemoryStream(archive); - - m_scene.EventManager.OnOarFileLoaded += LoadCompleted; - Dictionary archiveOptions = new Dictionary(); - archiveOptions.Add("merge", null); - m_oarEvent.Reset(); - m_archiverModule.DearchiveRegion(archiveReadStream, Guid.Empty, archiveOptions); - - m_oarEvent.WaitOne(60000); - - SceneObjectPart object1Existing = m_scene.GetSceneObjectPart(part1.Name); - Assert.That(object1Existing, Is.Not.Null, "object1 was not present after merge"); - Assert.That(object1Existing.Name, Is.EqualTo(part1.Name), "object1 names not identical after merge"); - Assert.That(object1Existing.GroupPosition, Is.EqualTo(part1.GroupPosition), "object1 group position not equal after merge"); - - SceneObjectPart object2PartMerged = m_scene.GetSceneObjectPart(part2.Name); - Assert.That(object2PartMerged, Is.Not.Null, "object2 was not present after merge"); - Assert.That(object2PartMerged.Name, Is.EqualTo(part2.Name), "object2 names not identical after merge"); - Assert.That(object2PartMerged.GroupPosition, Is.EqualTo(part2.GroupPosition), "object2 group position not equal after merge"); - } - } - - /// - /// Test saving a multi-region OAR. - /// - [Test] - public void TestSaveMultiRegionOar() - { - TestHelpers.InMethod(); - - // Create test regions - - int WIDTH = 2; - int HEIGHT = 2; - - List scenes = new List(); - - // Maps (Directory in OAR file -> scene) - Dictionary regionPaths = new Dictionary(); - - // Maps (Scene -> expected object paths) - Dictionary> expectedPaths = new Dictionary>(); - - // List of expected assets - List expectedAssets = new List(); - - for (uint y = 0; y < HEIGHT; y++) - { - for (uint x = 0; x < WIDTH; x++) - { - Scene scene; - if (x == 0 && y == 0) - { - scene = m_scene; // this scene was already created in SetUp() - } - else - { - scene = m_sceneHelpers.SetupScene(string.Format("Unit test region {0}", (y * WIDTH) + x + 1), UUID.Random(), 1000 + x, 1000 + y); - SceneHelpers.SetupSceneModules(scene, new ArchiverModule(), m_serialiserModule, new TerrainModule()); - } - scenes.Add(scene); - - string dir = String.Format("{0}_{1}_{2}", x + 1, y + 1, scene.RegionInfo.RegionName.Replace(" ", "_")); - regionPaths[dir] = scene; - - SceneObjectGroup sog1; - SceneObjectGroup sog2; - UUID ncAssetUuid; - - CreateTestObjects(scene, out sog1, out sog2, out ncAssetUuid); - - expectedPaths[scene.RegionInfo.RegionID] = new List(); - expectedPaths[scene.RegionInfo.RegionID].Add(ArchiveHelpers.CreateObjectPath(sog1)); - expectedPaths[scene.RegionInfo.RegionID].Add(ArchiveHelpers.CreateObjectPath(sog2)); - - expectedAssets.Add(ncAssetUuid); - } - } - - // Save OAR - MemoryStream archiveWriteStream = new MemoryStream(); - - Guid requestId = new Guid("00000000-0000-0000-0000-808080808080"); - - Dictionary options = new Dictionary(); - options.Add("all", true); - - m_scene.EventManager.OnOarFileSaved += SaveCompleted; - m_oarEvent.Reset(); - m_archiverModule.ArchiveRegion(archiveWriteStream, requestId, options); - - m_oarEvent.WaitOne(60000); - - - // Check that the OAR contains the expected data - Assert.That(m_lastRequestId, Is.EqualTo(requestId)); - - byte[] archive = archiveWriteStream.ToArray(); - MemoryStream archiveReadStream = new MemoryStream(archive); - TarArchiveReader tar = new TarArchiveReader(archiveReadStream); - - Dictionary> foundPaths = new Dictionary>(); - List foundAssets = new List(); - - foreach (Scene scene in scenes) - { - foundPaths[scene.RegionInfo.RegionID] = new List(); - } - - string filePath; - TarArchiveReader.TarEntryType tarEntryType; - - byte[] data = tar.ReadEntry(out filePath, out tarEntryType); - Assert.That(filePath, Is.EqualTo(ArchiveConstants.CONTROL_FILE_PATH)); - - Dictionary archiveOptions = new Dictionary(); - ArchiveReadRequest arr = new ArchiveReadRequest(m_scene, (Stream)null, Guid.Empty, archiveOptions); - arr.LoadControlFile(filePath, data, new DearchiveScenesInfo()); - - Assert.That(arr.ControlFileLoaded, Is.True); - - while (tar.ReadEntry(out filePath, out tarEntryType) != null) - { - if (filePath.StartsWith(ArchiveConstants.ASSETS_PATH)) - { - // Assets are shared, so this file doesn't belong to any specific region. - string fileName = filePath.Remove(0, ArchiveConstants.ASSETS_PATH.Length); - if (fileName.EndsWith("_notecard.txt")) - foundAssets.Add(UUID.Parse(fileName.Substring(0, fileName.Length - "_notecard.txt".Length))); - } - else - { - // This file belongs to one of the regions. Find out which one. - Assert.IsTrue(filePath.StartsWith(ArchiveConstants.REGIONS_PATH)); - string[] parts = filePath.Split(new Char[] { '/' }, 3); - Assert.AreEqual(3, parts.Length); - string regionDirectory = parts[1]; - string relativePath = parts[2]; - Scene scene = regionPaths[regionDirectory]; - - if (relativePath.StartsWith(ArchiveConstants.OBJECTS_PATH)) - { - foundPaths[scene.RegionInfo.RegionID].Add(relativePath); - } - } - } - - Assert.AreEqual(scenes.Count, foundPaths.Count); - foreach (Scene scene in scenes) - { - Assert.That(foundPaths[scene.RegionInfo.RegionID], Is.EquivalentTo(expectedPaths[scene.RegionInfo.RegionID])); - } - - Assert.That(foundAssets, Is.EquivalentTo(expectedAssets)); - } - - /// - /// Test loading a multi-region OAR. - /// - [Test] - public void TestLoadMultiRegionOar() - { - TestHelpers.InMethod(); - - // Create an ArchiveScenesGroup with the regions in the OAR. This is needed to generate the control file. - - int WIDTH = 2; - int HEIGHT = 2; - - for (uint y = 0; y < HEIGHT; y++) - { - for (uint x = 0; x < WIDTH; x++) - { - Scene scene; - if (x == 0 && y == 0) - { - scene = m_scene; // this scene was already created in SetUp() - } - else - { - scene = m_sceneHelpers.SetupScene(string.Format("Unit test region {0}", (y * WIDTH) + x + 1), UUID.Random(), 1000 + x, 1000 + y); - SceneHelpers.SetupSceneModules(scene, new ArchiverModule(), m_serialiserModule, new TerrainModule()); - } - } - } - - ArchiveScenesGroup scenesGroup = new ArchiveScenesGroup(); - m_sceneHelpers.SceneManager.ForEachScene(delegate(Scene scene) - { - scenesGroup.AddScene(scene); - }); - scenesGroup.CalcSceneLocations(); - - // Generate the OAR file - - MemoryStream archiveWriteStream = new MemoryStream(); - TarArchiveWriter tar = new TarArchiveWriter(archiveWriteStream); - - ArchiveWriteRequest writeRequest = new ArchiveWriteRequest(m_scene, (Stream)null, Guid.Empty); - writeRequest.MultiRegionFormat = true; - tar.WriteFile( - ArchiveConstants.CONTROL_FILE_PATH, writeRequest.CreateControlFile(scenesGroup)); - - SceneObjectPart part1 = CreateSceneObjectPart1(); - part1.SitTargetOrientation = new Quaternion(0.2f, 0.3f, 0.4f, 0.5f); - part1.SitTargetPosition = new Vector3(1, 2, 3); - - SceneObjectGroup object1 = new SceneObjectGroup(part1); - - // Let's put some inventory items into our object - string soundItemName = "sound-item1"; - UUID soundItemUuid = UUID.Parse("00000000-0000-0000-0000-000000000002"); - Type type = GetType(); - Assembly assembly = type.Assembly; - string soundDataResourceName = null; - string[] names = assembly.GetManifestResourceNames(); - foreach (string name in names) - { - if (name.EndsWith(".Resources.test-sound.wav")) - soundDataResourceName = name; - } - Assert.That(soundDataResourceName, Is.Not.Null); - - byte[] soundData; - UUID soundUuid; - CreateSoundAsset(tar, assembly, soundDataResourceName, out soundData, out soundUuid); - - TaskInventoryItem item1 - = new TaskInventoryItem { AssetID = soundUuid, ItemID = soundItemUuid, Name = soundItemName }; - part1.Inventory.AddInventoryItem(item1, true); - m_scene.AddNewSceneObject(object1, false); - - string object1FileName = string.Format( - "{0}_{1:000}-{2:000}-{3:000}__{4}.xml", - part1.Name, - Math.Round(part1.GroupPosition.X), Math.Round(part1.GroupPosition.Y), Math.Round(part1.GroupPosition.Z), - part1.UUID); - string path = "regions/1_1_Unit_test_region/" + ArchiveConstants.OBJECTS_PATH + object1FileName; - tar.WriteFile(path, SceneObjectSerializer.ToXml2Format(object1)); - - tar.Close(); - - - // Delete the current objects, to test that they're loaded from the OAR and didn't - // just remain in the scene. - m_sceneHelpers.SceneManager.ForEachScene(delegate(Scene scene) - { - scene.DeleteAllSceneObjects(); - }); - - // Create a "hole", to test that that the corresponding region isn't loaded from the OAR - m_sceneHelpers.SceneManager.CloseScene(SceneManager.Instance.Scenes[1]); - - - // Check thay the OAR file contains the expected data - - MemoryStream archiveReadStream = new MemoryStream(archiveWriteStream.ToArray()); - - m_scene.EventManager.OnOarFileLoaded += LoadCompleted; - m_oarEvent.Reset(); - m_archiverModule.DearchiveRegion(archiveReadStream); - - m_oarEvent.WaitOne(60000); - - Assert.That(m_lastErrorMessage, Is.Null); - - Assert.AreEqual(3, m_sceneHelpers.SceneManager.Scenes.Count); - - TestLoadedRegion(part1, soundItemName, soundData); - } - - private void TestLoadedRegion(SceneObjectPart part1, string soundItemName, byte[] soundData) - { - SceneObjectPart object1PartLoaded = m_scene.GetSceneObjectPart(part1.Name); - - Assert.That(object1PartLoaded, Is.Not.Null, "object1 was not loaded"); - Assert.That(object1PartLoaded.Name, Is.EqualTo(part1.Name), "object1 names not identical"); - Assert.That(object1PartLoaded.GroupPosition, Is.EqualTo(part1.GroupPosition), "object1 group position not equal"); - - Quaternion qtmp1 = new Quaternion ( - (float)Math.Round(object1PartLoaded.RotationOffset.X,5), - (float)Math.Round(object1PartLoaded.RotationOffset.Y,5), - (float)Math.Round(object1PartLoaded.RotationOffset.Z,5), - (float)Math.Round(object1PartLoaded.RotationOffset.W,5)); - Quaternion qtmp2 = new Quaternion ( - (float)Math.Round(part1.RotationOffset.X,5), - (float)Math.Round(part1.RotationOffset.Y,5), - (float)Math.Round(part1.RotationOffset.Z,5), - (float)Math.Round(part1.RotationOffset.W,5)); - - Assert.That(qtmp1, Is.EqualTo(qtmp2), "object1 rotation offset not equal"); - Assert.That( - object1PartLoaded.OffsetPosition, Is.EqualTo(part1.OffsetPosition), "object1 offset position not equal"); - Assert.That(object1PartLoaded.SitTargetOrientation, Is.EqualTo(part1.SitTargetOrientation)); - Assert.That(object1PartLoaded.SitTargetPosition, Is.EqualTo(part1.SitTargetPosition)); - - TaskInventoryItem loadedSoundItem = object1PartLoaded.Inventory.GetInventoryItems(soundItemName)[0]; - Assert.That(loadedSoundItem, Is.Not.Null, "loaded sound item was null"); - AssetBase loadedSoundAsset = m_scene.AssetService.Get(loadedSoundItem.AssetID.ToString()); - Assert.That(loadedSoundAsset, Is.Not.Null, "loaded sound asset was null"); - Assert.That(loadedSoundAsset.Data, Is.EqualTo(soundData), "saved and loaded sound data do not match"); - - Assert.Greater(m_scene.LandChannel.AllParcels().Count, 0, "incorrect number of parcels"); - } - } -} \ No newline at end of file diff --git a/OpenSim/Region/CoreModules/World/Archiver/Tests/Resources/test-sound.wav b/OpenSim/Region/CoreModules/World/Archiver/Tests/Resources/test-sound.wav deleted file mode 100755 index b45ee54d354c075cec2c681e057265bee4c8ccef..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 211648 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 diff --git a/OpenSim/Region/CoreModules/World/Land/Tests/LandManagementModuleTests.cs b/OpenSim/Region/CoreModules/World/Land/Tests/LandManagementModuleTests.cs deleted file mode 100644 index c512eac3e8c..00000000000 --- a/OpenSim/Region/CoreModules/World/Land/Tests/LandManagementModuleTests.cs +++ /dev/null @@ -1,266 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using NUnit.Framework; -using OpenMetaverse; -using OpenSim.Framework; -using OpenSim.Region.Framework.Scenes; -using OpenSim.Tests.Common; - -namespace OpenSim.Region.CoreModules.World.Land.Tests -{ - public class LandManagementModuleTests : OpenSimTestCase - { - [Test] - public void TestAddLandObject() - { - TestHelpers.InMethod(); -// TestHelpers.EnableLogging(); - - UUID userId = TestHelpers.ParseTail(0x1); - - LandManagementModule lmm = new LandManagementModule(); - Scene scene = new SceneHelpers().SetupScene(); - SceneHelpers.SetupSceneModules(scene, lmm); - - ILandObject lo = new LandObject(userId, false, scene); - lo.LandData.Name = "lo1"; - lo.SetLandBitmap( - lo.GetSquareLandBitmap(0, 0, (int)Constants.RegionSize, (int)Constants.RegionSize)); - lo = lmm.AddLandObject(lo); - - // TODO: Should add asserts to check that land object was added properly. - - // At the moment, this test just makes sure that we can't add a land object that overlaps the areas that - // the first still holds. - ILandObject lo2 = new LandObject(userId, false, scene); - lo2.SetLandBitmap( - lo2.GetSquareLandBitmap(0, 0, (int)Constants.RegionSize, (int)Constants.RegionSize)); - lo2.LandData.Name = "lo2"; - lo2 = lmm.AddLandObject(lo2); - - { - ILandObject loAtCoord = lmm.GetLandObject(0, 0); - Assert.That(loAtCoord.LandData.LocalID, Is.EqualTo(lo.LandData.LocalID)); - Assert.That(loAtCoord.LandData.GlobalID, Is.EqualTo(lo.LandData.GlobalID)); - } - - { - ILandObject loAtCoord = lmm.GetLandObject((int)Constants.RegionSize - 1, ((int)Constants.RegionSize - 1)); - Assert.That(loAtCoord.LandData.LocalID, Is.EqualTo(lo.LandData.LocalID)); - Assert.That(loAtCoord.LandData.GlobalID, Is.EqualTo(lo.LandData.GlobalID)); - } - } - - /// - /// Test parcels on region when no land data exists to be loaded. - /// - [Test] - public void TestLoadWithNoParcels() - { - TestHelpers.InMethod(); -// TestHelpers.EnableLogging(); - - SceneHelpers sh = new SceneHelpers(); - LandManagementModule lmm = new LandManagementModule(); - Scene scene = sh.SetupScene(); - SceneHelpers.SetupSceneModules(scene, lmm); - - scene.loadAllLandObjectsFromStorage(scene.RegionInfo.RegionID); - - ILandObject loAtCoord1 = lmm.GetLandObject(0, 0); - Assert.That(loAtCoord1.LandData.LocalID, Is.Not.EqualTo(0)); - Assert.That(loAtCoord1.LandData.GlobalID, Is.Not.EqualTo(UUID.Zero)); - - ILandObject loAtCoord2 = lmm.GetLandObject((int)Constants.RegionSize - 1, ((int)Constants.RegionSize - 1)); - Assert.That(loAtCoord2.LandData.LocalID, Is.EqualTo(loAtCoord1.LandData.LocalID)); - Assert.That(loAtCoord2.LandData.GlobalID, Is.EqualTo(loAtCoord1.LandData.GlobalID)); - } - - /// - /// Test parcels on region when a single parcel already exists but it does not cover the whole region. - /// - [Test] - public void TestLoadWithSinglePartialCoveringParcel() - { - TestHelpers.InMethod(); -// TestHelpers.EnableLogging(); - - UUID userId = TestHelpers.ParseTail(0x1); - - SceneHelpers sh = new SceneHelpers(); - LandManagementModule lmm = new LandManagementModule(); - Scene scene = sh.SetupScene(); - SceneHelpers.SetupSceneModules(scene, lmm); - - ILandObject originalLo1 = new LandObject(userId, false, scene); - originalLo1.LandData.Name = "lo1"; - originalLo1.SetLandBitmap( - originalLo1.GetSquareLandBitmap(0, 0, (int)Constants.RegionSize, (int)Constants.RegionSize / 2)); - - sh.SimDataService.StoreLandObject(originalLo1); - - scene.loadAllLandObjectsFromStorage(scene.RegionInfo.RegionID); - - ILandObject loAtCoord1 = lmm.GetLandObject(0, 0); - Assert.That(loAtCoord1.LandData.Name, Is.EqualTo(originalLo1.LandData.Name)); - Assert.That(loAtCoord1.LandData.GlobalID, Is.EqualTo(originalLo1.LandData.GlobalID)); - - ILandObject loAtCoord2 = lmm.GetLandObject((int)Constants.RegionSize - 1, ((int)Constants.RegionSize - 1)); - Assert.That(loAtCoord2.LandData.LocalID, Is.EqualTo(loAtCoord1.LandData.LocalID)); - Assert.That(loAtCoord2.LandData.GlobalID, Is.EqualTo(loAtCoord1.LandData.GlobalID)); - } - - /// - /// Test parcels on region when a single parcel already exists but it does not cover the whole region. - /// - [Test] - public void TestLoadWithMultiplePartialCoveringParcels() - { - TestHelpers.InMethod(); -// TestHelpers.EnableLogging(); - - UUID userId = TestHelpers.ParseTail(0x1); - - SceneHelpers sh = new SceneHelpers(); - LandManagementModule lmm = new LandManagementModule(); - Scene scene = sh.SetupScene(); - SceneHelpers.SetupSceneModules(scene, lmm); - - ILandObject originalLo1 = new LandObject(userId, false, scene); - originalLo1.LandData.Name = "lo1"; - originalLo1.SetLandBitmap( - originalLo1.GetSquareLandBitmap(0, 0, (int)Constants.RegionSize, (int)Constants.RegionSize / 2)); - - sh.SimDataService.StoreLandObject(originalLo1); - - ILandObject originalLo2 = new LandObject(userId, false, scene); - originalLo2.LandData.Name = "lo2"; - originalLo2.SetLandBitmap( - originalLo2.GetSquareLandBitmap( - 0, (int)Constants.RegionSize / 2, (int)Constants.RegionSize, ((int)Constants.RegionSize / 4) * 3)); - - sh.SimDataService.StoreLandObject(originalLo2); - - scene.loadAllLandObjectsFromStorage(scene.RegionInfo.RegionID); - - ILandObject loAtCoord1 = lmm.GetLandObject(0, 0); - Assert.That(loAtCoord1.LandData.Name, Is.EqualTo(originalLo1.LandData.Name)); - Assert.That(loAtCoord1.LandData.GlobalID, Is.EqualTo(originalLo1.LandData.GlobalID)); - - ILandObject loAtCoord2 - = lmm.GetLandObject((int)Constants.RegionSize - 1, (((int)Constants.RegionSize / 4) * 3) - 1); - Assert.That(loAtCoord2.LandData.Name, Is.EqualTo(originalLo2.LandData.Name)); - Assert.That(loAtCoord2.LandData.GlobalID, Is.EqualTo(originalLo2.LandData.GlobalID)); - - ILandObject loAtCoord3 = lmm.GetLandObject((int)Constants.RegionSize - 1, ((int)Constants.RegionSize - 1)); - Assert.That(loAtCoord3.LandData.LocalID, Is.Not.EqualTo(loAtCoord1.LandData.LocalID)); - Assert.That(loAtCoord3.LandData.LocalID, Is.Not.EqualTo(loAtCoord2.LandData.LocalID)); - Assert.That(loAtCoord3.LandData.GlobalID, Is.Not.EqualTo(loAtCoord1.LandData.GlobalID)); - Assert.That(loAtCoord3.LandData.GlobalID, Is.Not.EqualTo(loAtCoord2.LandData.GlobalID)); - } - - /// - /// Test parcels on region when whole region is parcelled (which should normally always be the case). - /// - [Test] - public void TestLoad() - { - TestHelpers.InMethod(); -// TestHelpers.EnableLogging(); - - UUID userId = TestHelpers.ParseTail(0x1); - - SceneHelpers sh = new SceneHelpers(); - LandManagementModule lmm = new LandManagementModule(); - Scene scene = sh.SetupScene(); - SceneHelpers.SetupSceneModules(scene, lmm); - - ILandObject originalLo1 = new LandObject(userId, false, scene); - originalLo1.LandData.Name = "lo1"; - originalLo1.SetLandBitmap( - originalLo1.GetSquareLandBitmap(0, 0, (int)Constants.RegionSize, (int)Constants.RegionSize / 2)); - - sh.SimDataService.StoreLandObject(originalLo1); - - ILandObject originalLo2 = new LandObject(userId, false, scene); - originalLo2.LandData.Name = "lo2"; - originalLo2.SetLandBitmap( - originalLo2.GetSquareLandBitmap(0, (int)Constants.RegionSize / 2, (int)Constants.RegionSize, (int)Constants.RegionSize)); - - sh.SimDataService.StoreLandObject(originalLo2); - - scene.loadAllLandObjectsFromStorage(scene.RegionInfo.RegionID); - - { - ILandObject loAtCoord = lmm.GetLandObject(0, 0); - Assert.That(loAtCoord.LandData.Name, Is.EqualTo(originalLo1.LandData.Name)); - Assert.That(loAtCoord.LandData.GlobalID, Is.EqualTo(originalLo1.LandData.GlobalID)); - } - - { - ILandObject loAtCoord = lmm.GetLandObject((int)Constants.RegionSize - 1, ((int)Constants.RegionSize - 1)); - Assert.That(loAtCoord.LandData.Name, Is.EqualTo(originalLo2.LandData.Name)); - Assert.That(loAtCoord.LandData.GlobalID, Is.EqualTo(originalLo2.LandData.GlobalID)); - } - } - - [Test] - public void TestSubdivide() - { - TestHelpers.InMethod(); -// TestHelpers.EnableLogging(); - - UUID userId = TestHelpers.ParseTail(0x1); - - LandManagementModule lmm = new LandManagementModule(); - Scene scene = new SceneHelpers().SetupScene(); - SceneHelpers.SetupSceneModules(scene, lmm); - - ILandObject lo = new LandObject(userId, false, scene); - lo.LandData.Name = "lo1"; - lo.SetLandBitmap( - lo.GetSquareLandBitmap(0, 0, (int)Constants.RegionSize, (int)Constants.RegionSize)); - lo = lmm.AddLandObject(lo); - - lmm.Subdivide(0, 0, Constants.LandUnit, Constants.LandUnit, userId); - - { - ILandObject loAtCoord = lmm.GetLandObject(0, 0); - Assert.That(loAtCoord.LandData.LocalID, Is.Not.EqualTo(lo.LandData.LocalID)); - Assert.That(loAtCoord.LandData.GlobalID, Is.Not.EqualTo(lo.LandData.GlobalID)); - } - - { - ILandObject loAtCoord = lmm.GetLandObject(Constants.LandUnit, Constants.LandUnit); - Assert.That(loAtCoord.LandData.LocalID, Is.EqualTo(lo.LandData.LocalID)); - Assert.That(loAtCoord.LandData.GlobalID, Is.EqualTo(lo.LandData.GlobalID)); - } - } - } -} \ No newline at end of file diff --git a/OpenSim/Region/CoreModules/World/Land/Tests/PrimCountModuleTests.cs b/OpenSim/Region/CoreModules/World/Land/Tests/PrimCountModuleTests.cs deleted file mode 100644 index a349aa1be58..00000000000 --- a/OpenSim/Region/CoreModules/World/Land/Tests/PrimCountModuleTests.cs +++ /dev/null @@ -1,382 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections.Generic; -using System.Reflection; -using log4net.Config; -using NUnit.Framework; -using OpenMetaverse; -using OpenMetaverse.Assets; -using OpenSim.Framework; -using OpenSim.Region.Framework.Interfaces; -using OpenSim.Region.Framework.Scenes; -using OpenSim.Tests.Common; - -namespace OpenSim.Region.CoreModules.World.Land.Tests -{ - [TestFixture] - public class PrimCountModuleTests : OpenSimTestCase - { - protected UUID m_userId = new UUID("00000000-0000-0000-0000-100000000000"); - protected UUID m_groupId = new UUID("00000000-0000-0000-8888-000000000000"); - protected UUID m_otherUserId = new UUID("99999999-9999-9999-9999-999999999999"); - protected TestScene m_scene; - protected PrimCountModule m_pcm; - - /// - /// A parcel that covers the entire sim except for a 1 unit wide strip on the eastern side. - /// - protected ILandObject m_lo; - - /// - /// A parcel that covers just the eastern strip of the sim. - /// - protected ILandObject m_lo2; - - [SetUp] - public override void SetUp() - { - base.SetUp(); - - m_pcm = new PrimCountModule(); - LandManagementModule lmm = new LandManagementModule(); - m_scene = new SceneHelpers().SetupScene(); - SceneHelpers.SetupSceneModules(m_scene, lmm, m_pcm); - - int xParcelDivider = (int)Constants.RegionSize - 1; - - ILandObject lo = new LandObject(m_userId, false, m_scene); - lo.LandData.Name = "m_lo"; - lo.SetLandBitmap( - lo.GetSquareLandBitmap(0, 0, xParcelDivider, (int)Constants.RegionSize)); - m_lo = lmm.AddLandObject(lo); - - ILandObject lo2 = new LandObject(m_userId, false, m_scene); - lo2.SetLandBitmap( - lo2.GetSquareLandBitmap(xParcelDivider, 0, (int)Constants.RegionSize, (int)Constants.RegionSize)); - lo2.LandData.Name = "m_lo2"; - m_lo2 = lmm.AddLandObject(lo2); - } - - /// - /// Test that counts before we do anything are correct. - /// - [Test] - public void TestInitialCounts() - { - IPrimCounts pc = m_lo.PrimCounts; - - Assert.That(pc.Owner, Is.EqualTo(0)); - Assert.That(pc.Group, Is.EqualTo(0)); - Assert.That(pc.Others, Is.EqualTo(0)); - Assert.That(pc.Total, Is.EqualTo(0)); - Assert.That(pc.Selected, Is.EqualTo(0)); - Assert.That(pc.Users[m_userId], Is.EqualTo(0)); - Assert.That(pc.Users[m_otherUserId], Is.EqualTo(0)); - Assert.That(pc.Simulator, Is.EqualTo(0)); - } - - /// - /// Test count after a parcel owner owned object is added. - /// - [Test] - public void TestAddOwnerObject() - { - TestHelpers.InMethod(); -// log4net.Config.XmlConfigurator.Configure(); - - IPrimCounts pc = m_lo.PrimCounts; - - SceneObjectGroup sog = SceneHelpers.CreateSceneObject(3, m_userId, "a", 0x01); - m_scene.AddNewSceneObject(sog, false); - - Assert.That(pc.Owner, Is.EqualTo(3)); - Assert.That(pc.Group, Is.EqualTo(0)); - Assert.That(pc.Others, Is.EqualTo(0)); - Assert.That(pc.Total, Is.EqualTo(3)); - Assert.That(pc.Selected, Is.EqualTo(0)); - Assert.That(pc.Users[m_userId], Is.EqualTo(3)); - Assert.That(pc.Users[m_otherUserId], Is.EqualTo(0)); - Assert.That(pc.Simulator, Is.EqualTo(3)); - - // Add a second object and retest - SceneObjectGroup sog2 = SceneHelpers.CreateSceneObject(2, m_userId, "b", 0x10); - m_scene.AddNewSceneObject(sog2, false); - - Assert.That(pc.Owner, Is.EqualTo(5)); - Assert.That(pc.Group, Is.EqualTo(0)); - Assert.That(pc.Others, Is.EqualTo(0)); - Assert.That(pc.Total, Is.EqualTo(5)); - Assert.That(pc.Selected, Is.EqualTo(0)); - Assert.That(pc.Users[m_userId], Is.EqualTo(5)); - Assert.That(pc.Users[m_otherUserId], Is.EqualTo(0)); - Assert.That(pc.Simulator, Is.EqualTo(5)); - } - - /// - /// Test count after a parcel owner owned copied object is added. - /// - [Test] - public void TestCopyOwnerObject() - { - TestHelpers.InMethod(); -// log4net.Config.XmlConfigurator.Configure(); - - IPrimCounts pc = m_lo.PrimCounts; - - SceneObjectGroup sog = SceneHelpers.CreateSceneObject(3, m_userId, "a", 0x01); - m_scene.AddNewSceneObject(sog, false); - m_scene.SceneGraph.DuplicateObject(sog.LocalId, Vector3.Zero, m_userId, UUID.Zero, Quaternion.Identity, false); - - Assert.That(pc.Owner, Is.EqualTo(6)); - Assert.That(pc.Group, Is.EqualTo(0)); - Assert.That(pc.Others, Is.EqualTo(0)); - Assert.That(pc.Total, Is.EqualTo(6)); - Assert.That(pc.Selected, Is.EqualTo(0)); - Assert.That(pc.Users[m_userId], Is.EqualTo(6)); - Assert.That(pc.Users[m_otherUserId], Is.EqualTo(0)); - Assert.That(pc.Simulator, Is.EqualTo(6)); - } - - /// - /// Test that parcel counts update correctly when an object is moved between parcels, where that movement - /// is not done directly by the user/ - /// - [Test] - public void TestMoveOwnerObject() - { - TestHelpers.InMethod(); -// log4net.Config.XmlConfigurator.Configure(); - - SceneObjectGroup sog = SceneHelpers.CreateSceneObject(3, m_userId, "a", 0x01); - m_scene.AddNewSceneObject(sog, false); - SceneObjectGroup sog2 = SceneHelpers.CreateSceneObject(2, m_userId, "b", 0x10); - m_scene.AddNewSceneObject(sog2, false); - - // Move the first scene object to the eastern strip parcel - sog.AbsolutePosition = new Vector3(254, 2, 2); - - IPrimCounts pclo1 = m_lo.PrimCounts; - - Assert.That(pclo1.Owner, Is.EqualTo(2)); - Assert.That(pclo1.Group, Is.EqualTo(0)); - Assert.That(pclo1.Others, Is.EqualTo(0)); - Assert.That(pclo1.Total, Is.EqualTo(2)); - Assert.That(pclo1.Selected, Is.EqualTo(0)); - Assert.That(pclo1.Users[m_userId], Is.EqualTo(2)); - Assert.That(pclo1.Users[m_otherUserId], Is.EqualTo(0)); - Assert.That(pclo1.Simulator, Is.EqualTo(5)); - - IPrimCounts pclo2 = m_lo2.PrimCounts; - - Assert.That(pclo2.Owner, Is.EqualTo(3)); - Assert.That(pclo2.Group, Is.EqualTo(0)); - Assert.That(pclo2.Others, Is.EqualTo(0)); - Assert.That(pclo2.Total, Is.EqualTo(3)); - Assert.That(pclo2.Selected, Is.EqualTo(0)); - Assert.That(pclo2.Users[m_userId], Is.EqualTo(3)); - Assert.That(pclo2.Users[m_otherUserId], Is.EqualTo(0)); - Assert.That(pclo2.Simulator, Is.EqualTo(5)); - - // Now move it back again - sog.AbsolutePosition = new Vector3(2, 2, 2); - - Assert.That(pclo1.Owner, Is.EqualTo(5)); - Assert.That(pclo1.Group, Is.EqualTo(0)); - Assert.That(pclo1.Others, Is.EqualTo(0)); - Assert.That(pclo1.Total, Is.EqualTo(5)); - Assert.That(pclo1.Selected, Is.EqualTo(0)); - Assert.That(pclo1.Users[m_userId], Is.EqualTo(5)); - Assert.That(pclo1.Users[m_otherUserId], Is.EqualTo(0)); - Assert.That(pclo1.Simulator, Is.EqualTo(5)); - - Assert.That(pclo2.Owner, Is.EqualTo(0)); - Assert.That(pclo2.Group, Is.EqualTo(0)); - Assert.That(pclo2.Others, Is.EqualTo(0)); - Assert.That(pclo2.Total, Is.EqualTo(0)); - Assert.That(pclo2.Selected, Is.EqualTo(0)); - Assert.That(pclo2.Users[m_userId], Is.EqualTo(0)); - Assert.That(pclo2.Users[m_otherUserId], Is.EqualTo(0)); - Assert.That(pclo2.Simulator, Is.EqualTo(5)); - } - - /// - /// Test count after a parcel owner owned object is removed. - /// - [Test] - public void TestRemoveOwnerObject() - { - TestHelpers.InMethod(); -// log4net.Config.XmlConfigurator.Configure(); - - IPrimCounts pc = m_lo.PrimCounts; - - m_scene.AddNewSceneObject(SceneHelpers.CreateSceneObject(1, m_userId, "a", 0x1), false); - SceneObjectGroup sogToDelete = SceneHelpers.CreateSceneObject(3, m_userId, "b", 0x10); - m_scene.AddNewSceneObject(sogToDelete, false); - m_scene.DeleteSceneObject(sogToDelete, false); - - Assert.That(pc.Owner, Is.EqualTo(1)); - Assert.That(pc.Group, Is.EqualTo(0)); - Assert.That(pc.Others, Is.EqualTo(0)); - Assert.That(pc.Total, Is.EqualTo(1)); - Assert.That(pc.Selected, Is.EqualTo(0)); - Assert.That(pc.Users[m_userId], Is.EqualTo(1)); - Assert.That(pc.Users[m_otherUserId], Is.EqualTo(0)); - Assert.That(pc.Simulator, Is.EqualTo(1)); - } - - [Test] - public void TestAddGroupObject() - { - TestHelpers.InMethod(); -// log4net.Config.XmlConfigurator.Configure(); - - m_lo.DeedToGroup(m_groupId); - - IPrimCounts pc = m_lo.PrimCounts; - - SceneObjectGroup sog = SceneHelpers.CreateSceneObject(3, m_otherUserId, "a", 0x01); - sog.GroupID = m_groupId; - m_scene.AddNewSceneObject(sog, false); - - Assert.That(pc.Owner, Is.EqualTo(0)); - Assert.That(pc.Group, Is.EqualTo(3)); - Assert.That(pc.Others, Is.EqualTo(0)); - Assert.That(pc.Total, Is.EqualTo(3)); - Assert.That(pc.Selected, Is.EqualTo(0)); - - // Is this desired behaviour? Not totally sure. - Assert.That(pc.Users[m_userId], Is.EqualTo(0)); - Assert.That(pc.Users[m_groupId], Is.EqualTo(0)); - Assert.That(pc.Users[m_otherUserId], Is.EqualTo(3)); - - Assert.That(pc.Simulator, Is.EqualTo(3)); - } - - /// - /// Test count after a parcel owner owned object is removed. - /// - [Test] - public void TestRemoveGroupObject() - { - TestHelpers.InMethod(); -// log4net.Config.XmlConfigurator.Configure(); - - m_lo.DeedToGroup(m_groupId); - - IPrimCounts pc = m_lo.PrimCounts; - - SceneObjectGroup sogToKeep = SceneHelpers.CreateSceneObject(1, m_userId, "a", 0x1); - sogToKeep.GroupID = m_groupId; - m_scene.AddNewSceneObject(sogToKeep, false); - - SceneObjectGroup sogToDelete = SceneHelpers.CreateSceneObject(3, m_userId, "b", 0x10); - m_scene.AddNewSceneObject(sogToDelete, false); - m_scene.DeleteSceneObject(sogToDelete, false); - - Assert.That(pc.Owner, Is.EqualTo(0)); - Assert.That(pc.Group, Is.EqualTo(1)); - Assert.That(pc.Others, Is.EqualTo(0)); - Assert.That(pc.Total, Is.EqualTo(1)); - Assert.That(pc.Selected, Is.EqualTo(0)); - Assert.That(pc.Users[m_userId], Is.EqualTo(1)); - Assert.That(pc.Users[m_groupId], Is.EqualTo(0)); - Assert.That(pc.Users[m_otherUserId], Is.EqualTo(0)); - Assert.That(pc.Simulator, Is.EqualTo(1)); - } - - [Test] - public void TestAddOthersObject() - { - TestHelpers.InMethod(); -// log4net.Config.XmlConfigurator.Configure(); - - IPrimCounts pc = m_lo.PrimCounts; - - SceneObjectGroup sog = SceneHelpers.CreateSceneObject(3, m_otherUserId, "a", 0x01); - m_scene.AddNewSceneObject(sog, false); - - Assert.That(pc.Owner, Is.EqualTo(0)); - Assert.That(pc.Group, Is.EqualTo(0)); - Assert.That(pc.Others, Is.EqualTo(3)); - Assert.That(pc.Total, Is.EqualTo(3)); - Assert.That(pc.Selected, Is.EqualTo(0)); - Assert.That(pc.Users[m_userId], Is.EqualTo(0)); - Assert.That(pc.Users[m_otherUserId], Is.EqualTo(3)); - Assert.That(pc.Simulator, Is.EqualTo(3)); - } - - [Test] - public void TestRemoveOthersObject() - { - TestHelpers.InMethod(); -// log4net.Config.XmlConfigurator.Configure(); - - IPrimCounts pc = m_lo.PrimCounts; - - m_scene.AddNewSceneObject(SceneHelpers.CreateSceneObject(1, m_otherUserId, "a", 0x1), false); - SceneObjectGroup sogToDelete = SceneHelpers.CreateSceneObject(3, m_otherUserId, "b", 0x10); - m_scene.AddNewSceneObject(sogToDelete, false); - m_scene.DeleteSceneObject(sogToDelete, false); - - Assert.That(pc.Owner, Is.EqualTo(0)); - Assert.That(pc.Group, Is.EqualTo(0)); - Assert.That(pc.Others, Is.EqualTo(1)); - Assert.That(pc.Total, Is.EqualTo(1)); - Assert.That(pc.Selected, Is.EqualTo(0)); - Assert.That(pc.Users[m_userId], Is.EqualTo(0)); - Assert.That(pc.Users[m_otherUserId], Is.EqualTo(1)); - Assert.That(pc.Simulator, Is.EqualTo(1)); - } - - /// - /// Test the count is correct after is has been tainted. - /// - [Test] - public void TestTaint() - { - TestHelpers.InMethod(); - IPrimCounts pc = m_lo.PrimCounts; - - SceneObjectGroup sog = SceneHelpers.CreateSceneObject(3, m_userId, "a", 0x01); - m_scene.AddNewSceneObject(sog, false); - - m_pcm.TaintPrimCount(); - - Assert.That(pc.Owner, Is.EqualTo(3)); - Assert.That(pc.Group, Is.EqualTo(0)); - Assert.That(pc.Others, Is.EqualTo(0)); - Assert.That(pc.Total, Is.EqualTo(3)); - Assert.That(pc.Selected, Is.EqualTo(0)); - Assert.That(pc.Users[m_userId], Is.EqualTo(3)); - Assert.That(pc.Users[m_otherUserId], Is.EqualTo(0)); - Assert.That(pc.Simulator, Is.EqualTo(3)); - } - } -} \ No newline at end of file diff --git a/OpenSim/Region/CoreModules/World/Media/Moap/Tests/MoapTests.cs b/OpenSim/Region/CoreModules/World/Media/Moap/Tests/MoapTests.cs deleted file mode 100644 index 0ac9e10b407..00000000000 --- a/OpenSim/Region/CoreModules/World/Media/Moap/Tests/MoapTests.cs +++ /dev/null @@ -1,102 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections.Generic; -using System.IO; -using System.Reflection; -using System.Threading; -using log4net.Config; -using NUnit.Framework; -using OpenMetaverse; -using OpenMetaverse.Assets; -using OpenSim.Framework; -using OpenSim.Region.CoreModules.World.Media.Moap; -using OpenSim.Region.Framework.Scenes; -using OpenSim.Region.Framework.Scenes.Serialization; -using OpenSim.Tests.Common; - -namespace OpenSim.Region.CoreModules.World.Media.Moap.Tests -{ - [TestFixture] - public class MoapTests : OpenSimTestCase - { - protected TestScene m_scene; - protected MoapModule m_module; - - [SetUp] - public override void SetUp() - { - base.SetUp(); - - m_module = new MoapModule(); - m_scene = new SceneHelpers().SetupScene(); - SceneHelpers.SetupSceneModules(m_scene, m_module); - } - - [Test] - public void TestClearMediaUrl() - { - TestHelpers.InMethod(); -// log4net.Config.XmlConfigurator.Configure(); - - SceneObjectPart part = SceneHelpers.AddSceneObject(m_scene).RootPart; - MediaEntry me = new MediaEntry(); - - m_module.SetMediaEntry(part, 1, me); - m_module.ClearMediaEntry(part, 1); - - Assert.That(part.Shape.Media[1], Is.EqualTo(null)); - - // Although we've cleared one face, other faces may still be present. So we need to check for an - // update media url version - Assert.That(part.MediaUrl, Is.EqualTo("x-mv:0000000002/" + UUID.Zero)); - - // By changing media flag to false, the face texture once again becomes identical to the DefaultTexture. - // Therefore, when libOMV reserializes it, it disappears and we are left with no face texture in this slot. - // Not at all confusing, eh? - Assert.That(part.Shape.Textures.FaceTextures[1], Is.Null); - } - - [Test] - public void TestSetMediaUrl() - { - TestHelpers.InMethod(); - - string homeUrl = "opensimulator.org"; - - SceneObjectPart part = SceneHelpers.AddSceneObject(m_scene).RootPart; - MediaEntry me = new MediaEntry() { HomeURL = homeUrl }; - - m_module.SetMediaEntry(part, 1, me); - - Assert.That(part.Shape.Media[1].HomeURL, Is.EqualTo(homeUrl)); - Assert.That(part.MediaUrl, Is.EqualTo("x-mv:0000000001/" + UUID.Zero)); - Assert.That(part.Shape.Textures.FaceTextures[1].MediaFlags, Is.True); - } - } -} \ No newline at end of file diff --git a/OpenSim/Region/CoreModules/World/Serialiser/Tests/SerialiserTests.cs b/OpenSim/Region/CoreModules/World/Serialiser/Tests/SerialiserTests.cs deleted file mode 100644 index aba520edd21..00000000000 --- a/OpenSim/Region/CoreModules/World/Serialiser/Tests/SerialiserTests.cs +++ /dev/null @@ -1,884 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSim Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System.Collections.Generic; -using System.IO; -using System.Text; -using System.Xml; -using log4net.Config; -using NUnit.Framework; -using OpenMetaverse; -using OpenSim.Framework; -using OpenSim.Region.Framework.Scenes; -using OpenSim.Region.Framework.Scenes.Serialization; -using OpenSim.Tests.Common; -using OpenMetaverse.StructuredData; - -namespace OpenSim.Region.CoreModules.World.Serialiser.Tests -{ - [TestFixture] - public class SerialiserTests : OpenSimTestCase - { - private const string ObjectRootPartStubXml = -@" - - - false - a6dacf01-4636-4bb9-8a97-30609438af9d - e6a5a05e-e8cc-4816-8701-04165e335790 - 1 - - 0 - e6a5a05e-e8cc-4816-8701-04165e335790 - 2698615125 - PrimMyRide - 0 - false - 1099511628032000 - 0 - 147.2392.69822.78084 - 000 - -4.371139E-08-1-4.371139E-080 - 000 - 000 - 000 - 000 - - - - - - 0 - 0 - - 1 - AAAAAAAAERGZmQAAAAAABQCVlZUAAAAAQEAAAABAQAAAAAAAAAAAAAAAAAAAAA== - AA== - 0 - 16 - 0 - 0 - 0 - 100 - 100 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 9 - 0 - 0 - 0 - 10100.5 - 0 - Square - Same - 00000000-0000-0000-0000-000000000000 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 1 - 0 - 0 - 0 - 1 - false - false - false - - 10100.5 - 0 - 0001 - 000 - 000 - 0001 - 0 - 1211330445 - 0 - 0 - 0 - 0 - 00000000-0000-0000-0000-000000000000 - a6dacf01-4636-4bb9-8a97-30609438af9d - a6dacf01-4636-4bb9-8a97-30609438af9d - 2147483647 - 2147483647 - 0 - 0 - 2147483647 - None - 00000000-0000-0000-0000-000000000000 - 0 - - - - MyNamespace - - MyStore - - the answer - 42 - - - - - - - "; - - private const string ObjectWithNoOtherPartsXml = ObjectRootPartStubXml + -@" - -"; - - private const string ObjectWithOtherPartsXml = ObjectRootPartStubXml + -@" - - - - false - a6dacf01-4636-4bb9-8a97-30609438af9d - 9958feb1-02a6-49e4-a4ce-eba6f578ee13 - 3 - 9958feb1-02a6-49e4-a4ce-eba6f578ee13 - 1154704500 - Alien Head 1 - 3 - false - false - 21990232560640000 - 0 - 125.5655127.34622.48036 - -0.21719360.10839840.0009994507 - -0.51221060.4851225-0.49574540.5064908 - 000 - 000 - 000 - (No Description) - 000255 - - - - 253 - 0 - - 5 - Vw3dpvgTRUOiIUOGsnpWlAB/f38AAAAAgL8AAACAPwAAAAAAAAAF4ABAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AA== - 0 - 32 - 0 - 0 - 0 - 100 - 100 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 9 - 0 - 0 - 0 - 9 - 0 - HalfCircle - Same - 00000000-0000-0000-0000-000000000000 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 1 - 0 - 0 - 0 - 1 - false - false - false - - 0.11481950.01438910.02768878 - 0001 - 000 - 000 - 0001 - 1154704499 - 1256611042 - 0 - 10 - 0 - 0 - 00000000-0000-0000-0000-000000000000 - 7b2022f0-5f19-488c-b7e5-829d8f96b448 - 7b2022f0-5f19-488c-b7e5-829d8f96b448 - 647168 - 647168 - 0 - 0 - 581632 - None - 00000000-0000-0000-0000-000000000000 - 0 - 000 - - - -2 - -2 - -2 - -2 - -2 - - - - - false - a6dacf01-4636-4bb9-8a97-30609438af9d - 674b6b86-f5aa-439a-8e00-0d75bc08c80a - 3 - 674b6b86-f5aa-439a-8e00-0d75bc08c80a - 1154704501 - Alien Head 2 - 3 - false - false - 21990232560640000 - 0 - 125.5655127.34622.48036 - -0.24909970.085201260.0009002686 - -0.47653680.5194498-0.53013720.4712104 - 000 - 000 - 000 - (No Description) - 000255 - - - - 252 - 0 - - 0 - Vw3dpvgTRUOiIUOGsnpWlAB/f38AAAAAgL8AAACAPwAAAAAAAAAF4ABAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AA== - 0 - 32 - 0 - 0 - 0 - 100 - 150 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 9 - 0 - 0 - 0 - 9 - 0 - Circle - Same - 00000000-0000-0000-0000-000000000000 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 1 - 0 - 0 - 0 - 1 - false - false - false - - 0.035743850.059580320.04764182 - 0001 - 000 - 000 - 0001 - 1154704499 - 1256611042 - 0 - 10 - 0 - 0 - 00000000-0000-0000-0000-000000000000 - 7b2022f0-5f19-488c-b7e5-829d8f96b448 - 7b2022f0-5f19-488c-b7e5-829d8f96b448 - 647168 - 647168 - 0 - 0 - 581632 - None - 00000000-0000-0000-0000-000000000000 - 0 - 000 - - - -2 - -2 - -2 - -2 - -2 - - - -"; - - private const string ObjectWithBadFloatsXml = @" - - - - false - a6dacf01-4636-4bb9-8a97-30609438af9d - e6a5a05e-e8cc-4816-8701-04165e335790 - 1 - - 0 - e6a5a05e-e8cc-4816-8701-04165e335790 - 2698615125 - NaughtyPrim - 0 - false - 1099511628032000 - 0 - 147.2392.69822.78084 - 000 - -4.371139E-08-1-4.371139E-080 - 000 - 000 - 000 - 000 - - - - - - 0 - 0 - - 1 - AAAAAAAAERGZmQAAAAAABQCVlZUAAAAAQEAAAABAQAAAAAAAAAAAAAAAAAAAAA== - AA== - 0 - 16 - 0 - 0 - 0 - 100 - 100 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 9 - 0 - 0 - 0 - 10100.5 - 0 - Square - Same - 00000000-0000-0000-0000-000000000000 - 0 - 0 - 0,5 - yo mamma - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 1 - 0 - 0 - 0 - 1 - false - false - false - - 10100.5 - 0 - 0001 - 000 - 000 - 0001 - 0 - 1211330445 - 0 - 0 - 0 - 0 - 00000000-0000-0000-0000-000000000000 - a6dacf01-4636-4bb9-8a97-30609438af9d - a6dacf01-4636-4bb9-8a97-30609438af9d - 2147483647 - 2147483647 - 0 - 0 - 2147483647 - None - 00000000-0000-0000-0000-000000000000 - 0 - - - - "; - - private const string ObjectWithNoPartsXml2 = @" - - - b46ef588-411e-4a8b-a284-d7dcfe8e74ef - 9be68fdd-f740-4a0f-9675-dfbbb536b946 - 0 - - 0 - 9be68fdd-f740-4a0f-9675-dfbbb536b946 - 720005 - PrimFun - 0 - 1099511628032000 - 0 - 153.9854121.490862.21781 - 000 - 0001 - 000 - 000 - 000 - 000 - - - - - - 0 - 0 - - 0 - 16 - 0 - 0 - 0 - 200 - 200 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 9 - 0 - 0 - 0 - 1.2831315.9038584.266288 - 0 - Circle - Same - 0 - iVVnRyTLQ+2SC0fK7RVGXwJ6yc/SU4RDA5nhJbLUw3R1AAAAAAAAaOw8QQOhPSRAAKE9JEAAAAAAAAAAAAAAAAAAAAA= - AA== - - 1.2831315.9038584.266288 - 0 - 0001 - 000 - 000 - 0010 - 0 - 1216066902 - 0 - 0 - 0 - 0 - 00000000-0000-0000-0000-000000000000 - b46ef588-411e-4a8b-a284-d7dcfe8e74ef - b46ef588-411e-4a8b-a284-d7dcfe8e74ef - 2147483647 - 2147483647 - 0 - 0 - 2147483647 - None - - - - MyNamespace - - MyStore - - last words - Rosebud - - - - - - 00000000-0000-0000-0000-000000000000 - - - "; - - protected Scene m_scene; - protected SerialiserModule m_serialiserModule; - - [OneTimeSetUp] - public void Init() - { - m_serialiserModule = new SerialiserModule(); - m_scene = new SceneHelpers().SetupScene(); - SceneHelpers.SetupSceneModules(m_scene, m_serialiserModule); - } - - [Test] - public void TestDeserializeXmlObjectWithNoOtherParts() - { - TestHelpers.InMethod(); - TestHelpers.EnableLogging(); - - SceneObjectGroup so = SceneObjectSerializer.FromOriginalXmlFormat(ObjectWithNoOtherPartsXml); - SceneObjectPart rootPart = so.RootPart; - - Assert.That(rootPart.UUID, Is.EqualTo(new UUID("e6a5a05e-e8cc-4816-8701-04165e335790"))); - Assert.That(rootPart.CreatorID, Is.EqualTo(new UUID("a6dacf01-4636-4bb9-8a97-30609438af9d"))); - Assert.That(rootPart.Name, Is.EqualTo("PrimMyRide")); - OSDMap store = rootPart.DynAttrs.GetStore("MyNamespace", "MyStore"); - Assert.AreEqual(42, store["the answer"].AsInteger()); - - // TODO: Check other properties - } - - [Test] - public void TestDeserializeXmlObjectWithOtherParts() - { - TestHelpers.InMethod(); - TestHelpers.EnableLogging(); - - SceneObjectGroup so = SceneObjectSerializer.FromOriginalXmlFormat(ObjectWithOtherPartsXml); - SceneObjectPart[] parts = so.Parts; - Assert.AreEqual(3, so.Parts.Length); - - { - SceneObjectPart part = parts[0]; - - Assert.That(part.UUID, Is.EqualTo(new UUID("e6a5a05e-e8cc-4816-8701-04165e335790"))); - Assert.That(part.CreatorID, Is.EqualTo(new UUID("a6dacf01-4636-4bb9-8a97-30609438af9d"))); - Assert.That(part.Name, Is.EqualTo("PrimMyRide")); - OSDMap store = part.DynAttrs.GetStore("MyNamespace", "MyStore"); - Assert.AreEqual(42, store["the answer"].AsInteger()); - } - - { - SceneObjectPart part = parts[1]; - - Assert.That(part.UUID, Is.EqualTo(new UUID("9958feb1-02a6-49e4-a4ce-eba6f578ee13"))); - Assert.That(part.CreatorID, Is.EqualTo(new UUID("a6dacf01-4636-4bb9-8a97-30609438af9d"))); - Assert.That(part.Name, Is.EqualTo("Alien Head 1")); - } - - { - SceneObjectPart part = parts[2]; - - Assert.That(part.UUID, Is.EqualTo(new UUID("674b6b86-f5aa-439a-8e00-0d75bc08c80a"))); - Assert.That(part.CreatorID, Is.EqualTo(new UUID("a6dacf01-4636-4bb9-8a97-30609438af9d"))); - Assert.That(part.Name, Is.EqualTo("Alien Head 2")); - } - - // TODO: Check other properties - } - - [Test] - public void TestDeserializeBadFloatsXml() - { - TestHelpers.InMethod(); -// log4net.Config.XmlConfigurator.Configure(); - - SceneObjectGroup so = SceneObjectSerializer.FromOriginalXmlFormat(ObjectWithBadFloatsXml); - SceneObjectPart rootPart = so.RootPart; - - Assert.That(rootPart.UUID, Is.EqualTo(new UUID("e6a5a05e-e8cc-4816-8701-04165e335790"))); - Assert.That(rootPart.CreatorID, Is.EqualTo(new UUID("a6dacf01-4636-4bb9-8a97-30609438af9d"))); - Assert.That(rootPart.Name, Is.EqualTo("NaughtyPrim")); - - // This terminates the deserialization earlier if couldn't be parsed. - // TODO: Need to address this - Assert.That(rootPart.GroupPosition.X, Is.EqualTo(147.23f)); - - Assert.That(rootPart.Shape.PathCurve, Is.EqualTo(16)); - - // Defaults for bad parses - Assert.That(rootPart.Shape.FlexiTension, Is.EqualTo(0)); - Assert.That(rootPart.Shape.FlexiDrag, Is.EqualTo(0)); - - // TODO: Check other properties - } - - [Test] - public void TestSerializeXml() - { - TestHelpers.InMethod(); - //log4net.Config.XmlConfigurator.Configure(); - - string rpName = "My Little Donkey"; - UUID rpUuid = UUID.Parse("00000000-0000-0000-0000-000000000964"); - UUID rpCreatorId = UUID.Parse("00000000-0000-0000-0000-000000000915"); - PrimitiveBaseShape shape = PrimitiveBaseShape.CreateSphere(); -// Vector3 groupPosition = new Vector3(10, 20, 30); -// Quaternion rotationOffset = new Quaternion(20, 30, 40, 50); -// Vector3 offsetPosition = new Vector3(5, 10, 15); - - SceneObjectPart rp = new SceneObjectPart(); - rp.UUID = rpUuid; - rp.Name = rpName; - rp.CreatorID = rpCreatorId; - rp.Shape = shape; - - string daNamespace = "MyNamespace"; - string daStoreName = "MyStore"; - string daKey = "foo"; - string daValue = "bar"; - OSDMap myStore = new OSDMap(); - myStore.Add(daKey, daValue); - rp.DynAttrs = new DAMap(); - rp.DynAttrs.SetStore(daNamespace, daStoreName, myStore); - - SceneObjectGroup so = new SceneObjectGroup(rp); - - // Need to add the object to the scene so that the request to get script state succeeds - m_scene.AddSceneObject(so); - - string xml = SceneObjectSerializer.ToOriginalXmlFormat(so); - - XmlTextReader xtr = new XmlTextReader(new StringReader(xml)); - xtr.DtdProcessing = DtdProcessing.Ignore; - xtr.ReadStartElement("SceneObjectGroup"); - xtr.ReadStartElement("RootPart"); - xtr.ReadStartElement("SceneObjectPart"); - - UUID uuid = UUID.Zero; - string name = null; - UUID creatorId = UUID.Zero; - DAMap daMap = null; - - while (xtr.Read() && xtr.Name != "SceneObjectPart") - { - if (xtr.NodeType != XmlNodeType.Element) - continue; - - switch (xtr.Name) - { - case "UUID": - xtr.ReadStartElement("UUID"); - try - { - uuid = UUID.Parse(xtr.ReadElementString("UUID")); - xtr.ReadEndElement(); - } - catch { } // ignore everything but ... - break; - case "Name": - name = xtr.ReadElementContentAsString(); - break; - case "CreatorID": - xtr.ReadStartElement("CreatorID"); - creatorId = UUID.Parse(xtr.ReadElementString("UUID")); - xtr.ReadEndElement(); - break; - case "DynAttrs": - daMap = new DAMap(); - daMap.ReadXml(xtr); - break; - } - } - - xtr.ReadEndElement(); - xtr.ReadEndElement(); - xtr.ReadStartElement("OtherParts"); - xtr.ReadEndElement(); - xtr.Close(); - - // TODO: More checks - Assert.That(uuid, Is.EqualTo(rpUuid)); - Assert.That(name, Is.EqualTo(rpName)); - Assert.That(creatorId, Is.EqualTo(rpCreatorId)); - Assert.NotNull(daMap); - Assert.AreEqual(daValue, daMap.GetStore(daNamespace, daStoreName)[daKey].AsString()); - } - - [Test] - public void TestDeserializeXml2() - { - TestHelpers.InMethod(); - //log4net.Config.XmlConfigurator.Configure(); - - SceneObjectGroup so = m_serialiserModule.DeserializeGroupFromXml2(ObjectWithNoPartsXml2); - SceneObjectPart rootPart = so.RootPart; - - Assert.That(rootPart.UUID, Is.EqualTo(new UUID("9be68fdd-f740-4a0f-9675-dfbbb536b946"))); - Assert.That(rootPart.CreatorID, Is.EqualTo(new UUID("b46ef588-411e-4a8b-a284-d7dcfe8e74ef"))); - Assert.That(rootPart.Name, Is.EqualTo("PrimFun")); - OSDMap store = rootPart.DynAttrs.GetStore("MyNamespace", "MyStore"); - Assert.AreEqual("Rosebud", store["last words"].AsString()); - - // TODO: Check other properties - } - - [Test] - public void TestSerializeXml2() - { - TestHelpers.InMethod(); - //log4net.Config.XmlConfigurator.Configure(); - - string rpName = "My Little Pony"; - UUID rpUuid = UUID.Parse("00000000-0000-0000-0000-000000000064"); - UUID rpCreatorId = UUID.Parse("00000000-0000-0000-0000-000000000015"); - PrimitiveBaseShape shape = PrimitiveBaseShape.CreateSphere(); -// Vector3 groupPosition = new Vector3(10, 20, 30); -// Quaternion rotationOffset = new Quaternion(20, 30, 40, 50); -// Vector3 offsetPosition = new Vector3(5, 10, 15); - - SceneObjectPart rp = new SceneObjectPart(); - rp.UUID = rpUuid; - rp.Name = rpName; - rp.CreatorID = rpCreatorId; - rp.Shape = shape; - - string daNamespace = "MyNamespace"; - string daStoreName = "MyStore"; - string daKey = "foo"; - string daValue = "bar"; - OSDMap myStore = new OSDMap(); - myStore.Add(daKey, daValue); - rp.DynAttrs = new DAMap(); - rp.DynAttrs.SetStore(daNamespace, daStoreName, myStore); - - SceneObjectGroup so = new SceneObjectGroup(rp); - - // Need to add the object to the scene so that the request to get script state succeeds - m_scene.AddSceneObject(so); - - Dictionary options = new Dictionary(); - options["old-guids"] = true; - string xml2 = m_serialiserModule.SerializeGroupToXml2(so, options); - - XmlTextReader xtr = new XmlTextReader(new StringReader(xml2)); - xtr.DtdProcessing = DtdProcessing.Ignore; - xtr.ReadStartElement("SceneObjectGroup"); - xtr.ReadStartElement("SceneObjectPart"); - - UUID uuid = UUID.Zero; - string name = null; - UUID creatorId = UUID.Zero; - DAMap daMap = null; - - while (xtr.Read() && xtr.Name != "SceneObjectPart") - { - if (xtr.NodeType != XmlNodeType.Element) - continue; - - switch (xtr.Name) - { - case "UUID": - xtr.ReadStartElement("UUID"); - uuid = UUID.Parse(xtr.ReadElementString("Guid")); - xtr.ReadEndElement(); - break; - case "Name": - name = xtr.ReadElementContentAsString(); - break; - case "CreatorID": - xtr.ReadStartElement("CreatorID"); - creatorId = UUID.Parse(xtr.ReadElementString("Guid")); - xtr.ReadEndElement(); - break; - case "DynAttrs": - daMap = new DAMap(); - daMap.ReadXml(xtr); - break; - } - } - - xtr.ReadEndElement(); - xtr.ReadStartElement("OtherParts"); - xtr.ReadEndElement(); - xtr.Close(); - - // TODO: More checks - Assert.That(uuid, Is.EqualTo(rpUuid)); - Assert.That(name, Is.EqualTo(rpName)); - Assert.That(creatorId, Is.EqualTo(rpCreatorId)); - Assert.NotNull(daMap); - Assert.AreEqual(daValue, daMap.GetStore(daNamespace, daStoreName)[daKey].AsString()); - } - } -} \ No newline at end of file diff --git a/OpenSim/Region/CoreModules/World/Terrain/Tests/TerrainModuleTests.cs b/OpenSim/Region/CoreModules/World/Terrain/Tests/TerrainModuleTests.cs deleted file mode 100644 index 9a679662f3b..00000000000 --- a/OpenSim/Region/CoreModules/World/Terrain/Tests/TerrainModuleTests.cs +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using NUnit.Framework; -using OpenSim.Framework; -using OpenSim.Region.CoreModules.World.Terrain; -using OpenSim.Region.Framework.Scenes; -using OpenSim.Tests.Common; - -namespace OpenSim.Region.CoreModules.Terrain.Tests -{ - public class TerrainModuleTests : OpenSimTestCase - { - [Test] - public void TestTerrainFill() - { - TestHelpers.InMethod(); -// TestHelpers.EnableLogging(); - - //UUID userId = TestHelpers.ParseTail(0x1); - - TerrainModule tm = new TerrainModule(); - Scene scene = new SceneHelpers().SetupScene(); - SceneHelpers.SetupSceneModules(scene, tm); - - // Fillheight of 30 - { - float fillHeight = 30; - - tm.InterfaceFillTerrain(new object[] { fillHeight }); - - float height = scene.Heightmap[128, 128]; - - Assert.AreEqual(fillHeight, height); - } - - // Max fillheight of 30 - // According to http://wiki.secondlife.com/wiki/Tips_for_Creating_Heightfields_and_Details_on_Terrain_RAW_Files#Notes_for_Creating_Height_Field_Maps_for_Second_Life - { - float fillHeight = 508; - - tm.InterfaceFillTerrain(new object[] { fillHeight }); - - float height = scene.Heightmap[128, 128]; - - Assert.AreEqual(fillHeight, height); - } - } - } -} \ No newline at end of file diff --git a/OpenSim/Region/CoreModules/World/Terrain/Tests/TerrainTest.cs b/OpenSim/Region/CoreModules/World/Terrain/Tests/TerrainTest.cs deleted file mode 100644 index e5e2e5ed17c..00000000000 --- a/OpenSim/Region/CoreModules/World/Terrain/Tests/TerrainTest.cs +++ /dev/null @@ -1,119 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using NUnit.Framework; -using OpenSim.Framework; -using OpenSim.Region.CoreModules.World.Terrain.PaintBrushes; -using OpenSim.Region.Framework.Scenes; -using OpenSim.Tests.Common; - -namespace OpenSim.Region.CoreModules.World.Terrain.Tests -{ - [TestFixture] - public class TerrainTest : OpenSimTestCase - { - [Test] - public void BrushTest() - { - int midRegion = (int)Constants.RegionSize / 2; - - // Create a mask that covers only the left half of the region - bool[,] allowMask = new bool[(int)Constants.RegionSize, 256]; - int x; - int y; - for (x = 0; x < midRegion; x++) - { - for (y = 0; y < (int)Constants.RegionSize; y++) - { - allowMask[x,y] = true; - } - } - - // - // Test RaiseSphere - // - TerrainChannel map = new TerrainChannel((int)Constants.RegionSize, (int)Constants.RegionSize); - ITerrainPaintableEffect effect = new RaiseSphere(); - - effect.PaintEffect(map, allowMask, midRegion, midRegion, -1.0f, 5, 6.0f, - 0, midRegion - 1,0, (int)Constants.RegionSize -1); - Assert.That(map[127, midRegion] > 0.0, "Raise brush should raising value at this point (127,128)."); - Assert.That(map[124, midRegion] > 0.0, "Raise brush should raising value at this point (124,128)."); - Assert.That(map[120, midRegion] == 0.0, "Raise brush should not change value at this point (120,128)."); - Assert.That(map[128, midRegion] == 0.0, "Raise brush should not change value at this point (128,128)."); -// Assert.That(map[0, midRegion] == 0.0, "Raise brush should not change value at this point (0,128)."); - // - // Test LowerSphere - // - map = new TerrainChannel((int)Constants.RegionSize, (int)Constants.RegionSize); - for (x=0; x= 0.0, "Lower should not lowering value below 0.0 at this point (127,128)."); - Assert.That(map[127, midRegion] == 0.0, "Lower brush should lowering value to 0.0 at this point (127,128)."); - Assert.That(map[125, midRegion] < 1.0, "Lower brush should lowering value at this point (124,128)."); - Assert.That(map[120, midRegion] == 1.0, "Lower brush should not change value at this point (120,128)."); - Assert.That(map[128, midRegion] == 1.0, "Lower brush should not change value at this point (128,128)."); -// Assert.That(map[0, midRegion] == 1.0, "Lower brush should not change value at this point (0,128)."); - } - - [Test] - public void TerrainChannelTest() - { - TerrainChannel x = new TerrainChannel((int)Constants.RegionSize, (int)Constants.RegionSize); - Assert.That(x[0, 0] == 0.0, "Terrain not initialising correctly."); - - x[0, 0] = 1.0f; - Assert.That(x[0, 0] == 1.0, "Terrain not setting values correctly."); - - x[0, 0] = 0; - x[0, 0] += 5.0f; - x[0, 0] -= 1.0f; - Assert.That(x[0, 0] == 4.0f, "Terrain addition/subtraction error."); - - x[0, 0] = 1.0f; - float[] floatsExport = x.GetFloatsSerialised(); - Assert.That(floatsExport[0] == 1.0f, "Export to float[] not working correctly."); - - x[0, 0] = 1.0f; - Assert.That(x.Tainted(0, 0), "Terrain channel tainting not working correctly."); - - TerrainChannel y = x.Copy(); - Assert.That(!ReferenceEquals(x, y), "Terrain copy not duplicating correctly."); - Assert.That(!ReferenceEquals(x.GetDoubles(), y.GetDoubles()), "Terrain array not duplicating correctly."); - } - } -} diff --git a/OpenSim/Region/Framework/OpenSim.Region.Framework.Tests.csproj b/OpenSim/Region/Framework/OpenSim.Region.Framework.Tests.csproj index 5e07d6a8367..eede3a1e123 100644 --- a/OpenSim/Region/Framework/OpenSim.Region.Framework.Tests.csproj +++ b/OpenSim/Region/Framework/OpenSim.Region.Framework.Tests.csproj @@ -15,9 +15,6 @@ ..\..\..\bin\OpenMetaverseTypes.dll False - - False - False @@ -189,4 +186,4 @@ - \ No newline at end of file + diff --git a/OpenSim/Region/Framework/OpenSim.Region.Framework.csproj b/OpenSim/Region/Framework/OpenSim.Region.Framework.csproj index 1ecfe55bca1..8c97c2eb7b8 100644 --- a/OpenSim/Region/Framework/OpenSim.Region.Framework.csproj +++ b/OpenSim/Region/Framework/OpenSim.Region.Framework.csproj @@ -24,9 +24,6 @@ ..\..\..\bin\OpenMetaverseTypes.dll False - - False - False @@ -85,4 +82,4 @@ - \ No newline at end of file + diff --git a/OpenSim/Region/Framework/Scenes/Tests/EntityManagerTests.cs b/OpenSim/Region/Framework/Scenes/Tests/EntityManagerTests.cs deleted file mode 100644 index fa698a9e683..00000000000 --- a/OpenSim/Region/Framework/Scenes/Tests/EntityManagerTests.cs +++ /dev/null @@ -1,177 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Reflection; -using System.Threading; -using System.Text; -using System.Collections.Generic; -using Nini.Config; -using NUnit.Framework; -using OpenMetaverse; -using OpenSim.Framework; -using OpenSim.Region.Framework.Scenes; -using OpenSim.Tests.Common; - -namespace OpenSim.Region.Framework.Scenes.Tests -{ - [TestFixture, LongRunning] - public class EntityManagerTests : OpenSimTestCase - { - static public Random random; - SceneObjectGroup found; - Scene scene = new SceneHelpers().SetupScene(); - - [Test] - public void T010_AddObjects() - { - TestHelpers.InMethod(); - - random = new Random(); - SceneObjectGroup found; - EntityManager entman = new EntityManager(); - SceneObjectGroup sog = NewSOG(); - UUID obj1 = sog.UUID; - uint li1 = sog.LocalId; - entman.Add(sog); - sog = NewSOG(); - UUID obj2 = sog.UUID; - uint li2 = sog.LocalId; - entman.Add(sog); - - found = (SceneObjectGroup)entman[obj1]; - Assert.That(found.UUID ,Is.EqualTo(obj1)); - found = (SceneObjectGroup)entman[li1]; - Assert.That(found.UUID ,Is.EqualTo(obj1)); - found = (SceneObjectGroup)entman[obj2]; - Assert.That(found.UUID ,Is.EqualTo(obj2)); - found = (SceneObjectGroup)entman[li2]; - Assert.That(found.UUID ,Is.EqualTo(obj2)); - - entman.Remove(obj1); - entman.Remove(li2); - - Assert.That(entman.ContainsKey(obj1), Is.False); - Assert.That(entman.ContainsKey(li1), Is.False); - Assert.That(entman.ContainsKey(obj2), Is.False); - Assert.That(entman.ContainsKey(li2), Is.False); - } - - [Test] - public void T011_ThreadAddRemoveTest() - { - TestHelpers.InMethod(); - - // This test adds and removes with mutiple threads, attempting to break the - // uuid and localid dictionary coherence. - EntityManager entman = new EntityManager(); - SceneObjectGroup sog = NewSOG(); - for (int j=0; j<20; j++) - { - List trdlist = new List(); - - for (int i=0; i<4; i++) - { - // Adds scene object - NewTestThreads test = new NewTestThreads(entman,sog); - Thread start = new Thread(new ThreadStart(test.TestAddSceneObject)); - start.Start(); - trdlist.Add(start); - - // Removes it - test = new NewTestThreads(entman,sog); - start = new Thread(new ThreadStart(test.TestRemoveSceneObject)); - start.Start(); - trdlist.Add(start); - } - foreach (Thread thread in trdlist) - { - thread.Join(); - } - if (entman.ContainsKey(sog.UUID) || entman.ContainsKey(sog.LocalId)) { - found = (SceneObjectGroup)entman[sog.UUID]; - Assert.That(found.UUID,Is.EqualTo(sog.UUID)); - found = (SceneObjectGroup)entman[sog.LocalId]; - Assert.That(found.UUID,Is.EqualTo(sog.UUID)); - } - } - } - - private SceneObjectGroup NewSOG() - { - SceneObjectPart sop = new SceneObjectPart(UUID.Random(), PrimitiveBaseShape.Default, Vector3.Zero, Quaternion.Identity, Vector3.Zero); - sop.Name = RandomName(); - sop.Description = sop.Name; - sop.Text = RandomName(); - sop.SitName = RandomName(); - sop.TouchName = RandomName(); - sop.Flags |= PrimFlags.Phantom; - - SceneObjectGroup sog = new SceneObjectGroup(sop); - scene.AddNewSceneObject(sog, false); - - return sog; - } - - private static string RandomName() - { - StringBuilder name = new StringBuilder(); - int size = random.Next(40,80); - char ch ; - for (int i=0; i - /// Basic scene object tests (create, read and delete but not update). - /// - [TestFixture] - public class SceneObjectBasicTests : OpenSimTestCase - { -// [TearDown] -// public void TearDown() -// { -// Console.WriteLine("TearDown"); -// GC.Collect(); -// Thread.Sleep(3000); -// } - -// public class GcNotify -// { -// public static AutoResetEvent gcEvent = new AutoResetEvent(false); -// private static bool _initialized = false; -// -// public static void Initialize() -// { -// if (!_initialized) -// { -// _initialized = true; -// new GcNotify(); -// } -// } -// -// private GcNotify(){} -// -// ~GcNotify() -// { -// if (!Environment.HasShutdownStarted && -// !AppDomain.CurrentDomain.IsFinalizingForUnload()) -// { -// Console.WriteLine("GcNotify called"); -// gcEvent.Set(); -// new GcNotify(); -// } -// } -// } - - /// - /// Test adding an object to a scene. - /// - [Test] - public void TestAddSceneObject() - { - TestHelpers.InMethod(); - - Scene scene = new SceneHelpers().SetupScene(); - int partsToTestCount = 3; - - SceneObjectGroup so - = SceneHelpers.CreateSceneObject(partsToTestCount, TestHelpers.ParseTail(0x1), "obj1", 0x10); - SceneObjectPart[] parts = so.Parts; - - Assert.That(scene.AddNewSceneObject(so, false), Is.True); - SceneObjectGroup retrievedSo = scene.GetSceneObjectGroup(so.UUID); - SceneObjectPart[] retrievedParts = retrievedSo.Parts; - - //m_log.Debug("retrievedPart : {0}", retrievedPart); - // If the parts have the same UUID then we will consider them as one and the same - Assert.That(retrievedSo.PrimCount, Is.EqualTo(partsToTestCount)); - - for (int i = 0; i < partsToTestCount; i++) - { - Assert.That(retrievedParts[i].Name, Is.EqualTo(parts[i].Name)); - Assert.That(retrievedParts[i].UUID, Is.EqualTo(parts[i].UUID)); - } - } - - [Test] - /// - /// It shouldn't be possible to add a scene object if one with that uuid already exists in the scene. - /// - public void TestAddExistingSceneObjectUuid() - { - TestHelpers.InMethod(); - - Scene scene = new SceneHelpers().SetupScene(); - - string obj1Name = "Alfred"; - string obj2Name = "Betty"; - UUID objUuid = new UUID("00000000-0000-0000-0000-000000000001"); - - SceneObjectPart part1 - = new SceneObjectPart(UUID.Zero, PrimitiveBaseShape.Default, Vector3.Zero, Quaternion.Identity, Vector3.Zero) - { Name = obj1Name, UUID = objUuid }; - - Assert.That(scene.AddNewSceneObject(new SceneObjectGroup(part1), false), Is.True); - - SceneObjectPart part2 - = new SceneObjectPart(UUID.Zero, PrimitiveBaseShape.Default, Vector3.Zero, Quaternion.Identity, Vector3.Zero) - { Name = obj2Name, UUID = objUuid }; - - Assert.That(scene.AddNewSceneObject(new SceneObjectGroup(part2), false), Is.False); - - SceneObjectPart retrievedPart = scene.GetSceneObjectPart(objUuid); - - //m_log.Debug("retrievedPart : {0}", retrievedPart); - // If the parts have the same UUID then we will consider them as one and the same - Assert.That(retrievedPart.Name, Is.EqualTo(obj1Name)); - Assert.That(retrievedPart.UUID, Is.EqualTo(objUuid)); - } - - /// - /// Test retrieving a scene object via the local id of one of its parts. - /// - [Test] - public void TestGetSceneObjectByPartLocalId() - { - TestHelpers.InMethod(); - - Scene scene = new SceneHelpers().SetupScene(); - int partsToTestCount = 3; - - SceneObjectGroup so - = SceneHelpers.CreateSceneObject(partsToTestCount, TestHelpers.ParseTail(0x1), "obj1", 0x10); - SceneObjectPart[] parts = so.Parts; - - scene.AddNewSceneObject(so, false); - - // Test getting via the root part's local id - Assert.That(scene.GetGroupByPrim(so.LocalId), Is.Not.Null); - - // Test getting via a non root part's local id - Assert.That(scene.GetGroupByPrim(parts[partsToTestCount - 1].LocalId), Is.Not.Null); - - // Test that we don't get back an object for a local id that doesn't exist - Assert.That(scene.GetGroupByPrim(999), Is.Null); - - uint soid = so.LocalId; - uint spid = parts[partsToTestCount - 1].LocalId; - - // Now delete the scene object and check again - scene.DeleteSceneObject(so, false); - - Assert.That(scene.GetGroupByPrim(soid), Is.Null); - Assert.That(scene.GetGroupByPrim(spid), Is.Null); - } - - /// - /// Test deleting an object from a scene. - /// - /// - /// This is the most basic form of delete. For all more sophisticated forms of derez (done asynchrnously - /// and where object can be taken to user inventory, etc.), see SceneObjectDeRezTests. - /// - [Test] - public void TestDeleteSceneObject() - { - TestHelpers.InMethod(); - - TestScene scene = new SceneHelpers().SetupScene(); - SceneObjectGroup so = SceneHelpers.AddSceneObject(scene); - - Assert.That(so.IsDeleted, Is.False); - uint retrievedPartID = so.LocalId; - - scene.DeleteSceneObject(so, false); - - SceneObjectPart retrievedPart = scene.GetSceneObjectPart(retrievedPartID); - - Assert.That(retrievedPart, Is.Null); - } - - /// - /// Changing a scene object uuid changes the root part uuid. This is a valid operation if the object is not - /// in a scene and is useful if one wants to supply a UUID directly rather than use the one generated by - /// OpenSim. - /// - [Test] - public void TestChangeSceneObjectUuid() - { - string rootPartName = "rootpart"; - UUID rootPartUuid = new UUID("00000000-0000-0000-0000-000000000001"); - string childPartName = "childPart"; - UUID childPartUuid = new UUID("00000000-0000-0000-0001-000000000000"); - - SceneObjectPart rootPart - = new SceneObjectPart(UUID.Zero, PrimitiveBaseShape.Default, Vector3.Zero, Quaternion.Identity, Vector3.Zero) - { Name = rootPartName, UUID = rootPartUuid }; - SceneObjectPart linkPart - = new SceneObjectPart(UUID.Zero, PrimitiveBaseShape.Default, Vector3.Zero, Quaternion.Identity, Vector3.Zero) - { Name = childPartName, UUID = childPartUuid }; - - SceneObjectGroup sog = new SceneObjectGroup(rootPart); - sog.AddPart(linkPart); - - Assert.That(sog.UUID, Is.EqualTo(rootPartUuid)); - Assert.That(sog.RootPart.UUID, Is.EqualTo(rootPartUuid)); - Assert.That(sog.Parts.Length, Is.EqualTo(2)); - - UUID newRootPartUuid = new UUID("00000000-0000-0000-0000-000000000002"); - sog.UUID = newRootPartUuid; - - Assert.That(sog.UUID, Is.EqualTo(newRootPartUuid)); - Assert.That(sog.RootPart.UUID, Is.EqualTo(newRootPartUuid)); - Assert.That(sog.Parts.Length, Is.EqualTo(2)); - } - } -} \ No newline at end of file diff --git a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectCopyTests.cs b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectCopyTests.cs deleted file mode 100644 index c27bc1a818d..00000000000 --- a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectCopyTests.cs +++ /dev/null @@ -1,348 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections.Generic; -using System.Reflection; -using Nini.Config; -using NUnit.Framework; -using OpenMetaverse; -using OpenSim.Framework; -using OpenSim.Region.CoreModules.Framework.EntityTransfer; -using OpenSim.Region.CoreModules.Framework.InventoryAccess; -using OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation; -using OpenSim.Region.CoreModules.World.Permissions; -using OpenSim.Region.Framework.Scenes; -using OpenSim.Services.Interfaces; -using OpenSim.Tests.Common; - -namespace OpenSim.Region.Framework.Scenes.Tests -{ - /* - /// - /// Test copying of scene objects. - /// - /// - /// This is at a level above the SceneObjectBasicTests, which act on the scene directly. - /// - [TestFixture] - public class SceneObjectCopyTests : OpenSimTestCase - { - [TestFixtureSetUp] - public void FixtureInit() - { - // Don't allow tests to be bamboozled by asynchronous events. Execute everything on the same thread. - // This facility was added after the original async delete tests were written, so it may be possible now - // to not bother explicitly disabling their async (since everything will be running sync). - Util.FireAndForgetMethod = FireAndForgetMethod.RegressionTest; - } - - [TestFixtureTearDown] - public void TearDown() - { - // We must set this back afterwards, otherwise later tests will fail since they're expecting multiple - // threads. Possibly, later tests should be rewritten so none of them require async stuff (which regression - // tests really shouldn't). - Util.FireAndForgetMethod = Util.DefaultFireAndForgetMethod; - } - - [Test] - public void TestTakeCopyWhenCopierIsOwnerWithPerms() - { - TestHelpers.InMethod(); -// TestHelpers.EnableLogging(); - - IConfigSource config = new IniConfigSource(); - config.AddConfig("Modules"); - config.Configs["Modules"].Set("InventoryAccessModule", "BasicInventoryAccessModule"); - - TestScene scene = new SceneHelpers().SetupScene("s1", TestHelpers.ParseTail(0x99), 1000, 1000, config); - SceneHelpers.SetupSceneModules(scene, config, new PermissionsModule(), new BasicInventoryAccessModule()); - UserAccount ua = UserAccountHelpers.CreateUserWithInventory(scene, TestHelpers.ParseTail(0x1)); - TestClient client = (TestClient)SceneHelpers.AddScenePresence(scene, ua.PrincipalID).ControllingClient; - - // Turn off the timer on the async sog deleter - we'll crank it by hand for this test. - AsyncSceneObjectGroupDeleter sogd = scene.SceneObjectGroupDeleter; - sogd.Enabled = false; - - SceneObjectGroup so = SceneHelpers.AddSceneObject(scene, "so1", ua.PrincipalID); - uint soLocalId = so.LocalId; -// so.UpdatePermissions( -// ua.PrincipalID, (byte)PermissionWho.Owner, so.LocalId, (uint)OpenMetaverse.PermissionMask.Copy, 1); -// so.UpdatePermissions( -// ua.PrincipalID, (byte)PermissionWho.Owner, so.LocalId, (uint)OpenMetaverse.PermissionMask.Transfer, 0); -// so.UpdatePermissions( -// ua.PrincipalID, (byte)PermissionWho.Base, so.LocalId, (uint)OpenMetaverse.PermissionMask.Transfer, 0); -// scene.HandleObjectPermissionsUpdate(client, client.AgentId, client.SessionId, (byte)PermissionWho.Owner, so.LocalId, (uint)OpenMetaverse.PermissionMask.Transfer, 0); - - // Ideally we might change these via client-focussed method calls as commented out above. However, this - // becomes very convoluted so we will set only the copy perm directly. - so.RootPart.BaseMask = (uint)OpenMetaverse.PermissionMask.Copy; -// so.RootPart.OwnerMask = (uint)OpenMetaverse.PermissionMask.Copy; - - List localIds = new List(); - localIds.Add(so.LocalId); - - // Specifying a UUID.Zero in this case will currently plop it in Lost and Found - scene.DeRezObjects(client, localIds, UUID.Zero, DeRezAction.TakeCopy, UUID.Zero); - - // Check that object isn't copied until we crank the sogd handle. - SceneObjectPart retrievedPart = scene.GetSceneObjectPart(so.LocalId); - Assert.That(retrievedPart, Is.Not.Null); - Assert.That(retrievedPart.ParentGroup.IsDeleted, Is.False); - - sogd.InventoryDeQueueAndDelete(); - - // Check that object is still there. - SceneObjectPart retrievedPart2 = scene.GetSceneObjectPart(so.LocalId); - Assert.That(retrievedPart2, Is.Not.Null); - Assert.That(client.ReceivedKills.Count, Is.EqualTo(0)); - - // Check that we have a copy in inventory - InventoryItemBase item - = UserInventoryHelpers.GetInventoryItem(scene.InventoryService, ua.PrincipalID, "Lost And Found/so1"); - Assert.That(item, Is.Not.Null); - } - - [Test] - public void TestTakeCopyWhenCopierIsOwnerWithoutPerms() - { - TestHelpers.InMethod(); -// TestHelpers.EnableLogging(); - - IConfigSource config = new IniConfigSource(); - config.AddConfig("Modules"); - config.Configs["Modules"].Set("InventoryAccessModule", "BasicInventoryAccessModule"); - - TestScene scene = new SceneHelpers().SetupScene("s1", TestHelpers.ParseTail(0x99), 1000, 1000, config); - SceneHelpers.SetupSceneModules(scene, config, new PermissionsModule(), new BasicInventoryAccessModule()); - UserAccount ua = UserAccountHelpers.CreateUserWithInventory(scene, TestHelpers.ParseTail(0x1)); - TestClient client = (TestClient)SceneHelpers.AddScenePresence(scene, ua.PrincipalID).ControllingClient; - - // Turn off the timer on the async sog deleter - we'll crank it by hand for this test. - AsyncSceneObjectGroupDeleter sogd = scene.SceneObjectGroupDeleter; - sogd.Enabled = false; - - SceneObjectGroup so = SceneHelpers.AddSceneObject(scene, "so1", ua.PrincipalID); - uint soLocalId = so.LocalId; - - so.RootPart.BaseMask = (uint)(OpenMetaverse.PermissionMask.All & ~OpenMetaverse.PermissionMask.Copy); - //so.RootPart.OwnerMask = (uint)(OpenMetaverse.PermissionMask.Copy & ~OpenMetaverse.PermissionMask.Copy); - - List localIds = new List(); - localIds.Add(so.LocalId); - - // Specifying a UUID.Zero in this case will currently plop it in Lost and Found - scene.DeRezObjects(client, localIds, UUID.Zero, DeRezAction.TakeCopy, UUID.Zero); - - // Check that object isn't copied until we crank the sogd handle. - SceneObjectPart retrievedPart = scene.GetSceneObjectPart(so.LocalId); - Assert.That(retrievedPart, Is.Not.Null); - Assert.That(retrievedPart.ParentGroup.IsDeleted, Is.False); - - sogd.InventoryDeQueueAndDelete(); - - // Check that object is still there. - SceneObjectPart retrievedPart2 = scene.GetSceneObjectPart(so.LocalId); - Assert.That(retrievedPart2, Is.Not.Null); - Assert.That(client.ReceivedKills.Count, Is.EqualTo(0)); - - // Check that we do not have a copy in inventory - InventoryItemBase item - = UserInventoryHelpers.GetInventoryItem(scene.InventoryService, ua.PrincipalID, "Lost And Found/so1"); - Assert.That(item, Is.Null); - } - - [Test] - public void TestTakeCopyWhenCopierIsNotOwnerWithPerms() - { - TestHelpers.InMethod(); -// TestHelpers.EnableLogging(); - - IConfigSource config = new IniConfigSource(); - config.AddConfig("Modules"); - config.Configs["Modules"].Set("InventoryAccessModule", "BasicInventoryAccessModule"); - - TestScene scene = new SceneHelpers().SetupScene("s1", TestHelpers.ParseTail(0x99), 1000, 1000, config); - SceneHelpers.SetupSceneModules(scene, config, new PermissionsModule(), new BasicInventoryAccessModule()); - UserAccount ua = UserAccountHelpers.CreateUserWithInventory(scene, TestHelpers.ParseTail(0x1)); - TestClient client = (TestClient)SceneHelpers.AddScenePresence(scene, ua.PrincipalID).ControllingClient; - - // Turn off the timer on the async sog deleter - we'll crank it by hand for this test. - AsyncSceneObjectGroupDeleter sogd = scene.SceneObjectGroupDeleter; - sogd.Enabled = false; - - SceneObjectGroup so = SceneHelpers.AddSceneObject(scene, "so1", TestHelpers.ParseTail(0x2)); - uint soLocalId = so.LocalId; - - // Base must allow transfer and copy - so.RootPart.BaseMask = (uint)(OpenMetaverse.PermissionMask.Copy | OpenMetaverse.PermissionMask.Transfer); - // Must be set so anyone can copy - so.RootPart.EveryoneMask = (uint)OpenMetaverse.PermissionMask.Copy; - - List localIds = new List(); - localIds.Add(so.LocalId); - - // Specifying a UUID.Zero in this case will plop it in the Objects folder - scene.DeRezObjects(client, localIds, UUID.Zero, DeRezAction.TakeCopy, UUID.Zero); - - // Check that object isn't copied until we crank the sogd handle. - SceneObjectPart retrievedPart = scene.GetSceneObjectPart(so.LocalId); - Assert.That(retrievedPart, Is.Not.Null); - Assert.That(retrievedPart.ParentGroup.IsDeleted, Is.False); - - sogd.InventoryDeQueueAndDelete(); - - // Check that object is still there. - SceneObjectPart retrievedPart2 = scene.GetSceneObjectPart(so.LocalId); - Assert.That(retrievedPart2, Is.Not.Null); - Assert.That(client.ReceivedKills.Count, Is.EqualTo(0)); - - // Check that we have a copy in inventory - InventoryItemBase item - = UserInventoryHelpers.GetInventoryItem(scene.InventoryService, ua.PrincipalID, "Objects/so1"); - Assert.That(item, Is.Not.Null); - } - - [Test] - public void TestTakeCopyWhenCopierIsNotOwnerWithoutPerms() - { - TestHelpers.InMethod(); -// TestHelpers.EnableLogging(); - - IConfigSource config = new IniConfigSource(); - config.AddConfig("Modules"); - config.Configs["Modules"].Set("InventoryAccessModule", "BasicInventoryAccessModule"); - - TestScene scene = new SceneHelpers().SetupScene("s1", TestHelpers.ParseTail(0x99), 1000, 1000, config); - SceneHelpers.SetupSceneModules(scene, config, new PermissionsModule(), new BasicInventoryAccessModule()); - UserAccount ua = UserAccountHelpers.CreateUserWithInventory(scene, TestHelpers.ParseTail(0x1)); - TestClient client = (TestClient)SceneHelpers.AddScenePresence(scene, ua.PrincipalID).ControllingClient; - - // Turn off the timer on the async sog deleter - we'll crank it by hand for this test. - AsyncSceneObjectGroupDeleter sogd = scene.SceneObjectGroupDeleter; - sogd.Enabled = false; - - SceneObjectGroup so = SceneHelpers.AddSceneObject(scene, "so1", TestHelpers.ParseTail(0x2)); - uint soLocalId = so.LocalId; - - { - // Check that object is not copied if copy base perms is missing. - // Should not allow copy if base does not have this. - so.RootPart.BaseMask = (uint)OpenMetaverse.PermissionMask.Transfer; - // Must be set so anyone can copy - so.RootPart.EveryoneMask = (uint)OpenMetaverse.PermissionMask.Copy; - - // Check that object is not copied - List localIds = new List(); - localIds.Add(so.LocalId); - - // Specifying a UUID.Zero in this case will plop it in the Objects folder if we have perms - scene.DeRezObjects(client, localIds, UUID.Zero, DeRezAction.TakeCopy, UUID.Zero); - - // Check that object isn't copied until we crank the sogd handle. - SceneObjectPart retrievedPart = scene.GetSceneObjectPart(so.LocalId); - Assert.That(retrievedPart, Is.Not.Null); - Assert.That(retrievedPart.ParentGroup.IsDeleted, Is.False); - - sogd.InventoryDeQueueAndDelete(); - // Check that object is still there. - SceneObjectPart retrievedPart2 = scene.GetSceneObjectPart(so.LocalId); - Assert.That(retrievedPart2, Is.Not.Null); - Assert.That(client.ReceivedKills.Count, Is.EqualTo(0)); - - // Check that we have a copy in inventory - InventoryItemBase item - = UserInventoryHelpers.GetInventoryItem(scene.InventoryService, ua.PrincipalID, "Objects/so1"); - Assert.That(item, Is.Null); - } - - { - // Check that object is not copied if copy trans perms is missing. - // Should not allow copy if base does not have this. - so.RootPart.BaseMask = (uint)OpenMetaverse.PermissionMask.Copy; - // Must be set so anyone can copy - so.RootPart.EveryoneMask = (uint)OpenMetaverse.PermissionMask.Copy; - - // Check that object is not copied - List localIds = new List(); - localIds.Add(so.LocalId); - - // Specifying a UUID.Zero in this case will plop it in the Objects folder if we have perms - scene.DeRezObjects(client, localIds, UUID.Zero, DeRezAction.TakeCopy, UUID.Zero); - - // Check that object isn't copied until we crank the sogd handle. - SceneObjectPart retrievedPart = scene.GetSceneObjectPart(so.LocalId); - Assert.That(retrievedPart, Is.Not.Null); - Assert.That(retrievedPart.ParentGroup.IsDeleted, Is.False); - - sogd.InventoryDeQueueAndDelete(); - // Check that object is still there. - SceneObjectPart retrievedPart2 = scene.GetSceneObjectPart(so.LocalId); - Assert.That(retrievedPart2, Is.Not.Null); - Assert.That(client.ReceivedKills.Count, Is.EqualTo(0)); - - // Check that we have a copy in inventory - InventoryItemBase item - = UserInventoryHelpers.GetInventoryItem(scene.InventoryService, ua.PrincipalID, "Objects/so1"); - Assert.That(item, Is.Null); - } - - { - // Check that object is not copied if everyone copy perms is missing. - // Should not allow copy if base does not have this. - so.RootPart.BaseMask = (uint)(OpenMetaverse.PermissionMask.Copy | OpenMetaverse.PermissionMask.Transfer); - // Make sure everyone perm does not allow copy - so.RootPart.EveryoneMask = (uint)(OpenMetaverse.PermissionMask.All & ~OpenMetaverse.PermissionMask.Copy); - - // Check that object is not copied - List localIds = new List(); - localIds.Add(so.LocalId); - - // Specifying a UUID.Zero in this case will plop it in the Objects folder if we have perms - scene.DeRezObjects(client, localIds, UUID.Zero, DeRezAction.TakeCopy, UUID.Zero); - - // Check that object isn't copied until we crank the sogd handle. - SceneObjectPart retrievedPart = scene.GetSceneObjectPart(so.LocalId); - Assert.That(retrievedPart, Is.Not.Null); - Assert.That(retrievedPart.ParentGroup.IsDeleted, Is.False); - - sogd.InventoryDeQueueAndDelete(); - // Check that object is still there. - SceneObjectPart retrievedPart2 = scene.GetSceneObjectPart(so.LocalId); - Assert.That(retrievedPart2, Is.Not.Null); - Assert.That(client.ReceivedKills.Count, Is.EqualTo(0)); - - // Check that we have a copy in inventory - InventoryItemBase item - = UserInventoryHelpers.GetInventoryItem(scene.InventoryService, ua.PrincipalID, "Objects/so1"); - Assert.That(item, Is.Null); - } - } - } - */ -} \ No newline at end of file diff --git a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectCrossingTests.cs b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectCrossingTests.cs deleted file mode 100644 index eb7b6f8526b..00000000000 --- a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectCrossingTests.cs +++ /dev/null @@ -1,287 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections.Generic; -using Nini.Config; -using NUnit.Framework; -using OpenMetaverse; -using OpenSim.Framework; -using OpenSim.Region.CoreModules.Framework; -using OpenSim.Region.CoreModules.Framework.EntityTransfer; -using OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation; -using OpenSim.Region.CoreModules.World.Land; -using OpenSim.Region.OptionalModules; -using OpenSim.Tests.Common; -using System.Threading; - -namespace OpenSim.Region.Framework.Scenes.Tests -{ - public class SceneObjectCrossingTests : OpenSimTestCase - { - [OneTimeSetUp] - public void FixtureInit() - { - // Don't allow tests to be bamboozled by asynchronous events. Execute everything on the same thread. - Util.FireAndForgetMethod = FireAndForgetMethod.RegressionTest; - } - - [OneTimeTearDown] - public void TearDown() - { - // We must set this back afterwards, otherwise later tests will fail since they're expecting multiple - // threads. Possibly, later tests should be rewritten so none of them require async stuff (which regression - // tests really shouldn't). - Util.FireAndForgetMethod = Util.DefaultFireAndForgetMethod; - } - - /// - /// Test cross with no prim limit module. - /// - [Test] - public void TestCrossOnSameSimulator() - { - - TestHelpers.InMethod(); -// TestHelpers.EnableLogging(); - - UUID userId = TestHelpers.ParseTail(0x1); - int sceneObjectIdTail = 0x2; - - EntityTransferModule etmA = new EntityTransferModule(); - EntityTransferModule etmB = new EntityTransferModule(); - LocalSimulationConnectorModule lscm = new LocalSimulationConnectorModule(); - - IConfigSource config = new IniConfigSource(); - IConfig modulesConfig = config.AddConfig("Modules"); - modulesConfig.Set("EntityTransferModule", etmA.Name); - modulesConfig.Set("SimulationServices", lscm.Name); - - SceneHelpers sh = new SceneHelpers(); - TestScene sceneA = sh.SetupScene("sceneA", TestHelpers.ParseTail(0x100), 1000, 1000); - TestScene sceneB = sh.SetupScene("sceneB", TestHelpers.ParseTail(0x200), 1000, 999); - - SceneHelpers.SetupSceneModules(new Scene[] { sceneA, sceneB }, config, lscm); - SceneHelpers.SetupSceneModules(sceneA, config, etmA); - SceneHelpers.SetupSceneModules(sceneB, config, etmB); - - SceneObjectGroup so1 = SceneHelpers.AddSceneObject(sceneA, 1, userId, "", sceneObjectIdTail); - UUID so1Id = so1.UUID; - so1.AbsolutePosition = new Vector3(128, 10, 20); - - // Cross with a negative value - so1.AbsolutePosition = new Vector3(128, -10, 20); - - // crossing is async - Thread.Sleep(500); - - Assert.IsNull(sceneA.GetSceneObjectGroup(so1Id)); - Assert.NotNull(sceneB.GetSceneObjectGroup(so1Id)); - } - - /// - /// Test cross with no prim limit module. - /// - /// - /// Possibly this should belong in ScenePresenceCrossingTests, though here it is the object that is being moved - /// where the avatar is just a passenger. - /// - [Test] - public void TestCrossOnSameSimulatorWithSittingAvatar() - { - TestHelpers.InMethod(); -// TestHelpers.EnableLogging(); - - UUID userId = TestHelpers.ParseTail(0x1); - int sceneObjectIdTail = 0x2; - Vector3 so1StartPos = new Vector3(128, 10, 20); - - EntityTransferModule etmA = new EntityTransferModule(); - EntityTransferModule etmB = new EntityTransferModule(); - LocalSimulationConnectorModule lscm = new LocalSimulationConnectorModule(); - - IConfigSource config = new IniConfigSource(); - IConfig modulesConfig = config.AddConfig("Modules"); - modulesConfig.Set("EntityTransferModule", etmA.Name); - modulesConfig.Set("SimulationServices", lscm.Name); - IConfig entityTransferConfig = config.AddConfig("EntityTransfer"); - - // In order to run a single threaded regression test we do not want the entity transfer module waiting - // for a callback from the destination scene before removing its avatar data. - entityTransferConfig.Set("wait_for_callback", false); - - SceneHelpers sh = new SceneHelpers(); - TestScene sceneA = sh.SetupScene("sceneA", TestHelpers.ParseTail(0x100), 1000, 1000); - TestScene sceneB = sh.SetupScene("sceneB", TestHelpers.ParseTail(0x200), 1000, 999); - - SceneHelpers.SetupSceneModules(new Scene[] { sceneA, sceneB }, config, lscm); - SceneHelpers.SetupSceneModules(sceneA, config, new CapabilitiesModule(), etmA); - SceneHelpers.SetupSceneModules(sceneB, config, new CapabilitiesModule(), etmB); - - SceneObjectGroup so1 = SceneHelpers.AddSceneObject(sceneA, 1, userId, "", sceneObjectIdTail); - UUID so1Id = so1.UUID; - so1.AbsolutePosition = so1StartPos; - - AgentCircuitData acd = SceneHelpers.GenerateAgentData(userId); - TestClient tc = new TestClient(acd, sceneA); - List destinationTestClients = new List(); - EntityTransferHelpers.SetupInformClientOfNeighbourTriggersNeighbourClientCreate(tc, destinationTestClients); - - ScenePresence sp1SceneA = SceneHelpers.AddScenePresence(sceneA, tc, acd); - sp1SceneA.AbsolutePosition = so1StartPos; - sp1SceneA.HandleAgentRequestSit(sp1SceneA.ControllingClient, sp1SceneA.UUID, so1.UUID, Vector3.Zero); - - sceneA.Update(4); - sceneB.Update(4); - // Cross - sceneA.SceneGraph.UpdatePrimGroupPosition( - so1.LocalId, new Vector3(so1StartPos.X, so1StartPos.Y - 20, so1StartPos.Z), sp1SceneA.ControllingClient); - - // crossing is async - sceneA.Update(4); - sceneB.Update(4); - Thread.Sleep(500); - - SceneObjectGroup so1PostCross; - - ScenePresence sp1SceneAPostCross = sceneA.GetScenePresence(userId); - Assert.IsTrue(sp1SceneAPostCross.IsChildAgent, "sp1SceneAPostCross.IsChildAgent unexpectedly false"); - - ScenePresence sp1SceneBPostCross = sceneB.GetScenePresence(userId); - TestClient sceneBTc = ((TestClient)sp1SceneBPostCross.ControllingClient); - sceneBTc.CompleteMovement(); - - sceneA.Update(4); - sceneB.Update(4); - - Assert.IsFalse(sp1SceneBPostCross.IsChildAgent, "sp1SceneAPostCross.IsChildAgent unexpectedly true"); - Assert.IsTrue(sp1SceneBPostCross.IsSatOnObject); - - Assert.IsNull(sceneA.GetSceneObjectGroup(so1Id), "uck"); - so1PostCross = sceneB.GetSceneObjectGroup(so1Id); - Assert.NotNull(so1PostCross); - Assert.AreEqual(1, so1PostCross.GetSittingAvatarsCount()); - - - Vector3 so1PostCrossPos = so1PostCross.AbsolutePosition; - -// Console.WriteLine("CRISSCROSS"); - - // Recross - sceneB.SceneGraph.UpdatePrimGroupPosition( - so1PostCross.LocalId, new Vector3(so1PostCrossPos.X, so1PostCrossPos.Y + 20, so1PostCrossPos.Z), sp1SceneBPostCross.ControllingClient); - - sceneA.Update(4); - sceneB.Update(4); - // crossing is async - Thread.Sleep(500); - - { - ScenePresence sp1SceneBPostReCross = sceneB.GetScenePresence(userId); - Assert.IsTrue(sp1SceneBPostReCross.IsChildAgent, "sp1SceneBPostReCross.IsChildAgent unexpectedly false"); - - ScenePresence sp1SceneAPostReCross = sceneA.GetScenePresence(userId); - TestClient sceneATc = ((TestClient)sp1SceneAPostReCross.ControllingClient); - sceneATc.CompleteMovement(); - - Assert.IsFalse(sp1SceneAPostReCross.IsChildAgent, "sp1SceneAPostCross.IsChildAgent unexpectedly true"); - Assert.IsTrue(sp1SceneAPostReCross.IsSatOnObject); - - Assert.IsNull(sceneB.GetSceneObjectGroup(so1Id), "uck2"); - SceneObjectGroup so1PostReCross = sceneA.GetSceneObjectGroup(so1Id); - Assert.NotNull(so1PostReCross); - Assert.AreEqual(1, so1PostReCross.GetSittingAvatarsCount()); - } - } - - /// - /// Test cross with no prim limit module. - /// - /// - /// XXX: This test may FCbe better off in a specific PrimLimitsModuleTest class in optional module tests in the - /// future (though it is configured as active by default, so not really optional). - /// - [Test] - public void TestCrossOnSameSimulatorPrimLimitsOkay() - { - TestHelpers.InMethod(); -// TestHelpers.EnableLogging(); - - UUID userId = TestHelpers.ParseTail(0x1); - int sceneObjectIdTail = 0x2; - - EntityTransferModule etmA = new EntityTransferModule(); - EntityTransferModule etmB = new EntityTransferModule(); - LocalSimulationConnectorModule lscm = new LocalSimulationConnectorModule(); - LandManagementModule lmmA = new LandManagementModule(); - LandManagementModule lmmB = new LandManagementModule(); - - IConfigSource config = new IniConfigSource(); - IConfig modulesConfig = config.AddConfig("Modules"); - modulesConfig.Set("EntityTransferModule", etmA.Name); - modulesConfig.Set("SimulationServices", lscm.Name); - - IConfig permissionsConfig = config.AddConfig("Permissions"); - permissionsConfig.Set("permissionmodules", "PrimLimitsModule"); - - SceneHelpers sh = new SceneHelpers(); - TestScene sceneA = sh.SetupScene("sceneA", TestHelpers.ParseTail(0x100), 1000, 1000); - TestScene sceneB = sh.SetupScene("sceneB", TestHelpers.ParseTail(0x200), 1000, 999); - - SceneHelpers.SetupSceneModules(new Scene[] { sceneA, sceneB }, config, lscm); - SceneHelpers.SetupSceneModules( - sceneA, config, etmA, lmmA, new PrimLimitsModule(), new PrimCountModule()); - SceneHelpers.SetupSceneModules( - sceneB, config, etmB, lmmB, new PrimLimitsModule(), new PrimCountModule()); - - // We must set up the parcel for this to work. Normally this is taken care of by OpenSimulator startup - // code which is not yet easily invoked by tests. - lmmA.EventManagerOnNoLandDataFromStorage(); - lmmB.EventManagerOnNoLandDataFromStorage(); - - AgentCircuitData acd = SceneHelpers.GenerateAgentData(userId); - TestClient tc = new TestClient(acd, sceneA); - List destinationTestClients = new List(); - EntityTransferHelpers.SetupInformClientOfNeighbourTriggersNeighbourClientCreate(tc, destinationTestClients); - ScenePresence sp1SceneA = SceneHelpers.AddScenePresence(sceneA, tc, acd); - - SceneObjectGroup so1 = SceneHelpers.AddSceneObject(sceneA, 1, userId, "", sceneObjectIdTail); - UUID so1Id = so1.UUID; - so1.AbsolutePosition = new Vector3(128, 10, 20); - - // Cross with a negative value. We must make this call rather than setting AbsolutePosition directly - // because only this will execute permission checks in the source region. - sceneA.SceneGraph.UpdatePrimGroupPosition(so1.LocalId, new Vector3(128, -10, 20), sp1SceneA.ControllingClient); - - // crossing is async - Thread.Sleep(500); - - Assert.IsNull(sceneA.GetSceneObjectGroup(so1Id)); - Assert.NotNull(sceneB.GetSceneObjectGroup(so1Id)); - } - } -} \ No newline at end of file diff --git a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectDeRezTests.cs b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectDeRezTests.cs deleted file mode 100644 index 0c0376e247a..00000000000 --- a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectDeRezTests.cs +++ /dev/null @@ -1,260 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections.Generic; -using System.Reflection; -using Nini.Config; -using NUnit.Framework; -using OpenMetaverse; -using OpenSim.Framework; -using OpenSim.Region.CoreModules.Framework.EntityTransfer; -using OpenSim.Region.CoreModules.Framework.InventoryAccess; -using OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation; -using OpenSim.Region.CoreModules.World.Permissions; -using OpenSim.Region.Framework.Scenes; -using OpenSim.Services.Interfaces; -using OpenSim.Tests.Common; - -namespace OpenSim.Region.Framework.Scenes.Tests -{ - /// - /// Tests derez of scene objects. - /// - /// - /// This is at a level above the SceneObjectBasicTests, which act on the scene directly. - /// TODO: These tests are incomplete - need to test more kinds of derez (e.g. return object). - /// - [TestFixture] - public class SceneObjectDeRezTests : OpenSimTestCase - { - [OneTimeSetUp] - public void FixtureInit() - { - // Don't allow tests to be bamboozled by asynchronous events. Execute everything on the same thread. - // This facility was added after the original async delete tests were written, so it may be possible now - // to not bother explicitly disabling their async (since everything will be running sync). - Util.FireAndForgetMethod = FireAndForgetMethod.RegressionTest; - } - - [OneTimeTearDown] - public void TearDown() - { - // We must set this back afterwards, otherwise later tests will fail since they're expecting multiple - // threads. Possibly, later tests should be rewritten so none of them require async stuff (which regression - // tests really shouldn't). - Util.FireAndForgetMethod = Util.DefaultFireAndForgetMethod; - } - - /// - /// Test deleting an object from a scene. - /// - [Test] - public void TestDeRezSceneObject() - { - TestHelpers.InMethod(); - - UUID userId = UUID.Parse("10000000-0000-0000-0000-000000000001"); - - TestScene scene = new SceneHelpers().SetupScene(); - IConfigSource configSource = new IniConfigSource(); - IConfig config = configSource.AddConfig("Startup"); - config.Set("serverside_object_permissions", true); - SceneHelpers.SetupSceneModules(scene, configSource, new object[] { new DefaultPermissionsModule() }); - IClientAPI client = SceneHelpers.AddScenePresence(scene, userId).ControllingClient; - - // Turn off the timer on the async sog deleter - we'll crank it by hand for this test. - AsyncSceneObjectGroupDeleter sogd = scene.SceneObjectGroupDeleter; - sogd.Enabled = false; - - SceneObjectGroup so = SceneHelpers.AddSceneObject(scene, "so1", userId); - uint soLocalId = so.LocalId; - - List localIds = new List(); - localIds.Add(so.LocalId); - scene.DeRezObjects(client, localIds, UUID.Zero, DeRezAction.Delete, UUID.Zero); - - // Check that object isn't deleted until we crank the sogd handle. - SceneObjectPart retrievedPart = scene.GetSceneObjectPart(so.LocalId); -// Assert.That(retrievedPart, Is.Not.Null); -// Assert.That(retrievedPart.ParentGroup.IsDeleted, Is.False); - - sogd.InventoryDeQueueAndDelete(); - -// SceneObjectPart retrievedPart2 = scene.GetSceneObjectPart(so.LocalId); - Assert.That(retrievedPart, Is.Null); - } - - /// - /// Test that child and root agents correctly receive KillObject notifications. - /// - [Test] - public void TestDeRezSceneObjectToAgents() - { - TestHelpers.InMethod(); -// TestHelpers.EnableLogging(); - - SceneHelpers sh = new SceneHelpers(); - TestScene sceneA = sh.SetupScene("sceneA", TestHelpers.ParseTail(0x100), 1000, 1000); - TestScene sceneB = sh.SetupScene("sceneB", TestHelpers.ParseTail(0x200), 1000, 999); - - // We need this so that the creation of the root client for userB in sceneB can trigger the creation of a child client in sceneA - LocalSimulationConnectorModule lscm = new LocalSimulationConnectorModule(); - EntityTransferModule etmB = new EntityTransferModule(); - IConfigSource config = new IniConfigSource(); - IConfig modulesConfig = config.AddConfig("Modules"); - modulesConfig.Set("EntityTransferModule", etmB.Name); - modulesConfig.Set("SimulationServices", lscm.Name); - SceneHelpers.SetupSceneModules(new Scene[] { sceneA, sceneB }, config, lscm); - SceneHelpers.SetupSceneModules(sceneB, config, etmB); - - // We need this for derez - //SceneHelpers.SetupSceneModules(sceneA, new PermissionsModule()); - - UserAccount uaA = UserAccountHelpers.CreateUserWithInventory(sceneA, "Andy", "AAA", 0x1, ""); - UserAccount uaB = UserAccountHelpers.CreateUserWithInventory(sceneA, "Brian", "BBB", 0x2, ""); - - TestClient clientA = (TestClient)SceneHelpers.AddScenePresence(sceneA, uaA).ControllingClient; - - // This is the more long-winded route we have to take to get a child client created for userB in sceneA - // rather than just calling AddScenePresence() as for userA - AgentCircuitData acd = SceneHelpers.GenerateAgentData(uaB); - TestClient clientB = new TestClient(acd, sceneB); - List childClientsB = new List(); - EntityTransferHelpers.SetupInformClientOfNeighbourTriggersNeighbourClientCreate(clientB, childClientsB); - - SceneHelpers.AddScenePresence(sceneB, clientB, acd); - - SceneObjectGroup so = SceneHelpers.AddSceneObject(sceneA); - uint soLocalId = so.LocalId; - - sceneA.DeleteSceneObject(so, false); - } - - /// - /// Test deleting an object from a scene where the deleter is not the owner - /// - /// - /// This test assumes that the deleter is not a god. - /// - [Test] - public void TestDeRezSceneObjectNotOwner() - { - TestHelpers.InMethod(); -// log4net.Config.XmlConfigurator.Configure(); - - UUID userId = UUID.Parse("10000000-0000-0000-0000-000000000001"); - UUID objectOwnerId = UUID.Parse("20000000-0000-0000-0000-000000000001"); - - TestScene scene = new SceneHelpers().SetupScene(); - IConfigSource configSource = new IniConfigSource(); - IConfig config = configSource.AddConfig("Startup"); - config.Set("serverside_object_permissions", true); - SceneHelpers.SetupSceneModules(scene, configSource, new object[] { new DefaultPermissionsModule() }); - IClientAPI client = SceneHelpers.AddScenePresence(scene, userId).ControllingClient; - - // Turn off the timer on the async sog deleter - we'll crank it by hand for this test. - AsyncSceneObjectGroupDeleter sogd = scene.SceneObjectGroupDeleter; - sogd.Enabled = false; - - SceneObjectPart part - = new SceneObjectPart(objectOwnerId, PrimitiveBaseShape.Default, Vector3.Zero, Quaternion.Identity, Vector3.Zero); - part.Name = "obj1"; - scene.AddNewSceneObject(new SceneObjectGroup(part), false); - List localIds = new List(); - localIds.Add(part.LocalId); - - scene.DeRezObjects(client, localIds, UUID.Zero, DeRezAction.Delete, UUID.Zero); - sogd.InventoryDeQueueAndDelete(); - - // Object should still be in the scene. - SceneObjectPart retrievedPart = scene.GetSceneObjectPart(part.LocalId); - Assert.That(retrievedPart.UUID, Is.EqualTo(part.UUID)); - } - - /// - /// Test deleting an object asynchronously to user inventory. - /// - [Test] - public void TestDeleteSceneObjectAsyncToUserInventory() - { - TestHelpers.InMethod(); -// TestHelpers.EnableLogging(); - - UUID agentId = UUID.Parse("00000000-0000-0000-0000-000000000001"); - string myObjectName = "Fred"; - - TestScene scene = new SceneHelpers().SetupScene(); - - IConfigSource configSource = new IniConfigSource(); - IConfig config = configSource.AddConfig("Modules"); - config.Set("InventoryAccessModule", "BasicInventoryAccessModule"); - SceneHelpers.SetupSceneModules( - scene, configSource, new object[] { new BasicInventoryAccessModule() }); - - SceneHelpers.SetupSceneModules(scene, new object[] { }); - - // Turn off the timer on the async sog deleter - we'll crank it by hand for this test. - AsyncSceneObjectGroupDeleter sogd = scene.SceneObjectGroupDeleter; - sogd.Enabled = false; - - SceneObjectGroup so = SceneHelpers.AddSceneObject(scene, myObjectName, agentId); - - UserAccount ua = UserAccountHelpers.CreateUserWithInventory(scene, agentId); - InventoryFolderBase folder1 - = UserInventoryHelpers.CreateInventoryFolder(scene.InventoryService, ua.PrincipalID, "folder1", false); - - IClientAPI client = SceneHelpers.AddScenePresence(scene, agentId).ControllingClient; - scene.DeRezObjects(client, new List() { so.LocalId }, UUID.Zero, DeRezAction.Take, folder1.ID); - -// SceneObjectPart retrievedPart = scene.GetSceneObjectPart(so.LocalId); - -// Assert.That(retrievedPart, Is.Not.Null); -// Assert.That(so.IsDeleted, Is.False); - - sogd.InventoryDeQueueAndDelete(); - - Assert.That(so.IsDeleted, Is.True); - - SceneObjectPart retrievedPart2 = scene.GetSceneObjectPart(so.LocalId); - Assert.That(retrievedPart2, Is.Null); - -// SceneSetupHelpers.DeleteSceneObjectAsync(scene, part, DeRezAction.Take, userInfo.RootFolder.ID, client); - - InventoryItemBase retrievedItem - = UserInventoryHelpers.GetInventoryItem( - scene.InventoryService, ua.PrincipalID, "folder1/" + myObjectName); - - // Check that we now have the taken part in our inventory - Assert.That(retrievedItem, Is.Not.Null); - - // Check that the taken part has actually disappeared -// SceneObjectPart retrievedPart = scene.GetSceneObjectPart(part.LocalId); -// Assert.That(retrievedPart, Is.Null); - } - } -} diff --git a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectLinkingTests.cs b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectLinkingTests.cs deleted file mode 100644 index 41f61ac424d..00000000000 --- a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectLinkingTests.cs +++ /dev/null @@ -1,373 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections.Generic; -using System.Reflection; -using NUnit.Framework; -using OpenMetaverse; -using OpenSim.Framework; -using OpenSim.Region.Framework.Scenes; -using OpenSim.Tests.Common; -using log4net; - -namespace OpenSim.Region.Framework.Scenes.Tests -{ - [TestFixture] - public class SceneObjectLinkingTests : OpenSimTestCase - { - private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - - /// - /// Links to self should be ignored. - /// - [Test] - public void TestLinkToSelf() - { - TestHelpers.InMethod(); - - UUID ownerId = TestHelpers.ParseTail(0x1); - int nParts = 3; - - TestScene scene = new SceneHelpers().SetupScene(); - SceneObjectGroup sog1 = SceneHelpers.CreateSceneObject(nParts, ownerId, "TestLinkToSelf_", 0x10); - scene.AddSceneObject(sog1); - scene.LinkObjects(ownerId, sog1.LocalId, new List() { sog1.Parts[1].LocalId }); -// sog1.LinkToGroup(sog1); - - Assert.That(sog1.Parts.Length, Is.EqualTo(nParts)); - } - - [Test] - public void TestLinkDelink2SceneObjects() - { - TestHelpers.InMethod(); - - bool debugtest = false; - - Scene scene = new SceneHelpers().SetupScene(); - SceneObjectGroup grp1 = SceneHelpers.AddSceneObject(scene); - SceneObjectPart part1 = grp1.RootPart; - SceneObjectGroup grp2 = SceneHelpers.AddSceneObject(scene); - SceneObjectPart part2 = grp2.RootPart; - - grp1.AbsolutePosition = new Vector3(10, 10, 10); - grp2.AbsolutePosition = Vector3.Zero; - - // <90,0,0> -// grp1.UpdateGroupRotationR(Quaternion.CreateFromEulers(90 * Utils.DEG_TO_RAD, 0, 0)); - - // <180,0,0> - grp2.UpdateGroupRotationR(Quaternion.CreateFromEulers(180 * Utils.DEG_TO_RAD, 0, 0)); - - // Required for linking - grp1.RootPart.ClearUpdateSchedule(); - grp2.RootPart.ClearUpdateSchedule(); - - // Link grp2 to grp1. part2 becomes child prim to grp1. grp2 is eliminated. - Assert.IsFalse(grp1.GroupContainsForeignPrims); - grp1.LinkToGroup(grp2); - Assert.IsTrue(grp1.GroupContainsForeignPrims); - - scene.Backup(true); - Assert.IsFalse(grp1.GroupContainsForeignPrims); - - // FIXME: Can't do this test yet since group 2 still has its root part! We can't yet null this since - // it might cause SOG.ProcessBackup() to fail due to the race condition. This really needs to be fixed. - Assert.That(grp2.IsDeleted, "SOG 2 was not registered as deleted after link."); - Assert.That(grp2.Parts.Length, Is.EqualTo(0), "Group 2 still contained children after delink."); - Assert.That(grp1.Parts.Length == 2); - - if (debugtest) - { - m_log.Debug("parts: " + grp1.Parts.Length); - m_log.Debug("Group1: Pos:"+grp1.AbsolutePosition+", Rot:"+grp1.GroupRotation); - m_log.Debug("Group1: Prim1: OffsetPosition:"+ part1.OffsetPosition+", OffsetRotation:"+part1.RotationOffset); - m_log.Debug("Group1: Prim2: OffsetPosition:"+part2.OffsetPosition+", OffsetRotation:"+part2.RotationOffset); - } - - // root part should have no offset position or rotation - Assert.That(part1.OffsetPosition == Vector3.Zero && part1.RotationOffset == Quaternion.Identity, - "root part should have no offset position or rotation"); - - // offset position should be root part position - part2.absolute position. - Assert.That(part2.OffsetPosition == new Vector3(-10, -10, -10), - "offset position should be root part position - part2.absolute position."); - - float roll = 0; - float pitch = 0; - float yaw = 0; - - // There's a euler anomoly at 180, 0, 0 so expect 180 to turn into -180. - part1.RotationOffset.GetEulerAngles(out roll, out pitch, out yaw); - Vector3 rotEuler1 = new Vector3(roll * Utils.RAD_TO_DEG, pitch * Utils.RAD_TO_DEG, yaw * Utils.RAD_TO_DEG); - - if (debugtest) - m_log.Debug(rotEuler1); - - part2.RotationOffset.GetEulerAngles(out roll, out pitch, out yaw); - Vector3 rotEuler2 = new Vector3(roll * Utils.RAD_TO_DEG, pitch * Utils.RAD_TO_DEG, yaw * Utils.RAD_TO_DEG); - - if (debugtest) - m_log.Debug(rotEuler2); - - Assert.That(rotEuler2.ApproxEquals(new Vector3(-180, 0, 0), 0.001f) || rotEuler2.ApproxEquals(new Vector3(180, 0, 0), 0.001f), - "Not exactly sure what this is asserting..."); - - // Delink part 2 - SceneObjectGroup grp3 = grp1.DelinkFromGroup(part2.LocalId); - - if (debugtest) - m_log.Debug("Group2: Prim2: OffsetPosition:" + part2.AbsolutePosition + ", OffsetRotation:" + part2.RotationOffset); - - Assert.That(grp1.Parts.Length, Is.EqualTo(1), "Group 1 still contained part2 after delink."); - Assert.That(part2.AbsolutePosition == Vector3.Zero, "The absolute position should be zero"); - Assert.NotNull(grp3); - } - - [Test] - public void TestLinkDelink2groups4SceneObjects() - { - TestHelpers.InMethod(); - - bool debugtest = false; - - Scene scene = new SceneHelpers().SetupScene(); - SceneObjectGroup grp1 = SceneHelpers.AddSceneObject(scene); - SceneObjectPart part1 = grp1.RootPart; - SceneObjectGroup grp2 = SceneHelpers.AddSceneObject(scene); - SceneObjectPart part2 = grp2.RootPart; - SceneObjectGroup grp3 = SceneHelpers.AddSceneObject(scene); - SceneObjectPart part3 = grp3.RootPart; - SceneObjectGroup grp4 = SceneHelpers.AddSceneObject(scene); - SceneObjectPart part4 = grp4.RootPart; - - grp1.AbsolutePosition = new Vector3(10, 10, 10); - grp2.AbsolutePosition = Vector3.Zero; - grp3.AbsolutePosition = new Vector3(20, 20, 20); - grp4.AbsolutePosition = new Vector3(40, 40, 40); - - // <90,0,0> -// grp1.UpdateGroupRotationR(Quaternion.CreateFromEulers(90 * Utils.DEG_TO_RAD, 0, 0)); - - // <180,0,0> - grp2.UpdateGroupRotationR(Quaternion.CreateFromEulers(180 * Utils.DEG_TO_RAD, 0, 0)); - - // <270,0,0> -// grp3.UpdateGroupRotationR(Quaternion.CreateFromEulers(270 * Utils.DEG_TO_RAD, 0, 0)); - - // <0,90,0> - grp4.UpdateGroupRotationR(Quaternion.CreateFromEulers(0, 90 * Utils.DEG_TO_RAD, 0)); - - // Required for linking - grp1.RootPart.ClearUpdateSchedule(); - grp2.RootPart.ClearUpdateSchedule(); - grp3.RootPart.ClearUpdateSchedule(); - grp4.RootPart.ClearUpdateSchedule(); - - // Link grp2 to grp1. part2 becomes child prim to grp1. grp2 is eliminated. - grp1.LinkToGroup(grp2); - - // Link grp4 to grp3. - grp3.LinkToGroup(grp4); - - // At this point we should have 4 parts total in two groups. - Assert.That(grp1.Parts.Length == 2, "Group1 children count should be 2"); - Assert.That(grp2.IsDeleted, "Group 2 was not registered as deleted after link."); - Assert.That(grp2.Parts.Length, Is.EqualTo(0), "Group 2 still contained parts after delink."); - Assert.That(grp3.Parts.Length == 2, "Group3 children count should be 2"); - Assert.That(grp4.IsDeleted, "Group 4 was not registered as deleted after link."); - Assert.That(grp4.Parts.Length, Is.EqualTo(0), "Group 4 still contained parts after delink."); - - if (debugtest) - { - m_log.Debug("--------After Link-------"); - m_log.Debug("Group1: parts:" + grp1.Parts.Length); - m_log.Debug("Group1: Pos:"+grp1.AbsolutePosition+", Rot:"+grp1.GroupRotation); - m_log.Debug("Group1: Prim1: OffsetPosition:" + part1.OffsetPosition + ", OffsetRotation:" + part1.RotationOffset); - m_log.Debug("Group1: Prim2: OffsetPosition:"+part2.OffsetPosition+", OffsetRotation:"+ part2.RotationOffset); - - m_log.Debug("Group3: parts:" + grp3.Parts.Length); - m_log.Debug("Group3: Pos:"+grp3.AbsolutePosition+", Rot:"+grp3.GroupRotation); - m_log.Debug("Group3: Prim1: OffsetPosition:"+part3.OffsetPosition+", OffsetRotation:"+part3.RotationOffset); - m_log.Debug("Group3: Prim2: OffsetPosition:"+part4.OffsetPosition+", OffsetRotation:"+part4.RotationOffset); - } - - // Required for linking - grp1.RootPart.ClearUpdateSchedule(); - grp3.RootPart.ClearUpdateSchedule(); - - // root part should have no offset position or rotation - Assert.That(part1.OffsetPosition == Vector3.Zero && part1.RotationOffset == Quaternion.Identity, - "root part should have no offset position or rotation (again)"); - - // offset position should be root part position - part2.absolute position. - Assert.That(part2.OffsetPosition == new Vector3(-10, -10, -10), - "offset position should be root part position - part2.absolute position (again)"); - - float roll = 0; - float pitch = 0; - float yaw = 0; - - // There's a euler anomoly at 180, 0, 0 so expect 180 to turn into -180. - part1.RotationOffset.GetEulerAngles(out roll, out pitch, out yaw); - Vector3 rotEuler1 = new Vector3(roll * Utils.RAD_TO_DEG, pitch * Utils.RAD_TO_DEG, yaw * Utils.RAD_TO_DEG); - - if (debugtest) - m_log.Debug(rotEuler1); - - part2.RotationOffset.GetEulerAngles(out roll, out pitch, out yaw); - Vector3 rotEuler2 = new Vector3(roll * Utils.RAD_TO_DEG, pitch * Utils.RAD_TO_DEG, yaw * Utils.RAD_TO_DEG); - - if (debugtest) - m_log.Debug(rotEuler2); - - Assert.That(rotEuler2.ApproxEquals(new Vector3(-180, 0, 0), 0.001f) || rotEuler2.ApproxEquals(new Vector3(180, 0, 0), 0.001f), - "Not sure what this assertion is all about..."); - - // Now we're linking the first group to the third group. This will make the first group child parts of the third one. - grp3.LinkToGroup(grp1); - - // Delink parts 2 and 3 - grp3.DelinkFromGroup(part2.LocalId); - grp3.DelinkFromGroup(part3.LocalId); - - if (debugtest) - { - m_log.Debug("--------After De-Link-------"); - m_log.Debug("Group1: parts:" + grp1.Parts.Length); - m_log.Debug("Group1: Pos:" + grp1.AbsolutePosition + ", Rot:" + grp1.GroupRotation); - m_log.Debug("Group1: Prim1: OffsetPosition:" + part1.OffsetPosition + ", OffsetRotation:" + part1.RotationOffset); - m_log.Debug("Group1: Prim2: OffsetPosition:" + part2.OffsetPosition + ", OffsetRotation:" + part2.RotationOffset); - - m_log.Debug("Group3: parts:" + grp3.Parts.Length); - m_log.Debug("Group3: Pos:" + grp3.AbsolutePosition + ", Rot:" + grp3.GroupRotation); - m_log.Debug("Group3: Prim1: OffsetPosition:" + part3.OffsetPosition + ", OffsetRotation:" + part3.RotationOffset); - m_log.Debug("Group3: Prim2: OffsetPosition:" + part4.OffsetPosition + ", OffsetRotation:" + part4.RotationOffset); - } - - Assert.That(part2.AbsolutePosition == Vector3.Zero, "Badness 1"); - Assert.That(part4.OffsetPosition == new Vector3(20, 20, 20), "Badness 2"); - Quaternion compareQuaternion = new Quaternion(0, 0.7071068f, 0, 0.7071068f); - Assert.That((part4.RotationOffset.X - compareQuaternion.X < 0.00003) - && (part4.RotationOffset.Y - compareQuaternion.Y < 0.00003) - && (part4.RotationOffset.Z - compareQuaternion.Z < 0.00003) - && (part4.RotationOffset.W - compareQuaternion.W < 0.00003), - "Badness 3"); - } - - /// - /// Test that a new scene object which is already linked is correctly persisted to the persistence layer. - /// - [Test] - public void TestNewSceneObjectLinkPersistence() - { - TestHelpers.InMethod(); - //log4net.Config.XmlConfigurator.Configure(); - - TestScene scene = new SceneHelpers().SetupScene(); - - string rootPartName = "rootpart"; - UUID rootPartUuid = new UUID("00000000-0000-0000-0000-000000000001"); - string linkPartName = "linkpart"; - UUID linkPartUuid = new UUID("00000000-0000-0000-0001-000000000000"); - - SceneObjectPart rootPart - = new SceneObjectPart(UUID.Zero, PrimitiveBaseShape.Default, Vector3.Zero, Quaternion.Identity, Vector3.Zero) - { Name = rootPartName, UUID = rootPartUuid }; - SceneObjectPart linkPart - = new SceneObjectPart(UUID.Zero, PrimitiveBaseShape.Default, Vector3.Zero, Quaternion.Identity, Vector3.Zero) - { Name = linkPartName, UUID = linkPartUuid }; - - SceneObjectGroup sog = new SceneObjectGroup(rootPart); - sog.AddPart(linkPart); - scene.AddNewSceneObject(sog, true); - - // In a test, we have to crank the backup handle manually. Normally this would be done by the timer invoked - // scene backup thread. - scene.Backup(true); - - List storedObjects = scene.SimulationDataService.LoadObjects(scene.RegionInfo.RegionID); - - Assert.That(storedObjects.Count, Is.EqualTo(1)); - Assert.That(storedObjects[0].Parts.Length, Is.EqualTo(2)); - Assert.That(storedObjects[0].ContainsPart(rootPartUuid)); - Assert.That(storedObjects[0].ContainsPart(linkPartUuid)); - } - - /// - /// Test that a delink of a previously linked object is correctly persisted to the database - /// - [Test] - public void TestDelinkPersistence() - { - TestHelpers.InMethod(); - //log4net.Config.XmlConfigurator.Configure(); - - TestScene scene = new SceneHelpers().SetupScene(); - - string rootPartName = "rootpart"; - UUID rootPartUuid = new UUID("00000000-0000-0000-0000-000000000001"); - string linkPartName = "linkpart"; - UUID linkPartUuid = new UUID("00000000-0000-0000-0001-000000000000"); - - SceneObjectPart rootPart - = new SceneObjectPart(UUID.Zero, PrimitiveBaseShape.Default, Vector3.Zero, Quaternion.Identity, Vector3.Zero) - { Name = rootPartName, UUID = rootPartUuid }; - - SceneObjectPart linkPart - = new SceneObjectPart(UUID.Zero, PrimitiveBaseShape.Default, Vector3.Zero, Quaternion.Identity, Vector3.Zero) - { Name = linkPartName, UUID = linkPartUuid }; - SceneObjectGroup linkGroup = new SceneObjectGroup(linkPart); - scene.AddNewSceneObject(linkGroup, true); - - SceneObjectGroup sog = new SceneObjectGroup(rootPart); - scene.AddNewSceneObject(sog, true); - - Assert.IsFalse(sog.GroupContainsForeignPrims); - sog.LinkToGroup(linkGroup); - Assert.IsTrue(sog.GroupContainsForeignPrims); - - scene.Backup(true); - Assert.AreEqual(1, scene.SimulationDataService.LoadObjects(scene.RegionInfo.RegionID).Count); - - // These changes should occur immediately without waiting for a backup pass - SceneObjectGroup groupToDelete = sog.DelinkFromGroup(linkPart, false); - Assert.IsFalse(groupToDelete.GroupContainsForeignPrims); - -/* backup is async - scene.DeleteSceneObject(groupToDelete, false); - - List storedObjects = scene.SimulationDataService.LoadObjects(scene.RegionInfo.RegionID); - - Assert.AreEqual(1, storedObjects.Count); - Assert.AreEqual(1, storedObjects[0].Parts.Length); - Assert.IsTrue(storedObjects[0].ContainsPart(rootPartUuid)); -*/ - } - } -} diff --git a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectResizeTests.cs b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectResizeTests.cs deleted file mode 100644 index 8b3a7e99cef..00000000000 --- a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectResizeTests.cs +++ /dev/null @@ -1,102 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Reflection; -using NUnit.Framework; -using OpenMetaverse; -using OpenSim.Framework; -using OpenSim.Region.Framework.Scenes; -using OpenSim.Tests.Common; - -namespace OpenSim.Region.Framework.Scenes.Tests -{ - /// - /// Basic scene object resize tests - /// - [TestFixture] - public class SceneObjectResizeTests : OpenSimTestCase - { - /// - /// Test resizing an object - /// - [Test] - public void TestResizeSceneObject() - { - TestHelpers.InMethod(); -// log4net.Config.XmlConfigurator.Configure(); - - Scene scene = new SceneHelpers().SetupScene(); - SceneObjectGroup g1 = SceneHelpers.AddSceneObject(scene); - - g1.GroupResize(new Vector3(2, 3, 4)); - - SceneObjectGroup g1Post = scene.GetSceneObjectGroup(g1.UUID); - - Assert.That(g1Post.RootPart.Scale.X, Is.EqualTo(2)); - Assert.That(g1Post.RootPart.Scale.Y, Is.EqualTo(3)); - Assert.That(g1Post.RootPart.Scale.Z, Is.EqualTo(4)); - -// Assert.That(g1Post.RootPart.UndoCount, Is.EqualTo(1)); - } - - /// - /// Test resizing an individual part in a scene object. - /// - [Test] - public void TestResizeSceneObjectPart() - { - TestHelpers.InMethod(); - //log4net.Config.XmlConfigurator.Configure(); - - Scene scene = new SceneHelpers().SetupScene(); - UUID owner = UUID.Random(); - SceneObjectGroup g1 = SceneHelpers.CreateSceneObject(2, owner); - g1.RootPart.Scale = new Vector3(2, 3, 4); - g1.Parts[1].Scale = new Vector3(5, 6, 7); - - scene.AddSceneObject(g1); - - SceneObjectGroup g1Post = scene.GetSceneObjectGroup(g1.UUID); - - g1Post.Parts[1].Resize(new Vector3(8, 9, 10)); - - SceneObjectGroup g1PostPost = scene.GetSceneObjectGroup(g1.UUID); - - SceneObjectPart g1RootPart = g1PostPost.RootPart; - SceneObjectPart g1ChildPart = g1PostPost.Parts[1]; - - Assert.That(g1RootPart.Scale.X, Is.EqualTo(2)); - Assert.That(g1RootPart.Scale.Y, Is.EqualTo(3)); - Assert.That(g1RootPart.Scale.Z, Is.EqualTo(4)); - - Assert.That(g1ChildPart.Scale.X, Is.EqualTo(8)); - Assert.That(g1ChildPart.Scale.Y, Is.EqualTo(9)); - Assert.That(g1ChildPart.Scale.Z, Is.EqualTo(10)); - } - } -} \ No newline at end of file diff --git a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectScriptTests.cs b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectScriptTests.cs deleted file mode 100644 index 8a2d2af90ff..00000000000 --- a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectScriptTests.cs +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections.Generic; -using System.Reflection; -using NUnit.Framework; -using OpenMetaverse; -using OpenSim.Framework; -using OpenSim.Region.Framework.Interfaces; -using OpenSim.Region.Framework.Scenes; -using OpenSim.Tests.Common; - -namespace OpenSim.Region.Framework.Scenes.Tests -{ - [TestFixture] - public class SceneObjectScriptTests : OpenSimTestCase - { - [Test] - public void TestAddScript() - { - TestHelpers.InMethod(); -// log4net.Config.XmlConfigurator.Configure(); - - UUID userId = TestHelpers.ParseTail(0x1); -// UUID itemId = TestHelpers.ParseTail(0x2); - string itemName = "Test Script Item"; - - Scene scene = new SceneHelpers().SetupScene(); - SceneObjectGroup so = SceneHelpers.CreateSceneObject(1, userId); - scene.AddNewSceneObject(so, true); - - InventoryItemBase itemTemplate = new InventoryItemBase(); - itemTemplate.Name = itemName; - itemTemplate.Folder = so.UUID; - itemTemplate.InvType = (int)InventoryType.LSL; - - SceneObjectPart partWhereScriptAdded = scene.RezNewScript(userId, itemTemplate); - - Assert.That(partWhereScriptAdded, Is.Not.Null); - - IEntityInventory primInventory = partWhereScriptAdded.Inventory; - Assert.That(primInventory.GetInventoryList().Count, Is.EqualTo(1)); - Assert.That(primInventory.ContainsScripts(), Is.True); - - IList primItems = primInventory.GetInventoryItems(itemName); - Assert.That(primItems.Count, Is.EqualTo(1)); - } - } -} \ No newline at end of file diff --git a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectSerializationTests.cs b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectSerializationTests.cs deleted file mode 100644 index e3ceb04e88f..00000000000 --- a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectSerializationTests.cs +++ /dev/null @@ -1,135 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections.Generic; -using System.Reflection; -using System.Threading; -using System.Xml; -using System.Linq; -using Nini.Config; -using NUnit.Framework; -using OpenMetaverse; -using OpenSim.Framework; -using OpenSim.Framework.Serialization.External; -using OpenSim.Region.Framework.Scenes; -using OpenSim.Region.Framework.Scenes.Serialization; -using OpenSim.Services.Interfaces; -using OpenSim.Tests.Common; - -namespace OpenSim.Region.Framework.Scenes.Tests -{ - /// - /// Basic scene object serialization tests. - /// - [TestFixture] - public class SceneObjectSerializationTests : OpenSimTestCase - { - - /// - /// Serialize and deserialize. - /// - [Test] - public void TestSerialDeserial() - { - TestHelpers.InMethod(); - - Scene scene = new SceneHelpers().SetupScene(); - int partsToTestCount = 3; - - SceneObjectGroup so - = SceneHelpers.CreateSceneObject(partsToTestCount, TestHelpers.ParseTail(0x1), "obj1", 0x10); - SceneObjectPart[] parts = so.Parts; - so.Name = "obj1"; - so.Description = "xpto"; - - string xml = SceneObjectSerializer.ToXml2Format(so); - Assert.That(!string.IsNullOrEmpty(xml), "SOG serialization resulted in empty or null string"); - - XmlDocument doc = new XmlDocument(); - doc.LoadXml(xml); - XmlNodeList nodes = doc.GetElementsByTagName("SceneObjectPart"); - Assert.That(nodes.Count, Is.EqualTo(3), "SOG serialization resulted in wrong number of SOPs"); - - SceneObjectGroup so2 = SceneObjectSerializer.FromXml2Format(xml); - Assert.IsNotNull(so2, "SOG deserialization resulted in null object"); - Assert.That(so2.Name == so.Name, "Name of deserialized object does not match original name"); - Assert.That(so2.Description == so.Description, "Description of deserialized object does not match original name"); - } - - /// - /// This checks for a bug reported in mantis #7514 - /// - [Test] - public void TestNamespaceAttribute() - { - TestHelpers.InMethod(); - - Scene scene = new SceneHelpers().SetupScene(); - UserAccount account = new UserAccount(UUID.Zero, UUID.Random(), "Test", "User", string.Empty); - scene.UserAccountService.StoreUserAccount(account); - int partsToTestCount = 1; - - SceneObjectGroup so - = SceneHelpers.CreateSceneObject(partsToTestCount, TestHelpers.ParseTail(0x1), "obj1", 0x10); - SceneObjectPart[] parts = so.Parts; - so.Name = "obj1"; - so.Description = "xpto"; - so.OwnerID = account.PrincipalID; - so.RootPart.CreatorID = so.OwnerID; - - string xml = SceneObjectSerializer.ToXml2Format(so); - Assert.That(!string.IsNullOrEmpty(xml), "SOG serialization resulted in empty or null string"); - - xml = ExternalRepresentationUtils.RewriteSOP(xml, "Test Scene", "http://localhost", scene.UserAccountService, UUID.Zero); - //Console.WriteLine(xml); - - XmlDocument doc = new XmlDocument(); - doc.LoadXml(xml); - - XmlNodeList nodes = doc.GetElementsByTagName("SceneObjectPart"); - Assert.That(nodes.Count, Is.GreaterThan(0), "SOG serialization resulted in no SOPs"); - foreach (XmlAttribute a in nodes[0].Attributes) - { - int count = a.Name.Count(c => c == ':'); - Assert.That(count, Is.EqualTo(1), "Cannot have multiple ':' in attribute name in SOP"); - } - nodes = doc.GetElementsByTagName("CreatorData"); - Assert.That(nodes.Count, Is.GreaterThan(0), "SOG serialization resulted in no CreatorData"); - foreach (XmlAttribute a in nodes[0].Attributes) - { - int count = a.Name.Count(c => c == ':'); - Assert.That(count, Is.EqualTo(1), "Cannot have multiple ':' in attribute name in CreatorData"); - } - - SceneObjectGroup so2 = SceneObjectSerializer.FromXml2Format(xml); - Assert.IsNotNull(so2, "SOG deserialization resulted in null object"); - Assert.AreNotEqual(so.RootPart.CreatorIdentification, so2.RootPart.CreatorIdentification, "RewriteSOP failed to transform CreatorData."); - Assert.That(so2.RootPart.CreatorIdentification.Contains("http://"), "RewriteSOP failed to add the homeURL to CreatorData"); - } - } -} \ No newline at end of file diff --git a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectSpatialTests.cs b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectSpatialTests.cs deleted file mode 100644 index c2c78228807..00000000000 --- a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectSpatialTests.cs +++ /dev/null @@ -1,153 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Reflection; -using System.Threading; -using NUnit.Framework; -using OpenMetaverse; -using OpenSim.Framework; -using OpenSim.Region.Framework.Scenes; -using OpenSim.Tests.Common; - -namespace OpenSim.Region.Framework.Scenes.Tests -{ - /// - /// Spatial scene object tests (will eventually cover root and child part position, rotation properties, etc.) - /// - [TestFixture] - public class SceneObjectSpatialTests : OpenSimTestCase - { - TestScene m_scene; - UUID m_ownerId = TestHelpers.ParseTail(0x1); - - [SetUp] - public override void SetUp() - { - base.SetUp(); - - m_scene = new SceneHelpers().SetupScene(); - } - - [Test] - public void TestGetSceneObjectGroupPosition() - { - TestHelpers.InMethod(); - - Vector3 position = new Vector3(10, 20, 30); - - SceneObjectGroup so - = SceneHelpers.CreateSceneObject(1, m_ownerId, "obj1", 0x10); - so.AbsolutePosition = position; - m_scene.AddNewSceneObject(so, false); - - Assert.That(so.AbsolutePosition, Is.EqualTo(position)); - } - - [Test] - public void TestGetRootPartPosition() - { - TestHelpers.InMethod(); - - Vector3 partPosition = new Vector3(10, 20, 30); - - SceneObjectGroup so - = SceneHelpers.CreateSceneObject(1, m_ownerId, "obj1", 0x10); - so.AbsolutePosition = partPosition; - m_scene.AddNewSceneObject(so, false); - - Assert.That(so.RootPart.AbsolutePosition, Is.EqualTo(partPosition)); - Assert.That(so.RootPart.GroupPosition, Is.EqualTo(partPosition)); - Assert.That(so.RootPart.GetWorldPosition(), Is.EqualTo(partPosition)); - Assert.That(so.RootPart.RelativePosition, Is.EqualTo(partPosition)); - Assert.That(so.RootPart.OffsetPosition, Is.EqualTo(Vector3.Zero)); - } - - [Test] - public void TestGetChildPartPosition() - { - TestHelpers.InMethod(); - - Vector3 rootPartPosition = new Vector3(10, 20, 30); - Vector3 childOffsetPosition = new Vector3(2, 3, 4); - - SceneObjectGroup so - = SceneHelpers.CreateSceneObject(2, m_ownerId, "obj1", 0x10); - so.AbsolutePosition = rootPartPosition; - so.Parts[1].OffsetPosition = childOffsetPosition; - - m_scene.AddNewSceneObject(so, false); - - // Calculate child absolute position. - Vector3 childPosition = new Vector3(rootPartPosition + childOffsetPosition); - - SceneObjectPart childPart = so.Parts[1]; - Assert.That(childPart.AbsolutePosition, Is.EqualTo(childPosition)); - Assert.That(childPart.GroupPosition, Is.EqualTo(rootPartPosition)); - Assert.That(childPart.GetWorldPosition(), Is.EqualTo(childPosition)); - Assert.That(childPart.RelativePosition, Is.EqualTo(childOffsetPosition)); - Assert.That(childPart.OffsetPosition, Is.EqualTo(childOffsetPosition)); - } - - [Test] - public void TestGetChildPartPositionAfterObjectRotation() - { - TestHelpers.InMethod(); - - Vector3 rootPartPosition = new Vector3(10, 20, 30); - Vector3 childOffsetPosition = new Vector3(2, 3, 4); - - SceneObjectGroup so - = SceneHelpers.CreateSceneObject(2, m_ownerId, "obj1", 0x10); - so.AbsolutePosition = rootPartPosition; - so.Parts[1].OffsetPosition = childOffsetPosition; - - m_scene.AddNewSceneObject(so, false); - - so.UpdateGroupRotationR(Quaternion.CreateFromEulers(0, 0, -90 * Utils.DEG_TO_RAD)); - - // Calculate child absolute position. - Vector3 rotatedChildOffsetPosition - = new Vector3(childOffsetPosition.Y, -childOffsetPosition.X, childOffsetPosition.Z); - - Vector3 childPosition = new Vector3(rootPartPosition + rotatedChildOffsetPosition); - - SceneObjectPart childPart = so.Parts[1]; - - Assert.That(childPart.AbsolutePosition, Is.EqualTo(childPosition)); - - Assert.That(childPart.GroupPosition, Is.EqualTo(rootPartPosition)); - Assert.That(childPart.GetWorldPosition(), Is.EqualTo(childPosition)); - - // Relative to root part as (0, 0, 0) - Assert.That(childPart.RelativePosition, Is.EqualTo(childOffsetPosition)); - - // Relative to root part as (0, 0, 0) - Assert.That(childPart.OffsetPosition, Is.EqualTo(childOffsetPosition)); - } - } -} \ No newline at end of file diff --git a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectStatusTests.cs b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectStatusTests.cs deleted file mode 100644 index 8d880830799..00000000000 --- a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectStatusTests.cs +++ /dev/null @@ -1,242 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections.Generic; -using System.Reflection; -using NUnit.Framework; -using OpenMetaverse; -using OpenSim.Framework; -using OpenSim.Region.Framework.Scenes; -using OpenSim.Tests.Common; - -namespace OpenSim.Region.Framework.Scenes.Tests -{ - /// - /// Basic scene object status tests - /// - [TestFixture] - public class SceneObjectStatusTests : OpenSimTestCase - { - private TestScene m_scene; - private UUID m_ownerId = TestHelpers.ParseTail(0x1); - private SceneObjectGroup m_so1; - private SceneObjectGroup m_so2; - - [SetUp] - public void Init() - { - m_scene = new SceneHelpers().SetupScene(); - m_so1 = SceneHelpers.CreateSceneObject(1, m_ownerId, "so1", 0x10); - m_so2 = SceneHelpers.CreateSceneObject(1, m_ownerId, "so2", 0x20); - } - - [Test] - public void TestSetTemporary() - { - TestHelpers.InMethod(); - - m_scene.AddSceneObject(m_so1); - m_so1.ScriptSetTemporaryStatus(true); - - // Is this really the correct flag? - Assert.That(m_so1.RootPart.Flags, Is.EqualTo(PrimFlags.TemporaryOnRez)); - Assert.That(m_so1.Backup, Is.False); - - // Test setting back to non-temporary - m_so1.ScriptSetTemporaryStatus(false); - - Assert.That(m_so1.RootPart.Flags, Is.EqualTo(PrimFlags.None)); - Assert.That(m_so1.Backup, Is.True); - } - - [Test] - public void TestSetPhantomSinglePrim() - { - TestHelpers.InMethod(); - - m_scene.AddSceneObject(m_so1); - - SceneObjectPart rootPart = m_so1.RootPart; - Assert.That(rootPart.Flags, Is.EqualTo(PrimFlags.None)); - - m_so1.ScriptSetPhantomStatus(true); - -// Console.WriteLine("so.RootPart.Flags [{0}]", so.RootPart.Flags); - Assert.That(rootPart.Flags, Is.EqualTo(PrimFlags.Phantom)); - - m_so1.ScriptSetPhantomStatus(false); - - Assert.That(rootPart.Flags, Is.EqualTo(PrimFlags.None)); - } - - [Test] - public void TestSetNonPhysicsVolumeDetectSinglePrim() - { - TestHelpers.InMethod(); - - m_scene.AddSceneObject(m_so1); - - SceneObjectPart rootPart = m_so1.RootPart; - Assert.That(rootPart.Flags, Is.EqualTo(PrimFlags.None)); - - m_so1.ScriptSetVolumeDetect(true); - -// Console.WriteLine("so.RootPart.Flags [{0}]", so.RootPart.Flags); - // PrimFlags.JointLP2P is incorrect it now means VolumeDetect (as defined by viewers) - Assert.That(rootPart.Flags, Is.EqualTo(PrimFlags.Phantom | PrimFlags.JointLP2P)); - - m_so1.ScriptSetVolumeDetect(false); - - Assert.That(rootPart.Flags, Is.EqualTo(PrimFlags.None)); - } - - [Test] - public void TestSetPhysicsSinglePrim() - { - TestHelpers.InMethod(); - - m_scene.AddSceneObject(m_so1); - - SceneObjectPart rootPart = m_so1.RootPart; - Assert.That(rootPart.Flags, Is.EqualTo(PrimFlags.None)); - - m_so1.ScriptSetPhysicsStatus(true); - - Assert.That(rootPart.Flags, Is.EqualTo(PrimFlags.Physics)); - - m_so1.ScriptSetPhysicsStatus(false); - - Assert.That(rootPart.Flags, Is.EqualTo(PrimFlags.None)); - } - - [Test] - public void TestSetPhysicsVolumeDetectSinglePrim() - { - TestHelpers.InMethod(); - - m_scene.AddSceneObject(m_so1); - - SceneObjectPart rootPart = m_so1.RootPart; - Assert.That(rootPart.Flags, Is.EqualTo(PrimFlags.None)); - - m_so1.ScriptSetPhysicsStatus(true); - m_so1.ScriptSetVolumeDetect(true); - - // PrimFlags.JointLP2P is incorrect it now means VolumeDetect (as defined by viewers) - Assert.That(rootPart.Flags, Is.EqualTo(PrimFlags.Phantom | PrimFlags.Physics | PrimFlags.JointLP2P)); - - m_so1.ScriptSetVolumeDetect(false); - - Assert.That(rootPart.Flags, Is.EqualTo(PrimFlags.Physics)); - } - - [Test] - public void TestSetPhysicsLinkset() - { - TestHelpers.InMethod(); - - m_scene.AddSceneObject(m_so1); - m_scene.AddSceneObject(m_so2); - - m_scene.LinkObjects(m_ownerId, m_so1.LocalId, new List() { m_so2.LocalId }); - - m_so1.ScriptSetPhysicsStatus(true); - - Assert.That(m_so1.RootPart.Flags, Is.EqualTo(PrimFlags.Physics)); - Assert.That(m_so1.Parts[1].Flags, Is.EqualTo(PrimFlags.Physics)); - - m_so1.ScriptSetPhysicsStatus(false); - - Assert.That(m_so1.RootPart.Flags, Is.EqualTo(PrimFlags.None)); - Assert.That(m_so1.Parts[1].Flags, Is.EqualTo(PrimFlags.None)); - - m_so1.ScriptSetPhysicsStatus(true); - - Assert.That(m_so1.RootPart.Flags, Is.EqualTo(PrimFlags.Physics)); - Assert.That(m_so1.Parts[1].Flags, Is.EqualTo(PrimFlags.Physics)); - } - - /// - /// Test that linking results in the correct physical status for all linkees. - /// - [Test] - public void TestLinkPhysicsBothPhysical() - { - TestHelpers.InMethod(); - - m_scene.AddSceneObject(m_so1); - m_scene.AddSceneObject(m_so2); - - m_so1.ScriptSetPhysicsStatus(true); - m_so2.ScriptSetPhysicsStatus(true); - - m_scene.LinkObjects(m_ownerId, m_so1.LocalId, new List() { m_so2.LocalId }); - - Assert.That(m_so1.RootPart.Flags, Is.EqualTo(PrimFlags.Physics)); - Assert.That(m_so1.Parts[1].Flags, Is.EqualTo(PrimFlags.Physics)); - } - - /// - /// Test that linking results in the correct physical status for all linkees. - /// - [Test] - public void TestLinkPhysicsRootPhysicalOnly() - { - TestHelpers.InMethod(); - - m_scene.AddSceneObject(m_so1); - m_scene.AddSceneObject(m_so2); - - m_so1.ScriptSetPhysicsStatus(true); - - m_scene.LinkObjects(m_ownerId, m_so1.LocalId, new List() { m_so2.LocalId }); - - Assert.That(m_so1.RootPart.Flags, Is.EqualTo(PrimFlags.Physics)); - Assert.That(m_so1.Parts[1].Flags, Is.EqualTo(PrimFlags.Physics)); - } - - /// - /// Test that linking results in the correct physical status for all linkees. - /// - [Test] - public void TestLinkPhysicsChildPhysicalOnly() - { - TestHelpers.InMethod(); - - m_scene.AddSceneObject(m_so1); - m_scene.AddSceneObject(m_so2); - - m_so2.ScriptSetPhysicsStatus(true); - - m_scene.LinkObjects(m_ownerId, m_so1.LocalId, new List() { m_so2.LocalId }); - - Assert.That(m_so1.RootPart.Flags, Is.EqualTo(PrimFlags.None)); - Assert.That(m_so1.Parts[1].Flags, Is.EqualTo(PrimFlags.None)); - } - } -} \ No newline at end of file diff --git a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectUndoRedoTests.cs b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectUndoRedoTests.cs deleted file mode 100644 index 340da9cef3d..00000000000 --- a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectUndoRedoTests.cs +++ /dev/null @@ -1,184 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* undo has changed, this tests dont apply without large changes -using System; -using System.Reflection; -using NUnit.Framework; -using OpenMetaverse; -using OpenSim.Framework; -using OpenSim.Region.Framework.Scenes; -using OpenSim.Tests.Common; - -namespace OpenSim.Region.Framework.Scenes.Tests -{ - /// - /// Tests for undo/redo - /// - public class SceneObjectUndoRedoTests : OpenSimTestCase - { - [Test] - public void TestUndoRedoResizeSceneObject() - { - TestHelpers.InMethod(); -// TestHelpers.EnableLogging(); - - Vector3 firstSize = new Vector3(2, 3, 4); - Vector3 secondSize = new Vector3(5, 6, 7); - - Scene scene = new SceneHelpers().SetupScene(); - scene.MaxUndoCount = 20; - SceneObjectGroup g1 = SceneHelpers.AddSceneObject(scene); - - // TODO: It happens to be the case that we are not storing undo states for SOPs which are not yet in a SOG, - // which is the way that AddSceneObject() sets up the object (i.e. it creates the SOP first). However, - // this is somewhat by chance. Really, we shouldn't be storing undo states at all if the object is not - // in a scene. - Assert.That(g1.RootPart.UndoCount, Is.EqualTo(0)); - - g1.GroupResize(firstSize); - Assert.That(g1.RootPart.UndoCount, Is.EqualTo(1)); - - g1.GroupResize(secondSize); - Assert.That(g1.RootPart.UndoCount, Is.EqualTo(2)); - - g1.RootPart.Undo(); - Assert.That(g1.RootPart.UndoCount, Is.EqualTo(1)); - Assert.That(g1.GroupScale, Is.EqualTo(firstSize)); - - g1.RootPart.Redo(); - Assert.That(g1.RootPart.UndoCount, Is.EqualTo(2)); - Assert.That(g1.GroupScale, Is.EqualTo(secondSize)); - } - - [Test] - public void TestUndoLimit() - { - TestHelpers.InMethod(); - - Vector3 firstSize = new Vector3(2, 3, 4); - Vector3 secondSize = new Vector3(5, 6, 7); - Vector3 thirdSize = new Vector3(8, 9, 10); - Vector3 fourthSize = new Vector3(11, 12, 13); - - Scene scene = new SceneHelpers().SetupScene(); - scene.MaxUndoCount = 2; - SceneObjectGroup g1 = SceneHelpers.AddSceneObject(scene); - - g1.GroupResize(firstSize); - g1.GroupResize(secondSize); - g1.GroupResize(thirdSize); - g1.GroupResize(fourthSize); - - g1.RootPart.Undo(); - g1.RootPart.Undo(); - g1.RootPart.Undo(); - - Assert.That(g1.RootPart.UndoCount, Is.EqualTo(0)); - Assert.That(g1.GroupScale, Is.EqualTo(secondSize)); - } - - [Test] - public void TestNoUndoOnObjectsNotInScene() - { - TestHelpers.InMethod(); - - Vector3 firstSize = new Vector3(2, 3, 4); - Vector3 secondSize = new Vector3(5, 6, 7); -// Vector3 thirdSize = new Vector3(8, 9, 10); -// Vector3 fourthSize = new Vector3(11, 12, 13); - - Scene scene = new SceneHelpers().SetupScene(); - scene.MaxUndoCount = 20; - SceneObjectGroup g1 = SceneHelpers.CreateSceneObject(1, TestHelpers.ParseTail(0x1)); - - g1.GroupResize(firstSize); - g1.GroupResize(secondSize); - - Assert.That(g1.RootPart.UndoCount, Is.EqualTo(0)); - - g1.RootPart.Undo(); - - Assert.That(g1.GroupScale, Is.EqualTo(secondSize)); - } - - [Test] - public void TestUndoBeyondAvailable() - { - TestHelpers.InMethod(); - - Vector3 newSize = new Vector3(2, 3, 4); - - Scene scene = new SceneHelpers().SetupScene(); - scene.MaxUndoCount = 20; - SceneObjectGroup g1 = SceneHelpers.AddSceneObject(scene); - Vector3 originalSize = g1.GroupScale; - - g1.RootPart.Undo(); - - Assert.That(g1.RootPart.UndoCount, Is.EqualTo(0)); - Assert.That(g1.GroupScale, Is.EqualTo(originalSize)); - - g1.GroupResize(newSize); - Assert.That(g1.RootPart.UndoCount, Is.EqualTo(1)); - Assert.That(g1.GroupScale, Is.EqualTo(newSize)); - - g1.RootPart.Undo(); - g1.RootPart.Undo(); - - Assert.That(g1.RootPart.UndoCount, Is.EqualTo(0)); - Assert.That(g1.GroupScale, Is.EqualTo(originalSize)); - } - - [Test] - public void TestRedoBeyondAvailable() - { - TestHelpers.InMethod(); - - Vector3 newSize = new Vector3(2, 3, 4); - - Scene scene = new SceneHelpers().SetupScene(); - scene.MaxUndoCount = 20; - SceneObjectGroup g1 = SceneHelpers.AddSceneObject(scene); - Vector3 originalSize = g1.GroupScale; - - g1.RootPart.Redo(); - - Assert.That(g1.RootPart.UndoCount, Is.EqualTo(0)); - Assert.That(g1.GroupScale, Is.EqualTo(originalSize)); - - g1.GroupResize(newSize); - g1.RootPart.Undo(); - g1.RootPart.Redo(); - g1.RootPart.Redo(); - - Assert.That(g1.RootPart.UndoCount, Is.EqualTo(1)); - Assert.That(g1.GroupScale, Is.EqualTo(newSize)); - } - } -} -*/ \ No newline at end of file diff --git a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectUserGroupTests.cs b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectUserGroupTests.cs deleted file mode 100644 index 4ec69cd8fdf..00000000000 --- a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectUserGroupTests.cs +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections.Generic; -using System.Reflection; -using Nini.Config; -using NUnit.Framework; -using OpenMetaverse; -using OpenSim.Framework; -using OpenSim.Region.CoreModules.Avatar.InstantMessage; -using OpenSim.Region.CoreModules.World.Permissions; -using OpenSim.Region.Framework.Interfaces; -using OpenSim.Region.Framework.Scenes; -using OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups; -using OpenSim.Tests.Common; - -namespace OpenSim.Region.Framework.Scenes.Tests -{ - [TestFixture] - public class SceneObjectUserGroupTests - { - /// - /// Test share with group object functionality - /// - /// This test is not yet fully implemented - [Test] - public void TestShareWithGroup() - { - TestHelpers.InMethod(); -// log4net.Config.XmlConfigurator.Configure(); - - UUID userId = UUID.Parse("10000000-0000-0000-0000-000000000001"); - - TestScene scene = new SceneHelpers().SetupScene(); - IConfigSource configSource = new IniConfigSource(); - - IConfig startupConfig = configSource.AddConfig("Startup"); - startupConfig.Set("serverside_object_permissions", true); - - IConfig groupsConfig = configSource.AddConfig("Groups"); - groupsConfig.Set("Enabled", true); - groupsConfig.Set("Module", "GroupsModule"); - groupsConfig.Set("DebugEnabled", true); - - SceneHelpers.SetupSceneModules( - scene, configSource, new object[] - { new DefaultPermissionsModule(), - new GroupsModule(), - new MockGroupsServicesConnector() }); - - IClientAPI client = SceneHelpers.AddScenePresence(scene, userId).ControllingClient; - - IGroupsModule groupsModule = scene.RequestModuleInterface(); - - groupsModule.CreateGroup(client, "group1", "To boldly go", true, UUID.Zero, 5, true, true, true); - } - } -} diff --git a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAgentTests.cs b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAgentTests.cs deleted file mode 100644 index 0f386bc57cc..00000000000 --- a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAgentTests.cs +++ /dev/null @@ -1,291 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections.Generic; -using System.Reflection; -using System.Text; -using System.Threading; -using System.Timers; -using Timer = System.Timers.Timer; -using Nini.Config; -using NUnit.Framework; -using OpenMetaverse; -using OpenSim.Framework; -using OpenSim.Region.Framework.Scenes; -using OpenSim.Region.Framework.Interfaces; -using OpenSim.Region.ClientStack.Linden; -using OpenSim.Region.CoreModules.Framework.EntityTransfer; -using OpenSim.Region.CoreModules.World.Serialiser; -using OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation; -using OpenSim.Tests.Common; -using GridRegion = OpenSim.Services.Interfaces.GridRegion; -using OpenSim.Services.Interfaces; - -namespace OpenSim.Region.Framework.Scenes.Tests -{ - /// - /// Scene presence tests - /// - [TestFixture] - public class ScenePresenceAgentTests : OpenSimTestCase - { -// public Scene scene, scene2, scene3; -// public UUID agent1, agent2, agent3; -// public static Random random; -// public ulong region1, region2, region3; -// public AgentCircuitData acd1; -// public TestClient testclient; - -// [TestFixtureSetUp] -// public void Init() -// { -//// TestHelpers.InMethod(); -//// -//// SceneHelpers sh = new SceneHelpers(); -//// -//// scene = sh.SetupScene("Neighbour x", UUID.Random(), 1000, 1000); -//// scene2 = sh.SetupScene("Neighbour x+1", UUID.Random(), 1001, 1000); -//// scene3 = sh.SetupScene("Neighbour x-1", UUID.Random(), 999, 1000); -//// -//// ISharedRegionModule interregionComms = new LocalSimulationConnectorModule(); -//// interregionComms.Initialise(new IniConfigSource()); -//// interregionComms.PostInitialise(); -//// SceneHelpers.SetupSceneModules(scene, new IniConfigSource(), interregionComms); -//// SceneHelpers.SetupSceneModules(scene2, new IniConfigSource(), interregionComms); -//// SceneHelpers.SetupSceneModules(scene3, new IniConfigSource(), interregionComms); -// -//// agent1 = UUID.Random(); -//// agent2 = UUID.Random(); -//// agent3 = UUID.Random(); -// -//// region1 = scene.RegionInfo.RegionHandle; -//// region2 = scene2.RegionInfo.RegionHandle; -//// region3 = scene3.RegionInfo.RegionHandle; -// } - - [Test] - public void TestCreateRootScenePresence() - { - TestHelpers.InMethod(); -// TestHelpers.EnableLogging(); - - UUID spUuid = TestHelpers.ParseTail(0x1); - - TestScene scene = new SceneHelpers().SetupScene(); - SceneHelpers.AddScenePresence(scene, spUuid); - - Assert.That(scene.AuthenticateHandler.GetAgentCircuitData(spUuid), Is.Not.Null); - Assert.That(scene.AuthenticateHandler.GetAgentCircuits().Count, Is.EqualTo(1)); - - ScenePresence sp = scene.GetScenePresence(spUuid); - Assert.That(sp, Is.Not.Null); - Assert.That(sp.IsChildAgent, Is.False); - Assert.That(sp.UUID, Is.EqualTo(spUuid)); - - Assert.That(scene.GetScenePresences().Count, Is.EqualTo(1)); - } - - /// - /// Test that duplicate complete movement calls are ignored. - /// - /// - /// If duplicate calls are not ignored then there is a risk of race conditions or other unexpected effects. - /// - [Test] - public void TestDupeCompleteMovementCalls() - { - TestHelpers.InMethod(); -// TestHelpers.EnableLogging(); - - UUID spUuid = TestHelpers.ParseTail(0x1); - - TestScene scene = new SceneHelpers().SetupScene(); - - int makeRootAgentEvents = 0; - scene.EventManager.OnMakeRootAgent += spi => makeRootAgentEvents++; - - ScenePresence sp = SceneHelpers.AddScenePresence(scene, spUuid); - - Assert.That(makeRootAgentEvents, Is.EqualTo(1)); - - // Normally these would be invoked by a CompleteMovement message coming in to the UDP stack. But for - // convenience, here we will invoke it manually. - sp.CompleteMovement(sp.ControllingClient, true); - - Assert.That(makeRootAgentEvents, Is.EqualTo(1)); - - // Check rest of exepcted parameters. - Assert.That(scene.AuthenticateHandler.GetAgentCircuitData(spUuid), Is.Not.Null); - Assert.That(scene.AuthenticateHandler.GetAgentCircuits().Count, Is.EqualTo(1)); - - Assert.That(sp.IsChildAgent, Is.False); - Assert.That(sp.UUID, Is.EqualTo(spUuid)); - - Assert.That(scene.GetScenePresences().Count, Is.EqualTo(1)); - } - - [Test] - public void TestCreateDuplicateRootScenePresence() - { - TestHelpers.InMethod(); -// TestHelpers.EnableLogging(); - - UUID spUuid = TestHelpers.ParseTail(0x1); - - // The etm is only invoked by this test to check whether an agent is still in transit if there is a dupe - EntityTransferModule etm = new EntityTransferModule(); - - IConfigSource config = new IniConfigSource(); - IConfig modulesConfig = config.AddConfig("Modules"); - modulesConfig.Set("EntityTransferModule", etm.Name); - IConfig entityTransferConfig = config.AddConfig("EntityTransfer"); - - // In order to run a single threaded regression test we do not want the entity transfer module waiting - // for a callback from the destination scene before removing its avatar data. - entityTransferConfig.Set("wait_for_callback", false); - - TestScene scene = new SceneHelpers().SetupScene(); - SceneHelpers.SetupSceneModules(scene, config, etm); - SceneHelpers.AddScenePresence(scene, spUuid); - SceneHelpers.AddScenePresence(scene, spUuid); - - Assert.That(scene.AuthenticateHandler.GetAgentCircuitData(spUuid), Is.Not.Null); - Assert.That(scene.AuthenticateHandler.GetAgentCircuits().Count, Is.EqualTo(1)); - - ScenePresence sp = scene.GetScenePresence(spUuid); - Assert.That(sp, Is.Not.Null); - Assert.That(sp.IsChildAgent, Is.False); - Assert.That(sp.UUID, Is.EqualTo(spUuid)); - } - - [Test] - public void TestCloseClient() - { - TestHelpers.InMethod(); -// TestHelpers.EnableLogging(); - - TestScene scene = new SceneHelpers().SetupScene(); - ScenePresence sp = SceneHelpers.AddScenePresence(scene, TestHelpers.ParseTail(0x1)); - - scene.CloseAgent(sp.UUID, false); - - Assert.That(scene.GetScenePresence(sp.UUID), Is.Null); - Assert.That(scene.AuthenticateHandler.GetAgentCircuitData(sp.UUID), Is.Null); - Assert.That(scene.AuthenticateHandler.GetAgentCircuits().Count, Is.EqualTo(0)); - -// TestHelpers.DisableLogging(); - } - - [Test] - public void TestCreateChildScenePresence() - { - TestHelpers.InMethod(); -// log4net.Config.XmlConfigurator.Configure(); - - LocalSimulationConnectorModule lsc = new LocalSimulationConnectorModule(); - - IConfigSource configSource = new IniConfigSource(); - IConfig config = configSource.AddConfig("Modules"); - config.Set("SimulationServices", "LocalSimulationConnectorModule"); - - SceneHelpers sceneHelpers = new SceneHelpers(); - TestScene scene = sceneHelpers.SetupScene(); - SceneHelpers.SetupSceneModules(scene, configSource, lsc); - - UUID agentId = TestHelpers.ParseTail(0x01); - AgentCircuitData acd = SceneHelpers.GenerateAgentData(agentId); - acd.child = true; - - GridRegion region = scene.GridService.GetRegionByName(UUID.Zero, scene.RegionInfo.RegionName); - string reason; - - // *** This is the first stage, when a neighbouring region is told that a viewer is about to try and - // establish a child scene presence. We pass in the circuit code that the client has to connect with *** - // XXX: ViaLogin may not be correct here. - EntityTransferContext ctx = new EntityTransferContext(); - scene.SimulationService.CreateAgent(null, region, acd, (uint)TeleportFlags.ViaLogin, ctx, out reason); - - Assert.That(scene.AuthenticateHandler.GetAgentCircuitData(agentId), Is.Not.Null); - Assert.That(scene.AuthenticateHandler.GetAgentCircuits().Count, Is.EqualTo(1)); - - // There's no scene presence yet since only an agent circuit has been established. - Assert.That(scene.GetScenePresence(agentId), Is.Null); - - // *** This is the second stage, where the client established a child agent/scene presence using the - // circuit code given to the scene in stage 1 *** - TestClient client = new TestClient(acd, scene); - scene.AddNewAgent(client, PresenceType.User); - - Assert.That(scene.AuthenticateHandler.GetAgentCircuitData(agentId), Is.Not.Null); - Assert.That(scene.AuthenticateHandler.GetAgentCircuits().Count, Is.EqualTo(1)); - - ScenePresence sp = scene.GetScenePresence(agentId); - Assert.That(sp, Is.Not.Null); - Assert.That(sp.UUID, Is.EqualTo(agentId)); - Assert.That(sp.IsChildAgent, Is.True); - } - - /// - /// Test that if a root agent logs into a region, a child agent is also established in the neighbouring region - /// - /// - /// Please note that unlike the other tests here, this doesn't rely on anything set up in the instance fields. - /// INCOMPLETE - /// - [Test] - public void TestChildAgentEstablishedInNeighbour() - { - TestHelpers.InMethod(); -// log4net.Config.XmlConfigurator.Configure(); - -// UUID agent1Id = UUID.Parse("00000000-0000-0000-0000-000000000001"); - - TestScene myScene1 = new SceneHelpers().SetupScene("Neighbour y", UUID.Random(), 1000, 1000); - TestScene myScene2 = new SceneHelpers().SetupScene("Neighbour y + 1", UUID.Random(), 1001, 1000); - - IConfigSource configSource = new IniConfigSource(); - IConfig config = configSource.AddConfig("Startup"); - config.Set("serverside_object_permissions", true); - - EntityTransferModule etm = new EntityTransferModule(); - - EventQueueGetModule eqgm1 = new EventQueueGetModule(); - SceneHelpers.SetupSceneModules(myScene1, configSource, etm, eqgm1); - - EventQueueGetModule eqgm2 = new EventQueueGetModule(); - SceneHelpers.SetupSceneModules(myScene2, configSource, etm, eqgm2); - -// SceneHelpers.AddScenePresence(myScene1, agent1Id); -// ScenePresence childPresence = myScene2.GetScenePresence(agent1); -// -// // TODO: Need to do a fair amount of work to allow synchronous establishment of child agents -// Assert.That(childPresence, Is.Not.Null); -// Assert.That(childPresence.IsChildAgent, Is.True); - } - } -} diff --git a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAnimationTests.cs b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAnimationTests.cs deleted file mode 100644 index d650c4346d9..00000000000 --- a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAnimationTests.cs +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections.Generic; -using System.Reflection; -using System.Text; -using System.Threading; -using System.Timers; -using Nini.Config; -using NUnit.Framework; -using OpenMetaverse; -using OpenSim.Framework; -using OpenSim.Region.Framework.Scenes; -using OpenSim.Region.Framework.Interfaces; -using OpenSim.Region.CoreModules.Framework.EntityTransfer; -using OpenSim.Region.CoreModules.World.Serialiser; -using OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation; -using OpenSim.Region.PhysicsModules.SharedBase; -using OpenSim.Tests.Common; - -namespace OpenSim.Region.Framework.Scenes.Tests -{ - /// - /// Scene presence animation tests - /// - [TestFixture] - public class ScenePresenceAnimationTests : OpenSimTestCase - { - [Test] - public void TestFlyingAnimation() - { - TestHelpers.InMethod(); -// log4net.Config.XmlConfigurator.Configure(); - - TestScene scene = new SceneHelpers().SetupScene(); - ScenePresence sp = SceneHelpers.AddScenePresence(scene, TestHelpers.ParseTail(0x1)); - sp.Flying = true; - sp.Animator.UpdateMovementAnimations(); - - Assert.That(sp.Animator.CurrentMovementAnimation, Is.EqualTo("HOVER")); - } - } -} \ No newline at end of file diff --git a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAutopilotTests.cs b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAutopilotTests.cs deleted file mode 100644 index 60baaf2de1d..00000000000 --- a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAutopilotTests.cs +++ /dev/null @@ -1,131 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections.Generic; -using System.Reflection; -using log4net; -using Nini.Config; -using NUnit.Framework; -using OpenMetaverse; -using OpenSim.Framework; -using OpenSim.Region.Framework.Interfaces; -using OpenSim.Region.Framework.Scenes; -using OpenSim.Tests.Common; - -namespace OpenSim.Region.Framework.Scenes.Tests -{ - [TestFixture] - public class ScenePresenceAutopilotTests : OpenSimTestCase - { - private TestScene m_scene; - - [OneTimeSetUp] - public void FixtureInit() - { - // Don't allow tests to be bamboozled by asynchronous events. Execute everything on the same thread. - Util.FireAndForgetMethod = FireAndForgetMethod.None; - } - - [OneTimeTearDown] - public void TearDown() - { - // We must set this back afterwards, otherwise later tests will fail since they're expecting multiple - // threads. Possibly, later tests should be rewritten not to worry about such things. - Util.FireAndForgetMethod = Util.DefaultFireAndForgetMethod; - } - - [SetUp] - public void Init() - { - m_scene = new SceneHelpers().SetupScene(); - } - - [Test] - public void TestMove() - { - TestHelpers.InMethod(); -// log4net.Config.XmlConfigurator.Configure(); - - ScenePresence sp = SceneHelpers.AddScenePresence(m_scene, TestHelpers.ParseTail(0x1)); - - Vector3 startPos = sp.AbsolutePosition; -// Vector3 startPos = new Vector3(128, 128, 30); - - // For now, we'll make the scene presence fly to simplify this test, but this needs to change. - sp.Flying = true; - - m_scene.Update(1); - Assert.That(sp.AbsolutePosition, Is.EqualTo(startPos)); - - Vector3 targetPos = startPos + new Vector3(0, 10, 0); - sp.MoveToTarget(targetPos, false, false, false); - - Assert.That(sp.AbsolutePosition, Is.EqualTo(startPos)); - Assert.That( - sp.Rotation, new QuaternionToleranceConstraint(new Quaternion(0, 0, 0.7071068f, 0.7071068f), 0.000001)); - - m_scene.Update(1); - - // We should really check the exact figure. - Assert.That(sp.AbsolutePosition.X, Is.EqualTo(startPos.X)); - Assert.That(sp.AbsolutePosition.Y, Is.GreaterThan(startPos.Y)); - Assert.That(sp.AbsolutePosition.Z, Is.EqualTo(startPos.Z)); - Assert.That(sp.AbsolutePosition.Z, Is.LessThan(targetPos.X)); - - m_scene.Update(50); - - double distanceToTarget = Util.GetDistanceTo(sp.AbsolutePosition, targetPos); - Assert.That(distanceToTarget, Is.LessThan(1), "Avatar not within 1 unit of target position on first move"); - Assert.That(sp.AbsolutePosition, Is.EqualTo(targetPos)); - Assert.That(sp.AgentControlFlags, Is.EqualTo((uint)AgentManager.ControlFlags.NONE)); - - // Try a second movement - startPos = sp.AbsolutePosition; - targetPos = startPos + new Vector3(10, 0, 0); - sp.MoveToTarget(targetPos, false, false, false); - - Assert.That(sp.AbsolutePosition, Is.EqualTo(startPos)); - Assert.That( - sp.Rotation, new QuaternionToleranceConstraint(new Quaternion(0, 0, 0, 1), 0.000001)); - - m_scene.Update(1); - - // We should really check the exact figure. - Assert.That(sp.AbsolutePosition.X, Is.GreaterThan(startPos.X)); - Assert.That(sp.AbsolutePosition.X, Is.LessThan(targetPos.X)); - Assert.That(sp.AbsolutePosition.Y, Is.EqualTo(startPos.Y)); - Assert.That(sp.AbsolutePosition.Z, Is.EqualTo(startPos.Z)); - - m_scene.Update(50); - - distanceToTarget = Util.GetDistanceTo(sp.AbsolutePosition, targetPos); - Assert.That(distanceToTarget, Is.LessThan(1), "Avatar not within 1 unit of target position on second move"); - Assert.That(sp.AbsolutePosition, Is.EqualTo(targetPos)); - } - } -} \ No newline at end of file diff --git a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceCapabilityTests.cs b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceCapabilityTests.cs deleted file mode 100644 index aa2676768cd..00000000000 --- a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceCapabilityTests.cs +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections.Generic; -using System.Reflection; -using System.Text; -using System.Threading; -using System.Timers; -using Timer = System.Timers.Timer; -using Nini.Config; -using NUnit.Framework; -using OpenMetaverse; -using OpenSim.Framework; -using OpenSim.Framework.Servers; -using OpenSim.Framework.Servers.HttpServer; -using OpenSim.Region.ClientStack.Linden; -using OpenSim.Region.CoreModules.Framework; -using OpenSim.Region.CoreModules.Framework.EntityTransfer; -using OpenSim.Region.CoreModules.World.Serialiser; -using OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation; -using OpenSim.Region.Framework.Scenes; -using OpenSim.Region.Framework.Interfaces; -using OpenSim.Tests.Common; -using GridRegion = OpenSim.Services.Interfaces.GridRegion; - -namespace OpenSim.Region.Framework.Scenes.Tests -{ - [TestFixture] - public class ScenePresenceCapabilityTests : OpenSimTestCase - { - [Test] - public void TestChildAgentSingleRegionCapabilities() - { - TestHelpers.InMethod(); -// TestHelpers.EnableLogging(); - - UUID spUuid = TestHelpers.ParseTail(0x1); - - // XXX: This is not great since the use of statics will mean that this has to be manually cleaned up for - // any subsequent test. - // XXX: May replace with a mock IHttpServer later. - BaseHttpServer httpServer = new BaseHttpServer(99999); - MainServer.AddHttpServer(httpServer); - MainServer.Instance = httpServer; - - CapabilitiesModule capsMod = new CapabilitiesModule(); - TestScene scene = new SceneHelpers().SetupScene(); - SceneHelpers.SetupSceneModules(scene, capsMod); - - ScenePresence sp = SceneHelpers.AddChildScenePresence(scene, spUuid); - //Assert.That(capsMod.GetCapsForUser(spUuid), Is.Not.Null); - - // TODO: Need to add tests for other ICapabiltiesModule methods. - -// scene.IncomingCloseAgent(sp.UUID, false); -// //Assert.That(capsMod.GetCapsForUser(spUuid), Is.Null); - scene.CloseAgent(sp.UUID, false); -// Assert.That(capsMod.GetCapsForUser(spUuid), Is.Null); - - // TODO: Need to add tests for other ICapabiltiesModule methods. - } - } -} diff --git a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceCrossingTests.cs b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceCrossingTests.cs deleted file mode 100644 index 34e1a87ab4b..00000000000 --- a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceCrossingTests.cs +++ /dev/null @@ -1,247 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections.Generic; -using System.Reflection; -using Nini.Config; -using NUnit.Framework; -using OpenMetaverse; -using OpenSim.Framework; -using OpenSim.Framework.Servers; -using OpenSim.Region.Framework.Interfaces; -using OpenSim.Region.CoreModules.Framework; -using OpenSim.Region.CoreModules.Framework.EntityTransfer; -using OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation; -using OpenSim.Region.CoreModules.World.Permissions; -using OpenSim.Tests.Common; -using OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups; -using System.Threading; - -namespace OpenSim.Region.Framework.Scenes.Tests -{ - [TestFixture] - public class ScenePresenceCrossingTests : OpenSimTestCase - { - [OneTimeSetUp] - public void FixtureInit() - { - // Don't allow tests to be bamboozled by asynchronous events. Execute everything on the same thread. - Util.FireAndForgetMethod = FireAndForgetMethod.RegressionTest; - } - - [OneTimeTearDown] - public void TearDown() - { - // We must set this back afterwards, otherwise later tests will fail since they're expecting multiple - // threads. Possibly, later tests should be rewritten so none of them require async stuff (which regression - // tests really shouldn't). - Util.FireAndForgetMethod = Util.DefaultFireAndForgetMethod; - } - - [Test] - public void TestCrossOnSameSimulator() - { - TestHelpers.InMethod(); -// TestHelpers.EnableLogging(); - - UUID userId = TestHelpers.ParseTail(0x1); - -// TestEventQueueGetModule eqmA = new TestEventQueueGetModule(); - EntityTransferModule etmA = new EntityTransferModule(); - EntityTransferModule etmB = new EntityTransferModule(); - LocalSimulationConnectorModule lscm = new LocalSimulationConnectorModule(); - - IConfigSource config = new IniConfigSource(); - IConfig modulesConfig = config.AddConfig("Modules"); - modulesConfig.Set("EntityTransferModule", etmA.Name); - modulesConfig.Set("SimulationServices", lscm.Name); -// IConfig entityTransferConfig = config.AddConfig("EntityTransfer"); - - // In order to run a single threaded regression test we do not want the entity transfer module waiting - // for a callback from the destination scene before removing its avatar data. -// entityTransferConfig.Set("wait_for_callback", false); - - SceneHelpers sh = new SceneHelpers(); - TestScene sceneA = sh.SetupScene("sceneA", TestHelpers.ParseTail(0x100), 1000, 1000); - TestScene sceneB = sh.SetupScene("sceneB", TestHelpers.ParseTail(0x200), 1000, 999); - - SceneHelpers.SetupSceneModules(new Scene[] { sceneA, sceneB }, config, lscm); - SceneHelpers.SetupSceneModules(sceneA, config, new CapabilitiesModule(), etmA); -// SceneHelpers.SetupSceneModules(sceneA, config, new CapabilitiesModule(), etmA, eqmA); - SceneHelpers.SetupSceneModules(sceneB, config, new CapabilitiesModule(), etmB); - - AgentCircuitData acd = SceneHelpers.GenerateAgentData(userId); - TestClient tc = new TestClient(acd, sceneA); - List destinationTestClients = new List(); - EntityTransferHelpers.SetupInformClientOfNeighbourTriggersNeighbourClientCreate(tc, destinationTestClients); - - ScenePresence originalSp = SceneHelpers.AddScenePresence(sceneA, tc, acd); - originalSp.AbsolutePosition = new Vector3(128, 32, 10); - -// originalSp.Flying = true; - -// Console.WriteLine("First pos {0}", originalSp.AbsolutePosition); - -// eqmA.ClearEvents(); - - AgentUpdateArgs moveArgs = new AgentUpdateArgs(); - //moveArgs.BodyRotation = Quaternion.CreateFromEulers(Vector3.Zero); - moveArgs.BodyRotation = Quaternion.CreateFromEulers(new Vector3(0, 0, (float)-(Math.PI / 2))); - moveArgs.ControlFlags = (uint)(AgentManager.ControlFlags.AGENT_CONTROL_AT_POS | AgentManager.ControlFlags.AGENT_CONTROL_FAST_AT); - - originalSp.HandleAgentUpdate(originalSp.ControllingClient, moveArgs); - - sceneA.Update(1); - -// Console.WriteLine("Second pos {0}", originalSp.AbsolutePosition); - - // FIXME: This is a sufficient number of updates to for the presence to reach the northern border. - // But really we want to do this in a more robust way. - for (int i = 0; i < 100; i++) - { - sceneA.Update(1); -// Console.WriteLine("Pos {0}", originalSp.AbsolutePosition); - } - - // Need to sort processing of EnableSimulator message on adding scene presences before we can test eqm - // messages -// Dictionary> eqmEvents = eqmA.Events; -// -// Assert.That(eqmEvents.Count, Is.EqualTo(1)); -// Assert.That(eqmEvents.ContainsKey(originalSp.UUID), Is.True); -// -// List spEqmEvents = eqmEvents[originalSp.UUID]; -// -// Assert.That(spEqmEvents.Count, Is.EqualTo(1)); -// Assert.That(spEqmEvents[0].Name, Is.EqualTo("CrossRegion")); - - // sceneA should now only have a child agent - ScenePresence spAfterCrossSceneA = sceneA.GetScenePresence(originalSp.UUID); - Assert.That(spAfterCrossSceneA.IsChildAgent, Is.True); - - ScenePresence spAfterCrossSceneB = sceneB.GetScenePresence(originalSp.UUID); - - // Agent remains a child until the client triggers complete movement - Assert.That(spAfterCrossSceneB.IsChildAgent, Is.True); - - TestClient sceneBTc = ((TestClient)spAfterCrossSceneB.ControllingClient); - - int agentMovementCompleteReceived = 0; - sceneBTc.OnReceivedMoveAgentIntoRegion += (ri, pos, look) => agentMovementCompleteReceived++; - - sceneBTc.CompleteMovement(); - - Assert.That(agentMovementCompleteReceived, Is.EqualTo(1)); - Assert.That(spAfterCrossSceneB.IsChildAgent, Is.False); - } - - /// - /// Test a cross attempt where the user can see into the neighbour but does not have permission to become - /// root there. - /// - [Test] - public void TestCrossOnSameSimulatorNoRootDestPerm() - { - TestHelpers.InMethod(); -// TestHelpers.EnableLogging(); - - UUID userId = TestHelpers.ParseTail(0x1); - - EntityTransferModule etmA = new EntityTransferModule(); - EntityTransferModule etmB = new EntityTransferModule(); - LocalSimulationConnectorModule lscm = new LocalSimulationConnectorModule(); - - IConfigSource config = new IniConfigSource(); - IConfig modulesConfig = config.AddConfig("Modules"); - modulesConfig.Set("EntityTransferModule", etmA.Name); - modulesConfig.Set("SimulationServices", lscm.Name); - - SceneHelpers sh = new SceneHelpers(); - TestScene sceneA = sh.SetupScene("sceneA", TestHelpers.ParseTail(0x100), 1000, 1000); - TestScene sceneB = sh.SetupScene("sceneB", TestHelpers.ParseTail(0x200), 1000, 999); - - SceneHelpers.SetupSceneModules(new Scene[] { sceneA, sceneB }, config, lscm); - SceneHelpers.SetupSceneModules(sceneA, config, new CapabilitiesModule(), etmA); - - // We need to set up the permisions module on scene B so that our later use of agent limit to deny - // QueryAccess won't succeed anyway because administrators are always allowed in and the default - // IsAdministrator if no permissions module is present is true. - SceneHelpers.SetupSceneModules(sceneB, config, new CapabilitiesModule(), new DefaultPermissionsModule(), etmB); - - AgentCircuitData acd = SceneHelpers.GenerateAgentData(userId); - TestClient tc = new TestClient(acd, sceneA); - List destinationTestClients = new List(); - EntityTransferHelpers.SetupInformClientOfNeighbourTriggersNeighbourClientCreate(tc, destinationTestClients); - - // Make sure sceneB will not accept this avatar. - sceneB.RegionInfo.EstateSettings.PublicAccess = false; - - ScenePresence originalSp = SceneHelpers.AddScenePresence(sceneA, tc, acd); - originalSp.AbsolutePosition = new Vector3(128, 32, 10); - - AgentUpdateArgs moveArgs = new AgentUpdateArgs(); - //moveArgs.BodyRotation = Quaternion.CreateFromEulers(Vector3.Zero); - moveArgs.BodyRotation = Quaternion.CreateFromEulers(new Vector3(0, 0, (float)-(Math.PI / 2))); - moveArgs.ControlFlags = (uint)(AgentManager.ControlFlags.AGENT_CONTROL_AT_POS | AgentManager.ControlFlags.AGENT_CONTROL_FAST_AT); - - originalSp.HandleAgentUpdate(originalSp.ControllingClient, moveArgs); - - sceneA.Update(1); - -// Console.WriteLine("Second pos {0}", originalSp.AbsolutePosition); - - // FIXME: This is a sufficient number of updates to for the presence to reach the northern border. - // But really we want to do this in a more robust way. - for (int i = 0; i < 100; i++) - { - sceneA.Update(1); -// Console.WriteLine("Pos {0}", originalSp.AbsolutePosition); - } - - // sceneA agent should still be root - ScenePresence spAfterCrossSceneA = sceneA.GetScenePresence(originalSp.UUID); - Assert.That(spAfterCrossSceneA.IsChildAgent, Is.False); - - ScenePresence spAfterCrossSceneB = sceneB.GetScenePresence(originalSp.UUID); - - // sceneB agent should still be child - Assert.That(spAfterCrossSceneB.IsChildAgent, Is.True); - - // sceneB should ignore unauthorized attempt to upgrade agent to root - TestClient sceneBTc = ((TestClient)spAfterCrossSceneB.ControllingClient); - - int agentMovementCompleteReceived = 0; - sceneBTc.OnReceivedMoveAgentIntoRegion += (ri, pos, look) => agentMovementCompleteReceived++; - - sceneBTc.CompleteMovement(); - - Assert.That(agentMovementCompleteReceived, Is.EqualTo(0)); - Assert.That(spAfterCrossSceneB.IsChildAgent, Is.True); - } - } -} diff --git a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceSitTests.cs b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceSitTests.cs deleted file mode 100644 index e3ebf365133..00000000000 --- a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceSitTests.cs +++ /dev/null @@ -1,251 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections.Generic; -using System.Reflection; -using Nini.Config; -using NUnit.Framework; -using OpenMetaverse; -using OpenSim.Framework; -using OpenSim.Framework.Servers; -using OpenSim.Region.Framework.Interfaces; -using OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation; -using OpenSim.Tests.Common; -using System.Threading; - -namespace OpenSim.Region.Framework.Scenes.Tests -{ - [TestFixture] - public class ScenePresenceSitTests : OpenSimTestCase - { - private TestScene m_scene; - private ScenePresence m_sp; - - [SetUp] - public void Init() - { - m_scene = new SceneHelpers().SetupScene(); - m_sp = SceneHelpers.AddScenePresence(m_scene, TestHelpers.ParseTail(0x1)); - } - - [Test] - public void TestSitOutsideRangeNoTarget() - { - TestHelpers.InMethod(); -// log4net.Config.XmlConfigurator.Configure(); - - // More than 10 meters away from 0, 0, 0 (default part position) - Vector3 startPos = new Vector3(10.1f, 0, 0); - m_sp.AbsolutePosition = startPos; - - SceneObjectPart part = SceneHelpers.AddSceneObject(m_scene).RootPart; - - m_sp.HandleAgentRequestSit(m_sp.ControllingClient, m_sp.UUID, part.UUID, Vector3.Zero); - - Assert.That(part.SitTargetAvatar, Is.EqualTo(UUID.Zero)); - Assert.That(part.GetSittingAvatarsCount(), Is.EqualTo(0)); - Assert.That(part.GetSittingAvatars(), Is.Null); - Assert.That(m_sp.ParentID, Is.EqualTo(0)); - Assert.AreEqual(startPos, m_sp.AbsolutePosition); - } - - [Test] - public void TestSitWithinRangeNoTarget() - { - TestHelpers.InMethod(); -// log4net.Config.XmlConfigurator.Configure(); - - // Less than 10 meters away from 0, 0, 0 (default part position) - Vector3 startPos = new Vector3(9.9f, 0, 0); - m_sp.AbsolutePosition = startPos; - - SceneObjectPart part = SceneHelpers.AddSceneObject(m_scene).RootPart; - - // We need to preserve this here because phys actor is removed by the sit. - Vector3 spPhysActorSize = m_sp.PhysicsActor.Size; - m_sp.HandleAgentRequestSit(m_sp.ControllingClient, m_sp.UUID, part.UUID, Vector3.Zero); - - Assert.That(m_sp.PhysicsActor, Is.Null); - - Assert.That( - m_sp.AbsolutePosition, - Is.EqualTo(part.AbsolutePosition + new Vector3(0, 0, spPhysActorSize.Z / 2))); - - Assert.That(part.SitTargetAvatar, Is.EqualTo(UUID.Zero)); - Assert.That(part.GetSittingAvatarsCount(), Is.EqualTo(1)); - HashSet sittingAvatars = part.GetSittingAvatars(); - Assert.That(sittingAvatars.Count, Is.EqualTo(1)); - Assert.That(sittingAvatars.Contains(m_sp)); - Assert.That(m_sp.ParentID, Is.EqualTo(part.LocalId)); - } - - [Test] - public void TestSitAndStandWithNoSitTarget() - { - TestHelpers.InMethod(); -// log4net.Config.XmlConfigurator.Configure(); - - // Make sure we're within range to sit - Vector3 startPos = new Vector3(1, 1, 1); - m_sp.AbsolutePosition = startPos; - - SceneObjectPart part = SceneHelpers.AddSceneObject(m_scene).RootPart; - - // We need to preserve this here because phys actor is removed by the sit. - Vector3 spPhysActorSize = m_sp.PhysicsActor.Size; - m_sp.HandleAgentRequestSit(m_sp.ControllingClient, m_sp.UUID, part.UUID, Vector3.Zero); - - Assert.That( - m_sp.AbsolutePosition, - Is.EqualTo(part.AbsolutePosition + new Vector3(0, 0, spPhysActorSize.Z / 2))); - - m_sp.StandUp(); - - Assert.That(part.SitTargetAvatar, Is.EqualTo(UUID.Zero)); - Assert.That(part.GetSittingAvatarsCount(), Is.EqualTo(0)); - Assert.That(part.GetSittingAvatars(), Is.Null); - Assert.That(m_sp.ParentID, Is.EqualTo(0)); - Assert.That(m_sp.PhysicsActor, Is.Not.Null); - } - - [Test] - public void TestSitAndStandWithNoSitTargetChildPrim() - { - TestHelpers.InMethod(); -// log4net.Config.XmlConfigurator.Configure(); - - // Make sure we're within range to sit - Vector3 startPos = new Vector3(1, 1, 1); - m_sp.AbsolutePosition = startPos; - - SceneObjectPart part = SceneHelpers.AddSceneObject(m_scene, 2, m_sp.UUID, "part", 0x10).Parts[1]; - part.OffsetPosition = new Vector3(2, 3, 4); - - // We need to preserve this here because phys actor is removed by the sit. - Vector3 spPhysActorSize = m_sp.PhysicsActor.Size; - m_sp.HandleAgentRequestSit(m_sp.ControllingClient, m_sp.UUID, part.UUID, Vector3.Zero); - - Assert.That( - m_sp.AbsolutePosition, - Is.EqualTo(part.AbsolutePosition + new Vector3(0, 0, spPhysActorSize.Z / 2))); - - m_sp.StandUp(); - - Assert.That(part.SitTargetAvatar, Is.EqualTo(UUID.Zero)); - Assert.That(part.GetSittingAvatarsCount(), Is.EqualTo(0)); - Assert.That(part.GetSittingAvatars(), Is.Null); - Assert.That(m_sp.ParentID, Is.EqualTo(0)); - Assert.That(m_sp.PhysicsActor, Is.Not.Null); - } - - [Test] - public void TestSitAndStandWithSitTarget() - { -/* sit position math as changed, this needs to be fixed later - TestHelpers.InMethod(); -// log4net.Config.XmlConfigurator.Configure(); - - // If a prim has a sit target then we can sit from any distance away - Vector3 startPos = new Vector3(128, 128, 30); - m_sp.AbsolutePosition = startPos; - - SceneObjectPart part = SceneHelpers.AddSceneObject(m_scene).RootPart; - part.SitTargetPosition = new Vector3(0, 0, 1); - - m_sp.HandleAgentRequestSit(m_sp.ControllingClient, m_sp.UUID, part.UUID, Vector3.Zero); - - Assert.That(part.SitTargetAvatar, Is.EqualTo(m_sp.UUID)); - Assert.That(m_sp.ParentID, Is.EqualTo(part.LocalId)); - - // This section is copied from ScenePresence.HandleAgentSit(). Correctness is not guaranteed. - double x, y, z, m1, m2; - - Quaternion r = part.SitTargetOrientation;; - m1 = r.X * r.X + r.Y * r.Y; - m2 = r.Z * r.Z + r.W * r.W; - - // Rotate the vector <0, 0, 1> - x = 2 * (r.X * r.Z + r.Y * r.W); - y = 2 * (-r.X * r.W + r.Y * r.Z); - z = m2 - m1; - - // Set m to be the square of the norm of r. - double m = m1 + m2; - - // This constant is emperically determined to be what is used in SL. - // See also http://opensimulator.org/mantis/view.php?id=7096 - double offset = 0.05; - - Vector3 up = new Vector3((float)x, (float)y, (float)z); - Vector3 sitOffset = up * (float)offset; - // End of copied section. - - Assert.That( - m_sp.AbsolutePosition, - Is.EqualTo(part.AbsolutePosition + part.SitTargetPosition - sitOffset + ScenePresence.SIT_TARGET_ADJUSTMENT)); - Assert.That(m_sp.PhysicsActor, Is.Null); - - Assert.That(part.GetSittingAvatarsCount(), Is.EqualTo(1)); - HashSet sittingAvatars = part.GetSittingAvatars(); - Assert.That(sittingAvatars.Count, Is.EqualTo(1)); - Assert.That(sittingAvatars.Contains(m_sp)); - - m_sp.StandUp(); - - Assert.That(part.SitTargetAvatar, Is.EqualTo(UUID.Zero)); - Assert.That(m_sp.ParentID, Is.EqualTo(0)); - Assert.That(m_sp.PhysicsActor, Is.Not.Null); - - Assert.That(part.SitTargetAvatar, Is.EqualTo(UUID.Zero)); - Assert.That(part.GetSittingAvatarsCount(), Is.EqualTo(0)); - Assert.That(part.GetSittingAvatars(), Is.Null); -*/ - } - - [Test] - public void TestSitAndStandOnGround() - { - TestHelpers.InMethod(); -// log4net.Config.XmlConfigurator.Configure(); - - // If a prim has a sit target then we can sit from any distance away -// Vector3 startPos = new Vector3(128, 128, 30); -// sp.AbsolutePosition = startPos; - - m_sp.HandleAgentSitOnGround(); - - Assert.That(m_sp.SitGround, Is.True); - Assert.That(m_sp.PhysicsActor, Is.Null); - - m_sp.StandUp(); - - Assert.That(m_sp.SitGround, Is.False); - Assert.That(m_sp.PhysicsActor, Is.Not.Null); - } - } -} diff --git a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceTeleportTests.cs b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceTeleportTests.cs deleted file mode 100644 index 4236094ab7e..00000000000 --- a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceTeleportTests.cs +++ /dev/null @@ -1,694 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections.Generic; -using System.IO; -using System.Net; -using System.Text; -using System.Threading; -using Nini.Config; -using NUnit.Framework; -using OpenMetaverse; -using OpenSim.Framework; -using OpenSim.Framework.Servers; -using OpenSim.Region.Framework.Interfaces; -using OpenSim.Region.CoreModules.Framework; -using OpenSim.Region.CoreModules.Framework.EntityTransfer; -using OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation; -using OpenSim.Region.CoreModules.World.Permissions; -using OpenSim.Tests.Common; - -namespace OpenSim.Region.Framework.Scenes.Tests -{ - /// - /// Teleport tests in a standalone OpenSim - /// - [TestFixture] - public class ScenePresenceTeleportTests : OpenSimTestCase - { - [OneTimeSetUp] - public void FixtureInit() - { - // Don't allow tests to be bamboozled by asynchronous events. Execute everything on the same thread. - Util.FireAndForgetMethod = FireAndForgetMethod.RegressionTest; - } - - [OneTimeTearDown] - public void TearDown() - { - // We must set this back afterwards, otherwise later tests will fail since they're expecting multiple - // threads. Possibly, later tests should be rewritten so none of them require async stuff (which regression - // tests really shouldn't). - Util.FireAndForgetMethod = Util.DefaultFireAndForgetMethod; - } - - [Test] - public void TestSameRegion() - { - TestHelpers.InMethod(); -// log4net.Config.XmlConfigurator.Configure(); - - EntityTransferModule etm = new EntityTransferModule(); - - IConfigSource config = new IniConfigSource(); - config.AddConfig("Modules"); - // Not strictly necessary since FriendsModule assumes it is the default (!) - config.Configs["Modules"].Set("EntityTransferModule", etm.Name); - - TestScene scene = new SceneHelpers().SetupScene("sceneA", TestHelpers.ParseTail(0x100), 1000, 1000); - SceneHelpers.SetupSceneModules(scene, config, etm); - - Vector3 teleportPosition = new Vector3(10, 11, 12); - Vector3 teleportLookAt = new Vector3(20, 21, 22); - - ScenePresence sp = SceneHelpers.AddScenePresence(scene, TestHelpers.ParseTail(0x1)); - sp.AbsolutePosition = new Vector3(30, 31, 32); - scene.RequestTeleportLocation( - sp.ControllingClient, - scene.RegionInfo.RegionHandle, - teleportPosition, - teleportLookAt, - (uint)TeleportFlags.ViaLocation); - - Assert.That(sp.AbsolutePosition, Is.EqualTo(teleportPosition)); - - Assert.That(scene.GetRootAgentCount(), Is.EqualTo(1)); - Assert.That(scene.GetChildAgentCount(), Is.EqualTo(0)); - - // Lookat is sent to the client only - sp.Lookat does not yield the same thing (calculation from camera - // position instead). -// Assert.That(sp.Lookat, Is.EqualTo(teleportLookAt)); - } - -/* - [Test] - public void TestSameSimulatorIsolatedRegionsV1() - { - TestHelpers.InMethod(); -// TestHelpers.EnableLogging(); - - UUID userId = TestHelpers.ParseTail(0x1); - - EntityTransferModule etmA = new EntityTransferModule(); - EntityTransferModule etmB = new EntityTransferModule(); - LocalSimulationConnectorModule lscm = new LocalSimulationConnectorModule(); - - IConfigSource config = new IniConfigSource(); - IConfig modulesConfig = config.AddConfig("Modules"); - modulesConfig.Set("EntityTransferModule", etmA.Name); - modulesConfig.Set("SimulationServices", lscm.Name); - IConfig entityTransferConfig = config.AddConfig("EntityTransfer"); - - // In order to run a single threaded regression test we do not want the entity transfer module waiting - // for a callback from the destination scene before removing its avatar data. - entityTransferConfig.Set("wait_for_callback", false); - - SceneHelpers sh = new SceneHelpers(); - TestScene sceneA = sh.SetupScene("sceneA", TestHelpers.ParseTail(0x100), 1000, 1000); - TestScene sceneB = sh.SetupScene("sceneB", TestHelpers.ParseTail(0x200), 1002, 1000); - - SceneHelpers.SetupSceneModules(sceneA, config, etmA); - SceneHelpers.SetupSceneModules(sceneB, config, etmB); - SceneHelpers.SetupSceneModules(new Scene[] { sceneA, sceneB }, config, lscm); - - // FIXME: Hack - this is here temporarily to revert back to older entity transfer behaviour - lscm.ServiceVersion = 0.1f; - - Vector3 teleportPosition = new Vector3(10, 11, 12); - Vector3 teleportLookAt = new Vector3(20, 21, 22); - - ScenePresence sp = SceneHelpers.AddScenePresence(sceneA, userId); - sp.AbsolutePosition = new Vector3(30, 31, 32); - - List destinationTestClients = new List(); - EntityTransferHelpers.SetupInformClientOfNeighbourTriggersNeighbourClientCreate( - (TestClient)sp.ControllingClient, destinationTestClients); - - sceneA.RequestTeleportLocation( - sp.ControllingClient, - sceneB.RegionInfo.RegionHandle, - teleportPosition, - teleportLookAt, - (uint)TeleportFlags.ViaLocation); - - // SetupInformClientOfNeighbour() will have handled the callback into the target scene to setup the child - // agent. This call will now complete the movement of the user into the destination and upgrade the agent - // from child to root. - destinationTestClients[0].CompleteMovement(); - - Assert.That(sceneA.GetScenePresence(userId), Is.Null); - - ScenePresence sceneBSp = sceneB.GetScenePresence(userId); - Assert.That(sceneBSp, Is.Not.Null); - Assert.That(sceneBSp.Scene.RegionInfo.RegionName, Is.EqualTo(sceneB.RegionInfo.RegionName)); - Assert.That(sceneBSp.AbsolutePosition, Is.EqualTo(teleportPosition)); - - Assert.That(sceneA.GetRootAgentCount(), Is.EqualTo(0)); - Assert.That(sceneA.GetChildAgentCount(), Is.EqualTo(0)); - Assert.That(sceneB.GetRootAgentCount(), Is.EqualTo(1)); - Assert.That(sceneB.GetChildAgentCount(), Is.EqualTo(0)); - - // TODO: Add assertions to check correct circuit details in both scenes. - - // Lookat is sent to the client only - sp.Lookat does not yield the same thing (calculation from camera - // position instead). -// Assert.That(sp.Lookat, Is.EqualTo(teleportLookAt)); - } -*/ - - [Test] - public void TestSameSimulatorIsolatedRegionsV2() - { - TestHelpers.InMethod(); -// TestHelpers.EnableLogging(); - - UUID userId = TestHelpers.ParseTail(0x1); - - EntityTransferModule etmA = new EntityTransferModule(); - EntityTransferModule etmB = new EntityTransferModule(); - LocalSimulationConnectorModule lscm = new LocalSimulationConnectorModule(); - - IConfigSource config = new IniConfigSource(); - IConfig modulesConfig = config.AddConfig("Modules"); - modulesConfig.Set("EntityTransferModule", etmA.Name); - modulesConfig.Set("SimulationServices", lscm.Name); - - SceneHelpers sh = new SceneHelpers(); - TestScene sceneA = sh.SetupScene("sceneA", TestHelpers.ParseTail(0x100), 1000, 1000); - TestScene sceneB = sh.SetupScene("sceneB", TestHelpers.ParseTail(0x200), 1002, 1000); - - SceneHelpers.SetupSceneModules(sceneA, config, etmA); - SceneHelpers.SetupSceneModules(sceneB, config, etmB); - SceneHelpers.SetupSceneModules(new Scene[] { sceneA, sceneB }, config, lscm); - - Vector3 teleportPosition = new Vector3(10, 11, 12); - Vector3 teleportLookAt = new Vector3(20, 21, 22); - - ScenePresence sp = SceneHelpers.AddScenePresence(sceneA, userId); - sp.AbsolutePosition = new Vector3(30, 31, 32); - - sceneA.Update(4); - sceneB.Update(4); - - List destinationTestClients = new List(); - EntityTransferHelpers.SetupSendRegionTeleportTriggersDestinationClientCreateAndCompleteMovement( - (TestClient)sp.ControllingClient, destinationTestClients); - - sceneA.RequestTeleportLocation( - sp.ControllingClient, - sceneB.RegionInfo.RegionHandle, - teleportPosition, - teleportLookAt, - (uint)TeleportFlags.ViaLocation); - - // Assert.That(sceneA.GetScenePresence(userId), Is.Null); - sceneA.Update(4); - sceneB.Update(4); - - ScenePresence sceneBSp = sceneB.GetScenePresence(userId); - Assert.That(sceneBSp, Is.Not.Null); - Assert.That(sceneBSp.Scene.RegionInfo.RegionName, Is.EqualTo(sceneB.RegionInfo.RegionName)); - Assert.That(sceneBSp.AbsolutePosition.X, Is.EqualTo(teleportPosition.X)); - Assert.That(sceneBSp.AbsolutePosition.Y, Is.EqualTo(teleportPosition.Y)); - - //Assert.That(sceneA.GetRootAgentCount(), Is.EqualTo(0)); - //Assert.That(sceneA.GetChildAgentCount(), Is.EqualTo(0)); - //Assert.That(sceneB.GetRootAgentCount(), Is.EqualTo(1)); - //Assert.That(sceneB.GetChildAgentCount(), Is.EqualTo(0)); - - // TODO: Add assertions to check correct circuit details in both scenes. - - // Lookat is sent to the client only - sp.Lookat does not yield the same thing (calculation from camera - // position instead). - // Assert.That(sp.Lookat, Is.EqualTo(teleportLookAt)); - } - - /// - /// Test teleport procedures when the target simulator returns false when queried about access. - /// - [Test] - public void TestSameSimulatorIsolatedRegions_DeniedOnQueryAccess() - { - TestHelpers.InMethod(); -// TestHelpers.EnableLogging(); - - UUID userId = TestHelpers.ParseTail(0x1); - Vector3 preTeleportPosition = new Vector3(30, 31, 32); - - EntityTransferModule etmA = new EntityTransferModule(); - EntityTransferModule etmB = new EntityTransferModule(); - - LocalSimulationConnectorModule lscm = new LocalSimulationConnectorModule(); - - IConfigSource config = new IniConfigSource(); - config.AddConfig("Modules"); - config.Configs["Modules"].Set("EntityTransferModule", etmA.Name); - config.Configs["Modules"].Set("SimulationServices", lscm.Name); - - config.AddConfig("EntityTransfer"); - - // In order to run a single threaded regression test we do not want the entity transfer module waiting - // for a callback from the destination scene before removing its avatar data. - config.Configs["EntityTransfer"].Set("wait_for_callback", false); - - config.AddConfig("Startup"); - config.Configs["Startup"].Set("serverside_object_permissions", true); - - SceneHelpers sh = new SceneHelpers(); - TestScene sceneA = sh.SetupScene("sceneA", TestHelpers.ParseTail(0x100), 1000, 1000); - TestScene sceneB = sh.SetupScene("sceneB", TestHelpers.ParseTail(0x200), 1002, 1000); - - SceneHelpers.SetupSceneModules(sceneA, config, etmA ); - - // We need to set up the permisions module on scene B so that our later use of agent limit to deny - // QueryAccess won't succeed anyway because administrators are always allowed in and the default - // IsAdministrator if no permissions module is present is true. - SceneHelpers.SetupSceneModules(sceneB, config, new object[] { new DefaultPermissionsModule(), etmB }); - - // Shared scene modules - SceneHelpers.SetupSceneModules(new Scene[] { sceneA, sceneB }, config, lscm); - - Vector3 teleportPosition = new Vector3(10, 11, 12); - Vector3 teleportLookAt = new Vector3(20, 21, 22); - - ScenePresence sp = SceneHelpers.AddScenePresence(sceneA, userId); - sp.AbsolutePosition = preTeleportPosition; - - // Make sceneB return false on query access - sceneB.RegionInfo.RegionSettings.AgentLimit = 0; - - sceneA.RequestTeleportLocation( - sp.ControllingClient, - sceneB.RegionInfo.RegionHandle, - teleportPosition, - teleportLookAt, - (uint)TeleportFlags.ViaLocation); - -// ((TestClient)sp.ControllingClient).CompleteTeleportClientSide(); - - Assert.That(sceneB.GetScenePresence(userId), Is.Null); - - ScenePresence sceneASp = sceneA.GetScenePresence(userId); - Assert.That(sceneASp, Is.Not.Null); - Assert.That(sceneASp.Scene.RegionInfo.RegionName, Is.EqualTo(sceneA.RegionInfo.RegionName)); - Assert.That(sceneASp.AbsolutePosition.X, Is.EqualTo(preTeleportPosition.X)); - Assert.That(sceneASp.AbsolutePosition.Y, Is.EqualTo(preTeleportPosition.Y)); - - Assert.That(sceneA.GetRootAgentCount(), Is.EqualTo(1)); - Assert.That(sceneA.GetChildAgentCount(), Is.EqualTo(0)); - Assert.That(sceneB.GetRootAgentCount(), Is.EqualTo(0)); - Assert.That(sceneB.GetChildAgentCount(), Is.EqualTo(0)); - - // TODO: Add assertions to check correct circuit details in both scenes. - - // Lookat is sent to the client only - sp.Lookat does not yield the same thing (calculation from camera - // position instead). -// Assert.That(sp.Lookat, Is.EqualTo(teleportLookAt)); - -// TestHelpers.DisableLogging(); - } - - /// - /// Test teleport procedures when the target simulator create agent step is refused. - /// - [Test] - public void TestSameSimulatorIsolatedRegions_DeniedOnCreateAgent() - { - TestHelpers.InMethod(); -// TestHelpers.EnableLogging(); - - UUID userId = TestHelpers.ParseTail(0x1); - Vector3 preTeleportPosition = new Vector3(30, 31, 32); - - EntityTransferModule etmA = new EntityTransferModule(); - EntityTransferModule etmB = new EntityTransferModule(); - LocalSimulationConnectorModule lscm = new LocalSimulationConnectorModule(); - - IConfigSource config = new IniConfigSource(); - config.AddConfig("Modules"); - config.Configs["Modules"].Set("EntityTransferModule", etmA.Name); - config.Configs["Modules"].Set("SimulationServices", lscm.Name); - - config.AddConfig("EntityTransfer"); - - // In order to run a single threaded regression test we do not want the entity transfer module waiting - // for a callback from the destination scene before removing its avatar data. - config.Configs["EntityTransfer"].Set("wait_for_callback", false); - - SceneHelpers sh = new SceneHelpers(); - TestScene sceneA = sh.SetupScene("sceneA", TestHelpers.ParseTail(0x100), 1000, 1000); - TestScene sceneB = sh.SetupScene("sceneB", TestHelpers.ParseTail(0x200), 1002, 1000); - - SceneHelpers.SetupSceneModules(sceneA, config, etmA); - SceneHelpers.SetupSceneModules(sceneB, config, etmB); - - // Shared scene modules - SceneHelpers.SetupSceneModules(new Scene[] { sceneA, sceneB }, config, lscm); - - Vector3 teleportPosition = new Vector3(10, 11, 12); - Vector3 teleportLookAt = new Vector3(20, 21, 22); - - ScenePresence sp = SceneHelpers.AddScenePresence(sceneA, userId); - sp.AbsolutePosition = preTeleportPosition; - - sceneA.Update(4); - sceneB.Update(4); - - // Make sceneB refuse CreateAgent - sceneB.LoginsEnabled = false; - - sceneA.RequestTeleportLocation( - sp.ControllingClient, - sceneB.RegionInfo.RegionHandle, - teleportPosition, - teleportLookAt, - (uint)TeleportFlags.ViaLocation); - - // ((TestClient)sp.ControllingClient).CompleteTeleportClientSide(); - - sceneA.Update(4); - sceneB.Update(4); - - Assert.That(sceneB.GetScenePresence(userId), Is.Null); - - ScenePresence sceneASp = sceneA.GetScenePresence(userId); - Assert.That(sceneASp, Is.Not.Null); - Assert.That(sceneASp.Scene.RegionInfo.RegionName, Is.EqualTo(sceneA.RegionInfo.RegionName)); - Assert.That(sceneASp.AbsolutePosition.X, Is.EqualTo(preTeleportPosition.X)); - Assert.That(sceneASp.AbsolutePosition.Y, Is.EqualTo(preTeleportPosition.Y)); - - Assert.That(sceneA.GetRootAgentCount(), Is.EqualTo(1)); - Assert.That(sceneA.GetChildAgentCount(), Is.EqualTo(0)); - Assert.That(sceneB.GetRootAgentCount(), Is.EqualTo(0)); - Assert.That(sceneB.GetChildAgentCount(), Is.EqualTo(0)); - - // TODO: Add assertions to check correct circuit details in both scenes. - - // Lookat is sent to the client only - sp.Lookat does not yield the same thing (calculation from camera - // position instead). -// Assert.That(sp.Lookat, Is.EqualTo(teleportLookAt)); - -// TestHelpers.DisableLogging(); - } - - /// - /// Test teleport when the destination region does not process (or does not receive) the connection attempt - /// from the viewer. - /// - /// - /// This could be quite a common case where the source region can connect to a remove destination region - /// (for CreateAgent) but the viewer cannot reach the destination region due to network issues. - /// - [Test] - public void TestSameSimulatorIsolatedRegions_DestinationDidNotProcessViewerConnection() - { - TestHelpers.InMethod(); -// TestHelpers.EnableLogging(); - - UUID userId = TestHelpers.ParseTail(0x1); - Vector3 preTeleportPosition = new Vector3(30, 31, 32); - - EntityTransferModule etmA = new EntityTransferModule(); - EntityTransferModule etmB = new EntityTransferModule(); - - LocalSimulationConnectorModule lscm = new LocalSimulationConnectorModule(); - - IConfigSource config = new IniConfigSource(); - config.AddConfig("Modules"); - config.Configs["Modules"].Set("EntityTransferModule", etmA.Name); - config.Configs["Modules"].Set("SimulationServices", lscm.Name); - - config.AddConfig("EntityTransfer"); - - // In order to run a single threaded regression test we do not want the entity transfer module waiting - // for a callback from the destination scene before removing its avatar data. - config.Configs["EntityTransfer"].Set("wait_for_callback", false); - -// config.AddConfig("Startup"); -// config.Configs["Startup"].Set("serverside_object_permissions", true); - - SceneHelpers sh = new SceneHelpers(); - TestScene sceneA = sh.SetupScene("sceneA", TestHelpers.ParseTail(0x100), 1000, 1000); - TestScene sceneB = sh.SetupScene("sceneB", TestHelpers.ParseTail(0x200), 1002, 1000); - - SceneHelpers.SetupSceneModules(sceneA, config, etmA ); - - // We need to set up the permisions module on scene B so that our later use of agent limit to deny - // QueryAccess won't succeed anyway because administrators are always allowed in and the default - // IsAdministrator if no permissions module is present is true. - SceneHelpers.SetupSceneModules(sceneB, config, new object[] { new DefaultPermissionsModule(), etmB }); - - // Shared scene modules - SceneHelpers.SetupSceneModules(new Scene[] { sceneA, sceneB }, config, lscm); - - Vector3 teleportPosition = new Vector3(10, 11, 12); - Vector3 teleportLookAt = new Vector3(20, 21, 22); - - ScenePresence sp = SceneHelpers.AddScenePresence(sceneA, userId); - sp.AbsolutePosition = preTeleportPosition; - - sceneA.Update(4); - sceneB.Update(4); - - sceneA.RequestTeleportLocation( - sp.ControllingClient, - sceneB.RegionInfo.RegionHandle, - teleportPosition, - teleportLookAt, - (uint)TeleportFlags.ViaLocation); - - // FIXME: Not setting up InformClientOfNeighbour on the TestClient means that it does not initiate - // communication with the destination region. But this is a very non-obvious way of doing it - really we - // should be forced to expicitly set this up. - sceneA.Update(4); - sceneB.Update(4); - - Assert.That(sceneB.GetScenePresence(userId), Is.Null); - - ScenePresence sceneASp = sceneA.GetScenePresence(userId); - Assert.That(sceneASp, Is.Not.Null); - Assert.That(sceneASp.Scene.RegionInfo.RegionName, Is.EqualTo(sceneA.RegionInfo.RegionName)); - Assert.That(sceneASp.AbsolutePosition.X, Is.EqualTo(preTeleportPosition.X)); - Assert.That(sceneASp.AbsolutePosition.Y, Is.EqualTo(preTeleportPosition.Y)); - - sceneA.SceneGraph.RecalculateStats(); - sceneB.SceneGraph.RecalculateStats(); - Assert.That(sceneA.GetRootAgentCount(), Is.EqualTo(1)); - Assert.That(sceneA.GetChildAgentCount(), Is.EqualTo(0)); - Assert.That(sceneB.GetRootAgentCount(), Is.EqualTo(0)); - Assert.That(sceneB.GetChildAgentCount(), Is.EqualTo(0)); - - // TODO: Add assertions to check correct circuit details in both scenes. - - // Lookat is sent to the client only - sp.Lookat does not yield the same thing (calculation from camera - // position instead). -// Assert.That(sp.Lookat, Is.EqualTo(teleportLookAt)); - -// TestHelpers.DisableLogging(); - } - -/* - [Test] - public void TestSameSimulatorNeighbouringRegionsV1() - { - TestHelpers.InMethod(); -// TestHelpers.EnableLogging(); - - UUID userId = TestHelpers.ParseTail(0x1); - - EntityTransferModule etmA = new EntityTransferModule(); - EntityTransferModule etmB = new EntityTransferModule(); - LocalSimulationConnectorModule lscm = new LocalSimulationConnectorModule(); - - IConfigSource config = new IniConfigSource(); - IConfig modulesConfig = config.AddConfig("Modules"); - modulesConfig.Set("EntityTransferModule", etmA.Name); - modulesConfig.Set("SimulationServices", lscm.Name); - IConfig entityTransferConfig = config.AddConfig("EntityTransfer"); - - // In order to run a single threaded regression test we do not want the entity transfer module waiting - // for a callback from the destination scene before removing its avatar data. - entityTransferConfig.Set("wait_for_callback", false); - - SceneHelpers sh = new SceneHelpers(); - TestScene sceneA = sh.SetupScene("sceneA", TestHelpers.ParseTail(0x100), 1000, 1000); - TestScene sceneB = sh.SetupScene("sceneB", TestHelpers.ParseTail(0x200), 1001, 1000); - - SceneHelpers.SetupSceneModules(new Scene[] { sceneA, sceneB }, config, lscm); - SceneHelpers.SetupSceneModules(sceneA, config, new CapabilitiesModule(), etmA); - SceneHelpers.SetupSceneModules(sceneB, config, new CapabilitiesModule(), etmB); - - // FIXME: Hack - this is here temporarily to revert back to older entity transfer behaviour - lscm.ServiceVersion = 0.1f; - - Vector3 teleportPosition = new Vector3(10, 11, 12); - Vector3 teleportLookAt = new Vector3(20, 21, 22); - - AgentCircuitData acd = SceneHelpers.GenerateAgentData(userId); - TestClient tc = new TestClient(acd, sceneA); - List destinationTestClients = new List(); - EntityTransferHelpers.SetupInformClientOfNeighbourTriggersNeighbourClientCreate(tc, destinationTestClients); - - ScenePresence beforeSceneASp = SceneHelpers.AddScenePresence(sceneA, tc, acd); - beforeSceneASp.AbsolutePosition = new Vector3(30, 31, 32); - - Assert.That(beforeSceneASp, Is.Not.Null); - Assert.That(beforeSceneASp.IsChildAgent, Is.False); - - ScenePresence beforeSceneBSp = sceneB.GetScenePresence(userId); - Assert.That(beforeSceneBSp, Is.Not.Null); - Assert.That(beforeSceneBSp.IsChildAgent, Is.True); - - // In this case, we will not receieve a second InformClientOfNeighbour since the viewer already knows - // about the neighbour region it is teleporting to. - sceneA.RequestTeleportLocation( - beforeSceneASp.ControllingClient, - sceneB.RegionInfo.RegionHandle, - teleportPosition, - teleportLookAt, - (uint)TeleportFlags.ViaLocation); - - destinationTestClients[0].CompleteMovement(); - - ScenePresence afterSceneASp = sceneA.GetScenePresence(userId); - Assert.That(afterSceneASp, Is.Not.Null); - Assert.That(afterSceneASp.IsChildAgent, Is.True); - - ScenePresence afterSceneBSp = sceneB.GetScenePresence(userId); - Assert.That(afterSceneBSp, Is.Not.Null); - Assert.That(afterSceneBSp.IsChildAgent, Is.False); - Assert.That(afterSceneBSp.Scene.RegionInfo.RegionName, Is.EqualTo(sceneB.RegionInfo.RegionName)); - Assert.That(afterSceneBSp.AbsolutePosition, Is.EqualTo(teleportPosition)); - - Assert.That(sceneA.GetRootAgentCount(), Is.EqualTo(0)); - Assert.That(sceneA.GetChildAgentCount(), Is.EqualTo(1)); - Assert.That(sceneB.GetRootAgentCount(), Is.EqualTo(1)); - Assert.That(sceneB.GetChildAgentCount(), Is.EqualTo(0)); - - // TODO: Add assertions to check correct circuit details in both scenes. - - // Lookat is sent to the client only - sp.Lookat does not yield the same thing (calculation from camera - // position instead). -// Assert.That(sp.Lookat, Is.EqualTo(teleportLookAt)); - -// TestHelpers.DisableLogging(); - } -*/ - - [Test] - public void TestSameSimulatorNeighbouringRegionsV2() - { - TestHelpers.InMethod(); -// TestHelpers.EnableLogging(); - - UUID userId = TestHelpers.ParseTail(0x1); - - EntityTransferModule etmA = new EntityTransferModule(); - EntityTransferModule etmB = new EntityTransferModule(); - LocalSimulationConnectorModule lscm = new LocalSimulationConnectorModule(); - - IConfigSource config = new IniConfigSource(); - IConfig modulesConfig = config.AddConfig("Modules"); - modulesConfig.Set("EntityTransferModule", etmA.Name); - modulesConfig.Set("SimulationServices", lscm.Name); - - SceneHelpers sh = new SceneHelpers(); - TestScene sceneA = sh.SetupScene("sceneA", TestHelpers.ParseTail(0x100), 1000, 1000); - TestScene sceneB = sh.SetupScene("sceneB", TestHelpers.ParseTail(0x200), 1001, 1000); - - SceneHelpers.SetupSceneModules(new Scene[] { sceneA, sceneB }, config, lscm); - SceneHelpers.SetupSceneModules(sceneA, config, new CapabilitiesModule(), etmA); - SceneHelpers.SetupSceneModules(sceneB, config, new CapabilitiesModule(), etmB); - - Vector3 teleportPosition = new Vector3(10, 11, 12); - Vector3 teleportLookAt = new Vector3(20, 21, 22); - - AgentCircuitData acd = SceneHelpers.GenerateAgentData(userId); - TestClient tc = new TestClient(acd, sceneA); - List destinationTestClients = new List(); - EntityTransferHelpers.SetupInformClientOfNeighbourTriggersNeighbourClientCreate(tc, destinationTestClients); - - ScenePresence beforeSceneASp = SceneHelpers.AddScenePresence(sceneA, tc, acd); - beforeSceneASp.AbsolutePosition = new Vector3(30, 31, 32); - - sceneA.Update(4); - sceneB.Update(4); - - Assert.That(beforeSceneASp, Is.Not.Null); - Assert.That(beforeSceneASp.IsChildAgent, Is.False); - - ScenePresence beforeSceneBSp = sceneB.GetScenePresence(userId); - Assert.That(beforeSceneBSp, Is.Not.Null); - Assert.That(beforeSceneBSp.IsChildAgent, Is.True); - - // Here, we need to make clientA's receipt of SendRegionTeleport trigger clientB's CompleteMovement(). This - // is to operate the teleport V2 mechanism where the EntityTransferModule will first request the client to - // CompleteMovement to the region and then call UpdateAgent to the destination region to confirm the receipt - // Both these operations will occur on different threads and will wait for each other. - // We have to do this via ThreadPool directly since FireAndForget has been switched to sync for the V1 - // test protocol, where we are trying to avoid unpredictable async operations in regression tests. - tc.OnTestClientSendRegionTeleport - += (regionHandle, simAccess, regionExternalEndPoint, locationID, flags, capsURL) - => ThreadPool.UnsafeQueueUserWorkItem(o => destinationTestClients[0].CompleteMovement(), null); - - sceneA.RequestTeleportLocation( - beforeSceneASp.ControllingClient, - sceneB.RegionInfo.RegionHandle, - teleportPosition, - teleportLookAt, - (uint)TeleportFlags.ViaLocation); - - sceneA.Update(4); - sceneB.Update(4); - - ScenePresence afterSceneASp = sceneA.GetScenePresence(userId); - Assert.That(afterSceneASp, Is.Not.Null); - Assert.That(afterSceneASp.IsChildAgent, Is.True); - - ScenePresence afterSceneBSp = sceneB.GetScenePresence(userId); - Assert.That(afterSceneBSp, Is.Not.Null); - Assert.That(afterSceneBSp.IsChildAgent, Is.False); - Assert.That(afterSceneBSp.Scene.RegionInfo.RegionName, Is.EqualTo(sceneB.RegionInfo.RegionName)); - Assert.That(afterSceneBSp.AbsolutePosition.X, Is.EqualTo(teleportPosition.X)); - Assert.That(afterSceneBSp.AbsolutePosition.Y, Is.EqualTo(teleportPosition.Y)); - - Assert.That(sceneA.GetRootAgentCount(), Is.EqualTo(0)); - Assert.That(sceneA.GetChildAgentCount(), Is.EqualTo(1)); - Assert.That(sceneB.GetRootAgentCount(), Is.EqualTo(1)); - Assert.That(sceneB.GetChildAgentCount(), Is.EqualTo(0)); - - // TODO: Add assertions to check correct circuit details in both scenes. - - // Lookat is sent to the client only - sp.Lookat does not yield the same thing (calculation from camera - // position instead). -// Assert.That(sp.Lookat, Is.EqualTo(teleportLookAt)); - -// TestHelpers.DisableLogging(); - } - } -} diff --git a/OpenSim/Region/Framework/Scenes/Tests/SceneStatisticsTests.cs b/OpenSim/Region/Framework/Scenes/Tests/SceneStatisticsTests.cs deleted file mode 100644 index 4ce6a95f363..00000000000 --- a/OpenSim/Region/Framework/Scenes/Tests/SceneStatisticsTests.cs +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections.Generic; -using System.Reflection; -using NUnit.Framework; -using OpenMetaverse; -using OpenSim.Framework; -using OpenSim.Region.Framework.Scenes; -using OpenSim.Tests.Common; - -namespace OpenSim.Region.Framework.Scenes.Tests -{ - [TestFixture] - public class SceneStatisticsTests : OpenSimTestCase - { - private TestScene m_scene; - - [SetUp] - public void Init() - { - m_scene = new SceneHelpers().SetupScene(); - } - - [Test] - public void TestAddRemovePhysicalLinkset() - { - Assert.That(m_scene.SceneGraph.GetActiveObjectsCount(), Is.EqualTo(0)); - - UUID ownerId = TestHelpers.ParseTail(0x1); - SceneObjectGroup so1 = SceneHelpers.CreateSceneObject(3, ownerId, "so1", 0x10); - m_scene.AddSceneObject(so1); - so1.ScriptSetPhysicsStatus(true); - - Assert.That(m_scene.SceneGraph.GetTotalObjectsCount(), Is.EqualTo(3)); - Assert.That(m_scene.SceneGraph.GetActiveObjectsCount(), Is.EqualTo(3)); - - m_scene.DeleteSceneObject(so1, false); - - Assert.That(m_scene.SceneGraph.GetTotalObjectsCount(), Is.EqualTo(0)); - Assert.That(m_scene.SceneGraph.GetActiveObjectsCount(), Is.EqualTo(0)); - } - } -} \ No newline at end of file diff --git a/OpenSim/Region/Framework/Scenes/Tests/SceneTelehubTests.cs b/OpenSim/Region/Framework/Scenes/Tests/SceneTelehubTests.cs deleted file mode 100644 index dbb6a37e610..00000000000 --- a/OpenSim/Region/Framework/Scenes/Tests/SceneTelehubTests.cs +++ /dev/null @@ -1,118 +0,0 @@ -/* - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using Nini.Config; -using NUnit.Framework; -using OpenMetaverse; -using OpenSim.Framework; -using OpenSim.Region.CoreModules.World.Estate; -using OpenSim.Region.Framework.Scenes; -using OpenSim.Region.Framework.Interfaces; -using OpenSim.Services.Interfaces; -using OpenSim.Tests.Common; - -namespace OpenSim.Region.Framework.Scenes.Tests -{ - /// - /// Scene telehub tests - /// - /// - /// TODO: Tests which run through normal functionality. Currently, the only test is one that checks behaviour - /// in the case of an error condition - /// - [TestFixture] - public class SceneTelehubTests : OpenSimTestCase - { - /// - /// Test for desired behaviour when a telehub has no spawn points - /// - [Test] - public void TestNoTelehubSpawnPoints() - { - TestHelpers.InMethod(); -// TestHelpers.EnableLogging(); - - EstateManagementModule emm = new EstateManagementModule(); - - SceneHelpers sh = new SceneHelpers(); - Scene scene = sh.SetupScene(); - SceneHelpers.SetupSceneModules(scene, emm); - - UUID telehubSceneObjectOwner = TestHelpers.ParseTail(0x1); - - SceneObjectGroup telehubSo = SceneHelpers.AddSceneObject(scene, "telehubObject", telehubSceneObjectOwner); - - emm.HandleOnEstateManageTelehub(null, UUID.Zero, UUID.Zero, "connect", telehubSo.LocalId); - scene.RegionInfo.EstateSettings.AllowDirectTeleport = false; - - // Must still be possible to successfully log in - UUID loggingInUserId = TestHelpers.ParseTail(0x2); - - UserAccount ua - = UserAccountHelpers.CreateUserWithInventory(scene, "Test", "User", loggingInUserId, "password"); - - SceneHelpers.AddScenePresence(scene, ua); - - Assert.That(scene.GetScenePresence(loggingInUserId), Is.Not.Null); - } - - /// - /// Test for desired behaviour when the scene object nominated as a telehub object does not exist. - /// - [Test] - public void TestNoTelehubSceneObject() - { - TestHelpers.InMethod(); -// TestHelpers.EnableLogging(); - - EstateManagementModule emm = new EstateManagementModule(); - - SceneHelpers sh = new SceneHelpers(); - Scene scene = sh.SetupScene(); - SceneHelpers.SetupSceneModules(scene, emm); - - UUID telehubSceneObjectOwner = TestHelpers.ParseTail(0x1); - - SceneObjectGroup telehubSo = SceneHelpers.AddSceneObject(scene, "telehubObject", telehubSceneObjectOwner); - SceneObjectGroup spawnPointSo = SceneHelpers.AddSceneObject(scene, "spawnpointObject", telehubSceneObjectOwner); - - emm.HandleOnEstateManageTelehub(null, UUID.Zero, UUID.Zero, "connect", telehubSo.LocalId); - emm.HandleOnEstateManageTelehub(null, UUID.Zero, UUID.Zero, "spawnpoint add", spawnPointSo.LocalId); - scene.RegionInfo.EstateSettings.AllowDirectTeleport = false; - - scene.DeleteSceneObject(telehubSo, false); - - // Must still be possible to successfully log in - UUID loggingInUserId = TestHelpers.ParseTail(0x2); - - UserAccount ua - = UserAccountHelpers.CreateUserWithInventory(scene, "Test", "User", loggingInUserId, "password"); - - SceneHelpers.AddScenePresence(scene, ua); - - Assert.That(scene.GetScenePresence(loggingInUserId), Is.Not.Null); - } - } -} \ No newline at end of file diff --git a/OpenSim/Region/Framework/Scenes/Tests/SceneTests.cs b/OpenSim/Region/Framework/Scenes/Tests/SceneTests.cs deleted file mode 100644 index 6c0af8f1a00..00000000000 --- a/OpenSim/Region/Framework/Scenes/Tests/SceneTests.cs +++ /dev/null @@ -1,107 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections.Generic; -using System.Reflection; -using System.Text; -using System.Threading; -using System.Timers; -using Timer=System.Timers.Timer; -using Nini.Config; -using NUnit.Framework; -using OpenMetaverse; -using OpenSim.Framework; -using OpenSim.Region.Framework.Scenes; -using OpenSim.Region.Framework.Interfaces; -using OpenSim.Region.CoreModules.World.Serialiser; -using OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation; -using OpenSim.Tests.Common; - -namespace OpenSim.Region.Framework.Scenes.Tests -{ - /// - /// Scene presence tests - /// - [TestFixture] - public class SceneTests : OpenSimTestCase - { - [Test] - public void TestCreateScene() - { - TestHelpers.InMethod(); - - new SceneHelpers().SetupScene(); - } - - [Test] - public void TestCreateVarScene() - { - TestHelpers.InMethod(); - UUID regionUuid = TestHelpers.ParseTail(0x1); - uint sizeX = 512; - uint sizeY = 512; - - Scene scene - = new SceneHelpers().SetupScene("scene", regionUuid, 1000, 1000, sizeX, sizeY, new IniConfigSource()); - - Assert.AreEqual(sizeX, scene.RegionInfo.RegionSizeX); - Assert.AreEqual(sizeY, scene.RegionInfo.RegionSizeY); - } - - /// - /// Very basic scene update test. Should become more elaborate with time. - /// - [Test] - public void TestUpdateScene() - { - TestHelpers.InMethod(); - - Scene scene = new SceneHelpers().SetupScene(); - scene.Update(1); - - Assert.That(scene.Frame, Is.EqualTo(1)); - } - - [Test] - public void TestShutdownScene() - { - TestHelpers.InMethod(); - - Scene scene = new SceneHelpers().SetupScene(); - scene.Close(); - - Assert.That(scene.ShuttingDown, Is.True); - Assert.That(scene.Active, Is.False); - - // Trying to update a shutdown scene should result in no update - scene.Update(1); - - Assert.That(scene.Frame, Is.EqualTo(0)); - } - } -} \ No newline at end of file diff --git a/OpenSim/Region/Framework/Scenes/Tests/SharedRegionModuleTests.cs b/OpenSim/Region/Framework/Scenes/Tests/SharedRegionModuleTests.cs deleted file mode 100644 index 80c11f92db4..00000000000 --- a/OpenSim/Region/Framework/Scenes/Tests/SharedRegionModuleTests.cs +++ /dev/null @@ -1,249 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections.Generic; -using System.Net; -using Mono.Addins; -using Nini.Config; -using NUnit.Framework; -using OpenMetaverse; -using OpenSim; -using OpenSim.ApplicationPlugins.RegionModulesController; -using OpenSim.Framework; -using OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid; -using OpenSim.Region.Framework.Interfaces; -using OpenSim.Tests.Common; - -namespace OpenSim.Region.Framework.Scenes.Tests -{ - public class SharedRegionModuleTests : OpenSimTestCase - { -// [Test] - public void TestLifecycle() - { - TestHelpers.InMethod(); - TestHelpers.EnableLogging(); - - UUID estateOwnerId = TestHelpers.ParseTail(0x1); - UUID regionId = TestHelpers.ParseTail(0x10); - - IConfigSource configSource = new IniConfigSource(); - configSource.AddConfig("Startup"); - configSource.AddConfig("Modules"); - -// // We use this to skip estate questions - // Turns out not to be needed is estate owner id is pre-set in region information. -// IConfig estateConfig = configSource.AddConfig(OpenSimBase.ESTATE_SECTION_NAME); -// estateConfig.Set("DefaultEstateOwnerName", "Zaphod Beeblebrox"); -// estateConfig.Set("DefaultEstateOwnerUUID", estateOwnerId); -// estateConfig.Set("DefaultEstateOwnerEMail", "zaphod@galaxy.com"); -// estateConfig.Set("DefaultEstateOwnerPassword", "two heads"); - - // For grid servic - configSource.AddConfig("GridService"); - configSource.Configs["Modules"].Set("GridServices", "RegionGridServicesConnector"); - configSource.Configs["GridService"].Set("StorageProvider", "OpenSim.Data.Null.dll:NullRegionData"); - configSource.Configs["GridService"].Set("LocalServiceModule", "OpenSim.Services.GridService.dll:GridService"); - configSource.Configs["GridService"].Set("ConnectionString", "!static"); - - RegionGridServicesConnector gridService = new RegionGridServicesConnector(); -// - OpenSim sim = new OpenSim(configSource); - - sim.SuppressExit = true; - sim.EnableInitialPluginLoad = false; - sim.LoadEstateDataService = false; - sim.NetServersInfo.HttpListenerPort = 0; - - IRegistryCore reg = sim.ApplicationRegistry; - - RegionInfo ri = new RegionInfo(); - ri.RegionID = regionId; - ri.EstateSettings.EstateOwner = estateOwnerId; - ri.InternalEndPoint = new IPEndPoint(0, 0); - - MockRegionModulesControllerPlugin rmcp = new MockRegionModulesControllerPlugin(); - sim.m_plugins = new List() { rmcp }; - reg.RegisterInterface(rmcp); - - // XXX: Have to initialize directly for now - rmcp.Initialise(sim); - - rmcp.AddNode(gridService); - - TestSharedRegion tsr = new TestSharedRegion(); - rmcp.AddNode(tsr); - - // FIXME: Want to use the real one eventually but this is currently directly tied into Mono.Addins - // which has been written in such a way that makes it impossible to use for regression tests. -// RegionModulesControllerPlugin rmcp = new RegionModulesControllerPlugin(); -// rmcp.LoadModulesFromAddins = false; -//// reg.RegisterInterface(rmcp); -// rmcp.Initialise(sim); -// rmcp.PostInitialise(); -// TypeExtensionNode node = new TypeExtensionNode(); -// node. -// rmcp.AddNode(node, configSource.Configs["Modules"], new Dictionary>()); - - sim.Startup(); - IScene scene; - sim.CreateRegion(ri, out scene); - - sim.Shutdown(); - - List co = tsr.CallOrder; - int expectedEventCount = 6; - - Assert.AreEqual( - expectedEventCount, - co.Count, - "Expected {0} events but only got {1} ({2})", - expectedEventCount, co.Count, string.Join(",", co)); - Assert.AreEqual("Initialise", co[0]); - Assert.AreEqual("PostInitialise", co[1]); - Assert.AreEqual("AddRegion", co[2]); - Assert.AreEqual("RegionLoaded", co[3]); - Assert.AreEqual("RemoveRegion", co[4]); - Assert.AreEqual("Close", co[5]); - } - } - - class TestSharedRegion : ISharedRegionModule - { - // FIXME: Should really use MethodInfo - public List CallOrder = new List(); - - public string Name { get { return "TestSharedRegion"; } } - - public Type ReplaceableInterface { get { return null; } } - - public void PostInitialise() - { - CallOrder.Add("PostInitialise"); - } - - public void Initialise(IConfigSource source) - { - CallOrder.Add("Initialise"); - } - - public void Close() - { - CallOrder.Add("Close"); - } - - public void AddRegion(Scene scene) - { - CallOrder.Add("AddRegion"); - } - - public void RemoveRegion(Scene scene) - { - CallOrder.Add("RemoveRegion"); - } - - public void RegionLoaded(Scene scene) - { - CallOrder.Add("RegionLoaded"); - } - } - - class MockRegionModulesControllerPlugin : IRegionModulesController, IApplicationPlugin - { - // List of shared module instances, for adding to Scenes - private List m_sharedInstances = new List(); - - // Config access - private OpenSimBase m_openSim; - - public string Version { get { return "0"; } } - public string Name { get { return "MockRegionModulesControllerPlugin"; } } - - public void Initialise() {} - - public void Initialise(OpenSimBase sim) - { - m_openSim = sim; - } - - /// - /// Called when the application loading is completed - /// - public void PostInitialise() - { - foreach (ISharedRegionModule module in m_sharedInstances) - module.PostInitialise(); - } - - public void AddRegionToModules(Scene scene) - { - List sharedlist = new List(); - - foreach (ISharedRegionModule module in m_sharedInstances) - { - module.AddRegion(scene); - scene.AddRegionModule(module.Name, module); - - sharedlist.Add(module); - } - - foreach (ISharedRegionModule module in sharedlist) - { - module.RegionLoaded(scene); - } - } - - public void RemoveRegionFromModules(Scene scene) - { - foreach (IRegionModuleBase module in scene.RegionModules.Values) - { -// m_log.DebugFormat("[REGIONMODULE]: Removing scene {0} from module {1}", -// scene.RegionInfo.RegionName, module.Name); - module.RemoveRegion(scene); - } - - scene.RegionModules.Clear(); - } - - public void AddNode(ISharedRegionModule module) - { - m_sharedInstances.Add(module); - module.Initialise(m_openSim.ConfigSource.Source); - } - - public void Dispose() - { - // We expect that all regions have been removed already - while (m_sharedInstances.Count > 0) - { - m_sharedInstances[0].Close(); - m_sharedInstances.RemoveAt(0); - } - } - } -} \ No newline at end of file diff --git a/OpenSim/Region/Framework/Scenes/Tests/TaskInventoryTests.cs b/OpenSim/Region/Framework/Scenes/Tests/TaskInventoryTests.cs deleted file mode 100644 index 8273e329625..00000000000 --- a/OpenSim/Region/Framework/Scenes/Tests/TaskInventoryTests.cs +++ /dev/null @@ -1,175 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections.Generic; -using System.Reflection; -using System.Text; -using System.Threading; -using System.Timers; -using Timer=System.Timers.Timer; -using Nini.Config; -using NUnit.Framework; -using OpenMetaverse; -using OpenMetaverse.Assets; -using OpenSim.Framework; -using OpenSim.Region.Framework.Scenes; -using OpenSim.Region.Framework.Interfaces; -using OpenSim.Region.CoreModules.Avatar.Inventory.Archiver; -using OpenSim.Region.CoreModules.World.Serialiser; -using OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation; -using OpenSim.Services.Interfaces; -using OpenSim.Tests.Common; - -namespace OpenSim.Region.Framework.Tests -{ - [TestFixture] - public class TaskInventoryTests : OpenSimTestCase - { - [Test] - public void TestAddTaskInventoryItem() - { - TestHelpers.InMethod(); -// log4net.Config.XmlConfigurator.Configure(); - - Scene scene = new SceneHelpers().SetupScene(); - UserAccount user1 = UserAccountHelpers.CreateUserWithInventory(scene); - SceneObjectGroup sog1 = SceneHelpers.CreateSceneObject(1, user1.PrincipalID); - SceneObjectPart sop1 = sog1.RootPart; - - // Create an object embedded inside the first - UUID taskSceneObjectItemId = UUID.Parse("00000000-0000-0000-0000-100000000000"); - TaskInventoryHelpers.AddSceneObject(scene.AssetService, sop1, "tso", taskSceneObjectItemId, user1.PrincipalID); - - TaskInventoryItem addedItem = sop1.Inventory.GetInventoryItem(taskSceneObjectItemId); - Assert.That(addedItem.ItemID, Is.EqualTo(taskSceneObjectItemId)); - Assert.That(addedItem.OwnerID, Is.EqualTo(user1.PrincipalID)); - Assert.That(addedItem.ParentID, Is.EqualTo(sop1.UUID)); - Assert.That(addedItem.InvType, Is.EqualTo((int)InventoryType.Object)); - Assert.That(addedItem.Type, Is.EqualTo((int)AssetType.Object)); - } - - [Test] - public void TestRezObjectFromInventoryItem() - { - TestHelpers.InMethod(); -// log4net.Config.XmlConfigurator.Configure(); - - Scene scene = new SceneHelpers().SetupScene(); - UserAccount user1 = UserAccountHelpers.CreateUserWithInventory(scene); - SceneObjectGroup sog1 = SceneHelpers.CreateSceneObject(1, user1.PrincipalID); - SceneObjectPart sop1 = sog1.RootPart; - - // Create an object embedded inside the first - UUID taskSceneObjectItemId = UUID.Parse("00000000-0000-0000-0000-100000000000"); - TaskInventoryItem taskSceneObjectItem - = TaskInventoryHelpers.AddSceneObject(scene.AssetService, sop1, "tso", taskSceneObjectItemId, user1.PrincipalID); - - scene.AddSceneObject(sog1); - - Vector3 rezPos = new Vector3(10, 10, 10); - Quaternion rezRot = new Quaternion(0.5f, 0.5f, 0.5f, 0.5f); - Vector3 rezVel = new Vector3(2, 2, 2); - - scene.RezObject(sop1, taskSceneObjectItem, rezPos, rezRot, rezVel, 0,false); - - SceneObjectGroup rezzedObject = scene.GetSceneObjectGroup("tso"); - - Assert.That(rezzedObject, Is.Not.Null); - Assert.That(rezzedObject.AbsolutePosition, Is.EqualTo(rezPos)); - - // Velocity doesn't get applied, probably because there is no physics in tests (yet) -// Assert.That(rezzedObject.Velocity, Is.EqualTo(rezVel)); - Assert.That(rezzedObject.Velocity, Is.EqualTo(Vector3.Zero)); - - // Confusingly, this isn't the rezzedObject.Rotation - Assert.That(rezzedObject.RootPart.RotationOffset, Is.EqualTo(rezRot)); - } - - /// - /// Test MoveTaskInventoryItem from a part inventory to a user inventory where the item has no parent folder assigned. - /// - /// - /// This should place it in the most suitable user folder. - /// - [Test] - public void TestMoveTaskInventoryItem() - { - TestHelpers.InMethod(); -// log4net.Config.XmlConfigurator.Configure(); - - Scene scene = new SceneHelpers().SetupScene(); - UserAccount user1 = UserAccountHelpers.CreateUserWithInventory(scene); - SceneObjectGroup sog1 = SceneHelpers.CreateSceneObject(1, user1.PrincipalID); - SceneObjectPart sop1 = sog1.RootPart; - TaskInventoryItem sopItem1 - = TaskInventoryHelpers.AddNotecard( - scene.AssetService, sop1, "ncItem", TestHelpers.ParseTail(0x800), TestHelpers.ParseTail(0x900), "Hello World!"); - - InventoryFolderBase folder - = InventoryArchiveUtils.FindFoldersByPath(scene.InventoryService, user1.PrincipalID, "Objects")[0]; - - // Perform test - string message; - scene.MoveTaskInventoryItem(user1.PrincipalID, folder.ID, sop1, sopItem1.ItemID, out message); - - InventoryItemBase ncUserItem - = InventoryArchiveUtils.FindItemByPath(scene.InventoryService, user1.PrincipalID, "Objects/ncItem"); - Assert.That(ncUserItem, Is.Not.Null, "Objects/ncItem was not found"); - } - - /// - /// Test MoveTaskInventoryItem from a part inventory to a user inventory where the item has no parent folder assigned. - /// - /// - /// This should place it in the most suitable user folder. - /// - [Test] - public void TestMoveTaskInventoryItemNoParent() - { - TestHelpers.InMethod(); -// log4net.Config.XmlConfigurator.Configure(); - - Scene scene = new SceneHelpers().SetupScene(); - UserAccount user1 = UserAccountHelpers.CreateUserWithInventory(scene); - SceneObjectGroup sog1 = SceneHelpers.CreateSceneObject(1, user1.PrincipalID); - - SceneObjectPart sop1 = sog1.RootPart; - TaskInventoryItem sopItem1 - = TaskInventoryHelpers.AddNotecard( - scene.AssetService, sop1, "ncItem", TestHelpers.ParseTail(0x800), TestHelpers.ParseTail(0x900), "Hello World!"); - - // Perform test - string message; - scene.MoveTaskInventoryItem(user1.PrincipalID, UUID.Zero, sop1, sopItem1.ItemID, out message); - - InventoryItemBase ncUserItem - = InventoryArchiveUtils.FindItemByPath(scene.InventoryService, user1.PrincipalID, "Notecards/ncItem"); - Assert.That(ncUserItem, Is.Not.Null, "Notecards/ncItem was not found"); - } - } -} \ No newline at end of file diff --git a/OpenSim/Region/Framework/Scenes/Tests/UserInventoryTests.cs b/OpenSim/Region/Framework/Scenes/Tests/UserInventoryTests.cs deleted file mode 100644 index 514e4970f14..00000000000 --- a/OpenSim/Region/Framework/Scenes/Tests/UserInventoryTests.cs +++ /dev/null @@ -1,200 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections.Generic; -using System.Reflection; -using System.Text; -using System.Threading; -using System.Timers; -using Timer=System.Timers.Timer; -using Nini.Config; -using NUnit.Framework; -using OpenMetaverse; -using OpenMetaverse.Assets; -using OpenSim.Framework; -using OpenSim.Region.Framework.Scenes; -using OpenSim.Region.CoreModules.Framework.InventoryAccess; -using OpenSim.Services.Interfaces; -using OpenSim.Tests.Common; - -namespace OpenSim.Region.Framework.Tests -{ - [TestFixture] - public class UserInventoryTests : OpenSimTestCase - { - [Test] - public void TestCreateInventoryFolders() - { - TestHelpers.InMethod(); -// TestHelpers.EnableLogging(); - - // For this test both folders will have the same name which is legal in SL user inventories. - string foldersName = "f1"; - - Scene scene = new SceneHelpers().SetupScene(); - UserAccount user1 = UserAccountHelpers.CreateUserWithInventory(scene, TestHelpers.ParseTail(1001)); - - UserInventoryHelpers.CreateInventoryFolder(scene.InventoryService, user1.PrincipalID, foldersName, false); - - List oneFolder - = UserInventoryHelpers.GetInventoryFolders(scene.InventoryService, user1.PrincipalID, foldersName); - - Assert.That(oneFolder.Count, Is.EqualTo(1)); - InventoryFolderBase firstRetrievedFolder = oneFolder[0]; - Assert.That(firstRetrievedFolder.Name, Is.EqualTo(foldersName)); - - UserInventoryHelpers.CreateInventoryFolder(scene.InventoryService, user1.PrincipalID, foldersName, false); - - List twoFolders - = UserInventoryHelpers.GetInventoryFolders(scene.InventoryService, user1.PrincipalID, foldersName); - - Assert.That(twoFolders.Count, Is.EqualTo(2)); - Assert.That(twoFolders[0].Name, Is.EqualTo(foldersName)); - Assert.That(twoFolders[1].Name, Is.EqualTo(foldersName)); - Assert.That(twoFolders[0].ID, Is.Not.EqualTo(twoFolders[1].ID)); - } - - [Test] - public void TestGiveInventoryItem() - { - TestHelpers.InMethod(); -// log4net.Config.XmlConfigurator.Configure(); - - Scene scene = new SceneHelpers().SetupScene(); - UserAccount user1 = UserAccountHelpers.CreateUserWithInventory(scene, TestHelpers.ParseTail(1001)); - UserAccount user2 = UserAccountHelpers.CreateUserWithInventory(scene, TestHelpers.ParseTail(1002)); - InventoryItemBase item1 = UserInventoryHelpers.CreateInventoryItem(scene, "item1", user1.PrincipalID); - - string message; - - scene.GiveInventoryItem(user2.PrincipalID, user1.PrincipalID, item1.ID, out message); - - InventoryItemBase retrievedItem1 - = UserInventoryHelpers.GetInventoryItem(scene.InventoryService, user2.PrincipalID, "Notecards/item1"); - - Assert.That(retrievedItem1, Is.Not.Null); - - // Try giving back the freshly received item - scene.GiveInventoryItem(user1.PrincipalID, user2.PrincipalID, retrievedItem1.ID, out message); - - List reretrievedItems - = UserInventoryHelpers.GetInventoryItems(scene.InventoryService, user1.PrincipalID, "Notecards/item1"); - - Assert.That(reretrievedItems.Count, Is.EqualTo(2)); - } - - [Test] - public void TestGiveInventoryFolder() - { - TestHelpers.InMethod(); -// TestHelpers.EnableLogging(); - - Scene scene = new SceneHelpers().SetupScene(); - UserAccount user1 = UserAccountHelpers.CreateUserWithInventory(scene, TestHelpers.ParseTail(1001)); - UserAccount user2 = UserAccountHelpers.CreateUserWithInventory(scene, TestHelpers.ParseTail(1002)); - InventoryFolderBase folder1 - = UserInventoryHelpers.CreateInventoryFolder(scene.InventoryService, user1.PrincipalID, "folder1", false); - - scene.GiveInventoryFolder(null, user2.PrincipalID, user1.PrincipalID, folder1.ID, UUID.Zero); - - InventoryFolderBase retrievedFolder1 - = UserInventoryHelpers.GetInventoryFolder(scene.InventoryService, user2.PrincipalID, "folder1"); - - Assert.That(retrievedFolder1, Is.Not.Null); - - // Try giving back the freshly received folder - scene.GiveInventoryFolder(null, user1.PrincipalID, user2.PrincipalID, retrievedFolder1.ID, UUID.Zero); - - List reretrievedFolders - = UserInventoryHelpers.GetInventoryFolders(scene.InventoryService, user1.PrincipalID, "folder1"); - - Assert.That(reretrievedFolders.Count, Is.EqualTo(2)); - } - - // Work in Progress test. All Assertions pertaining permissions are commented for now. - [Test] - public void TestGiveInventoryItemFullPerms() - { - TestHelpers.InMethod(); - - List modules = new List(); - IConfigSource config = DefaultConfig(modules); - Scene scene = new SceneHelpers().SetupScene("Inventory Permissions", UUID.Random(), 1000, 1000, config); - SceneHelpers.SetupSceneModules(scene, config, modules.ToArray()); - - UserAccount user1 = UserAccountHelpers.CreateUserWithInventory(scene, TestHelpers.ParseTail(1001)); - UserAccount user2 = UserAccountHelpers.CreateUserWithInventory(scene, TestHelpers.ParseTail(1002)); - ScenePresence sp1 = SceneHelpers.AddScenePresence(scene, user1.PrincipalID); - ScenePresence sp2 = SceneHelpers.AddScenePresence(scene, user2.PrincipalID); - - InventoryItemBase item1 = UserInventoryHelpers.CreateInventoryItem(scene, "SomeObject", user1.PrincipalID, InventoryType.Object); - // Set All perms in inventory - item1.NextPermissions = (uint)OpenMetaverse.PermissionMask.All; - scene.UpdateInventoryItem(sp1.ControllingClient, UUID.Zero, item1.ID, item1); - //Assert.That((item1.NextPermissions & (uint)OpenMetaverse.PermissionMask.All) == (uint)OpenMetaverse.PermissionMask.All); - - string message; - - InventoryItemBase retrievedItem1 = scene.GiveInventoryItem(user2.PrincipalID, user1.PrincipalID, item1.ID, out message); - Assert.That(retrievedItem1, Is.Not.Null); - //Assert.That((retrievedItem1.CurrentPermissions & (uint)OpenMetaverse.PermissionMask.All) == (uint)OpenMetaverse.PermissionMask.All); - - retrievedItem1 - = UserInventoryHelpers.GetInventoryItem(scene.InventoryService, user2.PrincipalID, "Objects/SomeObject"); - Assert.That(retrievedItem1, Is.Not.Null); - //Assert.That((retrievedItem1.BasePermissions & (uint)OpenMetaverse.PermissionMask.All) == (uint)OpenMetaverse.PermissionMask.All); - //Assert.That((retrievedItem1.CurrentPermissions & (uint)OpenMetaverse.PermissionMask.All) == (uint)OpenMetaverse.PermissionMask.All); - - // Rez the object - scene.RezObject(sp2.ControllingClient, retrievedItem1.ID, UUID.Zero, Vector3.Zero, Vector3.Zero, UUID.Zero, 0, false, false, false, UUID.Zero); - SceneObjectGroup sog = scene.GetSceneObjectGroup("SomeObject"); - Assert.That(sog, Is.Not.Null); - - // This is failing for all sorts of reasons. We'll fix it after perms are fixed. - //Console.WriteLine("Item Perms " + retrievedItem1.CurrentPermissions + " Obj Owner Perms " + sog.RootPart.OwnerMask + " Base Perms " + sog.RootPart.BaseMask + "\n"); - //Assert.True((sog.RootPart.OwnerMask & (uint)OpenMetaverse.PermissionMask.All) == (uint)OpenMetaverse.PermissionMask.All); - - } - - public static IConfigSource DefaultConfig(List modules) - { - IConfigSource config = new IniConfigSource(); - config.AddConfig("Modules"); - config.Configs["Modules"].Set("InventoryAccessModule", "BasicInventoryAccessModule"); - - config.AddConfig("Permissions"); - config.Configs["Permissions"].Set("permissionmodules", "DefaultPermissionsModule"); - config.Configs["Permissions"].Set("serverside_object_permissions", true); - config.Configs["Permissions"].Set("propagate_permissions", true); - - modules.Add(new BasicInventoryAccessModule()); - return config; - } - - } -} \ No newline at end of file diff --git a/OpenSim/Region/Framework/Scenes/Tests/UuidGathererTests.cs b/OpenSim/Region/Framework/Scenes/Tests/UuidGathererTests.cs deleted file mode 100644 index efe71e9dcf0..00000000000 --- a/OpenSim/Region/Framework/Scenes/Tests/UuidGathererTests.cs +++ /dev/null @@ -1,160 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System.Collections.Generic; -using System.Text; -using NUnit.Framework; -using OpenMetaverse; -using OpenSim.Framework; -using OpenSim.Region.Framework.Scenes; -using OpenSim.Services.Interfaces; -using OpenSim.Tests.Common; - -namespace OpenSim.Region.Framework.Scenes.Tests -{ - [TestFixture] - public class UuidGathererTests : OpenSimTestCase - { - protected IAssetService m_assetService; - protected UuidGatherer m_uuidGatherer; - - protected static string noteBase = @"Linden text version 2\n{\nLLEmbeddedItems version 1\n -{\ncount 0\n}\nText length xxx\n"; // len does not matter on this test - [SetUp] - public void Init() - { - // FIXME: We don't need a full scene here - it would be enough to set up the asset service. - Scene scene = new SceneHelpers().SetupScene(); - m_assetService = scene.AssetService; - m_uuidGatherer = new UuidGatherer(m_assetService); - } - - [Test] - public void TestCorruptAsset() - { - TestHelpers.InMethod(); - - UUID corruptAssetUuid = UUID.Parse("00000000-0000-0000-0000-000000000666"); - AssetBase corruptAsset - = AssetHelpers.CreateAsset(corruptAssetUuid, AssetType.Notecard, noteBase + "CORRUPT ASSET", UUID.Zero); - m_assetService.Store(corruptAsset); - - m_uuidGatherer.AddForInspection(corruptAssetUuid); - m_uuidGatherer.GatherAll(); - - // We count the uuid as gathered even if the asset itself is corrupt. - Assert.That(m_uuidGatherer.GatheredUuids.Count, Is.EqualTo(1)); - } - - /// - /// Test requests made for non-existent assets while we're gathering - /// - [Test] - public void TestMissingAsset() - { - TestHelpers.InMethod(); - - UUID missingAssetUuid = UUID.Parse("00000000-0000-0000-0000-000000000666"); - - m_uuidGatherer.AddForInspection(missingAssetUuid); - m_uuidGatherer.GatherAll(); - - Assert.That(m_uuidGatherer.GatheredUuids.Count, Is.EqualTo(0)); - } - - [Test] - public void TestNotecardAsset() - { - TestHelpers.InMethod(); - // TestHelpers.EnableLogging(); - - UUID ownerId = TestHelpers.ParseTail(0x10); - UUID embeddedId = TestHelpers.ParseTail(0x20); - UUID secondLevelEmbeddedId = TestHelpers.ParseTail(0x21); - UUID missingEmbeddedId = TestHelpers.ParseTail(0x22); - UUID ncAssetId = TestHelpers.ParseTail(0x30); - - AssetBase ncAsset - = AssetHelpers.CreateNotecardAsset( - ncAssetId, string.Format("{0}Hello{1}World{2}", noteBase, embeddedId, missingEmbeddedId)); - m_assetService.Store(ncAsset); - - AssetBase embeddedAsset - = AssetHelpers.CreateNotecardAsset(embeddedId, string.Format("{0}{1} We'll meet again.", noteBase, secondLevelEmbeddedId)); - m_assetService.Store(embeddedAsset); - - AssetBase secondLevelEmbeddedAsset - = AssetHelpers.CreateNotecardAsset(secondLevelEmbeddedId, noteBase + "Don't know where, don't know when."); - m_assetService.Store(secondLevelEmbeddedAsset); - - m_uuidGatherer.AddForInspection(ncAssetId); - m_uuidGatherer.GatherAll(); - - // foreach (UUID key in m_uuidGatherer.GatheredUuids.Keys) - // System.Console.WriteLine("key : {0}", key); - - Assert.That(m_uuidGatherer.GatheredUuids.Count, Is.EqualTo(3)); - Assert.That(m_uuidGatherer.GatheredUuids.ContainsKey(ncAssetId)); - Assert.That(m_uuidGatherer.GatheredUuids.ContainsKey(embeddedId)); - Assert.That(m_uuidGatherer.GatheredUuids.ContainsKey(secondLevelEmbeddedId)); - } - - [Test] - public void TestTaskItems() - { - TestHelpers.InMethod(); - // TestHelpers.EnableLogging(); - - UUID ownerId = TestHelpers.ParseTail(0x10); - - SceneObjectGroup soL0 = SceneHelpers.CreateSceneObject(1, ownerId, "l0", 0x20); - SceneObjectGroup soL1 = SceneHelpers.CreateSceneObject(1, ownerId, "l1", 0x21); - SceneObjectGroup soL2 = SceneHelpers.CreateSceneObject(1, ownerId, "l2", 0x22); - - TaskInventoryHelpers.AddScript( - m_assetService, soL2.RootPart, TestHelpers.ParseTail(0x33), TestHelpers.ParseTail(0x43), "l3-script", "gibberish"); - - TaskInventoryHelpers.AddSceneObject( - m_assetService, soL1.RootPart, "l2-item", TestHelpers.ParseTail(0x32), soL2, TestHelpers.ParseTail(0x42)); - TaskInventoryHelpers.AddSceneObject( - m_assetService, soL0.RootPart, "l1-item", TestHelpers.ParseTail(0x31), soL1, TestHelpers.ParseTail(0x41)); - - m_uuidGatherer.AddForInspection(soL0); - m_uuidGatherer.GatherAll(); - -// foreach (UUID key in m_uuidGatherer.GatheredUuids.Keys) -// System.Console.WriteLine("key : {0}", key); - - // We expect to see the default prim texture and the assets of the contained task items - Assert.That(m_uuidGatherer.GatheredUuids.Count, Is.EqualTo(4)); - Assert.That(m_uuidGatherer.GatheredUuids.ContainsKey(new UUID(Constants.DefaultTexture))); - Assert.That(m_uuidGatherer.GatheredUuids.ContainsKey(TestHelpers.ParseTail(0x41))); - Assert.That(m_uuidGatherer.GatheredUuids.ContainsKey(TestHelpers.ParseTail(0x42))); - Assert.That(m_uuidGatherer.GatheredUuids.ContainsKey(TestHelpers.ParseTail(0x43))); - } - } -} \ No newline at end of file diff --git a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/Tests/GroupsModuleTests.cs b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/Tests/GroupsModuleTests.cs deleted file mode 100644 index ccfcd8b3540..00000000000 --- a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/Tests/GroupsModuleTests.cs +++ /dev/null @@ -1,276 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections; -using System.Collections.Generic; -using System.Net; -using System.Reflection; -using Nini.Config; -using NUnit.Framework; -using OpenMetaverse; -using OpenMetaverse.Messages.Linden; -using OpenMetaverse.Packets; -using OpenMetaverse.StructuredData; -using OpenSim.Framework; -using OpenSim.Framework.Servers; -using OpenSim.Framework.Servers.HttpServer; -using OpenSim.Region.ClientStack.Linden; -using OpenSim.Region.CoreModules.Avatar.InstantMessage; -using OpenSim.Region.CoreModules.Framework; -using OpenSim.Region.Framework.Scenes; -using OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups; -using OpenSim.Tests.Common; - -namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups.Tests -{ - /// - /// Basic groups module tests - /// - [TestFixture] - public class GroupsModuleTests : OpenSimTestCase - { - [SetUp] - public override void SetUp() - { - base.SetUp(); - - uint port = 9999; - uint sslPort = 9998; - - // This is an unfortunate bit of clean up we have to do because MainServer manages things through static - // variables and the VM is not restarted between tests. - MainServer.RemoveHttpServer(port); - - BaseHttpServer server = new BaseHttpServer(port, false, sslPort, ""); - MainServer.AddHttpServer(server); - MainServer.Instance = server; - } - - [Test] - public void TestSendAgentGroupDataUpdate() - { -/* AgentGroupDataUpdate is udp - TestHelpers.InMethod(); -// TestHelpers.EnableLogging(); - - TestScene scene = new SceneHelpers().SetupScene(); - IConfigSource configSource = new IniConfigSource(); - IConfig config = configSource.AddConfig("Groups"); - config.Set("Enabled", true); - config.Set("Module", "GroupsModule"); - config.Set("DebugEnabled", true); - - GroupsModule gm = new GroupsModule(); - EventQueueGetModule eqgm = new EventQueueGetModule(); - - // We need a capabilities module active so that adding the scene presence creates an event queue in the - // EventQueueGetModule - SceneHelpers.SetupSceneModules( - scene, configSource, gm, new MockGroupsServicesConnector(), new CapabilitiesModule(), eqgm); - - ScenePresence sp = SceneHelpers.AddScenePresence(scene, TestHelpers.ParseStem("1")); - - gm.SendAgentGroupDataUpdate(sp.ControllingClient); - - Hashtable eventsResponse = eqgm.GetEvents(UUID.Zero, sp.UUID); - - if((int)eventsResponse["int_response_code"] != (int)HttpStatusCode.OK) - { - eventsResponse = eqgm.GetEvents(UUID.Zero, sp.UUID); - if((int)eventsResponse["int_response_code"] != (int)HttpStatusCode.OK) - eventsResponse = eqgm.GetEvents(UUID.Zero, sp.UUID); - } - - Assert.That((int)eventsResponse["int_response_code"], Is.EqualTo((int)HttpStatusCode.OK)); - -// Console.WriteLine("Response [{0}]", (string)eventsResponse["str_response_string"]); - - OSDMap rawOsd = (OSDMap)OSDParser.DeserializeLLSDXml((string)eventsResponse["str_response_string"]); - OSDArray eventsOsd = (OSDArray)rawOsd["events"]; - - bool foundUpdate = false; - foreach (OSD osd in eventsOsd) - { - OSDMap eventOsd = (OSDMap)osd; - - if (eventOsd["message"] == "AgentGroupDataUpdate") - foundUpdate = true; - } - - Assert.That(foundUpdate, Is.True, "Did not find AgentGroupDataUpdate in response"); - - // TODO: More checking of more actual event data. -*/ - } - - [Test] - public void TestSendGroupNotice() - { - TestHelpers.InMethod(); -// TestHelpers.EnableLogging(); - - TestScene scene = new SceneHelpers().SetupScene(); - - MessageTransferModule mtm = new MessageTransferModule(); - GroupsModule gm = new GroupsModule(); - GroupsMessagingModule gmm = new GroupsMessagingModule(); - MockGroupsServicesConnector mgsc = new MockGroupsServicesConnector(); - - IConfigSource configSource = new IniConfigSource(); - - { - IConfig config = configSource.AddConfig("Messaging"); - config.Set("MessageTransferModule", mtm.Name); - } - - { - IConfig config = configSource.AddConfig("Groups"); - config.Set("Enabled", true); - config.Set("Module", gm.Name); - config.Set("DebugEnabled", true); - config.Set("MessagingModule", gmm.Name); - config.Set("MessagingEnabled", true); - } - - SceneHelpers.SetupSceneModules(scene, configSource, mgsc, mtm, gm, gmm); - - UUID userId = TestHelpers.ParseTail(0x1); - string subjectText = "newman"; - string messageText = "Hello"; - string combinedSubjectMessage = string.Format("{0}|{1}", subjectText, messageText); - - ScenePresence sp = SceneHelpers.AddScenePresence(scene, TestHelpers.ParseTail(0x1)); - TestClient tc = (TestClient)sp.ControllingClient; - - UUID groupID = gm.CreateGroup(tc, "group1", null, true, UUID.Zero, 0, true, true, true); - gm.JoinGroupRequest(tc, groupID); - - // Create a second user who doesn't want to receive notices - ScenePresence sp2 = SceneHelpers.AddScenePresence(scene, TestHelpers.ParseTail(0x2)); - TestClient tc2 = (TestClient)sp2.ControllingClient; - gm.JoinGroupRequest(tc2, groupID); - gm.SetGroupAcceptNotices(tc2, groupID, false, true); - - List spReceivedMessages = new List(); - tc.OnReceivedInstantMessage += im => spReceivedMessages.Add(im); - - List sp2ReceivedMessages = new List(); - tc2.OnReceivedInstantMessage += im => sp2ReceivedMessages.Add(im); - - GridInstantMessage noticeIm = new GridInstantMessage(); - noticeIm.fromAgentID = userId.Guid; - noticeIm.toAgentID = groupID.Guid; - noticeIm.message = combinedSubjectMessage; - noticeIm.dialog = (byte)InstantMessageDialog.GroupNotice; - - tc.HandleImprovedInstantMessage(noticeIm); - - Assert.That(spReceivedMessages.Count, Is.EqualTo(1)); - Assert.That(spReceivedMessages[0].message, Is.EqualTo(combinedSubjectMessage)); - - List notices = mgsc.GetGroupNotices(UUID.Zero, groupID); - Assert.AreEqual(1, notices.Count); - - // OpenSimulator (possibly also SL) transport the notice ID as the session ID! - Assert.AreEqual(notices[0].NoticeID.Guid, spReceivedMessages[0].imSessionID); - - Assert.That(sp2ReceivedMessages.Count, Is.EqualTo(0)); - } - - /// - /// Run test with the MessageOnlineUsersOnly flag set. - /// - [Test] - public void TestSendGroupNoticeOnlineOnly() - { - TestHelpers.InMethod(); - // TestHelpers.EnableLogging(); - - TestScene scene = new SceneHelpers().SetupScene(); - - MessageTransferModule mtm = new MessageTransferModule(); - GroupsModule gm = new GroupsModule(); - GroupsMessagingModule gmm = new GroupsMessagingModule(); - - IConfigSource configSource = new IniConfigSource(); - - { - IConfig config = configSource.AddConfig("Messaging"); - config.Set("MessageTransferModule", mtm.Name); - } - - { - IConfig config = configSource.AddConfig("Groups"); - config.Set("Enabled", true); - config.Set("Module", gm.Name); - config.Set("DebugEnabled", true); - config.Set("MessagingModule", gmm.Name); - config.Set("MessagingEnabled", true); - config.Set("MessageOnlineUsersOnly", true); - } - - SceneHelpers.SetupSceneModules(scene, configSource, new MockGroupsServicesConnector(), mtm, gm, gmm); - - UUID userId = TestHelpers.ParseTail(0x1); - string subjectText = "newman"; - string messageText = "Hello"; - string combinedSubjectMessage = string.Format("{0}|{1}", subjectText, messageText); - - ScenePresence sp = SceneHelpers.AddScenePresence(scene, TestHelpers.ParseTail(0x1)); - TestClient tc = (TestClient)sp.ControllingClient; - - UUID groupID = gm.CreateGroup(tc, "group1", null, true, UUID.Zero, 0, true, true, true); - gm.JoinGroupRequest(tc, groupID); - - // Create a second user who doesn't want to receive notices - ScenePresence sp2 = SceneHelpers.AddScenePresence(scene, TestHelpers.ParseTail(0x2)); - TestClient tc2 = (TestClient)sp2.ControllingClient; - gm.JoinGroupRequest(tc2, groupID); - gm.SetGroupAcceptNotices(tc2, groupID, false, true); - - List spReceivedMessages = new List(); - tc.OnReceivedInstantMessage += im => spReceivedMessages.Add(im); - - List sp2ReceivedMessages = new List(); - tc2.OnReceivedInstantMessage += im => sp2ReceivedMessages.Add(im); - - GridInstantMessage noticeIm = new GridInstantMessage(); - noticeIm.fromAgentID = userId.Guid; - noticeIm.toAgentID = groupID.Guid; - noticeIm.message = combinedSubjectMessage; - noticeIm.dialog = (byte)InstantMessageDialog.GroupNotice; - - tc.HandleImprovedInstantMessage(noticeIm); - - Assert.That(spReceivedMessages.Count, Is.EqualTo(1)); - Assert.That(spReceivedMessages[0].message, Is.EqualTo(combinedSubjectMessage)); - - Assert.That(sp2ReceivedMessages.Count, Is.EqualTo(0)); - } - } -} \ No newline at end of file diff --git a/OpenSim/Region/OptionalModules/OpenSim.Region.OptionalModules.csproj b/OpenSim/Region/OptionalModules/OpenSim.Region.OptionalModules.csproj index 4e082e7f9e2..288527cc610 100644 --- a/OpenSim/Region/OptionalModules/OpenSim.Region.OptionalModules.csproj +++ b/OpenSim/Region/OptionalModules/OpenSim.Region.OptionalModules.csproj @@ -31,9 +31,6 @@ ..\..\..\bin\OpenMetaverseTypes.dll False - - False - False @@ -73,4 +70,4 @@ - \ No newline at end of file + diff --git a/OpenSim/Region/OptionalModules/Scripting/JsonStore/Tests/JsonStoreScriptModuleTests.cs b/OpenSim/Region/OptionalModules/Scripting/JsonStore/Tests/JsonStoreScriptModuleTests.cs deleted file mode 100644 index 77ee7855a52..00000000000 --- a/OpenSim/Region/OptionalModules/Scripting/JsonStore/Tests/JsonStoreScriptModuleTests.cs +++ /dev/null @@ -1,900 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections.Generic; -using System.Reflection; -using System.Text; -using log4net; -using Nini.Config; -using NUnit.Framework; -using OpenMetaverse; -using OpenSim.Framework; -using OpenSim.Region.CoreModules.Scripting.ScriptModuleComms; -using OpenSim.Region.Framework.Scenes; -using OpenSim.Region.ScriptEngine.Shared; -using OpenSim.Region.ScriptEngine.Shared.Api; -using OpenSim.Services.Interfaces; -using OpenSim.Tests.Common; - -namespace OpenSim.Region.OptionalModules.Scripting.JsonStore.Tests -{ - /// - /// Tests for inventory functions in LSL - /// - [TestFixture] - public class JsonStoreScriptModuleTests : OpenSimTestCase - { - private Scene m_scene; - private MockScriptEngine m_engine; - private ScriptModuleCommsModule m_smcm; - private JsonStoreScriptModule m_jssm; - - [TestFixtureSetUp] - public void FixtureInit() - { - // Don't allow tests to be bamboozled by asynchronous events. Execute everything on the same thread. - Util.FireAndForgetMethod = FireAndForgetMethod.RegressionTest; - } - - [TestFixtureTearDown] - public void TearDown() - { - // We must set this back afterwards, otherwise later tests will fail since they're expecting multiple - // threads. Possibly, later tests should be rewritten so none of them require async stuff (which regression - // tests really shouldn't). - Util.FireAndForgetMethod = Util.DefaultFireAndForgetMethod; - } - - [SetUp] - public override void SetUp() - { - base.SetUp(); - - IConfigSource configSource = new IniConfigSource(); - IConfig jsonStoreConfig = configSource.AddConfig("JsonStore"); - jsonStoreConfig.Set("Enabled", "true"); - - m_engine = new MockScriptEngine(); - m_smcm = new ScriptModuleCommsModule(); - JsonStoreModule jsm = new JsonStoreModule(); - m_jssm = new JsonStoreScriptModule(); - - m_scene = new SceneHelpers().SetupScene(); - SceneHelpers.SetupSceneModules(m_scene, configSource, m_engine, m_smcm, jsm, m_jssm); - - try - { - m_smcm.RegisterScriptInvocation(this, "DummyTestMethod"); - } - catch (ArgumentException) - { - Assert.Ignore("Ignoring test since running on .NET 3.5 or earlier."); - } - - // XXX: Unfortunately, ICommsModule currently has no way of deregistering methods. - } - - private object InvokeOp(string name, params object[] args) - { - return InvokeOpOnHost(name, UUID.Zero, args); - } - - private object InvokeOpOnHost(string name, UUID hostId, params object[] args) - { - return m_smcm.InvokeOperation(hostId, UUID.Zero, name, args); - } - - [Test] - public void TestJsonCreateStore() - { - TestHelpers.InMethod(); -// TestHelpers.EnableLogging(); - - // Test blank store - { - UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{}"); - Assert.That(storeId, Is.Not.EqualTo(UUID.Zero)); - } - - // Test single element store - { - UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{ 'Hello' : 'World' }"); - Assert.That(storeId, Is.Not.EqualTo(UUID.Zero)); - } - - // Test with an integer value - { - UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{ 'Hello' : 42.15 }"); - Assert.That(storeId, Is.Not.EqualTo(UUID.Zero)); - - string value = (string)InvokeOp("JsonGetValue", storeId, "Hello"); - Assert.That(value, Is.EqualTo("42.15")); - } - - // Test with an array as the root node - { - UUID storeId = (UUID)InvokeOp("JsonCreateStore", "[ 'one', 'two', 'three' ]"); - Assert.That(storeId, Is.Not.EqualTo(UUID.Zero)); - - string value = (string)InvokeOp("JsonGetValue", storeId, "[1]"); - Assert.That(value, Is.EqualTo("two")); - } - } - - [Test] - public void TestJsonDestroyStore() - { - TestHelpers.InMethod(); -// TestHelpers.EnableLogging(); - - UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{ 'Hello' : 'World' }"); - int dsrv = (int)InvokeOp("JsonDestroyStore", storeId); - - Assert.That(dsrv, Is.EqualTo(1)); - - int tprv = (int)InvokeOp("JsonGetNodeType", storeId, "Hello"); - Assert.That(tprv, Is.EqualTo(JsonStoreScriptModule.JSON_NODETYPE_UNDEF)); - } - - [Test] - public void TestJsonDestroyStoreNotExists() - { - TestHelpers.InMethod(); -// TestHelpers.EnableLogging(); - - UUID fakeStoreId = TestHelpers.ParseTail(0x500); - - int dsrv = (int)InvokeOp("JsonDestroyStore", fakeStoreId); - - Assert.That(dsrv, Is.EqualTo(0)); - } - - [Test] - public void TestJsonGetValue() - { - TestHelpers.InMethod(); -// TestHelpers.EnableLogging(); - - UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{ 'Hello' : { 'World' : 'Two' } }"); - - { - string value = (string)InvokeOp("JsonGetValue", storeId, "Hello.World"); - Assert.That(value, Is.EqualTo("Two")); - } - - // Test get of path section instead of leaf - { - string value = (string)InvokeOp("JsonGetValue", storeId, "Hello"); - Assert.That(value, Is.EqualTo("")); - } - - // Test get of non-existing value - { - string fakeValueGet = (string)InvokeOp("JsonGetValue", storeId, "foo"); - Assert.That(fakeValueGet, Is.EqualTo("")); - } - - // Test get from non-existing store - { - UUID fakeStoreId = TestHelpers.ParseTail(0x500); - string fakeStoreValueGet = (string)InvokeOp("JsonGetValue", fakeStoreId, "Hello"); - Assert.That(fakeStoreValueGet, Is.EqualTo("")); - } - } - - [Test] - public void TestJsonGetJson() - { - TestHelpers.InMethod(); -// TestHelpers.EnableLogging(); - - UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{ 'Hello' : { 'World' : 'Two' } }"); - - { - string value = (string)InvokeOp("JsonGetJson", storeId, "Hello.World"); - Assert.That(value, Is.EqualTo("'Two'")); - } - - // Test get of path section instead of leaf - { - string value = (string)InvokeOp("JsonGetJson", storeId, "Hello"); - Assert.That(value, Is.EqualTo("{\"World\":\"Two\"}")); - } - - // Test get of non-existing value - { - string fakeValueGet = (string)InvokeOp("JsonGetJson", storeId, "foo"); - Assert.That(fakeValueGet, Is.EqualTo("")); - } - - // Test get from non-existing store - { - UUID fakeStoreId = TestHelpers.ParseTail(0x500); - string fakeStoreValueGet = (string)InvokeOp("JsonGetJson", fakeStoreId, "Hello"); - Assert.That(fakeStoreValueGet, Is.EqualTo("")); - } - } - -// [Test] -// public void TestJsonTakeValue() -// { -// TestHelpers.InMethod(); -//// TestHelpers.EnableLogging(); -// -// UUID storeId -// = (UUID)m_smcm.InvokeOperation( -// UUID.Zero, UUID.Zero, "JsonCreateStore", new object[] { "{ 'Hello' : 'World' }" }); -// -// string value -// = (string)m_smcm.InvokeOperation( -// UUID.Zero, UUID.Zero, "JsonTakeValue", new object[] { storeId, "Hello" }); -// -// Assert.That(value, Is.EqualTo("World")); -// -// string value2 -// = (string)m_smcm.InvokeOperation( -// UUID.Zero, UUID.Zero, "JsonGetValue", new object[] { storeId, "Hello" }); -// -// Assert.That(value, Is.Null); -// } - - [Test] - public void TestJsonRemoveValue() - { - TestHelpers.InMethod(); -// TestHelpers.EnableLogging(); - - // Test remove of node in object pointing to a string - { - UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{ 'Hello' : 'World' }"); - - int returnValue = (int)InvokeOp( "JsonRemoveValue", storeId, "Hello"); - Assert.That(returnValue, Is.EqualTo(1)); - - int result = (int)InvokeOp("JsonGetNodeType", storeId, "Hello"); - Assert.That(result, Is.EqualTo(JsonStoreScriptModule.JSON_NODETYPE_UNDEF)); - - string returnValue2 = (string)InvokeOp("JsonGetValue", storeId, "Hello"); - Assert.That(returnValue2, Is.EqualTo("")); - } - - // Test remove of node in object pointing to another object - { - UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{ 'Hello' : { 'World' : 'Wally' } }"); - - int returnValue = (int)InvokeOp( "JsonRemoveValue", storeId, "Hello"); - Assert.That(returnValue, Is.EqualTo(1)); - - int result = (int)InvokeOp("JsonGetNodeType", storeId, "Hello"); - Assert.That(result, Is.EqualTo(JsonStoreScriptModule.JSON_NODETYPE_UNDEF)); - - string returnValue2 = (string)InvokeOp("JsonGetJson", storeId, "Hello"); - Assert.That(returnValue2, Is.EqualTo("")); - } - - // Test remove of node in an array - { - UUID storeId - = (UUID)InvokeOp("JsonCreateStore", "{ 'Hello' : [ 'value1', 'value2' ] }"); - - int returnValue = (int)InvokeOp( "JsonRemoveValue", storeId, "Hello[0]"); - Assert.That(returnValue, Is.EqualTo(1)); - - int result = (int)InvokeOp("JsonGetNodeType", storeId, "Hello[0]"); - Assert.That(result, Is.EqualTo(JsonStoreScriptModule.JSON_NODETYPE_VALUE)); - - result = (int)InvokeOp("JsonGetNodeType", storeId, "Hello[1]"); - Assert.That(result, Is.EqualTo(JsonStoreScriptModule.JSON_NODETYPE_UNDEF)); - - string stringReturnValue = (string)InvokeOp("JsonGetValue", storeId, "Hello[0]"); - Assert.That(stringReturnValue, Is.EqualTo("value2")); - - stringReturnValue = (string)InvokeOp("JsonGetJson", storeId, "Hello[1]"); - Assert.That(stringReturnValue, Is.EqualTo("")); - } - - // Test remove of non-existing value - { - UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{ 'Hello' : 'World' }"); - - int fakeValueRemove = (int)InvokeOp("JsonRemoveValue", storeId, "Cheese"); - Assert.That(fakeValueRemove, Is.EqualTo(0)); - } - - { - // Test get from non-existing store - UUID fakeStoreId = TestHelpers.ParseTail(0x500); - int fakeStoreValueRemove = (int)InvokeOp("JsonRemoveValue", fakeStoreId, "Hello"); - Assert.That(fakeStoreValueRemove, Is.EqualTo(0)); - } - } - -// [Test] -// public void TestJsonTestPath() -// { -// TestHelpers.InMethod(); -//// TestHelpers.EnableLogging(); -// -// UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{ 'Hello' : { 'World' : 'One' } }"); -// -// { -// int result = (int)InvokeOp("JsonTestPath", storeId, "Hello.World"); -// Assert.That(result, Is.EqualTo(1)); -// } -// -// // Test for path which does not resolve to a value. -// { -// int result = (int)InvokeOp("JsonTestPath", storeId, "Hello"); -// Assert.That(result, Is.EqualTo(0)); -// } -// -// { -// int result2 = (int)InvokeOp("JsonTestPath", storeId, "foo"); -// Assert.That(result2, Is.EqualTo(0)); -// } -// -// // Test with fake store -// { -// UUID fakeStoreId = TestHelpers.ParseTail(0x500); -// int fakeStoreValueRemove = (int)InvokeOp("JsonTestPath", fakeStoreId, "Hello"); -// Assert.That(fakeStoreValueRemove, Is.EqualTo(0)); -// } -// } - -// [Test] -// public void TestJsonTestPathJson() -// { -// TestHelpers.InMethod(); -//// TestHelpers.EnableLogging(); -// -// UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{ 'Hello' : { 'World' : 'One' } }"); -// -// { -// int result = (int)InvokeOp("JsonTestPathJson", storeId, "Hello.World"); -// Assert.That(result, Is.EqualTo(1)); -// } -// -// // Test for path which does not resolve to a value. -// { -// int result = (int)InvokeOp("JsonTestPathJson", storeId, "Hello"); -// Assert.That(result, Is.EqualTo(1)); -// } -// -// { -// int result2 = (int)InvokeOp("JsonTestPathJson", storeId, "foo"); -// Assert.That(result2, Is.EqualTo(0)); -// } -// -// // Test with fake store -// { -// UUID fakeStoreId = TestHelpers.ParseTail(0x500); -// int fakeStoreValueRemove = (int)InvokeOp("JsonTestPathJson", fakeStoreId, "Hello"); -// Assert.That(fakeStoreValueRemove, Is.EqualTo(0)); -// } -// } - - [Test] - public void TestJsonGetArrayLength() - { - TestHelpers.InMethod(); -// TestHelpers.EnableLogging(); - - UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{ 'Hello' : { 'World' : [ 'one', 2 ] } }"); - - { - int result = (int)InvokeOp("JsonGetArrayLength", storeId, "Hello.World"); - Assert.That(result, Is.EqualTo(2)); - } - - // Test path which is not an array - { - int result = (int)InvokeOp("JsonGetArrayLength", storeId, "Hello"); - Assert.That(result, Is.EqualTo(-1)); - } - - // Test fake path - { - int result = (int)InvokeOp("JsonGetArrayLength", storeId, "foo"); - Assert.That(result, Is.EqualTo(-1)); - } - - // Test fake store - { - UUID fakeStoreId = TestHelpers.ParseTail(0x500); - int result = (int)InvokeOp("JsonGetArrayLength", fakeStoreId, "Hello.World"); - Assert.That(result, Is.EqualTo(-1)); - } - } - - [Test] - public void TestJsonGetNodeType() - { - TestHelpers.InMethod(); -// TestHelpers.EnableLogging(); - - UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{ 'Hello' : { 'World' : [ 'one', 2 ] } }"); - - { - int result = (int)InvokeOp("JsonGetNodeType", storeId, "."); - Assert.That(result, Is.EqualTo(JsonStoreScriptModule.JSON_NODETYPE_OBJECT)); - } - - { - int result = (int)InvokeOp("JsonGetNodeType", storeId, "Hello"); - Assert.That(result, Is.EqualTo(JsonStoreScriptModule.JSON_NODETYPE_OBJECT)); - } - - { - int result = (int)InvokeOp("JsonGetNodeType", storeId, "Hello.World"); - Assert.That(result, Is.EqualTo(JsonStoreScriptModule.JSON_NODETYPE_ARRAY)); - } - - { - int result = (int)InvokeOp("JsonGetNodeType", storeId, "Hello.World[0]"); - Assert.That(result, Is.EqualTo(JsonStoreScriptModule.JSON_NODETYPE_VALUE)); - } - - { - int result = (int)InvokeOp("JsonGetNodeType", storeId, "Hello.World[1]"); - Assert.That(result, Is.EqualTo(JsonStoreScriptModule.JSON_NODETYPE_VALUE)); - } - - // Test for non-existent path - { - int result = (int)InvokeOp("JsonGetNodeType", storeId, "foo"); - Assert.That(result, Is.EqualTo(JsonStoreScriptModule.JSON_NODETYPE_UNDEF)); - } - - // Test for non-existent store - { - UUID fakeStoreId = TestHelpers.ParseTail(0x500); - int result = (int)InvokeOp("JsonGetNodeType", fakeStoreId, "."); - Assert.That(result, Is.EqualTo(JsonStoreScriptModule.JSON_NODETYPE_UNDEF)); - } - } - - [Test] - public void TestJsonList2Path() - { - TestHelpers.InMethod(); -// TestHelpers.EnableLogging(); - - // Invoking these methods directly since I just couldn't get comms module invocation to work for some reason - // - some confusion with the methods that take a params object[] invocation. - { - string result = m_jssm.JsonList2Path(UUID.Zero, UUID.Zero, new object[] { "foo" }); - Assert.That(result, Is.EqualTo("{foo}")); - } - - { - string result = m_jssm.JsonList2Path(UUID.Zero, UUID.Zero, new object[] { "foo", "bar" }); - Assert.That(result, Is.EqualTo("{foo}.{bar}")); - } - - { - string result = m_jssm.JsonList2Path(UUID.Zero, UUID.Zero, new object[] { "foo", 1, "bar" }); - Assert.That(result, Is.EqualTo("{foo}.[1].{bar}")); - } - } - - [Test] - public void TestJsonSetValue() - { - TestHelpers.InMethod(); -// TestHelpers.EnableLogging(); - - { - UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{}"); - - int result = (int)InvokeOp("JsonSetValue", storeId, "Fun", "Times"); - Assert.That(result, Is.EqualTo(1)); - - string value = (string)InvokeOp("JsonGetValue", storeId, "Fun"); - Assert.That(value, Is.EqualTo("Times")); - } - - // Test setting a key containing periods with delineation - { - UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{}"); - - int result = (int)InvokeOp("JsonSetValue", storeId, "{Fun.Circus}", "Times"); - Assert.That(result, Is.EqualTo(1)); - - string value = (string)InvokeOp("JsonGetValue", storeId, "{Fun.Circus}"); - Assert.That(value, Is.EqualTo("Times")); - } - - // *** Test [] *** - - // Test setting a key containing unbalanced ] without delineation. Expecting failure - { - UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{}"); - - int result = (int)InvokeOp("JsonSetValue", storeId, "Fun]Circus", "Times"); - Assert.That(result, Is.EqualTo(0)); - - string value = (string)InvokeOp("JsonGetValue", storeId, "Fun]Circus"); - Assert.That(value, Is.EqualTo("")); - } - - // Test setting a key containing unbalanced [ without delineation. Expecting failure - { - UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{}"); - - int result = (int)InvokeOp("JsonSetValue", storeId, "Fun[Circus", "Times"); - Assert.That(result, Is.EqualTo(0)); - - string value = (string)InvokeOp("JsonGetValue", storeId, "Fun[Circus"); - Assert.That(value, Is.EqualTo("")); - } - - // Test setting a key containing unbalanced [] without delineation. Expecting failure - { - UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{}"); - - int result = (int)InvokeOp("JsonSetValue", storeId, "Fun[]Circus", "Times"); - Assert.That(result, Is.EqualTo(0)); - - string value = (string)InvokeOp("JsonGetValue", storeId, "Fun[]Circus"); - Assert.That(value, Is.EqualTo("")); - } - - // Test setting a key containing unbalanced ] with delineation - { - UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{}"); - - int result = (int)InvokeOp("JsonSetValue", storeId, "{Fun]Circus}", "Times"); - Assert.That(result, Is.EqualTo(1)); - - string value = (string)InvokeOp("JsonGetValue", storeId, "{Fun]Circus}"); - Assert.That(value, Is.EqualTo("Times")); - } - - // Test setting a key containing unbalanced [ with delineation - { - UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{}"); - - int result = (int)InvokeOp("JsonSetValue", storeId, "{Fun[Circus}", "Times"); - Assert.That(result, Is.EqualTo(1)); - - string value = (string)InvokeOp("JsonGetValue", storeId, "{Fun[Circus}"); - Assert.That(value, Is.EqualTo("Times")); - } - - // Test setting a key containing empty balanced [] with delineation - { - UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{}"); - - int result = (int)InvokeOp("JsonSetValue", storeId, "{Fun[]Circus}", "Times"); - Assert.That(result, Is.EqualTo(1)); - - string value = (string)InvokeOp("JsonGetValue", storeId, "{Fun[]Circus}"); - Assert.That(value, Is.EqualTo("Times")); - } - -// // Commented out as this currently unexpectedly fails. -// // Test setting a key containing brackets around an integer with delineation -// { -// UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{}"); -// -// int result = (int)InvokeOp("JsonSetValue", storeId, "{Fun[0]Circus}", "Times"); -// Assert.That(result, Is.EqualTo(1)); -// -// string value = (string)InvokeOp("JsonGetValue", storeId, "{Fun[0]Circus}"); -// Assert.That(value, Is.EqualTo("Times")); -// } - - // *** Test {} *** - - // Test setting a key containing unbalanced } without delineation. Expecting failure (?) - { - UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{}"); - - int result = (int)InvokeOp("JsonSetValue", storeId, "Fun}Circus", "Times"); - Assert.That(result, Is.EqualTo(0)); - - string value = (string)InvokeOp("JsonGetValue", storeId, "Fun}Circus"); - Assert.That(value, Is.EqualTo("")); - } - - // Test setting a key containing unbalanced { without delineation. Expecting failure (?) - { - UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{}"); - - int result = (int)InvokeOp("JsonSetValue", storeId, "Fun{Circus", "Times"); - Assert.That(result, Is.EqualTo(0)); - - string value = (string)InvokeOp("JsonGetValue", storeId, "Fun}Circus"); - Assert.That(value, Is.EqualTo("")); - } - -// // Commented out as this currently unexpectedly fails. -// // Test setting a key containing unbalanced } -// { -// UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{}"); -// -// int result = (int)InvokeOp("JsonSetValue", storeId, "{Fun}Circus}", "Times"); -// Assert.That(result, Is.EqualTo(0)); -// } - - // Test setting a key containing unbalanced { with delineation - { - UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{}"); - - int result = (int)InvokeOp("JsonSetValue", storeId, "{Fun{Circus}", "Times"); - Assert.That(result, Is.EqualTo(1)); - - string value = (string)InvokeOp("JsonGetValue", storeId, "{Fun{Circus}"); - Assert.That(value, Is.EqualTo("Times")); - } - - // Test setting a key containing balanced {} with delineation. This should fail. - { - UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{}"); - - int result = (int)InvokeOp("JsonSetValue", storeId, "{Fun{Filled}Circus}", "Times"); - Assert.That(result, Is.EqualTo(0)); - - string value = (string)InvokeOp("JsonGetValue", storeId, "{Fun{Filled}Circus}"); - Assert.That(value, Is.EqualTo("")); - } - - // Test setting to location that does not exist. This should fail. - { - UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{}"); - - int result = (int)InvokeOp("JsonSetValue", storeId, "Fun.Circus", "Times"); - Assert.That(result, Is.EqualTo(0)); - - string value = (string)InvokeOp("JsonGetValue", storeId, "Fun.Circus"); - Assert.That(value, Is.EqualTo("")); - } - - // Test with fake store - { - UUID fakeStoreId = TestHelpers.ParseTail(0x500); - int fakeStoreValueSet = (int)InvokeOp("JsonSetValue", fakeStoreId, "Hello", "World"); - Assert.That(fakeStoreValueSet, Is.EqualTo(0)); - } - } - - [Test] - public void TestJsonSetJson() - { - TestHelpers.InMethod(); -// TestHelpers.EnableLogging(); - - // Single quoted token case - { - UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{ }"); - - int result = (int)InvokeOp("JsonSetJson", storeId, "Fun", "'Times'"); - Assert.That(result, Is.EqualTo(1)); - - string value = (string)InvokeOp("JsonGetValue", storeId, "Fun"); - Assert.That(value, Is.EqualTo("Times")); - } - - // Sub-tree case - { - UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{ }"); - - int result = (int)InvokeOp("JsonSetJson", storeId, "Fun", "{ 'Filled' : 'Times' }"); - Assert.That(result, Is.EqualTo(1)); - - string value = (string)InvokeOp("JsonGetValue", storeId, "Fun.Filled"); - Assert.That(value, Is.EqualTo("Times")); - } - - // If setting single strings in JsonSetValueJson, these must be single quoted tokens, not bare strings. - { - UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{ }"); - - int result = (int)InvokeOp("JsonSetJson", storeId, "Fun", "Times"); - Assert.That(result, Is.EqualTo(0)); - - string value = (string)InvokeOp("JsonGetValue", storeId, "Fun"); - Assert.That(value, Is.EqualTo("")); - } - - // Test setting to location that does not exist. This should fail. - { - UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{ }"); - - int result = (int)InvokeOp("JsonSetJson", storeId, "Fun.Circus", "'Times'"); - Assert.That(result, Is.EqualTo(0)); - - string value = (string)InvokeOp("JsonGetValue", storeId, "Fun.Circus"); - Assert.That(value, Is.EqualTo("")); - } - - // Test with fake store - { - UUID fakeStoreId = TestHelpers.ParseTail(0x500); - int fakeStoreValueSet = (int)InvokeOp("JsonSetJson", fakeStoreId, "Hello", "'World'"); - Assert.That(fakeStoreValueSet, Is.EqualTo(0)); - } - } - - /// - /// Test for writing json to a notecard - /// - /// - /// TODO: Really needs to test correct receipt of the link_message event. Could do this by directly fetching - /// it via the MockScriptEngine or perhaps by a dummy script instance. - /// - [Test] - public void TestJsonWriteNotecard() - { - TestHelpers.InMethod(); -// TestHelpers.EnableLogging(); - - SceneObjectGroup so = SceneHelpers.CreateSceneObject(1, TestHelpers.ParseTail(0x1)); - m_scene.AddSceneObject(so); - - UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{ 'Hello':'World' }"); - - { - string notecardName = "nc1"; - - // Write notecard - UUID writeNotecardRequestId = (UUID)InvokeOpOnHost("JsonWriteNotecard", so.UUID, storeId, "", notecardName); - Assert.That(writeNotecardRequestId, Is.Not.EqualTo(UUID.Zero)); - - TaskInventoryItem nc1Item = so.RootPart.Inventory.GetInventoryItem(notecardName); - Assert.That(nc1Item, Is.Not.Null); - - // TODO: Should independently check the contents. - } - - // TODO: Write partial test - - { - // Try to write notecard for a bad path - // In this case we do get a request id but no notecard is written. - string badPathNotecardName = "badPathNotecardName"; - - UUID writeNotecardBadPathRequestId - = (UUID)InvokeOpOnHost("JsonWriteNotecard", so.UUID, storeId, "flibble", badPathNotecardName); - Assert.That(writeNotecardBadPathRequestId, Is.Not.EqualTo(UUID.Zero)); - - TaskInventoryItem badPathItem = so.RootPart.Inventory.GetInventoryItem(badPathNotecardName); - Assert.That(badPathItem, Is.Null); - } - - { - // Test with fake store - // In this case we do get a request id but no notecard is written. - string fakeStoreNotecardName = "fakeStoreNotecardName"; - - UUID fakeStoreId = TestHelpers.ParseTail(0x500); - UUID fakeStoreWriteNotecardValue - = (UUID)InvokeOpOnHost("JsonWriteNotecard", so.UUID, fakeStoreId, "", fakeStoreNotecardName); - Assert.That(fakeStoreWriteNotecardValue, Is.Not.EqualTo(UUID.Zero)); - - TaskInventoryItem fakeStoreItem = so.RootPart.Inventory.GetInventoryItem(fakeStoreNotecardName); - Assert.That(fakeStoreItem, Is.Null); - } - } - - /// - /// Test for reading json from a notecard - /// - /// - /// TODO: Really needs to test correct receipt of the link_message event. Could do this by directly fetching - /// it via the MockScriptEngine or perhaps by a dummy script instance. - /// - [Test] - public void TestJsonReadNotecard() - { - TestHelpers.InMethod(); -// TestHelpers.EnableLogging(); - - string notecardName = "nc1"; - - SceneObjectGroup so = SceneHelpers.CreateSceneObject(1, TestHelpers.ParseTail(0x1)); - m_scene.AddSceneObject(so); - - UUID creatingStoreId = (UUID)InvokeOp("JsonCreateStore", "{ 'Hello':'World' }"); - - // Write notecard - InvokeOpOnHost("JsonWriteNotecard", so.UUID, creatingStoreId, "", notecardName); - - { - // Read notecard - UUID receivingStoreId = (UUID)InvokeOp("JsonCreateStore", "{}"); - UUID readNotecardRequestId = (UUID)InvokeOpOnHost("JsonReadNotecard", so.UUID, receivingStoreId, "", notecardName); - Assert.That(readNotecardRequestId, Is.Not.EqualTo(UUID.Zero)); - - string value = (string)InvokeOp("JsonGetValue", receivingStoreId, "Hello"); - Assert.That(value, Is.EqualTo("World")); - } - - { - // Read notecard to new single component path - UUID receivingStoreId = (UUID)InvokeOp("JsonCreateStore", "{}"); - UUID readNotecardRequestId = (UUID)InvokeOpOnHost("JsonReadNotecard", so.UUID, receivingStoreId, "make", notecardName); - Assert.That(readNotecardRequestId, Is.Not.EqualTo(UUID.Zero)); - - string value = (string)InvokeOp("JsonGetValue", receivingStoreId, "Hello"); - Assert.That(value, Is.EqualTo("")); - - value = (string)InvokeOp("JsonGetValue", receivingStoreId, "make.Hello"); - Assert.That(value, Is.EqualTo("World")); - } - - { - // Read notecard to new multi-component path. This should not work. - UUID receivingStoreId = (UUID)InvokeOp("JsonCreateStore", "{}"); - UUID readNotecardRequestId = (UUID)InvokeOpOnHost("JsonReadNotecard", so.UUID, receivingStoreId, "make.it", notecardName); - Assert.That(readNotecardRequestId, Is.Not.EqualTo(UUID.Zero)); - - string value = (string)InvokeOp("JsonGetValue", receivingStoreId, "Hello"); - Assert.That(value, Is.EqualTo("")); - - value = (string)InvokeOp("JsonGetValue", receivingStoreId, "make.it.Hello"); - Assert.That(value, Is.EqualTo("")); - } - - { - // Read notecard to existing multi-component path. This should work - UUID receivingStoreId = (UUID)InvokeOp("JsonCreateStore", "{ 'make' : { 'it' : 'so' } }"); - UUID readNotecardRequestId = (UUID)InvokeOpOnHost("JsonReadNotecard", so.UUID, receivingStoreId, "make.it", notecardName); - Assert.That(readNotecardRequestId, Is.Not.EqualTo(UUID.Zero)); - - string value = (string)InvokeOp("JsonGetValue", receivingStoreId, "Hello"); - Assert.That(value, Is.EqualTo("")); - - value = (string)InvokeOp("JsonGetValue", receivingStoreId, "make.it.Hello"); - Assert.That(value, Is.EqualTo("World")); - } - - { - // Read notecard to invalid path. This should not work. - UUID receivingStoreId = (UUID)InvokeOp("JsonCreateStore", "{ 'make' : { 'it' : 'so' } }"); - UUID readNotecardRequestId = (UUID)InvokeOpOnHost("JsonReadNotecard", so.UUID, receivingStoreId, "/", notecardName); - Assert.That(readNotecardRequestId, Is.Not.EqualTo(UUID.Zero)); - - string value = (string)InvokeOp("JsonGetValue", receivingStoreId, "Hello"); - Assert.That(value, Is.EqualTo("")); - } - - { - // Try read notecard to fake store. - UUID fakeStoreId = TestHelpers.ParseTail(0x500); - UUID readNotecardRequestId = (UUID)InvokeOpOnHost("JsonReadNotecard", so.UUID, fakeStoreId, "", notecardName); - Assert.That(readNotecardRequestId, Is.Not.EqualTo(UUID.Zero)); - - string value = (string)InvokeOp("JsonGetValue", fakeStoreId, "Hello"); - Assert.That(value, Is.EqualTo("")); - } - } - - public object DummyTestMethod(object o1, object o2, object o3, object o4, object o5) { return null; } - } -} diff --git a/OpenSim/Region/OptionalModules/World/NPC/Tests/NPCModuleTests.cs b/OpenSim/Region/OptionalModules/World/NPC/Tests/NPCModuleTests.cs deleted file mode 100644 index 9a1ea732748..00000000000 --- a/OpenSim/Region/OptionalModules/World/NPC/Tests/NPCModuleTests.cs +++ /dev/null @@ -1,486 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections.Generic; -using System.Reflection; -using log4net; -using Nini.Config; -using NUnit.Framework; -using OpenMetaverse; -using OpenSim.Framework; -using OpenSim.Region.CoreModules.Avatar.Attachments; -using OpenSim.Region.CoreModules.Avatar.AvatarFactory; -using OpenSim.Region.CoreModules.Framework.InventoryAccess; -using OpenSim.Region.CoreModules.Framework.UserManagement; -using OpenSim.Region.CoreModules.ServiceConnectorsOut.Avatar; -using OpenSim.Region.Framework.Interfaces; -using OpenSim.Region.Framework.Scenes; -using OpenSim.Services.AvatarService; -using OpenSim.Tests.Common; - -namespace OpenSim.Region.OptionalModules.World.NPC.Tests -{ - [TestFixture] - public class NPCModuleTests : OpenSimTestCase - { - private TestScene m_scene; - private AvatarFactoryModule m_afMod; - private UserManagementModule m_umMod; - private AttachmentsModule m_attMod; - private NPCModule m_npcMod; - - [TestFixtureSetUp] - public void FixtureInit() - { - // Don't allow tests to be bamboozled by asynchronous events. Execute everything on the same thread. - Util.FireAndForgetMethod = FireAndForgetMethod.None; - } - - [TestFixtureTearDown] - public void TearDown() - { - // We must set this back afterwards, otherwise later tests will fail since they're expecting multiple - // threads. Possibly, later tests should be rewritten not to worry about such things. - Util.FireAndForgetMethod = Util.DefaultFireAndForgetMethod; - } - - public void SetUpScene() - { - SetUpScene(256, 256); - } - - public void SetUpScene(uint sizeX, uint sizeY) - { - IConfigSource config = new IniConfigSource(); - config.AddConfig("NPC"); - config.Configs["NPC"].Set("Enabled", "true"); - config.AddConfig("Modules"); - config.Configs["Modules"].Set("InventoryAccessModule", "BasicInventoryAccessModule"); - - m_afMod = new AvatarFactoryModule(); - m_umMod = new UserManagementModule(); - m_attMod = new AttachmentsModule(); - m_npcMod = new NPCModule(); - - m_scene = new SceneHelpers().SetupScene("test scene", UUID.Random(), 1000, 1000, sizeX, sizeY, config); - SceneHelpers.SetupSceneModules(m_scene, config, m_afMod, m_umMod, m_attMod, m_npcMod, new BasicInventoryAccessModule()); - } - - [Test] - public void TestCreate() - { - TestHelpers.InMethod(); -// log4net.Config.XmlConfigurator.Configure(); - - SetUpScene(); - - ScenePresence sp = SceneHelpers.AddScenePresence(m_scene, TestHelpers.ParseTail(0x1)); -// ScenePresence originalAvatar = scene.GetScenePresence(originalClient.AgentId); - - // 8 is the index of the first baked texture in AvatarAppearance - UUID originalFace8TextureId = TestHelpers.ParseTail(0x10); - Primitive.TextureEntry originalTe = new Primitive.TextureEntry(UUID.Zero); - Primitive.TextureEntryFace originalTef = originalTe.CreateFace(8); - originalTef.TextureID = originalFace8TextureId; - - // We also need to add the texture to the asset service, otherwise the AvatarFactoryModule will tell - // ScenePresence.SendInitialData() to reset our entire appearance. - m_scene.AssetService.Store(AssetHelpers.CreateNotecardAsset(originalFace8TextureId)); - - m_afMod.SetAppearance(sp, originalTe, null, new WearableCacheItem[0] ); - - UUID npcId = m_npcMod.CreateNPC("John", "Smith", new Vector3(128, 128, 30), UUID.Zero, true, m_scene, sp.Appearance); - - ScenePresence npc = m_scene.GetScenePresence(npcId); - - Assert.That(npc, Is.Not.Null); - Assert.That(npc.Appearance.Texture.FaceTextures[8].TextureID, Is.EqualTo(originalFace8TextureId)); - Assert.That(m_umMod.GetUserName(npc.UUID), Is.EqualTo(string.Format("{0} {1}", npc.Firstname, npc.Lastname))); - - IClientAPI client; - Assert.That(m_scene.TryGetClient(npcId, out client), Is.True); - - // Have to account for both SP and NPC. - Assert.That(m_scene.AuthenticateHandler.GetAgentCircuits().Count, Is.EqualTo(2)); - } - - [Test] - public void TestRemove() - { - TestHelpers.InMethod(); -// log4net.Config.XmlConfigurator.Configure(); - - SetUpScene(); - - ScenePresence sp = SceneHelpers.AddScenePresence(m_scene, TestHelpers.ParseTail(0x1)); -// ScenePresence originalAvatar = scene.GetScenePresence(originalClient.AgentId); - - Vector3 startPos = new Vector3(128, 128, 30); - UUID npcId = m_npcMod.CreateNPC("John", "Smith", startPos, UUID.Zero, true, m_scene, sp.Appearance); - - m_npcMod.DeleteNPC(npcId, m_scene); - - ScenePresence deletedNpc = m_scene.GetScenePresence(npcId); - - Assert.That(deletedNpc, Is.Null); - IClientAPI client; - Assert.That(m_scene.TryGetClient(npcId, out client), Is.False); - - // Have to account for SP still present. - Assert.That(m_scene.AuthenticateHandler.GetAgentCircuits().Count, Is.EqualTo(1)); - } - - [Test] - public void TestCreateWithAttachments() - { - TestHelpers.InMethod(); -// TestHelpers.EnableLogging(); - - SetUpScene(); - - UUID userId = TestHelpers.ParseTail(0x1); - UserAccountHelpers.CreateUserWithInventory(m_scene, userId); - ScenePresence sp = SceneHelpers.AddScenePresence(m_scene, userId); - - UUID attItemId = TestHelpers.ParseTail(0x2); - UUID attAssetId = TestHelpers.ParseTail(0x3); - string attName = "att"; - - UserInventoryHelpers.CreateInventoryItem(m_scene, attName, attItemId, attAssetId, sp.UUID, InventoryType.Object); - - m_attMod.RezSingleAttachmentFromInventory(sp, attItemId, (uint)AttachmentPoint.Chest); - - UUID npcId = m_npcMod.CreateNPC("John", "Smith", new Vector3(128, 128, 30), UUID.Zero, true, m_scene, sp.Appearance); - - ScenePresence npc = m_scene.GetScenePresence(npcId); - - // Check scene presence status - Assert.That(npc.HasAttachments(), Is.True); - List attachments = npc.GetAttachments(); - Assert.That(attachments.Count, Is.EqualTo(1)); - SceneObjectGroup attSo = attachments[0]; - - // Just for now, we won't test the name since this is (wrongly) the asset part name rather than the item - // name. TODO: Do need to fix ultimately since the item may be renamed before being passed on to an NPC. -// Assert.That(attSo.Name, Is.EqualTo(attName)); - - Assert.That(attSo.AttachmentPoint, Is.EqualTo((byte)AttachmentPoint.Chest)); - Assert.That(attSo.IsAttachment); - Assert.That(attSo.UsesPhysics, Is.False); - Assert.That(attSo.IsTemporary, Is.False); - Assert.That(attSo.OwnerID, Is.EqualTo(npc.UUID)); - } - - [Test] - public void TestCreateWithMultiAttachments() - { - TestHelpers.InMethod(); -// TestHelpers.EnableLogging(); - - SetUpScene(); -// m_attMod.DebugLevel = 1; - - UUID userId = TestHelpers.ParseTail(0x1); - UserAccountHelpers.CreateUserWithInventory(m_scene, userId); - ScenePresence sp = SceneHelpers.AddScenePresence(m_scene, userId); - - InventoryItemBase att1Item - = UserInventoryHelpers.CreateInventoryItem( - m_scene, "att1", TestHelpers.ParseTail(0x2), TestHelpers.ParseTail(0x3), sp.UUID, InventoryType.Object); - InventoryItemBase att2Item - = UserInventoryHelpers.CreateInventoryItem( - m_scene, "att2", TestHelpers.ParseTail(0x12), TestHelpers.ParseTail(0x13), sp.UUID, InventoryType.Object); - - m_attMod.RezSingleAttachmentFromInventory(sp, att1Item.ID, (uint)AttachmentPoint.Chest); - m_attMod.RezSingleAttachmentFromInventory(sp, att2Item.ID, (uint)AttachmentPoint.Chest | 0x80); - - UUID npcId = m_npcMod.CreateNPC("John", "Smith", new Vector3(128, 128, 30), UUID.Zero, true, m_scene, sp.Appearance); - - ScenePresence npc = m_scene.GetScenePresence(npcId); - - // Check scene presence status - Assert.That(npc.HasAttachments(), Is.True); - List attachments = npc.GetAttachments(); - Assert.That(attachments.Count, Is.EqualTo(2)); - - // Just for now, we won't test the name since this is (wrongly) the asset part name rather than the item - // name. TODO: Do need to fix ultimately since the item may be renamed before being passed on to an NPC. -// Assert.That(attSo.Name, Is.EqualTo(attName)); - - TestAttachedObject(attachments[0], AttachmentPoint.Chest, npc.UUID); - TestAttachedObject(attachments[1], AttachmentPoint.Chest, npc.UUID); - - // Attached objects on the same point must have different FromItemIDs to be shown to other avatars, at least - // on Singularity 1.8.5. Otherwise, only one (the first ObjectUpdate sent) appears. - Assert.AreNotEqual(attachments[0].FromItemID, attachments[1].FromItemID); - } - - private void TestAttachedObject(SceneObjectGroup attSo, AttachmentPoint attPoint, UUID ownerId) - { - Assert.That(attSo.AttachmentPoint, Is.EqualTo((byte)attPoint)); - Assert.That(attSo.IsAttachment); - Assert.That(attSo.UsesPhysics, Is.False); - Assert.That(attSo.IsTemporary, Is.False); - Assert.That(attSo.OwnerID, Is.EqualTo(ownerId)); - } - - [Test] - public void TestLoadAppearance() - { - TestHelpers.InMethod(); -// log4net.Config.XmlConfigurator.Configure(); - - SetUpScene(); - - UUID userId = TestHelpers.ParseTail(0x1); - UserAccountHelpers.CreateUserWithInventory(m_scene, userId); - ScenePresence sp = SceneHelpers.AddScenePresence(m_scene, userId); - - UUID npcId = m_npcMod.CreateNPC("John", "Smith", new Vector3(128, 128, 30), UUID.Zero, true, m_scene, sp.Appearance); - - // Now add the attachment to the original avatar and use that to load a new appearance - // TODO: Could also run tests loading from a notecard though this isn't much different for our purposes here - UUID attItemId = TestHelpers.ParseTail(0x2); - UUID attAssetId = TestHelpers.ParseTail(0x3); - string attName = "att"; - - UserInventoryHelpers.CreateInventoryItem(m_scene, attName, attItemId, attAssetId, sp.UUID, InventoryType.Object); - - m_attMod.RezSingleAttachmentFromInventory(sp, attItemId, (uint)AttachmentPoint.Chest); - - m_npcMod.SetNPCAppearance(npcId, sp.Appearance, m_scene); - - ScenePresence npc = m_scene.GetScenePresence(npcId); - - // Check scene presence status - Assert.That(npc.HasAttachments(), Is.True); - List attachments = npc.GetAttachments(); - Assert.That(attachments.Count, Is.EqualTo(1)); - SceneObjectGroup attSo = attachments[0]; - - // Just for now, we won't test the name since this is (wrongly) the asset part name rather than the item - // name. TODO: Do need to fix ultimately since the item may be renamed before being passed on to an NPC. -// Assert.That(attSo.Name, Is.EqualTo(attName)); - - Assert.That(attSo.AttachmentPoint, Is.EqualTo((byte)AttachmentPoint.Chest)); - Assert.That(attSo.IsAttachment); - Assert.That(attSo.UsesPhysics, Is.False); - Assert.That(attSo.IsTemporary, Is.False); - Assert.That(attSo.OwnerID, Is.EqualTo(npc.UUID)); - } - - [Test] - public void TestMove() - { - TestHelpers.InMethod(); -// TestHelpers.EnableLogging(); - - SetUpScene(); - - ScenePresence sp = SceneHelpers.AddScenePresence(m_scene, TestHelpers.ParseTail(0x1)); -// ScenePresence originalAvatar = scene.GetScenePresence(originalClient.AgentId); - - Vector3 startPos = new Vector3(128, 128, 30); - UUID npcId = m_npcMod.CreateNPC("John", "Smith", startPos, UUID.Zero, true, m_scene, sp.Appearance); - - ScenePresence npc = m_scene.GetScenePresence(npcId); - Assert.That(npc.AbsolutePosition, Is.EqualTo(startPos)); - - // For now, we'll make the scene presence fly to simplify this test, but this needs to change. - npc.Flying = true; - - m_scene.Update(1); - Assert.That(npc.AbsolutePosition, Is.EqualTo(startPos)); - - Vector3 targetPos = startPos + new Vector3(0, 10, 0); - m_npcMod.MoveToTarget(npc.UUID, m_scene, targetPos, false, false, false); - - Assert.That(npc.AbsolutePosition, Is.EqualTo(startPos)); - //Assert.That(npc.Rotation, Is.EqualTo(new Quaternion(0, 0, 0.7071068f, 0.7071068f))); - Assert.That( - npc.Rotation, new QuaternionToleranceConstraint(new Quaternion(0, 0, 0.7071068f, 0.7071068f), 0.000001)); - - m_scene.Update(1); - - // We should really check the exact figure. - Assert.That(npc.AbsolutePosition.X, Is.EqualTo(startPos.X)); - Assert.That(npc.AbsolutePosition.Y, Is.GreaterThan(startPos.Y)); - Assert.That(npc.AbsolutePosition.Z, Is.EqualTo(startPos.Z)); - Assert.That(npc.AbsolutePosition.Z, Is.LessThan(targetPos.X)); - - m_scene.Update(10); - - double distanceToTarget = Util.GetDistanceTo(npc.AbsolutePosition, targetPos); - Assert.That(distanceToTarget, Is.LessThan(1), "NPC not within 1 unit of target position on first move"); - Assert.That(npc.AbsolutePosition, Is.EqualTo(targetPos)); - Assert.That(npc.AgentControlFlags, Is.EqualTo((uint)AgentManager.ControlFlags.NONE)); - - // Try a second movement - startPos = npc.AbsolutePosition; - targetPos = startPos + new Vector3(10, 0, 0); - m_npcMod.MoveToTarget(npc.UUID, m_scene, targetPos, false, false, false); - - Assert.That(npc.AbsolutePosition, Is.EqualTo(startPos)); -// Assert.That(npc.Rotation, Is.EqualTo(new Quaternion(0, 0, 0, 1))); - Assert.That( - npc.Rotation, new QuaternionToleranceConstraint(new Quaternion(0, 0, 0, 1), 0.000001)); - - m_scene.Update(1); - - // We should really check the exact figure. - Assert.That(npc.AbsolutePosition.X, Is.GreaterThan(startPos.X)); - Assert.That(npc.AbsolutePosition.X, Is.LessThan(targetPos.X)); - Assert.That(npc.AbsolutePosition.Y, Is.EqualTo(startPos.Y)); - Assert.That(npc.AbsolutePosition.Z, Is.EqualTo(startPos.Z)); - - m_scene.Update(10); - - distanceToTarget = Util.GetDistanceTo(npc.AbsolutePosition, targetPos); - Assert.That(distanceToTarget, Is.LessThan(1), "NPC not within 1 unit of target position on second move"); - Assert.That(npc.AbsolutePosition, Is.EqualTo(targetPos)); - } - - [Test] - public void TestMoveInVarRegion() - { - TestHelpers.InMethod(); -// TestHelpers.EnableLogging(); - - SetUpScene(512, 512); - - ScenePresence sp = SceneHelpers.AddScenePresence(m_scene, TestHelpers.ParseTail(0x1)); -// ScenePresence originalAvatar = scene.GetScenePresence(originalClient.AgentId); - - Vector3 startPos = new Vector3(128, 246, 30); - UUID npcId = m_npcMod.CreateNPC("John", "Smith", startPos, UUID.Zero, true, m_scene, sp.Appearance); - - ScenePresence npc = m_scene.GetScenePresence(npcId); - Assert.That(npc.AbsolutePosition, Is.EqualTo(startPos)); - - // For now, we'll make the scene presence fly to simplify this test, but this needs to change. - npc.Flying = true; - - m_scene.Update(1); - Assert.That(npc.AbsolutePosition, Is.EqualTo(startPos)); - - Vector3 targetPos = startPos + new Vector3(0, 20, 0); - m_npcMod.MoveToTarget(npc.UUID, m_scene, targetPos, false, false, false); - - Assert.That(npc.AbsolutePosition, Is.EqualTo(startPos)); - //Assert.That(npc.Rotation, Is.EqualTo(new Quaternion(0, 0, 0.7071068f, 0.7071068f))); - Assert.That( - npc.Rotation, new QuaternionToleranceConstraint(new Quaternion(0, 0, 0.7071068f, 0.7071068f), 0.000001)); - - m_scene.Update(1); - - // We should really check the exact figure. - Assert.That(npc.AbsolutePosition.X, Is.EqualTo(startPos.X)); - Assert.That(npc.AbsolutePosition.Y, Is.GreaterThan(startPos.Y)); - Assert.That(npc.AbsolutePosition.Z, Is.EqualTo(startPos.Z)); - Assert.That(npc.AbsolutePosition.Z, Is.LessThan(targetPos.X)); - - for (int i = 0; i < 20; i++) - { - m_scene.Update(1); -// Console.WriteLine("pos: {0}", npc.AbsolutePosition); - } - - double distanceToTarget = Util.GetDistanceTo(npc.AbsolutePosition, targetPos); - Assert.That(distanceToTarget, Is.LessThan(1), "NPC not within 1 unit of target position on first move"); - Assert.That(npc.AbsolutePosition, Is.EqualTo(targetPos)); - Assert.That(npc.AgentControlFlags, Is.EqualTo((uint)AgentManager.ControlFlags.NONE)); - } - - [Test] - public void TestSitAndStandWithSitTarget() - { - TestHelpers.InMethod(); -// log4net.Config.XmlConfigurator.Configure(); - - SetUpScene(); - - ScenePresence sp = SceneHelpers.AddScenePresence(m_scene, TestHelpers.ParseTail(0x1)); - - Vector3 startPos = new Vector3(128, 128, 30); - UUID npcId = m_npcMod.CreateNPC("John", "Smith", startPos, UUID.Zero, true, m_scene, sp.Appearance); - - ScenePresence npc = m_scene.GetScenePresence(npcId); - SceneObjectPart part = SceneHelpers.AddSceneObject(m_scene).RootPart; - - part.SitTargetPosition = new Vector3(0, 0, 1); - m_npcMod.Sit(npc.UUID, part.UUID, m_scene); - - Assert.That(part.SitTargetAvatar, Is.EqualTo(npcId)); - Assert.That(npc.ParentID, Is.EqualTo(part.LocalId)); -// Assert.That( -// npc.AbsolutePosition, -// Is.EqualTo(part.AbsolutePosition + part.SitTargetPosition + ScenePresence.SIT_TARGET_ADJUSTMENT)); - - m_npcMod.Stand(npc.UUID, m_scene); - - Assert.That(part.SitTargetAvatar, Is.EqualTo(UUID.Zero)); - Assert.That(npc.ParentID, Is.EqualTo(0)); - } - - [Test] - public void TestSitAndStandWithNoSitTarget() - { - TestHelpers.InMethod(); -// TestHelpers.EnableLogging(); - - SetUpScene(); - - ScenePresence sp = SceneHelpers.AddScenePresence(m_scene, TestHelpers.ParseTail(0x1)); - - // FIXME: To get this to work for now, we are going to place the npc right next to the target so that - // the autopilot doesn't trigger - Vector3 startPos = new Vector3(1, 1, 1); - - UUID npcId = m_npcMod.CreateNPC("John", "Smith", startPos, UUID.Zero, true, m_scene, sp.Appearance); - - ScenePresence npc = m_scene.GetScenePresence(npcId); - SceneObjectPart part = SceneHelpers.AddSceneObject(m_scene).RootPart; - - m_npcMod.Sit(npc.UUID, part.UUID, m_scene); - - Assert.That(part.SitTargetAvatar, Is.EqualTo(UUID.Zero)); - Assert.That(npc.ParentID, Is.EqualTo(part.LocalId)); - - // We should really be using the NPC size but this would mean preserving the physics actor since it is - // removed on sit. - Assert.That( - npc.AbsolutePosition, - Is.EqualTo(part.AbsolutePosition + new Vector3(0, 0, sp.PhysicsActor.Size.Z / 2))); - - m_npcMod.Stand(npc.UUID, m_scene); - - Assert.That(part.SitTargetAvatar, Is.EqualTo(UUID.Zero)); - Assert.That(npc.ParentID, Is.EqualTo(0)); - } - } -} diff --git a/OpenSim/Region/PhysicsModules/BulletS/Tests/BasicVehicles.cs b/OpenSim/Region/PhysicsModules/BulletS/Tests/BasicVehicles.cs deleted file mode 100644 index 1df209e885a..00000000000 --- a/OpenSim/Region/PhysicsModules/BulletS/Tests/BasicVehicles.cs +++ /dev/null @@ -1,152 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System.Collections.Generic; - -using NUnit.Framework; - -using OpenSim.Framework; -using OpenSim.Region.PhysicsModule.BulletS; -using OpenSim.Region.PhysicsModules.SharedBase; -using OpenSim.Tests.Common; - -using OpenMetaverse; - -namespace OpenSim.Region.PhysicsModule.BulletS.Tests -{ - [TestFixture] - public class BasicVehicles : OpenSimTestCase - { - // Documentation on attributes: http://www.nunit.org/index.php?p=attributes&r=2.6.1 - // Documentation on assertions: http://www.nunit.org/index.php?p=assertions&r=2.6.1 - - BSScene PhysicsScene { get; set; } - BSPrim TestVehicle { get; set; } - Vector3 TestVehicleInitPosition { get; set; } - float simulationTimeStep = 0.089f; - - [OneTimeSetUp] - public void Init() - { - Dictionary engineParams = new Dictionary(); - engineParams.Add("VehicleEnableAngularVerticalAttraction", "true"); - engineParams.Add("VehicleAngularVerticalAttractionAlgorithm", "1"); - PhysicsScene = BulletSimTestsUtil.CreateBasicPhysicsEngine(engineParams); - - PrimitiveBaseShape pbs = PrimitiveBaseShape.CreateSphere(); - Vector3 pos = new Vector3(100.0f, 100.0f, 0f); - pos.Z = PhysicsScene.TerrainManager.GetTerrainHeightAtXYZ(pos) + 2f; - TestVehicleInitPosition = pos; - Vector3 size = new Vector3(1f, 1f, 1f); - pbs.Scale = size; - Quaternion rot = Quaternion.Identity; - bool isPhys = false; - uint localID = 123; - - PhysicsScene.AddPrimShape("testPrim", pbs, pos, size, rot, isPhys, localID); - TestVehicle = (BSPrim)PhysicsScene.PhysObjects[localID]; - // The actual prim shape creation happens at taint time - PhysicsScene.ProcessTaints(); - - } - - [OneTimeTearDown] - public void TearDown() - { - if (PhysicsScene != null) - { - // The Dispose() will also free any physical objects in the scene - PhysicsScene.Dispose(); - PhysicsScene = null; - } - } - - [TestCase(2f, 0.2f, 0.25f, 0.25f, 0.25f)] - [TestCase(2f, 0.2f, -0.25f, 0.25f, 0.25f)] - [TestCase(2f, 0.2f, 0.25f, -0.25f, 0.25f)] - [TestCase(2f, 0.2f, -0.25f, -0.25f, 0.25f)] - // [TestCase(2f, 0.2f, 0.785f, 0.0f, 0.25f) /*, "Leaning 45 degrees to the side" */] - // [TestCase(2f, 0.2f, 1.650f, 0.0f, 0.25f) /*, "Leaning more than 90 degrees to the side" */] - // [TestCase(2f, 0.2f, 2.750f, 0.0f, 0.25f) /*, "Almost upside down, tipped right" */] - // [TestCase(2f, 0.2f,-2.750f, 0.0f, 0.25f) /*, "Almost upside down, tipped left" */] - // [TestCase(2f, 0.2f, 0.0f, 0.785f, 0.25f) /*, "Tipped back 45 degrees" */] - // [TestCase(2f, 0.2f, 0.0f, 1.650f, 0.25f) /*, "Tipped back more than 90 degrees" */] - // [TestCase(2f, 0.2f, 0.0f, 2.750f, 0.25f) /*, "Almost upside down, tipped back" */] - // [TestCase(2f, 0.2f, 0.0f,-2.750f, 0.25f) /*, "Almost upside down, tipped forward" */] - public void AngularVerticalAttraction(float timeScale, float efficiency, float initRoll, float initPitch, float initYaw) - { - // Enough simulation steps to cover the timescale the operation should take - int simSteps = (int)(timeScale / simulationTimeStep) + 1; - - // Tip the vehicle - Quaternion initOrientation = Quaternion.CreateFromEulers(initRoll, initPitch, initYaw); - TestVehicle.Orientation = initOrientation; - - TestVehicle.Position = TestVehicleInitPosition; - - // The vehicle controller is not enabled directly (by setting a vehicle type). - // Instead the appropriate values are set and calls are made just the parts of the - // controller we want to exercise. Stepping the physics engine then applies - // the actions of that one feature. - BSDynamics vehicleActor = TestVehicle.GetVehicleActor(true /* createIfNone */); - if (vehicleActor != null) - { - vehicleActor.ProcessFloatVehicleParam(Vehicle.VERTICAL_ATTRACTION_EFFICIENCY, efficiency); - vehicleActor.ProcessFloatVehicleParam(Vehicle.VERTICAL_ATTRACTION_TIMESCALE, timeScale); - // vehicleActor.enableAngularVerticalAttraction = true; - - TestVehicle.IsPhysical = true; - PhysicsScene.ProcessTaints(); - - // Step the simulator a bunch of times and vertical attraction should orient the vehicle up - for (int ii = 0; ii < simSteps; ii++) - { - vehicleActor.ForgetKnownVehicleProperties(); - vehicleActor.ComputeAngularVerticalAttraction(); - vehicleActor.PushKnownChanged(); - - PhysicsScene.Simulate(simulationTimeStep); - } - } - - TestVehicle.IsPhysical = false; - PhysicsScene.ProcessTaints(); - - // After these steps, the vehicle should be upright - /* - float finalRoll, finalPitch, finalYaw; - TestVehicle.Orientation.GetEulerAngles(out finalRoll, out finalPitch, out finalYaw); - Assert.That(finalRoll, Is.InRange(-0.01f, 0.01f)); - Assert.That(finalPitch, Is.InRange(-0.01f, 0.01f)); - Assert.That(finalYaw, Is.InRange(initYaw - 0.1f, initYaw + 0.1f)); - */ - - Vector3 upPointer = Vector3.UnitZ * TestVehicle.Orientation; - Assert.That(upPointer.Z, Is.GreaterThan(0.99f)); - } - } -} \ No newline at end of file diff --git a/OpenSim/Region/PhysicsModules/BulletS/Tests/BulletSimTests.cs b/OpenSim/Region/PhysicsModules/BulletS/Tests/BulletSimTests.cs deleted file mode 100644 index 95e53a62858..00000000000 --- a/OpenSim/Region/PhysicsModules/BulletS/Tests/BulletSimTests.cs +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using NUnit.Framework; - -using OpenSim.Tests.Common; - -namespace OpenSim.Region.PhysicsModule.BulletS.Tests -{ - [TestFixture] - public class BulletSimTests : OpenSimTestCase - { - // Documentation on attributes: http://www.nunit.org/index.php?p=attributes&r=2.6.1 - // Documentation on assertions: http://www.nunit.org/index.php?p=assertions&r=2.6.1 - - [OneTimeSetUp] - public void Init() - { - } - - [OneTimeTearDown] - public void TearDown() - { - } - } -} diff --git a/OpenSim/Region/PhysicsModules/BulletS/Tests/BulletSimTestsUtil.cs b/OpenSim/Region/PhysicsModules/BulletS/Tests/BulletSimTestsUtil.cs deleted file mode 100644 index 57abc7fd208..00000000000 --- a/OpenSim/Region/PhysicsModules/BulletS/Tests/BulletSimTestsUtil.cs +++ /dev/null @@ -1,111 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.IO; -using System.Collections.Generic; -using System.Text; - -using Nini.Config; - -using OpenSim.Framework; -using OpenSim.Region; -using OpenSim.Region.PhysicsModules.SharedBase; -using OpenSim.Region.PhysicsModule.Meshing; -using OpenSim.Region.Framework.Interfaces; - -using OpenMetaverse; -using OpenSim.Region.Framework.Scenes; - -namespace OpenSim.Region.PhysicsModule.BulletS.Tests -{ - // Utility functions for building up and tearing down the sample physics environments - public static class BulletSimTestsUtil - { - // 'engineName' is the Bullet engine to use. Either null (for unmanaged), "BulletUnmanaged" or "BulletXNA" - // 'params' is a set of keyValue pairs to set in the engine's configuration file (override defaults) - // May be 'null' if there are no overrides. - public static BSScene CreateBasicPhysicsEngine(Dictionary paramOverrides) - { - IConfigSource openSimINI = new IniConfigSource(); - IConfig startupConfig = openSimINI.AddConfig("Startup"); - startupConfig.Set("physics", "BulletSim"); - startupConfig.Set("meshing", "Meshmerizer"); - startupConfig.Set("cacheSculptMaps", "false"); // meshmerizer shouldn't save maps - - IConfig bulletSimConfig = openSimINI.AddConfig("BulletSim"); - // If the caller cares, specify the bullet engine otherwise it will default to "BulletUnmanaged". - // bulletSimConfig.Set("BulletEngine", "BulletUnmanaged"); - // bulletSimConfig.Set("BulletEngine", "BulletXNA"); - bulletSimConfig.Set("MeshSculptedPrim", "false"); - bulletSimConfig.Set("ForceSimplePrimMeshing", "true"); - if (paramOverrides != null) - { - foreach (KeyValuePair kvp in paramOverrides) - { - bulletSimConfig.Set(kvp.Key, kvp.Value); - } - } - - // If a special directory exists, put detailed logging therein. - // This allows local testing/debugging without having to worry that the build engine will output logs. - if (Directory.Exists("physlogs")) - { - bulletSimConfig.Set("PhysicsLoggingDir", "./physlogs"); - bulletSimConfig.Set("PhysicsLoggingEnabled", "True"); - bulletSimConfig.Set("PhysicsLoggingDoFlush", "True"); - bulletSimConfig.Set("VehicleLoggingEnabled", "True"); - } - - Vector3 regionExtent = new Vector3(Constants.RegionSize, Constants.RegionSize, Constants.RegionHeight); - - RegionInfo info = new RegionInfo(); - info.RegionName = "BSTestRegion"; - info.RegionSizeX = info.RegionSizeY = info.RegionSizeZ = Constants.RegionSize; - Scene scene = new Scene(info); - - IMesher mesher = new Meshmerizer(); - INonSharedRegionModule mod = mesher as INonSharedRegionModule; - mod.Initialise(openSimINI); - mod.AddRegion(scene); - mod.RegionLoaded(scene); - - BSScene pScene = new BSScene(); - mod = (pScene as INonSharedRegionModule); - mod.Initialise(openSimINI); - mod.AddRegion(scene); - mod.RegionLoaded(scene); - - // Since the asset requestor is not initialized, any mesh or sculptie will be a cube. - // In the future, add a fake asset fetcher to get meshes and sculpts. - // bsScene.RequestAssetMethod = ???; - - return pScene; - } - - } -} diff --git a/OpenSim/Region/PhysicsModules/BulletS/Tests/HullCreation.cs b/OpenSim/Region/PhysicsModules/BulletS/Tests/HullCreation.cs deleted file mode 100644 index 83c53ad3b54..00000000000 --- a/OpenSim/Region/PhysicsModules/BulletS/Tests/HullCreation.cs +++ /dev/null @@ -1,205 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; - -using NUnit.Framework; -using log4net; - -using OpenSim.Framework; -using OpenSim.Region.PhysicsModule.BulletS; -using OpenSim.Region.PhysicsModules.SharedBase; -using OpenSim.Tests.Common; - -using OpenMetaverse; - -namespace OpenSim.Region.PhysicsModule.BulletS.Tests -{ - [TestFixture] - public class HullCreation : OpenSimTestCase - { - // Documentation on attributes: http://www.nunit.org/index.php?p=attributes&r=2.6.1 - // Documentation on assertions: http://www.nunit.org/index.php?p=assertions&r=2.6.1 - - BSScene PhysicsScene { get; set; } - Vector3 ObjectInitPosition; - - [OneTimeSetUp] - public void Init() - { - - } - - [OneTimeTearDown] - public void TearDown() - { - if (PhysicsScene != null) - { - // The Dispose() will also free any physical objects in the scene - PhysicsScene.Dispose(); - PhysicsScene = null; - } - } - - [TestCase(7, 2, 5f, 5f, 32, 0f)] /* default hull parameters */ - public void GeomHullConvexDecomp(int maxDepthSplit, - int maxDepthSplitForSimpleShapes, - float concavityThresholdPercent, - float volumeConservationThresholdPercent, - int maxVertices, - float maxSkinWidth) - { - // Setup the physics engine to use the C# version of convex decomp - Dictionary engineParams = new Dictionary(); - engineParams.Add("MeshSculptedPrim", "true"); // ShouldMeshSculptedPrim - engineParams.Add("ForceSimplePrimMeshing", "false"); // ShouldForceSimplePrimMeshing - engineParams.Add("UseHullsForPhysicalObjects", "true"); // ShouldUseHullsForPhysicalObjects - engineParams.Add("ShouldRemoveZeroWidthTriangles", "true"); - engineParams.Add("ShouldUseBulletHACD", "false"); - engineParams.Add("ShouldUseSingleConvexHullForPrims", "true"); - engineParams.Add("ShouldUseGImpactShapeForPrims", "false"); - engineParams.Add("ShouldUseAssetHulls", "true"); - - engineParams.Add("CSHullMaxDepthSplit", maxDepthSplit.ToString()); - engineParams.Add("CSHullMaxDepthSplitForSimpleShapes", maxDepthSplitForSimpleShapes.ToString()); - engineParams.Add("CSHullConcavityThresholdPercent", concavityThresholdPercent.ToString()); - engineParams.Add("CSHullVolumeConservationThresholdPercent", volumeConservationThresholdPercent.ToString()); - engineParams.Add("CSHullMaxVertices", maxVertices.ToString()); - engineParams.Add("CSHullMaxSkinWidth", maxSkinWidth.ToString()); - - PhysicsScene = BulletSimTestsUtil.CreateBasicPhysicsEngine(engineParams); - - PrimitiveBaseShape pbs; - Vector3 pos; - Vector3 size; - Quaternion rot; - bool isPhys; - - // Cylinder - pbs = PrimitiveBaseShape.CreateCylinder(); - pos = new Vector3(100.0f, 100.0f, 0f); - pos.Z = PhysicsScene.TerrainManager.GetTerrainHeightAtXYZ(pos) + 10f; - ObjectInitPosition = pos; - size = new Vector3(2f, 2f, 2f); - pbs.Scale = size; - rot = Quaternion.Identity; - isPhys = true; - uint cylinderLocalID = 123; - PhysicsScene.AddPrimShape("testCylinder", pbs, pos, size, rot, isPhys, cylinderLocalID); - BSPrim primTypeCylinder = (BSPrim)PhysicsScene.PhysObjects[cylinderLocalID]; - - // Hollow Cylinder - pbs = PrimitiveBaseShape.CreateCylinder(); - pbs.ProfileHollow = (ushort)(0.70f * 50000); - pos = new Vector3(110.0f, 110.0f, 0f); - pos.Z = PhysicsScene.TerrainManager.GetTerrainHeightAtXYZ(pos) + 10f; - ObjectInitPosition = pos; - size = new Vector3(2f, 2f, 2f); - pbs.Scale = size; - rot = Quaternion.Identity; - isPhys = true; - uint hollowCylinderLocalID = 124; - PhysicsScene.AddPrimShape("testHollowCylinder", pbs, pos, size, rot, isPhys, hollowCylinderLocalID); - BSPrim primTypeHollowCylinder = (BSPrim)PhysicsScene.PhysObjects[hollowCylinderLocalID]; - - // Torus - // ProfileCurve = Circle, PathCurve = Curve1 - pbs = PrimitiveBaseShape.CreateSphere(); - pbs.ProfileShape = (byte)ProfileShape.Circle; - pbs.PathCurve = (byte)Extrusion.Curve1; - pbs.PathScaleX = 100; // default hollow info as set in the viewer - pbs.PathScaleY = (int)(.25f / 0.01f) + 200; - pos = new Vector3(120.0f, 120.0f, 0f); - pos.Z = PhysicsScene.TerrainManager.GetTerrainHeightAtXYZ(pos) + 10f; - ObjectInitPosition = pos; - size = new Vector3(2f, 4f, 4f); - pbs.Scale = size; - rot = Quaternion.Identity; - isPhys = true; - uint torusLocalID = 125; - PhysicsScene.AddPrimShape("testTorus", pbs, pos, size, rot, isPhys, torusLocalID); - BSPrim primTypeTorus = (BSPrim)PhysicsScene.PhysObjects[torusLocalID]; - - // The actual prim shape creation happens at taint time - PhysicsScene.ProcessTaints(); - - // Check out the created hull shapes and report their characteristics - ReportShapeGeom(primTypeCylinder); - ReportShapeGeom(primTypeHollowCylinder); - ReportShapeGeom(primTypeTorus); - } - - [TestCase] - public void GeomHullBulletHACD() - { - // Cylinder - // Hollow Cylinder - // Torus - } - - private void ReportShapeGeom(BSPrim prim) - { - if (prim != null) - { - if (prim.PhysShape.HasPhysicalShape) - { - BSShape physShape = prim.PhysShape; - string shapeType = physShape.GetType().ToString(); - switch (shapeType) - { - case "OpenSim.Region.Physics.BulletSPlugin.BSShapeNative": - BSShapeNative nShape = physShape as BSShapeNative; - prim.PhysScene.DetailLog("{0}, type={1}", prim.Name, shapeType); - break; - case "OpenSim.Region.Physics.BulletSPlugin.BSShapeMesh": - BSShapeMesh mShape = physShape as BSShapeMesh; - prim.PhysScene.DetailLog("{0}, mesh, shapeInfo={1}", prim.Name, mShape.shapeInfo); - break; - case "OpenSim.Region.Physics.BulletSPlugin.BSShapeHull": - // BSShapeHull hShape = physShape as BSShapeHull; - // prim.PhysScene.DetailLog("{0}, hull, shapeInfo={1}", prim.Name, hShape.shapeInfo); - break; - case "OpenSim.Region.Physics.BulletSPlugin.BSShapeConvexHull": - BSShapeConvexHull chShape = physShape as BSShapeConvexHull; - prim.PhysScene.DetailLog("{0}, convexHull, shapeInfo={1}", prim.Name, chShape.shapeInfo); - break; - case "OpenSim.Region.Physics.BulletSPlugin.BSShapeCompound": - BSShapeCompound cShape = physShape as BSShapeCompound; - prim.PhysScene.DetailLog("{0}, type={1}", prim.Name, shapeType); - break; - default: - prim.PhysScene.DetailLog("{0}, type={1}", prim.Name, shapeType); - break; - } - } - } - } - } -} \ No newline at end of file diff --git a/OpenSim/Region/PhysicsModules/BulletS/Tests/OpenSim.Region.PhysicsModule.BulletS.Tests.csproj b/OpenSim/Region/PhysicsModules/BulletS/Tests/OpenSim.Region.PhysicsModule.BulletS.Tests.csproj deleted file mode 100644 index d2e3f93e265..00000000000 --- a/OpenSim/Region/PhysicsModules/BulletS/Tests/OpenSim.Region.PhysicsModule.BulletS.Tests.csproj +++ /dev/null @@ -1,33 +0,0 @@ - - - net8.0 - - - - - - - - - - ..\..\..\..\..\bin\Nini.dll - False - - - ..\..\..\..\..\bin\OpenMetaverse.dll - False - - - ..\..\..\..\..\bin\OpenMetaverseTypes.dll - False - - - - - - - - - - - \ No newline at end of file diff --git a/OpenSim/Region/PhysicsModules/BulletS/Tests/Raycast.cs b/OpenSim/Region/PhysicsModules/BulletS/Tests/Raycast.cs deleted file mode 100755 index 4ba22244510..00000000000 --- a/OpenSim/Region/PhysicsModules/BulletS/Tests/Raycast.cs +++ /dev/null @@ -1,126 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; - -using NUnit.Framework; -using log4net; - -using OpenSim.Framework; -using OpenSim.Region.PhysicsModule.BulletS; -using OpenSim.Region.PhysicsModules.SharedBase; -using OpenSim.Tests.Common; - -using OpenMetaverse; - -namespace OpenSim.Region.PhysicsModule.BulletS.Tests -{ - [TestFixture] - public class BulletSimRaycast : OpenSimTestCase - { - // Documentation on attributes: http://www.nunit.org/index.php?p=attributes&r=2.6.1 - // Documentation on assertions: http://www.nunit.org/index.php?p=assertions&r=2.6.1 - - BSScene _physicsScene { get; set; } - BSPrim _targetSphere { get; set; } - Vector3 _targetSpherePosition { get; set; } - // float _simulationTimeStep = 0.089f; - - uint _targetLocalID = 123; - - [OneTimeSetUp] - public void Init() - { - Dictionary engineParams = new Dictionary(); - engineParams.Add("UseBulletRaycast", "true"); - _physicsScene = BulletSimTestsUtil.CreateBasicPhysicsEngine(engineParams); - - PrimitiveBaseShape pbs = PrimitiveBaseShape.CreateSphere(); - Vector3 pos = new Vector3(100.0f, 100.0f, 50f); - _targetSpherePosition = pos; - Vector3 size = new Vector3(10f, 10f, 10f); - pbs.Scale = size; - Quaternion rot = Quaternion.Identity; - bool isPhys = false; - - _physicsScene.AddPrimShape("TargetSphere", pbs, pos, size, rot, isPhys, _targetLocalID); - _targetSphere = (BSPrim)_physicsScene.PhysObjects[_targetLocalID]; - // The actual prim shape creation happens at taint time - _physicsScene.ProcessTaints(); - - } - - [OneTimeTearDown] - public void TearDown() - { - if (_physicsScene != null) - { - // The Dispose() will also free any physical objects in the scene - _physicsScene.Dispose(); - _physicsScene = null; - } - } - - // There is a 10x10x10 sphere at <100,100,50> - // Shoot rays around the sphere and verify it hits and doesn't hit - // TestCase parameters are of start and of end and expected result - [TestCase(100f, 50f, 50f, 100f, 150f, 50f, true, "Pass through sphere from front")] - [TestCase(50f, 100f, 50f, 150f, 100f, 50f, true, "Pass through sphere from side")] - [TestCase(50f, 50f, 50f, 150f, 150f, 50f, true, "Pass through sphere diaginally")] - [TestCase(100f, 100f, 100f, 100f, 100f, 20f, true, "Pass through sphere from above")] - [TestCase(20f, 20f, 50f, 80f, 80f, 50f, false, "Not reach sphere")] - [TestCase(50f, 50f, 65f, 150f, 150f, 65f, false, "Passed over sphere")] - public void RaycastAroundObject(float fromX, float fromY, float fromZ, float toX, float toY, float toZ, bool expected, string msg) - { - Vector3 fromPos = new Vector3(fromX, fromY, fromZ); - Vector3 toPos = new Vector3(toX, toY, toZ); - Vector3 direction = toPos - fromPos; - float len = Vector3.Distance(fromPos, toPos); - - List results = _physicsScene.RaycastWorld(fromPos, direction, len, 1); - - if (expected) - { - // The test coordinates should generate a hit - Assert.True(results.Count != 0, msg + ": Did not return a hit but expected to."); - Assert.True(results.Count == 1, msg + ": Raycast returned not just one hit result."); - Assert.True(results[0].ConsumerID == _targetLocalID, msg + ": Raycast returned a collision object other than the target"); - } - else - { - // The test coordinates should not generate a hit - if (results.Count > 0) - { - Assert.False(results.Count > 0, msg + ": Returned a hit at " + results[0].Pos.ToString()); - } - } - } - } -} \ No newline at end of file diff --git a/OpenSim/Region/PhysicsModules/Meshing/OpenSim.Region.PhysicsModule.Meshing.csproj b/OpenSim/Region/PhysicsModules/Meshing/OpenSim.Region.PhysicsModule.Meshing.csproj index 3747a0d16de..72d8465a62d 100644 --- a/OpenSim/Region/PhysicsModules/Meshing/OpenSim.Region.PhysicsModule.Meshing.csproj +++ b/OpenSim/Region/PhysicsModules/Meshing/OpenSim.Region.PhysicsModule.Meshing.csproj @@ -33,9 +33,6 @@ ..\..\..\..\bin\OpenMetaverseTypes.dll False - - False - @@ -43,4 +40,4 @@ - \ No newline at end of file + diff --git a/OpenSim/Region/PhysicsModules/ubOdeMeshing/OpenSim.Region.PhysicsModule.ubOdeMeshing.csproj b/OpenSim/Region/PhysicsModules/ubOdeMeshing/OpenSim.Region.PhysicsModule.ubOdeMeshing.csproj index b59eb648323..cdc21ca8f0c 100644 --- a/OpenSim/Region/PhysicsModules/ubOdeMeshing/OpenSim.Region.PhysicsModule.ubOdeMeshing.csproj +++ b/OpenSim/Region/PhysicsModules/ubOdeMeshing/OpenSim.Region.PhysicsModule.ubOdeMeshing.csproj @@ -35,9 +35,6 @@ ..\..\..\..\bin\OpenMetaverseTypes.dll False - - False - @@ -46,4 +43,4 @@ - \ No newline at end of file + diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OpenSim.Region.ScriptEngine.Shared.Api.csproj b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OpenSim.Region.ScriptEngine.Shared.Api.csproj index 0a4d87c8fc7..8903c90ac56 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OpenSim.Region.ScriptEngine.Shared.Api.csproj +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OpenSim.Region.ScriptEngine.Shared.Api.csproj @@ -27,9 +27,6 @@ ..\..\..\..\..\..\bin\OpenMetaverseTypes.dll False - - False - False @@ -48,4 +45,4 @@ - \ No newline at end of file + diff --git a/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiAvatarTests.cs b/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiAvatarTests.cs deleted file mode 100644 index a500f10c6c4..00000000000 --- a/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiAvatarTests.cs +++ /dev/null @@ -1,165 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections.Generic; -using System.Reflection; -using System.Text; -using log4net; -using Nini.Config; -using NUnit.Framework; -using OpenMetaverse; -using OpenMetaverse.Assets; -using OpenMetaverse.StructuredData; -using OpenSim.Framework; -using OpenSim.Region.CoreModules.Avatar.AvatarFactory; -using OpenSim.Region.OptionalModules.World.NPC; -using OpenSim.Region.Framework.Scenes; -using OpenSim.Region.ScriptEngine.Shared; -using OpenSim.Region.ScriptEngine.Shared.Api; -using OpenSim.Region.ScriptEngine.Shared.ScriptBase; -using OpenSim.Services.Interfaces; -using OpenSim.Tests.Common; -using LSL_Integer = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLInteger; -using LSL_List = OpenSim.Region.ScriptEngine.Shared.LSL_Types.list; - -namespace OpenSim.Region.ScriptEngine.Shared.Tests -{ - /// - /// Tests relating directly to avatars - /// - [TestFixture] - public class LSL_ApiAvatarTests : OpenSimTestCase - { - /* - protected Scene m_scene; - - [SetUp] - public override void SetUp() - { - base.SetUp(); - - IConfigSource initConfigSource = new IniConfigSource(); - IConfig config = initConfigSource.AddConfig("XEngine"); - config.Set("Enabled", "true"); - - config = initConfigSource.AddConfig("OSSL"); - config.Set("DebuggerSafe", false); - config.Set("AllowOSFunctions", "true"); - config.Set("OSFunctionThreatLevel", "Severe"); - - m_scene = new SceneHelpers().SetupScene(); - SceneHelpers.SetupSceneModules(m_scene, initConfigSource); - - m_engine = new YEngine.XEngine(); - m_engine.Initialise(initConfigSource); - m_engine.AddRegion(m_scene); - } - - /// - /// Test llSetLinkPrimtiveParams for agents. - /// - /// - /// Also testing entity updates here as well. Possibly that's putting 2 different concerns into one test and - /// this should be separated. - /// - [Test] - public void TestllSetLinkPrimitiveParamsForAgent() - { -/* siting avatars position changed - TestHelpers.InMethod(); -// TestHelpers.EnableLogging(); - - UUID userId = TestHelpers.ParseTail(0x1); - - SceneObjectPart part = SceneHelpers.AddSceneObject(m_scene).RootPart; - part.RotationOffset = new Quaternion(0.7071068f, 0, 0, 0.7071068f); - - LSL_Api apiGrp1 = new LSL_Api(); - apiGrp1.Initialize(m_engine, part, null); - - ScenePresence sp = SceneHelpers.AddScenePresence(m_scene, userId); - - // sp has to be less than 10 meters away from 0, 0, 0 (default part position) - Vector3 startPos = new Vector3(3, 2, 1); - sp.AbsolutePosition = startPos; - - sp.HandleAgentRequestSit(sp.ControllingClient, sp.UUID, part.UUID, Vector3.Zero); - - int entityUpdates = 0; - ((TestClient)sp.ControllingClient).OnReceivedEntityUpdate += (entity, flags) => { if (entity is ScenePresence) { entityUpdates++; }}; - - // Test position - { - Vector3 newPos = new Vector3(1, 2, 3); - apiGrp1.llSetLinkPrimitiveParams(2, new LSL_Types.list(ScriptBaseClass.PRIM_POSITION, newPos)); - - Assert.That(sp.OffsetPosition, Is.EqualTo(newPos)); - - m_scene.Update(1); - Assert.That(entityUpdates, Is.EqualTo(1)); - } - - // Test small reposition - { - Vector3 newPos = new Vector3(1.001f, 2, 3); - apiGrp1.llSetLinkPrimitiveParams(2, new LSL_Types.list(ScriptBaseClass.PRIM_POSITION, newPos)); - - Assert.That(sp.OffsetPosition, Is.EqualTo(newPos)); - - m_scene.Update(1); - Assert.That(entityUpdates, Is.EqualTo(2)); - } - - // Test world rotation - { - Quaternion newRot = new Quaternion(0, 0.7071068f, 0, 0.7071068f); - apiGrp1.llSetLinkPrimitiveParams(2, new LSL_Types.list(ScriptBaseClass.PRIM_ROTATION, newRot)); - - Assert.That( - sp.Rotation, new QuaternionToleranceConstraint(part.GetWorldRotation() * newRot, 0.000001)); - - m_scene.Update(1); - Assert.That(entityUpdates, Is.EqualTo(3)); - } - - // Test local rotation - { - Quaternion newRot = new Quaternion(0, 0.7071068f, 0, 0.7071068f); - apiGrp1.llSetLinkPrimitiveParams(2, new LSL_Types.list(ScriptBaseClass.PRIM_ROT_LOCAL, newRot)); - - Assert.That( - sp.Rotation, new QuaternionToleranceConstraint(newRot, 0.000001)); - - m_scene.Update(1); - Assert.That(entityUpdates, Is.EqualTo(4)); - } - - } - */ - } -} diff --git a/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiHttpTests.cs b/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiHttpTests.cs deleted file mode 100644 index 7fa2bea0132..00000000000 --- a/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiHttpTests.cs +++ /dev/null @@ -1,253 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections.Generic; -using System.IO; -using System.Net; -using System.Reflection; -using System.Text; -using log4net; -using Nini.Config; -using NUnit.Framework; -using OpenMetaverse; -using OpenSim.Framework; -using OpenSim.Framework.Servers; -using OpenSim.Framework.Servers.HttpServer; -using OpenSim.Region.CoreModules.Scripting.LSLHttp; -using OpenSim.Region.Framework.Scenes; -using OpenSim.Region.ScriptEngine.Shared; -using OpenSim.Region.ScriptEngine.Shared.Api; -using OpenSim.Region.ScriptEngine.Shared.ScriptBase; -using OpenSim.Services.Interfaces; -using OpenSim.Tests.Common; - -namespace OpenSim.Region.ScriptEngine.Shared.Tests -{ - /// - /// Tests for HTTP related functions in LSL - /// - [TestFixture] - public class LSL_ApiHttpTests : OpenSimTestCase - { - private Scene m_scene; - private MockScriptEngine m_engine; - private UrlModule m_urlModule; - - private TaskInventoryItem m_scriptItem; - private LSL_Api m_lslApi; - - [OneTimeSetUp] - public void TestFixtureSetUp() - { - // Don't allow tests to be bamboozled by asynchronous events. Execute everything on the same thread. - Util.FireAndForgetMethod = FireAndForgetMethod.RegressionTest; - } - - [OneTimeTearDown] - public void TestFixureTearDown() - { - // We must set this back afterwards, otherwise later tests will fail since they're expecting multiple - // threads. Possibly, later tests should be rewritten so none of them require async stuff (which regression - // tests really shouldn't). - Util.FireAndForgetMethod = Util.DefaultFireAndForgetMethod; - } - - [SetUp] - public override void SetUp() - { - base.SetUp(); - - // This is an unfortunate bit of clean up we have to do because MainServer manages things through static - // variables and the VM is not restarted between tests. - uint port = 9999; - MainServer.RemoveHttpServer(port); - - m_engine = new MockScriptEngine(); - m_urlModule = new UrlModule(); - - IConfigSource config = new IniConfigSource(); - config.AddConfig("Network"); - config.Configs["Network"].Set("ExternalHostNameForLSL", "127.0.0.1"); - m_scene = new SceneHelpers().SetupScene(); - - BaseHttpServer server = new BaseHttpServer(port); - MainServer.AddHttpServer(server); - MainServer.Instance = server; - - server.Start(); - - SceneHelpers.SetupSceneModules(m_scene, config, m_engine, m_urlModule); - - SceneObjectGroup so = SceneHelpers.AddSceneObject(m_scene); - m_scriptItem = TaskInventoryHelpers.AddScript(m_scene.AssetService, so.RootPart); - - // This is disconnected from the actual script - the mock engine does not set up any LSL_Api atm. - // Possibly this could be done and we could obtain it directly from the MockScriptEngine. - m_lslApi = new LSL_Api(); - m_lslApi.Initialize(m_engine, so.RootPart, m_scriptItem); - } - - [TearDown] - public void TearDown() - { - MainServer.Instance.Stop(); - } - - [Test] - public void TestLlReleaseUrl() - { - TestHelpers.InMethod(); - - m_lslApi.llRequestURL(); - string returnedUri = m_engine.PostedEvents[m_scriptItem.ItemID][0].Params[2].ToString(); - - { - // Check that the initial number of URLs is correct - Assert.That(m_lslApi.llGetFreeURLs().value, Is.EqualTo(m_urlModule.TotalUrls - 1)); - } - - { - // Check releasing a non-url - m_lslApi.llReleaseURL("GARBAGE"); - Assert.That(m_lslApi.llGetFreeURLs().value, Is.EqualTo(m_urlModule.TotalUrls - 1)); - } - - { - // Check releasing a non-existing url - m_lslApi.llReleaseURL("http://example.com"); - Assert.That(m_lslApi.llGetFreeURLs().value, Is.EqualTo(m_urlModule.TotalUrls - 1)); - } - - { - // Check URL release - m_lslApi.llReleaseURL(returnedUri); - Assert.That(m_lslApi.llGetFreeURLs().value, Is.EqualTo(m_urlModule.TotalUrls)); - - HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(returnedUri); - - bool gotExpectedException = false; - - try - { - using (HttpWebResponse webResponse = (HttpWebResponse)webRequest.GetResponse()) - {} - } - catch (WebException) - { -// using (HttpWebResponse response = (HttpWebResponse)e.Response) -// gotExpectedException = response.StatusCode == HttpStatusCode.NotFound; - gotExpectedException = true; - } - - Assert.That(gotExpectedException, Is.True); - } - - { - // Check releasing the same URL again - m_lslApi.llReleaseURL(returnedUri); - Assert.That(m_lslApi.llGetFreeURLs().value, Is.EqualTo(m_urlModule.TotalUrls)); - } - } - - [Test] - public void TestLlRequestUrl() - { - TestHelpers.InMethod(); - - string requestId = m_lslApi.llRequestURL(); - Assert.That(requestId, Is.Not.EqualTo(UUID.Zero.ToString())); - string returnedUri; - - { - // Check that URL is correctly set up - Assert.That(m_lslApi.llGetFreeURLs().value, Is.EqualTo(m_urlModule.TotalUrls - 1)); - - Assert.That(m_engine.PostedEvents.ContainsKey(m_scriptItem.ItemID)); - - List events = m_engine.PostedEvents[m_scriptItem.ItemID]; - Assert.That(events.Count, Is.EqualTo(1)); - EventParams eventParams = events[0]; - Assert.That(eventParams.EventName, Is.EqualTo("http_request")); - - UUID returnKey; - string rawReturnKey = eventParams.Params[0].ToString(); - string method = eventParams.Params[1].ToString(); - returnedUri = eventParams.Params[2].ToString(); - - Assert.That(UUID.TryParse(rawReturnKey, out returnKey), Is.True); - Assert.That(method, Is.EqualTo(ScriptBaseClass.URL_REQUEST_GRANTED)); - Assert.That(Uri.IsWellFormedUriString(returnedUri, UriKind.Absolute), Is.True); - } - - { - // Check that request to URL works. - string testResponse = "Hello World"; - - m_engine.ClearPostedEvents(); - m_engine.PostEventHook - += (itemId, evp) => m_lslApi.llHTTPResponse(evp.Params[0].ToString(), 200, testResponse); - -// Console.WriteLine("Trying {0}", returnedUri); - - AssertHttpResponse(returnedUri, testResponse); - - Assert.That(m_engine.PostedEvents.ContainsKey(m_scriptItem.ItemID)); - - List events = m_engine.PostedEvents[m_scriptItem.ItemID]; - Assert.That(events.Count, Is.EqualTo(1)); - EventParams eventParams = events[0]; - Assert.That(eventParams.EventName, Is.EqualTo("http_request")); - - UUID returnKey; - string rawReturnKey = eventParams.Params[0].ToString(); - string method = eventParams.Params[1].ToString(); - string body = eventParams.Params[2].ToString(); - - Assert.That(UUID.TryParse(rawReturnKey, out returnKey), Is.True); - Assert.That(method, Is.EqualTo("GET")); - Assert.That(body, Is.EqualTo("")); - } - } - - private void AssertHttpResponse(string uri, string expectedResponse) - { - HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(uri); - - using (HttpWebResponse webResponse = (HttpWebResponse)webRequest.GetResponse()) - { - using (Stream stream = webResponse.GetResponseStream()) - { - using (StreamReader reader = new StreamReader(stream)) - { - Assert.That(reader.ReadToEnd(), Is.EqualTo(expectedResponse)); - } - } - } - } - } -} diff --git a/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiInventoryTests.cs b/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiInventoryTests.cs deleted file mode 100644 index cc5f721bf08..00000000000 --- a/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiInventoryTests.cs +++ /dev/null @@ -1,300 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections.Generic; -using System.Reflection; -using System.Text; -using log4net; -using Nini.Config; -using NUnit.Framework; -using OpenMetaverse; -using OpenMetaverse.Assets; -using OpenMetaverse.StructuredData; -using OpenSim.Framework; -using OpenSim.Region.CoreModules.Avatar.AvatarFactory; -using OpenSim.Region.OptionalModules.World.NPC; -using OpenSim.Region.Framework.Scenes; -using OpenSim.Region.CoreModules.World.Permissions; -using OpenSim.Region.ScriptEngine.Shared; -using OpenSim.Region.ScriptEngine.Shared.Api; -using OpenSim.Services.Interfaces; -using OpenSim.Tests.Common; -using PermissionMask = OpenSim.Framework.PermissionMask; - -namespace OpenSim.Region.ScriptEngine.Shared.Tests -{ - /// - /// Tests for inventory functions in LSL - /// - [TestFixture] - /* - public class LSL_ApiInventoryTests : OpenSimTestCase - { - protected Scene m_scene; - protected XEngine.XEngine m_engine; - - [SetUp] - public override void SetUp() - { - base.SetUp(); - - IConfigSource initConfigSource = new IniConfigSource(); - IConfig config = initConfigSource.AddConfig("Startup"); - config.Set("serverside_object_permissions", true); - config =initConfigSource.AddConfig("Permissions"); - config.Set("permissionmodules", "DefaultPermissionsModule"); - config.Set("serverside_object_permissions", true); - config.Set("propagate_permissions", true); - - config = initConfigSource.AddConfig("XEngine"); - config.Set("Enabled", "true"); - config = initConfigSource.AddConfig("OSSL"); - config.Set("DebuggerSafe", false); - config.Set("AllowOSFunctions", "true"); - config.Set("OSFunctionThreatLevel", "Severe"); - - m_scene = new SceneHelpers().SetupScene(); - SceneHelpers.SetupSceneModules(m_scene, initConfigSource, new object[] { new DefaultPermissionsModule() }); - m_engine = new XEngine.XEngine(); - m_engine.Initialise(initConfigSource); - m_engine.AddRegion(m_scene); - } - - /// - /// Test giving inventory from an object to an object where both are owned by the same user. - /// - [Test] - public void TestLlGiveInventoryO2OSameOwner() - { - TestHelpers.InMethod(); -// log4net.Config.XmlConfigurator.Configure(); - - UUID userId = TestHelpers.ParseTail(0x1); - string inventoryItemName = "item1"; - - SceneObjectGroup so1 = SceneHelpers.CreateSceneObject(1, userId, "so1", 0x10); - m_scene.AddSceneObject(so1); - - // Create an object embedded inside the first - UUID itemId = TestHelpers.ParseTail(0x20); - TaskInventoryHelpers.AddSceneObject(m_scene.AssetService, so1.RootPart, inventoryItemName, itemId, userId); - - LSL_Api api = new LSL_Api(); - api.Initialize(m_engine, so1.RootPart, null); - - // Create a second object - SceneObjectGroup so2 = SceneHelpers.CreateSceneObject(1, userId, "so2", 0x100); - m_scene.AddSceneObject(so2); - - api.llGiveInventory(so2.UUID.ToString(), inventoryItemName); - - // Item has copy permissions so original should stay intact. - List originalItems = so1.RootPart.Inventory.GetInventoryItems(); - Assert.That(originalItems.Count, Is.EqualTo(1)); - - List copiedItems = so2.RootPart.Inventory.GetInventoryItems(inventoryItemName); - Assert.That(copiedItems.Count, Is.EqualTo(1)); - Assert.That(copiedItems[0].Name, Is.EqualTo(inventoryItemName)); - } - - /// - /// Test giving inventory from an object to an object where they have different owners - /// - [Test] - public void TestLlGiveInventoryO2ODifferentOwners() - { - TestHelpers.InMethod(); -// log4net.Config.XmlConfigurator.Configure(); - - UUID user1Id = TestHelpers.ParseTail(0x1); - UUID user2Id = TestHelpers.ParseTail(0x2); - string inventoryItemName = "item1"; - - SceneObjectGroup so1 = SceneHelpers.CreateSceneObject(1, user1Id, "so1", 0x10); - m_scene.AddSceneObject(so1); - LSL_Api api = new LSL_Api(); - api.Initialize(m_engine, so1.RootPart, null); - - // Create an object embedded inside the first - UUID itemId = TestHelpers.ParseTail(0x20); - TaskInventoryHelpers.AddSceneObject(m_scene.AssetService, so1.RootPart, inventoryItemName, itemId, user1Id); - - // Create a second object - SceneObjectGroup so2 = SceneHelpers.CreateSceneObject(1, user2Id, "so2", 0x100); - m_scene.AddSceneObject(so2); - LSL_Api api2 = new LSL_Api(); - api2.Initialize(m_engine, so2.RootPart, null); - - // *** Firstly, we test where llAllowInventoryDrop() has not been called. *** - api.llGiveInventory(so2.UUID.ToString(), inventoryItemName); - - { - // Item has copy permissions so original should stay intact. - List originalItems = so1.RootPart.Inventory.GetInventoryItems(); - Assert.That(originalItems.Count, Is.EqualTo(1)); - - // Should have not copied - List copiedItems = so2.RootPart.Inventory.GetInventoryItems(inventoryItemName); - Assert.That(copiedItems.Count, Is.EqualTo(0)); - } - - // *** Secondly, we turn on allow inventory drop in the target and retest. *** - api2.llAllowInventoryDrop(1); - api.llGiveInventory(so2.UUID.ToString(), inventoryItemName); - - { - // Item has copy permissions so original should stay intact. - List originalItems = so1.RootPart.Inventory.GetInventoryItems(); - Assert.That(originalItems.Count, Is.EqualTo(1)); - - // Should now have copied. - List copiedItems = so2.RootPart.Inventory.GetInventoryItems(inventoryItemName); - Assert.That(copiedItems.Count, Is.EqualTo(1)); - Assert.That(copiedItems[0].Name, Is.EqualTo(inventoryItemName)); - } - } - - /// - /// Test giving inventory from an object to an avatar that is not the object's owner. - /// - [Test] - public void TestLlGiveInventoryO2DifferentAvatar() - { - TestHelpers.InMethod(); - // TestHelpers.EnableLogging(); - - UUID user1Id = TestHelpers.ParseTail(0x1); - UUID user2Id = TestHelpers.ParseTail(0x2); - string inventoryItemName = "item1"; - - SceneObjectGroup so1 = SceneHelpers.CreateSceneObject(1, user1Id, "so1", 0x10); - m_scene.AddSceneObject(so1); - LSL_Api api = new LSL_Api(); - api.Initialize(m_engine, so1.RootPart, null); - - // Create an object embedded inside the first - UUID itemId = TestHelpers.ParseTail(0x20); - TaskInventoryHelpers.AddSceneObject(m_scene.AssetService, so1.RootPart, inventoryItemName, itemId, user1Id); - - UserAccountHelpers.CreateUserWithInventory(m_scene, user2Id); - - api.llGiveInventory(user2Id.ToString(), inventoryItemName); - - InventoryItemBase receivedItem - = UserInventoryHelpers.GetInventoryItem( - m_scene.InventoryService, user2Id, string.Format("Objects/{0}", inventoryItemName)); - - Assert.IsNotNull(receivedItem); - } - - /// - /// Test giving inventory from an object to an avatar that is not the object's owner and where the next - /// permissions do not include mod. - /// - [Test] - public void TestLlGiveInventoryO2DifferentAvatarNoMod() - { - TestHelpers.InMethod(); -// TestHelpers.EnableLogging(); - - UUID user1Id = TestHelpers.ParseTail(0x1); - UUID user2Id = TestHelpers.ParseTail(0x2); - string inventoryItemName = "item1"; - - SceneObjectGroup so1 = SceneHelpers.CreateSceneObject(1, user1Id, "so1", 0x10); - m_scene.AddSceneObject(so1); - LSL_Api api = new LSL_Api(); - api.Initialize(m_engine, so1.RootPart, null); - - // Create an object embedded inside the first - UUID itemId = TestHelpers.ParseTail(0x20); - TaskInventoryItem tii - = TaskInventoryHelpers.AddSceneObject(m_scene.AssetService, so1.RootPart, inventoryItemName, itemId, user1Id); - tii.NextPermissions &= ~((uint)PermissionMask.Modify); - - UserAccountHelpers.CreateUserWithInventory(m_scene, user2Id); - - api.llGiveInventory(user2Id.ToString(), inventoryItemName); - - InventoryItemBase receivedItem - = UserInventoryHelpers.GetInventoryItem( - m_scene.InventoryService, user2Id, string.Format("Objects/{0}", inventoryItemName)); - - Assert.IsNotNull(receivedItem); - Assert.AreEqual(0, receivedItem.CurrentPermissions & (uint)PermissionMask.Modify); - } - - [Test] - public void TestLlRemoteLoadScriptPin() - { - TestHelpers.InMethod(); -// TestHelpers.EnableLogging(); - - UUID user1Id = TestHelpers.ParseTail(0x1); - UUID user2Id = TestHelpers.ParseTail(0x2); - - SceneObjectGroup sourceSo = SceneHelpers.AddSceneObject(m_scene, "sourceSo", user1Id); - m_scene.AddSceneObject(sourceSo); - LSL_Api api = new LSL_Api(); - api.Initialize(m_engine, sourceSo.RootPart, null); - TaskInventoryHelpers.AddScript(m_scene.AssetService, sourceSo.RootPart, "script", "Hello World"); - - SceneObjectGroup targetSo = SceneHelpers.AddSceneObject(m_scene, "targetSo", user1Id); - SceneObjectGroup otherOwnedTargetSo = SceneHelpers.AddSceneObject(m_scene, "otherOwnedTargetSo", user2Id); - - // Test that we cannot load a script when the target pin has never been set (i.e. it is zero) - api.llRemoteLoadScriptPin(targetSo.UUID.ToString(), "script", 0, 0, 0); - Assert.IsNull(targetSo.RootPart.Inventory.GetInventoryItem("script")); - - // Test that we cannot load a script when the given pin does not match the target - targetSo.RootPart.ScriptAccessPin = 5; - api.llRemoteLoadScriptPin(targetSo.UUID.ToString(), "script", 3, 0, 0); - Assert.IsNull(targetSo.RootPart.Inventory.GetInventoryItem("script")); - - // Test that we cannot load into a prim with a different owner - otherOwnedTargetSo.RootPart.ScriptAccessPin = 3; - api.llRemoteLoadScriptPin(otherOwnedTargetSo.UUID.ToString(), "script", 3, 0, 0); - Assert.IsNull(otherOwnedTargetSo.RootPart.Inventory.GetInventoryItem("script")); - - // Test that we can load a script when given pin and dest pin match. - targetSo.RootPart.ScriptAccessPin = 3; - api.llRemoteLoadScriptPin(targetSo.UUID.ToString(), "script", 3, 0, 0); - TaskInventoryItem insertedItem = targetSo.RootPart.Inventory.GetInventoryItem("script"); - Assert.IsNotNull(insertedItem); - - // Test that we can no longer load if access pin is unset - targetSo.RootPart.Inventory.RemoveInventoryItem(insertedItem.ItemID); - Assert.IsNull(targetSo.RootPart.Inventory.GetInventoryItem("script")); - - targetSo.RootPart.ScriptAccessPin = 0; - api.llRemoteLoadScriptPin(otherOwnedTargetSo.UUID.ToString(), "script", 3, 0, 0); - Assert.IsNull(otherOwnedTargetSo.RootPart.Inventory.GetInventoryItem("script")); - } - } - */ -} diff --git a/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiLinkingTests.cs b/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiLinkingTests.cs deleted file mode 100644 index 9c262db1244..00000000000 --- a/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiLinkingTests.cs +++ /dev/null @@ -1,192 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections.Generic; -using System.Reflection; -using System.Text; -using log4net; -using Nini.Config; -using NUnit.Framework; -using OpenMetaverse; -using OpenMetaverse.Assets; -using OpenMetaverse.StructuredData; -using OpenSim.Framework; -using OpenSim.Region.CoreModules.Avatar.AvatarFactory; -using OpenSim.Region.OptionalModules.World.NPC; -using OpenSim.Region.Framework.Scenes; -using OpenSim.Region.ScriptEngine.Shared; -using OpenSim.Region.ScriptEngine.Shared.Api; -using OpenSim.Region.ScriptEngine.Shared.ScriptBase; -using OpenSim.Services.Interfaces; -using OpenSim.Tests.Common; - -namespace OpenSim.Region.ScriptEngine.Shared.Tests -{ - /// - /// Tests for linking functions in LSL - /// - /// - /// This relates to LSL. Actual linking functionality should be tested in the main - /// OpenSim.Region.Framework.Scenes.Tests.SceneObjectLinkingTests. - /// - [TestFixture] - public class LSL_ApiLinkingTests : OpenSimTestCase - { - /* - protected Scene m_scene; - protected XEngine.XEngine m_engine; - - [SetUp] - public override void SetUp() - { - base.SetUp(); - - IConfigSource initConfigSource = new IniConfigSource(); - IConfig config = initConfigSource.AddConfig("XEngine"); - config.Set("Enabled", "true"); - - config = initConfigSource.AddConfig("OSSL"); - config.Set("DebuggerSafe", false); - config.Set("AllowOSFunctions", "true"); - config.Set("OSFunctionThreatLevel", "Severe"); - - m_scene = new SceneHelpers().SetupScene(); - SceneHelpers.SetupSceneModules(m_scene, initConfigSource); - - m_engine = new XEngine.XEngine(); - m_engine.Initialise(initConfigSource); - m_engine.AddRegion(m_scene); - } - - [Test] - public void TestllCreateLink() - { - TestHelpers.InMethod(); - - UUID ownerId = TestHelpers.ParseTail(0x1); - - SceneObjectGroup grp1 = SceneHelpers.CreateSceneObject(2, ownerId, "grp1-", 0x10); - grp1.AbsolutePosition = new Vector3(10, 10, 10); - m_scene.AddSceneObject(grp1); - - // FIXME: This should really be a script item (with accompanying script) - TaskInventoryItem grp1Item - = TaskInventoryHelpers.AddNotecard( - m_scene.AssetService, grp1.RootPart, "ncItem", TestHelpers.ParseTail(0x800), TestHelpers.ParseTail(0x900), "Hello World!"); - grp1Item.PermsMask |= ScriptBaseClass.PERMISSION_CHANGE_LINKS; - - SceneObjectGroup grp2 = SceneHelpers.CreateSceneObject(2, ownerId, "grp2-", 0x20); - grp2.AbsolutePosition = new Vector3(20, 20, 20); - - // <180,0,0> - grp2.UpdateGroupRotationR(Quaternion.CreateFromEulers(180 * Utils.DEG_TO_RAD, 0, 0)); - - m_scene.AddSceneObject(grp2); - - LSL_Api apiGrp1 = new LSL_Api(); - apiGrp1.Initialize(m_engine, grp1.RootPart, grp1Item); - - apiGrp1.llCreateLink(grp2.UUID.ToString(), ScriptBaseClass.TRUE); - - Assert.That(grp1.Parts.Length, Is.EqualTo(4)); - Assert.That(grp2.IsDeleted, Is.True); - } - - [Test] - public void TestllBreakLink() - { - TestHelpers.InMethod(); - - UUID ownerId = TestHelpers.ParseTail(0x1); - - SceneObjectGroup grp1 = SceneHelpers.CreateSceneObject(2, ownerId, "grp1-", 0x10); - grp1.AbsolutePosition = new Vector3(10, 10, 10); - m_scene.AddSceneObject(grp1); - - // FIXME: This should really be a script item (with accompanying script) - TaskInventoryItem grp1Item - = TaskInventoryHelpers.AddNotecard( - m_scene.AssetService, grp1.RootPart, "ncItem", TestHelpers.ParseTail(0x800), TestHelpers.ParseTail(0x900), "Hello World!"); - - grp1Item.PermsMask |= ScriptBaseClass.PERMISSION_CHANGE_LINKS; - - LSL_Api apiGrp1 = new LSL_Api(); - apiGrp1.Initialize(m_engine, grp1.RootPart, grp1Item); - - apiGrp1.llBreakLink(2); - - Assert.That(grp1.Parts.Length, Is.EqualTo(1)); - - SceneObjectGroup grp2 = m_scene.GetSceneObjectGroup("grp1-Part1"); - Assert.That(grp2, Is.Not.Null); - } - - [Test] - public void TestllBreakAllLinks() - { - TestHelpers.InMethod(); - - UUID ownerId = TestHelpers.ParseTail(0x1); - - SceneObjectGroup grp1 = SceneHelpers.CreateSceneObject(3, ownerId, "grp1-", 0x10); - grp1.AbsolutePosition = new Vector3(10, 10, 10); - m_scene.AddSceneObject(grp1); - - // FIXME: This should really be a script item (with accompanying script) - TaskInventoryItem grp1Item - = TaskInventoryHelpers.AddNotecard( - m_scene.AssetService, grp1.RootPart, "ncItem", TestHelpers.ParseTail(0x800), TestHelpers.ParseTail(0x900), "Hello World!"); - - grp1Item.PermsMask |= ScriptBaseClass.PERMISSION_CHANGE_LINKS; - - LSL_Api apiGrp1 = new LSL_Api(); - apiGrp1.Initialize(m_engine, grp1.RootPart, grp1Item); - - apiGrp1.llBreakAllLinks(); - - { - SceneObjectGroup nowGrp = m_scene.GetSceneObjectGroup("grp1-Part1"); - Assert.That(nowGrp, Is.Not.Null); - Assert.That(nowGrp.Parts.Length, Is.EqualTo(1)); - } - - { - SceneObjectGroup nowGrp = m_scene.GetSceneObjectGroup("grp1-Part2"); - Assert.That(nowGrp, Is.Not.Null); - Assert.That(nowGrp.Parts.Length, Is.EqualTo(1)); - } - - { - SceneObjectGroup nowGrp = m_scene.GetSceneObjectGroup("grp1-Part3"); - Assert.That(nowGrp, Is.Not.Null); - Assert.That(nowGrp.Parts.Length, Is.EqualTo(1)); - } - } - } - */ -} diff --git a/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiListTests.cs b/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiListTests.cs deleted file mode 100644 index 7bc6d91b144..00000000000 --- a/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiListTests.cs +++ /dev/null @@ -1,139 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections.Generic; -using NUnit.Framework; -using OpenSim.Framework; -using OpenSim.Tests.Common; -using OpenSim.Region.ScriptEngine.Shared; -using OpenSim.Region.Framework.Scenes; -using Nini.Config; -using OpenSim.Region.ScriptEngine.Shared.Api; -using OpenSim.Region.ScriptEngine.Shared.ScriptBase; -using OpenMetaverse; - -using LSL_Float = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLFloat; -using LSL_Integer = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLInteger; -using LSL_List = OpenSim.Region.ScriptEngine.Shared.LSL_Types.list; -using LSL_String = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString; - -namespace OpenSim.Region.ScriptEngine.Shared.Tests -{ - [TestFixture] - public class LSL_ApiListTests : OpenSimTestCase - { - private LSL_Api m_lslApi; - - [SetUp] - public override void SetUp() - { - base.SetUp(); - - IConfigSource initConfigSource = new IniConfigSource(); - IConfig config = initConfigSource.AddConfig("XEngine"); - config.Set("Enabled", "true"); - - config = initConfigSource.AddConfig("OSSL"); - config.Set("DebuggerSafe", false); - config.Set("AllowOSFunctions", "true"); - config.Set("OSFunctionThreatLevel", "Severe"); - Scene scene = new SceneHelpers().SetupScene(); - SceneObjectPart part = SceneHelpers.AddSceneObject(scene).RootPart; - - XEngine.XEngine engine = new XEngine.XEngine(); - engine.Initialise(initConfigSource); - engine.AddRegion(scene); - - m_lslApi = new LSL_Api(); - m_lslApi.Initialize(engine, part, null); - } - - [Test] - public void TestllListFindList() - { - TestHelpers.InMethod(); - - LSL_List src = new LSL_List(new LSL_Integer(1), new LSL_Integer(2), new LSL_Integer(3)); - - { - // Test for a single item that should be found - int result = m_lslApi.llListFindList(src, new LSL_List(new LSL_Integer(4))); - Assert.That(result, Is.EqualTo(-1)); - } - - { - // Test for a single item that should be found - int result = m_lslApi.llListFindList(src, new LSL_List(new LSL_Integer(2))); - Assert.That(result, Is.EqualTo(1)); - } - - { - // Test for a constant that should be found - int result = m_lslApi.llListFindList(src, new LSL_List(ScriptBaseClass.AGENT)); - Assert.That(result, Is.EqualTo(0)); - } - - { - // Test for a list that should be found - int result = m_lslApi.llListFindList(src, new LSL_List(new LSL_Integer(2), new LSL_Integer(3))); - Assert.That(result, Is.EqualTo(1)); - } - - { - // Test for a single item not in the list - int result = m_lslApi.llListFindList(src, new LSL_List(new LSL_Integer(4))); - Assert.That(result, Is.EqualTo(-1)); - } - - { - // Test for something that should not be cast - int result = m_lslApi.llListFindList(src, new LSL_List(new LSL_String("4"))); - Assert.That(result, Is.EqualTo(-1)); - } - - { - // Test for a list not in the list - int result - = m_lslApi.llListFindList( - src, new LSL_List(new LSL_Integer(2), new LSL_Integer(3), new LSL_Integer(4))); - Assert.That(result, Is.EqualTo(-1)); - } - - { - LSL_List srcWithConstants - = new LSL_List(new LSL_Integer(3), ScriptBaseClass.AGENT, ScriptBaseClass.OS_NPC_LAND_AT_TARGET); - - // Test for constants that appears in the source list that should be found - int result - = m_lslApi.llListFindList(srcWithConstants, new LSL_List(new LSL_Integer(1), new LSL_Integer(2))); - - Assert.That(result, Is.EqualTo(1)); - } - } - } - } diff --git a/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiNotecardTests.cs b/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiNotecardTests.cs deleted file mode 100644 index dd60a87c786..00000000000 --- a/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiNotecardTests.cs +++ /dev/null @@ -1,269 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Net; -using System.Reflection; -using System.Text; -using log4net; -using Nini.Config; -using NUnit.Framework; -using OpenMetaverse; -using OpenSim.Framework; -using OpenSim.Framework.Servers; -using OpenSim.Framework.Servers.HttpServer; -using OpenSim.Region.CoreModules.Scripting.LSLHttp; -using OpenSim.Region.Framework.Scenes; -using OpenSim.Region.ScriptEngine.Shared; -using OpenSim.Region.ScriptEngine.Shared.Api; -using OpenSim.Region.ScriptEngine.Shared.ScriptBase; -using OpenSim.Services.Interfaces; -using OpenSim.Tests.Common; - -namespace OpenSim.Region.ScriptEngine.Shared.Tests -{ - /// - /// Tests for notecard related functions in LSL - /// - [TestFixture] - public class LSL_ApiNotecardTests : OpenSimTestCase - { - private Scene m_scene; - private MockScriptEngine m_engine; - - private SceneObjectGroup m_so; - private TaskInventoryItem m_scriptItem; - private LSL_Api m_lslApi; - - [OneTimeSetUp] - public void TestFixtureSetUp() - { - // Don't allow tests to be bamboozled by asynchronous events. Execute everything on the same thread. - Util.FireAndForgetMethod = FireAndForgetMethod.RegressionTest; - } - - [OneTimeTearDown] - public void TestFixureTearDown() - { - // We must set this back afterwards, otherwise later tests will fail since they're expecting multiple - // threads. Possibly, later tests should be rewritten so none of them require async stuff (which regression - // tests really shouldn't). - Util.FireAndForgetMethod = Util.DefaultFireAndForgetMethod; - } - - [SetUp] - public override void SetUp() - { - base.SetUp(); - - m_engine = new MockScriptEngine(); - - m_scene = new SceneHelpers().SetupScene(); - SceneHelpers.SetupSceneModules(m_scene, new IniConfigSource(), m_engine); - - m_so = SceneHelpers.AddSceneObject(m_scene); - m_scriptItem = TaskInventoryHelpers.AddScript(m_scene.AssetService, m_so.RootPart); - - // This is disconnected from the actual script - the mock engine does not set up any LSL_Api atm. - // Possibly this could be done and we could obtain it directly from the MockScriptEngine. - m_lslApi = new LSL_Api(); - m_lslApi.Initialize(m_engine, m_so.RootPart, m_scriptItem); - } - - [Test] - public void TestLlGetNotecardLine() - { - TestHelpers.InMethod(); - - string[] ncLines = { "One", "Twoè", "Three" }; - - TaskInventoryItem ncItem - = TaskInventoryHelpers.AddNotecard(m_scene.AssetService, m_so.RootPart, "nc", "1", "10", string.Join("\n", ncLines)); - - AssertValidNotecardLine(ncItem.Name, 0, ncLines[0]); - AssertValidNotecardLine(ncItem.Name, 2, ncLines[2]); - AssertValidNotecardLine(ncItem.Name, 3, ScriptBaseClass.EOF); - AssertValidNotecardLine(ncItem.Name, 4, ScriptBaseClass.EOF); - - // XXX: Is this correct or do we really expect no dataserver event to fire at all? - AssertValidNotecardLine(ncItem.Name, -1, ""); - AssertValidNotecardLine(ncItem.Name, -2, ""); - } - - [Test] - public void TestLlGetNotecardLine_NoNotecard() - { - TestHelpers.InMethod(); - - AssertInValidNotecardLine("nc", 0); - } - - [Test] - public void TestLlGetNotecardLine_NotANotecard() - { - TestHelpers.InMethod(); - - TaskInventoryItem ncItem = TaskInventoryHelpers.AddScript(m_scene.AssetService, m_so.RootPart, "nc1", "Not important"); - - AssertInValidNotecardLine(ncItem.Name, 0); - } - - private void AssertValidNotecardLine(string ncName, int lineNumber, string assertLine) - { - string key = m_lslApi.llGetNotecardLine(ncName, lineNumber); - Assert.That(key, Is.Not.EqualTo(UUID.Zero.ToString())); - - Assert.That(m_engine.PostedEvents.Count, Is.EqualTo(1)); - Assert.That(m_engine.PostedEvents.ContainsKey(m_scriptItem.ItemID)); - - List events = m_engine.PostedEvents[m_scriptItem.ItemID]; - Assert.That(events.Count, Is.EqualTo(1)); - EventParams eventParams = events[0]; - - Assert.That(eventParams.EventName, Is.EqualTo("dataserver")); - Assert.That(eventParams.Params[0].ToString(), Is.EqualTo(key)); - Assert.That(eventParams.Params[1].ToString(), Is.EqualTo(assertLine)); - - m_engine.ClearPostedEvents(); - } - - private void AssertInValidNotecardLine(string ncName, int lineNumber) - { - string key = m_lslApi.llGetNotecardLine(ncName, lineNumber); - Assert.That(key, Is.EqualTo(UUID.Zero.ToString())); - - Assert.That(m_engine.PostedEvents.Count, Is.EqualTo(0)); - } - -// [Test] -// public void TestLlReleaseUrl() -// { -// TestHelpers.InMethod(); -// -// m_lslApi.llRequestURL(); -// string returnedUri = m_engine.PostedEvents[m_scriptItem.ItemID][0].Params[2].ToString(); -// -// { -// // Check that the initial number of URLs is correct -// Assert.That(m_lslApi.llGetFreeURLs().value, Is.EqualTo(m_urlModule.TotalUrls - 1)); -// } -// -// { -// // Check releasing a non-url -// m_lslApi.llReleaseURL("GARBAGE"); -// Assert.That(m_lslApi.llGetFreeURLs().value, Is.EqualTo(m_urlModule.TotalUrls - 1)); -// } -// -// { -// // Check releasing a non-existing url -// m_lslApi.llReleaseURL("http://example.com"); -// Assert.That(m_lslApi.llGetFreeURLs().value, Is.EqualTo(m_urlModule.TotalUrls - 1)); -// } -// -// { -// // Check URL release -// m_lslApi.llReleaseURL(returnedUri); -// Assert.That(m_lslApi.llGetFreeURLs().value, Is.EqualTo(m_urlModule.TotalUrls)); -// -// HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(returnedUri); -// -// bool gotExpectedException = false; -// -// try -// { -// using (HttpWebResponse webResponse = (HttpWebResponse)webRequest.GetResponse()) -// {} -// } -// catch (WebException e) -// { -// using (HttpWebResponse response = (HttpWebResponse)e.Response) -// gotExpectedException = response.StatusCode == HttpStatusCode.NotFound; -// } -// -// Assert.That(gotExpectedException, Is.True); -// } -// -// { -// // Check releasing the same URL again -// m_lslApi.llReleaseURL(returnedUri); -// Assert.That(m_lslApi.llGetFreeURLs().value, Is.EqualTo(m_urlModule.TotalUrls)); -// } -// } -// -// [Test] -// public void TestLlRequestUrl() -// { -// TestHelpers.InMethod(); -// -// string requestId = m_lslApi.llRequestURL(); -// Assert.That(requestId, Is.Not.EqualTo(UUID.Zero.ToString())); -// string returnedUri; -// -// { -// // Check that URL is correctly set up -// Assert.That(m_lslApi.llGetFreeURLs().value, Is.EqualTo(m_urlModule.TotalUrls - 1)); -// -// Assert.That(m_engine.PostedEvents.ContainsKey(m_scriptItem.ItemID)); -// -// List events = m_engine.PostedEvents[m_scriptItem.ItemID]; -// Assert.That(events.Count, Is.EqualTo(1)); -// EventParams eventParams = events[0]; -// Assert.That(eventParams.EventName, Is.EqualTo("http_request")); -// -// UUID returnKey; -// string rawReturnKey = eventParams.Params[0].ToString(); -// string method = eventParams.Params[1].ToString(); -// returnedUri = eventParams.Params[2].ToString(); -// -// Assert.That(UUID.TryParse(rawReturnKey, out returnKey), Is.True); -// Assert.That(method, Is.EqualTo(ScriptBaseClass.URL_REQUEST_GRANTED)); -// Assert.That(Uri.IsWellFormedUriString(returnedUri, UriKind.Absolute), Is.True); -// } -// -// { -// // Check that request to URL works. -// string testResponse = "Hello World"; -// -// m_engine.ClearPostedEvents(); -// m_engine.PostEventHook -// += (itemId, evp) => m_lslApi.llHTTPResponse(evp.Params[0].ToString(), 200, testResponse); -// -//// Console.WriteLine("Trying {0}", returnedUri); -// HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(returnedUri); -// -// AssertHttpResponse(returnedUri, testResponse); -// -// Assert.That(m_engine.PostedEvents.ContainsKey(m_scriptItem.ItemID)); -// -// List events = m_engine.PostedEvents[m_scriptItem.ItemID]; -// Assert.That(events.Count, Is.EqualTo(1)); -// EventParams eventParams = events[0]; -// Assert.That(eventParams.EventName, Is.EqualTo("http_request")); -// -// UUID returnKey; -// string rawReturnKey = eventParams.Params[0].ToString(); -// string method = eventParams.Params[1].ToString(); -// string body = eventParams.Params[2].ToString(); -// -// Assert.That(UUID.TryParse(rawReturnKey, out returnKey), Is.True); -// Assert.That(method, Is.EqualTo("GET")); -// Assert.That(body, Is.EqualTo("")); -// } -// } -// -// private void AssertHttpResponse(string uri, string expectedResponse) -// { -// HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(uri); -// -// using (HttpWebResponse webResponse = (HttpWebResponse)webRequest.GetResponse()) -// { -// using (Stream stream = webResponse.GetResponseStream()) -// { -// using (StreamReader reader = new StreamReader(stream)) -// { -// Assert.That(reader.ReadToEnd(), Is.EqualTo(expectedResponse)); -// } -// } -// } -// } - } -} diff --git a/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiObjectTests.cs b/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiObjectTests.cs deleted file mode 100644 index cc550ad5fd8..00000000000 --- a/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiObjectTests.cs +++ /dev/null @@ -1,399 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections.Generic; -using System.Reflection; -using System.Text; -using log4net; -using Nini.Config; -using NUnit.Framework; -using OpenMetaverse; -using OpenMetaverse.Assets; -using OpenMetaverse.StructuredData; -using OpenSim.Framework; -using OpenSim.Region.CoreModules.Avatar.AvatarFactory; -using OpenSim.Region.OptionalModules.World.NPC; -using OpenSim.Region.Framework.Scenes; -using OpenSim.Region.ScriptEngine.Shared; -using OpenSim.Region.ScriptEngine.Shared.Api; -using OpenSim.Region.ScriptEngine.Shared.ScriptBase; -using OpenSim.Services.Interfaces; -using OpenSim.Tests.Common; -using LSL_Integer = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLInteger; -using LSL_List = OpenSim.Region.ScriptEngine.Shared.LSL_Types.list; - -namespace OpenSim.Region.ScriptEngine.Shared.Tests -{ - [TestFixture] - public class LSL_ApiObjectTests : OpenSimTestCase - { - /* - private const double VECTOR_COMPONENT_ACCURACY = 0.0000005d; - private const float FLOAT_ACCURACY = 0.00005f; - - protected Scene m_scene; - protected XEngine.XEngine m_engine; - - [SetUp] - public override void SetUp() - { - base.SetUp(); - - IConfigSource initConfigSource = new IniConfigSource(); - IConfig config = initConfigSource.AddConfig("XEngine"); - config.Set("Enabled", "true"); - - m_scene = new SceneHelpers().SetupScene(); - SceneHelpers.SetupSceneModules(m_scene, initConfigSource); - - m_engine = new XEngine.XEngine(); - m_engine.Initialise(initConfigSource); - m_engine.AddRegion(m_scene); - } - - [Test] - public void TestllGetLinkPrimitiveParams() - { - TestHelpers.InMethod(); - TestHelpers.EnableLogging(); - - UUID ownerId = TestHelpers.ParseTail(0x1); - - SceneObjectGroup grp1 = SceneHelpers.CreateSceneObject(2, ownerId, "grp1-", 0x10); - grp1.AbsolutePosition = new Vector3(10, 11, 12); - m_scene.AddSceneObject(grp1); - - LSL_Api apiGrp1 = new LSL_Api(); - apiGrp1.Initialize(m_engine, grp1.RootPart, null); - - // Check simple 1 prim case - { - LSL_List resList - = apiGrp1.llGetLinkPrimitiveParams(1, new LSL_List(new LSL_Integer(ScriptBaseClass.PRIM_ROTATION))); - - Assert.That(resList.Length, Is.EqualTo(1)); - } - - // Check 2 prim case - { - LSL_List resList - = apiGrp1.llGetLinkPrimitiveParams( - 1, - new LSL_List( - new LSL_Integer(ScriptBaseClass.PRIM_ROTATION), - new LSL_Integer(ScriptBaseClass.PRIM_LINK_TARGET), - new LSL_Integer(2), - new LSL_Integer(ScriptBaseClass.PRIM_ROTATION))); - - Assert.That(resList.Length, Is.EqualTo(2)); - } - - // Check invalid parameters are ignored - { - LSL_List resList - = apiGrp1.llGetLinkPrimitiveParams(3, new LSL_List(new LSL_Integer(ScriptBaseClass.PRIM_ROTATION))); - - Assert.That(resList.Length, Is.EqualTo(0)); - } - - // Check all parameters are ignored if an initial bad link is given - { - LSL_List resList - = apiGrp1.llGetLinkPrimitiveParams( - 3, - new LSL_List( - new LSL_Integer(ScriptBaseClass.PRIM_ROTATION), - new LSL_Integer(ScriptBaseClass.PRIM_LINK_TARGET), - new LSL_Integer(1), - new LSL_Integer(ScriptBaseClass.PRIM_ROTATION))); - - Assert.That(resList.Length, Is.EqualTo(0)); - } - - // Check only subsequent parameters are ignored when we hit the first bad link number - { - LSL_List resList - = apiGrp1.llGetLinkPrimitiveParams( - 1, - new LSL_List( - new LSL_Integer(ScriptBaseClass.PRIM_ROTATION), - new LSL_Integer(ScriptBaseClass.PRIM_LINK_TARGET), - new LSL_Integer(3), - new LSL_Integer(ScriptBaseClass.PRIM_ROTATION))); - - Assert.That(resList.Length, Is.EqualTo(1)); - } - } - - [Test] - // llSetPrimitiveParams and llGetPrimitiveParams test. - public void TestllSetPrimitiveParams() - { - TestHelpers.InMethod(); - - // Create Prim1. - Scene scene = new SceneHelpers().SetupScene(); - string obj1Name = "Prim1"; - UUID objUuid = new UUID("00000000-0000-0000-0000-000000000001"); - SceneObjectPart part1 = - new SceneObjectPart(UUID.Zero, PrimitiveBaseShape.Default, - Vector3.Zero, Quaternion.Identity, - Vector3.Zero) { Name = obj1Name, UUID = objUuid }; - Assert.That(scene.AddNewSceneObject(new SceneObjectGroup(part1), false), Is.True); - - LSL_Api apiGrp1 = new LSL_Api(); - apiGrp1.Initialize(m_engine, part1, null); - - // Note that prim hollow check is passed with the other prim params in order to allow the - // specification of a different check value from the prim param. A cylinder, prism, sphere, - // torus or ring, with a hole shape of square, is limited to a hollow of 70%. Test 5 below - // specifies a value of 95% and checks to see if 70% was properly returned. - - // Test a sphere. - CheckllSetPrimitiveParams( - apiGrp1, - "test 1", // Prim test identification string - new LSL_Types.Vector3(6.0d, 9.9d, 9.9d), // Prim size - ScriptBaseClass.PRIM_TYPE_SPHERE, // Prim type - ScriptBaseClass.PRIM_HOLE_DEFAULT, // Prim hole type - new LSL_Types.Vector3(0.0d, 0.075d, 0.0d), // Prim cut - 0.80f, // Prim hollow - new LSL_Types.Vector3(0.0d, 0.0d, 0.0d), // Prim twist - new LSL_Types.Vector3(0.32d, 0.76d, 0.0d), // Prim dimple - 0.80f); // Prim hollow check - - // Test a prism. - CheckllSetPrimitiveParams( - apiGrp1, - "test 2", // Prim test identification string - new LSL_Types.Vector3(3.5d, 3.5d, 3.5d), // Prim size - ScriptBaseClass.PRIM_TYPE_PRISM, // Prim type - ScriptBaseClass.PRIM_HOLE_CIRCLE, // Prim hole type - new LSL_Types.Vector3(0.0d, 1.0d, 0.0d), // Prim cut - 0.90f, // Prim hollow - new LSL_Types.Vector3(0.0d, 0.0d, 0.0d), // Prim twist - new LSL_Types.Vector3(2.0d, 1.0d, 0.0d), // Prim taper - new LSL_Types.Vector3(0.0d, 0.0d, 0.0d), // Prim shear - 0.90f); // Prim hollow check - - // Test a box. - CheckllSetPrimitiveParams( - apiGrp1, - "test 3", // Prim test identification string - new LSL_Types.Vector3(3.5d, 3.5d, 3.5d), // Prim size - ScriptBaseClass.PRIM_TYPE_BOX, // Prim type - ScriptBaseClass.PRIM_HOLE_TRIANGLE, // Prim hole type - new LSL_Types.Vector3(0.0d, 1.0d, 0.0d), // Prim cut - 0.99f, // Prim hollow - new LSL_Types.Vector3(1.0d, 0.0d, 0.0d), // Prim twist - new LSL_Types.Vector3(1.0d, 1.0d, 0.0d), // Prim taper - new LSL_Types.Vector3(0.0d, 0.0d, 0.0d), // Prim shear - 0.99f); // Prim hollow check - - // Test a tube. - CheckllSetPrimitiveParams( - apiGrp1, - "test 4", // Prim test identification string - new LSL_Types.Vector3(4.2d, 4.2d, 4.2d), // Prim size - ScriptBaseClass.PRIM_TYPE_TUBE, // Prim type - ScriptBaseClass.PRIM_HOLE_SQUARE, // Prim hole type - new LSL_Types.Vector3(0.0d, 1.0d, 0.0d), // Prim cut - 0.00f, // Prim hollow - new LSL_Types.Vector3(1.0d, -1.0d, 0.0d), // Prim twist - new LSL_Types.Vector3(1.0d, 0.05d, 0.0d), // Prim hole size - // Expression for y selected to test precision problems during byte - // cast in SetPrimitiveShapeParams. - new LSL_Types.Vector3(0.0d, 0.35d + 0.1d, 0.0d), // Prim shear - new LSL_Types.Vector3(0.0d, 1.0d, 0.0d), // Prim profile cut - // Expression for y selected to test precision problems during sbyte - // cast in SetPrimitiveShapeParams. - new LSL_Types.Vector3(-1.0d, 0.70d + 0.1d + 0.1d, 0.0d), // Prim taper - 1.11f, // Prim revolutions - 0.88f, // Prim radius - 0.95f, // Prim skew - 0.00f); // Prim hollow check - - // Test a prism. - CheckllSetPrimitiveParams( - apiGrp1, - "test 5", // Prim test identification string - new LSL_Types.Vector3(3.5d, 3.5d, 3.5d), // Prim size - ScriptBaseClass.PRIM_TYPE_PRISM, // Prim type - ScriptBaseClass.PRIM_HOLE_SQUARE, // Prim hole type - new LSL_Types.Vector3(0.0d, 1.0d, 0.0d), // Prim cut - 0.99f, // Prim hollow - // Expression for x selected to test precision problems during sbyte - // cast in SetPrimitiveShapeBlockParams. - new LSL_Types.Vector3(0.7d + 0.2d, 0.0d, 0.0d), // Prim twist - // Expression for y selected to test precision problems during sbyte - // cast in SetPrimitiveShapeParams. - new LSL_Types.Vector3(2.0d, (1.3d + 0.1d), 0.0d), // Prim taper - new LSL_Types.Vector3(0.0d, 0.0d, 0.0d), // Prim shear - 0.70f); // Prim hollow check - - // Test a sculpted prim. - CheckllSetPrimitiveParams( - apiGrp1, - "test 6", // Prim test identification string - new LSL_Types.Vector3(2.0d, 2.0d, 2.0d), // Prim size - ScriptBaseClass.PRIM_TYPE_SCULPT, // Prim type - "be293869-d0d9-0a69-5989-ad27f1946fd4", // Prim map - ScriptBaseClass.PRIM_SCULPT_TYPE_SPHERE); // Prim sculpt type - } - - // Set prim params for a box, cylinder or prism and check results. - public void CheckllSetPrimitiveParams(LSL_Api api, string primTest, - LSL_Types.Vector3 primSize, int primType, int primHoleType, LSL_Types.Vector3 primCut, - float primHollow, LSL_Types.Vector3 primTwist, LSL_Types.Vector3 primTaper, LSL_Types.Vector3 primShear, - float primHollowCheck) - { - // Set the prim params. - api.llSetPrimitiveParams(new LSL_Types.list(ScriptBaseClass.PRIM_SIZE, primSize, - ScriptBaseClass.PRIM_TYPE, primType, primHoleType, - primCut, primHollow, primTwist, primTaper, primShear)); - - // Get params for prim to validate settings. - LSL_Types.list primParams = - api.llGetPrimitiveParams(new LSL_Types.list(ScriptBaseClass.PRIM_SIZE, ScriptBaseClass.PRIM_TYPE)); - - // Validate settings. - CheckllSetPrimitiveParamsVector(primSize, api.llList2Vector(primParams, 0), primTest + " prim size"); - Assert.AreEqual(primType, api.llList2Integer(primParams, 1), - "TestllSetPrimitiveParams " + primTest + " prim type check fail"); - Assert.AreEqual(primHoleType, api.llList2Integer(primParams, 2), - "TestllSetPrimitiveParams " + primTest + " prim hole default check fail"); - CheckllSetPrimitiveParamsVector(primCut, api.llList2Vector(primParams, 3), primTest + " prim cut"); - Assert.AreEqual(primHollowCheck, api.llList2Float(primParams, 4), FLOAT_ACCURACY, - "TestllSetPrimitiveParams " + primTest + " prim hollow check fail"); - CheckllSetPrimitiveParamsVector(primTwist, api.llList2Vector(primParams, 5), primTest + " prim twist"); - CheckllSetPrimitiveParamsVector(primTaper, api.llList2Vector(primParams, 6), primTest + " prim taper"); - CheckllSetPrimitiveParamsVector(primShear, api.llList2Vector(primParams, 7), primTest + " prim shear"); - } - - // Set prim params for a sphere and check results. - public void CheckllSetPrimitiveParams(LSL_Api api, string primTest, - LSL_Types.Vector3 primSize, int primType, int primHoleType, LSL_Types.Vector3 primCut, - float primHollow, LSL_Types.Vector3 primTwist, LSL_Types.Vector3 primDimple, float primHollowCheck) - { - // Set the prim params. - api.llSetPrimitiveParams(new LSL_Types.list(ScriptBaseClass.PRIM_SIZE, primSize, - ScriptBaseClass.PRIM_TYPE, primType, primHoleType, - primCut, primHollow, primTwist, primDimple)); - - // Get params for prim to validate settings. - LSL_Types.list primParams = - api.llGetPrimitiveParams(new LSL_Types.list(ScriptBaseClass.PRIM_SIZE, ScriptBaseClass.PRIM_TYPE)); - - // Validate settings. - CheckllSetPrimitiveParamsVector(primSize, api.llList2Vector(primParams, 0), primTest + " prim size"); - Assert.AreEqual(primType, api.llList2Integer(primParams, 1), - "TestllSetPrimitiveParams " + primTest + " prim type check fail"); - Assert.AreEqual(primHoleType, api.llList2Integer(primParams, 2), - "TestllSetPrimitiveParams " + primTest + " prim hole default check fail"); - CheckllSetPrimitiveParamsVector(primCut, api.llList2Vector(primParams, 3), primTest + " prim cut"); - Assert.AreEqual(primHollowCheck, api.llList2Float(primParams, 4), FLOAT_ACCURACY, - "TestllSetPrimitiveParams " + primTest + " prim hollow check fail"); - CheckllSetPrimitiveParamsVector(primTwist, api.llList2Vector(primParams, 5), primTest + " prim twist"); - CheckllSetPrimitiveParamsVector(primDimple, api.llList2Vector(primParams, 6), primTest + " prim dimple"); - } - - // Set prim params for a torus, tube or ring and check results. - public void CheckllSetPrimitiveParams(LSL_Api api, string primTest, - LSL_Types.Vector3 primSize, int primType, int primHoleType, LSL_Types.Vector3 primCut, - float primHollow, LSL_Types.Vector3 primTwist, LSL_Types.Vector3 primHoleSize, - LSL_Types.Vector3 primShear, LSL_Types.Vector3 primProfCut, LSL_Types.Vector3 primTaper, - float primRev, float primRadius, float primSkew, float primHollowCheck) - { - // Set the prim params. - api.llSetPrimitiveParams(new LSL_Types.list(ScriptBaseClass.PRIM_SIZE, primSize, - ScriptBaseClass.PRIM_TYPE, primType, primHoleType, - primCut, primHollow, primTwist, primHoleSize, primShear, primProfCut, - primTaper, primRev, primRadius, primSkew)); - - // Get params for prim to validate settings. - LSL_Types.list primParams = - api.llGetPrimitiveParams(new LSL_Types.list(ScriptBaseClass.PRIM_SIZE, ScriptBaseClass.PRIM_TYPE)); - - // Valdate settings. - CheckllSetPrimitiveParamsVector(primSize, api.llList2Vector(primParams, 0), primTest + " prim size"); - Assert.AreEqual(primType, api.llList2Integer(primParams, 1), - "TestllSetPrimitiveParams " + primTest + " prim type check fail"); - Assert.AreEqual(primHoleType, api.llList2Integer(primParams, 2), - "TestllSetPrimitiveParams " + primTest + " prim hole default check fail"); - CheckllSetPrimitiveParamsVector(primCut, api.llList2Vector(primParams, 3), primTest + " prim cut"); - Assert.AreEqual(primHollowCheck, api.llList2Float(primParams, 4), FLOAT_ACCURACY, - "TestllSetPrimitiveParams " + primTest + " prim hollow check fail"); - CheckllSetPrimitiveParamsVector(primTwist, api.llList2Vector(primParams, 5), primTest + " prim twist"); - CheckllSetPrimitiveParamsVector(primHoleSize, api.llList2Vector(primParams, 6), primTest + " prim hole size"); - CheckllSetPrimitiveParamsVector(primShear, api.llList2Vector(primParams, 7), primTest + " prim shear"); - CheckllSetPrimitiveParamsVector(primProfCut, api.llList2Vector(primParams, 8), primTest + " prim profile cut"); - CheckllSetPrimitiveParamsVector(primTaper, api.llList2Vector(primParams, 9), primTest + " prim taper"); - Assert.AreEqual(primRev, api.llList2Float(primParams, 10), FLOAT_ACCURACY, - "TestllSetPrimitiveParams " + primTest + " prim revolutions fail"); - Assert.AreEqual(primRadius, api.llList2Float(primParams, 11), FLOAT_ACCURACY, - "TestllSetPrimitiveParams " + primTest + " prim radius fail"); - Assert.AreEqual(primSkew, api.llList2Float(primParams, 12), FLOAT_ACCURACY, - "TestllSetPrimitiveParams " + primTest + " prim skew fail"); - } - - // Set prim params for a sculpted prim and check results. - public void CheckllSetPrimitiveParams(LSL_Api api, string primTest, - LSL_Types.Vector3 primSize, int primType, string primMap, int primSculptType) - { - // Set the prim params. - api.llSetPrimitiveParams(new LSL_Types.list(ScriptBaseClass.PRIM_SIZE, primSize, - ScriptBaseClass.PRIM_TYPE, primType, primMap, primSculptType)); - - // Get params for prim to validate settings. - LSL_Types.list primParams = - api.llGetPrimitiveParams(new LSL_Types.list(ScriptBaseClass.PRIM_SIZE, ScriptBaseClass.PRIM_TYPE)); - - // Validate settings. - CheckllSetPrimitiveParamsVector(primSize, api.llList2Vector(primParams, 0), primTest + " prim size"); - Assert.AreEqual(primType, api.llList2Integer(primParams, 1), - "TestllSetPrimitiveParams " + primTest + " prim type check fail"); - Assert.AreEqual(primMap, (string)api.llList2String(primParams, 2), - "TestllSetPrimitiveParams " + primTest + " prim map check fail"); - Assert.AreEqual(primSculptType, api.llList2Integer(primParams, 3), - "TestllSetPrimitiveParams " + primTest + " prim type scuplt check fail"); - } - - public void CheckllSetPrimitiveParamsVector(LSL_Types.Vector3 vecCheck, LSL_Types.Vector3 vecReturned, string msg) - { - // Check each vector component against expected result. - Assert.AreEqual(vecCheck.x, vecReturned.x, VECTOR_COMPONENT_ACCURACY, - "TestllSetPrimitiveParams " + msg + " vector check fail on x component"); - Assert.AreEqual(vecCheck.y, vecReturned.y, VECTOR_COMPONENT_ACCURACY, - "TestllSetPrimitiveParams " + msg + " vector check fail on y component"); - Assert.AreEqual(vecCheck.z, vecReturned.z, VECTOR_COMPONENT_ACCURACY, - "TestllSetPrimitiveParams " + msg + " vector check fail on z component"); - } - - } - */ -} diff --git a/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiTest.cs b/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiTest.cs deleted file mode 100644 index e10699dcc17..00000000000 --- a/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiTest.cs +++ /dev/null @@ -1,278 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System.Collections.Generic; -using NUnit.Framework; -using OpenSim.Framework; -using OpenSim.Tests.Common; -using OpenSim.Region.ScriptEngine.Shared; -using OpenSim.Region.Framework.Scenes; -using Nini.Config; -using OpenSim.Region.ScriptEngine.Shared.Api; -using OpenSim.Region.ScriptEngine.Shared.ScriptBase; -using OpenMetaverse; -using System; - -namespace OpenSim.Region.ScriptEngine.Shared.Tests -{ - /// - /// Tests for LSL_Api - /// - [TestFixture, LongRunning] - public class LSL_ApiTest - { - private const double VECTOR_COMPONENT_ACCURACY = 0.0000005d; - private const double ANGLE_ACCURACY_IN_RADIANS = 1E-6; - private LSL_Api m_lslApi; - - [SetUp] - public void SetUp() - { - IConfigSource initConfigSource = new IniConfigSource(); - IConfig config = initConfigSource.AddConfig("XEngine"); - config.Set("Enabled", "true"); - - Scene scene = new SceneHelpers().SetupScene(); - SceneObjectPart part = SceneHelpers.AddSceneObject(scene).RootPart; - - XEngine.XEngine engine = new XEngine.XEngine(); - engine.Initialise(initConfigSource); - engine.AddRegion(scene); - - m_lslApi = new LSL_Api(); - m_lslApi.Initialize(engine, part, null); - } - - [Test] - public void TestllAngleBetween() - { - TestHelpers.InMethod(); - - CheckllAngleBetween(new Vector3(1, 0, 0), 0, 1, 1); - CheckllAngleBetween(new Vector3(1, 0, 0), 90, 1, 1); - CheckllAngleBetween(new Vector3(1, 0, 0), 180, 1, 1); - - CheckllAngleBetween(new Vector3(0, 1, 0), 0, 1, 1); - CheckllAngleBetween(new Vector3(0, 1, 0), 90, 1, 1); - CheckllAngleBetween(new Vector3(0, 1, 0), 180, 1, 1); - - CheckllAngleBetween(new Vector3(0, 0, 1), 0, 1, 1); - CheckllAngleBetween(new Vector3(0, 0, 1), 90, 1, 1); - CheckllAngleBetween(new Vector3(0, 0, 1), 180, 1, 1); - - CheckllAngleBetween(new Vector3(1, 1, 1), 0, 1, 1); - CheckllAngleBetween(new Vector3(1, 1, 1), 90, 1, 1); - CheckllAngleBetween(new Vector3(1, 1, 1), 180, 1, 1); - - CheckllAngleBetween(new Vector3(1, 0, 0), 0, 1.6f, 1.8f); - CheckllAngleBetween(new Vector3(1, 0, 0), 90, 0.3f, 3.9f); - CheckllAngleBetween(new Vector3(1, 0, 0), 180, 8.8f, 7.4f); - - CheckllAngleBetween(new Vector3(0, 1, 0), 0, 9.8f, -9.4f); - CheckllAngleBetween(new Vector3(0, 1, 0), 90, 8.4f, -8.2f); - CheckllAngleBetween(new Vector3(0, 1, 0), 180, 0.4f, -5.8f); - - CheckllAngleBetween(new Vector3(0, 0, 1), 0, -6.8f, 3.4f); - CheckllAngleBetween(new Vector3(0, 0, 1), 90, -3.6f, 5.6f); - CheckllAngleBetween(new Vector3(0, 0, 1), 180, -3.8f, 1.1f); - - CheckllAngleBetween(new Vector3(1, 1, 1), 0, -7.7f, -2.0f); - CheckllAngleBetween(new Vector3(1, 1, 1), 90, -3.0f, -9.1f); - CheckllAngleBetween(new Vector3(1, 1, 1), 180, -7.9f, -8.0f); - } - - private void CheckllAngleBetween(Vector3 axis,float originalAngle, float denorm1, float denorm2) - { - Quaternion rotation1 = Quaternion.CreateFromAxisAngle(axis, 0); - Quaternion rotation2 = Quaternion.CreateFromAxisAngle(axis, ToRadians(originalAngle)); - rotation1 *= denorm1; - rotation2 *= denorm2; - - double deducedAngle = FromLslFloat(m_lslApi.llAngleBetween(ToLslQuaternion(rotation2), ToLslQuaternion(rotation1))); - - Assert.That(deducedAngle, Is.EqualTo(ToRadians(originalAngle)).Within(ANGLE_ACCURACY_IN_RADIANS), "TestllAngleBetween check fail"); - } - - #region Conversions to and from LSL_Types - - private float ToRadians(double degrees) - { - return (float)(Math.PI * degrees / 180); - } - - // private double FromRadians(float radians) - // { - // return radians * 180 / Math.PI; - // } - - private double FromLslFloat(LSL_Types.LSLFloat lslFloat) - { - return lslFloat.value; - } - - // private LSL_Types.LSLFloat ToLslFloat(double value) - // { - // return new LSL_Types.LSLFloat(value); - // } - - // private Quaternion FromLslQuaternion(LSL_Types.Quaternion lslQuaternion) - // { - // return new Quaternion((float)lslQuaternion.x, (float)lslQuaternion.y, (float)lslQuaternion.z, (float)lslQuaternion.s); - // } - - private LSL_Types.Quaternion ToLslQuaternion(Quaternion quaternion) - { - return new LSL_Types.Quaternion(quaternion.X, quaternion.Y, quaternion.Z, quaternion.W); - } - - #endregion - - [Test] - // llRot2Euler test. - public void TestllRot2Euler() - { - TestHelpers.InMethod(); - - // 180, 90 and zero degree rotations. - CheckllRot2Euler(new LSL_Types.Quaternion(0.0f, 0.0f, 0.0f, 1.0f)); - CheckllRot2Euler(new LSL_Types.Quaternion(0.0f, 0.0f, 0.707107f, 0.707107f)); - CheckllRot2Euler(new LSL_Types.Quaternion(0.0f, 0.0f, 1.0f, 0.0f)); - CheckllRot2Euler(new LSL_Types.Quaternion(0.0f, 0.0f, 0.707107f, -0.707107f)); - CheckllRot2Euler(new LSL_Types.Quaternion(0.707107f, 0.0f, 0.0f, 0.707107f)); - CheckllRot2Euler(new LSL_Types.Quaternion(0.5f, -0.5f, 0.5f, 0.5f)); - CheckllRot2Euler(new LSL_Types.Quaternion(0.0f, -0.707107f, 0.707107f, 0.0f)); - CheckllRot2Euler(new LSL_Types.Quaternion(-0.5f, -0.5f, 0.5f, -0.5f)); - CheckllRot2Euler(new LSL_Types.Quaternion(1.0f, 0.0f, 0.0f, 0.0f)); - CheckllRot2Euler(new LSL_Types.Quaternion(0.707107f, -0.707107f, 0.0f, 0.0f)); - CheckllRot2Euler(new LSL_Types.Quaternion(0.0f, -1.0f, 0.0f, 0.0f)); - CheckllRot2Euler(new LSL_Types.Quaternion(-0.707107f, -0.707107f, 0.0f, 0.0f)); - CheckllRot2Euler(new LSL_Types.Quaternion(0.707107f, 0.0f, 0.0f, -0.707107f)); - CheckllRot2Euler(new LSL_Types.Quaternion(0.5f, -0.5f, -0.5f, -0.5f)); - CheckllRot2Euler(new LSL_Types.Quaternion(0.0f, -0.707107f, -0.707107f, 0.0f)); - CheckllRot2Euler(new LSL_Types.Quaternion(-0.5f, -0.5f, -0.5f, 0.5f)); - CheckllRot2Euler(new LSL_Types.Quaternion(0.0f, -0.707107f, 0.0f, 0.707107f)); - CheckllRot2Euler(new LSL_Types.Quaternion(-0.5f, -0.5f, 0.5f, 0.5f)); - CheckllRot2Euler(new LSL_Types.Quaternion(-0.707107f, 0.0f, 0.707107f, 0.0f)); - CheckllRot2Euler(new LSL_Types.Quaternion(-0.5f, 0.5f, 0.5f, -0.5f)); - CheckllRot2Euler(new LSL_Types.Quaternion(0.0f, -0.707107f, 0.0f, -0.707107f)); - CheckllRot2Euler(new LSL_Types.Quaternion(-0.5f, -0.5f, -0.5f, -0.5f)); - CheckllRot2Euler(new LSL_Types.Quaternion(-0.707107f, 0.0f, -0.707107f, 0.0f)); - CheckllRot2Euler(new LSL_Types.Quaternion(-0.5f, 0.5f, -0.5f, 0.5f)); - - // A couple of messy rotations. - CheckllRot2Euler(new LSL_Types.Quaternion(1.0f, 5.651f, -3.1f, 67.023f)); - CheckllRot2Euler(new LSL_Types.Quaternion(0.719188f, -0.408934f, -0.363998f, -0.427841f)); - - // Some deliberately malicious rotations (intended on provoking singularity errors) - // The "f" suffexes are deliberately omitted. - CheckllRot2Euler(new LSL_Types.Quaternion(0.50001f, 0.50001f, 0.50001f, 0.50001f)); - // More malice. The "f" suffixes are deliberately omitted. - CheckllRot2Euler(new LSL_Types.Quaternion(-0.701055, 0.092296, 0.701055, -0.092296)); - CheckllRot2Euler(new LSL_Types.Quaternion(-0.183005, -0.683010, 0.183005, 0.683010)); - CheckllRot2Euler(new LSL_Types.Quaternion(-0.430460, -0.560982, 0.430460, 0.560982)); - CheckllRot2Euler(new LSL_Types.Quaternion(-0.701066, 0.092301, -0.701066, 0.092301)); - CheckllRot2Euler(new LSL_Types.Quaternion(-0.183013, -0.683010, 0.183013, 0.683010)); - CheckllRot2Euler(new LSL_Types.Quaternion(-0.183005, -0.683014, -0.183005, -0.683014)); - CheckllRot2Euler(new LSL_Types.Quaternion(-0.353556, 0.612375, 0.353556, -0.612375)); - CheckllRot2Euler(new LSL_Types.Quaternion(0.353554, -0.612385, -0.353554, 0.612385)); - CheckllRot2Euler(new LSL_Types.Quaternion(-0.560989, 0.430450, 0.560989, -0.430450)); - CheckllRot2Euler(new LSL_Types.Quaternion(-0.183013, 0.683009, -0.183013, 0.683009)); - CheckllRot2Euler(new LSL_Types.Quaternion(0.430457, -0.560985, -0.430457, 0.560985)); - CheckllRot2Euler(new LSL_Types.Quaternion(0.353552, 0.612360, -0.353552, -0.612360)); - CheckllRot2Euler(new LSL_Types.Quaternion(-0.499991, 0.500003, 0.499991, -0.500003)); - CheckllRot2Euler(new LSL_Types.Quaternion(-0.353555, -0.612385, -0.353555, -0.612385)); - CheckllRot2Euler(new LSL_Types.Quaternion(0.701066, -0.092301, -0.701066, 0.092301)); - CheckllRot2Euler(new LSL_Types.Quaternion(-0.499991, 0.500007, 0.499991, -0.500007)); - CheckllRot2Euler(new LSL_Types.Quaternion(-0.683002, 0.183016, -0.683002, 0.183016)); - CheckllRot2Euler(new LSL_Types.Quaternion(0.430458, 0.560982, 0.430458, 0.560982)); - CheckllRot2Euler(new LSL_Types.Quaternion(0.499991, -0.500003, -0.499991, 0.500003)); - CheckllRot2Euler(new LSL_Types.Quaternion(-0.183009, 0.683011, -0.183009, 0.683011)); - CheckllRot2Euler(new LSL_Types.Quaternion(0.560975, -0.430457, 0.560975, -0.430457)); - CheckllRot2Euler(new LSL_Types.Quaternion(0.701055, 0.092300, 0.701055, 0.092300)); - CheckllRot2Euler(new LSL_Types.Quaternion(-0.560990, 0.430459, -0.560990, 0.430459)); - CheckllRot2Euler(new LSL_Types.Quaternion(-0.092302, -0.701059, -0.092302, -0.701059)); - } - - /// - /// Check an llRot2Euler conversion. - /// - /// - /// Testing Rot2Euler this way instead of comparing against expected angles because - /// 1. There are several ways to get to the original Quaternion. For example a rotation - /// of PI and -PI will give the same result. But PI and -PI aren't equal. - /// 2. This method checks to see if the calculated angles from a quaternion can be used - /// to create a new quaternion to produce the same rotation. - /// However, can't compare the newly calculated quaternion against the original because - /// once again, there are multiple quaternions that give the same result. For instance - /// == <-X, -Y, -Z, -S>. Additionally, the magnitude of S can be changed - /// and will still result in the same rotation if the values for X, Y, Z are also changed - /// to compensate. - /// However, if two quaternions represent the same rotation, then multiplying the first - /// quaternion by the conjugate of the second, will give a third quaternion representing - /// a zero rotation. This can be tested for by looking at the X, Y, Z values which should - /// be zero. - /// - /// - private void CheckllRot2Euler(LSL_Types.Quaternion rot) - { - // Call LSL function to convert quaternion rotaion to euler radians. - LSL_Types.Vector3 eulerCalc = m_lslApi.llRot2Euler(rot); - // Now use the euler radians to recalculate a new quaternion rotation - LSL_Types.Quaternion newRot = m_lslApi.llEuler2Rot(eulerCalc); - // Multiple original quaternion by conjugate of quaternion calculated with angles. - LSL_Types.Quaternion check = rot * new LSL_Types.Quaternion(-newRot.x, -newRot.y, -newRot.z, newRot.s); - - Assert.AreEqual(0.0, check.x, VECTOR_COMPONENT_ACCURACY, "TestllRot2Euler X bounds check fail"); - Assert.AreEqual(0.0, check.y, VECTOR_COMPONENT_ACCURACY, "TestllRot2Euler Y bounds check fail"); - Assert.AreEqual(0.0, check.z, VECTOR_COMPONENT_ACCURACY, "TestllRot2Euler Z bounds check fail"); - } - - [Test] - public void TestllVecNorm() - { - TestHelpers.InMethod(); - - // Check special case for normalizing zero vector. - CheckllVecNorm(new LSL_Types.Vector3(0.0d, 0.0d, 0.0d), new LSL_Types.Vector3(0.0d, 0.0d, 0.0d)); - // Check various vectors. - CheckllVecNorm(new LSL_Types.Vector3(10.0d, 25.0d, 0.0d), new LSL_Types.Vector3(0.371391d, 0.928477d, 0.0d)); - CheckllVecNorm(new LSL_Types.Vector3(1.0d, 0.0d, 0.0d), new LSL_Types.Vector3(1.0d, 0.0d, 0.0d)); - CheckllVecNorm(new LSL_Types.Vector3(-90.0d, 55.0d, 2.0d), new LSL_Types.Vector3(-0.853128d, 0.521356d, 0.018958d)); - CheckllVecNorm(new LSL_Types.Vector3(255.0d, 255.0d, 255.0d), new LSL_Types.Vector3(0.577350d, 0.577350d, 0.577350d)); - } - - public void CheckllVecNorm(LSL_Types.Vector3 vec, LSL_Types.Vector3 vecNormCheck) - { - // Call LSL function to normalize the vector. - LSL_Types.Vector3 vecNorm = m_lslApi.llVecNorm(vec); - // Check each vector component against expected result. - Assert.AreEqual(vecNorm.x, vecNormCheck.x, VECTOR_COMPONENT_ACCURACY, "TestllVecNorm vector check fail on x component"); - Assert.AreEqual(vecNorm.y, vecNormCheck.y, VECTOR_COMPONENT_ACCURACY, "TestllVecNorm vector check fail on y component"); - Assert.AreEqual(vecNorm.z, vecNormCheck.z, VECTOR_COMPONENT_ACCURACY, "TestllVecNorm vector check fail on z component"); - } - } -} diff --git a/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiUserTests.cs b/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiUserTests.cs deleted file mode 100644 index 70a3a9e3daf..00000000000 --- a/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiUserTests.cs +++ /dev/null @@ -1,157 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections.Generic; -using System.Threading; -using Nini.Config; -using NUnit.Framework; -using OpenMetaverse; -using OpenSim.Framework; -using OpenSim.Region.Framework.Scenes; -using OpenSim.Region.ScriptEngine.Shared.Api; -using OpenSim.Region.ScriptEngine.Shared.ScriptBase; -using OpenSim.Services.Interfaces; -using OpenSim.Tests.Common; - -namespace OpenSim.Region.ScriptEngine.Shared.Tests -{ - [TestFixture] - public class LSL_ApiUserTests : OpenSimTestCase - { - private Scene m_scene; - private MockScriptEngine m_engine; - - [SetUp] - public override void SetUp() - { - base.SetUp(); - - m_engine = new MockScriptEngine(); - - m_scene = new SceneHelpers().SetupScene(); - SceneHelpers.SetupSceneModules(m_scene, m_engine); - } - - [Test] - public void TestLlRequestAgentDataOnline() - { - TestHelpers.InMethod(); -// TestHelpers.EnableLogging(); - - UUID userId = TestHelpers.ParseTail(0x1); - - UserAccount ua1 = UserAccountHelpers.CreateUserWithInventory(m_scene, userId); - - SceneObjectPart part = SceneHelpers.AddSceneObject(m_scene).RootPart; - TaskInventoryItem scriptItem = TaskInventoryHelpers.AddScript(m_scene.AssetService, part); - - LSL_Api apiGrp1 = new LSL_Api(); - apiGrp1.Initialize(m_engine, part, scriptItem); - - // Initially long timeout to test cache - apiGrp1.LlRequestAgentDataCacheTimeoutMs = 20000; - - // Offline test - { - apiGrp1.llRequestAgentData(userId.ToString(), ScriptBaseClass.DATA_ONLINE); - - Assert.That(m_engine.PostedEvents.ContainsKey(scriptItem.ItemID)); - - List events = m_engine.PostedEvents[scriptItem.ItemID]; - Assert.That(events.Count, Is.EqualTo(1)); - EventParams eventParams = events[0]; - Assert.That(eventParams.EventName, Is.EqualTo("dataserver")); - - string data = eventParams.Params[1].ToString(); - Assert.AreEqual(0, int.Parse(data)); - - m_engine.PostedEvents.Clear(); - } - - // Online test. Should get the 'wrong' result because of caching. - ScenePresence sp = SceneHelpers.AddScenePresence(m_scene, ua1); - - { - apiGrp1.llRequestAgentData(userId.ToString(), ScriptBaseClass.DATA_ONLINE); - - Assert.That(m_engine.PostedEvents.ContainsKey(scriptItem.ItemID)); - - List events = m_engine.PostedEvents[scriptItem.ItemID]; - Assert.That(events.Count, Is.EqualTo(1)); - EventParams eventParams = events[0]; - Assert.That(eventParams.EventName, Is.EqualTo("dataserver")); - - string data = eventParams.Params[1].ToString(); - Assert.AreEqual(0, int.Parse(data)); - - m_engine.PostedEvents.Clear(); - } - - apiGrp1.LlRequestAgentDataCacheTimeoutMs = 20; - - // Make absolutely sure that we should trigger cache timeout. - Thread.Sleep(apiGrp1.LlRequestAgentDataCacheTimeoutMs + 50); - - { - apiGrp1.llRequestAgentData(userId.ToString(), ScriptBaseClass.DATA_ONLINE); - - Assert.That(m_engine.PostedEvents.ContainsKey(scriptItem.ItemID)); - - List events = m_engine.PostedEvents[scriptItem.ItemID]; - Assert.That(events.Count, Is.EqualTo(1)); - EventParams eventParams = events[0]; - Assert.That(eventParams.EventName, Is.EqualTo("dataserver")); - - string data = eventParams.Params[1].ToString(); - Assert.AreEqual(1, int.Parse(data)); - - m_engine.PostedEvents.Clear(); - } - - m_scene.CloseAgent(userId, false); - - Thread.Sleep(apiGrp1.LlRequestAgentDataCacheTimeoutMs + 50); - - { - apiGrp1.llRequestAgentData(userId.ToString(), ScriptBaseClass.DATA_ONLINE); - - Assert.That(m_engine.PostedEvents.ContainsKey(scriptItem.ItemID)); - - List events = m_engine.PostedEvents[scriptItem.ItemID]; - Assert.That(events.Count, Is.EqualTo(1)); - EventParams eventParams = events[0]; - Assert.That(eventParams.EventName, Is.EqualTo("dataserver")); - - string data = eventParams.Params[1].ToString(); - Assert.AreEqual(0, int.Parse(data)); - - m_engine.PostedEvents.Clear(); - } - } - } -} diff --git a/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_TypesTestLSLFloat.cs b/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_TypesTestLSLFloat.cs deleted file mode 100644 index f81e0af04d8..00000000000 --- a/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_TypesTestLSLFloat.cs +++ /dev/null @@ -1,661 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System.Collections.Generic; -using NUnit.Framework; -using OpenSim.Tests.Common; -using OpenSim.Region.ScriptEngine.Shared; - -namespace OpenSim.Region.ScriptEngine.Shared.Tests -{ - [TestFixture] - public class LSL_TypesTestLSLFloat : OpenSimTestCase - { - // Used for testing equality of two floats. - private double _lowPrecisionTolerance = 0.000001; - - private Dictionary m_intDoubleSet; - private Dictionary m_doubleDoubleSet; - private Dictionary m_doubleIntSet; - private Dictionary m_doubleUintSet; - private Dictionary m_stringDoubleSet; - private Dictionary m_doubleStringSet; - private List m_intList; - private List m_doubleList; - - /// - /// Sets up dictionaries and arrays used in the tests. - /// - [OneTimeSetUp] - public void SetUpDataSets() - { - m_intDoubleSet = new Dictionary(); - m_intDoubleSet.Add(2, 2.0); - m_intDoubleSet.Add(-2, -2.0); - m_intDoubleSet.Add(0, 0.0); - m_intDoubleSet.Add(1, 1.0); - m_intDoubleSet.Add(-1, -1.0); - m_intDoubleSet.Add(999999999, 999999999.0); - m_intDoubleSet.Add(-99999999, -99999999.0); - - m_doubleDoubleSet = new Dictionary(); - m_doubleDoubleSet.Add(2.0, 2.0); - m_doubleDoubleSet.Add(-2.0, -2.0); - m_doubleDoubleSet.Add(0.0, 0.0); - m_doubleDoubleSet.Add(1.0, 1.0); - m_doubleDoubleSet.Add(-1.0, -1.0); - m_doubleDoubleSet.Add(999999999.0, 999999999.0); - m_doubleDoubleSet.Add(-99999999.0, -99999999.0); - m_doubleDoubleSet.Add(0.5, 0.5); - m_doubleDoubleSet.Add(0.0005, 0.0005); - m_doubleDoubleSet.Add(0.6805, 0.6805); - m_doubleDoubleSet.Add(-0.5, -0.5); - m_doubleDoubleSet.Add(-0.0005, -0.0005); - m_doubleDoubleSet.Add(-0.6805, -0.6805); - m_doubleDoubleSet.Add(548.5, 548.5); - m_doubleDoubleSet.Add(2.0005, 2.0005); - m_doubleDoubleSet.Add(349485435.6805, 349485435.6805); - m_doubleDoubleSet.Add(-548.5, -548.5); - m_doubleDoubleSet.Add(-2.0005, -2.0005); - m_doubleDoubleSet.Add(-349485435.6805, -349485435.6805); - - m_doubleIntSet = new Dictionary(); - m_doubleIntSet.Add(2.0, 2); - m_doubleIntSet.Add(-2.0, -2); - m_doubleIntSet.Add(0.0, 0); - m_doubleIntSet.Add(1.0, 1); - m_doubleIntSet.Add(-1.0, -1); - m_doubleIntSet.Add(999999999.0, 999999999); - m_doubleIntSet.Add(-99999999.0, -99999999); - m_doubleIntSet.Add(0.5, 0); - m_doubleIntSet.Add(0.0005, 0); - m_doubleIntSet.Add(0.6805, 0); - m_doubleIntSet.Add(-0.5, 0); - m_doubleIntSet.Add(-0.0005, 0); - m_doubleIntSet.Add(-0.6805, 0); - m_doubleIntSet.Add(548.5, 548); - m_doubleIntSet.Add(2.0005, 2); - m_doubleIntSet.Add(349485435.6805, 349485435); - m_doubleIntSet.Add(-548.5, -548); - m_doubleIntSet.Add(-2.0005, -2); - m_doubleIntSet.Add(-349485435.6805, -349485435); - - m_doubleUintSet = new Dictionary(); - m_doubleUintSet.Add(2.0, 2); - m_doubleUintSet.Add(-2.0, 2); - m_doubleUintSet.Add(0.0, 0); - m_doubleUintSet.Add(1.0, 1); - m_doubleUintSet.Add(-1.0, 1); - m_doubleUintSet.Add(999999999.0, 999999999); - m_doubleUintSet.Add(-99999999.0, 99999999); - m_doubleUintSet.Add(0.5, 0); - m_doubleUintSet.Add(0.0005, 0); - m_doubleUintSet.Add(0.6805, 0); - m_doubleUintSet.Add(-0.5, 0); - m_doubleUintSet.Add(-0.0005, 0); - m_doubleUintSet.Add(-0.6805, 0); - m_doubleUintSet.Add(548.5, 548); - m_doubleUintSet.Add(2.0005, 2); - m_doubleUintSet.Add(349485435.6805, 349485435); - m_doubleUintSet.Add(-548.5, 548); - m_doubleUintSet.Add(-2.0005, 2); - m_doubleUintSet.Add(-349485435.6805, 349485435); - - m_stringDoubleSet = new Dictionary(); - m_stringDoubleSet.Add("2", 2.0); - m_stringDoubleSet.Add("-2", -2.0); - m_stringDoubleSet.Add("1", 1.0); - m_stringDoubleSet.Add("-1", -1.0); - m_stringDoubleSet.Add("0", 0.0); - m_stringDoubleSet.Add("999999999.0", 999999999.0); - m_stringDoubleSet.Add("-99999999.0", -99999999.0); - m_stringDoubleSet.Add("0.5", 0.5); - m_stringDoubleSet.Add("0.0005", 0.0005); - m_stringDoubleSet.Add("0.6805", 0.6805); - m_stringDoubleSet.Add("-0.5", -0.5); - m_stringDoubleSet.Add("-0.0005", -0.0005); - m_stringDoubleSet.Add("-0.6805", -0.6805); - m_stringDoubleSet.Add("548.5", 548.5); - m_stringDoubleSet.Add("2.0005", 2.0005); - m_stringDoubleSet.Add("349485435.6805", 349485435.6805); - m_stringDoubleSet.Add("-548.5", -548.5); - m_stringDoubleSet.Add("-2.0005", -2.0005); - m_stringDoubleSet.Add("-349485435.6805", -349485435.6805); - // some oddball combinations and exponents - m_stringDoubleSet.Add("", 0.0); - m_stringDoubleSet.Add("1.0E+5", 100000.0); - m_stringDoubleSet.Add("-1.0E+5", -100000.0); - m_stringDoubleSet.Add("-1E+5", -100000.0); - m_stringDoubleSet.Add("-1.E+5", -100000.0); - m_stringDoubleSet.Add("-1.E+5.0", -100000.0); - m_stringDoubleSet.Add("1ef", 1.0); - m_stringDoubleSet.Add("e10", 0.0); - m_stringDoubleSet.Add("1.e0.0", 1.0); - - m_doubleStringSet = new Dictionary(); - m_doubleStringSet.Add(2.0, "2.000000"); - m_doubleStringSet.Add(-2.0, "-2.000000"); - m_doubleStringSet.Add(1.0, "1.000000"); - m_doubleStringSet.Add(-1.0, "-1.000000"); - m_doubleStringSet.Add(0.0, "0.000000"); - m_doubleStringSet.Add(999999999.0, "999999999.000000"); - m_doubleStringSet.Add(-99999999.0, "-99999999.000000"); - m_doubleStringSet.Add(0.5, "0.500000"); - m_doubleStringSet.Add(0.0005, "0.000500"); - m_doubleStringSet.Add(0.6805, "0.680500"); - m_doubleStringSet.Add(-0.5, "-0.500000"); - m_doubleStringSet.Add(-0.0005, "-0.000500"); - m_doubleStringSet.Add(-0.6805, "-0.680500"); - m_doubleStringSet.Add(548.5, "548.500000"); - m_doubleStringSet.Add(2.0005, "2.000500"); - m_doubleStringSet.Add(349485435.6805, "349485435.680500"); - m_doubleStringSet.Add(-548.5, "-548.500000"); - m_doubleStringSet.Add(-2.0005, "-2.000500"); - m_doubleStringSet.Add(-349485435.6805, "-349485435.680500"); - - m_doubleList = new List(); - m_doubleList.Add(2.0); - m_doubleList.Add(-2.0); - m_doubleList.Add(1.0); - m_doubleList.Add(-1.0); - m_doubleList.Add(999999999.0); - m_doubleList.Add(-99999999.0); - m_doubleList.Add(0.5); - m_doubleList.Add(0.0005); - m_doubleList.Add(0.6805); - m_doubleList.Add(-0.5); - m_doubleList.Add(-0.0005); - m_doubleList.Add(-0.6805); - m_doubleList.Add(548.5); - m_doubleList.Add(2.0005); - m_doubleList.Add(349485435.6805); - m_doubleList.Add(-548.5); - m_doubleList.Add(-2.0005); - m_doubleList.Add(-349485435.6805); - - m_intList = new List(); - m_intList.Add(2); - m_intList.Add(-2); - m_intList.Add(0); - m_intList.Add(1); - m_intList.Add(-1); - m_intList.Add(999999999); - m_intList.Add(-99999999); - } - - /// - /// Tests constructing a LSLFloat from an integer. - /// - [Test] - public void TestConstructFromInt() - { - TestHelpers.InMethod(); - - LSL_Types.LSLFloat testFloat; - - foreach (KeyValuePair number in m_intDoubleSet) - { - testFloat = new LSL_Types.LSLFloat(number.Key); - Assert.That(testFloat.value, new DoubleToleranceConstraint(number.Value, _lowPrecisionTolerance)); - } - } - - /// - /// Tests constructing a LSLFloat from a double. - /// - [Test] - public void TestConstructFromDouble() - { - TestHelpers.InMethod(); - - LSL_Types.LSLFloat testFloat; - - foreach (KeyValuePair number in m_doubleDoubleSet) - { - testFloat = new LSL_Types.LSLFloat(number.Key); - Assert.That(testFloat.value, new DoubleToleranceConstraint(number.Value, _lowPrecisionTolerance)); - } - } - - /// - /// Tests LSLFloat is correctly cast explicitly to integer. - /// - [Test] - public void TestExplicitCastLSLFloatToInt() - { - TestHelpers.InMethod(); - - int testNumber; - - foreach (KeyValuePair number in m_doubleIntSet) - { - testNumber = (int) new LSL_Types.LSLFloat(number.Key); - Assert.AreEqual(number.Value, testNumber, "Converting double " + number.Key + ", expecting int " + number.Value); - } - } - - /// - /// Tests LSLFloat is correctly cast explicitly to unsigned integer. - /// - [Test] - public void TestExplicitCastLSLFloatToUint() - { - TestHelpers.InMethod(); - - uint testNumber; - - foreach (KeyValuePair number in m_doubleUintSet) - { - testNumber = (uint) new LSL_Types.LSLFloat(number.Key); - Assert.AreEqual(number.Value, testNumber, "Converting double " + number.Key + ", expecting uint " + number.Value); - } - } - - /// - /// Tests LSLFloat is correctly cast implicitly to Boolean if non-zero. - /// - [Test] - public void TestImplicitCastLSLFloatToBooleanTrue() - { - TestHelpers.InMethod(); - - LSL_Types.LSLFloat testFloat; - bool testBool; - - foreach (double number in m_doubleList) - { - testFloat = new LSL_Types.LSLFloat(number); - testBool = testFloat; - - Assert.IsTrue(testBool); - } - } - - /// - /// Tests LSLFloat is correctly cast implicitly to Boolean if zero. - /// - [Test] - public void TestImplicitCastLSLFloatToBooleanFalse() - { - TestHelpers.InMethod(); - - LSL_Types.LSLFloat testFloat = new LSL_Types.LSLFloat(0.0); - bool testBool = testFloat; - - Assert.IsFalse(testBool); - } - - /// - /// Tests integer is correctly cast implicitly to LSLFloat. - /// - [Test] - public void TestImplicitCastIntToLSLFloat() - { - TestHelpers.InMethod(); - - LSL_Types.LSLFloat testFloat; - - foreach (int number in m_intList) - { - testFloat = number; - Assert.That(testFloat.value, new DoubleToleranceConstraint(number, _lowPrecisionTolerance)); - } - } - - /// - /// Tests LSLInteger is correctly cast implicitly to LSLFloat. - /// - [Test] - public void TestImplicitCastLSLIntegerToLSLFloat() - { - TestHelpers.InMethod(); - - LSL_Types.LSLFloat testFloat; - - foreach (int number in m_intList) - { - testFloat = new LSL_Types.LSLInteger(number); - Assert.That(testFloat.value, new DoubleToleranceConstraint(number, _lowPrecisionTolerance)); - } - } - - /// - /// Tests LSLInteger is correctly cast explicitly to LSLFloat. - /// - [Test] - public void TestExplicitCastLSLIntegerToLSLFloat() - { - TestHelpers.InMethod(); - - LSL_Types.LSLFloat testFloat; - - foreach (int number in m_intList) - { - testFloat = (LSL_Types.LSLFloat) new LSL_Types.LSLInteger(number); - Assert.That(testFloat.value, new DoubleToleranceConstraint(number, _lowPrecisionTolerance)); - } - } - - /// - /// Tests string is correctly cast explicitly to LSLFloat. - /// - [Test] - public void TestExplicitCastStringToLSLFloat() - { - TestHelpers.InMethod(); - - LSL_Types.LSLFloat testFloat; - - foreach (KeyValuePair number in m_stringDoubleSet) - { - testFloat = (LSL_Types.LSLFloat) number.Key; - Assert.That(testFloat.value, new DoubleToleranceConstraint(number.Value, _lowPrecisionTolerance)); - } - } - - /// - /// Tests LSLString is correctly cast implicitly to LSLFloat. - /// - [Test] - public void TestExplicitCastLSLStringToLSLFloat() - { - TestHelpers.InMethod(); - - LSL_Types.LSLFloat testFloat; - - foreach (KeyValuePair number in m_stringDoubleSet) - { - testFloat = (LSL_Types.LSLFloat) new LSL_Types.LSLString(number.Key); - Assert.That(testFloat.value, new DoubleToleranceConstraint(number.Value, _lowPrecisionTolerance)); - } - } - - /// - /// Tests double is correctly cast implicitly to LSLFloat. - /// - [Test] - public void TestImplicitCastDoubleToLSLFloat() - { - TestHelpers.InMethod(); - - LSL_Types.LSLFloat testFloat; - - foreach (double number in m_doubleList) - { - testFloat = number; - Assert.That(testFloat.value, new DoubleToleranceConstraint(number, _lowPrecisionTolerance)); - } - } - - /// - /// Tests LSLFloat is correctly cast implicitly to double. - /// - [Test] - public void TestImplicitCastLSLFloatToDouble() - { - TestHelpers.InMethod(); - - double testNumber; - LSL_Types.LSLFloat testFloat; - - foreach (double number in m_doubleList) - { - testFloat = new LSL_Types.LSLFloat(number); - testNumber = testFloat; - - Assert.That(testNumber, new DoubleToleranceConstraint(number, _lowPrecisionTolerance)); - } - } - - /// - /// Tests LSLFloat is correctly cast explicitly to float - /// - [Test] - public void TestExplicitCastLSLFloatToFloat() - { - TestHelpers.InMethod(); - - float testFloat; - float numberAsFloat; - LSL_Types.LSLFloat testLSLFloat; - - foreach (double number in m_doubleList) - { - testLSLFloat = new LSL_Types.LSLFloat(number); - numberAsFloat = (float)number; - testFloat = (float)testLSLFloat; - - Assert.That((double)testFloat, new DoubleToleranceConstraint((double)numberAsFloat, _lowPrecisionTolerance)); - } - } - - /// - /// Tests the equality (==) operator. - /// - [Test] - public void TestEqualsOperator() - { - TestHelpers.InMethod(); - - LSL_Types.LSLFloat testFloatA, testFloatB; - - foreach (double number in m_doubleList) - { - testFloatA = new LSL_Types.LSLFloat(number); - testFloatB = new LSL_Types.LSLFloat(number); - Assert.IsTrue(testFloatA == testFloatB); - - testFloatB = new LSL_Types.LSLFloat(number + 1.0); - Assert.IsFalse(testFloatA == testFloatB); - } - } - - /// - /// Tests the inequality (!=) operator. - /// - [Test] - public void TestNotEqualOperator() - { - TestHelpers.InMethod(); - - LSL_Types.LSLFloat testFloatA, testFloatB; - - foreach (double number in m_doubleList) - { - testFloatA = new LSL_Types.LSLFloat(number); - testFloatB = new LSL_Types.LSLFloat(number + 1.0); - Assert.IsTrue(testFloatA != testFloatB); - - testFloatB = new LSL_Types.LSLFloat(number); - Assert.IsFalse(testFloatA != testFloatB); - } - } - - /// - /// Tests the increment operator. - /// - [Test] - public void TestIncrementOperator() - { - TestHelpers.InMethod(); - - LSL_Types.LSLFloat testFloat; - double testNumber; - - foreach (double number in m_doubleList) - { - testFloat = new LSL_Types.LSLFloat(number); - - testNumber = testFloat++; - Assert.That(testNumber, new DoubleToleranceConstraint(number, _lowPrecisionTolerance)); - - testNumber = testFloat; - Assert.That(testNumber, new DoubleToleranceConstraint(number + 1.0, _lowPrecisionTolerance)); - - testNumber = ++testFloat; - Assert.That(testNumber, new DoubleToleranceConstraint(number + 2.0, _lowPrecisionTolerance)); - } - } - - /// - /// Tests the decrement operator. - /// - [Test] - public void TestDecrementOperator() - { - TestHelpers.InMethod(); - - LSL_Types.LSLFloat testFloat; - double testNumber; - - foreach (double number in m_doubleList) - { - testFloat = new LSL_Types.LSLFloat(number); - - testNumber = testFloat--; - Assert.That(testNumber, new DoubleToleranceConstraint(number, _lowPrecisionTolerance)); - - testNumber = testFloat; - Assert.That(testNumber, new DoubleToleranceConstraint(number - 1.0, _lowPrecisionTolerance)); - - testNumber = --testFloat; - Assert.That(testNumber, new DoubleToleranceConstraint(number - 2.0, _lowPrecisionTolerance)); - } - } - - /// - /// Tests LSLFloat.ToString(). - /// - [Test] - public void TestToString() - { - TestHelpers.InMethod(); - - LSL_Types.LSLFloat testFloat; - - foreach (KeyValuePair number in m_doubleStringSet) - { - testFloat = new LSL_Types.LSLFloat(number.Key); - Assert.AreEqual(number.Value, testFloat.ToString()); - } - } - - /// - /// Tests addition of two LSLFloats. - /// - [Test] - public void TestAddTwoLSLFloats() - { - TestHelpers.InMethod(); - - LSL_Types.LSLFloat testResult; - - foreach (KeyValuePair number in m_doubleDoubleSet) - { - testResult = new LSL_Types.LSLFloat(number.Key) + new LSL_Types.LSLFloat(number.Value); - Assert.That(testResult.value, new DoubleToleranceConstraint(number.Key + number.Value, _lowPrecisionTolerance)); - } - } - - /// - /// Tests subtraction of two LSLFloats. - /// - [Test] - public void TestSubtractTwoLSLFloats() - { - TestHelpers.InMethod(); - - LSL_Types.LSLFloat testResult; - - foreach (KeyValuePair number in m_doubleDoubleSet) - { - testResult = new LSL_Types.LSLFloat(number.Key) - new LSL_Types.LSLFloat(number.Value); - Assert.That(testResult.value, new DoubleToleranceConstraint(number.Key - number.Value, _lowPrecisionTolerance)); - } - } - - /// - /// Tests multiplication of two LSLFloats. - /// - [Test] - public void TestMultiplyTwoLSLFloats() - { - TestHelpers.InMethod(); - - LSL_Types.LSLFloat testResult; - - foreach (KeyValuePair number in m_doubleDoubleSet) - { - testResult = new LSL_Types.LSLFloat(number.Key) * new LSL_Types.LSLFloat(number.Value); - Assert.That(testResult.value, new DoubleToleranceConstraint(number.Key * number.Value, _lowPrecisionTolerance)); - } - } - - /// - /// Tests division of two LSLFloats. - /// - [Test] - public void TestDivideTwoLSLFloats() - { - TestHelpers.InMethod(); - - LSL_Types.LSLFloat testResult; - - foreach (KeyValuePair number in m_doubleDoubleSet) - { - if (number.Value != 0.0) // Let's avoid divide by zero. - { - testResult = new LSL_Types.LSLFloat(number.Key) / new LSL_Types.LSLFloat(number.Value); - Assert.That(testResult.value, new DoubleToleranceConstraint(number.Key / number.Value, _lowPrecisionTolerance)); - } - } - } - - /// - /// Tests boolean correctly cast implicitly to LSLFloat. - /// - [Test] - public void TestImplicitCastBooleanToLSLFloat() - { - TestHelpers.InMethod(); - - LSL_Types.LSLFloat testFloat; - - testFloat = (1 == 0); - Assert.That(testFloat.value, new DoubleToleranceConstraint(0.0, _lowPrecisionTolerance)); - - testFloat = (1 == 1); - Assert.That(testFloat.value, new DoubleToleranceConstraint(1.0, _lowPrecisionTolerance)); - - testFloat = false; - Assert.That(testFloat.value, new DoubleToleranceConstraint(0.0, _lowPrecisionTolerance)); - - testFloat = true; - Assert.That(testFloat.value, new DoubleToleranceConstraint(1.0, _lowPrecisionTolerance)); - } - } -} \ No newline at end of file diff --git a/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_TypesTestLSLInteger.cs b/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_TypesTestLSLInteger.cs deleted file mode 100644 index 41b5bcc0b8f..00000000000 --- a/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_TypesTestLSLInteger.cs +++ /dev/null @@ -1,150 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System.Collections.Generic; -using NUnit.Framework; -using OpenSim.Tests.Common; -using OpenSim.Region.ScriptEngine.Shared; - -namespace OpenSim.Region.ScriptEngine.Shared.Tests -{ - [TestFixture] - public class LSL_TypesTestLSLInteger : OpenSimTestCase - { - private Dictionary m_doubleIntSet; - private Dictionary m_stringIntSet; - - /// - /// Sets up dictionaries and arrays used in the tests. - /// - [OneTimeSetUp] - public void SetUpDataSets() - { - m_doubleIntSet = new Dictionary(); - m_doubleIntSet.Add(2.0, 2); - m_doubleIntSet.Add(-2.0, -2); - m_doubleIntSet.Add(0.0, 0); - m_doubleIntSet.Add(1.0, 1); - m_doubleIntSet.Add(-1.0, -1); - m_doubleIntSet.Add(999999999.0, 999999999); - m_doubleIntSet.Add(-99999999.0, -99999999); - - m_stringIntSet = new Dictionary(); - m_stringIntSet.Add("2", 2); - m_stringIntSet.Add("-2", -2); - m_stringIntSet.Add("0", 0); - m_stringIntSet.Add("1", 1); - m_stringIntSet.Add("-1", -1); - m_stringIntSet.Add("123.9", 123); - m_stringIntSet.Add("999999999", 999999999); - m_stringIntSet.Add("-99999999", -99999999); - m_stringIntSet.Add("", 0); - m_stringIntSet.Add("aa", 0); - m_stringIntSet.Add("56foo", 56); - m_stringIntSet.Add("42", 42); - m_stringIntSet.Add("42 is the answer", 42); - m_stringIntSet.Add(" 42", 42); - m_stringIntSet.Add("42,123,456", 42); - m_stringIntSet.Add("0xff", 255); - m_stringIntSet.Add("12345678900000", -1); - } - - /// - /// Tests LSLFloat is correctly cast explicitly to LSLInteger. - /// - [Test] - public void TestExplicitCastLSLFloatToLSLInteger() - { - TestHelpers.InMethod(); - - LSL_Types.LSLInteger testInteger; - - foreach (KeyValuePair number in m_doubleIntSet) - { - testInteger = (LSL_Types.LSLInteger) new LSL_Types.LSLFloat(number.Key); - Assert.AreEqual(testInteger.value, number.Value); - } - } - - /// - /// Tests string is correctly cast explicitly to LSLInteger. - /// - [Test] - public void TestExplicitCastStringToLSLInteger() - { - TestHelpers.InMethod(); - - LSL_Types.LSLInteger testInteger; - - foreach (KeyValuePair number in m_stringIntSet) - { - testInteger = (LSL_Types.LSLInteger) number.Key; - Assert.AreEqual(testInteger.value, number.Value); - } - } - - /// - /// Tests LSLString is correctly cast explicitly to LSLInteger. - /// - [Test] - public void TestExplicitCastLSLStringToLSLInteger() - { - TestHelpers.InMethod(); - - LSL_Types.LSLInteger testInteger; - - foreach (KeyValuePair number in m_stringIntSet) - { - testInteger = (LSL_Types.LSLInteger) new LSL_Types.LSLString(number.Key); - Assert.AreEqual(testInteger.value, number.Value); - } - } - - /// - /// Tests boolean correctly cast implicitly to LSLInteger. - /// - [Test] - public void TestImplicitCastBooleanToLSLInteger() - { - TestHelpers.InMethod(); - - LSL_Types.LSLInteger testInteger; - - testInteger = (1 == 0); - Assert.AreEqual(0, testInteger.value); - - testInteger = (1 == 1); - Assert.AreEqual(1, testInteger.value); - - testInteger = false; - Assert.AreEqual(0, testInteger.value); - - testInteger = true; - Assert.AreEqual(1, testInteger.value); - } - } -} diff --git a/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_TypesTestLSLString.cs b/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_TypesTestLSLString.cs deleted file mode 100644 index 70c1a381c06..00000000000 --- a/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_TypesTestLSLString.cs +++ /dev/null @@ -1,144 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System.Collections.Generic; -using NUnit.Framework; -using OpenSim.Tests.Common; -using OpenSim.Region.ScriptEngine.Shared; - -namespace OpenSim.Region.ScriptEngine.Shared.Tests -{ - [TestFixture] - public class LSL_TypesTestLSLString : OpenSimTestCase - { - private Dictionary m_doubleStringSet; - - /// - /// Sets up dictionaries and arrays used in the tests. - /// - [OneTimeSetUp] - public void SetUpDataSets() - { - m_doubleStringSet = new Dictionary(); - m_doubleStringSet.Add(2, "2.000000"); - m_doubleStringSet.Add(-2, "-2.000000"); - m_doubleStringSet.Add(0, "0.000000"); - m_doubleStringSet.Add(1, "1.000000"); - m_doubleStringSet.Add(-1, "-1.000000"); - m_doubleStringSet.Add(999999999, "999999999.000000"); - m_doubleStringSet.Add(-99999999, "-99999999.000000"); - m_doubleStringSet.Add(0.5, "0.500000"); - m_doubleStringSet.Add(0.0005, "0.000500"); - m_doubleStringSet.Add(0.6805, "0.680500"); - m_doubleStringSet.Add(-0.5, "-0.500000"); - m_doubleStringSet.Add(-0.0005, "-0.000500"); - m_doubleStringSet.Add(-0.6805, "-0.680500"); - m_doubleStringSet.Add(548.5, "548.500000"); - m_doubleStringSet.Add(2.0005, "2.000500"); - m_doubleStringSet.Add(349485435.6805, "349485435.680500"); - m_doubleStringSet.Add(-548.5, "-548.500000"); - m_doubleStringSet.Add(-2.0005, "-2.000500"); - m_doubleStringSet.Add(-349485435.6805, "-349485435.680500"); - } - - /// - /// Tests constructing a LSLString from an LSLFloat. - /// - [Test] - public void TestConstructFromLSLFloat() - { - TestHelpers.InMethod(); - - LSL_Types.LSLString testString; - - foreach (KeyValuePair number in m_doubleStringSet) - { - testString = new LSL_Types.LSLString(new LSL_Types.LSLFloat(number.Key)); - Assert.AreEqual(number.Value, testString.m_string); - } - } - - /// - /// Tests constructing a LSLString from an LSLFloat. - /// - [Test] - public void TestExplicitCastLSLFloatToLSLString() - { - TestHelpers.InMethod(); - - LSL_Types.LSLString testString; - - foreach (KeyValuePair number in m_doubleStringSet) - { - testString = (LSL_Types.LSLString) new LSL_Types.LSLFloat(number.Key); - Assert.AreEqual(number.Value, testString.m_string); - } - } - - /// - /// Test constructing a Quaternion from a string. - /// - [Test] - public void TestExplicitCastLSLStringToQuaternion() - { - TestHelpers.InMethod(); - - string quaternionString = "<0.00000, 0.70711, 0.00000, 0.70711>"; - LSL_Types.LSLString quaternionLSLString = new LSL_Types.LSLString(quaternionString); - - LSL_Types.Quaternion expectedQuaternion = new LSL_Types.Quaternion(0.0, 0.70711, 0.0, 0.70711); - LSL_Types.Quaternion stringQuaternion = (LSL_Types.Quaternion) quaternionString; - LSL_Types.Quaternion LSLStringQuaternion = (LSL_Types.Quaternion) quaternionLSLString; - - Assert.AreEqual(expectedQuaternion, stringQuaternion); - Assert.AreEqual(expectedQuaternion, LSLStringQuaternion); - } - - /// - /// Tests boolean correctly cast explicitly to LSLString. - /// - [Test] - public void TestImplicitCastBooleanToLSLFloat() - { - TestHelpers.InMethod(); - - LSL_Types.LSLString testString; - - testString = (LSL_Types.LSLString) (1 == 0); - Assert.AreEqual("0", testString.m_string); - - testString = (LSL_Types.LSLString) (1 == 1); - Assert.AreEqual("1", testString.m_string); - - testString = (LSL_Types.LSLString) false; - Assert.AreEqual("0", testString.m_string); - - testString = (LSL_Types.LSLString) true; - Assert.AreEqual("1", testString.m_string); - } - } -} diff --git a/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_TypesTestList.cs b/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_TypesTestList.cs deleted file mode 100644 index fe2113bd561..00000000000 --- a/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_TypesTestList.cs +++ /dev/null @@ -1,295 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System.Collections.Generic; -using NUnit.Framework; -using OpenSim.Tests.Common; -using OpenSim.Region.ScriptEngine.Shared; - -namespace OpenSim.Region.ScriptEngine.Shared.Tests -{ - /// - /// Tests the LSL_Types.list class. - /// - [TestFixture] - public class LSL_TypesTestList : OpenSimTestCase - { - /// - /// Tests concatenating a string to a list. - /// - [Test] - public void TestConcatenateString() - { - TestHelpers.InMethod(); - - LSL_Types.list testList = new LSL_Types.list(new LSL_Types.LSLInteger(1), new LSL_Types.LSLInteger('a'), new LSL_Types.LSLString("test")); - testList += new LSL_Types.LSLString("addition"); - - Assert.AreEqual(4, testList.Length); - Assert.AreEqual(new LSL_Types.LSLString("addition"), testList.Data[3]); - Assert.AreEqual(typeof(LSL_Types.LSLString), testList.Data[3].GetType()); - - LSL_Types.list secondTestList = testList + new LSL_Types.LSLString("more"); - - Assert.AreEqual(5, secondTestList.Length); - Assert.AreEqual(new LSL_Types.LSLString("more"), secondTestList.Data[4]); - Assert.AreEqual(typeof(LSL_Types.LSLString), secondTestList.Data[4].GetType()); - } - - /// - /// Tests concatenating an integer to a list. - /// - [Test] - public void TestConcatenateInteger() - { - TestHelpers.InMethod(); - - LSL_Types.list testList = new LSL_Types.list(new LSL_Types.LSLInteger(1), new LSL_Types.LSLInteger('a'), new LSL_Types.LSLString("test")); - testList += new LSL_Types.LSLInteger(20); - - Assert.AreEqual(4, testList.Length); - Assert.AreEqual(new LSL_Types.LSLInteger(20), testList.Data[3]); - Assert.AreEqual(typeof(LSL_Types.LSLInteger), testList.Data[3].GetType()); - - LSL_Types.list secondTestList = testList + new LSL_Types.LSLInteger(2); - - Assert.AreEqual(5, secondTestList.Length); - Assert.AreEqual(new LSL_Types.LSLInteger(2), secondTestList.Data[4]); - Assert.AreEqual(typeof(LSL_Types.LSLInteger), secondTestList.Data[4].GetType()); - } - - /// - /// Tests concatenating a float to a list. - /// - [Test] - public void TestConcatenateDouble() - { - TestHelpers.InMethod(); - - LSL_Types.list testList = new LSL_Types.list(new LSL_Types.LSLInteger(1), new LSL_Types.LSLInteger('a'), new LSL_Types.LSLString("test")); - testList += new LSL_Types.LSLFloat(2.0f); - - Assert.AreEqual(4, testList.Length); - Assert.AreEqual(new LSL_Types.LSLFloat(2.0f), testList.Data[3]); - Assert.AreEqual(typeof(LSL_Types.LSLFloat), testList.Data[3].GetType()); - - LSL_Types.list secondTestList = testList + new LSL_Types.LSLFloat(0.04f); - - Assert.AreEqual(5, secondTestList.Length); - Assert.AreEqual(new LSL_Types.LSLFloat(0.04f), secondTestList.Data[4]); - Assert.AreEqual(typeof(LSL_Types.LSLFloat), secondTestList.Data[4].GetType()); - } - - /// - /// Tests casting LSLInteger item to LSLInteger. - /// - [Test] - public void TestCastLSLIntegerItemToLSLInteger() - { - TestHelpers.InMethod(); - - LSL_Types.LSLInteger testValue = new LSL_Types.LSLInteger(123); - LSL_Types.list testList = new LSL_Types.list(testValue); - - Assert.AreEqual(testValue, (LSL_Types.LSLInteger)testList.Data[0]); - } - - /// - /// Tests casting LSLFloat item to LSLFloat. - /// - [Test] - public void TestCastLSLFloatItemToLSLFloat() - { - TestHelpers.InMethod(); - - LSL_Types.LSLFloat testValue = new LSL_Types.LSLFloat(123.45678987); - LSL_Types.list testList = new LSL_Types.list(testValue); - - Assert.AreEqual(testValue, (LSL_Types.LSLFloat)testList.Data[0]); - } - - /// - /// Tests casting LSLString item to LSLString. - /// - [Test] - public void TestCastLSLStringItemToLSLString() - { - TestHelpers.InMethod(); - - LSL_Types.LSLString testValue = new LSL_Types.LSLString("hello there"); - LSL_Types.list testList = new LSL_Types.list(testValue); - - Assert.AreEqual(testValue, (LSL_Types.LSLString)testList.Data[0]); - } - - /// - /// Tests casting Vector3 item to Vector3. - /// - [Test] - public void TestCastVector3ItemToVector3() - { - TestHelpers.InMethod(); - - LSL_Types.Vector3 testValue = new LSL_Types.Vector3(12.34, 56.987654, 0.00987); - LSL_Types.list testList = new LSL_Types.list(testValue); - - Assert.AreEqual(testValue, (LSL_Types.Vector3)testList.Data[0]); - } - /// - /// Tests casting Quaternion item to Quaternion. - /// - [Test] - public void TestCastQuaternionItemToQuaternion() - { - TestHelpers.InMethod(); - - LSL_Types.Quaternion testValue = new LSL_Types.Quaternion(12.34, 56.44323, 765.983421, 0.00987); - LSL_Types.list testList = new LSL_Types.list(testValue); - - Assert.AreEqual(testValue, (LSL_Types.Quaternion)testList.Data[0]); - } - -//==================================================================================== - - /// - /// Tests GetLSLIntegerItem for LSLInteger item. - /// - [Test] - public void TestGetLSLIntegerItemForLSLIntegerItem() - { - TestHelpers.InMethod(); - - LSL_Types.LSLInteger testValue = new LSL_Types.LSLInteger(999911); - LSL_Types.list testList = new LSL_Types.list(testValue); - - Assert.AreEqual(testValue, testList.GetLSLIntegerItem(0)); - } - - /// - /// Tests GetLSLFloatItem for LSLFloat item. - /// - [Test] - public void TestGetLSLFloatItemForLSLFloatItem() - { - TestHelpers.InMethod(); - - LSL_Types.LSLFloat testValue = new LSL_Types.LSLFloat(321.45687876); - LSL_Types.list testList = new LSL_Types.list(testValue); - - Assert.AreEqual(testValue, testList.GetLSLFloatItem(0)); - } - - /// - /// Tests GetLSLFloatItem for LSLInteger item. - /// - [Test] - public void TestGetLSLFloatItemForLSLIntegerItem() - { - TestHelpers.InMethod(); - - LSL_Types.LSLInteger testValue = new LSL_Types.LSLInteger(3060987); - LSL_Types.LSLFloat testFloatValue = new LSL_Types.LSLFloat(testValue); - LSL_Types.list testList = new LSL_Types.list(testValue); - - Assert.AreEqual(testFloatValue, testList.GetLSLFloatItem(0)); - } - - /// - /// Tests GetLSLStringItem for LSLString item. - /// - [Test] - public void TestGetLSLStringItemForLSLStringItem() - { - TestHelpers.InMethod(); - - LSL_Types.LSLString testValue = new LSL_Types.LSLString("hello all"); - LSL_Types.list testList = new LSL_Types.list(testValue); - - Assert.AreEqual(testValue, testList.GetLSLStringItem(0)); - } - - /// - /// Tests GetLSLStringItem for key item. - /// - [Test] - public void TestGetLSLStringItemForKeyItem() - { - TestHelpers.InMethod(); - - LSL_Types.key testValue - = new LSL_Types.key("98000000-0000-2222-3333-100000001000"); - LSL_Types.LSLString testStringValue = new LSL_Types.LSLString(testValue); - LSL_Types.list testList = new LSL_Types.list(testValue); - - Assert.AreEqual(testStringValue, testList.GetLSLStringItem(0)); - } - - /// - /// Tests GetVector3Item for Vector3 item. - /// - [Test] - public void TestGetVector3ItemForVector3Item() - { - TestHelpers.InMethod(); - - LSL_Types.Vector3 testValue = new LSL_Types.Vector3(92.34, 58.98754, -0.10987); - LSL_Types.list testList = new LSL_Types.list(testValue); - - Assert.AreEqual(testValue, testList.GetVector3Item(0)); - } - /// - /// Tests GetQuaternionItem for Quaternion item. - /// - [Test] - public void TestGetQuaternionItemForQuaternionItem() - { - TestHelpers.InMethod(); - - LSL_Types.Quaternion testValue = new LSL_Types.Quaternion(12.64, 59.43723, 765.3421, 4.00987); - // make that nonsense a quaternion - testValue.Normalize(); - LSL_Types.list testList = new LSL_Types.list(testValue); - - Assert.AreEqual(testValue, testList.GetQuaternionItem(0)); - } - - /// - /// Tests GetKeyItem for key item. - /// - [Test] - public void TestGetKeyItemForKeyItem() - { - TestHelpers.InMethod(); - - LSL_Types.key testValue - = new LSL_Types.key("00000000-0000-2222-3333-100000001012"); - LSL_Types.list testList = new LSL_Types.list(testValue); - - Assert.AreEqual(testValue, testList.GetKeyItem(0)); - } - } -} \ No newline at end of file diff --git a/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_TypesTestVector3.cs b/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_TypesTestVector3.cs deleted file mode 100644 index 0c838afa3c7..00000000000 --- a/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_TypesTestVector3.cs +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System.Collections.Generic; -using NUnit.Framework; -using OpenSim.Tests.Common; -using OpenSim.Region.ScriptEngine.Shared; - -namespace OpenSim.Region.ScriptEngine.Shared.Tests -{ - /// - /// Tests for Vector3 - /// - [TestFixture] - public class LSL_TypesTestVector3 : OpenSimTestCase - { - [Test] - public void TestDotProduct() - { - TestHelpers.InMethod(); - - // The numbers we test for. - Dictionary expectsSet = new Dictionary(); - expectsSet.Add("<1, 2, 3> * <2, 3, 4>", 20.0); - expectsSet.Add("<1, 2, 3> * <0, 0, 0>", 0.0); - - double result; - string[] parts; - string[] delim = { "*" }; - - foreach (KeyValuePair ex in expectsSet) - { - parts = ex.Key.Split(delim, System.StringSplitOptions.None); - result = new LSL_Types.Vector3(parts[0]) * new LSL_Types.Vector3(parts[1]); - Assert.AreEqual(ex.Value, result); - } - } - } -} diff --git a/OpenSim/Region/ScriptEngine/Shared/Tests/OSSL_ApiAppearanceTest.cs b/OpenSim/Region/ScriptEngine/Shared/Tests/OSSL_ApiAppearanceTest.cs deleted file mode 100644 index 60c78e37194..00000000000 --- a/OpenSim/Region/ScriptEngine/Shared/Tests/OSSL_ApiAppearanceTest.cs +++ /dev/null @@ -1,167 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections.Generic; -using System.Reflection; -using System.Text; -using log4net; -using Nini.Config; -using NUnit.Framework; -using OpenMetaverse; -using OpenMetaverse.Assets; -using OpenMetaverse.StructuredData; -using OpenSim.Framework; -using OpenSim.Region.CoreModules.Avatar.AvatarFactory; -using OpenSim.Region.OptionalModules.World.NPC; -using OpenSim.Region.Framework.Scenes; -using OpenSim.Region.ScriptEngine.Shared; -using OpenSim.Region.ScriptEngine.Shared.Api; -using OpenSim.Services.Interfaces; -using OpenSim.Tests.Common; - -namespace OpenSim.Region.ScriptEngine.Shared.Tests -{ - /// - /// Tests for OSSL_Api - /// - [TestFixture] - public class OSSL_ApiAppearanceTest : OpenSimTestCase - { - /* - protected Scene m_scene; - protected XEngine.XEngine m_engine; - - [SetUp] - public override void SetUp() - { - base.SetUp(); - - IConfigSource initConfigSource = new IniConfigSource(); - IConfig config = initConfigSource.AddConfig("XEngine"); - config.Set("Enabled", "true"); - - config = initConfigSource.AddConfig("NPC"); - config.Set("Enabled", "true"); - - config = initConfigSource.AddConfig("OSSL"); - config.Set("DebuggerSafe", false); - config.Set("AllowOSFunctions", "true"); - config.Set("OSFunctionThreatLevel", "Severe"); - - - m_scene = new SceneHelpers().SetupScene(); - SceneHelpers.SetupSceneModules(m_scene, initConfigSource, new AvatarFactoryModule(), new NPCModule()); - - m_engine = new XEngine.XEngine(); - m_engine.Initialise(initConfigSource); - m_engine.AddRegion(m_scene); - } - - [Test] - public void TestOsOwnerSaveAppearance() - { - TestHelpers.InMethod(); -// log4net.Config.XmlConfigurator.Configure(); - - UUID userId = TestHelpers.ParseTail(0x1); - float newHeight = 1.9f; - - ScenePresence sp = SceneHelpers.AddScenePresence(m_scene, userId); - sp.Appearance.AvatarHeight = newHeight; - SceneObjectGroup so = SceneHelpers.CreateSceneObject(1, userId, 0x10); - SceneObjectPart part = so.RootPart; - m_scene.AddSceneObject(so); - - OSSL_Api osslApi = new OSSL_Api(); - osslApi.Initialize(m_engine, part, null); - - string notecardName = "appearanceNc"; - - osslApi.osOwnerSaveAppearance(notecardName); - - IList items = part.Inventory.GetInventoryItems(notecardName); - Assert.That(items.Count, Is.EqualTo(1)); - - TaskInventoryItem ncItem = items[0]; - Assert.That(ncItem.Name, Is.EqualTo(notecardName)); - - AssetBase ncAsset = m_scene.AssetService.Get(ncItem.AssetID.ToString()); - Assert.That(ncAsset, Is.Not.Null); - - AssetNotecard anc = new AssetNotecard(UUID.Zero, ncAsset.Data); - anc.Decode(); - OSDMap appearanceOsd = (OSDMap)OSDParser.DeserializeLLSDXml(anc.BodyText); - AvatarAppearance savedAppearance = new AvatarAppearance(); - savedAppearance.Unpack(appearanceOsd); - - Assert.That(savedAppearance.AvatarHeight, Is.EqualTo(sp.Appearance.AvatarHeight)); - } - - [Test] - public void TestOsAgentSaveAppearance() - { - TestHelpers.InMethod(); -// log4net.Config.XmlConfigurator.Configure(); - - UUID ownerId = TestHelpers.ParseTail(0x1); - UUID nonOwnerId = TestHelpers.ParseTail(0x2); - float newHeight = 1.9f; - - ScenePresence sp = SceneHelpers.AddScenePresence(m_scene, nonOwnerId); - sp.Appearance.AvatarHeight = newHeight; - SceneObjectGroup so = SceneHelpers.CreateSceneObject(1, ownerId, 0x10); - SceneObjectPart part = so.RootPart; - m_scene.AddSceneObject(so); - - OSSL_Api osslApi = new OSSL_Api(); - osslApi.Initialize(m_engine, part, null); - - string notecardName = "appearanceNc"; - - osslApi.osAgentSaveAppearance(new LSL_Types.LSLString(nonOwnerId.ToString()), notecardName); - - IList items = part.Inventory.GetInventoryItems(notecardName); - Assert.That(items.Count, Is.EqualTo(1)); - - TaskInventoryItem ncItem = items[0]; - Assert.That(ncItem.Name, Is.EqualTo(notecardName)); - - AssetBase ncAsset = m_scene.AssetService.Get(ncItem.AssetID.ToString()); - Assert.That(ncAsset, Is.Not.Null); - - AssetNotecard anc = new AssetNotecard(UUID.Zero, ncAsset.Data); - anc.Decode(); - OSDMap appearanceOsd = (OSDMap)OSDParser.DeserializeLLSDXml(anc.BodyText); - AvatarAppearance savedAppearance = new AvatarAppearance(); - savedAppearance.Unpack(appearanceOsd); - - Assert.That(savedAppearance.AvatarHeight, Is.EqualTo(sp.Appearance.AvatarHeight)); - } - } - */ -} diff --git a/OpenSim/Region/ScriptEngine/Shared/Tests/OSSL_ApiAttachmentTests.cs b/OpenSim/Region/ScriptEngine/Shared/Tests/OSSL_ApiAttachmentTests.cs deleted file mode 100644 index 4b13c1c3ea3..00000000000 --- a/OpenSim/Region/ScriptEngine/Shared/Tests/OSSL_ApiAttachmentTests.cs +++ /dev/null @@ -1,234 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections.Generic; -using System.Reflection; -using System.Text; -using log4net; -using Nini.Config; -using NUnit.Framework; -using OpenMetaverse; -using OpenMetaverse.Assets; -using OpenMetaverse.StructuredData; -using OpenSim.Framework; -using OpenSim.Region.CoreModules.Avatar.Attachments; -using OpenSim.Region.CoreModules.Framework.InventoryAccess; -using OpenSim.Region.Framework.Scenes; -using OpenSim.Region.ScriptEngine.Shared; -using OpenSim.Region.ScriptEngine.Shared.Api; -using OpenSim.Services.Interfaces; -using OpenSim.Tests.Common; - -namespace OpenSim.Region.ScriptEngine.Shared.Tests -{ - /// - /// Tests for OSSL attachment functions - /// - /// - /// TODO: Add tests for all functions - /// - [TestFixture] - public class OSSL_ApiAttachmentTests : OpenSimTestCase - { - protected Scene m_scene; - protected XEngine.XEngine m_engine; - - [SetUp] - public override void SetUp() - { - base.SetUp(); - - IConfigSource initConfigSource = new IniConfigSource(); - - IConfig xengineConfig = initConfigSource.AddConfig("XEngine"); - xengineConfig.Set("Enabled", "true"); - - IConfig oconfig = initConfigSource.AddConfig("OSSL"); - oconfig.Set("DebuggerSafe", false); - oconfig.Set("AllowOSFunctions", "true"); - oconfig.Set("OSFunctionThreatLevel", "Severe"); - - IConfig modulesConfig = initConfigSource.AddConfig("Modules"); - modulesConfig.Set("InventoryAccessModule", "BasicInventoryAccessModule"); - - m_scene = new SceneHelpers().SetupScene(); - SceneHelpers.SetupSceneModules( - m_scene, initConfigSource, new AttachmentsModule(), new BasicInventoryAccessModule()); - - m_engine = new XEngine.XEngine(); - m_engine.Initialise(initConfigSource); - m_engine.AddRegion(m_scene); - } - - [Test] - public void TestOsForceAttachToAvatarFromInventory() - { - TestHelpers.InMethod(); -// TestHelpers.EnableLogging(); - - string taskInvObjItemName = "sphere"; - UUID taskInvObjItemId = UUID.Parse("00000000-0000-0000-0000-100000000000"); - AttachmentPoint attachPoint = AttachmentPoint.Chin; - - UserAccount ua1 = UserAccountHelpers.CreateUserWithInventory(m_scene, 0x1); - ScenePresence sp = SceneHelpers.AddScenePresence(m_scene, ua1.PrincipalID); - SceneObjectGroup inWorldObj = SceneHelpers.AddSceneObject(m_scene, "inWorldObj", ua1.PrincipalID); - TaskInventoryItem scriptItem = TaskInventoryHelpers.AddScript(m_scene.AssetService, inWorldObj.RootPart); - - new LSL_Api().Initialize(m_engine, inWorldObj.RootPart, scriptItem); - OSSL_Api osslApi = new OSSL_Api(); - osslApi.Initialize(m_engine, inWorldObj.RootPart, scriptItem); - -// SceneObjectGroup sog1 = SceneHelpers.CreateSceneObject(1, ua1.PrincipalID); - - // Create an object embedded inside the first - TaskInventoryHelpers.AddSceneObject(m_scene.AssetService, inWorldObj.RootPart, taskInvObjItemName, taskInvObjItemId, ua1.PrincipalID); - - osslApi.osForceAttachToAvatarFromInventory(taskInvObjItemName, (int)attachPoint); - - // Check scene presence status - Assert.That(sp.HasAttachments(), Is.True); - List attachments = sp.GetAttachments(); - Assert.That(attachments.Count, Is.EqualTo(1)); - SceneObjectGroup attSo = attachments[0]; - Assert.That(attSo.Name, Is.EqualTo(taskInvObjItemName)); - Assert.That(attSo.AttachmentPoint, Is.EqualTo((uint)attachPoint)); - Assert.That(attSo.IsAttachment); - Assert.That(attSo.UsesPhysics, Is.False); - Assert.That(attSo.IsTemporary, Is.False); - - // Check appearance status - List attachmentsInAppearance = sp.Appearance.GetAttachments(); - Assert.That(attachmentsInAppearance.Count, Is.EqualTo(1)); - Assert.That(sp.Appearance.GetAttachpoint(attachmentsInAppearance[0].ItemID), Is.EqualTo((uint)attachPoint)); - } - - /// - /// Make sure we can't force attach anything other than objects. - /// - [Test] - public void TestOsForceAttachToAvatarFromInventoryNotObject() - { - TestHelpers.InMethod(); -// TestHelpers.EnableLogging(); - - string taskInvObjItemName = "sphere"; - UUID taskInvObjItemId = UUID.Parse("00000000-0000-0000-0000-100000000000"); - AttachmentPoint attachPoint = AttachmentPoint.Chin; - - UserAccount ua1 = UserAccountHelpers.CreateUserWithInventory(m_scene, 0x1); - ScenePresence sp = SceneHelpers.AddScenePresence(m_scene, ua1.PrincipalID); - SceneObjectGroup inWorldObj = SceneHelpers.AddSceneObject(m_scene, "inWorldObj", ua1.PrincipalID); - TaskInventoryItem scriptItem = TaskInventoryHelpers.AddScript(m_scene.AssetService, inWorldObj.RootPart); - - new LSL_Api().Initialize(m_engine, inWorldObj.RootPart, scriptItem); - OSSL_Api osslApi = new OSSL_Api(); - osslApi.Initialize(m_engine, inWorldObj.RootPart, scriptItem); - - // Create an object embedded inside the first - TaskInventoryHelpers.AddNotecard( - m_scene.AssetService, inWorldObj.RootPart, taskInvObjItemName, taskInvObjItemId, TestHelpers.ParseTail(0x900), "Hello World!"); - - bool exceptionCaught = false; - - try - { - osslApi.osForceAttachToAvatarFromInventory(taskInvObjItemName, (int)attachPoint); - } - catch (Exception) - { - exceptionCaught = true; - } - - Assert.That(exceptionCaught, Is.True); - - // Check scene presence status - Assert.That(sp.HasAttachments(), Is.False); - List attachments = sp.GetAttachments(); - Assert.That(attachments.Count, Is.EqualTo(0)); - - // Check appearance status - List attachmentsInAppearance = sp.Appearance.GetAttachments(); - Assert.That(attachmentsInAppearance.Count, Is.EqualTo(0)); - } - - [Test] - public void TestOsForceAttachToOtherAvatarFromInventory() - { - TestHelpers.InMethod(); -// TestHelpers.EnableLogging(); - - string taskInvObjItemName = "sphere"; - UUID taskInvObjItemId = UUID.Parse("00000000-0000-0000-0000-100000000000"); - AttachmentPoint attachPoint = AttachmentPoint.Chin; - - UserAccount ua1 = UserAccountHelpers.CreateUserWithInventory(m_scene, "user", "one", 0x1, "pass"); - UserAccount ua2 = UserAccountHelpers.CreateUserWithInventory(m_scene, "user", "two", 0x2, "pass"); - - ScenePresence sp = SceneHelpers.AddScenePresence(m_scene, ua1); - SceneObjectGroup inWorldObj = SceneHelpers.AddSceneObject(m_scene, "inWorldObj", ua1.PrincipalID); - TaskInventoryItem scriptItem = TaskInventoryHelpers.AddScript(m_scene.AssetService, inWorldObj.RootPart); - - new LSL_Api().Initialize(m_engine, inWorldObj.RootPart, scriptItem); - OSSL_Api osslApi = new OSSL_Api(); - osslApi.Initialize(m_engine, inWorldObj.RootPart, scriptItem); - - // Create an object embedded inside the first - TaskInventoryHelpers.AddSceneObject( - m_scene.AssetService, inWorldObj.RootPart, taskInvObjItemName, taskInvObjItemId, ua1.PrincipalID); - - ScenePresence sp2 = SceneHelpers.AddScenePresence(m_scene, ua2); - - osslApi.osForceAttachToOtherAvatarFromInventory(sp2.UUID.ToString(), taskInvObjItemName, (int)attachPoint); - - // Check scene presence status - Assert.That(sp.HasAttachments(), Is.False); - List attachments = sp.GetAttachments(); - Assert.That(attachments.Count, Is.EqualTo(0)); - - Assert.That(sp2.HasAttachments(), Is.True); - List attachments2 = sp2.GetAttachments(); - Assert.That(attachments2.Count, Is.EqualTo(1)); - SceneObjectGroup attSo = attachments2[0]; - Assert.That(attSo.Name, Is.EqualTo(taskInvObjItemName)); - Assert.That(attSo.OwnerID, Is.EqualTo(ua2.PrincipalID)); - Assert.That(attSo.AttachmentPoint, Is.EqualTo((uint)attachPoint)); - Assert.That(attSo.IsAttachment); - Assert.That(attSo.UsesPhysics, Is.False); - Assert.That(attSo.IsTemporary, Is.False); - - // Check appearance status - List attachmentsInAppearance = sp.Appearance.GetAttachments(); - Assert.That(attachmentsInAppearance.Count, Is.EqualTo(0)); - - List attachmentsInAppearance2 = sp2.Appearance.GetAttachments(); - Assert.That(attachmentsInAppearance2.Count, Is.EqualTo(1)); - Assert.That(sp2.Appearance.GetAttachpoint(attachmentsInAppearance2[0].ItemID), Is.EqualTo((uint)attachPoint)); - } - } -} diff --git a/OpenSim/Region/ScriptEngine/Shared/Tests/OSSL_ApiNpcTests.cs b/OpenSim/Region/ScriptEngine/Shared/Tests/OSSL_ApiNpcTests.cs deleted file mode 100644 index 108998ed641..00000000000 --- a/OpenSim/Region/ScriptEngine/Shared/Tests/OSSL_ApiNpcTests.cs +++ /dev/null @@ -1,354 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections.Generic; -using System.Reflection; -using System.Text; -using log4net; -using Nini.Config; -using NUnit.Framework; -using OpenMetaverse; -using OpenMetaverse.Assets; -using OpenMetaverse.StructuredData; -using OpenSim.Framework; -using OpenSim.Region.CoreModules.Avatar.Attachments; -using OpenSim.Region.CoreModules.Avatar.AvatarFactory; -using OpenSim.Region.OptionalModules.World.NPC; -using OpenSim.Region.Framework.Scenes; -using OpenSim.Region.ScriptEngine.Shared; -using OpenSim.Region.ScriptEngine.Shared.Api; -using OpenSim.Region.ScriptEngine.Shared.ScriptBase; -using OpenSim.Services.Interfaces; -using OpenSim.Tests.Common; - -namespace OpenSim.Region.ScriptEngine.Shared.Tests -{ - /// - /// Tests for OSSL NPC API - /// - [TestFixture] - public class OSSL_NpcApiAppearanceTest : OpenSimTestCase - { - protected Scene m_scene; - protected XEngine.XEngine m_engine; - - [SetUp] - public override void SetUp() - { - base.SetUp(); - - IConfigSource initConfigSource = new IniConfigSource(); - IConfig config = initConfigSource.AddConfig("XEngine"); - config.Set("Enabled", "true"); - - config = initConfigSource.AddConfig("NPC"); - config.Set("Enabled", "true"); - - config = initConfigSource.AddConfig("OSSL"); - config.Set("DebuggerSafe", false); - config.Set("AllowOSFunctions", "true"); - config.Set("OSFunctionThreatLevel", "Severe"); - - m_scene = new SceneHelpers().SetupScene(); - SceneHelpers.SetupSceneModules( - m_scene, initConfigSource, new AvatarFactoryModule(), new AttachmentsModule(), new NPCModule()); - - m_engine = new XEngine.XEngine(); - m_engine.Initialise(initConfigSource); - m_engine.AddRegion(m_scene); - } - - /// - /// Test creation of an NPC where the appearance data comes from a notecard - /// - [Test] - public void TestOsNpcCreateUsingAppearanceFromNotecard() - { - TestHelpers.InMethod(); - - // Store an avatar with a different height from default in a notecard. - UUID userId = TestHelpers.ParseTail(0x1); - float newHeight = 1.9f; - - ScenePresence sp = SceneHelpers.AddScenePresence(m_scene, userId); - sp.Appearance.AvatarHeight = newHeight; - SceneObjectGroup so = SceneHelpers.CreateSceneObject(1, userId, 0x10); - SceneObjectPart part = so.RootPart; - m_scene.AddSceneObject(so); - - OSSL_Api osslApi = new OSSL_Api(); - osslApi.Initialize(m_engine, part, null); - - string notecardName = "appearanceNc"; - osslApi.osOwnerSaveAppearance(notecardName); - - // Try creating a bot using the appearance in the notecard. - string npcRaw = osslApi.osNpcCreate("Jane", "Doe", new LSL_Types.Vector3(128, 128, 128), notecardName); - Assert.That(npcRaw, Is.Not.Null); - - UUID npcId = new UUID(npcRaw); - ScenePresence npc = m_scene.GetScenePresence(npcId); - Assert.That(npc, Is.Not.Null); - Assert.That(npc.Appearance.AvatarHeight, Is.EqualTo(newHeight)); - } - - [Test] - public void TestOsNpcCreateNotExistingNotecard() - { - TestHelpers.InMethod(); - - UUID userId = TestHelpers.ParseTail(0x1); - - SceneObjectGroup so = SceneHelpers.CreateSceneObject(1, userId, 0x10); - m_scene.AddSceneObject(so); - - OSSL_Api osslApi = new OSSL_Api(); - osslApi.Initialize(m_engine, so.RootPart, null); - - bool gotExpectedException = false; - try - { - osslApi.osNpcCreate("Jane", "Doe", new LSL_Types.Vector3(128, 128, 128), "not existing notecard name"); - } - catch (ScriptException) - { - gotExpectedException = true; - } - - Assert.That(gotExpectedException, Is.True); - } - - /// - /// Test creation of an NPC where the appearance data comes from an avatar already in the region. - /// - [Test] - public void TestOsNpcCreateUsingAppearanceFromAvatar() - { - TestHelpers.InMethod(); -// TestHelpers.EnableLogging(); - - // Store an avatar with a different height from default in a notecard. - UUID userId = TestHelpers.ParseTail(0x1); - float newHeight = 1.9f; - - ScenePresence sp = SceneHelpers.AddScenePresence(m_scene, userId); - sp.Appearance.AvatarHeight = newHeight; - SceneObjectGroup so = SceneHelpers.CreateSceneObject(1, userId, 0x10); - SceneObjectPart part = so.RootPart; - m_scene.AddSceneObject(so); - - OSSL_Api osslApi = new OSSL_Api(); - osslApi.Initialize(m_engine, part, null); - - string notecardName = "appearanceNc"; - osslApi.osOwnerSaveAppearance(notecardName); - - // Try creating a bot using the existing avatar's appearance - string npcRaw = osslApi.osNpcCreate("Jane", "Doe", new LSL_Types.Vector3(128, 128, 128), sp.UUID.ToString()); - Assert.That(npcRaw, Is.Not.Null); - - UUID npcId = new UUID(npcRaw); - ScenePresence npc = m_scene.GetScenePresence(npcId); - Assert.That(npc, Is.Not.Null); - Assert.That(npc.Appearance.AvatarHeight, Is.EqualTo(newHeight)); - } - - [Test] - public void TestOsNpcLoadAppearance() - { - TestHelpers.InMethod(); - //TestHelpers.EnableLogging(); - - // Store an avatar with a different height from default in a notecard. - UUID userId = TestHelpers.ParseTail(0x1); - float firstHeight = 1.9f; - float secondHeight = 2.1f; - string firstAppearanceNcName = "appearanceNc1"; - string secondAppearanceNcName = "appearanceNc2"; - - ScenePresence sp = SceneHelpers.AddScenePresence(m_scene, userId); - sp.Appearance.AvatarHeight = firstHeight; - SceneObjectGroup so = SceneHelpers.CreateSceneObject(1, userId, 0x10); - SceneObjectPart part = so.RootPart; - m_scene.AddSceneObject(so); - - OSSL_Api osslApi = new OSSL_Api(); - osslApi.Initialize(m_engine, part, null); - - osslApi.osOwnerSaveAppearance(firstAppearanceNcName); - - string npcRaw - = osslApi.osNpcCreate("Jane", "Doe", new LSL_Types.Vector3(128, 128, 128), firstAppearanceNcName); - - // Create a second appearance notecard with a different height - sp.Appearance.AvatarHeight = secondHeight; - osslApi.osOwnerSaveAppearance(secondAppearanceNcName); - - osslApi.osNpcLoadAppearance(npcRaw, secondAppearanceNcName); - - UUID npcId = new UUID(npcRaw); - ScenePresence npc = m_scene.GetScenePresence(npcId); - Assert.That(npc, Is.Not.Null); - Assert.That(npc.Appearance.AvatarHeight, Is.EqualTo(secondHeight)); - } - - [Test] - public void TestOsNpcLoadAppearanceNotExistingNotecard() - { - TestHelpers.InMethod(); - - // Store an avatar with a different height from default in a notecard. - UUID userId = TestHelpers.ParseTail(0x1); - float firstHeight = 1.9f; -// float secondHeight = 2.1f; - string firstAppearanceNcName = "appearanceNc1"; - string secondAppearanceNcName = "appearanceNc2"; - - ScenePresence sp = SceneHelpers.AddScenePresence(m_scene, userId); - sp.Appearance.AvatarHeight = firstHeight; - SceneObjectGroup so = SceneHelpers.CreateSceneObject(1, userId, 0x10); - SceneObjectPart part = so.RootPart; - m_scene.AddSceneObject(so); - - OSSL_Api osslApi = new OSSL_Api(); - osslApi.Initialize(m_engine, part, null); - - osslApi.osOwnerSaveAppearance(firstAppearanceNcName); - - string npcRaw - = osslApi.osNpcCreate("Jane", "Doe", new LSL_Types.Vector3(128, 128, 128), firstAppearanceNcName); - - bool gotExpectedException = false; - try - { - osslApi.osNpcLoadAppearance(npcRaw, secondAppearanceNcName); - } - catch (ScriptException) - { - gotExpectedException = true; - } - - Assert.That(gotExpectedException, Is.True); - - UUID npcId = new UUID(npcRaw); - ScenePresence npc = m_scene.GetScenePresence(npcId); - Assert.That(npc, Is.Not.Null); - Assert.That(npc.Appearance.AvatarHeight, Is.EqualTo(firstHeight)); - } - - /// - /// Test removal of an owned NPC. - /// - [Test] - public void TestOsNpcRemoveOwned() - { - TestHelpers.InMethod(); - - // Store an avatar with a different height from default in a notecard. - UUID userId = TestHelpers.ParseTail(0x1); - UUID otherUserId = TestHelpers.ParseTail(0x2); - float newHeight = 1.9f; - - SceneHelpers.AddScenePresence(m_scene, otherUserId); - - ScenePresence sp = SceneHelpers.AddScenePresence(m_scene, userId); - sp.Appearance.AvatarHeight = newHeight; - - SceneObjectGroup so = SceneHelpers.CreateSceneObject(1, userId, 0x10); - SceneObjectPart part = so.RootPart; - m_scene.AddSceneObject(so); - - SceneObjectGroup otherSo = SceneHelpers.CreateSceneObject(1, otherUserId, 0x20); - SceneObjectPart otherPart = otherSo.RootPart; - m_scene.AddSceneObject(otherSo); - - OSSL_Api osslApi = new OSSL_Api(); - osslApi.Initialize(m_engine, part, null); - - OSSL_Api otherOsslApi = new OSSL_Api(); - otherOsslApi.Initialize(m_engine, otherPart, null); - - string notecardName = "appearanceNc"; - osslApi.osOwnerSaveAppearance(notecardName); - - string npcRaw - = osslApi.osNpcCreate( - "Jane", "Doe", new LSL_Types.Vector3(128, 128, 128), notecardName, ScriptBaseClass.OS_NPC_CREATOR_OWNED); - - otherOsslApi.osNpcRemove(npcRaw); - - // Should still be around - UUID npcId = new UUID(npcRaw); - ScenePresence npc = m_scene.GetScenePresence(npcId); - Assert.That(npc, Is.Not.Null); - - osslApi.osNpcRemove(npcRaw); - - npc = m_scene.GetScenePresence(npcId); - - // Now the owner deleted it and it's gone - Assert.That(npc, Is.Null); - } - - /// - /// Test removal of an unowned NPC. - /// - [Test] - public void TestOsNpcRemoveUnowned() - { - TestHelpers.InMethod(); -// log4net.Config.XmlConfigurator.Configure(); - - // Store an avatar with a different height from default in a notecard. - UUID userId = TestHelpers.ParseTail(0x1); - float newHeight = 1.9f; - - ScenePresence sp = SceneHelpers.AddScenePresence(m_scene, userId); - sp.Appearance.AvatarHeight = newHeight; - SceneObjectGroup so = SceneHelpers.CreateSceneObject(1, userId, 0x10); - SceneObjectPart part = so.RootPart; - m_scene.AddSceneObject(so); - - OSSL_Api osslApi = new OSSL_Api(); - osslApi.Initialize(m_engine, part, null); - - string notecardName = "appearanceNc"; - osslApi.osOwnerSaveAppearance(notecardName); - - string npcRaw - = osslApi.osNpcCreate( - "Jane", "Doe", new LSL_Types.Vector3(128, 128, 128), notecardName, ScriptBaseClass.OS_NPC_NOT_OWNED); - - osslApi.osNpcRemove(npcRaw); - - UUID npcId = new UUID(npcRaw); - ScenePresence npc = m_scene.GetScenePresence(npcId); - Assert.That(npc, Is.Null); - } - } -} diff --git a/OpenSim/Server/Handlers/Asset/Tests/AssetServerPostHandlerTests.cs b/OpenSim/Server/Handlers/Asset/Tests/AssetServerPostHandlerTests.cs deleted file mode 100644 index 4d2228a025f..00000000000 --- a/OpenSim/Server/Handlers/Asset/Tests/AssetServerPostHandlerTests.cs +++ /dev/null @@ -1,109 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.IO; -using System.Net; -using System.Text; -using System.Xml; -using System.Xml.Serialization; -using Nini.Config; -using NUnit.Framework; -using OpenMetaverse; -using OpenSim.Framework; -using OpenSim.Server.Handlers.Asset; -using OpenSim.Services.AssetService; -using OpenSim.Services.Interfaces; -using OpenSim.Tests.Common; - -namespace OpenSim.Server.Handlers.Asset.Test -{ - [TestFixture] - public class AssetServerPostHandlerTests : OpenSimTestCase - { - [Test] - public void TestGoodAssetStoreRequest() - { - TestHelpers.InMethod(); - - UUID assetId = TestHelpers.ParseTail(0x1); - - IConfigSource config = new IniConfigSource(); - config.AddConfig("AssetService"); - config.Configs["AssetService"].Set("StorageProvider", "OpenSim.Tests.Common.dll"); - - AssetService assetService = new AssetService(config); - - AssetServerPostHandler asph = new AssetServerPostHandler(assetService); - - AssetBase asset = AssetHelpers.CreateNotecardAsset(assetId, "Hello World"); - - MemoryStream buffer = new MemoryStream(); - - XmlWriterSettings settings = new XmlWriterSettings(); - settings.Encoding = Encoding.UTF8; - - using (XmlWriter writer = XmlWriter.Create(buffer, settings)) - { - XmlSerializer serializer = new XmlSerializer(typeof(AssetBase)); - serializer.Serialize(writer, asset); - writer.Flush(); - } - - buffer.Position = 0; - asph.Handle(null, buffer, null, null); - - AssetBase retrievedAsset = assetService.Get(assetId.ToString()); - - Assert.That(retrievedAsset, Is.Not.Null); - } - - [Test] - public void TestBadXmlAssetStoreRequest() - { - TestHelpers.InMethod(); - - IConfigSource config = new IniConfigSource(); - config.AddConfig("AssetService"); - config.Configs["AssetService"].Set("StorageProvider", "OpenSim.Tests.Common.dll"); - - AssetService assetService = new AssetService(config); - - AssetServerPostHandler asph = new AssetServerPostHandler(assetService); - - MemoryStream buffer = new MemoryStream(); - byte[] badData = new byte[] { 0x48, 0x65, 0x6c, 0x6c, 0x6f }; - buffer.Write(badData, 0, badData.Length); - buffer.Position = 0; - - TestOSHttpResponse response = new TestOSHttpResponse(); - asph.Handle(null, buffer, null, response); - - Assert.That(response.StatusCode, Is.EqualTo((int)HttpStatusCode.BadRequest)); - } - } -} \ No newline at end of file diff --git a/OpenSim/Server/ServerMain.cs b/OpenSim/Server/ServerMain.cs index 1e5874ecece..7545015eb41 100644 --- a/OpenSim/Server/ServerMain.cs +++ b/OpenSim/Server/ServerMain.cs @@ -142,27 +142,28 @@ public static int Main(string[] args) connList = string.Join(",", servicesList.ToArray()); } - // temporay set the platform dependent System.Drawing.Common.dll - string targetdll = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), - "System.Drawing.Common.dll"); - string src = targetdll + (Util.IsWindows() ? ".win" : ".linux"); - try - { - if (!File.Exists(targetdll)) - File.Copy(src, targetdll); - else - { - FileInfo targetInfo = new(targetdll); - FileInfo srcInfo = new(src); - if (targetInfo.Length != srcInfo.Length) - File.Copy(src, targetdll, true); - } - } - catch (Exception e) - { - m_log.Error("Failed to copy System.Drawing.Common.dll for current platform" + e.Message); - throw; - } + // NOPE + // // temporay set the platform dependent System.Drawing.Common.dll + // string targetdll = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), + // "System.Drawing.Common.dll"); + // string src = targetdll + (Util.IsWindows() ? ".win" : ".linux"); + // try + // { + // if (!File.Exists(targetdll)) + // File.Copy(src, targetdll); + // else + // { + // FileInfo targetInfo = new(targetdll); + // FileInfo srcInfo = new(src); + // if (targetInfo.Length != srcInfo.Length) + // File.Copy(src, targetdll, true); + // } + // } + // catch (Exception e) + // { + // m_log.Error("Failed to copy System.Drawing.Common.dll for current platform" + e.Message); + // throw; + // } string[] conns = connList.Split(new char[] {',', ' ', '\n', '\r', '\t'}); diff --git a/OpenSim/Services/Connectors/OpenSim.Services.Connectors.csproj b/OpenSim/Services/Connectors/OpenSim.Services.Connectors.csproj index 8da03b91c83..121d2258e7a 100644 --- a/OpenSim/Services/Connectors/OpenSim.Services.Connectors.csproj +++ b/OpenSim/Services/Connectors/OpenSim.Services.Connectors.csproj @@ -29,9 +29,6 @@ ..\..\..\bin\OpenMetaverseTypes.dll False - - False - False @@ -52,4 +49,4 @@ - \ No newline at end of file + diff --git a/OpenSim/Services/InventoryService/Tests/OpenSim.Services.InventoryService.Tests.csproj b/OpenSim/Services/InventoryService/Tests/OpenSim.Services.InventoryService.Tests.csproj deleted file mode 100644 index 3c669920baa..00000000000 --- a/OpenSim/Services/InventoryService/Tests/OpenSim.Services.InventoryService.Tests.csproj +++ /dev/null @@ -1,50 +0,0 @@ - - - net8.0 - - - - - - - - ..\..\..\..\bin\Nini.dll - False - - - ..\..\..\..\bin\nunit.framework.dll - False - - - ..\..\..\..\bin\OpenMetaverse.dll - False - - - ..\..\..\..\bin\OpenMetaverse.StructuredData.dll - False - - - ..\..\..\..\bin\OpenMetaverseTypes.dll - False - - - False - - - False - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/OpenSim/Services/InventoryService/Tests/XInventoryServiceTests.cs b/OpenSim/Services/InventoryService/Tests/XInventoryServiceTests.cs deleted file mode 100644 index 2e4637c661e..00000000000 --- a/OpenSim/Services/InventoryService/Tests/XInventoryServiceTests.cs +++ /dev/null @@ -1,175 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using Nini.Config; -using NUnit.Framework; -using OpenMetaverse; -using OpenSim.Framework; -using OpenSim.Server.Base; -using OpenSim.Services.Interfaces; -using OpenSim.Tests.Common; - -namespace OpenSim.Services.InventoryService.Tests -{ - /// - /// Tests for the XInventoryService - /// - /// - /// TODO: Fill out more tests. - /// - [TestFixture] - public class XInventoryServiceTests : OpenSimTestCase - { - private IInventoryService CreateXInventoryService() - { - IConfigSource config = new IniConfigSource(); - config.AddConfig("InventoryService"); - config.Configs["InventoryService"].Set("StorageProvider", "OpenSim.Tests.Common.dll"); - - return ServerUtils.LoadPlugin( - "OpenSim.Services.InventoryService.dll:XInventoryService", new Object[] { config }); - } - - /// - /// Tests add item operation. - /// - /// - /// TODO: Test all operations. - /// - [Test] - public void TestAddItem() - { - TestHelpers.InMethod(); - - string creatorId = TestHelpers.ParseTail(0x1).ToString(); - UUID ownerId = TestHelpers.ParseTail(0x2); - UUID itemId = TestHelpers.ParseTail(0x10); - UUID assetId = TestHelpers.ParseTail(0x20); - UUID folderId = TestHelpers.ParseTail(0x30); - int invType = (int)InventoryType.Animation; - int assetType = (int)AssetType.Animation; - string itemName = "item1"; - - IInventoryService xis = CreateXInventoryService(); - - InventoryItemBase itemToStore - = new InventoryItemBase(itemId, ownerId) - { - CreatorIdentification = creatorId.ToString(), - AssetID = assetId, - Name = itemName, - Folder = folderId, - InvType = invType, - AssetType = assetType - }; - - Assert.That(xis.AddItem(itemToStore), Is.True); - - InventoryItemBase itemRetrieved = xis.GetItem(UUID.Zero, itemId); - - Assert.That(itemRetrieved, Is.Not.Null); - Assert.That(itemRetrieved.CreatorId, Is.EqualTo(creatorId)); - Assert.That(itemRetrieved.Owner, Is.EqualTo(ownerId)); - Assert.That(itemRetrieved.AssetID, Is.EqualTo(assetId)); - Assert.That(itemRetrieved.Folder, Is.EqualTo(folderId)); - Assert.That(itemRetrieved.InvType, Is.EqualTo(invType)); - Assert.That(itemRetrieved.AssetType, Is.EqualTo(assetType)); - Assert.That(itemRetrieved.Name, Is.EqualTo(itemName)); - } - - [Test] - public void TestUpdateItem() - { - TestHelpers.InMethod(); -// TestHelpers.EnableLogging(); - - string creatorId = TestHelpers.ParseTail(0x1).ToString(); - UUID ownerId = TestHelpers.ParseTail(0x2); - UUID itemId = TestHelpers.ParseTail(0x10); - UUID assetId = TestHelpers.ParseTail(0x20); - UUID folderId = TestHelpers.ParseTail(0x30); - int invType = (int)InventoryType.Animation; - int assetType = (int)AssetType.Animation; - string itemName = "item1"; - string itemName2 = "item2"; - - IInventoryService xis = CreateXInventoryService(); - - InventoryItemBase itemToStore - = new InventoryItemBase(itemId, ownerId) - { - CreatorIdentification = creatorId.ToString(), - AssetID = assetId, - Name = itemName, - Folder = folderId, - InvType = invType, - AssetType = assetType - }; - - Assert.That(xis.AddItem(itemToStore), Is.True); - - // Normal update - itemToStore.Name = itemName2; - - Assert.That(xis.UpdateItem(itemToStore), Is.True); - - InventoryItemBase itemRetrieved = xis.GetItem(UUID.Zero, itemId); - - Assert.That(itemRetrieved, Is.Not.Null); - Assert.That(itemRetrieved.Name, Is.EqualTo(itemName2)); - - // Attempt to update properties that should never change - string creatorId2 = TestHelpers.ParseTail(0x7).ToString(); - UUID ownerId2 = TestHelpers.ParseTail(0x8); - UUID folderId2 = TestHelpers.ParseTail(0x70); - int invType2 = (int)InventoryType.CallingCard; - int assetType2 = (int)AssetType.CallingCard; - string itemName3 = "item3"; - - itemToStore.CreatorIdentification = creatorId2.ToString(); - itemToStore.Owner = ownerId2; - itemToStore.Folder = folderId2; - itemToStore.InvType = invType2; - itemToStore.AssetType = assetType2; - itemToStore.Name = itemName3; - - Assert.That(xis.UpdateItem(itemToStore), Is.True); - - itemRetrieved = xis.GetItem(itemRetrieved.Owner, itemRetrieved.ID); - - Assert.That(itemRetrieved, Is.Not.Null); - Assert.That(itemRetrieved.CreatorId, Is.EqualTo(creatorId)); - Assert.That(itemRetrieved.Owner, Is.EqualTo(ownerId)); - Assert.That(itemRetrieved.AssetID, Is.EqualTo(assetId)); - Assert.That(itemRetrieved.Folder, Is.EqualTo(folderId)); - Assert.That(itemRetrieved.InvType, Is.EqualTo(invType)); - Assert.That(itemRetrieved.AssetType, Is.EqualTo(assetType)); - Assert.That(itemRetrieved.Name, Is.EqualTo(itemName3)); - } - } -} diff --git a/OpenSim/Services/SimulationService/OpenSim.Services.SimulationService.csproj b/OpenSim/Services/SimulationService/OpenSim.Services.SimulationService.csproj index 22d138f12eb..217a2157386 100644 --- a/OpenSim/Services/SimulationService/OpenSim.Services.SimulationService.csproj +++ b/OpenSim/Services/SimulationService/OpenSim.Services.SimulationService.csproj @@ -23,9 +23,6 @@ ..\..\..\bin\OpenMetaverseTypes.dll False - - False - False @@ -41,4 +38,4 @@ - \ No newline at end of file + diff --git a/OpenSim/Tests/Clients/Assets/AssetsClient.cs b/OpenSim/Tests/Clients/Assets/AssetsClient.cs deleted file mode 100644 index d6731ed81ab..00000000000 --- a/OpenSim/Tests/Clients/Assets/AssetsClient.cs +++ /dev/null @@ -1,124 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections.Generic; -using System.Net; -using System.Text; -using System.Reflection; -using System.Threading; - -using OpenMetaverse; -using log4net; -using log4net.Appender; -using log4net.Layout; - -using OpenSim.Framework; -using OpenSim.Services.Interfaces; -using OpenSim.Services.Connectors; - -namespace OpenSim.Tests.Clients.AssetsClient -{ - public class AssetsClient - { - private static readonly ILog m_log = - LogManager.GetLogger( - MethodBase.GetCurrentMethod().DeclaringType); - - private static int m_MaxThreadID = 0; - private static readonly int NREQS = 150; - private static int m_NReceived = 0; - - public static void Main(string[] args) - { - ConsoleAppender consoleAppender = new ConsoleAppender(); - consoleAppender.Layout = - new PatternLayout("[%thread] - %message%newline"); - log4net.Config.BasicConfigurator.Configure(consoleAppender); - - string serverURI = "http://127.0.0.1:8003"; - if (args.Length > 1) - serverURI = args[1]; - int max1, max2; - ThreadPool.GetMaxThreads(out max1, out max2); - m_log.InfoFormat("[ASSET CLIENT]: Connecting to {0} max threads = {1} - {2}", serverURI, max1, max2); - ThreadPool.GetMinThreads(out max1, out max2); - m_log.InfoFormat("[ASSET CLIENT]: Connecting to {0} min threads = {1} - {2}", serverURI, max1, max2); - - if (!ThreadPool.SetMinThreads(1, 1)) - m_log.WarnFormat("[ASSET CLIENT]: Failed to set min threads"); - - if (!ThreadPool.SetMaxThreads(10, 3)) - m_log.WarnFormat("[ASSET CLIENT]: Failed to set max threads"); - - ThreadPool.GetMaxThreads(out max1, out max2); - m_log.InfoFormat("[ASSET CLIENT]: Post set max threads = {1} - {2}", serverURI, max1, max2); - ThreadPool.GetMinThreads(out max1, out max2); - m_log.InfoFormat("[ASSET CLIENT]: Post set min threads = {1} - {2}", serverURI, max1, max2); - - AssetServicesConnector m_Connector = new AssetServicesConnector(serverURI); - m_Connector.MaxAssetRequestConcurrency = 30; - - for (int i = 0; i < NREQS; i++) - { - UUID uuid = UUID.Random(); - m_Connector.Get(uuid.ToString(), null, ResponseReceived); - m_log.InfoFormat("[ASSET CLIENT]: [{0}] requested asset {1}", i, uuid); - } - - for (int i = 0; i < 500; i++) - { - var x = i; - ThreadPool.QueueUserWorkItem(delegate - { - Dummy(x); - }); - } - - Thread.Sleep(30 * 1000); - m_log.InfoFormat("[ASSET CLIENT]: Received responses {0}", m_NReceived); - } - - private static void ResponseReceived(string id, Object sender, AssetBase asset) - { - if (Thread.CurrentThread.ManagedThreadId > m_MaxThreadID) - m_MaxThreadID = Thread.CurrentThread.ManagedThreadId; - int max1, max2; - ThreadPool.GetAvailableThreads(out max1, out max2); - m_log.InfoFormat("[ASSET CLIENT]: Received asset {0} ({1}) ({2}-{3}) {4}", id, m_MaxThreadID, max1, max2, DateTime.Now.ToString("hh:mm:ss")); - m_NReceived++; - } - - private static void Dummy(int i) - { - int max1, max2; - ThreadPool.GetAvailableThreads(out max1, out max2); - m_log.InfoFormat("[ASSET CLIENT]: ({0}) Hello! {1} - {2} {3}", i, max1, max2, DateTime.Now.ToString("hh:mm:ss")); - Thread.Sleep(2000); - } - } -} diff --git a/OpenSim/Tests/Clients/Assets/OpenSim.Tests.Clients.AssetClient.csproj b/OpenSim/Tests/Clients/Assets/OpenSim.Tests.Clients.AssetClient.csproj deleted file mode 100644 index 9b186df6f80..00000000000 --- a/OpenSim/Tests/Clients/Assets/OpenSim.Tests.Clients.AssetClient.csproj +++ /dev/null @@ -1,30 +0,0 @@ - - - net8.0 - Exe - - - - - - - - - ..\..\..\..\bin\Nini.dll - False - - - ..\..\..\..\bin\OpenMetaverse.dll - False - - - ..\..\..\..\bin\OpenMetaverseTypes.dll - False - - - - - - - - \ No newline at end of file diff --git a/OpenSim/Tests/Clients/Grid/GridClient.cs b/OpenSim/Tests/Clients/Grid/GridClient.cs deleted file mode 100644 index 7d3aee31380..00000000000 --- a/OpenSim/Tests/Clients/Grid/GridClient.cs +++ /dev/null @@ -1,205 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections.Generic; -using System.Text; -using System.Reflection; - -using OpenMetaverse; -using log4net; -using log4net.Appender; -using log4net.Layout; - -using OpenSim.Framework; -using OpenSim.Services.Interfaces; -using GridRegion = OpenSim.Services.Interfaces.GridRegion; -using OpenSim.Services.Connectors; - -namespace OpenSim.Tests.Clients.GridClient -{ - public class GridClient - { -// private static readonly ILog m_log = -// LogManager.GetLogger( -// MethodBase.GetCurrentMethod().DeclaringType); - - public static void Main(string[] args) - { - ConsoleAppender consoleAppender = new ConsoleAppender(); - consoleAppender.Layout = - new PatternLayout("%date [%thread] %-5level %logger [%property{NDC}] - %message%newline"); - log4net.Config.BasicConfigurator.Configure(consoleAppender); - - string serverURI = "http://127.0.0.1:8001"; - GridServicesConnector m_Connector = new GridServicesConnector(serverURI); - - GridRegion r1 = CreateRegion("Test Region 1", 1000, 1000); - GridRegion r2 = CreateRegion("Test Region 2", 1001, 1000); - GridRegion r3 = CreateRegion("Test Region 3", 1005, 1000); - - Console.WriteLine("[GRID CLIENT]: *** Registering region 1"); - string msg = m_Connector.RegisterRegion(UUID.Zero, r1); - if (msg == String.Empty) - Console.WriteLine("[GRID CLIENT]: Successfully registered region 1"); - else - Console.WriteLine("[GRID CLIENT]: region 1 failed to register"); - - Console.WriteLine("[GRID CLIENT]: *** Registering region 2"); - msg = m_Connector.RegisterRegion(UUID.Zero, r2); - if (msg == String.Empty) - Console.WriteLine("[GRID CLIENT]: Successfully registered region 2"); - else - Console.WriteLine("[GRID CLIENT]: region 2 failed to register"); - - Console.WriteLine("[GRID CLIENT]: *** Registering region 3"); - msg = m_Connector.RegisterRegion(UUID.Zero, r3); - if (msg == String.Empty) - Console.WriteLine("[GRID CLIENT]: Successfully registered region 3"); - else - Console.WriteLine("[GRID CLIENT]: region 3 failed to register"); - - - bool success; - Console.WriteLine("[GRID CLIENT]: *** Deregistering region 3"); - success = m_Connector.DeregisterRegion(r3.RegionID); - if (success) - Console.WriteLine("[GRID CLIENT]: Successfully deregistered region 3"); - else - Console.WriteLine("[GRID CLIENT]: region 3 failed to deregister"); - Console.WriteLine("[GRID CLIENT]: *** Registering region 3 again"); - msg = m_Connector.RegisterRegion(UUID.Zero, r3); - if (msg == String.Empty) - Console.WriteLine("[GRID CLIENT]: Successfully registered region 3"); - else - Console.WriteLine("[GRID CLIENT]: region 3 failed to register"); - - Console.WriteLine("[GRID CLIENT]: *** GetNeighbours of region 1"); - List regions = m_Connector.GetNeighbours(UUID.Zero, r1.RegionID); - if (regions == null) - Console.WriteLine("[GRID CLIENT]: GetNeighbours of region 1 failed"); - else if (regions.Count > 0) - { - if (regions.Count != 1) - Console.WriteLine("[GRID CLIENT]: GetNeighbours of region 1 returned more neighbours than expected: " + regions.Count); - else - Console.WriteLine("[GRID CLIENT]: GetNeighbours of region 1 returned the right neighbour " + regions[0].RegionName); - } - else - Console.WriteLine("[GRID CLIENT]: GetNeighbours of region 1 returned 0 neighbours"); - - - Console.WriteLine("[GRID CLIENT]: *** GetRegionByUUID of region 2 (this should succeed)"); - GridRegion region = m_Connector.GetRegionByUUID(UUID.Zero, r2.RegionID); - if (region == null) - Console.WriteLine("[GRID CLIENT]: GetRegionByUUID returned null"); - else - Console.WriteLine("[GRID CLIENT]: GetRegionByUUID returned region " + region.RegionName); - - Console.WriteLine("[GRID CLIENT]: *** GetRegionByUUID of non-existent region (this should fail)"); - region = m_Connector.GetRegionByUUID(UUID.Zero, UUID.Random()); - if (region == null) - Console.WriteLine("[GRID CLIENT]: GetRegionByUUID returned null"); - else - Console.WriteLine("[GRID CLIENT]: GetRegionByUUID returned region " + region.RegionName); - - Console.WriteLine("[GRID CLIENT]: *** GetRegionByName of region 3 (this should succeed)"); - region = m_Connector.GetRegionByName(UUID.Zero, r3.RegionName); - if (region == null) - Console.WriteLine("[GRID CLIENT]: GetRegionByName returned null"); - else - Console.WriteLine("[GRID CLIENT]: GetRegionByName returned region " + region.RegionName); - - Console.WriteLine("[GRID CLIENT]: *** GetRegionByName of non-existent region (this should fail)"); - region = m_Connector.GetRegionByName(UUID.Zero, "Foo"); - if (region == null) - Console.WriteLine("[GRID CLIENT]: GetRegionByName returned null"); - else - Console.WriteLine("[GRID CLIENT]: GetRegionByName returned region " + region.RegionName); - - Console.WriteLine("[GRID CLIENT]: *** GetRegionsByName (this should return 3 regions)"); - regions = m_Connector.GetRegionsByName(UUID.Zero, "Test", 10); - if (regions == null) - Console.WriteLine("[GRID CLIENT]: GetRegionsByName returned null"); - else - Console.WriteLine("[GRID CLIENT]: GetRegionsByName returned " + regions.Count + " regions"); - - Console.WriteLine("[GRID CLIENT]: *** GetRegionRange (this should return 2 regions)"); - regions = m_Connector.GetRegionRange(UUID.Zero, - (int)Util.RegionToWorldLoc(900), (int)Util.RegionToWorldLoc(1002), - (int)Util.RegionToWorldLoc(900), (int)Util.RegionToWorldLoc(1002) ); - if (regions == null) - Console.WriteLine("[GRID CLIENT]: GetRegionRange returned null"); - else - Console.WriteLine("[GRID CLIENT]: GetRegionRange returned " + regions.Count + " regions"); - Console.WriteLine("[GRID CLIENT]: *** GetRegionRange (this should return 0 regions)"); - regions = m_Connector.GetRegionRange(UUID.Zero, - (int)Util.RegionToWorldLoc(900), (int)Util.RegionToWorldLoc(950), - (int)Util.RegionToWorldLoc(900), (int)Util.RegionToWorldLoc(950) ); - if (regions == null) - Console.WriteLine("[GRID CLIENT]: GetRegionRange returned null"); - else - Console.WriteLine("[GRID CLIENT]: GetRegionRange returned " + regions.Count + " regions"); - - Console.Write("Proceed to deregister? Press enter..."); - Console.ReadLine(); - - // Deregister them all - Console.WriteLine("[GRID CLIENT]: *** Deregistering region 1"); - success = m_Connector.DeregisterRegion(r1.RegionID); - if (success) - Console.WriteLine("[GRID CLIENT]: Successfully deregistered region 1"); - else - Console.WriteLine("[GRID CLIENT]: region 1 failed to deregister"); - Console.WriteLine("[GRID CLIENT]: *** Deregistering region 2"); - success = m_Connector.DeregisterRegion(r2.RegionID); - if (success) - Console.WriteLine("[GRID CLIENT]: Successfully deregistered region 2"); - else - Console.WriteLine("[GRID CLIENT]: region 2 failed to deregister"); - Console.WriteLine("[GRID CLIENT]: *** Deregistering region 3"); - success = m_Connector.DeregisterRegion(r3.RegionID); - if (success) - Console.WriteLine("[GRID CLIENT]: Successfully deregistered region 3"); - else - Console.WriteLine("[GRID CLIENT]: region 3 failed to deregister"); - - } - - private static GridRegion CreateRegion(string name, uint xcell, uint ycell) - { - GridRegion region = new GridRegion(xcell, ycell); - region.RegionName = name; - region.RegionID = UUID.Random(); - region.ExternalHostName = "127.0.0.1"; - region.HttpPort = 9000; - region.InternalEndPoint = new System.Net.IPEndPoint(System.Net.IPAddress.Parse("0.0.0.0"), 9000); - - return region; - } - } -} diff --git a/OpenSim/Tests/Common/ANumericalToleranceConstraint.cs b/OpenSim/Tests/Common/ANumericalToleranceConstraint.cs deleted file mode 100644 index 15c88021fcf..00000000000 --- a/OpenSim/Tests/Common/ANumericalToleranceConstraint.cs +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using NUnit.Framework.Constraints; - -namespace OpenSim.Tests.Common -{ - public abstract class ANumericalToleranceConstraint : Constraint - { - protected double _tolerance; - - public ANumericalToleranceConstraint(double tolerance) - { - if (tolerance < 0) - { - throw new ArgumentException("Tolerance cannot be negative."); - } - _tolerance = tolerance; - } - - protected bool IsWithinDoubleConstraint(double doubleValue, double baseValue) - { - if (doubleValue >= baseValue - _tolerance && doubleValue <= baseValue + _tolerance) - { - return true; - } - - return false; - } - } -} diff --git a/OpenSim/Tests/Common/DatabaseTestAttribute.cs b/OpenSim/Tests/Common/DatabaseTestAttribute.cs deleted file mode 100644 index d6a03cd6883..00000000000 --- a/OpenSim/Tests/Common/DatabaseTestAttribute.cs +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections.Generic; -using System.Text; -using NUnit.Framework; - -namespace OpenSim.Tests.Common -{ - [AttributeUsage(AttributeTargets.All, - AllowMultiple=false, - Inherited=true)] - public class DatabaseTestAttribute : LongRunningAttribute - { - public DatabaseTestAttribute() : base("Database") - { - } - } -} \ No newline at end of file diff --git a/OpenSim/Tests/Common/DoubleToleranceConstraint.cs b/OpenSim/Tests/Common/DoubleToleranceConstraint.cs deleted file mode 100644 index b2f20571ae4..00000000000 --- a/OpenSim/Tests/Common/DoubleToleranceConstraint.cs +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using NUnit.Framework; -using NUnit.Framework.Constraints; - -namespace OpenSim.Tests.Common -{ - public class DoubleToleranceConstraint : ANumericalToleranceConstraint - { - private double _baseValue; - private double _valueToBeTested; - - public DoubleToleranceConstraint(double baseValue, double tolerance) : base(tolerance) - { - _baseValue = baseValue; - } - - /// - ///Test whether the constraint is satisfied by a given value - /// - ///The value to be tested - /// - ///True for success, false for failure - /// - public override bool Matches(object valueToBeTested) - { - if (valueToBeTested == null) - { - throw new ArgumentException("Constraint cannot be used upon null values."); - } - if (valueToBeTested.GetType() != typeof(double)) - { - throw new ArgumentException("Constraint cannot be used upon non double-values."); - } - - _valueToBeTested = (double)valueToBeTested; - - return IsWithinDoubleConstraint(_valueToBeTested, _baseValue); - } - - public override void WriteDescriptionTo(MessageWriter writer) - { - writer.WriteExpectedValue(string.Format("A value {0} within tolerance of plus or minus {1}",_baseValue,_tolerance)); - } - - public override void WriteActualValueTo(MessageWriter writer) - { - writer.WriteActualValue(_valueToBeTested); - } - } -} diff --git a/OpenSim/Tests/Common/Helpers/AssetHelpers.cs b/OpenSim/Tests/Common/Helpers/AssetHelpers.cs deleted file mode 100644 index 974da4ca2bd..00000000000 --- a/OpenSim/Tests/Common/Helpers/AssetHelpers.cs +++ /dev/null @@ -1,168 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System.Text; -using OpenMetaverse; -using OpenMetaverse.Assets; -using OpenSim.Framework; -using OpenSim.Region.Framework.Scenes; -using OpenSim.Region.Framework.Scenes.Serialization; -using OpenSim.Services.Interfaces; - -namespace OpenSim.Tests.Common -{ - public class AssetHelpers - { - /// - /// Create a notecard asset with a random uuids and dummy text. - /// - /// - public static AssetBase CreateNotecardAsset() - { - return CreateNotecardAsset(UUID.Random()); - } - - /// - /// Create a notecard asset with dummy text and a random owner. - /// - /// /param> - /// - public static AssetBase CreateNotecardAsset(UUID assetId) - { - return CreateNotecardAsset(assetId, "hello"); - } - - /// - /// Create a notecard asset with a random owner. - /// - /// /param> - /// - /// - public static AssetBase CreateNotecardAsset(UUID assetId, string text) - { - return CreateAsset(assetId, AssetType.Notecard, text, UUID.Random()); - } - -// /// -// /// Create and store a notecard asset with a random uuid and dummy text. -// /// -// /// /param> -// /// -// public static AssetBase CreateNotecardAsset(Scene scene, UUID creatorId) -// { -// AssetBase asset = CreateAsset(UUID.Random(), AssetType.Notecard, "hello", creatorId); -// scene.AssetService.Store(asset); -// return asset; -// } - - /// - /// Create an asset from the given object. - /// - /// - /// The hexadecimal last part of the UUID for the asset created. A UUID of the form "00000000-0000-0000-0000-{0:XD12}" - /// will be used. - /// - /// - /// - public static AssetBase CreateAsset(int assetUuidTail, SceneObjectGroup sog) - { - return CreateAsset(new UUID(string.Format("00000000-0000-0000-0000-{0:X12}", assetUuidTail)), sog); - } - - /// - /// Create an asset from the given object. - /// - /// - /// - /// - public static AssetBase CreateAsset(UUID assetUuid, SceneObjectGroup sog) - { - return CreateAsset( - assetUuid, - AssetType.Object, - Encoding.ASCII.GetBytes(SceneObjectSerializer.ToOriginalXmlFormat(sog)), - sog.OwnerID); - } - - /// - /// Create an asset from the given scene object. - /// - /// - /// The hexadecimal last part of the UUID for the asset created. A UUID of the form "00000000-0000-0000-0000-{0:XD12}" - /// will be used. - /// - /// - /// - public static AssetBase CreateAsset(int assetUuidTail, CoalescedSceneObjects coa) - { - return CreateAsset(new UUID(string.Format("00000000-0000-0000-0000-{0:X12}", assetUuidTail)), coa); - } - - /// - /// Create an asset from the given scene object. - /// - /// - /// - /// - public static AssetBase CreateAsset(UUID assetUuid, CoalescedSceneObjects coa) - { - return CreateAsset( - assetUuid, - AssetType.Object, - Encoding.ASCII.GetBytes(CoalescedSceneObjectsSerializer.ToXml(coa)), - coa.CreatorId); - } - - /// - /// Create an asset from the given data. - /// - public static AssetBase CreateAsset(UUID assetUuid, AssetType assetType, string text, UUID creatorID) - { - AssetNotecard anc = new AssetNotecard(); - anc.BodyText = text; - anc.Encode(); - - return CreateAsset(assetUuid, assetType, anc.AssetData, creatorID); - } - - /// - /// Create an asset from the given data. - /// - public static AssetBase CreateAsset(UUID assetUuid, AssetType assetType, byte[] data, UUID creatorID) - { - AssetBase asset = new AssetBase(assetUuid, assetUuid.ToString(), (sbyte)assetType, creatorID.ToString()); - asset.Data = data; - return asset; - } - - public static string ReadAssetAsString(IAssetService assetService, UUID uuid) - { - byte[] assetData = assetService.GetData(uuid.ToString()); - return Encoding.ASCII.GetString(assetData); - } - } -} diff --git a/OpenSim/Tests/Common/Helpers/BaseRequestHandlerHelpers.cs b/OpenSim/Tests/Common/Helpers/BaseRequestHandlerHelpers.cs deleted file mode 100644 index b27c7197801..00000000000 --- a/OpenSim/Tests/Common/Helpers/BaseRequestHandlerHelpers.cs +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections.Generic; -using System.Text; -using NUnit.Framework; -using OpenSim.Framework; -using OpenSim.Framework.Servers; -using OpenSim.Framework.Servers.HttpServer; - -namespace OpenSim.Tests.Common -{ - public class BaseRequestHandlerHelpers - { - private static string[] m_emptyStringArray = new string[] { }; - - public static void BaseTestGetParams(BaseRequestHandler handler, string assetsPath) - { - Assert.AreEqual(String.Empty, handler.GetParam(null), "Failed on null path."); - Assert.AreEqual(String.Empty, handler.GetParam(""), "Failed on empty path."); - Assert.AreEqual(String.Empty, handler.GetParam("s"), "Failed on short url."); - Assert.AreEqual(String.Empty, handler.GetParam("corruptUrl"), "Failed on corruptUrl."); - - Assert.AreEqual(String.Empty, handler.GetParam(assetsPath)); - Assert.AreEqual("/", handler.GetParam(assetsPath + "/")); - Assert.AreEqual("/a", handler.GetParam(assetsPath + "/a")); - Assert.AreEqual("/b/", handler.GetParam(assetsPath + "/b/")); - Assert.AreEqual("/c/d", handler.GetParam(assetsPath + "/c/d")); - Assert.AreEqual("/e/f/", handler.GetParam(assetsPath + "/e/f/")); - } - - public static void BaseTestSplitParams(BaseRequestHandler handler, string assetsPath) - { - Assert.AreEqual(m_emptyStringArray, handler.SplitParams(null), "Failed on null."); - Assert.AreEqual(m_emptyStringArray, handler.SplitParams(""), "Failed on empty path."); - Assert.AreEqual(m_emptyStringArray, handler.SplitParams("corruptUrl"), "Failed on corrupt url."); - - Assert.AreEqual(m_emptyStringArray, handler.SplitParams(assetsPath), "Failed on empty params."); - Assert.AreEqual(m_emptyStringArray, handler.SplitParams(assetsPath + "/"), "Failed on single slash."); - - Assert.AreEqual(new string[] { "a" }, handler.SplitParams(assetsPath + "/a"), "Failed on first segment."); - Assert.AreEqual(new string[] { "b" }, handler.SplitParams(assetsPath + "/b/"), "Failed on second slash."); - Assert.AreEqual(new string[] { "c", "d" }, handler.SplitParams(assetsPath + "/c/d"), "Failed on second segment."); - Assert.AreEqual(new string[] { "e", "f" }, handler.SplitParams(assetsPath + "/e/f/"), "Failed on trailing slash."); - } - - public static byte[] EmptyByteArray = new byte[] {}; - - } -} diff --git a/OpenSim/Tests/Common/Helpers/ClientStackHelpers.cs b/OpenSim/Tests/Common/Helpers/ClientStackHelpers.cs deleted file mode 100644 index cfb776b2467..00000000000 --- a/OpenSim/Tests/Common/Helpers/ClientStackHelpers.cs +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Net; -using Nini.Config; -using OpenMetaverse; -using OpenMetaverse.Packets; -using OpenSim.Framework; -using OpenSim.Region.ClientStack.LindenUDP; -using OpenSim.Region.Framework.Scenes; - -namespace OpenSim.Tests.Common -{ - /// - /// This class adds full UDP client classes and associated scene presence to scene. - /// - /// - /// This is used for testing client stack code. For testing other code, use SceneHelper methods instead since - /// they operate without the burden of setting up UDP structures which should be unnecessary for testing scene - /// code. - /// - public static class ClientStackHelpers - { - public static ScenePresence AddChildClient( - Scene scene, LLUDPServer udpServer, UUID agentId, UUID sessionId, uint circuitCode) - { - IPEndPoint testEp = new IPEndPoint(IPAddress.Loopback, 999); - - UseCircuitCodePacket uccp = new UseCircuitCodePacket(); - - UseCircuitCodePacket.CircuitCodeBlock uccpCcBlock - = new UseCircuitCodePacket.CircuitCodeBlock(); - uccpCcBlock.Code = circuitCode; - uccpCcBlock.ID = agentId; - uccpCcBlock.SessionID = sessionId; - uccp.CircuitCode = uccpCcBlock; - - byte[] uccpBytes = uccp.ToBytes(); - UDPPacketBuffer upb = new UDPPacketBuffer(testEp, uccpBytes.Length); - upb.DataLength = uccpBytes.Length; // God knows why this isn't set by the constructor. - Buffer.BlockCopy(uccpBytes, 0, upb.Data, 0, uccpBytes.Length); - - AgentCircuitData acd = new AgentCircuitData(); - acd.AgentID = agentId; - acd.SessionID = sessionId; - - scene.AuthenticateHandler.AddNewCircuit(circuitCode, acd); - - udpServer.PacketReceived(upb); - - return scene.GetScenePresence(agentId); - } - - public static TestLLUDPServer AddUdpServer(Scene scene) - { - return AddUdpServer(scene, new IniConfigSource()); - } - - public static TestLLUDPServer AddUdpServer(Scene scene, IniConfigSource configSource) - { - uint port = 0; - AgentCircuitManager acm = scene.AuthenticateHandler; - - TestLLUDPServer udpServer = new TestLLUDPServer(IPAddress.Any, port, 0, configSource, acm); - udpServer.AddScene(scene); - - return udpServer; - } - } -} diff --git a/OpenSim/Tests/Common/Helpers/EntityTransferHelpers.cs b/OpenSim/Tests/Common/Helpers/EntityTransferHelpers.cs deleted file mode 100644 index b0c9596665d..00000000000 --- a/OpenSim/Tests/Common/Helpers/EntityTransferHelpers.cs +++ /dev/null @@ -1,123 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections.Generic; -using System.IO; -using System.Net; -using System.Reflection; -using System.Text; -using System.Threading; -using log4net; -using Nini.Config; -using NUnit.Framework; -using OpenMetaverse; -using OpenSim.Framework; - -using OpenSim.Framework.Servers; -using OpenSim.Region.Framework.Interfaces; -using OpenSim.Region.Framework.Scenes; -using OpenSim.Region.CoreModules.Framework; -using OpenSim.Tests.Common; - -namespace OpenSim.Tests.Common -{ - public static class EntityTransferHelpers - { - private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - - /// - /// Set up correct handling of the InformClientOfNeighbour call from the source region that triggers the - /// viewer to setup a connection with the destination region. - /// - /// - /// - /// A list that will be populated with any TestClients set up in response to - /// being informed about a destination region. - /// - public static void SetupInformClientOfNeighbourTriggersNeighbourClientCreate( - TestClient tc, List neighbourTcs) - { - // XXX: Confusingly, this is also used for non-neighbour notification (as in teleports that do not use the - // event queue). - - tc.OnTestClientInformClientOfNeighbour += (neighbourHandle, neighbourExternalEndPoint) => - { - uint x, y; - Util.RegionHandleToRegionLoc(neighbourHandle, out x, out y); - - m_log.DebugFormat( - "[TEST CLIENT]: Processing inform client of neighbour located at {0},{1} at {2}", - x, y, neighbourExternalEndPoint); - - AgentCircuitData newAgent = tc.RequestClientInfo(); - - Scene neighbourScene; - SceneManager.Instance.TryGetScene(x, y, out neighbourScene); - - TestClient neighbourTc = new TestClient(newAgent, neighbourScene); - neighbourTcs.Add(neighbourTc); - neighbourScene.AddNewAgent(neighbourTc, PresenceType.User); - }; - } - - /// - /// Set up correct handling of the InformClientOfNeighbour call from the source region that triggers the - /// viewer to setup a connection with the destination region. - /// - /// - /// - /// A list that will be populated with any TestClients set up in response to - /// being informed about a destination region. - /// - public static void SetupSendRegionTeleportTriggersDestinationClientCreateAndCompleteMovement( - TestClient client, List destinationClients) - { - client.OnTestClientSendRegionTeleport - += (regionHandle, simAccess, regionExternalEndPoint, locationID, flags, capsURL) => - { - uint x, y; - Util.RegionHandleToRegionLoc(regionHandle, out x, out y); - - m_log.DebugFormat( - "[TEST CLIENT]: Processing send region teleport for destination at {0},{1} at {2}", - x, y, regionExternalEndPoint); - - AgentCircuitData newAgent = client.RequestClientInfo(); - - Scene destinationScene; - SceneManager.Instance.TryGetScene(x, y, out destinationScene); - - TestClient destinationClient = new TestClient(newAgent, destinationScene); - destinationClients.Add(destinationClient); - destinationScene.AddNewAgent(destinationClient, PresenceType.User); - - ThreadPool.UnsafeQueueUserWorkItem(o => destinationClient.CompleteMovement(), null); - }; - } - } -} diff --git a/OpenSim/Tests/Common/Helpers/SceneHelpers.cs b/OpenSim/Tests/Common/Helpers/SceneHelpers.cs deleted file mode 100644 index 60b9732ab8e..00000000000 --- a/OpenSim/Tests/Common/Helpers/SceneHelpers.cs +++ /dev/null @@ -1,739 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Net; -using System.Collections.Generic; -using Nini.Config; -using OpenMetaverse; -using OpenSim.Data.Null; -using OpenSim.Framework; - -using OpenSim.Framework.Console; -using OpenSim.Region.PhysicsModules.SharedBase; -using OpenSim.Region.Framework.Interfaces; -using OpenSim.Region.Framework.Scenes; -using OpenSim.Region.CoreModules.Avatar.Gods; -using OpenSim.Region.CoreModules.ServiceConnectorsOut.Asset; -using OpenSim.Region.CoreModules.ServiceConnectorsOut.Authentication; -using OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory; -using OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid; -using OpenSim.Region.CoreModules.ServiceConnectorsOut.UserAccounts; -using OpenSim.Region.CoreModules.ServiceConnectorsOut.Presence; -using OpenSim.Region.PhysicsModule.BasicPhysics; -using OpenSim.Services.Interfaces; -using OpenSim.Server.Base; - -using BaseServerUtils = OpenSim.Server.Base.ServerUtils; - -namespace OpenSim.Tests.Common -{ - /// - /// Helpers for setting up scenes. - /// - public class SceneHelpers - { - /// - /// We need a scene manager so that test clients can retrieve a scene when performing teleport tests. - /// - public SceneManager SceneManager { get; private set; } - - public ISimulationDataService SimDataService { get; private set; } - - private AgentCircuitManager m_acm = new AgentCircuitManager(); - private IEstateDataService m_estateDataService = null; - - private LocalAssetServicesConnector m_assetService; - private LocalAuthenticationServicesConnector m_authenticationService; - private LocalInventoryServicesConnector m_inventoryService; - private RegionGridServicesConnector m_gridService; - private LocalUserAccountServicesConnector m_userAccountService; - private LocalPresenceServicesConnector m_presenceService; - - private TestsAssetCache m_cache; - - private PhysicsScene m_physicsScene; - - public SceneHelpers() : this(null) {} - - public SceneHelpers(TestsAssetCache cache) - { - SceneManager = new SceneManager(); - - m_assetService = StartAssetService(cache); - m_authenticationService = StartAuthenticationService(); - m_inventoryService = StartInventoryService(); - m_gridService = StartGridService(); - m_userAccountService = StartUserAccountService(); - m_presenceService = StartPresenceService(); - - m_inventoryService.PostInitialise(); - m_assetService.PostInitialise(); - m_userAccountService.PostInitialise(); - m_presenceService.PostInitialise(); - - m_cache = cache; - - m_physicsScene = StartPhysicsScene(); - - SimDataService = BaseServerUtils.LoadPlugin("OpenSim.Tests.Common.dll", null); - } - - /// - /// Set up a test scene - /// - /// - /// Automatically starts services, as would the normal runtime. - /// - /// - public TestScene SetupScene() - { - return SetupScene("Unit test region", UUID.Random(), 1000, 1000); - } - - public TestScene SetupScene(string name, UUID id, uint x, uint y) - { - return SetupScene(name, id, x, y, new IniConfigSource()); - } - - public TestScene SetupScene(string name, UUID id, uint x, uint y, IConfigSource configSource) - { - return SetupScene(name, id, x, y, Constants.RegionSize, Constants.RegionSize, configSource); - } - - /// - /// Set up a scene. - /// - /// Name of the region - /// ID of the region - /// X co-ordinate of the region - /// Y co-ordinate of the region - /// X size of scene - /// Y size of scene - /// - /// - public TestScene SetupScene( - string name, UUID id, uint x, uint y, uint sizeX, uint sizeY, IConfigSource configSource) - { - Console.WriteLine("Setting up test scene {0}", name); - - // We must set up a console otherwise setup of some modules may fail - MainConsole.Instance = new MockConsole(); - - RegionInfo regInfo = new RegionInfo(x, y, new IPEndPoint(IPAddress.Loopback, 9000), "127.0.0.1"); - regInfo.RegionName = name; - regInfo.RegionID = id; - regInfo.RegionSizeX = sizeX; - regInfo.RegionSizeY = sizeY; - regInfo.ServerURI = "http://127.0.0.1:9000/"; - - - TestScene testScene = new TestScene( - regInfo, m_acm, SimDataService, m_estateDataService, configSource, null); - - testScene.RegionInfo.EstateSettings = new EstateSettings(); - testScene.RegionInfo.EstateSettings.EstateOwner = UUID.Random(); - - INonSharedRegionModule godsModule = new GodsModule(); - godsModule.Initialise(new IniConfigSource()); - godsModule.AddRegion(testScene); - - // Add scene to physics - ((INonSharedRegionModule)m_physicsScene).AddRegion(testScene); - ((INonSharedRegionModule)m_physicsScene).RegionLoaded(testScene); - - // Add scene to services - m_assetService.AddRegion(testScene); - - if (m_cache != null) - { - m_cache.AddRegion(testScene); - m_cache.RegionLoaded(testScene); - testScene.AddRegionModule(m_cache.Name, m_cache); - } - - m_assetService.RegionLoaded(testScene); - testScene.AddRegionModule(m_assetService.Name, m_assetService); - - m_authenticationService.AddRegion(testScene); - m_authenticationService.RegionLoaded(testScene); - testScene.AddRegionModule(m_authenticationService.Name, m_authenticationService); - - m_inventoryService.AddRegion(testScene); - m_inventoryService.RegionLoaded(testScene); - testScene.AddRegionModule(m_inventoryService.Name, m_inventoryService); - - m_gridService.AddRegion(testScene); - m_gridService.RegionLoaded(testScene); - testScene.AddRegionModule(m_gridService.Name, m_gridService); - - m_userAccountService.AddRegion(testScene); - m_userAccountService.RegionLoaded(testScene); - testScene.AddRegionModule(m_userAccountService.Name, m_userAccountService); - - m_presenceService.AddRegion(testScene); - m_presenceService.RegionLoaded(testScene); - testScene.AddRegionModule(m_presenceService.Name, m_presenceService); - - testScene.SetModuleInterfaces(); - - testScene.LandChannel = new TestLandChannel(testScene); - testScene.LoadWorldMap(); - - testScene.LoginsEnabled = true; - testScene.RegisterRegionWithGrid(); - - SceneManager.Add(testScene); - - return testScene; - } - - private static LocalAssetServicesConnector StartAssetService(TestsAssetCache cache) - { - IConfigSource config = new IniConfigSource(); - config.AddConfig("Modules"); - config.Configs["Modules"].Set("AssetServices", "LocalAssetServicesConnector"); - config.AddConfig("AssetService"); - config.Configs["AssetService"].Set("LocalServiceModule", "OpenSim.Services.AssetService.dll:AssetService"); - config.Configs["AssetService"].Set("StorageProvider", "OpenSim.Tests.Common.dll"); - - LocalAssetServicesConnector assetService = new LocalAssetServicesConnector(); - assetService.Initialise(config); - - if (cache != null) - { - IConfigSource cacheConfig = new IniConfigSource(); - cacheConfig.AddConfig("Modules"); - cacheConfig.Configs["Modules"].Set("AssetCaching", "TestsAssetCache"); - cacheConfig.AddConfig("AssetCache"); - - cache.Initialise(cacheConfig); - } - - return assetService; - } - - private static LocalAuthenticationServicesConnector StartAuthenticationService() - { - IConfigSource config = new IniConfigSource(); - config.AddConfig("Modules"); - config.AddConfig("AuthenticationService"); - config.Configs["Modules"].Set("AuthenticationServices", "LocalAuthenticationServicesConnector"); - config.Configs["AuthenticationService"].Set( - "LocalServiceModule", "OpenSim.Services.AuthenticationService.dll:PasswordAuthenticationService"); - config.Configs["AuthenticationService"].Set("StorageProvider", "OpenSim.Data.Null.dll"); - - LocalAuthenticationServicesConnector service = new LocalAuthenticationServicesConnector(); - service.Initialise(config); - - return service; - } - - private static LocalInventoryServicesConnector StartInventoryService() - { - IConfigSource config = new IniConfigSource(); - config.AddConfig("Modules"); - config.AddConfig("InventoryService"); - config.Configs["Modules"].Set("InventoryServices", "LocalInventoryServicesConnector"); - config.Configs["InventoryService"].Set("LocalServiceModule", "OpenSim.Services.InventoryService.dll:XInventoryService"); - config.Configs["InventoryService"].Set("StorageProvider", "OpenSim.Tests.Common.dll"); - - LocalInventoryServicesConnector inventoryService = new LocalInventoryServicesConnector(); - inventoryService.Initialise(config); - - return inventoryService; - } - - private static RegionGridServicesConnector StartGridService() - { - IConfigSource config = new IniConfigSource(); - config.AddConfig("Modules"); - config.AddConfig("GridService"); - config.Configs["Modules"].Set("GridServices", "RegionGridServicesConnector"); - config.Configs["GridService"].Set("StorageProvider", "OpenSim.Data.Null.dll:NullRegionData"); - config.Configs["GridService"].Set("LocalServiceModule", "OpenSim.Services.GridService.dll:GridService"); - config.Configs["GridService"].Set("ConnectionString", "!static"); - - RegionGridServicesConnector gridService = new RegionGridServicesConnector(); - gridService.Initialise(config); - - return gridService; - } - - /// - /// Start a user account service - /// - /// - /// - private static LocalUserAccountServicesConnector StartUserAccountService() - { - IConfigSource config = new IniConfigSource(); - config.AddConfig("Modules"); - config.AddConfig("UserAccountService"); - config.Configs["Modules"].Set("UserAccountServices", "LocalUserAccountServicesConnector"); - config.Configs["UserAccountService"].Set("StorageProvider", "OpenSim.Data.Null.dll"); - config.Configs["UserAccountService"].Set( - "LocalServiceModule", "OpenSim.Services.UserAccountService.dll:UserAccountService"); - - LocalUserAccountServicesConnector userAccountService = new LocalUserAccountServicesConnector(); - userAccountService.Initialise(config); - - return userAccountService; - } - - /// - /// Start a presence service - /// - /// - private static LocalPresenceServicesConnector StartPresenceService() - { - // Unfortunately, some services share data via statics, so we need to null every time to stop interference - // between tests. - // This is a massive non-obvious pita. - NullPresenceData.Instance = null; - - IConfigSource config = new IniConfigSource(); - config.AddConfig("Modules"); - config.AddConfig("PresenceService"); - config.Configs["Modules"].Set("PresenceServices", "LocalPresenceServicesConnector"); - config.Configs["PresenceService"].Set("StorageProvider", "OpenSim.Data.Null.dll"); - config.Configs["PresenceService"].Set( - "LocalServiceModule", "OpenSim.Services.PresenceService.dll:PresenceService"); - - LocalPresenceServicesConnector presenceService = new LocalPresenceServicesConnector(); - presenceService.Initialise(config); - - return presenceService; - } - - private static PhysicsScene StartPhysicsScene() - { - IConfigSource config = new IniConfigSource(); - config.AddConfig("Startup"); - config.Configs["Startup"].Set("physics", "basicphysics"); - - PhysicsScene pScene = new BasicScene(); - INonSharedRegionModule mod = pScene as INonSharedRegionModule; - mod.Initialise(config); - - return pScene; - } - - /// - /// Setup modules for a scene using their default settings. - /// - /// - /// - public static void SetupSceneModules(Scene scene, params object[] modules) - { - SetupSceneModules(scene, new IniConfigSource(), modules); - } - - /// - /// Setup modules for a scene. - /// - /// - /// If called directly, then all the modules must be shared modules. - /// - /// - /// - /// - public static void SetupSceneModules(Scene scene, IConfigSource config, params object[] modules) - { - SetupSceneModules(new Scene[] { scene }, config, modules); - } - - /// - /// Setup modules for a scene using their default settings. - /// - /// - /// - public static void SetupSceneModules(Scene[] scenes, params object[] modules) - { - SetupSceneModules(scenes, new IniConfigSource(), modules); - } - - /// - /// Setup modules for scenes. - /// - /// - /// If called directly, then all the modules must be shared modules. - /// - /// We are emulating here the normal calls made to setup region modules - /// (Initialise(), PostInitialise(), AddRegion, RegionLoaded()). - /// TODO: Need to reuse normal runtime module code. - /// - /// - /// - /// - public static void SetupSceneModules(Scene[] scenes, IConfigSource config, params object[] modules) - { - List newModules = new List(); - foreach (object module in modules) - { - IRegionModuleBase m = (IRegionModuleBase)module; -// Console.WriteLine("MODULE {0}", m.Name); - m.Initialise(config); - newModules.Add(m); - } - - foreach (IRegionModuleBase module in newModules) - { - if (module is ISharedRegionModule) ((ISharedRegionModule)module).PostInitialise(); - } - - foreach (IRegionModuleBase module in newModules) - { - foreach (Scene scene in scenes) - { - module.AddRegion(scene); - scene.AddRegionModule(module.Name, module); - } - } - - // RegionLoaded is fired after all modules have been appropriately added to all scenes - foreach (IRegionModuleBase module in newModules) - foreach (Scene scene in scenes) - module.RegionLoaded(scene); - - foreach (Scene scene in scenes) { scene.SetModuleInterfaces(); } - } - - /// - /// Generate some standard agent connection data. - /// - /// - /// - public static AgentCircuitData GenerateAgentData(UUID agentId) - { - AgentCircuitData acd = GenerateCommonAgentData(); - - acd.AgentID = agentId; - acd.firstname = "testfirstname"; - acd.lastname = "testlastname"; - acd.ServiceURLs = new Dictionary(); - - return acd; - } - - /// - /// Generate some standard agent connection data. - /// - /// - /// - public static AgentCircuitData GenerateAgentData(UserAccount ua) - { - AgentCircuitData acd = GenerateCommonAgentData(); - - acd.AgentID = ua.PrincipalID; - acd.firstname = ua.FirstName; - acd.lastname = ua.LastName; - acd.ServiceURLs = ua.ServiceURLs; - - return acd; - } - - private static AgentCircuitData GenerateCommonAgentData() - { - AgentCircuitData acd = new AgentCircuitData(); - - // XXX: Sessions must be unique, otherwise one presence can overwrite another in NullPresenceData. - acd.SessionID = UUID.Random(); - acd.SecureSessionID = UUID.Random(); - - acd.circuitcode = 123; - acd.BaseFolder = UUID.Zero; - acd.InventoryFolder = UUID.Zero; - acd.startpos = Vector3.Zero; - acd.CapsPath = "http://wibble.com"; - acd.Appearance = new AvatarAppearance(); - - return acd; - } - - /// - /// Add a root agent where the details of the agent connection (apart from the id) are unimportant for the test - /// - /// - /// XXX: Use the version of this method that takes the UserAccount structure wherever possible - this will - /// make the agent circuit data (e.g. first, lastname) consistent with the user account data. - /// - /// - /// - /// - public static ScenePresence AddScenePresence(Scene scene, UUID agentId) - { - return AddScenePresence(scene, GenerateAgentData(agentId)); - } - - /// - /// Add a root agent. - /// - /// - /// - /// - public static ScenePresence AddScenePresence(Scene scene, UserAccount ua) - { - return AddScenePresence(scene, GenerateAgentData(ua)); - } - - /// - /// Add a root agent. - /// - /// - /// This function - /// - /// 1) Tells the scene that an agent is coming. Normally, the login service (local if standalone, from the - /// userserver if grid) would give initial login data back to the client and separately tell the scene that the - /// agent was coming. - /// - /// 2) Connects the agent with the scene - /// - /// This function performs actions equivalent with notifying the scene that an agent is - /// coming and then actually connecting the agent to the scene. The one step missed out is the very first - /// - /// - /// - /// - public static ScenePresence AddScenePresence(Scene scene, AgentCircuitData agentData) - { - return AddScenePresence(scene, new TestClient(agentData, scene), agentData); - } - - /// - /// Add a root agent. - /// - /// - /// This function - /// - /// 1) Tells the scene that an agent is coming. Normally, the login service (local if standalone, from the - /// userserver if grid) would give initial login data back to the client and separately tell the scene that the - /// agent was coming. - /// - /// 2) Connects the agent with the scene - /// - /// This function performs actions equivalent with notifying the scene that an agent is - /// coming and then actually connecting the agent to the scene. The one step missed out is the very first - /// - /// - /// - /// - public static ScenePresence AddScenePresence( - Scene scene, IClientAPI client, AgentCircuitData agentData) - { - // We emulate the proper login sequence here by doing things in four stages - - // Stage 0: login - // We need to punch through to the underlying service because scene will not, correctly, let us call it - // through it's reference to the LPSC - LocalPresenceServicesConnector lpsc = (LocalPresenceServicesConnector)scene.PresenceService; - lpsc.m_PresenceService.LoginAgent(agentData.AgentID.ToString(), agentData.SessionID, agentData.SecureSessionID); - - // Stages 1 & 2 - ScenePresence sp = IntroduceClientToScene(scene, client, agentData, TeleportFlags.ViaLogin); - - // Stage 3: Complete the entrance into the region. This converts the child agent into a root agent. - sp.CompleteMovement(sp.ControllingClient, true); - - return sp; - } - - /// - /// Introduce an agent into the scene by adding a new client. - /// - /// The scene presence added - /// - /// - /// - /// - private static ScenePresence IntroduceClientToScene( - Scene scene, IClientAPI client, AgentCircuitData agentData, TeleportFlags tf) - { - string reason; - - // Stage 1: tell the scene to expect a new user connection - if (!scene.NewUserConnection(agentData, (uint)tf, null, out reason)) - Console.WriteLine("NewUserConnection failed: " + reason); - - // Stage 2: add the new client as a child agent to the scene - scene.AddNewAgent(client, PresenceType.User); - - return scene.GetScenePresence(client.AgentId); - } - - public static ScenePresence AddChildScenePresence(Scene scene, UUID agentId) - { - return AddChildScenePresence(scene, GenerateAgentData(agentId)); - } - - public static ScenePresence AddChildScenePresence(Scene scene, AgentCircuitData acd) - { - acd.child = true; - - // XXX: ViaLogin may not be correct for child agents - TestClient client = new TestClient(acd, scene); - return IntroduceClientToScene(scene, client, acd, TeleportFlags.ViaLogin); - } - - /// - /// Add a test object - /// - /// - /// - public static SceneObjectGroup AddSceneObject(Scene scene) - { - return AddSceneObject(scene, "Test Object", UUID.Random()); - } - - /// - /// Add a test object - /// - /// - /// - /// - /// - public static SceneObjectGroup AddSceneObject(Scene scene, string name, UUID ownerId) - { - SceneObjectGroup so = new SceneObjectGroup(CreateSceneObjectPart(name, UUID.Random(), ownerId)); - - //part.UpdatePrimFlags(false, false, true); - //part.ObjectFlags |= (uint)PrimFlags.Phantom; - - scene.AddNewSceneObject(so, true); - so.InvalidateDeepEffectivePerms(); - - return so; - } - - /// - /// Add a test object - /// - /// - /// - /// The number of parts that should be in the scene object - /// - /// - /// - /// The prefix to be given to part names. This will be suffixed with "Part" - /// (e.g. mynamePart1 for the root part) - /// - /// - /// The hexadecimal last part of the UUID for parts created. A UUID of the form "00000000-0000-0000-0000-{0:XD12}" - /// will be given to the root part, and incremented for each part thereafter. - /// - /// - public static SceneObjectGroup AddSceneObject(Scene scene, int parts, UUID ownerId, string partNamePrefix, int uuidTail) - { - SceneObjectGroup so = CreateSceneObject(parts, ownerId, partNamePrefix, uuidTail); - - scene.AddNewSceneObject(so, false); - so.InvalidateDeepEffectivePerms(); - - return so; - } - - /// - /// Create a scene object part. - /// - /// - /// - /// - /// - public static SceneObjectPart CreateSceneObjectPart(string name, UUID id, UUID ownerId) - { - return new SceneObjectPart( - ownerId, PrimitiveBaseShape.Default, Vector3.Zero, Quaternion.Identity, Vector3.Zero) - { Name = name, UUID = id, Scale = new Vector3(1, 1, 1) }; - } - - /// - /// Create a scene object but do not add it to the scene. - /// - /// - /// UUID always starts at 00000000-0000-0000-0000-000000000001. For some purposes, (e.g. serializing direct - /// to another object's inventory) we do not need a scene unique ID. So it would be better to add the - /// UUID when we actually add an object to a scene rather than on creation. - /// - /// The number of parts that should be in the scene object - /// - /// - public static SceneObjectGroup CreateSceneObject(int parts, UUID ownerId) - { - return CreateSceneObject(parts, ownerId, 0x1); - } - - /// - /// Create a scene object but do not add it to the scene. - /// - /// The number of parts that should be in the scene object - /// - /// - /// The hexadecimal last part of the UUID for parts created. A UUID of the form "00000000-0000-0000-0000-{0:XD12}" - /// will be given to the root part, and incremented for each part thereafter. - /// - /// - public static SceneObjectGroup CreateSceneObject(int parts, UUID ownerId, int uuidTail) - { - return CreateSceneObject(parts, ownerId, "", uuidTail); - } - - /// - /// Create a scene object but do not add it to the scene. - /// - /// - /// The number of parts that should be in the scene object - /// - /// - /// - /// The prefix to be given to part names. This will be suffixed with "Part" - /// (e.g. mynamePart1 for the root part) - /// - /// - /// The hexadecimal last part of the UUID for parts created. A UUID of the form "00000000-0000-0000-0000-{0:XD12}" - /// will be given to the root part, and incremented for each part thereafter. - /// - /// - public static SceneObjectGroup CreateSceneObject(int parts, UUID ownerId, string partNamePrefix, int uuidTail) - { - string rawSogId = string.Format("00000000-0000-0000-0000-{0:X12}", uuidTail); - - SceneObjectGroup sog - = new SceneObjectGroup( - CreateSceneObjectPart(string.Format("{0}Part1", partNamePrefix), new UUID(rawSogId), ownerId)); - - if (parts > 1) - for (int i = 2; i <= parts; i++) - sog.AddPart( - CreateSceneObjectPart( - string.Format("{0}Part{1}", partNamePrefix, i), - new UUID(string.Format("00000000-0000-0000-0000-{0:X12}", uuidTail + i - 1)), - ownerId)); - - return sog; - } - } -} diff --git a/OpenSim/Tests/Common/Helpers/TaskInventoryHelpers.cs b/OpenSim/Tests/Common/Helpers/TaskInventoryHelpers.cs deleted file mode 100644 index e3110f677c7..00000000000 --- a/OpenSim/Tests/Common/Helpers/TaskInventoryHelpers.cs +++ /dev/null @@ -1,210 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using OpenMetaverse; -using OpenMetaverse.Assets; -using OpenSim.Framework; -using OpenSim.Region.Framework.Scenes; -using OpenSim.Services.Interfaces; - -namespace OpenSim.Tests.Common -{ - /// - /// Utility functions for carrying out task inventory tests. - /// - /// - public static class TaskInventoryHelpers - { - /// - /// Add a notecard item to the given part. - /// - /// - /// - /// - /// UUID or UUID stem - /// UUID or UUID stem - /// The tex to put in the notecard. - /// The item that was added - public static TaskInventoryItem AddNotecard( - IAssetService assetService, SceneObjectPart part, string itemName, string itemIDStem, string assetIDStem, string text) - { - return AddNotecard( - assetService, part, itemName, TestHelpers.ParseStem(itemIDStem), TestHelpers.ParseStem(assetIDStem), text); - } - - /// - /// Add a notecard item to the given part. - /// - /// - /// - /// - /// - /// - /// The tex to put in the notecard. - /// The item that was added - public static TaskInventoryItem AddNotecard( - IAssetService assetService, SceneObjectPart part, string itemName, UUID itemID, UUID assetID, string text) - { - AssetNotecard nc = new AssetNotecard(); - nc.BodyText = text; - nc.Encode(); - - AssetBase ncAsset - = AssetHelpers.CreateAsset(assetID, AssetType.Notecard, nc.AssetData, UUID.Zero); - assetService.Store(ncAsset); - - TaskInventoryItem ncItem - = new TaskInventoryItem - { Name = itemName, AssetID = assetID, ItemID = itemID, - Type = (int)AssetType.Notecard, InvType = (int)InventoryType.Notecard }; - part.Inventory.AddInventoryItem(ncItem, true); - - return ncItem; - } - - /// - /// Add a simple script to the given part. - /// - /// - /// TODO: Accept input for item and asset IDs to avoid mysterious script failures that try to use any of these - /// functions more than once in a test. - /// - /// - /// - /// The item that was added - public static TaskInventoryItem AddScript(IAssetService assetService, SceneObjectPart part) - { - return AddScript(assetService, part, "scriptItem", "default { state_entry() { llSay(0, \"Hello World\"); } }"); - } - - /// - /// Add a simple script to the given part. - /// - /// - /// TODO: Accept input for item and asset IDs so that we have completely replicatable regression tests rather - /// than a random component. - /// - /// - /// - /// Name of the script to add - /// LSL script source - /// The item that was added - public static TaskInventoryItem AddScript( - IAssetService assetService, SceneObjectPart part, string scriptName, string scriptSource) - { - return AddScript(assetService, part, UUID.Random(), UUID.Random(), scriptName, scriptSource); - } - - /// - /// Add a simple script to the given part. - /// - /// - /// TODO: Accept input for item and asset IDs so that we have completely replicatable regression tests rather - /// than a random component. - /// - /// - /// - /// Item UUID for the script - /// Asset UUID for the script - /// Name of the script to add - /// LSL script source - /// The item that was added - public static TaskInventoryItem AddScript( - IAssetService assetService, SceneObjectPart part, UUID itemId, UUID assetId, string scriptName, string scriptSource) - { - AssetScriptText ast = new AssetScriptText(); - ast.Source = scriptSource; - ast.Encode(); - - AssetBase asset - = AssetHelpers.CreateAsset(assetId, AssetType.LSLText, ast.AssetData, UUID.Zero); - assetService.Store(asset); - TaskInventoryItem item - = new TaskInventoryItem - { Name = scriptName, AssetID = assetId, ItemID = itemId, - Type = (int)AssetType.LSLText, InvType = (int)InventoryType.LSL }; - part.Inventory.AddInventoryItem(item, true); - - return item; - } - - /// - /// Add a scene object item to the given part. - /// - /// - /// TODO: Accept input for item and asset IDs to avoid mysterious script failures that try to use any of these - /// functions more than once in a test. - /// - /// - /// - /// - /// - /// - /// - /// - public static TaskInventoryItem AddSceneObject( - IAssetService assetService, SceneObjectPart sop, string itemName, UUID itemId, SceneObjectGroup soToAdd, UUID soAssetId) - { - AssetBase taskSceneObjectAsset = AssetHelpers.CreateAsset(soAssetId, soToAdd); - assetService.Store(taskSceneObjectAsset); - TaskInventoryItem taskSceneObjectItem - = new TaskInventoryItem - { Name = itemName, - AssetID = taskSceneObjectAsset.FullID, - ItemID = itemId, - OwnerID = soToAdd.OwnerID, - Type = (int)AssetType.Object, - InvType = (int)InventoryType.Object }; - sop.Inventory.AddInventoryItem(taskSceneObjectItem, true); - - return taskSceneObjectItem; - } - - /// - /// Add a scene object item to the given part. - /// - /// - /// TODO: Accept input for item and asset IDs to avoid mysterious script failures that try to use any of these - /// functions more than once in a test. - /// - /// - /// - /// - /// - /// - /// - public static TaskInventoryItem AddSceneObject( - IAssetService assetService, SceneObjectPart sop, string itemName, UUID itemId, UUID userId) - { - SceneObjectGroup taskSceneObject = SceneHelpers.CreateSceneObject(1, userId); - - return TaskInventoryHelpers.AddSceneObject( - assetService, sop, itemName, itemId, taskSceneObject, TestHelpers.ParseTail(0x10)); - } - } -} \ No newline at end of file diff --git a/OpenSim/Tests/Common/Helpers/UserAccountHelpers.cs b/OpenSim/Tests/Common/Helpers/UserAccountHelpers.cs deleted file mode 100644 index e6af34b879f..00000000000 --- a/OpenSim/Tests/Common/Helpers/UserAccountHelpers.cs +++ /dev/null @@ -1,160 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System.Collections.Generic; -using OpenMetaverse; - -using OpenSim.Region.Framework.Scenes; -using OpenSim.Services.Interfaces; - -namespace OpenSim.Tests.Common -{ - /// - /// Utility functions for carrying out user profile related tests. - /// - public static class UserAccountHelpers - { -// /// -// /// Create a test user with a standard inventory -// /// -// /// -// /// -// /// Callback to invoke when inventory has been loaded. This is required because -// /// loading may be asynchronous, even on standalone -// /// -// /// -// public static CachedUserInfo CreateUserWithInventory( -// CommunicationsManager commsManager, OnInventoryReceivedDelegate callback) -// { -// UUID userId = UUID.Parse("00000000-0000-0000-0000-000000000099"); -// return CreateUserWithInventory(commsManager, userId, callback); -// } -// -// /// -// /// Create a test user with a standard inventory -// /// -// /// -// /// User ID -// /// -// /// Callback to invoke when inventory has been loaded. This is required because -// /// loading may be asynchronous, even on standalone -// /// -// /// -// public static CachedUserInfo CreateUserWithInventory( -// CommunicationsManager commsManager, UUID userId, OnInventoryReceivedDelegate callback) -// { -// return CreateUserWithInventory(commsManager, "Bill", "Bailey", userId, callback); -// } -// -// /// -// /// Create a test user with a standard inventory -// /// -// /// -// /// First name of user -// /// Last name of user -// /// User ID -// /// -// /// Callback to invoke when inventory has been loaded. This is required because -// /// loading may be asynchronous, even on standalone -// /// -// /// -// public static CachedUserInfo CreateUserWithInventory( -// CommunicationsManager commsManager, string firstName, string lastName, -// UUID userId, OnInventoryReceivedDelegate callback) -// { -// return CreateUserWithInventory(commsManager, firstName, lastName, "troll", userId, callback); -// } -// -// /// -// /// Create a test user with a standard inventory -// /// -// /// -// /// First name of user -// /// Last name of user -// /// Password -// /// User ID -// /// -// /// Callback to invoke when inventory has been loaded. This is required because -// /// loading may be asynchronous, even on standalone -// /// -// /// -// public static CachedUserInfo CreateUserWithInventory( -// CommunicationsManager commsManager, string firstName, string lastName, string password, -// UUID userId, OnInventoryReceivedDelegate callback) -// { -// LocalUserServices lus = (LocalUserServices)commsManager.UserService; -// lus.AddUser(firstName, lastName, password, "bill@bailey.com", 1000, 1000, userId); -// -// CachedUserInfo userInfo = commsManager.UserProfileCacheService.GetUserDetails(userId); -// userInfo.OnInventoryReceived += callback; -// userInfo.FetchInventory(); -// -// return userInfo; -// } - - public static UserAccount CreateUserWithInventory(Scene scene) - { - return CreateUserWithInventory(scene, TestHelpers.ParseTail(99)); - } - - public static UserAccount CreateUserWithInventory(Scene scene, UUID userId) - { - return CreateUserWithInventory(scene, "Bill", "Bailey", userId, "troll"); - } - - public static UserAccount CreateUserWithInventory(Scene scene, int userId) - { - return CreateUserWithInventory(scene, "Bill", "Bailey", TestHelpers.ParseTail(userId), "troll"); - } - - public static UserAccount CreateUserWithInventory( - Scene scene, string firstName, string lastName, UUID userId, string pw) - { - UserAccount ua = new UserAccount(userId) { FirstName = firstName, LastName = lastName }; - CreateUserWithInventory(scene, ua, pw); - return ua; - } - - public static UserAccount CreateUserWithInventory( - Scene scene, string firstName, string lastName, int userId, string pw) - { - UserAccount ua - = new UserAccount(TestHelpers.ParseTail(userId)) { FirstName = firstName, LastName = lastName }; - CreateUserWithInventory(scene, ua, pw); - return ua; - } - - public static void CreateUserWithInventory(Scene scene, UserAccount ua, string pw) - { - // FIXME: This should really be set up by UserAccount itself - ua.ServiceURLs = new Dictionary(); - scene.UserAccountService.StoreUserAccount(ua); - scene.InventoryService.CreateUserInventory(ua.PrincipalID); - scene.AuthenticationService.SetPassword(ua.PrincipalID, pw); - } - } -} \ No newline at end of file diff --git a/OpenSim/Tests/Common/Helpers/UserInventoryHelpers.cs b/OpenSim/Tests/Common/Helpers/UserInventoryHelpers.cs deleted file mode 100644 index e18866598c3..00000000000 --- a/OpenSim/Tests/Common/Helpers/UserInventoryHelpers.cs +++ /dev/null @@ -1,374 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections.Generic; -using OpenMetaverse; -using OpenSim.Framework; -using OpenSim.Region.CoreModules.Avatar.Inventory.Archiver; -using OpenSim.Region.Framework.Scenes; -using OpenSim.Services.Interfaces; - -namespace OpenSim.Tests.Common -{ - /// - /// Utility functions for carrying out user inventory tests. - /// - public static class UserInventoryHelpers - { - public static readonly string PATH_DELIMITER = "/"; - - /// - /// Add an existing scene object as an item in the user's inventory. - /// - /// - /// Will be added to the system Objects folder. - /// - /// - /// - /// - /// - /// The inventory item created. - public static InventoryItemBase AddInventoryItem( - Scene scene, SceneObjectGroup so, int inventoryIdTail, int assetIdTail) - { - return AddInventoryItem( - scene, - so.Name, - TestHelpers.ParseTail(inventoryIdTail), - InventoryType.Object, - AssetHelpers.CreateAsset(TestHelpers.ParseTail(assetIdTail), so), - so.OwnerID); - } - - /// - /// Add an existing scene object as an item in the user's inventory at the given path. - /// - /// - /// - /// - /// - /// The inventory item created. - public static InventoryItemBase AddInventoryItem( - Scene scene, SceneObjectGroup so, int inventoryIdTail, int assetIdTail, string path) - { - return AddInventoryItem( - scene, - so.Name, - TestHelpers.ParseTail(inventoryIdTail), - InventoryType.Object, - AssetHelpers.CreateAsset(TestHelpers.ParseTail(assetIdTail), so), - so.OwnerID, - path); - } - - /// - /// Adds the given item to the existing system folder for its type (e.g. an object will go in the "Objects" - /// folder). - /// - /// - /// - /// - /// - /// The serialized asset for this item - /// - /// - private static InventoryItemBase AddInventoryItem( - Scene scene, string itemName, UUID itemId, InventoryType itemType, AssetBase asset, UUID userId) - { - return AddInventoryItem( - scene, itemName, itemId, itemType, asset, userId, - scene.InventoryService.GetFolderForType(userId, (FolderType)asset.Type).Name); - } - - /// - /// Adds the given item to an inventory folder - /// - /// - /// - /// - /// - /// The serialized asset for this item - /// - /// Existing inventory path at which to add. - /// - private static InventoryItemBase AddInventoryItem( - Scene scene, string itemName, UUID itemId, InventoryType itemType, AssetBase asset, UUID userId, string path) - { - scene.AssetService.Store(asset); - - InventoryItemBase item = new InventoryItemBase(); - item.Name = itemName; - item.AssetID = asset.FullID; - item.ID = itemId; - item.Owner = userId; - item.AssetType = asset.Type; - item.InvType = (int)itemType; - item.BasePermissions = (uint)OpenMetaverse.PermissionMask.All | - (uint)(Framework.PermissionMask.FoldedMask | Framework.PermissionMask.FoldedCopy | Framework.PermissionMask.FoldedModify | Framework.PermissionMask.FoldedTransfer); - item.CurrentPermissions = (uint)OpenMetaverse.PermissionMask.All | - (uint)(Framework.PermissionMask.FoldedMask | Framework.PermissionMask.FoldedCopy | Framework.PermissionMask.FoldedModify | Framework.PermissionMask.FoldedTransfer); - - InventoryFolderBase folder = InventoryArchiveUtils.FindFoldersByPath(scene.InventoryService, userId, path)[0]; - - item.Folder = folder.ID; - scene.AddInventoryItem(item); - - return item; - } - - /// - /// Creates a notecard in the objects folder and specify an item id. - /// - /// - /// - /// - /// - /// - public static InventoryItemBase CreateInventoryItem(Scene scene, string itemName, UUID userId) - { - return CreateInventoryItem(scene, itemName, UUID.Random(), UUID.Random(), userId, InventoryType.Notecard); - } - - /// - /// Creates an item of the given type with an accompanying asset. - /// - /// - /// - /// - /// - /// Type of item to create - /// - public static InventoryItemBase CreateInventoryItem( - Scene scene, string itemName, UUID userId, InventoryType type) - { - return CreateInventoryItem(scene, itemName, UUID.Random(), UUID.Random(), userId, type); - } - - /// - /// Creates a notecard in the objects folder and specify an item id. - /// - /// - /// - /// - /// - /// - /// Type of item to create - /// - public static InventoryItemBase CreateInventoryItem( - Scene scene, string itemName, UUID itemId, UUID assetId, UUID userId, InventoryType itemType) - { - AssetBase asset = null; - - if (itemType == InventoryType.Notecard) - { - asset = AssetHelpers.CreateNotecardAsset(); - asset.CreatorID = userId.ToString(); - } - else if (itemType == InventoryType.Object) - { - asset = AssetHelpers.CreateAsset(assetId, SceneHelpers.CreateSceneObject(1, userId)); - } - else - { - throw new Exception(string.Format("Inventory type {0} not supported", itemType)); - } - - return AddInventoryItem(scene, itemName, itemId, itemType, asset, userId); - } - - /// - /// Create inventory folders starting from the user's root folder. - /// - /// - /// - /// - /// The folders to create. Multiple folders can be specified on a path delimited by the PATH_DELIMITER - /// - /// - /// If true, then folders in the path which already the same name are - /// used. This applies to the terminal folder as well. - /// If false, then all folders in the path are created, even if there is already a folder at a particular - /// level with the same name. - /// - /// - /// The folder created. If the path contains multiple folders then the last one created is returned. - /// Will return null if the root folder could not be found. - /// - public static InventoryFolderBase CreateInventoryFolder( - IInventoryService inventoryService, UUID userId, string path, bool useExistingFolders) - { - return CreateInventoryFolder(inventoryService, userId, UUID.Random(), path, useExistingFolders); - } - - /// - /// Create inventory folders starting from the user's root folder. - /// - /// - /// - /// - /// - /// The folders to create. Multiple folders can be specified on a path delimited by the PATH_DELIMITER - /// - /// - /// If true, then folders in the path which already the same name are - /// used. This applies to the terminal folder as well. - /// If false, then all folders in the path are created, even if there is already a folder at a particular - /// level with the same name. - /// - /// - /// The folder created. If the path contains multiple folders then the last one created is returned. - /// Will return null if the root folder could not be found. - /// - public static InventoryFolderBase CreateInventoryFolder( - IInventoryService inventoryService, UUID userId, UUID folderId, string path, bool useExistingFolders) - { - InventoryFolderBase rootFolder = inventoryService.GetRootFolder(userId); - - if (null == rootFolder) - return null; - - return CreateInventoryFolder(inventoryService, folderId, rootFolder, path, useExistingFolders); - } - - /// - /// Create inventory folders starting from a given parent folder - /// - /// - /// If any stem of the path names folders that already exist then these are not recreated. This includes the - /// final folder. - /// TODO: May need to make it an option to create duplicate folders. - /// - /// - /// ID of the folder to create - /// - /// - /// The folder to create. - /// - /// - /// If true, then folders in the path which already the same name are - /// used. This applies to the terminal folder as well. - /// If false, then all folders in the path are created, even if there is already a folder at a particular - /// level with the same name. - /// - /// - /// The folder created. If the path contains multiple folders then the last one created is returned. - /// - public static InventoryFolderBase CreateInventoryFolder( - IInventoryService inventoryService, UUID folderId, InventoryFolderBase parentFolder, string path, bool useExistingFolders) - { - string[] components = path.Split(new string[] { PATH_DELIMITER }, 2, StringSplitOptions.None); - - InventoryFolderBase folder = null; - - if (useExistingFolders) - folder = InventoryArchiveUtils.FindFolderByPath(inventoryService, parentFolder, components[0]); - - if (folder == null) - { -// Console.WriteLine("Creating folder {0} at {1}", components[0], parentFolder.Name); - - UUID folderIdForCreate; - - if (components.Length > 1) - folderIdForCreate = UUID.Random(); - else - folderIdForCreate = folderId; - - folder - = new InventoryFolderBase( - folderIdForCreate, components[0], parentFolder.Owner, (short)AssetType.Unknown, parentFolder.ID, 0); - - inventoryService.AddFolder(folder); - } -// else -// { -// Console.WriteLine("Found existing folder {0}", folder.Name); -// } - - if (components.Length > 1) - return CreateInventoryFolder(inventoryService, folderId, folder, components[1], useExistingFolders); - else - return folder; - } - - /// - /// Get the inventory folder that matches the path name. If there are multiple folders then only the first - /// is returned. - /// - /// - /// - /// - /// null if no folder matching the path was found - public static InventoryFolderBase GetInventoryFolder(IInventoryService inventoryService, UUID userId, string path) - { - List folders = GetInventoryFolders(inventoryService, userId, path); - - if (folders.Count != 0) - return folders[0]; - else - return null; - } - - /// - /// Get the inventory folders that match the path name. - /// - /// - /// - /// - /// An empty list if no matching folders were found - public static List GetInventoryFolders(IInventoryService inventoryService, UUID userId, string path) - { - return InventoryArchiveUtils.FindFoldersByPath(inventoryService, userId, path); - } - - /// - /// Get the inventory item that matches the path name. If there are multiple items then only the first - /// is returned. - /// - /// - /// - /// - /// null if no item matching the path was found - public static InventoryItemBase GetInventoryItem(IInventoryService inventoryService, UUID userId, string path) - { - return InventoryArchiveUtils.FindItemByPath(inventoryService, userId, path); - } - - /// - /// Get the inventory items that match the path name. - /// - /// - /// - /// - /// An empty list if no matching items were found. - public static List GetInventoryItems(IInventoryService inventoryService, UUID userId, string path) - { - return InventoryArchiveUtils.FindItemsByPath(inventoryService, userId, path); - } - } -} diff --git a/OpenSim/Tests/Common/LongRunningAttribute.cs b/OpenSim/Tests/Common/LongRunningAttribute.cs deleted file mode 100644 index 6013fcb2186..00000000000 --- a/OpenSim/Tests/Common/LongRunningAttribute.cs +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections.Generic; -using System.Text; -using NUnit.Framework; - -namespace OpenSim.Tests.Common -{ - [AttributeUsage(AttributeTargets.All, - AllowMultiple = false, - Inherited = true)] - public class LongRunningAttribute : CategoryAttribute - { - public LongRunningAttribute() : this("Long Running Test") - { - - } - - protected LongRunningAttribute(string category) : base(category) - { - } - } -} diff --git a/OpenSim/Tests/Common/Mock/BaseAssetRepository.cs b/OpenSim/Tests/Common/Mock/BaseAssetRepository.cs deleted file mode 100644 index d0430ff63a9..00000000000 --- a/OpenSim/Tests/Common/Mock/BaseAssetRepository.cs +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections.Generic; -using OpenMetaverse; -using OpenSim.Framework; - -namespace OpenSim.Tests.Common -{ - public class BaseAssetRepository - { - protected Dictionary Assets = new Dictionary(); - - public AssetBase FetchAsset(UUID uuid) - { - if (AssetsExist(new[] { uuid })[0]) - return Assets[uuid]; - else - return null; - } - - public void CreateAsset(AssetBase asset) - { - Assets[asset.FullID] = asset; - } - - public void UpdateAsset(AssetBase asset) - { - CreateAsset(asset); - } - - public bool[] AssetsExist(UUID[] uuids) - { - return Array.ConvertAll(uuids, id => Assets.ContainsKey(id)); - } - } -} \ No newline at end of file diff --git a/OpenSim/Tests/Common/Mock/MockAssetDataPlugin.cs b/OpenSim/Tests/Common/Mock/MockAssetDataPlugin.cs deleted file mode 100644 index aaf61e7df21..00000000000 --- a/OpenSim/Tests/Common/Mock/MockAssetDataPlugin.cs +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections.Generic; -using OpenMetaverse; -using OpenSim.Framework; -using OpenSim.Data; - -namespace OpenSim.Tests.Common -{ - /// - /// In memory asset data plugin for test purposes. Could be another dll when properly filled out and when the - /// mono addin plugin system starts co-operating with the unit test system. Currently no locking since unit - /// tests are single threaded. - /// - public class MockAssetDataPlugin : BaseAssetRepository, IAssetDataPlugin - { - public string Version { get { return "0"; } } - public string Name { get { return "MockAssetDataPlugin"; } } - - public void Initialise() {} - public void Initialise(string connect) {} - public void Dispose() {} - - private readonly List assets = new List(); - - public AssetBase GetAsset(UUID uuid) - { - return assets.Find(x=>x.FullID == uuid); - } - - public bool StoreAsset(AssetBase asset) - { - assets.Add(asset); - return true; - } - - public List FetchAssetMetadataSet(int start, int count) { return new List(count); } - - public bool Delete(string id) - { - return false; - } - } -} diff --git a/OpenSim/Tests/Common/Mock/MockGroupsServicesConnector.cs b/OpenSim/Tests/Common/Mock/MockGroupsServicesConnector.cs deleted file mode 100644 index e9deac768d6..00000000000 --- a/OpenSim/Tests/Common/Mock/MockGroupsServicesConnector.cs +++ /dev/null @@ -1,436 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections; -using System.Collections.Generic; -using System.Reflection; -using log4net; -using Mono.Addins; -using Nini.Config; -using OpenMetaverse; -using OpenSim.Data; -using OpenSim.Data.Null; -using OpenSim.Framework; -using OpenSim.Region.Framework.Interfaces; -using OpenSim.Region.Framework.Scenes; -using OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups; - -namespace OpenSim.Tests.Common -{ - [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")] - public class MockGroupsServicesConnector : ISharedRegionModule, IGroupsServicesConnector - { - private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - - IXGroupData m_data = new NullXGroupData(null, null); - - public string Name - { - get { return "MockGroupsServicesConnector"; } - } - - public Type ReplaceableInterface - { - get { return null; } - } - - public void Initialise(IConfigSource config) - { - } - - public void Close() - { - } - - public void AddRegion(Scene scene) - { - m_log.DebugFormat("[MOCK GROUPS SERVICES CONNECTOR]: Adding to region {0}", scene.RegionInfo.RegionName); - scene.RegisterModuleInterface(this); - } - - public void RemoveRegion(Scene scene) - { - } - - public void RegionLoaded(Scene scene) - { - } - - public void PostInitialise() - { - } - - public UUID CreateGroup(UUID requestingAgentID, string name, string charter, bool showInList, UUID insigniaID, - int membershipFee, bool openEnrollment, bool allowPublish, - bool maturePublish, UUID founderID) - { - XGroup group = new XGroup() - { - groupID = UUID.Random(), - ownerRoleID = UUID.Random(), - name = name, - charter = charter, - showInList = showInList, - insigniaID = insigniaID, - membershipFee = membershipFee, - openEnrollment = openEnrollment, - allowPublish = allowPublish, - maturePublish = maturePublish, - founderID = founderID, - everyonePowers = (ulong)XmlRpcGroupsServicesConnectorModule.DefaultEveryonePowers, - ownersPowers = (ulong)XmlRpcGroupsServicesConnectorModule.DefaultOwnerPowers - }; - - if (m_data.StoreGroup(group)) - { - m_log.DebugFormat("[MOCK GROUPS SERVICES CONNECTOR]: Created group {0} {1}", group.name, group.groupID); - return group.groupID; - } - else - { - m_log.ErrorFormat("[MOCK GROUPS SERVICES CONNECTOR]: Failed to create group {0}", name); - return UUID.Zero; - } - } - - public void UpdateGroup(UUID requestingAgentID, UUID groupID, string charter, bool showInList, - UUID insigniaID, int membershipFee, bool openEnrollment, - bool allowPublish, bool maturePublish) - { - } - - public void AddGroupRole(UUID requestingAgentID, UUID groupID, UUID roleID, string name, string description, - string title, ulong powers) - { - } - - public void RemoveGroupRole(UUID requestingAgentID, UUID groupID, UUID roleID) - { - } - - public void UpdateGroupRole(UUID requestingAgentID, UUID groupID, UUID roleID, string name, string description, - string title, ulong powers) - { - } - - private XGroup GetXGroup(UUID groupID, string name) - { - XGroup group = m_data.GetGroup(groupID); - - - if (group == null) - m_log.DebugFormat("[MOCK GROUPS SERVICES CONNECTOR]: No group found with ID {0}", groupID); - - return group; - } - - public GroupRecord GetGroupRecord(UUID requestingAgentID, UUID groupID, string groupName) - { - m_log.DebugFormat( - "[MOCK GROUPS SERVICES CONNECTOR]: Processing GetGroupRecord() for groupID {0}, name {1}", - groupID, groupName); - - XGroup xg = GetXGroup(groupID, groupName); - - if (xg == null) - return null; - - GroupRecord gr = new GroupRecord() - { - GroupID = xg.groupID, - GroupName = xg.name, - AllowPublish = xg.allowPublish, - MaturePublish = xg.maturePublish, - Charter = xg.charter, - FounderID = xg.founderID, - // FIXME: group picture storage location unknown - MembershipFee = xg.membershipFee, - OpenEnrollment = xg.openEnrollment, - OwnerRoleID = xg.ownerRoleID, - ShowInList = xg.showInList - }; - - return gr; - } - - public GroupProfileData GetMemberGroupProfile(UUID requestingAgentID, UUID GroupID, UUID AgentID) - { - return default(GroupProfileData); - } - - public void SetAgentActiveGroup(UUID requestingAgentID, UUID AgentID, UUID GroupID) - { - } - - public void SetAgentActiveGroupRole(UUID requestingAgentID, UUID AgentID, UUID GroupID, UUID RoleID) - { - } - - public void SetAgentGroupInfo(UUID requestingAgentID, UUID agentID, UUID groupID, bool acceptNotices, bool listInProfile) - { - m_log.DebugFormat( - "[MOCK GROUPS SERVICES CONNECTOR]: SetAgentGroupInfo, requestingAgentID {0}, agentID {1}, groupID {2}, acceptNotices {3}, listInProfile {4}", - requestingAgentID, agentID, groupID, acceptNotices, listInProfile); - - XGroup group = GetXGroup(groupID, null); - - if (group == null) - return; - - XGroupMember xgm = null; - if (!group.members.TryGetValue(agentID, out xgm)) - return; - - xgm.acceptNotices = acceptNotices; - xgm.listInProfile = listInProfile; - - m_data.StoreGroup(group); - } - - public void AddAgentToGroupInvite(UUID requestingAgentID, UUID inviteID, UUID groupID, UUID roleID, UUID agentID) - { - } - - public GroupInviteInfo GetAgentToGroupInvite(UUID requestingAgentID, UUID inviteID) - { - return null; - } - - public void RemoveAgentToGroupInvite(UUID requestingAgentID, UUID inviteID) - { - } - - public void AddAgentToGroup(UUID requestingAgentID, UUID agentID, UUID groupID, UUID roleID) - { - m_log.DebugFormat( - "[MOCK GROUPS SERVICES CONNECTOR]: AddAgentToGroup, requestingAgentID {0}, agentID {1}, groupID {2}, roleID {3}", - requestingAgentID, agentID, groupID, roleID); - - XGroup group = GetXGroup(groupID, null); - - if (group == null) - return; - - XGroupMember groupMember = new XGroupMember() - { - agentID = agentID, - groupID = groupID, - roleID = roleID - }; - - group.members[agentID] = groupMember; - - m_data.StoreGroup(group); - } - - public void RemoveAgentFromGroup(UUID requestingAgentID, UUID AgentID, UUID GroupID) - { - } - - public void AddAgentToGroupRole(UUID requestingAgentID, UUID AgentID, UUID GroupID, UUID RoleID) - { - } - - public void RemoveAgentFromGroupRole(UUID requestingAgentID, UUID AgentID, UUID GroupID, UUID RoleID) - { - } - - public List FindGroups(UUID requestingAgentID, string search) - { - return null; - } - - public GroupMembershipData GetAgentGroupMembership(UUID requestingAgentID, UUID AgentID, UUID GroupID) - { - return null; - } - - public GroupMembershipData GetAgentActiveMembership(UUID requestingAgentID, UUID AgentID) - { - return null; - } - - public List GetAgentGroupMemberships(UUID requestingAgentID, UUID AgentID) - { - return new List(); - } - - public List GetAgentGroupRoles(UUID requestingAgentID, UUID AgentID, UUID GroupID) - { - return null; - } - - public List GetGroupRoles(UUID requestingAgentID, UUID GroupID) - { - return null; - } - - public List GetGroupMembers(UUID requestingAgentID, UUID groupID) - { - m_log.DebugFormat( - "[MOCK GROUPS SERVICES CONNECTOR]: GetGroupMembers, requestingAgentID {0}, groupID {1}", - requestingAgentID, groupID); - - List groupMembers = new List(); - - XGroup group = GetXGroup(groupID, null); - - if (group == null) - return groupMembers; - - foreach (XGroupMember xgm in group.members.Values) - { - GroupMembersData gmd = new GroupMembersData(); - gmd.AgentID = xgm.agentID; - gmd.IsOwner = group.founderID == gmd.AgentID; - gmd.AcceptNotices = xgm.acceptNotices; - gmd.ListInProfile = xgm.listInProfile; - - groupMembers.Add(gmd); - } - - return groupMembers; - } - - public List GetGroupRoleMembers(UUID requestingAgentID, UUID GroupID) - { - return null; - } - - public List GetGroupNotices(UUID requestingAgentID, UUID groupID) - { - XGroup group = GetXGroup(groupID, null); - - if (group == null) - return null; - - List notices = new List(); - - foreach (XGroupNotice notice in group.notices.Values) - { - GroupNoticeData gnd = new GroupNoticeData() - { - NoticeID = notice.noticeID, - Timestamp = notice.timestamp, - FromName = notice.fromName, - Subject = notice.subject, - HasAttachment = notice.hasAttachment, - AssetType = (byte)notice.assetType - }; - - notices.Add(gnd); - } - - return notices; - } - - public GroupNoticeInfo GetGroupNotice(UUID requestingAgentID, UUID noticeID) - { - m_log.DebugFormat( - "[MOCK GROUPS SERVICES CONNECTOR]: GetGroupNotices, requestingAgentID {0}, noticeID {1}", - requestingAgentID, noticeID); - - // Yes, not an efficient way to do it. - Dictionary groups = m_data.GetGroups(); - - foreach (XGroup group in groups.Values) - { - if (group.notices.ContainsKey(noticeID)) - { - XGroupNotice n = group.notices[noticeID]; - - GroupNoticeInfo gni = new GroupNoticeInfo(); - gni.GroupID = n.groupID; - gni.Message = n.message; - gni.BinaryBucket = n.binaryBucket; - gni.noticeData.NoticeID = n.noticeID; - gni.noticeData.Timestamp = n.timestamp; - gni.noticeData.FromName = n.fromName; - gni.noticeData.Subject = n.subject; - gni.noticeData.HasAttachment = n.hasAttachment; - gni.noticeData.AssetType = (byte)n.assetType; - - return gni; - } - } - - return null; - } - - public void AddGroupNotice(UUID requestingAgentID, UUID groupID, UUID noticeID, string fromName, string subject, string message, byte[] binaryBucket) - { - m_log.DebugFormat( - "[MOCK GROUPS SERVICES CONNECTOR]: AddGroupNotice, requestingAgentID {0}, groupID {1}, noticeID {2}, fromName {3}, subject {4}, message {5}, binaryBucket.Length {6}", - requestingAgentID, groupID, noticeID, fromName, subject, message, binaryBucket.Length); - - XGroup group = GetXGroup(groupID, null); - - if (group == null) - return; - - XGroupNotice groupNotice = new XGroupNotice() - { - groupID = groupID, - noticeID = noticeID, - fromName = fromName, - subject = subject, - message = message, - timestamp = (uint)Util.UnixTimeSinceEpoch(), - hasAttachment = false, - assetType = 0, - binaryBucket = binaryBucket - }; - - group.notices[noticeID] = groupNotice; - - m_data.StoreGroup(group); - } - - public void ResetAgentGroupChatSessions(UUID agentID) - { - } - - public bool hasAgentBeenInvitedToGroupChatSession(UUID agentID, UUID groupID) - { - return false; - } - - public bool hasAgentDroppedGroupChatSession(UUID agentID, UUID groupID) - { - return false; - } - - public void AgentDroppedFromGroupChatSession(UUID agentID, UUID groupID) - { - } - - public void AgentInvitedToGroupChatSession(UUID agentID, UUID groupID) - { - } - } -} \ No newline at end of file diff --git a/OpenSim/Tests/Common/Mock/MockRegionDataPlugin.cs b/OpenSim/Tests/Common/Mock/MockRegionDataPlugin.cs deleted file mode 100644 index ab0e4f4454e..00000000000 --- a/OpenSim/Tests/Common/Mock/MockRegionDataPlugin.cs +++ /dev/null @@ -1,375 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System.Reflection; -using System.Collections.Generic; -using log4net; -using OpenMetaverse; -using OpenSim.Framework; -using OpenSim.Region.Framework.Interfaces; -using OpenSim.Region.Framework.Scenes; - -namespace OpenSim.Data.Null -{ - public class NullDataService : ISimulationDataService - { - private NullDataStore m_store; - - public NullDataService() - { - m_store = new NullDataStore(); - } - - public void StoreObject(SceneObjectGroup obj, UUID regionUUID) - { - m_store.StoreObject(obj, regionUUID); - } - - public void RemoveObject(UUID uuid, UUID regionUUID) - { - m_store.RemoveObject(uuid, regionUUID); - } - - public void StorePrimInventory(UUID primID, ICollection items) - { - m_store.StorePrimInventory(primID, items); - } - - public List LoadObjects(UUID regionUUID) - { - return m_store.LoadObjects(regionUUID); - } - - public void StoreTerrain(double[,] terrain, UUID regionID) - { - m_store.StoreTerrain(terrain, regionID); - } - - public void StoreTerrain(TerrainData terrain, UUID regionID) - { - m_store.StoreTerrain(terrain, regionID); - } - - public void StoreBakedTerrain(TerrainData terrain, UUID regionID) - { - m_store.StoreBakedTerrain(terrain, regionID); - } - - public double[,] LoadTerrain(UUID regionID) - { - return m_store.LoadTerrain(regionID); - } - - public TerrainData LoadTerrain(UUID regionID, int pSizeX, int pSizeY, int pSizeZ) - { - return m_store.LoadTerrain(regionID, pSizeX, pSizeY, pSizeZ); - } - - public TerrainData LoadBakedTerrain(UUID regionID, int pSizeX, int pSizeY, int pSizeZ) - { - return m_store.LoadBakedTerrain(regionID, pSizeX, pSizeY, pSizeZ); - } - - public void StoreLandObject(ILandObject Parcel) - { - m_store.StoreLandObject(Parcel); - } - - public void RemoveLandObject(UUID globalID) - { - m_store.RemoveLandObject(globalID); - } - - public List LoadLandObjects(UUID regionUUID) - { - return m_store.LoadLandObjects(regionUUID); - } - - public void StoreRegionSettings(RegionSettings rs) - { - m_store.StoreRegionSettings(rs); - } - - public RegionSettings LoadRegionSettings(UUID regionUUID) - { - return m_store.LoadRegionSettings(regionUUID); - } - - public string LoadRegionEnvironmentSettings(UUID regionUUID) - { - return m_store.LoadRegionEnvironmentSettings(regionUUID); - } - - public void StoreRegionEnvironmentSettings(UUID regionUUID, string settings) - { - m_store.StoreRegionEnvironmentSettings(regionUUID, settings); - } - - public void RemoveRegionEnvironmentSettings(UUID regionUUID) - { - m_store.RemoveRegionEnvironmentSettings(regionUUID); - } - - public UUID[] GetObjectIDs(UUID regionID) - { - return new UUID[0]; - } - - public void SaveExtra(UUID regionID, string name, string value) - { - } - - public void RemoveExtra(UUID regionID, string name) - { - } - - public Dictionary GetExtra(UUID regionID) - { - return null; - } - } - - /// - /// Mock region data plugin. This obeys the api contract for persistence but stores everything in memory, so that - /// tests can check correct persistence. - /// - public class NullDataStore : ISimulationDataStore - { -// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - - protected Dictionary m_regionSettings = new Dictionary(); - protected Dictionary m_sceneObjectParts = new Dictionary(); - protected Dictionary> m_primItems - = new Dictionary>(); - protected Dictionary m_terrains = new Dictionary(); - protected Dictionary m_bakedterrains = new Dictionary(); - protected Dictionary m_landData = new Dictionary(); - - public void Initialise(string dbfile) - { - return; - } - - public void Dispose() - { - } - - public void StoreRegionSettings(RegionSettings rs) - { - m_regionSettings[rs.RegionUUID] = rs; - } - - #region Environment Settings - public string LoadRegionEnvironmentSettings(UUID regionUUID) - { - //This connector doesn't support the Environment module yet - return string.Empty; - } - - public void StoreRegionEnvironmentSettings(UUID regionUUID, string settings) - { - //This connector doesn't support the Environment module yet - } - - public void RemoveRegionEnvironmentSettings(UUID regionUUID) - { - //This connector doesn't support the Environment module yet - } - #endregion - - public RegionSettings LoadRegionSettings(UUID regionUUID) - { - RegionSettings rs = null; - m_regionSettings.TryGetValue(regionUUID, out rs); - - if (rs == null) - rs = new RegionSettings(); - - return rs; - } - - public void StoreObject(SceneObjectGroup obj, UUID regionUUID) - { - // We can't simply store groups here because on delinking, OpenSim will not update the original group - // directly. Rather, the newly delinked parts will be updated to be in their own scene object group - // Therefore, we need to store parts rather than groups. - foreach (SceneObjectPart prim in obj.Parts) - { -// m_log.DebugFormat( -// "[MOCK REGION DATA PLUGIN]: Storing part {0} {1} in object {2} {3} in region {4}", -// prim.Name, prim.UUID, obj.Name, obj.UUID, regionUUID); - - m_sceneObjectParts[prim.UUID] = prim; - } - } - - public void RemoveObject(UUID obj, UUID regionUUID) - { - // All parts belonging to the object with the uuid are removed. - List parts = new List(m_sceneObjectParts.Values); - foreach (SceneObjectPart part in parts) - { - if (part.ParentGroup.UUID == obj) - { -// m_log.DebugFormat( -// "[MOCK REGION DATA PLUGIN]: Removing part {0} {1} as part of object {2} from {3}", -// part.Name, part.UUID, obj, regionUUID); - m_sceneObjectParts.Remove(part.UUID); - } - } - } - - public void StorePrimInventory(UUID primID, ICollection items) - { - m_primItems[primID] = items; - } - - public List LoadObjects(UUID regionUUID) - { - Dictionary objects = new Dictionary(); - - // Create all of the SOGs from the root prims first - foreach (SceneObjectPart prim in m_sceneObjectParts.Values) - { - if (prim.IsRoot) - { -// m_log.DebugFormat( -// "[MOCK REGION DATA PLUGIN]: Loading root part {0} {1} in {2}", prim.Name, prim.UUID, regionUUID); - objects[prim.UUID] = new SceneObjectGroup(prim); - } - } - - // Add all of the children objects to the SOGs - foreach (SceneObjectPart prim in m_sceneObjectParts.Values) - { - SceneObjectGroup sog; - if (prim.UUID != prim.ParentUUID) - { - if (objects.TryGetValue(prim.ParentUUID, out sog)) - { - int originalLinkNum = prim.LinkNum; - - sog.AddPart(prim); - - // SceneObjectGroup.AddPart() tries to be smart and automatically set the LinkNum. - // We override that here - if (originalLinkNum != 0) - prim.LinkNum = originalLinkNum; - } - else - { -// m_log.WarnFormat( -// "[MOCK REGION DATA PLUGIN]: Database contains an orphan child prim {0} {1} in region {2} pointing to missing parent {3}. This prim will not be loaded.", -// prim.Name, prim.UUID, regionUUID, prim.ParentUUID); - } - } - } - - // TODO: Load items. This is assymetric - we store items as a separate method but don't retrieve them that - // way! - - return new List(objects.Values); - } - - public void StoreTerrain(TerrainData ter, UUID regionID) - { - m_terrains[regionID] = ter; - } - - public void StoreBakedTerrain(TerrainData ter, UUID regionID) - { - m_bakedterrains[regionID] = ter; - } - - public void StoreTerrain(double[,] ter, UUID regionID) - { - m_terrains[regionID] = new TerrainData(ter); - } - - public TerrainData LoadTerrain(UUID regionID, int pSizeX, int pSizeY, int pSizeZ) - { - if (m_terrains.ContainsKey(regionID)) - return m_terrains[regionID]; - else - return null; - } - - public TerrainData LoadBakedTerrain(UUID regionID, int pSizeX, int pSizeY, int pSizeZ) - { - if (m_bakedterrains.ContainsKey(regionID)) - return m_bakedterrains[regionID]; - else - return null; - } - - public double[,] LoadTerrain(UUID regionID) - { - if (m_terrains.ContainsKey(regionID)) - return m_terrains[regionID].GetDoubles(); - else - return null; - } - - public void RemoveLandObject(UUID globalID) - { - if (m_landData.ContainsKey(globalID)) - m_landData.Remove(globalID); - } - - public void StoreLandObject(ILandObject land) - { - m_landData[land.LandData.GlobalID] = land.LandData; - } - - public List LoadLandObjects(UUID regionUUID) - { - return new List(m_landData.Values); - } - - public void Shutdown() - { - } - - public UUID[] GetObjectIDs(UUID regionID) - { - return new UUID[0]; - } - - public void SaveExtra(UUID regionID, string name, string value) - { - } - - public void RemoveExtra(UUID regionID, string name) - { - } - - public Dictionary GetExtra(UUID regionID) - { - return null; - } - } -} diff --git a/OpenSim/Tests/Common/Mock/MockScriptEngine.cs b/OpenSim/Tests/Common/Mock/MockScriptEngine.cs deleted file mode 100644 index 2d0947bd846..00000000000 --- a/OpenSim/Tests/Common/Mock/MockScriptEngine.cs +++ /dev/null @@ -1,294 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections; -using System.Collections.Generic; -using System.Reflection; -using Nini.Config; -using OpenMetaverse; -using OpenSim.Framework; -using OpenSim.Region.Framework.Interfaces; -using OpenSim.Region.Framework.Scenes; -using OpenSim.Region.ScriptEngine.Interfaces; -using OpenSim.Region.ScriptEngine.Shared; - -namespace OpenSim.Tests.Common -{ - public class MockScriptEngine : INonSharedRegionModule, IScriptModule, IScriptEngine - { - public IConfigSource ConfigSource { get; private set; } - - public IConfig Config { get; private set; } - - private Scene m_scene; - - /// - /// Expose posted events to tests. - /// - public Dictionary> PostedEvents { get; private set; } - - /// - /// A very primitive way of hooking text cose to a posed event. - /// - /// - /// May be replaced with something that uses more original code in the future. - /// - public event Action PostEventHook; - - public void Initialise(IConfigSource source) - { - ConfigSource = source; - - // Can set later on if required - Config = new IniConfig("MockScriptEngine", ConfigSource); - - PostedEvents = new Dictionary>(); - } - - public void Close() - { - } - - public void AddRegion(Scene scene) - { - m_scene = scene; - - m_scene.StackModuleInterface(this); - } - - public void RemoveRegion(Scene scene) - { - } - - public void RegionLoaded(Scene scene) - { - } - - public string Name { get { return "Mock Script Engine"; } } - public string ScriptEngineName { get { return Name; } } - - public Type ReplaceableInterface { get { return null; } } - -#pragma warning disable 0067 - public event ScriptRemoved OnScriptRemoved; - public event ObjectRemoved OnObjectRemoved; -#pragma warning restore 0067 - - public string GetXMLState (UUID itemID) - { - throw new System.NotImplementedException (); - } - - public bool SetXMLState(UUID itemID, string xml) - { - throw new System.NotImplementedException (); - } - - public void CancelScriptEvent(UUID itemID, string eventName) - { - - } - - public bool PostScriptEvent(UUID itemID, string name, object[] args) - { -// Console.WriteLine("Posting event {0} for {1}", name, itemID); - - return PostScriptEvent(itemID, new EventParams(name, args, null)); - } - - public bool PostScriptEvent(UUID itemID, EventParams evParams) - { - List eventsForItem; - - if (!PostedEvents.ContainsKey(itemID)) - { - eventsForItem = new List(); - PostedEvents.Add(itemID, eventsForItem); - } - else - { - eventsForItem = PostedEvents[itemID]; - } - - eventsForItem.Add(evParams); - - if (PostEventHook != null) - PostEventHook(itemID, evParams); - - return true; - } - - public bool PostObjectEvent(uint localID, EventParams evParams) - { - return PostObjectEvent(m_scene.GetSceneObjectPart(localID), evParams); - } - - public bool PostObjectEvent(UUID itemID, string name, object[] args) - { - return PostObjectEvent(m_scene.GetSceneObjectPart(itemID), new EventParams(name, args, null)); - } - - private bool PostObjectEvent(SceneObjectPart part, EventParams evParams) - { - foreach (TaskInventoryItem item in part.Inventory.GetInventoryItems(InventoryType.LSL)) - PostScriptEvent(item.ItemID, evParams); - - return true; - } - - public bool SuspendScript(UUID itemID) - { - throw new System.NotImplementedException (); - } - - public bool ResumeScript(UUID itemID) - { - throw new System.NotImplementedException (); - } - - public ArrayList GetScriptErrors(UUID itemID) - { - throw new System.NotImplementedException (); - } - - public bool HasScript(UUID itemID, out bool running) - { - throw new System.NotImplementedException (); - } - - public bool GetScriptState(UUID itemID) - { - throw new System.NotImplementedException (); - } - - public void SaveAllState() - { - throw new System.NotImplementedException (); - } - - public void StartProcessing() - { - throw new System.NotImplementedException (); - } - - public float GetScriptExecutionTime(List itemIDs) - { - return 0; - } - - public int GetScriptsMemory(List itemIDs) - { - return 0; - } - - public Dictionary GetObjectScriptsExecutionTimes() - { - throw new System.NotImplementedException (); - } - - public IScriptWorkItem QueueEventHandler(object parms) - { - throw new System.NotImplementedException (); - } - - public DetectParams GetDetectParams(UUID item, int number) - { - throw new System.NotImplementedException (); - } - - public void SetMinEventDelay(UUID itemID, double delay) - { - throw new System.NotImplementedException (); - } - - public int GetStartParameter(UUID itemID) - { - throw new System.NotImplementedException (); - } - - public void SetScriptState(UUID itemID, bool state, bool self) - { - throw new System.NotImplementedException (); - } - - public void SetState(UUID itemID, string newState) - { - throw new System.NotImplementedException (); - } - - public void ApiResetScript(UUID itemID) - { - throw new System.NotImplementedException (); - } - - public void ResetScript (UUID itemID) - { - throw new System.NotImplementedException (); - } - - public IScriptApi GetApi(UUID itemID, string name) - { - throw new System.NotImplementedException (); - } - - public Scene World { get { return m_scene; } } - - public IScriptModule ScriptModule { get { return this; } } - - public string ScriptEnginePath { get { throw new System.NotImplementedException (); }} - - public string ScriptClassName { get { throw new System.NotImplementedException (); } } - - public string ScriptBaseClassName { get { throw new System.NotImplementedException (); } } - - public string[] ScriptReferencedAssemblies { get { throw new System.NotImplementedException (); } } - - public ParameterInfo[] ScriptBaseClassParameters { get { throw new System.NotImplementedException (); } } - - public void ClearPostedEvents() - { - PostedEvents.Clear(); - } - - public void SleepScript(UUID itemID, int delay) - { - } - - public ICollection GetTopObjectStats(float mintime, int minmemory, out float totaltime, out float totalmemory) - { - totaltime = 0; - totalmemory = 0; - return null; - } - - public bool PostObjectLinksetDataEvent(uint localID, int action, ReadOnlySpan name, ReadOnlySpan value) - { - throw new NotImplementedException(); - } - } -} diff --git a/OpenSim/Tests/Common/Mock/TestClient.cs b/OpenSim/Tests/Common/Mock/TestClient.cs deleted file mode 100755 index e7363187671..00000000000 --- a/OpenSim/Tests/Common/Mock/TestClient.cs +++ /dev/null @@ -1,1419 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections.Generic; -using System.Net; -using System.Reflection; -using System.Threading; -using log4net; -using OpenMetaverse; -using OpenMetaverse.Packets; -using OpenSim.Framework; -using OpenSim.Region.Framework.Interfaces; -using OpenSim.Region.Framework.Scenes; -using OpenSim.Framework.Client; - -namespace OpenSim.Tests.Common -{ - public class TestClient : IClientAPI, IClientCore - { - private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - - EventWaitHandle wh = new EventWaitHandle (false, EventResetMode.AutoReset, "Crossing"); - - private Scene m_scene; - - // Properties so that we can get at received data for test purposes - public List ReceivedKills { get; private set; } - public List ReceivedOfflineNotifications { get; private set; } - public List ReceivedOnlineNotifications { get; private set; } - public List ReceivedFriendshipTerminations { get; private set; } - - public List SentImageDataPackets { get; private set; } - public List SentImagePacketPackets { get; private set; } - public List SentImageNotInDatabasePackets { get; private set; } - - // Test client specific events - for use by tests to implement some IClientAPI behaviour. - public event Action OnReceivedMoveAgentIntoRegion; - public event Action OnTestClientInformClientOfNeighbour; - public event TestClientOnSendRegionTeleportDelegate OnTestClientSendRegionTeleport; - - public event Action OnReceivedEntityUpdate; - - public event OnReceivedChatMessageDelegate OnReceivedChatMessage; - public event Action OnReceivedInstantMessage; - - public event Action OnReceivedSendRebakeAvatarTextures; - - public delegate void TestClientOnSendRegionTeleportDelegate( - ulong regionHandle, byte simAccess, IPEndPoint regionExternalEndPoint, - uint locationID, uint flags, string capsURL); - - public delegate void OnReceivedChatMessageDelegate( - string message, byte type, Vector3 fromPos, string fromName, - UUID fromAgentID, UUID ownerID, byte source, byte audible); - - -// disable warning: public events, part of the public API -#pragma warning disable 67 - - public event Action OnLogout; - public event ObjectPermissions OnObjectPermissions; - - public event MoneyTransferRequest OnMoneyTransferRequest; - public event ParcelBuy OnParcelBuy; - public event Action OnConnectionClosed; - public event MoveItemsAndLeaveCopy OnMoveItemsAndLeaveCopy; - public event ImprovedInstantMessage OnInstantMessage; - public event ChatMessage OnChatFromClient; - public event TextureRequest OnRequestTexture; - public event RezObject OnRezObject; - public event ModifyTerrain OnModifyTerrain; - public event BakeTerrain OnBakeTerrain; - public event SetAppearance OnSetAppearance; - public event AvatarNowWearing OnAvatarNowWearing; - public event RezSingleAttachmentFromInv OnRezSingleAttachmentFromInv; - public event RezMultipleAttachmentsFromInv OnRezMultipleAttachmentsFromInv; - public event UUIDNameRequest OnDetachAttachmentIntoInv; - public event ObjectAttach OnObjectAttach; - public event ObjectDeselect OnObjectDetach; - public event ObjectDrop OnObjectDrop; - public event StartAnim OnStartAnim; - public event StopAnim OnStopAnim; - public event ChangeAnim OnChangeAnim; - public event LinkObjects OnLinkObjects; - public event DelinkObjects OnDelinkObjects; - public event RequestMapBlocks OnRequestMapBlocks; - public event RequestMapName OnMapNameRequest; - public event TeleportLocationRequest OnTeleportLocationRequest; - public event TeleportLandmarkRequest OnTeleportLandmarkRequest; - public event TeleportCancel OnTeleportCancel; - public event DisconnectUser OnDisconnectUser; - public event RequestAvatarProperties OnRequestAvatarProperties; - public event SetAlwaysRun OnSetAlwaysRun; - - public event DeRezObject OnDeRezObject; - public event RezRestoreToWorld OnRezRestoreToWorld; - public event Action OnRegionHandShakeReply; - public event GenericCall1 OnRequestWearables; - public event Action OnCompleteMovementToRegion; - public event UpdateAgent OnPreAgentUpdate; - public event UpdateAgent OnAgentUpdate; - public event UpdateAgent OnAgentCameraUpdate; - public event AgentRequestSit OnAgentRequestSit; - public event AgentSit OnAgentSit; - public event AvatarPickerRequest OnAvatarPickerRequest; - public event Action OnRequestAvatarsData; - public event AddNewPrim OnAddPrim; - public event RequestGodlikePowers OnRequestGodlikePowers; - public event GodKickUser OnGodKickUser; - public event ObjectDuplicate OnObjectDuplicate; - public event GrabObject OnGrabObject; - public event DeGrabObject OnDeGrabObject; - public event MoveObject OnGrabUpdate; - public event SpinStart OnSpinStart; - public event SpinObject OnSpinUpdate; - public event SpinStop OnSpinStop; - public event ViewerEffectEventHandler OnViewerEffect; - - public event AgentDataUpdate OnAgentDataUpdateRequest; - public event TeleportLocationRequest OnSetStartLocationRequest; - - public event UpdateShape OnUpdatePrimShape; - public event ObjectExtraParams OnUpdateExtraParams; - public event RequestObjectPropertiesFamily OnRequestObjectPropertiesFamily; - public event ObjectSelect OnObjectSelect; - public event ObjectRequest OnObjectRequest; - public event GenericCall7 OnObjectDescription; - public event GenericCall7 OnObjectName; - public event GenericCall7 OnObjectClickAction; - public event GenericCall7 OnObjectMaterial; - public event UpdatePrimFlags OnUpdatePrimFlags; - public event UpdatePrimTexture OnUpdatePrimTexture; - public event ClientChangeObject onClientChangeObject; - public event UpdateVector OnUpdatePrimGroupPosition; - public event UpdateVector OnUpdatePrimSinglePosition; - public event UpdatePrimRotation OnUpdatePrimGroupRotation; - public event UpdatePrimSingleRotation OnUpdatePrimSingleRotation; - public event UpdatePrimSingleRotationPosition OnUpdatePrimSingleRotationPosition; - public event UpdatePrimGroupRotation OnUpdatePrimGroupMouseRotation; - public event UpdateVector OnUpdatePrimScale; - public event UpdateVector OnUpdatePrimGroupScale; - public event StatusChange OnChildAgentStatus; - public event GenericCall2 OnStopMovement; - public event Action OnRemoveAvatar; - - public event CreateNewInventoryItem OnCreateNewInventoryItem; - public event LinkInventoryItem OnLinkInventoryItem; - public event CreateInventoryFolder OnCreateNewInventoryFolder; - public event UpdateInventoryFolder OnUpdateInventoryFolder; - public event MoveInventoryFolder OnMoveInventoryFolder; - public event RemoveInventoryFolder OnRemoveInventoryFolder; - public event RemoveInventoryItem OnRemoveInventoryItem; - public event FetchInventoryDescendents OnFetchInventoryDescendents; - public event PurgeInventoryDescendents OnPurgeInventoryDescendents; - public event FetchInventory OnFetchInventory; - public event RequestTaskInventory OnRequestTaskInventory; - public event UpdateInventoryItem OnUpdateInventoryItem; - public event CopyInventoryItem OnCopyInventoryItem; - public event MoveInventoryItem OnMoveInventoryItem; - public event UDPAssetUploadRequest OnAssetUploadRequest; - public event RequestTerrain OnRequestTerrain; - public event RequestTerrain OnUploadTerrain; - public event XferReceive OnXferReceive; - public event RequestXfer OnRequestXfer; - public event ConfirmXfer OnConfirmXfer; - public event AbortXfer OnAbortXfer; - public event RezScript OnRezScript; - public event UpdateTaskInventory OnUpdateTaskInventory; - public event MoveTaskInventory OnMoveTaskItem; - public event RemoveTaskInventory OnRemoveTaskItem; - public event RequestAsset OnRequestAsset; - public event GenericMessage OnGenericMessage; - public event UUIDNameRequest OnNameFromUUIDRequest; - public event UUIDNameRequest OnUUIDGroupNameRequest; - - public event ParcelPropertiesRequest OnParcelPropertiesRequest; - public event ParcelDivideRequest OnParcelDivideRequest; - public event ParcelJoinRequest OnParcelJoinRequest; - public event ParcelPropertiesUpdateRequest OnParcelPropertiesUpdateRequest; - public event ParcelAbandonRequest OnParcelAbandonRequest; - public event ParcelGodForceOwner OnParcelGodForceOwner; - public event ParcelReclaim OnParcelReclaim; - public event ParcelReturnObjectsRequest OnParcelReturnObjectsRequest; - public event ParcelAccessListRequest OnParcelAccessListRequest; - public event ParcelAccessListUpdateRequest OnParcelAccessListUpdateRequest; - public event ParcelSelectObjects OnParcelSelectObjects; - public event ParcelObjectOwnerRequest OnParcelObjectOwnerRequest; - public event ParcelDeedToGroup OnParcelDeedToGroup; - public event ObjectDeselect OnObjectDeselect; - public event RegionInfoRequest OnRegionInfoRequest; - public event EstateCovenantRequest OnEstateCovenantRequest; - public event EstateChangeInfo OnEstateChangeInfo; - public event EstateManageTelehub OnEstateManageTelehub; - public event CachedTextureRequest OnCachedTextureRequest; - - public event ObjectDuplicateOnRay OnObjectDuplicateOnRay; - - public event FriendActionDelegate OnApproveFriendRequest; - public event FriendActionDelegate OnDenyFriendRequest; - public event FriendshipTermination OnTerminateFriendship; - public event GrantUserFriendRights OnGrantUserRights; - - public event EconomyDataRequest OnEconomyDataRequest; - public event MoneyBalanceRequest OnMoneyBalanceRequest; - public event UpdateAvatarProperties OnUpdateAvatarProperties; - - public event ObjectIncludeInSearch OnObjectIncludeInSearch; - public event UUIDNameRequest OnTeleportHomeRequest; - - public event ScriptAnswer OnScriptAnswer; - public event RequestPayPrice OnRequestPayPrice; - public event ObjectSaleInfo OnObjectSaleInfo; - public event ObjectBuy OnObjectBuy; - public event BuyObjectInventory OnBuyObjectInventory; - public event AgentSit OnUndo; - public event AgentSit OnRedo; - public event LandUndo OnLandUndo; - - public event ForceReleaseControls OnForceReleaseControls; - - public event GodLandStatRequest OnLandStatRequest; - public event RequestObjectPropertiesFamily OnObjectGroupRequest; - - public event DetailedEstateDataRequest OnDetailedEstateDataRequest; - public event SetEstateFlagsRequest OnSetEstateFlagsRequest; - public event SetEstateTerrainBaseTexture OnSetEstateTerrainBaseTexture; - public event SetEstateTerrainDetailTexture OnSetEstateTerrainDetailTexture; - public event SetEstateTerrainTextureHeights OnSetEstateTerrainTextureHeights; - public event CommitEstateTerrainTextureRequest OnCommitEstateTerrainTextureRequest; - public event SetRegionTerrainSettings OnSetRegionTerrainSettings; - public event EstateRestartSimRequest OnEstateRestartSimRequest; - public event EstateChangeCovenantRequest OnEstateChangeCovenantRequest; - public event UpdateEstateAccessDeltaRequest OnUpdateEstateAccessDeltaRequest; - public event SimulatorBlueBoxMessageRequest OnSimulatorBlueBoxMessageRequest; - public event EstateBlueBoxMessageRequest OnEstateBlueBoxMessageRequest; - public event EstateDebugRegionRequest OnEstateDebugRegionRequest; - public event EstateTeleportOneUserHomeRequest OnEstateTeleportOneUserHomeRequest; - public event EstateTeleportAllUsersHomeRequest OnEstateTeleportAllUsersHomeRequest; - public event ScriptReset OnScriptReset; - public event GetScriptRunning OnGetScriptRunning; - public event SetScriptRunning OnSetScriptRunning; - public event Action OnAutoPilotGo; - - public event TerrainUnacked OnUnackedTerrain; - - public event RegionHandleRequest OnRegionHandleRequest; - public event ParcelInfoRequest OnParcelInfoRequest; - - public event ActivateGesture OnActivateGesture; - public event DeactivateGesture OnDeactivateGesture; - public event ObjectOwner OnObjectOwner; - - public event DirPlacesQuery OnDirPlacesQuery; - public event DirFindQuery OnDirFindQuery; - public event DirLandQuery OnDirLandQuery; - public event DirPopularQuery OnDirPopularQuery; - public event DirClassifiedQuery OnDirClassifiedQuery; - public event EventInfoRequest OnEventInfoRequest; - public event ParcelSetOtherCleanTime OnParcelSetOtherCleanTime; - - public event MapItemRequest OnMapItemRequest; - - public event OfferCallingCard OnOfferCallingCard; - public event AcceptCallingCard OnAcceptCallingCard; - public event DeclineCallingCard OnDeclineCallingCard; - - public event SoundTrigger OnSoundTrigger; - - public event StartLure OnStartLure; - public event TeleportLureRequest OnTeleportLureRequest; - public event NetworkStats OnNetworkStatsUpdate; - - public event ClassifiedInfoRequest OnClassifiedInfoRequest; - public event ClassifiedInfoUpdate OnClassifiedInfoUpdate; - public event ClassifiedDelete OnClassifiedDelete; - public event ClassifiedGodDelete OnClassifiedGodDelete; - - public event EventNotificationAddRequest OnEventNotificationAddRequest; - public event EventNotificationRemoveRequest OnEventNotificationRemoveRequest; - public event EventGodDelete OnEventGodDelete; - - public event ParcelDwellRequest OnParcelDwellRequest; - - public event UserInfoRequest OnUserInfoRequest; - public event UpdateUserInfo OnUpdateUserInfo; - - public event RetrieveInstantMessages OnRetrieveInstantMessages; - - public event PickDelete OnPickDelete; - public event PickGodDelete OnPickGodDelete; - public event PickInfoUpdate OnPickInfoUpdate; - public event AvatarNotesUpdate OnAvatarNotesUpdate; - - public event MuteListRequest OnMuteListRequest; - - public event AvatarInterestUpdate OnAvatarInterestUpdate; - - public event PlacesQuery OnPlacesQuery; - - public event FindAgentUpdate OnFindAgent; - public event TrackAgentUpdate OnTrackAgent; - public event NewUserReport OnUserReport; - public event SaveStateHandler OnSaveState; - public event GroupAccountSummaryRequest OnGroupAccountSummaryRequest; - public event GroupAccountDetailsRequest OnGroupAccountDetailsRequest; - public event GroupAccountTransactionsRequest OnGroupAccountTransactionsRequest; - public event FreezeUserUpdate OnParcelFreezeUser; - public event EjectUserUpdate OnParcelEjectUser; - public event ParcelBuyPass OnParcelBuyPass; - public event ParcelGodMark OnParcelGodMark; - public event GroupActiveProposalsRequest OnGroupActiveProposalsRequest; - public event GroupVoteHistoryRequest OnGroupVoteHistoryRequest; - public event SimWideDeletesDelegate OnSimWideDeletes; - public event SendPostcard OnSendPostcard; - public event ChangeInventoryItemFlags OnChangeInventoryItemFlags; - public event MuteListEntryUpdate OnUpdateMuteListEntry; - public event MuteListEntryRemove OnRemoveMuteListEntry; - public event GodlikeMessage onGodlikeMessage; - public event GodUpdateRegionInfoUpdate OnGodUpdateRegionInfoUpdate; - public event GenericCall2 OnUpdateThrottles; - public event AgentFOV OnAgentFOV; - -#pragma warning restore 67 - - /// - /// This agent's UUID - /// - private UUID m_agentId; - - public ISceneAgent SceneAgent { get; set; } - - public bool SupportObjectAnimations { get; set; } - - /// - /// The last caps seed url that this client was given. - /// - public string CapsSeedUrl; - - private Vector3 startPos = new Vector3(((int)Constants.RegionSize * 0.5f), ((int)Constants.RegionSize * 0.5f), 2); - - public virtual Vector3 StartPos - { - get { return startPos; } - set { } - } - - public float StartFar { get; set; } - - public virtual UUID AgentId - { - get { return m_agentId; } - } - - public UUID SessionId { get; set; } - - public UUID SecureSessionId { get; set; } - - public virtual string FirstName - { - get { return m_firstName; } - } - private string m_firstName; - - public virtual string LastName - { - get { return m_lastName; } - } - private string m_lastName; - - public virtual String Name - { - get { return FirstName + " " + LastName; } - } - - public int PingTimeMS { get { return 0; } } - - public bool IsActive - { - get { return true; } - set { } - } - - public bool IsLoggingOut { get; set; } - - public UUID ActiveGroupId - { - get { return UUID.Zero; } - set { } - } - - public string ActiveGroupName - { - get { return String.Empty; } - set { } - } - - public ulong ActiveGroupPowers - { - get { return 0; } - set { } - } - - public bool IsGroupMember(UUID groupID) - { - return false; - } - - public Dictionary GetGroupPowers() - { - return new Dictionary(); - } - - public void SetGroupPowers(Dictionary powers) { } - - public ulong GetGroupPowers(UUID groupID) - { - return 0; - } - - public virtual int NextAnimationSequenceNumber - { - get { return 1; } - set { } - } - - public IScene Scene - { - get { return m_scene; } - } - - public UUID ScopeId - { - get { return UUID.Zero; } - } - - public bool SendLogoutPacketWhenClosing - { - set { } - } - - private uint m_circuitCode; - - public uint CircuitCode - { - get { return m_circuitCode; } - set { m_circuitCode = value; } - } - - public IPEndPoint RemoteEndPoint - { - get { return new IPEndPoint(IPAddress.Loopback, (ushort)m_circuitCode); } - } - - public List SelectedObjects {get; private set;} - - /// - /// Constructor - /// - /// - /// - /// - public TestClient(AgentCircuitData agentData, Scene scene) - { - m_agentId = agentData.AgentID; - m_firstName = agentData.firstname; - m_lastName = agentData.lastname; - m_circuitCode = agentData.circuitcode; - m_scene = scene; - SessionId = agentData.SessionID; - SecureSessionId = agentData.SecureSessionID; - CapsSeedUrl = agentData.CapsPath; - - ReceivedKills = new List(); - ReceivedOfflineNotifications = new List(); - ReceivedOnlineNotifications = new List(); - ReceivedFriendshipTerminations = new List(); - - SentImageDataPackets = new List(); - SentImagePacketPackets = new List(); - SentImageNotInDatabasePackets = new List(); - } - - /// - /// Trigger chat coming from this connection. - /// - /// - /// - /// - public bool Chat(int channel, ChatTypeEnum type, string message) - { - ChatMessage handlerChatFromClient = OnChatFromClient; - - if (handlerChatFromClient != null) - { - OSChatMessage args = new OSChatMessage(); - args.Channel = channel; - args.From = Name; - args.Message = message; - args.Type = type; - - args.Scene = Scene; - args.Sender = this; - args.SenderUUID = AgentId; - - handlerChatFromClient(this, args); - } - - return true; - } - - /// - /// Attempt a teleport to the given region. - /// - /// - /// - /// - public void Teleport(ulong regionHandle, Vector3 position, Vector3 lookAt) - { - OnTeleportLocationRequest(this, regionHandle, position, lookAt, 16); - } - - public void CompleteMovement() - { - if (OnCompleteMovementToRegion != null) - OnCompleteMovementToRegion(this, true); - } - - /// - /// Emulate sending an IM from the viewer to the simulator. - /// - /// - public void HandleImprovedInstantMessage(GridInstantMessage im) - { - ImprovedInstantMessage handlerInstantMessage = OnInstantMessage; - - if (handlerInstantMessage != null) - handlerInstantMessage(this, im); - } - - public virtual void ActivateGesture(UUID assetId, UUID gestureId) - { - } - - public virtual void SendWearables(AvatarWearable[] wearables, int serial) - { - } - - public virtual void SendAppearance(UUID agentID, byte[] visualParams, byte[] textureEntry, float hover) - { - } - - public void SendCachedTextureResponse(ISceneEntity avatar, int serial, List cachedTextures) - { - - } - - public virtual void Kick(string message) - { - } - - public virtual void SendAvatarPickerReply(UUID QueryID, List users) - { - } - - public virtual void SendAgentDataUpdate(UUID agentid, UUID activegroupid, string firstname, string lastname, ulong grouppowers, string groupname, string grouptitle) - { - } - - public virtual void SendKillObject(List localID) - { - ReceivedKills.AddRange(localID); - } - - public void SendPartFullUpdate(ISceneEntity ent, uint? parentID) - { - } - - public virtual void SetChildAgentThrottle(byte[] throttle) - { - } - - public virtual void SetChildAgentThrottle(byte[] throttle, float factor) - { - } - - public void SetAgentThrottleSilent(int throttle, int setting) - { - } - - public int GetAgentThrottleSilent(int throttle) - { - return 0; - } - - public byte[] GetThrottlesPacked(float multiplier) - { - return Array.Empty(); - } - - public virtual void SendAnimations(UUID[] animations, int[] seqs, UUID sourceAgentId, UUID[] objectIDs) - { - } - - public virtual void SendChatMessage( - string message, byte type, Vector3 fromPos, string fromName, - UUID fromAgentID, UUID ownerID, byte source, byte audible) - { -// Console.WriteLine("mmm {0} {1} {2}", message, Name, AgentId); - if (OnReceivedChatMessage != null) - OnReceivedChatMessage(message, type, fromPos, fromName, fromAgentID, ownerID, source, audible); - } - - public void SendInstantMessage(GridInstantMessage im) - { - if (OnReceivedInstantMessage != null) - OnReceivedInstantMessage(im); - } - - public void SendGenericMessage(string method, UUID invoice, List message) - { - - } - - public void SendGenericMessage(string method, UUID invoice, List message) - { - - } - - public virtual bool CanSendLayerData() - { - return false; - } - - public virtual void SendLayerData() - { - } - - public void SendLayerData(int[] map) - { - } - - public virtual void SendWindData(int version, Vector2[] windSpeeds) { } - - public virtual void MoveAgentIntoRegion(RegionInfo regInfo, Vector3 pos, Vector3 look) - { - if (OnReceivedMoveAgentIntoRegion != null) - OnReceivedMoveAgentIntoRegion(regInfo, pos, look); - } - - public virtual AgentCircuitData RequestClientInfo() - { - AgentCircuitData agentData = new AgentCircuitData(); - agentData.AgentID = AgentId; - agentData.SessionID = SessionId; - agentData.SecureSessionID = UUID.Zero; - agentData.circuitcode = m_circuitCode; - agentData.child = false; - agentData.firstname = m_firstName; - agentData.lastname = m_lastName; - - ICapabilitiesModule capsModule = m_scene.RequestModuleInterface(); - if (capsModule != null) - { - agentData.CapsPath = capsModule.GetCapsPath(m_agentId); - agentData.ChildrenCapSeeds = new Dictionary(capsModule.GetChildrenSeeds(m_agentId)); - } - - return agentData; - } - - public virtual void InformClientOfNeighbour(ulong neighbourHandle, IPEndPoint neighbourExternalEndPoint) - { - if (OnTestClientInformClientOfNeighbour != null) - OnTestClientInformClientOfNeighbour(neighbourHandle, neighbourExternalEndPoint); - } - - public virtual void SendRegionTeleport( - ulong regionHandle, byte simAccess, IPEndPoint regionExternalEndPoint, - uint locationID, uint flags, string capsURL) - { - m_log.DebugFormat( - "[TEST CLIENT]: Received SendRegionTeleport for {0} {1} on {2}", m_firstName, m_lastName, m_scene.Name); - - CapsSeedUrl = capsURL; - - if (OnTestClientSendRegionTeleport != null) - OnTestClientSendRegionTeleport( - regionHandle, simAccess, regionExternalEndPoint, locationID, flags, capsURL); - } - - public virtual void SendTeleportFailed(string reason) - { - m_log.DebugFormat( - "[TEST CLIENT]: Teleport failed for {0} {1} on {2} with reason {3}", - m_firstName, m_lastName, m_scene.Name, reason); - } - - public virtual void CrossRegion(ulong newRegionHandle, Vector3 pos, Vector3 lookAt, - IPEndPoint newRegionExternalEndPoint, string capsURL) - { - // This is supposed to send a packet to the client telling it's ready to start region crossing. - // Instead I will just signal I'm ready, mimicking the communication behavior. - // It's ugly, but avoids needless communication setup. This is used in ScenePresenceTests.cs. - // Arthur V. - - wh.Set(); - } - - public virtual void SendMapBlock(List mapBlocks, uint flag) - { - } - - public virtual void SendLocalTeleport(Vector3 position, Vector3 lookAt, uint flags) - { - } - - public virtual void SendTeleportStart(uint flags) - { - } - - public void SendTeleportProgress(uint flags, string message) - { - } - - public virtual void SendMoneyBalance(UUID transaction, bool success, byte[] description, int balance, int transactionType, UUID sourceID, bool sourceIsGroup, UUID destID, bool destIsGroup, int amount, string item) - { - } - - public virtual void SendPayPrice(UUID objectID, int[] payPrice) - { - } - - public virtual void SendCoarseLocationUpdate(List users, List CoarseLocations) - { - } - - public virtual void SendDialog(string objectname, UUID objectID, UUID ownerID, string ownerFirstName, string ownerLastName, string msg, UUID textureID, int ch, string[] buttonlabels) - { - } - - public void SendEntityFullUpdateImmediate(ISceneEntity ent) - { - } - - public void SendEntityTerseUpdateImmediate(ISceneEntity ent) - { - } - - public void SendEntityUpdate(ISceneEntity entity, PrimUpdateFlags updateFlags) - { - if (OnReceivedEntityUpdate != null) - OnReceivedEntityUpdate(entity, updateFlags); - } - - public void ReprioritizeUpdates() - { - } - - public void FlushPrimUpdates() - { - } - - public void SendInventoryFolderDetails(UUID ownerID, UUID folderID, - List items, - List folders, - int version, - int descendents, - bool fetchFolders, - bool fetchItems) - { - } - - public void SendInventoryItemDetails(InventoryItemBase[] items) - { - } - - public void SendInventoryItemCreateUpdate(InventoryItemBase Item, uint callbackID) - { - } - - public void SendInventoryItemCreateUpdate(InventoryItemBase Item, UUID transactionID, uint callbackId) - { - } - - public void SendRemoveInventoryItem(UUID itemID) - { - } - - public void SendRemoveInventoryItems(UUID[] items) - { - } - - public void SendBulkUpdateInventory(InventoryNodeBase node, UUID? transactionID = null) - { - } - - public void SendBulkUpdateInventory(InventoryFolderBase[] folders, InventoryItemBase[] items) - { - } - - public void SendTakeControls(int controls, bool passToAgent, bool TakeControls) - { - } - - public virtual void SendTaskInventory(UUID taskID, short serial, byte[] fileName) - { - } - - public virtual void SendXferPacket(ulong xferID, uint packet, - byte[] XferData, int XferDataOffset, int XferDatapktLen, bool isTaskInventory) - { - } - - public virtual void SendAbortXferPacket(ulong xferID) - { - - } - - public virtual void SendEconomyData(float EnergyEfficiency, int ObjectCapacity, int ObjectCount, int PriceEnergyUnit, - int PriceGroupCreate, int PriceObjectClaim, float PriceObjectRent, float PriceObjectScaleFactor, - int PriceParcelClaim, float PriceParcelClaimFactor, int PriceParcelRent, int PricePublicObjectDecay, - int PricePublicObjectDelete, int PriceRentLight, int PriceUpload, int TeleportMinPrice, float TeleportPriceExponent) - { - } - - public virtual void SendNameReply(UUID profileId, string firstname, string lastname) - { - } - - public virtual void SendPreLoadSound(UUID objectID, UUID ownerID, UUID soundID) - { - } - - public virtual void SendPlayAttachedSound(UUID soundID, UUID objectID, UUID ownerID, float gain, - byte flags) - { - } - - public void SendTriggeredSound(UUID soundID, UUID ownerID, UUID objectID, UUID parentID, ulong handle, Vector3 position, float gain) - { - } - - public void SendAttachedSoundGainChange(UUID objectID, float gain) - { - - } - - public void SendAlertMessage(string message) - { - } - - public void SendAgentAlertMessage(string message, bool modal) - { - } - - public void SendAlertMessage(string message, string info) - { - } - - public void SendSystemAlertMessage(string message) - { - } - - public void SendLoadURL(string objectname, UUID objectID, UUID ownerID, bool groupOwned, string message, - string url) - { - } - - public virtual void SendRegionHandshake() - { - if (OnRegionHandShakeReply != null) - { - OnRegionHandShakeReply(this); - } - } - - public void SendAssetUploadCompleteMessage(sbyte AssetType, bool Success, UUID AssetFullID) - { - } - - public void SendConfirmXfer(ulong xferID, uint PacketID) - { - } - - public void SendXferRequest(ulong XferID, short AssetType, UUID vFileID, byte FilePath, byte[] FileName) - { - } - - public void SendInitiateDownload(string simFileName, string clientFileName) - { - } - - public void SendImageFirstPart(ushort numParts, UUID ImageUUID, uint ImageSize, byte[] ImageData, byte imageCodec) - { - ImageDataPacket im = new ImageDataPacket(); - im.Header.Reliable = false; - im.ImageID.Packets = numParts; - im.ImageID.ID = ImageUUID; - - if (ImageSize > 0) - im.ImageID.Size = ImageSize; - - im.ImageData.Data = ImageData; - im.ImageID.Codec = imageCodec; - im.Header.Zerocoded = true; - SentImageDataPackets.Add(im); - } - - public void SendImageNextPart(ushort partNumber, UUID imageUuid, byte[] imageData) - { - ImagePacketPacket im = new ImagePacketPacket(); - im.Header.Reliable = false; - im.ImageID.Packet = partNumber; - im.ImageID.ID = imageUuid; - im.ImageData.Data = imageData; - SentImagePacketPackets.Add(im); - } - - public void SendImageNotFound(UUID imageid) - { - ImageNotInDatabasePacket p = new ImageNotInDatabasePacket(); - p.ImageID.ID = imageid; - - SentImageNotInDatabasePackets.Add(p); - } - - public void SendShutdownConnectionNotice() - { - } - - public void SendSimStats(SimStats stats) - { - } - - public void SendObjectPropertiesFamilyData(ISceneEntity Entity, uint RequestFlags) - { - } - - public void SendObjectPropertiesReply(ISceneEntity entity) - { - } - - public void SendAgentOffline(UUID[] agentIDs) - { - ReceivedOfflineNotifications.AddRange(agentIDs); - } - - public void SendAgentOnline(UUID[] agentIDs) - { - ReceivedOnlineNotifications.AddRange(agentIDs); - } - - public void SendFindAgent(UUID HunterID, UUID PreyID, double GlobalX, double GlobalY) - { - } - - public void SendSitResponse(UUID TargetID, Vector3 OffsetPos, - Quaternion SitOrientation, bool autopilot, - Vector3 CameraAtOffset, Vector3 CameraEyeOffset, bool ForceMouseLook) - { - } - - public void SendAdminResponse(UUID Token, uint AdminLevel) - { - } - - public void SendGroupMembership(GroupMembershipData[] GroupMembership) - { - } - - public void SendViewerTime(Vector3 sunDir, float sunphase) - { - } - - public void SendViewerEffect(ViewerEffectPacket.EffectBlock[] effectBlocks) - { - } - - public void SendAvatarProperties(UUID avatarID, string aboutText, string bornOn, Byte[] membershipType, - string flAbout, uint flags, UUID flImageID, UUID imageID, string profileURL, - UUID partnerID) - { - } - - public int DebugPacketLevel { get; set; } - public float FOV { get => throw new NotImplementedException(); set => throw new NotImplementedException(); } - public int viewHeight { get => throw new NotImplementedException(); set => throw new NotImplementedException(); } - public int viewWidth { get => throw new NotImplementedException(); set => throw new NotImplementedException(); } - - public void InPacket(object NewPack) - { - } - - public void ProcessInPacket(Packet NewPack) - { - } - - /// - /// This is a TestClient only method to do shutdown tasks that are normally carried out by LLUDPServer.RemoveClient() - /// - public void Logout() - { - // We must set this here so that the presence is removed from the PresenceService by the PresenceDetector - IsLoggingOut = true; - - Close(); - } - - public void Close() - { - Close(true, false); - } - - public void Close(bool sendStop, bool force) - { - // Fire the callback for this connection closing - // This is necesary to get the presence detector to notice that a client has logged out. - if (OnConnectionClosed != null) - OnConnectionClosed(this); - - m_scene.RemoveClient(AgentId, true); - } - - public void Start() - { - throw new NotImplementedException(); - } - - public void Stop() - { - } - - public void SendBlueBoxMessage(UUID FromAvatarID, String FromAvatarName, String Message) - { - - } - public void SendLogoutPacket() - { - } - - public void Terminate() - { - } - - public ClientInfo GetClientInfo() - { - return null; - } - - public void SetClientInfo(ClientInfo info) - { - } - - public void SendScriptQuestion(UUID objectID, string taskName, string ownerName, UUID itemID, int question) - { - } - public void SendHealth(float health) - { - } - - public void SendTelehubInfo(UUID ObjectID, string ObjectName, Vector3 ObjectPos, Quaternion ObjectRot, List SpawnPoint) - { - } - - public void SendEstateList(UUID invoice, int code, UUID[] Data, uint estateID) - { - } - - public void SendBannedUserList(UUID invoice, EstateBan[] banlist, uint estateID) - { - } - - public void SendRegionInfoToEstateMenu(RegionInfoForEstateMenuArgs args) - { - } - - public void SendEstateCovenantInformation(UUID covenant) - { - } - - public void SendDetailedEstateData(UUID invoice, string estateName, uint estateID, uint parentEstate, uint estateFlags, uint sunPosition, UUID covenant, uint covenantChanged, string abuseEmail, UUID estateOwner) - { - } - - public void SendLandProperties(int sequence_id, bool snap_selection, int request_result, ILandObject lo, float simObjectBonusFactor, int parcelObjectCapacity, int simObjectCapacity, uint regionFlags) - { - } - - public void SendLandAccessListData(List accessList, uint accessFlag, int localLandID) - { - } - - public void SendForceClientSelectObjects(List objectIDs) - { - } - - public void SendCameraConstraint(Vector4 ConstraintPlane) - { - } - - public void SendLandObjectOwners(LandData land, List groups, Dictionary ownersAndCount) - { - } - - public void SendLandParcelOverlay(byte[] data, int sequence_id) - { - } - - public void SendParcelMediaCommand(uint flags, ParcelMediaCommandEnum command, float time) - { - } - - public void SendParcelMediaUpdate(string mediaUrl, UUID mediaTextureID, byte autoScale, string mediaType, - string mediaDesc, int mediaWidth, int mediaHeight, byte mediaLoop) - { - } - - public void SendGroupNameReply(UUID groupLLUID, string GroupName) - { - } - - public void SendLandStatReply(uint reportType, uint requestFlags, uint resultCount, LandStatReportItem[] lsrpia) - { - } - - public void SendScriptRunningReply(UUID objectID, UUID itemID, bool running) - { - } - - public void SendAsset(AssetRequestToClient req) - { - } - - public void SendTexture(AssetBase TextureAsset) - { - - } - - public void SendSetFollowCamProperties (UUID objectID, SortedDictionary parameters) - { - } - - public void SendClearFollowCamProperties (UUID objectID) - { - } - - public void SendRegionHandle (UUID regoinID, ulong handle) - { - } - - public void SendParcelInfo (RegionInfo info, LandData land, UUID parcelID, uint x, uint y) - { - } - - public void SetClientOption(string option, string value) - { - } - - public string GetClientOption(string option) - { - return string.Empty; - } - - public void SendScriptTeleportRequest(string objName, string simName, Vector3 pos, Vector3 lookAt) - { - } - - public void SendDirPlacesReply(UUID queryID, DirPlacesReplyData[] data) - { - } - - public void SendDirPeopleReply(UUID queryID, DirPeopleReplyData[] data) - { - } - - public void SendDirEventsReply(UUID queryID, DirEventsReplyData[] data) - { - } - - public void SendDirGroupsReply(UUID queryID, DirGroupsReplyData[] data) - { - } - - public void SendDirClassifiedReply(UUID queryID, DirClassifiedReplyData[] data) - { - } - - public void SendDirLandReply(UUID queryID, DirLandReplyData[] data) - { - } - - public void SendDirPopularReply(UUID queryID, DirPopularReplyData[] data) - { - } - - public void SendMapItemReply(mapItemReply[] replies, uint mapitemtype, uint flags) - { - } - - public void SendEventInfoReply (EventData info) - { - } - - public void SendOfferCallingCard (UUID destID, UUID transactionID) - { - } - - public void SendAcceptCallingCard (UUID transactionID) - { - } - - public void SendDeclineCallingCard (UUID transactionID) - { - } - - public void SendAvatarGroupsReply(UUID avatarID, GroupMembershipData[] data) - { - } - - public void SendAgentGroupDataUpdate(UUID avatarID, GroupMembershipData[] data) - { - } - - public void SendJoinGroupReply(UUID groupID, bool success) - { - } - - public void SendEjectGroupMemberReply(UUID agentID, UUID groupID, bool succss) - { - } - - public void SendLeaveGroupReply(UUID groupID, bool success) - { - } - - public void SendTerminateFriend(UUID exFriendID) - { - ReceivedFriendshipTerminations.Add(exFriendID); - } - - public bool AddGenericPacketHandler(string MethodName, GenericMessage handler) - { - //throw new NotImplementedException(); - return false; - } - - public void SendAvatarClassifiedReply(UUID targetID, UUID[] classifiedID, string[] name) - { - } - - public void SendClassifiedInfoReply(UUID classifiedID, UUID creatorID, uint creationDate, uint expirationDate, uint category, string name, string description, UUID parcelID, uint parentEstate, UUID snapshotID, string simName, Vector3 globalPos, string parcelName, byte classifiedFlags, int price) - { - } - - public void SendAgentDropGroup(UUID groupID) - { - } - - public void SendAvatarNotesReply(UUID targetID, string text) - { - } - - public void SendAvatarPicksReply(UUID targetID, Dictionary picks) - { - } - - public void SendAvatarClassifiedReply(UUID targetID, Dictionary classifieds) - { - } - - public void SendParcelDwellReply(int localID, UUID parcelID, float dwell) - { - } - - public void SendUserInfoReply(bool imViaEmail, bool visible, string email) - { - } - - public void SendCreateGroupReply(UUID groupID, bool success, string message) - { - } - - public void RefreshGroupMembership() - { - } - - public void UpdateGroupMembership(GroupMembershipData[] data) - { - } - - public void GroupMembershipRemove(UUID GroupID) - { - } - - public void GroupMembershipAddReplace(UUID GroupID,ulong GroupPowers) - { - } - - public void SendUseCachedMuteList() - { - } - - public void SendEmpytMuteList() - { - } - - public void SendMuteListUpdate(string filename) - { - } - - public void SendPickInfoReply(UUID pickID,UUID creatorID, bool topPick, UUID parcelID, string name, string desc, UUID snapshotID, string user, string originalName, string simName, Vector3 posGlobal, int sortOrder, bool enabled) - { - } - - public bool TryGet(out T iface) - { - iface = default(T); - return false; - } - - public T Get() - { - return default(T); - } - - public void Disconnect(string reason) - { - } - - public void Disconnect() - { - } - - public void SendRebakeAvatarTextures(UUID textureID) - { - if (OnReceivedSendRebakeAvatarTextures != null) - OnReceivedSendRebakeAvatarTextures(textureID); - } - - public void SendAvatarInterestsReply(UUID avatarID, uint wantMask, string wantText, uint skillsMask, string skillsText, string languages) - { - } - - public void SendGroupAccountingDetails(IClientAPI sender,UUID groupID, UUID transactionID, UUID sessionID, int amt) - { - } - - public void SendGroupAccountingSummary(IClientAPI sender,UUID groupID, uint moneyAmt, int totalTier, int usedTier) - { - } - - public void SendGroupTransactionsSummaryDetails(IClientAPI sender,UUID groupID, UUID transactionID, UUID sessionID,int amt) - { - } - - public void SendGroupVoteHistory(UUID groupID, UUID transactionID, GroupVoteHistory[] Votes) - { - } - - public void SendGroupActiveProposals(UUID groupID, UUID transactionID, GroupActiveProposals[] Proposals) - { - } - - public void SendChangeUserRights(UUID agentID, UUID friendID, int rights) - { - } - - public void SendTextBoxRequest(string message, int chatChannel, string objectname, UUID ownerID, string ownerFirstName, string ownerLastName, UUID objectId) - { - } - - public void SendAgentTerseUpdate(ISceneEntity presence) - { - } - - public void SendPlacesReply(UUID queryID, UUID transactionID, PlacesReplyData[] data) - { - } - - public void SendSelectedPartsProprieties(List parts) - { - } - - public void SendPartPhysicsProprieties(ISceneEntity entity) - { - } - - public uint GetViewerCaps() - { - return 0x1000; - } - - } -} diff --git a/OpenSim/Tests/Common/Mock/TestEventQueueGetModule.cs b/OpenSim/Tests/Common/Mock/TestEventQueueGetModule.cs deleted file mode 100644 index 2050ac1622b..00000000000 --- a/OpenSim/Tests/Common/Mock/TestEventQueueGetModule.cs +++ /dev/null @@ -1,237 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections; -using System.Collections.Generic; -using System.Net; -using System.Reflection; -using System.Text; -using System.Threading; -using log4net; -using Nini.Config; -using Mono.Addins; -using OpenMetaverse; -using OpenMetaverse.StructuredData; -using OpenSim.Framework; -using OpenSim.Framework.Servers; -using OpenSim.Region.ClientStack.Linden; -using OpenSim.Region.Framework.Interfaces; -using OpenSim.Region.Framework.Scenes; - -namespace OpenSim.Tests.Common -{ - public class TestEventQueueGetModule : IEventQueue, INonSharedRegionModule - { - public class Event - { - public string Name { get; set; } - public object[] Args { get; set; } - - public Event(string name, object[] args) - { - name = Name; - args = Args; - } - } - - public Dictionary> Events { get; set; } - - public void Initialise(IConfigSource source) {} - - public void Close() {} - - public void AddRegion(Scene scene) - { - Events = new Dictionary>(); - scene.RegisterModuleInterface(this); - } - - public void RemoveRegion (Scene scene) {} - - public void RegionLoaded (Scene scene) {} - - public string Name { get { return "TestEventQueueGetModule"; } } - - public Type ReplaceableInterface { get { return null; } } - - private void AddEvent(UUID avatarID, string name, params object[] args) - { - Console.WriteLine("Adding event {0} for {1}", name, avatarID); - - List avEvents; - - if (!Events.ContainsKey(avatarID)) - { - avEvents = new List(); - Events[avatarID] = avEvents; - } - else - { - avEvents = Events[avatarID]; - } - - avEvents.Add(new Event(name, args)); - } - - public void ClearEvents() - { - if (Events != null) - Events.Clear(); - } - - public bool Enqueue(string o, UUID avatarID) - { - AddEvent(avatarID, "Enqueue", o); - return true; - } - public bool Enqueue(byte[] o, UUID avatarID) - { - return true; - } - public bool Enqueue(OSD o, UUID avatarID) - { - return true; - } - public bool Enqueue(osUTF8 o, UUID avatarID) - { - return true; - } - public void EnableSimulator (ulong handle, IPEndPoint endPoint, UUID avatarID, int regionSizeX, int regionSizeY) - { - AddEvent(avatarID, "EnableSimulator", handle); - } - - public void EstablishAgentCommunication (UUID avatarID, IPEndPoint endPoint, string capsPath, - ulong regionHandle, int regionSizeX, int regionSizeY) - { - AddEvent(avatarID, "EstablishAgentCommunication", endPoint, capsPath); - } - - public void TeleportFinishEvent (ulong regionHandle, byte simAccess, IPEndPoint regionExternalEndPoint, - uint locationID, uint flags, string capsURL, UUID agentID, int regionSizeX, int regionSizeY) - { - AddEvent(agentID, "TeleportFinishEvent", regionHandle, simAccess, regionExternalEndPoint, locationID, flags, capsURL); - } - - public void CrossRegion (ulong handle, Vector3 pos, Vector3 lookAt, IPEndPoint newRegionExternalEndPoint, - string capsURL, UUID avatarID, UUID sessionID, int regionSizeX, int regionSizeY) - { - AddEvent(avatarID, "CrossRegion", handle, pos, lookAt, newRegionExternalEndPoint, capsURL, sessionID); - } - - public void ChatterboxInvitation( - UUID sessionID, string sessionName, UUID fromAgent, string message, UUID toAgent, string fromName, - byte dialog, uint timeStamp, bool offline, int parentEstateID, Vector3 position, uint ttl, - UUID transactionID, bool fromGroup, byte[] binaryBucket) - { - AddEvent( - toAgent, "ChatterboxInvitation", sessionID, sessionName, fromAgent, message, toAgent, fromName, dialog, - timeStamp, offline, parentEstateID, position, ttl, transactionID, fromGroup, binaryBucket); - } - - public void ChatterBoxSessionStartReply(UUID sessionID, string sessionName, int type, - bool voiceEnabled, bool voiceModerated, UUID tmpSessionID, - bool sucess, string error, - UUID toAgent) - { - AddEvent(toAgent, "ChatterBoxSessionStartReply", sessionID, sessionName, type, - voiceEnabled, voiceModerated, tmpSessionID, - sucess, error); - } - - public void ChatterBoxSessionAgentListUpdates (UUID sessionID, UUID toAgent, List updates) - { - AddEvent(toAgent, "ChatterBoxSessionAgentListUpdates", sessionID, toAgent, updates); - } - - public void ChatterBoxForceClose (UUID toAgent, UUID sessionID, string reason) - { - AddEvent(toAgent, "ForceCloseChatterBoxSession", sessionID, reason); - } - - public void ParcelProperties (OpenMetaverse.Messages.Linden.ParcelPropertiesMessage parcelPropertiesMessage, UUID avatarID) - { - AddEvent(avatarID, "ParcelProperties", parcelPropertiesMessage); - } - - public void GroupMembershipData(UUID receiverAgent, GroupMembershipData[] data) - { - AddEvent(receiverAgent, "AgentGroupDataUpdate", data); - } - - public void ScriptRunningEvent (UUID objectID, UUID itemID, bool running, UUID avatarID) - { - Console.WriteLine("ONE"); - throw new System.NotImplementedException (); - } - - public byte[] BuildEvent(string eventName, OSD eventBody) - { - Console.WriteLine("TWOoo"); - throw new System.NotImplementedException(); - } - - public void partPhysicsProperties (uint localID, byte physhapetype, float density, float friction, float bounce, float gravmod, UUID avatarID) - { - AddEvent(avatarID, "partPhysicsProperties", localID, physhapetype, density, friction, bounce, gravmod); - } - - public void WindlightRefreshEvent(int interpolate, UUID avatarID) - { - } - - public void SendBulkUpdateInventoryItem(InventoryItemBase item, UUID avatarID, UUID? transationID = null) - { - } - - public osUTF8 StartEvent(string eventName) - { - return null; - } - - public osUTF8 StartEvent(string eventName, int cap) - { - return null; - } - - public byte[] EndEventToBytes(osUTF8 sb) - { - return Array.Empty(); - } - - public void SendLargeGenericMessage(UUID avatarID, UUID? transationID, UUID? sessionID, string method, UUID invoice, List message) - { - throw new NotImplementedException(); - } - - public void SendLargeGenericMessage(UUID avatarID, UUID? transationID, UUID? sessionID, string method, UUID invoice, List message) - { - throw new NotImplementedException(); - } - } -} \ No newline at end of file diff --git a/OpenSim/Tests/Common/Mock/TestGroupsDataPlugin.cs b/OpenSim/Tests/Common/Mock/TestGroupsDataPlugin.cs deleted file mode 100644 index 8e2d8e6c989..00000000000 --- a/OpenSim/Tests/Common/Mock/TestGroupsDataPlugin.cs +++ /dev/null @@ -1,339 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; - -using OpenMetaverse; -using OpenSim.Data; - -namespace OpenSim.Tests.Common.Mock -{ - public class TestGroupsDataPlugin : IGroupsData - { - class CompositeKey - { - private readonly string _key; - public string Key - { - get { return _key; } - } - - public CompositeKey(UUID _k1, string _k2) - { - _key = _k1.ToString() + _k2; - } - - public CompositeKey(UUID _k1, string _k2, string _k3) - { - _key = _k1.ToString() + _k2 + _k3; - } - - public override bool Equals(object obj) - { - if (obj is CompositeKey) - { - return Key == ((CompositeKey)obj).Key; - } - return false; - } - - public override int GetHashCode() - { - return base.GetHashCode(); - } - - public override string ToString() - { - return Key; - } - } - - private Dictionary m_Groups; - private Dictionary m_Membership; - private Dictionary m_Roles; - private Dictionary m_RoleMembership; - private Dictionary m_Invites; - private Dictionary m_Notices; - private Dictionary m_Principals; - - public TestGroupsDataPlugin(string connectionString, string realm) - { - m_Groups = new Dictionary(); - m_Membership = new Dictionary(); - m_Roles = new Dictionary(); - m_RoleMembership = new Dictionary(); - m_Invites = new Dictionary(); - m_Notices = new Dictionary(); - m_Principals = new Dictionary(); - } - - #region groups table - public bool StoreGroup(GroupData data) - { - return false; - } - - public GroupData RetrieveGroup(UUID groupID) - { - if (m_Groups.ContainsKey(groupID)) - return m_Groups[groupID]; - - return null; - } - - public GroupData RetrieveGroup(string name) - { - return m_Groups.Values.First(g => g.Data.ContainsKey("Name") && g.Data["Name"] == name); - } - - public GroupData[] RetrieveGroups(string pattern) - { - if (string.IsNullOrEmpty(pattern)) - pattern = "1"; - - IEnumerable groups = m_Groups.Values.Where(g => g.Data.ContainsKey("Name") && (g.Data["Name"].StartsWith(pattern) || g.Data["Name"].EndsWith(pattern))); - - return (groups != null) ? groups.ToArray() : new GroupData[0]; - } - - public bool DeleteGroup(UUID groupID) - { - return m_Groups.Remove(groupID); - } - - public int GroupsCount() - { - return m_Groups.Count; - } - #endregion - - #region membership table - public MembershipData RetrieveMember(UUID groupID, string pricipalID) - { - CompositeKey dkey = new CompositeKey(groupID, pricipalID); - if (m_Membership.ContainsKey(dkey)) - return m_Membership[dkey]; - - return null; - } - - public MembershipData[] RetrieveMembers(UUID groupID) - { - IEnumerable keys = m_Membership.Keys.Where(k => k.Key.StartsWith(groupID.ToString())); - return keys.Where(m_Membership.ContainsKey).Select(x => m_Membership[x]).ToArray(); - } - - public MembershipData[] RetrieveMemberships(string principalID) - { - IEnumerable keys = m_Membership.Keys.Where(k => k.Key.EndsWith(principalID.ToString())); - return keys.Where(m_Membership.ContainsKey).Select(x => m_Membership[x]).ToArray(); - } - - public MembershipData[] RetrievePrincipalGroupMemberships(string principalID) - { - return RetrieveMemberships(principalID); - } - - public MembershipData RetrievePrincipalGroupMembership(string principalID, UUID groupID) - { - CompositeKey dkey = new CompositeKey(groupID, principalID); - if (m_Membership.ContainsKey(dkey)) - return m_Membership[dkey]; - return null; - } - - public bool StoreMember(MembershipData data) - { - CompositeKey dkey = new CompositeKey(data.GroupID, data.PrincipalID); - m_Membership[dkey] = data; - return true; - } - - public bool DeleteMember(UUID groupID, string principalID) - { - CompositeKey dkey = new CompositeKey(groupID, principalID); - if (m_Membership.ContainsKey(dkey)) - return m_Membership.Remove(dkey); - - return false; - } - - public int MemberCount(UUID groupID) - { - return m_Membership.Count; - } - #endregion - - #region roles table - public bool StoreRole(RoleData data) - { - CompositeKey dkey = new CompositeKey(data.GroupID, data.RoleID.ToString()); - m_Roles[dkey] = data; - return true; - } - - public RoleData RetrieveRole(UUID groupID, UUID roleID) - { - CompositeKey dkey = new CompositeKey(groupID, roleID.ToString()); - if (m_Roles.ContainsKey(dkey)) - return m_Roles[dkey]; - - return null; - } - - public RoleData[] RetrieveRoles(UUID groupID) - { - IEnumerable keys = m_Roles.Keys.Where(k => k.Key.StartsWith(groupID.ToString())); - return keys.Where(m_Roles.ContainsKey).Select(x => m_Roles[x]).ToArray(); - } - - public bool DeleteRole(UUID groupID, UUID roleID) - { - CompositeKey dkey = new CompositeKey(groupID, roleID.ToString()); - if (m_Roles.ContainsKey(dkey)) - return m_Roles.Remove(dkey); - - return false; - } - - public int RoleCount(UUID groupID) - { - return m_Roles.Count; - } - #endregion - - #region rolememberhip table - public RoleMembershipData[] RetrieveRolesMembers(UUID groupID) - { - IEnumerable keys = m_Roles.Keys.Where(k => k.Key.StartsWith(groupID.ToString())); - return keys.Where(m_RoleMembership.ContainsKey).Select(x => m_RoleMembership[x]).ToArray(); - } - - public RoleMembershipData[] RetrieveRoleMembers(UUID groupID, UUID roleID) - { - IEnumerable keys = m_Roles.Keys.Where(k => k.Key.StartsWith(groupID.ToString() + roleID.ToString())); - return keys.Where(m_RoleMembership.ContainsKey).Select(x => m_RoleMembership[x]).ToArray(); - } - - public RoleMembershipData[] RetrieveMemberRoles(UUID groupID, string principalID) - { - IEnumerable keys = m_Roles.Keys.Where(k => k.Key.StartsWith(groupID.ToString()) && k.Key.EndsWith(principalID)); - return keys.Where(m_RoleMembership.ContainsKey).Select(x => m_RoleMembership[x]).ToArray(); - } - - public RoleMembershipData RetrieveRoleMember(UUID groupID, UUID roleID, string principalID) - { - CompositeKey dkey = new CompositeKey(groupID, roleID.ToString(), principalID); - if (m_RoleMembership.ContainsKey(dkey)) - return m_RoleMembership[dkey]; - - return null; - } - - public int RoleMemberCount(UUID groupID, UUID roleID) - { - return m_RoleMembership.Count; - } - - public bool StoreRoleMember(RoleMembershipData data) - { - CompositeKey dkey = new CompositeKey(data.GroupID, data.RoleID.ToString(), data.PrincipalID); - m_RoleMembership[dkey] = data; - return true; - } - - public bool DeleteRoleMember(RoleMembershipData data) - { - CompositeKey dkey = new CompositeKey(data.GroupID, data.RoleID.ToString(), data.PrincipalID); - if (m_RoleMembership.ContainsKey(dkey)) - return m_RoleMembership.Remove(dkey); - - return false; - } - - public bool DeleteMemberAllRoles(UUID groupID, string principalID) - { - List keys = m_RoleMembership.Keys.Where(k => k.Key.StartsWith(groupID.ToString()) && k.Key.EndsWith(principalID)).ToList(); - foreach (CompositeKey k in keys) - m_RoleMembership.Remove(k); - return true; - } - #endregion - - #region principals table - public bool StorePrincipal(PrincipalData data) - { - m_Principals[data.PrincipalID] = data; - return true; - } - - public PrincipalData RetrievePrincipal(string principalID) - { - if (m_Principals.ContainsKey(principalID)) - return m_Principals[principalID]; - - return null; - } - - public bool DeletePrincipal(string principalID) - { - if (m_Principals.ContainsKey(principalID)) - return m_Principals.Remove(principalID); - return false; - } - #endregion - - #region invites table - public bool StoreInvitation(InvitationData data) - { - return false; - } - - public InvitationData RetrieveInvitation(UUID inviteID) - { - return null; - } - - public InvitationData RetrieveInvitation(UUID groupID, string principalID) - { - return null; - } - - public bool DeleteInvite(UUID inviteID) - { - return false; - } - - public void DeleteOldInvites() - { - } - #endregion - - #region notices table - public bool StoreNotice(NoticeData data) - { - return false; - } - - public NoticeData RetrieveNotice(UUID noticeID) - { - return null; - } - - public NoticeData[] RetrieveNotices(UUID groupID) - { - return new NoticeData[0]; - } - - public bool DeleteNotice(UUID noticeID) - { - return false; - } - - public void DeleteOldNotices() - { - } - #endregion - - } -} diff --git a/OpenSim/Tests/Common/Mock/TestHttpClientContext.cs b/OpenSim/Tests/Common/Mock/TestHttpClientContext.cs deleted file mode 100644 index 72938304921..00000000000 --- a/OpenSim/Tests/Common/Mock/TestHttpClientContext.cs +++ /dev/null @@ -1,112 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections.Generic; -using System.IO; -using System.Net; -using System.Net.Sockets; -using System.Text; -using OSHttpServer; -using OpenSim.Framework; - -namespace OpenSim.Tests.Common -{ -/* - public class TestHttpClientContext: IHttpClientContext - { - /// - /// Bodies of responses from the server. - /// - public string ResponseBody - { - get { return Encoding.UTF8.GetString(m_responseStream.ToArray()); } - } - - public Byte[] ResponseBodyBytes - { - get{ return m_responseStream.ToArray(); } - } - - private MemoryStream m_responseStream = new MemoryStream(); - - public bool IsSecured { get; set; } - - public bool Secured - { - get { return IsSecured; } - set { IsSecured = value; } - } - - public TestHttpClientContext(bool secured) - { - Secured = secured; - } - - public void Disconnect(SocketError error) - { -// Console.WriteLine("TestHttpClientContext.Disconnect Received disconnect with status {0}", error); - } - - public void Respond(string httpVersion, HttpStatusCode statusCode, string reason, string body) {Console.WriteLine("x");} - public void Respond(string httpVersion, HttpStatusCode statusCode, string reason) {Console.WriteLine("xx");} - public void Respond(string body) { Console.WriteLine("xxx");} - - public void Send(byte[] buffer) - { - // Getting header data here -// Console.WriteLine("xxxx: Got {0}", Encoding.UTF8.GetString(buffer)); - } - - public void Send(byte[] buffer, int offset, int size) - { -// Util.PrintCallStack(); -// -// Console.WriteLine( -// "TestHttpClientContext.Send(byte[], int, int) got offset={0}, size={1}, buffer={2}", -// offset, size, Encoding.UTF8.GetString(buffer)); - - m_responseStream.Write(buffer, offset, size); - } - - public void Respond(string httpVersion, HttpStatusCode statusCode, string reason, string body, string contentType) {Console.WriteLine("xxxxxx");} - public void Close() { } - public bool EndWhenDone { get { return false;} set { return;}} - - public HTTPNetworkContext GiveMeTheNetworkStreamIKnowWhatImDoing() - { - return new HTTPNetworkContext(); - } - - public event EventHandler Disconnected = delegate { }; - /// - /// A request have been received in the context. - /// - public event EventHandler RequestReceived = delegate { }; - } -*/ -} \ No newline at end of file diff --git a/OpenSim/Tests/Common/Mock/TestHttpRequest.cs b/OpenSim/Tests/Common/Mock/TestHttpRequest.cs deleted file mode 100644 index b69c70db5cd..00000000000 --- a/OpenSim/Tests/Common/Mock/TestHttpRequest.cs +++ /dev/null @@ -1,175 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections.Specialized; -using System.IO; -using OSHttpServer; - -namespace OpenSim.Tests.Common -{ -/* - public class TestHttpRequest: IHttpRequest - { - private string _uriPath; - public bool BodyIsComplete - { - get { return true; } - } - public string[] AcceptTypes - { - get {return _acceptTypes; } - } - private string[] _acceptTypes; - public Stream Body - { - get { return _body; } - set { _body = value;} - } - private Stream _body; - public ConnectionType Connection - { - get { return _connection; } - set { _connection = value; } - } - private ConnectionType _connection; - public int ContentLength - { - get { return _contentLength; } - set { _contentLength = value; } - } - private int _contentLength; - public NameValueCollection Headers - { - get { return _headers; } - } - private NameValueCollection _headers = new NameValueCollection(); - - public string HttpVersion { get; set; } - - public string Method - { - get { return _method; } - set { _method = value; } - } - private string _method = null; - public HttpInput QueryString - { - get { return _queryString; } - } - private HttpInput _queryString = null; - public Uri Uri - { - get { return _uri; } - set { _uri = value; } - } - private Uri _uri = null; - public string[] UriParts - { - get { return _uri.Segments; } - } - public HttpParam Param - { - get { return null; } - } - public HttpForm Form - { - get { return null; } - } - public bool IsAjax - { - get { return false; } - } - public RequestCookies Cookies - { - get { return null; } - } - - public TestHttpRequest() - { - HttpVersion = "HTTP/1.1"; - } - - public TestHttpRequest(string contentEncoding, string contentType, string userAgent, - string remoteAddr, string remotePort, string[] acceptTypes, - ConnectionType connectionType, int contentLength, Uri uri) : base() - { - _headers["content-encoding"] = contentEncoding; - _headers["content-type"] = contentType; - _headers["user-agent"] = userAgent; - _headers["remote_addr"] = remoteAddr; - _headers["remote_port"] = remotePort; - - _acceptTypes = acceptTypes; - _connection = connectionType; - _contentLength = contentLength; - _uri = uri; - } - - public void DecodeBody(FormDecoderProvider providers) {} - public void SetCookies(RequestCookies cookies) {} - public void AddHeader(string name, string value) - { - _headers.Add(name, value); - } - public int AddToBody(byte[] bytes, int offset, int length) - { - return 0; - } - public void Clear() {} - - public object Clone() - { - TestHttpRequest clone = new TestHttpRequest(); - clone._acceptTypes = _acceptTypes; - clone._connection = _connection; - clone._contentLength = _contentLength; - clone._uri = _uri; - clone._headers = new NameValueCollection(_headers); - - return clone; - } - public IHttpResponse CreateResponse(IHttpClientContext context) - { - return new HttpResponse(context, this); - } - /// - /// Path and query (will be merged with the host header) and put in Uri - /// - /// - public string UriPath - { - get { return _uriPath; } - set - { - _uriPath = value; - - } - } - } -*/ -} \ No newline at end of file diff --git a/OpenSim/Tests/Common/Mock/TestHttpResponse.cs b/OpenSim/Tests/Common/Mock/TestHttpResponse.cs deleted file mode 100644 index f6f789819c9..00000000000 --- a/OpenSim/Tests/Common/Mock/TestHttpResponse.cs +++ /dev/null @@ -1,173 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.IO; -using System.Net; -using System.Text; -using OSHttpServer; - -namespace OpenSim.Tests.Common -{ -/* - public class TestHttpResponse: IHttpResponse - { - public Stream Body - { - get { return _body; } - - set { _body = value; } - } - private Stream _body; - - public string ProtocolVersion - { - get { return _protocolVersion; } - set { _protocolVersion = value; } - } - private string _protocolVersion; - - public bool Chunked - { - get { return _chunked; } - - set { _chunked = value; } - } - private bool _chunked; - - public ConnectionType Connection - { - get { return _connection; } - - set { _connection = value; } - } - private ConnectionType _connection; - - public Encoding Encoding - { - get { return _encoding; } - - set { _encoding = value; } - } - private Encoding _encoding; - - public int KeepAlive - { - get { return _keepAlive; } - - set { _keepAlive = value; } - } - private int _keepAlive; - - public HttpStatusCode Status - { - get { return _status; } - - set { _status = value; } - } - private HttpStatusCode _status; - - public string Reason - { - get { return _reason; } - - set { _reason = value; } - } - private string _reason; - - public long ContentLength - { - get { return _contentLength; } - - set { _contentLength = value; } - } - private long _contentLength; - - public string ContentType - { - get { return _contentType; } - - set { _contentType = value; } - } - private string _contentType; - - public bool HeadersSent - { - get { return _headersSent; } - } - private bool _headersSent; - - public bool Sent - { - get { return _sent; } - } - private bool _sent; - - public ResponseCookies Cookies - { - get { return _cookies; } - } - private ResponseCookies _cookies = null; - - public TestHttpResponse() - { - _headersSent = false; - _sent = false; - } - - public void AddHeader(string name, string value) {} - - public void Send() - { - if (!_headersSent) SendHeaders(); - if (_sent) throw new InvalidOperationException("stuff already sent"); - _sent = true; - } - - public void SendBody(byte[] buffer, int offset, int count) - { - if (!_headersSent) SendHeaders(); - _sent = true; - } - - public void SendBody(byte[] buffer) - { - if (!_headersSent) SendHeaders(); - _sent = true; - } - - public void SendHeaders() - { - if (_headersSent) throw new InvalidOperationException("headers already sent"); - _headersSent = true; - } - - public void Redirect(Uri uri) {} - public void Redirect(string url) {} - } -*/ -} \ No newline at end of file diff --git a/OpenSim/Tests/Common/Mock/TestInventoryDataPlugin.cs b/OpenSim/Tests/Common/Mock/TestInventoryDataPlugin.cs deleted file mode 100644 index 04cda547bd1..00000000000 --- a/OpenSim/Tests/Common/Mock/TestInventoryDataPlugin.cs +++ /dev/null @@ -1,219 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections.Generic; -using System.Reflection; -using log4net; -using OpenMetaverse; -using OpenSim.Framework; -using OpenSim.Data; - -namespace OpenSim.Tests.Common -{ - /// - /// In memory inventory data plugin for test purposes. Could be another dll when properly filled out and when the - /// mono addin plugin system starts co-operating with the unit test system. Currently no locking since unit - /// tests are single threaded. - /// - public class TestInventoryDataPlugin : IInventoryDataPlugin - { -// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - - /// - /// Inventory folders - /// - private Dictionary m_folders = new Dictionary(); - - //// - /// Inventory items - /// - private Dictionary m_items = new Dictionary(); - - /// - /// User root folders - /// - private Dictionary m_rootFolders = new Dictionary(); - - public string Version { get { return "0"; } } - public string Name { get { return "TestInventoryDataPlugin"; } } - - public void Initialise() {} - public void Initialise(string connect) {} - public void Dispose() {} - - public List getFolderHierarchy(UUID parentID) - { - List folders = new List(); - - foreach (InventoryFolderBase folder in m_folders.Values) - { - if (folder.ParentID == parentID) - { - folders.AddRange(getFolderHierarchy(folder.ID)); - folders.Add(folder); - } - } - - return folders; - } - - public List getInventoryInFolder(UUID folderID) - { -// InventoryFolderBase folder = m_folders[folderID]; - -// m_log.DebugFormat("[MOCK INV DB]: Getting items in folder {0} {1}", folder.Name, folder.ID); - - List items = new List(); - - foreach (InventoryItemBase item in m_items.Values) - { - if (item.Folder == folderID) - { -// m_log.DebugFormat("[MOCK INV DB]: getInventoryInFolder() adding item {0}", item.Name); - items.Add(item); - } - } - - return items; - } - - public List getUserRootFolders(UUID user) { return null; } - - public InventoryFolderBase getUserRootFolder(UUID user) - { -// m_log.DebugFormat("[MOCK INV DB]: Looking for root folder for {0}", user); - - InventoryFolderBase folder = null; - m_rootFolders.TryGetValue(user, out folder); - - return folder; - } - - public List getInventoryFolders(UUID parentID) - { -// InventoryFolderBase parentFolder = m_folders[parentID]; - -// m_log.DebugFormat("[MOCK INV DB]: Getting folders in folder {0} {1}", parentFolder.Name, parentFolder.ID); - - List folders = new List(); - - foreach (InventoryFolderBase folder in m_folders.Values) - { - if (folder.ParentID == parentID) - { -// m_log.DebugFormat( -// "[MOCK INV DB]: Found folder {0} {1} in {2} {3}", -// folder.Name, folder.ID, parentFolder.Name, parentFolder.ID); - - folders.Add(folder); - } - } - - return folders; - } - - public InventoryFolderBase getInventoryFolder(UUID folderId) - { - InventoryFolderBase folder = null; - m_folders.TryGetValue(folderId, out folder); - - return folder; - } - - public InventoryFolderBase queryInventoryFolder(UUID folderID) - { - return getInventoryFolder(folderID); - } - - public void addInventoryFolder(InventoryFolderBase folder) - { -// m_log.DebugFormat( -// "[MOCK INV DB]: Adding inventory folder {0} {1} type {2}", -// folder.Name, folder.ID, (AssetType)folder.Type); - - m_folders[folder.ID] = folder; - - if (folder.ParentID.IsZero()) - { -// m_log.DebugFormat( -// "[MOCK INV DB]: Adding root folder {0} {1} for {2}", folder.Name, folder.ID, folder.Owner); - m_rootFolders[folder.Owner] = folder; - } - } - - public void updateInventoryFolder(InventoryFolderBase folder) - { - m_folders[folder.ID] = folder; - } - - public void moveInventoryFolder(InventoryFolderBase folder) - { - // Simple replace - updateInventoryFolder(folder); - } - - public void deleteInventoryFolder(UUID folderId) - { - if (m_folders.ContainsKey(folderId)) - m_folders.Remove(folderId); - } - - public void addInventoryItem(InventoryItemBase item) - { - InventoryFolderBase folder = m_folders[item.Folder]; - -// m_log.DebugFormat( -// "[MOCK INV DB]: Adding inventory item {0} {1} in {2} {3}", item.Name, item.ID, folder.Name, folder.ID); - - m_items[item.ID] = item; - } - - public void updateInventoryItem(InventoryItemBase item) { addInventoryItem(item); } - - public void deleteInventoryItem(UUID itemId) - { - if (m_items.ContainsKey(itemId)) - m_items.Remove(itemId); - } - - public InventoryItemBase getInventoryItem(UUID itemId) - { - if (m_items.ContainsKey(itemId)) - return m_items[itemId]; - else - return null; - } - - public InventoryItemBase queryInventoryItem(UUID item) - { - return null; - } - - public List fetchActiveGestures(UUID avatarID) { return null; } - } -} diff --git a/OpenSim/Tests/Common/Mock/TestLLUDPServer.cs b/OpenSim/Tests/Common/Mock/TestLLUDPServer.cs deleted file mode 100644 index d32d1b5510c..00000000000 --- a/OpenSim/Tests/Common/Mock/TestLLUDPServer.cs +++ /dev/null @@ -1,171 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections.Generic; -using System.Net; -using System.Net.Sockets; -using Nini.Config; -using OpenMetaverse.Packets; -using OpenSim.Framework; -using OpenSim.Region.ClientStack.LindenUDP; - -namespace OpenSim.Tests.Common -{ - /// - /// This class enables regression testing of the LLUDPServer by allowing us to intercept outgoing data. - /// - public class TestLLUDPServer : LLUDPServer - { - public List PacketsSent { get; private set; } - - public TestLLUDPServer(IPAddress listenIP, uint port, int proxyPortOffsetParm, IConfigSource configSource, AgentCircuitManager circuitManager) - : base(listenIP, port, proxyPortOffsetParm, configSource, circuitManager) - { - PacketsSent = new List(); - } - - public override void SendAckImmediate(IPEndPoint remoteEndpoint, PacketAckPacket ack) - { - PacketsSent.Add(ack); - } - - public override void SendPacket( - LLUDPClient udpClient, Packet packet, ThrottleOutPacketType category, bool allowSplitting, UnackedPacketMethod method) - { - PacketsSent.Add(packet); - } - - public void ClientOutgoingPacketHandler(IClientAPI client, bool resendUnacked, bool sendAcks, bool sendPing) - { - m_resendUnacked = resendUnacked; - m_sendAcks = sendAcks; - m_sendPing = sendPing; - - ClientOutgoingPacketHandler(client); - } - -//// /// -//// /// The chunks of data to pass to the LLUDPServer when it calls EndReceive -//// /// -//// protected Queue m_chunksToLoad = new Queue(); -// -//// protected override void BeginReceive() -//// { -//// if (m_chunksToLoad.Count > 0 && m_chunksToLoad.Peek().BeginReceiveException) -//// { -//// ChunkSenderTuple tuple = m_chunksToLoad.Dequeue(); -//// reusedEpSender = tuple.Sender; -//// throw new SocketException(); -//// } -//// } -// -//// protected override bool EndReceive(out int numBytes, IAsyncResult result, ref EndPoint epSender) -//// { -//// numBytes = 0; -//// -//// //m_log.Debug("Queue size " + m_chunksToLoad.Count); -//// -//// if (m_chunksToLoad.Count <= 0) -//// return false; -//// -//// ChunkSenderTuple tuple = m_chunksToLoad.Dequeue(); -//// RecvBuffer = tuple.Data; -//// numBytes = tuple.Data.Length; -//// epSender = tuple.Sender; -//// -//// return true; -//// } -// -//// public override void SendPacketTo(byte[] buffer, int size, SocketFlags flags, uint circuitcode) -//// { -//// // Don't do anything just yet -//// } -// -// /// -// /// Signal that this chunk should throw an exception on Socket.BeginReceive() -// /// -// /// -// public void LoadReceiveWithBeginException(EndPoint epSender) -// { -// ChunkSenderTuple tuple = new ChunkSenderTuple(epSender); -// tuple.BeginReceiveException = true; -// m_chunksToLoad.Enqueue(tuple); -// } -// -// /// -// /// Load some data to be received by the LLUDPServer on the next receive call -// /// -// /// -// /// -// public void LoadReceive(byte[] data, EndPoint epSender) -// { -// m_chunksToLoad.Enqueue(new ChunkSenderTuple(data, epSender)); -// } -// -// /// -// /// Load a packet to be received by the LLUDPServer on the next receive call -// /// -// /// -// public void LoadReceive(Packet packet, EndPoint epSender) -// { -// LoadReceive(packet.ToBytes(), epSender); -// } -// -// /// -// /// Calls the protected asynchronous result method. This fires out all data chunks currently queued for send -// /// -// /// -// public void ReceiveData(IAsyncResult result) -// { -// // Doesn't work the same way anymore -//// while (m_chunksToLoad.Count > 0) -//// OnReceivedData(result); -// } - } - - /// - /// Record the data and sender tuple - /// - public class ChunkSenderTuple - { - public byte[] Data; - public EndPoint Sender; - public bool BeginReceiveException; - - public ChunkSenderTuple(byte[] data, EndPoint sender) - { - Data = data; - Sender = sender; - } - - public ChunkSenderTuple(EndPoint sender) - { - Sender = sender; - } - } -} diff --git a/OpenSim/Tests/Common/Mock/TestLandChannel.cs b/OpenSim/Tests/Common/Mock/TestLandChannel.cs deleted file mode 100644 index 38a4a2a476d..00000000000 --- a/OpenSim/Tests/Common/Mock/TestLandChannel.cs +++ /dev/null @@ -1,130 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System.Collections.Generic; -using OpenMetaverse; -using OpenSim.Framework; -using OpenSim.Region.Framework.Interfaces; -using OpenSim.Region.Framework.Scenes; -using OpenSim.Region.CoreModules.World.Land; - -namespace OpenSim.Tests.Common -{ - /// - /// Land channel for test purposes - /// - public class TestLandChannel : ILandChannel - { - private Scene m_scene; - private List m_parcels; - - public float BanLineSafeHeight { get { return 100f; } } - - public TestLandChannel(Scene scene) - { - m_scene = scene; - m_parcels = new List(); - SetupDefaultParcel(); - } - - private void SetupDefaultParcel() - { - ILandObject obj = new LandObject(UUID.Zero, false, m_scene); - obj.LandData.Name = "Your Parcel"; - m_parcels.Add(obj); - } - - public List ParcelsNearPoint(Vector3 position) - { - return new List(); - } - - public List AllParcels() - { - return m_parcels; - } - - public void Clear(bool setupDefaultParcel) - { - m_parcels.Clear(); - - if (setupDefaultParcel) - SetupDefaultParcel(); - } - - protected ILandObject GetNoLand() - { - ILandObject obj = new LandObject(UUID.Zero, false, m_scene); - obj.LandData.Name = "NO LAND"; - return obj; - } - - public ILandObject GetLandObject(Vector3 position) - { - return GetLandObject(position.X, position.Y); - } - - public ILandObject GetLandObject(int x, int y) - { - return GetNoLand(); - } - - public ILandObject GetLandObjectClippedXY(float x, float y) - { - return GetNoLand(); - } - - public ILandObject GetLandObject(int localID) - { - return GetNoLand(); - } - - public ILandObject GetLandObject(UUID ID) - { - return GetNoLand(); - } - - public ILandObject GetLandObject(float x, float y) - { - return GetNoLand(); - } - - public bool IsLandPrimCountTainted() { return false; } - public bool IsForcefulBansAllowed() { return false; } - public void UpdateLandObject(int localID, LandData data) {} - public void SendParcelsOverlay(IClientAPI client) {} - public void ReturnObjectsInParcel(int localID, uint returnType, UUID[] agentIDs, UUID[] taskIDs, IClientAPI remoteClient) {} - public void setParcelObjectMaxOverride(overrideParcelMaxPrimCountDelegate overrideDel) {} - public void setSimulatorObjectMaxOverride(overrideSimulatorMaxPrimCountDelegate overrideDel) {} - public void SetParcelOtherCleanTime(IClientAPI remoteClient, int localID, int otherCleanTime) {} - - public void Join(int start_x, int start_y, int end_x, int end_y, UUID attempting_user_id) {} - public void Subdivide(int start_x, int start_y, int end_x, int end_y, UUID attempting_user_id) {} - public void sendClientInitialLandInfo(IClientAPI remoteClient, bool overlay) { } - public void ClearAllEnvironments(){ } - } -} \ No newline at end of file diff --git a/OpenSim/Tests/Common/Mock/TestOSHttpRequest.cs b/OpenSim/Tests/Common/Mock/TestOSHttpRequest.cs deleted file mode 100644 index 722ab704787..00000000000 --- a/OpenSim/Tests/Common/Mock/TestOSHttpRequest.cs +++ /dev/null @@ -1,192 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections; -using System.Collections.Generic; -using System.Collections.Specialized; -using System.IO; -using System.Net; -using System.Text; -using System.Web; -using OpenSim.Framework.Servers.HttpServer; - -namespace OpenSim.Tests.Common -{ - public class TestOSHttpRequest : IOSHttpRequest - { - public string[] AcceptTypes - { - get - { - throw new NotImplementedException (); - } - } - - public Encoding ContentEncoding - { - get - { - throw new NotImplementedException (); - } - } - - public long ContentLength - { - get - { - throw new NotImplementedException (); - } - } - - public long ContentLength64 - { - get - { - throw new NotImplementedException (); - } - } - - public string ContentType - { - get - { - throw new NotImplementedException (); - } - } - - - public bool HasEntityBody - { - get - { - throw new NotImplementedException (); - } - } - - public NameValueCollection Headers { get; set; } - - public string HttpMethod - { - get - { - throw new NotImplementedException (); - } - } - - public Stream InputStream { get; set;} - - public bool IsSecured - { - get - { - throw new NotImplementedException (); - } - } - - public bool KeepAlive - { - get - { - throw new NotImplementedException (); - } - } - - public NameValueCollection QueryString - { - get - { - throw new NotImplementedException (); - } - } - - public Hashtable Query - { - get - { - throw new NotImplementedException(); - } - } - - public Dictionary QueryAsDictionary - { - get - { - throw new NotImplementedException(); - } - } - - public HashSet QueryFlags - { - get - { - throw new NotImplementedException(); - } - } - - public string RawUrl - { - get - { - throw new NotImplementedException (); - } - } - - public IPEndPoint RemoteIPEndPoint - { - get - { - throw new NotImplementedException(); - } - } - - public IPEndPoint LocalIPEndPoint - { - get - { - throw new NotImplementedException(); - } - } - - public Uri Url { get; set; } - public string UriPath { get;} - public double ArrivalTS { get; } - - public string UserAgent - { - get - { - throw new NotImplementedException (); - } - } - - public TestOSHttpRequest() - { - Headers = new NameValueCollection(); - } - } -} \ No newline at end of file diff --git a/OpenSim/Tests/Common/Mock/TestOSHttpResponse.cs b/OpenSim/Tests/Common/Mock/TestOSHttpResponse.cs deleted file mode 100644 index 6afcb05d8ab..00000000000 --- a/OpenSim/Tests/Common/Mock/TestOSHttpResponse.cs +++ /dev/null @@ -1,139 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections.Generic; -using System.IO; -using System.Net; -using System.Text; -using OpenSim.Framework.Servers.HttpServer; - -namespace OpenSim.Tests.Common -{ - public class TestOSHttpResponse : IOSHttpResponse - { - /// - /// Content type property. - /// - /// - /// Setting this property will also set IsContentTypeSet to - /// true. - /// - public string ContentType { get; set; } - - /// - /// Boolean property indicating whether the content type - /// property actively has been set. - /// - /// - /// IsContentTypeSet will go away together with .NET base. - /// - // public bool IsContentTypeSet - // { - // get { return _contentTypeSet; } - // } - // private bool _contentTypeSet; - - /// - /// Length of the body content; 0 if there is no body. - /// - public long ContentLength { get; set; } - - /// - /// Alias for ContentLength. - /// - public long ContentLength64 { get; set; } - - public int Priority { get; set; } - public byte[] RawBuffer { get; set; } - public int RawBufferStart { get; set; } - public int RawBufferLen { get; set; } - - /// - /// Encoding of the body content. - /// - public Encoding ContentEncoding { get; set; } - - public bool KeepAlive { get; set; } - - /// - /// Get or set the keep alive timeout property (default is - /// 20). Setting this to 0 also disables KeepAlive. Setting - /// this to something else but 0 also enable KeepAlive. - /// - public int KeepAliveTimeout { get; set; } - - /// - /// Return the output stream feeding the body. - /// - /// - /// On its way out... - /// - public Stream OutputStream { get; private set; } - - public string ProtocolVersion { get; set; } - - /// - /// Return the output stream feeding the body. - /// - public Stream Body { get; private set; } - - /// - /// Chunk transfers. - /// - public bool SendChunked { get; set; } - - /// - /// HTTP status code. - /// - public int StatusCode { get; set; } - - /// - /// HTTP status description. - /// - public string StatusDescription { get; set; } - - public double RequestTS { get; } - - /// - /// Set response as a http redirect - /// - /// redirection target url - /// the response Status, must be Redirect, Moved,MovedPermanently,RedirectKeepVerb, RedirectMethod, TemporaryRedirect. Defaults to Redirect - public void Redirect(string url, HttpStatusCode redirStatusCode = HttpStatusCode.Redirect) { throw new NotImplementedException(); } - /// - /// Add a header field and content to the response. - /// - /// string containing the header field - /// name - /// string containing the header field - /// value - public void AddHeader(string key, string value) { throw new NotImplementedException(); } - - public void Send() { } - } -} \ No newline at end of file diff --git a/OpenSim/Tests/Common/Mock/TestScene.cs b/OpenSim/Tests/Common/Mock/TestScene.cs deleted file mode 100644 index 0b3d4465fc1..00000000000 --- a/OpenSim/Tests/Common/Mock/TestScene.cs +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using Nini.Config; -using OpenSim.Framework; - -using OpenSim.Framework.Servers; -using OpenSim.Region.Framework; -using OpenSim.Region.Framework.Interfaces; -using OpenSim.Region.Framework.Scenes; -using OpenSim.Region.PhysicsModules.SharedBase; -using OpenSim.Services.Interfaces; - -namespace OpenSim.Tests.Common -{ - public class TestScene : Scene - { - public TestScene( - RegionInfo regInfo, AgentCircuitManager authen, - ISimulationDataService simDataService, IEstateDataService estateDataService, - IConfigSource config, string simulatorVersion) - : base(regInfo, authen, simDataService, estateDataService, - config, simulatorVersion) - { - } - - ~TestScene() - { - //Console.WriteLine("TestScene destructor called for {0}", RegionInfo.RegionName); - Console.WriteLine("TestScene destructor called"); - } - - /// - /// Temporarily override session authentication for tests (namely teleport). - /// - /// - /// TODO: This needs to be mocked out properly. - /// - /// - /// - public override bool VerifyUserPresence(AgentCircuitData agent, out string reason) - { - reason = String.Empty; - return true; - } - - public AsyncSceneObjectGroupDeleter SceneObjectGroupDeleter - { - get { return m_asyncSceneObjectDeleter; } - } - } -} diff --git a/OpenSim/Tests/Common/Mock/TestXInventoryDataPlugin.cs b/OpenSim/Tests/Common/Mock/TestXInventoryDataPlugin.cs deleted file mode 100644 index a48315e1de8..00000000000 --- a/OpenSim/Tests/Common/Mock/TestXInventoryDataPlugin.cs +++ /dev/null @@ -1,172 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Reflection; -using log4net; -using OpenMetaverse; -using OpenSim.Framework; -using OpenSim.Data; -using OpenSim.Data.Null; - -namespace OpenSim.Tests.Common -{ - public class TestXInventoryDataPlugin : NullGenericDataHandler, IXInventoryData - { - private Dictionary m_allFolders = new Dictionary(); - private Dictionary m_allItems = new Dictionary(); - - public TestXInventoryDataPlugin(string conn, string realm) {} - - public XInventoryItem[] GetItems(string[] fields, string[] vals) - { -// Console.WriteLine( -// "Requesting items, fields {0}, vals {1}", string.Join(", ", fields), string.Join(", ", vals)); - - List origItems = Get(fields, vals, m_allItems.Values.ToList()); - - XInventoryItem[] items = origItems.Select(i => i.Clone()).ToArray(); - -// Console.WriteLine("Found {0} items", items.Length); -// Array.ForEach(items, i => Console.WriteLine("Found item {0} {1}", i.inventoryName, i.inventoryID)); - - return items; - } - - public XInventoryFolder[] GetFolders(string[] fields, string[] vals) - { -// Console.WriteLine( -// "Requesting folders, fields {0}, vals {1}", string.Join(", ", fields), string.Join(", ", vals)); - - List origFolders - = Get(fields, vals, m_allFolders.Values.ToList()); - - XInventoryFolder[] folders = origFolders.Select(f => f.Clone()).ToArray(); - -// Console.WriteLine("Found {0} folders", folders.Length); -// Array.ForEach(folders, f => Console.WriteLine("Found folder {0} {1}", f.folderName, f.folderID)); - - return folders; - } - - public bool StoreFolder(XInventoryFolder folder) - { - m_allFolders[folder.folderID] = folder.Clone(); - -// Console.WriteLine("Added folder {0} {1}", folder.folderName, folder.folderID); - - return true; - } - - public bool StoreItem(XInventoryItem item) - { - m_allItems[item.inventoryID] = item.Clone(); - -// Console.WriteLine( -// "Added item {0} {1}, folder {2}, creator {3}, owner {4}", -// item.inventoryName, item.inventoryID, item.parentFolderID, item.creatorID, item.avatarID); - - return true; - } - - public bool DeleteFolders(string field, string val) - { - return DeleteFolders(new string[] { field }, new string[] { val }); - } - - public bool DeleteFolders(string[] fields, string[] vals) - { - XInventoryFolder[] foldersToDelete = GetFolders(fields, vals); - Array.ForEach(foldersToDelete, f => m_allFolders.Remove(f.folderID)); - - return true; - } - - public bool DeleteItems(string field, string val) - { - return DeleteItems(new string[] { field }, new string[] { val }); - } - - public bool DeleteItems(string[] fields, string[] vals) - { - XInventoryItem[] itemsToDelete = GetItems(fields, vals); - Array.ForEach(itemsToDelete, i => m_allItems.Remove(i.inventoryID)); - - return true; - } - - public bool MoveItem(string id, string newParent) - { - UUID uid = new UUID(id); - UUID upid = new UUID(newParent); - m_allItems[uid].parentFolderID = upid; - return true; - } - - public bool MoveItems(string[] ids, string[] newParents) - { - if(ids.Length != newParents.Length) - return false; - for(int i =0; i< ids.Length;++i) - MoveItem(ids[i], newParents[i]); - return true; - } - - public bool MoveFolder(string id, string newParent) - { - // Don't use GetFolders() here - it takes a clone! - XInventoryFolder folder = m_allFolders[new UUID(id)]; - - if (folder == null) - return false; - - folder.parentFolderID = new UUID(newParent); - -// XInventoryFolder[] newParentFolders -// = GetFolders(new string[] { "folderID" }, new string[] { folder.parentFolderID.ToString() }); - -// Console.WriteLine( -// "Moved folder {0} {1}, to {2} {3}", -// folder.folderName, folder.folderID, newParentFolders[0].folderName, folder.parentFolderID); - - // TODO: Really need to implement folder version incrementing, though this should be common code anyway, - // not reimplemented in each db plugin. - - return true; - } - - public XInventoryItem[] GetActiveGestures(UUID principalID) { throw new NotImplementedException(); } - public int GetAssetPermissions(UUID principalID, UUID assetID) { throw new NotImplementedException(); } - - public XInventoryFolder[] GetFolder(string field, string val) - { - throw new NotImplementedException(); - } - } -} \ No newline at end of file diff --git a/OpenSim/Tests/Common/OpenSim.Tests.Common.csproj b/OpenSim/Tests/Common/OpenSim.Tests.Common.csproj deleted file mode 100644 index 52037adc5c1..00000000000 --- a/OpenSim/Tests/Common/OpenSim.Tests.Common.csproj +++ /dev/null @@ -1,56 +0,0 @@ - - - net8.0 - - - - - - - - - - - - - ..\..\..\bin\Nini.dll - False - - - ..\..\..\bin\OpenMetaverse.dll - False - - - ..\..\..\bin\OpenMetaverse.StructuredData.dll - False - - - ..\..\..\bin\OpenMetaverseTypes.dll - False - - - False - - - False - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/OpenSim/Tests/Common/OpenSimTestCase.cs b/OpenSim/Tests/Common/OpenSimTestCase.cs deleted file mode 100644 index 9fea34820c9..00000000000 --- a/OpenSim/Tests/Common/OpenSimTestCase.cs +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using NUnit.Framework; -using OpenSim.Framework; -using OpenSim.Framework.Servers; - -namespace OpenSim.Tests.Common -{ - [TestFixture] - public class OpenSimTestCase - { - [SetUp] - public virtual void SetUp() - { - //TestHelpers.InMethod(); - // Disable logging for each test so that one where logging is enabled doesn't cause all subsequent tests - // to have logging on if it failed with an exception. - TestHelpers.DisableLogging(); - - // This is an unfortunate bit of clean up we have to do because MainServer manages things through static - // variables and the VM is not restarted between tests. - if (MainServer.Instance != null) - { - MainServer.RemoveHttpServer(MainServer.Instance.Port); -// MainServer.Instance = null; - } - } - } -} \ No newline at end of file diff --git a/OpenSim/Tests/Common/QuaternionToleranceConstraint.cs b/OpenSim/Tests/Common/QuaternionToleranceConstraint.cs deleted file mode 100644 index b38c382f53b..00000000000 --- a/OpenSim/Tests/Common/QuaternionToleranceConstraint.cs +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using OpenMetaverse; -using NUnit.Framework; -using NUnit.Framework.Constraints; - -namespace OpenSim.Tests.Common -{ - public class QuaternionToleranceConstraint : ANumericalToleranceConstraint - { - private Quaternion _baseValue; - private Quaternion _valueToBeTested; - - public QuaternionToleranceConstraint(Quaternion baseValue, double tolerance) : base(tolerance) - { - _baseValue = baseValue; - } - - /// - /// Test whether the constraint is satisfied by a given value - /// - /// The value to be tested - /// - /// True for success, false for failure - /// - public override bool Matches(object valueToBeTested) - { - if (valueToBeTested == null) - { - throw new ArgumentException("Constraint cannot be used upon null values."); - } - if (valueToBeTested.GetType() != typeof (Quaternion)) - { - throw new ArgumentException("Constraint cannot be used upon non quaternion values."); - } - - _valueToBeTested = (Quaternion)valueToBeTested; - - return (IsWithinDoubleConstraint(_valueToBeTested.X, _baseValue.X) && - IsWithinDoubleConstraint(_valueToBeTested.Y, _baseValue.Y) && - IsWithinDoubleConstraint(_valueToBeTested.Z, _baseValue.Z) && - IsWithinDoubleConstraint(_valueToBeTested.W, _baseValue.W)); - } - - public override void WriteDescriptionTo(MessageWriter writer) - { - writer.WriteExpectedValue( - string.Format("A value {0} within tolerance of plus or minus {1}", _baseValue, _tolerance)); - } - - public override void WriteActualValueTo(MessageWriter writer) - { - writer.WriteActualValue(_valueToBeTested); - } - } -} \ No newline at end of file diff --git a/OpenSim/Tests/Common/TestHelpers.cs b/OpenSim/Tests/Common/TestHelpers.cs deleted file mode 100644 index 2b2af346705..00000000000 --- a/OpenSim/Tests/Common/TestHelpers.cs +++ /dev/null @@ -1,164 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Diagnostics; -using System.IO; -using System.Text; -using NUnit.Framework; -using OpenMetaverse; - -namespace OpenSim.Tests.Common -{ - public class TestHelpers - { - private static Stream EnableLoggingConfigStream - = new MemoryStream( - Encoding.UTF8.GetBytes( -@" - - - - - - - - - - - - - - - - -")); - - private static MemoryStream DisableLoggingConfigStream - = new MemoryStream( - Encoding.UTF8.GetBytes( -// "")); - //""))); -// "")); -// ""))); -// "")); - "")); - - public static bool AssertThisDelegateCausesArgumentException(TestDelegate d) - { - try - { - d(); - } - catch(ArgumentException) - { - return true; - } - - return false; - } - - /// - /// A debugging method that can be used to print out which test method you are in - /// - public static void InMethod() - { - StackTrace stackTrace = new StackTrace(); - Console.WriteLine(); - Console.WriteLine("===> In Test Method : {0} <===", stackTrace.GetFrame(1).GetMethod().Name); - } - - public static void EnableLogging() - { - log4net.Config.XmlConfigurator.Configure(EnableLoggingConfigStream); - EnableLoggingConfigStream.Position = 0; - } - - /// - /// Disable logging whilst running the tests. - /// - /// - /// Remember, if a regression test throws an exception before completing this will not be invoked if it's at - /// the end of the test. - /// TODO: Always invoke this after every test - probably need to make all test cases inherit from a common - /// TestCase class where this can be done. - /// - public static void DisableLogging() - { - log4net.Config.XmlConfigurator.Configure(DisableLoggingConfigStream); - DisableLoggingConfigStream.Position = 0; - } - - /// - /// Parse a UUID stem into a full UUID. - /// - /// - /// The fragment will come at the start of the UUID. The rest will be 0s - /// - /// - /// - /// A UUID fragment that will be parsed into a full UUID. Therefore, it can only contain - /// cahracters which are valid in a UUID, except for "-" which is currently only allowed if a full UUID is - /// given as the 'fragment'. - /// - public static UUID ParseStem(string stem) - { - string rawUuid = stem.PadRight(32, '0'); - - return UUID.Parse(rawUuid); - } - - /// - /// Parse tail section into full UUID. - /// - /// - /// - public static UUID ParseTail(int tail) - { - return new UUID(string.Format("00000000-0000-0000-0000-{0:X12}", tail)); - } - - /// - /// Parse a UUID tail section into a full UUID. - /// - /// - /// The fragment will come at the end of the UUID. The rest will be 0s - /// - /// - /// - /// A UUID fragment that will be parsed into a full UUID. Therefore, it can only contain - /// cahracters which are valid in a UUID, except for "-" which is currently only allowed if a full UUID is - /// given as the 'fragment'. - /// - public static UUID ParseTail(string stem) - { - string rawUuid = stem.PadLeft(32, '0'); - - return UUID.Parse(rawUuid); - } - } -} diff --git a/OpenSim/Tests/Common/TestLogging.cs b/OpenSim/Tests/Common/TestLogging.cs deleted file mode 100644 index 4a08344321c..00000000000 --- a/OpenSim/Tests/Common/TestLogging.cs +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections.Generic; -using System.Text; -using log4net.Appender; -using log4net.Layout; - -namespace OpenSim.Tests.Common -{ - public static class TestLogging - { - public static void LogToConsole() - { - ConsoleAppender consoleAppender = new ConsoleAppender(); - consoleAppender.Layout = - new PatternLayout("%date [%thread] %-5level %logger [%property{NDC}] - %message%newline"); - log4net.Config.BasicConfigurator.Configure(consoleAppender); - } - } -} diff --git a/OpenSim/Tests/Common/TestsAssetCache.cs b/OpenSim/Tests/Common/TestsAssetCache.cs deleted file mode 100644 index faa8a95111b..00000000000 --- a/OpenSim/Tests/Common/TestsAssetCache.cs +++ /dev/null @@ -1,145 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Reflection; -using Nini.Config; -using OpenSim.Framework; -using OpenSim.Region.Framework.Interfaces; -using OpenSim.Region.Framework.Scenes; -using log4net; - -namespace OpenSim.Tests.Common -{ - public class TestsAssetCache : ISharedRegionModule, IAssetCache - { - - private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - - private bool m_Enabled; - public MemoryCache m_Cache; - - public string Name - { - get { return "TestsAssetCache"; } - } - - public Type ReplaceableInterface - { - get { return null; } - } - - public void Initialise(IConfigSource source) - { - m_Cache = MemoryCache.Default; - m_Enabled = true; - } - - public void PostInitialise() - { - } - - public void Close() - { - } - - public void AddRegion(Scene scene) - { - if (m_Enabled) - scene.RegisterModuleInterface(this); - } - - public void RemoveRegion(Scene scene) - { - } - - public void RegionLoaded(Scene scene) - { - } - - //////////////////////////////////////////////////////////// - // IAssetCache - // - public bool Check(string id) - { - // XXX This is probably not an efficient implementation. - AssetBase asset; - if (!Get(id, out asset)) - return false; - return asset != null; - } - - public void Cache(AssetBase asset, bool replace = true) - { - if (asset != null) - { - //CacheItemPolicy policy = new CacheItemPolicy(); - //m_Cache.Set(asset.ID, asset, policy); - } - } - - public void CacheNegative(string id) - { - // We don't do negative caching - } - - public bool Get(string id, out AssetBase asset) - { - //asset = (AssetBase)m_Cache.Get(id); - asset = null; - return true; - } - - public bool GetFromMemory(string id, out AssetBase asset) - { - //asset = (AssetBase)m_Cache.Get(id); - asset = null; - return true; - } - - public AssetBase GetCached(string id) - { - //return (AssetBase)m_Cache.Get(id); - return null; - } - - public void Expire(string id) - { - //m_Cache.Remove(id); - } - - public void Clear() - { - } - /* - public bool UpdateContent(string id, byte[] data) - { - return false; - } - */ - } -} diff --git a/OpenSim/Tests/Common/VectorToleranceConstraint.cs b/OpenSim/Tests/Common/VectorToleranceConstraint.cs deleted file mode 100644 index 2fa20edec92..00000000000 --- a/OpenSim/Tests/Common/VectorToleranceConstraint.cs +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using OpenMetaverse; -using NUnit.Framework; -using NUnit.Framework.Constraints; - -namespace OpenSim.Tests.Common -{ - public class VectorToleranceConstraint : ANumericalToleranceConstraint - { - private Vector3 _baseValue; - private Vector3 _valueToBeTested; - - public VectorToleranceConstraint(Vector3 baseValue, double tolerance) : base(tolerance) - { - _baseValue = baseValue; - } - - /// - ///Test whether the constraint is satisfied by a given value - /// - ///The value to be tested - /// - ///True for success, false for failure - /// - public override bool Matches(object valueToBeTested) - { - if (valueToBeTested == null) - { - throw new ArgumentException("Constraint cannot be used upon null values."); - } - if (valueToBeTested.GetType() != typeof (Vector3)) - { - throw new ArgumentException("Constraint cannot be used upon non vector values."); - } - - _valueToBeTested = (Vector3) valueToBeTested; - - return (IsWithinDoubleConstraint(_valueToBeTested.X, _baseValue.X) && - IsWithinDoubleConstraint(_valueToBeTested.Y, _baseValue.Y) && - IsWithinDoubleConstraint(_valueToBeTested.Z, _baseValue.Z)); - } - - public override void WriteDescriptionTo(MessageWriter writer) - { - writer.WriteExpectedValue( - string.Format("A value {0} within tolerance of plus or minus {1}", _baseValue, _tolerance)); - } - - public override void WriteActualValueTo(MessageWriter writer) - { - writer.WriteActualValue(_valueToBeTested); - } - } -} diff --git a/OpenSim/Tests/ConfigurationLoaderTest.cs b/OpenSim/Tests/ConfigurationLoaderTest.cs deleted file mode 100644 index a14f1672c8f..00000000000 --- a/OpenSim/Tests/ConfigurationLoaderTest.cs +++ /dev/null @@ -1,150 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System.IO; -using Nini.Config; -using NUnit.Framework; -using OpenSim.Framework; -using OpenSim.Tests.Common; - -namespace OpenSim.Tests -{ - [TestFixture] - public class ConfigurationLoaderTests : OpenSimTestCase - { - private const string m_testSubdirectory = "test"; - private string m_basePath; - private string m_workingDirectory; - private IConfigSource m_config; - - /// - /// Set up a test directory. - /// - [SetUp] - public override void SetUp() - { - base.SetUp(); - - m_basePath = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName()); - string path = Path.Combine(m_basePath, m_testSubdirectory); - Directory.CreateDirectory(path); - m_workingDirectory = Directory.GetCurrentDirectory(); - Directory.SetCurrentDirectory(path); - } - - /// - /// Remove the test directory. - /// - [TearDown] - public void TearDown() - { - Directory.SetCurrentDirectory(m_workingDirectory); - Directory.Delete(m_basePath, true); - } - - /// - /// Test the including of ini files with absolute and relative paths. - /// - [Test] - public void IncludeTests() - { - const string mainIniFile = "OpenSimDefaults.ini"; - m_config = new IniConfigSource(); - - // Create ini files in a directory structure - IniConfigSource ini; - IConfig config; - - ini = new IniConfigSource(); - config = ini.AddConfig("IncludeTest"); - config.Set("Include-absolute", "absolute/one/config/setting.ini"); - config.Set("Include-absolute1", "absolute/two/config/setting1.ini"); - config.Set("Include-absolute2", "absolute/two/config/setting2.ini"); - config.Set("Include-relative", "../" + m_testSubdirectory + "/relative/one/config/setting.ini"); - config.Set("Include-relative1", "../" + m_testSubdirectory + "/relative/two/config/setting1.ini"); - config.Set("Include-relative2", "../" + m_testSubdirectory + "/relative/two/config/setting2.ini"); - CreateIni(mainIniFile, ini); - - ini = new IniConfigSource(); - ini.AddConfig("Absolute1").Set("name1", "value1"); - CreateIni("absolute/one/config/setting.ini", ini); - - ini = new IniConfigSource(); - ini.AddConfig("Absolute2").Set("name2", 2.3); - CreateIni("absolute/two/config/setting1.ini", ini); - - ini = new IniConfigSource(); - ini.AddConfig("Absolute2").Set("name3", "value3"); - CreateIni("absolute/two/config/setting2.ini", ini); - - ini = new IniConfigSource(); - ini.AddConfig("Relative1").Set("name4", "value4"); - CreateIni("relative/one/config/setting.ini", ini); - - ini = new IniConfigSource(); - ini.AddConfig("Relative2").Set("name5", true); - CreateIni("relative/two/config/setting1.ini", ini); - - ini = new IniConfigSource(); - ini.AddConfig("Relative2").Set("name6", 6); - CreateIni("relative/two/config/setting2.ini", ini); - - // Prepare call to ConfigurationLoader.LoadConfigSettings() - ConfigurationLoader cl = new ConfigurationLoader(); - IConfigSource argvSource = new IniConfigSource(); - EnvConfigSource envConfigSource = new EnvConfigSource(); - argvSource.AddConfig("Startup").Set("inifile", mainIniFile); - argvSource.AddConfig("Network"); - ConfigSettings configSettings; - NetworkServersInfo networkInfo; - - OpenSimConfigSource source = cl.LoadConfigSettings(argvSource, envConfigSource, - out configSettings, out networkInfo); - - // Remove default config - config = source.Source.Configs["Startup"]; - source.Source.Configs.Remove(config); - config = source.Source.Configs["Network"]; - source.Source.Configs.Remove(config); - - // Finally, we are able to check the result - Assert.AreEqual(m_config.ToString(), source.Source.ToString(), - "Configuration with includes does not contain all settings."); - } - - private void CreateIni(string filepath, IniConfigSource source) - { - string path = Path.GetDirectoryName(filepath); - if (path != string.Empty) - { - Directory.CreateDirectory(path); - } - source.Save(filepath); - m_config.Merge(source); - } - } -} diff --git a/OpenSim/Tests/OpenSim.Tests.csproj b/OpenSim/Tests/OpenSim.Tests.csproj deleted file mode 100644 index ee535b89d24..00000000000 --- a/OpenSim/Tests/OpenSim.Tests.csproj +++ /dev/null @@ -1,81 +0,0 @@ - - - net8.0 - - - - ..\..\bin\Nini.dll - False - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/OpenSim/Tests/Performance/NPCPerformanceTests.cs b/OpenSim/Tests/Performance/NPCPerformanceTests.cs deleted file mode 100644 index b064dca8fb1..00000000000 --- a/OpenSim/Tests/Performance/NPCPerformanceTests.cs +++ /dev/null @@ -1,189 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.Reflection; -using log4net; -using Nini.Config; -using NUnit.Framework; -using OpenMetaverse; -using OpenSim.Framework; - -using OpenSim.Region.CoreModules.Avatar.Attachments; -using OpenSim.Region.CoreModules.Avatar.AvatarFactory; -using OpenSim.Region.CoreModules.Framework.InventoryAccess; -using OpenSim.Region.CoreModules.Framework.UserManagement; -using OpenSim.Region.CoreModules.ServiceConnectorsOut.Avatar; -using OpenSim.Region.Framework.Interfaces; -using OpenSim.Region.Framework.Scenes; -using OpenSim.Region.OptionalModules.World.NPC; -using OpenSim.Services.AvatarService; -using OpenSim.Tests.Common; - -namespace OpenSim.Tests.Performance -{ - /// - /// NPC performance tests - /// - /// - /// Don't rely on the numbers given by these tests - they will vary a lot depending on what is already cached, - /// how much memory is free, etc. In some cases, later larger tests will apparently take less time than smaller - /// earlier tests. - /// - [TestFixture] - public class NPCPerformanceTests : OpenSimTestCase - { - private TestScene scene; - private AvatarFactoryModule afm; - private UserManagementModule umm; - private AttachmentsModule am; - - [OneTimeSetUp] - public void FixtureInit() - { - // Don't allow tests to be bamboozled by asynchronous events. Execute everything on the same thread. - Util.FireAndForgetMethod = FireAndForgetMethod.None; - } - - [OneTimeTearDown] - public void TearDown() - { - scene.Close(); - scene = null; - GC.Collect(); - GC.WaitForPendingFinalizers(); - - // We must set this back afterwards, otherwise later tests will fail since they're expecting multiple - // threads. Possibly, later tests should be rewritten not to worry about such things. - Util.FireAndForgetMethod = Util.DefaultFireAndForgetMethod; - } - - [SetUp] - public void Init() - { - IConfigSource config = new IniConfigSource(); - config.AddConfig("NPC"); - config.Configs["NPC"].Set("Enabled", "true"); - config.AddConfig("Modules"); - config.Configs["Modules"].Set("InventoryAccessModule", "BasicInventoryAccessModule"); - - afm = new AvatarFactoryModule(); - umm = new UserManagementModule(); - am = new AttachmentsModule(); - - scene = new SceneHelpers().SetupScene(); - SceneHelpers.SetupSceneModules(scene, config, afm, umm, am, new BasicInventoryAccessModule(), new NPCModule()); - } - - [Test] - public void Test_0001_AddRemove100NPCs() - { - TestHelpers.InMethod(); -// log4net.Config.XmlConfigurator.Configure(); - - TestAddRemoveNPCs(100); - } - - [Test] - public void Test_0002_AddRemove1000NPCs() - { - TestHelpers.InMethod(); -// log4net.Config.XmlConfigurator.Configure(); - - TestAddRemoveNPCs(1000); - } - - [Test] - public void Test_0003_AddRemove2000NPCs() - { - TestHelpers.InMethod(); -// log4net.Config.XmlConfigurator.Configure(); - - TestAddRemoveNPCs(2000); - } - - private void TestAddRemoveNPCs(int numberOfNpcs) - { - ScenePresence sp = SceneHelpers.AddScenePresence(scene, TestHelpers.ParseTail(0x1)); -// ScenePresence originalAvatar = scene.GetScenePresence(originalClient.AgentId); - - // 8 is the index of the first baked texture in AvatarAppearance - UUID originalFace8TextureId = TestHelpers.ParseTail(0x10); - Primitive.TextureEntry originalTe = new Primitive.TextureEntry(UUID.Zero); - Primitive.TextureEntryFace originalTef = originalTe.CreateFace(8); - originalTef.TextureID = originalFace8TextureId; - - // We also need to add the texture to the asset service, otherwise the AvatarFactoryModule will tell - // ScenePresence.SendInitialData() to reset our entire appearance. - scene.AssetService.Store(AssetHelpers.CreateNotecardAsset(originalFace8TextureId)); - - afm.SetAppearance(sp, originalTe, null, new WearableCacheItem[0]); - - INPCModule npcModule = scene.RequestModuleInterface(); - - List npcs = new List(); - - long startGcMemory = GC.GetTotalMemory(true); - Stopwatch sw = new Stopwatch(); - sw.Start(); - - for (int i = 0; i < numberOfNpcs; i++) - { - npcs.Add( - npcModule.CreateNPC("John", "Smith", new Vector3(128, 128, 30), UUID.Zero, true, scene, sp.Appearance)); - } - - for (int i = 0; i < numberOfNpcs; i++) - { - Assert.That(npcs[i], Is.Not.Null); - - ScenePresence npc = scene.GetScenePresence(npcs[i]); - Assert.That(npc, Is.Not.Null); - } - - for (int i = 0; i < numberOfNpcs; i++) - { - Assert.That(npcModule.DeleteNPC(npcs[i], scene), Is.True); - ScenePresence npc = scene.GetScenePresence(npcs[i]); - Assert.That(npc, Is.Null); - } - - sw.Stop(); - - long endGcMemory = GC.GetTotalMemory(true); - - Console.WriteLine("Took {0} ms", sw.ElapsedMilliseconds); - Console.WriteLine( - "End {0} MB, Start {1} MB, Diff {2} MB", - endGcMemory / 1024 / 1024, - startGcMemory / 1024 / 1024, - (endGcMemory - startGcMemory) / 1024 / 1024); - } - } -} diff --git a/OpenSim/Tests/Performance/ObjectPerformanceTests.cs b/OpenSim/Tests/Performance/ObjectPerformanceTests.cs deleted file mode 100644 index 9dad423a5fe..00000000000 --- a/OpenSim/Tests/Performance/ObjectPerformanceTests.cs +++ /dev/null @@ -1,174 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Diagnostics; -using System.Reflection; -using log4net; -using NUnit.Framework; -using OpenMetaverse; -using OpenSim.Framework; -using OpenSim.Region.Framework.Scenes; -using OpenSim.Tests.Common; - -namespace OpenSim.Tests.Performance -{ - /// - /// Object performance tests - /// - /// - /// Don't rely on the numbers given by these tests - they will vary a lot depending on what is already cached, - /// how much memory is free, etc. In some cases, later larger tests will apparently take less time than smaller - /// earlier tests. - /// - [TestFixture] - public class ObjectPerformanceTests : OpenSimTestCase - { - [TearDown] - public void TearDown() - { - GC.Collect(); - GC.WaitForPendingFinalizers(); - } - -// [Test] -// public void Test0000Clean() -// { -// TestHelpers.InMethod(); -//// log4net.Config.XmlConfigurator.Configure(); -// -// TestAddObjects(200000); -// } - - [Test] - public void Test_0001_10K_1PrimObjects() - { - TestHelpers.InMethod(); -// log4net.Config.XmlConfigurator.Configure(); - - TestAddObjects(1, 10000); - } - - [Test] - public void Test_0002_100K_1PrimObjects() - { - TestHelpers.InMethod(); -// log4net.Config.XmlConfigurator.Configure(); - - TestAddObjects(1, 100000); - } - - [Test] - public void Test_0003_200K_1PrimObjects() - { - TestHelpers.InMethod(); -// log4net.Config.XmlConfigurator.Configure(); - - TestAddObjects(1, 200000); - } - - [Test] - public void Test_0011_100_100PrimObjects() - { - TestHelpers.InMethod(); -// log4net.Config.XmlConfigurator.Configure(); - - TestAddObjects(100, 100); - } - - [Test] - public void Test_0012_1K_100PrimObjects() - { - TestHelpers.InMethod(); -// log4net.Config.XmlConfigurator.Configure(); - - TestAddObjects(100, 1000); - } - - [Test] - public void Test_0013_2K_100PrimObjects() - { - TestHelpers.InMethod(); -// log4net.Config.XmlConfigurator.Configure(); - - TestAddObjects(100, 2000); - } - - private void TestAddObjects(int primsInEachObject, int objectsToAdd) - { - UUID ownerId = new UUID("F0000000-0000-0000-0000-000000000000"); - - // Using a local variable for scene, at least on mono 2.6.7, means that it's much more likely to be garbage - // collected when we teardown this test. If it's done in a member variable, even if that is subsequently - // nulled out, the garbage collect can be delayed. - TestScene scene = new SceneHelpers().SetupScene(); - -// Process process = Process.GetCurrentProcess(); -// long startProcessMemory = process.PrivateMemorySize64; - long startGcMemory = GC.GetTotalMemory(true); - DateTime start = DateTime.Now; - - for (int i = 1; i <= objectsToAdd; i++) - { - SceneObjectGroup so = SceneHelpers.CreateSceneObject(primsInEachObject, ownerId, "part_", i); - Assert.That(scene.AddNewSceneObject(so, false), Is.True, string.Format("Object {0} was not created", i)); - } - - TimeSpan elapsed = DateTime.Now - start; -// long processMemoryAlloc = process.PrivateMemorySize64 - startProcessMemory; - long endGcMemory = GC.GetTotalMemory(false); - - for (int i = 1; i <= objectsToAdd; i++) - { - Assert.That( - scene.GetSceneObjectGroup(TestHelpers.ParseTail(i)), - Is.Not.Null, - string.Format("Object {0} could not be retrieved", i)); - } - - // When a scene object is added to a scene, it is placed in the update list for sending to viewers - // (though in this case we have none). When it is deleted, it is not removed from the update which is - // fine since it will later be ignored. - // - // However, that means that we need to manually run an update here to clear out that list so that deleted - // objects will be clean up by the garbage collector before the next stress test is run. - scene.Update(1); - - Console.WriteLine( - "Took {0}ms, {1}MB ({2} - {3}) to create {4} objects each containing {5} prim(s)", - Math.Round(elapsed.TotalMilliseconds), - (endGcMemory - startGcMemory) / 1024 / 1024, - endGcMemory / 1024 / 1024, - startGcMemory / 1024 / 1024, - objectsToAdd, - primsInEachObject); - - scene.Close(); -// scene = null; - } - } -} \ No newline at end of file diff --git a/OpenSim/Tests/Performance/OpenSim.Tests.Performance.csproj b/OpenSim/Tests/Performance/OpenSim.Tests.Performance.csproj deleted file mode 100644 index 29e8ffecfb3..00000000000 --- a/OpenSim/Tests/Performance/OpenSim.Tests.Performance.csproj +++ /dev/null @@ -1,46 +0,0 @@ - - - net8.0 - - - - - - - - - - ..\..\..\bin\Nini.dll - False - - - ..\..\..\bin\OpenMetaverse.dll - False - - - ..\..\..\bin\OpenMetaverse.StructuredData.dll - False - - - ..\..\..\bin\OpenMetaverseTypes.dll - False - - - ..\..\..\bin\XMLRPC.dll - False - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/OpenSim/Tests/Performance/ScriptPerformanceTests.cs b/OpenSim/Tests/Performance/ScriptPerformanceTests.cs deleted file mode 100644 index 550771d34c7..00000000000 --- a/OpenSim/Tests/Performance/ScriptPerformanceTests.cs +++ /dev/null @@ -1,169 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.Reflection; -using System.Threading; -using log4net; -using Nini.Config; -using NUnit.Framework; -using OpenMetaverse; -using OpenSim.Framework; -using OpenSim.Region.CoreModules.Scripting.WorldComm; -using OpenSim.Region.Framework.Interfaces; -using OpenSim.Region.Framework.Scenes; -using OpenSim.Region.ScriptEngine.XEngine; -using OpenSim.Tests.Common; - -namespace OpenSim.Tests.Performance -{ - /// - /// Script performance tests - /// - /// - /// Don't rely on the numbers given by these tests - they will vary a lot depending on what is already cached, - /// how much memory is free, etc. In some cases, later larger tests will apparently take less time than smaller - /// earlier tests. - /// - [TestFixture] - public class ScriptPerformanceTests : OpenSimTestCase - { - /* - * private TestScene m_scene; - private XEngine m_xEngine; - private AutoResetEvent m_chatEvent = new AutoResetEvent(false); - - private int m_expectedChatMessages; - private List m_osChatMessagesReceived = new List(); - - [SetUp] - public void Init() - { - //AppDomain.CurrentDomain.SetData("APPBASE", Environment.CurrentDirectory + "/bin"); -// Console.WriteLine(AppDomain.CurrentDomain.BaseDirectory); - m_xEngine = new XEngine(); - - // Necessary to stop serialization complaining - WorldCommModule wcModule = new WorldCommModule(); - - IniConfigSource configSource = new IniConfigSource(); - - IConfig startupConfig = configSource.AddConfig("Startup"); - startupConfig.Set("DefaultScriptEngine", "XEngine"); - - IConfig xEngineConfig = configSource.AddConfig("XEngine"); - xEngineConfig.Set("Enabled", "true"); - - // These tests will not run with AppDomainLoading = true, at least on mono. For unknown reasons, the call - // to AssemblyResolver.OnAssemblyResolve fails. - xEngineConfig.Set("AppDomainLoading", "false"); - - m_scene = new SceneHelpers().SetupScene("My Test", UUID.Random(), 1000, 1000, configSource); - SceneHelpers.SetupSceneModules(m_scene, configSource, m_xEngine, wcModule); - - m_scene.EventManager.OnChatFromWorld += OnChatFromWorld; - m_scene.StartScripts(); - } - - [TearDown] - public void TearDown() - { - m_scene.Close(); - m_scene = null; - GC.Collect(); - GC.WaitForPendingFinalizers(); - } - - [Test] - public void TestCompileAndStart100Scripts() - { - TestHelpers.InMethod(); - log4net.Config.XmlConfigurator.Configure(); - - TestCompileAndStartScripts(100); - } - - private void TestCompileAndStartScripts(int scriptsToCreate) - { - UUID userId = TestHelpers.ParseTail(0x1); - - m_expectedChatMessages = scriptsToCreate; - int startingObjectIdTail = 0x100; - - GC.Collect(); - - for (int idTail = startingObjectIdTail;idTail < startingObjectIdTail + scriptsToCreate; idTail++) - { - AddObjectAndScript(idTail, userId); - } - - m_chatEvent.WaitOne(40000 + scriptsToCreate * 1000); - - Assert.That(m_osChatMessagesReceived.Count, Is.EqualTo(m_expectedChatMessages)); - - foreach (OSChatMessage msg in m_osChatMessagesReceived) - Assert.That( - msg.Message, - Is.EqualTo("Script running"), - string.Format( - "Message from {0} was {1} rather than {2}", msg.SenderUUID, msg.Message, "Script running")); - } - - private void AddObjectAndScript(int objectIdTail, UUID userId) - { -// UUID itemId = TestHelpers.ParseTail(0x3); - string itemName = string.Format("AddObjectAndScript() Item for object {0}", objectIdTail); - - SceneObjectGroup so = SceneHelpers.CreateSceneObject(1, userId, "AddObjectAndScriptPart_", objectIdTail); - m_scene.AddNewSceneObject(so, true); - - InventoryItemBase itemTemplate = new InventoryItemBase(); -// itemTemplate.ID = itemId; - itemTemplate.Name = itemName; - itemTemplate.Folder = so.UUID; - itemTemplate.InvType = (int)InventoryType.LSL; - - m_scene.RezNewScript(userId, itemTemplate); - } - - private void OnChatFromWorld(object sender, OSChatMessage oscm) - { -// Console.WriteLine("Got chat [{0}]", oscm.Message); - - lock (m_osChatMessagesReceived) - { - m_osChatMessagesReceived.Add(oscm); - - if (m_osChatMessagesReceived.Count == m_expectedChatMessages) - m_chatEvent.Set(); - } - } - } - */ -} \ No newline at end of file diff --git a/OpenSim/Tests/Permissions/Common.cs b/OpenSim/Tests/Permissions/Common.cs deleted file mode 100644 index 90a3dce1b3c..00000000000 --- a/OpenSim/Tests/Permissions/Common.cs +++ /dev/null @@ -1,374 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -using System; -using System.Collections.Generic; -using System.Threading; -using Nini.Config; -using NUnit.Framework; -using OpenMetaverse; -using OpenSim.Framework; -using OpenSim.Region.Framework.Scenes; -using OpenSim.Region.CoreModules.World.Permissions; -using OpenSim.Region.CoreModules.Avatar.Inventory.Transfer; -using OpenSim.Region.CoreModules.Framework.InventoryAccess; -using OpenSim.Services.Interfaces; -using OpenSim.Tests.Common; -using PermissionMask = OpenSim.Framework.PermissionMask; - -namespace OpenSim.Tests.Permissions -{ - [SetUpFixture] - public class Common : OpenSimTestCase - { - public static Common TheInstance; - - public static TestScene TheScene - { - get { return TheInstance.m_Scene; } - } - - public static ScenePresence[] TheAvatars - { - get { return TheInstance.m_Avatars; } - } - - private static string Perms = "Owner: {0}; Group: {1}; Everyone: {2}; Next: {3}"; - private TestScene m_Scene; - private ScenePresence[] m_Avatars = new ScenePresence[3]; - - [SetUp] - public override void SetUp() - { - if (TheInstance == null) - TheInstance = this; - - base.SetUp(); - TestHelpers.EnableLogging(); - - IConfigSource config = new IniConfigSource(); - config.AddConfig("Messaging"); - config.Configs["Messaging"].Set("InventoryTransferModule", "InventoryTransferModule"); - - config.AddConfig("Modules"); - config.Configs["Modules"].Set("InventoryAccessModule", "BasicInventoryAccessModule"); - - config.AddConfig("InventoryService"); - config.Configs["InventoryService"].Set("LocalServiceModule", "OpenSim.Services.InventoryService.dll:XInventoryService"); - config.Configs["InventoryService"].Set("StorageProvider", "OpenSim.Tests.Common.dll:TestXInventoryDataPlugin"); - - config.AddConfig("Groups"); - config.Configs["Groups"].Set("Enabled", "true"); - config.Configs["Groups"].Set("Module", "Groups Module V2"); - config.Configs["Groups"].Set("StorageProvider", "OpenSim.Tests.Common.dll:TestGroupsDataPlugin"); - config.Configs["Groups"].Set("ServicesConnectorModule", "Groups Local Service Connector"); - config.Configs["Groups"].Set("LocalService", "local"); - - m_Scene = new SceneHelpers().SetupScene("Test", UUID.Random(), 1000, 1000, config); - // Add modules - SceneHelpers.SetupSceneModules(m_Scene, config, new DefaultPermissionsModule(), new InventoryTransferModule(), new BasicInventoryAccessModule()); - - SetUpBasicEnvironment(); - } - - /// - /// The basic environment consists of: - /// - 3 avatars: A1, A2, A3 - /// - 6 simple boxes inworld belonging to A0 and with Next Owner perms: - /// C, CT, MC, MCT, MT, T - /// - Copies of all of these boxes in A0's inventory in the Objects folder - /// - One additional box inworld and in A0's inventory which is a copy of MCT, but - /// with C removed in inventory. This one is called MCT-C - /// - private void SetUpBasicEnvironment() - { - Console.WriteLine("===> SetUpBasicEnvironment <==="); - - // Add 3 avatars - for (int i = 0; i < 3; i++) - { - UUID id = TestHelpers.ParseTail(i + 1); - - m_Avatars[i] = AddScenePresence("Bot", "Bot_" + (i+1), id); - Assert.That(m_Avatars[i], Is.Not.Null); - Assert.That(m_Avatars[i].IsChildAgent, Is.False); - Assert.That(m_Avatars[i].UUID, Is.EqualTo(id)); - Assert.That(m_Scene.GetScenePresences().Count, Is.EqualTo(i + 1)); - } - - AddA1Object("Box C", 10, PermissionMask.Copy); - AddA1Object("Box CT", 11, PermissionMask.Copy | PermissionMask.Transfer); - AddA1Object("Box MC", 12, PermissionMask.Modify | PermissionMask.Copy); - AddA1Object("Box MCT", 13, PermissionMask.Modify | PermissionMask.Copy | PermissionMask.Transfer); - AddA1Object("Box MT", 14, PermissionMask.Modify | PermissionMask.Transfer); - AddA1Object("Box T", 15, PermissionMask.Transfer); - - // MCT-C - AddA1Object("Box MCT-C", 16, PermissionMask.Modify | PermissionMask.Copy | PermissionMask.Transfer); - - Thread.Sleep(5000); - - InventoryFolderBase objsFolder = UserInventoryHelpers.GetInventoryFolder(m_Scene.InventoryService, m_Avatars[0].UUID, "Objects"); - List items = m_Scene.InventoryService.GetFolderItems(m_Avatars[0].UUID, objsFolder.ID); - Assert.That(items.Count, Is.EqualTo(7)); - - RevokePermission(0, "Box MCT-C", PermissionMask.Copy); - } - - private ScenePresence AddScenePresence(string first, string last, UUID id) - { - UserAccount ua1 = UserAccountHelpers.CreateUserWithInventory(m_Scene, first, last, id, "pw"); - ScenePresence sp = SceneHelpers.AddScenePresence(m_Scene, id); - Assert.That(m_Scene.AuthenticateHandler.GetAgentCircuitData(id), Is.Not.Null); - - return sp; - } - - private void AddA1Object(string name, int suffix, PermissionMask nextOwnerPerms) - { - // Create a Box. Default permissions are just T - SceneObjectGroup box = AddSceneObject(name, suffix, 1, m_Avatars[0].UUID); - Assert.True((box.RootPart.NextOwnerMask & (int)PermissionMask.Copy) == 0); - Assert.True((box.RootPart.NextOwnerMask & (int)PermissionMask.Modify) == 0); - Assert.True((box.RootPart.NextOwnerMask & (int)PermissionMask.Transfer) != 0); - - // field = 16 is NextOwner - // set = 1 means add the permission; set = 0 means remove permission - - if ((nextOwnerPerms & PermissionMask.Copy) != 0) - m_Scene.HandleObjectPermissionsUpdate(m_Avatars[0].ControllingClient, m_Avatars[0].UUID, - m_Avatars[0].ControllingClient.SessionId, 16, box.LocalId, (uint)PermissionMask.Copy, 1); - - if ((nextOwnerPerms & PermissionMask.Modify) != 0) - m_Scene.HandleObjectPermissionsUpdate(m_Avatars[0].ControllingClient, m_Avatars[0].UUID, - m_Avatars[0].ControllingClient.SessionId, 16, box.LocalId, (uint)PermissionMask.Modify, 1); - - if ((nextOwnerPerms & PermissionMask.Transfer) == 0) - m_Scene.HandleObjectPermissionsUpdate(m_Avatars[0].ControllingClient, m_Avatars[0].UUID, - m_Avatars[0].ControllingClient.SessionId, 16, box.LocalId, (uint)PermissionMask.Transfer, 0); - - PrintPerms(box); - AssertPermissions(nextOwnerPerms, (PermissionMask)box.RootPart.NextOwnerMask, box.OwnerID.ToString().Substring(34) + " : " + box.Name); - - TakeCopyToInventory(0, box); - - } - - public void RevokePermission(int ownerIndex, string name, PermissionMask perm) - { - InventoryItemBase item = Common.TheInstance.GetItemFromInventory(m_Avatars[ownerIndex].UUID, "Objects", name); - Assert.That(item, Is.Not.Null); - - // Clone it, so to avoid aliasing -- just like the viewer does. - InventoryItemBase clone = Common.TheInstance.CloneInventoryItem(item); - // Revoke the permission in this copy - clone.NextPermissions &= ~(uint)perm; - Common.TheInstance.AssertPermissions((PermissionMask)clone.NextPermissions & ~perm, - (PermissionMask)clone.NextPermissions, Common.TheInstance.IdStr(clone)); - Assert.That(clone.ID == item.ID); - - // Update properties of the item in inventory. This should affect the original item above. - Common.TheScene.UpdateInventoryItem(m_Avatars[ownerIndex].ControllingClient, UUID.Zero, clone.ID, clone); - - item = Common.TheInstance.GetItemFromInventory(m_Avatars[ownerIndex].UUID, "Objects", name); - Assert.That(item, Is.Not.Null); - Common.TheInstance.PrintPerms(item); - Common.TheInstance.AssertPermissions((PermissionMask)item.NextPermissions & ~perm, - (PermissionMask)item.NextPermissions, Common.TheInstance.IdStr(item)); - - } - - public void PrintPerms(SceneObjectGroup sog) - { - Console.WriteLine("SOG " + sog.Name + " (" + sog.OwnerID.ToString().Substring(34) + "): " + - String.Format(Perms, (PermissionMask)sog.EffectiveOwnerPerms, - (PermissionMask)sog.EffectiveGroupPerms, (PermissionMask)sog.EffectiveEveryOnePerms, (PermissionMask)sog.RootPart.NextOwnerMask)); - - } - - public void PrintPerms(InventoryItemBase item) - { - Console.WriteLine("Inv " + item.Name + " (" + item.Owner.ToString().Substring(34) + "): " + - String.Format(Perms, (PermissionMask)item.BasePermissions, - (PermissionMask)item.GroupPermissions, (PermissionMask)item.EveryOnePermissions, (PermissionMask)item.NextPermissions)); - - } - - public void AssertPermissions(PermissionMask desired, PermissionMask actual, string message) - { - if ((desired & PermissionMask.Copy) != 0) - Assert.True((actual & PermissionMask.Copy) != 0, message); - else - Assert.True((actual & PermissionMask.Copy) == 0, message); - - if ((desired & PermissionMask.Modify) != 0) - Assert.True((actual & PermissionMask.Modify) != 0, message); - else - Assert.True((actual & PermissionMask.Modify) == 0, message); - - if ((desired & PermissionMask.Transfer) != 0) - Assert.True((actual & PermissionMask.Transfer) != 0, message); - else - Assert.True((actual & PermissionMask.Transfer) == 0, message); - - } - - public SceneObjectGroup AddSceneObject(string name, int suffix, int partsToTestCount, UUID ownerID) - { - SceneObjectGroup so = SceneHelpers.CreateSceneObject(partsToTestCount, ownerID, name, suffix); - so.Name = name; - so.Description = name; - - Assert.That(m_Scene.AddNewSceneObject(so, false), Is.True); - SceneObjectGroup retrievedSo = m_Scene.GetSceneObjectGroup(so.UUID); - - // If the parts have the same UUID then we will consider them as one and the same - Assert.That(retrievedSo.PrimCount, Is.EqualTo(partsToTestCount)); - - return so; - } - - public void TakeCopyToInventory(int userIndex, SceneObjectGroup sog) - { - InventoryFolderBase objsFolder = UserInventoryHelpers.GetInventoryFolder(m_Scene.InventoryService, m_Avatars[userIndex].UUID, "Objects"); - Assert.That(objsFolder, Is.Not.Null); - - List localIds = new List(); localIds.Add(sog.LocalId); - // This is an async operation - m_Scene.DeRezObjects(m_Avatars[userIndex].ControllingClient, localIds, m_Avatars[userIndex].UUID, DeRezAction.TakeCopy, objsFolder.ID); - } - - public InventoryItemBase GetItemFromInventory(UUID userID, string folderName, string itemName) - { - InventoryFolderBase objsFolder = UserInventoryHelpers.GetInventoryFolder(m_Scene.InventoryService, userID, folderName); - Assert.That(objsFolder, Is.Not.Null); - List items = m_Scene.InventoryService.GetFolderItems(userID, objsFolder.ID); - InventoryItemBase item = items.Find(i => i.Name == itemName); - Assert.That(item, Is.Not.Null); - - return item; - } - - public InventoryItemBase CloneInventoryItem(InventoryItemBase item) - { - InventoryItemBase clone = new InventoryItemBase(item.ID); - clone.Name = item.Name; - clone.Description = item.Description; - clone.AssetID = item.AssetID; - clone.AssetType = item.AssetType; - clone.BasePermissions = item.BasePermissions; - clone.CreatorId = item.CreatorId; - clone.CurrentPermissions = item.CurrentPermissions; - clone.EveryOnePermissions = item.EveryOnePermissions; - clone.Flags = item.Flags; - clone.Folder = item.Folder; - clone.GroupID = item.GroupID; - clone.GroupOwned = item.GroupOwned; - clone.GroupPermissions = item.GroupPermissions; - clone.InvType = item.InvType; - clone.NextPermissions = item.NextPermissions; - clone.Owner = item.Owner; - - return clone; - } - - public void DeleteObjectsFolders() - { - // Delete everything in A2 and A3's Objects folders, so we can restart - for (int i = 1; i < 3; i++) - { - InventoryFolderBase objsFolder = UserInventoryHelpers.GetInventoryFolder(Common.TheScene.InventoryService, Common.TheAvatars[i].UUID, "Objects"); - Assert.That(objsFolder, Is.Not.Null); - - List items = Common.TheScene.InventoryService.GetFolderItems(Common.TheAvatars[i].UUID, objsFolder.ID); - List ids = new List(); - foreach (InventoryItemBase it in items) - ids.Add(it.ID); - - Common.TheScene.InventoryService.DeleteItems(Common.TheAvatars[i].UUID, ids); - items = Common.TheScene.InventoryService.GetFolderItems(Common.TheAvatars[i].UUID, objsFolder.ID); - Assert.That(items.Count, Is.EqualTo(0), "A" + (i + 1)); - } - - } - - public string IdStr(InventoryItemBase item) - { - return item.Owner.ToString().Substring(34) + " : " + item.Name; - } - - public string IdStr(SceneObjectGroup sog) - { - return sog.OwnerID.ToString().Substring(34) + " : " + sog.Name; - } - - public void GiveInventoryItem(UUID itemId, ScenePresence giverSp, ScenePresence receiverSp) - { - TestClient giverClient = (TestClient)giverSp.ControllingClient; - TestClient receiverClient = (TestClient)receiverSp.ControllingClient; - - UUID initialSessionId = TestHelpers.ParseTail(0x10); - byte[] giveImBinaryBucket = new byte[17]; - byte[] itemIdBytes = itemId.GetBytes(); - Array.Copy(itemIdBytes, 0, giveImBinaryBucket, 1, itemIdBytes.Length); - - GridInstantMessage giveIm - = new GridInstantMessage( - m_Scene, - giverSp.UUID, - giverSp.Name, - receiverSp.UUID, - (byte)InstantMessageDialog.InventoryOffered, - false, - "inventory offered msg", - initialSessionId, - false, - Vector3.Zero, - giveImBinaryBucket, - true); - - giverClient.HandleImprovedInstantMessage(giveIm); - - // These details might not all be correct. - GridInstantMessage acceptIm - = new GridInstantMessage( - m_Scene, - receiverSp.UUID, - receiverSp.Name, - giverSp.UUID, - (byte)InstantMessageDialog.InventoryAccepted, - false, - "inventory accepted msg", - initialSessionId, - false, - Vector3.Zero, - null, - true); - - receiverClient.HandleImprovedInstantMessage(acceptIm); - } - } -} diff --git a/OpenSim/Tests/Permissions/DirectTransferTests.cs b/OpenSim/Tests/Permissions/DirectTransferTests.cs deleted file mode 100644 index 0f251dba436..00000000000 --- a/OpenSim/Tests/Permissions/DirectTransferTests.cs +++ /dev/null @@ -1,153 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using NUnit.Framework; -using OpenMetaverse; -using OpenSim.Framework; -using OpenSim.Region.Framework.Scenes; -using OpenSim.Tests.Common; -using PermissionMask = OpenSim.Framework.PermissionMask; - -namespace OpenSim.Tests.Permissions -{ - /// - /// Basic scene object tests (create, read and delete but not update). - /// - [TestFixture] - public class DirectTransferTests - { - - [SetUp] - public void SetUp() - { - // In case we're dealing with some older version of nunit - if (Common.TheInstance == null) - { - Common.TheInstance = new Common(); - Common.TheInstance.SetUp(); - } - - Common.TheInstance.DeleteObjectsFolders(); - } - - /// - /// Test giving simple objecta with various combinations of next owner perms. - /// - [Test] - public void TestGiveBox() - { - TestHelpers.InMethod(); - - // C, CT, MC, MCT, MT, T - string[] names = new string[6] { "Box C", "Box CT", "Box MC", "Box MCT", "Box MT", "Box T" }; - PermissionMask[] perms = new PermissionMask[6] { - PermissionMask.Copy, - PermissionMask.Copy | PermissionMask.Transfer, - PermissionMask.Modify | PermissionMask.Copy, - PermissionMask.Modify | PermissionMask.Copy | PermissionMask.Transfer, - PermissionMask.Modify | PermissionMask.Transfer, - PermissionMask.Transfer - }; - - for (int i = 0; i < 6; i++) - TestOneBox(names[i], perms[i]); - } - - private void TestOneBox(string name, PermissionMask mask) - { - InventoryItemBase item = Common.TheInstance.GetItemFromInventory(Common.TheAvatars[0].UUID, "Objects", name); - - Common.TheInstance.GiveInventoryItem(item.ID, Common.TheAvatars[0], Common.TheAvatars[1]); - - item = Common.TheInstance.GetItemFromInventory(Common.TheAvatars[1].UUID, "Objects", name); - - // Check the receiver - Common.TheInstance.PrintPerms(item); - Common.TheInstance.AssertPermissions(mask, (PermissionMask)item.BasePermissions, item.Owner.ToString().Substring(34) + " : " + item.Name); - - int nObjects = Common.TheScene.GetSceneObjectGroups().Count; - // Rez it and check perms in scene too - Common.TheScene.RezObject(Common.TheAvatars[1].ControllingClient, item.ID, UUID.Zero, Vector3.One, Vector3.Zero, UUID.Zero, 0, false, false, false, UUID.Zero); - Assert.That(Common.TheScene.GetSceneObjectGroups().Count, Is.EqualTo(nObjects + 1)); - - SceneObjectGroup box = Common.TheScene.GetSceneObjectGroups().Find(sog => sog.OwnerID == Common.TheAvatars[1].UUID && sog.Name == name); - Common.TheInstance.PrintPerms(box); - Assert.That(box, Is.Not.Null); - - // Check Owner permissions - Common.TheInstance.AssertPermissions(mask, (PermissionMask)box.EffectiveOwnerPerms, box.OwnerID.ToString().Substring(34) + " : " + box.Name); - - // Check Next Owner permissions - Common.TheInstance.AssertPermissions(mask, (PermissionMask)box.RootPart.NextOwnerMask, box.OwnerID.ToString().Substring(34) + " : " + box.Name); - - } - - /// - /// Test giving simple objecta with variour combinations of next owner perms. - /// - [Test] - public void TestDoubleGiveWithChange() - { - TestHelpers.InMethod(); - - string name = "Box MCT-C"; - InventoryItemBase item = Common.TheInstance.GetItemFromInventory(Common.TheAvatars[0].UUID, "Objects", name); - - // Now give the item to A2. We give the original item, not a clone. - // The giving methods are supposed to duplicate it. - Common.TheInstance.GiveInventoryItem(item.ID, Common.TheAvatars[0], Common.TheAvatars[1]); - - item = Common.TheInstance.GetItemFromInventory(Common.TheAvatars[1].UUID, "Objects", name); - - // Check the receiver - Common.TheInstance.PrintPerms(item); - Common.TheInstance.AssertPermissions(PermissionMask.Modify | PermissionMask.Transfer, - (PermissionMask)item.BasePermissions, Common.TheInstance.IdStr(item)); - - // --------------------------- - // Second transfer - //---------------------------- - - // A2 revokes M - Common.TheInstance.RevokePermission(1, name, PermissionMask.Modify); - - item = Common.TheInstance.GetItemFromInventory(Common.TheAvatars[1].UUID, "Objects", name); - - // Now give the item to A3. We give the original item, not a clone. - // The giving methods are supposed to duplicate it. - Common.TheInstance.GiveInventoryItem(item.ID, Common.TheAvatars[1], Common.TheAvatars[2]); - - item = Common.TheInstance.GetItemFromInventory(Common.TheAvatars[2].UUID, "Objects", name); - - // Check the receiver - Common.TheInstance.PrintPerms(item); - Common.TheInstance.AssertPermissions(PermissionMask.Transfer, - (PermissionMask)item.BasePermissions, Common.TheInstance.IdStr(item)); - - } - } -} \ No newline at end of file diff --git a/OpenSim/Tests/Permissions/IndirectTransferTests.cs b/OpenSim/Tests/Permissions/IndirectTransferTests.cs deleted file mode 100644 index 909bda31b1d..00000000000 --- a/OpenSim/Tests/Permissions/IndirectTransferTests.cs +++ /dev/null @@ -1,132 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System.Collections.Generic; -using System.Threading; -using NUnit.Framework; -using OpenMetaverse; -using OpenSim.Framework; -using OpenSim.Region.Framework.Scenes; -using OpenSim.Tests.Common; -using PermissionMask = OpenSim.Framework.PermissionMask; - -namespace OpenSim.Tests.Permissions -{ - /// - /// Basic scene object tests (create, read and delete but not update). - /// - [TestFixture] - public class IndirectTransferTests - { - - [SetUp] - public void SetUp() - { - // In case we're dealing with some older version of nunit - if (Common.TheInstance == null) - { - Common.TheInstance = new Common(); - Common.TheInstance.SetUp(); - } - Common.TheInstance.DeleteObjectsFolders(); - } - - /// - /// Test giving simple objecta with various combinations of next owner perms. - /// - [Test] - public void SimpleTakeCopy() - { - TestHelpers.InMethod(); - - // The Objects folder of A2 - InventoryFolderBase objsFolder = UserInventoryHelpers.GetInventoryFolder(Common.TheScene.InventoryService, Common.TheAvatars[1].UUID, "Objects"); - - // C, CT, MC, MCT, MT, T - string[] names = new string[6] { "Box C", "Box CT", "Box MC", "Box MCT", "Box MT", "Box T" }; - PermissionMask[] perms = new PermissionMask[6] { - PermissionMask.Copy, - PermissionMask.Copy | PermissionMask.Transfer, - PermissionMask.Modify | PermissionMask.Copy, - PermissionMask.Modify | PermissionMask.Copy | PermissionMask.Transfer, - PermissionMask.Modify | PermissionMask.Transfer, - PermissionMask.Transfer - }; - - // Try A2 takes copies of objects that cannot be copied. - for (int i = 0; i < 6; i++) - TakeOneBox(Common.TheScene.GetSceneObjectGroups(), names[i], perms[i]); - // Ad-hoc. Enough time to let the take work. - Thread.Sleep(6000); - - List items = Common.TheScene.InventoryService.GetFolderItems(Common.TheAvatars[1].UUID, objsFolder.ID); - Assert.That(items.Count, Is.EqualTo(0)); - - // A1 makes the objects copyable - for (int i = 0; i < 6; i++) - MakeCopyable(Common.TheScene.GetSceneObjectGroups(), names[i]); - - // Try A2 takes copies of objects that can be copied. - for (int i = 0; i < 6; i++) - TakeOneBox(Common.TheScene.GetSceneObjectGroups(), names[i], perms[i]); - // Ad-hoc. Enough time to let the take work. - Thread.Sleep(6000); - - items = Common.TheScene.InventoryService.GetFolderItems(Common.TheAvatars[1].UUID, objsFolder.ID); - Assert.That(items.Count, Is.EqualTo(6)); - - for (int i = 0; i < 6; i++) - { - InventoryItemBase item = Common.TheInstance.GetItemFromInventory(Common.TheAvatars[1].UUID, "Objects", names[i]); - Assert.That(item, Is.Not.Null); - Common.TheInstance.AssertPermissions(perms[i], (PermissionMask)item.BasePermissions, Common.TheInstance.IdStr(item)); - } - } - - private void TakeOneBox(List objs, string name, PermissionMask mask) - { - // Find the object inworld - SceneObjectGroup box = objs.Find(sog => sog.Name == name && sog.OwnerID == Common.TheAvatars[0].UUID); - Assert.That(box, Is.Not.Null, name); - - // A2's inventory (index 1) - Common.TheInstance.TakeCopyToInventory(1, box); - } - - private void MakeCopyable(List objs, string name) - { - SceneObjectGroup box = objs.Find(sog => sog.Name == name && sog.OwnerID == Common.TheAvatars[0].UUID); - Assert.That(box, Is.Not.Null, name); - - // field = 8 is Everyone - // set = 1 means add the permission; set = 0 means remove permission - Common.TheScene.HandleObjectPermissionsUpdate(Common.TheAvatars[0].ControllingClient, Common.TheAvatars[0].UUID, - Common.TheAvatars[0].ControllingClient.SessionId, 8, box.LocalId, (uint)PermissionMask.Copy, 1); - Common.TheInstance.PrintPerms(box); - } - } -} \ No newline at end of file diff --git a/OpenSim/Tests/Permissions/OpenSim.Tests.Permissions.csproj b/OpenSim/Tests/Permissions/OpenSim.Tests.Permissions.csproj deleted file mode 100644 index 6c21b61bbed..00000000000 --- a/OpenSim/Tests/Permissions/OpenSim.Tests.Permissions.csproj +++ /dev/null @@ -1,36 +0,0 @@ - - - net8.0 - - - - - - - - - - - - ..\..\..\bin\Nini.dll - False - - - ..\..\..\bin\OpenMetaverse.dll - False - - - ..\..\..\bin\OpenMetaverseTypes.dll - False - - - - - - - - - - - - \ No newline at end of file diff --git a/OpenSim/Tests/Robust/Clients/Grid/GridClient.cs b/OpenSim/Tests/Robust/Clients/Grid/GridClient.cs deleted file mode 100644 index 15498517eb1..00000000000 --- a/OpenSim/Tests/Robust/Clients/Grid/GridClient.cs +++ /dev/null @@ -1,133 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections.Generic; -using System.Text; -using System.Reflection; - -using OpenMetaverse; -using NUnit.Framework; - -using OpenSim.Framework; -using OpenSim.Services.Interfaces; -using GridRegion = OpenSim.Services.Interfaces.GridRegion; -using OpenSim.Services.Connectors; - -namespace Robust.Tests -{ - [TestFixture] - public class GridClient - { -// private static readonly ILog m_log = -// LogManager.GetLogger( -// MethodBase.GetCurrentMethod().DeclaringType); - - [Test] - public void Grid_001() - { - GridServicesConnector m_Connector = new GridServicesConnector(DemonServer.Address); - - GridRegion r1 = CreateRegion("Test Region 1", 1000, 1000); - GridRegion r2 = CreateRegion("Test Region 2", 1001, 1000); - GridRegion r3 = CreateRegion("Test Region 3", 1005, 1000); - - string msg = m_Connector.RegisterRegion(UUID.Zero, r1); - Assert.AreEqual(msg, string.Empty, "Region 1 failed to register"); - - msg = m_Connector.RegisterRegion(UUID.Zero, r2); - Assert.AreEqual(msg, string.Empty, "Region 2 failed to register"); - - msg = m_Connector.RegisterRegion(UUID.Zero, r3); - Assert.AreEqual(msg, string.Empty, "Region 3 failed to register"); - - bool success; - success = m_Connector.DeregisterRegion(r3.RegionID); - Assert.AreEqual(success, true, "Region 3 failed to deregister"); - - msg = m_Connector.RegisterRegion(UUID.Zero, r3); - Assert.AreEqual(msg, string.Empty, "Region 3 failed to re-register"); - - List regions = m_Connector.GetNeighbours(UUID.Zero, r1.RegionID); - Assert.AreNotEqual(regions, null, "GetNeighbours of region 1 failed"); - Assert.AreEqual(regions.Count, 1, "Region 1 should have 1 neighbor"); - Assert.AreEqual(regions[0].RegionName, "Test Region 2", "Region 1 has the wrong neighbor"); - - GridRegion region = m_Connector.GetRegionByUUID(UUID.Zero, r2.RegionID); - Assert.AreNotEqual(region, null, "GetRegionByUUID for region 2 failed"); - Assert.AreEqual(region.RegionName, "Test Region 2", "GetRegionByUUID of region 2 returned wrong region"); - - region = m_Connector.GetRegionByUUID(UUID.Zero, UUID.Random()); - Assert.AreEqual(region, null, "Region with randon id should not exist"); - - region = m_Connector.GetRegionByName(UUID.Zero, r3.RegionName); - Assert.AreNotEqual(region, null, "GetRegionByUUID for region 3 failed"); - Assert.AreEqual(region.RegionName, "Test Region 3", "GetRegionByUUID of region 3 returned wrong region"); - - region = m_Connector.GetRegionByName(UUID.Zero, "Foo"); - Assert.AreEqual(region, null, "Region Foo should not exist"); - - regions = m_Connector.GetRegionsByName(UUID.Zero, "Test", 10); - Assert.AreNotEqual(regions, null, "GetRegionsByName failed"); - Assert.AreEqual(regions.Count, 3, "GetRegionsByName should return 3"); - - regions = m_Connector.GetRegionRange(UUID.Zero, - (int)Util.RegionToWorldLoc(900), (int)Util.RegionToWorldLoc(1002), - (int)Util.RegionToWorldLoc(900), (int)Util.RegionToWorldLoc(1002) ); - Assert.AreNotEqual(regions, null, "GetRegionRange failed"); - Assert.AreEqual(regions.Count, 2, "GetRegionRange should return 2"); - - regions = m_Connector.GetRegionRange(UUID.Zero, - (int)Util.RegionToWorldLoc(900), (int)Util.RegionToWorldLoc(950), - (int)Util.RegionToWorldLoc(900), (int)Util.RegionToWorldLoc(950) ); - Assert.AreNotEqual(regions, null, "GetRegionRange (bis) failed"); - Assert.AreEqual(regions.Count, 0, "GetRegionRange (bis) should return 0"); - - // Deregister them all - success = m_Connector.DeregisterRegion(r1.RegionID); - Assert.AreEqual(success, true, "Region 1 failed to deregister"); - - success = m_Connector.DeregisterRegion(r2.RegionID); - Assert.AreEqual(success, true, "Region 2 failed to deregister"); - - success = m_Connector.DeregisterRegion(r3.RegionID); - Assert.AreEqual(success, true, "Region 3 failed to deregister"); - } - - private static GridRegion CreateRegion(string name, uint xcell, uint ycell) - { - GridRegion region = new GridRegion(xcell, ycell); - region.RegionName = name; - region.RegionID = UUID.Random(); - region.ExternalHostName = "127.0.0.1"; - region.HttpPort = 9000; - region.InternalEndPoint = new System.Net.IPEndPoint(System.Net.IPAddress.Parse("0.0.0.0"), 9000); - - return region; - } - } -} diff --git a/OpenSim/Tests/Robust/Clients/Grid/GridForm.html b/OpenSim/Tests/Robust/Clients/Grid/GridForm.html deleted file mode 100644 index 252920f38d3..00000000000 --- a/OpenSim/Tests/Robust/Clients/Grid/GridForm.html +++ /dev/null @@ -1,11 +0,0 @@ - - -
-xmin: -xmax: -ymin: -ymax: - - -
- diff --git a/OpenSim/Tests/Robust/Clients/InstantMessage/IMClient.cs b/OpenSim/Tests/Robust/Clients/InstantMessage/IMClient.cs deleted file mode 100644 index 4eba7b90847..00000000000 --- a/OpenSim/Tests/Robust/Clients/InstantMessage/IMClient.cs +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections.Generic; -using System.Text; - -using OpenMetaverse; -using NUnit.Framework; - -using OpenSim.Framework; -using OpenSim.Services.Interfaces; -using OpenSim.Services.Connectors.InstantMessage; - -namespace Robust.Tests -{ - [TestFixture] - public class IMClient - { - [Test] - public void HGIM_001() - { - GridInstantMessage im = new GridInstantMessage(); - im.fromAgentID = new Guid(); - im.toAgentID = new Guid(); - im.message = "Hello"; - im.imSessionID = new Guid(); - - bool success = InstantMessageServiceConnector.SendInstantMessage(DemonServer.Address, im, String.Empty); - Assert.IsFalse(success, "Sending of IM succeeded, but it should have failed"); - } - - } -} diff --git a/OpenSim/Tests/Robust/Clients/Inventory/InventoryClient.cs b/OpenSim/Tests/Robust/Clients/Inventory/InventoryClient.cs deleted file mode 100644 index fe46a4f523c..00000000000 --- a/OpenSim/Tests/Robust/Clients/Inventory/InventoryClient.cs +++ /dev/null @@ -1,205 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections.Generic; -using System.Text; -using System.Reflection; - -using OpenMetaverse; -using NUnit.Framework; - -using OpenSim.Framework; -using OpenSim.Services.Interfaces; -using OpenSim.Services.Connectors; - -using OpenSim.Tests.Common; - -namespace Robust.Tests -{ - [TestFixture] - public class InventoryClient - { -// private static readonly ILog m_log = -// LogManager.GetLogger( -// MethodBase.GetCurrentMethod().DeclaringType); - - private UUID m_userID = new UUID("00000000-0000-0000-0000-333333333333"); - private UUID m_rootFolderID; - private UUID m_notecardsFolder; - private UUID m_objectsFolder; - - [Test] - public void Inventory_001_CreateInventory() - { - TestHelpers.InMethod(); - XInventoryServicesConnector m_Connector = new XInventoryServicesConnector(DemonServer.Address); - - // Create an inventory that looks like this: - // - // /My Inventory - // - // /Objects - // Some Object - // /Notecards - // Notecard 1 - // Notecard 2 - // /Test Folder - // Link to notecard -> /Notecards/Notecard 2 - // Link to Objects folder -> /Objects - - bool success = m_Connector.CreateUserInventory(m_userID); - Assert.IsTrue(success, "Failed to create user inventory"); - - m_rootFolderID = m_Connector.GetRootFolder(m_userID).ID; - Assert.AreNotEqual(m_rootFolderID, UUID.Zero, "Root folder ID must not be UUID.Zero"); - - InventoryFolderBase of = m_Connector.GetFolderForType(m_userID, FolderType.Object); - Assert.IsNotNull(of, "Failed to retrieve Objects folder"); - m_objectsFolder = of.ID; - Assert.AreNotEqual(m_objectsFolder, UUID.Zero, "Objects folder ID must not be UUID.Zero"); - - // Add an object - InventoryItemBase item = new InventoryItemBase(new UUID("b0000000-0000-0000-0000-00000000000b"), m_userID); - item.AssetID = UUID.Random(); - item.AssetType = (int)AssetType.Object; - item.Folder = m_objectsFolder; - item.Name = "Some Object"; - item.Description = string.Empty; - success = m_Connector.AddItem(item); - Assert.IsTrue(success, "Failed to add object to inventory"); - - InventoryFolderBase ncf = m_Connector.GetFolderForType(m_userID, FolderType.Notecard); - Assert.IsNotNull(of, "Failed to retrieve Notecards folder"); - m_notecardsFolder = ncf.ID; - Assert.AreNotEqual(m_notecardsFolder, UUID.Zero, "Notecards folder ID must not be UUID.Zero"); - m_notecardsFolder = ncf.ID; - - // Add a notecard - item = new InventoryItemBase(new UUID("10000000-0000-0000-0000-000000000001"), m_userID); - item.AssetID = UUID.Random(); - item.AssetType = (int)AssetType.Notecard; - item.Folder = m_notecardsFolder; - item.Name = "Test Notecard 1"; - item.Description = string.Empty; - success = m_Connector.AddItem(item); - Assert.IsTrue(success, "Failed to add Notecard 1 to inventory"); - // Add another notecard - item.ID = new UUID("20000000-0000-0000-0000-000000000002"); - item.AssetID = new UUID("a0000000-0000-0000-0000-00000000000a"); - item.Name = "Test Notecard 2"; - item.Description = string.Empty; - success = m_Connector.AddItem(item); - Assert.IsTrue(success, "Failed to add Notecard 2 to inventory"); - - // Add a folder - InventoryFolderBase folder = new InventoryFolderBase(new UUID("f0000000-0000-0000-0000-00000000000f"), "Test Folder", m_userID, m_rootFolderID); - folder.Type = (int)FolderType.None; - success = m_Connector.AddFolder(folder); - Assert.IsTrue(success, "Failed to add Test Folder to inventory"); - - // Add a link to notecard 2 in Test Folder - item.AssetID = item.ID; // use item ID of notecard 2 - item.ID = new UUID("40000000-0000-0000-0000-000000000004"); - item.AssetType = (int)AssetType.Link; - item.Folder = folder.ID; - item.Name = "Link to notecard"; - item.Description = string.Empty; - success = m_Connector.AddItem(item); - Assert.IsTrue(success, "Failed to add link to notecard to inventory"); - - // Add a link to the Objects folder in Test Folder - item.AssetID = m_Connector.GetFolderForType(m_userID, FolderType.Object).ID; // use item ID of Objects folder - item.ID = new UUID("50000000-0000-0000-0000-000000000005"); - item.AssetType = (int)AssetType.LinkFolder; - item.Folder = folder.ID; - item.Name = "Link to Objects folder"; - item.Description = string.Empty; - success = m_Connector.AddItem(item); - Assert.IsTrue(success, "Failed to add link to objects folder to inventory"); - - InventoryCollection coll = m_Connector.GetFolderContent(m_userID, m_rootFolderID); - Assert.IsNotNull(coll, "Failed to retrieve contents of root folder"); - Assert.Greater(coll.Folders.Count, 0, "Root folder does not have any subfolders"); - - coll = m_Connector.GetFolderContent(m_userID, folder.ID); - Assert.IsNotNull(coll, "Failed to retrieve contents of Test Folder"); - Assert.AreEqual(coll.Items.Count + coll.Folders.Count, 2, "Test Folder is expected to have exactly 2 things inside"); - - } - - [Test] - public void Inventory_002_MultipleItemsRequest() - { - TestHelpers.InMethod(); - XInventoryServicesConnector m_Connector = new XInventoryServicesConnector(DemonServer.Address); - - // Prefetch Notecard 1, will be cached from here on - InventoryItemBase item = m_Connector.GetItem(m_userID, new UUID("10000000-0000-0000-0000-000000000001")); - Assert.NotNull(item, "Failed to get Notecard 1"); - Assert.AreEqual("Test Notecard 1", item.Name, "Wrong name for Notecard 1"); - - UUID[] uuids = new UUID[2]; - uuids[0] = item.ID; - uuids[1] = new UUID("20000000-0000-0000-0000-000000000002"); - - InventoryItemBase[] items = m_Connector.GetMultipleItems(m_userID, uuids); - Assert.NotNull(items, "Failed to get multiple items"); - Assert.IsTrue(items.Length == 2, "Requested 2 items, but didn't receive 2 items"); - - // Now they should both be cached - items = m_Connector.GetMultipleItems(m_userID, uuids); - Assert.NotNull(items, "(Repeat) Failed to get multiple items"); - Assert.IsTrue(items.Length == 2, "(Repeat) Requested 2 items, but didn't receive 2 items"); - - // This item doesn't exist, but [0] does, and it's cached. - uuids[1] = new UUID("bb000000-0000-0000-0000-0000000000bb"); - // Fetching should return 2 items, but [1] should be null - items = m_Connector.GetMultipleItems(m_userID, uuids); - Assert.NotNull(items, "(Three times) Failed to get multiple items"); - Assert.IsTrue(items.Length == 2, "(Three times) Requested 2 items, but didn't receive 2 items"); - Assert.AreEqual("Test Notecard 1", items[0].Name, "(Three times) Wrong name for Notecard 1"); - Assert.IsNull(items[1], "(Three times) Expecting 2nd item to be null"); - - // Now both don't exist - uuids[0] = new UUID("aa000000-0000-0000-0000-0000000000aa"); - items = m_Connector.GetMultipleItems(m_userID, uuids); - Assert.Null(items[0], "Request to multiple non-existent items is supposed to return null [0]"); - Assert.Null(items[1], "Request to multiple non-existent items is supposed to return null [1]"); - - // This item exists, and it's not cached - uuids[1] = new UUID("b0000000-0000-0000-0000-00000000000b"); - // Fetching should return 2 items, but [0] should be null - items = m_Connector.GetMultipleItems(m_userID, uuids); - Assert.NotNull(items, "(Four times) Failed to get multiple items"); - Assert.IsTrue(items.Length == 2, "(Four times) Requested 2 items, but didn't receive 2 items"); - Assert.AreEqual("Some Object", items[1].Name, "(Four times) Wrong name for Some Object"); - Assert.IsNull(items[0], "(Four times) Expecting 1st item to be null"); - - } - } -} diff --git a/OpenSim/Tests/Robust/Clients/Presence/PresenceClient.cs b/OpenSim/Tests/Robust/Clients/Presence/PresenceClient.cs deleted file mode 100644 index 31c8ee96ef2..00000000000 --- a/OpenSim/Tests/Robust/Clients/Presence/PresenceClient.cs +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections.Generic; -using System.Text; -using System.Reflection; - -using OpenMetaverse; -using NUnit.Framework; - -using OpenSim.Framework; -using OpenSim.Services.Interfaces; -using OpenSim.Services.Connectors; - -namespace Robust.Tests -{ - [TestFixture] - public class PresenceClient - { - [Test] - public void Presence_001() - { - PresenceServicesConnector m_Connector = new PresenceServicesConnector(DemonServer.Address); - - UUID user1 = UUID.Random(); - UUID session1 = UUID.Random(); - UUID region1 = UUID.Random(); - - bool success = m_Connector.LoginAgent(user1.ToString(), session1, UUID.Zero); - Assert.AreEqual(success, true, "Failed to add user session"); - - PresenceInfo pinfo = m_Connector.GetAgent(session1); - Assert.AreNotEqual(pinfo, null, "Unable to retrieve session"); - Assert.AreEqual(pinfo.UserID, user1.ToString(), "Retrieved session does not match expected userID"); - Assert.AreNotEqual(pinfo.RegionID, region1, "Retrieved session is unexpectedly in region"); - - success = m_Connector.ReportAgent(session1, region1); - Assert.AreEqual(success, true, "Failed to report session in region 1"); - - pinfo = m_Connector.GetAgent(session1); - Assert.AreNotEqual(pinfo, null, "Unable to session presence"); - Assert.AreEqual(pinfo.UserID, user1.ToString(), "Retrieved session does not match expected userID"); - Assert.AreEqual(pinfo.RegionID, region1, "Retrieved session is not in expected region"); - - success = m_Connector.LogoutAgent(session1); - Assert.AreEqual(success, true, "Failed to remove session"); - - pinfo = m_Connector.GetAgent(session1); - Assert.AreEqual(pinfo, null, "Session is still there, even though it shouldn't"); - - success = m_Connector.ReportAgent(session1, UUID.Random()); - Assert.AreEqual(success, false, "Remove non-existing session should fail"); - } - - } -} diff --git a/OpenSim/Tests/Robust/Clients/UserAccounts/UserAccountsClient.cs b/OpenSim/Tests/Robust/Clients/UserAccounts/UserAccountsClient.cs deleted file mode 100644 index 3238dc9a31c..00000000000 --- a/OpenSim/Tests/Robust/Clients/UserAccounts/UserAccountsClient.cs +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections.Generic; -using System.Text; -using System.Reflection; - -using OpenMetaverse; -using NUnit.Framework; - -using OpenSim.Framework; -using OpenSim.Services.Interfaces; -using OpenSim.Services.Connectors; - -namespace Robust.Tests -{ - [TestFixture] - public class UserAccountsClient - { - [Test] - public void UserAccounts_001() - { - UserAccountServicesConnector m_Connector = new UserAccountServicesConnector(DemonServer.Address); - - string first = "Completely"; - string last = "Clueless"; - string email = "foo@bar.com"; - - UserAccount account = m_Connector.CreateUser(first, last, "123", email, UUID.Zero); - Assert.IsNotNull(account, "Failed to create account " + first + " " + last); - UUID user1 = account.PrincipalID; - - account = m_Connector.GetUserAccount(UUID.Zero, user1); - Assert.NotNull(account, "Failed to retrieve account for user id " + user1); - Assert.AreEqual(account.FirstName, first, "First name does not match"); - Assert.AreEqual(account.LastName, last, "Last name does not match"); - - account = m_Connector.GetUserAccount(UUID.Zero, first, last); - Assert.IsNotNull(account, "Failed to retrieve account for user " + first + " " + last); - Assert.AreEqual(account.FirstName, first, "First name does not match (bis)"); - Assert.AreEqual(account.LastName, last, "Last name does not match (bis)"); - - account.Email = "user@example.com"; - bool success = m_Connector.StoreUserAccount(account); - Assert.IsTrue(success, "Failed to store existing account"); - - account = m_Connector.GetUserAccount(UUID.Zero, user1); - Assert.NotNull(account, "Failed to retrieve account for user id " + user1); - Assert.AreEqual(account.Email, "user@example.com", "Incorrect email"); - - account = new UserAccount(UUID.Zero, "DoesNot", "Exist", "xxx@xxx.com"); - success = m_Connector.StoreUserAccount(account); - Assert.IsFalse(success, "Storing a non-existing account must fail"); - - account = m_Connector.GetUserAccount(UUID.Zero, "DoesNot", "Exist"); - Assert.IsNull(account, "Account DoesNot Exist must not be there"); - - } - - } -} diff --git a/OpenSim/Tests/Robust/Robust.Tests.csproj b/OpenSim/Tests/Robust/Robust.Tests.csproj deleted file mode 100644 index c976717a054..00000000000 --- a/OpenSim/Tests/Robust/Robust.Tests.csproj +++ /dev/null @@ -1,37 +0,0 @@ - - - net8.0 - - - - - - - - - - ..\..\..\bin\Nini.dll - False - - - ..\..\..\bin\OpenMetaverse.dll - False - - - ..\..\..\bin\OpenMetaverseTypes.dll - False - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/OpenSim/Tests/Robust/Server/DemonServer.cs b/OpenSim/Tests/Robust/Server/DemonServer.cs deleted file mode 100644 index 1e0797e1ac9..00000000000 --- a/OpenSim/Tests/Robust/Server/DemonServer.cs +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections.Generic; -using System.IO; -using System.Threading; - -using Nini.Config; -using log4net; -using NUnit.Framework; - -using OpenSim.Server; - -namespace Robust.Tests -{ - [SetUpFixture] - public class DemonServer : OpenSimServer - { - private Thread m_demon; - - public static string Address = "http://localhost:8888"; - - [SetUp] - public void StartDemon() - { - if (File.Exists("Robust.Tests.log")) - File.Delete("Robust.Tests.log"); - - Console.WriteLine("**** Starting demon Robust server ****"); - m_demon = new Thread( () => Main(new string[] {"-inifile=Robust.Tests.ini"})); - m_demon.Start(); - // Give some time for the server to instantiate all services - Thread.Sleep(3000); - Console.WriteLine("**** Setup Finished ****"); - } - - [TearDown] - public void StopDemon() - { - Console.WriteLine("**** Killing demon Robust Server ****"); - m_Server.Shutdown(); - } - } -} diff --git a/OpenSim/Tests/Stress/OpenSim.Tests.Stress.csproj b/OpenSim/Tests/Stress/OpenSim.Tests.Stress.csproj deleted file mode 100644 index 29e8ffecfb3..00000000000 --- a/OpenSim/Tests/Stress/OpenSim.Tests.Stress.csproj +++ /dev/null @@ -1,46 +0,0 @@ - - - net8.0 - - - - - - - - - - ..\..\..\bin\Nini.dll - False - - - ..\..\..\bin\OpenMetaverse.dll - False - - - ..\..\..\bin\OpenMetaverse.StructuredData.dll - False - - - ..\..\..\bin\OpenMetaverseTypes.dll - False - - - ..\..\..\bin\XMLRPC.dll - False - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/OpenSim/Tests/Stress/VectorRenderModuleStressTests.cs b/OpenSim/Tests/Stress/VectorRenderModuleStressTests.cs deleted file mode 100644 index e9767f3e84a..00000000000 --- a/OpenSim/Tests/Stress/VectorRenderModuleStressTests.cs +++ /dev/null @@ -1,130 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Reflection; -using System.Threading; -using log4net.Config; -using NUnit.Framework; -using OpenMetaverse; -using OpenMetaverse.Assets; -using OpenSim.Framework; -using OpenSim.Region.CoreModules.Scripting.DynamicTexture; -using OpenSim.Region.CoreModules.Scripting.VectorRender; -using OpenSim.Region.Framework.Scenes; -using OpenSim.Region.Framework.Scenes.Serialization; -using OpenSim.Tests.Common; - -namespace OpenSim.Tests.Stress -{ - [TestFixture] - public class VectorRenderModuleStressTests : OpenSimTestCase - { - public Scene Scene { get; private set; } - public DynamicTextureModule Dtm { get; private set; } - public VectorRenderModule Vrm { get; private set; } - - private void SetupScene(bool reuseTextures) - { - Scene = new SceneHelpers().SetupScene(); - - Dtm = new DynamicTextureModule(); - Dtm.ReuseTextures = reuseTextures; - - Vrm = new VectorRenderModule(); - - SceneHelpers.SetupSceneModules(Scene, Dtm, Vrm); - } - - [Test] - public void TestConcurrentRepeatedDraw() - { - int threads = 4; - TestHelpers.InMethod(); - - SetupScene(false); - - List drawers = new List(); - - for (int i = 0; i < threads; i++) - { - Drawer d = new Drawer(this, i); - drawers.Add(d); - Console.WriteLine("Starting drawer {0}", i); - Util.FireAndForget(o => d.Draw(), null, "VectorRenderModuleStressTests.TestConcurrentRepeatedDraw"); - } - - Thread.Sleep(10 * 60 * 1000); - - drawers.ForEach(d => d.Ready = false); - drawers.ForEach(d => Console.WriteLine("Drawer {0} drew {1} textures", d.Number, d.Pass + 1)); - } - - class Drawer - { - public int Number { get; private set; } - public int Pass { get; private set; } - public bool Ready { get; set; } - - private VectorRenderModuleStressTests m_tests; - - public Drawer(VectorRenderModuleStressTests tests, int number) - { - m_tests = tests; - Number = number; - Ready = true; - } - - public void Draw() - { - SceneObjectGroup so = SceneHelpers.AddSceneObject(m_tests.Scene); - - while (Ready) - { - UUID originalTextureID = so.RootPart.Shape.Textures.GetFace(0).TextureID; - - // Ensure unique text - string text = string.Format("{0:D2}{1}", Number, Pass); - - m_tests.Dtm.AddDynamicTextureData( - m_tests.Scene.RegionInfo.RegionID, - so.UUID, - m_tests.Vrm.GetContentType(), - string.Format("PenColour BLACK; MoveTo 40,220; FontSize 32; Text {0};", text), - ""); - - Assert.That(originalTextureID, Is.Not.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID)); - - Pass++; - } - } - } - } -} \ No newline at end of file diff --git a/bin/Robust.Tests.dll.config b/bin/Robust.Tests.dll.config deleted file mode 100644 index a4c43e75d04..00000000000 --- a/bin/Robust.Tests.dll.config +++ /dev/null @@ -1,43 +0,0 @@ - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/bin/Robust.Tests.ini b/bin/Robust.Tests.ini deleted file mode 100644 index bf7263304d2..00000000000 --- a/bin/Robust.Tests.ini +++ /dev/null @@ -1,468 +0,0 @@ -; * FOR TESTS ONLY -- DO NOT USE THIS FILE -[Const] - - ; The URL of the Robust server - BaseURL = "http://127.0.0.1" - - ; The public port of the Robust server - PublicPort = "8888" - - ; The private port of the Robust server, same for testing - PrivatePort = "8888" - - -; * The startup section lists all the connectors to start up in this server -; * instance. This may be only one, or it may be the entire server suite. -; * Multiple connectors should be separated by commas. -; * -; * These are the IN connectors the server uses, the in connectors -; * read this config file and load the needed service and database connectors -; * -; * The full syntax of a connector string is: -; * [[@]/][:] -; * -[Startup] - ; Place to create a PID file - ; If no path if specified then a PID file is not created. - ; PIDFile = "/tmp/Robust.exe.pid" - - ; Plugin Registry Location - ; Set path to directory for plugin registry. Information - ; about the registered repositories and installed plugins - ; will be stored here - ; The Robust.exe process must have R/W access to the location - RegistryLocation = "." - - ; Modular configurations - ; Set path to directory for modular ini files... - ; The Robust.exe process must have R/W access to the location - ConfigDirectory = "." - - console = "rest" - - ; Console commands can be saved to a file, so the command history persists after a restart. (default is true) - ConsoleHistoryFileEnabled = false - - ; The history file can be just a filename (relative to OpenSim's bin/ directory - ; or it can be a full path to somewhere else. (default is OpenSimConsoleHistory.txt in bin/) - ConsoleHistoryFile = "RobustConsoleHistory.txt" - - ; How many lines of command history should we keep? (default is 100) - ConsoleHistoryFileLines = 100 - -[ServiceList] - GridServiceConnector = "${Const|PrivatePort}/OpenSim.Server.Handlers.dll:GridServiceConnector" - PresenceServiceConnector = "${Const|PrivatePort}/OpenSim.Server.Handlers.dll:PresenceServiceConnector" - InstantMessageServerConnector = "${Const|PublicPort}/OpenSim.Server.Handlers.dll:InstantMessageServerConnector" - UserAccountServiceConnector = "${Const|PrivatePort}/OpenSim.Server.Handlers.dll:UserAccountServiceConnector" - InventoryInConnector = "${Const|PrivatePort}/OpenSim.Server.Handlers.dll:XInventoryInConnector" - - ;; Uncomment as more tests are added - ;AssetServiceConnector = "${Const|PrivatePort}/OpenSim.Server.Handlers.dll:AssetServiceConnector" - ;GridInfoServerInConnector = "${Const|PublicPort}/OpenSim.Server.Handlers.dll:GridInfoServerInConnector" - ;AuthenticationServiceConnector = "${Const|PrivatePort}/OpenSim.Server.Handlers.dll:AuthenticationServiceConnector" - ;OpenIdServerConnector = "${Const|PublicPort}/OpenSim.Server.Handlers.dll:OpenIdServerConnector" - ;AvatarServiceConnector = "${Const|PrivatePort}/OpenSim.Server.Handlers.dll:AvatarServiceConnector" - ;LLLoginServiceInConnector = "${Const|PublicPort}/OpenSim.Server.Handlers.dll:LLLoginServiceInConnector" - ;GridUserServiceConnector = "${Const|PrivatePort}/OpenSim.Server.Handlers.dll:GridUserServiceConnector" - ;FriendsServiceConnector = "${Const|PrivatePort}/OpenSim.Server.Handlers.dll:FriendsServiceConnector" - ;MapAddServiceConnector = "${Const|PrivatePort}/OpenSim.Server.Handlers.dll:MapAddServiceConnector" - ;MapGetServiceConnector = "${Const|PublicPort}/OpenSim.Server.Handlers.dll:MapGetServiceConnector" - ;OfflineIMServiceConnector = "${Const|PrivatePort}/OpenSim.Addons.OfflineIM.dll:OfflineIMServiceRobustConnector" - ;GroupsServiceConnector = "${Const|PrivatePort}/OpenSim.Addons.Groups.dll:GroupsServiceRobustConnector" - ;BakedTextureService = "${Const|PrivatePort}/OpenSim.Server.Handlers.dll:XBakesConnector" - ;UserProfilesServiceConnector = "${Const|PublicPort}/OpenSim.Server.Handlers.dll:UserProfilesConnector" - ;EstateDataService = "${Const|PrivatePort}/OpenSim.Server.Handlers.dll:EstateDataRobustConnector" - -; * This is common for all services, it's the network setup for the entire -; * server instance, if none is specified above -; * -[Network] - port = ${Const|PrivatePort} - - ;; The follow 3 variables are for HTTP Basic Authentication for the Robust services. - ;; Use this if your central services in port ${Const|PrivatePort} need to be accessible on the Internet - ;; but you want to protect them from unauthorized access. - ; AuthType = "BasicHttpAuthentication" - ; HttpAuthUsername = "some_username" - ; HttpAuthPassword = "some_password" - ;; - ;; AuthType above can be overriden in any of the service sections below by - ; AuthType = "None" - ;; This is useful in cases where you want to protect most of the services, - ;; but unprotect individual services. Username and Password can also be - ;; overriden if you want to use different credentials for the different services. - - ;; By default, scripts are not allowed to call private services via llHttpRequest() - ;; Such calls are detected by the X-SecondLife-Shared HTTP header - ;; If you allow such calls you must be sure that they are restricted to very trusted scripters - ;; (remember scripts can also be in visiting avatar attachments). - ;; This can be overriden in individual private service sections if necessary - AllowllHTTPRequestIn = false - - ; * The following are for the remote console - ; * They have no effect for the local or basic console types - ; * Leave commented to diable logins to the console - ;ConsoleUser = Test - ;ConsolePass = secret - ;ConsolePort = 0 - - -[DatabaseService] - ; PGSQL - ; Uncomment these lines if you want to use PGSQL storage - ; Change the connection string to your db details - ;StorageProvider = "OpenSim.Data.PGSQL.dll" - ;ConnectionString = "Server=localhost;Database=opensim;User Id=opensim; password=***;" - - ; Null - ; Uncomment these lines if you want to use MySQL storage - ; Change the connection string to your db details - StorageProvider = "OpenSim.Data.Null.dll" - ConnectionString = "" - - -; * As an example, the below configuration precisely mimicks the legacy -; * asset server. It is read by the asset IN connector (defined above) -; * and it then loads the OUT connector (a local database module). That, -; * in turn, reads the asset loader and database connection information -; * -[AssetService] - LocalServiceModule = "OpenSim.Services.AssetService.dll:AssetService" - DefaultAssetLoader = "" - - ; Allow maptile assets to remotely deleted by remote calls to the asset service. - ; There is no harm in having this as false - it just means that historical maptile assets are not deleted. - ; This only applies to maptiles served via the version 1 viewer mechanisms - ; Default is false - AllowRemoteDelete = false - - ; Allow all assets to be remotely deleted. - ; Only set this to true if you are operating a grid where you control all calls to the asset service - ; (where a necessary condition is that you control all simulators) and you need this for admin purposes. - ; If set to true, AllowRemoteDelete = true is required as well. - ; Default is false. - AllowRemoteDeleteAllTypes = false - - -; * This configuration loads the inventory server modules. It duplicates -; * the function of the legacy inventory server -; * -[InventoryService] - LocalServiceModule = "OpenSim.Services.InventoryService.dll:XInventoryService" - - StorageProvider = "OpenSim.Tests.Common.dll:TestXInventoryDataPlugin" - ConnectionString = "" - - ; Will calls to purge folders (empty trash) and immediately delete/update items or folders (not move to trash first) succeed? - ; If this is set to false then some other arrangement must be made to perform these operations if necessary. - AllowDelete = true - - -; * This is the new style grid service. -; * "Realm" is the table that is used for user lookup. -; * It defaults to "regions", which uses the legacy tables -; * -[GridService] - LocalServiceModule = "OpenSim.Services.GridService.dll:GridService" - ; Realm = "regions" - ; AllowDuplicateNames = "True" - - ;; Next, we can specify properties of regions, including default and fallback regions - ;; The syntax is: Region_ = "" - ;; or: Region_ = "" - ;; where can be DefaultRegion, DefaultHGRegion, FallbackRegion, NoDirectLogin, Persistent, LockedOut, Reservation, NoMove, Authenticate - ;; - ;; DefaultRegion If a local login cannot be placed in the required region (e.g. home region does not exist, avatar is not allowed entry, etc.) - ;; then this region becomes the destination. Only the first online default region will be used. If no DefaultHGRegion - ;; is specified then this will also be used as the region for hypergrid connections that require it (commonly because they have not specified - ;; an explicit region. - ;; - ;; DefaultHGRegion If an avatar connecting via the hypergrid does not specify a region, then they are placed here. Only the first online - ;; region will be used. - ;; - ;; FallbackRegion If the DefaultRegion is not available for a local login, then any FallbackRegions are tried instead. These are tried in the - ;; order specified. This only applies to local logins at this time, not Hypergrid connections. - ;; - ;; NoDirectLogin A hypergrid user cannot directly connect to this region. This does not apply to local logins. - ;; - ;; Persistent When the simulator is shutdown, the region is signalled as offline but left registered on the grid. - ;; - ;; Example specification: - ; Region_Welcome_Area = "DefaultRegion, FallbackRegion" - ; (replace spaces with underscore) - - ;; Allow supporting viewers to export content - ;; Set to false to prevent export - ExportSupported = true - - - - -; * This is the new style authentication service. Currently, only MySQL -; * is implemented. -; * -[AuthenticationService] - ; for the server connector - LocalServiceModule = "OpenSim.Services.AuthenticationService.dll:PasswordAuthenticationService" - - ;; Allow the service to process HTTP getauthinfo calls. - ;; Default is false. - ; AllowGetAuthInfo = false - - ;; Allow the service to process HTTP setauthinfo calls. - ;; Default is false. - ; AllowSetAuthInfo = false - - ;; Allow the service to process HTTP setpassword calls. - ;; Default is false. - ; AllowSetPassword = false - - -; * This is the new style authentication service. Currently, only MySQL -; * is implemented. "Realm" is the table that is used for user lookup. -; * It defaults to "useraccounts", which uses the new style. -; * Realm = "users" will use the legacy tables as an authentication source -; * -[UserAccountService] - StorageProvider = "OpenSim.Data.Null.dll" - ConnectionString = "" - - ; for the server connector - LocalServiceModule = "OpenSim.Services.UserAccountService.dll:UserAccountService" - ; Realm = "useraccounts" - - ; These are for creating new accounts by the service - ;AuthenticationService = "OpenSim.Services.AuthenticationService.dll:PasswordAuthenticationService" - PresenceService = "OpenSim.Services.PresenceService.dll:PresenceService" - GridService = "OpenSim.Services.GridService.dll:GridService" - InventoryService = "OpenSim.Services.InventoryService.dll:XInventoryService" - ;AvatarService = "OpenSim.Services.AvatarService.dll:AvatarService" - ;GridUserService = "OpenSim.Services.UserAccountService.dll:GridUserService" - - ;; This switch creates the minimum set of body parts and avatar entries for a viewer 2 - ;; to show a default "Ruth" avatar rather than a cloud for a newly created user. - ;; Default is false - CreateDefaultAvatarEntries = true - - ;; Allow the service to process HTTP createuser calls. - ;; Default is false. - AllowCreateUser = true - - ;; Allow the service to process HTTP setaccount calls. - ;; Default is false. - AllowSetAccount = true - - -[GridUserService] - ; for the server connector - LocalServiceModule = "OpenSim.Services.UserAccountService.dll:GridUserService" - - -[PresenceService] - ; for the server connector - LocalServiceModule = "OpenSim.Services.PresenceService.dll:PresenceService" - ; Set this to true to allow the use of advanced web services and multiple - ; bots using one account - AllowDuplicatePresences = false; - - -[AvatarService] - ; for the server connector - LocalServiceModule = "OpenSim.Services.AvatarService.dll:AvatarService" - - -[FriendsService] - ; for the server connector - LocalServiceModule = "OpenSim.Services.FriendsService.dll:FriendsService" - -[EstateService] - LocalServiceModule = "OpenSim.Services.EstateService.dll:EstateDataService" - -[LibraryService] - LibraryName = "OpenSim Library" - DefaultLibrary = "./inventory/Libraries.xml" - - -[LoginService] - ; for the server connector - LocalServiceModule = "OpenSim.Services.LLLoginService.dll:LLLoginService" - ; for the service - UserAccountService = "OpenSim.Services.UserAccountService.dll:UserAccountService" - GridUserService = "OpenSim.Services.UserAccountService.dll:GridUserService" - AuthenticationService = "OpenSim.Services.AuthenticationService.dll:PasswordAuthenticationService" - InventoryService = "OpenSim.Services.InventoryService.dll:XInventoryService" - AvatarService = "OpenSim.Services.AvatarService.dll:AvatarService" - PresenceService = "OpenSim.Services.PresenceService.dll:PresenceService" - GridService = "OpenSim.Services.GridService.dll:GridService" - SimulationService ="OpenSim.Services.Connectors.dll:SimulationServiceConnector" - LibraryService = "OpenSim.Services.InventoryService.dll:LibraryService" - FriendsService = "OpenSim.Services.FriendsService.dll:FriendsService" - - ; The minimum user level required for a user to be able to login. 0 by default - ; If you disable a particular user's account then you can set their login level below this number. - ; You can also change this level from the console though these changes will not be persisted. - ; MinLoginLevel = 0 - - ; Ask co-operative viewers to use a different currency name - ;Currency = "" - - ;; Set minimum fee to publish classified - ; ClassifiedFee = 0 - - WelcomeMessage = "Welcome, Avatar!" - AllowRemoteSetLoginLevel = "false" - - ; For V2 map - MapTileURL = "${Const|BaseURL}:${Const|PublicPort}/"; - - ; Url to search service - ; SearchURL = "${Const|BaseURL}:${Const|PublicPort}/"; - - ; For V3 destination guide - ; DestinationGuide = "${Const|BaseURL}/guide" - - ; For V3 avatar picker (( work in progress )) - ; AvatarPicker = "${Const|BaseURL}/avatars" - - ; If you run this login server behind a proxy, set this to true - ; HasProxy = false - - ;; Regular expressions for controlling which client versions are accepted/denied. - ;; An empty string means nothing is checked. - ;; - ;; Example 1: allow only these 3 types of clients (any version of them) - ;; AllowedClients = "Imprudence|Hippo|Second Life" - ;; - ;; Example 2: allow all clients except these - ;; DeniedClients = "Twisted|Crawler|Cryolife|FuckLife|StreetLife|GreenLife|AntiLife|KORE-Phaze|Synlyfe|Purple Second Life|SecondLi |Emerald" - ;; - ;; Note that these are regular expressions, so every character counts. - ;; Also note that this is very weak security and should not be trusted as a reliable means - ;; for keeping bad clients out; modified clients can fake their identifiers. - ;; - ;; - ;AllowedClients = "" - ;DeniedClients = "" - - ;# {DSTZone} {} {Override Daylight Saving Time rules} {* none local} "America/Los_Angeles;Pacific Standard Time" - ;; Viewers do not listen to timezone sent by the server. They use Pacific Standard Time instead, - ;; but rely on the server to calculate Daylight Saving Time. Sending another DST than US Pacific - ;; would result in time inconsistencies between grids (during summer and around DST transition period) - ;; default let OpenSim calculate US Pacific DST - ;; "none" disable DST (equivallent to "local" with system set to GMT) - ;; "local" force legacy behaviour (using local system time to calculate DST) - ; DSTZone = "America/Los_Angeles;Pacific Standard Time" - - ;# {DSTZone} {} {Override Daylight Saving Time rules} {* none local} "America/Los_Angeles;Pacific Standard Time" - ;; Viewers do not receive timezone information from the server - almost all (?) default to Pacific Standard Time - ;; However, they do rely on the server to tell them whether it's Daylight Saving Time or not. - ;; Hence, calculating DST based on a different timezone can result in a misleading viewer display and inconsistencies between grids. - ;; By default, this setting uses various timezone names to calculate DST with regards to the viewer's standard PST. - ;; Options are - ;; "none" no DST - ;; "local" use the server's only timezone to calculate DST. This is previous OpenSimulator behaviour. - ;; "America/Los_Angeles;Pacific Standard Time" use these timezone names to look up Daylight savings. - ;; 'America/Los_Angeles' is used on Linux/Mac systems whilst 'Pacific Standard Time' is used on Windows - DSTZone = "America/Los_Angeles;Pacific Standard Time" - - ;Basic Login Service Dos Protection Tweaks - ;; - ;; Some Grids/Users use a transparent proxy that makes use of the X-Forwarded-For HTTP Header, If you do, set this to true - ;; If you set this to true and you don't have a transparent proxy, it may allow attackers to put random things in the X-Forwarded-For header to - ;; get around this basic DOS protection. - ;DOSAllowXForwardedForHeader = false - ;; - ;; The protector adds up requests during this rolling period of time, default 10 seconds - ;DOSRequestTimeFrameMS = 10000 - ;; - ;; The amount of requests in the above timeframe from the same endpoint that triggers protection - ;DOSMaxRequestsInTimeFrame = 5 - ;; - ;; The amount of time that a specific endpoint is blocked. Default 2 minutes. - ;DOSForgiveClientAfterMS = 120000 - ;; - ;; To turn off basic dos protection, set the DOSMaxRequestsInTimeFrame to 0. - - -[MapImageService] - LocalServiceModule = "OpenSim.Services.MapImageService.dll:MapImageService" - - ; Set this if you want to change the default - ; TilesStoragePath = "maptiles" - ; - ; If for some reason you have the AddMapTile service outside the firewall (e.g. ${Const|PublicPort}), - ; you may want to set this. Otherwise, don't set it, because it's already protected. - ; GridService = "OpenSim.Services.GridService.dll:GridService" - ; - ; Additionally, if you run this server behind a proxy, set this to true - ; HasProxy = false - - -[Messaging] - ; OfflineIM - OfflineIMService = "" - - -[GridInfoService] - ; These settings are used to return information on a get_grid_info call. - ; Client launcher scripts and third-party clients make use of this to - ; autoconfigure the client and to provide a nice user experience. If you - ; want to facilitate that, you should configure the settings here according - ; to your grid or standalone setup. - ; - ; See http://opensimulator.org/wiki/GridInfo - - ; login uri: for grid this is the login server URI - login = ${Const|BaseURL}:${Const|PublicPort}/ - - ; long grid name: the long name of your grid - gridname = "the lost continent of hippo" - - ; short grid name: the short name of your grid - gridnick = "hippogrid" - - ; login page: optional: if it exists it will be used to tell the client to use - ; this as splash page - ;welcome = ${Const|BaseURL}/welcome - - ; helper uri: optional: if it exists if will be used to tell the client to use - ; this for all economy related things - ;economy = ${Const|BaseURL}:${Const|PublicPort}/ - - ; web page of grid: optional: page providing further information about your grid - ;about = ${Const|BaseURL}/about/ - - ; account creation: optional: page providing further information about obtaining - ; a user account on your grid - ;register = ${Const|BaseURL}/register - - ; help: optional: page providing further assistance for users of your grid - ;help = ${Const|BaseURL}/help - - ; password help: optional: page providing password assistance for users of your grid - ;password = ${Const|BaseURL}/password - - -[UserProfilesService] - LocalServiceModule = "OpenSim.Services.UserProfilesService.dll:UserProfilesService" - Enabled = false - ;; Configure this for separate profiles database - ;; ConnectionString = "Data Source=localhost;Database=opensim;User ID=opensim;Password=*****;Old Guids=true;" - ;; Realm = UserProfiles - UserAccountService = OpenSim.Services.UserAccountService.dll:UserAccountService - AuthenticationServiceModule = "OpenSim.Services.AuthenticationService.dll:PasswordAuthenticationService" - - -[BakedTextureService] - LocalServiceModule = "OpenSim.Server.Handlers.dll:XBakes" - ;; This directory must be writable by the user ROBUST runs as. It will be created automatically. - BaseDirectory = "./bakes" - -[HGInstantMessageService] - LocalServiceModule = "OpenSim.Services.HypergridService.dll:HGInstantMessageService" - GridService = "OpenSim.Services.GridService.dll:GridService" - PresenceService = "OpenSim.Services.PresenceService.dll:PresenceService" - UserAgentService = "" - ; This should always be true in the Robust config - InGatekeeper = True diff --git a/bin/System.Drawing.Common.dll.linux b/bin/System.Drawing.Common.dll.linux deleted file mode 100644 index 9e26473d19758449ffdf145fe1975e6a627e3639..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 427112 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

(3RkJ%yVF<3!xI*lX^* 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 diff --git a/bin/System.Drawing.Common.dll.win b/bin/System.Drawing.Common.dll.win deleted file mode 100644 index 7c9e87b4e1820b2beb6928ab1dd927d23a8cb2e7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 454248 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�Q$QrG!1cj(vNR~%ioVHm)It4uz^t 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 diff --git a/bin/prebuild.dll b/bin/prebuild.dll deleted file mode 100644 index 14ca3d2116c0604ded1149b63d592c3c83eb1696..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 245760 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

)EAjZmX4%THJ{}KPj$vO% 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