Merge branch 'master' of /home/opensim/var/repo/opensim

integration
BlueWall 2012-08-30 12:17:39 -04:00
commit 48ebea163b
31 changed files with 1033 additions and 196 deletions

4
.gitignore vendored
View File

@ -30,6 +30,10 @@ bin/*.db-journal
bin/addin-db-* bin/addin-db-*
bin/*.dll bin/*.dll
bin/OpenSim.vshost.exe.config bin/OpenSim.vshost.exe.config
bin/OpenSim.32BitLaunch.vshost.exe.config
bin/OpenSim.32BitLaunch.log
UpgradeLog.XML
_UpgradeReport_Files/
bin/ScriptEngines/*-*-*-*-* bin/ScriptEngines/*-*-*-*-*
bin/ScriptEngines/*.dll bin/ScriptEngines/*.dll
bin/ScriptEngines/*/*.dll bin/ScriptEngines/*/*.dll

View File

@ -135,14 +135,25 @@
<delete dir="%temp%"/> <delete dir="%temp%"/>
</target> </target>
<target name="torture" depends="build, find-nunit"> <target name="test-stress" depends="build, find-nunit">
<setenv name="MONO_THREADS_PER_CPU" value="100" /> <setenv name="MONO_THREADS_PER_CPU" value="100" />
<exec program="${nunitcmd}" failonerror="true" resultproperty="testresult.opensim.tests.torture"> <exec program="${nunitcmd}" failonerror="true" resultproperty="testresult.opensim.tests.stress">
<arg value="./bin/OpenSim.Tests.Torture.dll" /> <arg value="./bin/OpenSim.Tests.Stress.dll" />
</exec> </exec>
<fail message="Failures reported in unit tests." unless="${int::parse(testresult.opensim.tests.torture)==0}" /> <fail message="Failures reported in stress tests." unless="${int::parse(testresult.opensim.tests.stress)==0}" />
<delete dir="%temp%"/>
</target>
<target name="test-perf" depends="build, find-nunit">
<setenv name="MONO_THREADS_PER_CPU" value="100" />
<exec program="${nunitcmd}" failonerror="true" resultproperty="testresult.opensim.tests.performance">
<arg value="./bin/OpenSim.Tests.Performance.dll" />
</exec>
<fail message="Failures reported in performance tests." unless="${int::parse(testresult.opensim.tests.performance)==0}" />
<delete dir="%temp%"/> <delete dir="%temp%"/>
</target> </target>

View File

@ -40,6 +40,11 @@ namespace OpenSim.Data
public UUID folderID; public UUID folderID;
public UUID agentID; public UUID agentID;
public UUID parentFolderID; public UUID parentFolderID;
public XInventoryFolder Clone()
{
return (XInventoryFolder)MemberwiseClone();
}
} }
public class XInventoryItem public class XInventoryItem
@ -64,6 +69,11 @@ namespace OpenSim.Data
public UUID avatarID; public UUID avatarID;
public UUID parentFolderID; public UUID parentFolderID;
public int inventoryGroupPermissions; public int inventoryGroupPermissions;
public XInventoryItem Clone()
{
return (XInventoryItem)MemberwiseClone();
}
} }
public interface IXInventoryData public interface IXInventoryData

View File

@ -73,32 +73,26 @@ namespace OpenSim.Framework
{ {
} }
public InventoryFolderBase(UUID id) public InventoryFolderBase(UUID id) : this()
{ {
ID = id; ID = id;
} }
public InventoryFolderBase(UUID id, UUID owner) public InventoryFolderBase(UUID id, UUID owner) : this(id)
{ {
ID = id;
Owner = owner; Owner = owner;
} }
public InventoryFolderBase(UUID id, string name, UUID owner, UUID parent) public InventoryFolderBase(UUID id, string name, UUID owner, UUID parent) : this(id, owner)
{ {
ID = id;
Name = name; Name = name;
Owner = owner;
ParentID = parent; ParentID = parent;
} }
public InventoryFolderBase(UUID id, string name, UUID owner, short type, UUID parent, ushort version) public InventoryFolderBase(
UUID id, string name, UUID owner, short type, UUID parent, ushort version) : this(id, name, owner, parent)
{ {
ID = id;
Name = name;
Owner = owner;
Type = type; Type = type;
ParentID = parent;
Version = version; Version = version;
} }
} }

View File

@ -65,9 +65,14 @@ namespace OpenSim.Framework.Serialization
UserAccount account = userService.GetUserAccount(UUID.Zero, userId); UserAccount account = userService.GetUserAccount(UUID.Zero, userId);
if (account != null) if (account != null)
{
return MakeOspa(account.FirstName, account.LastName); return MakeOspa(account.FirstName, account.LastName);
}
// else // else
// {
// m_log.WarnFormat("[OSP RESOLVER]: No user account for {0}", userId); // m_log.WarnFormat("[OSP RESOLVER]: No user account for {0}", userId);
// System.Console.WriteLine("[OSP RESOLVER]: No user account for {0}", userId);
// }
return null; return null;
} }
@ -79,10 +84,13 @@ namespace OpenSim.Framework.Serialization
/// <returns></returns> /// <returns></returns>
public static string MakeOspa(string firstName, string lastName) public static string MakeOspa(string firstName, string lastName)
{ {
// m_log.DebugFormat("[OSP RESOLVER]: Making OSPA for {0} {1}", firstName, lastName); string ospa
= OSPA_PREFIX + OSPA_NAME_KEY + OSPA_PAIR_SEPARATOR + firstName + OSPA_NAME_VALUE_SEPARATOR + lastName;
return // m_log.DebugFormat("[OSP RESOLVER]: Made OSPA {0} for {1} {2}", ospa, firstName, lastName);
OSPA_PREFIX + OSPA_NAME_KEY + OSPA_PAIR_SEPARATOR + firstName + OSPA_NAME_VALUE_SEPARATOR + lastName; // System.Console.WriteLine("[OSP RESOLVER]: Made OSPA {0} for {1} {2}", ospa, firstName, lastName);
return ospa;
} }
/// <summary> /// <summary>

View File

@ -350,38 +350,38 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests
Assert.That(sog1.RootPart.CreatorID, Is.EqualTo(m_uaLL1.PrincipalID)); Assert.That(sog1.RootPart.CreatorID, Is.EqualTo(m_uaLL1.PrincipalID));
} }
/// <summary> // /// <summary>
/// Test loading a V0.1 OpenSim Inventory Archive (subject to change since there is no fixed format yet) where // /// 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. // /// an account exists with the same name as the creator, though not the same id.
/// </summary> // /// </summary>
[Test] // [Test]
public void TestLoadIarV0_1SameNameCreator() // public void TestLoadIarV0_1SameNameCreator()
{ // {
TestHelpers.InMethod(); // TestHelpers.InMethod();
// log4net.Config.XmlConfigurator.Configure(); // TestHelpers.EnableLogging();
//
UserAccountHelpers.CreateUserWithInventory(m_scene, m_uaMT, "meowfood"); // UserAccountHelpers.CreateUserWithInventory(m_scene, m_uaMT, "meowfood");
UserAccountHelpers.CreateUserWithInventory(m_scene, m_uaLL2, "hampshire"); // UserAccountHelpers.CreateUserWithInventory(m_scene, m_uaLL2, "hampshire");
//
m_archiverModule.DearchiveInventory(m_uaMT.FirstName, m_uaMT.LastName, "/", "meowfood", m_iarStream); // m_archiverModule.DearchiveInventory(m_uaMT.FirstName, m_uaMT.LastName, "/", "meowfood", m_iarStream);
InventoryItemBase foundItem1 // InventoryItemBase foundItem1
= InventoryArchiveUtils.FindItemByPath(m_scene.InventoryService, m_uaMT.PrincipalID, m_item1Name); // = InventoryArchiveUtils.FindItemByPath(m_scene.InventoryService, m_uaMT.PrincipalID, m_item1Name);
//
Assert.That( // Assert.That(
foundItem1.CreatorId, Is.EqualTo(m_uaLL2.PrincipalID.ToString()), // foundItem1.CreatorId, Is.EqualTo(m_uaLL2.PrincipalID.ToString()),
"Loaded item non-uuid creator doesn't match original"); // "Loaded item non-uuid creator doesn't match original");
Assert.That( // Assert.That(
foundItem1.CreatorIdAsUuid, Is.EqualTo(m_uaLL2.PrincipalID), // foundItem1.CreatorIdAsUuid, Is.EqualTo(m_uaLL2.PrincipalID),
"Loaded item uuid creator doesn't match original"); // "Loaded item uuid creator doesn't match original");
Assert.That(foundItem1.Owner, Is.EqualTo(m_uaMT.PrincipalID), // Assert.That(foundItem1.Owner, Is.EqualTo(m_uaMT.PrincipalID),
"Loaded item owner doesn't match inventory reciever"); // "Loaded item owner doesn't match inventory reciever");
//
AssetBase asset1 = m_scene.AssetService.Get(foundItem1.AssetID.ToString()); // AssetBase asset1 = m_scene.AssetService.Get(foundItem1.AssetID.ToString());
string xmlData = Utils.BytesToString(asset1.Data); // string xmlData = Utils.BytesToString(asset1.Data);
SceneObjectGroup sog1 = SceneObjectSerializer.FromOriginalXmlFormat(xmlData); // SceneObjectGroup sog1 = SceneObjectSerializer.FromOriginalXmlFormat(xmlData);
//
Assert.That(sog1.RootPart.CreatorID, Is.EqualTo(m_uaLL2.PrincipalID)); // Assert.That(sog1.RootPart.CreatorID, Is.EqualTo(m_uaLL2.PrincipalID));
} // }
/// <summary> /// <summary>
/// Test loading a V0.1 OpenSim Inventory Archive (subject to change since there is no fixed format yet) where /// Test loading a V0.1 OpenSim Inventory Archive (subject to change since there is no fixed format yet) where

View File

@ -49,6 +49,11 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
public const int DISP_EXPIRE = 1; public const int DISP_EXPIRE = 1;
public const int DISP_TEMP = 2; public const int DISP_TEMP = 2;
/// <summary>
/// If true then where possible dynamic textures are reused.
/// </summary>
public bool ReuseTextures { get; set; }
private Dictionary<UUID, Scene> RegisteredScenes = new Dictionary<UUID, Scene>(); private Dictionary<UUID, Scene> RegisteredScenes = new Dictionary<UUID, Scene>();
private Dictionary<string, IDynamicTextureRender> RenderPlugins = private Dictionary<string, IDynamicTextureRender> RenderPlugins =
@ -56,6 +61,15 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
private Dictionary<UUID, DynamicTextureUpdater> Updaters = new Dictionary<UUID, DynamicTextureUpdater>(); private Dictionary<UUID, DynamicTextureUpdater> Updaters = new Dictionary<UUID, DynamicTextureUpdater>();
/// <summary>
/// Record dynamic textures that we can reuse for a given data and parameter combination rather than
/// regenerate.
/// </summary>
/// <remarks>
/// Key is string.Format("{0}{1}", data
/// </remarks>
private Cache m_reuseableDynamicTextures;
#region IDynamicTextureManager Members #region IDynamicTextureManager Members
public void RegisterRender(string handleType, IDynamicTextureRender render) public void RegisterRender(string handleType, IDynamicTextureRender render)
@ -71,7 +85,8 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
/// </summary> /// </summary>
/// <param name="id"></param> /// <param name="id"></param>
/// <param name="data"></param> /// <param name="data"></param>
public void ReturnData(UUID id, byte[] data) /// <param name="isReuseable">True if the data generated can be reused for subsequent identical requests</param>
public void ReturnData(UUID id, byte[] data, bool isReuseable)
{ {
DynamicTextureUpdater updater = null; DynamicTextureUpdater updater = null;
@ -88,7 +103,11 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
if (RegisteredScenes.ContainsKey(updater.SimUUID)) if (RegisteredScenes.ContainsKey(updater.SimUUID))
{ {
Scene scene = RegisteredScenes[updater.SimUUID]; Scene scene = RegisteredScenes[updater.SimUUID];
updater.DataReceived(data, scene); UUID newTextureID = updater.DataReceived(data, scene);
if (ReuseTextures && isReuseable && !updater.BlendWithOldTexture)
m_reuseableDynamicTextures.Store(
GenerateReusableTextureKey(updater.BodyData, updater.Params), newTextureID);
} }
} }
@ -169,6 +188,11 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
{ {
if (RenderPlugins.ContainsKey(contentType)) if (RenderPlugins.ContainsKey(contentType))
{ {
// If we want to reuse dynamic textures then we have to ignore any request from the caller to expire
// them.
if (ReuseTextures)
disp = disp & ~DISP_EXPIRE;
DynamicTextureUpdater updater = new DynamicTextureUpdater(); DynamicTextureUpdater updater = new DynamicTextureUpdater();
updater.SimUUID = simID; updater.SimUUID = simID;
updater.PrimID = primID; updater.PrimID = primID;
@ -183,6 +207,15 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
updater.Url = "Local image"; updater.Url = "Local image";
updater.Disp = disp; updater.Disp = disp;
object reusableTextureUUID = null;
if (ReuseTextures)
reusableTextureUUID
= m_reuseableDynamicTextures.Get(GenerateReusableTextureKey(data, extraParams));
// We cannot reuse a dynamic texture if the data is going to be blended with something already there.
if (reusableTextureUUID == null || updater.BlendWithOldTexture)
{
lock (Updaters) lock (Updaters)
{ {
if (!Updaters.ContainsKey(updater.UpdaterID)) if (!Updaters.ContainsKey(updater.UpdaterID))
@ -192,12 +225,31 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
} }
RenderPlugins[contentType].AsyncConvertData(updater.UpdaterID, data, extraParams); RenderPlugins[contentType].AsyncConvertData(updater.UpdaterID, data, extraParams);
}
else
{
// No need to add to updaters as the texture is always the same. Not that this functionality
// apppears to be implemented anyway.
if (RegisteredScenes.ContainsKey(updater.SimUUID))
{
SceneObjectPart part = RegisteredScenes[updater.SimUUID].GetSceneObjectPart(updater.PrimID);
if (part != null)
updater.UpdatePart(part, (UUID)reusableTextureUUID);
}
}
return updater.UpdaterID; return updater.UpdaterID;
} }
return UUID.Zero; return UUID.Zero;
} }
private string GenerateReusableTextureKey(string data, string extraParams)
{
return string.Format("{0}{1}", data, extraParams);
}
public void GetDrawStringSize(string contentType, string text, string fontName, int fontSize, public void GetDrawStringSize(string contentType, string text, string fontName, int fontSize,
out double xSize, out double ySize) out double xSize, out double ySize)
{ {
@ -224,6 +276,12 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
public void PostInitialise() public void PostInitialise()
{ {
// ReuseTextures = true;
if (ReuseTextures)
{
m_reuseableDynamicTextures = new Cache(CacheMedium.Memory, CacheStrategy.Conservative);
m_reuseableDynamicTextures.DefaultTTL = new TimeSpan(24, 0, 0);
}
} }
public void Close() public void Close()
@ -268,10 +326,61 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
BodyData = null; BodyData = null;
} }
/// <summary>
/// Update the given part with the new texture.
/// </summary>
/// <returns>
/// The old texture UUID.
/// </returns>
public UUID UpdatePart(SceneObjectPart part, UUID textureID)
{
UUID oldID;
lock (part)
{
// mostly keep the values from before
Primitive.TextureEntry tmptex = part.Shape.Textures;
// FIXME: Need to return the appropriate ID if only a single face is replaced.
oldID = tmptex.DefaultTexture.TextureID;
if (Face == ALL_SIDES)
{
oldID = tmptex.DefaultTexture.TextureID;
tmptex.DefaultTexture.TextureID = textureID;
}
else
{
try
{
Primitive.TextureEntryFace texface = tmptex.CreateFace((uint)Face);
texface.TextureID = textureID;
tmptex.FaceTextures[Face] = texface;
}
catch (Exception)
{
tmptex.DefaultTexture.TextureID = textureID;
}
}
// I'm pretty sure we always want to force this to true
// I'm pretty sure noone whats to set fullbright true if it wasn't true before.
// tmptex.DefaultTexture.Fullbright = true;
part.UpdateTextureEntry(tmptex.GetBytes());
}
return oldID;
}
/// <summary> /// <summary>
/// Called once new texture data has been received for this updater. /// Called once new texture data has been received for this updater.
/// </summary> /// </summary>
public void DataReceived(byte[] data, Scene scene) /// <param name="data"></param>
/// <param name="scene"></param>
/// <param name="isReuseable">True if the data given is reuseable.</param>
/// <returns>The asset UUID given to the incoming data.</returns>
public UUID DataReceived(byte[] data, Scene scene)
{ {
SceneObjectPart part = scene.GetSceneObjectPart(PrimID); SceneObjectPart part = scene.GetSceneObjectPart(PrimID);
@ -281,7 +390,8 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
String.Format("DynamicTextureModule: Error preparing image using URL {0}", Url); String.Format("DynamicTextureModule: Error preparing image using URL {0}", Url);
scene.SimChat(Utils.StringToBytes(msg), ChatTypeEnum.Say, scene.SimChat(Utils.StringToBytes(msg), ChatTypeEnum.Say,
0, part.ParentGroup.RootPart.AbsolutePosition, part.Name, part.UUID, false); 0, part.ParentGroup.RootPart.AbsolutePosition, part.Name, part.UUID, false);
return;
return UUID.Zero;
} }
byte[] assetData = null; byte[] assetData = null;
@ -323,52 +433,23 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
cacheLayerDecode = null; cacheLayerDecode = null;
} }
UUID oldID = UUID.Zero; UUID oldID = UpdatePart(part, asset.FullID);
lock (part)
{
// mostly keep the values from before
Primitive.TextureEntry tmptex = part.Shape.Textures;
// remove the old asset from the cache
oldID = tmptex.DefaultTexture.TextureID;
if (Face == ALL_SIDES)
{
tmptex.DefaultTexture.TextureID = asset.FullID;
}
else
{
try
{
Primitive.TextureEntryFace texface = tmptex.CreateFace((uint)Face);
texface.TextureID = asset.FullID;
tmptex.FaceTextures[Face] = texface;
}
catch (Exception)
{
tmptex.DefaultTexture.TextureID = asset.FullID;
}
}
// I'm pretty sure we always want to force this to true
// I'm pretty sure noone whats to set fullbright true if it wasn't true before.
// tmptex.DefaultTexture.Fullbright = true;
part.UpdateTextureEntry(tmptex.GetBytes());
}
if (oldID != UUID.Zero && ((Disp & DISP_EXPIRE) != 0)) if (oldID != UUID.Zero && ((Disp & DISP_EXPIRE) != 0))
{ {
if (oldAsset == null) oldAsset = scene.AssetService.Get(oldID.ToString()); if (oldAsset == null)
oldAsset = scene.AssetService.Get(oldID.ToString());
if (oldAsset != null) if (oldAsset != null)
{ {
if (oldAsset.Temporary == true) if (oldAsset.Temporary)
{ {
scene.AssetService.Delete(oldID.ToString()); scene.AssetService.Delete(oldID.ToString());
} }
} }
} }
return asset.FullID;
} }
private byte[] BlendTextures(byte[] frontImage, byte[] backImage, bool setNewAlpha, byte newAlpha) private byte[] BlendTextures(byte[] frontImage, byte[] backImage, bool setNewAlpha, byte newAlpha)

View File

@ -84,6 +84,7 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp
public string body; public string body;
public int responseCode; public int responseCode;
public string responseBody; public string responseBody;
public string responseType = "text/plain";
//public ManualResetEvent ev; //public ManualResetEvent ev;
public bool requestDone; public bool requestDone;
public int startTime; public int startTime;
@ -302,6 +303,22 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp
} }
} }
public void HttpContentType(UUID request, string type)
{
lock (m_UrlMap)
{
if (m_RequestMap.ContainsKey(request))
{
UrlData urlData = m_RequestMap[request];
urlData.requests[request].responseType = type;
}
else
{
m_log.Info("[HttpRequestHandler] There is no http-in request with id " + request.ToString());
}
}
}
public void HttpResponse(UUID request, int status, string body) public void HttpResponse(UUID request, int status, string body)
{ {
lock (m_UrlMap) lock (m_UrlMap)
@ -504,7 +521,8 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp
//put response //put response
response["int_response_code"] = requestData.responseCode; response["int_response_code"] = requestData.responseCode;
response["str_response_string"] = requestData.responseBody; response["str_response_string"] = requestData.responseBody;
response["content_type"] = "text/plain"; response["content_type"] = requestData.responseType;
// response["content_type"] = "text/plain";
response["keepalive"] = false; response["keepalive"] = false;
response["reusecontext"] = false; response["reusecontext"] = false;

View File

@ -67,12 +67,18 @@ namespace OpenSim.Region.CoreModules.Scripting.LoadImageURL
return true; return true;
} }
// public bool AlwaysIdenticalConversion(string bodyData, string extraParams)
// {
// // We don't support conversion of body data.
// return false;
// }
public byte[] ConvertUrl(string url, string extraParams) public byte[] ConvertUrl(string url, string extraParams)
{ {
return null; return null;
} }
public byte[] ConvertStream(Stream data, string extraParams) public byte[] ConvertData(string bodyData, string extraParams)
{ {
return null; return null;
} }
@ -236,9 +242,11 @@ namespace OpenSim.Region.CoreModules.Scripting.LoadImageURL
stream.Close(); stream.Close();
} }
} }
m_log.DebugFormat("[LOADIMAGEURLMODULE] Returning {0} bytes of image data for request {1}", m_log.DebugFormat("[LOADIMAGEURLMODULE] Returning {0} bytes of image data for request {1}",
imageJ2000.Length, state.RequestID); imageJ2000.Length, state.RequestID);
m_textureManager.ReturnData(state.RequestID, imageJ2000);
m_textureManager.ReturnData(state.RequestID, imageJ2000, false);
} }
#region Nested type: RequestState #region Nested type: RequestState

View File

@ -45,31 +45,250 @@ using OpenSim.Tests.Common.Mock;
namespace OpenSim.Region.CoreModules.Scripting.VectorRender.Tests namespace OpenSim.Region.CoreModules.Scripting.VectorRender.Tests
{ {
[TestFixture] [TestFixture]
public class VectorRenderModuleTests public class VectorRenderModuleTests : OpenSimTestCase
{ {
Scene m_scene;
DynamicTextureModule m_dtm;
VectorRenderModule m_vrm;
private void SetupScene(bool reuseTextures)
{
m_scene = new SceneHelpers().SetupScene();
m_dtm = new DynamicTextureModule();
m_dtm.ReuseTextures = reuseTextures;
m_vrm = new VectorRenderModule();
SceneHelpers.SetupSceneModules(m_scene, m_dtm, m_vrm);
}
[Test] [Test]
public void TestDraw() public void TestDraw()
{ {
TestHelpers.InMethod(); TestHelpers.InMethod();
Scene scene = new SceneHelpers().SetupScene(); SetupScene(false);
DynamicTextureModule dtm = new DynamicTextureModule(); SceneObjectGroup so = SceneHelpers.AddSceneObject(m_scene);
VectorRenderModule vrm = new VectorRenderModule();
SceneHelpers.SetupSceneModules(scene, dtm, vrm);
SceneObjectGroup so = SceneHelpers.AddSceneObject(scene);
UUID originalTextureID = so.RootPart.Shape.Textures.GetFace(0).TextureID; UUID originalTextureID = so.RootPart.Shape.Textures.GetFace(0).TextureID;
dtm.AddDynamicTextureData( m_dtm.AddDynamicTextureData(
scene.RegionInfo.RegionID, m_scene.RegionInfo.RegionID,
so.UUID, so.UUID,
vrm.GetContentType(), m_vrm.GetContentType(),
"PenColour BLACK; MoveTo 40,220; FontSize 32; Text Hello World;", "PenColour BLACK; MoveTo 40,220; FontSize 32; Text Hello World;",
"", "",
0); 0);
Assert.That(originalTextureID, Is.Not.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID));
}
[Test]
public void TestRepeatSameDraw()
{
TestHelpers.InMethod();
string dtText = "PenColour BLACK; MoveTo 40,220; FontSize 32; Text Hello World;";
SetupScene(false);
SceneObjectGroup so = SceneHelpers.AddSceneObject(m_scene);
m_dtm.AddDynamicTextureData(
m_scene.RegionInfo.RegionID,
so.UUID,
m_vrm.GetContentType(),
dtText,
"",
0);
UUID firstDynamicTextureID = so.RootPart.Shape.Textures.GetFace(0).TextureID;
m_dtm.AddDynamicTextureData(
m_scene.RegionInfo.RegionID,
so.UUID,
m_vrm.GetContentType(),
dtText,
"",
0);
Assert.That(firstDynamicTextureID, Is.Not.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID));
}
[Test]
public void TestRepeatSameDrawDifferentExtraParams()
{
TestHelpers.InMethod();
string dtText = "PenColour BLACK; MoveTo 40,220; FontSize 32; Text Hello World;";
SetupScene(false);
SceneObjectGroup so = SceneHelpers.AddSceneObject(m_scene);
m_dtm.AddDynamicTextureData(
m_scene.RegionInfo.RegionID,
so.UUID,
m_vrm.GetContentType(),
dtText,
"",
0);
UUID firstDynamicTextureID = so.RootPart.Shape.Textures.GetFace(0).TextureID;
m_dtm.AddDynamicTextureData(
m_scene.RegionInfo.RegionID,
so.UUID,
m_vrm.GetContentType(),
dtText,
"alpha:250",
0);
Assert.That(firstDynamicTextureID, Is.Not.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID));
}
[Test]
public void TestRepeatSameDrawContainingImage()
{
TestHelpers.InMethod();
string dtText
= "PenColour BLACK; MoveTo 40,220; FontSize 32; Text Hello World; Image http://localhost/shouldnotexist.png";
SetupScene(false);
SceneObjectGroup so = SceneHelpers.AddSceneObject(m_scene);
m_dtm.AddDynamicTextureData(
m_scene.RegionInfo.RegionID,
so.UUID,
m_vrm.GetContentType(),
dtText,
"",
0);
UUID firstDynamicTextureID = so.RootPart.Shape.Textures.GetFace(0).TextureID;
m_dtm.AddDynamicTextureData(
m_scene.RegionInfo.RegionID,
so.UUID,
m_vrm.GetContentType(),
dtText,
"",
0);
Assert.That(firstDynamicTextureID, Is.Not.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID));
}
[Test]
public void TestDrawReusingTexture()
{
TestHelpers.InMethod();
SetupScene(true);
SceneObjectGroup so = SceneHelpers.AddSceneObject(m_scene);
UUID originalTextureID = so.RootPart.Shape.Textures.GetFace(0).TextureID;
m_dtm.AddDynamicTextureData(
m_scene.RegionInfo.RegionID,
so.UUID,
m_vrm.GetContentType(),
"PenColour BLACK; MoveTo 40,220; FontSize 32; Text Hello World;",
"",
0);
Assert.That(originalTextureID, Is.Not.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID)); Assert.That(originalTextureID, Is.Not.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID));
} }
[Test]
public void TestRepeatSameDrawReusingTexture()
{
TestHelpers.InMethod();
string dtText = "PenColour BLACK; MoveTo 40,220; FontSize 32; Text Hello World;";
SetupScene(true);
SceneObjectGroup so = SceneHelpers.AddSceneObject(m_scene);
m_dtm.AddDynamicTextureData(
m_scene.RegionInfo.RegionID,
so.UUID,
m_vrm.GetContentType(),
dtText,
"",
0);
UUID firstDynamicTextureID = so.RootPart.Shape.Textures.GetFace(0).TextureID;
m_dtm.AddDynamicTextureData(
m_scene.RegionInfo.RegionID,
so.UUID,
m_vrm.GetContentType(),
dtText,
"",
0);
Assert.That(firstDynamicTextureID, Is.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID));
}
[Test]
public void TestRepeatSameDrawDifferentExtraParamsReusingTexture()
{
TestHelpers.InMethod();
string dtText = "PenColour BLACK; MoveTo 40,220; FontSize 32; Text Hello World;";
SetupScene(true);
SceneObjectGroup so = SceneHelpers.AddSceneObject(m_scene);
m_dtm.AddDynamicTextureData(
m_scene.RegionInfo.RegionID,
so.UUID,
m_vrm.GetContentType(),
dtText,
"",
0);
UUID firstDynamicTextureID = so.RootPart.Shape.Textures.GetFace(0).TextureID;
m_dtm.AddDynamicTextureData(
m_scene.RegionInfo.RegionID,
so.UUID,
m_vrm.GetContentType(),
dtText,
"alpha:250",
0);
Assert.That(firstDynamicTextureID, Is.Not.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID));
}
[Test]
public void TestRepeatSameDrawContainingImageReusingTexture()
{
TestHelpers.InMethod();
string dtText
= "PenColour BLACK; MoveTo 40,220; FontSize 32; Text Hello World; Image http://localhost/shouldnotexist.png";
SetupScene(true);
SceneObjectGroup so = SceneHelpers.AddSceneObject(m_scene);
m_dtm.AddDynamicTextureData(
m_scene.RegionInfo.RegionID,
so.UUID,
m_vrm.GetContentType(),
dtText,
"",
0);
UUID firstDynamicTextureID = so.RootPart.Shape.Textures.GetFace(0).TextureID;
m_dtm.AddDynamicTextureData(
m_scene.RegionInfo.RegionID,
so.UUID,
m_vrm.GetContentType(),
dtText,
"",
0);
Assert.That(firstDynamicTextureID, Is.Not.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID));
}
} }
} }

View File

@ -30,6 +30,7 @@ using System.Drawing;
using System.Drawing.Imaging; using System.Drawing.Imaging;
using System.Globalization; using System.Globalization;
using System.IO; using System.IO;
using System.Linq;
using System.Net; using System.Net;
using Nini.Config; using Nini.Config;
using OpenMetaverse; using OpenMetaverse;
@ -47,7 +48,6 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender
{ {
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
private string m_name = "VectorRenderModule";
private Scene m_scene; private Scene m_scene;
private IDynamicTextureManager m_textureManager; private IDynamicTextureManager m_textureManager;
private Graphics m_graph; private Graphics m_graph;
@ -61,12 +61,12 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender
public string GetContentType() public string GetContentType()
{ {
return ("vector"); return "vector";
} }
public string GetName() public string GetName()
{ {
return m_name; return Name;
} }
public bool SupportsAsynchronous() public bool SupportsAsynchronous()
@ -74,14 +74,26 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender
return true; return true;
} }
// public bool AlwaysIdenticalConversion(string bodyData, string extraParams)
// {
// string[] lines = GetLines(bodyData);
// return lines.Any((str, r) => str.StartsWith("Image"));
// }
public byte[] ConvertUrl(string url, string extraParams) public byte[] ConvertUrl(string url, string extraParams)
{ {
return null; return null;
} }
public byte[] ConvertStream(Stream data, string extraParams) public byte[] ConvertData(string bodyData, string extraParams)
{ {
return null; bool reuseable;
return Draw(bodyData, extraParams, out reuseable);
}
private byte[] ConvertData(string bodyData, string extraParams, out bool reuseable)
{
return Draw(bodyData, extraParams, out reuseable);
} }
public bool AsyncConvertUrl(UUID id, string url, string extraParams) public bool AsyncConvertUrl(UUID id, string url, string extraParams)
@ -91,7 +103,12 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender
public bool AsyncConvertData(UUID id, string bodyData, string extraParams) public bool AsyncConvertData(UUID id, string bodyData, string extraParams)
{ {
Draw(bodyData, id, extraParams); // XXX: This isn't actually being done asynchronously!
bool reuseable;
byte[] data = ConvertData(bodyData, extraParams, out reuseable);
m_textureManager.ReturnData(id, data, reuseable);
return true; return true;
} }
@ -152,7 +169,7 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender
public string Name public string Name
{ {
get { return m_name; } get { return "VectorRenderModule"; }
} }
public bool IsSharedModule public bool IsSharedModule
@ -162,7 +179,7 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender
#endregion #endregion
private void Draw(string data, UUID id, string extraParams) private byte[] Draw(string data, string extraParams, out bool reuseable)
{ {
// We need to cater for old scripts that didnt use extraParams neatly, they use either an integer size which represents both width and height, or setalpha // We need to cater for old scripts that didnt use extraParams neatly, they use either an integer size which represents both width and height, or setalpha
// we will now support multiple comma seperated params in the form width:256,height:512,alpha:255 // we will now support multiple comma seperated params in the form width:256,height:512,alpha:255
@ -343,7 +360,7 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender
} }
} }
GDIDraw(data, graph, altDataDelim); GDIDraw(data, graph, altDataDelim, out reuseable);
} }
byte[] imageJ2000 = new byte[0]; byte[] imageJ2000 = new byte[0];
@ -359,7 +376,7 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender
e.Message, e.StackTrace); e.Message, e.StackTrace);
} }
m_textureManager.ReturnData(id, imageJ2000); return imageJ2000;
} }
finally finally
{ {
@ -434,8 +451,21 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender
} }
*/ */
private void GDIDraw(string data, Graphics graph, char dataDelim) /// <summary>
/// Split input data into discrete command lines.
/// </summary>
/// <returns></returns>
/// <param name='data'></param>
/// <param name='dataDelim'></param>
private string[] GetLines(string data, char dataDelim)
{ {
char[] lineDelimiter = { dataDelim };
return data.Split(lineDelimiter);
}
private void GDIDraw(string data, Graphics graph, char dataDelim, out bool reuseable)
{
reuseable = true;
Point startPoint = new Point(0, 0); Point startPoint = new Point(0, 0);
Point endPoint = new Point(0, 0); Point endPoint = new Point(0, 0);
Pen drawPen = null; Pen drawPen = null;
@ -450,11 +480,9 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender
myFont = new Font(fontName, fontSize); myFont = new Font(fontName, fontSize);
myBrush = new SolidBrush(Color.Black); myBrush = new SolidBrush(Color.Black);
char[] lineDelimiter = {dataDelim};
char[] partsDelimiter = {','}; char[] partsDelimiter = {','};
string[] lines = data.Split(lineDelimiter);
foreach (string line in lines) foreach (string line in GetLines(data, dataDelim))
{ {
string nextLine = line.Trim(); string nextLine = line.Trim();
//replace with switch, or even better, do some proper parsing //replace with switch, or even better, do some proper parsing
@ -485,6 +513,10 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender
} }
else if (nextLine.StartsWith("Image")) else if (nextLine.StartsWith("Image"))
{ {
// We cannot reuse any generated texture involving fetching an image via HTTP since that image
// can change.
reuseable = false;
float x = 0; float x = 0;
float y = 0; float y = 0;
GetParams(partsDelimiter, ref nextLine, 5, ref x, ref y); GetParams(partsDelimiter, ref nextLine, 5, ref x, ref y);

View File

@ -414,6 +414,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain
private void LoadPlugins() private void LoadPlugins()
{ {
m_plugineffects = new Dictionary<string, ITerrainEffect>(); m_plugineffects = new Dictionary<string, ITerrainEffect>();
LoadPlugins(Assembly.GetCallingAssembly());
string plugineffectsPath = "Terrain"; string plugineffectsPath = "Terrain";
// Load the files in the Terrain/ dir // Load the files in the Terrain/ dir
@ -427,6 +428,16 @@ namespace OpenSim.Region.CoreModules.World.Terrain
try try
{ {
Assembly library = Assembly.LoadFrom(file); Assembly library = Assembly.LoadFrom(file);
LoadPlugins(library);
}
catch (BadImageFormatException)
{
}
}
}
private void LoadPlugins(Assembly library)
{
foreach (Type pluginType in library.GetTypes()) foreach (Type pluginType in library.GetTypes())
{ {
try try
@ -438,13 +449,13 @@ namespace OpenSim.Region.CoreModules.World.Terrain
if (pluginType.GetInterface("ITerrainEffect", false) != null) if (pluginType.GetInterface("ITerrainEffect", false) != null)
{ {
ITerrainEffect terEffect = (ITerrainEffect) Activator.CreateInstance(library.GetType(pluginType.ToString())); ITerrainEffect terEffect = (ITerrainEffect)Activator.CreateInstance(library.GetType(pluginType.ToString()));
InstallPlugin(typeName, terEffect); InstallPlugin(typeName, terEffect);
} }
else if (pluginType.GetInterface("ITerrainLoader", false) != null) else if (pluginType.GetInterface("ITerrainLoader", false) != null)
{ {
ITerrainLoader terLoader = (ITerrainLoader) Activator.CreateInstance(library.GetType(pluginType.ToString())); ITerrainLoader terLoader = (ITerrainLoader)Activator.CreateInstance(library.GetType(pluginType.ToString()));
m_loaders[terLoader.FileExtension] = terLoader; m_loaders[terLoader.FileExtension] = terLoader;
m_log.Info("L ... " + typeName); m_log.Info("L ... " + typeName);
} }
@ -454,11 +465,6 @@ namespace OpenSim.Region.CoreModules.World.Terrain
} }
} }
} }
catch (BadImageFormatException)
{
}
}
}
public void InstallPlugin(string pluginName, ITerrainEffect effect) public void InstallPlugin(string pluginName, ITerrainEffect effect)
{ {
@ -1176,7 +1182,8 @@ namespace OpenSim.Region.CoreModules.World.Terrain
private void InterfaceRunPluginEffect(Object[] args) private void InterfaceRunPluginEffect(Object[] args)
{ {
if ((string) args[0] == "list") string firstArg = (string)args[0];
if (firstArg == "list")
{ {
m_log.Info("List of loaded plugins"); m_log.Info("List of loaded plugins");
foreach (KeyValuePair<string, ITerrainEffect> kvp in m_plugineffects) foreach (KeyValuePair<string, ITerrainEffect> kvp in m_plugineffects)
@ -1185,14 +1192,14 @@ namespace OpenSim.Region.CoreModules.World.Terrain
} }
return; return;
} }
if ((string) args[0] == "reload") if (firstArg == "reload")
{ {
LoadPlugins(); LoadPlugins();
return; return;
} }
if (m_plugineffects.ContainsKey((string) args[0])) if (m_plugineffects.ContainsKey(firstArg))
{ {
m_plugineffects[(string) args[0]].RunEffect(m_channel); m_plugineffects[firstArg].RunEffect(m_channel);
CheckForTerrainUpdates(); CheckForTerrainUpdates();
} }
else else

View File

@ -33,7 +33,7 @@ namespace OpenSim.Region.Framework.Interfaces
public interface IDynamicTextureManager public interface IDynamicTextureManager
{ {
void RegisterRender(string handleType, IDynamicTextureRender render); void RegisterRender(string handleType, IDynamicTextureRender render);
void ReturnData(UUID id, byte[] data); void ReturnData(UUID id, byte[] data, bool isReuseable);
UUID AddDynamicTextureURL(UUID simID, UUID primID, string contentType, string url, string extraParams, UUID AddDynamicTextureURL(UUID simID, UUID primID, string contentType, string url, string extraParams,
int updateTimer); int updateTimer);
@ -113,8 +113,20 @@ namespace OpenSim.Region.Framework.Interfaces
string GetName(); string GetName();
string GetContentType(); string GetContentType();
bool SupportsAsynchronous(); bool SupportsAsynchronous();
// /// <summary>
// /// Return true if converting the input body and extra params data will always result in the same byte[] array
// /// </summary>
// /// <remarks>
// /// This method allows the caller to use a previously generated asset if it has one.
// /// </remarks>
// /// <returns></returns>
// /// <param name='bodyData'></param>
// /// <param name='extraParams'></param>
// bool AlwaysIdenticalConversion(string bodyData, string extraParams);
byte[] ConvertUrl(string url, string extraParams); byte[] ConvertUrl(string url, string extraParams);
byte[] ConvertStream(Stream data, string extraParams); byte[] ConvertData(string bodyData, string extraParams);
bool AsyncConvertUrl(UUID id, string url, string extraParams); bool AsyncConvertUrl(UUID id, string url, string extraParams);
bool AsyncConvertData(UUID id, string bodyData, string extraParams); bool AsyncConvertData(UUID id, string bodyData, string extraParams);
void GetDrawStringSize(string text, string fontName, int fontSize, void GetDrawStringSize(string text, string fontName, int fontSize,

View File

@ -39,6 +39,8 @@ namespace OpenSim.Region.Framework.Interfaces
UUID RequestSecureURL(IScriptModule engine, SceneObjectPart host, UUID itemID); UUID RequestSecureURL(IScriptModule engine, SceneObjectPart host, UUID itemID);
void ReleaseURL(string url); void ReleaseURL(string url);
void HttpResponse(UUID request, int status, string body); void HttpResponse(UUID request, int status, string body);
void HttpContentType(UUID request, string type);
string GetHttpHeader(UUID request, string header); string GetHttpHeader(UUID request, string header);
int GetFreeUrls(); int GetFreeUrls();

View File

@ -50,8 +50,40 @@ using OpenSim.Tests.Common.Mock;
namespace OpenSim.Region.Framework.Tests namespace OpenSim.Region.Framework.Tests
{ {
[TestFixture] [TestFixture]
public class UserInventoryTests public class UserInventoryTests : OpenSimTestCase
{ {
[Test]
public void TestCreateInventoryFolders()
{
TestHelpers.InMethod();
// TestHelpers.EnableLogging();
// For this test both folders will have the same name which is legal in SL user inventories.
string foldersName = "f1";
Scene scene = new SceneHelpers().SetupScene();
UserAccount user1 = UserAccountHelpers.CreateUserWithInventory(scene, TestHelpers.ParseTail(1001));
UserInventoryHelpers.CreateInventoryFolder(scene.InventoryService, user1.PrincipalID, foldersName);
List<InventoryFolderBase> oneFolder
= UserInventoryHelpers.GetInventoryFolders(scene.InventoryService, user1.PrincipalID, foldersName);
Assert.That(oneFolder.Count, Is.EqualTo(1));
InventoryFolderBase firstRetrievedFolder = oneFolder[0];
Assert.That(firstRetrievedFolder.Name, Is.EqualTo(foldersName));
UserInventoryHelpers.CreateInventoryFolder(scene.InventoryService, user1.PrincipalID, foldersName);
List<InventoryFolderBase> twoFolders
= UserInventoryHelpers.GetInventoryFolders(scene.InventoryService, user1.PrincipalID, foldersName);
Assert.That(twoFolders.Count, Is.EqualTo(2));
Assert.That(twoFolders[0].Name, Is.EqualTo(foldersName));
Assert.That(twoFolders[1].Name, Is.EqualTo(foldersName));
Assert.That(twoFolders[0].ID, Is.Not.EqualTo(twoFolders[1].ID));
}
[Test] [Test]
public void TestGiveInventoryItem() public void TestGiveInventoryItem()
{ {
@ -83,7 +115,7 @@ namespace OpenSim.Region.Framework.Tests
public void TestGiveInventoryFolder() public void TestGiveInventoryFolder()
{ {
TestHelpers.InMethod(); TestHelpers.InMethod();
// log4net.Config.XmlConfigurator.Configure(); // TestHelpers.EnableLogging();
Scene scene = new SceneHelpers().SetupScene(); Scene scene = new SceneHelpers().SetupScene();
UserAccount user1 = UserAccountHelpers.CreateUserWithInventory(scene, TestHelpers.ParseTail(1001)); UserAccount user1 = UserAccountHelpers.CreateUserWithInventory(scene, TestHelpers.ParseTail(1001));

View File

@ -7208,7 +7208,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
{ {
m_host.AddScriptLPS(1); m_host.AddScriptLPS(1);
setLinkPrimParams(ScriptBaseClass.LINK_THIS, rules); setLinkPrimParams(ScriptBaseClass.LINK_THIS, rules, "llSetPrimitiveParams");
ScriptSleep(200); ScriptSleep(200);
} }
@ -7217,7 +7217,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
{ {
m_host.AddScriptLPS(1); m_host.AddScriptLPS(1);
setLinkPrimParams(linknumber, rules); setLinkPrimParams(linknumber, rules, "llSetLinkPrimitiveParams");
ScriptSleep(200); ScriptSleep(200);
} }
@ -7226,17 +7226,18 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
{ {
m_host.AddScriptLPS(1); m_host.AddScriptLPS(1);
setLinkPrimParams(linknumber, rules); setLinkPrimParams(linknumber, rules, "llSetLinkPrimitiveParamsFast");
} }
protected void setLinkPrimParams(int linknumber, LSL_List rules) protected void setLinkPrimParams(int linknumber, LSL_List rules, string originFunc)
{ {
List<SceneObjectPart> parts = GetLinkParts(linknumber); List<SceneObjectPart> parts = GetLinkParts(linknumber);
LSL_List remaining = null; LSL_List remaining = null;
uint rulesParsed = 0;
foreach (SceneObjectPart part in parts) foreach (SceneObjectPart part in parts)
remaining = SetPrimParams(part, rules); remaining = SetPrimParams(part, rules, originFunc, ref rulesParsed);
while (remaining != null && remaining.Length > 2) while (remaining != null && remaining.Length > 2)
{ {
@ -7245,13 +7246,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
parts = GetLinkParts(linknumber); parts = GetLinkParts(linknumber);
foreach (SceneObjectPart part in parts) foreach (SceneObjectPart part in parts)
remaining = SetPrimParams(part, rules); remaining = SetPrimParams(part, rules, originFunc, ref rulesParsed);
} }
} }
protected LSL_List SetPrimParams(SceneObjectPart part, LSL_List rules) protected LSL_List SetPrimParams(SceneObjectPart part, LSL_List rules, string originFunc, ref uint rulesParsed)
{ {
int idx = 0; int idx = 0;
int idxStart = 0;
bool positionChanged = false; bool positionChanged = false;
LSL_Vector currentPosition = GetPartLocalPos(part); LSL_Vector currentPosition = GetPartLocalPos(part);
@ -7260,9 +7262,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
{ {
while (idx < rules.Length) while (idx < rules.Length)
{ {
++rulesParsed;
int code = rules.GetLSLIntegerItem(idx++); int code = rules.GetLSLIntegerItem(idx++);
int remain = rules.Length - idx; int remain = rules.Length - idx;
idxStart = idx;
int face; int face;
LSL_Vector v; LSL_Vector v;
@ -7639,7 +7643,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
} }
catch (InvalidCastException e) catch (InvalidCastException e)
{ {
ShoutError(e.Message); ShoutError(string.Format(
"{0} error running rule #{1}: arg #{2} ",
originFunc, rulesParsed, idx - idxStart) + e.Message);
} }
finally finally
{ {
@ -10113,31 +10119,30 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
public LSL_Float llListStatistics(int operation, LSL_List src) public LSL_Float llListStatistics(int operation, LSL_List src)
{ {
m_host.AddScriptLPS(1); m_host.AddScriptLPS(1);
LSL_List nums = LSL_List.ToDoubleList(src);
switch (operation) switch (operation)
{ {
case ScriptBaseClass.LIST_STAT_RANGE: case ScriptBaseClass.LIST_STAT_RANGE:
return nums.Range(); return src.Range();
case ScriptBaseClass.LIST_STAT_MIN: case ScriptBaseClass.LIST_STAT_MIN:
return nums.Min(); return src.Min();
case ScriptBaseClass.LIST_STAT_MAX: case ScriptBaseClass.LIST_STAT_MAX:
return nums.Max(); return src.Max();
case ScriptBaseClass.LIST_STAT_MEAN: case ScriptBaseClass.LIST_STAT_MEAN:
return nums.Mean(); return src.Mean();
case ScriptBaseClass.LIST_STAT_MEDIAN: case ScriptBaseClass.LIST_STAT_MEDIAN:
return nums.Median(); return LSL_List.ToDoubleList(src).Median();
case ScriptBaseClass.LIST_STAT_NUM_COUNT: case ScriptBaseClass.LIST_STAT_NUM_COUNT:
return nums.NumericLength(); return src.NumericLength();
case ScriptBaseClass.LIST_STAT_STD_DEV: case ScriptBaseClass.LIST_STAT_STD_DEV:
return nums.StdDev(); return src.StdDev();
case ScriptBaseClass.LIST_STAT_SUM: case ScriptBaseClass.LIST_STAT_SUM:
return nums.Sum(); return src.Sum();
case ScriptBaseClass.LIST_STAT_SUM_SQUARES: case ScriptBaseClass.LIST_STAT_SUM_SQUARES:
return nums.SumSqrs(); return src.SumSqrs();
case ScriptBaseClass.LIST_STAT_GEOMETRIC_MEAN: case ScriptBaseClass.LIST_STAT_GEOMETRIC_MEAN:
return nums.GeometricMean(); return src.GeometricMean();
case ScriptBaseClass.LIST_STAT_HARMONIC_MEAN: case ScriptBaseClass.LIST_STAT_HARMONIC_MEAN:
return nums.HarmonicMean(); return src.HarmonicMean();
default: default:
return 0.0; return 0.0;
} }
@ -10761,7 +10766,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
return tid.ToString(); return tid.ToString();
} }
public void SetPrimitiveParamsEx(LSL_Key prim, LSL_List rules) public void SetPrimitiveParamsEx(LSL_Key prim, LSL_List rules, string originFunc)
{ {
SceneObjectPart obj = World.GetSceneObjectPart(new UUID(prim)); SceneObjectPart obj = World.GetSceneObjectPart(new UUID(prim));
if (obj == null) if (obj == null)
@ -10770,14 +10775,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
if (obj.OwnerID != m_host.OwnerID) if (obj.OwnerID != m_host.OwnerID)
return; return;
LSL_List remaining = SetPrimParams(obj, rules); uint rulesParsed = 0;
LSL_List remaining = SetPrimParams(obj, rules, originFunc, ref rulesParsed);
while ((object)remaining != null && remaining.Length > 2) while ((object)remaining != null && remaining.Length > 2)
{ {
LSL_Integer newLink = remaining.GetLSLIntegerItem(0); LSL_Integer newLink = remaining.GetLSLIntegerItem(0);
LSL_List newrules = remaining.GetSublist(1, -1); LSL_List newrules = remaining.GetSublist(1, -1);
foreach(SceneObjectPart part in GetLinkParts(obj, newLink)){ foreach(SceneObjectPart part in GetLinkParts(obj, newLink)){
remaining = SetPrimParams(part, newrules); remaining = SetPrimParams(part, newrules, originFunc, ref rulesParsed);
} }
} }
} }

View File

@ -140,12 +140,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
internal float m_ScriptDistanceFactor = 1.0f; internal float m_ScriptDistanceFactor = 1.0f;
internal Dictionary<string, FunctionPerms > m_FunctionPerms = new Dictionary<string, FunctionPerms >(); internal Dictionary<string, FunctionPerms > m_FunctionPerms = new Dictionary<string, FunctionPerms >();
protected IUrlModule m_UrlModule = null;
public void Initialize(IScriptEngine ScriptEngine, SceneObjectPart host, TaskInventoryItem item) public void Initialize(IScriptEngine ScriptEngine, SceneObjectPart host, TaskInventoryItem item)
{ {
m_ScriptEngine = ScriptEngine; m_ScriptEngine = ScriptEngine;
m_host = host; m_host = host;
m_item = item; m_item = item;
m_UrlModule = m_ScriptEngine.World.RequestModuleInterface<IUrlModule>();
if (m_ScriptEngine.Config.GetBoolean("AllowOSFunctions", false)) if (m_ScriptEngine.Config.GetBoolean("AllowOSFunctions", false))
m_OSFunctionsEnabled = true; m_OSFunctionsEnabled = true;
@ -2988,7 +2992,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
m_host.AddScriptLPS(1); m_host.AddScriptLPS(1);
InitLSL(); InitLSL();
m_LSL_Api.SetPrimitiveParamsEx(prim, rules); m_LSL_Api.SetPrimitiveParamsEx(prim, rules, "osSetPrimitiveParams");
} }
/// <summary> /// <summary>
@ -3358,5 +3362,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
return new LSL_Key(m_host.ParentGroup.FromPartID.ToString()); return new LSL_Key(m_host.ParentGroup.FromPartID.ToString());
} }
/// <summary>
/// Sets the response type for an HTTP request/response
/// </summary>
/// <returns></returns>
public void osSetContentType(LSL_Key id, string type)
{
CheckThreatLevel(ThreatLevel.High,"osSetResponseType");
if (m_UrlModule != null)
m_UrlModule.HttpContentType(new UUID(id),type);
}
} }
} }

View File

@ -424,7 +424,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces
LSL_String llXorBase64StringsCorrect(string str1, string str2); LSL_String llXorBase64StringsCorrect(string str1, string str2);
void print(string str); void print(string str);
void SetPrimitiveParamsEx(LSL_Key prim, LSL_List rules); void SetPrimitiveParamsEx(LSL_Key prim, LSL_List rules, string originFunc);
LSL_List GetPrimitiveParamsEx(LSL_Key prim, LSL_List rules); LSL_List GetPrimitiveParamsEx(LSL_Key prim, LSL_List rules);
} }
} }

View File

@ -40,16 +40,75 @@ using LSL_Key = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString;
namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces
{ {
/// <summary>
/// To permit region owners to enable the extended scripting functionality
/// of OSSL, without allowing malicious scripts to access potentially
/// troublesome functions, each OSSL function is assigned a threat level,
/// and access to the functions is granted or denied based on a default
/// threshold set in OpenSim.ini (which can be overridden for individual
/// functions on a case-by-case basis)
/// </summary>
public enum ThreatLevel public enum ThreatLevel
{ {
// Not documented, presumably means permanently disabled ?
NoAccess = -1, NoAccess = -1,
/// <summary>
/// Function is no threat at all. It doesn't constitute a threat to
/// either users or the system and has no known side effects.
/// </summary>
None = 0, None = 0,
/// <summary>
/// Abuse of this command can cause a nuisance to the region operator,
/// such as log message spew.
/// </summary>
Nuisance = 1, Nuisance = 1,
/// <summary>
/// Extreme levels of abuse of this function can cause impaired
/// functioning of the region, or very gullible users can be tricked
/// into experiencing harmless effects.
/// </summary>
VeryLow = 2, VeryLow = 2,
/// <summary>
/// Intentional abuse can cause crashes or malfunction under certain
/// circumstances, which can be easily rectified; or certain users can
/// be tricked into certain situations in an avoidable manner.
/// </summary>
Low = 3, Low = 3,
/// <summary>
/// Intentional abuse can cause denial of service and crashes with
/// potential of data or state loss; or trusting users can be tricked
/// into embarrassing or uncomfortable situations.
/// </summary>
Moderate = 4, Moderate = 4,
/// <summary>
/// Casual abuse can cause impaired functionality or temporary denial
/// of service conditions. Intentional abuse can easily cause crashes
/// with potential data loss, or can be used to trick experienced and
/// cautious users into unwanted situations, or changes global data
/// permanently and without undo ability.
/// </summary>
High = 5, High = 5,
/// <summary>
/// Even normal use may, depending on the number of instances, or
/// frequency of use, result in severe service impairment or crash
/// with loss of data, or can be used to cause unwanted or harmful
/// effects on users without giving the user a means to avoid it.
/// </summary>
VeryHigh = 6, VeryHigh = 6,
/// <summary>
/// Even casual use is a danger to region stability, or function allows
/// console or OS command execution, or function allows taking money
/// without consent, or allows deletion or modification of user data,
/// or allows the compromise of sensitive data by design.
/// </summary>
Severe = 7 Severe = 7
}; };
@ -306,5 +365,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces
/// </summary> /// </summary>
/// <returns>Rezzing object key or NULL_KEY if rezzed by agent or otherwise unknown.</returns> /// <returns>Rezzing object key or NULL_KEY if rezzed by agent or otherwise unknown.</returns>
LSL_Key osGetRezzingObject(); LSL_Key osGetRezzingObject();
/// <summary>
/// Sets the response type for an HTTP request/response
/// </summary>
/// <returns></returns>
void osSetContentType(LSL_Key id, string type);
} }
} }

View File

@ -955,5 +955,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
{ {
return m_OSSL_Functions.osGetRezzingObject(); return m_OSSL_Functions.osGetRezzingObject();
} }
public void osSetContentType(LSL_Key id, string type)
{
m_OSSL_Functions.osSetContentType(id,type);
}
} }
} }

View File

@ -1137,7 +1137,7 @@ namespace OpenSim.Region.ScriptEngine.Shared
{ {
list ret = new list(); list ret = new list();
double entry; double entry;
for (int i = 0; i < src.Data.Length - 1; i++) for (int i = 0; i < src.Data.Length; i++)
{ {
if (double.TryParse(src.Data[i].ToString(), NumberStyles.Float, Culture.NumberFormatInfo, out entry)) if (double.TryParse(src.Data[i].ToString(), NumberStyles.Float, Culture.NumberFormatInfo, out entry))
{ {

View File

@ -94,6 +94,7 @@ namespace OpenSim.Services.InventoryService
m_Database = LoadPlugin<IXInventoryData>(dllName, m_Database = LoadPlugin<IXInventoryData>(dllName,
new Object[] {connString, String.Empty}); new Object[] {connString, String.Empty});
if (m_Database == null) if (m_Database == null)
throw new Exception("Could not find a storage interface in the given module"); throw new Exception("Could not find a storage interface in the given module");
} }
@ -326,7 +327,7 @@ namespace OpenSim.Services.InventoryService
if (check != null) if (check != null)
return false; return false;
if (folder.Type != (short)AssetType.Folder || folder.Type != (short)AssetType.Unknown) if (folder.Type != (short)AssetType.Folder && folder.Type != (short)AssetType.Unknown)
{ {
InventoryFolderBase rootFolder = GetRootFolder(folder.Owner); InventoryFolderBase rootFolder = GetRootFolder(folder.Owner);

View File

@ -245,7 +245,7 @@ namespace OpenSim.Tests.Common
config.AddConfig("Modules"); config.AddConfig("Modules");
config.AddConfig("InventoryService"); config.AddConfig("InventoryService");
config.Configs["Modules"].Set("InventoryServices", "LocalInventoryServicesConnector"); config.Configs["Modules"].Set("InventoryServices", "LocalInventoryServicesConnector");
config.Configs["InventoryService"].Set("LocalServiceModule", "OpenSim.Services.InventoryService.dll:InventoryService"); config.Configs["InventoryService"].Set("LocalServiceModule", "OpenSim.Services.InventoryService.dll:XInventoryService");
config.Configs["InventoryService"].Set("StorageProvider", "OpenSim.Tests.Common.dll"); config.Configs["InventoryService"].Set("StorageProvider", "OpenSim.Tests.Common.dll");
LocalInventoryServicesConnector inventoryService = new LocalInventoryServicesConnector(); LocalInventoryServicesConnector inventoryService = new LocalInventoryServicesConnector();

View File

@ -199,7 +199,9 @@ namespace OpenSim.Tests.Common
string[] components = path.Split(new string[] { PATH_DELIMITER }, 2, StringSplitOptions.None); string[] components = path.Split(new string[] { PATH_DELIMITER }, 2, StringSplitOptions.None);
InventoryFolderBase newFolder InventoryFolderBase newFolder
= new InventoryFolderBase(UUID.Random(), components[0], parentFolder.Owner, parentFolder.ID); = new InventoryFolderBase(
UUID.Random(), components[0], parentFolder.Owner, (short)AssetType.Unknown, parentFolder.ID, 0);
inventoryService.AddFolder(newFolder); inventoryService.AddFolder(newFolder);
if (components.Length > 1) if (components.Length > 1)

View File

@ -0,0 +1,131 @@
/*
* Copyright (c) Contributors, http://opensimulator.org/
* See CONTRIBUTORS.TXT for a full list of copyright holders.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the OpenSimulator Project nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using log4net;
using OpenMetaverse;
using OpenSim.Framework;
using OpenSim.Data;
namespace OpenSim.Tests.Common.Mock
{
public class TestXInventoryDataPlugin : IXInventoryData
{
private Dictionary<UUID, XInventoryFolder> m_allFolders = new Dictionary<UUID, XInventoryFolder>();
private Dictionary<UUID, XInventoryItem> m_allItems = new Dictionary<UUID, XInventoryItem>();
public TestXInventoryDataPlugin(string conn, string realm) {}
public XInventoryItem[] GetItems(string[] fields, string[] vals)
{
List<XInventoryItem> origItems = Get<XInventoryItem>(fields, vals, m_allItems.Values.ToList());
return origItems.Select(i => i.Clone()).ToArray();
}
public XInventoryFolder[] GetFolders(string[] fields, string[] vals)
{
List<XInventoryFolder> origFolders
= Get<XInventoryFolder>(fields, vals, m_allFolders.Values.ToList());
return origFolders.Select(f => f.Clone()).ToArray();
}
private List<T> Get<T>(string[] fields, string[] vals, List<T> inputEntities)
{
List<T> entities = inputEntities;
for (int i = 0; i < fields.Length; i++)
{
entities
= entities.Where(
e =>
{
FieldInfo fi = typeof(T).GetField(fields[i]);
if (fi == null)
throw new NotImplementedException(string.Format("No field {0} for val {1}", fields[i], vals[i]));
return fi.GetValue(e).ToString() == vals[i];
}
).ToList();
}
return entities;
}
public bool StoreFolder(XInventoryFolder folder)
{
m_allFolders[folder.folderID] = folder.Clone();
// Console.WriteLine("Added folder {0} {1}", folder.folderName, folder.folderID);
return true;
}
public bool StoreItem(XInventoryItem item)
{
m_allItems[item.inventoryID] = item.Clone();
// Console.WriteLine("Added item {0} {1}, creator {2}, owner {3}", item.inventoryName, item.inventoryID, item.creatorID, item.avatarID);
return true;
}
public bool DeleteFolders(string field, string val)
{
return DeleteFolders(new string[] { field }, new string[] { val });
}
public bool DeleteFolders(string[] fields, string[] vals)
{
XInventoryFolder[] foldersToDelete = GetFolders(fields, vals);
Array.ForEach(foldersToDelete, f => m_allFolders.Remove(f.folderID));
return true;
}
public bool DeleteItems(string field, string val)
{
return DeleteItems(new string[] { field }, new string[] { val });
}
public bool DeleteItems(string[] fields, string[] vals)
{
XInventoryItem[] itemsToDelete = GetItems(fields, vals);
Array.ForEach(itemsToDelete, i => m_allItems.Remove(i.inventoryID));
return true;
}
public bool MoveItem(string id, string newParent) { throw new NotImplementedException(); }
public XInventoryItem[] GetActiveGestures(UUID principalID) { throw new NotImplementedException(); }
public int GetAssetPermissions(UUID principalID, UUID assetID) { throw new NotImplementedException(); }
}
}

View File

@ -95,6 +95,7 @@ namespace OpenSim.Tests.Common
public static void EnableLogging() public static void EnableLogging()
{ {
log4net.Config.XmlConfigurator.Configure(EnableLoggingConfigStream); log4net.Config.XmlConfigurator.Configure(EnableLoggingConfigStream);
EnableLoggingConfigStream.Position = 0;
} }
/// <summary> /// <summary>

View File

@ -47,10 +47,10 @@ using OpenSim.Services.AvatarService;
using OpenSim.Tests.Common; using OpenSim.Tests.Common;
using OpenSim.Tests.Common.Mock; using OpenSim.Tests.Common.Mock;
namespace OpenSim.Tests.Torture namespace OpenSim.Tests.Performance
{ {
/// <summary> /// <summary>
/// NPC torture tests /// NPC performance tests
/// </summary> /// </summary>
/// <remarks> /// <remarks>
/// Don't rely on the numbers given by these tests - they will vary a lot depending on what is already cached, /// Don't rely on the numbers given by these tests - they will vary a lot depending on what is already cached,
@ -58,7 +58,7 @@ namespace OpenSim.Tests.Torture
/// earlier tests. /// earlier tests.
/// </remarks> /// </remarks>
[TestFixture] [TestFixture]
public class NPCTortureTests public class NPCPerformanceTests
{ {
private TestScene scene; private TestScene scene;
private AvatarFactoryModule afm; private AvatarFactoryModule afm;

View File

@ -36,10 +36,10 @@ using OpenSim.Region.Framework.Scenes;
using OpenSim.Tests.Common; using OpenSim.Tests.Common;
using OpenSim.Tests.Common.Mock; using OpenSim.Tests.Common.Mock;
namespace OpenSim.Tests.Torture namespace OpenSim.Tests.Performance
{ {
/// <summary> /// <summary>
/// Object torture tests /// Object performance tests
/// </summary> /// </summary>
/// <remarks> /// <remarks>
/// Don't rely on the numbers given by these tests - they will vary a lot depending on what is already cached, /// Don't rely on the numbers given by these tests - they will vary a lot depending on what is already cached,
@ -47,7 +47,7 @@ namespace OpenSim.Tests.Torture
/// earlier tests. /// earlier tests.
/// </remarks> /// </remarks>
[TestFixture] [TestFixture]
public class ObjectTortureTests public class ObjectPerformanceTests
{ {
[TearDown] [TearDown]
public void TearDown() public void TearDown()

View File

@ -42,10 +42,10 @@ using OpenSim.Region.ScriptEngine.XEngine;
using OpenSim.Tests.Common; using OpenSim.Tests.Common;
using OpenSim.Tests.Common.Mock; using OpenSim.Tests.Common.Mock;
namespace OpenSim.Tests.Torture namespace OpenSim.Tests.Performance
{ {
/// <summary> /// <summary>
/// Script torture tests /// Script performance tests
/// </summary> /// </summary>
/// <remarks> /// <remarks>
/// Don't rely on the numbers given by these tests - they will vary a lot depending on what is already cached, /// Don't rely on the numbers given by these tests - they will vary a lot depending on what is already cached,
@ -53,7 +53,7 @@ namespace OpenSim.Tests.Torture
/// earlier tests. /// earlier tests.
/// </remarks> /// </remarks>
[TestFixture] [TestFixture]
public class ScriptTortureTests public class ScriptPerformanceTests
{ {
private TestScene m_scene; private TestScene m_scene;
private XEngine m_xEngine; private XEngine m_xEngine;

View File

@ -0,0 +1,132 @@
/*
* Copyright (c) Contributors, http://opensimulator.org/
* See CONTRIBUTORS.TXT for a full list of copyright holders.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the OpenSimulator Project nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Threading;
using log4net.Config;
using NUnit.Framework;
using OpenMetaverse;
using OpenMetaverse.Assets;
using OpenSim.Framework;
using OpenSim.Region.CoreModules.Scripting.DynamicTexture;
using OpenSim.Region.CoreModules.Scripting.VectorRender;
using OpenSim.Region.Framework.Scenes;
using OpenSim.Region.Framework.Scenes.Serialization;
using OpenSim.Tests.Common;
using OpenSim.Tests.Common.Mock;
namespace OpenSim.Tests.Stress
{
[TestFixture]
public class VectorRenderModuleStressTests : OpenSimTestCase
{
public Scene Scene { get; private set; }
public DynamicTextureModule Dtm { get; private set; }
public VectorRenderModule Vrm { get; private set; }
private void SetupScene(bool reuseTextures)
{
Scene = new SceneHelpers().SetupScene();
Dtm = new DynamicTextureModule();
Dtm.ReuseTextures = reuseTextures;
Vrm = new VectorRenderModule();
SceneHelpers.SetupSceneModules(Scene, Dtm, Vrm);
}
[Test]
public void TestConcurrentRepeatedDraw()
{
int threads = 4;
TestHelpers.InMethod();
SetupScene(false);
List<Drawer> drawers = new List<Drawer>();
for (int i = 0; i < threads; i++)
{
Drawer d = new Drawer(this, i);
drawers.Add(d);
Console.WriteLine("Starting drawer {0}", i);
Util.FireAndForget(o => d.Draw());
}
Thread.Sleep(10 * 60 * 1000);
drawers.ForEach(d => d.Ready = false);
drawers.ForEach(d => Console.WriteLine("Drawer {0} drew {1} textures", d.Number, d.Pass + 1));
}
class Drawer
{
public int Number { get; private set; }
public int Pass { get; private set; }
public bool Ready { get; set; }
private VectorRenderModuleStressTests m_tests;
public Drawer(VectorRenderModuleStressTests tests, int number)
{
m_tests = tests;
Number = number;
Ready = true;
}
public void Draw()
{
SceneObjectGroup so = SceneHelpers.AddSceneObject(m_tests.Scene);
while (Ready)
{
UUID originalTextureID = so.RootPart.Shape.Textures.GetFace(0).TextureID;
// Ensure unique text
string text = string.Format("{0:D2}{1}", Number, Pass);
m_tests.Dtm.AddDynamicTextureData(
m_tests.Scene.RegionInfo.RegionID,
so.UUID,
m_tests.Vrm.GetContentType(),
string.Format("PenColour BLACK; MoveTo 40,220; FontSize 32; Text {0};", text),
"",
0);
Assert.That(originalTextureID, Is.Not.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID));
Pass++;
}
}
}
}
}

View File

@ -3289,7 +3289,47 @@
</Files> </Files>
</Project> </Project>
<Project frameworkVersion="v3_5" name="OpenSim.Tests.Torture" path="OpenSim/Tests/Torture" type="Library"> <Project frameworkVersion="v3_5" name="OpenSim.Tests.Stress" path="OpenSim/Tests/Stress" type="Library">
<Configuration name="Debug">
<Options>
<OutputPath>../../../bin/</OutputPath>
</Options>
</Configuration>
<Configuration name="Release">
<Options>
<OutputPath>../../../bin/</OutputPath>
</Options>
</Configuration>
<ReferencePath>../../../bin/</ReferencePath>
<Reference name="System"/>
<Reference name="System.Xml"/>
<Reference name="System.Data"/>
<Reference name="log4net" path="../../../bin/"/>
<Reference name="Nini" path="../../../bin/"/>
<Reference name="nunit.framework" path="../../../bin/"/>
<Reference name="OpenMetaverse" path="../../../bin/"/>
<Reference name="OpenMetaverseTypes" path="../../../bin/"/>
<Reference name="OpenMetaverse.StructuredData" path="../../../bin/"/>
<Reference name="XMLRPC" path="../../../bin/"/>
<Reference name="OpenSim.Framework"/>
<Reference name="OpenSim.Framework.Communications"/>
<Reference name="OpenSim.Framework.Console"/>
<Reference name="OpenSim.Framework.Servers.HttpServer"/>
<Reference name="OpenSim.Region.CoreModules"/>
<Reference name="OpenSim.Region.Framework"/>
<Reference name="OpenSim.Region.OptionalModules"/>
<Reference name="OpenSim.Region.ScriptEngine.Shared"/>
<Reference name="OpenSim.Region.ScriptEngine.XEngine"/>
<Reference name="OpenSim.Services.Interfaces"/>
<Reference name="OpenSim.Services.AvatarService"/>
<Reference name="OpenSim.Tests.Common"/>
<Files>
<Match pattern="*.cs" recurse="false"/>
</Files>
</Project>
<Project frameworkVersion="v3_5" name="OpenSim.Tests.Performance" path="OpenSim/Tests/Performance" type="Library">
<Configuration name="Debug"> <Configuration name="Debug">
<Options> <Options>
<OutputPath>../../../bin/</OutputPath> <OutputPath>../../../bin/</OutputPath>