Initial sources for planned 2.0 luaj vm release. Most interpreter features and library functions working.

This commit is contained in:
James Roseborough
2009-10-27 06:12:24 +00:00
parent d16fad00e8
commit 3863ff8e46
116 changed files with 33600 additions and 122 deletions

View File

@@ -0,0 +1,74 @@
/*******************************************************************************
* Copyright (c) 2009 Luaj.org. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
******************************************************************************/
package org.luaj.luajc;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import org.luaj.vm2.LuaClosure;
import org.luaj.vm2.Print;
import org.luaj.vm2.Prototype;
import org.luaj.vm2.LuaTable;
import org.luaj.vm2.LuaValue;
import org.luaj.vm2.compiler.LuaC;
import org.luaj.vm2.lib.JsePlatform;
/** Test the plain old bytecode interpreter */
public class TestLuaJ {
// create the script
public static String name = "script";
public static String script =
"function r(q,...)\n"+
" local a=arg\n"+
" return a and a[2]\n"+
"end\n" +
"function s(q,...)\n"+
" local a=arg\n"+
" local b=...\n"+
" return a and a[2],b\n"+
"end\n" +
"print( r(111,222,333),s(111,222,333) )";
public static void main(String[] args) throws Exception {
System.out.println(script);
// create an environment to run in
LuaTable _G = JsePlatform.standardGlobals();
LuaC.install();
// compile into a chunk, or load as a class
InputStream is = new ByteArrayInputStream( script.getBytes() );
Prototype p = LuaC.compile(is, "script");
print( p );
LuaValue chunk = new LuaClosure(p,_G);
chunk.call();
}
private static void print(Prototype p) {
System.out.println("--- "+p.is_vararg);
Print.printCode(p);
if (p.p!=null)
for ( int i=0,n=p.p.length; i<n; i++ )
print( p.p[i] );
}
}

View File

@@ -0,0 +1,71 @@
/*******************************************************************************
* Copyright (c) 2009 Luaj.org. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
******************************************************************************/
package org.luaj.luajc;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import org.luaj.vm2.LuaTable;
import org.luaj.vm2.LuaValue;
import org.luaj.vm2.Varargs;
import org.luaj.vm2.lib.JsePlatform;
import org.luaj.vm2.luajc.LuaJCompiler;
public class TestLuaJC {
// create the script
public static String name = "script";
public static String script =
"local a='a\\ab\\bf\\fn\\nt\\tv\\vw\\133x\\222y'\n"+
"local t={string.byte(a,1,#a)}\n"+
"print( table.concat(t,',') )\n";
public static void main(String[] args) throws Exception {
System.out.println(script);
// create an environment to run in
LuaTable _G = JsePlatform.standardGlobals();
// compile into a chunk, or load as a class
LuaValue chunk;
if ( ! (args.length>0 && args[0].equals("nocompile")) ) {
InputStream is = new ByteArrayInputStream( script.getBytes() );
String java =LuaJCompiler.compileToJava(is, "script");
System.out.println("java:\n"+java);
chunk = LuaJCompiler.javaCompile(java, "script");
} else {
chunk = (LuaValue) Class.forName("script").newInstance();
}
chunk.setfenv(_G);
// call with arguments
LuaValue[] vargs = new LuaValue[args.length];
for ( int i=0; i<args.length; i++ )
vargs[i] = LuaValue.valueOf(args[i]);
Varargs cargs = LuaValue.varargsOf(vargs);
Varargs v = chunk.invoke(cargs);
// print the result
for ( int i=1; i<=v.narg(); i++ )
System.out.println("result["+i+"]: "+v.arg(i));
}
}

View File

@@ -0,0 +1,66 @@
/*******************************************************************************
* Copyright (c) 2009 Luaj.org. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
******************************************************************************/
package org.luaj.vm2;
import junit.framework.Test;
import junit.framework.TestSuite;
import org.luaj.vm2.CompatibiltyTest.LuaJCCompatibilityTest;
import org.luaj.vm2.WeakTableTest.WeakKeyTableTest;
import org.luaj.vm2.WeakTableTest.WeakKeyValueTableTest;
public class AllTests {
public static Test suite() {
TestSuite suite = new TestSuite("All Tests for Luaj-vm2");
// table tests
TestSuite vm = new TestSuite("VM Tests");
vm.addTestSuite(TypeTest.class);
vm.addTestSuite(UnaryBinaryOperatorsTest.class);
vm.addTestSuite(MetatableTest.class);
vm.addTestSuite(LuaOperationsTest.class);
suite.addTest(vm);
// table tests
TestSuite table = new TestSuite("Table Tests");
table.addTestSuite(TableTest.class);
table.addTestSuite(TableArrayTest.class);
table.addTestSuite(TableHashTest.class);
table.addTestSuite(WeakTableTest.class);
table.addTestSuite(WeakKeyTableTest.class);
table.addTestSuite(WeakKeyValueTableTest.class);
suite.addTest(table);
// compatiblity tests
suite.addTest(CompatibiltyTest.suite());
// luajc regression tests
TestSuite luajc = new TestSuite("Luajc Tests");
luajc.addTestSuite(FragmentsTest.class);
luajc.addTest( new TestSuite( LuaJCCompatibilityTest.class, "LuaJC Compatiblity Tests" ) );
suite.addTest(luajc);
return suite;
}
}

View File

@@ -0,0 +1,94 @@
/*******************************************************************************
* Copyright (c) 2009 Luaj.org. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
******************************************************************************/
package org.luaj.vm2;
import junit.framework.Test;
import junit.framework.TestSuite;
/**
* Compatibility tests for the Luaj VM
*
* Results are compared for exact match with
* the installed C-based lua environment.
*/
public class CompatibiltyTest {
private static final String dir = "test/lua";
abstract protected static class CompatibiltyTestSuite extends ScriptDrivenTest {
protected CompatibiltyTestSuite(PlatformType platform) {
super(platform,dir);
}
public void testBaseLib() { runTest("baselib"); }
public void testCoroutineLib() { runTest("coroutinelib"); }
public void testDebugLib() { runTest("debuglib"); }
public void testErrors() { runTest("errors"); }
public void testFunctions() { runTest("functions"); }
public void testIoLib() { runTest("iolib"); }
public void testMathLib() { runTest("mathlib"); }
public void testOsLib() { runTest("oslib"); }
public void testStringLib() { runTest("stringlib"); }
public void testTableLib() { runTest("tablelib"); }
public void testTailcalls() { runTest("tailcalls"); }
public void testUpvalues() { runTest("upvalues"); }
public void testVm() { runTest("vm"); }
}
public static Test suite() {
TestSuite suite = new TestSuite("Compatibility Tests");
suite.addTest( new TestSuite( JseCompatibilityTest.class, "JSE Tests" ) );
suite.addTest( new TestSuite( JmeCompatibilityTest.class, "JME Tests" ) );
return suite;
}
public static class JmeCompatibilityTest extends CompatibiltyTestSuite {
public JmeCompatibilityTest() {
super(ScriptDrivenTest.PlatformType.JME);
}
protected void setUp() throws Exception {
System.setProperty("JME", "true");
super.setUp();
}
}
public static class JseCompatibilityTest extends CompatibiltyTestSuite {
public JseCompatibilityTest() {
super(ScriptDrivenTest.PlatformType.JSE);
}
protected void setUp() throws Exception {
System.setProperty("JME", "false");
super.setUp();
}
}
public static class LuaJCCompatibilityTest extends CompatibiltyTestSuite {
public LuaJCCompatibilityTest() {
super(ScriptDrivenTest.PlatformType.LUAJIT);
}
protected void setUp() throws Exception {
System.setProperty("JME", "false");
super.setUp();
}
// skipping - not supported yet
public void testDebugLib() {}
}
}

View File

@@ -0,0 +1,212 @@
/*******************************************************************************
* Copyright (c) 2009 Luaj.org. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
******************************************************************************/
package org.luaj.vm2;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import junit.framework.TestCase;
import org.luaj.vm2.luajc.LuaJCompiler;
/**
* Test compilation of various fragments that have
* caused problems for jit compiling during development.
*
*/
public class FragmentsTest extends TestCase {
public void runFragment( Varargs expected, String script ) {
try {
String name = getName();
LuaTable _G = org.luaj.vm2.lib.JsePlatform.standardGlobals();
InputStream is = new ByteArrayInputStream(script.getBytes("UTF-8"));
String java = LuaJCompiler.compileToJava(is, name);
LuaValue chunk = LuaJCompiler.javaCompile(java, name);
chunk.setfenv(_G);
Varargs actual = chunk.invoke();
assertEquals( expected.narg(), actual.narg() );
for ( int i=1; i<=actual.narg(); i++ )
assertEquals( expected.arg(i), actual.arg(i) );
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
fail(e.toString());
}
}
public void testArgParam() {
// the name "arg" is treated specially, and ends up masking the argument value in 5.1
runFragment( LuaValue.NIL,
"function v(arg,...)\n" +
" return arg\n" +
"end\n" +
"return v('abc')\n" );
}
public void testMultiAssign() {
// arargs evaluations are all done before assignments
runFragment( LuaValue.varargsOf(new LuaValue[]{
LuaValue.valueOf(111),
LuaValue.valueOf(111),
LuaValue.valueOf(111)}),
"a,b,c = 1,10,100\n" +
"a,b,c = a+b+c, a+b+c, a+b+c\n" +
"return a,b,c\n" );
}
public void testUpvalues() {
runFragment( LuaValue.valueOf(999),
"local a = function(x)\n" +
" return function(y)\n" +
" return x + y\n" +
" end\n" +
"end\n" +
"local b = a(222)\n" +
"local c = b(777)\n" +
"print( 'c=', c )\n" +
"return c\n" );
}
public void testNeedsArgAndHasArg() {
runFragment( LuaValue.varargsOf(LuaValue.valueOf(333),LuaValue.NIL,LuaValue.valueOf(222)),
"function r(q,...)\n"+
" local a=arg\n"+
" return a and a[2]\n"+
"end\n" +
"function s(q,...)\n"+
" local a=arg\n"+
" local b=...\n"+
" return a and a[2],b\n"+
"end\n" +
"return r(111,222,333),s(111,222,333)" );
}
public void testNonAsciiStringLiterals() {
runFragment( LuaValue.valueOf("7,8,12,10,9,11,133,222"),
"local a='\\a\\b\\f\\n\\t\\v\\133\\222'\n"+
"local t={string.byte(a,1,#a)}\n"+
"return table.concat(t,',')\n" );
}
public void testControlCharStringLiterals() {
runFragment( LuaValue.valueOf("97,0,98,18,99,18,100,18,48,101"),
"local a='a\\0b\\18c\\018d\\0180e'\n"+
"local t={string.byte(a,1,#a)}\n"+
"return table.concat(t,',')\n" );
}
public void testLoopVarNames() {
runFragment( LuaValue.valueOf(" 234,1,aa 234,2,bb"),
"local w = ''\n"+
"function t()\n"+
" for f,var in ipairs({'aa','bb'}) do\n"+
" local s = 234\n"+
" w = w..' '..s..','..f..','..var\n"+
" end\n"+
"end\n" +
"t()\n" +
"return w\n" );
}
public void testForLoops() {
runFragment( LuaValue.valueOf("12345 357 963"),
"local s,t,u = '','',''\n"+
"for m=1,5 do\n"+
" s = s..m\n"+
"end\n"+
"for m=3,7,2 do\n"+
" t = t..m\n"+
"end\n"+
"for m=9,3,-3 do\n"+
" u = u..m\n"+
"end\n"+
"return s..' '..t..' '..u\n" );
}
public void testLocalFunctionDeclarations() {
runFragment( LuaValue.varargsOf(LuaValue.valueOf("function"),LuaValue.valueOf("nil")),
"local function aaa()\n"+
" return type(aaa)\n"+
"end\n"+
"local bbb = function()\n"+
" return type(bbb)\n"+
"end\n"+
"return aaa(),bbb()\n" );
}
public void testNilsInTableConstructor() {
runFragment( LuaValue.valueOf("1=111 2=222 3=333 "),
"local t = { 111, 222, 333, nil, nil }\n"+
"local s = ''\n"+
"for i,v in ipairs(t) do \n" +
" s=s..tostring(i)..'='..tostring(v)..' '\n" +
"end\n"+
"return s\n" );
}
public void testUnreachableCode() {
runFragment( LuaValue.valueOf(66),
"local function foo(x) return x * 2 end\n" +
"local function bar(x, y)\n" +
" if x==y then\n" +
" return y\n" +
" else\n" +
" return foo(x)\n" +
" end\n" +
"end\n" +
"return bar(33,44)\n" );
}
public void testVarargsWithParameters() {
runFragment( LuaValue.valueOf(222),
"local func = function(t,...)\n"+
" return (...)\n"+
"end\n"+
"return func(111,222,333)\n" );
}
public void testNoReturnValuesPlainCall() {
runFragment( LuaValue.TRUE,
"local testtable = {}\n"+
"return pcall( function() testtable[1]=2 end ) )\n" );
}
public void testVarargsInTableConstructor() {
runFragment( LuaValue.valueOf(222),
"local function foo() return 111,222,333 end\n"+
"local t = {'a','b',c='c',foo()}\n"+
"return t[4]\n" );
}
public void testVarargsInFirstArg() {
runFragment( LuaValue.valueOf(123),
"function aaa(x) return x end\n" +
"function bbb(y) return y end\n" +
"function ccc(z) return z end\n" +
"return ccc( aaa(bbb(123)), aaa(456) )\n" );
}
}

View File

@@ -0,0 +1,262 @@
/*******************************************************************************
* Copyright (c) 2009 Luaj.org. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
******************************************************************************/
package org.luaj.vm2;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.lang.reflect.InvocationTargetException;
import junit.framework.TestCase;
import org.luaj.vm2.TypeTest.MyData;
import org.luaj.vm2.compiler.LuaC;
import org.luaj.vm2.lib.ZeroArgFunction;
public class LuaOperationsTest extends TestCase {
private final int sampleint = 77;
private final long samplelong = 123400000000L;
private final double sampledouble = 55.25;
private final String samplestringstring = "abcdef";
private final String samplestringint = String.valueOf(sampleint);
private final String samplestringlong = String.valueOf(samplelong);
private final String samplestringdouble = String.valueOf(sampledouble);
private final Object sampleobject = new Object();
private final MyData sampledata = new MyData();
private final LuaValue somenil = LuaValue.NIL;
private final LuaValue sometrue = LuaValue.TRUE;
private final LuaValue somefalse = LuaValue.FALSE;
private final LuaValue zero = LuaValue.ZERO;
private final LuaValue intint = LuaValue.valueOf(sampleint);
private final LuaValue longdouble = LuaValue.valueOf(samplelong);
private final LuaValue doubledouble = LuaValue.valueOf(sampledouble);
private final LuaValue stringstring = LuaValue.valueOf(samplestringstring);
private final LuaValue stringint = LuaValue.valueOf(samplestringint);
private final LuaValue stringlong = LuaValue.valueOf(samplestringlong);
private final LuaValue stringdouble = LuaValue.valueOf(samplestringdouble);
private final LuaTable table = LuaValue.listOf( new LuaValue[] { LuaValue.valueOf("aaa"), LuaValue.valueOf("bbb") } );
private final LuaFunction somefunc = new ZeroArgFunction("sample",0,table) { public LuaValue call() { return NONE;}};
private final LuaThread thread = new LuaThread(somefunc,table);
private final Prototype proto = new Prototype();
private final LuaClosure someclosure = new LuaClosure(proto,table);
private final LuaUserdata userdataobj = LuaValue.userdataOf(sampleobject);
private final LuaUserdata userdatacls = LuaValue.userdataOf(sampledata);
private void throwsLuaError(String methodName, Object obj) {
try {
LuaValue.class.getMethod(methodName).invoke(obj);
fail("failed to throw LuaError as required");
} catch (InvocationTargetException e) {
if ( ! (e.getTargetException() instanceof LuaError) )
fail("not a LuaError: "+e.getTargetException());
return; // pass
} catch ( Exception e ) {
fail( "bad exception: "+e );
}
}
private void throwsLuaError(String methodName, Object obj, Object arg) {
try {
LuaValue.class.getMethod(methodName,LuaValue.class).invoke(obj,arg);
fail("failed to throw LuaError as required");
} catch (InvocationTargetException e) {
if ( ! (e.getTargetException() instanceof LuaError) )
fail("not a LuaError: "+e.getTargetException());
return; // pass
} catch ( Exception e ) {
fail( "bad exception: "+e );
}
}
public void testLen() {
throwsLuaError( "len", somenil );
throwsLuaError( "len", sometrue );
throwsLuaError( "len", somefalse );
throwsLuaError( "len", zero );
throwsLuaError( "len", intint );
throwsLuaError( "len", longdouble );
throwsLuaError( "len", doubledouble );
assertEquals( LuaInteger.valueOf(samplestringstring.length()), stringstring.len() );
assertEquals( LuaInteger.valueOf(samplestringint.length()), stringint.len() );
assertEquals( LuaInteger.valueOf(samplestringlong.length()), stringlong.len() );
assertEquals( LuaInteger.valueOf(samplestringdouble.length()), stringdouble.len() );
assertEquals( LuaInteger.valueOf(2), table.len() );
throwsLuaError( "len", somefunc );
throwsLuaError( "len", thread );
throwsLuaError( "len", someclosure );
throwsLuaError( "len", userdataobj );
throwsLuaError( "len", userdatacls );
}
public void testLength() {
throwsLuaError( "length", somenil );
throwsLuaError( "length", sometrue );
throwsLuaError( "length", somefalse );
throwsLuaError( "length", zero );
throwsLuaError( "length", intint );
throwsLuaError( "length", longdouble );
throwsLuaError( "length", doubledouble );
assertEquals( samplestringstring.length(), stringstring.length() );
assertEquals( samplestringint.length(), stringint.length() );
assertEquals( samplestringlong.length(), stringlong.length() );
assertEquals( samplestringdouble.length(), stringdouble.length() );
assertEquals( 2, table.length() );
throwsLuaError( "length", somefunc );
throwsLuaError( "length", thread );
throwsLuaError( "length", someclosure );
throwsLuaError( "length", userdataobj );
throwsLuaError( "length", userdatacls );
}
public void testGetfenv() {
throwsLuaError( "getfenv", somenil );
throwsLuaError( "getfenv", sometrue );
throwsLuaError( "getfenv", somefalse );
throwsLuaError( "getfenv", zero );
throwsLuaError( "getfenv", intint );
throwsLuaError( "getfenv", longdouble );
throwsLuaError( "getfenv", doubledouble );
throwsLuaError( "getfenv", stringstring );
throwsLuaError( "getfenv", stringint );
throwsLuaError( "getfenv", stringlong );
throwsLuaError( "getfenv", stringdouble );
throwsLuaError( "getfenv", table );
assertTrue( table == thread.getfenv() );
assertTrue( table == someclosure.getfenv() );
assertTrue( table == somefunc.getfenv() );
throwsLuaError( "getfenv", userdataobj );
throwsLuaError( "getfenv", userdatacls );
}
public void testSetfenv() {
LuaTable table2 = LuaValue.listOf( new LuaValue[] {
LuaValue.valueOf("ccc"),
LuaValue.valueOf("ddd") } );
throwsLuaError( "setfenv", somenil, table2 );
throwsLuaError( "setfenv", sometrue, table2 );
throwsLuaError( "setfenv", somefalse, table2 );
throwsLuaError( "setfenv", zero, table2 );
throwsLuaError( "setfenv", intint, table2 );
throwsLuaError( "setfenv", longdouble, table2 );
throwsLuaError( "setfenv", doubledouble, table2 );
throwsLuaError( "setfenv", stringstring, table2 );
throwsLuaError( "setfenv", stringint, table2 );
throwsLuaError( "setfenv", stringlong, table2 );
throwsLuaError( "setfenv", stringdouble, table2 );
throwsLuaError( "setfenv", table, table2 );
thread.setfenv(table2);
assertTrue( table2 == thread.getfenv() );
assertTrue( table == someclosure.getfenv() );
assertTrue( table == somefunc.getfenv() );
someclosure.setfenv(table2);
assertTrue( table2 == someclosure.getfenv() );
assertTrue( table == somefunc.getfenv() );
somefunc.setfenv(table2);
assertTrue( table2 == somefunc.getfenv() );
throwsLuaError( "setfenv", userdataobj, table2 );
throwsLuaError( "setfenv", userdatacls, table2 );
}
public Prototype createPrototype( String script, String name ) {
try {
LuaTable _G = org.luaj.vm2.lib.JsePlatform.standardGlobals();
InputStream is = new ByteArrayInputStream(script.getBytes("UTF-8"));
return LuaC.compile(is, name);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
fail(e.toString());
return null;
}
}
public void testFunctionClosureThreadEnv() {
// set up suitable environments for execution
LuaValue aaa = LuaValue.valueOf("aaa");
LuaValue eee = LuaValue.valueOf("eee");
LuaTable _G = org.luaj.vm2.lib.JsePlatform.standardGlobals();
LuaC.install();
LuaTable newenv = LuaValue.tableOf( new LuaValue[] {
LuaValue.valueOf("a"), LuaValue.valueOf("aaa"),
LuaValue.valueOf("b"), LuaValue.valueOf("bbb"), } );
LuaTable mt = LuaValue.tableOf( new LuaValue[] { LuaValue.INDEX, _G } );
newenv.setmetatable(mt);
_G.set("a", aaa);
newenv.set("a", eee);
// function tests
{
LuaFunction f = new ZeroArgFunction("f",0,_G) { public LuaValue call() { return env.get("a");}};
assertEquals( aaa, f.call() );
f.setfenv(newenv);
assertEquals( newenv, f.getfenv() );
assertEquals( eee, f.call() );
}
// closure tests
{
Prototype p = createPrototype( "return a\n", "closuretester" );
LuaClosure c = new LuaClosure(p, _G);
assertEquals( aaa, c.call() );
c.setfenv(newenv);
assertEquals( newenv, c.getfenv() );
assertEquals( eee, c.call() );
}
// thread tests, functions created in threads inherit the thread's environment initially
// those closures created not in any other function get the thread's enviroment
Prototype p2 = createPrototype( "return loadstring('return a')", "threadtester" );
{
LuaThread t = new LuaThread(new LuaClosure(p2,_G), _G);
Varargs v = t.resume(LuaValue.NONE);
assertEquals(LuaValue.TRUE, v.arg(1) );
LuaValue f = v.arg(2);
assertEquals( LuaValue.TFUNCTION, f.type() );
assertEquals( aaa, f.call() );
assertEquals( _G, f.getfenv() );
}
{
// change the thread environment after creation!
LuaThread t = new LuaThread(new LuaClosure(p2,_G), _G);
t.setfenv(newenv);
Varargs v = t.resume(LuaValue.NONE);
assertEquals(LuaValue.TRUE, v.arg(1) );
LuaValue f = v.arg(2);
assertEquals( LuaValue.TFUNCTION, f.type() );
assertEquals( eee, f.call() );
assertEquals( newenv, f.getfenv() );
}
{
// let the closure have a different environment from the thread
Prototype p3 = createPrototype( "return function() return a end", "envtester" );
LuaThread t = new LuaThread(new LuaClosure(p3,newenv), _G);
Varargs v = t.resume(LuaValue.NONE);
assertEquals(LuaValue.TRUE, v.arg(1) );
LuaValue f = v.arg(2);
assertEquals( LuaValue.TFUNCTION, f.type() );
assertEquals( eee, f.call() );
assertEquals( newenv, f.getfenv() );
}
}
}

View File

