From 8960418e7d51a0f861e7b4cb800f007d76862c9c Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Wed, 6 Mar 2013 21:37:53 +0000 Subject: 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. --- OpenSim/Region/Framework/Scenes/ScenePresence.cs | 37 +++--- .../Scenes/Tests/ScenePresenceAgentTests.cs | 103 --------------- .../Scenes/Tests/ScenePresenceCrossingTests.cs | 140 +++++++++++++++++++++ .../BasicPhysicsPlugin/BasicPhysicsScene.cs | 9 +- OpenSim/Tests/Common/Mock/TestClient.cs | 4 + 5 files changed, 170 insertions(+), 123 deletions(-) create mode 100644 OpenSim/Region/Framework/Scenes/Tests/ScenePresenceCrossingTests.cs (limited to 'OpenSim') diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs index 39a885c..a7c7539 100644 --- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs +++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs @@ -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 /// The vector in which to move. This is relative to the rotation argument 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; } diff --git a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAgentTests.cs b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAgentTests.cs index 5faf131..bbfbbfc 100644 --- a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAgentTests.cs +++ b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAgentTests.cs @@ -289,108 +289,5 @@ namespace OpenSim.Region.Framework.Scenes.Tests // // 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."); -// } } } \ No newline at end of file diff --git a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceCrossingTests.cs b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceCrossingTests.cs new file mode 100644 index 0000000..ef9fff5 --- /dev/null +++ b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceCrossingTests.cs @@ -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); + } + } +} \ No newline at end of file diff --git a/OpenSim/Region/Physics/BasicPhysicsPlugin/BasicPhysicsScene.cs b/OpenSim/Region/Physics/BasicPhysicsPlugin/BasicPhysicsScene.cs index c4b9117..0816b7b 100644 --- a/OpenSim/Region/Physics/BasicPhysicsPlugin/BasicPhysicsScene.cs +++ b/OpenSim/Region/Physics/BasicPhysicsPlugin/BasicPhysicsScene.cs @@ -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) { diff --git a/OpenSim/Tests/Common/Mock/TestClient.cs b/OpenSim/Tests/Common/Mock/TestClient.cs index 182f4d9..a448cc5 100644 --- a/OpenSim/Tests/Common/Mock/TestClient.cs +++ b/OpenSim/Tests/Common/Mock/TestClient.cs @@ -60,6 +60,8 @@ namespace OpenSim.Tests.Common.Mock public List SentImagePacketPackets { get; private set; } public List SentImageNotInDatabasePackets { get; private set; } + public event Action 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() -- cgit v1.1