From 5d6d0aa14226fe31e59c4f2e8a9bd6d6dfc4f995 Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Tue, 15 Feb 2011 08:38:37 -0800 Subject: [PATCH 01/81] Catch HttpServer exception: mantis #5381 --- bin/HttpServer_OpenSim.dll | Bin 115712 -> 115712 bytes bin/HttpServer_OpenSim.pdb | Bin 409088 -> 409088 bytes 2 files changed, 0 insertions(+), 0 deletions(-) diff --git a/bin/HttpServer_OpenSim.dll b/bin/HttpServer_OpenSim.dll index a7a1303c63a454d186cd99f206b470a6127d054c..95ea5dd7ffc4891df56a52ba27d558cb81ea2d1a 100644 GIT binary patch delta 434 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 Hd3gLAM%y~8 delta 7702 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 k<&mTmn(o#5ysNL2K` Date: Wed, 16 Feb 2011 08:06:11 +0000 Subject: [PATCH 02/81] Change the QUERYACCESS method to eliminate spurious access denied messages --- .../EntityTransfer/EntityTransferModule.cs | 10 +++++----- .../Simulation/LocalSimulationConnector.cs | 5 +++-- .../Simulation/RemoteSimulationConnector.cs | 7 ++++--- OpenSim/Region/Framework/Scenes/Scene.cs | 3 ++- .../Server/Handlers/Simulation/AgentHandlers.cs | 11 +++++++++-- .../Simulation/SimulationServiceConnector.cs | 17 ++++++++++++++++- .../Services/Interfaces/ISimulationService.cs | 2 +- 7 files changed, 40 insertions(+), 15 deletions(-) diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs index 1337143a31..98aa563a4f 100644 --- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs +++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs @@ -284,9 +284,10 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer return; } - if (!m_aScene.SimulationService.QueryAccess(finalDestination, sp.ControllingClient.AgentId, Vector3.Zero)) + string reason; + if (!m_aScene.SimulationService.QueryAccess(finalDestination, sp.ControllingClient.AgentId, Vector3.Zero, out reason)) { - sp.ControllingClient.SendTeleportFailed("The destination region has refused access"); + sp.ControllingClient.SendTeleportFailed("Teleport failed: " + reason); return; } @@ -323,8 +324,6 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer agentCircuit.CapsPath = CapsUtil.GetRandomCapsObjectPath(); } - string reason = String.Empty; - // Let's create an agent there if one doesn't exist yet. bool logout = false; if (!CreateAgent(sp, reg, finalDestination, agentCircuit, teleportFlags, out reason, out logout)) @@ -778,7 +777,8 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer GridRegion neighbourRegion = scene.GridService.GetRegionByPosition(scene.RegionInfo.ScopeID, (int)x, (int)y); - if (!scene.SimulationService.QueryAccess(neighbourRegion, agent.ControllingClient.AgentId, newpos)) + string reason; + if (!scene.SimulationService.QueryAccess(neighbourRegion, agent.ControllingClient.AgentId, newpos, out reason)) { agent.ControllingClient.SendAlertMessage("Cannot region cross into banned parcel"); if (r == null) diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/LocalSimulationConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/LocalSimulationConnector.cs index 56720b7b7a..a298b65820 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/LocalSimulationConnector.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/LocalSimulationConnector.cs @@ -257,15 +257,16 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation return false; } - public bool QueryAccess(GridRegion destination, UUID id, Vector3 position) + public bool QueryAccess(GridRegion destination, UUID id, Vector3 position, out string reason) { + reason = "Communications failure"; if (destination == null) return false; foreach (Scene s in m_sceneList) { if (s.RegionInfo.RegionID == destination.RegionID) - return s.QueryAccess(id, position); + return s.QueryAccess(id, position, out reason); } //m_log.Debug("[LOCAL COMMS]: region not found for QueryAccess"); return false; diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/RemoteSimulationConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/RemoteSimulationConnector.cs index c4919b319c..0c92bd1c57 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/RemoteSimulationConnector.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/RemoteSimulationConnector.cs @@ -239,18 +239,19 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation } - public bool QueryAccess(GridRegion destination, UUID id, Vector3 position) + public bool QueryAccess(GridRegion destination, UUID id, Vector3 position, out string reason) { + reason = "Communications failure"; if (destination == null) return false; // Try local first - if (m_localBackend.QueryAccess(destination, id, position)) + if (m_localBackend.QueryAccess(destination, id, position, out reason)) return true; // else do the remote thing if (!m_localBackend.IsLocalRegion(destination.RegionHandle)) - return m_remoteConnector.QueryAccess(destination, id, position); + return m_remoteConnector.QueryAccess(destination, id, position, out reason); return false; diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index 355671cde3..2fd6b52cea 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -4923,8 +4923,9 @@ namespace OpenSim.Region.Framework.Scenes // from logging into the region, teleporting into the region // or corssing the broder walking, but will NOT prevent // child agent creation, thereby emulating the SL behavior. - public bool QueryAccess(UUID agentID, Vector3 position) + public bool QueryAccess(UUID agentID, Vector3 position, out string reason) { + reason = String.Empty; return true; } } diff --git a/OpenSim/Server/Handlers/Simulation/AgentHandlers.cs b/OpenSim/Server/Handlers/Simulation/AgentHandlers.cs index 6a23deefb2..372a59c038 100644 --- a/OpenSim/Server/Handlers/Simulation/AgentHandlers.cs +++ b/OpenSim/Server/Handlers/Simulation/AgentHandlers.cs @@ -341,10 +341,17 @@ namespace OpenSim.Server.Handlers.Simulation GridRegion destination = new GridRegion(); destination.RegionID = regionID; - bool result = m_SimulationService.QueryAccess(destination, id, position); + string reason; + bool result = m_SimulationService.QueryAccess(destination, id, position, out reason); responsedata["int_response_code"] = HttpStatusCode.OK; - responsedata["str_response_string"] = result.ToString(); + + OSDMap resp = new OSDMap(2); + + resp["success"] = OSD.FromBoolean(result); + resp["reason"] = OSD.FromString(reason); + + responsedata["str_response_string"] = OSDParser.SerializeJsonString(resp); } protected virtual void DoAgentGet(Hashtable request, Hashtable responsedata, UUID id, UUID regionID) diff --git a/OpenSim/Services/Connectors/Simulation/SimulationServiceConnector.cs b/OpenSim/Services/Connectors/Simulation/SimulationServiceConnector.cs index cc6bffb7bb..f6ee493bfc 100644 --- a/OpenSim/Services/Connectors/Simulation/SimulationServiceConnector.cs +++ b/OpenSim/Services/Connectors/Simulation/SimulationServiceConnector.cs @@ -256,8 +256,10 @@ namespace OpenSim.Services.Connectors.Simulation /// /// - public bool QueryAccess(GridRegion destination, UUID id, Vector3 position) + public bool QueryAccess(GridRegion destination, UUID id, Vector3 position, out string reason) { + reason = "Failed to contact destination"; + // m_log.DebugFormat("[REMOTE SIMULATION CONNECTOR]: QueryAccess start, position={0}", position); IPEndPoint ext = destination.ExternalEndPoint; @@ -283,8 +285,21 @@ namespace OpenSim.Services.Connectors.Simulation m_log.Info("[REMOTE SIMULATION CONNECTOR]: The above web util error was caused by a TP to a sim that doesn't support QUERYACCESS and can be ignored"); return true; } + + reason = result["Message"]; } + else + { + reason = "Communications failure"; + } + + return false; } + + OSDMap resp = (OSDMap)result["_Result"]; + success = resp["success"].AsBoolean(); + reason = resp["reason"].AsString(); + return success; } catch (Exception e) diff --git a/OpenSim/Services/Interfaces/ISimulationService.cs b/OpenSim/Services/Interfaces/ISimulationService.cs index 48a2185b62..b7967578ce 100644 --- a/OpenSim/Services/Interfaces/ISimulationService.cs +++ b/OpenSim/Services/Interfaces/ISimulationService.cs @@ -60,7 +60,7 @@ namespace OpenSim.Services.Interfaces bool RetrieveAgent(GridRegion destination, UUID id, out IAgentData agent); - bool QueryAccess(GridRegion destination, UUID id, Vector3 position); + bool QueryAccess(GridRegion destination, UUID id, Vector3 position, out string reason); /// /// Message from receiving region to departing region, telling it got contacted by the client. From fc84225038a44e114fe58e4b789b746c9b7a8338 Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Wed, 16 Feb 2011 08:18:49 -0800 Subject: [PATCH 03/81] XFF capitalization strikes again -- this time in the XMLRPC method. mantis #5386 --- .../Framework/Servers/HttpServer/BaseHttpServer.cs | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs b/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs index 4c35132ad1..1d05b0284b 100644 --- a/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs +++ b/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs @@ -785,7 +785,19 @@ namespace OpenSim.Framework.Servers.HttpServer if (methodWasFound) { xmlRprcRequest.Params.Add(request.Url); // Param[2] - xmlRprcRequest.Params.Add(request.Headers.Get("X-Forwarded-For")); // Param[3] + + string xff = "X-Forwarded-For"; + string xfflower = xff.ToLower(); + foreach (string s in request.Headers.AllKeys) + { + if (s != null && s.Equals(xfflower)) + { + xff = xfflower; + break; + } + } + xmlRprcRequest.Params.Add(request.Headers.Get(xff)); // Param[3] + try { From 5c15c5e0ffa2da1bbc57e590d05ca19d46470f89 Mon Sep 17 00:00:00 2001 From: Marck Date: Wed, 16 Feb 2011 17:42:01 +0100 Subject: [PATCH 04/81] Changed default directory for storing map tile images from remote regions. --- OpenSim/Services/GridService/HypergridLinker.cs | 2 +- bin/Robust.HG.ini.example | 2 +- bin/config-include/GridCommon.ini.example | 2 +- bin/config-include/StandaloneCommon.ini.example | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/OpenSim/Services/GridService/HypergridLinker.cs b/OpenSim/Services/GridService/HypergridLinker.cs index 9d98c8f59c..12ea453bbc 100644 --- a/OpenSim/Services/GridService/HypergridLinker.cs +++ b/OpenSim/Services/GridService/HypergridLinker.cs @@ -121,7 +121,7 @@ namespace OpenSim.Services.GridService m_Check4096 = gridConfig.GetBoolean("Check4096", true); - m_MapTileDirectory = gridConfig.GetString("MapTileDirectory", string.Empty); + m_MapTileDirectory = gridConfig.GetString("MapTileDirectory", "maptiles"); m_GatekeeperConnector = new GatekeeperServiceConnector(m_AssetService); diff --git a/bin/Robust.HG.ini.example b/bin/Robust.HG.ini.example index 9adf1ac5ff..f12a1434ef 100644 --- a/bin/Robust.HG.ini.example +++ b/bin/Robust.HG.ini.example @@ -72,7 +72,7 @@ ServiceConnectors = "8003/OpenSim.Server.Handlers.dll:AssetServiceConnector,8003 AssetService = "OpenSim.Services.AssetService.dll:AssetService" ;; Directory for map tile images of linked regions - ; MapTileDirectory = "./" + ; MapTileDirectory = "./maptiles" ;; Next, we can specify properties of regions, including default and fallback regions ;; The syntax is: Region_ = "" diff --git a/bin/config-include/GridCommon.ini.example b/bin/config-include/GridCommon.ini.example index e1bcf00f51..4dc0e53342 100644 --- a/bin/config-include/GridCommon.ini.example +++ b/bin/config-include/GridCommon.ini.example @@ -43,7 +43,7 @@ ;AllowHypergridMapSearch = true ;; Directory for map tile images of linked regions - ; MapTileDirectory = "./" + ; MapTileDirectory = "./maptiles" [AvatarService] ; diff --git a/bin/config-include/StandaloneCommon.ini.example b/bin/config-include/StandaloneCommon.ini.example index 213219c12b..816e9a6f10 100644 --- a/bin/config-include/StandaloneCommon.ini.example +++ b/bin/config-include/StandaloneCommon.ini.example @@ -70,7 +70,7 @@ ; Check4096 = true ;; Directory for map tile images of remote regions - ; MapTileDirectory = "./" + ; MapTileDirectory = "./maptiles" ;; Next, we can specify properties of regions, including default and fallback regions ;; The syntax is: Region_ = "" From 25265c964f22a34fa3757ae487c15744f1da5850 Mon Sep 17 00:00:00 2001 From: Marck Date: Wed, 16 Feb 2011 18:34:44 +0100 Subject: [PATCH 05/81] Changed console command "alert" and added new command "alert-user". This addresses Mantis #4709. Command "alert" always sends a message to everybody; the variant "alert general" has been removed. Sending messages to one user is done with the dedicated command "alert-user". --- .../CoreModules/Avatar/Dialog/DialogModule.cs | 60 ++++++------------- 1 file changed, 18 insertions(+), 42 deletions(-) diff --git a/OpenSim/Region/CoreModules/Avatar/Dialog/DialogModule.cs b/OpenSim/Region/CoreModules/Avatar/Dialog/DialogModule.cs index 2b3d2a9b14..8a977c9b44 100644 --- a/OpenSim/Region/CoreModules/Avatar/Dialog/DialogModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Dialog/DialogModule.cs @@ -49,16 +49,15 @@ namespace OpenSim.Region.CoreModules.Avatar.Dialog { m_scene = scene; m_scene.RegisterModuleInterface(this); - + m_scene.AddCommand( - this, "alert", "alert ", - "Send an alert to a user", + this, "alert", "alert ", + "Send an alert to everyone", HandleAlertConsoleCommand); m_scene.AddCommand( - this, "alert general", "alert [general] ", - "Send an alert to everyone", - "If keyword 'general' is omitted, then must be surrounded by quotation marks.", + this, "alert-user", "alert-user ", + "Send an alert to a user", HandleAlertConsoleCommand); } @@ -177,55 +176,32 @@ namespace OpenSim.Region.CoreModules.Avatar.Dialog { if (m_scene.ConsoleScene() != null && m_scene.ConsoleScene() != m_scene) return; - - bool isGeneral = false; - string firstName = string.Empty; - string lastName = string.Empty; + string message = string.Empty; - if (cmdparams.Length > 1) + if (cmdparams[0].ToLower().Equals("alert")) { - firstName = cmdparams[1]; - isGeneral = firstName.ToLower().Equals("general"); - } - if (cmdparams.Length == 2 && !isGeneral) - { - // alert "message" - message = cmdparams[1]; - isGeneral = true; - } - else if (cmdparams.Length > 2 && isGeneral) - { - // alert general - message = CombineParams(cmdparams, 2); + message = CombineParams(cmdparams, 1); + m_log.InfoFormat("[DIALOG]: Sending general alert in region {0} with message {1}", + m_scene.RegionInfo.RegionName, message); + SendGeneralAlert(message); } else if (cmdparams.Length > 3) { - // alert - lastName = cmdparams[2]; + string firstName = cmdparams[1]; + string lastName = cmdparams[2]; message = CombineParams(cmdparams, 3); + m_log.InfoFormat( + "[DIALOG]: Sending alert in region {0} to {1} {2} with message {3}", + m_scene.RegionInfo.RegionName, firstName, lastName, message); + SendAlertToUser(firstName, lastName, message, false); } else { OpenSim.Framework.Console.MainConsole.Instance.Output( - "Usage: alert \"message\" | alert general | alert "); + "Usage: alert | alert-user "); return; } - - if (isGeneral) - { - m_log.InfoFormat( - "[DIALOG]: Sending general alert in region {0} with message {1}", - m_scene.RegionInfo.RegionName, message); - SendGeneralAlert(message); - } - else - { - m_log.InfoFormat( - "[DIALOG]: Sending alert in region {0} to {1} {2} with message {3}", - m_scene.RegionInfo.RegionName, firstName, lastName, message); - SendAlertToUser(firstName, lastName, message, false); - } } private string CombineParams(string[] commandParams, int pos) From c6f2d66eae890bae56cdb9acf6b2691fe539b5f0 Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Wed, 16 Feb 2011 09:57:12 -0800 Subject: [PATCH 06/81] Fix bug introduced by Query Access. The response does not come in a packaged _Result field, it comes as simple OSDMap with 2 fields in it. Also in this commit: comment out irrelevant debug message on AuthService. --- .../PasswordAuthenticationService.cs | 2 +- .../Simulation/SimulationServiceConnector.cs | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/OpenSim/Services/AuthenticationService/PasswordAuthenticationService.cs b/OpenSim/Services/AuthenticationService/PasswordAuthenticationService.cs index 17619ff14f..2fc92487d6 100644 --- a/OpenSim/Services/AuthenticationService/PasswordAuthenticationService.cs +++ b/OpenSim/Services/AuthenticationService/PasswordAuthenticationService.cs @@ -71,7 +71,7 @@ namespace OpenSim.Services.AuthenticationService string hashed = Util.Md5Hash(password + ":" + data.Data["passwordSalt"].ToString()); - m_log.DebugFormat("[PASS AUTH]: got {0}; hashed = {1}; stored = {2}", password, hashed, data.Data["passwordHash"].ToString()); + //m_log.DebugFormat("[PASS AUTH]: got {0}; hashed = {1}; stored = {2}", password, hashed, data.Data["passwordHash"].ToString()); if (data.Data["passwordHash"].ToString() == hashed) { diff --git a/OpenSim/Services/Connectors/Simulation/SimulationServiceConnector.cs b/OpenSim/Services/Connectors/Simulation/SimulationServiceConnector.cs index f6ee493bfc..8aa88cbeec 100644 --- a/OpenSim/Services/Connectors/Simulation/SimulationServiceConnector.cs +++ b/OpenSim/Services/Connectors/Simulation/SimulationServiceConnector.cs @@ -274,7 +274,11 @@ namespace OpenSim.Services.Connectors.Simulation try { OSDMap result = WebUtil.ServiceOSDRequest(uri, request, "QUERYACCESS", 10000); - bool success = result["Success"].AsBoolean(); + bool success = result["success"].AsBoolean(); + reason = result["reason"].AsString(); + + //m_log.DebugFormat("[REMOTE SIMULATION CONNECTOR]: QueryAccess to {0} returned {1}", uri, success); + if (!success) { if (result.ContainsKey("Message")) @@ -296,10 +300,6 @@ namespace OpenSim.Services.Connectors.Simulation return false; } - OSDMap resp = (OSDMap)result["_Result"]; - success = resp["success"].AsBoolean(); - reason = resp["reason"].AsString(); - return success; } catch (Exception e) From 47a5d8d7420f86088d75e4b578e7e997ba2d11c8 Mon Sep 17 00:00:00 2001 From: Marck Date: Fri, 21 Jan 2011 19:55:35 +0100 Subject: [PATCH 07/81] Make osTeleportOwner work in foreign regions by relaxing the restrictions on teleporting an agent. --- .../Shared/Api/Implementation/OSSL_Api.cs | 23 +++++++++++-------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs index 688dfe4649..402d3a5ecf 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs @@ -681,10 +681,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api // CheckThreatLevel(ThreatLevel.High, "osTeleportAgent"); - TeleportAgent(agent, regionName, position, lookat); + TeleportAgent(agent, regionName, position, lookat, false); } - private void TeleportAgent(string agent, string regionName, LSL_Types.Vector3 position, LSL_Types.Vector3 lookat) + private void TeleportAgent(string agent, string regionName, + LSL_Types.Vector3 position, LSL_Types.Vector3 lookat, bool relaxRestrictions) { m_host.AddScriptLPS(1); UUID agentId = new UUID(); @@ -694,7 +695,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api if (presence != null) { // agent must be over owners land to avoid abuse - if (m_host.OwnerID + if (relaxRestrictions || + m_host.OwnerID == World.LandChannel.GetLandObject( presence.AbsolutePosition.X, presence.AbsolutePosition.Y).LandData.OwnerID) { @@ -728,10 +730,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api // CheckThreatLevel(ThreatLevel.High, "osTeleportAgent"); - TeleportAgent(agent, regionX, regionY, position, lookat); + TeleportAgent(agent, regionX, regionY, position, lookat, false); } - private void TeleportAgent(string agent, int regionX, int regionY, LSL_Types.Vector3 position, LSL_Types.Vector3 lookat) + private void TeleportAgent(string agent, int regionX, int regionY, + LSL_Types.Vector3 position, LSL_Types.Vector3 lookat, bool relaxRestrictions) { ulong regionHandle = Util.UIntsToLong(((uint)regionX * (uint)Constants.RegionSize), ((uint)regionY * (uint)Constants.RegionSize)); @@ -742,8 +745,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api ScenePresence presence = World.GetScenePresence(agentId); if (presence != null) { - // agent must be over owners land to avoid abuse - if (m_host.OwnerID + // For osTeleportAgent, agent must be over owners land to avoid abuse + // For osTeleportOwner, this restriction isn't necessary + if (relaxRestrictions || + m_host.OwnerID == World.LandChannel.GetLandObject( presence.AbsolutePosition.X, presence.AbsolutePosition.Y).LandData.OwnerID) { @@ -766,7 +771,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api // Threat level None because this is what can already be done with the World Map in the viewer CheckThreatLevel(ThreatLevel.None, "osTeleportOwner"); - TeleportAgent(m_host.OwnerID.ToString(), regionName, position, lookat); + TeleportAgent(m_host.OwnerID.ToString(), regionName, position, lookat, true); } public void osTeleportOwner(LSL_Types.Vector3 position, LSL_Types.Vector3 lookat) @@ -778,7 +783,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api { CheckThreatLevel(ThreatLevel.None, "osTeleportOwner"); - TeleportAgent(m_host.OwnerID.ToString(), regionX, regionY, position, lookat); + TeleportAgent(m_host.OwnerID.ToString(), regionX, regionY, position, lookat, true); } // Functions that get information from the agent itself. From 4f9c3c73ad8cc2178e44c724c72a4bb292e5ea93 Mon Sep 17 00:00:00 2001 From: Marck Date: Fri, 21 Jan 2011 20:00:04 +0100 Subject: [PATCH 08/81] Add support for new naming syntax of linked regions to osTeleportAgent and osTeleportOwner. --- OpenSim/Region/Framework/Scenes/Scene.cs | 6 +++--- .../Shared/Api/Implementation/OSSL_Api.cs | 17 ++--------------- 2 files changed, 5 insertions(+), 18 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index 2fd6b52cea..02a0268e36 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -3770,15 +3770,15 @@ namespace OpenSim.Region.Framework.Scenes public void RequestTeleportLocation(IClientAPI remoteClient, string regionName, Vector3 position, Vector3 lookat, uint teleportFlags) { - GridRegion regionInfo = GridService.GetRegionByName(UUID.Zero, regionName); - if (regionInfo == null) + List regions = GridService.GetRegionsByName(RegionInfo.ScopeID, regionName, 1); + if (regions == null || regions.Count == 0) { // can't find the region: Tell viewer and abort remoteClient.SendTeleportFailed("The region '" + regionName + "' could not be found."); return; } - RequestTeleportLocation(remoteClient, regionInfo.RegionHandle, position, lookat, teleportFlags); + RequestTeleportLocation(remoteClient, regions[0].RegionHandle, position, lookat, teleportFlags); } /// diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs index 402d3a5ecf..64931d06c5 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs @@ -694,26 +694,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api ScenePresence presence = World.GetScenePresence(agentId); if (presence != null) { - // agent must be over owners land to avoid abuse + // For osTeleportAgent, agent must be over owners land to avoid abuse + // For osTeleportOwner, this restriction isn't necessary if (relaxRestrictions || m_host.OwnerID == World.LandChannel.GetLandObject( presence.AbsolutePosition.X, presence.AbsolutePosition.Y).LandData.OwnerID) { - // Check for hostname, attempt to make a HG link, - // and convert the regionName to the target region - if (regionName.Contains(".") && regionName.Contains(":")) - { - // Even though we use none of the results, we need to perform this call because it appears - // to have some the side effect of setting up hypergrid teleport locations. - World.GridService.GetRegionsByName(World.RegionInfo.ScopeID, regionName, 1); -// List regions = World.GridService.GetRegionsByName(World.RegionInfo.ScopeID, regionName, 1); - - string[] parts = regionName.Split(new char[] { ':' }); - if (parts.Length > 2) - regionName = parts[0] + ':' + parts[1] + "/ " + parts[2]; - regionName = "http://" + regionName; - } World.RequestTeleportLocation(presence.ControllingClient, regionName, new Vector3((float)position.x, (float)position.y, (float)position.z), new Vector3((float)lookat.x, (float)lookat.y, (float)lookat.z), (uint)TPFlags.ViaLocation); From 47252214354cb768ecddb50062d650d22f7d1c4f Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Fri, 18 Feb 2011 20:54:00 +0000 Subject: [PATCH 09/81] Stop the avatar sometimes pausing for more than a second on the border when region crossing. This restores a RemoveFromPhysicalScene() call in ScenePresence.CheckForBorderCrossing() when the agent has been placed in transit. If we don't remove the agent from the physical scene, then the method continues to be called via ScenePresence.Update() until the handover of the client between regions is completed. Since this handover can take more than 1000ms (due to the 1000ms event queue polling response from the server), this results in the avatar pausing on the border for the entire handover period. --- OpenSim/Region/Framework/Scenes/ScenePresence.cs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs index cd70de8440..4150f4a245 100644 --- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs +++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs @@ -2776,6 +2776,13 @@ namespace OpenSim.Region.Framework.Scenes } else { + // We must remove the agent from the physical scene if it has been placed in transit. If we don't, + // then this method continues to be called from ScenePresence.Update() until the handover of the client between + // regions is completed. Since this handover can take more than 1000ms (due to the 1000ms + // event queue polling response from the server), this results in the avatar pausing on the border + // for the handover period. + RemoveFromPhysicalScene(); + // This constant has been inferred from experimentation // I'm not sure what this value should be, so I tried a few values. timeStep = 0.04f; From e774679f62dc0de54c1926b1b4a611ca317d2bd7 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Fri, 18 Feb 2011 21:19:16 +0000 Subject: [PATCH 10/81] minor: add method doc to a few ScenePresence methods --- OpenSim/Region/Framework/Scenes/ScenePresence.cs | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs index 4150f4a245..b47ec3c6ce 100644 --- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs +++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs @@ -2652,8 +2652,11 @@ namespace OpenSim.Region.Framework.Scenes #region Border Crossing Methods /// - /// Checks to see if the avatar is in range of a border and calls CrossToNewRegion + /// Starts the process of moving an avatar into another region if they are crossing the border. /// + /// + /// Also removes the avatar from the physical scene if transit has started. + /// protected void CheckForBorderCrossing() { if (IsChildAgent) @@ -2721,7 +2724,6 @@ namespace OpenSim.Region.Framework.Scenes neighbor = HaveNeighbor(Cardinals.N, ref fix); } - // Makes sure avatar does not end up outside region if (neighbor <= 0) { @@ -2794,6 +2796,15 @@ namespace OpenSim.Region.Framework.Scenes } } + /// + /// Checks whether this region has a neighbour in the given direction. + /// + /// + /// + /// + /// An integer which represents a compass point. N == 1, going clockwise until we reach NW == 8. + /// Returns a positive integer if there is a region in that direction, a negative integer if not. + /// protected int HaveNeighbor(Cardinals car, ref int[] fix) { uint neighbourx = m_regionInfo.RegionLocX; From 88da253c947c78e97f78119203e3c2f216a788e2 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Fri, 18 Feb 2011 21:54:44 +0000 Subject: [PATCH 11/81] Add very basic test which invokes the scene update loop once and checks the frame number. This makes Scene.Update() match its original description of performing a single update, which also matches the semantics of SOG and ScenePresence. --- OpenSim/Region/Framework/Scenes/Scene.cs | 323 +++++++++--------- .../Scenes/Tests/ScenePresenceTests.cs | 3 - .../Framework/Scenes/Tests/SceneTests.cs | 71 ++++ 3 files changed, 232 insertions(+), 165 deletions(-) create mode 100644 OpenSim/Region/Framework/Scenes/Tests/SceneTests.cs diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index 02a0268e36..e0af2d6709 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -129,7 +129,16 @@ namespace OpenSim.Region.Framework.Scenes protected ICapabilitiesModule m_capsModule; // Central Update Loop protected int m_fps = 10; - protected uint m_frame; + + /// + /// Current scene frame number + /// + public uint Frame + { + get; + protected set; + } + protected float m_timespan = 0.089f; protected DateTime m_lastupdate = DateTime.UtcNow; @@ -1183,7 +1192,8 @@ namespace OpenSim.Region.Framework.Scenes try { - Update(); + while (!shuttingdown) + Update(); m_lastUpdate = Util.EnvironmentTickCount(); m_firstHeartbeat = false; @@ -1200,187 +1210,176 @@ namespace OpenSim.Region.Framework.Scenes Watchdog.RemoveThread(); } - /// - /// Performs per-frame updates on the scene, this should be the central scene loop - /// public override void Update() - { - float physicsFPS; - int maintc; + { + TimeSpan SinceLastFrame = DateTime.UtcNow - m_lastupdate; + float physicsFPS = 0f; - while (!shuttingdown) + int maintc = Util.EnvironmentTickCount(); + int tmpFrameMS = maintc; + tempOnRezMS = eventMS = backupMS = terrainMS = landMS = 0; + + // Increment the frame counter + ++Frame; + + try { - TimeSpan SinceLastFrame = DateTime.UtcNow - m_lastupdate; - physicsFPS = 0f; + // Check if any objects have reached their targets + CheckAtTargets(); - maintc = Util.EnvironmentTickCount(); - int tmpFrameMS = maintc; - tempOnRezMS = eventMS = backupMS = terrainMS = landMS = 0; + // Update SceneObjectGroups that have scheduled themselves for updates + // Objects queue their updates onto all scene presences + if (Frame % m_update_objects == 0) + m_sceneGraph.UpdateObjectGroups(); - // Increment the frame counter - ++m_frame; + // Run through all ScenePresences looking for updates + // Presence updates and queued object updates for each presence are sent to clients + if (Frame % m_update_presences == 0) + m_sceneGraph.UpdatePresences(); - try + // Coarse locations relate to positions of green dots on the mini-map (on a SecondLife client) + if (Frame % m_update_coarse_locations == 0) { - // Check if any objects have reached their targets - CheckAtTargets(); - - // Update SceneObjectGroups that have scheduled themselves for updates - // Objects queue their updates onto all scene presences - if (m_frame % m_update_objects == 0) - m_sceneGraph.UpdateObjectGroups(); - - // Run through all ScenePresences looking for updates - // Presence updates and queued object updates for each presence are sent to clients - if (m_frame % m_update_presences == 0) - m_sceneGraph.UpdatePresences(); - - // Coarse locations relate to positions of green dots on the mini-map (on a SecondLife client) - if (m_frame % m_update_coarse_locations == 0) + List coarseLocations; + List avatarUUIDs; + SceneGraph.GetCoarseLocations(out coarseLocations, out avatarUUIDs, 60); + // Send coarse locations to clients + ForEachScenePresence(delegate(ScenePresence presence) { - List coarseLocations; - List avatarUUIDs; - SceneGraph.GetCoarseLocations(out coarseLocations, out avatarUUIDs, 60); - // Send coarse locations to clients - ForEachScenePresence(delegate(ScenePresence presence) - { - presence.SendCoarseLocations(coarseLocations, avatarUUIDs); - }); + presence.SendCoarseLocations(coarseLocations, avatarUUIDs); + }); + } + + int tmpPhysicsMS2 = Util.EnvironmentTickCount(); + if ((Frame % m_update_physics == 0) && m_physics_enabled) + m_sceneGraph.UpdatePreparePhysics(); + physicsMS2 = Util.EnvironmentTickCountSubtract(tmpPhysicsMS2); + + // Apply any pending avatar force input to the avatar's velocity + if (Frame % m_update_entitymovement == 0) + m_sceneGraph.UpdateScenePresenceMovement(); + + // Perform the main physics update. This will do the actual work of moving objects and avatars according to their + // velocity + int tmpPhysicsMS = Util.EnvironmentTickCount(); + if (Frame % m_update_physics == 0) + { + if (m_physics_enabled) + physicsFPS = m_sceneGraph.UpdatePhysics(Math.Max(SinceLastFrame.TotalSeconds, m_timespan)); + if (SynchronizeScene != null) + SynchronizeScene(this); + } + physicsMS = Util.EnvironmentTickCountSubtract(tmpPhysicsMS); + + // Delete temp-on-rez stuff + if (Frame % 1000 == 0 && !m_cleaningTemps) + { + int tmpTempOnRezMS = Util.EnvironmentTickCount(); + m_cleaningTemps = true; + Util.FireAndForget(delegate { CleanTempObjects(); m_cleaningTemps = false; }); + tempOnRezMS = Util.EnvironmentTickCountSubtract(tmpTempOnRezMS); + } + + if (RegionStatus != RegionStatus.SlaveScene) + { + if (Frame % m_update_events == 0) + { + int evMS = Util.EnvironmentTickCount(); + UpdateEvents(); + eventMS = Util.EnvironmentTickCountSubtract(evMS); ; } - int tmpPhysicsMS2 = Util.EnvironmentTickCount(); - if ((m_frame % m_update_physics == 0) && m_physics_enabled) - m_sceneGraph.UpdatePreparePhysics(); - physicsMS2 = Util.EnvironmentTickCountSubtract(tmpPhysicsMS2); - - // Apply any pending avatar force input to the avatar's velocity - if (m_frame % m_update_entitymovement == 0) - m_sceneGraph.UpdateScenePresenceMovement(); - - // Perform the main physics update. This will do the actual work of moving objects and avatars according to their - // velocity - int tmpPhysicsMS = Util.EnvironmentTickCount(); - if (m_frame % m_update_physics == 0) + if (Frame % m_update_backup == 0) { - if (m_physics_enabled) - physicsFPS = m_sceneGraph.UpdatePhysics(Math.Max(SinceLastFrame.TotalSeconds, m_timespan)); - if (SynchronizeScene != null) - SynchronizeScene(this); - } - physicsMS = Util.EnvironmentTickCountSubtract(tmpPhysicsMS); - - // Delete temp-on-rez stuff - if (m_frame % 1000 == 0 && !m_cleaningTemps) - { - int tmpTempOnRezMS = Util.EnvironmentTickCount(); - m_cleaningTemps = true; - Util.FireAndForget(delegate { CleanTempObjects(); m_cleaningTemps = false; }); - tempOnRezMS = Util.EnvironmentTickCountSubtract(tmpTempOnRezMS); + int backMS = Util.EnvironmentTickCount(); + UpdateStorageBackup(); + backupMS = Util.EnvironmentTickCountSubtract(backMS); } - if (RegionStatus != RegionStatus.SlaveScene) + if (Frame % m_update_terrain == 0) { - if (m_frame % m_update_events == 0) - { - int evMS = Util.EnvironmentTickCount(); - UpdateEvents(); - eventMS = Util.EnvironmentTickCountSubtract(evMS); ; - } - - if (m_frame % m_update_backup == 0) - { - int backMS = Util.EnvironmentTickCount(); - UpdateStorageBackup(); - backupMS = Util.EnvironmentTickCountSubtract(backMS); - } - - if (m_frame % m_update_terrain == 0) - { - int terMS = Util.EnvironmentTickCount(); - UpdateTerrain(); - terrainMS = Util.EnvironmentTickCountSubtract(terMS); - } - - //if (m_frame % m_update_land == 0) - //{ - // int ldMS = Util.EnvironmentTickCount(); - // UpdateLand(); - // landMS = Util.EnvironmentTickCountSubtract(ldMS); - //} - - frameMS = Util.EnvironmentTickCountSubtract(tmpFrameMS); - otherMS = tempOnRezMS + eventMS + backupMS + terrainMS + landMS; - lastCompletedFrame = Util.EnvironmentTickCount(); - - // if (m_frame%m_update_avatars == 0) - // UpdateInWorldTime(); - StatsReporter.AddPhysicsFPS(physicsFPS); - StatsReporter.AddTimeDilation(TimeDilation); - StatsReporter.AddFPS(1); - StatsReporter.SetRootAgents(m_sceneGraph.GetRootAgentCount()); - StatsReporter.SetChildAgents(m_sceneGraph.GetChildAgentCount()); - StatsReporter.SetObjects(m_sceneGraph.GetTotalObjectsCount()); - StatsReporter.SetActiveObjects(m_sceneGraph.GetActiveObjectsCount()); - StatsReporter.addFrameMS(frameMS); - StatsReporter.addPhysicsMS(physicsMS + physicsMS2); - StatsReporter.addOtherMS(otherMS); - StatsReporter.SetActiveScripts(m_sceneGraph.GetActiveScriptsCount()); - StatsReporter.addScriptLines(m_sceneGraph.GetScriptLPS()); + int terMS = Util.EnvironmentTickCount(); + UpdateTerrain(); + terrainMS = Util.EnvironmentTickCountSubtract(terMS); } - if (LoginsDisabled && m_frame == 20) - { - // In 99.9% of cases it is a bad idea to manually force garbage collection. However, - // this is a rare case where we know we have just went through a long cycle of heap - // allocations, and there is no more work to be done until someone logs in - GC.Collect(); + //if (Frame % m_update_land == 0) + //{ + // int ldMS = Util.EnvironmentTickCount(); + // UpdateLand(); + // landMS = Util.EnvironmentTickCountSubtract(ldMS); + //} - IConfig startupConfig = m_config.Configs["Startup"]; - if (startupConfig == null || !startupConfig.GetBoolean("StartDisabled", false)) - { - m_log.DebugFormat("[REGION]: Enabling logins for {0}", RegionInfo.RegionName); - LoginsDisabled = false; - m_sceneGridService.InformNeighborsThatRegionisUp(RequestModuleInterface(), RegionInfo); - } + frameMS = Util.EnvironmentTickCountSubtract(tmpFrameMS); + otherMS = tempOnRezMS + eventMS + backupMS + terrainMS + landMS; + lastCompletedFrame = Util.EnvironmentTickCount(); + + // if (Frame%m_update_avatars == 0) + // UpdateInWorldTime(); + StatsReporter.AddPhysicsFPS(physicsFPS); + StatsReporter.AddTimeDilation(TimeDilation); + StatsReporter.AddFPS(1); + StatsReporter.SetRootAgents(m_sceneGraph.GetRootAgentCount()); + StatsReporter.SetChildAgents(m_sceneGraph.GetChildAgentCount()); + StatsReporter.SetObjects(m_sceneGraph.GetTotalObjectsCount()); + StatsReporter.SetActiveObjects(m_sceneGraph.GetActiveObjectsCount()); + StatsReporter.addFrameMS(frameMS); + StatsReporter.addPhysicsMS(physicsMS + physicsMS2); + StatsReporter.addOtherMS(otherMS); + StatsReporter.SetActiveScripts(m_sceneGraph.GetActiveScriptsCount()); + StatsReporter.addScriptLines(m_sceneGraph.GetScriptLPS()); + } + + if (LoginsDisabled && Frame == 20) + { + // In 99.9% of cases it is a bad idea to manually force garbage collection. However, + // this is a rare case where we know we have just went through a long cycle of heap + // allocations, and there is no more work to be done until someone logs in + GC.Collect(); + + IConfig startupConfig = m_config.Configs["Startup"]; + if (startupConfig == null || !startupConfig.GetBoolean("StartDisabled", false)) + { + m_log.DebugFormat("[REGION]: Enabling logins for {0}", RegionInfo.RegionName); + LoginsDisabled = false; + m_sceneGridService.InformNeighborsThatRegionisUp(RequestModuleInterface(), RegionInfo); } } - catch (NotImplementedException) - { - throw; - } - catch (AccessViolationException e) - { - m_log.Error("[REGION]: Failed with exception " + e.ToString() + " On Region: " + RegionInfo.RegionName); - } - //catch (NullReferenceException e) - //{ - // m_log.Error("[REGION]: Failed with exception " + e.ToString() + " On Region: " + RegionInfo.RegionName); - //} - catch (InvalidOperationException e) - { - m_log.Error("[REGION]: Failed with exception " + e.ToString() + " On Region: " + RegionInfo.RegionName); - } - catch (Exception e) - { - m_log.Error("[REGION]: Failed with exception " + e.ToString() + " On Region: " + RegionInfo.RegionName); - } - finally - { - m_lastupdate = DateTime.UtcNow; - } - - maintc = Util.EnvironmentTickCountSubtract(maintc); - maintc = (int)(m_timespan * 1000) - maintc; - - if (maintc > 0) - Thread.Sleep(maintc); - - // Tell the watchdog that this thread is still alive - Watchdog.UpdateThread(); } - } + catch (NotImplementedException) + { + throw; + } + catch (AccessViolationException e) + { + m_log.Error("[REGION]: Failed with exception " + e.ToString() + " On Region: " + RegionInfo.RegionName); + } + //catch (NullReferenceException e) + //{ + // m_log.Error("[REGION]: Failed with exception " + e.ToString() + " On Region: " + RegionInfo.RegionName); + //} + catch (InvalidOperationException e) + { + m_log.Error("[REGION]: Failed with exception " + e.ToString() + " On Region: " + RegionInfo.RegionName); + } + catch (Exception e) + { + m_log.Error("[REGION]: Failed with exception " + e.ToString() + " On Region: " + RegionInfo.RegionName); + } + finally + { + m_lastupdate = DateTime.UtcNow; + } - + maintc = Util.EnvironmentTickCountSubtract(maintc); + maintc = (int)(m_timespan * 1000) - maintc; + + if (maintc > 0) + Thread.Sleep(maintc); + + // Tell the watchdog that this thread is still alive + Watchdog.UpdateThread(); + } public void AddGroupTarget(SceneObjectGroup grp) { diff --git a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceTests.cs b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceTests.cs index ef52363611..8286e4f919 100644 --- a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceTests.cs +++ b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceTests.cs @@ -116,9 +116,6 @@ namespace OpenSim.Region.Framework.Scenes.Tests agent.ChildrenCapSeeds = new Dictionary(); agent.child = true; - if (scene.PresenceService == null) - Console.WriteLine("Presence Service is null"); - scene.PresenceService.LoginAgent(agent.AgentID.ToString(), agent.SessionID, agent.SecureSessionID); string reason; diff --git a/OpenSim/Region/Framework/Scenes/Tests/SceneTests.cs b/OpenSim/Region/Framework/Scenes/Tests/SceneTests.cs new file mode 100644 index 0000000000..9aba8a8bfc --- /dev/null +++ b/OpenSim/Region/Framework/Scenes/Tests/SceneTests.cs @@ -0,0 +1,71 @@ +/* + * 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 NUnit.Framework.SyntaxHelpers; +using OpenMetaverse; +using OpenSim.Framework; +using OpenSim.Framework.Communications; +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; +using OpenSim.Tests.Common.Mock; +using OpenSim.Tests.Common.Setup; + +namespace OpenSim.Region.Framework.Scenes.Tests +{ + /// + /// Scene presence tests + /// + [TestFixture] + public class SceneTests + { + /// + /// Very basic scene update test. Should become more elaborate with time. + /// + [Test] + public void TestUpdateScene() + { + TestHelper.InMethod(); + + Scene scene = SceneSetupHelpers.SetupScene(); + scene.Update(); + + Assert.That(scene.Frame, Is.EqualTo(1)); + } + } +} \ No newline at end of file From 60d47836ce4bc25d6eed637f506a459dccde6b82 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Fri, 18 Feb 2011 22:00:52 +0000 Subject: [PATCH 12/81] minor: remove mono compiler warning --- .../Connectors/Simulation/SimulationServiceConnector.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OpenSim/Services/Connectors/Simulation/SimulationServiceConnector.cs b/OpenSim/Services/Connectors/Simulation/SimulationServiceConnector.cs index 8aa88cbeec..463b2fbc7f 100644 --- a/OpenSim/Services/Connectors/Simulation/SimulationServiceConnector.cs +++ b/OpenSim/Services/Connectors/Simulation/SimulationServiceConnector.cs @@ -185,7 +185,7 @@ namespace OpenSim.Services.Connectors.Simulation } // unreachable - return true; +// return true; } /// From c763edf56dab869982b5ba002d798f147112a361 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Fri, 18 Feb 2011 22:20:08 +0000 Subject: [PATCH 13/81] separate attachment tests out into their own class --- .../Framework/Scenes/Tests/AttachmentTests.cs | 180 ++++++++++++++++++ .../Scenes/Tests/ScenePresenceTests.cs | 50 ----- 2 files changed, 180 insertions(+), 50 deletions(-) create mode 100644 OpenSim/Region/Framework/Scenes/Tests/AttachmentTests.cs diff --git a/OpenSim/Region/Framework/Scenes/Tests/AttachmentTests.cs b/OpenSim/Region/Framework/Scenes/Tests/AttachmentTests.cs new file mode 100644 index 0000000000..60e47f6881 --- /dev/null +++ b/OpenSim/Region/Framework/Scenes/Tests/AttachmentTests.cs @@ -0,0 +1,180 @@ +/* + * 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 NUnit.Framework.SyntaxHelpers; +using OpenMetaverse; +using OpenSim.Framework; +using OpenSim.Framework.Communications; +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; +using OpenSim.Tests.Common.Mock; +using OpenSim.Tests.Common.Setup; + +namespace OpenSim.Region.Framework.Scenes.Tests +{ + /// + /// Scene presence tests + /// + [TestFixture] + public class AttachmentTests + { + public Scene scene, scene2; + public UUID agent1; + public static Random random; + public ulong region1, region2; + public AgentCircuitData acd1; + public SceneObjectGroup sog1, sog2, sog3; + + [TestFixtureSetUp] + public void Init() + { + TestHelper.InMethod(); + + scene = SceneSetupHelpers.SetupScene("Neighbour x", UUID.Random(), 1000, 1000); + scene2 = SceneSetupHelpers.SetupScene("Neighbour x+1", UUID.Random(), 1001, 1000); + + ISharedRegionModule interregionComms = new LocalSimulationConnectorModule(); + interregionComms.Initialise(new IniConfigSource()); + interregionComms.PostInitialise(); + SceneSetupHelpers.SetupSceneModules(scene, new IniConfigSource(), interregionComms); + SceneSetupHelpers.SetupSceneModules(scene2, new IniConfigSource(), interregionComms); + + agent1 = UUID.Random(); + random = new Random(); + sog1 = NewSOG(UUID.Random(), scene, agent1); + sog2 = NewSOG(UUID.Random(), scene, agent1); + sog3 = NewSOG(UUID.Random(), scene, agent1); + + //ulong neighbourHandle = Utils.UIntsToLong((uint)(neighbourx * Constants.RegionSize), (uint)(neighboury * Constants.RegionSize)); + region1 = scene.RegionInfo.RegionHandle; + region2 = scene2.RegionInfo.RegionHandle; + + SceneSetupHelpers.AddRootAgent(scene, agent1); + } + + [TearDown] + public void TearDown() + { + if (MainServer.Instance != null) MainServer.Instance.Stop(); + } + + [Test] + public void T030_TestAddAttachments() + { + TestHelper.InMethod(); + + ScenePresence presence = scene.GetScenePresence(agent1); + + presence.AddAttachment(sog1); + presence.AddAttachment(sog2); + presence.AddAttachment(sog3); + + Assert.That(presence.HasAttachments(), Is.True); + Assert.That(presence.ValidateAttachments(), Is.True); + } + + [Test] + public void T031_RemoveAttachments() + { + TestHelper.InMethod(); + + ScenePresence presence = scene.GetScenePresence(agent1); + presence.RemoveAttachment(sog1); + presence.RemoveAttachment(sog2); + presence.RemoveAttachment(sog3); + Assert.That(presence.HasAttachments(), Is.False); + } + + // I'm commenting this test because scene setup NEEDS InventoryService to + // be non-null + //[Test] + public void T032_CrossAttachments() + { + TestHelper.InMethod(); + + ScenePresence presence = scene.GetScenePresence(agent1); + ScenePresence presence2 = scene2.GetScenePresence(agent1); + presence2.AddAttachment(sog1); + presence2.AddAttachment(sog2); + + ISharedRegionModule serialiser = new SerialiserModule(); + SceneSetupHelpers.SetupSceneModules(scene, new IniConfigSource(), serialiser); + SceneSetupHelpers.SetupSceneModules(scene2, new IniConfigSource(), serialiser); + + Assert.That(presence.HasAttachments(), Is.False, "Presence has attachments before cross"); + + //Assert.That(presence2.CrossAttachmentsIntoNewRegion(region1, true), Is.True, "Cross was not successful"); + Assert.That(presence2.HasAttachments(), Is.False, "Presence2 objects were not deleted"); + Assert.That(presence.HasAttachments(), Is.True, "Presence has not received new objects"); + } + + private SceneObjectGroup NewSOG(UUID uuid, Scene scene, UUID agent) + { + SceneObjectPart sop = new SceneObjectPart(); + sop.Name = RandomName(); + sop.Description = RandomName(); + sop.Text = RandomName(); + sop.SitName = RandomName(); + sop.TouchName = RandomName(); + sop.UUID = uuid; + sop.Shape = PrimitiveBaseShape.Default; + sop.Shape.State = 1; + sop.OwnerID = agent; + + SceneObjectGroup sog = new SceneObjectGroup(sop); + sog.SetScene(scene); + + return sog; + } + + private static string RandomName() + { + StringBuilder name = new StringBuilder(); + int size = random.Next(5,12); + char ch; + for (int i = 0; i < size; i++) + { + ch = Convert.ToChar(Convert.ToInt32(Math.Floor(26 * random.NextDouble() + 65))) ; + name.Append(ch); + } + + return name.ToString(); + } + } +} \ No newline at end of file diff --git a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceTests.cs b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceTests.cs index 8286e4f919..d82760ee94 100644 --- a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceTests.cs +++ b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceTests.cs @@ -331,56 +331,6 @@ namespace OpenSim.Region.Framework.Scenes.Tests Assert.That(presence.IsChildAgent, Is.False, "Presence was not made root in old region again."); } - [Test] - public void T030_TestAddAttachments() - { - TestHelper.InMethod(); - - ScenePresence presence = scene.GetScenePresence(agent1); - - presence.AddAttachment(sog1); - presence.AddAttachment(sog2); - presence.AddAttachment(sog3); - - Assert.That(presence.HasAttachments(), Is.True); - Assert.That(presence.ValidateAttachments(), Is.True); - } - - [Test] - public void T031_RemoveAttachments() - { - TestHelper.InMethod(); - - ScenePresence presence = scene.GetScenePresence(agent1); - presence.RemoveAttachment(sog1); - presence.RemoveAttachment(sog2); - presence.RemoveAttachment(sog3); - Assert.That(presence.HasAttachments(), Is.False); - } - - // I'm commenting this test because scene setup NEEDS InventoryService to - // be non-null - //[Test] - public void T032_CrossAttachments() - { - TestHelper.InMethod(); - - ScenePresence presence = scene.GetScenePresence(agent1); - ScenePresence presence2 = scene2.GetScenePresence(agent1); - presence2.AddAttachment(sog1); - presence2.AddAttachment(sog2); - - ISharedRegionModule serialiser = new SerialiserModule(); - SceneSetupHelpers.SetupSceneModules(scene, new IniConfigSource(), serialiser); - SceneSetupHelpers.SetupSceneModules(scene2, new IniConfigSource(), serialiser); - - Assert.That(presence.HasAttachments(), Is.False, "Presence has attachments before cross"); - - //Assert.That(presence2.CrossAttachmentsIntoNewRegion(region1, true), Is.True, "Cross was not successful"); - Assert.That(presence2.HasAttachments(), Is.False, "Presence2 objects were not deleted"); - Assert.That(presence.HasAttachments(), Is.True, "Presence has not received new objects"); - } - [TearDown] public void TearDown() { From c155f57dbe6b36697d2e1e50d4de43f7af2b97d1 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Fri, 18 Feb 2011 22:22:51 +0000 Subject: [PATCH 14/81] remove unused test teardown method --- .../Region/Framework/Scenes/Tests/AttachmentTests.cs | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/Tests/AttachmentTests.cs b/OpenSim/Region/Framework/Scenes/Tests/AttachmentTests.cs index 60e47f6881..af4464081b 100644 --- a/OpenSim/Region/Framework/Scenes/Tests/AttachmentTests.cs +++ b/OpenSim/Region/Framework/Scenes/Tests/AttachmentTests.cs @@ -49,7 +49,7 @@ using OpenSim.Tests.Common.Setup; namespace OpenSim.Region.Framework.Scenes.Tests { /// - /// Scene presence tests + /// Attachment tests /// [TestFixture] public class AttachmentTests @@ -86,13 +86,7 @@ namespace OpenSim.Region.Framework.Scenes.Tests region2 = scene2.RegionInfo.RegionHandle; SceneSetupHelpers.AddRootAgent(scene, agent1); - } - - [TearDown] - public void TearDown() - { - if (MainServer.Instance != null) MainServer.Instance.Stop(); - } + } [Test] public void T030_TestAddAttachments() From 023f953f39709e90c8eb31bc332dc2c01346cbd9 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Fri, 18 Feb 2011 22:25:45 +0000 Subject: [PATCH 15/81] remove another unused test teardown method --- OpenSim/Region/Framework/Scenes/Tests/ScenePresenceTests.cs | 6 ------ 1 file changed, 6 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceTests.cs b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceTests.cs index d82760ee94..ddff89669a 100644 --- a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceTests.cs +++ b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceTests.cs @@ -331,12 +331,6 @@ namespace OpenSim.Region.Framework.Scenes.Tests Assert.That(presence.IsChildAgent, Is.False, "Presence was not made root in old region again."); } - [TearDown] - public void TearDown() - { - if (MainServer.Instance != null) MainServer.Instance.Stop(); - } - public static string GetRandomCapsObjectPath() { UUID caps = UUID.Random(); From eb699df5f6c7a68a500e38dc994ed7c2f2aa89d9 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Fri, 18 Feb 2011 22:49:19 +0000 Subject: [PATCH 16/81] On SceneSetupHelpers, go back to calling ScenePresence.CompleteMovement() for the last stage of AddRootAgent() instead of SP.MakeRootAgent() Going this extra step doesn't appear to cause any test failures. This is arguably better for test purposes, though at some stage another method may arise which does just call AddRootAgent(). --- .../Scenes/Tests/ScenePresenceTests.cs | 60 +++++++++++++------ .../Tests/Common/Setup/SceneSetupHelpers.cs | 8 +-- 2 files changed, 44 insertions(+), 24 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceTests.cs b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceTests.cs index ddff89669a..92c73be722 100644 --- a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceTests.cs +++ b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceTests.cs @@ -172,25 +172,6 @@ namespace OpenSim.Region.Framework.Scenes.Tests Assert.That(neighbours.Count, Is.EqualTo(2)); } - - public void fixNullPresence() - { - string firstName = "testfirstname"; - - AgentCircuitData agent = new AgentCircuitData(); - agent.AgentID = agent1; - agent.firstname = firstName; - 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 = GetRandomCapsObjectPath(); - - acd1 = agent; - } [Test] public void T013_TestRemoveNeighbourRegion() @@ -208,6 +189,28 @@ namespace OpenSim.Region.Framework.Scenes.Tests CompleteAvatarMovement */ } + + /// + /// 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 structures + /// + [Test] + public void TestChildAgentEstablished() + { + UUID agent1Id = UUID.Parse("00000000-0000-0000-0000-000000000001"); + + TestScene myScene1 = SceneSetupHelpers.SetupScene("Neighbour x", UUID.Random(), 1000, 1000); + TestScene myScene2 = SceneSetupHelpers.SetupScene("Neighbour x+1", UUID.Random(), 1001, 1000); + + SceneSetupHelpers.AddRootAgent(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); + } // I'm commenting this test, because this is not supposed to happen here //[Test] @@ -330,7 +333,26 @@ namespace OpenSim.Region.Framework.Scenes.Tests Assert.That(presence2.IsChildAgent, Is.True, "Did not return from region as expected."); Assert.That(presence.IsChildAgent, Is.False, "Presence was not made root in old region again."); } + + public void fixNullPresence() + { + string firstName = "testfirstname"; + AgentCircuitData agent = new AgentCircuitData(); + agent.AgentID = agent1; + agent.firstname = firstName; + 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 = GetRandomCapsObjectPath(); + + acd1 = agent; + } + public static string GetRandomCapsObjectPath() { UUID caps = UUID.Random(); diff --git a/OpenSim/Tests/Common/Setup/SceneSetupHelpers.cs b/OpenSim/Tests/Common/Setup/SceneSetupHelpers.cs index 8b1649635c..d199e42440 100644 --- a/OpenSim/Tests/Common/Setup/SceneSetupHelpers.cs +++ b/OpenSim/Tests/Common/Setup/SceneSetupHelpers.cs @@ -504,12 +504,10 @@ namespace OpenSim.Tests.Common.Setup TestClient client = new TestClient(agentData, scene); scene.AddNewClient(client); - // Stage 3: Invoke agent crossing, which converts the child agent into a root agent (with appearance, - // inventory, etc.) - //scene.AgentCrossing(agentData.AgentID, new Vector3(90, 90, 90), false); OBSOLETE - + // Stage 3: Complete the entrance into the region. This converts the child agent into a root agent. ScenePresence scp = scene.GetScenePresence(agentData.AgentID); - scp.MakeRootAgent(new Vector3(90, 90, 90), true); + scp.CompleteMovement(client); + //scp.MakeRootAgent(new Vector3(90, 90, 90), true); return client; } From dd9efc183812a66b1654aaeb419945cf57650b08 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Fri, 18 Feb 2011 23:05:56 +0000 Subject: [PATCH 17/81] extend TestChildAgentEstablished() test slightly to put in EntityTransferModule. Not yet enabled. --- OpenSim/Region/Framework/Scenes/ScenePresence.cs | 4 +++- .../Framework/Scenes/Tests/ScenePresenceTests.cs | 11 +++++++++-- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs index b47ec3c6ce..51b8dcc004 100644 --- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs +++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs @@ -1161,7 +1161,9 @@ namespace OpenSim.Region.Framework.Scenes if (m_agentTransfer != null) m_agentTransfer.EnableChildAgents(this); else - m_log.DebugFormat("[SCENE PRESENCE]: Unable to create child agents in neighbours, because AgentTransferModule is not active"); + m_log.DebugFormat( + "[SCENE PRESENCE]: Unable to create child agents in neighbours, because AgentTransferModule is not active for region {0}", + m_scene.RegionInfo.RegionName); IFriendsModule friendsModule = m_scene.RequestModuleInterface(); if (friendsModule != null) diff --git a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceTests.cs b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceTests.cs index 92c73be722..60bc86c719 100644 --- a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceTests.cs +++ b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceTests.cs @@ -40,6 +40,7 @@ using OpenSim.Framework; using OpenSim.Framework.Communications; 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.Tests.Common; @@ -199,10 +200,16 @@ namespace OpenSim.Region.Framework.Scenes.Tests [Test] public void TestChildAgentEstablished() { + TestHelper.InMethod(); + log4net.Config.XmlConfigurator.Configure(); + UUID agent1Id = UUID.Parse("00000000-0000-0000-0000-000000000001"); - TestScene myScene1 = SceneSetupHelpers.SetupScene("Neighbour x", UUID.Random(), 1000, 1000); - TestScene myScene2 = SceneSetupHelpers.SetupScene("Neighbour x+1", UUID.Random(), 1001, 1000); + TestScene myScene1 = SceneSetupHelpers.SetupScene("Neighbour y", UUID.Random(), 1000, 1000); + TestScene myScene2 = SceneSetupHelpers.SetupScene("Neighbour y + 1", UUID.Random(), 1001, 1000); + + EntityTransferModule etm = new EntityTransferModule(); + SceneSetupHelpers.SetupSceneModules(myScene1, etm); SceneSetupHelpers.AddRootAgent(myScene1, agent1Id); ScenePresence childPresence = myScene2.GetScenePresence(agent1); From 5c92f62941e21b6e5eec503ab95f149092e20217 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Fri, 18 Feb 2011 23:10:46 +0000 Subject: [PATCH 18/81] minor: remove mono compiler warning --- OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs b/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs index 584c57719a..583214ca0b 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs @@ -845,7 +845,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP private void HandleUseCircuitCode(object o) { - DateTime startTime = DateTime.Now; +// DateTime startTime = DateTime.Now; object[] array = (object[])o; UDPPacketBuffer buffer = (UDPPacketBuffer)array[0]; UseCircuitCodePacket packet = (UseCircuitCodePacket)array[1]; From 8249d77991352697b4972f7109c014db0ebd5f68 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Fri, 18 Feb 2011 23:25:59 +0000 Subject: [PATCH 19/81] If GridService.GetNeighbours() could not find the region then log a warning rather than causing a null reference on the normal log line This also extends the TestChildAgentEstablished() test to actually activate the EntityTransferModule, though the test is not yet viable --- .../Framework/Scenes/Tests/ScenePresenceTests.cs | 7 +++++-- OpenSim/Services/GridService/GridService.cs | 12 +++++++++++- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceTests.cs b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceTests.cs index 60bc86c719..5e1ff79b6b 100644 --- a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceTests.cs +++ b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceTests.cs @@ -201,15 +201,18 @@ namespace OpenSim.Region.Framework.Scenes.Tests public void TestChildAgentEstablished() { TestHelper.InMethod(); - log4net.Config.XmlConfigurator.Configure(); +// log4net.Config.XmlConfigurator.Configure(); UUID agent1Id = UUID.Parse("00000000-0000-0000-0000-000000000001"); TestScene myScene1 = SceneSetupHelpers.SetupScene("Neighbour y", UUID.Random(), 1000, 1000); TestScene myScene2 = SceneSetupHelpers.SetupScene("Neighbour y + 1", UUID.Random(), 1001, 1000); + IConfigSource configSource = new IniConfigSource(); + configSource.AddConfig("Modules").Set("EntityTransferModule", "BasicEntityTransferModule"); EntityTransferModule etm = new EntityTransferModule(); - SceneSetupHelpers.SetupSceneModules(myScene1, etm); + + SceneSetupHelpers.SetupSceneModules(myScene1, configSource, etm); SceneSetupHelpers.AddRootAgent(myScene1, agent1Id); ScenePresence childPresence = myScene2.GetScenePresence(agent1); diff --git a/OpenSim/Services/GridService/GridService.cs b/OpenSim/Services/GridService/GridService.cs index aeff9b524f..985d77b02d 100644 --- a/OpenSim/Services/GridService/GridService.cs +++ b/OpenSim/Services/GridService/GridService.cs @@ -271,6 +271,7 @@ namespace OpenSim.Services.GridService { List rinfos = new List(); RegionData region = m_Database.Get(regionID, scopeID); + if (region != null) { // Not really? Maybe? @@ -278,15 +279,24 @@ namespace OpenSim.Services.GridService region.posX + (int)Constants.RegionSize + 1, region.posY + (int)Constants.RegionSize + 1, scopeID); foreach (RegionData rdata in rdatas) + { if (rdata.RegionID != regionID) { int flags = Convert.ToInt32(rdata.Data["flags"]); if ((flags & (int)Data.RegionFlags.Hyperlink) == 0) // no hyperlinks as neighbours rinfos.Add(RegionData2RegionInfo(rdata)); } + } + m_log.DebugFormat("[GRID SERVICE]: region {0} has {1} neighbours", region.RegionName, rinfos.Count); } - m_log.DebugFormat("[GRID SERVICE]: region {0} has {1} neighbours", region.RegionName, rinfos.Count); + else + { + m_log.WarnFormat( + "[GRID SERVICE]: GetNeighbours() called for scope {0}, region {1} but no such region found", + scopeID, regionID); + } + return rinfos; } From 60fe3d48ee83f004861044c51537256c0c389478 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Fri, 18 Feb 2011 23:50:54 +0000 Subject: [PATCH 20/81] Put some CapabilitiesModule null checks in Scene Stop tests setting up a capabilities module by default --- OpenSim/Framework/Capabilities/Caps.cs | 1 - OpenSim/Region/Framework/Scenes/Scene.cs | 15 +++++++++++---- OpenSim/Tests/Common/Mock/TestClient.cs | 7 +++++-- OpenSim/Tests/Common/Setup/SceneSetupHelpers.cs | 8 ++++---- 4 files changed, 20 insertions(+), 11 deletions(-) diff --git a/OpenSim/Framework/Capabilities/Caps.cs b/OpenSim/Framework/Capabilities/Caps.cs index c2f9c3ab7b..3be97b5c89 100644 --- a/OpenSim/Framework/Capabilities/Caps.cs +++ b/OpenSim/Framework/Capabilities/Caps.cs @@ -181,7 +181,6 @@ namespace OpenSim.Framework.Capabilities RegisterRegionServiceHandlers(capsBase); RegisterInventoryServiceHandlers(capsBase); - } public void RegisterRegionServiceHandlers(string capsBase) diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index e0af2d6709..ee1e0beee4 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -3010,7 +3010,9 @@ namespace OpenSim.Region.Framework.Scenes (childagentYN ? "child" : "root"), agentID, RegionInfo.RegionName); m_sceneGraph.removeUserCount(!childagentYN); - CapsModule.RemoveCapsHandler(agentID); + + if (CapsModule != null) + CapsModule.RemoveCapsHandler(agentID); // REFACTORING PROBLEM -- well not really a problem, but just to point out that whatever // this method is doing is HORRIBLE!!! @@ -3265,8 +3267,11 @@ namespace OpenSim.Region.Framework.Scenes RegionInfo.RegionName, (agent.child ? "child" : "root"), agent.firstname, agent.lastname, agent.AgentID, agent.circuitcode); - CapsModule.NewUserConnection(agent); - CapsModule.AddCapsHandler(agent.AgentID); + if (CapsModule != null) + { + CapsModule.NewUserConnection(agent); + CapsModule.AddCapsHandler(agent.AgentID); + } } else { @@ -3281,7 +3286,9 @@ namespace OpenSim.Region.Framework.Scenes agent.AgentID, RegionInfo.RegionName); sp.AdjustKnownSeeds(); - CapsModule.NewUserConnection(agent); + + if (CapsModule != null) + CapsModule.NewUserConnection(agent); } } diff --git a/OpenSim/Tests/Common/Mock/TestClient.cs b/OpenSim/Tests/Common/Mock/TestClient.cs index dc0d4deb18..ebe0a72a87 100644 --- a/OpenSim/Tests/Common/Mock/TestClient.cs +++ b/OpenSim/Tests/Common/Mock/TestClient.cs @@ -560,8 +560,11 @@ namespace OpenSim.Tests.Common.Mock agentData.lastname = m_lastName; ICapabilitiesModule capsModule = m_scene.RequestModuleInterface(); - agentData.CapsPath = capsModule.GetCapsPath(m_agentId); - agentData.ChildrenCapSeeds = new Dictionary(capsModule.GetChildrenSeeds(m_agentId)); + if (capsModule != null) + { + agentData.CapsPath = capsModule.GetCapsPath(m_agentId); + agentData.ChildrenCapSeeds = new Dictionary(capsModule.GetChildrenSeeds(m_agentId)); + } return agentData; } diff --git a/OpenSim/Tests/Common/Setup/SceneSetupHelpers.cs b/OpenSim/Tests/Common/Setup/SceneSetupHelpers.cs index d199e42440..91426166e0 100644 --- a/OpenSim/Tests/Common/Setup/SceneSetupHelpers.cs +++ b/OpenSim/Tests/Common/Setup/SceneSetupHelpers.cs @@ -164,10 +164,10 @@ namespace OpenSim.Tests.Common.Setup TestScene testScene = new TestScene( regInfo, acm, scs, simDataService, estateDataService, null, false, false, false, configSource, null); - INonSharedRegionModule capsModule = new CapabilitiesModule(); - capsModule.Initialise(new IniConfigSource()); - testScene.AddRegionModule(capsModule.Name, capsModule); - capsModule.AddRegion(testScene); +// INonSharedRegionModule capsModule = new CapabilitiesModule(); +// capsModule.Initialise(new IniConfigSource()); +// testScene.AddRegionModule(capsModule.Name, capsModule); +// capsModule.AddRegion(testScene); IRegionModule godsModule = new GodsModule(); godsModule.Initialise(testScene, new IniConfigSource()); From 9d668b09ca893c706745cd2b8fb9b7922b6eeee6 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Sat, 19 Feb 2011 00:07:16 +0000 Subject: [PATCH 21/81] remove unused code to share services between scenes in SceneSetupHelpers - this is done differently elsewhere --- .../Tests/Common/Setup/SceneSetupHelpers.cs | 68 +++++-------------- 1 file changed, 16 insertions(+), 52 deletions(-) diff --git a/OpenSim/Tests/Common/Setup/SceneSetupHelpers.cs b/OpenSim/Tests/Common/Setup/SceneSetupHelpers.cs index 91426166e0..3980c180cd 100644 --- a/OpenSim/Tests/Common/Setup/SceneSetupHelpers.cs +++ b/OpenSim/Tests/Common/Setup/SceneSetupHelpers.cs @@ -132,24 +132,11 @@ namespace OpenSim.Tests.Common.Setup public static TestScene SetupScene( string name, UUID id, uint x, uint y, String realServices) { - bool newScene = false; - Console.WriteLine("Setting up test scene {0}", name); - // REFACTORING PROBLEM! - //// If cm is the same as our last commsManager used, this means the tester wants to link - //// regions. In this case, don't use the sameshared region modules and dont initialize them again. - //// Also, no need to start another MainServer and MainConsole instance. - //if (cm == null || cm != commsManager) - //{ - // System.Console.WriteLine("Starting a brand new scene"); - // newScene = true; - MainConsole.Instance = new MockConsole("TEST PROMPT"); - // MainServer.Instance = new BaseHttpServer(980); - // commsManager = cm; - //} - // We must set up a console otherwise setup of some modules may fail + MainConsole.Instance = new MockConsole("TEST PROMPT"); + RegionInfo regInfo = new RegionInfo(x, y, new IPEndPoint(IPAddress.Loopback, 9000), "127.0.0.1"); regInfo.RegionName = name; regInfo.RegionID = id; @@ -164,50 +151,27 @@ namespace OpenSim.Tests.Common.Setup TestScene testScene = new TestScene( regInfo, acm, scs, simDataService, estateDataService, null, false, false, false, configSource, null); -// INonSharedRegionModule capsModule = new CapabilitiesModule(); -// capsModule.Initialise(new IniConfigSource()); -// testScene.AddRegionModule(capsModule.Name, capsModule); -// capsModule.AddRegion(testScene); - IRegionModule godsModule = new GodsModule(); godsModule.Initialise(testScene, new IniConfigSource()); testScene.AddModule(godsModule.Name, godsModule); realServices = realServices.ToLower(); - // IConfigSource config = new IniConfigSource(); - // If we have a brand new scene, need to initialize shared region modules - if ((m_assetService == null && m_inventoryService == null) || newScene) - { - if (realServices.Contains("asset")) - StartAssetService(testScene, true); - else - StartAssetService(testScene, false); - - // For now, always started a 'real' authentication service - StartAuthenticationService(testScene, true); - - if (realServices.Contains("inventory")) - StartInventoryService(testScene, true); - else - StartInventoryService(testScene, false); - - StartGridService(testScene, true); - StartUserAccountService(testScene); - StartPresenceService(testScene); - } - // If not, make sure the shared module gets references to this new scene + if (realServices.Contains("asset")) + StartAssetService(testScene, true); else - { - m_assetService.AddRegion(testScene); - m_assetService.RegionLoaded(testScene); - m_inventoryService.AddRegion(testScene); - m_inventoryService.RegionLoaded(testScene); - m_userAccountService.AddRegion(testScene); - m_userAccountService.RegionLoaded(testScene); - m_presenceService.AddRegion(testScene); - m_presenceService.RegionLoaded(testScene); + StartAssetService(testScene, false); - } + // For now, always started a 'real' authentication service + StartAuthenticationService(testScene, true); + + if (realServices.Contains("inventory")) + StartInventoryService(testScene, true); + else + StartInventoryService(testScene, false); + + StartGridService(testScene, true); + StartUserAccountService(testScene); + StartPresenceService(testScene); m_inventoryService.PostInitialise(); m_assetService.PostInitialise(); From b3a1d8c7f787dd2ad24b925bfcdd08b676b3d8b3 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Sat, 19 Feb 2011 00:11:08 +0000 Subject: [PATCH 22/81] Remove unused SceneSetupHelpers.DeleteObjectAsync(). Calling async code in automated tests is never a good idea - things become very fragile very quickly --- .../Tests/Common/Setup/SceneSetupHelpers.cs | 19 ------------------- 1 file changed, 19 deletions(-) diff --git a/OpenSim/Tests/Common/Setup/SceneSetupHelpers.cs b/OpenSim/Tests/Common/Setup/SceneSetupHelpers.cs index 3980c180cd..5be70bc710 100644 --- a/OpenSim/Tests/Common/Setup/SceneSetupHelpers.cs +++ b/OpenSim/Tests/Common/Setup/SceneSetupHelpers.cs @@ -505,24 +505,5 @@ namespace OpenSim.Tests.Common.Setup return part; } - - /// - /// Delete a scene object asynchronously - /// - /// - /// - /// - /// - /// - public static void DeleteSceneObjectAsync( - TestScene scene, SceneObjectPart part, DeRezAction action, UUID destinationId, IClientAPI client) - { - // Turn off the timer on the async sog deleter - we'll crank it by hand within a unit test - AsyncSceneObjectGroupDeleter sogd = scene.SceneObjectGroupDeleter; - sogd.Enabled = false; - - scene.DeRezObjects(client, new List() { part.LocalId }, UUID.Zero, action, destinationId); - sogd.InventoryDeQueueAndDelete(); - } } } From 9e47018cfb42cc67a1d414e73396861b3a6b99ea Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Sat, 19 Feb 2011 00:14:13 +0000 Subject: [PATCH 23/81] Remove test T020_TestMakeRootAgent() which hasn't been active for ages anyway This test was non-viable. Keeping inactive T021_TestCrossToNewRegion() around for now since it's still useful for reference purposes in constructing a future working test. --- .../Scenes/Tests/ScenePresenceTests.cs | 19 ------------------- 1 file changed, 19 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceTests.cs b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceTests.cs index 5e1ff79b6b..fd2d6fab2d 100644 --- a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceTests.cs +++ b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceTests.cs @@ -222,25 +222,6 @@ namespace OpenSim.Region.Framework.Scenes.Tests // Assert.That(childPresence.IsChildAgent, Is.True); } - // I'm commenting this test, because this is not supposed to happen here - //[Test] - public void T020_TestMakeRootAgent() - { - TestHelper.InMethod(); - - ScenePresence presence = scene.GetScenePresence(agent1); - Assert.That(presence.IsChildAgent, Is.False, "Starts out as a root agent"); - - presence.MakeChildAgent(); - Assert.That(presence.IsChildAgent, Is.True, "Did not change to child agent after MakeChildAgent"); - - // Accepts 0 but rejects Constants.RegionSize - Vector3 pos = new Vector3(0,unchecked(Constants.RegionSize-1),0); - presence.MakeRootAgent(pos,true); - Assert.That(presence.IsChildAgent, Is.False, "Did not go back to root agent"); - Assert.That(presence.AbsolutePosition, Is.EqualTo(pos), "Position is not the same one entered"); - } - // I'm commenting this test because it does not represent // crossings. The Thread.Sleep's in here are not meaningful mocks, // and they sometimes fail in panda. From af22b7cb1af041ab685128f507265d9c7e7fac9c Mon Sep 17 00:00:00 2001 From: Marck Date: Tue, 22 Feb 2011 13:00:45 +0100 Subject: [PATCH 24/81] GetRegion(s)ByName with SQLite behaves like it does with other databases. The in-memory storage of region data that is used by default with SQLite now handles wildcards in region names in the same way as SQL queries do with other databases. --- OpenSim/Data/Null/NullRegionData.cs | 50 ++++++++++++++++++++++------- 1 file changed, 39 insertions(+), 11 deletions(-) diff --git a/OpenSim/Data/Null/NullRegionData.cs b/OpenSim/Data/Null/NullRegionData.cs index 2065355890..53e5207a6e 100644 --- a/OpenSim/Data/Null/NullRegionData.cs +++ b/OpenSim/Data/Null/NullRegionData.cs @@ -51,27 +51,55 @@ namespace OpenSim.Data.Null //Console.WriteLine("[XXX] NullRegionData constructor"); } + private delegate bool Matcher(string value); + public List Get(string regionName, UUID scopeID) { if (Instance != this) return Instance.Get(regionName, scopeID); + string cleanName = regionName.ToLower(); + + // Handle SQL wildcards + const string wildcard = "%"; + bool wildcardPrefix = false; + bool wildcardSuffix = false; + if (cleanName.Equals(wildcard)) + { + wildcardPrefix = wildcardSuffix = true; + cleanName = string.Empty; + } + else + { + if (cleanName.StartsWith(wildcard)) + { + wildcardPrefix = true; + cleanName = cleanName.Substring(1); + } + if (regionName.EndsWith(wildcard)) + { + wildcardSuffix = true; + cleanName = cleanName.Remove(cleanName.Length - 1); + } + } + Matcher queryMatch; + if (wildcardPrefix && wildcardSuffix) + queryMatch = delegate(string s) { return s.Contains(cleanName); }; + else if (wildcardSuffix) + queryMatch = delegate(string s) { return s.StartsWith(cleanName); }; + else if (wildcardPrefix) + queryMatch = delegate(string s) { return s.EndsWith(cleanName); }; + else + queryMatch = delegate(string s) { return s.Equals(cleanName); }; + + // Find region data List ret = new List(); foreach (RegionData r in m_regionData.Values) { - if (regionName.Contains("%")) - { - string cleanname = regionName.Replace("%", ""); - m_log.DebugFormat("[NULL REGION DATA]: comparing {0} to {1}", cleanname.ToLower(), r.RegionName.ToLower()); - if (r.RegionName.ToLower().Contains(cleanname.ToLower())) + m_log.DebugFormat("[NULL REGION DATA]: comparing {0} to {1}", cleanName, r.RegionName.ToLower()); + if (queryMatch(r.RegionName.ToLower())) ret.Add(r); - } - else - { - if (r.RegionName.ToLower() == regionName.ToLower()) - ret.Add(r); - } } if (ret.Count > 0) From 5a16fa882c0f1a6200bc3fdb63b0f4564acf0e6d Mon Sep 17 00:00:00 2001 From: Mic Bowman Date: Tue, 22 Feb 2011 13:23:54 -0800 Subject: [PATCH 25/81] Parameterizes the view distance used to compute and manage child agents in neighbor regions. This means you can extend the view on a simulator beyond the default 3x3 regions. This uses a region default draw distance and should be replaced at some point by the avatar specified draw distance. That will require more careful, dynamic recomputation of child agents every time the draw distance changes. WARNING: this is experimental and has known instabilities. specifically all regions "within site" should be running the same default draw distance or agents will not be closed correctly. --- OpenSim/Framework/Util.cs | 13 +++++-- .../EntityTransfer/EntityTransferModule.cs | 37 +++++++++++++------ .../EntityTransfer/HGEntityTransferModule.cs | 4 +- OpenSim/Region/Framework/Scenes/Scene.cs | 9 +++++ .../Region/Framework/Scenes/ScenePresence.cs | 24 +++++++++--- bin/OpenSimDefaults.ini | 7 ++++ 6 files changed, 73 insertions(+), 21 deletions(-) diff --git a/OpenSim/Framework/Util.cs b/OpenSim/Framework/Util.cs index 533e53abd5..5a5046e547 100644 --- a/OpenSim/Framework/Util.cs +++ b/OpenSim/Framework/Util.cs @@ -459,10 +459,17 @@ namespace OpenSim.Framework /// Old region y-coord /// New region y-coord /// - public static bool IsOutsideView(uint oldx, uint newx, uint oldy, uint newy) + public static bool IsOutsideView(float drawdist, uint oldx, uint newx, uint oldy, uint newy) { - // Eventually this will be a function of the draw distance / camera position too. - return (((int)Math.Abs((int)(oldx - newx)) > 1) || ((int)Math.Abs((int)(oldy - newy)) > 1)); + int dd = (int)((drawdist + Constants.RegionSize - 1) / Constants.RegionSize); + + int startX = (int)oldx - dd; + int startY = (int)oldy - dd; + + int endX = (int)oldx + dd; + int endY = (int)oldy + dd; + + return (newx < startX || endX < newx || newy < startY || endY < newy); } public static string FieldToString(byte[] bytes) diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs index 98aa563a4f..95c771e60f 100644 --- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs +++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs @@ -318,7 +318,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer agentCircuit.Id0 = currentAgentCircuit.Id0; } - if (NeedsNewAgent(oldRegionX, newRegionX, oldRegionY, newRegionY)) + if (NeedsNewAgent(sp.DrawDistance, oldRegionX, newRegionX, oldRegionY, newRegionY)) { // brand new agent, let's create a new caps seed agentCircuit.CapsPath = CapsUtil.GetRandomCapsObjectPath(); @@ -336,7 +336,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer // OK, it got this agent. Let's close some child agents sp.CloseChildAgents(newRegionX, newRegionY); IClientIPEndpoint ipepClient; - if (NeedsNewAgent(oldRegionX, newRegionX, oldRegionY, newRegionY)) + if (NeedsNewAgent(sp.DrawDistance, oldRegionX, newRegionX, oldRegionY, newRegionY)) { //sp.ControllingClient.SendTeleportProgress(teleportFlags, "Creating agent..."); #region IP Translation for NAT @@ -447,7 +447,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer // Finally, let's close this previously-known-as-root agent, when the jump is outside the view zone - if (NeedsClosing(oldRegionX, newRegionX, oldRegionY, newRegionY, reg)) + if (NeedsClosing(sp.DrawDistance, oldRegionX, newRegionX, oldRegionY, newRegionY, reg)) { Thread.Sleep(5000); sp.Close(); @@ -521,14 +521,14 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer return region; } - protected virtual bool NeedsNewAgent(uint oldRegionX, uint newRegionX, uint oldRegionY, uint newRegionY) + protected virtual bool NeedsNewAgent(float drawdist, uint oldRegionX, uint newRegionX, uint oldRegionY, uint newRegionY) { - return Util.IsOutsideView(oldRegionX, newRegionX, oldRegionY, newRegionY); + return Util.IsOutsideView(drawdist, oldRegionX, newRegionX, oldRegionY, newRegionY); } - protected virtual bool NeedsClosing(uint oldRegionX, uint newRegionX, uint oldRegionY, uint newRegionY, GridRegion reg) + protected virtual bool NeedsClosing(float drawdist, uint oldRegionX, uint newRegionX, uint oldRegionY, uint newRegionY, GridRegion reg) { - return Util.IsOutsideView(oldRegionX, newRegionX, oldRegionY, newRegionY); + return Util.IsOutsideView(drawdist, oldRegionX, newRegionX, oldRegionY, newRegionY); } protected virtual bool IsOutsideRegion(Scene s, Vector3 pos) @@ -1045,7 +1045,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer if (m_regionInfo != null) { - neighbours = RequestNeighbours(sp.Scene, m_regionInfo.RegionLocX, m_regionInfo.RegionLocY); + neighbours = RequestNeighbours(sp, m_regionInfo.RegionLocX, m_regionInfo.RegionLocY); } else { @@ -1272,8 +1272,9 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer /// /// /// - protected List RequestNeighbours(Scene pScene, uint pRegionLocX, uint pRegionLocY) + protected List RequestNeighbours(ScenePresence avatar, uint pRegionLocX, uint pRegionLocY) { + Scene pScene = avatar.Scene; RegionInfo m_regionInfo = pScene.RegionInfo; Border[] northBorders = pScene.NorthBorders.ToArray(); @@ -1281,10 +1282,24 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer Border[] eastBorders = pScene.EastBorders.ToArray(); Border[] westBorders = pScene.WestBorders.ToArray(); - // Legacy one region. Provided for simplicity while testing the all inclusive method in the else statement. + // Leaving this as a "megaregions" computation vs "non-megaregions" computation; it isn't + // clear what should be done with a "far view" given that megaregions already extended the + // view to include everything in the megaregion if (northBorders.Length <= 1 && southBorders.Length <= 1 && eastBorders.Length <= 1 && westBorders.Length <= 1) { - return pScene.GridService.GetNeighbours(m_regionInfo.ScopeID, m_regionInfo.RegionID); + int dd = avatar.DrawDistance < Constants.RegionSize ? (int)Constants.RegionSize : (int)avatar.DrawDistance; + + int startX = (int)pRegionLocX * (int)Constants.RegionSize - dd + (int)(Constants.RegionSize/2); + int startY = (int)pRegionLocY * (int)Constants.RegionSize - dd + (int)(Constants.RegionSize/2); + + int endX = (int)pRegionLocX * (int)Constants.RegionSize + dd + (int)(Constants.RegionSize/2); + int endY = (int)pRegionLocY * (int)Constants.RegionSize + dd + (int)(Constants.RegionSize/2); + + List neighbours = + avatar.Scene.GridService.GetRegionRange(m_regionInfo.ScopeID, startX, endX, startY, endY); + + neighbours.RemoveAll(delegate(GridRegion r) { return r.RegionID == m_regionInfo.RegionID; }); + return neighbours; } else { diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs index 35dcd95aa0..79e76b4cbf 100644 --- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs +++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs @@ -130,9 +130,9 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer return region; } - protected override bool NeedsClosing(uint oldRegionX, uint newRegionX, uint oldRegionY, uint newRegionY, GridRegion reg) + protected override bool NeedsClosing(float drawdist, uint oldRegionX, uint newRegionX, uint oldRegionY, uint newRegionY, GridRegion reg) { - if (base.NeedsClosing(oldRegionX, newRegionX, oldRegionY, newRegionY, reg)) + if (base.NeedsClosing(drawdist, oldRegionX, newRegionX, oldRegionY, newRegionY, reg)) return true; int flags = m_aScene.GridService.GetRegionFlags(m_aScene.RegionInfo.ScopeID, reg.RegionID); diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index ee1e0beee4..7def7e9ca3 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -83,6 +83,13 @@ namespace OpenSim.Region.Framework.Scenes public bool m_useFlySlow; public bool m_usePreJump; public bool m_seeIntoRegionFromNeighbor; + + protected float m_defaultDrawDistance = 255.0f; + public float DefaultDrawDistance + { + get { return m_defaultDrawDistance; } + } + // TODO: need to figure out how allow client agents but deny // root agents when ACL denies access to root agent public bool m_strictAccessControl = true; @@ -627,6 +634,8 @@ namespace OpenSim.Region.Framework.Scenes // IConfig startupConfig = m_config.Configs["Startup"]; + m_defaultDrawDistance = startupConfig.GetFloat("DefaultDrawDistance",m_defaultDrawDistance); + //Animation states m_useFlySlow = startupConfig.GetBoolean("enableflyslow", false); // TODO: Change default to true once the feature is supported diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs index 51b8dcc004..9e9481e815 100644 --- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs +++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs @@ -626,7 +626,7 @@ namespace OpenSim.Region.Framework.Scenes Utils.LongToUInts(handle, out x, out y); x = x / Constants.RegionSize; y = y / Constants.RegionSize; - if (Util.IsOutsideView(x, Scene.RegionInfo.RegionLocX, y, Scene.RegionInfo.RegionLocY)) + if (Util.IsOutsideView(DrawDistance, x, Scene.RegionInfo.RegionLocX, y, Scene.RegionInfo.RegionLocY)) { old.Add(handle); } @@ -700,6 +700,7 @@ namespace OpenSim.Region.Framework.Scenes private ScenePresence(IClientAPI client, Scene world, RegionInfo reginfo) : this() { + m_DrawDistance = world.DefaultDrawDistance; m_rootRegionHandle = reginfo.RegionHandle; m_controllingClient = client; m_firstname = m_controllingClient.FirstName; @@ -1279,7 +1280,11 @@ namespace OpenSim.Region.Framework.Scenes m_CameraUpAxis = agentData.CameraUpAxis; // The Agent's Draw distance setting - m_DrawDistance = agentData.Far; + // When we get to the point of re-computing neighbors everytime this + // changes, then start using the agent's drawdistance rather than the + // region's draw distance. + // m_DrawDistance = agentData.Far; + m_DrawDistance = Scene.DefaultDrawDistance; // Check if Client has camera in 'follow cam' or 'build' mode. Vector3 camdif = (Vector3.One * m_bodyRot - Vector3.One * CameraRotation); @@ -2913,7 +2918,7 @@ namespace OpenSim.Region.Framework.Scenes //m_log.Debug("---> x: " + x + "; newx:" + newRegionX + "; Abs:" + (int)Math.Abs((int)(x - newRegionX))); //m_log.Debug("---> y: " + y + "; newy:" + newRegionY + "; Abs:" + (int)Math.Abs((int)(y - newRegionY))); - if (Util.IsOutsideView(x, newRegionX, y, newRegionY)) + if (Util.IsOutsideView(DrawDistance, x, newRegionX, y, newRegionY)) { byebyeRegions.Add(handle); } @@ -2989,7 +2994,12 @@ namespace OpenSim.Region.Framework.Scenes Vector3 offset = new Vector3(shiftx, shifty, 0f); - m_DrawDistance = cAgentData.Far; + // When we get to the point of re-computing neighbors everytime this + // changes, then start using the agent's drawdistance rather than the + // region's draw distance. + // m_DrawDistance = cAgentData.Far; + m_DrawDistance = Scene.DefaultDrawDistance; + if (cAgentData.Position != new Vector3(-1f, -1f, -1f)) // UGH!! m_pos = cAgentData.Position + offset; @@ -3139,7 +3149,11 @@ namespace OpenSim.Region.Framework.Scenes m_CameraLeftAxis = cAgent.LeftAxis; m_CameraUpAxis = cAgent.UpAxis; - m_DrawDistance = cAgent.Far; + // When we get to the point of re-computing neighbors everytime this + // changes, then start using the agent's drawdistance rather than the + // region's draw distance. + // m_DrawDistance = cAgent.Far; + m_DrawDistance = Scene.DefaultDrawDistance; if ((cAgent.Throttles != null) && cAgent.Throttles.Length > 0) ControllingClient.SetChildAgentThrottle(cAgent.Throttles); diff --git a/bin/OpenSimDefaults.ini b/bin/OpenSimDefaults.ini index 475d4a0c53..96ffb7ea6b 100644 --- a/bin/OpenSimDefaults.ini +++ b/bin/OpenSimDefaults.ini @@ -94,6 +94,13 @@ ; Warning! Don't use this with regions that have existing content!, This will likely break them CombineContiguousRegions = false + ; Extend the region's draw distance; 255m is the default which includes + ; one neighbor on each side of the current region, 767m would go three + ; neighbors on each side for a total of 49 regions in view. Warning, unless + ; all the regions have the same drawdistance, you will end up with strange + ; effects because the agents that get closed may be inconsistent. + ; DefaultDrawDistance = 255.0 + ; If you have only one region in an instance, or to avoid the many bugs ; that you can trigger in modules by restarting a region, set this to ; true to make the entire instance exit instead of restarting the region. From 1bb0bae78aa6654730e1095ba07086679de529de Mon Sep 17 00:00:00 2001 From: Mic Bowman Date: Tue, 22 Feb 2011 13:30:38 -0800 Subject: [PATCH 26/81] Forces the owner of a rezzed object to be the "rezzer" of the object rather than the owner of the inventory item. In theory, this shouldn't happen unless you are using grid-wide library for inventory. --- .../Framework/InventoryAccess/InventoryAccessModule.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs b/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs index 7bb8789f16..bd316c6200 100644 --- a/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs +++ b/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs @@ -524,6 +524,8 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess if (item != null) { + item.Owner = remoteClient.AgentId; + AssetBase rezAsset = m_Scene.AssetService.Get(item.AssetID.ToString()); if (rezAsset != null) From db7c758b7f4d2d1f7f7fa7708256ef18bd69c294 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Thu, 24 Feb 2011 00:55:50 +0000 Subject: [PATCH 27/81] On a Grid Handler exception, explicitly log the exception message and stack trace so that we get somewhat better diagnostics on windows --- OpenSim/Server/Handlers/Grid/GridServerPostHandler.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/OpenSim/Server/Handlers/Grid/GridServerPostHandler.cs b/OpenSim/Server/Handlers/Grid/GridServerPostHandler.cs index 913c6c9b3a..edc05612db 100644 --- a/OpenSim/Server/Handlers/Grid/GridServerPostHandler.cs +++ b/OpenSim/Server/Handlers/Grid/GridServerPostHandler.cs @@ -115,15 +115,15 @@ namespace OpenSim.Server.Handlers.Grid case "get_region_flags": return GetRegionFlags(request); } + m_log.DebugFormat("[GRID HANDLER]: unknown method {0} request {1}", method.Length, method); } catch (Exception e) { - m_log.DebugFormat("[GRID HANDLER]: Exception {0}", e); + m_log.ErrorFormat("[GRID HANDLER]: Exception {0} {1}", e.Message, e.StackTrace); } return FailureResult(); - } #region Method-specific handlers From 2f5394e70ddefb5e7ec6a04022eef42a8ac89b0d Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Thu, 24 Feb 2011 22:33:54 +0000 Subject: [PATCH 28/81] Fix bug where avatars in other regions would not always show up on the mini-map --- OpenSim/Region/Framework/Scenes/SceneGraph.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/OpenSim/Region/Framework/Scenes/SceneGraph.cs b/OpenSim/Region/Framework/Scenes/SceneGraph.cs index 969ff13ac7..734ba22e9c 100644 --- a/OpenSim/Region/Framework/Scenes/SceneGraph.cs +++ b/OpenSim/Region/Framework/Scenes/SceneGraph.cs @@ -204,9 +204,10 @@ namespace OpenSim.Region.Framework.Scenes for (int i = 0; i < Math.Min(presences.Count, maxLocations); ++i) { ScenePresence sp = presences[i]; + // If this presence is a child agent, we don't want its coarse locations if (sp.IsChildAgent) - return; + continue; if (sp.ParentID != 0) { From 197cc3883fe5c532588f6b721d5f9d1295c24abc Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Fri, 25 Feb 2011 01:16:47 +0000 Subject: [PATCH 29/81] Fix bug where having no maximum memory cache timeout would cause the flotsam asset cache to try using Double.MaxValue, which would cause the underlying OpenMetaverse.ExpiringCache to choke. There is probably an underlying bug to fix in ExpiringCache. --- OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs b/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs index 6ed48674b2..edb6710829 100644 --- a/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs +++ b/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs @@ -252,7 +252,7 @@ namespace Flotsam.RegionModules.AssetCache } else { - m_MemoryCache.AddOrUpdate(key, asset, Double.MaxValue); + m_MemoryCache.AddOrUpdate(key, asset, m_DefaultMemoryExpiration); } } } From beff0ac32f0575e7805fd0691ba3907b3d13b70c Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Fri, 25 Feb 2011 01:18:43 +0000 Subject: [PATCH 30/81] log actual cache directory for FlotsamAssetCache instead of always logging the default --- OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs b/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs index edb6710829..90fb9b3175 100644 --- a/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs +++ b/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs @@ -147,7 +147,7 @@ namespace Flotsam.RegionModules.AssetCache } m_CacheDirectory = assetConfig.GetString("CacheDirectory", m_DefaultCacheDirectory); - m_log.InfoFormat("[FLOTSAM ASSET CACHE]: Cache Directory", m_DefaultCacheDirectory); + m_log.InfoFormat("[FLOTSAM ASSET CACHE]: Cache Directory", m_CacheDirectory); m_MemoryCacheEnabled = assetConfig.GetBoolean("MemoryCacheEnabled", false); m_MemoryExpiration = TimeSpan.FromHours(assetConfig.GetDouble("MemoryCacheTimeout", m_DefaultMemoryExpiration)); From 939c47ac521dee943083d87abe70a7271ee78077 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Fri, 25 Feb 2011 01:25:38 +0000 Subject: [PATCH 31/81] instead of using different default memory expiration depending on whether there is a [FLOTSAM ASSET CACHE] section present at all, use the same default all the time this simplifies the code --- .../Region/CoreModules/Asset/FlotsamAssetCache.cs | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs b/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs index 90fb9b3175..02a4e4d979 100644 --- a/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs +++ b/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs @@ -92,7 +92,7 @@ namespace Flotsam.RegionModules.AssetCache // Expiration is expressed in hours. private const double m_DefaultMemoryExpiration = 1.0; private const double m_DefaultFileExpiration = 48; - private TimeSpan m_MemoryExpiration = TimeSpan.Zero; + private TimeSpan m_MemoryExpiration = TimeSpan.FromHours(m_DefaultMemoryExpiration); private TimeSpan m_FileExpiration = TimeSpan.Zero; private TimeSpan m_FileExpirationCleanupTimer = TimeSpan.Zero; @@ -245,16 +245,7 @@ namespace Flotsam.RegionModules.AssetCache private void UpdateMemoryCache(string key, AssetBase asset) { if (m_MemoryCacheEnabled) - { - if (m_MemoryExpiration > TimeSpan.Zero) - { - m_MemoryCache.AddOrUpdate(key, asset, m_MemoryExpiration); - } - else - { - m_MemoryCache.AddOrUpdate(key, asset, m_DefaultMemoryExpiration); - } - } + m_MemoryCache.AddOrUpdate(key, asset, m_MemoryExpiration); } public void Cache(AssetBase asset) From 0f545abfc17392c4a2113b07a945bd4cc7b8366f Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Fri, 25 Feb 2011 01:31:38 +0000 Subject: [PATCH 32/81] Make the file expiration defaults the same whether the whole [FLOTSAM ASSET CACHE] section is missing or just the particular config values --- OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs b/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs index 02a4e4d979..9adb68bc0d 100644 --- a/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs +++ b/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs @@ -93,8 +93,8 @@ namespace Flotsam.RegionModules.AssetCache private const double m_DefaultMemoryExpiration = 1.0; private const double m_DefaultFileExpiration = 48; private TimeSpan m_MemoryExpiration = TimeSpan.FromHours(m_DefaultMemoryExpiration); - private TimeSpan m_FileExpiration = TimeSpan.Zero; - private TimeSpan m_FileExpirationCleanupTimer = TimeSpan.Zero; + private TimeSpan m_FileExpiration = TimeSpan.FromHours(m_DefaultFileExpiration); + private TimeSpan m_FileExpirationCleanupTimer = TimeSpan.FromHours(m_DefaultFileExpiration); private static int m_CacheDirectoryTiers = 1; private static int m_CacheDirectoryTierLen = 3; @@ -441,7 +441,7 @@ namespace Flotsam.RegionModules.AssetCache private void CleanupExpiredFiles(object source, ElapsedEventArgs e) { if (m_LogLevel >= 2) - m_log.DebugFormat("[FLOTSAM ASSET CACHE]: Checking for expired files older then {0}.", m_FileExpiration.ToString()); + m_log.DebugFormat("[FLOTSAM ASSET CACHE]: Checking for expired files older then {0}.", m_FileExpiration); // Purge all files last accessed prior to this point DateTime purgeLine = DateTime.Now - m_FileExpiration; From 2b04cab1ee4b7c89bdfbe93622f421f031879943 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Fri, 25 Feb 2011 02:15:06 +0000 Subject: [PATCH 33/81] change some log messages from info to debug --- .../CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs | 2 +- OpenSim/Region/Framework/Scenes/Scene.cs | 2 +- OpenSim/Region/Framework/Scenes/ScenePresence.cs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs b/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs index f8ce444b50..08ac62418e 100644 --- a/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs @@ -167,7 +167,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory } } - m_log.InfoFormat("[AVFACTORY]: complete texture check for {0}", client.AgentId); + m_log.DebugFormat("[AVFACTORY]: complete texture check for {0}", client.AgentId); // If we only found default textures, then the appearance is not cached return (defonly ? false : true); diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index 7def7e9ca3..1a6a70bfbe 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -3210,7 +3210,7 @@ namespace OpenSim.Region.Framework.Scenes // TeleportFlags.ViaLandmark | TeleportFlags.ViaLocation | TeleportFlags.ViaLandmark | TeleportFlags.Default - Regular Teleport // Don't disable this log message - it's too helpful - m_log.InfoFormat( + m_log.DebugFormat( "[CONNECTION BEGIN]: Region {0} told of incoming {1} agent {2} {3} {4} (circuit code {5}, teleportflags {6})", RegionInfo.RegionName, (agent.child ? "child" : "root"), agent.firstname, agent.lastname, agent.AgentID, agent.circuitcode, teleportFlags); diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs index 9e9481e815..00a1487ab6 100644 --- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs +++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs @@ -2442,7 +2442,7 @@ namespace OpenSim.Region.Framework.Scenes // If we are using the the cached appearance then send it out to everyone if (cachedappearance) { - m_log.InfoFormat("[SCENEPRESENCE]: baked textures are in the cache for {0}", Name); + m_log.DebugFormat("[SCENEPRESENCE]: baked textures are in the cache for {0}", Name); // If the avatars baked textures are all in the cache, then we have a // complete appearance... send it out, if not, then we'll send it when From cea47491de6723230a49b1ac99cecc5c32758f40 Mon Sep 17 00:00:00 2001 From: Melanie Date: Sun, 27 Feb 2011 18:55:17 +0100 Subject: [PATCH 34/81] Fix a few little things --- .../Framework/InventoryAccess/InventoryAccessModule.cs | 3 +++ OpenSim/Region/Framework/Scenes/Scene.Inventory.cs | 2 ++ 2 files changed, 5 insertions(+) diff --git a/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs b/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs index bd316c6200..798547a82d 100644 --- a/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs +++ b/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs @@ -148,6 +148,9 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess InventoryItemBase item = new InventoryItemBase(itemID, remoteClient.AgentId); item = m_Scene.InventoryService.GetItem(item); + if (item.Owner != remoteClient.AgentId) + return UUID.Zero; + if (item != null) { if ((InventoryType)item.InvType == InventoryType.Notecard) diff --git a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs index e2d96d9a37..fcbcf593ba 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs @@ -321,6 +321,8 @@ namespace OpenSim.Region.Framework.Scenes // Passing something to another avatar or a an object will already InventoryItemBase item = new InventoryItemBase(itemID, remoteClient.AgentId); item = InventoryService.GetItem(item); + if (item.Owner != remoteClient.AgentId) + return; if (item != null) { From b82b0b16770af89b0bbe48ba63a0d9fec9839d6d Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Tue, 1 Mar 2011 09:20:50 -0800 Subject: [PATCH 35/81] Normalizing comparison to lower case, just in case ppl set their config vars inconsistently. (maybe related to mantis #5386) --- OpenSim/Services/HypergridService/UserAgentService.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OpenSim/Services/HypergridService/UserAgentService.cs b/OpenSim/Services/HypergridService/UserAgentService.cs index 3ead180a0b..445d45e250 100644 --- a/OpenSim/Services/HypergridService/UserAgentService.cs +++ b/OpenSim/Services/HypergridService/UserAgentService.cs @@ -253,7 +253,7 @@ namespace OpenSim.Services.HypergridService TravelingAgentInfo travel = m_TravelingAgents[sessionID]; - return travel.GridExternalName == thisGridExternalName; + return travel.GridExternalName.ToLower() == thisGridExternalName.ToLower(); } public bool VerifyClient(UUID sessionID, string reportedIP) From 3c89527b222c2ddc50553ce1c49f22e9f05db11b Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Sat, 5 Mar 2011 00:06:51 +0000 Subject: [PATCH 36/81] Fix bug where llSetPrimMediaParams() reported success but never set the media texture. We weren't setting the TextureEntryFace.MediaFlags = true when a media texture was set directly via a script. This was being done when the viewer was setting them directly. --- .../CoreModules/World/Media/Moap/MoapModule.cs | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/OpenSim/Region/CoreModules/World/Media/Moap/MoapModule.cs b/OpenSim/Region/CoreModules/World/Media/Moap/MoapModule.cs index 7c5d044347..9132753460 100644 --- a/OpenSim/Region/CoreModules/World/Media/Moap/MoapModule.cs +++ b/OpenSim/Region/CoreModules/World/Media/Moap/MoapModule.cs @@ -227,15 +227,24 @@ namespace OpenSim.Region.CoreModules.Media.Moap public void SetMediaEntry(SceneObjectPart part, int face, MediaEntry me) { +// m_log.DebugFormat("[MOAP]: SetMediaEntry for {0}, face {1}", part.Name, face); + CheckFaceParam(part, face); if (null == part.Shape.Media) part.Shape.Media = new PrimitiveBaseShape.MediaList(new MediaEntry[part.GetNumberOfSides()]); - + lock (part.Shape.Media) - part.Shape.Media[face] = me; + part.Shape.Media[face] = me; UpdateMediaUrl(part, UUID.Zero); + + // Temporary code to fix llSetPrimMediaParams() bug, pending refactoring + Primitive.TextureEntry te = part.Shape.Textures; + Primitive.TextureEntryFace teFace = te.CreateFace((uint)face); + teFace.MediaFlags = true; + part.Shape.Textures = te; + part.ScheduleFullUpdate(); part.TriggerScriptChangedEvent(Changed.MEDIA); } @@ -333,7 +342,7 @@ namespace OpenSim.Region.CoreModules.Media.Moap } // m_log.DebugFormat("[MOAP]: Received {0} media entries for prim {1}", omu.FaceMedia.Length, primId); - +// // for (int i = 0; i < omu.FaceMedia.Length; i++) // { // MediaEntry me = omu.FaceMedia[i]; @@ -380,6 +389,8 @@ namespace OpenSim.Region.CoreModules.Media.Moap } else { +// m_log.DebugFormat("[MOAP]: Setting existing media list for {0}", part.Name); + // We need to go through the media textures one at a time to make sure that we have permission // to change them From 481ca910da47e68546623573ac9bba669d7b44c1 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Sat, 5 Mar 2011 01:07:05 +0000 Subject: [PATCH 37/81] add test for MoapModule.SetMediaUrl() --- .../World/Media/Moap/Tests/MoapTests.cs | 72 +++++++++++++++++++ prebuild.xml | 1 + 2 files changed, 73 insertions(+) create mode 100644 OpenSim/Region/CoreModules/World/Media/Moap/Tests/MoapTests.cs diff --git a/OpenSim/Region/CoreModules/World/Media/Moap/Tests/MoapTests.cs b/OpenSim/Region/CoreModules/World/Media/Moap/Tests/MoapTests.cs new file mode 100644 index 0000000000..d4c9245ec4 --- /dev/null +++ b/OpenSim/Region/CoreModules/World/Media/Moap/Tests/MoapTests.cs @@ -0,0 +1,72 @@ +/* + * 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 NUnit.Framework.SyntaxHelpers; +using OpenMetaverse; +using OpenMetaverse.Assets; +using OpenSim.Framework; +using OpenSim.Region.CoreModules.Media.Moap; +using OpenSim.Region.Framework.Scenes; +using OpenSim.Region.Framework.Scenes.Serialization; +using OpenSim.Tests.Common; +using OpenSim.Tests.Common.Mock; +using OpenSim.Tests.Common.Setup; + +namespace OpenSim.Region.CoreModules.World.Media.Moap.Tests +{ + [TestFixture] + public class MoapTests + { + [Test] + public void TestSetMediaUrl() + { + TestHelper.InMethod(); + + string homeUrl = "opensimulator.org"; + + MoapModule module = new MoapModule(); + TestScene scene = SceneSetupHelpers.SetupScene(); + SceneSetupHelpers.SetupSceneModules(scene, module); + + SceneObjectPart part = SceneSetupHelpers.AddSceneObject(scene); + MediaEntry me = new MediaEntry() { HomeURL = homeUrl }; + + module.SetMediaEntry(part, 1, me); + + Assert.That(part.Shape.Media[1].HomeURL, Is.EqualTo(homeUrl)); + Assert.That(part.MediaUrl, Is.EqualTo("x-mv:0000000000/" + UUID.Zero)); + Assert.That(part.Shape.Textures.FaceTextures[1].MediaFlags, Is.True); + } + } +} \ No newline at end of file diff --git a/prebuild.xml b/prebuild.xml index cbe539ea17..b31812dc17 100644 --- a/prebuild.xml +++ b/prebuild.xml @@ -2927,6 +2927,7 @@ + From 72cb498fd0c167867d71c26e55afedc2e23ab9b4 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Sat, 5 Mar 2011 01:13:59 +0000 Subject: [PATCH 38/81] minor: Make MoapModule namespace consistent with other modules --- OpenSim/Region/CoreModules/World/Media/Moap/MoapModule.cs | 2 +- OpenSim/Region/CoreModules/World/Media/Moap/Tests/MoapTests.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/OpenSim/Region/CoreModules/World/Media/Moap/MoapModule.cs b/OpenSim/Region/CoreModules/World/Media/Moap/MoapModule.cs index 9132753460..b6ec6dc9f2 100644 --- a/OpenSim/Region/CoreModules/World/Media/Moap/MoapModule.cs +++ b/OpenSim/Region/CoreModules/World/Media/Moap/MoapModule.cs @@ -50,7 +50,7 @@ using Caps = OpenSim.Framework.Capabilities.Caps; using OSDArray = OpenMetaverse.StructuredData.OSDArray; using OSDMap = OpenMetaverse.StructuredData.OSDMap; -namespace OpenSim.Region.CoreModules.Media.Moap +namespace OpenSim.Region.CoreModules.World.Media.Moap { [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "MoapModule")] public class MoapModule : INonSharedRegionModule, IMoapModule diff --git a/OpenSim/Region/CoreModules/World/Media/Moap/Tests/MoapTests.cs b/OpenSim/Region/CoreModules/World/Media/Moap/Tests/MoapTests.cs index d4c9245ec4..9e5c7ae5d2 100644 --- a/OpenSim/Region/CoreModules/World/Media/Moap/Tests/MoapTests.cs +++ b/OpenSim/Region/CoreModules/World/Media/Moap/Tests/MoapTests.cs @@ -36,7 +36,7 @@ using NUnit.Framework.SyntaxHelpers; using OpenMetaverse; using OpenMetaverse.Assets; using OpenSim.Framework; -using OpenSim.Region.CoreModules.Media.Moap; +using OpenSim.Region.CoreModules.World.Media.Moap; using OpenSim.Region.Framework.Scenes; using OpenSim.Region.Framework.Scenes.Serialization; using OpenSim.Tests.Common; From 8efb01b3df1ea98d5e4a68aa220bafc4ab5306f4 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Sat, 5 Mar 2011 01:15:27 +0000 Subject: [PATCH 39/81] minor: remove some mono compiler warnings --- .../Agent/UDP/Linden/LindenUDPInfoModule.cs | 2 +- .../Voice/FreeSwitchVoice/FreeSwitchVoiceModule.cs | 12 ++++++------ .../SimianGroupsServicesConnectorModule.cs | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/OpenSim/Region/OptionalModules/Agent/UDP/Linden/LindenUDPInfoModule.cs b/OpenSim/Region/OptionalModules/Agent/UDP/Linden/LindenUDPInfoModule.cs index dfeecb1bbc..6a24cc1092 100644 --- a/OpenSim/Region/OptionalModules/Agent/UDP/Linden/LindenUDPInfoModule.cs +++ b/OpenSim/Region/OptionalModules/Agent/UDP/Linden/LindenUDPInfoModule.cs @@ -51,7 +51,7 @@ namespace OpenSim.Region.CoreModules.UDP.Linden [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "LindenUDPInfoModule")] public class LindenUDPInfoModule : ISharedRegionModule { - private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); +// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); protected Dictionary m_scenes = new Dictionary(); diff --git a/OpenSim/Region/OptionalModules/Avatar/Voice/FreeSwitchVoice/FreeSwitchVoiceModule.cs b/OpenSim/Region/OptionalModules/Avatar/Voice/FreeSwitchVoice/FreeSwitchVoiceModule.cs index e9c545308c..05a1c3b427 100644 --- a/OpenSim/Region/OptionalModules/Avatar/Voice/FreeSwitchVoice/FreeSwitchVoiceModule.cs +++ b/OpenSim/Region/OptionalModules/Avatar/Voice/FreeSwitchVoice/FreeSwitchVoiceModule.cs @@ -92,7 +92,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.FreeSwitchVoice private static string m_freeSwitchUrlResetPassword; private uint m_freeSwitchServicePort; private string m_openSimWellKnownHTTPAddress; - private string m_freeSwitchContext; +// private string m_freeSwitchContext; private readonly Dictionary m_UUIDName = new Dictionary(); private Dictionary m_ParcelAddress = new Dictionary(); @@ -144,7 +144,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.FreeSwitchVoice m_freeSwitchDefaultWellKnownIP = map["DefaultWellKnownIP"].AsString(); m_freeSwitchDefaultTimeout = map["DefaultTimeout"].AsInteger(); m_freeSwitchUrlResetPassword = String.Empty; - m_freeSwitchContext = map["Context"].AsString(); +// m_freeSwitchContext = map["Context"].AsString(); if (String.IsNullOrEmpty(m_freeSwitchRealm) || String.IsNullOrEmpty(m_freeSwitchAPIPrefix)) @@ -662,7 +662,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.FreeSwitchVoice resp.Append(""); response["str_response_string"] = resp.ToString(); - Regex normalizeEndLines = new Regex(@"\r\n", RegexOptions.Compiled | RegexOptions.Singleline | RegexOptions.Multiline); +// Regex normalizeEndLines = new Regex(@"\r\n", RegexOptions.Compiled | RegexOptions.Singleline | RegexOptions.Multiline); //m_log.DebugFormat("[FREESWITCH]: {0}", normalizeEndLines.Replace((string)response["str_response_string"],"")); return response; @@ -671,9 +671,9 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.FreeSwitchVoice public Hashtable FreeSwitchSLVoiceSigninHTTPHandler(Hashtable request) { m_log.Debug("[FreeSwitchVoice] FreeSwitchSLVoiceSigninHTTPHandler called"); - string requestbody = (string)request["body"]; - string uri = (string)request["uri"]; - string contenttype = (string)request["content-type"]; +// string requestbody = (string)request["body"]; +// string uri = (string)request["uri"]; +// string contenttype = (string)request["content-type"]; Hashtable requestBody = ParseRequestBody((string)request["body"]); diff --git a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/SimianGroupsServicesConnectorModule.cs b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/SimianGroupsServicesConnectorModule.cs index 81725c55c7..02751eafa7 100644 --- a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/SimianGroupsServicesConnectorModule.cs +++ b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/SimianGroupsServicesConnectorModule.cs @@ -712,7 +712,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); GroupMembershipData data = null; - bool foundData = false; +// bool foundData = false; OSDMap UserGroupMemberInfo; if (SimianGetGenericEntry(agentID, "GroupMember", groupID.ToString(), out UserGroupMemberInfo)) From 3c0d607f454492bbec622e4dc36696ca969dd247 Mon Sep 17 00:00:00 2001 From: Mic Bowman Date: Fri, 4 Mar 2011 17:17:53 -0800 Subject: [PATCH 40/81] Changed order of checks for local regions when processing AgentUpdate messages. Should improve throttles and reprioritization when an avatar is moving. --- .../Simulation/RemoteSimulationConnector.cs | 22 +++++-------------- 1 file changed, 6 insertions(+), 16 deletions(-) diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/RemoteSimulationConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/RemoteSimulationConnector.cs index 0c92bd1c57..67f4d6030c 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/RemoteSimulationConnector.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/RemoteSimulationConnector.cs @@ -192,15 +192,10 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation return false; // Try local first - if (m_localBackend.UpdateAgent(destination, cAgentData)) - return true; - - // else do the remote thing - if (!m_localBackend.IsLocalRegion(destination.RegionHandle)) - return m_remoteConnector.UpdateAgent(destination, cAgentData); - - return false; + if (m_localBackend.IsLocalRegion(destination.RegionHandle)) + return m_localBackend.UpdateAgent(destination, cAgentData); + return m_remoteConnector.UpdateAgent(destination, cAgentData); } public bool UpdateAgent(GridRegion destination, AgentPosition cAgentData) @@ -209,15 +204,10 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation return false; // Try local first - if (m_localBackend.UpdateAgent(destination, cAgentData)) - return true; - - // else do the remote thing - if (!m_localBackend.IsLocalRegion(destination.RegionHandle)) - return m_remoteConnector.UpdateAgent(destination, cAgentData); - - return false; + if (m_localBackend.IsLocalRegion(destination.RegionHandle)) + return m_localBackend.UpdateAgent(destination, cAgentData); + return m_remoteConnector.UpdateAgent(destination, cAgentData); } public bool RetrieveAgent(GridRegion destination, UUID id, out IAgentData agent) From 9f85ee29ac9f5e0aa8c1976944f9af12da3514db Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Sat, 5 Mar 2011 02:18:03 +0000 Subject: [PATCH 41/81] Change MoapModule.ClearMediaEntry to set TextureEntryFace.MediaFlags back to false Implement test for ClearMediaEntry() --- OpenSim/Framework/PrimitiveBaseShape.cs | 2 +- .../World/Media/Moap/MoapModule.cs | 30 ++++++++++++- .../World/Media/Moap/Tests/MoapTests.cs | 45 ++++++++++++++++--- 3 files changed, 68 insertions(+), 9 deletions(-) diff --git a/OpenSim/Framework/PrimitiveBaseShape.cs b/OpenSim/Framework/PrimitiveBaseShape.cs index 927415e850..7b5fb2e8f1 100644 --- a/OpenSim/Framework/PrimitiveBaseShape.cs +++ b/OpenSim/Framework/PrimitiveBaseShape.cs @@ -250,7 +250,7 @@ namespace OpenSim.Framework { get { - //m_log.DebugFormat("[SHAPE]: get m_textureEntry length {0}", m_textureEntry.Length); +// m_log.DebugFormat("[SHAPE]: get m_textureEntry length {0}", m_textureEntry.Length); try { return new Primitive.TextureEntry(m_textureEntry, 0, m_textureEntry.Length); } catch { } diff --git a/OpenSim/Region/CoreModules/World/Media/Moap/MoapModule.cs b/OpenSim/Region/CoreModules/World/Media/Moap/MoapModule.cs index b6ec6dc9f2..ffb3221bc6 100644 --- a/OpenSim/Region/CoreModules/World/Media/Moap/MoapModule.cs +++ b/OpenSim/Region/CoreModules/World/Media/Moap/MoapModule.cs @@ -225,6 +225,12 @@ namespace OpenSim.Region.CoreModules.World.Media.Moap return me; } + /// + /// Set the media entry on the face of the given part. + /// + /// /param> + /// + /// public void SetMediaEntry(SceneObjectPart part, int face, MediaEntry me) { // m_log.DebugFormat("[MOAP]: SetMediaEntry for {0}, face {1}", part.Name, face); @@ -249,9 +255,31 @@ namespace OpenSim.Region.CoreModules.World.Media.Moap part.TriggerScriptChangedEvent(Changed.MEDIA); } + /// + /// Clear the media entry from the face of the given part. + /// + /// + /// public void ClearMediaEntry(SceneObjectPart part, int face) { - SetMediaEntry(part, face, null); + CheckFaceParam(part, face); + + // If no media has been set up yetthen we don't need to clear anything + if (null == part.Shape.Media) + return; + + lock (part.Shape.Media) + part.Shape.Media[face] = null; + + UpdateMediaUrl(part, UUID.Zero); + + Primitive.TextureEntry te = part.Shape.Textures; + Primitive.TextureEntryFace teFace = te.CreateFace((uint)face); + teFace.MediaFlags = false; + part.Shape.Textures = te; + + part.ScheduleFullUpdate(); + part.TriggerScriptChangedEvent(Changed.MEDIA); } /// diff --git a/OpenSim/Region/CoreModules/World/Media/Moap/Tests/MoapTests.cs b/OpenSim/Region/CoreModules/World/Media/Moap/Tests/MoapTests.cs index 9e5c7ae5d2..7a68e55c7e 100644 --- a/OpenSim/Region/CoreModules/World/Media/Moap/Tests/MoapTests.cs +++ b/OpenSim/Region/CoreModules/World/Media/Moap/Tests/MoapTests.cs @@ -48,21 +48,52 @@ namespace OpenSim.Region.CoreModules.World.Media.Moap.Tests [TestFixture] public class MoapTests { + protected TestScene m_scene; + protected MoapModule m_module; + + [SetUp] + public void SetUp() + { + m_module = new MoapModule(); + m_scene = SceneSetupHelpers.SetupScene(); + SceneSetupHelpers.SetupSceneModules(m_scene, m_module); + } + + [Test] + public void TestClearMediaUrl() + { + TestHelper.InMethod(); +// log4net.Config.XmlConfigurator.Configure(); + + SceneObjectPart part = SceneSetupHelpers.AddSceneObject(m_scene); + 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:0000000001/" + 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() { TestHelper.InMethod(); - string homeUrl = "opensimulator.org"; + string homeUrl = "opensimulator.org"; - MoapModule module = new MoapModule(); - TestScene scene = SceneSetupHelpers.SetupScene(); - SceneSetupHelpers.SetupSceneModules(scene, module); - - SceneObjectPart part = SceneSetupHelpers.AddSceneObject(scene); + SceneObjectPart part = SceneSetupHelpers.AddSceneObject(m_scene); MediaEntry me = new MediaEntry() { HomeURL = homeUrl }; - module.SetMediaEntry(part, 1, me); + m_module.SetMediaEntry(part, 1, me); Assert.That(part.Shape.Media[1].HomeURL, Is.EqualTo(homeUrl)); Assert.That(part.MediaUrl, Is.EqualTo("x-mv:0000000000/" + UUID.Zero)); From 9e579a7891d6eb4c3e5a0593d67837ed423135ee Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Sat, 5 Mar 2011 02:21:53 +0000 Subject: [PATCH 42/81] Fold ClearMediaEntry() back into SetMediaEntry() --- .../World/Media/Moap/MoapModule.cs | 30 ++++++------------- 1 file changed, 9 insertions(+), 21 deletions(-) diff --git a/OpenSim/Region/CoreModules/World/Media/Moap/MoapModule.cs b/OpenSim/Region/CoreModules/World/Media/Moap/MoapModule.cs index ffb3221bc6..b8943adbe8 100644 --- a/OpenSim/Region/CoreModules/World/Media/Moap/MoapModule.cs +++ b/OpenSim/Region/CoreModules/World/Media/Moap/MoapModule.cs @@ -230,7 +230,7 @@ namespace OpenSim.Region.CoreModules.World.Media.Moap /// /// /param> /// - /// + /// If null, then the media entry is cleared. public void SetMediaEntry(SceneObjectPart part, int face, MediaEntry me) { // m_log.DebugFormat("[MOAP]: SetMediaEntry for {0}, face {1}", part.Name, face); @@ -238,7 +238,12 @@ namespace OpenSim.Region.CoreModules.World.Media.Moap CheckFaceParam(part, face); if (null == part.Shape.Media) - part.Shape.Media = new PrimitiveBaseShape.MediaList(new MediaEntry[part.GetNumberOfSides()]); + { + if (me == null) + return; + else + part.Shape.Media = new PrimitiveBaseShape.MediaList(new MediaEntry[part.GetNumberOfSides()]); + } lock (part.Shape.Media) part.Shape.Media[face] = me; @@ -248,7 +253,7 @@ namespace OpenSim.Region.CoreModules.World.Media.Moap // Temporary code to fix llSetPrimMediaParams() bug, pending refactoring Primitive.TextureEntry te = part.Shape.Textures; Primitive.TextureEntryFace teFace = te.CreateFace((uint)face); - teFace.MediaFlags = true; + teFace.MediaFlags = me != null; part.Shape.Textures = te; part.ScheduleFullUpdate(); @@ -262,24 +267,7 @@ namespace OpenSim.Region.CoreModules.World.Media.Moap /// public void ClearMediaEntry(SceneObjectPart part, int face) { - CheckFaceParam(part, face); - - // If no media has been set up yetthen we don't need to clear anything - if (null == part.Shape.Media) - return; - - lock (part.Shape.Media) - part.Shape.Media[face] = null; - - UpdateMediaUrl(part, UUID.Zero); - - Primitive.TextureEntry te = part.Shape.Textures; - Primitive.TextureEntryFace teFace = te.CreateFace((uint)face); - teFace.MediaFlags = false; - part.Shape.Textures = te; - - part.ScheduleFullUpdate(); - part.TriggerScriptChangedEvent(Changed.MEDIA); + SetMediaEntry(part, face, null); } /// From 2e46027c14fb7a7084e3909cd8b57db5565cce7d Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Sat, 5 Mar 2011 02:34:44 +0000 Subject: [PATCH 43/81] Construct test load iar only once and reuse for each test, rather than recreating it every time --- .../Archiver/Tests/InventoryArchiverTests.cs | 26 +++++++++++++------ 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs index 76d0b85774..8a84c7a2d9 100644 --- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs +++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs @@ -53,9 +53,14 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests public class InventoryArchiverTests { protected ManualResetEvent mre = new ManualResetEvent(false); - + /// - /// Stream of data representing a common IAR that can be reused in load tests. + /// 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; @@ -79,12 +84,18 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests } [SetUp] - public void Init() + public void SetUp() { - ConstructDefaultIarForTestLoad(); + m_iarStream = new MemoryStream(m_iarStreamBytes); } - protected void ConstructDefaultIarForTestLoad() + [TestFixtureSetUp] + public void FixtureSetup() + { + ConstructDefaultIarBytesForTestLoad(); + } + + protected void ConstructDefaultIarBytesForTestLoad() { string archiveItemName = InventoryArchiveWriteRequest.CreateArchiveItemName(m_item1Name, UUID.Random()); @@ -107,7 +118,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests = string.Format("{0}{1}", ArchiveConstants.INVENTORY_PATH, archiveItemName); tar.WriteFile(item1FileName, UserInventoryItemSerializer.Serialize(item1, new Dictionary(), scene.UserAccountService)); tar.Close(); - m_iarStream = new MemoryStream(archiveWriteStream.ToArray()); + m_iarStreamBytes = archiveWriteStream.ToArray(); } /// @@ -392,8 +403,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests UserProfileTestUtils.CreateUserWithInventory(scene, m_ua1, "meowfood"); UserProfileTestUtils.CreateUserWithInventory(scene, m_ua2, "hampshire"); - archiverModule.DearchiveInventory(m_ua1.FirstName, m_ua1.LastName, "/", "meowfood", m_iarStream); - + archiverModule.DearchiveInventory(m_ua1.FirstName, m_ua1.LastName, "/", "meowfood", m_iarStream); InventoryItemBase foundItem1 = InventoryArchiveUtils.FindItemByPath(scene.InventoryService, m_ua1.PrincipalID, m_item1Name); From 9b345ebf73663a04d8baa69f0fb48ab80b8b1a58 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Sat, 5 Mar 2011 02:42:47 +0000 Subject: [PATCH 44/81] factor out SetPartMediaFlags() function in MoapModule. --- .../World/Media/Moap/MoapModule.cs | 31 ++++++++++++------- 1 file changed, 20 insertions(+), 11 deletions(-) diff --git a/OpenSim/Region/CoreModules/World/Media/Moap/MoapModule.cs b/OpenSim/Region/CoreModules/World/Media/Moap/MoapModule.cs index b8943adbe8..898ca4a4c3 100644 --- a/OpenSim/Region/CoreModules/World/Media/Moap/MoapModule.cs +++ b/OpenSim/Region/CoreModules/World/Media/Moap/MoapModule.cs @@ -250,11 +250,7 @@ namespace OpenSim.Region.CoreModules.World.Media.Moap UpdateMediaUrl(part, UUID.Zero); - // Temporary code to fix llSetPrimMediaParams() bug, pending refactoring - Primitive.TextureEntry te = part.Shape.Textures; - Primitive.TextureEntryFace teFace = te.CreateFace((uint)face); - teFace.MediaFlags = me != null; - part.Shape.Textures = te; + SetPartMediaFlags(part, face, me != null); part.ScheduleFullUpdate(); part.TriggerScriptChangedEvent(Changed.MEDIA); @@ -270,6 +266,23 @@ namespace OpenSim.Region.CoreModules.World.Media.Moap SetMediaEntry(part, face, null); } + /// + /// Set the media flags on the texture face of the given part. + /// + /// + /// The fact that we need a separate function to do what should be a simple one line operation is BUTT UGLY. + /// + /// + /// + /// + protected void SetPartMediaFlags(SceneObjectPart part, int face, bool flag) + { + Primitive.TextureEntry te = part.Shape.Textures; + Primitive.TextureEntryFace teFace = te.CreateFace((uint)face); + teFace.MediaFlags = flag; + part.Shape.Textures = te; + } + /// /// Sets or gets per face media textures. /// @@ -393,10 +406,7 @@ namespace OpenSim.Region.CoreModules.World.Media.Moap // FIXME: Race condition here since some other texture entry manipulator may overwrite/get // overwritten. Unfortunately, PrimitiveBaseShape does not allow us to change texture entry // directly. - Primitive.TextureEntry te = part.Shape.Textures; - Primitive.TextureEntryFace face = te.CreateFace((uint)i); - face.MediaFlags = true; - part.Shape.Textures = te; + SetPartMediaFlags(part, i, true); // m_log.DebugFormat( // "[MOAP]: Media flags for face {0} is {1}", // i, part.Shape.Textures.FaceTextures[i].MediaFlags); @@ -428,8 +438,7 @@ namespace OpenSim.Region.CoreModules.World.Media.Moap if (null == media[i]) continue; - Primitive.TextureEntryFace face = te.CreateFace((uint)i); - face.MediaFlags = true; + SetPartMediaFlags(part, i, true); // m_log.DebugFormat( // "[MOAP]: Media flags for face {0} is {1}", From 9923a2ff1002d722ccebea8bf4d71718ed4e2a03 Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Tue, 8 Mar 2011 09:02:29 -0800 Subject: [PATCH 45/81] Pull up Assembly of the MySQL classes as a protected property, so that it can be overwritten in subclasses. That way extensions can decide in which assembly migration resources should be looked up. This is just a refactor -- no functional changes whatsoever. --- OpenSim/Data/MySQL/MySQLAssetData.cs | 10 ++++++---- OpenSim/Data/MySQL/MySQLAuthenticationData.cs | 8 +++++++- OpenSim/Data/MySQL/MySQLEstateData.cs | 8 ++++++-- OpenSim/Data/MySQL/MySQLGenericTableHandler.cs | 7 ++++++- OpenSim/Data/MySQL/MySQLRegionData.cs | 9 ++++++++- OpenSim/Data/MySQL/MySQLSimulationData.cs | 8 ++++++-- 6 files changed, 39 insertions(+), 11 deletions(-) diff --git a/OpenSim/Data/MySQL/MySQLAssetData.cs b/OpenSim/Data/MySQL/MySQLAssetData.cs index ed92f3ebc2..e740232a31 100644 --- a/OpenSim/Data/MySQL/MySQLAssetData.cs +++ b/OpenSim/Data/MySQL/MySQLAssetData.cs @@ -47,6 +47,11 @@ namespace OpenSim.Data.MySQL private string m_connectionString; private object m_dbLock = new object(); + protected virtual Assembly Assembly + { + get { return GetType().Assembly; } + } + #region IPlugin Members public override string Version { get { return "1.0.0.0"; } } @@ -66,13 +71,10 @@ namespace OpenSim.Data.MySQL { m_connectionString = connect; - // This actually does the roll forward assembly stuff - Assembly assem = GetType().Assembly; - using (MySqlConnection dbcon = new MySqlConnection(m_connectionString)) { dbcon.Open(); - Migration m = new Migration(dbcon, assem, "AssetStore"); + Migration m = new Migration(dbcon, Assembly, "AssetStore"); m.Update(); } } diff --git a/OpenSim/Data/MySQL/MySQLAuthenticationData.cs b/OpenSim/Data/MySQL/MySQLAuthenticationData.cs index 5056aee6c1..8d82f61bda 100644 --- a/OpenSim/Data/MySQL/MySQLAuthenticationData.cs +++ b/OpenSim/Data/MySQL/MySQLAuthenticationData.cs @@ -28,6 +28,7 @@ using System; using System.Collections; using System.Collections.Generic; +using System.Reflection; using System.Data; using OpenMetaverse; using OpenSim.Framework; @@ -42,6 +43,11 @@ namespace OpenSim.Data.MySQL private int m_LastExpire; // private string m_connectionString; + protected virtual Assembly Assembly + { + get { return GetType().Assembly; } + } + public MySqlAuthenticationData(string connectionString, string realm) : base(connectionString) { @@ -51,7 +57,7 @@ namespace OpenSim.Data.MySQL using (MySqlConnection dbcon = new MySqlConnection(m_connectionString)) { dbcon.Open(); - Migration m = new Migration(dbcon, GetType().Assembly, "AuthStore"); + Migration m = new Migration(dbcon, Assembly, "AuthStore"); m.Update(); } } diff --git a/OpenSim/Data/MySQL/MySQLEstateData.cs b/OpenSim/Data/MySQL/MySQLEstateData.cs index c42c687ed9..de72a6a931 100644 --- a/OpenSim/Data/MySQL/MySQLEstateData.cs +++ b/OpenSim/Data/MySQL/MySQLEstateData.cs @@ -54,6 +54,11 @@ namespace OpenSim.Data.MySQL private Dictionary m_FieldMap = new Dictionary(); + protected virtual Assembly Assembly + { + get { return GetType().Assembly; } + } + public MySQLEstateStore() { } @@ -82,8 +87,7 @@ namespace OpenSim.Data.MySQL { dbcon.Open(); - Assembly assem = GetType().Assembly; - Migration m = new Migration(dbcon, assem, "EstateStore"); + Migration m = new Migration(dbcon, Assembly, "EstateStore"); m.Update(); Type t = typeof(EstateSettings); diff --git a/OpenSim/Data/MySQL/MySQLGenericTableHandler.cs b/OpenSim/Data/MySQL/MySQLGenericTableHandler.cs index 7c23a47d04..8efe4e9bd6 100644 --- a/OpenSim/Data/MySQL/MySQLGenericTableHandler.cs +++ b/OpenSim/Data/MySQL/MySQLGenericTableHandler.cs @@ -46,6 +46,11 @@ namespace OpenSim.Data.MySQL protected string m_Realm; protected FieldInfo m_DataField = null; + protected virtual Assembly Assembly + { + get { return GetType().Assembly; } + } + public MySQLGenericTableHandler(string connectionString, string realm, string storeName) : base(connectionString) { @@ -57,7 +62,7 @@ namespace OpenSim.Data.MySQL using (MySqlConnection dbcon = new MySqlConnection(m_connectionString)) { dbcon.Open(); - Migration m = new Migration(dbcon, GetType().Assembly, storeName); + Migration m = new Migration(dbcon, Assembly, storeName); m.Update(); } } diff --git a/OpenSim/Data/MySQL/MySQLRegionData.cs b/OpenSim/Data/MySQL/MySQLRegionData.cs index d04e3dc996..c20c39263a 100644 --- a/OpenSim/Data/MySQL/MySQLRegionData.cs +++ b/OpenSim/Data/MySQL/MySQLRegionData.cs @@ -29,6 +29,8 @@ using System; using System.Collections; using System.Collections.Generic; using System.Data; +using System.Reflection; + using OpenMetaverse; using OpenSim.Framework; using OpenSim.Data; @@ -42,6 +44,11 @@ namespace OpenSim.Data.MySQL private List m_ColumnNames; //private string m_connectionString; + protected virtual Assembly Assembly + { + get { return GetType().Assembly; } + } + public MySqlRegionData(string connectionString, string realm) : base(connectionString) { @@ -51,7 +58,7 @@ namespace OpenSim.Data.MySQL using (MySqlConnection dbcon = new MySqlConnection(m_connectionString)) { dbcon.Open(); - Migration m = new Migration(dbcon, GetType().Assembly, "GridStore"); + Migration m = new Migration(dbcon, Assembly, "GridStore"); m.Update(); } } diff --git a/OpenSim/Data/MySQL/MySQLSimulationData.cs b/OpenSim/Data/MySQL/MySQLSimulationData.cs index 02997b3278..e14d775b45 100644 --- a/OpenSim/Data/MySQL/MySQLSimulationData.cs +++ b/OpenSim/Data/MySQL/MySQLSimulationData.cs @@ -52,6 +52,11 @@ namespace OpenSim.Data.MySQL private string m_connectionString; private object m_dbLock = new object(); + protected virtual Assembly Assembly + { + get { return GetType().Assembly; } + } + public MySQLSimulationData() { } @@ -71,8 +76,7 @@ namespace OpenSim.Data.MySQL // Apply new Migrations // - Assembly assem = GetType().Assembly; - Migration m = new Migration(dbcon, assem, "RegionStore"); + Migration m = new Migration(dbcon, Assembly, "RegionStore"); m.Update(); // Clean dropped attachments From 743a6b0da5a98329997c98463feca37885ae7c58 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Tue, 8 Mar 2011 22:44:02 +0000 Subject: [PATCH 46/81] Make -m shortcut option for --merge on load iar specific. Correct some log message origins. --- .../Inventory/Archiver/InventoryArchiverModule.cs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiverModule.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiverModule.cs index 26edba4b6c..576a154719 100644 --- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiverModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiverModule.cs @@ -109,9 +109,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver scene.AddCommand( this, "load iar", - "load iar [--merge] []", + "load iar [-m|--merge] []", "Load user inventory archive (IAR).", - "--merge is an option which merges the loaded IAR with existing inventory folders where possible, rather than always creating new ones" + "-m|--merge is an option which merges the loaded IAR with existing inventory folders where possible, rather than always creating new ones" + " is user's first name." + Environment.NewLine + " is user's last name." + Environment.NewLine + " is the path inside the user's inventory where the IAR should be loaded." + Environment.NewLine @@ -181,7 +181,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver catch (EntryPointNotFoundException e) { m_log.ErrorFormat( - "[ARCHIVER]: Mismatch between Mono and zlib1g library version when trying to create compression stream." + "[INVENTORY ARCHIVER]: Mismatch between Mono and zlib1g library version when trying to create compression stream." + "If you've manually installed Mono, have you appropriately updated zlib1g as well?"); m_log.Error(e); @@ -221,7 +221,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver catch (EntryPointNotFoundException e) { m_log.ErrorFormat( - "[ARCHIVER]: Mismatch between Mono and zlib1g library version when trying to create compression stream." + "[INVENTORY ARCHIVER]: Mismatch between Mono and zlib1g library version when trying to create compression stream." + "If you've manually installed Mono, have you appropriately updated zlib1g as well?"); m_log.Error(e); @@ -269,7 +269,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver catch (EntryPointNotFoundException e) { m_log.ErrorFormat( - "[ARCHIVER]: Mismatch between Mono and zlib1g library version when trying to create compression stream." + "[INVENTORY ARCHIVER]: Mismatch between Mono and zlib1g library version when trying to create compression stream." + "If you've manually installed Mono, have you appropriately updated zlib1g as well?"); m_log.Error(e); @@ -317,7 +317,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver catch (EntryPointNotFoundException e) { m_log.ErrorFormat( - "[ARCHIVER]: Mismatch between Mono and zlib1g library version when trying to create compression stream." + "[INVENTORY ARCHIVER]: Mismatch between Mono and zlib1g library version when trying to create compression stream." + "If you've manually installed Mono, have you appropriately updated zlib1g as well?"); m_log.Error(e); @@ -358,7 +358,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver if (mainParams.Count < 6) { m_log.Error( - "[INVENTORY ARCHIVER]: usage is load iar [--merge] []"); + "[INVENTORY ARCHIVER]: usage is load iar [-m|--merge] []"); return; } From 8a2360bf815d4d78fcff34a69dec24782494bd2e Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Wed, 9 Mar 2011 01:21:31 +0000 Subject: [PATCH 47/81] Simplify TestLoadIarV0_1AbsentUsers() to use common IAR test setup. Make static dictionaries on NullUserAccountData instance instead to stop user accounts being carried over between tests --- OpenSim/Data/Null/NullUserAccountData.cs | 65 +++++++++++++++---- .../Serialization/External/OspResolver.cs | 19 +++++- .../Archiver/InventoryArchiveReadRequest.cs | 2 + .../Archiver/Tests/InventoryArchiverTests.cs | 65 +++++-------------- .../Tests/Common/Setup/SceneSetupHelpers.cs | 6 +- 5 files changed, 89 insertions(+), 68 deletions(-) diff --git a/OpenSim/Data/Null/NullUserAccountData.cs b/OpenSim/Data/Null/NullUserAccountData.cs index ede23fb8fe..ec54dba2e8 100644 --- a/OpenSim/Data/Null/NullUserAccountData.cs +++ b/OpenSim/Data/Null/NullUserAccountData.cs @@ -28,6 +28,9 @@ using System; using System.Collections; using System.Collections.Generic; +using System.Reflection; +using System.Text; +using log4net; using OpenMetaverse; using OpenSim.Framework; using OpenSim.Data; @@ -36,12 +39,17 @@ namespace OpenSim.Data.Null { public class NullUserAccountData : IUserAccountData { - private static Dictionary m_DataByUUID = new Dictionary(); - private static Dictionary m_DataByName = new Dictionary(); - private static Dictionary m_DataByEmail = new Dictionary(); + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + private Dictionary m_DataByUUID = new Dictionary(); + private Dictionary m_DataByName = new Dictionary(); + private Dictionary m_DataByEmail = new Dictionary(); public NullUserAccountData(string connectionString, string realm) { +// m_log.DebugFormat( +// "[NULL USER ACCOUNT DATA]: Initializing new NullUserAccountData with connectionString [{0}], realm [{1}]", +// connectionString, realm); } /// @@ -54,6 +62,15 @@ namespace OpenSim.Data.Null /// public UserAccountData[] Get(string[] fields, string[] values) { +// if (m_log.IsDebugEnabled) +// { +// m_log.DebugFormat( +// "[NULL USER ACCOUNT DATA]: Called Get with fields [{0}], values [{1}]", +// string.Join(", ", fields), string.Join(", ", values)); +// } + + UserAccountData[] userAccounts = new UserAccountData[0]; + List fieldsLst = new List(fields); if (fieldsLst.Contains("PrincipalID")) { @@ -61,41 +78,61 @@ namespace OpenSim.Data.Null UUID id = UUID.Zero; if (UUID.TryParse(values[i], out id)) if (m_DataByUUID.ContainsKey(id)) - return new UserAccountData[] { m_DataByUUID[id] }; - } - if (fieldsLst.Contains("FirstName") && fieldsLst.Contains("LastName")) + userAccounts = new UserAccountData[] { m_DataByUUID[id] }; + } + else if (fieldsLst.Contains("FirstName") && fieldsLst.Contains("LastName")) { int findex = fieldsLst.IndexOf("FirstName"); int lindex = fieldsLst.IndexOf("LastName"); if (m_DataByName.ContainsKey(values[findex] + " " + values[lindex])) - return new UserAccountData[] { m_DataByName[values[findex] + " " + values[lindex]] }; - } - if (fieldsLst.Contains("Email")) + { + userAccounts = new UserAccountData[] { m_DataByName[values[findex] + " " + values[lindex]] }; + } + } + else if (fieldsLst.Contains("Email")) { int i = fieldsLst.IndexOf("Email"); if (m_DataByEmail.ContainsKey(values[i])) - return new UserAccountData[] { m_DataByEmail[values[i]] }; + userAccounts = new UserAccountData[] { m_DataByEmail[values[i]] }; } - - // Fail - return new UserAccountData[0]; + +// if (m_log.IsDebugEnabled) +// { +// StringBuilder sb = new StringBuilder(); +// foreach (UserAccountData uad in userAccounts) +// sb.AppendFormat("({0} {1} {2}) ", uad.FirstName, uad.LastName, uad.PrincipalID); +// +// m_log.DebugFormat( +// "[NULL USER ACCOUNT DATA]: Returning {0} user accounts out of {1}: [{2}]", userAccounts.Length, m_DataByName.Count, sb); +// } + + return userAccounts; } public bool Store(UserAccountData data) { if (data == null) return false; - + + m_log.DebugFormat( + "[NULL USER ACCOUNT DATA]: Storing user account {0} {1} {2} {3}", + data.FirstName, data.LastName, data.PrincipalID, this.GetHashCode()); + m_DataByUUID[data.PrincipalID] = data; m_DataByName[data.FirstName + " " + data.LastName] = data; if (data.Data.ContainsKey("Email") && data.Data["Email"] != null && data.Data["Email"] != string.Empty) m_DataByEmail[data.Data["Email"]] = data; + +// m_log.DebugFormat("m_DataByUUID count is {0}, m_DataByName count is {1}", m_DataByUUID.Count, m_DataByName.Count); return true; } public UserAccountData[] GetUsers(UUID scopeID, string query) { +// m_log.DebugFormat( +// "[NULL USER ACCOUNT DATA]: Called GetUsers with scope [{0}], query [{1}]", scopeID, query); + string[] words = query.Split(new char[] { ' ' }); for (int i = 0; i < words.Length; i++) diff --git a/OpenSim/Framework/Serialization/External/OspResolver.cs b/OpenSim/Framework/Serialization/External/OspResolver.cs index 7e3dd1b79b..d31d27c4a6 100644 --- a/OpenSim/Framework/Serialization/External/OspResolver.cs +++ b/OpenSim/Framework/Serialization/External/OspResolver.cs @@ -66,6 +66,8 @@ namespace OpenSim.Framework.Serialization UserAccount account = userService.GetUserAccount(UUID.Zero, userId); if (account != null) return MakeOspa(account.FirstName, account.LastName); +// else +// m_log.WarnFormat("[OSP RESOLVER]: No user account for {0}", userId); return null; } @@ -77,6 +79,8 @@ namespace OpenSim.Framework.Serialization /// public static string MakeOspa(string firstName, string lastName) { +// m_log.DebugFormat("[OSP RESOLVER]: Making OSPA for {0} {1}", firstName, lastName); + return OSPA_PREFIX + OSPA_NAME_KEY + OSPA_PAIR_SEPARATOR + firstName + OSPA_NAME_VALUE_SEPARATOR + lastName; } @@ -97,7 +101,10 @@ namespace OpenSim.Framework.Serialization public static UUID ResolveOspa(string ospa, IUserAccountService userService) { if (!ospa.StartsWith(OSPA_PREFIX)) - return UUID.Zero; + { +// m_log.DebugFormat("[OSP RESOLVER]: ResolveOspa() got unrecognized format [{0}]", ospa); + return UUID.Zero; + } // m_log.DebugFormat("[OSP RESOLVER]: Resolving {0}", ospa); @@ -161,7 +168,17 @@ namespace OpenSim.Framework.Serialization UserAccount account = userService.GetUserAccount(UUID.Zero, firstName, lastName); if (account != null) + { +// m_log.DebugFormat( +// "[OSP RESOLVER]: Found user account with uuid {0} for {1} {2}", +// account.PrincipalID, firstName, lastName); + return account.PrincipalID; + } +// else +// { +// m_log.DebugFormat("[OSP RESOLVER]: No resolved OSPA user account for {0}", name); +// } // XXX: Disable temporary user profile creation for now as implementation is incomplete - justincc /* diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs index 603070614c..7849d88320 100644 --- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs +++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs @@ -400,6 +400,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver UUID ospResolvedId = OspResolver.ResolveOspa(item.CreatorId, m_scene.UserAccountService); if (UUID.Zero != ospResolvedId) // The user exists in this grid { +// m_log.DebugFormat("[INVENTORY ARCHIVER]: Found creator {0} via OSPA resolution", ospResolvedId); + item.CreatorIdAsUuid = ospResolvedId; // XXX: For now, don't preserve the OSPA in the creator id (which actually gets persisted to the diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs index 8a84c7a2d9..de9550557b 100644 --- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs +++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs @@ -97,6 +97,11 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests protected void ConstructDefaultIarBytesForTestLoad() { +// log4net.Config.XmlConfigurator.Configure(); + + Scene scene = SceneSetupHelpers.SetupScene("Inventory"); + UserProfileTestUtils.CreateUserWithInventory(scene, m_ua2, "hampshire"); + string archiveItemName = InventoryArchiveWriteRequest.CreateArchiveItemName(m_item1Name, UUID.Random()); MemoryStream archiveWriteStream = new MemoryStream(); @@ -106,14 +111,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests item1.Name = m_item1Name; item1.AssetID = UUID.Random(); item1.GroupID = UUID.Random(); - //item1.CreatorId = OspResolver.MakeOspa(m_ua2.FirstName, m_ua2.LastName); - //item1.CreatorId = userUuid.ToString(); - item1.CreatorId = m_ua2.PrincipalID.ToString(); + item1.CreatorIdAsUuid = m_ua2.PrincipalID; item1.Owner = UUID.Zero; - Scene scene = SceneSetupHelpers.SetupScene("Inventory"); - UserProfileTestUtils.CreateUserWithInventory(scene, m_ua2, "hampshire"); - string item1FileName = string.Format("{0}{1}", ArchiveConstants.INVENTORY_PATH, archiveItemName); tar.WriteFile(item1FileName, UserInventoryItemSerializer.Serialize(item1, new Dictionary(), scene.UserAccountService)); @@ -390,7 +390,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests public void TestLoadIarV0_1ExistingUsers() { TestHelper.InMethod(); - //log4net.Config.XmlConfigurator.Configure(); +// log4net.Config.XmlConfigurator.Configure(); SerialiserModule serialiserModule = new SerialiserModule(); InventoryArchiverModule archiverModule = new InventoryArchiverModule(); @@ -414,9 +414,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests // Assert.That( // foundItem1.CreatorId, Is.EqualTo(item1.CreatorId), // "Loaded item non-uuid creator doesn't match original"); - Assert.That( - foundItem1.CreatorId, Is.EqualTo(m_ua2.PrincipalID.ToString()), - "Loaded item non-uuid creator doesn't match original"); +// Assert.That( +// foundItem1.CreatorId, Is.EqualTo(m_ua2.PrincipalID.ToString()), +// "Loaded item non-uuid creator doesn't match original"); Assert.That( foundItem1.CreatorIdAsUuid, Is.EqualTo(m_ua2.PrincipalID), @@ -529,64 +529,29 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests /// Test loading a V0.1 OpenSim Inventory Archive (subject to change since there is no fixed format yet) where /// embedded creators do not exist in the system /// - /// - /// This may possibly one day get overtaken by the as yet incomplete temporary profiles feature - /// (as tested in the a later commented out test) - /// This test is currently disabled [Test] public void TestLoadIarV0_1AbsentUsers() { TestHelper.InMethod(); - //log4net.Config.XmlConfigurator.Configure(); +// log4net.Config.XmlConfigurator.Configure(); - string userFirstName = "Charlie"; - string userLastName = "Chan"; - UUID userUuid = UUID.Parse("00000000-0000-0000-0000-000000000999"); - string userItemCreatorFirstName = "Bat"; - string userItemCreatorLastName = "Man"; - //UUID userItemCreatorUuid = UUID.Parse("00000000-0000-0000-0000-000000008888"); - - string itemName = "b.lsl"; - string archiveItemName = InventoryArchiveWriteRequest.CreateArchiveItemName(itemName, UUID.Random()); - - MemoryStream archiveWriteStream = new MemoryStream(); - TarArchiveWriter tar = new TarArchiveWriter(archiveWriteStream); - - InventoryItemBase item1 = new InventoryItemBase(); - item1.Name = itemName; - item1.AssetID = UUID.Random(); - item1.GroupID = UUID.Random(); - item1.CreatorId = OspResolver.MakeOspa(userItemCreatorFirstName, userItemCreatorLastName); - //item1.CreatorId = userUuid.ToString(); - //item1.CreatorId = "00000000-0000-0000-0000-000000000444"; - item1.Owner = UUID.Zero; - - string item1FileName - = string.Format("{0}{1}", ArchiveConstants.INVENTORY_PATH, archiveItemName); - tar.WriteFile(item1FileName, UserInventoryItemSerializer.Serialize(item1, new Dictionary(), null)); - tar.Close(); - - MemoryStream archiveReadStream = new MemoryStream(archiveWriteStream.ToArray()); 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 = SceneSetupHelpers.SetupScene("inventory"); - SceneSetupHelpers.SetupSceneModules(scene, serialiserModule, archiverModule); - UserProfileTestUtils.CreateUserWithInventory(scene, userFirstName, userLastName, userUuid, "meowfood"); - archiverModule.DearchiveInventory(userFirstName, userLastName, "/", "meowfood", archiveReadStream); + UserProfileTestUtils.CreateUserWithInventory(scene, m_ua1, "password"); + archiverModule.DearchiveInventory(m_ua1.FirstName, m_ua1.LastName, "/", "password", m_iarStream); InventoryItemBase foundItem1 - = InventoryArchiveUtils.FindItemByPath(scene.InventoryService, userUuid, itemName); + = InventoryArchiveUtils.FindItemByPath(scene.InventoryService, m_ua1.PrincipalID, m_item1Name); 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.CreatorIdAsUuid, Is.EqualTo(userUuid), + foundItem1.CreatorIdAsUuid, Is.EqualTo(m_ua1.PrincipalID), "Loaded item uuid creator doesn't match that of the loading user"); } diff --git a/OpenSim/Tests/Common/Setup/SceneSetupHelpers.cs b/OpenSim/Tests/Common/Setup/SceneSetupHelpers.cs index 5be70bc710..08cc7c5fcd 100644 --- a/OpenSim/Tests/Common/Setup/SceneSetupHelpers.cs +++ b/OpenSim/Tests/Common/Setup/SceneSetupHelpers.cs @@ -304,12 +304,12 @@ namespace OpenSim.Tests.Common.Setup config.Configs["UserAccountService"].Set( "LocalServiceModule", "OpenSim.Services.UserAccountService.dll:UserAccountService"); - if (m_userAccountService == null) - { +// if (m_userAccountService == null) +// { ISharedRegionModule userAccountService = new LocalUserAccountServicesConnector(); userAccountService.Initialise(config); m_userAccountService = userAccountService; - } +// } m_userAccountService.AddRegion(testScene); m_userAccountService.RegionLoaded(testScene); From f375a5e9cbe96b0a07c52f27b0a4b2b620e5d6d8 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Wed, 9 Mar 2011 01:31:47 +0000 Subject: [PATCH 48/81] Simplify SceneSetupHelpers class by removing all code which was originally preserving service instances between tests. This wasn't being used anyway and just leads to hard to diagnose test failures. --- .../Tests/Common/Setup/SceneSetupHelpers.cs | 93 ++++++++----------- 1 file changed, 40 insertions(+), 53 deletions(-) diff --git a/OpenSim/Tests/Common/Setup/SceneSetupHelpers.cs b/OpenSim/Tests/Common/Setup/SceneSetupHelpers.cs index 08cc7c5fcd..2aeafc823f 100644 --- a/OpenSim/Tests/Common/Setup/SceneSetupHelpers.cs +++ b/OpenSim/Tests/Common/Setup/SceneSetupHelpers.cs @@ -59,19 +59,14 @@ namespace OpenSim.Tests.Common.Setup { // These static variables in order to allow regions to be linked by shared modules and same // CommunicationsManager. - private static ISharedRegionModule m_assetService = null; -// private static ISharedRegionModule m_authenticationService = null; private static ISharedRegionModule m_inventoryService = null; - private static ISharedRegionModule m_gridService = null; - private static ISharedRegionModule m_userAccountService = null; - private static ISharedRegionModule m_presenceService = null; /// /// Set up a test scene /// - /// + /// /// Automatically starts service threads, as would the normal runtime. - /// + /// /// public static TestScene SetupScene() { @@ -156,10 +151,7 @@ namespace OpenSim.Tests.Common.Setup testScene.AddModule(godsModule.Name, godsModule); realServices = realServices.ToLower(); - if (realServices.Contains("asset")) - StartAssetService(testScene, true); - else - StartAssetService(testScene, false); + LocalAssetServicesConnector assetService = StartAssetService(testScene, realServices.Contains("asset")); // For now, always started a 'real' authentication service StartAuthenticationService(testScene, true); @@ -169,14 +161,15 @@ namespace OpenSim.Tests.Common.Setup else StartInventoryService(testScene, false); - StartGridService(testScene, true); - StartUserAccountService(testScene); - StartPresenceService(testScene); + StartGridService(testScene, true); + LocalUserAccountServicesConnector userAccountService = StartUserAccountService(testScene); + LocalPresenceServicesConnector presenceService = StartPresenceService(testScene); m_inventoryService.PostInitialise(); - m_assetService.PostInitialise(); - m_userAccountService.PostInitialise(); - m_presenceService.PostInitialise(); + assetService.PostInitialise(); + userAccountService.PostInitialise(); + presenceService.PostInitialise(); + testScene.RegionInfo.EstateSettings.EstateOwner = UUID.Random(); testScene.SetModuleInterfaces(); @@ -191,11 +184,7 @@ namespace OpenSim.Tests.Common.Setup // It's really not a good idea to use static variables as they carry over between tests, leading to // problems that are extremely hard to debug. Really, these static fields need to be eliminated - // tests using multiple regions that need to share modules need to find another solution. - m_assetService = null; m_inventoryService = null; - m_gridService = null; - m_userAccountService = null; - m_presenceService = null; testScene.RegionInfo.EstateSettings = new EstateSettings(); testScene.LoginsDisabled = false; @@ -203,9 +192,9 @@ namespace OpenSim.Tests.Common.Setup return testScene; } - private static void StartAssetService(Scene testScene, bool real) + private static LocalAssetServicesConnector StartAssetService(Scene testScene, bool real) { - ISharedRegionModule assetService = new LocalAssetServicesConnector(); + LocalAssetServicesConnector assetService = new LocalAssetServicesConnector(); IConfigSource config = new IniConfigSource(); config.AddConfig("Modules"); config.AddConfig("AssetService"); @@ -219,7 +208,8 @@ namespace OpenSim.Tests.Common.Setup assetService.AddRegion(testScene); assetService.RegionLoaded(testScene); testScene.AddRegionModule(assetService.Name, assetService); - m_assetService = assetService; + + return assetService; } private static void StartAuthenticationService(Scene testScene, bool real) @@ -268,7 +258,7 @@ namespace OpenSim.Tests.Common.Setup m_inventoryService = inventoryService; } - private static void StartGridService(Scene testScene, bool real) + private static LocalGridServicesConnector StartGridService(Scene testScene, bool real) { IConfigSource config = new IniConfigSource(); config.AddConfig("Modules"); @@ -277,24 +267,25 @@ namespace OpenSim.Tests.Common.Setup config.Configs["GridService"].Set("StorageProvider", "OpenSim.Data.Null.dll:NullRegionData"); if (real) config.Configs["GridService"].Set("LocalServiceModule", "OpenSim.Services.GridService.dll:GridService"); - if (m_gridService == null) - { - ISharedRegionModule gridService = new LocalGridServicesConnector(); - gridService.Initialise(config); - m_gridService = gridService; - } + + LocalGridServicesConnector gridService = new LocalGridServicesConnector(); + gridService.Initialise(config); + //else // config.Configs["GridService"].Set("LocalServiceModule", "OpenSim.Tests.Common.dll:TestGridService"); - m_gridService.AddRegion(testScene); - m_gridService.RegionLoaded(testScene); + gridService.AddRegion(testScene); + gridService.RegionLoaded(testScene); //testScene.AddRegionModule(m_gridService.Name, m_gridService); + + return gridService; } /// /// Start a user account service /// /// - private static void StartUserAccountService(Scene testScene) + /// + private static LocalUserAccountServicesConnector StartUserAccountService(Scene testScene) { IConfigSource config = new IniConfigSource(); config.AddConfig("Modules"); @@ -304,23 +295,21 @@ namespace OpenSim.Tests.Common.Setup config.Configs["UserAccountService"].Set( "LocalServiceModule", "OpenSim.Services.UserAccountService.dll:UserAccountService"); -// if (m_userAccountService == null) -// { - ISharedRegionModule userAccountService = new LocalUserAccountServicesConnector(); - userAccountService.Initialise(config); - m_userAccountService = userAccountService; -// } + LocalUserAccountServicesConnector userAccountService = new LocalUserAccountServicesConnector(); + userAccountService.Initialise(config); - m_userAccountService.AddRegion(testScene); - m_userAccountService.RegionLoaded(testScene); - testScene.AddRegionModule(m_userAccountService.Name, m_userAccountService); + userAccountService.AddRegion(testScene); + userAccountService.RegionLoaded(testScene); + testScene.AddRegionModule(userAccountService.Name, userAccountService); + + return userAccountService; } /// /// Start a presence service /// /// - private static void StartPresenceService(Scene testScene) + private static LocalPresenceServicesConnector StartPresenceService(Scene testScene) { IConfigSource config = new IniConfigSource(); config.AddConfig("Modules"); @@ -330,16 +319,14 @@ namespace OpenSim.Tests.Common.Setup config.Configs["PresenceService"].Set( "LocalServiceModule", "OpenSim.Services.PresenceService.dll:PresenceService"); - if (m_presenceService == null) - { - ISharedRegionModule presenceService = new LocalPresenceServicesConnector(); - presenceService.Initialise(config); - m_presenceService = presenceService; - } + LocalPresenceServicesConnector presenceService = new LocalPresenceServicesConnector(); + presenceService.Initialise(config); - m_presenceService.AddRegion(testScene); - m_presenceService.RegionLoaded(testScene); - testScene.AddRegionModule(m_presenceService.Name, m_presenceService); + presenceService.AddRegion(testScene); + presenceService.RegionLoaded(testScene); + testScene.AddRegionModule(presenceService.Name, presenceService); + + return presenceService; } /// From 2fa8fc505223cbd2b6e327fe946748c717dda3b5 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Wed, 9 Mar 2011 01:37:31 +0000 Subject: [PATCH 49/81] remove inventory service preserving code from SceneSetupHelpers too --- .../Tests/Common/Setup/SceneSetupHelpers.cs | 47 ++++--------------- 1 file changed, 10 insertions(+), 37 deletions(-) diff --git a/OpenSim/Tests/Common/Setup/SceneSetupHelpers.cs b/OpenSim/Tests/Common/Setup/SceneSetupHelpers.cs index 2aeafc823f..aa4b285981 100644 --- a/OpenSim/Tests/Common/Setup/SceneSetupHelpers.cs +++ b/OpenSim/Tests/Common/Setup/SceneSetupHelpers.cs @@ -57,10 +57,6 @@ namespace OpenSim.Tests.Common.Setup /// public class SceneSetupHelpers { - // These static variables in order to allow regions to be linked by shared modules and same - // CommunicationsManager. - private static ISharedRegionModule m_inventoryService = null; - /// /// Set up a test scene /// @@ -81,24 +77,9 @@ namespace OpenSim.Tests.Common.Setup /// public static TestScene SetupScene(String realServices) { - return SetupScene( - "Unit test region", UUID.Random(), 1000, 1000, realServices); + return SetupScene("Unit test region", UUID.Random(), 1000, 1000, realServices); } - // REFACTORING PROBLEM. No idea what the difference is with the previous one - ///// - ///// Set up a test scene - ///// - ///// - ///// Starts real inventory and asset services, as opposed to mock ones, if true - ///// This should be the same if simulating two scenes within a standalone - ///// - //public static TestScene SetupScene(String realServices) - //{ - // return SetupScene( - // "Unit test region", UUID.Random(), 1000, 1000, ""); - //} - /// /// Set up a test scene /// @@ -110,7 +91,7 @@ namespace OpenSim.Tests.Common.Setup /// public static TestScene SetupScene(string name, UUID id, uint x, uint y) { - return SetupScene(name, id, x, y,""); + return SetupScene(name, id, x, y, ""); } /// @@ -156,16 +137,12 @@ namespace OpenSim.Tests.Common.Setup // For now, always started a 'real' authentication service StartAuthenticationService(testScene, true); - if (realServices.Contains("inventory")) - StartInventoryService(testScene, true); - else - StartInventoryService(testScene, false); - + LocalInventoryServicesConnector inventoryService = StartInventoryService(testScene, realServices.Contains("inventory")); StartGridService(testScene, true); LocalUserAccountServicesConnector userAccountService = StartUserAccountService(testScene); LocalPresenceServicesConnector presenceService = StartPresenceService(testScene); - m_inventoryService.PostInitialise(); + inventoryService.PostInitialise(); assetService.PostInitialise(); userAccountService.PostInitialise(); presenceService.PostInitialise(); @@ -181,11 +158,6 @@ namespace OpenSim.Tests.Common.Setup testScene.PhysicsScene = physicsPluginManager.GetPhysicsScene("basicphysics", "ZeroMesher", new IniConfigSource(), "test"); - // It's really not a good idea to use static variables as they carry over between tests, leading to - // problems that are extremely hard to debug. Really, these static fields need to be eliminated - - // tests using multiple regions that need to share modules need to find another solution. - m_inventoryService = null; - testScene.RegionInfo.EstateSettings = new EstateSettings(); testScene.LoginsDisabled = false; @@ -233,9 +205,9 @@ namespace OpenSim.Tests.Common.Setup //m_authenticationService = service; } - private static void StartInventoryService(Scene testScene, bool real) + private static LocalInventoryServicesConnector StartInventoryService(Scene testScene, bool real) { - ISharedRegionModule inventoryService = new LocalInventoryServicesConnector(); + LocalInventoryServicesConnector inventoryService = new LocalInventoryServicesConnector(); IConfigSource config = new IniConfigSource(); config.AddConfig("Modules"); config.AddConfig("InventoryService"); @@ -255,7 +227,8 @@ namespace OpenSim.Tests.Common.Setup inventoryService.AddRegion(testScene); inventoryService.RegionLoaded(testScene); testScene.AddRegionModule(inventoryService.Name, inventoryService); - m_inventoryService = inventoryService; + + return inventoryService; } private static LocalGridServicesConnector StartGridService(Scene testScene, bool real) @@ -423,7 +396,7 @@ namespace OpenSim.Tests.Common.Setup /// /// Add a root agent. /// - /// + /// /// This function /// /// 1) Tells the scene that an agent is coming. Normally, the login service (local if standalone, from the @@ -434,7 +407,7 @@ namespace OpenSim.Tests.Common.Setup /// /// 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 - /// + /// /// /// /// From ae507bb0600774624f876c4562391cec0111eee8 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Wed, 9 Mar 2011 01:53:27 +0000 Subject: [PATCH 50/81] Split out path tests from InventoryArchiveTests. Factor common code into test case parent --- .../Tests/InventoryArchiveTestCase.cs | 124 ++++ .../Archiver/Tests/InventoryArchiverTests.cs | 533 +----------------- .../Inventory/Archiver/Tests/PathTests.cs | 436 ++++++++++++++ 3 files changed, 562 insertions(+), 531 deletions(-) create mode 100644 OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveTestCase.cs create mode 100644 OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/PathTests.cs diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveTestCase.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveTestCase.cs new file mode 100644 index 0000000000..023c452a23 --- /dev/null +++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveTestCase.cs @@ -0,0 +1,124 @@ +/* + * 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 NUnit.Framework.SyntaxHelpers; +using OpenMetaverse; +using OpenSim.Data; +using OpenSim.Framework; +using OpenSim.Framework.Serialization; +using OpenSim.Framework.Serialization.External; +using OpenSim.Framework.Communications; +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; +using OpenSim.Tests.Common.Mock; +using OpenSim.Tests.Common.Setup; + +namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests +{ + [TestFixture] + public class InventoryArchiveTestCase + { + 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_ua1 + = new UserAccount { + PrincipalID = UUID.Parse("00000000-0000-0000-0000-000000000555"), + FirstName = "Mr", + LastName = "Tiddles" }; + protected UserAccount m_ua2 + = new UserAccount { + PrincipalID = UUID.Parse("00000000-0000-0000-0000-000000000666"), + FirstName = "Lord", + LastName = "Lucan" }; + protected string m_item1Name = "b.lsl"; + + [SetUp] + public void SetUp() + { + m_iarStream = new MemoryStream(m_iarStreamBytes); + } + + [TestFixtureSetUp] + public void FixtureSetup() + { + ConstructDefaultIarBytesForTestLoad(); + } + + protected void ConstructDefaultIarBytesForTestLoad() + { +// log4net.Config.XmlConfigurator.Configure(); + + Scene scene = SceneSetupHelpers.SetupScene("Inventory"); + UserProfileTestUtils.CreateUserWithInventory(scene, m_ua2, "hampshire"); + + string archiveItemName = InventoryArchiveWriteRequest.CreateArchiveItemName(m_item1Name, UUID.Random()); + + MemoryStream archiveWriteStream = new MemoryStream(); + TarArchiveWriter tar = new TarArchiveWriter(archiveWriteStream); + + InventoryItemBase item1 = new InventoryItemBase(); + item1.Name = m_item1Name; + item1.AssetID = UUID.Random(); + item1.GroupID = UUID.Random(); + item1.CreatorIdAsUuid = m_ua2.PrincipalID; + item1.Owner = UUID.Zero; + + string item1FileName + = string.Format("{0}{1}", ArchiveConstants.INVENTORY_PATH, archiveItemName); + tar.WriteFile(item1FileName, UserInventoryItemSerializer.Serialize(item1, new Dictionary(), scene.UserAccountService)); + tar.Close(); + m_iarStreamBytes = archiveWriteStream.ToArray(); + } + + protected void SaveCompleted( + Guid id, bool succeeded, UserAccount userInfo, string invPath, Stream saveStream, + Exception reportedException) + { + mre.Set(); + } + } +} \ No newline at end of file diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs index de9550557b..edbbd81106 100644 --- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs +++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs @@ -50,195 +50,8 @@ using OpenSim.Tests.Common.Setup; namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests { [TestFixture] - public class InventoryArchiverTests - { - 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_ua1 - = new UserAccount { - PrincipalID = UUID.Parse("00000000-0000-0000-0000-000000000555"), - FirstName = "Mr", - LastName = "Tiddles" }; - protected UserAccount m_ua2 - = new UserAccount { - PrincipalID = UUID.Parse("00000000-0000-0000-0000-000000000666"), - FirstName = "Lord", - LastName = "Lucan" }; - string m_item1Name = "b.lsl"; - - private void SaveCompleted( - Guid id, bool succeeded, UserAccount userInfo, string invPath, Stream saveStream, - Exception reportedException) - { - mre.Set(); - } - - [SetUp] - public void SetUp() - { - m_iarStream = new MemoryStream(m_iarStreamBytes); - } - - [TestFixtureSetUp] - public void FixtureSetup() - { - ConstructDefaultIarBytesForTestLoad(); - } - - protected void ConstructDefaultIarBytesForTestLoad() - { -// log4net.Config.XmlConfigurator.Configure(); - - Scene scene = SceneSetupHelpers.SetupScene("Inventory"); - UserProfileTestUtils.CreateUserWithInventory(scene, m_ua2, "hampshire"); - - string archiveItemName = InventoryArchiveWriteRequest.CreateArchiveItemName(m_item1Name, UUID.Random()); - - MemoryStream archiveWriteStream = new MemoryStream(); - TarArchiveWriter tar = new TarArchiveWriter(archiveWriteStream); - - InventoryItemBase item1 = new InventoryItemBase(); - item1.Name = m_item1Name; - item1.AssetID = UUID.Random(); - item1.GroupID = UUID.Random(); - item1.CreatorIdAsUuid = m_ua2.PrincipalID; - item1.Owner = UUID.Zero; - - string item1FileName - = string.Format("{0}{1}", ArchiveConstants.INVENTORY_PATH, archiveItemName); - tar.WriteFile(item1FileName, UserInventoryItemSerializer.Serialize(item1, new Dictionary(), scene.UserAccountService)); - tar.Close(); - m_iarStreamBytes = archiveWriteStream.ToArray(); - } - - /// - /// Test saving an inventory path to a V0.1 OpenSim Inventory Archive - /// (subject to change since there is no fixed format yet). - /// - [Test] - public void TestSavePathToIarV0_1() - { - TestHelper.InMethod(); -// log4net.Config.XmlConfigurator.Configure(); - - InventoryArchiverModule archiverModule = new InventoryArchiverModule(); - - Scene scene = SceneSetupHelpers.SetupScene("Inventory"); - SceneSetupHelpers.SetupSceneModules(scene, archiverModule); - - // Create user - string userFirstName = "Jock"; - string userLastName = "Stirrup"; - string userPassword = "troll"; - UUID userId = UUID.Parse("00000000-0000-0000-0000-000000000020"); - UserProfileTestUtils.CreateUserWithInventory(scene, userFirstName, userLastName, userId, userPassword); - - // Create asset - SceneObjectGroup object1; - SceneObjectPart part1; - { - string partName = "My Little Dog Object"; - 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 = "My Little Dog"; - item1.AssetID = asset1.FullID; - item1.ID = item1Id; - InventoryFolderBase objsFolder - = InventoryArchiveUtils.FindFolderByPath(scene.InventoryService, userId, "Objects")[0]; - item1.Folder = objsFolder.ID; - scene.AddInventoryItem(item1); - - MemoryStream archiveWriteStream = new MemoryStream(); - archiverModule.OnInventoryArchiveSaved += SaveCompleted; - - // Test saving a particular path - mre.Reset(); - archiverModule.ArchiveInventory( - Guid.NewGuid(), userFirstName, userLastName, "Objects", 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}{2}", - ArchiveConstants.INVENTORY_PATH, - InventoryArchiveWriteRequest.CreateArchiveFolderName(objsFolder), - 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. - } - + public class InventoryArchiverTests : InventoryArchiveTestCase + { /// /// Test saving a single inventory item to a V0.1 OpenSim Inventory Archive /// (subject to change since there is no fixed format yet). @@ -356,30 +169,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests // TODO: Test presence of more files and contents of files. } - /// - /// Test that things work when the load path specified starts with a slash - /// - [Test] - public void TestLoadIarPathStartsWithSlash() - { - TestHelper.InMethod(); -// log4net.Config.XmlConfigurator.Configure(); - - SerialiserModule serialiserModule = new SerialiserModule(); - InventoryArchiverModule archiverModule = new InventoryArchiverModule(); - Scene scene = SceneSetupHelpers.SetupScene("inventory"); - SceneSetupHelpers.SetupSceneModules(scene, serialiserModule, archiverModule); - - UserProfileTestUtils.CreateUserWithInventory(scene, m_ua1, "password"); - archiverModule.DearchiveInventory(m_ua1.FirstName, m_ua1.LastName, "/Objects", "password", m_iarStream); - - InventoryItemBase foundItem1 - = InventoryArchiveUtils.FindItemByPath( - scene.InventoryService, m_ua1.PrincipalID, "/Objects/" + m_item1Name); - - Assert.That(foundItem1, Is.Not.Null, "Didn't find loaded item 1 in TestLoadIarFolderStartsWithSlash()"); - } - /// /// Test loading a V0.1 OpenSim Inventory Archive (subject to change since there is no fixed format yet) where /// an account exists with the creator name. @@ -443,88 +232,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests Assert.That(foundItem3, Is.Not.Null, "Didn't find loaded item 3"); } - [Test] - public void TestIarV0_1WithEscapedChars() - { - TestHelper.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 = SceneSetupHelpers.SetupScene("Inventory"); - SceneSetupHelpers.SetupSceneModules(scene, archiverModule); - - // Create user - string userFirstName = "Jock"; - string userLastName = "Stirrup"; - UUID userId = UUID.Parse("00000000-0000-0000-0000-000000000020"); - UserProfileTestUtils.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.FindFolderByPath(scene.InventoryService, userId, "Objects")[0]; - item1.Folder = objsFolder.ID; - scene.AddInventoryItem(item1); - - MemoryStream archiveWriteStream = new MemoryStream(); - archiverModule.OnInventoryArchiveSaved += SaveCompleted; - - mre.Reset(); - archiverModule.ArchiveInventory( - Guid.NewGuid(), userFirstName, userLastName, "Objects", userPassword, archiveWriteStream); - mre.WaitOne(60000, false); - - // LOAD ITEM - MemoryStream archiveReadStream = new MemoryStream(archiveWriteStream.ToArray()); - - archiverModule.DearchiveInventory(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 loading a V0.1 OpenSim Inventory Archive (subject to change since there is no fixed format yet) where /// embedded creators do not exist in the system @@ -554,241 +261,5 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests foundItem1.CreatorIdAsUuid, Is.EqualTo(m_ua1.PrincipalID), "Loaded item uuid creator doesn't match that of the loading user"); } - - /// - /// Test loading a V0.1 OpenSim Inventory Archive (subject to change since there is no fixed format yet) where - /// no account exists with the creator name - /// - /// Disabled since temporary profiles have not yet been implemented. - /// - //[Test] - //public void TestLoadIarV0_1TempProfiles() - //{ - // TestHelper.InMethod(); - - // //log4net.Config.XmlConfigurator.Configure(); - - // string userFirstName = "Dennis"; - // string userLastName = "Menace"; - // UUID userUuid = UUID.Parse("00000000-0000-0000-0000-000000000aaa"); - // string user2FirstName = "Walter"; - // string user2LastName = "Mitty"; - - // string itemName = "b.lsl"; - // string archiveItemName = InventoryArchiveWriteRequest.CreateArchiveItemName(itemName, UUID.Random()); - - // MemoryStream archiveWriteStream = new MemoryStream(); - // TarArchiveWriter tar = new TarArchiveWriter(archiveWriteStream); - - // InventoryItemBase item1 = new InventoryItemBase(); - // item1.Name = itemName; - // item1.AssetID = UUID.Random(); - // item1.GroupID = UUID.Random(); - // item1.CreatorId = OspResolver.MakeOspa(user2FirstName, user2LastName); - // item1.Owner = UUID.Zero; - - // string item1FileName - // = string.Format("{0}{1}", ArchiveConstants.INVENTORY_PATH, archiveItemName); - // tar.WriteFile(item1FileName, UserInventoryItemSerializer.Serialize(item1)); - // tar.Close(); - - // MemoryStream archiveReadStream = new MemoryStream(archiveWriteStream.ToArray()); - // 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 = SceneSetupHelpers.SetupScene(); - // IUserAdminService userAdminService = scene.CommsManager.UserAdminService; - - // SceneSetupHelpers.SetupSceneModules(scene, serialiserModule, archiverModule); - // userAdminService.AddUser( - // userFirstName, userLastName, "meowfood", String.Empty, 1000, 1000, userUuid); - - // archiverModule.DearchiveInventory(userFirstName, userLastName, "/", "troll", archiveReadStream); - - // // Check that a suitable temporary user profile has been created. - // UserProfileData user2Profile - // = scene.CommsManager.UserService.GetUserProfile( - // OspResolver.HashName(user2FirstName + " " + user2LastName)); - // Assert.That(user2Profile, Is.Not.Null); - // Assert.That(user2Profile.FirstName == user2FirstName); - // Assert.That(user2Profile.SurName == user2LastName); - - // CachedUserInfo userInfo - // = scene.CommsManager.UserProfileCacheService.GetUserDetails(userFirstName, userLastName); - // userInfo.OnInventoryReceived += InventoryReceived; - - // lock (this) - // { - // userInfo.FetchInventory(); - // Monitor.Wait(this, 60000); - // } - - // InventoryItemBase foundItem = userInfo.RootFolder.FindItemByPath(itemName); - - // Assert.That(foundItem.CreatorId, Is.EqualTo(item1.CreatorId)); - // Assert.That( - // foundItem.CreatorIdAsUuid, Is.EqualTo(OspResolver.HashName(user2FirstName + " " + user2LastName))); - // Assert.That(foundItem.Owner, Is.EqualTo(userUuid)); - - // Console.WriteLine("### Successfully completed {0} ###", MethodBase.GetCurrentMethod()); - //} - - /// - /// Test replication of an archive path to the user's inventory. - /// - [Test] - public void TestNewIarPath() - { - TestHelper.InMethod(); -// log4net.Config.XmlConfigurator.Configure(); - - Scene scene = SceneSetupHelpers.SetupScene("inventory"); - UserAccount ua1 = UserProfileTestUtils.CreateUserWithInventory(scene); - - Dictionary foldersCreated = new Dictionary(); - HashSet nodesLoaded = new HashSet(); - - 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(scene, ua1, null, (Stream)null, false) - .ReplicateArchivePathToUserInventory( - iarPath1, scene.InventoryService.GetRootFolder(ua1.PrincipalID), - foldersCreated, nodesLoaded); - - List folder1Candidates - = InventoryArchiveUtils.FindFolderByPath(scene.InventoryService, ua1.PrincipalID, folder1Name); - Assert.That(folder1Candidates.Count, Is.EqualTo(1)); - - InventoryFolderBase folder1 = folder1Candidates[0]; - List folder2aCandidates - = InventoryArchiveUtils.FindFolderByPath(scene.InventoryService, folder1, folder2aName); - Assert.That(folder2aCandidates.Count, Is.EqualTo(1)); - } - - { - // Test replication of path2 - new InventoryArchiveReadRequest(scene, ua1, null, (Stream)null, false) - .ReplicateArchivePathToUserInventory( - iarPath2, scene.InventoryService.GetRootFolder(ua1.PrincipalID), - foldersCreated, nodesLoaded); - - List folder1Candidates - = InventoryArchiveUtils.FindFolderByPath(scene.InventoryService, ua1.PrincipalID, folder1Name); - Assert.That(folder1Candidates.Count, Is.EqualTo(1)); - - InventoryFolderBase folder1 = folder1Candidates[0]; - - List folder2aCandidates - = InventoryArchiveUtils.FindFolderByPath(scene.InventoryService, folder1, folder2aName); - Assert.That(folder2aCandidates.Count, Is.EqualTo(1)); - - List folder2bCandidates - = InventoryArchiveUtils.FindFolderByPath(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() - { - TestHelper.InMethod(); - //log4net.Config.XmlConfigurator.Configure(); - - Scene scene = SceneSetupHelpers.SetupScene("inventory"); - UserAccount ua1 = UserProfileTestUtils.CreateUserWithInventory(scene); - - string folder1ExistingName = "a"; - string folder2Name = "b"; - - InventoryFolderBase folder1 - = UserInventoryTestUtils.CreateInventoryFolder( - scene.InventoryService, ua1.PrincipalID, folder1ExistingName); - - string folder1ArchiveName = InventoryArchiveWriteRequest.CreateArchiveFolderName(folder1ExistingName, UUID.Random()); - string folder2ArchiveName = InventoryArchiveWriteRequest.CreateArchiveFolderName(folder2Name, UUID.Random()); - - string itemArchivePath = string.Join("", new string[] { folder1ArchiveName, folder2ArchiveName }); - - new InventoryArchiveReadRequest(scene, ua1, null, (Stream)null, false) - .ReplicateArchivePathToUserInventory( - itemArchivePath, scene.InventoryService.GetRootFolder(ua1.PrincipalID), - new Dictionary(), new HashSet()); - - List folder1PostCandidates - = InventoryArchiveUtils.FindFolderByPath(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.FindFolderByPath(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() - { - TestHelper.InMethod(); -// log4net.Config.XmlConfigurator.Configure(); - - Scene scene = SceneSetupHelpers.SetupScene("inventory"); - UserAccount ua1 = UserProfileTestUtils.CreateUserWithInventory(scene); - - string folder1ExistingName = "a"; - string folder2Name = "b"; - - InventoryFolderBase folder1 - = UserInventoryTestUtils.CreateInventoryFolder( - scene.InventoryService, ua1.PrincipalID, folder1ExistingName); - - string folder1ArchiveName = InventoryArchiveWriteRequest.CreateArchiveFolderName(folder1ExistingName, UUID.Random()); - string folder2ArchiveName = InventoryArchiveWriteRequest.CreateArchiveFolderName(folder2Name, UUID.Random()); - - string itemArchivePath = string.Join("", new string[] { folder1ArchiveName, folder2ArchiveName }); - - new InventoryArchiveReadRequest(scene, ua1, folder1ExistingName, (Stream)null, true) - .ReplicateArchivePathToUserInventory( - itemArchivePath, scene.InventoryService.GetRootFolder(ua1.PrincipalID), - new Dictionary(), new HashSet()); - - List folder1PostCandidates - = InventoryArchiveUtils.FindFolderByPath(scene.InventoryService, ua1.PrincipalID, folder1ExistingName); - Assert.That(folder1PostCandidates.Count, Is.EqualTo(1)); - Assert.That(folder1PostCandidates[0].ID, Is.EqualTo(folder1.ID)); - - List folder2PostCandidates - = InventoryArchiveUtils.FindFolderByPath(scene.InventoryService, folder1PostCandidates[0], "b"); - Assert.That(folder2PostCandidates.Count, Is.EqualTo(1)); - } } } \ No newline at end of file diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/PathTests.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/PathTests.cs new file mode 100644 index 0000000000..34eeaf3672 --- /dev/null +++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/PathTests.cs @@ -0,0 +1,436 @@ +/* + * 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 NUnit.Framework.SyntaxHelpers; +using OpenMetaverse; +using OpenSim.Data; +using OpenSim.Framework; +using OpenSim.Framework.Serialization; +using OpenSim.Framework.Serialization.External; +using OpenSim.Framework.Communications; +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; +using OpenSim.Tests.Common.Mock; +using OpenSim.Tests.Common.Setup; + +namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests +{ + [TestFixture] + public class PathTests : InventoryArchiveTestCase + { + /// + /// Test saving an inventory path to a V0.1 OpenSim Inventory Archive + /// (subject to change since there is no fixed format yet). + /// + [Test] + public void TestSavePathToIarV0_1() + { + TestHelper.InMethod(); +// log4net.Config.XmlConfigurator.Configure(); + + InventoryArchiverModule archiverModule = new InventoryArchiverModule(); + + Scene scene = SceneSetupHelpers.SetupScene("Inventory"); + SceneSetupHelpers.SetupSceneModules(scene, archiverModule); + + // Create user + string userFirstName = "Jock"; + string userLastName = "Stirrup"; + string userPassword = "troll"; + UUID userId = UUID.Parse("00000000-0000-0000-0000-000000000020"); + UserProfileTestUtils.CreateUserWithInventory(scene, userFirstName, userLastName, userId, userPassword); + + // Create asset + SceneObjectGroup object1; + SceneObjectPart part1; + { + string partName = "My Little Dog Object"; + 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 = "My Little Dog"; + item1.AssetID = asset1.FullID; + item1.ID = item1Id; + InventoryFolderBase objsFolder + = InventoryArchiveUtils.FindFolderByPath(scene.InventoryService, userId, "Objects")[0]; + item1.Folder = objsFolder.ID; + scene.AddInventoryItem(item1); + + MemoryStream archiveWriteStream = new MemoryStream(); + archiverModule.OnInventoryArchiveSaved += SaveCompleted; + + // Test saving a particular path + mre.Reset(); + archiverModule.ArchiveInventory( + Guid.NewGuid(), userFirstName, userLastName, "Objects", 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}{2}", + ArchiveConstants.INVENTORY_PATH, + InventoryArchiveWriteRequest.CreateArchiveFolderName(objsFolder), + 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 that things work when the load path specified starts with a slash + /// + [Test] + public void TestLoadIarPathStartsWithSlash() + { + TestHelper.InMethod(); +// log4net.Config.XmlConfigurator.Configure(); + + SerialiserModule serialiserModule = new SerialiserModule(); + InventoryArchiverModule archiverModule = new InventoryArchiverModule(); + Scene scene = SceneSetupHelpers.SetupScene("inventory"); + SceneSetupHelpers.SetupSceneModules(scene, serialiserModule, archiverModule); + + UserProfileTestUtils.CreateUserWithInventory(scene, m_ua1, "password"); + archiverModule.DearchiveInventory(m_ua1.FirstName, m_ua1.LastName, "/Objects", "password", m_iarStream); + + InventoryItemBase foundItem1 + = InventoryArchiveUtils.FindItemByPath( + scene.InventoryService, m_ua1.PrincipalID, "/Objects/" + m_item1Name); + + Assert.That(foundItem1, Is.Not.Null, "Didn't find loaded item 1 in TestLoadIarFolderStartsWithSlash()"); + } + + [Test] + public void TestIarV0_1WithEscapedChars() + { + TestHelper.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 = SceneSetupHelpers.SetupScene("Inventory"); + SceneSetupHelpers.SetupSceneModules(scene, archiverModule); + + // Create user + string userFirstName = "Jock"; + string userLastName = "Stirrup"; + UUID userId = UUID.Parse("00000000-0000-0000-0000-000000000020"); + UserProfileTestUtils.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.FindFolderByPath(scene.InventoryService, userId, "Objects")[0]; + item1.Folder = objsFolder.ID; + scene.AddInventoryItem(item1); + + MemoryStream archiveWriteStream = new MemoryStream(); + archiverModule.OnInventoryArchiveSaved += SaveCompleted; + + mre.Reset(); + archiverModule.ArchiveInventory( + Guid.NewGuid(), userFirstName, userLastName, "Objects", userPassword, archiveWriteStream); + mre.WaitOne(60000, false); + + // LOAD ITEM + MemoryStream archiveReadStream = new MemoryStream(archiveWriteStream.ToArray()); + + archiverModule.DearchiveInventory(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() + { + TestHelper.InMethod(); +// log4net.Config.XmlConfigurator.Configure(); + + Scene scene = SceneSetupHelpers.SetupScene("inventory"); + UserAccount ua1 = UserProfileTestUtils.CreateUserWithInventory(scene); + + Dictionary foldersCreated = new Dictionary(); + HashSet nodesLoaded = new HashSet(); + + 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(scene, ua1, null, (Stream)null, false) + .ReplicateArchivePathToUserInventory( + iarPath1, scene.InventoryService.GetRootFolder(ua1.PrincipalID), + foldersCreated, nodesLoaded); + + List folder1Candidates + = InventoryArchiveUtils.FindFolderByPath(scene.InventoryService, ua1.PrincipalID, folder1Name); + Assert.That(folder1Candidates.Count, Is.EqualTo(1)); + + InventoryFolderBase folder1 = folder1Candidates[0]; + List folder2aCandidates + = InventoryArchiveUtils.FindFolderByPath(scene.InventoryService, folder1, folder2aName); + Assert.That(folder2aCandidates.Count, Is.EqualTo(1)); + } + + { + // Test replication of path2 + new InventoryArchiveReadRequest(scene, ua1, null, (Stream)null, false) + .ReplicateArchivePathToUserInventory( + iarPath2, scene.InventoryService.GetRootFolder(ua1.PrincipalID), + foldersCreated, nodesLoaded); + + List folder1Candidates + = InventoryArchiveUtils.FindFolderByPath(scene.InventoryService, ua1.PrincipalID, folder1Name); + Assert.That(folder1Candidates.Count, Is.EqualTo(1)); + + InventoryFolderBase folder1 = folder1Candidates[0]; + + List folder2aCandidates + = InventoryArchiveUtils.FindFolderByPath(scene.InventoryService, folder1, folder2aName); + Assert.That(folder2aCandidates.Count, Is.EqualTo(1)); + + List folder2bCandidates + = InventoryArchiveUtils.FindFolderByPath(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() + { + TestHelper.InMethod(); + //log4net.Config.XmlConfigurator.Configure(); + + Scene scene = SceneSetupHelpers.SetupScene("inventory"); + UserAccount ua1 = UserProfileTestUtils.CreateUserWithInventory(scene); + + string folder1ExistingName = "a"; + string folder2Name = "b"; + + InventoryFolderBase folder1 + = UserInventoryTestUtils.CreateInventoryFolder( + scene.InventoryService, ua1.PrincipalID, folder1ExistingName); + + string folder1ArchiveName = InventoryArchiveWriteRequest.CreateArchiveFolderName(folder1ExistingName, UUID.Random()); + string folder2ArchiveName = InventoryArchiveWriteRequest.CreateArchiveFolderName(folder2Name, UUID.Random()); + + string itemArchivePath = string.Join("", new string[] { folder1ArchiveName, folder2ArchiveName }); + + new InventoryArchiveReadRequest(scene, ua1, null, (Stream)null, false) + .ReplicateArchivePathToUserInventory( + itemArchivePath, scene.InventoryService.GetRootFolder(ua1.PrincipalID), + new Dictionary(), new HashSet()); + + List folder1PostCandidates + = InventoryArchiveUtils.FindFolderByPath(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.FindFolderByPath(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() + { + TestHelper.InMethod(); +// log4net.Config.XmlConfigurator.Configure(); + + Scene scene = SceneSetupHelpers.SetupScene("inventory"); + UserAccount ua1 = UserProfileTestUtils.CreateUserWithInventory(scene); + + string folder1ExistingName = "a"; + string folder2Name = "b"; + + InventoryFolderBase folder1 + = UserInventoryTestUtils.CreateInventoryFolder( + scene.InventoryService, ua1.PrincipalID, folder1ExistingName); + + string folder1ArchiveName = InventoryArchiveWriteRequest.CreateArchiveFolderName(folder1ExistingName, UUID.Random()); + string folder2ArchiveName = InventoryArchiveWriteRequest.CreateArchiveFolderName(folder2Name, UUID.Random()); + + string itemArchivePath = string.Join("", new string[] { folder1ArchiveName, folder2ArchiveName }); + + new InventoryArchiveReadRequest(scene, ua1, folder1ExistingName, (Stream)null, true) + .ReplicateArchivePathToUserInventory( + itemArchivePath, scene.InventoryService.GetRootFolder(ua1.PrincipalID), + new Dictionary(), new HashSet()); + + List folder1PostCandidates + = InventoryArchiveUtils.FindFolderByPath(scene.InventoryService, ua1.PrincipalID, folder1ExistingName); + Assert.That(folder1PostCandidates.Count, Is.EqualTo(1)); + Assert.That(folder1PostCandidates[0].ID, Is.EqualTo(folder1.ID)); + + List folder2PostCandidates + = InventoryArchiveUtils.FindFolderByPath(scene.InventoryService, folder1PostCandidates[0], "b"); + Assert.That(folder2PostCandidates.Count, Is.EqualTo(1)); + } + } +} \ No newline at end of file From 3e5b1a1de5931afc431fe55db4bd3b5e7f0637df Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Wed, 9 Mar 2011 20:53:35 +0000 Subject: [PATCH 51/81] Update MySql.Data.dll to version 6.3.6. This version fixes a bug so that MySqlCommand.CommandTimeout = 0 now correctly sets an infinite command timeout. This might help with failures on long-running migrations. The mysql.data.dll v2 is used from the mysql package (as opposed to v4). The v4 version (probably standing for NET 4.0) does not work under mono 2.6.7, which is still commonly used. --- bin/MySql.Data.dll | Bin 360448 -> 353792 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/bin/MySql.Data.dll b/bin/MySql.Data.dll index c28c618f236031e21d0cea03b22b6e8790107df4..992aa5621cc13880d2c16d9527816c58193d3a26 100644 GIT binary patch literal 353792 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Ξ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 ey literal 360448 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 I|AQ3xzpOfD3;+NC From 20aeace8d75fa5a1a3d0ba1d3d9ab6cdad2cf088 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Wed, 9 Mar 2011 22:03:12 +0000 Subject: [PATCH 52/81] Add log messages on teleport failure to better pin down the cause. --- .../Framework/EntityTransfer/EntityTransferModule.cs | 12 +++++++++--- .../Simulation/SimulationServiceConnector.cs | 6 +++--- OpenSim/Services/Interfaces/ISimulationService.cs | 7 +++++++ 3 files changed, 19 insertions(+), 6 deletions(-) diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs index 95c771e60f..c88be7ddb0 100644 --- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs +++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs @@ -399,6 +399,10 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer if (!UpdateAgent(reg, finalDestination, agent)) { // Region doesn't take it + m_log.WarnFormat( + "[ENTITY TRANSFER MODULE]: UpdateAgent failed on teleport of {0} to {1}. Returning avatar to source region.", + sp.Name, finalDestination.RegionName); + Fail(sp, finalDestination); return; } @@ -425,16 +429,18 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer // that the client contacted the destination before we send the attachments and close things here. if (!WaitForCallback(sp.UUID)) { - Fail(sp, finalDestination); + m_log.WarnFormat( + "[ENTITY TRANSFER MODULE]: Teleport of {0} to {1} failed due to no callback from destination region. Returning avatar to source region.", + sp.Name, finalDestination.RegionName); + + Fail(sp, finalDestination); return; } - // CrossAttachmentsIntoNewRegion is a synchronous call. We shouldn't need to wait after it CrossAttachmentsIntoNewRegion(finalDestination, sp, true); // Well, this is it. The agent is over there. - KillEntity(sp.Scene, sp.LocalId); // May need to logout or other cleanup diff --git a/OpenSim/Services/Connectors/Simulation/SimulationServiceConnector.cs b/OpenSim/Services/Connectors/Simulation/SimulationServiceConnector.cs index 463b2fbc7f..93b3ae62a9 100644 --- a/OpenSim/Services/Connectors/Simulation/SimulationServiceConnector.cs +++ b/OpenSim/Services/Connectors/Simulation/SimulationServiceConnector.cs @@ -79,9 +79,6 @@ namespace OpenSim.Services.Connectors.Simulation return "agent/"; } - /// - /// - /// public bool CreateAgent(GridRegion destination, AgentCircuitData aCircuit, uint flags, out string reason) { // m_log.DebugFormat("[REMOTE SIMULATION CONNECTOR]: CreateAgent start"); @@ -109,6 +106,9 @@ namespace OpenSim.Services.Connectors.Simulation if (result["Success"].AsBoolean()) return true; + m_log.WarnFormat( + "[REMOTE SIMULATION CONNECTOR]: Failed to create agent {0} {1} at remote simulator {1}", + aCircuit.firstname, aCircuit.lastname, destination.RegionName); reason = result["Message"] != null ? result["Message"].AsString() : "error"; return false; } diff --git a/OpenSim/Services/Interfaces/ISimulationService.cs b/OpenSim/Services/Interfaces/ISimulationService.cs index b7967578ce..55c9cc5717 100644 --- a/OpenSim/Services/Interfaces/ISimulationService.cs +++ b/OpenSim/Services/Interfaces/ISimulationService.cs @@ -40,6 +40,13 @@ namespace OpenSim.Services.Interfaces #region Agents + /// + /// Ask the simulator hosting the destination to create an agent on that region. + /// + /// + /// + /// + /// Reason message in the event of a failure. bool CreateAgent(GridRegion destination, AgentCircuitData aCircuit, uint flags, out string reason); /// From 9456bb77fbf794bb6fc2808e6cfd69c9bb1d1326 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Wed, 9 Mar 2011 23:25:24 +0000 Subject: [PATCH 53/81] Upgrade nunit.framework.dll to version 2.5.9. Fix up tests appropriately. This version removes the NUnit.Framework.SyntaxHelpers namespace, so any modules with their own tests will need to delete this using statement. --- OpenSim/Data/Tests/AssetTests.cs | 18 +----------------- OpenSim/Data/Tests/EstateTests.cs | 15 +-------------- OpenSim/Data/Tests/InventoryTests.cs | 12 ------------ .../Data/Tests/PropertyCompareConstraint.cs | 1 - OpenSim/Data/Tests/PropertyScrambler.cs | 2 -- OpenSim/Data/Tests/RegionTests.cs | 11 ----------- .../Framework/Servers/Tests/OSHttpTests.cs | 1 - OpenSim/Framework/Tests/AnimationTests.cs | 1 - .../Framework/Tests/PrimeNumberHelperTests.cs | 3 --- OpenSim/Framework/Tests/UtilTest.cs | 1 - .../Tests/InventoryArchiveTestCase.cs | 1 - .../Archiver/Tests/InventoryArchiverTests.cs | 1 - .../Inventory/Archiver/Tests/PathTests.cs | 1 - .../Grid/Tests/GridConnectorsTests.cs | 1 - .../Presence/Tests/PresenceConnectorsTests.cs | 1 - .../World/Archiver/Tests/ArchiverTests.cs | 1 - .../World/Media/Moap/Tests/MoapTests.cs | 1 - .../World/Serialiser/Tests/SerialiserTests.cs | 1 - .../Framework/Scenes/Tests/AttachmentTests.cs | 1 - .../Scenes/Tests/EntityManagerTests.cs | 1 - .../Framework/Scenes/Tests/SceneGraphTests.cs | 1 - .../Scenes/Tests/SceneObjectBasicTests.cs | 1 - .../Scenes/Tests/SceneObjectDeRezTests.cs | 1 - .../Scenes/Tests/SceneObjectLinkingTests.cs | 1 - .../Scenes/Tests/SceneObjectUserGroupTests.cs | 1 - .../Scenes/Tests/ScenePresenceTests.cs | 1 - .../Framework/Scenes/Tests/SceneTests.cs | 1 - .../Scenes/Tests/StandaloneTeleportTests.cs | 1 - .../Scenes/Tests/TaskInventoryTests.cs | 1 - .../Scenes/Tests/UuidGathererTests.cs | 1 - .../XmlRpcGroups/Tests/GroupsModuleTests.cs | 1 - .../Tests/Common/DoubleToleranceConstraint.cs | 1 + OpenSim/Tests/Common/TestHelper.cs | 3 +-- .../Tests/Common/VectorToleranceConstraint.cs | 1 + bin/nunit.framework.dll | Bin 77824 -> 135168 bytes 35 files changed, 5 insertions(+), 86 deletions(-) diff --git a/OpenSim/Data/Tests/AssetTests.cs b/OpenSim/Data/Tests/AssetTests.cs index 800b9bfba2..32f74a9b1e 100644 --- a/OpenSim/Data/Tests/AssetTests.cs +++ b/OpenSim/Data/Tests/AssetTests.cs @@ -35,10 +35,6 @@ using OpenSim.Framework; using System.Data.Common; using log4net; -#if !NUNIT25 -using NUnit.Framework.SyntaxHelpers; -#endif - // DBMS-specific: using MySql.Data.MySqlClient; using OpenSim.Data.MySQL; @@ -51,15 +47,6 @@ using OpenSim.Data.SQLite; namespace OpenSim.Data.Tests { - -#if NUNIT25 - - [TestFixture(typeof(MySqlConnection), typeof(MySQLAssetData), Description="Basic Asset store tests (MySQL)")] - [TestFixture(typeof(SqlConnection), typeof(MSSQLAssetData), Description = "Basic Asset store tests (MS SQL Server)")] - [TestFixture(typeof(SqliteConnection), typeof(SQLiteAssetData), Description = "Basic Asset store tests (SQLite)")] - -#else - [TestFixture(Description = "Asset store tests (SQLite)")] public class SQLiteAssetTests : AssetTests { @@ -75,9 +62,6 @@ namespace OpenSim.Data.Tests { } -#endif - - public class AssetTests : BasicDataServiceTest where TConn : DbConnection, new() where TAssetData : AssetDataBase, new() @@ -218,4 +202,4 @@ namespace OpenSim.Data.Tests Assert.That(a3a, Constraints.PropertyCompareConstraint(a3)); } } -} +} \ No newline at end of file diff --git a/OpenSim/Data/Tests/EstateTests.cs b/OpenSim/Data/Tests/EstateTests.cs index fbf8ba658e..3354e284da 100644 --- a/OpenSim/Data/Tests/EstateTests.cs +++ b/OpenSim/Data/Tests/EstateTests.cs @@ -28,7 +28,6 @@ using System; using log4net.Config; using NUnit.Framework; -using NUnit.Framework.SyntaxHelpers; using OpenMetaverse; using OpenSim.Framework; using OpenSim.Region.Framework.Interfaces; @@ -49,15 +48,6 @@ using OpenSim.Data.SQLite; namespace OpenSim.Data.Tests { - -#if NUNIT25 - - [TestFixture(typeof(MySqlConnection), typeof(MySQLEstateStore), Description = "Estate store tests (MySQL)")] - [TestFixture(typeof(SqlConnection), typeof(MSSQLEstateStore), Description = "Estate store tests (MS SQL Server)")] - [TestFixture(typeof(SqliteConnection), typeof(SQLiteEstateStore), Description = "Estate store tests (SQLite)")] - -#else - [TestFixture(Description = "Estate store tests (SQLite)")] public class SQLiteEstateTests : EstateTests { @@ -73,8 +63,6 @@ namespace OpenSim.Data.Tests { } -#endif - public class EstateTests : BasicDataServiceTest where TConn : DbConnection, new() where TEstateStore : class, IEstateDataStore, new() @@ -520,6 +508,5 @@ namespace OpenSim.Data.Tests } #endregion - } -} +} \ No newline at end of file diff --git a/OpenSim/Data/Tests/InventoryTests.cs b/OpenSim/Data/Tests/InventoryTests.cs index 9c2a2d6fd5..758f9704b7 100644 --- a/OpenSim/Data/Tests/InventoryTests.cs +++ b/OpenSim/Data/Tests/InventoryTests.cs @@ -25,12 +25,9 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -// #define NUNIT25 - using System; using log4net.Config; using NUnit.Framework; -using NUnit.Framework.SyntaxHelpers; using OpenMetaverse; using OpenSim.Framework; using log4net; @@ -49,14 +46,6 @@ using OpenSim.Data.SQLite; namespace OpenSim.Data.Tests { -#if NUNIT25 - - [TestFixture(typeof(SqliteConnection), typeof(SQLiteInventoryStore), Description = "Inventory store tests (SQLite)")] - [TestFixture(typeof(MySqlConnection), typeof(MySQLInventoryData), Description = "Inventory store tests (MySQL)")] - [TestFixture(typeof(SqlConnection), typeof(MSSQLInventoryData), Description = "Inventory store tests (MS SQL Server)")] - -#else - [TestFixture(Description = "Inventory store tests (SQLite)")] public class SQLiteInventoryTests : InventoryTests { @@ -71,7 +60,6 @@ namespace OpenSim.Data.Tests public class MSSQLInventoryTests : InventoryTests { } -#endif public class InventoryTests : BasicDataServiceTest where TConn : DbConnection, new() diff --git a/OpenSim/Data/Tests/PropertyCompareConstraint.cs b/OpenSim/Data/Tests/PropertyCompareConstraint.cs index f3d41df586..6c79bda9ec 100644 --- a/OpenSim/Data/Tests/PropertyCompareConstraint.cs +++ b/OpenSim/Data/Tests/PropertyCompareConstraint.cs @@ -34,7 +34,6 @@ using System.Linq.Expressions; using System.Reflection; using NUnit.Framework; using NUnit.Framework.Constraints; -using NUnit.Framework.SyntaxHelpers; using OpenMetaverse; using OpenSim.Framework; diff --git a/OpenSim/Data/Tests/PropertyScrambler.cs b/OpenSim/Data/Tests/PropertyScrambler.cs index 132294ad30..c5d40c2373 100644 --- a/OpenSim/Data/Tests/PropertyScrambler.cs +++ b/OpenSim/Data/Tests/PropertyScrambler.cs @@ -32,13 +32,11 @@ using System.Linq.Expressions; using System.Reflection; using System.Text; using NUnit.Framework; -using NUnit.Framework.SyntaxHelpers; using OpenMetaverse; using OpenSim.Framework; namespace OpenSim.Data.Tests { - //This is generic so that the lambda expressions will work right in IDEs. public class PropertyScrambler { diff --git a/OpenSim/Data/Tests/RegionTests.cs b/OpenSim/Data/Tests/RegionTests.cs index 23d498d6fa..9598716e0d 100644 --- a/OpenSim/Data/Tests/RegionTests.cs +++ b/OpenSim/Data/Tests/RegionTests.cs @@ -31,7 +31,6 @@ using System.Drawing; using System.Text; using log4net.Config; using NUnit.Framework; -using NUnit.Framework.SyntaxHelpers; using OpenMetaverse; using OpenSim.Framework; using OpenSim.Region.Framework.Interfaces; @@ -52,14 +51,6 @@ using OpenSim.Data.SQLite; namespace OpenSim.Data.Tests { -#if NUNIT25 - - [TestFixture(typeof(SqliteConnection), typeof(SQLiteRegionData), Description = "Region store tests (SQLite)")] - [TestFixture(typeof(MySqlConnection), typeof(MySqlRegionData), Description = "Region store tests (MySQL)")] - [TestFixture(typeof(SqlConnection), typeof(MSSQLRegionData), Description = "Region store tests (MS SQL Server)")] - -#else - [TestFixture(Description = "Region store tests (SQLite)")] public class SQLiteRegionTests : RegionTests { @@ -75,8 +66,6 @@ namespace OpenSim.Data.Tests { } -#endif - public class RegionTests : BasicDataServiceTest where TConn : DbConnection, new() where TRegStore : class, ISimulationDataStore, new() diff --git a/OpenSim/Framework/Servers/Tests/OSHttpTests.cs b/OpenSim/Framework/Servers/Tests/OSHttpTests.cs index e62407adfa..dc4eb8f4bf 100644 --- a/OpenSim/Framework/Servers/Tests/OSHttpTests.cs +++ b/OpenSim/Framework/Servers/Tests/OSHttpTests.cs @@ -34,7 +34,6 @@ using System.Text; using HttpServer; using HttpServer.FormDecoders; using NUnit.Framework; -using NUnit.Framework.SyntaxHelpers; using OpenSim.Framework.Servers.HttpServer; namespace OpenSim.Framework.Servers.Tests diff --git a/OpenSim/Framework/Tests/AnimationTests.cs b/OpenSim/Framework/Tests/AnimationTests.cs index 719ddce306..9aa95afa43 100644 --- a/OpenSim/Framework/Tests/AnimationTests.cs +++ b/OpenSim/Framework/Tests/AnimationTests.cs @@ -28,7 +28,6 @@ using System; using System.Reflection; using NUnit.Framework; -using NUnit.Framework.SyntaxHelpers; using OpenMetaverse; using OpenMetaverse.StructuredData; using OpenSim.Framework; diff --git a/OpenSim/Framework/Tests/PrimeNumberHelperTests.cs b/OpenSim/Framework/Tests/PrimeNumberHelperTests.cs index d741f9116d..36bc6e75f9 100644 --- a/OpenSim/Framework/Tests/PrimeNumberHelperTests.cs +++ b/OpenSim/Framework/Tests/PrimeNumberHelperTests.cs @@ -28,7 +28,6 @@ using System; using System.Reflection; using NUnit.Framework; -using NUnit.Framework.SyntaxHelpers; using OpenMetaverse; using OpenMetaverse.StructuredData; using OpenSim.Framework; @@ -38,8 +37,6 @@ namespace OpenSim.Framework.Tests [TestFixture] public class PrimeNumberHelperTests { - - [Test] public void TestGetPrime() { diff --git a/OpenSim/Framework/Tests/UtilTest.cs b/OpenSim/Framework/Tests/UtilTest.cs index 89f5c0cba9..5eac411944 100644 --- a/OpenSim/Framework/Tests/UtilTest.cs +++ b/OpenSim/Framework/Tests/UtilTest.cs @@ -27,7 +27,6 @@ using System; using NUnit.Framework; -using NUnit.Framework.SyntaxHelpers; using OpenMetaverse; using OpenSim.Tests.Common; diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveTestCase.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveTestCase.cs index 023c452a23..3ec5e53114 100644 --- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveTestCase.cs +++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveTestCase.cs @@ -31,7 +31,6 @@ using System.IO; using System.Reflection; using System.Threading; using NUnit.Framework; -using NUnit.Framework.SyntaxHelpers; using OpenMetaverse; using OpenSim.Data; using OpenSim.Framework; diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs index edbbd81106..67d71596bf 100644 --- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs +++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs @@ -31,7 +31,6 @@ using System.IO; using System.Reflection; using System.Threading; using NUnit.Framework; -using NUnit.Framework.SyntaxHelpers; using OpenMetaverse; using OpenSim.Data; using OpenSim.Framework; diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/PathTests.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/PathTests.cs index 34eeaf3672..4b7de0ca47 100644 --- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/PathTests.cs +++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/PathTests.cs @@ -31,7 +31,6 @@ using System.IO; using System.Reflection; using System.Threading; using NUnit.Framework; -using NUnit.Framework.SyntaxHelpers; using OpenMetaverse; using OpenSim.Data; using OpenSim.Framework; diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/Tests/GridConnectorsTests.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/Tests/GridConnectorsTests.cs index e54ee02f43..18db9fa0e3 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/Tests/GridConnectorsTests.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/Tests/GridConnectorsTests.cs @@ -32,7 +32,6 @@ using System.Reflection; using System.Threading; using log4net.Config; using NUnit.Framework; -using NUnit.Framework.SyntaxHelpers; using OpenMetaverse; using OpenSim.Framework; using Nini.Config; diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Presence/Tests/PresenceConnectorsTests.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Presence/Tests/PresenceConnectorsTests.cs index ef910f4c26..e471f756d0 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Presence/Tests/PresenceConnectorsTests.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Presence/Tests/PresenceConnectorsTests.cs @@ -32,7 +32,6 @@ using System.Reflection; using System.Threading; using log4net.Config; using NUnit.Framework; -using NUnit.Framework.SyntaxHelpers; using OpenMetaverse; using OpenSim.Framework; using Nini.Config; diff --git a/OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs b/OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs index 04b6e3d3f9..e2760a2065 100644 --- a/OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs +++ b/OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs @@ -32,7 +32,6 @@ using System.Reflection; using System.Threading; using log4net.Config; using NUnit.Framework; -using NUnit.Framework.SyntaxHelpers; using OpenMetaverse; using OpenMetaverse.Assets; using OpenSim.Framework; diff --git a/OpenSim/Region/CoreModules/World/Media/Moap/Tests/MoapTests.cs b/OpenSim/Region/CoreModules/World/Media/Moap/Tests/MoapTests.cs index 7a68e55c7e..5b85830f5f 100644 --- a/OpenSim/Region/CoreModules/World/Media/Moap/Tests/MoapTests.cs +++ b/OpenSim/Region/CoreModules/World/Media/Moap/Tests/MoapTests.cs @@ -32,7 +32,6 @@ using System.Reflection; using System.Threading; using log4net.Config; using NUnit.Framework; -using NUnit.Framework.SyntaxHelpers; using OpenMetaverse; using OpenMetaverse.Assets; using OpenSim.Framework; diff --git a/OpenSim/Region/CoreModules/World/Serialiser/Tests/SerialiserTests.cs b/OpenSim/Region/CoreModules/World/Serialiser/Tests/SerialiserTests.cs index f10e848f68..dafaa0c107 100644 --- a/OpenSim/Region/CoreModules/World/Serialiser/Tests/SerialiserTests.cs +++ b/OpenSim/Region/CoreModules/World/Serialiser/Tests/SerialiserTests.cs @@ -30,7 +30,6 @@ using System.IO; using System.Xml; using log4net.Config; using NUnit.Framework; -using NUnit.Framework.SyntaxHelpers; using OpenMetaverse; using OpenSim.Framework; using OpenSim.Region.Framework.Scenes; diff --git a/OpenSim/Region/Framework/Scenes/Tests/AttachmentTests.cs b/OpenSim/Region/Framework/Scenes/Tests/AttachmentTests.cs index af4464081b..855b5894b6 100644 --- a/OpenSim/Region/Framework/Scenes/Tests/AttachmentTests.cs +++ b/OpenSim/Region/Framework/Scenes/Tests/AttachmentTests.cs @@ -34,7 +34,6 @@ using System.Timers; using Timer=System.Timers.Timer; using Nini.Config; using NUnit.Framework; -using NUnit.Framework.SyntaxHelpers; using OpenMetaverse; using OpenSim.Framework; using OpenSim.Framework.Communications; diff --git a/OpenSim/Region/Framework/Scenes/Tests/EntityManagerTests.cs b/OpenSim/Region/Framework/Scenes/Tests/EntityManagerTests.cs index b3c3e22af6..667b74ea95 100644 --- a/OpenSim/Region/Framework/Scenes/Tests/EntityManagerTests.cs +++ b/OpenSim/Region/Framework/Scenes/Tests/EntityManagerTests.cs @@ -32,7 +32,6 @@ using System.Text; using System.Collections.Generic; using Nini.Config; using NUnit.Framework; -using NUnit.Framework.SyntaxHelpers; using OpenMetaverse; using OpenSim.Framework; using OpenSim.Framework.Communications; diff --git a/OpenSim/Region/Framework/Scenes/Tests/SceneGraphTests.cs b/OpenSim/Region/Framework/Scenes/Tests/SceneGraphTests.cs index 9244bc3461..ca635d708d 100644 --- a/OpenSim/Region/Framework/Scenes/Tests/SceneGraphTests.cs +++ b/OpenSim/Region/Framework/Scenes/Tests/SceneGraphTests.cs @@ -28,7 +28,6 @@ using System; using System.Reflection; using NUnit.Framework; -using NUnit.Framework.SyntaxHelpers; using OpenMetaverse; using OpenSim.Framework; using OpenSim.Framework.Communications; diff --git a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectBasicTests.cs b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectBasicTests.cs index 4969b09149..a6a95ef885 100644 --- a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectBasicTests.cs +++ b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectBasicTests.cs @@ -28,7 +28,6 @@ using System; using System.Reflection; using NUnit.Framework; -using NUnit.Framework.SyntaxHelpers; using OpenMetaverse; using OpenSim.Framework; using OpenSim.Framework.Communications; diff --git a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectDeRezTests.cs b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectDeRezTests.cs index 39116b6615..0d260266ef 100644 --- a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectDeRezTests.cs +++ b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectDeRezTests.cs @@ -30,7 +30,6 @@ using System.Collections.Generic; using System.Reflection; using Nini.Config; using NUnit.Framework; -using NUnit.Framework.SyntaxHelpers; using OpenMetaverse; using OpenSim.Framework; using OpenSim.Framework.Communications; diff --git a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectLinkingTests.cs b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectLinkingTests.cs index b84298f2fa..bdfcd1dc29 100644 --- a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectLinkingTests.cs +++ b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectLinkingTests.cs @@ -29,7 +29,6 @@ using System; using System.Collections.Generic; using System.Reflection; using NUnit.Framework; -using NUnit.Framework.SyntaxHelpers; using OpenMetaverse; using OpenSim.Framework; using OpenSim.Framework.Communications; diff --git a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectUserGroupTests.cs b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectUserGroupTests.cs index c78038f7a7..8876a435b6 100644 --- a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectUserGroupTests.cs +++ b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectUserGroupTests.cs @@ -30,7 +30,6 @@ using System.Collections.Generic; using System.Reflection; using Nini.Config; using NUnit.Framework; -using NUnit.Framework.SyntaxHelpers; using OpenMetaverse; using OpenSim.Framework; using OpenSim.Framework.Communications; diff --git a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceTests.cs b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceTests.cs index fd2d6fab2d..efb757fa6c 100644 --- a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceTests.cs +++ b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceTests.cs @@ -34,7 +34,6 @@ using System.Timers; using Timer=System.Timers.Timer; using Nini.Config; using NUnit.Framework; -using NUnit.Framework.SyntaxHelpers; using OpenMetaverse; using OpenSim.Framework; using OpenSim.Framework.Communications; diff --git a/OpenSim/Region/Framework/Scenes/Tests/SceneTests.cs b/OpenSim/Region/Framework/Scenes/Tests/SceneTests.cs index 9aba8a8bfc..abcce66e23 100644 --- a/OpenSim/Region/Framework/Scenes/Tests/SceneTests.cs +++ b/OpenSim/Region/Framework/Scenes/Tests/SceneTests.cs @@ -34,7 +34,6 @@ using System.Timers; using Timer=System.Timers.Timer; using Nini.Config; using NUnit.Framework; -using NUnit.Framework.SyntaxHelpers; using OpenMetaverse; using OpenSim.Framework; using OpenSim.Framework.Communications; diff --git a/OpenSim/Region/Framework/Scenes/Tests/StandaloneTeleportTests.cs b/OpenSim/Region/Framework/Scenes/Tests/StandaloneTeleportTests.cs index cafe48afdd..8588f7f599 100644 --- a/OpenSim/Region/Framework/Scenes/Tests/StandaloneTeleportTests.cs +++ b/OpenSim/Region/Framework/Scenes/Tests/StandaloneTeleportTests.cs @@ -29,7 +29,6 @@ using System; using System.Reflection; using Nini.Config; using NUnit.Framework; -using NUnit.Framework.SyntaxHelpers; using OpenMetaverse; using OpenSim.Framework; using OpenSim.Framework.Communications; diff --git a/OpenSim/Region/Framework/Scenes/Tests/TaskInventoryTests.cs b/OpenSim/Region/Framework/Scenes/Tests/TaskInventoryTests.cs index fe59d4f031..8138bcc19a 100644 --- a/OpenSim/Region/Framework/Scenes/Tests/TaskInventoryTests.cs +++ b/OpenSim/Region/Framework/Scenes/Tests/TaskInventoryTests.cs @@ -34,7 +34,6 @@ using System.Timers; using Timer=System.Timers.Timer; using Nini.Config; using NUnit.Framework; -using NUnit.Framework.SyntaxHelpers; using OpenMetaverse; using OpenMetaverse.Assets; using OpenSim.Framework; diff --git a/OpenSim/Region/Framework/Scenes/Tests/UuidGathererTests.cs b/OpenSim/Region/Framework/Scenes/Tests/UuidGathererTests.cs index 5e6124b4f9..6b70865533 100644 --- a/OpenSim/Region/Framework/Scenes/Tests/UuidGathererTests.cs +++ b/OpenSim/Region/Framework/Scenes/Tests/UuidGathererTests.cs @@ -28,7 +28,6 @@ using System.Collections.Generic; using System.Text; using NUnit.Framework; -using NUnit.Framework.SyntaxHelpers; using OpenMetaverse; using OpenSim.Framework; using OpenSim.Region.Framework.Scenes; diff --git a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/Tests/GroupsModuleTests.cs b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/Tests/GroupsModuleTests.cs index bc55b04743..6de97b7269 100644 --- a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/Tests/GroupsModuleTests.cs +++ b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/Tests/GroupsModuleTests.cs @@ -29,7 +29,6 @@ using System; using System.Reflection; using Nini.Config; using NUnit.Framework; -using NUnit.Framework.SyntaxHelpers; using OpenMetaverse; using OpenSim.Framework; using OpenSim.Framework.Communications; diff --git a/OpenSim/Tests/Common/DoubleToleranceConstraint.cs b/OpenSim/Tests/Common/DoubleToleranceConstraint.cs index c397a6230b..b2f20571ae 100644 --- a/OpenSim/Tests/Common/DoubleToleranceConstraint.cs +++ b/OpenSim/Tests/Common/DoubleToleranceConstraint.cs @@ -27,6 +27,7 @@ using System; using NUnit.Framework; +using NUnit.Framework.Constraints; namespace OpenSim.Tests.Common { diff --git a/OpenSim/Tests/Common/TestHelper.cs b/OpenSim/Tests/Common/TestHelper.cs index 9d530635f3..1722e59864 100644 --- a/OpenSim/Tests/Common/TestHelper.cs +++ b/OpenSim/Tests/Common/TestHelper.cs @@ -27,11 +27,10 @@ using System; using System.Diagnostics; +using NUnit.Framework; namespace OpenSim.Tests.Common { - public delegate void TestDelegate(); - public class TestHelper { public static bool AssertThisDelegateCausesArgumentException(TestDelegate d) diff --git a/OpenSim/Tests/Common/VectorToleranceConstraint.cs b/OpenSim/Tests/Common/VectorToleranceConstraint.cs index 118cc707f8..2fa20edec9 100644 --- a/OpenSim/Tests/Common/VectorToleranceConstraint.cs +++ b/OpenSim/Tests/Common/VectorToleranceConstraint.cs @@ -28,6 +28,7 @@ using System; using OpenMetaverse; using NUnit.Framework; +using NUnit.Framework.Constraints; namespace OpenSim.Tests.Common { diff --git a/bin/nunit.framework.dll b/bin/nunit.framework.dll index d68d9f20c5ab7154fa4cf17b0f720c5c5b48eade..875e0984208d52e5c96a409b52996547198af17a 100644 GIT binary patch literal 135168 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 literal 77824 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 YFyg?710xQMI56VChyx=IyxSc3AOBQO>Hq)$ From 07f68c83181dffcdc1a064b10ef805b1d4605602 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Wed, 9 Mar 2011 23:54:52 +0000 Subject: [PATCH 54/81] minor: change the order of some default iar setup in test case --- .../Archiver/Tests/InventoryArchiveTestCase.cs | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveTestCase.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveTestCase.cs index 3ec5e53114..5ec7bc4e52 100644 --- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveTestCase.cs +++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveTestCase.cs @@ -93,8 +93,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests Scene scene = SceneSetupHelpers.SetupScene("Inventory"); UserProfileTestUtils.CreateUserWithInventory(scene, m_ua2, "hampshire"); - - string archiveItemName = InventoryArchiveWriteRequest.CreateArchiveItemName(m_item1Name, UUID.Random()); MemoryStream archiveWriteStream = new MemoryStream(); TarArchiveWriter tar = new TarArchiveWriter(archiveWriteStream); @@ -106,10 +104,14 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests item1.CreatorIdAsUuid = m_ua2.PrincipalID; item1.Owner = UUID.Zero; - string item1FileName - = string.Format("{0}{1}", ArchiveConstants.INVENTORY_PATH, archiveItemName); - tar.WriteFile(item1FileName, UserInventoryItemSerializer.Serialize(item1, new Dictionary(), scene.UserAccountService)); + string archiveItem1Name = InventoryArchiveWriteRequest.CreateArchiveItemName(m_item1Name, UUID.Random()); + string archiveItem1Path = string.Format("{0}{1}", ArchiveConstants.INVENTORY_PATH, archiveItem1Name); + tar.WriteFile( + archiveItem1Path, + UserInventoryItemSerializer.Serialize( + item1, new Dictionary(), scene.UserAccountService)); tar.Close(); + m_iarStreamBytes = archiveWriteStream.ToArray(); } From fa1996155e26847a508739e512513cf1f52b687e Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Wed, 9 Mar 2011 23:58:26 +0000 Subject: [PATCH 55/81] Make the item created in the default test iar an object rather than a script --- .../Tests/InventoryArchiveTestCase.cs | 29 +++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveTestCase.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveTestCase.cs index 5ec7bc4e52..ca5bc53561 100644 --- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveTestCase.cs +++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveTestCase.cs @@ -73,7 +73,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests PrincipalID = UUID.Parse("00000000-0000-0000-0000-000000000666"), FirstName = "Lord", LastName = "Lucan" }; - protected string m_item1Name = "b.lsl"; + protected string m_item1Name = "Ray Gun Item"; [SetUp] public void SetUp() @@ -96,10 +96,35 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests MemoryStream archiveWriteStream = new MemoryStream(); TarArchiveWriter tar = new TarArchiveWriter(archiveWriteStream); + + // Create asset + SceneObjectGroup object1; + SceneObjectPart part1; + { + string partName = "Ray Gun Object"; + 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 InventoryItemBase item1 = new InventoryItemBase(); item1.Name = m_item1Name; - item1.AssetID = UUID.Random(); + item1.AssetID = asset1.FullID; item1.GroupID = UUID.Random(); item1.CreatorIdAsUuid = m_ua2.PrincipalID; item1.Owner = UUID.Zero; From 549b0ea17ced61af995984bf8c155477bf9d624b Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Thu, 10 Mar 2011 00:06:32 +0000 Subject: [PATCH 56/81] Split the inventory path testing parts of TestLoadIarV0_1ExistingUsers() into a new test TestLoadIarToInventoryPaths() --- .../Archiver/Tests/InventoryArchiverTests.cs | 22 --------- .../Inventory/Archiver/Tests/PathTests.cs | 47 ++++++++++++++++++- 2 files changed, 46 insertions(+), 23 deletions(-) diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs index 67d71596bf..5f75c4aab6 100644 --- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs +++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs @@ -172,8 +172,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests /// Test loading a V0.1 OpenSim Inventory Archive (subject to change since there is no fixed format yet) where /// an account exists with the creator name. /// - /// - /// This test also does some deeper probing of loading into nested inventory structures [Test] public void TestLoadIarV0_1ExistingUsers() { @@ -194,8 +192,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests archiverModule.DearchiveInventory(m_ua1.FirstName, m_ua1.LastName, "/", "meowfood", m_iarStream); InventoryItemBase foundItem1 = InventoryArchiveUtils.FindItemByPath(scene.InventoryService, m_ua1.PrincipalID, m_item1Name); - - Assert.That(foundItem1, Is.Not.Null, "Didn't find loaded item 1"); // We have to disable this check since loaded items that did find users via OSPA resolution are now only storing the // UUID, not the OSPA itself. @@ -211,24 +207,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests "Loaded item uuid creator doesn't match original"); Assert.That(foundItem1.Owner, Is.EqualTo(m_ua1.PrincipalID), "Loaded item owner doesn't match inventory reciever"); - - // Now try loading to a root child folder - UserInventoryTestUtils.CreateInventoryFolder(scene.InventoryService, m_ua1.PrincipalID, "xA"); - MemoryStream archiveReadStream = new MemoryStream(m_iarStream.ToArray()); - archiverModule.DearchiveInventory(m_ua1.FirstName, m_ua1.LastName, "xA", "meowfood", archiveReadStream); - - InventoryItemBase foundItem2 - = InventoryArchiveUtils.FindItemByPath(scene.InventoryService, m_ua1.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 - UserInventoryTestUtils.CreateInventoryFolder(scene.InventoryService, m_ua1.PrincipalID, "xB/xC"); - archiveReadStream = new MemoryStream(archiveReadStream.ToArray()); - archiverModule.DearchiveInventory(m_ua1.FirstName, m_ua1.LastName, "xB/xC", "meowfood", archiveReadStream); - - InventoryItemBase foundItem3 - = InventoryArchiveUtils.FindItemByPath(scene.InventoryService, m_ua1.PrincipalID, "xB/xC/" + m_item1Name); - Assert.That(foundItem3, Is.Not.Null, "Didn't find loaded item 3"); } /// diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/PathTests.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/PathTests.cs index 4b7de0ca47..1220a7090a 100644 --- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/PathTests.cs +++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/PathTests.cs @@ -169,6 +169,51 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests // TODO: Test presence of more files and contents of files. } + /// + /// Test loading an IAR to various different inventory paths. + /// + [Test] + public void TestLoadIarToInventoryPaths() + { + TestHelper.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 = SceneSetupHelpers.SetupScene("inventory"); + + SceneSetupHelpers.SetupSceneModules(scene, serialiserModule, archiverModule); + + UserProfileTestUtils.CreateUserWithInventory(scene, m_ua1, "meowfood"); + UserProfileTestUtils.CreateUserWithInventory(scene, m_ua2, "hampshire"); + + archiverModule.DearchiveInventory(m_ua1.FirstName, m_ua1.LastName, "/", "meowfood", m_iarStream); + InventoryItemBase foundItem1 + = InventoryArchiveUtils.FindItemByPath(scene.InventoryService, m_ua1.PrincipalID, m_item1Name); + + Assert.That(foundItem1, Is.Not.Null, "Didn't find loaded item 1"); + + // Now try loading to a root child folder + UserInventoryTestUtils.CreateInventoryFolder(scene.InventoryService, m_ua1.PrincipalID, "xA"); + MemoryStream archiveReadStream = new MemoryStream(m_iarStream.ToArray()); + archiverModule.DearchiveInventory(m_ua1.FirstName, m_ua1.LastName, "xA", "meowfood", archiveReadStream); + + InventoryItemBase foundItem2 + = InventoryArchiveUtils.FindItemByPath(scene.InventoryService, m_ua1.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 + UserInventoryTestUtils.CreateInventoryFolder(scene.InventoryService, m_ua1.PrincipalID, "xB/xC"); + archiveReadStream = new MemoryStream(archiveReadStream.ToArray()); + archiverModule.DearchiveInventory(m_ua1.FirstName, m_ua1.LastName, "xB/xC", "meowfood", archiveReadStream); + + InventoryItemBase foundItem3 + = InventoryArchiveUtils.FindItemByPath(scene.InventoryService, m_ua1.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 /// @@ -194,7 +239,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests } [Test] - public void TestIarV0_1WithEscapedChars() + public void TestLoadIarPathWithEscapedChars() { TestHelper.InMethod(); // log4net.Config.XmlConfigurator.Configure(); From 4dd60b7dce4421bec89e9964a3fb51a1658945ad Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Thu, 10 Mar 2011 00:19:17 +0000 Subject: [PATCH 57/81] Change existing users load iar test so that it fulfills it's original intention (i.e. OSPA resolution, which is still active). Will need to write a separate test for the simplest case where creator accounts with appropriate uuids exist on iar load. --- .../Tests/InventoryArchiveTestCase.cs | 7 ++++++- .../Archiver/Tests/InventoryArchiverTests.cs | 19 +++++++++---------- 2 files changed, 15 insertions(+), 11 deletions(-) diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveTestCase.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveTestCase.cs index ca5bc53561..dcafc49ee4 100644 --- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveTestCase.cs +++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveTestCase.cs @@ -72,7 +72,12 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests = new UserAccount { PrincipalID = UUID.Parse("00000000-0000-0000-0000-000000000666"), FirstName = "Lord", - LastName = "Lucan" }; + LastName = "Lucan" }; + protected UserAccount m_ua3 + = new UserAccount { + PrincipalID = UUID.Parse("00000000-0000-0000-0000-000000000777"), + FirstName = "Lord", + LastName = "Lucan" }; protected string m_item1Name = "Ray Gun Item"; [SetUp] diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs index 5f75c4aab6..b52014b12a 100644 --- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs +++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs @@ -170,10 +170,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests /// /// Test loading a V0.1 OpenSim Inventory Archive (subject to change since there is no fixed format yet) where - /// an account exists with the creator name. + /// an account exists with the same name as the creator, though not the same id. /// [Test] - public void TestLoadIarV0_1ExistingUsers() + public void TestLoadIarV0_1SameNameCreator() { TestHelper.InMethod(); // log4net.Config.XmlConfigurator.Configure(); @@ -187,7 +187,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests SceneSetupHelpers.SetupSceneModules(scene, serialiserModule, archiverModule); UserProfileTestUtils.CreateUserWithInventory(scene, m_ua1, "meowfood"); - UserProfileTestUtils.CreateUserWithInventory(scene, m_ua2, "hampshire"); + UserProfileTestUtils.CreateUserWithInventory(scene, m_ua3, "hampshire"); archiverModule.DearchiveInventory(m_ua1.FirstName, m_ua1.LastName, "/", "meowfood", m_iarStream); InventoryItemBase foundItem1 @@ -198,12 +198,11 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests // Assert.That( // foundItem1.CreatorId, Is.EqualTo(item1.CreatorId), // "Loaded item non-uuid creator doesn't match original"); -// Assert.That( -// foundItem1.CreatorId, Is.EqualTo(m_ua2.PrincipalID.ToString()), -// "Loaded item non-uuid creator doesn't match original"); - Assert.That( - foundItem1.CreatorIdAsUuid, Is.EqualTo(m_ua2.PrincipalID), + foundItem1.CreatorId, Is.EqualTo(m_ua3.PrincipalID.ToString()), + "Loaded item non-uuid creator doesn't match original"); + Assert.That( + foundItem1.CreatorIdAsUuid, Is.EqualTo(m_ua3.PrincipalID), "Loaded item uuid creator doesn't match original"); Assert.That(foundItem1.Owner, Is.EqualTo(m_ua1.PrincipalID), "Loaded item owner doesn't match inventory reciever"); @@ -211,10 +210,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests /// /// Test loading a V0.1 OpenSim Inventory Archive (subject to change since there is no fixed format yet) where - /// embedded creators do not exist in the system + /// the creator or an account with the creator's name does not exist within the system. /// [Test] - public void TestLoadIarV0_1AbsentUsers() + public void TestLoadIarV0_1AbsentCreator() { TestHelper.InMethod(); // log4net.Config.XmlConfigurator.Configure(); From a151afebe3348ad05db3d78074e3eaf99dc06afe Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Thu, 10 Mar 2011 19:40:19 +0000 Subject: [PATCH 58/81] When setting up default iar for testing, use iar archiving code rather than constructing the tar manually --- .../Tests/InventoryArchiveTestCase.cs | 20 +++++++++---------- .../Archiver/Tests/InventoryArchiverTests.cs | 6 ++++++ .../Inventory/Archiver/Tests/PathTests.cs | 4 +--- 3 files changed, 17 insertions(+), 13 deletions(-) diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveTestCase.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveTestCase.cs index dcafc49ee4..d77bff2741 100644 --- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveTestCase.cs +++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveTestCase.cs @@ -96,11 +96,13 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests { // log4net.Config.XmlConfigurator.Configure(); + InventoryArchiverModule archiverModule = new InventoryArchiverModule(); Scene scene = SceneSetupHelpers.SetupScene("Inventory"); + SceneSetupHelpers.SetupSceneModules(scene, archiverModule); + UserProfileTestUtils.CreateUserWithInventory(scene, m_ua2, "hampshire"); MemoryStream archiveWriteStream = new MemoryStream(); - TarArchiveWriter tar = new TarArchiveWriter(archiveWriteStream); // Create asset SceneObjectGroup object1; @@ -129,18 +131,16 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests // Create 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.CreatorIdAsUuid = m_ua2.PrincipalID; - item1.Owner = UUID.Zero; - - string archiveItem1Name = InventoryArchiveWriteRequest.CreateArchiveItemName(m_item1Name, UUID.Random()); - string archiveItem1Path = string.Format("{0}{1}", ArchiveConstants.INVENTORY_PATH, archiveItem1Name); - tar.WriteFile( - archiveItem1Path, - UserInventoryItemSerializer.Serialize( - item1, new Dictionary(), scene.UserAccountService)); - tar.Close(); + item1.Owner = m_ua2.PrincipalID; + item1.Folder = scene.InventoryService.GetRootFolder(m_ua2.PrincipalID).ID; + scene.AddInventoryItem(item1); + + archiverModule.ArchiveInventory( + Guid.NewGuid(), m_ua2.FirstName, m_ua2.LastName, m_item1Name, "hampshire", archiveWriteStream); m_iarStreamBytes = archiveWriteStream.ToArray(); } diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs index b52014b12a..3eb4104e73 100644 --- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs +++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs @@ -206,6 +206,12 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests "Loaded item uuid creator doesn't match original"); Assert.That(foundItem1.Owner, Is.EqualTo(m_ua1.PrincipalID), "Loaded item owner doesn't match inventory reciever"); + +// AssetBase asset1 = 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_ua3.PrincipalID.ToString())); } /// diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/PathTests.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/PathTests.cs index 1220a7090a..66c19f4a34 100644 --- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/PathTests.cs +++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/PathTests.cs @@ -84,9 +84,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests Quaternion rotationOffset = new Quaternion(20, 30, 40, 50); Vector3 offsetPosition = new Vector3(5, 10, 15); - part1 - = new SceneObjectPart( - ownerId, shape, groupPosition, rotationOffset, offsetPosition); + part1 = new SceneObjectPart(ownerId, shape, groupPosition, rotationOffset, offsetPosition); part1.Name = partName; object1 = new SceneObjectGroup(part1); From db2ad62c9b52baaa7e2b1d8fed481cbd336f4f1b Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Thu, 10 Mar 2011 19:52:19 +0000 Subject: [PATCH 59/81] in AssetHelpers.CreateAsset(), create objects using the 'original' xml format rather than 'xml2' --- OpenSim/Tests/Common/Setup/AssetHelpers.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OpenSim/Tests/Common/Setup/AssetHelpers.cs b/OpenSim/Tests/Common/Setup/AssetHelpers.cs index 8647cfed51..ff4423f7ab 100644 --- a/OpenSim/Tests/Common/Setup/AssetHelpers.cs +++ b/OpenSim/Tests/Common/Setup/AssetHelpers.cs @@ -68,7 +68,7 @@ namespace OpenSim.Tests.Common return CreateAsset( assetUuid, AssetType.Object, - Encoding.ASCII.GetBytes(SceneObjectSerializer.ToXml2Format(sog)), + Encoding.ASCII.GetBytes(SceneObjectSerializer.ToOriginalXmlFormat(sog)), sog.OwnerID); } From b821f748ac591258f015ecf3ba8011d5561c488d Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Thu, 10 Mar 2011 21:56:15 +0000 Subject: [PATCH 60/81] For objects loaded from an IAR, make sure the CreatorID points towards the OSP resolved ID if newer CreationData is not present. This should resolve issues where the creator for rezzed objects was being shown as "Unknown user" where previous behaviour was to show the OSP resolved account. This is being done by parsing the serialized objects and updating the CreatorID if no CreationData exists. This operation might be expensive for sculpties where the sculpt texture is inlined with the object data. Will just have to see. This relies on the IAR streaming inventory data before asset data (as is currently the case). Will need to introduce more stringent checks for file order on loading (much like JAR zips must start with the manifest file). This is for IAR loading only. Tests updated to check this behaviour. --- .../Archiver/InventoryArchiveReadRequest.cs | 40 +++++++++++++++++-- .../Archiver/Tests/InventoryArchiverTests.cs | 10 ++--- .../Scenes/SceneObjectPartInventory.cs | 8 +++- 3 files changed, 48 insertions(+), 10 deletions(-) diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs index 7849d88320..d0510d3da1 100644 --- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs +++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs @@ -41,6 +41,7 @@ using OpenSim.Framework.Serialization; using OpenSim.Framework.Serialization.External; using OpenSim.Region.CoreModules.World.Archiver; using OpenSim.Region.Framework.Scenes; +using OpenSim.Region.Framework.Scenes.Serialization; using OpenSim.Region.Framework.Interfaces; using OpenSim.Services.Interfaces; @@ -75,6 +76,12 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver /// The stream from which the inventory archive will be loaded. /// private Stream m_loadStream; + + /// + /// Record the creator id that should be associated with an asset. This is used to adjust asset creator ids + /// after OSP resolution (since OSP creators are only stored in the item + /// + protected Dictionary m_creatorIdForAssetId = new Dictionary(); public InventoryArchiveReadRequest( Scene scene, UserAccount userInfo, string invPath, string loadPath, bool merge) @@ -420,6 +427,13 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver // Reset folder ID to the one in which we want to load it item.Folder = loadFolder.ID; + // Record the creator id for the item's asset so that we can use it later, if necessary, when the asset + // is loaded. + // FIXME: This relies on the items coming before the assets in the TAR file. Need to create stronger + // checks for this, and maybe even an external tool for creating OARs which enforces this, rather than + // relying on native tar tools. + m_creatorIdForAssetId[item.AssetID] = item.CreatorIdAsUuid; + m_scene.AddInventoryItem(item); return item; @@ -448,18 +462,38 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver } string extension = filename.Substring(i); - string uuid = filename.Remove(filename.Length - extension.Length); + string rawUuid = filename.Remove(filename.Length - extension.Length); + UUID assetId = new UUID(rawUuid); if (ArchiveConstants.EXTENSION_TO_ASSET_TYPE.ContainsKey(extension)) { sbyte assetType = ArchiveConstants.EXTENSION_TO_ASSET_TYPE[extension]; if (assetType == (sbyte)AssetType.Unknown) - m_log.WarnFormat("[INVENTORY ARCHIVER]: Importing {0} byte asset {1} with unknown type", data.Length, uuid); + { + m_log.WarnFormat("[INVENTORY ARCHIVER]: Importing {0} byte asset {1} with unknown type", data.Length, assetId); + } + else if (assetType == (sbyte)AssetType.Object) + { + if (m_creatorIdForAssetId.ContainsKey(assetId)) + { + string xmlData = Utils.BytesToString(data); + SceneObjectGroup sog = SceneObjectSerializer.FromOriginalXmlFormat(xmlData); + foreach (SceneObjectPart sop in sog.Parts) + { + if (sop.CreatorData == null || sop.CreatorData == "") + { + sop.CreatorID = m_creatorIdForAssetId[assetId]; + } + } + + data = Utils.StringToBytes(SceneObjectSerializer.ToOriginalXmlFormat(sog)); + } + } //m_log.DebugFormat("[INVENTORY ARCHIVER]: Importing asset {0}, type {1}", uuid, assetType); - AssetBase asset = new AssetBase(new UUID(uuid), "RandomName", assetType, UUID.Zero.ToString()); + AssetBase asset = new AssetBase(assetId, "From IAR", assetType, UUID.Zero.ToString()); asset.Data = data; m_scene.AssetService.Store(asset); diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs index 3eb4104e73..5065227967 100644 --- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs +++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs @@ -207,11 +207,11 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests Assert.That(foundItem1.Owner, Is.EqualTo(m_ua1.PrincipalID), "Loaded item owner doesn't match inventory reciever"); -// AssetBase asset1 = 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_ua3.PrincipalID.ToString())); + AssetBase asset1 = 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_ua3.PrincipalID)); } /// diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs index 67e59c6564..fa404c01bd 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs @@ -1089,9 +1089,13 @@ namespace OpenSim.Region.Framework.Scenes public Dictionary GetScriptStates() { + Dictionary ret = new Dictionary(); + + if (m_part.ParentGroup.Scene == null) // Group not in a scene + return ret; + IScriptModule[] engines = m_part.ParentGroup.Scene.RequestModuleInterfaces(); - - Dictionary ret = new Dictionary(); + if (engines == null) // No engine at all return ret; From ce4421497e47d709018e6aba9e99317d6a936b98 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Thu, 10 Mar 2011 22:38:52 +0000 Subject: [PATCH 61/81] re-enable item.CreatorId check in TestLoadIarV0_1AbsentCreator() --- .../Inventory/Archiver/InventoryArchiveReadRequest.cs | 5 +++-- .../Inventory/Archiver/Tests/InventoryArchiverTests.cs | 6 +++--- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs index d0510d3da1..7d50e51173 100644 --- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs +++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs @@ -411,7 +411,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver item.CreatorIdAsUuid = ospResolvedId; - // XXX: For now, don't preserve the OSPA in the creator id (which actually gets persisted to the + // Don't preserve the OSPA in the creator id (which actually gets persisted to the // database). Instead, replace with the UUID that we found. item.CreatorId = ospResolvedId.ToString(); @@ -419,7 +419,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver } else if (item.CreatorData == null || item.CreatorData == String.Empty) { - item.CreatorIdAsUuid = m_userInfo.PrincipalID; + item.CreatorId = m_userInfo.PrincipalID.ToString(); + item.CreatorIdAsUuid = new UUID(item.CreatorId); } item.Owner = m_userInfo.PrincipalID; diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs index 5065227967..a092b6578e 100644 --- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs +++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs @@ -236,9 +236,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests = InventoryArchiveUtils.FindItemByPath(scene.InventoryService, m_ua1.PrincipalID, m_item1Name); 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.CreatorId, Is.EqualTo(m_ua1.PrincipalID.ToString()), + "Loaded item non-uuid creator doesn't match that of the loading user"); Assert.That( foundItem1.CreatorIdAsUuid, Is.EqualTo(m_ua1.PrincipalID), "Loaded item uuid creator doesn't match that of the loading user"); From 66d2d35425ee61e11445fc04c6d4949cdde85b87 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Thu, 10 Mar 2011 22:40:24 +0000 Subject: [PATCH 62/81] extend TestLoadIarV0_1AbsentCreator() to check serialized object CreatorId as well --- .../Inventory/Archiver/Tests/InventoryArchiverTests.cs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs index a092b6578e..78faefd242 100644 --- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs +++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs @@ -242,6 +242,12 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests Assert.That( foundItem1.CreatorIdAsUuid, Is.EqualTo(m_ua1.PrincipalID), "Loaded item uuid creator doesn't match that of the loading user"); + + AssetBase asset1 = 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_ua1.PrincipalID)); } } } \ No newline at end of file From 9ecb745ed77c33631503e8ebbbfe82fd5fc3bb7c Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Thu, 10 Mar 2011 22:48:19 +0000 Subject: [PATCH 63/81] factor out common scene setup code in InventoryArchiveTestCase --- .../Tests/InventoryArchiveTestCase.cs | 2 +- .../Archiver/Tests/InventoryArchiverTests.cs | 72 +++++++++---------- 2 files changed, 33 insertions(+), 41 deletions(-) diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveTestCase.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveTestCase.cs index d77bff2741..31e6d75488 100644 --- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveTestCase.cs +++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveTestCase.cs @@ -81,7 +81,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests protected string m_item1Name = "Ray Gun Item"; [SetUp] - public void SetUp() + public virtual void SetUp() { m_iarStream = new MemoryStream(m_iarStreamBytes); } diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs index 78faefd242..79b47777f5 100644 --- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs +++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs @@ -50,7 +50,22 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests { [TestFixture] public class InventoryArchiverTests : 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 = SceneSetupHelpers.SetupScene("Inventory"); + SceneSetupHelpers.SetupSceneModules(m_scene, serialiserModule, m_archiverModule); + } + /// /// Test saving a single inventory item to a V0.1 OpenSim Inventory Archive /// (subject to change since there is no fixed format yet). @@ -61,17 +76,12 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests TestHelper.InMethod(); // log4net.Config.XmlConfigurator.Configure(); - InventoryArchiverModule archiverModule = new InventoryArchiverModule(); - - Scene scene = SceneSetupHelpers.SetupScene("Inventory"); - SceneSetupHelpers.SetupSceneModules(scene, archiverModule); - // Create user string userFirstName = "Jock"; string userLastName = "Stirrup"; string userPassword = "troll"; UUID userId = UUID.Parse("00000000-0000-0000-0000-000000000020"); - UserProfileTestUtils.CreateUserWithInventory(scene, userFirstName, userLastName, userId, userPassword); + UserProfileTestUtils.CreateUserWithInventory(m_scene, userFirstName, userLastName, userId, userPassword); // Create asset SceneObjectGroup object1; @@ -90,12 +100,12 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests part1.Name = partName; object1 = new SceneObjectGroup(part1); - scene.AddNewSceneObject(object1, false); + m_scene.AddNewSceneObject(object1, false); } UUID asset1Id = UUID.Parse("00000000-0000-0000-0000-000000000060"); AssetBase asset1 = AssetHelpers.CreateAsset(asset1Id, object1); - scene.AssetService.Store(asset1); + m_scene.AssetService.Store(asset1); // Create item UUID item1Id = UUID.Parse("00000000-0000-0000-0000-000000000080"); @@ -105,15 +115,15 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests item1.AssetID = asset1.FullID; item1.ID = item1Id; InventoryFolderBase objsFolder - = InventoryArchiveUtils.FindFolderByPath(scene.InventoryService, userId, "Objects")[0]; + = InventoryArchiveUtils.FindFolderByPath(m_scene.InventoryService, userId, "Objects")[0]; item1.Folder = objsFolder.ID; - scene.AddInventoryItem(item1); + m_scene.AddInventoryItem(item1); MemoryStream archiveWriteStream = new MemoryStream(); - archiverModule.OnInventoryArchiveSaved += SaveCompleted; + m_archiverModule.OnInventoryArchiveSaved += SaveCompleted; mre.Reset(); - archiverModule.ArchiveInventory( + m_archiverModule.ArchiveInventory( Guid.NewGuid(), userFirstName, userLastName, "Objects/" + item1Name, userPassword, archiveWriteStream); mre.WaitOne(60000, false); @@ -177,27 +187,14 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests { TestHelper.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 = SceneSetupHelpers.SetupScene("inventory"); - - SceneSetupHelpers.SetupSceneModules(scene, serialiserModule, archiverModule); - UserProfileTestUtils.CreateUserWithInventory(scene, m_ua1, "meowfood"); - UserProfileTestUtils.CreateUserWithInventory(scene, m_ua3, "hampshire"); + UserProfileTestUtils.CreateUserWithInventory(m_scene, m_ua1, "meowfood"); + UserProfileTestUtils.CreateUserWithInventory(m_scene, m_ua3, "hampshire"); - archiverModule.DearchiveInventory(m_ua1.FirstName, m_ua1.LastName, "/", "meowfood", m_iarStream); + m_archiverModule.DearchiveInventory(m_ua1.FirstName, m_ua1.LastName, "/", "meowfood", m_iarStream); InventoryItemBase foundItem1 - = InventoryArchiveUtils.FindItemByPath(scene.InventoryService, m_ua1.PrincipalID, m_item1Name); + = InventoryArchiveUtils.FindItemByPath(m_scene.InventoryService, m_ua1.PrincipalID, m_item1Name); -// We have to disable this check since loaded items that did find users via OSPA resolution are now only storing the -// UUID, not the OSPA itself. -// Assert.That( -// foundItem1.CreatorId, Is.EqualTo(item1.CreatorId), -// "Loaded item non-uuid creator doesn't match original"); Assert.That( foundItem1.CreatorId, Is.EqualTo(m_ua3.PrincipalID.ToString()), "Loaded item non-uuid creator doesn't match original"); @@ -207,7 +204,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests Assert.That(foundItem1.Owner, Is.EqualTo(m_ua1.PrincipalID), "Loaded item owner doesn't match inventory reciever"); - AssetBase asset1 = scene.AssetService.Get(foundItem1.AssetID.ToString()); + AssetBase asset1 = m_scene.AssetService.Get(foundItem1.AssetID.ToString()); string xmlData = Utils.BytesToString(asset1.Data); SceneObjectGroup sog1 = SceneObjectSerializer.FromOriginalXmlFormat(xmlData); @@ -224,16 +221,11 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests TestHelper.InMethod(); // log4net.Config.XmlConfigurator.Configure(); - SerialiserModule serialiserModule = new SerialiserModule(); - InventoryArchiverModule archiverModule = new InventoryArchiverModule(); - Scene scene = SceneSetupHelpers.SetupScene("inventory"); - SceneSetupHelpers.SetupSceneModules(scene, serialiserModule, archiverModule); - - UserProfileTestUtils.CreateUserWithInventory(scene, m_ua1, "password"); - archiverModule.DearchiveInventory(m_ua1.FirstName, m_ua1.LastName, "/", "password", m_iarStream); + UserProfileTestUtils.CreateUserWithInventory(m_scene, m_ua1, "password"); + m_archiverModule.DearchiveInventory(m_ua1.FirstName, m_ua1.LastName, "/", "password", m_iarStream); InventoryItemBase foundItem1 - = InventoryArchiveUtils.FindItemByPath(scene.InventoryService, m_ua1.PrincipalID, m_item1Name); + = InventoryArchiveUtils.FindItemByPath(m_scene.InventoryService, m_ua1.PrincipalID, m_item1Name); Assert.That(foundItem1, Is.Not.Null, "Didn't find loaded item 1"); Assert.That( @@ -243,7 +235,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests foundItem1.CreatorIdAsUuid, Is.EqualTo(m_ua1.PrincipalID), "Loaded item uuid creator doesn't match that of the loading user"); - AssetBase asset1 = scene.AssetService.Get(foundItem1.AssetID.ToString()); + AssetBase asset1 = m_scene.AssetService.Get(foundItem1.AssetID.ToString()); string xmlData = Utils.BytesToString(asset1.Data); SceneObjectGroup sog1 = SceneObjectSerializer.FromOriginalXmlFormat(xmlData); From 8d69e6831136fea089ed0ca04249bf65ba66db28 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Thu, 10 Mar 2011 22:52:41 +0000 Subject: [PATCH 64/81] refactor: rename test user account fields --- .../Tests/InventoryArchiveTestCase.cs | 16 +++++------ .../Archiver/Tests/InventoryArchiverTests.cs | 28 +++++++++---------- .../Inventory/Archiver/Tests/PathTests.cs | 26 ++++++++--------- 3 files changed, 35 insertions(+), 35 deletions(-) diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveTestCase.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveTestCase.cs index 31e6d75488..e5127a0118 100644 --- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveTestCase.cs +++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveTestCase.cs @@ -63,17 +63,17 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests /// protected MemoryStream m_iarStream; - protected UserAccount m_ua1 + protected UserAccount m_uaMT = new UserAccount { PrincipalID = UUID.Parse("00000000-0000-0000-0000-000000000555"), FirstName = "Mr", LastName = "Tiddles" }; - protected UserAccount m_ua2 + protected UserAccount m_uaLL1 = new UserAccount { PrincipalID = UUID.Parse("00000000-0000-0000-0000-000000000666"), FirstName = "Lord", LastName = "Lucan" }; - protected UserAccount m_ua3 + protected UserAccount m_uaLL2 = new UserAccount { PrincipalID = UUID.Parse("00000000-0000-0000-0000-000000000777"), FirstName = "Lord", @@ -100,7 +100,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests Scene scene = SceneSetupHelpers.SetupScene("Inventory"); SceneSetupHelpers.SetupSceneModules(scene, archiverModule); - UserProfileTestUtils.CreateUserWithInventory(scene, m_ua2, "hampshire"); + UserProfileTestUtils.CreateUserWithInventory(scene, m_uaLL1, "hampshire"); MemoryStream archiveWriteStream = new MemoryStream(); @@ -134,13 +134,13 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests item1.ID = UUID.Parse("00000000-0000-0000-0000-000000000020"); item1.AssetID = asset1.FullID; item1.GroupID = UUID.Random(); - item1.CreatorIdAsUuid = m_ua2.PrincipalID; - item1.Owner = m_ua2.PrincipalID; - item1.Folder = scene.InventoryService.GetRootFolder(m_ua2.PrincipalID).ID; + item1.CreatorIdAsUuid = m_uaLL1.PrincipalID; + item1.Owner = m_uaLL1.PrincipalID; + item1.Folder = scene.InventoryService.GetRootFolder(m_uaLL1.PrincipalID).ID; scene.AddInventoryItem(item1); archiverModule.ArchiveInventory( - Guid.NewGuid(), m_ua2.FirstName, m_ua2.LastName, m_item1Name, "hampshire", archiveWriteStream); + Guid.NewGuid(), m_uaLL1.FirstName, m_uaLL1.LastName, m_item1Name, "hampshire", archiveWriteStream); m_iarStreamBytes = archiveWriteStream.ToArray(); } diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs index 79b47777f5..c7aad5eedc 100644 --- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs +++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs @@ -188,27 +188,27 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests TestHelper.InMethod(); // log4net.Config.XmlConfigurator.Configure(); - UserProfileTestUtils.CreateUserWithInventory(m_scene, m_ua1, "meowfood"); - UserProfileTestUtils.CreateUserWithInventory(m_scene, m_ua3, "hampshire"); + UserProfileTestUtils.CreateUserWithInventory(m_scene, m_uaMT, "meowfood"); + UserProfileTestUtils.CreateUserWithInventory(m_scene, m_uaLL2, "hampshire"); - m_archiverModule.DearchiveInventory(m_ua1.FirstName, m_ua1.LastName, "/", "meowfood", m_iarStream); + m_archiverModule.DearchiveInventory(m_uaMT.FirstName, m_uaMT.LastName, "/", "meowfood", m_iarStream); InventoryItemBase foundItem1 - = InventoryArchiveUtils.FindItemByPath(m_scene.InventoryService, m_ua1.PrincipalID, m_item1Name); + = InventoryArchiveUtils.FindItemByPath(m_scene.InventoryService, m_uaMT.PrincipalID, m_item1Name); Assert.That( - foundItem1.CreatorId, Is.EqualTo(m_ua3.PrincipalID.ToString()), + foundItem1.CreatorId, Is.EqualTo(m_uaLL2.PrincipalID.ToString()), "Loaded item non-uuid creator doesn't match original"); Assert.That( - foundItem1.CreatorIdAsUuid, Is.EqualTo(m_ua3.PrincipalID), + foundItem1.CreatorIdAsUuid, Is.EqualTo(m_uaLL2.PrincipalID), "Loaded item uuid creator doesn't match original"); - Assert.That(foundItem1.Owner, Is.EqualTo(m_ua1.PrincipalID), + 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_ua3.PrincipalID)); + Assert.That(sog1.RootPart.CreatorID, Is.EqualTo(m_uaLL2.PrincipalID)); } /// @@ -221,25 +221,25 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests TestHelper.InMethod(); // log4net.Config.XmlConfigurator.Configure(); - UserProfileTestUtils.CreateUserWithInventory(m_scene, m_ua1, "password"); - m_archiverModule.DearchiveInventory(m_ua1.FirstName, m_ua1.LastName, "/", "password", m_iarStream); + UserProfileTestUtils.CreateUserWithInventory(m_scene, m_uaMT, "password"); + m_archiverModule.DearchiveInventory(m_uaMT.FirstName, m_uaMT.LastName, "/", "password", m_iarStream); InventoryItemBase foundItem1 - = InventoryArchiveUtils.FindItemByPath(m_scene.InventoryService, m_ua1.PrincipalID, m_item1Name); + = 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_ua1.PrincipalID.ToString()), + 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_ua1.PrincipalID), + 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_ua1.PrincipalID)); + 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/PathTests.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/PathTests.cs index 66c19f4a34..0e8f647dbc 100644 --- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/PathTests.cs +++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/PathTests.cs @@ -184,31 +184,31 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests SceneSetupHelpers.SetupSceneModules(scene, serialiserModule, archiverModule); - UserProfileTestUtils.CreateUserWithInventory(scene, m_ua1, "meowfood"); - UserProfileTestUtils.CreateUserWithInventory(scene, m_ua2, "hampshire"); + UserProfileTestUtils.CreateUserWithInventory(scene, m_uaMT, "meowfood"); + UserProfileTestUtils.CreateUserWithInventory(scene, m_uaLL1, "hampshire"); - archiverModule.DearchiveInventory(m_ua1.FirstName, m_ua1.LastName, "/", "meowfood", m_iarStream); + archiverModule.DearchiveInventory(m_uaMT.FirstName, m_uaMT.LastName, "/", "meowfood", m_iarStream); InventoryItemBase foundItem1 - = InventoryArchiveUtils.FindItemByPath(scene.InventoryService, m_ua1.PrincipalID, m_item1Name); + = 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 - UserInventoryTestUtils.CreateInventoryFolder(scene.InventoryService, m_ua1.PrincipalID, "xA"); + UserInventoryTestUtils.CreateInventoryFolder(scene.InventoryService, m_uaMT.PrincipalID, "xA"); MemoryStream archiveReadStream = new MemoryStream(m_iarStream.ToArray()); - archiverModule.DearchiveInventory(m_ua1.FirstName, m_ua1.LastName, "xA", "meowfood", archiveReadStream); + archiverModule.DearchiveInventory(m_uaMT.FirstName, m_uaMT.LastName, "xA", "meowfood", archiveReadStream); InventoryItemBase foundItem2 - = InventoryArchiveUtils.FindItemByPath(scene.InventoryService, m_ua1.PrincipalID, "xA/" + m_item1Name); + = 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 - UserInventoryTestUtils.CreateInventoryFolder(scene.InventoryService, m_ua1.PrincipalID, "xB/xC"); + UserInventoryTestUtils.CreateInventoryFolder(scene.InventoryService, m_uaMT.PrincipalID, "xB/xC"); archiveReadStream = new MemoryStream(archiveReadStream.ToArray()); - archiverModule.DearchiveInventory(m_ua1.FirstName, m_ua1.LastName, "xB/xC", "meowfood", archiveReadStream); + archiverModule.DearchiveInventory(m_uaMT.FirstName, m_uaMT.LastName, "xB/xC", "meowfood", archiveReadStream); InventoryItemBase foundItem3 - = InventoryArchiveUtils.FindItemByPath(scene.InventoryService, m_ua1.PrincipalID, "xB/xC/" + m_item1Name); + = InventoryArchiveUtils.FindItemByPath(scene.InventoryService, m_uaMT.PrincipalID, "xB/xC/" + m_item1Name); Assert.That(foundItem3, Is.Not.Null, "Didn't find loaded item 3"); } @@ -226,12 +226,12 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests Scene scene = SceneSetupHelpers.SetupScene("inventory"); SceneSetupHelpers.SetupSceneModules(scene, serialiserModule, archiverModule); - UserProfileTestUtils.CreateUserWithInventory(scene, m_ua1, "password"); - archiverModule.DearchiveInventory(m_ua1.FirstName, m_ua1.LastName, "/Objects", "password", m_iarStream); + UserProfileTestUtils.CreateUserWithInventory(scene, m_uaMT, "password"); + archiverModule.DearchiveInventory(m_uaMT.FirstName, m_uaMT.LastName, "/Objects", "password", m_iarStream); InventoryItemBase foundItem1 = InventoryArchiveUtils.FindItemByPath( - scene.InventoryService, m_ua1.PrincipalID, "/Objects/" + m_item1Name); + scene.InventoryService, m_uaMT.PrincipalID, "/Objects/" + m_item1Name); Assert.That(foundItem1, Is.Not.Null, "Didn't find loaded item 1 in TestLoadIarFolderStartsWithSlash()"); } From ad1dea5affe24674ada19b801cab423f667f7979 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Thu, 10 Mar 2011 22:56:11 +0000 Subject: [PATCH 65/81] Add test for simple case where creator account with appropriate uuid exists on the target system for an iar load --- .../Archiver/Tests/InventoryArchiverTests.cs | 32 +++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs index c7aad5eedc..7f156f8904 100644 --- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs +++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs @@ -178,6 +178,38 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests // TODO: Test presence of more files and contents of files. } + /// + /// Test case where a creator account exists for the creator UUID embedded in item metadata and serialized + /// objects. + /// + [Test] + public void TestLoadIarCreatorAccountPresent() + { + TestHelper.InMethod(); +// log4net.Config.XmlConfigurator.Configure(); + + UserProfileTestUtils.CreateUserWithInventory(m_scene, m_uaLL1, "meowfood"); + + m_archiverModule.DearchiveInventory(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. From 836ab6b0e87c16bcff171d0491476f19d7c18a2c Mon Sep 17 00:00:00 2001 From: Mic Bowman Date: Thu, 10 Mar 2011 15:23:46 -0800 Subject: [PATCH 66/81] Change how map blocks are encoded to make map search work with viewer 2. --- .../Region/CoreModules/World/WorldMap/MapSearchModule.cs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/OpenSim/Region/CoreModules/World/WorldMap/MapSearchModule.cs b/OpenSim/Region/CoreModules/World/WorldMap/MapSearchModule.cs index a9e46d04c2..7bb7544e89 100644 --- a/OpenSim/Region/CoreModules/World/WorldMap/MapSearchModule.cs +++ b/OpenSim/Region/CoreModules/World/WorldMap/MapSearchModule.cs @@ -113,7 +113,7 @@ namespace OpenSim.Region.CoreModules.World.WorldMap data = new MapBlockData(); data.Agents = 0; data.Access = info.Access; - data.MapImageId = info.TerrainImage; + data.MapImageId = UUID.Zero; // could use info.TerrainImage but it seems to break viewer2 data.Name = info.RegionName; data.RegionFlags = 0; // TODO not used? data.WaterHeight = 0; // not used @@ -135,7 +135,9 @@ namespace OpenSim.Region.CoreModules.World.WorldMap data.Y = 0; blocks.Add(data); - remoteClient.SendMapBlock(blocks, 0); + // not sure what the flags do here, but seems to be necessary + // to set to "2" for viewer 2 + remoteClient.SendMapBlock(blocks, 2); } // private Scene GetClientScene(IClientAPI client) From cb863851e0149a931f3c79fdc7301e7086c3c16f Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Fri, 11 Mar 2011 22:38:51 +0000 Subject: [PATCH 67/81] Update/simplify test running instructions --- TESTING.txt | 81 +++++------------------------------------------------ 1 file changed, 7 insertions(+), 74 deletions(-) diff --git a/TESTING.txt b/TESTING.txt index e0a7748e6f..54fc976e95 100644 --- a/TESTING.txt +++ b/TESTING.txt @@ -2,23 +2,14 @@ == Running Tests == -On Linux: +On Linux you will need to have NUnit installed (http://www.nunit.org). +This is commonly available in distribution package repositories. + +When this is installed, run the command > nant test -This will print out to the console the test state. - -On Windows: Please see the TESTING ON WINDOWS section below. - - -Also, every checkin will run tests that are kicked off by bamboo. -Results are posted here: http://www.opensimulator.org:8085/ as well as -to #opensim-dev IRC channel. - -== Writing Tests == - -Tests are written to run under NUnit. For more information on NUnit -please see: http://www.nunit.org/index.php +Please see the TESTING ON WINDOWS section below for Windows instructions. == Adding Tests == @@ -32,70 +23,15 @@ that if you are writing tests they end up in a "Tests" sub-directory of the directory where the code you are testing resides. If you have added a new test assembly that hasn't existed before you -must list it in both ".nant/local.include" and ".nant/bamboo.build" +must list it in both ".nant/local.include" for it to be accessible to Linux users and to the continuous integration system. - -=== The Gory Details === -The following is the original document which started off this -document. It should probably be better integrated with the new info. - -==UPDATE== - -The text immediately following is an update to the testing documentation. The -update is written on 2008.08.30 and is copied from an email to the opensim-dev -mailing list[1]. The information below the update, beginning with the section -titled TESTING, is still relevant, so please read this document in its -entirety. - -Mike Mazur - -[1] https://lists.berlios.de/pipermail/opensim-dev/2008-August/002695.html - -""" -The tests are contained in certain DLLs. At the time of writing, these DLLs -have tests in them: - -OpenSim.Region.ScriptEngine.Common.Tests.dll -OpenSim.Region.ScriptEngine.Shared.CodeTools.Tests.dll -OpenSim.Region.ScriptEngine.Shared.Tests.dll -OpenSim.Framework.Tests.dll OpenSim.Region.CoreModules.dll -OpenSim.Region.Physics.OdePlugin.dll[2] - -The console command used to run the tests is `nunit-console` (or -`nunit-console2` on some systems). This command takes a listing of DLLs to -inspect for tests. - -Currently Bamboo's[3] build file (.nant/bamboo.build) lists only those DLLs -for nunit-console to use. However it would be equally correct to simply pass -in all DLLs in bin/; those without tests are just skipped. - -The nunit-console command generates a file TestResults.txt by default. This is -an XML file containing a listing of all DLLs inspected, tests executed, -successes, failures, etc. If nunit-console is passed in all DLLs in bin/, this -file bloats with lots of entries like this: - - - - - - - - -Therefore it makes more sense to me to specify the DLLs when running -nunit-console. - -[2] Note that OpenSim.Region.Physics.OdePlugin.dll is in bin/Physics/ and -needs to be first copied to bin/ before nunit-console is executed. -[3] http://opensimulator.org:8085/ -""" - ==TESTING ON WINDOWS== To use nunit testing on opensim code, you have a variety of methods. The easiast methods involve using IDE capabilities to test code. Using -VS2005/2008 I recommend using the testing capabilities of Resarper(commercial) +VS2005/2008 I recommend using the testing capabilities of Resharper(commercial) or TestDriven.Net(free). Both will recognize nunit tests within your application and allow you to test them individually, or all at once, etc. You will also be able to step into debug mode into a test through these add-ins @@ -133,6 +69,3 @@ Example nunit-console2 OpenSim.Framework.Tests.dll (on linux) nunit-console OpenSim.Framework.Tests.dll (on windows) - -For more information on testing contact the autor of this testing readme: Daedius Moskvitch ( daedius @@@@ daedius com) - From 367ed585e0f4a7e4d540230c586531abd75e2228 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Sat, 12 Mar 2011 00:21:52 +0000 Subject: [PATCH 68/81] introduce iar load checks which make sure archive.xml comes first, then inventory nodes, then assets this is necessary for correct loading. "save iar" always saves in this order so there shouldn't be any problems - these checks are to give better feedback to other systems that may construct IARs. --- .../Archiver/InventoryArchiveReadRequest.cs | 33 ++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs index 7d50e51173..4d97c0aed4 100644 --- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs +++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs @@ -111,6 +111,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver /// A list of the inventory nodes loaded. If folders were loaded then only the root folders are /// returned /// + /// Thrown if load fails. public HashSet Execute() { try @@ -143,15 +144,29 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver byte[] data; TarArchiveReader.TarEntryType entryType; + bool controlFileLoaded = false, assetsLoaded = false, inventoryNodesLoaded = false; while ((data = archive.ReadEntry(out filePath, out entryType)) != null) { if (filePath == ArchiveConstants.CONTROL_FILE_PATH) { LoadControlFile(filePath, data); + controlFileLoaded = true; } else if (filePath.StartsWith(ArchiveConstants.ASSETS_PATH)) { + if (!controlFileLoaded) + throw new Exception( + string.Format( + "The IAR you are trying to load does not list {0} before {1}. Aborting load", + ArchiveConstants.CONTROL_FILE_PATH, ArchiveConstants.ASSETS_PATH)); + + if (!inventoryNodesLoaded) + throw new Exception( + string.Format( + "The IAR you are trying to load does not list all {0} before {1}. Aborting load", + ArchiveConstants.INVENTORY_PATH, ArchiveConstants.ASSETS_PATH)); + if (LoadAsset(filePath, data)) successfulAssetRestores++; else @@ -160,10 +175,24 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver if ((successfulAssetRestores) % 50 == 0) m_log.DebugFormat( "[INVENTORY ARCHIVER]: Loaded {0} assets...", - successfulAssetRestores); + successfulAssetRestores); + + assetsLoaded = true; } else if (filePath.StartsWith(ArchiveConstants.INVENTORY_PATH)) { + if (!controlFileLoaded) + throw new Exception( + string.Format( + "The IAR you are trying to load does not list {0} before {1}. Aborting load", + ArchiveConstants.CONTROL_FILE_PATH, ArchiveConstants.INVENTORY_PATH)); + + if (assetsLoaded) + throw new Exception( + string.Format( + "The IAR you are trying to load does not list all {0} before {1}. Aborting load", + ArchiveConstants.INVENTORY_PATH, ArchiveConstants.ASSETS_PATH)); + filePath = filePath.Substring(ArchiveConstants.INVENTORY_PATH.Length); // Trim off the file portion if we aren't already dealing with a directory path @@ -188,6 +217,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver loadedNodes.Add(item); } } + + inventoryNodesLoaded = true; } } From a3c7c04ead1b1388d2093edf66d37edecdeccc61 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Sat, 12 Mar 2011 00:28:23 +0000 Subject: [PATCH 69/81] refactor: make boolean load indicators on load iars instance fields --- .../Archiver/InventoryArchiveReadRequest.cs | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs index 4d97c0aed4..367960c9da 100644 --- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs +++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs @@ -82,6 +82,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver /// after OSP resolution (since OSP creators are only stored in the item /// protected Dictionary m_creatorIdForAssetId = new Dictionary(); + + protected bool m_controlFileLoaded; + protected bool m_assetsLoaded; + protected bool m_inventoryNodesLoaded; public InventoryArchiveReadRequest( Scene scene, UserAccount userInfo, string invPath, string loadPath, bool merge) @@ -144,24 +148,23 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver byte[] data; TarArchiveReader.TarEntryType entryType; - bool controlFileLoaded = false, assetsLoaded = false, inventoryNodesLoaded = false; while ((data = archive.ReadEntry(out filePath, out entryType)) != null) { if (filePath == ArchiveConstants.CONTROL_FILE_PATH) { LoadControlFile(filePath, data); - controlFileLoaded = true; + m_controlFileLoaded = true; } else if (filePath.StartsWith(ArchiveConstants.ASSETS_PATH)) { - if (!controlFileLoaded) + if (!m_controlFileLoaded) throw new Exception( string.Format( "The IAR you are trying to load does not list {0} before {1}. Aborting load", ArchiveConstants.CONTROL_FILE_PATH, ArchiveConstants.ASSETS_PATH)); - if (!inventoryNodesLoaded) + if (!m_inventoryNodesLoaded) throw new Exception( string.Format( "The IAR you are trying to load does not list all {0} before {1}. Aborting load", @@ -177,17 +180,17 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver "[INVENTORY ARCHIVER]: Loaded {0} assets...", successfulAssetRestores); - assetsLoaded = true; + m_assetsLoaded = true; } else if (filePath.StartsWith(ArchiveConstants.INVENTORY_PATH)) { - if (!controlFileLoaded) + if (!m_controlFileLoaded) throw new Exception( string.Format( "The IAR you are trying to load does not list {0} before {1}. Aborting load", ArchiveConstants.CONTROL_FILE_PATH, ArchiveConstants.INVENTORY_PATH)); - if (assetsLoaded) + if (m_assetsLoaded) throw new Exception( string.Format( "The IAR you are trying to load does not list all {0} before {1}. Aborting load", @@ -218,7 +221,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver } } - inventoryNodesLoaded = true; + m_inventoryNodesLoaded = true; } } From c4060e56ef2aa2d4d68d33ae3081c6a0d2d37f7c Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Sat, 12 Mar 2011 00:35:40 +0000 Subject: [PATCH 70/81] factor out iar asset load code into its own method --- .../Archiver/InventoryArchiveReadRequest.cs | 69 +++++++++++-------- 1 file changed, 40 insertions(+), 29 deletions(-) diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs index 367960c9da..cf4ba91eef 100644 --- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs +++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs @@ -86,6 +86,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver protected bool m_controlFileLoaded; protected bool m_assetsLoaded; protected bool m_inventoryNodesLoaded; + + protected int m_successfulAssetRestores; + protected int m_failedAssetRestores; public InventoryArchiveReadRequest( Scene scene, UserAccount userInfo, string invPath, string loadPath, bool merge) @@ -121,8 +124,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver try { string filePath = "ERROR"; - int successfulAssetRestores = 0; - int failedAssetRestores = 0; int successfulItemRestores = 0; HashSet loadedNodes = new HashSet(); @@ -154,33 +155,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver if (filePath == ArchiveConstants.CONTROL_FILE_PATH) { LoadControlFile(filePath, data); - m_controlFileLoaded = true; - } + } else if (filePath.StartsWith(ArchiveConstants.ASSETS_PATH)) { - if (!m_controlFileLoaded) - throw new Exception( - string.Format( - "The IAR you are trying to load does not list {0} before {1}. Aborting load", - ArchiveConstants.CONTROL_FILE_PATH, ArchiveConstants.ASSETS_PATH)); - - if (!m_inventoryNodesLoaded) - throw new Exception( - string.Format( - "The IAR you are trying to load does not list all {0} before {1}. Aborting load", - ArchiveConstants.INVENTORY_PATH, ArchiveConstants.ASSETS_PATH)); - - if (LoadAsset(filePath, data)) - successfulAssetRestores++; - else - failedAssetRestores++; - - if ((successfulAssetRestores) % 50 == 0) - m_log.DebugFormat( - "[INVENTORY ARCHIVER]: Loaded {0} assets...", - successfulAssetRestores); - - m_assetsLoaded = true; + LoadAssetFile(filePath, data); } else if (filePath.StartsWith(ArchiveConstants.INVENTORY_PATH)) { @@ -229,7 +207,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver m_log.DebugFormat( "[INVENTORY ARCHIVER]: Successfully loaded {0} assets with {1} failures", - successfulAssetRestores, failedAssetRestores); + m_successfulAssetRestores, m_failedAssetRestores); m_log.InfoFormat("[INVENTORY ARCHIVER]: Successfully loaded {0} items", successfulItemRestores); return loadedNodes; @@ -566,7 +544,40 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver majorVersion, MAX_MAJOR_VERSION)); } - m_log.InfoFormat("[INVENTORY ARCHIVER]: Loading IAR with version {0}", version); + m_controlFileLoaded = true; + m_log.InfoFormat("[INVENTORY ARCHIVER]: Loading IAR with version {0}", version); } + + /// + /// Load asset file + /// + /// + /// + protected void LoadAssetFile(string path, byte[] data) + { + if (!m_controlFileLoaded) + throw new Exception( + string.Format( + "The IAR you are trying to load does not list {0} before {1}. Aborting load", + ArchiveConstants.CONTROL_FILE_PATH, ArchiveConstants.ASSETS_PATH)); + + if (!m_inventoryNodesLoaded) + throw new Exception( + string.Format( + "The IAR you are trying to load does not list all {0} before {1}. Aborting load", + ArchiveConstants.INVENTORY_PATH, ArchiveConstants.ASSETS_PATH)); + + if (LoadAsset(path, data)) + m_successfulAssetRestores++; + else + m_failedAssetRestores++; + + if ((m_successfulAssetRestores) % 50 == 0) + m_log.DebugFormat( + "[INVENTORY ARCHIVER]: Loaded {0} assets...", + m_successfulAssetRestores); + + m_assetsLoaded = true; + } } } \ No newline at end of file From f6b638fec92596e0671d0484c3b63bd600ef38ea Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Sat, 12 Mar 2011 00:49:13 +0000 Subject: [PATCH 71/81] factor inventory file loading into its own method --- .../Archiver/InventoryArchiveReadRequest.cs | 137 ++++++++++-------- 1 file changed, 80 insertions(+), 57 deletions(-) diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs index cf4ba91eef..9b98de3b67 100644 --- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs +++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs @@ -77,18 +77,35 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver /// private Stream m_loadStream; - /// - /// Record the creator id that should be associated with an asset. This is used to adjust asset creator ids - /// after OSP resolution (since OSP creators are only stored in the item - /// - protected Dictionary m_creatorIdForAssetId = new Dictionary(); - protected bool m_controlFileLoaded; protected bool m_assetsLoaded; protected bool m_inventoryNodesLoaded; protected int m_successfulAssetRestores; protected int m_failedAssetRestores; + protected int m_successfulItemRestores; + + /// + /// Root destination folder for the IAR load. + /// + protected InventoryFolderBase m_rootDestinationFolder; + + /// + /// Inventory nodes loaded from the iar. + /// + protected HashSet m_loadedNodes = new HashSet(); + + /// + /// In order to load identically named folders, we need to keep track of the folders that we have already + /// resolved. + /// + Dictionary m_resolvedFolders = new Dictionary(); + + /// + /// Record the creator id that should be associated with an asset. This is used to adjust asset creator ids + /// after OSP resolution (since OSP creators are only stored in the item + /// + protected Dictionary m_creatorIdForAssetId = new Dictionary(); public InventoryArchiveReadRequest( Scene scene, UserAccount userInfo, string invPath, string loadPath, bool merge) @@ -114,6 +131,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver /// /// Execute the request /// + /// + /// Only call this once. To load another IAR, construct another request object. + /// /// /// A list of the inventory nodes loaded. If folders were loaded then only the root folders are /// returned @@ -124,9 +144,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver try { string filePath = "ERROR"; - int successfulItemRestores = 0; - - HashSet loadedNodes = new HashSet(); List folderCandidates = InventoryArchiveUtils.FindFolderByPath( @@ -137,16 +154,11 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver // Possibly provide an option later on to automatically create this folder if it does not exist m_log.ErrorFormat("[INVENTORY ARCHIVER]: Inventory path {0} does not exist", m_invPath); - return loadedNodes; + return m_loadedNodes; } - InventoryFolderBase rootDestinationFolder = folderCandidates[0]; + m_rootDestinationFolder = folderCandidates[0]; archive = new TarArchiveReader(m_loadStream); - - // In order to load identically named folders, we need to keep track of the folders that we have already - // resolved - Dictionary resolvedFolders = new Dictionary(); - byte[] data; TarArchiveReader.TarEntryType entryType; @@ -162,44 +174,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver } else if (filePath.StartsWith(ArchiveConstants.INVENTORY_PATH)) { - if (!m_controlFileLoaded) - throw new Exception( - string.Format( - "The IAR you are trying to load does not list {0} before {1}. Aborting load", - ArchiveConstants.CONTROL_FILE_PATH, ArchiveConstants.INVENTORY_PATH)); - - if (m_assetsLoaded) - throw new Exception( - string.Format( - "The IAR you are trying to load does not list all {0} before {1}. Aborting load", - ArchiveConstants.INVENTORY_PATH, ArchiveConstants.ASSETS_PATH)); - - filePath = filePath.Substring(ArchiveConstants.INVENTORY_PATH.Length); - - // Trim off the file portion if we aren't already dealing with a directory path - if (TarArchiveReader.TarEntryType.TYPE_DIRECTORY != entryType) - filePath = filePath.Remove(filePath.LastIndexOf("/") + 1); - - InventoryFolderBase foundFolder - = ReplicateArchivePathToUserInventory( - filePath, rootDestinationFolder, resolvedFolders, loadedNodes); - - if (TarArchiveReader.TarEntryType.TYPE_DIRECTORY != entryType) - { - InventoryItemBase item = LoadItem(data, foundFolder); - - if (item != null) - { - successfulItemRestores++; - - // If we aren't loading the folder containing the item then well need to update the - // viewer separately for that item. - if (!loadedNodes.Contains(foundFolder)) - loadedNodes.Add(item); - } - } - - m_inventoryNodesLoaded = true; + LoadInventoryFile(filePath, entryType, data); } } @@ -208,9 +183,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver m_log.DebugFormat( "[INVENTORY ARCHIVER]: Successfully loaded {0} assets with {1} failures", m_successfulAssetRestores, m_failedAssetRestores); - m_log.InfoFormat("[INVENTORY ARCHIVER]: Successfully loaded {0} items", successfulItemRestores); + m_log.InfoFormat("[INVENTORY ARCHIVER]: Successfully loaded {0} items", m_successfulItemRestores); - return loadedNodes; + return m_loadedNodes; } finally { @@ -548,6 +523,54 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver m_log.InfoFormat("[INVENTORY ARCHIVER]: Loading IAR with version {0}", version); } + /// + /// Load inventory file + /// + /// + /// + /// + protected void LoadInventoryFile(string path, TarArchiveReader.TarEntryType entryType, byte[] data) + { + if (!m_controlFileLoaded) + throw new Exception( + string.Format( + "The IAR you are trying to load does not list {0} before {1}. Aborting load", + ArchiveConstants.CONTROL_FILE_PATH, ArchiveConstants.INVENTORY_PATH)); + + if (m_assetsLoaded) + throw new Exception( + string.Format( + "The IAR you are trying to load does not list all {0} before {1}. Aborting load", + ArchiveConstants.INVENTORY_PATH, ArchiveConstants.ASSETS_PATH)); + + path = path.Substring(ArchiveConstants.INVENTORY_PATH.Length); + + // Trim off the file portion if we aren't already dealing with a directory path + if (TarArchiveReader.TarEntryType.TYPE_DIRECTORY != entryType) + path = path.Remove(path.LastIndexOf("/") + 1); + + InventoryFolderBase foundFolder + = ReplicateArchivePathToUserInventory( + path, m_rootDestinationFolder, m_resolvedFolders, m_loadedNodes); + + if (TarArchiveReader.TarEntryType.TYPE_DIRECTORY != entryType) + { + InventoryItemBase item = LoadItem(data, foundFolder); + + if (item != null) + { + m_successfulItemRestores++; + + // If we aren't loading the folder containing the item then well need to update the + // viewer separately for that item. + if (!m_loadedNodes.Contains(foundFolder)) + m_loadedNodes.Add(item); + } + } + + m_inventoryNodesLoaded = true; + } + /// /// Load asset file /// @@ -578,6 +601,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver m_successfulAssetRestores); m_assetsLoaded = true; - } + } } } \ No newline at end of file From f6f8d124d16783d44758b19d621d027b9cf72572 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Sat, 12 Mar 2011 00:52:43 +0000 Subject: [PATCH 72/81] minor: remove mono compiler warning --- OpenSim/Data/Tests/InventoryTests.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OpenSim/Data/Tests/InventoryTests.cs b/OpenSim/Data/Tests/InventoryTests.cs index 758f9704b7..6cf7e20f3f 100644 --- a/OpenSim/Data/Tests/InventoryTests.cs +++ b/OpenSim/Data/Tests/InventoryTests.cs @@ -153,7 +153,7 @@ namespace OpenSim.Data.Tests 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, Text.Matches(f1a.Name), "Assert.That(name1, Text.Matches(f1a.Name))"); + Assert.That(name1, Is.StringMatching(f1a.Name), "Assert.That(name1, Text.Matches(f1a.Name))"); } // we now have the following tree From cee5e3e264a71861dd018ee9bad47e6ea2ac0338 Mon Sep 17 00:00:00 2001 From: Melanie Date: Mon, 14 Mar 2011 12:56:50 +0100 Subject: [PATCH 73/81] Up the timeout on slow requests to 3000 to stop console spam. Make sure request method and target are reported correctly and drop the txn id as it's empty 99% of the time. --- .../Servers/HttpServer/BaseHttpServer.cs | 26 +++++++++++++++---- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs b/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs index 1d05b0284b..953ed856b6 100644 --- a/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs +++ b/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs @@ -378,6 +378,22 @@ namespace OpenSim.Framework.Servers.HttpServer /// public virtual void HandleRequest(OSHttpRequest request, OSHttpResponse response) { + if (request.HttpMethod == String.Empty) // Can't handle empty requests, not wasting a thread + { + try + { + SendHTML500(response); + } + catch + { + } + + return; + } + + string requestMethod = request.HttpMethod; + string uriString = request.RawUrl; + string reqnum = "unknown"; int tickstart = Environment.TickCount; @@ -495,7 +511,7 @@ namespace OpenSim.Framework.Servers.HttpServer request.InputStream.Close(); - // HTTP IN support. The script engine taes it from here + // HTTP IN support. The script engine takes it from here // Nothing to worry about for us. // if (buffer == null) @@ -609,9 +625,9 @@ namespace OpenSim.Framework.Servers.HttpServer { m_log.ErrorFormat("[BASE HTTP SERVER]: HandleRequest() threw ", e); } - catch (InvalidOperationException e) + catch (Exception e) { - m_log.ErrorFormat("[BASE HTTP SERVER]: HandleRequest() threw {0}", e); + m_log.ErrorFormat("[BASE HTTP SERVER]: HandleRequest() threw " + e.ToString()); SendHTML500(response); } finally @@ -619,9 +635,9 @@ namespace OpenSim.Framework.Servers.HttpServer // Every month or so this will wrap and give bad numbers, not really a problem // since its just for reporting, 200ms limit can be adjusted int tickdiff = Environment.TickCount - tickstart; - if (tickdiff > 500) + if (tickdiff > 3000) m_log.InfoFormat( - "[BASE HTTP SERVER]: slow request <{0}> for {1} took {2} ms", reqnum, request.RawUrl, tickdiff); + "[BASE HTTP SERVER]: slow {0} request for {1} from {2} took {3} ms", requestMethod, uriString, request.RemoteIPEndPoint.ToString(), tickdiff); } } From 9885f68f44ec91155d435ba9693eb57107378f45 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Mon, 14 Mar 2011 22:47:14 +0000 Subject: [PATCH 74/81] When setting media on a prim values, use generic object permissions instead of media permissions. Media permissions are just meant to be checked when we want to know if a user should be shown the navigation bar or allowed to navigate. It should not be checked when we're setting the media up. This bug was preventing a user from ever setting any more values if they had unchecked the owner settings. --- .../Region/CoreModules/World/Permissions/PermissionsModule.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs b/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs index 364dd6cb28..170c35f814 100644 --- a/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs +++ b/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs @@ -642,7 +642,7 @@ namespace OpenSim.Region.CoreModules.World.Permissions /// implemented by callers. /// /// - /// + /// This is a scene object group UUID /// /// protected bool GenericObjectPermission(UUID currentUser, UUID objId, bool denyOnLocked) @@ -1896,7 +1896,7 @@ namespace OpenSim.Region.CoreModules.World.Permissions // "[PERMISSIONS]: Checking CanControlPrimMedia for {0} on {1} face {2} with control permissions {3}", // agentID, primID, face, me.ControlPermissions); - return GenericPrimMediaPermission(part, agentID, me.ControlPermissions); + return GenericObjectPermission(agentID, part.ParentGroup.UUID, true); } private bool CanInteractWithPrimMedia(UUID agentID, UUID primID, int face) From 48c62eb51bdf475303ee3007354b98fd6fd4fc05 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Mon, 14 Mar 2011 23:17:15 +0000 Subject: [PATCH 75/81] Add current method output to all persistence level tests so that we can track where we are in the test suite --- OpenSim/Data/Tests/AssetTests.cs | 7 ++++ OpenSim/Data/Tests/EstateTests.cs | 17 ++++++++ OpenSim/Data/Tests/InventoryTests.cs | 27 +++++++++++++ OpenSim/Data/Tests/RegionTests.cs | 59 ++++++++++++++++++++++------ 4 files changed, 99 insertions(+), 11 deletions(-) diff --git a/OpenSim/Data/Tests/AssetTests.cs b/OpenSim/Data/Tests/AssetTests.cs index 32f74a9b1e..b5ae2444eb 100644 --- a/OpenSim/Data/Tests/AssetTests.cs +++ b/OpenSim/Data/Tests/AssetTests.cs @@ -32,6 +32,7 @@ using NUnit.Framework; using NUnit.Framework.Constraints; using OpenMetaverse; using OpenSim.Framework; +using OpenSim.Tests.Common; using System.Data.Common; using log4net; @@ -105,6 +106,8 @@ namespace OpenSim.Data.Tests [Test] public void T001_LoadEmpty() { + TestHelper.InMethod(); + Assert.That(m_db.ExistsAsset(uuid1), Is.False); Assert.That(m_db.ExistsAsset(uuid2), Is.False); Assert.That(m_db.ExistsAsset(uuid3), Is.False); @@ -113,6 +116,8 @@ namespace OpenSim.Data.Tests [Test] public void T010_StoreReadVerifyAssets() { + TestHelper.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()); @@ -178,6 +183,8 @@ namespace OpenSim.Data.Tests [Test] public void T020_CheckForWeirdCreatorID() { + TestHelper.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. diff --git a/OpenSim/Data/Tests/EstateTests.cs b/OpenSim/Data/Tests/EstateTests.cs index 3354e284da..8d332daa2f 100644 --- a/OpenSim/Data/Tests/EstateTests.cs +++ b/OpenSim/Data/Tests/EstateTests.cs @@ -31,6 +31,7 @@ using NUnit.Framework; using OpenMetaverse; using OpenSim.Framework; using OpenSim.Region.Framework.Interfaces; +using OpenSim.Tests.Common; using System.Text; using log4net; using System.Reflection; @@ -106,6 +107,8 @@ namespace OpenSim.Data.Tests [Test] public void T010_EstateSettingsSimpleStorage_MinimumParameterSet() { + TestHelper.InMethod(); + EstateSettingsSimpleStorage( REGION_ID, DataTestUtil.STRING_MIN, @@ -137,6 +140,8 @@ namespace OpenSim.Data.Tests [Test] public void T011_EstateSettingsSimpleStorage_MaximumParameterSet() { + TestHelper.InMethod(); + EstateSettingsSimpleStorage( REGION_ID, DataTestUtil.STRING_MAX(64), @@ -168,6 +173,8 @@ namespace OpenSim.Data.Tests [Test] public void T012_EstateSettingsSimpleStorage_AccurateParameterSet() { + TestHelper.InMethod(); + EstateSettingsSimpleStorage( REGION_ID, DataTestUtil.STRING_MAX(1), @@ -199,6 +206,8 @@ namespace OpenSim.Data.Tests [Test] public void T012_EstateSettingsRandomStorage() { + TestHelper.InMethod(); + // Letting estate store generate rows to database for us EstateSettings originalSettings = db.LoadEstateSettings(REGION_ID, true); new PropertyScrambler() @@ -218,6 +227,8 @@ namespace OpenSim.Data.Tests [Test] public void T020_EstateSettingsManagerList() { + TestHelper.InMethod(); + // Letting estate store generate rows to database for us EstateSettings originalSettings = db.LoadEstateSettings(REGION_ID, true); @@ -237,6 +248,8 @@ namespace OpenSim.Data.Tests [Test] public void T021_EstateSettingsUserList() { + TestHelper.InMethod(); + // Letting estate store generate rows to database for us EstateSettings originalSettings = db.LoadEstateSettings(REGION_ID, true); @@ -256,6 +269,8 @@ namespace OpenSim.Data.Tests [Test] public void T022_EstateSettingsGroupList() { + TestHelper.InMethod(); + // Letting estate store generate rows to database for us EstateSettings originalSettings = db.LoadEstateSettings(REGION_ID, true); @@ -275,6 +290,8 @@ namespace OpenSim.Data.Tests [Test] public void T022_EstateSettingsBanList() { + TestHelper.InMethod(); + // Letting estate store generate rows to database for us EstateSettings originalSettings = db.LoadEstateSettings(REGION_ID, true); diff --git a/OpenSim/Data/Tests/InventoryTests.cs b/OpenSim/Data/Tests/InventoryTests.cs index 6cf7e20f3f..cf3bac1cf9 100644 --- a/OpenSim/Data/Tests/InventoryTests.cs +++ b/OpenSim/Data/Tests/InventoryTests.cs @@ -30,6 +30,7 @@ using log4net.Config; using NUnit.Framework; using OpenMetaverse; using OpenSim.Framework; +using OpenSim.Tests.Common; using log4net; using System.Reflection; using System.Data.Common; @@ -113,6 +114,8 @@ namespace OpenSim.Data.Tests [Test] public void T001_LoadEmpty() { + TestHelper.InMethod(); + Assert.That(db.getInventoryFolder(zero), Is.Null); Assert.That(db.getInventoryFolder(folder1), Is.Null); Assert.That(db.getInventoryFolder(folder2), Is.Null); @@ -131,6 +134,8 @@ namespace OpenSim.Data.Tests [Test] public void T010_FolderNonParent() { + TestHelper.InMethod(); + InventoryFolderBase f1 = NewFolder(folder2, folder1, owner1, name2); // the folder will go in db.addInventoryFolder(f1); @@ -141,6 +146,8 @@ namespace OpenSim.Data.Tests [Test] public void T011_FolderCreate() { + TestHelper.InMethod(); + InventoryFolderBase f1 = NewFolder(folder1, zero, owner1, name1); // TODO: this is probably wrong behavior, but is what we have // db.updateInventoryFolder(f1); @@ -164,6 +171,8 @@ namespace OpenSim.Data.Tests [Test] public void T012_FolderList() { + TestHelper.InMethod(); + InventoryFolderBase f2 = NewFolder(folder3, folder1, owner1, name3); db.addInventoryFolder(f2); @@ -178,6 +187,8 @@ namespace OpenSim.Data.Tests [Test] public void T013_FolderHierarchy() { + TestHelper.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; @@ -191,6 +202,8 @@ namespace OpenSim.Data.Tests [Test] public void T014_MoveFolder() { + TestHelper.InMethod(); + InventoryFolderBase f2 = db.getInventoryFolder(folder2); f2.ParentID = folder3; db.moveInventoryFolder(f2); @@ -205,6 +218,8 @@ namespace OpenSim.Data.Tests [Test] public void T015_FolderHierarchy() { + TestHelper.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))"); @@ -216,6 +231,8 @@ namespace OpenSim.Data.Tests [Test] public void T100_NoItems() { + TestHelper.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))"); @@ -228,6 +245,8 @@ namespace OpenSim.Data.Tests [Test] public void T101_CreatItems() { + TestHelper.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)); @@ -237,6 +256,8 @@ namespace OpenSim.Data.Tests [Test] public void T102_CompareItems() { + TestHelper.InMethod(); + InventoryItemBase i1 = db.getInventoryItem(item1); InventoryItemBase i2 = db.getInventoryItem(item2); InventoryItemBase i3 = db.getInventoryItem(item3); @@ -254,6 +275,8 @@ namespace OpenSim.Data.Tests [Test] public void T103_UpdateItem() { + TestHelper.InMethod(); + // TODO: probably shouldn't have the ability to have an // owner of an item in a folder not owned by the user @@ -272,6 +295,8 @@ namespace OpenSim.Data.Tests [Test] public void T104_RandomUpdateItem() { + TestHelper.InMethod(); + PropertyScrambler folderScrambler = new PropertyScrambler() .DontScramble(x => x.Owner) @@ -329,6 +354,8 @@ namespace OpenSim.Data.Tests [Test] public void T999_StillNull() { + TestHelper.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); diff --git a/OpenSim/Data/Tests/RegionTests.cs b/OpenSim/Data/Tests/RegionTests.cs index 9598716e0d..2dc177a0ce 100644 --- a/OpenSim/Data/Tests/RegionTests.cs +++ b/OpenSim/Data/Tests/RegionTests.cs @@ -35,6 +35,7 @@ using OpenMetaverse; using OpenSim.Framework; using OpenSim.Region.Framework.Interfaces; using OpenSim.Region.Framework.Scenes; +using OpenSim.Tests.Common; using log4net; using System.Reflection; using System.Data.Common; @@ -120,15 +121,18 @@ namespace OpenSim.Data.Tests string[] reg_tables = new string[] { "prims", "primshapes", "primitems", "terrain", "land", "landaccesslist", "regionban", "regionsettings" }; + if (m_rebuildDB) { DropTables(reg_tables); ResetMigrations("RegionStore"); - }else + } + else + { ClearTables(reg_tables); + } } - // Test Plan // Prims // - empty test - 001 @@ -147,6 +151,8 @@ namespace OpenSim.Data.Tests [Test] public void T001_LoadEmpty() { + TestHelper.InMethod(); + List objs = db.LoadObjects(region1); List objs3 = db.LoadObjects(region3); List land = db.LoadLandObjects(region1); @@ -163,6 +169,8 @@ namespace OpenSim.Data.Tests [Test] public void T010_StoreSimpleObject() { + TestHelper.InMethod(); + SceneObjectGroup sog = NewSOG("object1", prim1, region1); SceneObjectGroup sog2 = NewSOG("object2", prim2, region1); @@ -196,6 +204,8 @@ namespace OpenSim.Data.Tests [Test] public void T011_ObjectNames() { + TestHelper.InMethod(); + List objs = db.LoadObjects(region1); foreach (SceneObjectGroup sog in objs) { @@ -208,6 +218,8 @@ namespace OpenSim.Data.Tests [Test] public void T012_SceneParts() { + TestHelper.InMethod(); + UUID tmp0 = UUID.Random(); UUID tmp1 = UUID.Random(); UUID tmp2 = UUID.Random(); @@ -241,6 +253,8 @@ namespace OpenSim.Data.Tests [Test] public void T013_DatabasePersistency() { + TestHelper.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. @@ -416,6 +430,8 @@ namespace OpenSim.Data.Tests [Test] public void T014_UpdateObject() { + TestHelper.InMethod(); + string text1 = "object1 text"; SceneObjectGroup sog = FindSOG("object1", region1); sog.RootPart.Text = text1; @@ -521,6 +537,8 @@ namespace OpenSim.Data.Tests [Test] public void T015_LargeSceneObjects() { + TestHelper.InMethod(); + UUID id = UUID.Random(); Dictionary mydic = new Dictionary(); SceneObjectGroup sog = NewSOG("Test SOG", id, region4); @@ -565,6 +583,8 @@ namespace OpenSim.Data.Tests //[Test] public void T016_RandomSogWithSceneParts() { + TestHelper.InMethod(); + PropertyScrambler scrambler = new PropertyScrambler() .DontScramble(x => x.UUID); @@ -631,15 +651,16 @@ namespace OpenSim.Data.Tests 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() { + TestHelper.InMethod(); + SceneObjectGroup sog = GetMySOG("object1"); TaskInventoryItem t = sog.GetInventoryItem(sog.RootPart.LocalId, item1); Assert.That(t, Is.Null); @@ -659,10 +680,11 @@ namespace OpenSim.Data.Tests db.StorePrimInventory(sog.RootPart.UUID, list); } - [Test] public void T021_PrimInventoryBasic() { + TestHelper.InMethod(); + SceneObjectGroup sog = GetMySOG("object1"); InventoryItemBase i = NewItem(item1, zero, zero, itemname1, zero); @@ -690,20 +712,19 @@ namespace OpenSim.Data.Tests 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() { + TestHelper.InMethod(); + InventoryItemBase i = new InventoryItemBase(); UUID id = UUID.Random(); i.ID = id; @@ -775,6 +796,8 @@ namespace OpenSim.Data.Tests [ExpectedException(typeof(ArgumentException))] public void T026_PrimInventoryMany() { + TestHelper.InMethod(); + UUID i1,i2,i3,i4; i1 = UUID.Random(); i2 = UUID.Random(); @@ -805,15 +828,18 @@ namespace OpenSim.Data.Tests [Test] public void T052_RemoveObject() { + TestHelper.InMethod(); + db.RemoveObject(prim1, region1); SceneObjectGroup sog = FindSOG("object1", region1); Assert.That(sog, Is.Null); } - [Test] public void T100_DefaultRegionInfo() { + TestHelper.InMethod(); + RegionSettings r1 = db.LoadRegionSettings(region1); Assert.That(r1.RegionUUID, Is.EqualTo(region1), "Assert.That(r1.RegionUUID, Is.EqualTo(region1))"); @@ -824,6 +850,8 @@ namespace OpenSim.Data.Tests [Test] public void T101_UpdateRegionInfo() { + TestHelper.InMethod(); + int agentlimit = random.Next(); double objectbonus = random.Next(); int maturity = random.Next(); @@ -922,13 +950,14 @@ namespace OpenSim.Data.Tests //Assert.That(r1a.TerrainImageID,Is.EqualTo(terimgid), "Assert.That(r1a.TerrainImageID,Is.EqualTo(terimgid))"); Assert.That(r1a.FixedSun,Is.True); Assert.That(r1a.SunPosition, Is.EqualTo(sunpos), "Assert.That(r1a.SunPosition, Is.EqualTo(sunpos))"); - Assert.That(r1a.Covenant, Is.EqualTo(cov), "Assert.That(r1a.Covenant, Is.EqualTo(cov))"); - + Assert.That(r1a.Covenant, Is.EqualTo(cov), "Assert.That(r1a.Covenant, Is.EqualTo(cov))"); } [Test] public void T300_NoTerrain() { + TestHelper.InMethod(); + Assert.That(db.LoadTerrain(zero), Is.Null); Assert.That(db.LoadTerrain(region1), Is.Null); Assert.That(db.LoadTerrain(region2), Is.Null); @@ -938,6 +967,8 @@ namespace OpenSim.Data.Tests [Test] public void T301_CreateTerrain() { + TestHelper.InMethod(); + double[,] t1 = GenTerrain(height1); db.StoreTerrain(t1, region1); @@ -950,6 +981,8 @@ namespace OpenSim.Data.Tests [Test] public void T302_FetchTerrain() { + TestHelper.InMethod(); + double[,] baseterrain1 = GenTerrain(height1); double[,] baseterrain2 = GenTerrain(height2); double[,] t1 = db.LoadTerrain(region1); @@ -960,6 +993,8 @@ namespace OpenSim.Data.Tests [Test] public void T303_UpdateTerrain() { + TestHelper.InMethod(); + double[,] baseterrain1 = GenTerrain(height1); double[,] baseterrain2 = GenTerrain(height2); db.StoreTerrain(baseterrain2, region1); @@ -972,6 +1007,8 @@ namespace OpenSim.Data.Tests [Test] public void T400_EmptyLand() { + TestHelper.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))"); From 8509678e483bc7b91721d25d822be0a21e4f7be9 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Mon, 14 Mar 2011 23:26:50 +0000 Subject: [PATCH 76/81] Add method doc to T015_LargeSceneObjects() and slightly clean up formatting. This test takes a considerable time on SQLite but should remain since it's testing storage and retrieval of a scene object with 31 parts. --- OpenSim/Data/Tests/RegionTests.cs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/OpenSim/Data/Tests/RegionTests.cs b/OpenSim/Data/Tests/RegionTests.cs index 2dc177a0ce..edc9d84c9b 100644 --- a/OpenSim/Data/Tests/RegionTests.cs +++ b/OpenSim/Data/Tests/RegionTests.cs @@ -533,7 +533,10 @@ namespace OpenSim.Data.Tests 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() { @@ -543,7 +546,7 @@ namespace OpenSim.Data.Tests 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++) + for (int i = 0; i < 30; i++) { UUID tmp = UUID.Random(); SceneObjectPart sop = NewSOP(("Test SOP " + i.ToString()),tmp); @@ -568,7 +571,7 @@ namespace OpenSim.Data.Tests SceneObjectGroup retsog = FindSOG("Test SOG", region4); SceneObjectPart[] parts = retsog.Parts; - for (int i=0;i<30;i++) + 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))"); From 38c3be07b8e9c6a4cec312118bf908305af6495f Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Mon, 14 Mar 2011 23:32:44 +0000 Subject: [PATCH 77/81] when retrieving a sog in database tests, don't bother adding the scene since this isn't used --- OpenSim/Data/Tests/RegionTests.cs | 15 +-------------- 1 file changed, 1 insertion(+), 14 deletions(-) diff --git a/OpenSim/Data/Tests/RegionTests.cs b/OpenSim/Data/Tests/RegionTests.cs index edc9d84c9b..e049826eb8 100644 --- a/OpenSim/Data/Tests/RegionTests.cs +++ b/OpenSim/Data/Tests/RegionTests.cs @@ -1047,25 +1047,12 @@ namespace OpenSim.Data.Tests return true; } - private SceneObjectGroup FindSOG(string name, UUID r) { List objs = db.LoadObjects(r); foreach (SceneObjectGroup sog in objs) - { - SceneObjectPart p = sog.RootPart; - if (p.Name == name) { - RegionInfo regionInfo = new RegionInfo(); - regionInfo.RegionID = r; - regionInfo.RegionLocX = 0; - regionInfo.RegionLocY = 0; - - Scene scene = new Scene(regionInfo); - sog.SetScene(scene); - + if (sog.Name == name) return sog; - } - } return null; } From fdcf910e00824ceb3db5166a2b3173c882ee059f Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Mon, 14 Mar 2011 23:35:03 +0000 Subject: [PATCH 78/81] Fix a bug in T015_LargeSceneObjects() where the large scene object was stored 31 times (1 time for each added part) instead of once at the end, even though only the largest 31 prim scene object was retrieved and tested. This considerably speeds up the test, when on sqlite it now only takes 2 seconds rather than 30+ --- OpenSim/Data/Tests/RegionTests.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/OpenSim/Data/Tests/RegionTests.cs b/OpenSim/Data/Tests/RegionTests.cs index e049826eb8..44cf1ab3ef 100644 --- a/OpenSim/Data/Tests/RegionTests.cs +++ b/OpenSim/Data/Tests/RegionTests.cs @@ -565,10 +565,11 @@ namespace OpenSim.Data.Tests sop.Acceleration = accel; mydic.Add(tmp,sop); - sog.AddPart(sop); - db.StoreObject(sog, region4); + sog.AddPart(sop); } + db.StoreObject(sog, region4); + SceneObjectGroup retsog = FindSOG("Test SOG", region4); SceneObjectPart[] parts = retsog.Parts; for (int i = 0; i < 30; i++) From 28c335e25f6641b259f1e3315045f253887429e4 Mon Sep 17 00:00:00 2001 From: BlueWall Date: Tue, 15 Mar 2011 17:16:50 -0400 Subject: [PATCH 79/81] Hello, World! --- CONTRIBUTORS.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CONTRIBUTORS.txt b/CONTRIBUTORS.txt index 38343a4bbc..a0af1ca941 100644 --- a/CONTRIBUTORS.txt +++ b/CONTRIBUTORS.txt @@ -28,7 +28,7 @@ people that make the day to day of OpenSim happen. * Diva (Crista Lopes, University of California, Irvine) * nlin (3Di) * Arthur Rodrigo S Valadares (IBM) - +* BlueWall (James Hughes) = Past Open Sim Developers = These folks are alumns of the OpenSim core group, but are now From aadd0e8d42b0a5b401cde9d4d3a56ce2e527201a Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Wed, 16 Mar 2011 00:14:58 +0000 Subject: [PATCH 80/81] minor: bring comment into line with code reality --- OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs b/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs index 953ed856b6..ccec9b70eb 100644 --- a/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs +++ b/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs @@ -633,7 +633,7 @@ namespace OpenSim.Framework.Servers.HttpServer finally { // Every month or so this will wrap and give bad numbers, not really a problem - // since its just for reporting, 200ms limit can be adjusted + // since its just for reporting, tickdiff limit can be adjusted int tickdiff = Environment.TickCount - tickstart; if (tickdiff > 3000) m_log.InfoFormat( From a3651eb5d0325807baa9a2bdc9a1bae8d413bc9f Mon Sep 17 00:00:00 2001 From: BlueWall Date: Thu, 17 Mar 2011 05:48:42 -0400 Subject: [PATCH 81/81] Thanks Kevin Cozens for a patch that: Fixes several spelling mistakes --- .../Rest/Inventory/RestInventoryServices.cs | 6 +++--- OpenSim/Framework/Servers/HttpServer/OSHttpHandler.cs | 2 +- OpenSim/Framework/UndoStack.cs | 2 +- OpenSim/Region/CoreModules/LightShare/LightShareModule.cs | 4 ++-- .../CoreModules/World/LegacyMap/TexturedMapTileRenderer.cs | 6 +++--- 5 files changed, 10 insertions(+), 10 deletions(-) diff --git a/OpenSim/ApplicationPlugins/Rest/Inventory/RestInventoryServices.cs b/OpenSim/ApplicationPlugins/Rest/Inventory/RestInventoryServices.cs index b4156621bb..536f167793 100644 --- a/OpenSim/ApplicationPlugins/Rest/Inventory/RestInventoryServices.cs +++ b/OpenSim/ApplicationPlugins/Rest/Inventory/RestInventoryServices.cs @@ -2129,17 +2129,17 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory } catch (DllNotFoundException) { - Rest.Log.ErrorFormat("OpenJpeg is not installed correctly on this system. Asset Data is emtpy for {0}", ic.Item.Name); + Rest.Log.ErrorFormat("OpenJpeg is not installed correctly on this system. Asset Data is empty for {0}", ic.Item.Name); ic.Asset.Data = new Byte[0]; } catch (IndexOutOfRangeException) { - Rest.Log.ErrorFormat("OpenJpeg was unable to encode this. Asset Data is emtpy for {0}", ic.Item.Name); + Rest.Log.ErrorFormat("OpenJpeg was unable to encode this. Asset Data is empty for {0}", ic.Item.Name); ic.Asset.Data = new Byte[0]; } catch (Exception) { - Rest.Log.ErrorFormat("OpenJpeg was unable to encode this. Asset Data is emtpy for {0}", ic.Item.Name); + Rest.Log.ErrorFormat("OpenJpeg was unable to encode this. Asset Data is empty for {0}", ic.Item.Name); ic.Asset.Data = new Byte[0]; } } diff --git a/OpenSim/Framework/Servers/HttpServer/OSHttpHandler.cs b/OpenSim/Framework/Servers/HttpServer/OSHttpHandler.cs index 129a5449fb..2c2b47ded2 100644 --- a/OpenSim/Framework/Servers/HttpServer/OSHttpHandler.cs +++ b/OpenSim/Framework/Servers/HttpServer/OSHttpHandler.cs @@ -83,7 +83,7 @@ namespace OpenSim.Framework.Servers.HttpServer /// /// Regular expression used to match against path of the /// incoming HTTP request. If you want to match any string - /// either use '.*' or null. To match on the emtpy string use + /// either use '.*' or null. To match on the empty string use /// '^$'. /// public virtual Regex Path diff --git a/OpenSim/Framework/UndoStack.cs b/OpenSim/Framework/UndoStack.cs index 4d800ae425..fde63b1cf1 100644 --- a/OpenSim/Framework/UndoStack.cs +++ b/OpenSim/Framework/UndoStack.cs @@ -90,7 +90,7 @@ namespace OpenSim.Framework return deleted; } else - throw new InvalidOperationException("Cannot pop from emtpy stack"); + throw new InvalidOperationException("Cannot pop from empty stack"); } public T Peek() diff --git a/OpenSim/Region/CoreModules/LightShare/LightShareModule.cs b/OpenSim/Region/CoreModules/LightShare/LightShareModule.cs index 88f392dcdb..00b0aa9137 100644 --- a/OpenSim/Region/CoreModules/LightShare/LightShareModule.cs +++ b/OpenSim/Region/CoreModules/LightShare/LightShareModule.cs @@ -75,7 +75,7 @@ namespace OpenSim.Region.CoreModules.World.LightShare m_scene = scene; m_scene.RegisterModuleInterface(this); m_scene.EventManager.OnPluginConsole += EventManager_OnPluginConsole; - + // ini file settings try { @@ -229,7 +229,7 @@ namespace OpenSim.Region.CoreModules.World.LightShare { Command wlload = new Command("load", CommandIntentions.COMMAND_NON_HAZARDOUS, HandleLoad, "Load windlight profile from the database and broadcast"); Command wlenable = new Command("enable", CommandIntentions.COMMAND_NON_HAZARDOUS, HandleEnable, "Enable the windlight plugin"); - Command wldisable = new Command("disable", CommandIntentions.COMMAND_NON_HAZARDOUS, HandleDisable, "Enable the windlight plugin"); + Command wldisable = new Command("disable", CommandIntentions.COMMAND_NON_HAZARDOUS, HandleDisable, "Disable the windlight plugin"); m_commander.RegisterCommand("load", wlload); m_commander.RegisterCommand("enable", wlenable); diff --git a/OpenSim/Region/CoreModules/World/LegacyMap/TexturedMapTileRenderer.cs b/OpenSim/Region/CoreModules/World/LegacyMap/TexturedMapTileRenderer.cs index 071314ac9a..aa14054cf5 100644 --- a/OpenSim/Region/CoreModules/World/LegacyMap/TexturedMapTileRenderer.cs +++ b/OpenSim/Region/CoreModules/World/LegacyMap/TexturedMapTileRenderer.cs @@ -188,17 +188,17 @@ namespace OpenSim.Region.CoreModules.World.LegacyMap } catch (DllNotFoundException) { - m_log.ErrorFormat("[TexturedMapTileRenderer]: OpenJpeg is not installed correctly on this system. Asset Data is emtpy for {0}", id); + m_log.ErrorFormat("[TexturedMapTileRenderer]: OpenJpeg is not installed correctly on this system. Asset Data is empty for {0}", id); } catch (IndexOutOfRangeException) { - m_log.ErrorFormat("[TexturedMapTileRenderer]: OpenJpeg was unable to encode this. Asset Data is emtpy for {0}", id); + m_log.ErrorFormat("[TexturedMapTileRenderer]: OpenJpeg was unable to encode this. Asset Data is empty for {0}", id); } catch (Exception) { - m_log.ErrorFormat("[TexturedMapTileRenderer]: OpenJpeg was unable to encode this. Asset Data is emtpy for {0}", id); + m_log.ErrorFormat("[TexturedMapTileRenderer]: OpenJpeg was unable to encode this. Asset Data is empty for {0}", id); } return null;