Add regression test for presence crossing between regions on the same simulator.
Unlike a much earlier commented out version of this test, this is done in synchronous mode.user_profiles
							parent
							
								
									a9f380d124
								
							
						
					
					
						commit
						8960418e7d
					
				|  | @ -1613,32 +1613,28 @@ namespace OpenSim.Region.Framework.Scenes | |||
|                     bool controlland = (((flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) != 0) || | ||||
|                                         ((flags & AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG) != 0)); | ||||
| 
 | ||||
| 
 | ||||
|                    //m_log.Debug("[CONTROL]: " +flags); | ||||
|                     // Applies a satisfying roll effect to the avatar when flying. | ||||
|                     if (((flags & AgentManager.ControlFlags.AGENT_CONTROL_TURN_LEFT) != 0) && ((flags & AgentManager.ControlFlags.AGENT_CONTROL_YAW_POS) != 0)) | ||||
|                     if ((flags & AgentManager.ControlFlags.AGENT_CONTROL_TURN_LEFT) != 0 && (flags & AgentManager.ControlFlags.AGENT_CONTROL_YAW_POS) != 0) | ||||
|                     { | ||||
| 
 | ||||
|                         ApplyFlyingRoll(FLY_ROLL_RADIANS_PER_UPDATE, ((flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_POS) != 0), ((flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) != 0)); | ||||
|                          | ||||
|                          | ||||
|                         ApplyFlyingRoll( | ||||
|                             FLY_ROLL_RADIANS_PER_UPDATE,  | ||||
|                             (flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_POS) != 0,  | ||||
|                             (flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) != 0); | ||||
|                     }  | ||||
|                     else if (((flags & AgentManager.ControlFlags.AGENT_CONTROL_TURN_RIGHT) != 0) && | ||||
|                              ((flags & AgentManager.ControlFlags.AGENT_CONTROL_YAW_NEG) != 0)) | ||||
|                     else if ((flags & AgentManager.ControlFlags.AGENT_CONTROL_TURN_RIGHT) != 0 && | ||||
|                              (flags & AgentManager.ControlFlags.AGENT_CONTROL_YAW_NEG) != 0) | ||||
|                     { | ||||
|                         ApplyFlyingRoll(-FLY_ROLL_RADIANS_PER_UPDATE, ((flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_POS) != 0), ((flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) != 0)); | ||||
|                         | ||||
| 
 | ||||
|                         ApplyFlyingRoll( | ||||
|                             -FLY_ROLL_RADIANS_PER_UPDATE,  | ||||
|                             (flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_POS) != 0,  | ||||
|                             (flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) != 0);                       | ||||
|                     } | ||||
|                     else | ||||
|                     { | ||||
|                         if (m_AngularVelocity.Z != 0) | ||||
|                             m_AngularVelocity.Z += CalculateFlyingRollResetToZero(FLY_ROLL_RESET_RADIANS_PER_UPDATE); | ||||
|                          | ||||
|                     } | ||||
| 
 | ||||
|                     | ||||
| 
 | ||||
|                             m_AngularVelocity.Z += CalculateFlyingRollResetToZero(FLY_ROLL_RESET_RADIANS_PER_UPDATE);                         | ||||
|                     }                   | ||||
| 
 | ||||
