Fix issue where lsl -> c# generation in co-operative termination mode did not correctly handle single statement versions of for, while and do-while loops.
Add regression tests to validate the fix. This problem will not affect the default abort termination mode.0.7.4-extended
parent
e67b84613d
commit
4a0b9c411e
|
@ -31,7 +31,6 @@ using System.Collections.Generic;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using log4net;
|
using log4net;
|
||||||
using Tools;
|
using Tools;
|
||||||
|
|
||||||
using OpenSim.Region.Framework.Interfaces;
|
using OpenSim.Region.Framework.Interfaces;
|
||||||
|
|
||||||
namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
|
namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
|
||||||
|
@ -479,19 +478,26 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
|
||||||
{
|
{
|
||||||
string retstr = String.Empty;
|
string retstr = String.Empty;
|
||||||
bool printSemicolon = true;
|
bool printSemicolon = true;
|
||||||
|
bool transformToBlock = false;
|
||||||
retstr += Indent();
|
|
||||||
|
|
||||||
if (m_insertCoopTerminationChecks)
|
if (m_insertCoopTerminationChecks)
|
||||||
{
|
{
|
||||||
// We have to check in event functions as well because the user can manually call these.
|
// A non-braced single line do while structure cannot contain multiple statements.
|
||||||
if (previousSymbol is GlobalFunctionDefinition
|
// So to insert the termination check we change this to a braced control structure instead.
|
||||||
|| previousSymbol is WhileStatement
|
if (previousSymbol is WhileStatement
|
||||||
|| previousSymbol is DoWhileStatement
|
|| previousSymbol is DoWhileStatement
|
||||||
|| previousSymbol is ForLoop
|
|| previousSymbol is ForLoop)
|
||||||
|| previousSymbol is StateEvent)
|
{
|
||||||
retstr += Generate(m_coopTerminationCheck);
|
transformToBlock = true;
|
||||||
|
|
||||||
|
// FIXME: This will be wrongly indented because the previous for/while/dowhile will have already indented.
|
||||||
|
retstr += GenerateIndentedLine("{");
|
||||||
|
|
||||||
|
retstr += GenerateIndentedLine(m_coopTerminationCheck);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
retstr += Indent();
|
||||||
|
|
||||||
if (0 < s.kids.Count)
|
if (0 < s.kids.Count)
|
||||||
{
|
{
|
||||||
|
@ -508,6 +514,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
|
||||||
if (printSemicolon)
|
if (printSemicolon)
|
||||||
retstr += GenerateLine(";");
|
retstr += GenerateLine(";");
|
||||||
|
|
||||||
|
if (transformToBlock)
|
||||||
|
{
|
||||||
|
// FIXME: This will be wrongly indented because the for/while/dowhile is currently handling the unindent
|
||||||
|
retstr += GenerateIndentedLine("}");
|
||||||
|
}
|
||||||
|
|
||||||
return retstr;
|
return retstr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -55,10 +55,22 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance.Tests
|
||||||
|
|
||||||
private OSChatMessage m_osChatMessageReceived;
|
private OSChatMessage m_osChatMessageReceived;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Number of chat messages received so far. Reset before each test.
|
||||||
|
/// </summary>
|
||||||
|
private int m_chatMessagesReceived;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Number of chat messages expected. m_chatEvent is not fired until this number is reached or exceeded.
|
||||||
|
/// </summary>
|
||||||
|
private int m_chatMessagesThreshold;
|
||||||
|
|
||||||
[SetUp]
|
[SetUp]
|
||||||
public void Init()
|
public void Init()
|
||||||
{
|
{
|
||||||
m_osChatMessageReceived = null;
|
m_osChatMessageReceived = null;
|
||||||
|
m_chatMessagesReceived = 0;
|
||||||
|
m_chatMessagesThreshold = 0;
|
||||||
m_chatEvent = new AutoResetEvent(false);
|
m_chatEvent = new AutoResetEvent(false);
|
||||||
m_stoppedEvent = new AutoResetEvent(false);
|
m_stoppedEvent = new AutoResetEvent(false);
|
||||||
|
|
||||||
|
@ -125,6 +137,25 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance.Tests
|
||||||
TestStop(script);
|
TestStop(script);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestNoStopOnSingleStatementForLoop()
|
||||||
|
{
|
||||||
|
TestHelpers.InMethod();
|
||||||
|
// TestHelpers.EnableLogging();
|
||||||
|
|
||||||
|
string script =
|
||||||
|
@"default
|
||||||
|
{
|
||||||
|
state_entry()
|
||||||
|
{
|
||||||
|
integer i = 0;
|
||||||
|
for (i = 0; i <= 1; i++) llSay(0, ""Iter "" + (string)i);
|
||||||
|
}
|
||||||
|
}";
|
||||||
|
|
||||||
|
TestSingleStatementNoStop(script);
|
||||||
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void TestStopOnLongSingleStatementForLoop()
|
public void TestStopOnLongSingleStatementForLoop()
|
||||||
{
|
{
|
||||||
|
@ -139,8 +170,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance.Tests
|
||||||
integer i = 0;
|
integer i = 0;
|
||||||
llSay(0, ""Thin Lizzy"");
|
llSay(0, ""Thin Lizzy"");
|
||||||
|
|
||||||
for (i = 0; i < 2147483647; i++)
|
for (i = 0; i < 2147483647; i++) llSay(0, ""Iter "" + (string)i);
|
||||||
llSay(0, ""Iter "" + (string)i);
|
|
||||||
}
|
}
|
||||||
}";
|
}";
|
||||||
|
|
||||||
|
@ -171,6 +201,25 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance.Tests
|
||||||
TestStop(script);
|
TestStop(script);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestNoStopOnSingleStatementWhileLoop()
|
||||||
|
{
|
||||||
|
TestHelpers.InMethod();
|
||||||
|
// TestHelpers.EnableLogging();
|
||||||
|
|
||||||
|
string script =
|
||||||
|
@"default
|
||||||
|
{
|
||||||
|
state_entry()
|
||||||
|
{
|
||||||
|
integer i = 0;
|
||||||
|
while (i < 2) llSay(0, ""Iter "" + (string)i++);
|
||||||
|
}
|
||||||
|
}";
|
||||||
|
|
||||||
|
TestSingleStatementNoStop(script);
|
||||||
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void TestStopOnLongSingleStatementWhileLoop()
|
public void TestStopOnLongSingleStatementWhileLoop()
|
||||||
{
|
{
|
||||||
|
@ -218,7 +267,50 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance.Tests
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void TestStopOnLongDoWhileLoop()
|
public void TestNoStopOnSingleStatementDoWhileLoop()
|
||||||
|
{
|
||||||
|
TestHelpers.InMethod();
|
||||||
|
// TestHelpers.EnableLogging();
|
||||||
|
|
||||||
|
string script =
|
||||||
|
@"default
|
||||||
|
{
|
||||||
|
state_entry()
|
||||||
|
{
|
||||||
|
integer i = 0;
|
||||||
|
|
||||||
|
do llSay(0, ""Iter "" + (string)i++);
|
||||||
|
while (i < 2);
|
||||||
|
}
|
||||||
|
}";
|
||||||
|
|
||||||
|
TestSingleStatementNoStop(script);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestStopOnLongSingleStatementDoWhileLoop()
|
||||||
|
{
|
||||||
|
TestHelpers.InMethod();
|
||||||
|
// TestHelpers.EnableLogging();
|
||||||
|
|
||||||
|
string script =
|
||||||
|
@"default
|
||||||
|
{
|
||||||
|
state_entry()
|
||||||
|
{
|
||||||
|
integer i = 0;
|
||||||
|
llSay(0, ""Thin Lizzy"");
|
||||||
|
|
||||||
|
do llSay(0, ""Iter "" + (string)i++);
|
||||||
|
while (1 == 1);
|
||||||
|
}
|
||||||
|
}";
|
||||||
|
|
||||||
|
TestStop(script);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestStopOnLongCompoundStatementDoWhileLoop()
|
||||||
{
|
{
|
||||||
TestHelpers.InMethod();
|
TestHelpers.InMethod();
|
||||||
// TestHelpers.EnableLogging();
|
// TestHelpers.EnableLogging();
|
||||||
|
@ -320,14 +412,13 @@ default
|
||||||
TestStop(script);
|
TestStop(script);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void TestStop(string script)
|
private SceneObjectPart CreateScript(string script, string itemName, UUID userId)
|
||||||
{
|
{
|
||||||
UUID userId = TestHelpers.ParseTail(0x1);
|
|
||||||
// UUID objectId = TestHelpers.ParseTail(0x100);
|
// UUID objectId = TestHelpers.ParseTail(0x100);
|
||||||
// UUID itemId = TestHelpers.ParseTail(0x3);
|
// UUID itemId = TestHelpers.ParseTail(0x3);
|
||||||
string itemName = "TestStop() Item";
|
|
||||||
|
|
||||||
SceneObjectGroup so = SceneHelpers.CreateSceneObject(1, userId, "TestStop", 0x100);
|
SceneObjectGroup so
|
||||||
|
= SceneHelpers.CreateSceneObject(1, userId, string.Format("Object for {0}", itemName), 0x100);
|
||||||
m_scene.AddNewSceneObject(so, true);
|
m_scene.AddNewSceneObject(so, true);
|
||||||
|
|
||||||
InventoryItemBase itemTemplate = new InventoryItemBase();
|
InventoryItemBase itemTemplate = new InventoryItemBase();
|
||||||
|
@ -338,14 +429,57 @@ default
|
||||||
|
|
||||||
m_scene.EventManager.OnChatFromWorld += OnChatFromWorld;
|
m_scene.EventManager.OnChatFromWorld += OnChatFromWorld;
|
||||||
|
|
||||||
SceneObjectPart partWhereRezzed = m_scene.RezNewScript(userId, itemTemplate, script);
|
return m_scene.RezNewScript(userId, itemTemplate, script);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void TestSingleStatementNoStop(string script)
|
||||||
|
{
|
||||||
|
// In these tests we expect to see at least 2 chat messages to confirm that the loop is working properly.
|
||||||
|
m_chatMessagesThreshold = 2;
|
||||||
|
|
||||||
|
UUID userId = TestHelpers.ParseTail(0x1);
|
||||||
|
// UUID objectId = TestHelpers.ParseTail(0x100);
|
||||||
|
// UUID itemId = TestHelpers.ParseTail(0x3);
|
||||||
|
string itemName = "TestNoStop";
|
||||||
|
|
||||||
|
SceneObjectPart partWhereRezzed = CreateScript(script, itemName, userId);
|
||||||
TaskInventoryItem rezzedItem = partWhereRezzed.Inventory.GetInventoryItem(itemName);
|
TaskInventoryItem rezzedItem = partWhereRezzed.Inventory.GetInventoryItem(itemName);
|
||||||
|
|
||||||
// Wait for the script to start the event before we try stopping it.
|
// Wait for the script to start the event before we try stopping it.
|
||||||
m_chatEvent.WaitOne(60000);
|
m_chatEvent.WaitOne(60000);
|
||||||
|
|
||||||
|
if (m_osChatMessageReceived == null)
|
||||||
|
Assert.Fail("Script did not start");
|
||||||
|
else
|
||||||
|
Assert.That(m_chatMessagesReceived, Is.EqualTo(2));
|
||||||
|
|
||||||
|
bool running;
|
||||||
|
TaskInventoryItem scriptItem = partWhereRezzed.Inventory.GetInventoryItem(itemName);
|
||||||
|
Assert.That(
|
||||||
|
SceneObjectPartInventory.TryGetScriptInstanceRunning(m_scene, scriptItem, out running), Is.True);
|
||||||
|
Assert.That(running, Is.True);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void TestStop(string script)
|
||||||
|
{
|
||||||
|
// In these tests we're only interested in the first message to confirm that the script has started.
|
||||||
|
m_chatMessagesThreshold = 1;
|
||||||
|
|
||||||
|
UUID userId = TestHelpers.ParseTail(0x1);
|
||||||
|
// UUID objectId = TestHelpers.ParseTail(0x100);
|
||||||
|
// UUID itemId = TestHelpers.ParseTail(0x3);
|
||||||
|
string itemName = "TestStop";
|
||||||
|
|
||||||
|
SceneObjectPart partWhereRezzed = CreateScript(script, itemName, userId);
|
||||||
|
TaskInventoryItem rezzedItem = partWhereRezzed.Inventory.GetInventoryItem(itemName);
|
||||||
|
|
||||||
|
// Wait for the script to start the event before we try stopping it.
|
||||||
|
m_chatEvent.WaitOne(60000);
|
||||||
|
|
||||||
|
if (m_osChatMessageReceived != null)
|
||||||
Console.WriteLine("Script started with message [{0}]", m_osChatMessageReceived.Message);
|
Console.WriteLine("Script started with message [{0}]", m_osChatMessageReceived.Message);
|
||||||
|
else
|
||||||
|
Assert.Fail("Script did not start");
|
||||||
|
|
||||||
// FIXME: This is a very poor way of trying to avoid a low-probability race condition where the script
|
// FIXME: This is a very poor way of trying to avoid a low-probability race condition where the script
|
||||||
// executes llSay() but has not started the next statement before we try to stop it.
|
// executes llSay() but has not started the next statement before we try to stop it.
|
||||||
|
@ -367,11 +501,14 @@ default
|
||||||
|
|
||||||
private void OnChatFromWorld(object sender, OSChatMessage oscm)
|
private void OnChatFromWorld(object sender, OSChatMessage oscm)
|
||||||
{
|
{
|
||||||
m_scene.EventManager.OnChatFromWorld -= OnChatFromWorld;
|
|
||||||
Console.WriteLine("Got chat [{0}]", oscm.Message);
|
Console.WriteLine("Got chat [{0}]", oscm.Message);
|
||||||
|
|
||||||
m_osChatMessageReceived = oscm;
|
m_osChatMessageReceived = oscm;
|
||||||
|
|
||||||
|
if (++m_chatMessagesReceived >= m_chatMessagesThreshold)
|
||||||
|
{
|
||||||
|
m_scene.EventManager.OnChatFromWorld -= OnChatFromWorld;
|
||||||
m_chatEvent.Set();
|
m_chatEvent.Set();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue