From eefd39a0d5b88e8b54654accd7ba756dac377451 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Sat, 22 Sep 2012 00:23:25 +0100 Subject: [PATCH] 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. --- .../Shared/Api/Implementation/LSL_Api.cs | 24 ++-- .../Shared/Tests/LSL_ApiListTests.cs | 134 ++++++++++++++++++ 2 files changed, 150 insertions(+), 8 deletions(-) create mode 100644 OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiListTests.cs diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index 77f71df543..475e2bbf06 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -5436,27 +5436,36 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api /// Returns the index of the first occurrence of test /// in src. /// - + /// Source list + /// List to search for + /// + /// The index number of the point in src where test was found if it was found. + /// Otherwise returns -1 + /// public LSL_Integer llListFindList(LSL_List src, LSL_List test) { - int index = -1; int length = src.Length - test.Length + 1; m_host.AddScriptLPS(1); // If either list is empty, do not match - if (src.Length != 0 && test.Length != 0) { 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; 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; + if (j == test.Length) { index = i; @@ -5467,19 +5476,18 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api } return index; - } public LSL_String llGetObjectName() { m_host.AddScriptLPS(1); - return m_host.Name!=null?m_host.Name:String.Empty; + return m_host.Name !=null ? m_host.Name : String.Empty; } public void llSetObjectName(string name) { m_host.AddScriptLPS(1); - m_host.Name = name!=null?name:String.Empty; + m_host.Name = name != null ? name : String.Empty; } public LSL_String llGetDate() diff --git a/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiListTests.cs b/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiListTests.cs new file mode 100644 index 0000000000..dd23be8857 --- /dev/null +++ b/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiListTests.cs @@ -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)); + } + } + } + } \ No newline at end of file