@@ -0,0 +1,366 @@
/*******************************************************************************
* Copyright (c) 2009 Luaj.org. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
******************************************************************************/
package org.luaj.vm2;
import junit.framework.TestCase;
import org.luaj.vm2.TypeTest.MyData;
import org.luaj.vm2.lib.StringLib;
import org.luaj.vm2.lib.ThreeArgFunction;
import org.luaj.vm2.lib.TwoArgFunction;
import org.luaj.vm2.lib.ZeroArgFunction;
public class MetatableTest extends TestCase {
private final String samplestring = "abcdef";
private final Object sampleobject = new Object();
private final MyData sampledata = new MyData();
private final LuaValue string = LuaValue.valueOf(samplestring);
private final LuaTable table = LuaValue.tableOf();
private final LuaFunction function = new ZeroArgFunction() { public LuaValue call() { return NONE;}};
private final LuaThread thread = new LuaThread(function,table);
private final LuaClosure closure = new LuaClosure();
private final LuaUserdata userdata = LuaValue.userdataOf(sampleobject);
private final LuaUserdata userdatamt = LuaValue.userdataOf(sampledata,table);
protected void setUp() throws Exception {
// needed for metatable ops to work on strings
new StringLib();
}
protected void tearDown() throws Exception {
super.tearDown();
LuaBoolean.s_metatable = null;
LuaFunction.s_metatable = null;
LuaNil.s_metatable = null;
LuaNumber.s_metatable = null;
// LuaString.s_metatable = null;
LuaThread.s_metatable = null;
}
public void testGetMetatable() {
assertEquals( null, LuaValue.NIL.getmetatable() );
assertEquals( null, LuaValue.TRUE.getmetatable() );
assertEquals( null, LuaValue.ONE.getmetatable() );
// assertEquals( null, string.getmetatable() );
assertEquals( null, table.getmetatable() );
assertEquals( null, function.getmetatable() );
assertEquals( null, thread.getmetatable() );
assertEquals( null, closure.getmetatable() );
assertEquals( null, userdata.getmetatable() );
assertEquals( table, userdatamt.getmetatable() );
}
public void testSetMetatable() {
LuaValue mt = LuaValue.tableOf();
assertEquals( null, table.getmetatable() );
assertEquals( null, userdata.getmetatable() );
assertEquals( table, userdatamt.getmetatable() );
assertEquals( table, table.setmetatable(mt) );
assertEquals( userdata, userdata.setmetatable(mt) );
assertEquals( userdatamt, userdatamt.setmetatable(mt) );
assertEquals( mt, table.getmetatable() );
assertEquals( mt, userdata.getmetatable() );
assertEquals( mt, userdatamt.getmetatable() );
// these all get metatable behind-the-scenes
assertEquals( null, LuaValue.NIL.getmetatable() );
assertEquals( null, LuaValue.TRUE.getmetatable() );
assertEquals( null, LuaValue.ONE.getmetatable() );
// assertEquals( null, string.getmetatable() );
assertEquals( null, function.getmetatable() );
assertEquals( null, thread.getmetatable() );
assertEquals( null, closure.getmetatable() );
LuaNil.s_metatable = mt;
assertEquals( mt, LuaValue.NIL.getmetatable() );
assertEquals( null, LuaValue.TRUE.getmetatable() );
assertEquals( null, LuaValue.ONE.getmetatable() );
// assertEquals( null, string.getmetatable() );
assertEquals( null, function.getmetatable() );
assertEquals( null, thread.getmetatable() );
assertEquals( null, closure.getmetatable() );
LuaBoolean.s_metatable = mt;
assertEquals( mt, LuaValue.TRUE.getmetatable() );
assertEquals( null, LuaValue.ONE.getmetatable() );
// assertEquals( null, string.getmetatable() );
assertEquals( null, function.getmetatable() );
assertEquals( null, thread.getmetatable() );
assertEquals( null, closure.getmetatable() );
LuaNumber.s_metatable = mt;
assertEquals( mt, LuaValue.ONE.getmetatable() );
assertEquals( mt, LuaValue.valueOf(1.25).getmetatable() );
// assertEquals( null, string.getmetatable() );
assertEquals( null, function.getmetatable() );
assertEquals( null, thread.getmetatable() );
assertEquals( null, closure.getmetatable() );
// LuaString.s_metatable = mt;
// assertEquals( mt, string.getmetatable() );
assertEquals( null, function.getmetatable() );
assertEquals( null, thread.getmetatable() );
assertEquals( null, closure.getmetatable() );
LuaFunction.s_metatable = mt;
assertEquals( mt, function.getmetatable() );
assertEquals( null, thread.getmetatable() );
LuaThread.s_metatable = mt;
assertEquals( mt, thread.getmetatable() );
}
public void testMetatableIndex() {
assertEquals( table, table.setmetatable(null) );
assertEquals( userdata, userdata.setmetatable(null) );
assertEquals( userdatamt, userdatamt.setmetatable(null) );
assertEquals( LuaValue.NIL, table.get(1) );
assertEquals( LuaValue.NIL, userdata.get(1) );
assertEquals( LuaValue.NIL, userdatamt.get(1) );
// empty metatable
LuaValue mt = LuaValue.tableOf();
assertEquals( table, table.setmetatable(mt) );
assertEquals( userdata, userdata.setmetatable(mt) );
LuaBoolean.s_metatable = mt;
LuaFunction.s_metatable = mt;
LuaNil.s_metatable = mt;
LuaNumber.s_metatable = mt;
// LuaString.s_metatable = mt;
LuaThread.s_metatable = mt;
assertEquals( mt, table.getmetatable() );
assertEquals( mt, userdata.getmetatable() );
assertEquals( mt, LuaValue.NIL.getmetatable() );
assertEquals( mt, LuaValue.TRUE.getmetatable() );
assertEquals( mt, LuaValue.ONE.getmetatable() );
// assertEquals( StringLib.instance, string.getmetatable() );
assertEquals( mt, function.getmetatable() );
assertEquals( mt, thread.getmetatable() );
// plain metatable
LuaValue abc = LuaValue.valueOf("abc");
mt.set( LuaValue.INDEX, LuaValue.listOf(new LuaValue[] { abc } ) );
assertEquals( abc, table.get(1) );
assertEquals( abc, userdata.get(1) );
assertEquals( abc, LuaValue.NIL.get(1) );
assertEquals( abc, LuaValue.TRUE.get(1) );
assertEquals( abc, LuaValue.ONE.get(1) );
// assertEquals( abc, string.get(1) );
assertEquals( abc, function.get(1) );
assertEquals( abc, thread.get(1) );
// plain metatable
mt.set( LuaValue.INDEX, new TwoArgFunction() {
public LuaValue call(LuaValue arg1, LuaValue arg2) {
return LuaValue.valueOf( arg1.typename()+"["+arg2.toString()+"]=xyz" );
}
});
assertEquals( "table[1]=xyz", table.get(1).toString() );
assertEquals( "userdata[1]=xyz", userdata.get(1).toString() );
assertEquals( "nil[1]=xyz", LuaValue.NIL.get(1).toString() );
assertEquals( "boolean[1]=xyz", LuaValue.TRUE.get(1).toString() );
assertEquals( "number[1]=xyz", LuaValue.ONE.get(1).toString() );
// assertEquals( "string[1]=xyz", string.get(1).toString() );
assertEquals( "function[1]=xyz", function.get(1).toString() );
assertEquals( "thread[1]=xyz", thread.get(1).toString() );
}
public void testMetatableNewIndex() {
// empty metatable
LuaValue mt = LuaValue.tableOf();
assertEquals( table, table.setmetatable(mt) );
assertEquals( userdata, userdata.setmetatable(mt) );
LuaBoolean.s_metatable = mt;
LuaFunction.s_metatable = mt;
LuaNil.s_metatable = mt;
LuaNumber.s_metatable = mt;
// LuaString.s_metatable = mt;
LuaThread.s_metatable = mt;
// plain metatable
final LuaValue fallback = LuaValue.tableOf();
LuaValue abc = LuaValue.valueOf("abc");
mt.set( LuaValue.NEWINDEX, fallback );
table.set(2,abc);
userdata.set(3,abc);
LuaValue.NIL.set(4,abc);
LuaValue.TRUE.set(5,abc);
LuaValue.ONE.set(6,abc);
// string.set(7,abc);
function.set(8,abc);
thread.set(9,abc);
assertEquals( abc, fallback.get(2) );
assertEquals( abc, fallback.get(3) );
assertEquals( abc, fallback.get(4) );
assertEquals( abc, fallback.get(5) );
assertEquals( abc, fallback.get(6) );
// assertEquals( abc, StringLib.instance.get(7) );
assertEquals( abc, fallback.get(8) );
assertEquals( abc, fallback.get(9) );
// metatable with function call
mt.set( LuaValue.NEWINDEX, new ThreeArgFunction() {
public LuaValue call(LuaValue arg1, LuaValue arg2, LuaValue arg3) {
fallback.rawset(arg2, LuaValue.valueOf( "via-func-"+arg3 ));
return NONE;
}
});
table.set(12,abc);
userdata.set(13,abc);
LuaValue.NIL.set(14,abc);
LuaValue.TRUE.set(15,abc);
LuaValue.ONE.set(16,abc);
// string.set(17,abc);
function.set(18,abc);
thread.set(19,abc);
LuaValue via = LuaValue.valueOf( "via-func-abc" );
assertEquals( via, fallback.get(12) );
assertEquals( via, fallback.get(13) );
assertEquals( via, fallback.get(14) );
assertEquals( via, fallback.get(15) );
assertEquals( via, fallback.get(16) );
// assertEquals( via, StringLib.instance.get(17) );
assertEquals( via, fallback.get(18) );
assertEquals( via, fallback.get(19) );
}
private void checkTable( LuaValue t,
LuaValue aa, LuaValue bb, LuaValue cc, LuaValue dd, LuaValue ee, LuaValue ff, LuaValue gg,
LuaValue ra, LuaValue rb, LuaValue rc, LuaValue rd, LuaValue re, LuaValue rf, LuaValue rg ) {
assertEquals( aa, t.get("aa") );
assertEquals( bb, t.get("bb") );
assertEquals( cc, t.get("cc") );
assertEquals( dd, t.get("dd") );
assertEquals( ee, t.get("ee") );
assertEquals( ff, t.get("ff") );
assertEquals( gg, t.get("gg") );
assertEquals( ra, t.rawget("aa") );
assertEquals( rb, t.rawget("bb") );
assertEquals( rc, t.rawget("cc") );
assertEquals( rd, t.rawget("dd") );
assertEquals( re, t.rawget("ee") );
assertEquals( rf, t.rawget("ff") );
assertEquals( rg, t.rawget("gg") );
}
private LuaValue makeTable( String key1, String val1, String key2, String val2 ) {
return LuaValue.tableOf( new LuaValue[] {
LuaValue.valueOf(key1), LuaValue.valueOf(val1),
LuaValue.valueOf(key2), LuaValue.valueOf(val2),
} );
}
public void testRawsetMetatableSet() {
// set up tables
LuaValue m = makeTable( "aa", "aaa", "bb", "bbb" );
m.set(LuaValue.INDEX, m);
m.set(LuaValue.NEWINDEX, m);
LuaValue s = makeTable( "cc", "ccc", "dd", "ddd" );
LuaValue t = makeTable( "cc", "ccc", "dd", "ddd" );
t.setmetatable(m);
LuaValue aaa = LuaValue.valueOf("aaa");
LuaValue bbb = LuaValue.valueOf("bbb");
LuaValue ccc = LuaValue.valueOf("ccc");
LuaValue ddd = LuaValue.valueOf("ddd");
LuaValue ppp = LuaValue.valueOf("ppp");
LuaValue qqq = LuaValue.valueOf("qqq");
LuaValue rrr = LuaValue.valueOf("rrr");
LuaValue sss = LuaValue.valueOf("sss");
LuaValue ttt = LuaValue.valueOf("ttt");
LuaValue www = LuaValue.valueOf("www");
LuaValue xxx = LuaValue.valueOf("xxx");
LuaValue yyy = LuaValue.valueOf("yyy");
LuaValue zzz = LuaValue.valueOf("zzz");
LuaValue nil = LuaValue.NIL;
// check initial values
// values via "bet()" values via "rawget()"
checkTable( s, nil,nil,ccc,ddd,nil,nil,nil, nil,nil,ccc,ddd,nil,nil,nil );
checkTable( t, aaa,bbb,ccc,ddd,nil,nil,nil, nil,nil,ccc,ddd,nil,nil,nil );
checkTable( m, aaa,bbb,nil,nil,nil,nil,nil, aaa,bbb,nil,nil,nil,nil,nil );
// rawset()
s.rawset("aa", www);
checkTable( s, www,nil,ccc,ddd,nil,nil,nil, www,nil,ccc,ddd,nil,nil,nil );
checkTable( t, aaa,bbb,ccc,ddd,nil,nil,nil, nil,nil,ccc,ddd,nil,nil,nil );
checkTable( m, aaa,bbb,nil,nil,nil,nil,nil, aaa,bbb,nil,nil,nil,nil,nil );
s.rawset("cc", xxx);
checkTable( s, www,nil,xxx,ddd,nil,nil,nil, www,nil,xxx,ddd,nil,nil,nil );
checkTable( t, aaa,bbb,ccc,ddd,nil,nil,nil, nil,nil,ccc,ddd,nil,nil,nil );
checkTable( m, aaa,bbb,nil,nil,nil,nil,nil, aaa,bbb,nil,nil,nil,nil,nil );
t.rawset("bb", yyy);
checkTable( s, www,nil,xxx,ddd,nil,nil,nil, www,nil,xxx,ddd,nil,nil,nil );
checkTable( t, aaa,yyy,ccc,ddd,nil,nil,nil, nil,yyy,ccc,ddd,nil,nil,nil );
checkTable( m, aaa,bbb,nil,nil,nil,nil,nil, aaa,bbb,nil,nil,nil,nil,nil );
t.rawset("dd", zzz);
checkTable( s, www,nil,xxx,ddd,nil,nil,nil, www,nil,xxx,ddd,nil,nil,nil );
checkTable( t, aaa,yyy,ccc,zzz,nil,nil,nil, nil,yyy,ccc,zzz,nil,nil,nil );
checkTable( m, aaa,bbb,nil,nil,nil,nil,nil, aaa,bbb,nil,nil,nil,nil,nil );
// set() invoking metatables
s.set("ee", ppp);
checkTable( s, www,nil,xxx,ddd,ppp,nil,nil, www,nil,xxx,ddd,ppp,nil,nil );
checkTable( t, aaa,yyy,ccc,zzz,nil,nil,nil, nil,yyy,ccc,zzz,nil,nil,nil );
checkTable( m, aaa,bbb,nil,nil,nil,nil,nil, aaa,bbb,nil,nil,nil,nil,nil );
s.set("cc", qqq);
checkTable( s, www,nil,qqq,ddd,ppp,nil,nil, www,nil,qqq,ddd,ppp,nil,nil );
checkTable( t, aaa,yyy,ccc,zzz,nil,nil,nil, nil,yyy,ccc,zzz,nil,nil,nil );
checkTable( m, aaa,bbb,nil,nil,nil,nil,nil, aaa,bbb,nil,nil,nil,nil,nil );
t.set("ff", rrr);
checkTable( s, www,nil,qqq,ddd,ppp,nil,nil, www,nil,qqq,ddd,ppp,nil,nil );
checkTable( t, aaa,yyy,ccc,zzz,nil,rrr,nil, nil,yyy,ccc,zzz,nil,nil,nil );
checkTable( m, aaa,bbb,nil,nil,nil,rrr,nil, aaa,bbb,nil,nil,nil,rrr,nil );
t.set("dd", sss);
checkTable( s, www,nil,qqq,ddd,ppp,nil,nil, www,nil,qqq,ddd,ppp,nil,nil );
checkTable( t, aaa,yyy,ccc,sss,nil,rrr,nil, nil,yyy,ccc,sss,nil,nil,nil );
checkTable( m, aaa,bbb,nil,nil,nil,rrr,nil, aaa,bbb,nil,nil,nil,rrr,nil );
m.set("gg", ttt);
checkTable( s, www,nil,qqq,ddd,ppp,nil,nil, www,nil,qqq,ddd,ppp,nil,nil );
checkTable( t, aaa,yyy,ccc,sss,nil,rrr,ttt, nil,yyy,ccc,sss,nil,nil,nil );
checkTable( m, aaa,bbb,nil,nil,nil,rrr,ttt, aaa,bbb,nil,nil,nil,rrr,ttt );
// make s fall back to t
s.setmetatable(LuaValue.tableOf(new LuaValue[] {LuaValue.INDEX,t,LuaValue.NEWINDEX,t}));
checkTable( s, www,yyy,qqq,ddd,ppp,rrr,ttt, www,nil,qqq,ddd,ppp,nil,nil );
checkTable( t, aaa,yyy,ccc,sss,nil,rrr,ttt, nil,yyy,ccc,sss,nil,nil,nil );
checkTable( m, aaa,bbb,nil,nil,nil,rrr,ttt, aaa,bbb,nil,nil,nil,rrr,ttt );
s.set("aa", www);
checkTable( s, www,yyy,qqq,ddd,ppp,rrr,ttt, www,nil,qqq,ddd,ppp,nil,nil );
checkTable( t, aaa,yyy,ccc,sss,nil,rrr,ttt, nil,yyy,ccc,sss,nil,nil,nil );
checkTable( m, aaa,bbb,nil,nil,nil,rrr,ttt, aaa,bbb,nil,nil,nil,rrr,ttt );
s.set("bb", zzz);
checkTable( s, www,zzz,qqq,ddd,ppp,rrr,ttt, www,nil,qqq,ddd,ppp,nil,nil );
checkTable( t, aaa,zzz,ccc,sss,nil,rrr,ttt, nil,zzz,ccc,sss,nil,nil,nil );
checkTable( m, aaa,bbb,nil,nil,nil,rrr,ttt, aaa,bbb,nil,nil,nil,rrr,ttt );
s.set("ee", xxx);
checkTable( s, www,zzz,qqq,ddd,xxx,rrr,ttt, www,nil,qqq,ddd,xxx,nil,nil );
checkTable( t, aaa,zzz,ccc,sss,nil,rrr,ttt, nil,zzz,ccc,sss,nil,nil,nil );
checkTable( m, aaa,bbb,nil,nil,nil,rrr,ttt, aaa,bbb,nil,nil,nil,rrr,ttt );
s.set("ff", yyy);
checkTable( s, www,zzz,qqq,ddd,xxx,yyy,ttt, www,nil,qqq,ddd,xxx,nil,nil );
checkTable( t, aaa,zzz,ccc,sss,nil,yyy,ttt, nil,zzz,ccc,sss,nil,nil,nil );
checkTable( m, aaa,bbb,nil,nil,nil,yyy,ttt, aaa,bbb,nil,nil,nil,yyy,ttt );
}
}

View File

