Fix llListFindList() returning no match when there is a match with a script constant component in the source list.

Adds regression test for this case.
Based on http://opensimulator.org/mantis/view.php?id=6156
Thanks SignpostMarv.
0.7.4-extended
Justin Clark-Casey (justincc) 2012-09-22 00:23:25 +01:00
parent 176b1c85c0
commit eefd39a0d5
2 changed files with 150 additions and 8 deletions

View File

@ -5436,27 +5436,36 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
/// Returns the index of the first occurrence of test /// Returns the index of the first occurrence of test
/// in src. /// in src.
/// </summary> /// </summary>
/// <param name="src">Source list</param>
/// <param name="test">List to search for</param>
/// <returns>
/// The index number of the point in src where test was found if it was found.
/// Otherwise returns -1
/// </returns>
public LSL_Integer llListFindList(LSL_List src, LSL_List test) public LSL_Integer llListFindList(LSL_List src, LSL_List test)
{ {
int index = -1; int index = -1;
int length = src.Length - test.Length + 1; int length = src.Length - test.Length + 1;
m_host.AddScriptLPS(1); m_host.AddScriptLPS(1);
// If either list is empty, do not match // If either list is empty, do not match
if (src.Length != 0 && test.Length != 0) if (src.Length != 0 && test.Length != 0)
{ {
for (int i = 0; i < length; i++) for (int i = 0; i < length; i++)
{ {
if (src.Data[i].Equals(test.Data[0])) // Why this piece of insanity? This is because most script constants are C# value types (e.g. int)
// rather than wrapped LSL types. Such a script constant does not have int.Equal(LSL_Integer) code
// and so the comparison fails even if the LSL_Integer conceptually has the same value.
// Therefore, here we test Equals on both the source and destination objects.
// However, a future better approach may be use LSL struct script constants (e.g. LSL_Integer(1)).
if (src.Data[i].Equals(test.Data[0]) || test.Data[0].Equals(src.Data[i]))
{ {
int j; int j;
for (j = 1; j < test.Length; j++) for (j = 1; j < test.Length; j++)
if (!src.Data[i+j].Equals(test.Data[j])) if (!(src.Data[i+j].Equals(test.Data[j]) || test.Data[j].Equals(src.Data[i+j])))
break; break;
if (j == test.Length) if (j == test.Length)
{ {
index = i; index = i;
@ -5467,7 +5476,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
} }
return index; return index;
} }
public LSL_String llGetObjectName() public LSL_String llGetObjectName()

View File

@ -0,0 +1,134 @@
/*
* 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 NUnit.Framework;
using OpenSim.Framework;
using OpenSim.Tests.Common;
using OpenSim.Region.ScriptEngine.Shared;
using OpenSim.Region.Framework.Scenes;
using Nini.Config;
using OpenSim.Region.ScriptEngine.Shared.Api;
using OpenSim.Region.ScriptEngine.Shared.ScriptBase;
using OpenMetaverse;
using OpenSim.Tests.Common.Mock;
using LSL_Float = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLFloat;
using LSL_Integer = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLInteger;
using LSL_List = OpenSim.Region.ScriptEngine.Shared.LSL_Types.list;
using LSL_String = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString;
namespace OpenSim.Region.ScriptEngine.Shared.Tests
{
[TestFixture]
public class LSL_ApiListTests
{
private LSL_Api m_lslApi;
[SetUp]
public void SetUp()
{
IConfigSource initConfigSource = new IniConfigSource();
IConfig config = initConfigSource.AddConfig("XEngine");
config.Set("Enabled", "true");
Scene scene = new SceneHelpers().SetupScene();
SceneObjectPart part = SceneHelpers.AddSceneObject(scene).RootPart;
XEngine.XEngine engine = new XEngine.XEngine();
engine.Initialise(initConfigSource);
engine.AddRegion(scene);
m_lslApi = new LSL_Api();
m_lslApi.Initialize(engine, part, null);
}
[Test]
public void TestllListFindList()
{
TestHelpers.InMethod();
LSL_List src = new LSL_List(new LSL_Integer(1), new LSL_Integer(2), new LSL_Integer(3));
{
// Test for a single item that should be found
int result = m_lslApi.llListFindList(src, new LSL_List(new LSL_Integer(4)));
Assert.That(result, Is.EqualTo(-1));
}
{
// Test for a single item that should be found
int result = m_lslApi.llListFindList(src, new LSL_List(new LSL_Integer(2)));
Assert.That(result, Is.EqualTo(1));
}
{
// Test for a constant that should be found
int result = m_lslApi.llListFindList(src, new LSL_List(ScriptBaseClass.AGENT));
Assert.That(result, Is.EqualTo(0));
}
{
// Test for a list that should be found
int result = m_lslApi.llListFindList(src, new LSL_List(new LSL_Integer(2), new LSL_Integer(3)));
Assert.That(result, Is.EqualTo(1));
}
{
// Test for a single item not in the list
int result = m_lslApi.llListFindList(src, new LSL_List(new LSL_Integer(4)));
Assert.That(result, Is.EqualTo(-1));
}
{
// Test for something that should not be cast
int result = m_lslApi.llListFindList(src, new LSL_List(new LSL_String("4")));
Assert.That(result, Is.EqualTo(-1));
}
{
// Test for a list not in the list
int result
= m_lslApi.llListFindList(
src, new LSL_List(new LSL_Integer(2), new LSL_Integer(3), new LSL_Integer(4)));
Assert.That(result, Is.EqualTo(-1));
}
{
LSL_List srcWithConstants
= new LSL_List(new LSL_Integer(3), ScriptBaseClass.AGENT, ScriptBaseClass.OS_NPC_LAND_AT_TARGET);
// Test for constants that appears in the source list that should be found
int result
= m_lslApi.llListFindList(srcWithConstants, new LSL_List(new LSL_Integer(1), new LSL_Integer(2)));
Assert.That(result, Is.EqualTo(1));
}
}
}
}