|                     if (Flying && IsColliding && controlland) | ||||
|                     { | ||||
|  | @ -2400,7 +2396,8 @@ namespace OpenSim.Region.Framework.Scenes | |||
|         /// <param name="vec">The vector in which to move.  This is relative to the rotation argument</param> | ||||
|         public void AddNewMovement(Vector3 vec) | ||||
|         { | ||||
| //            m_log.DebugFormat("[SCENE PRESENCE]: Adding new movement {0} for {1}", vec, Name); | ||||
| //            m_log.DebugFormat( | ||||
| //                "[SCENE PRESENCE]: Adding new movement {0} with rotation {1} for {2}", vec, Rotation, Name); | ||||
| 
 | ||||
|             Vector3 direc = vec * Rotation; | ||||
|             direc.Normalize(); | ||||
|  | @ -2420,6 +2417,8 @@ namespace OpenSim.Region.Framework.Scenes | |||
| 
 | ||||
|             direc *= 0.03f * 128f * SpeedModifier; | ||||
| 
 | ||||
| //            m_log.DebugFormat("[SCENE PRESENCE]: Force to apply before modification was {0} for {1}", direc, Name); | ||||
| 
 | ||||
|             if (PhysicsActor != null) | ||||
|             { | ||||
|                 if (Flying) | ||||
|  | @ -2453,6 +2452,8 @@ namespace OpenSim.Region.Framework.Scenes | |||
|                 } | ||||
|             } | ||||
| 
 | ||||
| //            m_log.DebugFormat("[SCENE PRESENCE]: Setting force to apply to {0} for {1}", direc, Name); | ||||
| 
 | ||||
|             // TODO: Add the force instead of only setting it to support multiple forces per frame? | ||||
|             m_forceToApply = direc; | ||||
|         } | ||||
|  |  | |||
|  | @ -288,109 +288,6 @@ namespace OpenSim.Region.Framework.Scenes.Tests | |||
| //            ScenePresence presence = scene.GetScenePresence(agent1); | ||||
| // | ||||
| //            Assert.That(presence, Is.Null, "presence is not null"); | ||||
| //        } | ||||
| 
 | ||||
