aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
authorJustin Clark-Casey (justincc)2013-01-30 03:44:56 +0000
committerJustin Clark-Casey (justincc)2013-01-30 03:52:22 +0000
commit5ac84a37935d8e1c62484032259d09f5ac95c0e7 (patch)
tree00917b383828319d974202e6f9c184808da68660
parentBulletSim: fix physics repositioning when under ground to only happen (diff)
downloadopensim-SC-5ac84a37935d8e1c62484032259d09f5ac95c0e7.zip
opensim-SC-5ac84a37935d8e1c62484032259d09f5ac95c0e7.tar.gz
opensim-SC-5ac84a37935d8e1c62484032259d09f5ac95c0e7.tar.bz2
opensim-SC-5ac84a37935d8e1c62484032259d09f5ac95c0e7.tar.xz
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.
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/CodeTools/CSCodeGenerator.cs30
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Instance/Tests/CoopTerminationTests.cs163
2 files changed, 171 insertions, 22 deletions
diff --git a/OpenSim/Region/ScriptEngine/Shared/CodeTools/CSCodeGenerator.cs b/OpenSim/Region/ScriptEngine/Shared/CodeTools/CSCodeGenerator.cs
index 985e598..9e32f40 100644
--- a/OpenSim/Region/ScriptEngine/Shared/CodeTools/CSCodeGenerator.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/CodeTools/CSCodeGenerator.cs
@@ -31,7 +31,6 @@ using System.Collections.Generic;
31using System.Reflection; 31using System.Reflection;
32using log4net; 32using log4net;
33using Tools; 33using Tools;
34
35using OpenSim.Region.Framework.Interfaces; 34using OpenSim.Region.Framework.Interfaces;
36 35
37namespace OpenSim.Region.ScriptEngine.Shared.CodeTools 36namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
@@ -479,20 +478,27 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
479 { 478 {
480 string retstr = String.Empty; 479 string retstr = String.Empty;
481 bool printSemicolon = true; 480 bool printSemicolon = true;
482 481 bool transformToBlock = false;
483 retstr += Indent();
484 482
485 if (m_insertCoopTerminationChecks) 483 if (m_insertCoopTerminationChecks)
486 { 484 {
487 // We have to check in event functions as well because the user can manually call these. 485 // A non-braced single line do while structure cannot contain multiple statements.
488 if (previousSymbol is GlobalFunctionDefinition 486 // So to insert the termination check we change this to a braced control structure instead.
489 || previousSymbol is WhileStatement 487 if (previousSymbol is WhileStatement
490 || previousSymbol is DoWhileStatement 488 || previousSymbol is DoWhileStatement
491 || previousSymbol is ForLoop 489 || previousSymbol is ForLoop)
492 || previousSymbol is StateEvent) 490 {
493 retstr += Generate(m_coopTerminationCheck); 491 transformToBlock = true;
492
493 // FIXME: This will be wrongly indented because the previous for/while/dowhile will have already indented.
494 retstr += GenerateIndentedLine("{");
495
496 retstr += GenerateIndentedLine(m_coopTerminationCheck);
497 }
494 } 498 }
495 499
500 retstr += Indent();
501
496 if (0 < s.kids.Count) 502 if (0 < s.kids.Count)
497 { 503 {
498 // Jump label prints its own colon, we don't need a semicolon. 504 // Jump label prints its own colon, we don't need a semicolon.
@@ -508,6 +514,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
508 if (printSemicolon) 514 if (printSemicolon)
509 retstr += GenerateLine(";"); 515 retstr += GenerateLine(";");
510 516
517 if (transformToBlock)
518 {
519 // FIXME: This will be wrongly indented because the for/while/dowhile is currently handling the unindent
520 retstr += GenerateIndentedLine("}");
521 }
522
511 return retstr; 523 return retstr;
512 } 524 }
513 525
diff --git a/OpenSim/Region/ScriptEngine/Shared/Instance/Tests/CoopTerminationTests.cs b/OpenSim/Region/ScriptEngine/Shared/Instance/Tests/CoopTerminationTests.cs
index 2c80826..7ea30bf1 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Instance/Tests/CoopTerminationTests.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Instance/Tests/CoopTerminationTests.cs
@@ -55,10 +55,22 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance.Tests
55 55
56 private OSChatMessage m_osChatMessageReceived; 56 private OSChatMessage m_osChatMessageReceived;
57 57
58 /// <summary>
59 /// Number of chat messages received so far. Reset before each test.
60 /// </summary>
61 private int m_chatMessagesReceived;
62
63 /// <summary>
64 /// Number of chat messages expected. m_chatEvent is not fired until this number is reached or exceeded.
65 /// </summary>
66 private int m_chatMessagesThreshold;
67
58 [SetUp] 68 [SetUp]
59 public void Init() 69 public void Init()
60 { 70 {
61 m_osChatMessageReceived = null; 71 m_osChatMessageReceived = null;
72 m_chatMessagesReceived = 0;
73 m_chatMessagesThreshold = 0;
62 m_chatEvent = new AutoResetEvent(false); 74 m_chatEvent = new AutoResetEvent(false);
63 m_stoppedEvent = new AutoResetEvent(false); 75 m_stoppedEvent = new AutoResetEvent(false);
64 76
@@ -126,6 +138,25 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance.Tests
126 } 138 }
127 139
128 [Test] 140 [Test]
141 public void TestNoStopOnSingleStatementForLoop()
142 {
143 TestHelpers.InMethod();
144// TestHelpers.EnableLogging();
145
146 string script =
147@"default
148{
149 state_entry()
150 {
151 integer i = 0;
152 for (i = 0; i <= 1; i++) llSay(0, ""Iter "" + (string)i);
153 }
154}";
155
156 TestSingleStatementNoStop(script);
157 }
158
159 [Test]
129 public void TestStopOnLongSingleStatementForLoop() 160 public void TestStopOnLongSingleStatementForLoop()
130 { 161 {
131 TestHelpers.InMethod(); 162 TestHelpers.InMethod();
@@ -139,8 +170,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance.Tests
139 integer i = 0; 170 integer i = 0;
140 llSay(0, ""Thin Lizzy""); 171 llSay(0, ""Thin Lizzy"");
141 172
142 for (i = 0; i < 2147483647; i++) 173 for (i = 0; i < 2147483647; i++) llSay(0, ""Iter "" + (string)i);
143 llSay(0, ""Iter "" + (string)i);
144 } 174 }
145}"; 175}";
146 176
@@ -172,6 +202,25 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance.Tests
172 } 202 }
173 203
174 [Test] 204 [Test]
205 public void TestNoStopOnSingleStatementWhileLoop()
206 {
207 TestHelpers.InMethod();
208// TestHelpers.EnableLogging();
209
210 string script =
211@"default
212{
213 state_entry()
214 {
215 integer i = 0;
216 while (i < 2) llSay(0, ""Iter "" + (string)i++);
217 }
218}";
219
220 TestSingleStatementNoStop(script);
221 }
222
223 [Test]
175 public void TestStopOnLongSingleStatementWhileLoop() 224 public void TestStopOnLongSingleStatementWhileLoop()
176 { 225 {
177 TestHelpers.InMethod(); 226 TestHelpers.InMethod();
@@ -218,7 +267,50 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance.Tests
218 } 267 }
219 268
220 [Test] 269 [Test]
221 public void TestStopOnLongDoWhileLoop() 270 public void TestNoStopOnSingleStatementDoWhileLoop()
271 {
272 TestHelpers.InMethod();
273// TestHelpers.EnableLogging();
274
275 string script =
276@"default
277{
278 state_entry()
279 {
280 integer i = 0;
281
282 do llSay(0, ""Iter "" + (string)i++);
283 while (i < 2);
284 }
285}";
286
287 TestSingleStatementNoStop(script);
288 }
289
290 [Test]
291 public void TestStopOnLongSingleStatementDoWhileLoop()
292 {
293 TestHelpers.InMethod();
294// TestHelpers.EnableLogging();
295
296 string script =
297@"default
298{
299 state_entry()
300 {
301 integer i = 0;
302 llSay(0, ""Thin Lizzy"");
303
304 do llSay(0, ""Iter "" + (string)i++);
305 while (1 == 1);
306 }
307}";
308
309 TestStop(script);
310 }
311
312 [Test]
313 public void TestStopOnLongCompoundStatementDoWhileLoop()
222 { 314 {
223 TestHelpers.InMethod(); 315 TestHelpers.InMethod();
224// TestHelpers.EnableLogging(); 316// TestHelpers.EnableLogging();
@@ -234,7 +326,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance.Tests
234 do 326 do
235 { 327 {
236 llSay(0, ""Iter "" + (string)i++); 328 llSay(0, ""Iter "" + (string)i++);
237} while (1 == 1); 329 } while (1 == 1);
238 } 330 }
239}"; 331}";
240 332
@@ -320,14 +412,13 @@ default
320 TestStop(script); 412 TestStop(script);
321 } 413 }
322 414
323 private void TestStop(string script) 415 private SceneObjectPart CreateScript(string script, string itemName, UUID userId)
324 { 416 {
325 UUID userId = TestHelpers.ParseTail(0x1);
326// UUID objectId = TestHelpers.ParseTail(0x100); 417// UUID objectId = TestHelpers.ParseTail(0x100);
327// UUID itemId = TestHelpers.ParseTail(0x3); 418// UUID itemId = TestHelpers.ParseTail(0x3);
328 string itemName = "TestStop() Item";
329 419
330 SceneObjectGroup so = SceneHelpers.CreateSceneObject(1, userId, "TestStop", 0x100); 420 SceneObjectGroup so
421 = SceneHelpers.CreateSceneObject(1, userId, string.Format("Object for {0}", itemName), 0x100);
331 m_scene.AddNewSceneObject(so, true); 422 m_scene.AddNewSceneObject(so, true);
332 423
333 InventoryItemBase itemTemplate = new InventoryItemBase(); 424 InventoryItemBase itemTemplate = new InventoryItemBase();
@@ -338,14 +429,57 @@ default
338 429
339 m_scene.EventManager.OnChatFromWorld += OnChatFromWorld; 430 m_scene.EventManager.OnChatFromWorld += OnChatFromWorld;
340 431
341 SceneObjectPart partWhereRezzed = m_scene.RezNewScript(userId, itemTemplate, script); 432 return m_scene.RezNewScript(userId, itemTemplate, script);
433 }
434
435 private void TestSingleStatementNoStop(string script)
436 {
437 // In these tests we expect to see at least 2 chat messages to confirm that the loop is working properly.
438 m_chatMessagesThreshold = 2;
342 439
440 UUID userId = TestHelpers.ParseTail(0x1);
441// UUID objectId = TestHelpers.ParseTail(0x100);
442// UUID itemId = TestHelpers.ParseTail(0x3);
443 string itemName = "TestNoStop";
444
445 SceneObjectPart partWhereRezzed = CreateScript(script, itemName, userId);
343 TaskInventoryItem rezzedItem = partWhereRezzed.Inventory.GetInventoryItem(itemName); 446 TaskInventoryItem rezzedItem = partWhereRezzed.Inventory.GetInventoryItem(itemName);
344 447
345 // Wait for the script to start the event before we try stopping it. 448 // Wait for the script to start the event before we try stopping it.
346 m_chatEvent.WaitOne(60000); 449 m_chatEvent.WaitOne(60000);
347 450
348 Console.WriteLine("Script started with message [{0}]", m_osChatMessageReceived.Message); 451 if (m_osChatMessageReceived == null)
452 Assert.Fail("Script did not start");
453 else
454 Assert.That(m_chatMessagesReceived, Is.EqualTo(2));
455
456 bool running;
457 TaskInventoryItem scriptItem = partWhereRezzed.Inventory.GetInventoryItem(itemName);
458 Assert.That(
459 SceneObjectPartInventory.TryGetScriptInstanceRunning(m_scene, scriptItem, out running), Is.True);
460 Assert.That(running, Is.True);
461 }
462
463 private void TestStop(string script)
464 {
465 // In these tests we're only interested in the first message to confirm that the script has started.
466 m_chatMessagesThreshold = 1;
467
468 UUID userId = TestHelpers.ParseTail(0x1);
469// UUID objectId = TestHelpers.ParseTail(0x100);
470// UUID itemId = TestHelpers.ParseTail(0x3);
471 string itemName = "TestStop";
472
473 SceneObjectPart partWhereRezzed = CreateScript(script, itemName, userId);
474 TaskInventoryItem rezzedItem = partWhereRezzed.Inventory.GetInventoryItem(itemName);
475
476 // Wait for the script to start the event before we try stopping it.
477 m_chatEvent.WaitOne(60000);
478
479 if (m_osChatMessageReceived != null)
480 Console.WriteLine("Script started with message [{0}]", m_osChatMessageReceived.Message);
481 else
482 Assert.Fail("Script did not start");
349 483
350 // FIXME: This is a very poor way of trying to avoid a low-probability race condition where the script 484 // FIXME: This is a very poor way of trying to avoid a low-probability race condition where the script
351 // executes llSay() but has not started the next statement before we try to stop it. 485 // executes llSay() but has not started the next statement before we try to stop it.
@@ -367,11 +501,14 @@ default
367 501
368 private void OnChatFromWorld(object sender, OSChatMessage oscm) 502 private void OnChatFromWorld(object sender, OSChatMessage oscm)
369 { 503 {
370 m_scene.EventManager.OnChatFromWorld -= OnChatFromWorld;
371 Console.WriteLine("Got chat [{0}]", oscm.Message); 504 Console.WriteLine("Got chat [{0}]", oscm.Message);
372
373 m_osChatMessageReceived = oscm; 505 m_osChatMessageReceived = oscm;
374 m_chatEvent.Set(); 506
507 if (++m_chatMessagesReceived >= m_chatMessagesThreshold)
508 {
509 m_scene.EventManager.OnChatFromWorld -= OnChatFromWorld;
510 m_chatEvent.Set();
511 }
375 } 512 }
376 } 513 }
377} \ No newline at end of file 514} \ No newline at end of file