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.0.7.1-dev
parent
e774679f62
commit
88da253c94
|
@ -129,7 +129,16 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
protected ICapabilitiesModule m_capsModule;
|
protected ICapabilitiesModule m_capsModule;
|
||||||
// Central Update Loop
|
// Central Update Loop
|
||||||
protected int m_fps = 10;
|
protected int m_fps = 10;
|
||||||
protected uint m_frame;
|
|
||||||
|
/// <summary>
|
||||||
|
/// Current scene frame number
|
||||||
|
/// </summary>
|
||||||
|
public uint Frame
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
protected set;
|
||||||
|
}
|
||||||
|
|
||||||
protected float m_timespan = 0.089f;
|
protected float m_timespan = 0.089f;
|
||||||
protected DateTime m_lastupdate = DateTime.UtcNow;
|
protected DateTime m_lastupdate = DateTime.UtcNow;
|
||||||
|
|
||||||
|
@ -1183,7 +1192,8 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
Update();
|
while (!shuttingdown)
|
||||||
|
Update();
|
||||||
|
|
||||||
m_lastUpdate = Util.EnvironmentTickCount();
|
m_lastUpdate = Util.EnvironmentTickCount();
|
||||||
m_firstHeartbeat = false;
|
m_firstHeartbeat = false;
|
||||||
|
@ -1200,188 +1210,177 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
Watchdog.RemoveThread();
|
Watchdog.RemoveThread();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Performs per-frame updates on the scene, this should be the central scene loop
|
|
||||||
/// </summary>
|
|
||||||
public override void Update()
|
public override void Update()
|
||||||
{
|
{
|
||||||
float physicsFPS;
|
TimeSpan SinceLastFrame = DateTime.UtcNow - m_lastupdate;
|
||||||
int maintc;
|
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;
|
// Check if any objects have reached their targets
|
||||||
physicsFPS = 0f;
|
CheckAtTargets();
|
||||||
|
|
||||||
maintc = Util.EnvironmentTickCount();
|
// Update SceneObjectGroups that have scheduled themselves for updates
|
||||||
int tmpFrameMS = maintc;
|
// Objects queue their updates onto all scene presences
|
||||||
tempOnRezMS = eventMS = backupMS = terrainMS = landMS = 0;
|
if (Frame % m_update_objects == 0)
|
||||||
|
m_sceneGraph.UpdateObjectGroups();
|
||||||
|
|
||||||
// Increment the frame counter
|
// Run through all ScenePresences looking for updates
|
||||||
++m_frame;
|
// 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
|
List<Vector3> coarseLocations;
|
||||||
CheckAtTargets();
|
List<UUID> avatarUUIDs;
|
||||||
|
SceneGraph.GetCoarseLocations(out coarseLocations, out avatarUUIDs, 60);
|
||||||
// Update SceneObjectGroups that have scheduled themselves for updates
|
// Send coarse locations to clients
|
||||||
// Objects queue their updates onto all scene presences
|
ForEachScenePresence(delegate(ScenePresence presence)
|
||||||
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<Vector3> coarseLocations;
|
presence.SendCoarseLocations(coarseLocations, avatarUUIDs);
|
||||||
List<UUID> avatarUUIDs;
|
});
|
||||||
SceneGraph.GetCoarseLocations(out coarseLocations, out avatarUUIDs, 60);
|
}
|
||||||
// Send coarse locations to clients
|
|
||||||
ForEachScenePresence(delegate(ScenePresence presence)
|
int tmpPhysicsMS2 = Util.EnvironmentTickCount();
|
||||||
{
|
if ((Frame % m_update_physics == 0) && m_physics_enabled)
|
||||||
presence.SendCoarseLocations(coarseLocations, avatarUUIDs);
|
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 (Frame % m_update_backup == 0)
|
||||||
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 (m_physics_enabled)
|
int backMS = Util.EnvironmentTickCount();
|
||||||
physicsFPS = m_sceneGraph.UpdatePhysics(Math.Max(SinceLastFrame.TotalSeconds, m_timespan));
|
UpdateStorageBackup();
|
||||||
if (SynchronizeScene != null)
|
backupMS = Util.EnvironmentTickCountSubtract(backMS);
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (RegionStatus != RegionStatus.SlaveScene)
|
if (Frame % m_update_terrain == 0)
|
||||||
{
|
{
|
||||||
if (m_frame % m_update_events == 0)
|
int terMS = Util.EnvironmentTickCount();
|
||||||
{
|
UpdateTerrain();
|
||||||
int evMS = Util.EnvironmentTickCount();
|
terrainMS = Util.EnvironmentTickCountSubtract(terMS);
|
||||||
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());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (LoginsDisabled && m_frame == 20)
|
//if (Frame % m_update_land == 0)
|
||||||
{
|
//{
|
||||||
// In 99.9% of cases it is a bad idea to manually force garbage collection. However,
|
// int ldMS = Util.EnvironmentTickCount();
|
||||||
// this is a rare case where we know we have just went through a long cycle of heap
|
// UpdateLand();
|
||||||
// allocations, and there is no more work to be done until someone logs in
|
// landMS = Util.EnvironmentTickCountSubtract(ldMS);
|
||||||
GC.Collect();
|
//}
|
||||||
|
|
||||||
IConfig startupConfig = m_config.Configs["Startup"];
|
frameMS = Util.EnvironmentTickCountSubtract(tmpFrameMS);
|
||||||
if (startupConfig == null || !startupConfig.GetBoolean("StartDisabled", false))
|
otherMS = tempOnRezMS + eventMS + backupMS + terrainMS + landMS;
|
||||||
{
|
lastCompletedFrame = Util.EnvironmentTickCount();
|
||||||
m_log.DebugFormat("[REGION]: Enabling logins for {0}", RegionInfo.RegionName);
|
|
||||||
LoginsDisabled = false;
|
// if (Frame%m_update_avatars == 0)
|
||||||
m_sceneGridService.InformNeighborsThatRegionisUp(RequestModuleInterface<INeighbourService>(), RegionInfo);
|
// 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<INeighbourService>(), 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)
|
public void AddGroupTarget(SceneObjectGroup grp)
|
||||||
{
|
{
|
||||||
lock (m_groupsWithTargets)
|
lock (m_groupsWithTargets)
|
||||||
|
|
|
@ -116,9 +116,6 @@ namespace OpenSim.Region.Framework.Scenes.Tests
|
||||||
agent.ChildrenCapSeeds = new Dictionary<ulong, string>();
|
agent.ChildrenCapSeeds = new Dictionary<ulong, string>();
|
||||||
agent.child = true;
|
agent.child = true;
|
||||||
|
|
||||||
if (scene.PresenceService == null)
|
|
||||||
Console.WriteLine("Presence Service is null");
|
|
||||||
|
|
||||||
scene.PresenceService.LoginAgent(agent.AgentID.ToString(), agent.SessionID, agent.SecureSessionID);
|
scene.PresenceService.LoginAgent(agent.AgentID.ToString(), agent.SessionID, agent.SecureSessionID);
|
||||||
|
|
||||||
string reason;
|
string reason;
|
||||||
|
|
|
@ -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
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Scene presence tests
|
||||||
|
/// </summary>
|
||||||
|
[TestFixture]
|
||||||
|
public class SceneTests
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Very basic scene update test. Should become more elaborate with time.
|
||||||
|
/// </summary>
|
||||||
|
[Test]
|
||||||
|
public void TestUpdateScene()
|
||||||
|
{
|
||||||
|
TestHelper.InMethod();
|
||||||
|
|
||||||
|
Scene scene = SceneSetupHelpers.SetupScene();
|
||||||
|
scene.Update();
|
||||||
|
|
||||||
|
Assert.That(scene.Frame, Is.EqualTo(1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue