LSL Language Test 2

From Second Life Wiki
Jump to navigation Jump to search

<lsl> integer gTestsPassed = 0; integer gTestsFailed = 0;

key gNullKey = NULL_KEY; key gStringInAKey = "foo"; string gKeyInAString = gNullKey;

integer gVisitedStateTest = FALSE;

testPassed(string description, string actual, string expected) {

   ++gTestsPassed;
   //llSay(0, description);

}

testFailed(string description, string actual, string expected) {

   ++gTestsFailed;
   llSay(0, "FAILED!: " + description + " (" + actual + " expected " + expected + ")");

}

ensureTrue(string description, integer actual) {

   if(actual)
   {
       testPassed(description, (string) actual, (string) TRUE);
   }
   else
   {
       testFailed(description, (string) actual, (string) TRUE);
   }

}

ensureFalse(string description, integer actual) {

   if(actual)
   {
       testFailed(description, (string) actual, (string) FALSE);
   }
   else
   {
       testPassed(description, (string) actual, (string) FALSE);
   }

}

ensureIntegerEqual(string description, integer actual, integer expected) {

   if(actual == expected)
   {
       testPassed(description, (string) actual, (string) expected);
   }
   else
   {
       testFailed(description, (string) actual, (string) expected);
   }

}

integer floatEqual(float actual, float expected) {

   float error = llFabs(expected - actual);
   float epsilon = 0.001;
   if(error > epsilon)
   {
       llSay(0,"Float equality delta " + (string)error);
       return FALSE;
   }
   return TRUE;

}

ensureFloatEqual(string description, float actual, float expected) {

   if(floatEqual(actual, expected))
   {
       testPassed(description, (string) actual, (string) expected);
   }
   else
   {
       testFailed(description, (string) actual, (string) expected);
   }

}

ensureFloatExactEqual(string description, float actual, float expected) {

   if(actual == expected)
   {
       testPassed(description, (string) actual, (string) expected);
   }
   else
   {
       testFailed(description, (string) actual, (string) expected);
   }

}

ensureStringEqual(string description, string actual, string expected) {

   if(actual == expected)
   {
       testPassed(description, (string) actual, (string) expected);
   }
   else
   {
       testFailed(description, (string) actual, (string) expected);
   }

}

ensureKeyEqual(string description, key actual, key expected) {

   if(actual == expected)
   {
       testPassed(description, (string) actual, (string) expected);
   }
   else
   {
       testFailed(description, (string) actual, (string) expected);
   }

}

ensureVectorEqual(string description, vector actual, vector expected) {

   if(floatEqual(actual.x, expected.x) &&
       floatEqual(actual.y, expected.y) &&
       floatEqual(actual.z, expected.z))
   {
       testPassed(description, (string) actual, (string) expected);
   }
   else
   {
       testFailed(description, (string) actual, (string) expected);
   }

}

ensureRotationEqual(string description, rotation actual, rotation expected) {

   if(floatEqual(actual.x, expected.x) &&
       floatEqual(actual.y, expected.y) &&
       floatEqual(actual.z, expected.z) &&
       floatEqual(actual.s, expected.s))
   {
       testPassed(description, (string) actual, (string) expected);
   }
   else
   {
       testFailed(description, (string) actual, (string) expected);
   }

}

ensureListEqual(string description, list actual, list expected) {

   if(actual == expected)
   {
       testPassed(description, (string) actual, (string) expected);
   }
   else
   {
       testFailed(description, (string) actual, (string) expected);
   }

}

vector gVector;

float testReturnFloat() {

   return 1.0;

}


key testReturnKey() {

   return NULL_KEY;

}

testArgumentAccessor(vector v) {

   v = <0,0,0>;
   v.x = testReturnFloat();
   v.y = testReturnFloat();
   v.z = testReturnFloat();
   ensureVectorEqual("testArgumentAccessor", v, <1,1,1>);

}

testLocalAccessor() {

   vector v = <0,0,0>;
   v.x = testReturnFloat();
   v.y = testReturnFloat();
   v.z = testReturnFloat();
   ensureVectorEqual("testLocalAccessor", v, <1,1,1>);

}