|         // 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. | ||||
|         // We need to talk in order to develop a test | ||||
|         // that really tests region crossings. There are 3 async components, | ||||
|         // but things are synchronous among them. So there should be | ||||
|         // 3 threads in here. | ||||
|         //[Test] | ||||
| //        public void T021_TestCrossToNewRegion() | ||||
| //        { | ||||
| //            TestHelpers.InMethod(); | ||||
| // | ||||
| //            scene.RegisterRegionWithGrid(); | ||||
| //            scene2.RegisterRegionWithGrid(); | ||||
| // | ||||
| //            // Adding child agent to region 1001 | ||||
| //            string reason; | ||||
| //            scene2.NewUserConnection(acd1,0, out reason); | ||||
| //            scene2.AddNewClient(testclient, PresenceType.User); | ||||
| // | ||||
| //            ScenePresence presence = scene.GetScenePresence(agent1); | ||||
| //            presence.MakeRootAgent(new Vector3(0,unchecked(Constants.RegionSize-1),0), true); | ||||
| // | ||||
| //            ScenePresence presence2 = scene2.GetScenePresence(agent1); | ||||
| // | ||||
| //           // Adding neighbour region caps info to presence2 | ||||
| // | ||||
| //            string cap = presence.ControllingClient.RequestClientInfo().CapsPath; | ||||
| //            presence2.AddNeighbourRegion(region1, cap); | ||||
| // | ||||
| //            Assert.That(presence.IsChildAgent, Is.False, "Did not start root in origin region."); | ||||
| //            Assert.That(presence2.IsChildAgent, Is.True, "Is not a child on destination region."); | ||||
| // | ||||
| //            // Cross to x+1 | ||||
| //            presence.AbsolutePosition = new Vector3(Constants.RegionSize+1,3,100); | ||||
| //            presence.Update(); | ||||
| // | ||||
| //            EventWaitHandle wh = new EventWaitHandle (false, EventResetMode.AutoReset, "Crossing"); | ||||
| // | ||||
| //            // Mimicking communication between client and server, by waiting OK from client | ||||
| //            // sent by TestClient.CrossRegion call. Originally, this is network comm. | ||||
| //            if (!wh.WaitOne(5000,false)) | ||||
| //            { | ||||
| //                presence.Update(); | ||||
| //                if (!wh.WaitOne(8000,false)) | ||||
| //                    throw new ArgumentException("1 - Timeout waiting for signal/variable."); | ||||
| //            } | ||||
| // | ||||
| //            // This is a TestClient specific method that fires OnCompleteMovementToRegion event, which | ||||
| //            // would normally be fired after receiving the reply packet from comm. done on the last line. | ||||
| //            testclient.CompleteMovement(); | ||||
| // | ||||
| //            // Crossings are asynchronous | ||||
| //            int timer = 10; | ||||
| // | ||||
| //            // Make sure cross hasn't already finished | ||||
| //            if (!presence.IsInTransit && !presence.IsChildAgent) | ||||
| //            { | ||||
| //                // If not and not in transit yet, give it some more time | ||||
| //                Thread.Sleep(5000); | ||||
| //            } | ||||
| // | ||||
| //            // Enough time, should at least be in transit by now. | ||||
| //            while (presence.IsInTransit && timer > 0) | ||||
| //            { | ||||
| //                Thread.Sleep(1000); | ||||
| //                timer-=1; | ||||
| //            } | ||||
| // | ||||
| //            Assert.That(timer,Is.GreaterThan(0),"Timed out waiting to cross 2->1."); | ||||
| //            Assert.That(presence.IsChildAgent, Is.True, "Did not complete region cross as expected."); | ||||
| //            Assert.That(presence2.IsChildAgent, Is.False, "Did not receive root status after receiving agent."); | ||||
| // | ||||
| //            // Cross Back | ||||
| //            presence2.AbsolutePosition = new Vector3(-10, 3, 100); | ||||
| //            presence2.Update(); | ||||
| // | ||||
| //            if (!wh.WaitOne(5000,false)) | ||||
| //            { | ||||
| //                presence2.Update(); | ||||
| //                if (!wh.WaitOne(8000,false)) | ||||
| //                    throw new ArgumentException("2 - Timeout waiting for signal/variable."); | ||||
| //            } | ||||
| //            testclient.CompleteMovement(); | ||||
| // | ||||
| //            if (!presence2.IsInTransit && !presence2.IsChildAgent) | ||||
| //            { | ||||
| //                // If not and not in transit yet, give it some more time | ||||
| //                Thread.Sleep(5000); | ||||
| //            } | ||||
| // | ||||
| //            // Enough time, should at least be in transit by now. | ||||
| //            while (presence2.IsInTransit && timer > 0) | ||||
| //            { | ||||
| //                Thread.Sleep(1000); | ||||
| //                timer-=1; | ||||
| //            } | ||||
| // | ||||
| //            Assert.That(timer,Is.GreaterThan(0),"Timed out waiting to cross 1->2."); | ||||
| //            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."); | ||||
| //        } | ||||
|     } | ||||
| } | ||||
|  | @ -0,0 +1,140 @@ | |||
| /* | ||||
|  * Copyright (c) Contributors, http://opensimulator.org/ | ||||
|  * See CONTRIBUTORS.TXT for a full list of copyright holders. | ||||
|  * | ||||
|  * Redistribution and use in source and binary forms, with or without | ||||
|  * modification, are permitted provided that the following conditions are met: | ||||
|  *     * Redistributions of source code must retain the above copyright | ||||
|  *       notice, this list of conditions and the following disclaimer. | ||||
|  *     * Redistributions in binary form must reproduce the above copyright | ||||
|  *       notice, this list of conditions and the following disclaimer in the | ||||
|  *       documentation and/or other materials provided with the distribution. | ||||
|  *     * Neither the name of the OpenSimulator Project nor the | ||||
|  *       names of its contributors may be used to endorse or promote products | ||||
|  *       derived from this software without specific prior written permission. | ||||
|  * | ||||
|  * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY | ||||
|  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | ||||
|  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | ||||
|  * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY | ||||
|  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | ||||
|  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | ||||
|  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | ||||
|  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||||
|  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | ||||
|  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||||
|  */ | ||||
| 
 | ||||
| using System; | ||||
| using System.Reflection; | ||||
| using Nini.Config; | ||||
| using NUnit.Framework; | ||||
| using OpenMetaverse; | ||||
| using OpenSim.Framework; | ||||
| using OpenSim.Framework.Communications; | ||||
| using OpenSim.Framework.Servers; | ||||
| using OpenSim.Region.Framework.Interfaces; | ||||
| using OpenSim.Region.CoreModules.Framework; | ||||
| using OpenSim.Region.CoreModules.Framework.EntityTransfer; | ||||
| using OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation; | ||||
| using OpenSim.Tests.Common; | ||||
| using OpenSim.Tests.Common.Mock; | ||||
| 
 | ||||