@@ -0,0 +1,247 @@
/*******************************************************************************
* Copyright (c) 2009 Luaj.org. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
******************************************************************************/
package org.luaj.vm2;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintStream;
import junit.framework.TestCase;
import org.luaj.vm2.compiler.LuaC;
import org.luaj.vm2.lib.BaseLib;
import org.luaj.vm2.lib.CoroutineLib;
import org.luaj.vm2.lib.DebugLib;
import org.luaj.vm2.luajc.LuaJCompiler;
abstract
public class ScriptDrivenTest extends TestCase {
public static final boolean nocompile = "true".equals(System.getProperty("nocompile"));
public enum PlatformType {
JME, JSE, LUAJIT,
}
private final PlatformType platform;
private final String basedir;
protected ScriptDrivenTest( PlatformType platform, String directory ) {
this.platform = platform;
this.basedir = directory;
}
// */
protected void runTest(String testName) {
try {
// create globals
LuaC.install();
LuaTable _G = null;
switch ( platform ) {
default:
case JSE:
case LUAJIT:
_G = org.luaj.vm2.lib.JsePlatform.standardGlobals();
break;
case JME:
_G = org.luaj.vm2.lib.JmePlatform.standardGlobals();
break;
}
DebugLib.install( _G );
// override print()
final ByteArrayOutputStream output = new ByteArrayOutputStream();
final PrintStream oldps = BaseLib.STDOUT;
final PrintStream ps = new PrintStream( output );
BaseLib.STDOUT = ps;
// run the script
try {
LuaValue chunk = loadScript(testName, _G);
chunk.call(LuaValue.valueOf(platform.toString()));
ps.flush();
final String actualOutput = new String(output.toByteArray());
final String expectedOutput = getExpectedOutput(testName);
assertEquals(expectedOutput, actualOutput);
} finally {
BaseLib.STDOUT = oldps;
ps.close();
}
} catch ( IOException ioe ) {
throw new RuntimeException(ioe.toString());
} catch ( InterruptedException ie ) {
throw new RuntimeException(ie.toString());
}
}
protected LuaValue loadScript(String name, LuaTable _G) throws IOException {
File file = new File(basedir+"/"+name+".lua");
if ( !file.exists() )
fail("Could not load script for test case: " + name);
InputStream script=null;
try {
// Use "stdin" instead of resource name so that output matches
// standard Lua.
switch ( this.platform ) {
case LUAJIT:
if ( nocompile ) {
LuaValue c = (LuaValue) Class.forName(name).newInstance();
c.setfenv(_G);
return c;
} else {
script = new FileInputStream(file);
return LuaJCompiler.compile( script, name, _G);
}
default:
script = new FileInputStream(file);
Prototype p = LoadState.undump(script, "stdin");
return new LuaClosure(p,_G);
}
} catch ( Exception e ) {
e.printStackTrace();
throw new IOException( e.toString() );
} finally {
if ( script != null )
script.close();
}
}
private String getExpectedOutput(final String name) throws IOException,
InterruptedException {
String expectedOutputName = basedir+"/"+name+"-expected.out";
File file = new File( expectedOutputName );
if ( file.exists() ) {
InputStream is = new FileInputStream(file);
try {
return readString(is);
} finally {
is.close();
}
} else {
file = new File(basedir+"/"+name+".lua");
if ( !file.exists() )
fail("Could not load script for test case: " + name);
InputStream script = new FileInputStream(file);
// }
try {
String luaCommand = System.getProperty("LUA_COMMAND");
if ( luaCommand == null )
luaCommand = "lua";
String[] args = new String[] { luaCommand, "-", platform.toString() };
return collectProcessOutput(args, script);
} finally {
script.close();
}
}
}
private String collectProcessOutput(String[] cmd, final InputStream input)
throws IOException, InterruptedException {
Runtime r = Runtime.getRuntime();
final ByteArrayOutputStream baos = new ByteArrayOutputStream();
final Process p = r.exec(cmd);
try {
// start a thread to write the given input to the subprocess.
Thread inputCopier = (new Thread() {
public void run() {
try {
OutputStream processStdIn = p.getOutputStream();
try {
copy(input, processStdIn);
} finally {
processStdIn.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
});
inputCopier.start();
// start another thread to read output from the subprocess.
Thread outputCopier = (new Thread() {
public void run() {
try {
InputStream processStdOut = p.getInputStream();
try {
copy(processStdOut, baos);
} finally {
processStdOut.close();
}
} catch (IOException ioe) {
ioe.printStackTrace();
}
}
});
outputCopier.start();
// start another thread to read output from the subprocess.
Thread errorCopier = (new Thread() {
public void run() {
try {
InputStream processError = p.getErrorStream();
try {
copy(processError, System.err);
} finally {
processError.close();
}
} catch (IOException ioe) {
ioe.printStackTrace();
}
}
});
errorCopier.start();
p.waitFor();
inputCopier.join();
outputCopier.join();
errorCopier.join();
return new String(baos.toByteArray());
} finally {
p.destroy();
}
}
private String readString(InputStream is) throws IOException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
copy(is, baos);
return new String(baos.toByteArray());
}
private void copy(InputStream is, OutputStream os) throws IOException {
byte[] buf = new byte[1024];
int r;
while ((r = is.read(buf)) >= 0) {
os.write(buf, 0, r);
}
}
}

View File

@@ -0,0 +1,355 @@
/*******************************************************************************
* Copyright (c) 2009 Luaj.org. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
******************************************************************************/
package org.luaj.vm2;
import java.util.Vector;
import org.luaj.vm2.LuaDouble;
import org.luaj.vm2.LuaInteger;
import org.luaj.vm2.LuaString;
import org.luaj.vm2.LuaTable;
import org.luaj.vm2.LuaValue;
import junit.framework.TestCase;
/**
* Tests for tables used as lists.
*/
public class TableArrayTest extends TestCase {
protected LuaTable new_Table() {
return new LuaTable();
}
protected LuaTable new_Table(int n,int m) {
return new LuaTable(n,m);
}
public void testInOrderIntegerKeyInsertion() {
LuaTable t = new_Table();
for ( int i = 1; i <= 32; ++i ) {
t.set( i, LuaString.valueOf( "Test Value! "+i ) );
}
// Ensure all keys are still there.
for ( int i = 1; i <= 32; ++i ) {
assertEquals( "Test Value! " + i, t.get( i ).toString() );
}
// Ensure capacities make sense
assertEquals( 0, t.hashCapacity() );
assertTrue( t.arrayCapacity() >= 32 );
assertTrue( t.arrayCapacity() <= 64 );
}
public void testResize() {
LuaTable t = new_Table();
// NOTE: This order of insertion is important.
t.set(3, LuaInteger.valueOf(3));
t.set(1, LuaInteger.valueOf(1));
t.set(5, LuaInteger.valueOf(5));
t.set(4, LuaInteger.valueOf(4));
t.set(6, LuaInteger.valueOf(6));
t.set(2, LuaInteger.valueOf(2));
for ( int i = 1; i < 6; ++i ) {
assertEquals(LuaInteger.valueOf(i), t.get(i));
}
assertTrue( t.arrayCapacity() >= 0 && t.arrayCapacity() <= 2 );
assertTrue( t.hashCapacity() >= 4 );
}
public void testOutOfOrderIntegerKeyInsertion() {
LuaTable t = new_Table();
for ( int i = 32; i > 0; --i ) {
t.set( i, LuaString.valueOf( "Test Value! "+i ) );
}
// Ensure all keys are still there.
for ( int i = 1; i <= 32; ++i ) {
assertEquals( "Test Value! "+i, t.get( i ).toString() );
}
// Ensure capacities make sense
assertTrue( t.arrayCapacity() >= 0 );
assertTrue( t.arrayCapacity() <= 6 );
assertTrue( t.hashCapacity() >= 16 );
assertTrue( t.hashCapacity() <= 64 );
}
public void testStringAndIntegerKeys() {
LuaTable t = new_Table();
for ( int i = 0; i < 10; ++i ) {
LuaString str = LuaString.valueOf( String.valueOf( i ) );
t.set( i, str );
t.set( str, LuaInteger.valueOf( i ) );
}
assertTrue( t.arrayCapacity() >= 9 ); // 1, 2, ..., 9
assertTrue( t.arrayCapacity() <= 18 );
assertTrue( t.hashCapacity() >= 11 ); // 0, "0", "1", ..., "9"
assertTrue( t.hashCapacity() <= 33 );
LuaValue[] keys = t.keys();
int intKeys = 0;
int stringKeys = 0;
assertEquals( 20, keys.length );
for ( int i = 0; i < keys.length; ++i ) {
LuaValue k = keys[i];
if ( k instanceof LuaInteger ) {
final int ik = k.toint();
assertTrue( ik >= 0 && ik < 10 );
final int mask = 1 << ik;
assertTrue( ( intKeys & mask ) == 0 );
intKeys |= mask;
} else if ( k instanceof LuaString ) {
final int ik = Integer.parseInt( k.toString() );
assertEquals( String.valueOf( ik ), k.toString() );
assertTrue( ik >= 0 && ik < 10 );
final int mask = 1 << ik;
assertTrue( "Key \""+ik+"\" found more than once", ( stringKeys & mask ) == 0 );
stringKeys |= mask;
} else {
fail( "Unexpected type of key found" );
}
}
assertEquals( 0x03FF, intKeys );
assertEquals( 0x03FF, stringKeys );
}
public void testBadInitialCapacity() {
LuaTable t = new_Table(0, 1);
t.set( "test", LuaString.valueOf("foo") );
t.set( "explode", LuaString.valueOf("explode") );
assertEquals( 2, t.keyCount() );
}
public void testRemove0() {
LuaTable t = new_Table(2, 0);
t.set( 1, LuaString.valueOf("foo") );
t.set( 2, LuaString.valueOf("bah") );
assertNotSame(LuaValue.NIL, t.get(1));
assertNotSame(LuaValue.NIL, t.get(2));
assertEquals(LuaValue.NIL, t.get(3));
t.set( 1, LuaValue.NIL );
t.set( 2, LuaValue.NIL );
t.set( 3, LuaValue.NIL );
assertEquals(LuaValue.NIL, t.get(1));
assertEquals(LuaValue.NIL, t.get(2));
assertEquals(LuaValue.NIL, t.get(3));
}
public void testRemove1() {
LuaTable t = new_Table(0, 1);
assertEquals( 0, t.keyCount() );
t.set( "test", LuaString.valueOf("foo") );
assertEquals( 1, t.keyCount() );
t.set( "explode", LuaValue.NIL );
assertEquals( 1, t.keyCount() );
t.set( 42, LuaValue.NIL );
assertEquals( 1, t.keyCount() );
t.set( new_Table(), LuaValue.NIL );
assertEquals( 1, t.keyCount() );
t.set( "test", LuaValue.NIL );
assertEquals( 0, t.keyCount() );
t.set( 10, LuaInteger.valueOf( 5 ) );
t.set( 10, LuaValue.NIL );
assertEquals( 0, t.keyCount() );
}
public void testRemove2() {
LuaTable t = new_Table(0, 1);
t.set( "test", LuaString.valueOf("foo") );
t.set( "string", LuaInteger.valueOf( 10 ) );
assertEquals( 2, t.keyCount() );
t.set( "string", LuaValue.NIL );
t.set( "three", LuaDouble.valueOf( 3.14 ) );
assertEquals( 2, t.keyCount() );
t.set( "test", LuaValue.NIL );
assertEquals( 1, t.keyCount() );
t.set( 10, LuaInteger.valueOf( 5 ) );
assertEquals( 2, t.keyCount() );
t.set( 10, LuaValue.NIL );
assertEquals( 1, t.keyCount() );
t.set( "three", LuaValue.NIL );
assertEquals( 0, t.keyCount() );
}
public void testInOrderlen() {
LuaTable t = new_Table();
for ( int i = 1; i <= 32; ++i ) {
LuaValue v = LuaString.valueOf( "Test Value! "+i );
t.set( i, v );
assertEquals( i, t.length() );
assertEquals( i, t.maxn() );
}
}
public void testOutOfOrderlen() {
LuaTable t = new_Table();
for ( int j=8; j<32; j+=8 ) {
for ( int i = j; i > 0; --i ) {
t.set( i, LuaString.valueOf( "Test Value! "+i ) );
}
assertEquals( j, t.length() );
assertEquals( j, t.maxn() );
}
}
public void testStringKeyslen() {
LuaTable t = new_Table();
for ( int i = 1; i <= 32; ++i ) {
t.set( "str-"+i, LuaString.valueOf( "String Key Test Value! "+i ) );
assertEquals( 0, t.length() );
assertEquals( 0, t.maxn() );
}
}
public void testMixedKeyslen() {
LuaTable t = new_Table();
for ( int i = 1; i <= 32; ++i ) {
t.set( "str-"+i, LuaString.valueOf( "String Key Test Value! "+i ) );
t.set( i, LuaString.valueOf( "Int Key Test Value! "+i ) );
assertEquals( i, t.length() );
assertEquals( i, t.maxn() );
}
}
private static final void compareLists(LuaTable t,Vector v) {
int n = v.size();
assertEquals(v.size(),t.length());
for ( int j=0; j<n; j++ ) {
Object vj = v.elementAt(j);
Object tj = t.get(j+1).toString();
vj = ((LuaString)vj).toString();
assertEquals(vj,tj);
}
}
public void testInsertBeginningOfList() {
LuaTable t = new_Table();
Vector v = new Vector();
for ( int i = 1; i <= 32; ++i ) {
LuaString test = LuaString.valueOf("Test Value! "+i);
t.insert(1, test);
v.insertElementAt(test, 0);
compareLists(t,v);
}
}
public void testInsertEndOfList() {
LuaTable t = new_Table();
Vector v = new Vector();
for ( int i = 1; i <= 32; ++i ) {
LuaString test = LuaString.valueOf("Test Value! "+i);
t.insert(0, test);
v.insertElementAt(test, v.size());
compareLists(t,v);
}
}
public void testInsertMiddleOfList() {
LuaTable t = new_Table();
Vector v = new Vector();
for ( int i = 1; i <= 32; ++i ) {
LuaString test = LuaString.valueOf("Test Value! "+i);
int m = i / 2;
t.insert(m+1, test);
v.insertElementAt(test, m);
compareLists(t,v);
}
}
private static final void prefillLists(LuaTable t,Vector v) {
for ( int i = 1; i <= 32; ++i ) {
LuaString test = LuaString.valueOf("Test Value! "+i);
t.insert(0, test);
v.insertElementAt(test, v.size());
}
}
public void testRemoveBeginningOfList() {
LuaTable t = new_Table();
Vector v = new Vector();
prefillLists(t,v);
for ( int i = 1; i <= 32; ++i ) {
t.remove(1);
v.removeElementAt(0);
compareLists(t,v);
}
}
public void testRemoveEndOfList() {
LuaTable t = new_Table();
Vector v = new Vector();
prefillLists(t,v);
for ( int i = 1; i <= 32; ++i ) {
t.remove(0);
v.removeElementAt(v.size()-1);
compareLists(t,v);
}
}
public void testRemoveMiddleOfList() {
LuaTable t = new_Table();
Vector v = new Vector();
prefillLists(t,v);
for ( int i = 1; i <= 32; ++i ) {
int m = v.size() / 2;
t.remove(m+1);
v.removeElementAt(m);
compareLists(t,v);
}
}
}

View File

@@ -0,0 +1,245 @@
/*******************************************************************************
* Copyright (c) 2009 Luaj.org. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
******************************************************************************/
package org.luaj.vm2;
import junit.framework.TestCase;
import org.luaj.vm2.LuaString;
import org.luaj.vm2.LuaTable;
import org.luaj.vm2.LuaValue;
import org.luaj.vm2.lib.TwoArgFunction;
/**
* Tests for tables used as lists.
*/
public class TableHashTest extends TestCase {
protected LuaTable new_Table() {
return new LuaTable();
}
protected LuaTable new_Table(int n,int m) {
return new LuaTable(n,m);
}
public void testSetRemove() {
LuaTable t = new_Table();
assertEquals( 0, t.hashCapacity() );
assertEquals( 0, t.length() );
assertEquals( 0, t.keyCount() );
String[] keys = { "abc", "def", "ghi", "jkl", "mno", "pqr", "stu", "wxy", "z01",
"cd", "ef", "g", "hi", "jk", "lm", "no", "pq", "rs", };
int[] capacities = { 0, 2, 4, 4, 7, 7, 7, 10, 10, 14, 14, 14, 14, 19, 19, 19, 19, 25, 25, 25 };
for ( int i = 0; i < keys.length; ++i ) {
assertEquals( capacities[i], t.hashCapacity() );
String si = "Test Value! "+i;
t.set( keys[i], si );
assertEquals( 0, t.length() );
assertEquals( i+1, t.keyCount() );
}
assertEquals( capacities[keys.length], t.hashCapacity() );
for ( int i = 0; i < keys.length; ++i ) {
LuaValue vi = LuaString.valueOf( "Test Value! "+i );
assertEquals( vi, t.get( keys[i] ) );
assertEquals( vi, t.get( LuaString.valueOf(keys[i]) ) );
assertEquals( vi, t.rawget( keys[i] ) );
assertEquals( vi, t.rawget( keys[i] ) );
}
// replace with new values
for ( int i = 0; i < keys.length; ++i ) {
t.set( keys[i], LuaString.valueOf( "Replacement Value! "+i ) );
assertEquals( 0, t.length() );
assertEquals( keys.length, t.keyCount() );
assertEquals( capacities[keys.length], t.hashCapacity() );
}
for ( int i = 0; i < keys.length; ++i ) {
LuaValue vi = LuaString.valueOf( "Replacement Value! "+i );
assertEquals( vi, t.get( keys[i] ) );
}
// remove
for ( int i = 0; i < keys.length; ++i ) {
t.set( keys[i], LuaValue.NIL );
assertEquals( 0, t.length() );
assertEquals( keys.length-i-1, t.keyCount() );
if ( i<keys.length-1 )
assertEquals( capacities[keys.length], t.hashCapacity() );
else
assertTrue( 0<=t.hashCapacity() );
}
for ( int i = 0; i < keys.length; ++i ) {
assertEquals( LuaValue.NIL, t.get( keys[i] ) );
}
}
public void testIndexMetatag() {
LuaTable t = new_Table();
LuaTable mt = new_Table();
LuaTable fb = new_Table();
// set basic values
t.set( "ppp", "abc" );
t.set( 123, "def" );
mt.set(LuaValue.INDEX, fb);
fb.set( "qqq", "ghi" );
fb.set( 456, "jkl" );
// check before setting metatable
assertEquals( "abc", t.get("ppp").toString() );
assertEquals( "def", t.get(123).toString() );
assertEquals( "nil", t.get("qqq").toString() );
assertEquals( "nil", t.get(456).toString() );
assertEquals( "nil", fb.get("ppp").toString() );
assertEquals( "nil", fb.get(123).toString() );
assertEquals( "ghi", fb.get("qqq").toString() );
assertEquals( "jkl", fb.get(456).toString() );
assertEquals( "nil", mt.get("ppp").toString() );
assertEquals( "nil", mt.get(123).toString() );
assertEquals( "nil", mt.get("qqq").toString() );
assertEquals( "nil", mt.get(456).toString() );
// check before setting metatable
t.setmetatable(mt);
assertEquals( mt, t.getmetatable() );
assertEquals( "abc", t.get("ppp").toString() );
assertEquals( "def", t.get(123).toString() );
assertEquals( "ghi", t.get("qqq").toString() );
assertEquals( "jkl", t.get(456).toString() );
assertEquals( "nil", fb.get("ppp").toString() );
assertEquals( "nil", fb.get(123).toString() );
assertEquals( "ghi", fb.get("qqq").toString() );
assertEquals( "jkl", fb.get(456).toString() );
assertEquals( "nil", mt.get("ppp").toString() );
assertEquals( "nil", mt.get(123).toString() );
assertEquals( "nil", mt.get("qqq").toString() );
assertEquals( "nil", mt.get(456).toString() );
// set metatable to metatable without values
t.setmetatable(fb);
assertEquals( "abc", t.get("ppp").toString() );
assertEquals( "def", t.get(123).toString() );
assertEquals( "nil", t.get("qqq").toString() );
assertEquals( "nil", t.get(456).toString() );
// set metatable to null
t.setmetatable(null);
assertEquals( "abc", t.get("ppp").toString() );
assertEquals( "def", t.get(123).toString() );
assertEquals( "nil", t.get("qqq").toString() );
assertEquals( "nil", t.get(456).toString() );
}
public void testIndexFunction() {
final LuaTable t = new_Table();
final LuaTable mt = new_Table();
final TwoArgFunction fb = new TwoArgFunction() {
public LuaValue call(LuaValue tbl, LuaValue key) {
assertEquals(tbl, t);
return valueOf("from mt: "+key);
}
};
// set basic values
t.set( "ppp", "abc" );
t.set( 123, "def" );
mt.set(LuaValue.INDEX, fb);
// check before setting metatable
assertEquals( "abc", t.get("ppp").toString() );
assertEquals( "def", t.get(123).toString() );
assertEquals( "nil", t.get("qqq").toString() );
assertEquals( "nil", t.get(456).toString() );
// check before setting metatable
t.setmetatable(mt);
assertEquals( mt, t.getmetatable() );
assertEquals( "abc", t.get("ppp").toString() );
assertEquals( "def", t.get(123).toString() );
assertEquals( "from mt: qqq", t.get("qqq").toString() );
assertEquals( "from mt: 456", t.get(456).toString() );
// use raw set
t.rawset("qqq", "alt-qqq");
t.rawset(456, "alt-456");
assertEquals( "abc", t.get("ppp").toString() );
assertEquals( "def", t.get(123).toString() );
assertEquals( "alt-qqq", t.get("qqq").toString() );
assertEquals( "alt-456", t.get(456).toString() );
// remove using raw set
t.rawset("qqq", LuaValue.NIL);
t.rawset(456, LuaValue.NIL);
assertEquals( "abc", t.get("ppp").toString() );
assertEquals( "def", t.get(123).toString() );
assertEquals( "from mt: qqq", t.get("qqq").toString() );
assertEquals( "from mt: 456", t.get(456).toString() );
// set metatable to null
t.setmetatable(null);
assertEquals( "abc", t.get("ppp").toString() );
assertEquals( "def", t.get(123).toString() );
assertEquals( "nil", t.get("qqq").toString() );
assertEquals( "nil", t.get(456).toString() );
}
public void testNext() {
final LuaTable t = new_Table();
assertEquals( LuaValue.NIL, t.next(LuaValue.NIL) );
// insert array elements
t.set( 1, "one" );
assertEquals( LuaValue.valueOf(1), t.next(LuaValue.NIL).arg(1) );
assertEquals( LuaValue.valueOf("one"), t.next(LuaValue.NIL).arg(2) );
assertEquals( LuaValue.NIL, t.next(LuaValue.ONE) );
t.set( 2, "two" );
assertEquals( LuaValue.valueOf(1), t.next(LuaValue.NIL).arg(1) );
assertEquals( LuaValue.valueOf("one"), t.next(LuaValue.NIL).arg(2) );
assertEquals( LuaValue.valueOf(2), t.next(LuaValue.ONE).arg(1) );
assertEquals( LuaValue.valueOf("two"), t.next(LuaValue.ONE).arg(2) );
assertEquals( LuaValue.NIL, t.next(LuaValue.valueOf(2)) );
// insert hash elements
t.set( "aa", "aaa" );
assertEquals( LuaValue.valueOf(1), t.next(LuaValue.NIL).arg(1) );
assertEquals( LuaValue.valueOf("one"), t.next(LuaValue.NIL).arg(2) );
assertEquals( LuaValue.valueOf(2), t.next(LuaValue.ONE).arg(1) );
assertEquals( LuaValue.valueOf("two"), t.next(LuaValue.ONE).arg(2) );
assertEquals( LuaValue.valueOf("aa"), t.next(LuaValue.valueOf(2)).arg(1) );
assertEquals( LuaValue.valueOf("aaa"), t.next(LuaValue.valueOf(2)).arg(2) );
assertEquals( LuaValue.NIL, t.next(LuaValue.valueOf("aa")) );
t.set( "bb", "bbb" );
assertEquals( LuaValue.valueOf(1), t.next(LuaValue.NIL).arg(1) );
assertEquals( LuaValue.valueOf("one"), t.next(LuaValue.NIL).arg(2) );
assertEquals( LuaValue.valueOf(2), t.next(LuaValue.ONE).arg(1) );
assertEquals( LuaValue.valueOf("two"), t.next(LuaValue.ONE).arg(2) );
assertEquals( LuaValue.valueOf("aa"), t.next(LuaValue.valueOf(2)).arg(1) );
assertEquals( LuaValue.valueOf("aaa"), t.next(LuaValue.valueOf(2)).arg(2) );
assertEquals( LuaValue.valueOf("bb"), t.next(LuaValue.valueOf("aa")).arg(1) );
assertEquals( LuaValue.valueOf("bbb"), t.next(LuaValue.valueOf("aa")).arg(2) );
assertEquals( LuaValue.NIL, t.next(LuaValue.valueOf("bb")) );
}
}

View File

@@ -0,0 +1,340 @@
/*******************************************************************************
* Copyright (c) 2009 Luaj.org. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
******************************************************************************/
package org.luaj.vm2;
import java.util.Vector;
import junit.framework.TestCase;
public class TableTest extends TestCase {
protected LuaTable new_Table() {
return new LuaTable();
}
protected LuaTable new_Table(int n,int m) {
return new LuaTable(n,m);
}
public void testInOrderIntegerKeyInsertion() {
LuaTable t = new_Table();
for ( int i = 1; i <= 32; ++i ) {
t.set( i, LuaValue.valueOf( "Test Value! "+i ) );
}
// Ensure all keys are still there.
for ( int i = 1; i <= 32; ++i ) {
assertEquals( "Test Value! " + i, t.get( i ).toString() );
}
// Ensure capacities make sense
assertEquals( 0, t.hashCapacity() );
assertTrue( t.arrayCapacity() >= 32 );
assertTrue( t.arrayCapacity() <= 64 );
}
public void testRekeyCount() {
LuaTable t = new_Table();
// NOTE: This order of insertion is important.
t.set(3, LuaInteger.valueOf(3));
t.set(1, LuaInteger.valueOf(1));
t.set(5, LuaInteger.valueOf(5));
t.set(4, LuaInteger.valueOf(4));
t.set(6, LuaInteger.valueOf(6));
t.set(2, LuaInteger.valueOf(2));
for ( int i = 1; i < 6; ++i ) {
assertEquals(LuaInteger.valueOf(i), t.get(i));
}
assertTrue( t.arrayCapacity() >= 0 && t.arrayCapacity() <= 2 );
assertTrue( t.hashCapacity() >= 4 );
}
public void testOutOfOrderIntegerKeyInsertion() {
LuaTable t = new_Table();
for ( int i = 32; i > 0; --i ) {
t.set( i, LuaValue.valueOf( "Test Value! "+i ) );
}
// Ensure all keys are still there.
for ( int i = 1; i <= 32; ++i ) {
assertEquals( "Test Value! "+i, t.get( i ).toString() );
}
// Ensure capacities make sense
assertTrue( t.arrayCapacity() >= 0 );
assertTrue( t.arrayCapacity() <= 6 );
assertTrue( t.hashCapacity() >= 16 );
assertTrue( t.hashCapacity() <= 64 );
}
public void testStringAndIntegerKeys() {
LuaTable t = new_Table();
for ( int i = 0; i < 10; ++i ) {
LuaString str = LuaValue.valueOf( String.valueOf( i ) );
t.set( i, str );
t.set( str, LuaInteger.valueOf( i ) );
}
assertTrue( t.arrayCapacity() >= 9 ); // 1, 2, ..., 9
assertTrue( t.arrayCapacity() <= 18 );
assertTrue( t.hashCapacity() >= 11 ); // 0, "0", "1", ..., "9"
assertTrue( t.hashCapacity() <= 33 );
LuaValue[] keys = t.keys();
int intKeys = 0;
int stringKeys = 0;
assertEquals( 20, keys.length );
for ( int i = 0; i < keys.length; ++i ) {
LuaValue k = keys[i];
if ( k instanceof LuaInteger ) {
final int ik = k.toint();
assertTrue( ik >= 0 && ik < 10 );
final int mask = 1 << ik;
assertTrue( ( intKeys & mask ) == 0 );
intKeys |= mask;
} else if ( k instanceof LuaString ) {
final int ik = Integer.parseInt( k.strvalue().toString() );
assertEquals( String.valueOf( ik ), k.strvalue().toString() );
assertTrue( ik >= 0 && ik < 10 );
final int mask = 1 << ik;
assertTrue( "Key \""+ik+"\" found more than once", ( stringKeys & mask ) == 0 );
stringKeys |= mask;
} else {
fail( "Unexpected type of key found" );
}
}
assertEquals( 0x03FF, intKeys );
assertEquals( 0x03FF, stringKeys );
}
public void testBadInitialCapacity() {
LuaTable t = new_Table(0, 1);
t.set( "test", LuaValue.valueOf("foo") );
t.set( "explode", LuaValue.valueOf("explode") );
assertEquals( 2, t.keyCount() );
}
public void testRemove0() {
LuaTable t = new_Table(2, 0);
t.set( 1, LuaValue.valueOf("foo") );
t.set( 2, LuaValue.valueOf("bah") );
assertNotSame(LuaValue.NIL, t.get(1));
assertNotSame(LuaValue.NIL, t.get(2));
assertEquals(LuaValue.NIL, t.get(3));
t.set( 1, LuaValue.NIL );
t.set( 2, LuaValue.NIL );
t.set( 3, LuaValue.NIL );
assertEquals(LuaValue.NIL, t.get(1));
assertEquals(LuaValue.NIL, t.get(2));
assertEquals(LuaValue.NIL, t.get(3));
}
public void testRemove1() {
LuaTable t = new_Table(0, 1);
t.set( "test", LuaValue.valueOf("foo") );
t.set( "explode", LuaValue.NIL );
t.set( 42, LuaValue.NIL );
t.set( new_Table(), LuaValue.NIL );
t.set( "test", LuaValue.NIL );
assertEquals( 0, t.keyCount() );
t.set( 10, LuaInteger.valueOf( 5 ) );
t.set( 10, LuaValue.NIL );
assertEquals( 0, t.keyCount() );
}
public void testRemove2() {
LuaTable t = new_Table(0, 1);
t.set( "test", LuaValue.valueOf("foo") );
t.set( "string", LuaInteger.valueOf( 10 ) );
assertEquals( 2, t.keyCount() );
t.set( "string", LuaValue.NIL );
t.set( "three", LuaValue.valueOf( 3.14 ) );
assertEquals( 2, t.keyCount() );
t.set( "test", LuaValue.NIL );
assertEquals( 1, t.keyCount() );
t.set( 10, LuaInteger.valueOf( 5 ) );
assertEquals( 2, t.keyCount() );
t.set( 10, LuaValue.NIL );
assertEquals( 1, t.keyCount() );
t.set( "three", LuaValue.NIL );
assertEquals( 0, t.keyCount() );
}
public void testInOrderLuaLength() {
LuaTable t = new_Table();
for ( int i = 1; i <= 32; ++i ) {
t.set( i, LuaValue.valueOf( "Test Value! "+i ) );
assertEquals( i, t.length() );
assertEquals( i, t.maxn() );
}
}
public void testOutOfOrderLuaLength() {
LuaTable t = new_Table();
for ( int j=8; j<32; j+=8 ) {
for ( int i = j; i > 0; --i ) {
t.set( i, LuaValue.valueOf( "Test Value! "+i ) );
}
assertEquals( j, t.length() );
assertEquals( j, t.maxn() );
}
}
public void testStringKeysLuaLength() {
LuaTable t = new_Table();
for ( int i = 1; i <= 32; ++i ) {
t.set( "str-"+i, LuaValue.valueOf( "String Key Test Value! "+i ) );
assertEquals( 0, t.length() );
assertEquals( 0, t.maxn() );
}
}
public void testMixedKeysLuaLength() {
LuaTable t = new_Table();
for ( int i = 1; i <= 32; ++i ) {
t.set( "str-"+i, LuaValue.valueOf( "String Key Test Value! "+i ) );
t.set( i, LuaValue.valueOf( "Int Key Test Value! "+i ) );
assertEquals( i, t.length() );
assertEquals( i, t.maxn() );
}
}
private static final void compareLists(LuaTable t,Vector v) {
int n = v.size();
assertEquals(v.size(),t.length());
for ( int j=0; j<n; j++ ) {
Object vj = v.elementAt(j);
Object tj = t.get(j+1).toString();
vj = ((LuaString)vj).toString();
assertEquals(vj,tj);
}
}
public void testInsertBeginningOfList() {
LuaTable t = new_Table();
Vector v = new Vector();
for ( int i = 1; i <= 32; ++i ) {
LuaString test = LuaValue.valueOf("Test Value! "+i);
t.insert(1, test);
v.insertElementAt(test, 0);
compareLists(t,v);
}
}
public void testInsertEndOfList() {
LuaTable t = new_Table();
Vector v = new Vector();
for ( int i = 1; i <= 32; ++i ) {
LuaString test = LuaValue.valueOf("Test Value! "+i);
t.insert(0, test);
v.insertElementAt(test, v.size());
compareLists(t,v);
}
}
public void testInsertMiddleOfList() {
LuaTable t = new_Table();
Vector v = new Vector();
for ( int i = 1; i <= 32; ++i ) {
LuaString test = LuaValue.valueOf("Test Value! "+i);
int m = i / 2;
t.insert(m+1, test);
v.insertElementAt(test, m);
compareLists(t,v);
}
}
private static final void prefillLists(LuaTable t,Vector v) {
for ( int i = 1; i <= 32; ++i ) {
LuaString test = LuaValue.valueOf("Test Value! "+i);
t.insert(0, test);
v.insertElementAt(test, v.size());
}
}
public void testRemoveBeginningOfList() {
LuaTable t = new_Table();
Vector v = new Vector();
prefillLists(t,v);
for ( int i = 1; i <= 32; ++i ) {
t.remove(1);
v.removeElementAt(0);
compareLists(t,v);
}
}
public void testRemoveEndOfList() {
LuaTable t = new_Table();
Vector v = new Vector();
prefillLists(t,v);
for ( int i = 1; i <= 32; ++i ) {
t.remove(0);
v.removeElementAt(v.size()-1);
compareLists(t,v);
}
}
public void testRemoveMiddleOfList() {
LuaTable t = new_Table();
Vector v = new Vector();
prefillLists(t,v);
for ( int i = 1; i <= 32; ++i ) {
int m = v.size() / 2;
t.remove(m+1);
v.removeElementAt(m);
compareLists(t,v);
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,557 @@
/*******************************************************************************
* Copyright (c) 2009 Luaj.org. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
******************************************************************************/
package org.luaj.vm2;
import org.luaj.vm2.LuaDouble;
import org.luaj.vm2.LuaInteger;
import org.luaj.vm2.LuaString;
import org.luaj.vm2.LuaValue;
import junit.framework.TestCase;
/**
* Tests of basic unary and binary operators on main value types.
*/
public class UnaryBinaryOperatorsTest extends TestCase {
LuaValue dummy;
protected void setUp() throws Exception {
super.setUp();
dummy = LuaValue.ZERO;
}
public void testEqualsBool() {
assertEquals(LuaValue.FALSE,LuaValue.FALSE);
assertEquals(LuaValue.TRUE,LuaValue.TRUE);
assertTrue(LuaValue.FALSE.equals(LuaValue.FALSE));
assertTrue(LuaValue.TRUE.equals(LuaValue.TRUE));
assertTrue(!LuaValue.FALSE.equals(LuaValue.TRUE));
assertTrue(!LuaValue.TRUE.equals(LuaValue.FALSE));
assertTrue(LuaValue.FALSE.eq_b(LuaValue.FALSE));
assertTrue(LuaValue.TRUE.eq_b(LuaValue.TRUE));
assertFalse(LuaValue.FALSE.eq_b(LuaValue.TRUE));
assertFalse(LuaValue.TRUE.eq_b(LuaValue.FALSE));
assertEquals(LuaValue.TRUE, LuaValue.FALSE.eq(LuaValue.FALSE));
assertEquals(LuaValue.TRUE, LuaValue.TRUE.eq(LuaValue.TRUE));
assertEquals(LuaValue.FALSE, LuaValue.FALSE.eq(LuaValue.TRUE));
assertEquals(LuaValue.FALSE, LuaValue.TRUE.eq(LuaValue.FALSE));
assertFalse(LuaValue.FALSE.neq_b(LuaValue.FALSE));
assertFalse(LuaValue.TRUE.neq_b(LuaValue.TRUE));
assertTrue(LuaValue.FALSE.neq_b(LuaValue.TRUE));
assertTrue(LuaValue.TRUE.neq_b(LuaValue.FALSE));
assertEquals(LuaValue.FALSE, LuaValue.FALSE.neq(LuaValue.FALSE));
assertEquals(LuaValue.FALSE, LuaValue.TRUE.neq(LuaValue.TRUE));
assertEquals(LuaValue.TRUE, LuaValue.FALSE.neq(LuaValue.TRUE));
assertEquals(LuaValue.TRUE, LuaValue.TRUE.neq(LuaValue.FALSE));
assertTrue(LuaValue.TRUE.toboolean());
assertFalse(LuaValue.FALSE.toboolean());
}
public void testNot() {
LuaValue ia=LuaValue.valueOf(3);
LuaValue da=LuaValue.valueOf(.25);
LuaValue sa=LuaValue.valueOf("1.5");
LuaValue ba=LuaValue.TRUE, bb=LuaValue.FALSE;
// like kinds
assertEquals(LuaValue.FALSE, ia.not());
assertEquals(LuaValue.FALSE, da.not());
assertEquals(LuaValue.FALSE, sa.not());
assertEquals(LuaValue.FALSE, ba.not());
assertEquals(LuaValue.TRUE, bb.not());
}
public void testNeg() {
LuaValue ia=LuaValue.valueOf(3), ib=LuaValue.valueOf(-4);
LuaValue da=LuaValue.valueOf(.25), db=LuaValue.valueOf(-.5);
LuaValue sa=LuaValue.valueOf("1.5"), sb=LuaValue.valueOf("-2.0");
// like kinds
assertEquals(-3., ia.neg().todouble());
assertEquals(-.25, da.neg().todouble());
assertEquals(-1.5, sa.neg().todouble());
assertEquals(4., ib.neg().todouble());
assertEquals(.5, db.neg().todouble());
assertEquals(2.0, sb.neg().todouble());
}
public void testDoublesBecomeInts() {
// DoubleValue.valueOf should return int
LuaValue ia=LuaInteger.valueOf(345), da=LuaDouble.valueOf(345.0), db=LuaDouble.valueOf(345.5);
LuaValue sa=LuaValue.valueOf("3.0"), sb=LuaValue.valueOf("3"), sc=LuaValue.valueOf("-2.0"), sd=LuaValue.valueOf("-2");
assertEquals(ia,da);
assertTrue(ia instanceof LuaInteger);
assertTrue(da instanceof LuaInteger);
assertTrue(db instanceof LuaDouble);
assertEquals( ia.toint(), 345 );
assertEquals( da.toint(), 345 );
assertEquals( da.todouble(), 345.0 );
assertEquals( db.todouble(), 345.5 );
assertTrue(sa instanceof LuaString);
assertTrue(sb instanceof LuaString);
assertTrue(sc instanceof LuaString);
assertTrue(sd instanceof LuaString);
assertEquals( 3., sa.todouble() );
assertEquals( 3., sb.todouble() );
assertEquals( -2., sc.todouble() );
assertEquals( -2., sd.todouble() );
}
public void testEqualsInt() {
LuaValue ia=LuaInteger.valueOf(345), ib=LuaInteger.valueOf(345), ic=LuaInteger.valueOf(-345);
LuaString sa=LuaString.valueOf("345"), sb=LuaString.valueOf("345"), sc=LuaString.valueOf("-345");
// objects should be different
assertNotSame(ia, ib);
assertNotSame(sa, sb);
assertNotSame(ia, ic);
assertNotSame(sa, sc);
// assert equals for same type
assertEquals(ia, ib);
assertEquals(sa, sb);
assertFalse(ia.equals(ic));
assertFalse(sa.equals(sc));
// check object equality for different types
assertFalse(ia.equals(sa));
assertFalse(sa.equals(ia));
}
public void testEqualsDouble() {
LuaValue da=LuaDouble.valueOf(345.5), db=LuaDouble.valueOf(345.5), dc=LuaDouble.valueOf(-345.5);
LuaString sa=LuaString.valueOf("345.5"), sb=LuaString.valueOf("345.5"), sc=LuaString.valueOf("-345.5");
// objects should be different
assertNotSame(da, db);
assertNotSame(sa, sb);
assertNotSame(da, dc);
assertNotSame(sa, sc);
// assert equals for same type
assertEquals(da, db);
assertEquals(sa, sb);
assertFalse(da.equals(dc));
assertFalse(sa.equals(sc));
// check object equality for different types
assertFalse(da.equals(sa));
assertFalse(sa.equals(da));
}
public void testEqInt() {
LuaValue ia=LuaInteger.valueOf(345), ib=LuaInteger.valueOf(345), ic=LuaInteger.valueOf(-123);
LuaValue sa=LuaString.valueOf("345"), sb=LuaString.valueOf("345"), sc=LuaString.valueOf("-345");
// check arithmetic equality among same types
assertEquals(ia.eq(ib),LuaValue.TRUE);
assertEquals(sa.eq(sb),LuaValue.TRUE);
assertEquals(ia.eq(ic),LuaValue.FALSE);
assertEquals(sa.eq(sc),LuaValue.FALSE);
// check arithmetic equality among different types
assertEquals(ia.eq(sa),LuaValue.FALSE);
assertEquals(sa.eq(ia),LuaValue.FALSE);
}
public void testEqDouble() {
LuaValue da=LuaDouble.valueOf(345.5), db=LuaDouble.valueOf(345.5), dc=LuaDouble.valueOf(-345.5);
LuaValue sa=LuaString.valueOf("345.5"), sb=LuaString.valueOf("345.5"), sc=LuaString.valueOf("-345.5");
// check arithmetic equality among same types
assertEquals(da.eq(db),LuaValue.TRUE);
assertEquals(sa.eq(sb),LuaValue.TRUE);
assertEquals(da.eq(dc),LuaValue.FALSE);
assertEquals(sa.eq(sc),LuaValue.FALSE);
// check arithmetic equality among different types
assertEquals(da.eq(sa),LuaValue.FALSE);
assertEquals(sa.eq(da),LuaValue.FALSE);
}
public void testAdd() {
LuaValue ia=LuaValue.valueOf(111), ib=LuaValue.valueOf(44);
LuaValue da=LuaValue.valueOf(55.25), db=LuaValue.valueOf(3.5);
LuaValue sa=LuaValue.valueOf("22.125"), sb=LuaValue.valueOf("7.25");
// check types
assertTrue( ia instanceof LuaInteger );
assertTrue( ib instanceof LuaInteger );
assertTrue( da instanceof LuaDouble );
assertTrue( db instanceof LuaDouble );
assertTrue( sa instanceof LuaString );
assertTrue( sb instanceof LuaString );
// like kinds
assertEquals(155.0, ia.add(ib).todouble());
assertEquals(58.75, da.add(db).todouble());
assertEquals(29.375, sa.add(sb).todouble());
// unlike kinds
assertEquals(166.25, ia.add(da).todouble());
assertEquals(166.25, da.add(ia).todouble());
assertEquals(133.125,ia.add(sa).todouble());
assertEquals(133.125,sa.add(ia).todouble());
assertEquals(77.375, da.add(sa).todouble());
assertEquals(77.375, sa.add(da).todouble());
}
public void testSub() {
LuaValue ia=LuaValue.valueOf(111), ib=LuaValue.valueOf(44);
LuaValue da=LuaValue.valueOf(55.25), db=LuaValue.valueOf(3.5);
LuaValue sa=LuaValue.valueOf("22.125"), sb=LuaValue.valueOf("7.25");
// like kinds
assertEquals(67.0, ia.sub(ib).todouble());
assertEquals(51.75, da.sub(db).todouble());
assertEquals(14.875, sa.sub(sb).todouble());
// unlike kinds
assertEquals(55.75, ia.sub(da).todouble());
assertEquals(-55.75, da.sub(ia).todouble());
assertEquals(88.875, ia.sub(sa).todouble());
assertEquals(-88.875, sa.sub(ia).todouble());
assertEquals(33.125, da.sub(sa).todouble());
assertEquals(-33.125, sa.sub(da).todouble());
}
public void testMul() {
LuaValue ia=LuaValue.valueOf(3), ib=LuaValue.valueOf(4);
LuaValue da=LuaValue.valueOf(.25), db=LuaValue.valueOf(.5);
LuaValue sa=LuaValue.valueOf("1.5"), sb=LuaValue.valueOf("2.0");
// like kinds
assertEquals(12.0, ia.mul(ib).todouble());
assertEquals(.125, da.mul(db).todouble());
assertEquals(3.0, sa.mul(sb).todouble());
// unlike kinds
assertEquals(.75, ia.mul(da).todouble());
assertEquals(.75, da.mul(ia).todouble());
assertEquals(4.5, ia.mul(sa).todouble());
assertEquals(4.5, sa.mul(ia).todouble());
assertEquals(.375, da.mul(sa).todouble());
assertEquals(.375, sa.mul(da).todouble());
}
public void testDiv() {
LuaValue ia=LuaValue.valueOf(3), ib=LuaValue.valueOf(4);
LuaValue da=LuaValue.valueOf(.25), db=LuaValue.valueOf(.5);
LuaValue sa=LuaValue.valueOf("1.5"), sb=LuaValue.valueOf("2.0");
// like kinds
assertEquals(3./4., ia.div(ib).todouble());
assertEquals(.25/.5, da.div(db).todouble());
assertEquals(1.5/2., sa.div(sb).todouble());
// unlike kinds
assertEquals(3./.25, ia.div(da).todouble());
assertEquals(.25/3., da.div(ia).todouble());
assertEquals(3./1.5, ia.div(sa).todouble());
assertEquals(1.5/3., sa.div(ia).todouble());
assertEquals(.25/1.5, da.div(sa).todouble());
assertEquals(1.5/.25, sa.div(da).todouble());
}
public void testPow() {
LuaValue ia=LuaValue.valueOf(3), ib=LuaValue.valueOf(4);
LuaValue da=LuaValue.valueOf(4.), db=LuaValue.valueOf(.5);
LuaValue sa=LuaValue.valueOf("1.5"), sb=LuaValue.valueOf("2.0");
// like kinds
assertEquals(Math.pow(3.,4.), ia.pow(ib).todouble());
assertEquals(Math.pow(4.,.5), da.pow(db).todouble());
assertEquals(Math.pow(1.5,2.), sa.pow(sb).todouble());
// unlike kinds
assertEquals(Math.pow(3.,4.), ia.pow(da).todouble());
assertEquals(Math.pow(4.,3.), da.pow(ia).todouble());
assertEquals(Math.pow(3.,1.5), ia.pow(sa).todouble());
assertEquals(Math.pow(1.5,3.), sa.pow(ia).todouble());
assertEquals(Math.pow(4.,1.5), da.pow(sa).todouble());
assertEquals(Math.pow(1.5,4.), sa.pow(da).todouble());
}
private static double luaMod(double x, double y) {
return y!=0? x-y*Math.floor(x/y): Double.NaN;
}
public void testMod() {
LuaValue ia=LuaValue.valueOf(3), ib=LuaValue.valueOf(-4);
LuaValue da=LuaValue.valueOf(.25), db=LuaValue.valueOf(-.5);
LuaValue sa=LuaValue.valueOf("1.5"), sb=LuaValue.valueOf("-2.0");
// like kinds
assertEquals(luaMod(3.,-4.), ia.mod(ib).todouble());
assertEquals(luaMod(.25,-.5), da.mod(db).todouble());
assertEquals(luaMod(1.5,-2.), sa.mod(sb).todouble());
// unlike kinds
assertEquals(luaMod(3.,.25), ia.mod(da).todouble());
assertEquals(luaMod(.25,3.), da.mod(ia).todouble());
assertEquals(luaMod(3.,1.5), ia.mod(sa).todouble());
assertEquals(luaMod(1.5,3.), sa.mod(ia).todouble());
assertEquals(luaMod(.25,1.5), da.mod(sa).todouble());
assertEquals(luaMod(1.5,.25), sa.mod(da).todouble());
}
public void testCompareStrings() {
// these are lexical compare!
LuaValue sa=LuaValue.valueOf("-1.5");
LuaValue sb=LuaValue.valueOf("-2.0");
LuaValue sc=LuaValue.valueOf("1.5");
LuaValue sd=LuaValue.valueOf("2.0");
assertEquals(LuaValue.FALSE, sa.lt(sa));
assertEquals(LuaValue.TRUE, sa.lt(sb));
assertEquals(LuaValue.TRUE, sa.lt(sc));
assertEquals(LuaValue.TRUE, sa.lt(sd));
assertEquals(LuaValue.FALSE, sb.lt(sa));
assertEquals(LuaValue.FALSE, sb.lt(sb));
assertEquals(LuaValue.TRUE, sb.lt(sc));
assertEquals(LuaValue.TRUE, sb.lt(sd));
assertEquals(LuaValue.FALSE, sc.lt(sa));
assertEquals(LuaValue.FALSE, sc.lt(sb));
assertEquals(LuaValue.FALSE, sc.lt(sc));
assertEquals(LuaValue.TRUE, sc.lt(sd));
assertEquals(LuaValue.FALSE, sd.lt(sa));
assertEquals(LuaValue.FALSE, sd.lt(sb));
assertEquals(LuaValue.FALSE, sd.lt(sc));
assertEquals(LuaValue.FALSE, sd.lt(sd));
}
public void testLt() {
LuaValue ia=LuaValue.valueOf(3), ib=LuaValue.valueOf(4);
LuaValue da=LuaValue.valueOf(.25), db=LuaValue.valueOf(.5);
// like kinds
assertEquals(3.<4., ia.lt(ib).toboolean());
assertEquals(.25<.5, da.lt(db).toboolean());
assertEquals(3.<4., ia.lt_b(ib));
assertEquals(.25<.5, da.lt_b(db));
// unlike kinds
assertEquals(3.<.25, ia.lt(da).toboolean());
assertEquals(.25<3., da.lt(ia).toboolean());
assertEquals(3.<.25, ia.lt_b(da));
assertEquals(.25<3., da.lt_b(ia));
}
public void testLtEq() {
LuaValue ia=LuaValue.valueOf(3), ib=LuaValue.valueOf(4);
LuaValue da=LuaValue.valueOf(.25), db=LuaValue.valueOf(.5);
// like kinds
assertEquals(3.<=4., ia.lteq(ib).toboolean());
assertEquals(.25<=.5, da.lteq(db).toboolean());
assertEquals(3.<=4., ia.lteq_b(ib));
assertEquals(.25<=.5, da.lteq_b(db));
// unlike kinds
assertEquals(3.<=.25, ia.lteq(da).toboolean());
assertEquals(.25<=3., da.lteq(ia).toboolean());
assertEquals(3.<=.25, ia.lteq_b(da));
assertEquals(.25<=3., da.lteq_b(ia));
}
public void testGt() {
LuaValue ia=LuaValue.valueOf(3), ib=LuaValue.valueOf(4);
LuaValue da=LuaValue.valueOf(.25), db=LuaValue.valueOf(.5);
// like kinds
assertEquals(3.>4., ia.gt(ib).toboolean());
assertEquals(.25>.5, da.gt(db).toboolean());
assertEquals(3.>4., ia.gt_b(ib));
assertEquals(.25>.5, da.gt_b(db));
// unlike kinds
assertEquals(3.>.25, ia.gt(da).toboolean());
assertEquals(.25>3., da.gt(ia).toboolean());
assertEquals(3.>.25, ia.gt_b(da));
assertEquals(.25>3., da.gt_b(ia));
}
public void testGtEq() {
LuaValue ia=LuaValue.valueOf(3), ib=LuaValue.valueOf(4);
LuaValue da=LuaValue.valueOf(.25), db=LuaValue.valueOf(.5);
// like kinds
assertEquals(3.>=4., ia.gteq(ib).toboolean());
assertEquals(.25>=.5, da.gteq(db).toboolean());
assertEquals(3.>=4., ia.gteq_b(ib));
assertEquals(.25>=.5, da.gteq_b(db));
// unlike kinds
assertEquals(3.>=.25, ia.gteq(da).toboolean());
assertEquals(.25>=3., da.gteq(ia).toboolean());
assertEquals(3.>=.25, ia.gteq_b(da));
assertEquals(.25>=3., da.gteq_b(ia));
}
public void testNotEq() {
LuaValue ia=LuaValue.valueOf(3), ib=LuaValue.valueOf(4);
LuaValue da=LuaValue.valueOf(.25), db=LuaValue.valueOf(.5);
LuaValue sa=LuaValue.valueOf("1.5"), sb=LuaValue.valueOf("2.0");
// like kinds
assertEquals(3.!=4., ia.neq(ib).toboolean());
assertEquals(.25!=.5, da.neq(db).toboolean());
assertEquals(1.5!=2., sa.neq(sb).toboolean());
assertEquals(3.!=4., ia.neq_b(ib));
assertEquals(.25!=.5, da.neq_b(db));
assertEquals(1.5!=2., sa.neq_b(sb));
// unlike kinds
assertEquals(3.!=.25, ia.neq(da).toboolean());
assertEquals(.25!=3., da.neq(ia).toboolean());
assertEquals(3.!=1.5, ia.neq(sa).toboolean());
assertEquals(1.5!=3., sa.neq(ia).toboolean());
assertEquals(.25!=1.5, da.neq(sa).toboolean());
assertEquals(1.5!=.25, sa.neq(da).toboolean());
assertEquals(3.!=.25, ia.neq_b(da));
assertEquals(.25!=3., da.neq_b(ia));
assertEquals(3.!=1.5, ia.neq_b(sa));
assertEquals(1.5!=3., sa.neq_b(ia));
assertEquals(.25!=1.5, da.neq_b(sa));
assertEquals(1.5!=.25, sa.neq_b(da));
}
public void testAnd() {
LuaValue ia=LuaValue.valueOf(3), ib=LuaValue.valueOf(4);
LuaValue da=LuaValue.valueOf(.25), db=LuaValue.valueOf(.5);
LuaValue sa=LuaValue.valueOf("1.5"), sb=LuaValue.valueOf("2.0");
LuaValue ba=LuaValue.TRUE, bb=LuaValue.FALSE;
// like kinds
assertSame(ib, ia.and(ib));
assertSame(db, da.and(db));
assertSame(sb, sa.and(sb));
// unlike kinds
assertSame(da, ia.and(da));
assertSame(ia, da.and(ia));
assertSame(sa, ia.and(sa));
assertSame(ia, sa.and(ia));
assertSame(sa, da.and(sa));
assertSame(da, sa.and(da));
// boolean values
assertSame(bb, ba.and(bb));
assertSame(bb, bb.and(ba));
assertSame(ia, ba.and(ia));
assertSame(bb, bb.and(ia));
}
public void testOr() {
LuaValue ia=LuaValue.valueOf(3), ib=LuaValue.valueOf(4);
LuaValue da=LuaValue.valueOf(.25), db=LuaValue.valueOf(.5);
LuaValue sa=LuaValue.valueOf("1.5"), sb=LuaValue.valueOf("2.0");
LuaValue ba=LuaValue.TRUE, bb=LuaValue.FALSE;
// like kinds
assertSame(ia, ia.or(ib));
assertSame(da, da.or(db));
assertSame(sa, sa.or(sb));
// unlike kinds
assertSame(ia, ia.or(da));
assertSame(da, da.or(ia));
assertSame(ia, ia.or(sa));
assertSame(sa, sa.or(ia));
assertSame(da, da.or(sa));
assertSame(sa, sa.or(da));
// boolean values
assertSame(ba, ba.or(bb));
assertSame(ba, bb.or(ba));
assertSame(ba, ba.or(ia));
assertSame(ia, bb.or(ia));
}
public void testLexicalComparison() {
LuaValue aaa = LuaValue.valueOf("aaa");
LuaValue baa = LuaValue.valueOf("baa");
LuaValue Aaa = LuaValue.valueOf("Aaa");
LuaValue aba = LuaValue.valueOf("aba");
LuaValue aaaa = LuaValue.valueOf("aaaa");
LuaValue t = LuaValue.TRUE;
LuaValue f = LuaValue.FALSE;
// basics
assertEquals(t, aaa.eq(aaa));
assertEquals(t, aaa.lt(baa));
assertEquals(t, aaa.lteq(baa));
assertEquals(f, aaa.gt(baa));
assertEquals(f, aaa.gteq(baa));
assertEquals(f, baa.lt(aaa));
assertEquals(f, baa.lteq(aaa));
assertEquals(t, baa.gt(aaa));
assertEquals(t, baa.gteq(aaa));
assertEquals(t, aaa.lteq(aaa));
assertEquals(t, aaa.gteq(aaa));
// different case
assertEquals(t, Aaa.eq(Aaa));
assertEquals(t, Aaa.lt(aaa));
assertEquals(t, Aaa.lteq(aaa));
assertEquals(f, Aaa.gt(aaa));
assertEquals(f, Aaa.gteq(aaa));
assertEquals(f, aaa.lt(Aaa));
assertEquals(f, aaa.lteq(Aaa));
assertEquals(t, aaa.gt(Aaa));
assertEquals(t, aaa.gteq(Aaa));
assertEquals(t, Aaa.lteq(Aaa));
assertEquals(t, Aaa.gteq(Aaa));
// second letter differs
assertEquals(t, aaa.eq(aaa));
assertEquals(t, aaa.lt(aba));
assertEquals(t, aaa.lteq(aba));
assertEquals(f, aaa.gt(aba));
assertEquals(f, aaa.gteq(aba));
assertEquals(f, aba.lt(aaa));
assertEquals(f, aba.lteq(aaa));
assertEquals(t, aba.gt(aaa));
assertEquals(t, aba.gteq(aaa));
assertEquals(t, aaa.lteq(aaa));
assertEquals(t, aaa.gteq(aaa));
// longer
assertEquals(t, aaa.eq(aaa));
assertEquals(t, aaa.lt(aaaa));
assertEquals(t, aaa.lteq(aaaa));
assertEquals(f, aaa.gt(aaaa));
assertEquals(f, aaa.gteq(aaaa));
assertEquals(f, aaaa.lt(aaa));
assertEquals(f, aaaa.lteq(aaa));
assertEquals(t, aaaa.gt(aaa));
assertEquals(t, aaaa.gteq(aaa));
assertEquals(t, aaa.lteq(aaa));
assertEquals(t, aaa.gteq(aaa));
}
}

View File

@@ -0,0 +1,188 @@
/*******************************************************************************
* Copyright (c) 2009 Luaj.org. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
******************************************************************************/
package org.luaj.vm2;
import java.lang.ref.WeakReference;
import java.util.Random;
public class WeakTableTest extends TableTest {
protected LuaTable new_Table() { return new WeakTable(false, true); }
protected LuaTable new_Table(int n,int m) { return new WeakTable(false, true); }
public static class WeakKeyTableTest extends TableTest {
protected LuaTable new_Table() { return new WeakTable(true, false); }
protected LuaTable new_Table(int n,int m) { return new WeakTable(true, false); }
}
public static class WeakKeyValueTableTest extends TableTest {
protected LuaTable new_Table() { return new WeakTable(true, true); }
protected LuaTable new_Table(int n,int m) { return new WeakTable(true, true); }
}
public void testWeakValuesTable() {
LuaTable t = new_Table();
Object obj = new Object();
LuaTable tableValue = new LuaTable();
LuaString stringValue = LuaString.valueOf("this is a test");
t.set("table", tableValue);
t.set("userdata", LuaValue.userdataOf(obj, null));
t.set("string", stringValue);
t.set("string2", LuaString.valueOf("another string"));
assertTrue("table must have at least 4 elements", t.hashKeys.length > 4);
// check that table can be used to get elements
assertEquals(tableValue, t.get("table"));
assertEquals(stringValue, t.get("string"));
assertEquals(obj, t.get("userdata").checkuserdata());
// nothing should be collected, since we have strong references here
System.gc();
// check that elements are still there
assertEquals(tableValue, t.get("table"));
assertEquals(stringValue, t.get("string"));
assertEquals(obj, t.get("userdata").checkuserdata());
// drop our strong references
obj = null;
tableValue = null;
stringValue = null;
// Garbage collection should cause weak entries to be dropped.
System.gc();
// check that they are dropped
assertEquals(LuaValue.NIL, t.get("table"));
assertEquals(LuaValue.NIL, t.get("userdata"));
assertFalse("strings should not be in weak references", t.get("string").isnil());
}
public static class MyData {
public final int value;
public MyData( int value ) {
this.value = value;
}
public int hashCode() {
return value;
}
public boolean equals( Object o ) {
return (o instanceof MyData) && ((MyData)o).value == value;
}
public String toSting() {
return "mydata-"+value;
}
}
public void testWeakKeysTable() {
LuaTable t = new WeakTable(true, false);
LuaValue key = LuaValue.userdataOf(new MyData(111));
LuaValue val = LuaValue.userdataOf(new MyData(222));
// set up the table
t.set( key, val );
assertEquals( val, t.get(key) );
System.gc();
assertEquals( val, t.get(key) );
// drop key and value references, replace them with new ones
WeakReference origkey = new WeakReference(key);
WeakReference origval = new WeakReference(val);
key = LuaValue.userdataOf(new MyData(111));
val = LuaValue.userdataOf(new MyData(222));
// new key and value should be interchangeable (feature of this test class
assertEquals( key, origkey.get() );
assertEquals( val, origval.get() );
assertEquals( val, t.get(key) );
assertEquals( val, t.get((LuaValue) origkey.get()) );
assertEquals( origval.get(), t.get(key) );
// value should not be reachable after gc
System.gc();
assertEquals( null, origkey.get() );
assertEquals( LuaValue.NIL, t.get(key) );
// value should also be gone after gc after access!
System.gc();
assertEquals( null, origkey.get() );
assertEquals( null, origval.get() );
}
public void testWeakKeysValuesTable() {
LuaTable t = new WeakTable(true, true);
LuaValue key = LuaValue.userdataOf(new MyData(111));
LuaValue val = LuaValue.userdataOf(new MyData(222));
LuaValue key2 = LuaValue.userdataOf(new MyData(333));
LuaValue val2 = LuaValue.userdataOf(new MyData(444));
LuaValue key3 = LuaValue.userdataOf(new MyData(555));
LuaValue val3 = LuaValue.userdataOf(new MyData(666));
// set up the table
t.set( key, val );
t.set( key2, val2 );
t.set( key3, val3 );
assertEquals( val, t.get(key) );
assertEquals( val2, t.get(key2) );
assertEquals( val3, t.get(key3) );
System.gc();
assertEquals( val, t.get(key) );
assertEquals( val2, t.get(key2) );
assertEquals( val3, t.get(key3) );
// drop key and value references, replace them with new ones
WeakReference origkey = new WeakReference(key);
WeakReference origval = new WeakReference(val);
WeakReference origkey2 = new WeakReference(key2);
WeakReference origval2 = new WeakReference(val2);
WeakReference origkey3 = new WeakReference(key3);
WeakReference origval3 = new WeakReference(val3);
key = LuaValue.userdataOf(new MyData(111));
val = LuaValue.userdataOf(new MyData(222));
key2 = LuaValue.userdataOf(new MyData(333));
// don't drop val2, or key3
val3 = LuaValue.userdataOf(new MyData(666));
// no values should be reachable after gc
System.gc();
assertEquals( null, origkey.get() );
assertEquals( null, origval.get() );
assertEquals( null, origkey2.get() );
assertEquals( null, origval3.get() );
assertEquals( LuaValue.NIL, t.get(key) );
assertEquals( LuaValue.NIL, t.get(key2) );
assertEquals( LuaValue.NIL, t.get(key3) );
// all originals should be gone after gc, then access
val2 = null;
key3 = null;
System.gc();
assertEquals( null, origval2.get() );
assertEquals( null, origkey3.get() );
}
}

288
test/lua/baselib.lua Normal file
View File

@@ -0,0 +1,288 @@
-- tostring replacement that assigns ids
local ts,id,nid,types = tostring,{},0,{table='tbl',thread='thr',userdata='uda',['function']='func'}
tostring = function(x)
if not x or not types[type(x)] then return ts(x) end
if not id[x] then nid=nid+1; id[x]=types[type(x)]..'.'..nid end
return id[x]
end
-- wrap pcall to return one result
-- error message are tested elsewhere
local pc = pcall
local pcall = function(...)
local s,e = pc(...)
if s then return e end
return false, type(e)
end
-- print
print()
print(11)
print("abc",123,nil,"pqr")
print( nil and 'T' or 'F' )
print( false and 'T' or 'F' )
print( 0 and 'T' or 'F' )
-- assert
print( 'assert(true)', assert(true) )
print( 'pcall(assert,true)', pcall(assert,true) )
print( 'pcall(assert,false)', pcall(assert,false) )
print( 'pcall(assert,nil)', pcall(assert,nil) )
print( 'pcall(assert,true,"msg")', pcall(assert,true,"msg") )
print( 'pcall(assert,false,"msg")', pcall(assert,false,"msg") )
print( 'pcall(assert,nil,"msg")', pcall(assert,nil,"msg") )
print( 'pcall(assert,false,"msg","msg2")', pcall(assert,false,"msg","msg2") )
-- collectgarbage (not supported)
print( 'collectgarbage("count")', type(collectgarbage("count")))
print( 'collectgarbage("collect")', type(collectgarbage("collect")))
print( 'collectgarbage("count")', type(collectgarbage("count")))
-- dofile (not supported)
-- ipairs
print( 'pcall(ipairs)', pcall(ipairs) )
print( 'pcall(ipairs,nil)', pcall(ipairs,nil) )
print( 'pcall(ipairs,"a")', pcall(ipairs,"a") )
print( 'pcall(ipairs,1)', pcall(ipairs,1) )
for k,v in ipairs({}) do print('ipairs1',k,v)end
for k,v in ipairs({'one','two'}) do print('ipairs2',k,v)end
for k,v in ipairs({aa='aaa',bb='bbb'}) do print('ipairs3',k,v)end
for k,v in ipairs({aa='aaa',bb='bbb','one','two'}) do print('ipairs4',k,v)end
for k,v in ipairs({[30]='30',[20]='20'}) do print('ipairs5',k,v)end
-- load
-- loadfile
-- loadstring
local lst = "print(3+4); return 8"
local chunk, err = loadstring( lst )
print( 'loadstring("'..lst..'")', chunk, err )
print( 'loadstring("'..lst..'")()', chunk() )
-- pairs
print( 'pcall(pairs)', pcall(pairs) )
print( 'pcall(pairs,nil)', pcall(pairs,nil) )
print( 'pcall(pairs,"a")', pcall(pairs,"a") )
print( 'pcall(pairs,1)', pcall(pairs,1) )
for k,v in pairs({}) do print('pairs1',k,v)end
for k,v in pairs({'one','two'}) do print('pairs2',k,v)end
for k,v in pairs({aa='aaa',bb='bbb'}) do print('pairs3',k,v)end
for k,v in pairs({aa='aaa',bb='bbb','one','two'}) do print('pairs4',k,v)end
for k,v in pairs({[20]='30',[30]='20'}) do print('pairs5',k,v)end
-- _G
print( '_G["abc"] (before)', _G["abc"] )
abc='def'
print( '_G["abc"] (after)', _G["abc"] )
-- type
print( 'type(nil)', type(nil) )
print( 'type("a")', type("a") )
print( 'type(1)', type(1) )
print( 'type(1.5)', type(1.5) )
print( 'type(function() end)', type(function() end) )
print( 'type({})', type({}) )
print( 'type(true)', type(true) )
print( 'type(false)', type(false) )
print( 'pcall(type,type)', pcall(type,type) )
print( 'pcall(type)', pcall(type) )
print( '(function() return pcall(type) end)()', (function() return pcall(type) end)() )
local function la() return pcall(type) end
print( 'la()', la() )
function ga() return pcall(type) end
print( 'ga()', ga() )
-- getfenv, setfenv: tested in setfenv.lua
-- getmetatable, setmetatable
ta = { aa1="aaa1", aa2="aaa2" }
tb = { bb1="bbb1", bb2="bbb2" }
print( 'getmetatable(ta)', getmetatable(ta) )
print( 'getmetatable(tb)', getmetatable(tb) )
print( 'setmetatable(ta),{cc1="ccc1"}', type( setmetatable(ta,{cc1="ccc1"}) ) )
print( 'setmetatable(tb),{dd1="ddd1"}', type( setmetatable(tb,{dd1="ddd1"}) ) )
print( 'getmetatable(ta)["cc1"]', getmetatable(ta)["cc1"] )
print( 'getmetatable(tb)["dd1"]', getmetatable(tb)["dd1"] )
print( 'getmetatable(1)', getmetatable(1) )
print( 'pcall(setmetatable,1)', pcall(setmetatable,1) )
print( 'pcall(setmetatable,nil)', pcall(setmetatable,nil) )
print( 'pcall(setmetatable,"ABC")', pcall(setmetatable,"ABC") )
print( 'pcall(setmetatable,function() end)', pcall(setmetatable,function() end) )
-- rawget,rawset
local mt = {aa="aaa", bb="bbb"}
mt.__index = mt
mt.__newindex = mt
local s = {cc="ccc", dd="ddd", }
local t = {cc="ccc", dd="ddd"}
setmetatable(t,mt)
print( 'pcall(rawget)', pcall(rawget))
print( 'pcall(rawget,"a")', pcall(rawget,"a"))
print( 'pcall(rawget,s)', pcall(rawget,s))
print( 'pcall(rawget,t)', pcall(rawget,t))
function printtables()
function printtable(name,t)
print( ' '..name, t["aa"], t["bb"], t["cc"], t["dd"], t["ee"], t["ff"], t["gg"] )
print( ' '..name,
rawget(t,"aa"),
rawget(t,"bb"),
rawget(t,"cc"),
rawget(t,"dd"),
rawget(t,"ee"),
rawget(t,"ff"),
rawget(t,"gg") )
end
printtable( 's', s )
printtable( 't', t )
printtable( 'mt', mt )
end
printtables()
print( 'pcall(rawset,s,"aa","www")', rawset(s,"aa","www"))
printtables()
print( 'pcall(rawset,s,"cc","xxx")', rawset(s,"cc","xxx"))
printtables()
print( 'pcall(rawset,t,"aa","yyy")', rawset(t,"aa","yyy"))
printtables()
print( 'pcall(rawset,t,"dd","zzz")', rawset(t,"dd","zzz"))
printtables()
printtables()
print( 's["ee"]="ppp"' ); s["ee"]="ppp"
printtables()
print( 's["cc"]="qqq"' ); s["cc"]="qqq"
printtables()
print( 't["ff"]="rrr"' ); t["ff"]="rrr"
printtables()
print( 't["dd"]="sss"' ); t["dd"]="sss"
printtables()
print( 'mt["gg"]="ttt"' ); mt["gg"]="ttt"
printtables()
-- select
print( 'pcall(select)', pcall(select) )
print( 'select(1,11,22,33,44,55)', select(1,11,22,33,44,55) )
print( 'select(2,11,22,33,44,55)', select(2,11,22,33,44,55) )
print( 'select(3,11,22,33,44,55)', select(3,11,22,33,44,55) )
print( 'select(4,11,22,33,44,55)', select(4,11,22,33,44,55) )
print( 'pcall(select,5,11,22,33,44,55)', pcall(select,5,11,22,33,44,55) )
print( 'pcall(select,6,11,22,33,44,55)', pcall(select,6,11,22,33,44,55) )
print( 'pcall(select,7,11,22,33,44,55)', pcall(select,7,11,22,33,44,55) )
print( 'pcall(select,0,11,22,33,44,55)', pcall(select,0,11,22,33,44,55) )
print( 'pcall(select,-1,11,22,33,44,55)', pcall(select,-1,11,22,33,44,55) )
print( 'pcall(select,-2,11,22,33,44,55)', pcall(select,-2,11,22,33,44,55) )
print( 'pcall(select,-4,11,22,33,44,55)', pcall(select,-4,11,22,33,44,55) )
print( 'pcall(select,-5,11,22,33,44,55)', pcall(select,-5,11,22,33,44,55) )
print( 'pcall(select,-6,11,22,33,44,55)', pcall(select,-6,11,22,33,44,55) )
print( 'pcall(select,1)', pcall(select,1) )
print( 'pcall(select,select)', pcall(select,select) )
print( 'pcall(select,{})', pcall(select,{}) )
print( 'pcall(select,"2",11,22,33)', pcall(select,"2",11,22,33) )
print( 'pcall(select,"abc",11,22,33)', pcall(select,"abc",11,22,33) )
-- tonumber
print( 'pcall(tonumber)', pcall(tostring) )
print( 'pcall(tonumber,nil)', pcall(tonumber,nil) )
print( 'pcall(tonumber,"abc")', pcall(tonumber,"abc") )
print( 'pcall(tonumber,"123")', pcall(tonumber,"123") )
print( 'pcall(tonumber,"123",10)', pcall(tonumber,"123", 10) )
print( 'pcall(tonumber,"123",8)', pcall(tonumber,"123", 8) )
print( 'pcall(tonumber,"123",6)', pcall(tonumber,"123", 6) )
print( 'pcall(tonumber,"10101",4)', pcall(tonumber,"10101", 4) )
print( 'pcall(tonumber,"10101",3)', pcall(tonumber,"10101", 3) )
print( 'pcall(tonumber,"10101",2)', pcall(tonumber,"10101", 2) )
print( 'pcall(tonumber,"1a1",16)', pcall(tonumber,"1a1", 16) )
print( 'pcall(tonumber,"1a1",32)', pcall(tonumber,"1a1", 32) )
print( 'pcall(tonumber,"1a1",54)', pcall(tonumber,"1a1", 54) )
print( 'pcall(tonumber,"1a1",1)', pcall(tonumber,"1a1", 1) )
print( 'pcall(tonumber,"1a1",0)', pcall(tonumber,"1a1", 0) )
print( 'pcall(tonumber,"1a1",-1)', pcall(tonumber,"1a1", -1) )
print( 'pcall(tonumber,"1a1","32")', pcall(tonumber,"1a1", "32") )
print( 'pcall(tonumber,"123","456")', pcall(tonumber,"123","456") )
print( 'pcall(tonumber,"1a1",10)', pcall(tonumber,"1a1", 10) )
print( 'pcall(tonumber,"151",4)', pcall(tonumber,"151", 4) )
print( 'pcall(tonumber,"151",3)', pcall(tonumber,"151", 3) )
print( 'pcall(tonumber,"151",2)', pcall(tonumber,"151", 2) )
print( 'pcall(tonumber,"123",8,8)', pcall(tonumber,"123", 8, 8) )
print( 'pcall(tonumber,123)', pcall(tonumber,123) )
print( 'pcall(tonumber,true)', pcall(tonumber,true) )
print( 'pcall(tonumber,false)', pcall(tonumber,false) )
print( 'pcall(tonumber,tonumber)', pcall(tonumber,tonumber) )
print( 'pcall(tonumber,function() end)', pcall(tonumber,function() end) )
print( 'pcall(tonumber,{"one","two",a="aa",b="bb"})', pcall(tonumber,{"one","two",a="aa",b="bb"}) )
print( 'pcall(tonumber,"123.456")', pcall(tonumber,"123.456") )
print( 'pcall(tonumber," 123.456")', pcall(tonumber," 123.456") )
print( 'pcall(tonumber," 234qwer")', pcall(tonumber," 234qwer") )
print( 'pcall(tonumber,"0x20")', pcall(tonumber,"0x20") )
print( 'pcall(tonumber," 0x20")', pcall(tonumber," 0x20") )
print( 'pcall(tonumber,"0x20 ")', pcall(tonumber,"0x20 ") )
print( 'pcall(tonumber," 0x20 ")', pcall(tonumber," 0x20 ") )
print( 'pcall(tonumber,"0X20")', pcall(tonumber,"0X20") )
print( 'pcall(tonumber," 0X20")', pcall(tonumber," 0X20") )
print( 'pcall(tonumber,"0X20 ")', pcall(tonumber,"0X20 ") )
print( 'pcall(tonumber," 0X20 ")', pcall(tonumber," 0X20 ") )
print( 'pcall(tonumber,"0x20",10)', pcall(tonumber,"0x20",10) )
print( 'pcall(tonumber,"0x20",16)', pcall(tonumber,"0x20",16) )
print( 'pcall(tonumber,"0x20",8)', pcall(tonumber,"0x20",8) )
-- tostring
print( 'pcall(tostring)', pcall(tostring) )
print( 'pcall(tostring,nil)', pcall(tostring,nil) )
print( 'pcall(tostring,"abc")', pcall(tostring,"abc") )
print( 'pcall(tostring,"abc","def")', pcall(tostring,"abc","def") )
print( 'pcall(tostring,123)', pcall(tostring,123) )
print( 'pcall(tostring,true)', pcall(tostring,true) )
print( 'pcall(tostring,false)', pcall(tostring,false) )
print( 'tostring(tostring)', type(tostring(tostring)) )
print( 'tostring(function() end)', type(tostring(function() end)) )
print( 'tostring({"one","two",a="aa",b="bb"})', type(tostring({"one","two",a="aa",b="bb"})) )
-- unpack
print( 'pcall(unpack)', pcall(unpack) );
print( 'pcall(unpack,nil)', pcall(unpack,nil) );
print( 'pcall(unpack,"abc")', pcall(unpack,"abc") );
print( 'pcall(unpack,1)', pcall(unpack,1) );
print( 'unpack({"aa"})', unpack({"aa"}) );
print( 'unpack({"aa","bb"})', unpack({"aa","bb"}) );
print( 'unpack({"aa","bb","cc"})', unpack({"aa","bb","cc"}) );
local t = {"aa","bb","cc","dd","ee","ff"}
print( 'pcall(unpack,t)', pcall(unpack,t) );
print( 'pcall(unpack,t,2)', pcall(unpack,t,2) );
print( 'pcall(unpack,t,2,5)', pcall(unpack,t,2,5) );
print( 'pcall(unpack,t,2,6)', pcall(unpack,t,2,6) );
print( 'pcall(unpack,t,2,7)', pcall(unpack,t,2,7) );
print( 'pcall(unpack,t,1)', pcall(unpack,t,1) );
print( 'pcall(unpack,t,1,5)', pcall(unpack,t,1,5) );
print( 'pcall(unpack,t,1,6)', pcall(unpack,t,1,6) );
print( 'pcall(unpack,t,1,7)', pcall(unpack,t,1,7) );
print( 'pcall(unpack,t,0)', pcall(unpack,t,0) );
print( 'pcall(unpack,t,0,5)', pcall(unpack,t,0,5) );
print( 'pcall(unpack,t,0,6)', pcall(unpack,t,0,6) );
print( 'pcall(unpack,t,0,7)', pcall(unpack,t,0,7) );
print( 'pcall(unpack,t,-1)', pcall(unpack,t,-1) );
print( 'pcall(unpack,t,-1,5)', pcall(unpack,t,-1,5) );
print( 'pcall(unpack,t,-1,6)', pcall(unpack,t,-1,6) );
print( 'pcall(unpack,t,-1,7)', pcall(unpack,t,-1,7) );
print( 'pcall(unpack,t,2,4)', pcall(unpack,t,2,4) );
print( 'pcall(unpack,t,2,5)', pcall(unpack,t,2,5) );
print( 'pcall(unpack,t,2,6)', pcall(unpack,t,2,6) );
print( 'pcall(unpack,t,2,7)', pcall(unpack,t,2,7) );
print( 'pcall(unpack,t,2,8)', pcall(unpack,t,2,8) );
print( 'pcall(unpack,t,2,2)', pcall(unpack,t,2,0) );
print( 'pcall(unpack,t,2,1)', pcall(unpack,t,2,0) );
print( 'pcall(unpack,t,2,0)', pcall(unpack,t,2,0) );
print( 'pcall(unpack,t,2,-1)', pcall(unpack,t,2,-1) );
t[0] = 'zz'
t[-1] = 'yy'
t[-2] = 'xx'
print( 'pcall(unpack,t,0)', pcall(unpack,t,0) );
print( 'pcall(unpack,t,2,0)', pcall(unpack,t,2,0) );
print( 'pcall(unpack,t,2,-1)', pcall(unpack,t,2,-1) );
print( 'pcall(unpack,t,"3")', pcall(unpack,t,"3") );
print( 'pcall(unpack,t,"a")', pcall(unpack,t,"a") );
print( 'pcall(unpack,t,function() end)', pcall(unpack,t,function() end) );
-- _VERSION
print( '_VERSION', type(_VERSION) )

97
test/lua/coroutinelib.lua Normal file
View File

@@ -0,0 +1,97 @@
function printrunning()
if coroutine.running() == nil then
print("running is nil");
else
print("running is not nil")
end
end
function foo (a)
print("foo", a)
return coroutine.yield(2*a)
end
co = coroutine.create(function (a,b)
print("co-body", a, b)
local r = foo(a+1)
print("co-body", r)
local r, s = coroutine.yield(a+b, a-b)
print("co-body", r, s)
printrunning()
print("co.status.inside",coroutine.status(co));
local co2 = coroutine.create(function()
print("co.status.inside2",coroutine.status(co));
end)
print("co.status.inside",coroutine.status(co));
coroutine.resume(co2);
return b, "end"
end)
function exercise()
printrunning()
print("co.status",coroutine.status(co));
print("main", coroutine.resume(co, 1, 10))
print("co.status",coroutine.status(co));
print("main", coroutine.resume(co, "r"))
print("co.status",coroutine.status(co));
print("main", coroutine.resume(co, "x", "y"))
print("co.status",coroutine.status(co));
print("main", coroutine.resume(co, "x", "y"))
print("co.status",coroutine.status(co));
end
exercise();
co = coroutine.create(function (a,b)
print("co-body", a, b)
-- TODO: make java and C behave the same for yielding in pcalls
-- local status,r = pcall( foo, a+1 )
foo(a+1)
print("co-body", status,r)
local r, s = coroutine.yield(a+b, a-b)
print("co-body", r, s)
return b, "end"
end)
exercise();
-- wrap test
local g = coroutine.wrap(function (a,b)
print("co-body", a, b)
local r = foo(a+1)
print("co-body", r)
local r, s = coroutine.yield(a+b, a-b)
print("co-body", r, s)
return b, "end"
end )
print("g", g(1, 10))
print("g", g("r"))
print("g", g("x", "y"))
local s,e = pcall( g, "x", "y" )
print("g", string.match(e,'cannot resume dead coroutine') or 'badmessage: '..tostring(e))
-- varargs passing
local echo = function(msg,...)
print( msg, ...)
return ...
end
local echocr = function(...)
echo('(echocr) first args', unpack(arg,1,arg.n))
local a = arg
while true do
a = { echo( '(echoch) yield returns', coroutine.yield( unpack(a) ) ) }
end
end
local c = coroutine.create( echocr )
local step = function(...)
echo( '(main) resume returns',
coroutine.resume(c, echo('(main) sending args', ...)) )
end
step(111,222,333)
step()
step(111)
step(111,222,333)

236
test/lua/debuglib.lua Normal file
View File

@@ -0,0 +1,236 @@
local print,tostring,_G,pcall,ipairs,isnumber = print,tostring,_G,pcall,ipairs,isnumber
local e,f,g,h,s
print( 'has debug', debug~=nil )
if not debug then error( 'no debug' ) end
print( '----- debug.getfenv, debug.setfenv' )
f = function(a)
return 'f:'..tostring(a)..'|'..tostring(b)
end
s,e,g = pcall( debug.getfenv, f )
print( s, type(e), type(g), (e==G), pcall( f, 'abc' ) )
s,e,g = pcall( debug.setfenv, f, {b='def'} )
print( s, type(e), type(g), (e==G), pcall( f, 'abc' ) )
s,e,g = pcall( debug.getfenv, f )
print( s, type(e), type(g), (e==G), pcall( f, 'abc' ) )
print( '----- debug.getlocal, debug.setlocal' )
h = function(v,i,n)
s = 'h-'..v..'-'..i
local x1,y1 = debug.getlocal(v,i)
local x2,y2 = debug.setlocal(v,i,n)
local x3,y3 = debug.getlocal(v,i)
return s..' -> '..v..'-'..i..' '..
'get='..tostring(x1)..','..tostring(y1)..' '..
'set='..tostring(x2)..','..tostring(y2)..' '..
'get='..tostring(x3)..','..tostring(y3)..' '
end
g = function(...)
local p,q,r=7,8,9
local t = h(...)
local b = table.concat({...},',')
return t..'\tg locals='..p..','..q..','..r..' tbl={'..b..'}'
end
f = function(a,b,c)
local d,e,f = 4,5,6
local t = g(a,b,c)
return t..'\tf locals='..','..a..','..b..','..c..','..d..','..e..','..f
end
for lvl=3,2,-1 do
for lcl=0,7 do
print( pcall( f, lvl, lcl, '#' ) )
end
end
for lvl=1,1 do
for lcl=3,7 do
print( pcall( f, lvl, lcl, '#' ) )
end
end
print( '----- debug.getupvalue, debug.setupvalue' )
local m,n,o = 101,102,103
f = function(p,q,r)
local p,q,r = 104,105,106
local g = function(s,t,u)
local v,w,x = 107,108,109
return function()
return m,n,o,p,q,r,v,w,x
end
end
return g
end
g = f()
h = g()
local callh = function()
local t = {}
for i,v in ipairs( { pcall(h) } ) do
t[i] = tostring(v)
end
return table.concat(t,',')
end
print( 'h', h() )
local funs = { f, g, h }
local names = { 'f', 'g', 'h' }
for i=1,3 do
local fun,name = funs[i],names[i]
for index=0,10 do
local s1,x1,y1 = pcall( debug.getupvalue, fun, index )
local s2,x2,y2 = pcall( debug.setupvalue, fun, index, 666000+i*111000+index )
local s3,x3,y3 = pcall( debug.getupvalue, fun, index )
print( name..' -> '..i..'-'..index..' '..
'get='..tostring(s1)..','..tostring(x1)..','..tostring(y1)..' '..
'set='..tostring(s2)..','..tostring(x2)..','..tostring(y2)..' '..
'get='..tostring(s3)..','..tostring(x3)..','..tostring(y3)..' '..
'tbl='..callh() )
end
end
print( '----- debug.setmetatable, debug.getmetatable' )
local a = {a='bbb'}
local b = {}
local mt = {__index={b='ccc'}}
print( 'a.a='..tostring(a.a)..' a.b='..tostring(a.b)..' b.a='..tostring(b.a)..' b.b='..tostring(b.b))
local s1,x1,y1 = pcall( debug.getmetatable, a )
local s2,x2,y2 = pcall( debug.setmetatable, a, mt )
print( 'a.a='..tostring(a.a)..' a.b='..tostring(a.b)..' b.a='..tostring(b.a)..' b.b='..tostring(b.b))
local s3,x3,y3 = pcall( debug.getmetatable, a )
local s4,x4,y4 = pcall( debug.getmetatable, b )
local s5,x5,y5 = pcall( debug.setmetatable, a, nil )
print( 'a.a='..tostring(a.a)..' a.b='..tostring(a.b)..' b.a='..tostring(b.a)..' b.b='..tostring(b.b))
local s6,x6,y6 = pcall( debug.getmetatable, a )
if not s1 then print( 's1 error', x1 ) end
if not s2 then print( 's2 error', x2 ) end
if not s3 then print( 's3 error', x3 ) end
if not s4 then print( 's4 error', x4 ) end
if not s5 then print( 's5 error', x5 ) end
if not s6 then print( 's6 error', x6 ) end
print( 'get='..tostring(s1)..','..tostring(x1==nil)..','..tostring(y1) )
print( 'set='..tostring(s2)..','..tostring(x2==a)..','..tostring(y2) )
print( 'get='..tostring(s3)..','..tostring(x3==mt)..','..tostring(y3) )
print( 'get='..tostring(s4)..','..tostring(x4==nil)..','..tostring(y4) )
print( 'set='..tostring(s5)..','..tostring(x5==a)..','..tostring(y5) )
print( 'get='..tostring(s6)..','..tostring(x6==nil)..','..tostring(y6) )
print( pcall( debug.getmetatable, 1 ) )
-- print( pcall( debug.setmetatable, 1, {} ) )
-- print( pcall( debug.setmetatable, 1, nil ) )
print( '----- debug.getinfo' )
local printfield = function(tbl, field)
local x = tbl[field]
if x == nil then return end
local typ = type(x)
if typ=='table' then
x = '{'..table.concat(x,',')..'}'
elseif typ=='function' then
x = typ
elseif typ=='string' then
if field == 'source' then
x = x:sub(2)
end
end
print( ' '..field..': '..tostring(x) )
end
local fields = { 'source', 'short_src', 'what',
'currentline', 'linedefined', 'lastlinedefined',
'nups', 'func', 'activelines' }
local printinfo = function(...)
for i,a in ipairs(arg) do
if type(a) == 'table' then
for j,field in ipairs(fields) do
printfield( a, field)
end
else
print( tostring(a) )
end
end
end
function test()
local x = 5
function f()
x = x + 1
return x
end
function g()
x = x - 1
print( '---' )
printinfo( 'debug.getinfo(1)', debug.getinfo(1) )
printinfo( 'debug.getinfo(1,"")', debug.getinfo(1, "") )
printinfo( 'debug.getinfo(1,"l")', debug.getinfo(1, "l") )
printinfo( 'debug.getinfo(1,"fL")', debug.getinfo(1, "fL") )
printinfo( 'debug.getinfo(2)', debug.getinfo(2) )
printinfo( 'debug.getinfo(2,"l")', debug.getinfo(2, "l") )
printinfo( 'debug.getinfo(2,"fL")', debug.getinfo(2, "fL") )
printinfo( 'debug.getinfo(10,"")', pcall( debug.getinfo, 10, "" ) )
printinfo( 'debug.getinfo(-10,"")', pcall( debug.getinfo, -10, "" ) )
--[[
for i=1,3 do
printinfo( 'debug.traceback("msg")', debug.traceback('msg') )
printinfo( 'debug.traceback("another",'..i..')', debug.traceback('another',i) )
end
--]]
print( '---' )
return x
end
print(f())
print(g())
return f, g
end
local options = "nSlufL"
local e,f,g = pcall( test )
print( 'e,f,g', e, type(f), type(g) )
printinfo( 'debug.getinfo(f)', pcall(debug.getinfo, f) )
printinfo( 'debug.getinfo(f,"'..options..'")', pcall(debug.getinfo, f, options) )
for j=1,6 do
local opts = options:sub(j,j)
printinfo( 'debug.getinfo(f,"'..opts..'")', pcall(debug.getinfo, f, opts) )
end
printinfo( 'debug.getinfo(g)', pcall(debug.getinfo, g) )
printinfo( 'debug.getinfo(test)', pcall(debug.getinfo, test) )
print( '----- debug.sethook, debug.gethook' )
f = function(x)
g = function(y)
return math.min(x,h)
end
local a = g(x)
return a + a
end
local hook = function(...)
print( ' ... in hook', ... )
local info = debug.getinfo(2,"Sl")
if info then
print( ' info[2]='..tostring(info.short_src)..','..tostring(info.currentline) )
end
end
local tryfunc = function(hook,mask,func,arg)
local x,f,h,m
pcall( function()
debug.sethook(hook,mask)
x = func(arg)
f,h,m = debug.gethook()
end )
debug.sethook()
return x,f,h,m
end
local tryhooks = function(mask)
local s1,a1,b1,c1,d1 = pcall( tryfunc, hook, mask, f, 333 )
print( 'hook = '..mask..' -> '..
'result='..tostring(s1)..','..tostring(a1)..','..
type(b1)..','..type(c1)..','..
tostring(b1==f)..','..tostring(c1==hook)..','..
tostring(d1)..' ' )
end
--[[
tryhooks("c")
tryhooks("r")
tryhooks("l")
tryhooks("crl")
--]]

137
test/lua/errors.lua Normal file
View File

@@ -0,0 +1,137 @@
-- tostring replacement that assigns ids
local ts,id,nid,types = tostring,{},0,{table='tbl',thread='thr',userdata='uda',['function']='func'}
tostring = function(x)
if not x or not types[type(x)] then return ts(x) end
if not id[x] then nid=nid+1; id[x]=types[type(x)]..'.'..nid end
return id[x]
end
-- test of common types of errors
-- local function c(f,...) return f(...) end
-- local function b(...) return c(...) end
--local function a(...) return (pcall(b,...)) end
local function a(...) local s,e=pcall(...) if s then return s,e else return false,type(e) end end
s = 'some string'
local t = {}
-- error message tests
print( 'a(error)', a(error) )
print( 'a(error,"msg")', a(error,"msg") )
print( 'a(error,"msg",0)', a(error,"msg",0) )
print( 'a(error,"msg",1)', a(error,"msg",1) )
print( 'a(error,"msg",2)', a(error,"msg",2) )
print( 'a(error,"msg",3)', a(error,"msg",3) )
print( 'a(error,"msg",4)', a(error,"msg",4) )
print( 'a(error,"msg",5)', a(error,"msg",5) )
print( 'a(error,"msg",6)', a(error,"msg",6) )
-- call errors
print( 'a(nil())', a(function() return n() end) )
print( 'a(t()) ', a(function() return t() end) )
print( 'a(s()) ', a(function() return s() end) )
print( 'a(true())', a(function() local b = true; return b() end) )
-- arithmetic errors
print( 'a(nil+1)', a(function() return nil+1 end) )
print( 'a(a+1) ', a(function() return a+1 end) )
print( 'a(s+1) ', a(function() return s+1 end) )
print( 'a(true+1)', a(function() local b = true; return b+1 end) )
-- table errors
print( 'a(nil.x)', a(function() return n.x end) )
print( 'a(a.x) ', a(function() return a.x end) )
print( 'a(s.x) ', a(function() return s.x end) )
print( 'a(true.x)', a(function() local b = true; return b.x end) )
print( 'a(nil.x=5)', a(function() n.x=5 end) )
print( 'a(a.x=5) ', a(function() a.x=5 end) )
print( 'a(s.x=5) ', a(function() s.x=5 end) )
print( 'a(true.x=5)', a(function() local b = true; b.x=5 end) )
-- len operator
print( 'a(#nil) ', a(function() return #n end) )
print( 'a(#t) ', a(function() return #t end) )
print( 'a(#s) ', a(function() return #s end) )
print( 'a(#a) ', a(function() return #a end) )
print( 'a(#true)', a(function() local b = true; return #b end) )
-- comparison errors
print( 'a(nil>1)', a(function() return nil>1 end) )
print( 'a(a>1) ', a(function() return a>1 end) )
print( 'a(s>1) ', a(function() return s>1 end) )
print( 'a(true>1)', a(function() local b = true; return b>1 end) )
-- unary minus errors
print( 'a(-nil)', a(function() return -n end) )
print( 'a(-a) ', a(function() return -a end) )
print( 'a(-s) ', a(function() return -s end) )
print( 'a(-true)', a(function() local b = true; return -b end) )
-- string concatenation
local function concatsuite(comparefunc)
print( '"a".."b"', comparefunc("a","b") )
print( '"a"..nil', comparefunc("a",nil) )
print( 'nil.."b"', comparefunc(nil,"b") )
print( '"a"..{}', comparefunc("a",{}) )
print( '{}.."b"', comparefunc({},"b") )
print( '"a"..2', comparefunc("a",2) )
print( '2.."b"', comparefunc(2,"b") )
print( '"a"..print', comparefunc("a",print) )
print( 'print.."b"', comparefunc(print,"b") )
print( '"a"..true', comparefunc("a",true) )
print( 'true.."b"', comparefunc(true,"b") )
print( 'nil..true', comparefunc(nil,true) )
print( '"a"..3.5', comparefunc("a",3.5) )
print( '3.5.."b"', comparefunc(3.5,"b") )
end
local function strconcat(a,b)
return (pcall( function() return a..b end) )
end
local function tblconcat(a,b)
local t={a,b}
return (pcall( function() return table.concat(t,'-',1,2) end ))
end
print( '-------- string concatenation' )
concatsuite(strconcat)
print( '-------- table concatenation' )
concatsuite(tblconcat)
-- pairs
print( '-------- pairs tests' )
print( 'a(pairs(nil))', a(function() return pairs(nil,{}) end) )
print( 'a(pairs(a)) ', a(function() return pairs(a,{}) end) )
print( 'a(pairs(s)) ', a(function() return pairs(s,{}) end) )
print( 'a(pairs(t)) ', a(function() return pairs(t,{}) end) )
print( 'a(pairs(true))', a(function() local b = true; return pairs(b,{}) end) )
-- setmetatable
print( '-------- setmetatable tests' )
function sm(...)
return tostring(setmetatable(...))
end
print( 'a(setmetatable(nil))', a(function() return sm(nil,{}) end) )
print( 'a(setmetatable(a)) ', a(function() return sm(a,{}) end) )
print( 'a(setmetatable(s)) ', a(function() return sm(s,{}) end) )
print( 'a(setmetatable(true))', a(function() local b = true; return sm(b,{}) end) )
print( 'a(setmetatable(t)) ', a(function() return sm(t,{}) end) )
print( 'a(getmetatable(t)) ', a(function() return getmetatable(t),type(getmetatable(t)) end) )
print( 'a(setmetatable(t*)) ', a(function() return sm(t,{__metatable={}}) end) )
print( 'a(getmetatable(t)) ', a(function() return getmetatable(t),type(getmetatable(t)) end) )
print( 'a(setmetatable(t)) ', a(function() return sm(t,{}) end) )
print( 'a(getmetatable(t)) ', a(function() return getmetatable(t),type(getmetatable(t)) end) )
t = {}
print( 'a(setmetatable(t)) ', a(function() return sm(t,{}) end) )
print( 'a(getmetatable(t)) ', a(function() return getmetatable(t),type(getmetatable(t)) end) )
print( 'a(setmetatable(t*)) ', a(function() return sm(t,{__metatable='some string'}) end) )
print( 'a(getmetatable(t)) ', a(function() return getmetatable(t),type(getmetatable(t)) end) )
print( 'a(setmetatable(t)) ', a(function() return sm(t,{}) end) )
print( 'a(getmetatable(t)) ', a(function() return getmetatable(t),type(getmetatable(t)) end) )
print( 'a(setmetatable(t,nil)) ', a(function() return sm(t,nil) end) )
print( 'a(setmetatable(t)) ', a(function() return sm(t) end) )
print( 'a(setmetatable({},"abc")) ', a(function() return sm({},'abc') end) )
-- bad args to error!
print( 'error("msg","arg")', a(function() error('some message', 'some bad arg') end) )
-- loadfile, dofile on missing files
print( 'loadfile("bogus.txt")', a(function() return loadfile("bogus.txt") end) )
print( 'dofile("bogus.txt")', a(function() return dofile("bogus.txt") end) )

74
test/lua/functions.lua Normal file
View File

@@ -0,0 +1,74 @@
function f0() print( "f0:" ) end
function f1(a) print( "f1:", a ) end
function f2(a,b) print( "f2:", a, b ) end
function f3(a,b,c) print( "f3:", a, b, c ) end
function f4(a,b,c,d) print( "f4:", a, b, c, d ) end
f0() f0( "a1/1" ) f0( "a1/2", "a2/2" ) f0( "a1/3", "a2/3", "a3/3" ) f0( "a1/4", "a2/4", "a3/4", "a4/4" )
f1() f1( "a1/1" ) f1( "a1/2", "a2/2" ) f1( "a1/3", "a2/3", "a3/3" ) f1( "a1/4", "a2/4", "a3/4", "a4/4" )
f2() f2( "a1/1" ) f2( "a1/2", "a2/2" ) f2( "a1/3", "a2/3", "a3/3" ) f2( "a1/4", "a2/4", "a3/4", "a4/4" )
f3() f3( "a1/1" ) f3( "a1/2", "a2/2" ) f3( "a1/3", "a2/3", "a3/3" ) f3( "a1/4", "a2/4", "a3/4", "a4/4" )
f4() f4( "a1/1" ) f4( "a1/2", "a2/2" ) f4( "a1/3", "a2/3", "a3/3" ) f4( "a1/4", "a2/4", "a3/4", "a4/4" )
function g0(a,b,c,d) return end
function g1(a,b,c,d) return d end
function g2(a,b,c,d) return c, d end
function g3(a,b,c,d) return b, c, d end
function g4(a,b,c,d) return a, b, c, d end
z = g0("c0.1/4", "c0.2/4", "c0.3/4", "c0.4/4")
print( "z0:", z )
z = g2("c2.1/4", "c2.2/4", "c2.3/4", "c2.4/4")
print( "z2:", z )
z = g4("c4.1/4", "c4.2/4", "c4.3/4", "c4.4/4")
print( "z4:", z )
a,b,c,d = g0( "c0.1/4", "c0.2/4", "c0.3/4", "c0.4/4" )
print( "g0:", a, b, c, d, "(eol)" )
a,b,c,d = g2( "b2.1/4", "b2.2/4", "b2.3/4", "b2.4/4" )
print( "g2:", a, b, c, d, "(eol)" )
a,b,c,d = g4( "b4.1/4", "b4.2/4", "b4.3/4", "b4.4/4" )
print( "g4:", a, b, c, d, "(eol)" )
function func(a,b,c)
return a, b, c
end
print( func(11, 12, 13) )
print( func(23, 22, 21) )
print( func(func(32,33,34), func(45,46,47), func(58,59,50)) )
function p(a,...)
print("a",a)
print("...",...)
print("...,a",...,a)
print("a,...",a,...)
end
p()
p("q")
p("q","r")
p("q","r","s")
-- tail call tests
function first(...)
return 'abc', ..., '|', ...
end
function second(a,...)
return 'def', ..., '|', a, ...
end
function third( a, b, c )
print( 'third', first( a, b, c ) )
print( 'third', second( a, b, c ) )
return second( a, b, c )
end
print( 'third', third() )
print( 'third', third('p') )
print( 'third', third('p','q') )
print( 'third', third('p','q','r') )
print( 'third', third('p','q','r','s') )
print( 'third', third() )

137
test/lua/iolib.lua Normal file
View File

@@ -0,0 +1,137 @@
local platform = ...
print( 'platform', platform )
-- simple io-library tests
--
-- C version on Windows will add change \n into \r\n for text files at least
--
print( io ~= nil )
print( io.open ~= nil )
print( io.stdin ~= nil )
print( io.stdout ~= nil )
print( io.stderr ~= nil )
print( 'write', io.write() )
print( 'write', io.write("This") )
print( 'write', io.write(" is a pen.") )
print( 'flush', io.flush() )
local f = io.open("abc.txt","w")
print( 'f', type(f) )
print( io.type(f) )
print( 'write', f:write("abcdef 12345 \t\t 678910 more\aaaaaaa\bbbbthe rest") )
print( 'type(f)', io.type(f) )
print( 'close', f:close() )
print( 'type(f)', io.type(f) )
print( 'type("f")', io.type("f") )
local g = io.open("abc.txt","r")
local t = { g:read(3, 3, "*n", "*n", "*l", "*l", "*a") }
for i,v in ipairs(t) do
print( string.format("%q",tostring(v)), type(v))
print( '----- ', i )
end
local h,s = io.open("abc.txt", "a")
print( 'h', io.type(h), string.sub(tostring(h),1,6), s )
print( 'write', h:write('and more and more and more text.') )
print( 'close', h:close() )
if platform ~= 'JME' then
local j = io.open( "abc.txt", "r" )
print( 'j', io.type(j) )
print( 'seek', j:seek("set", 3) )
print( 'read', j:read(4), j:read(3) )
print( 'seek', j:seek("set", 2) )
print( 'read', j:read(4), j:read(3) )
print( 'seek', j:seek("cur", -8 ) )
print( 'read', j:read(4), j:read(3) )
print( 'seek(cur,0)', j:seek("cur",0) )
print( 'seek(cur,20)', j:seek("cur",20) )
print( 'seek(end,-5)', j:seek("end", -5) )
print( 'read(4)', string.format("%q", tostring(j:read(4))) )
print( 'read(4)', string.format("%q", tostring(j:read(4))) )
print( 'read(4)', string.format("%q", tostring(j:read(4))) )
print( 'close', j:close() )
end
-- write a few lines, including a non-terminating one
f = io.open("abc.txt","w")
print( 'f', io.type(f) )
print( 'write', f:write("line one\nline two\n\nafter blank line\nunterminated line") )
print( 'type(f)', io.type(f) )
print( 'close', f:close() )
-- read using io.lines()
for l in io.lines("abc.txt") do
print( string.format('%q',l) )
end
io.input("abc.txt")
for l in io.lines() do
print( string.format('%q',l) )
end
io.input(io.open("abc.txt","r"))
for l in io.lines() do
print( string.format('%q',l) )
end
io.input("abc.txt")
io.input(io.input())
for l in io.lines() do
print( string.format('%q',l) )
end
local count = 0
io.tmpfile = function()
count = count + 1
return io.open("tmp"..count..".out","w")
end
local a = io.tmpfile()
local b = io.tmpfile()
print( io.type(a) )
print( io.type(b) )
print( "a:write", a:write('aaaaaaa') )
print( "b:write", b:write('bbbbbbb') )
print( "a:setvbuf", a:setvbuf("no") )
print( "a:setvbuf", a:setvbuf("full",1024) )
print( "a:setvbuf", a:setvbuf("line") )
print( "a:write", a:write('ccccc') )
print( "b:write", b:write('ddddd') )
print( "a:flush", a:flush() )
print( "b:flush", b:flush() )
--[[
print( "a:read", a:read(7) )
print( "b:read", b:read(7) )
print( "a:seek", a:seek("cur",-4) )
print( "b:seek", b:seek("cur",-4) )
print( "a:read", ( a:read(7) ) )
print( "b:read", ( b:read(7) ) )
print( "a:seek", a:seek("cur",-8) )
print( "b:seek", b:seek("cur",-8) )
print( "a:read", ( a:read(7) ) )
print( "b:read", ( b:read(7) ) )
--]]
local pcall = function(...) return ( pcall(...) )end
print( 'a:close', pcall( a.close, a ) )
print( 'a:write', pcall( a.write, a, 'eee') )
print( 'a:flush', pcall( a.flush, a) )
print( 'a:read', pcall( a.read, a, 5) )
print( 'a:lines', pcall( a.lines, a) )
print( 'a:seek', pcall( a.seek, a, "cur", -2) )
print( 'a:setvbuf', pcall( a.setvbuf, a, "no") )
print( 'a:close', pcall( a.close, a ) )
print( 'io.type(a)', pcall( io.type, a ) )
print( 'io.close()', pcall( io.close ) )
print( 'io.close(io.output())', pcall( io.close, io.output() ) )
io.output('abc.txt')
print( 'io.close()', pcall( io.close ) )
print( 'io.write', pcall( io.write, 'eee') )
print( 'io.flush', pcall( io.flush) )
print( 'io.close', pcall( io.close ) )
io.input('abc.txt'):close()
print( 'io.read', pcall( io.read, 5) )
print( 'io.lines', pcall( io.lines) )

223
test/lua/mathlib.lua Normal file
View File

@@ -0,0 +1,223 @@
local platform = ...
print( 'platform', platform )
local aliases = {
['0']='<zero>',
['-0']='<zero>',
['nan']='<nan>',
['inf']='<pos-inf>',
['-inf']='<neg-inf>',
['1.#INF']='<pos-inf>',
['-1.#INF']='<neg-inf>',
['1.#IND']='<nan>',
['-1.#IND']='<nan>',
}
local UNOPVALUES = { -2.5, -2, 0, 2, 2.5, "'-2.5'", "'-2'", "'0'", "'2'", "'2.5'" }
local NUMBERPAIRS = {
{ 2, 0 }, { -2.5, 0 }, { 2, 1 },
{ 5, 2 }, {-5, 2 }, {16, 2}, {-16, -2},
{256, .5}, {256, .25}, {256, 0.625},
{256, -0.5}, {256, -.25}, {256, -.625}, {-256, .5},
{ .5, 0}, {.5, 1}, {.5, 2}, {.5, -1}, {.5, 2},
{2.25, 0}, {2.25, 2}, {2.25, .5}, {2.25, 2.5}, {-2, 0},
{ 3, 3 },
}
local STRINGPAIRS = {
{ "'2'", "'0'" }, { "'2.5'","'3'" }, { "'-2'", "'1.5'" }, { "'-2.5'", "'-1.5'" },
{ "'3.0'", "'3.0'" }, { 2.75, 2.75 }, { "'2.75'", "'2.75'" },
}
local MIXEDPAIRS = {
{ 3, "'3'" }, { "'3'", 3 }, { 2.75, "'2.75'" }, { "'2.75'", 2.75 },
{ -3, "'-4'" }, { "'-3'", 4 }, { -3, "'4'" }, { "'-3'", -4 },
{ -4.75, "'2.75'" }, { "'-2.75'", 1.75 }, { 4.75, "'-2.75'" }, { "'2.75'", -1.75 },
}
local BINOPVALUES = {}
local RELATIONALOPVALUES = {}
local function addall( t, s )
for i,v in ipairs(s) do
t[#t+1] = v
end
end
addall( BINOPVALUES, NUMBERPAIRS )
addall( BINOPVALUES, STRINGPAIRS )
addall( BINOPVALUES, MIXEDPAIRS )
addall( RELATIONALOPVALUES, NUMBERPAIRS )
addall( RELATIONALOPVALUES, STRINGPAIRS )
local VARARGSVALUES = {
{ 4, }, { -4.5 }, { "'5.5'" }, { "'-5'" },
{ 4, "'8'" }, { -4.5, "'-8'" }, { "'5.5'", 2.2 }, { "'-5'", -2.2 },
{ 111,222,333 }, { -222,-333,-111 }, { 444,-111,-222 },
}
local CONSTANTS = {
"huge", "pi",
}
local UNARYOPS = {
"-", "not ",
}
local BINARYOPS = {
"+", "-", "*", "^", "/", "%",
}
local RELATIONALS = {
"==", "~=", ">", "<", ">=", "<=",
}
local ONEARG_JME = {
"abs", "ceil", "cos", "deg",
"exp", "floor", "frexp", "modf",
"rad", "sin", "sqrt", "tan",
}
local ONEARG_JSE = {
"acos", "asin", "atan", "cosh",
"log", "log10", "sinh", "tanh",
}
local TWOARGS_JME = {
"fmod", "ldexp", "pow",
}
local TWOARGS_JSE = {
"atan2",
}
local VARARGSFUNCS = {
"max", "min",
}
local ts = tostring
tostring = function(x)
local s = ts(x)
if type(x)~='number' then return s end
if aliases[s] then return aliases[s] end
if #s < 7 then return s end
local a,b = string.match(s,'([%-0-9%.]*)([eE]?[%-0-9]*)')
return a and (string.sub(a,1,6)..(b or '')) or s
end
local function eval( expr, script )
script = script or ('return '..expr)
local s,a,b = loadstring( script, 'expr' )
if s then print( expr, pcall( s ) )
else print( expr, 'loadstring:', a ) end
end
-- misc tests
print( '---------- miscellaneous tests ----------' )
eval( 'math.sin( 0.0 )' )
eval( 'math.cos( math.pi )' )
eval( 'math.sqrt( 9.0 )' )
eval( 'math.modf( 5.25 )')
eval( 'math.frexp(0.00625)' )
eval( '-5 ^ 2' )
eval( '-5 / 2' )
eval( '-5 % 2' )
-- constants
print( '---------- constants ----------' )
for i,v in ipairs(CONSTANTS) do
eval( 'math.'..v )
end
-- unary operators
for i,v in ipairs(UNARYOPS) do
print( '---------- unary operator '..v..' ----------' )
for j,a in ipairs(UNOPVALUES) do
eval( v..a, 'return '..v..a )
end
end
-- binary operators
for i,v in ipairs(BINARYOPS) do
print( '---------- binary operator '..v..' ----------' )
for j,xy in ipairs(BINOPVALUES) do
eval( xy[1]..v..xy[2],
'local x,y='..xy[1]..','..xy[2]..'; return x'..v..'y' )
end
end
-- relational operators
for i,v in ipairs(RELATIONALS) do
print( '---------- binary operator '..v..' ----------' )
for j,xy in ipairs(RELATIONALOPVALUES) do
eval( xy[1]..v..xy[2],
'local x,y='..xy[1]..','..xy[2]..'; return x'..v..'y' )
end
end
-- one-argument math functions
for i,v in ipairs(ONEARG_JME) do
print( '---------- math.'..v..' ----------' )
for j,x in ipairs(UNOPVALUES) do
eval( 'math.'..v..'('..x..')' )
end
end
if platform ~= 'JME' then
for i,v in ipairs(ONEARG_JSE) do
print( '---------- math.'..v..' (jse only) ----------' )
for j,x in ipairs(UNOPVALUES) do
eval( 'math.'..v..'('..x..')' )
end
end
end
-- two-argument math functions
for i,v in ipairs(TWOARGS_JME) do
print( '---------- math.'..v..' ----------' )
for j,x in ipairs(BINOPVALUES) do
eval( 'math.'..v..'('..x[1]..','..x[2]..')' )
end
end
if platform ~= 'JME' then
for i,v in ipairs(TWOARGS_JSE) do
print( '---------- math.'..v..' (jse only) ----------' )
for j,x in ipairs(BINOPVALUES) do
eval( 'math.'..v..'('..x[1]..','..x[2]..')' )
end
end
end
-- var-arg math functions
for i,v in ipairs(VARARGSFUNCS) do
print( '---------- math.'..v..' ----------' )
for j,x in ipairs(VARARGSVALUES) do
eval( 'math.'..v..'('..table.concat(x,',')..')' )
end
end
-- random tests
print("----------- Random number tests")
local function testrandom(string,lo,hi)
local c,e = loadstring('return '..string)
for i=1,5 do
local s,e = pcall(c)
if s then
print( string, s and type(e) or e, (e>=lo) and (e<=hi) )
else
print( string, 'error', e )
end
end
end
testrandom('math.random()',0,1)
testrandom('math.random(5,10)',5,10)
testrandom('math.random(30)',0,30)
testrandom('math.random(-4,-2)',-4,-2)
local t = {}
print( math.randomseed(20) )
for i=1,20 do
t[i] = math.random()
end
print( '-- comparing new numbers')
for i=1,20 do
print( t[i] == math.random(), t[i] == t[0] )
end
print( '-- resetting seed')
print( math.randomseed(20) )
for i=1,20 do
print( t[i] == math.random() )
end
--]]

40
test/lua/oslib.lua Normal file
View File

@@ -0,0 +1,40 @@
-- simple os-library tests
--
-- because the nature of the "os" library is to provide os-specific behavior,
-- the compatibility tests must be extremely loose, and can really only
-- compare things like return value type to be meaningful.
--
-- actual os behavior needs to go in an oslib function test
--
local pcall = function(...)
local s,e,f = pcall(...)
return s,type(e)
end
print( 'os', type(os) )
print( 'os.clock()', pcall( os.clock ) )
print( 'os.date()', pcall( os.date ) )
print( 'os.difftime(123000, 21500)', pcall( os.difftime, 123000, 21250 ) )
print( 'os.execute("bogus")', pcall( os.execute, '' ) )
print( 'os.getenv()', pcall( os.getenv ) )
print( 'os.getenv("bogus.key")', pcall( os.getenv, 'bogus.key' ) )
local s,p = pcall( os.tmpname )
local s,q = pcall( os.tmpname )
print( 'os.tmpname()', s, p )
print( 'os.tmpname()', s, q )
-- permission denied on windows
--print( 'os.remove(p)', pcall( os.remove, p ) )
--print( 'os.rename(p,q)', pcall( os.rename, p, q ) )
local s,f = pcall( io.open, p,"w" )
print( 'io.open', s, f )
print( 'write', pcall( f.write, f, "abcdef 12345" ) )
print( 'close', pcall( f.close, f ) )
print( 'os.rename(p,q)', pcall( os.rename, p, q ) )
print( 'os.remove(q)', pcall( os.remove, q ) )
print( 'os.remove(q)', pcall( os.remove, q ) )
-- setlocale not supported on jse yet
-- print( 'os.setlocale()', pcall( os.setlocale ) )
-- print( 'os.setlocale("jp")', pcall( os.setlocale, "jp" ) )
-- print( 'os.setlocale("us","monetary")', pcall( os.setlocale, "us", "monetary" ) )
-- print( 'os.setlocale(nil,"all")', pcall( os.setlocale, nil, "all" ) )
print( 'os.setlocale("c")', pcall( os.setlocale, "c" ) )
print( 'os.exit', type(os.exit) )

174
test/lua/stringlib.lua Normal file
View File

@@ -0,0 +1,174 @@
print( string.find("1234567890", ".", 0, true) )
print( string.find( 'alo alx 123 b\0o b\0o', '(..*) %1' ) )
print( string.find( 'aloALO', '%l*' ) )
print( string.find( ' \n isto <20> assim', '%S%S*' ) )
print( string.find( "", "" ) )
print( string.find( "ababaabbaba", "abb" ) )
print( string.find( "ababaabbaba", "abb", 7 ) )
print( string.match( "aabaa", "a*" ) )
print( string.match( "aabaa", "a*", 3 ) )
print( string.match( "aabaa", "a*b" ) )
print( string.match( "aabaa", "a*b", 3 ) )
print( string.match( "abbaaababaabaaabaa", "b(a*)b" ) )
print( string.match( "abbaaababaabaaabaa", "b(a*)()b" ) )
print( string.match( "abbaaababaabaaabaa", "b(a*)()b", 3 ) )
print( string.match( "abbaaababaabaaabaa", "b(a*)()b", 8 ) )
print( string.match( "abbaaababaabaaabaa", "b(a*)()b", 12 ) )
print( string.byte("hi", -3) )
print( string.gsub("ABC", "@(%x+)", function(s) return "|abcd" end) )
print( string.gsub("@123", "@(%x+)", function(s) return "|abcd" end) )
print( string.gsub("ABC@123", "@(%x+)", function(s) return "|abcd" end) )
print( string.gsub("ABC@123@def", "@(%x+)", function(s) return "|abcd" end) )
print( string.gsub("ABC@123@qrs@def@tuv", "@(%x+)", function(s) return "|abcd" end) )
print( string.gsub("ABC@123@qrs@def@tuv", "@(%x+)", function(s) return "@ab" end) )
print( tostring(1234567890123) )
print( tostring(1234567890124) )
print( tostring(1234567890125) )
function f1(s, p)
print(p)
p = string.gsub(p, "%%([0-9])", function (s) return "%" .. (s+1) end)
print(p)
p = string.gsub(p, "^(^?)", "%1()", 1)
print(p)
p = string.gsub(p, "($?)$", "()%1", 1)
print(p)
local t = {string.match(s, p)}
return string.sub(s, t[1], t[#t] - 1)
end
print( pcall( f1, 'alo alx 123 b\0o b\0o', '(..*) %1' ) )
local function badpat()
print( string.gsub( "alo", "(.)", "%2" ) )
end
print( ( pcall( badpat ) ) )
for k, v in string.gmatch("w=200&h=150", "(%w+)=(%w+)") do
print(k, v)
end
-- string.sub
function t(str)
local i = { 0, 1, 2, 8, -1 }
for ki,vi in ipairs(i) do
local s,v = pcall( string.sub, str, vi )
print( 'string.sub("'..str..'",'..tostring(vi)..')='..tostring(s)..',"'..tostring(v)..'"' )
local j = { 0, 1, 2, 4, 8, -1 }
for kj,vj in ipairs(j) do
local s,v = pcall( string.sub, str, vi, vj )
print( 'string.sub("'..str..'",'..tostring(vi)..','..tostring(vj)..')='..tostring(s)..',"'..tostring(v)..'"' )
end
end
end
t( 'abcdefghijklmn' )
t( 'abcdefg' )
t( 'abcd' )
t( 'abc' )
t( 'ab' )
t( 'a' )
t( '' )
print(string.len("Hello, world"))
print(#"Hello, world")
print(string.len("\0\0\0"))
print(#"\0\0\0")
print(string.len("\0\1\2\3"))
print(#"\0\1\2\3")
local s = "My JaCk-O-lAnTeRn CaSe TeXt"
print(s, string.len(s), #s)
-- string.format
print(string.format("(%.0d) (%.0d) (%.0d)", 0, -5, 9))
print(string.format("(%.1d) (%.1d) (%.1d)", 0, -5, 9))
print(string.format("(%.2d) (%.2d) (%.2d)", 0, -5, 9))
print(string.format("(%+.0d) (%+.0d) (%+.0d)", 0, -5, 9))
print(string.format("(%+.1d) (%+.1d) (%+.1d)", 0, -5, 9))
print(string.format("(%+.2d) (%+.2d) (%+.2d)", 0, -5, 9))
print(string.format("(%+3d) (% 3d) (%+ 3d)", 55, 55, 55))
print(string.format("(%-1d) (%-1d) (%-1d)", 1, 12, -12))
print(string.format("(%-2d) (%-2d) (%-2d)", 1, 12, -12))
print(string.format("(%-3d) (%-3d) (%-3d)", 1, 12, -12))
print(string.format("(%8x) (%8d) (%8o)", 255, 255, 255))
print(string.format("(%08x) (%08d) (%08o)", 255, 255, 255))
print(string.format("simple%ssimple", " simple "))
print(string.format("%%"))
specials = "\"specials\": %% \000 \r \n"
print(string.format("specials (%%s): ----->%s<----", specials) )
print(string.format("specials (%%q): ----->%q<----", specials) )
print(string.format("controls (%%q): ----->%q<----", ' \a \b \f \t \v \\ ') )
print(string.format("extended (%%q): ----->%q<----", ' \222 \223 \224 ') )
print(string.format("embedded newlines: %s\n%s\n%s", '======>', '<======>', '<======='))
print(string.format("this is a %s long string", string.rep("really, ", 30)))
local function pc(...)
local s,e = pcall(...)
return s and e or 'false-'..type(e)
end
local function strtests(name,func,...)
print(name, 'good', pc( func, ... ) )
print(name, 'empty', pc( func ) )
print(name, 'table', pc( func, {} ) )
print(name, 'nil', pc( func, nil ) )
end
strtests('lower', string.lower, s )
strtests('upper', string.upper, s )
strtests('reverse', string.reverse, s )
strtests('char', string.char, 92, 60, 61, 93 )
strtests('dump', string.dump, loadstring('print("hello, world")', 'sample') )
-- floating point formats (not supported yet)
--[==[
local prefixes = {'','+','-'}
local lengths = {'7','2','0','1',''}
local letters = {'f','e','g'}
local fmt, spec, desc
for i,letter in ipairs(letters) do
for k,before in ipairs(lengths) do
for j,prefix in ipairs(prefixes) do
spec = '(%'..prefix..before..letter..')'
fmt = spec..'\t'..spec..'\t'..spec..'\t'..spec..'\t'..spec..'\t'..spec
print(spec, string.format(fmt, 12.34, -12.34, 1/11, -1/11, 300/11, -300/11) )
for l,after in ipairs(lengths) do
spec = '(%'..prefix..before..'.'..after..letter..')'
fmt = spec..' '..spec..' '..spec..' '..spec..' '..spec..' '..spec
print(spec, string.format(fmt, 12.34, -12.34, 1/11, -1/11, 300/11, -300/11) )
end
end
end
end
--]==]
local function fmterr(...)
local r, s = pcall(...)
if r then
return s
else
print( 'initial error -->'..tostring(s) )
s = string.gsub(s, "stdin:%d+:%s*", "")
return s
end
end
print(fmterr(string.find, "ab%c)0(", "%"))
print(fmterr(string.find, "ab%c)0(", "("))
print(pcall(string.find, "ab%c)0(", ")"))

274
test/lua/tablelib.lua Normal file
View File

@@ -0,0 +1,274 @@
local func = function(t,...)
return (...)
end
local tbl = setmetatable({},{__index=func})
print( tbl[2] )
-- tostring replacement that assigns ids
local ts,id,nid,types = tostring,{},0,{table='tbl',thread='thr',userdata='uda',['function']='func'}
tostring = function(x)
if not x or not types[type(x)] then return ts(x) end
if not id[x] then nid=nid+1; id[x]=types[type(x)]..'.'..nid end
return id[x]
end
local t = { "one", "two", "three", a='aaa', b='bbb', c='ccc' }
table.insert(t,'six');
table.insert(t,1,'seven');
table.insert(t,4,'eight');
table.insert(t,7,'nine');
table.insert(t,10,'ten'); print( #t )
-- concat
print( '-- concat tests' )
function tryconcat(t)
print( table.concat(t) )
print( table.concat(t,'--') )
print( table.concat(t,',',2) )
print( table.concat(t,',',2,2) )
print( table.concat(t,',',5,2) )
end
tryconcat( { "one", "two", "three", a='aaa', b='bbb', c='ccc' } )
tryconcat( { "one", "two", "three", "four", "five" } )
function tryconcat(t)
print( table.concat(t) )
print( table.concat(t,'--') )
print( table.concat(t,',',2) )
end
tryconcat( { a='aaa', b='bbb', c='ccc', d='ddd', e='eee' } )
tryconcat( { [501]="one", [502]="two", [503]="three", [504]="four", [505]="five" } )
tryconcat( {} )
-- print the elements of a table in a platform-independent way
function eles(t,f)
f = f or pairs
all = {}
for k,v in f(t) do
table.insert( all, "["..tostring(k).."]="..tostring(v) )
end
table.sort( all )
return "{"..table.concat(all,',').."}"
end
-- insert, maxn
print( '-- insert, len tests' )
local t = { "one", "two", "three", a='aaa', b='bbb', c='ccc' }
print( eles(t), #t )
table.insert(t,'six'); print( eles(t), #t )
table.insert(t,1,'seven'); print( eles(t), #t )
table.insert(t,4,'eight'); print( eles(t), #t )
table.insert(t,7,'nine'); print( eles(t), #t )
table.insert(t,10,'ten'); print( eles(t), #t )
print( '#{}', #{} )
print( '#{"a"}', #{"a"} )
print( '#{"a","b"}', #{"a","b"} )
print( '#{"a",nil}', #{"a",nil} )
print( '#{nil,nil}', #{nil,nil} )
print( '#{nil,"b"}', #{nil,"b"}==0 or #{nil,"b"}==2 )
print( '#{"a","b","c"}', #{"a","b","c"} )
print( '#{"a","b",nil}', #{"a","b",nil} )
print( '#{"a",nil,nil}', #{"a",nil,nil} )
print( '#{nil,nil,nil}', #{nil,nil,nil} )
print( '#{nil,nil,"c"}', #{nil,nil,"c"}==0 or #{nil,nil,"c"}==3 )
print( '#{nil,"b","c"}', #{nil,"b","c"}==0 or #{nil,"b","c"}==3 )
print( '#{nil,"b",nil}', #{nil,"b",nil}==0 or #{nil,"b",nil}==2 )
print( '#{"a",nil,"c"}', #{"a",nil,"c"}==1 or #{"a",nil,"c"}==3 )
-- remove
print( '-- remove tests' )
t = { "one", "two", "three", "four", "five", "six", "seven", [10]="ten", a='aaa', b='bbb', c='ccc' }
print( eles(t), #t )
print( 'table.remove(t)', table.remove(t) ); print( eles(t), #t )
print( 'table.remove(t,1)', table.remove(t,1) ); print( eles(t), #t )
print( 'table.remove(t,3)', table.remove(t,3) ); print( eles(t), #t )
print( 'table.remove(t,5)', table.remove(t,5) ); print( eles(t), #t )
print( 'table.remove(t,10)', table.remove(t,10) ); print( eles(t), #t )
print( 'table.remove(t,-1)', table.remove(t,-1) ); print( eles(t), #t )
print( 'table.remove(t,-1)', table.remove(t,-1) ) ; print( eles(t), #t )
-- sort
print( '-- sort tests' )
function sorttest(t,f)
t = (t)
print( table.concat(t,'-') )
if f then
table.sort(t,f)
else
table.sort(t)
end
print( table.concat(t,'-') )
end
sorttest{ "one", "two", "three" }
sorttest{ "www", "vvv", "uuu", "ttt", "sss", "zzz", "yyy", "xxx" }
sorttest( { "www", "vvv", "uuu", "ttt", "sss", "zzz", "yyy", "xxx" }, function(a,b) return b<a end)
-- getn
t0 = {}
t1 = { 'one', 'two', 'three' }
t2 = { a1='aa', a2='bb', a3='cc' }
t3 = { 'one', 'two', 'three', a1='aa', a2='bb', a3='cc' }
print( 'getn('..eles(t0)..')', pcall( table.getn, t0 ) )
print( 'getn('..eles(t1)..')', pcall( table.getn, t1 ) )
print( 'getn('..eles(t2)..')', pcall( table.getn, t2 ) )
print( 'getn('..eles(t3)..')', pcall( table.getn, t3 ) )
-- foreach
function test( f, t, result, name )
status, value = pcall( f, t, function(...)
print(' -- ',...)
print(' next',next(t,(...)))
return result
end )
print( name, 's,v', status, value )
end
function testall( f, t, name )
test( f, t, nil, name..'nil' )
test( f, t, false, name..'fls' )
test( f, t, 100, name..'100' )
end
testall( table.foreach, t0, 'table.foreach('..eles(t0)..')' )
testall( table.foreach, t1, 'table.foreach('..eles(t1)..')' )
testall( table.foreach, t2, 'table.foreach('..eles(t2)..')' )
testall( table.foreach, t3, 'table.foreach('..eles(t3)..')' )
testall( table.foreachi, t0, 'table.foreachi('..eles(t0)..')' )
testall( table.foreachi, t1, 'table.foreachi('..eles(t1)..')' )
testall( table.foreachi, t2, 'table.foreachi('..eles(t2)..')' )
testall( table.foreachi, t3, 'table.foreachi('..eles(t3)..')' )
-- pairs, ipairs
--[[
function testpairs(f, t, name)
print( name )
for a,b in f(t) do
print( ' ', a, b )
end
end
function testbothpairs(t)
testpairs( pairs, t, 'pairs( '..eles(t)..' )' )
testpairs( ipairs, t, 'ipairs( '..eles(t)..' )' )
end
for i,t in ipairs({t0,t1,t2,t3}) do
testbothpairs(t)
end
t = { 'one', 'two', 'three', 'four', 'five' }
testbothpairs(t)
t[6] = 'six'
testbothpairs(t)
t[4] = nil
testbothpairs(t)
--]]
-- tests of setlist table constructors
-- length and unpack are tested elsewhere
print('----- unpack tests -------')
local function a(...) return ... end
print('unpack -',unpack({}))
print('unpack a',unpack({'a'}))
print('unpack .',unpack({nil},1,1))
print('unpack ab',unpack({'a', 'b'}))
print('unpack .b',unpack({nil, 'b'},1,2))
print('unpack a.',unpack({'a', nil},1,2))
print('unpack abc',unpack({'a', 'b', 'c'}))
print('unpack .ab',unpack({nil, 'a', 'b'},1,3))
print('unpack a.b',unpack({'a', nil, 'b'},1,3))
print('unpack ab.',unpack({'a', 'b', nil},1,3))
print('unpack ..b',unpack({nil, nil, 'b'},1,3))
print('unpack a..',unpack({'a', nil, nil},1,3))
print('unpack .b.',unpack({nil, 'b', nil},1,3))
print('unpack ...',unpack({nil, nil, nil},1,3))
print('unpack (-)',unpack({a()}))
print('unpack (a)',unpack({a('a')}))
print('unpack (.)',unpack({a(nil)},1,1))
print('unpack (ab)',unpack({a('a', 'b')}))
print('unpack (.b)',unpack({a(nil, 'b')},1,2))
print('unpack (a.)',unpack({a('a', nil)},1,2))
print('unpack (abc)',unpack({a('a', 'b', 'c')}))
print('unpack (.ab)',unpack({a(nil, 'a', 'b')},1,3))
print('unpack (a.b)',unpack({a('a', nil, 'b')},1,3))
print('unpack (ab.)',unpack({a('a', 'b', nil)},1,3))
print('unpack (..b)',unpack({a(nil, nil, 'b')},1,3))
print('unpack (a..)',unpack({a('a', nil, nil)},1,3))
print('unpack (.b.)',unpack({a(nil, 'b', nil)},1,3))
print('unpack (...)',unpack({a(nil, nil, nil)},1,3))
-- misc tests
print('----- misc table initializer tests -------')
print( # { 'abc', 'def', 'ghi', nil } ) -- should be 3 !
print( # { 'abc', 'def', 'ghi', false } ) -- should be 4 !
print( # { 'abc', 'def', 'ghi', 0 } ) -- should be 4 !
-- basic table operation tests
print('----- basic table operations -------')
local dummyfunc = function(t,...)
print( 'metatable call args', type(t), ...)
return 'dummy'
end
local makeloud = function(t)
return setmetatable(t,{
__index=function(t,k)
print( '__index', type(t), k )
return rawset(t,k)
end,
__newindex=function(t,k,v)
print( '__newindex', type(t), k, v )
rawset(t,k,v)
end})
end
local tests = {
{'basic table', {}},
{'function metatable on __index', setmetatable({},{__index=dummyfunc})},
{'function metatable on __newindex', setmetatable({},{__newindex=dummyfunc})},
{'plain metatable on __index', setmetatable({},makeloud({}))},
{'plain metatable on __newindex', setmetatable({},makeloud({}))},
}
local function shoulderr(s,e)
return s,type(e)
end
for i,test in ipairs(tests) do
local testname = test[1]
local testtable = test[2]
print( '------ basic table tests on '..testname..' '..type(testtable) )
print( 't[1]=2', pcall( function() testtable[1]=2 end ) )
print( 't[1]', pcall( function() return testtable[1] end ) )
print( 't[1]=nil', pcall( function() testtable[1]=nil end ) )
print( 't[1]', pcall( function() return testtable[1] end ) )
print( 't["a"]="b"', pcall( function() testtable["a"]="b" end ) )
print( 't["a"],t.a', pcall( function() return testtable["a"],testtable.a end ) )
print( 't.a="c"', pcall( function() testtable.a="c" end ) )
print( 't["a"],t.a', pcall( function() return testtable["a"],testtable.a end ) )
print( 't.a=nil', pcall( function() testtable.a=nil end ) )
print( 't["a"],t.a', pcall( function() return testtable["a"],testtable.a end ) )
print( 't[nil]="d"', shoulderr( pcall( function() testtable[nil]="d" end ) ) )
print( 't[nil]', pcall( function() return testtable[nil] end ) )
print( 't[nil]=nil', shoulderr( pcall( function() testtable[nil]=nil end ) ) )
print( 't[nil]', pcall( function() return testtable[nil] end ) )
end
print( '-- sort tests' )
local function tryall(cmp)
local function try(t)
print( table.concat(t,'-') )
if pcall( table.sort, t, cmp ) then
print( table.concat(t,'-') )
else
print( 'sort failed' )
end
end
try{ 2, 4, 6, 8, 1, 3, 5, 7 }
try{ 333, 222, 111 }
try{ "www", "xxx", "yyy", "aaa", "bbb", "ccc" }
try{ 21, 23, "25", 27, 22, "24", 26, 28 }
end
local function comparator(a,b)
return tonumber(a)<tonumber(b)
end
print ( 'default (lexical) comparator' )
tryall()
print ( 'custom (numerical) comparator' )
tryall(comparator)

100
test/lua/tailcalls.lua Normal file
View File

@@ -0,0 +1,100 @@
-- tostring replacement that assigns ids
local ts,id,nid,types = tostring,{},0,{table='tbl',thread='thr',userdata='uda',['function']='func'}
tostring = function(x)
if not x or not types[type(x)] then return ts(x) end
if not id[x] then nid=nid+1; id[x]=types[type(x)]..'.'..nid end
return id[x]
end
function a()
return pcall( function() end )
end
function b()
return pcall( function() print 'b' end )
end
function c()
return pcall( function() return 'c' end )
end
print( pcall( a ) )
print( pcall( b ) )
print( pcall( c ) )
local function sum(...)
local s = 0
for i,v in ipairs({...}) do
s = s + v
end
return s
end
local function f1(n,a,b,c)
local a = a or 0
local b = b or 0
local c = c or 0
if n <= 0 then
return a,a+b,a+b+c
end
return f1(n-1,a,a+b,a+b+c)
end
local function f2(n,...)
if n <= 0 then
print( " --f2, n<=0, returning sum(...)", ... )
return sum(...)
end
print( " --f2, n>0, returning f2(n-1,n,...)", n-1,n,... )
return f2(n-1,n,...)
end
local function f3(n,...)
if n <= 0 then
return sum(...)
end
print( " f3,n-1,n,...", f3,n-1,n,... )
return pcall(f3,n-1,n,...)
end
local function all(f)
for n=0,3 do
t = {}
for m=1,5 do
print( "--f, n, unpack(t)", f, n, unpack(t) )
print( pcall( f, n, unpack(t)) )
t[m] = m
end
end
end
all(f1)
all(f2)
all(f3)
local function f(x)
-- tailcall to a builtin
return math.abs(x)
end
local function factorial(i)
local function helper(product, n)
if n <= 0 then
return product
else
-- tail call to a nested Lua function
return helper(n * product, n - 1)
end
end
return helper(1, i)
end
local result1 = factorial(5)
print(result1)
print(factorial(5))
local result2 = f(-1234)
print( result2 )

97
test/lua/upvalues.lua Normal file
View File

@@ -0,0 +1,97 @@
print( '-------- simple upvalues tests --------' )
local function simpleupvalues()
function test()
local x = 5
function f()
x = x + 1
return x
end
function g()
x = x - 1
return x
end
print(f())
print(g())
return f, g
end
f1, g1 = test()
print("f1()=", f1())
print("g1()=", g1())
f2, g2 = test()
print("f2()=", f2())
print("g2()=", g2())
print("g1()=", g1())
print("f1()=", f1())
end
print( 'simplevalues result:', pcall( simpleupvalues ) )
-- The point of this test is that when an upvalue is created, it may
-- need to be inserted in the middle of the list, rather than always
-- appended at the end. Otherwise, it may not be found when it is
-- needed by another closure.
print( '----------- upvalued in middle ------------' )
local function middleupvaluestest()
local function test()
local x = 3
local y = 5
local z = 7
local function f()
print("y=", y)
end
local function g()
print("z=", z)
end
local function h()
print("x=", x)
end
local function setter(x1, y1, z1)
x = x1
y = y1
z = z1
end
return f, g, h, setter
end
local f, g, h, setter = test()
h()
f()
g()
setter("x", "y", "z")
h()
f()
g()
end
print( pcall( middleupvaluestest ) )
print( '--------- nested upvalues ----------' )
local function nestedupvaluestest()
local f
do
local x = 10
function g()
print(x, f())
end
end
function f()
return 20
end
g()
end
print( 'nestedupvaluestest result:', pcall( nestedupvaluestest ) )

250
test/lua/vm.lua Normal file
View File

@@ -0,0 +1,250 @@
print( '-------- basic vm tests --------' )
print( '-- boolean tests' )
local function booleantests()
t = true
f = false
n = nil
s = "Hello"
z = 0
one = 1
print(t)
print(f)
print(not t)
print(not f)
print(not n)
print(not z)
print(not s)
print(not(not(t)))
print(not(not(z)))
print(not(not(n)))
print(t and f)
print(t or f)
print(f and t)
print(f or t)
print(f or one)
print(f or z)
print(f or n)
print(t and one)
print(t and z)
print(t and n)
end
print( 'booleantests result:', pcall( booleantests ) )
print( '------------- varargs' )
local function varargstest()
function p(a,...)
print("a",a)
print("...",...)
print("...,a",...,a)
print("a,...",a,...)
end
function q(a,...)
print("a,arg[1],arg[2],arg[3]",a,arg.n,arg[1],arg[2],arg[3])
end
function r(a,...)
print("a,arg",a,arg)
print("a",a)
print("...",...)
print("...,a",...,a)
print("a,...",a,...)
end
function s(a)
local arg = { '1', '2', '3' }
print("a,arg[1],arg[2],arg[3]",a,arg[1],arg[2],arg[3])
print("a",a)
end
function t(a,...)
local arg = { '1', '2', '3' }
print("a,arg[1],arg[2],arg[3]",a,arg[1],arg[2],arg[3])
print("a",a)
print("...",...)
print("...,a",...,a)
print("a,...",a,...)
end
function u(arg)
print( 'arg', arg )
end
function v(arg,...)
print( 'arg', arg )
print("...",...)
print("arg,...",arg,...)
end
arg = { "global-1", "global-2", "global-3" }
function tryall(f,name)
print( '---- function '..name..'()' )
print( '--'..name..'():' )
print( ' ->', pcall( f ) )
print( '--'..name..'("q"):' )
print( ' ->', pcall( f, "q" ) )
print( '--'..name..'("q","r"):' )
print( ' ->', pcall( f, "q", "r" ) )
print( '--'..name..'("q","r","s"):' )
print( ' ->', pcall( f, "q", "r", "s" ) )
end
tryall(p,'p')
tryall(q,'q')
tryall(r,'r')
tryall(s,'s')
tryall(t,'t')
tryall(u,'u')
tryall(v,'v')
end
print( 'varargstest result:', pcall( varargstest ) )
-- The purpose of this test case is to demonstrate that
-- basic metatable operations on non-table types work.
-- i.e. that s.sub(s,...) could be used in place of string.sub(s,...)
print( '---------- metatable tests' )
local function metatabletests()
-- tostring replacement that assigns ids
local ts,id,nid,types = tostring,{},0,{table='tbl',thread='thr',userdata='uda',['function']='func'}
tostring = function(x)
if not x or not types[type(x)] then return ts(x) end
if not id[x] then nid=nid+1; id[x]=types[type(x)]..'.'..nid end
return id[x]
end
local results = function(s,e,...)
if s then return e,... end
return false,type(e)
end
local pcall = function(...)
return results( pcall(...) )
end
local s = "hello"
print(s:sub(2,4))
local t = {}
function op(name,...)
local a,b = pcall( setmetatable, t, ... )
print( name, t, getmetatable(t), a, b )
end
op('set{} ',{})
op('set-nil',nil)
op('set{} ',{})
op('set')
op('set{} ',{})
op('set{} ',{})
op('set{}{}',{},{})
op('set-nil',nil)
op('set{__}',{__metatable={}})
op('set{} ',{})
op('set-nil',nil)
t = {}
op('set{} ',{})
op('set-nil',nil)
op('set{__}',{__metatable='abc'})
op('set{} ',{})
op('set-nil',nil)
local i = 1234
local t = setmetatable( {}, {
__mode="v",
__index=function(t,k)
local v = i
i = i + 1
rawset(t,k,v)
return v
end,
} )
local l = { 'a', 'b', 'a', 'b', 'c', 'a', 'b', 'c', 'd' }
for i,key in ipairs(l) do
print( 't.'..key, t[key] )
end
end
print( 'metatabletests result:', pcall( metatabletests ) )
-- test tables with more than 50 elements
print( '------------ huge tables' )
local function hugetables()
local t = { 1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,
}
print ("#t=",#t,'t[1,50,51,59]', t[1], t[50], t[51], t[59])
print (table.concat(t,','))
local t2= { 0,3,4,7,9,8,12,15,23,5,
10,13,14,17,19,18,112,115,123,15,
20,33,24,27,29,28,212,215,223,25,
40,43,44,47,49,48,412,415,423,45,
50,53,54,57,59,58,512,515,523,55,
60,63,64,67,69,68,612,615,623,65,
70,73,74,77,79,78,72,715,723,75,
}
print ("#t2=",#t2,'t[1,50,51,59]', t[1], t[50], t[51], t[59])
print (table.concat(t2,','))
local t = {
[2000]='a', [2001]='b', [2002]='c', [2003]='d', [2004]='e', [2005]='f', [2006]='g', [2007]='h', [2008]='i', [2009]='j',
[3000]='a', [3001]='b', [3002]='c', [3003]='d', [3004]='e', [3005]='f', [3006]='g', [3007]='h', [3008]='i', [3009]='j',
[4000]='a', [4001]='b', [4002]='c', [4003]='d', [4004]='e', [4005]='f', [4006]='g', [4007]='h', [4008]='i', [4009]='j',
[5000]='a', [5001]='b', [5002]='c', [5003]='d', [5004]='e', [5005]='f', [5006]='g', [5007]='h', [5008]='i', [5009]='j',
[6000]='a', [6001]='b', [6002]='c', [6003]='d', [6004]='e', [6005]='f', [6006]='g', [6007]='h', [6008]='i', [6009]='j',
[7000]='a', [7001]='b', [7002]='c', [7003]='d', [7004]='e', [7005]='f', [7006]='g', [7007]='h', [7008]='i', [7009]='j',
[8000]='a', [8001]='b', [8002]='c', [8003]='d', [8004]='e', [8005]='f', [8006]='g', [8007]='h', [8008]='i', [8009]='j',
}
for i=2000,8000,1000 do
for j=0,9,1 do
print( 't['..tostring(i+j)..']', t[i+j] )
end
end
end
print( 'hugetables result:', pcall( hugetables ) )
print( '--------- many locals' )
local function manylocals()
-- test program with more than 50 non-sequential integer elements
local t0000='a'; local t0001='b'; local t0002='c'; local t0003='d'; local t0004='e'; local t0005='f'; local t0006='g'; local t0007='h'; local t0008='i'; local t0009='j';
local t1000='a'; local t1001='b'; local t1002='c'; local t1003='d'; local t1004='e'; local t1005='f'; local t1006='g'; local t1007='h'; local t1008='i'; local t1009='j';
local t2000='a'; local t2001='b'; local t2002='c'; local t2003='d'; local t2004='e'; local t2005='f'; local t2006='g'; local t2007='h'; local t2008='i'; local t2009='j';
local t3000='a'; local t3001='b'; local t3002='c'; local t3003='d'; local t3004='e'; local t3005='f'; local t3006='g'; local t3007='h'; local t3008='i'; local t3009='j';
local t4000='a'; local t4001='b'; local t4002='c'; local t4003='d'; local t4004='e'; local t4005='f'; local t4006='g'; local t4007='h'; local t4008='i'; local t4009='j';
local t5000='a'; local t5001='b'; local t5002='c'; local t5003='d'; local t5004='e'; local t5005='f'; local t5006='g'; local t5007='h'; local t5008='i'; local t5009='j';
local t6000='a'; local t6001='b'; local t6002='c'; local t6003='d'; local t6004='e'; local t6005='f'; local t6006='g'; local t6007='h'; local t6008='i'; local t6009='j';
local t7000='a'; local t7001='b'; local t7002='c'; local t7003='d'; local t7004='e'; local t7005='f'; local t7006='g'; local t7007='h'; local t7008='i'; local t7009='j';
local t8000='a'; local t8001='b'; local t8002='c'; local t8003='d'; local t8004='e'; local t8005='f'; local t8006='g'; local t8007='h'; local t8008='i'; local t8009='j';
local t9000='a'; local t9001='b'; local t9002='c'; local t9003='d'; local t9004='e'; local t9005='f'; local t9006='g'; local t9007='h'; local t9008='i'; local t9009='j';
local t10000='a'; local t10001='b'; local t10002='c'; local t10003='d'; local t10004='e'; local t10005='f'; local t10006='g'; local t10007='h'; local t10008='i'; local t10009='j';
local t11000='a'; local t11001='b'; local t11002='c'; local t11003='d'; local t11004='e'; local t11005='f'; local t11006='g'; local t11007='h'; local t11008='i'; local t11009='j';
local t12000='a'; local t12001='b'; local t12002='c'; local t12003='d'; local t12004='e'; local t12005='f'; local t12006='g'; local t12007='h'; local t12008='i'; local t12009='j';
local t13000='a'; local t13001='b'; local t13002='c'; local t13003='d'; local t13004='e'; local t13005='f'; local t13006='g'; local t13007='h'; local t13008='i'; local t13009='j';
-- print the variables
print(t0000,'a'); print(t0001,'b'); print(t0002,'c'); print(t0003,'d'); print(t0004,'e'); print(t0005,'f'); print(t0006,'g'); print(t0007,'h'); print(t0008,'i'); print(t0009,'j');
print(t1000,'a'); print(t1001,'b'); print(t1002,'c'); print(t1003,'d'); print(t1004,'e'); print(t1005,'f'); print(t1006,'g'); print(t1007,'h'); print(t1008,'i'); print(t1009,'j');
print(t2000,'a'); print(t2001,'b'); print(t2002,'c'); print(t2003,'d'); print(t2004,'e'); print(t2005,'f'); print(t2006,'g'); print(t2007,'h'); print(t2008,'i'); print(t2009,'j');
print(t3000,'a'); print(t3001,'b'); print(t3002,'c'); print(t3003,'d'); print(t3004,'e'); print(t3005,'f'); print(t3006,'g'); print(t3007,'h'); print(t3008,'i'); print(t3009,'j');
print(t4000,'a'); print(t4001,'b'); print(t4002,'c'); print(t4003,'d'); print(t4004,'e'); print(t4005,'f'); print(t4006,'g'); print(t4007,'h'); print(t4008,'i'); print(t4009,'j');
print(t5000,'a'); print(t5001,'b'); print(t5002,'c'); print(t5003,'d'); print(t5004,'e'); print(t5005,'f'); print(t5006,'g'); print(t5007,'h'); print(t5008,'i'); print(t5009,'j');
print(t6000,'a'); print(t6001,'b'); print(t6002,'c'); print(t6003,'d'); print(t6004,'e'); print(t6005,'f'); print(t6006,'g'); print(t6007,'h'); print(t6008,'i'); print(t6009,'j');
print(t7000,'a'); print(t7001,'b'); print(t7002,'c'); print(t7003,'d'); print(t7004,'e'); print(t7005,'f'); print(t7006,'g'); print(t7007,'h'); print(t7008,'i'); print(t7009,'j');
print(t8000,'a'); print(t8001,'b'); print(t8002,'c'); print(t8003,'d'); print(t8004,'e'); print(t8005,'f'); print(t8006,'g'); print(t8007,'h'); print(t8008,'i'); print(t8009,'j');
print(t9000,'a'); print(t9001,'b'); print(t9002,'c'); print(t9003,'d'); print(t9004,'e'); print(t9005,'f'); print(t9006,'g'); print(t9007,'h'); print(t9008,'i'); print(t9009,'j');
print(t10000,'a'); print(t10001,'b'); print(t10002,'c'); print(t10003,'d'); print(t10004,'e'); print(t10005,'f'); print(t10006,'g'); print(t10007,'h'); print(t10008,'i'); print(t10009,'j');
print(t11000,'a'); print(t11001,'b'); print(t11002,'c'); print(t11003,'d'); print(t11004,'e'); print(t11005,'f'); print(t11006,'g'); print(t11007,'h'); print(t11008,'i'); print(t11009,'j');
print(t12000,'a'); print(t12001,'b'); print(t12002,'c'); print(t12003,'d'); print(t12004,'e'); print(t12005,'f'); print(t12006,'g'); print(t12007,'h'); print(t12008,'i'); print(t12009,'j');
print(t13000,'a'); print(t13001,'b'); print(t13002,'c'); print(t13003,'d'); print(t13004,'e'); print(t13005,'f'); print(t13006,'g'); print(t13007,'h'); print(t13008,'i'); print(t13009,'j');
end
print( 'manylocals result:', pcall( manylocals ) )