testGlobalAccessor() {

   gVector = <0,0,0>;
   gVector.x = testReturnFloat();
   gVector.y = testReturnFloat();
   gVector.z = testReturnFloat();
   ensureVectorEqual("testGlobalAccessor", gVector, <1,1,1>);

}

tests() {

   // Ensure that multiple states containing the same handler work (SVC-1372 Regression)
   ensureTrue("gVisitedStateTest ", gVisitedStateTest);

   ensureFloatExactEqual("1.4e-45 == (float)\"1.4e-45\"", 1.4e-45, (float)"1.4e-45");

   // Managed pointer save/restore tests.
   testArgumentAccessor(<0,0,0>);
   testLocalAccessor();
   testGlobalAccessor();

   // Multiple list element saving (SVC-1712 Regression)
   ensureStringEqual("(string)[1, testReturnFloat(), testReturnFloat()] == \"11.01.0\"", (string)[1, testReturnFloat(), testReturnFloat()], "11.0000001.000000");

   // Key equality (SVC-1720 Regression)
   key k = "foo";
   key k2 = "foo";
   ensureKeyEqual("k = \"foo\";k2 = \"foo\";k == k2", k, k2);

   // List comparison. Not actual comparison, just length.
   ensureIntegerEqual("[] == []", [] == [], 1);
   ensureIntegerEqual("[1] == [2]", [1] == [2], 1);
   ensureIntegerEqual("[1,2] == [1,2]", [1,2] == [1,2], 1);
   ensureIntegerEqual("[1,2] == [2]", [1,2] == [2], 0);
   ensureIntegerEqual("[1] == [2,3]", [1] == [2,3], 0);

   ensureIntegerEqual("[] != []", [] != [], 0);
   ensureIntegerEqual("[1] != [2]", [1] != [2], 0);
   ensureIntegerEqual("[1,2] != [1,2]", [1,2] != [1,2], 0);
   ensureIntegerEqual("[1,2] != [2]", [1,2] != [2], 1);
   ensureIntegerEqual("[1] != [2,3]", [1] != [2,3], -1);

   // Parsing numbers with junk after
   ensureFloatEqual("(float)\"5.0a\" == 5.0", (float) "5a", 5.0);
   ensureFloatEqual("(integer)\"12foo\" == 12", (integer) "12foo", 12);

   // List value semantics across addition (SVC-1448 Regression)
   list l;
   l = [42];
   l + 1;
   ensureListEqual("list l = [42]; l + 1; l == [42]", l, [42]);
   l = [42];
   l + 1.5;
   ensureListEqual("list l = [42]; l + 1.5; l == [42]", l, [42]);
   l = [42];
   l + NULL_KEY;
   ensureListEqual("list l = [42]; l + NULL_KEY; l == [42]", l, [42]);
   l = [42];
   l + <1,2,3>;    
   ensureListEqual("list l = [42]; l + <1,2,3>; l == [42]", l, [42]);
   l = [42];
   l + <1,2,3,4>;    
   ensureListEqual("list l = [42]; l + <1,2,3>; l == [42]", l, [42]);


   // Conditional test of key (SVC-1776/SVC-1811 Regression)
   if(k)
   {
       testFailed("if(k)", "TRUE", "FALSE");
   }
   else
   {
       testPassed("if(k)", "FALSE", "FALSE");
   }

   // String/Key equality (SVC-1770 Regression)
   ensureIntegerEqual("k == \"foo\"",k == "foo", TRUE);

   // String/Key equality (SVC-1772 Regression)
   ensureIntegerEqual("gStringInAKey == \"foo\"", gStringInAKey == "foo", TRUE);
   ensureIntegerEqual("gNullKey == NULL_KEY", gNullKey == NULL_KEY, TRUE);

   // Key to string cast on assignment (SVC-1707 Regression)
   k = NULL_KEY;
   string s;
   s = k;
   ensureStringEqual("k = NULL_KEY; string s; s = k;", s, NULL_KEY);

   // Loop semantics for vectors
   vector v = <1,1,1>;
   while (v) { v = ZERO_VECTOR; } 
   ensureVectorEqual( "while (v) { v = ZERO_VECTOR; }", v, ZERO_VECTOR);

   v = <2,2,2>;
   do {  v = ZERO_VECTOR; } while (v);   
   ensureVectorEqual( "v = <2,2,2>; do { v = ZERO_VECTOR } while (v);", v, ZERO_VECTOR);

   for (v = <3,3,3>;v;v=ZERO_VECTOR) {}
   ensureVectorEqual( "for (v = <3,3,3>;v;v=ZERO_VECTOR) {}", v, ZERO_VECTOR);

   // Loops with keys
   k = "7c42811e-229f-4500-b6d7-2c37324ff816";
   while (k) { k = NULL_KEY; } 
   ensureKeyEqual( "while (k) { k = NULL_KEY; }", k, NULL_KEY);

   k = "7c42811e-229f-4500-b6d7-2c37324ff816";
   do {  k = NULL_KEY; } while (k);   
   ensureKeyEqual( "k = \"7c42811e-229f-4500-b6d7-2c37324ff816\"; do { k = NULL_KEY } while (k);", k, NULL_KEY);

   for (k = "7c42811e-229f-4500-b6d7-2c37324ff816"; k; k=NULL_KEY) {}
   ensureKeyEqual( "for (k = \"7c42811e-229f-4500-b6d7-2c37324ff816\";k;k=NULL_KEY) {}", k, NULL_KEY);  

   // Loops with rotations
   rotation q = <1,1,1,1>;
   while (q) { q = ZERO_ROTATION; } 
   ensureRotationEqual( "while (q) { q = ZERO_ROTATION; }", q, ZERO_ROTATION);

   q = <2,2,2,2>;
   do {  q = ZERO_ROTATION; } while (q);   
   ensureRotationEqual( "q = <2,2,2>; do { v = ZERO_ROTATION } while (q);", q, ZERO_ROTATION);

   for (q = <3,3,3,3>; q; q=ZERO_ROTATION) {}
   ensureRotationEqual( "for (q = <3,3,3,3>;q;q=ZERO_ROTATION) {}", q, ZERO_ROTATION);    

   // Loops with lists
   l = [1];
   while (l) { l = []; } 
   ensureListEqual( "while (l) { l = []; }", l, []); // Fails on LSL, SVC-689

   l = [2];
   do { l = []; } while (l);   
   ensureListEqual( "l = [2]; do { v = [] } while (l);", l, []);

   for (l = [3]; l; l=[]) {}
   ensureListEqual( "for (l = [3];l;l=[]) {}", l, []);  // Fails on LSL, SVC-689

   // Loop for strings
   s = "1!";
   while (s) { s = ""; } 
   ensureStringEqual( "while (s) { s = \"\"; }", s, "");

   s = "2!";
   do {  s = ""; } while (s);   
   ensureStringEqual( "s = \"2!\"; do { s = \"\" } while (s);", s, "");

   for (s = "3!";s;s="") {}
   ensureStringEqual( "for (s = \"3!\";s;s=\"\") {}", s, "");

   // Loop for integers
   integer i = 1;
   while (i) { i = 0; } 
   ensureIntegerEqual( "while (i) { i = 0; }", i, 0);

   i = 2;
   do {  i = 0; } while (i);   
   ensureIntegerEqual( "i = 2; do { i = 0 } while (i);", i, 0);

   for (i = 3;i;i=0) {}
   ensureIntegerEqual( "for (i = 3;i;i=0) {}", i, 0);    

   // Loop for floats
   float f = 1;
   while (f) { f = 0; } 
   ensureFloatEqual( "while (f) { f = 0; }", f, 0);

   f = 2;
   do {  f = 0; } while (f);   
   ensureFloatEqual( "f = 2; do { f = 0 } while (f);", f, 0);

   for (f = 3;f;f=0) {}
   ensureFloatEqual( "for (f = 3;f;f=0) {}", f, 0);  


   // Unary vector multiplication
   v = <1,2,3>;
   v *= 2;
   ensureVectorEqual("v = <1,2,3>; v *= 2;", v, <2,4,6>);

   v = <1,2,3>;
   v *= 0.5;
   ensureVectorEqual("v = <1,2,3>; v *= 0.5;", v, <0.5,1,1.5>);

   // Indentify rotation
   v = <1,0,0>;
   v *= ZERO_ROTATION;
   ensureVectorEqual("vector v = <1,0,0>; v *= ZERO_ROTATION;", v, <1,0,0>);

   // Unary vector cross product (note no unary dot product exists)
   v = <0,1,0>;
   v %= <0,0,1>;
   ensureVectorEqual("vector v = <0,1,0>; v %= <0,0,1>;", v, <1,0,0>);

   // Unary rotation
   rotation r = ZERO_ROTATION;
   r *= ZERO_ROTATION;
   ensureRotationEqual("rotation r = ZERO_ROTATION; r *= ZERO_ROTATION;",r,ZERO_ROTATION);


   // SVC-1399 Floating point negative zero
   ensureStringEqual("(string)-0.0", (string)-0.0, "-0.000000");
   ensureStringEqual("(string)<-0.0,0.0,-0.0>", (string)<-0.0,0.0,-0.0>, "<-0.00000, 0.00000, -0.00000>");
   ensureStringEqual("(string)<-0.0,0.0,-0.0,0.0>", 
       (string)<-0.0,0.0,-0.0,0.0>, "<-0.00000, 0.00000, -0.00000, 0.00000>");

   ensureStringEqual("llList2CSV([-0.0, <-0.0,0.0,-0.0>, <-0.0,0.0,-0.0,0.0>])", 
       llList2CSV([-0.0, <-0.0,0.0,-0.0>, <-0.0,0.0,-0.0,0.0>]), 
       "-0.000000, <-0.000000, 0.000000, -0.000000>, <-0.000000, 0.000000, -0.000000, 0.000000>");

   ensureStringEqual("llDumpList2String([-0.0, <-0.0,0.0,-0.0>, <-0.0,0.0,-0.0,0.0>], \" ~ \")", 
       llDumpList2String([-0.0, <-0.0,0.0,-0.0>, <-0.0,0.0,-0.0,0.0>], " ~ "), 
       "-0.000000 ~ <-0.000000, 0.000000, -0.000000> ~ <-0.000000, 0.000000, -0.000000, 0.000000>");

   ensureStringEqual("(string)[-0.0, <-0.0,0.0,-0.0>, <-0.0,0.0,-0.0,0.0>]", 
       (string)[-0.0, <-0.0,0.0,-0.0>, <-0.0,0.0,-0.0,0.0>], 
       "-0.000000<-0.000000, 0.000000, -0.000000><-0.000000, 0.000000, -0.000000, 0.000000>");

   ensureStringEqual("llList2String([-0.0], 0)", llList2String([-0.0], 0), "-0.000000"); 

   ensureStringEqual("(string)(float)\"-0.0\"", (string)((float)"-0.0"), "-0.000000");
   ensureStringEqual("(string)(vector)\"<-0.0,0.0,-0.0>\"", 
       (string)((vector)"<-0.0,0.0,-0.0>"), "<-0.00000, 0.00000, -0.00000>");
   ensureStringEqual("(string)(rotation)\"<-0.0,0.0,-0.0,0.0>\"", 
       (string)((rotation)"<-0.0,0.0,-0.0,0.0>"), "<-0.00000, 0.00000, -0.00000, 0.00000>");

   ensureKeyEqual("testReturnKey() == NULL_KEY", testReturnKey(), NULL_KEY);
   
   
   key defaultKey;
   ensureKeyEqual("key defaultKey;", defaultKey, "");
   
   integer defaultInteger;
   ensureIntegerEqual("key defaultInteger;", defaultInteger, 0);
   
   float defaultFloat;
   ensureFloatEqual("key defaultInteger;", defaultFloat, 0);
   
   string defaultString;
   ensureStringEqual("string defaultString;", defaultString, "");

}

runTests() {

   llResetTime();
   tests();
   llSay(0, "Ran " + (string)(gTestsPassed + gTestsFailed) + " tests in " + (string) llGetTime() + " seconds with " + (string)gTestsFailed + " failures");

   // Reset globals.
   gVisitedStateTest = FALSE;
   gTestsPassed = 0;
   gTestsFailed = 0;

}

default {

   state_entry()
   {
       state StateTest;
   }

   touch_start(integer total_number)
   {
       state StateTest;
   }

}

state StateTest {

   state_entry()
   {
       ensureFalse("gVisitedStateTest", gVisitedStateTest);
       gVisitedStateTest = TRUE;
       runTests();
   }

   touch_start(integer total_number)
   {
       state default;
   }

} </lsl>