| namespace OpenSim.Region.Framework.Scenes.Tests | ||||
| { | ||||
|     [TestFixture] | ||||
|     public class ScenePresenceCrossingTests : OpenSimTestCase | ||||
|     { | ||||
|         [TestFixtureSetUp] | ||||
|         public void FixtureInit() | ||||
|         { | ||||
|             // Don't allow tests to be bamboozled by asynchronous events.  Execute everything on the same thread. | ||||
|             Util.FireAndForgetMethod = FireAndForgetMethod.RegressionTest; | ||||
|         } | ||||
| 
 | ||||
|         [TestFixtureTearDown] | ||||
|         public void TearDown() | ||||
|         { | ||||
|             // We must set this back afterwards, otherwise later tests will fail since they're expecting multiple | ||||
|             // threads.  Possibly, later tests should be rewritten so none of them require async stuff (which regression | ||||
|             // tests really shouldn't). | ||||
|             Util.FireAndForgetMethod = Util.DefaultFireAndForgetMethod; | ||||
|         } | ||||
| 
 | ||||
|         [Test] | ||||
|         public void TestCrossOnSameSimulator() | ||||
|         { | ||||
|             TestHelpers.InMethod(); | ||||
|             TestHelpers.EnableLogging(); | ||||
| 
 | ||||
|             UUID userId = TestHelpers.ParseTail(0x1); | ||||
| 
 | ||||
|             EntityTransferModule etmA = new EntityTransferModule(); | ||||
|             EntityTransferModule etmB = new EntityTransferModule(); | ||||
|             LocalSimulationConnectorModule lscm = new LocalSimulationConnectorModule(); | ||||
| 
 | ||||
|             IConfigSource config = new IniConfigSource(); | ||||
|             IConfig modulesConfig = config.AddConfig("Modules"); | ||||
|             modulesConfig.Set("EntityTransferModule", etmA.Name); | ||||
|             modulesConfig.Set("SimulationServices", lscm.Name); | ||||
|             IConfig entityTransferConfig = config.AddConfig("EntityTransfer"); | ||||
| 
 | ||||
|             // In order to run a single threaded regression test we do not want the entity transfer module waiting | ||||
|             // for a callback from the destination scene before removing its avatar data. | ||||
| //            entityTransferConfig.Set("wait_for_callback", false); | ||||
| 
 | ||||
|             SceneHelpers sh = new SceneHelpers(); | ||||
|             TestScene sceneA = sh.SetupScene("sceneA", TestHelpers.ParseTail(0x100), 1000, 1000); | ||||
|             TestScene sceneB = sh.SetupScene("sceneB", TestHelpers.ParseTail(0x200), 1000, 999); | ||||
| 
 | ||||
|             SceneHelpers.SetupSceneModules(new Scene[] { sceneA, sceneB }, config, lscm); | ||||
|             SceneHelpers.SetupSceneModules(sceneA, config, new CapabilitiesModule(), etmA); | ||||
|             SceneHelpers.SetupSceneModules(sceneB, config, new CapabilitiesModule(), etmB); | ||||
| 
 | ||||
|             ScenePresence originalSp = SceneHelpers.AddScenePresence(sceneA, userId, sh.SceneManager); | ||||
|             originalSp.AbsolutePosition = new Vector3(128, 32, 10); | ||||
| 
 | ||||
| //            originalSp.Flying = true; | ||||
| 
 | ||||
| //            Console.WriteLine("First pos {0}", originalSp.AbsolutePosition); | ||||
| 
 | ||||
|             AgentUpdateArgs moveArgs = new AgentUpdateArgs(); | ||||
|             //moveArgs.BodyRotation = Quaternion.CreateFromEulers(Vector3.Zero); | ||||
|             moveArgs.BodyRotation = Quaternion.CreateFromEulers(new Vector3(0, 0, (float)-(Math.PI / 2))); | ||||
|             moveArgs.ControlFlags = (uint)AgentManager.ControlFlags.AGENT_CONTROL_AT_POS; | ||||
| 
 | ||||
|             originalSp.HandleAgentUpdate(originalSp.ControllingClient, moveArgs); | ||||
| 
 | ||||
|             sceneA.Update(1); | ||||
| 
 | ||||
| //            Console.WriteLine("Second pos {0}", originalSp.AbsolutePosition); | ||||
| 
 | ||||
|             // FIXME: This is a sufficient number of updates to for the presence to reach the northern border. | ||||
|             // But really we want to do this in a more robust way. | ||||
|             for (int i = 0; i < 100; i++) | ||||
|             { | ||||
|                 sceneA.Update(1); | ||||
| //                Console.WriteLine("Pos {0}", originalSp.AbsolutePosition); | ||||
|             } | ||||
| 
 | ||||
|             // sceneA should now only have a child agent | ||||
|             ScenePresence spAfterCrossSceneA = sceneA.GetScenePresence(originalSp.UUID); | ||||
|             Assert.That(spAfterCrossSceneA.IsChildAgent, Is.True); | ||||
| 
 | ||||
|             ScenePresence spAfterCrossSceneB = sceneB.GetScenePresence(originalSp.UUID); | ||||
| 
 | ||||
|             // Agent remains a child until the client triggers complete movement | ||||
|             Assert.That(spAfterCrossSceneB.IsChildAgent, Is.True); | ||||
| 
 | ||||
|             TestClient sceneBTc = ((TestClient)spAfterCrossSceneB.ControllingClient); | ||||
| 
 | ||||
|             bool receivedCompleteMovement = false; | ||||
|             sceneBTc.OnReceivedMoveAgentIntoRegion += (ri, pos, look) => receivedCompleteMovement = true; | ||||
| 
 | ||||
|             sceneBTc.CompleteMovement(); | ||||
| 
 | ||||
|             Assert.That(receivedCompleteMovement, Is.True); | ||||
|             Assert.That(spAfterCrossSceneB.IsChildAgent, Is.False); | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | @ -102,6 +102,8 @@ namespace OpenSim.Region.Physics.BasicPhysicsPlugin | |||
| 
 | ||||
|         public override float Simulate(float timeStep) | ||||
|         { | ||||
| //            Console.WriteLine("Simulating"); | ||||
| 
 | ||||
|             float fps = 0; | ||||
|             for (int i = 0; i < _actors.Count; ++i) | ||||
|             { | ||||
|  | @ -109,8 +111,11 @@ namespace OpenSim.Region.Physics.BasicPhysicsPlugin | |||
|                 Vector3 actorPosition = actor.Position; | ||||
|                 Vector3 actorVelocity = actor.Velocity; | ||||
| 
 | ||||
|                 actorPosition.X += actor.Velocity.X*timeStep; | ||||
|                 actorPosition.Y += actor.Velocity.Y*timeStep; | ||||
| //                Console.WriteLine( | ||||
| //                    "Processing actor {0}, starting pos {1}, starting vel {2}", i, actorPosition, actorVelocity); | ||||
| 
 | ||||
|                 actorPosition.X += actor.Velocity.X * timeStep; | ||||
|                 actorPosition.Y += actor.Velocity.Y * timeStep; | ||||
| 
 | ||||
|                 if (actor.Position.Y < 0) | ||||
|                 { | ||||
|  |  | |||
|  | @ -60,6 +60,8 @@ namespace OpenSim.Tests.Common.Mock | |||
|         public List<ImagePacketPacket> SentImagePacketPackets { get; private set; } | ||||
|         public List<ImageNotInDatabasePacket> SentImageNotInDatabasePackets { get; private set; } | ||||
| 
 | ||||
|         public event Action<RegionInfo, Vector3, Vector3> OnReceivedMoveAgentIntoRegion; | ||||
| 
 | ||||
| // disable warning: public events, part of the public API | ||||
| #pragma warning disable 67 | ||||
| 
 | ||||
|  | @ -566,6 +568,8 @@ namespace OpenSim.Tests.Common.Mock | |||
| 
 | ||||
|         public virtual void MoveAgentIntoRegion(RegionInfo regInfo, Vector3 pos, Vector3 look) | ||||
|         { | ||||
|             if (OnReceivedMoveAgentIntoRegion != null) | ||||
|                 OnReceivedMoveAgentIntoRegion(regInfo, pos, look); | ||||
|         } | ||||
| 
 | ||||
|         public virtual AgentCircuitData RequestClientInfo() | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue
	
	 Justin Clark-Casey (justincc)
						Justin Clark-Casey (justincc)