From 0d18988a9693bcafd8d954cf2b6613670d9b05d7 Mon Sep 17 00:00:00 2001 From: James Roseborough Date: Sat, 3 Apr 2010 15:14:30 +0000 Subject: [PATCH] Add test for luajava, compiler, and compatibility witn luavm 1.0 --- .classpath | 1 + bin/LuaJit0.class | Bin 1140 -> 0 bytes src/core/org/luaj/vm2/Print.java | 4 +- src/test/compile/repack.sh | 20 -- src/test/compile/unpack.sh | 12 -- .../java/org/luaj/vm/CompatibiltyTest.java | 198 ------------------ .../java/org/luaj/vm/LuaJavaCoercionTest.java | 187 ----------------- test/junit/org/luaj/vm2/AllTests.java | 2 + .../luaj/vm2}/compiler/AbstractUnitTests.java | 37 ++-- .../luaj/vm2}/compiler/CompilerUnitTests.java | 4 +- .../vm2}/compiler/DumpLoadEndianIntTest.java | 38 ++-- .../luaj/vm2}/compiler/RegressionTests.java | 4 +- .../org/luaj/vm2}/compiler/SimpleTests.java | 42 ++-- .../org/luaj/vm2/compiler}/lua5.1-tests.zip | Bin .../org/luaj/vm2/compiler}/regressions.zip | Bin .../vm2/vm1/Luajvm1CompatibilityTest.java | 167 +++++++++++++++ test/junit/org/luaj/vm2/vm1/luajvm1-tests.zip | Bin 0 -> 31828 bytes 17 files changed, 237 insertions(+), 479 deletions(-) delete mode 100644 bin/LuaJit0.class delete mode 100644 src/test/compile/repack.sh delete mode 100644 src/test/compile/unpack.sh delete mode 100644 src/test/java/org/luaj/vm/CompatibiltyTest.java delete mode 100644 src/test/java/org/luaj/vm/LuaJavaCoercionTest.java rename {src/test/java/org/luaj => test/junit/org/luaj/vm2}/compiler/AbstractUnitTests.java (72%) rename {src/test/java/org/luaj => test/junit/org/luaj/vm2}/compiler/CompilerUnitTests.java (93%) rename {src/test/java/org/luaj => test/junit/org/luaj/vm2}/compiler/DumpLoadEndianIntTest.java (89%) rename {src/test/java/org/luaj => test/junit/org/luaj/vm2}/compiler/RegressionTests.java (93%) rename {src/test/java/org/luaj => test/junit/org/luaj/vm2}/compiler/SimpleTests.java (71%) rename {src/test/compile => test/junit/org/luaj/vm2/compiler}/lua5.1-tests.zip (100%) rename {src/test/compile => test/junit/org/luaj/vm2/compiler}/regressions.zip (100%) create mode 100644 test/junit/org/luaj/vm2/vm1/Luajvm1CompatibilityTest.java create mode 100644 test/junit/org/luaj/vm2/vm1/luajvm1-tests.zip diff --git a/.classpath b/.classpath index 4430e29d..15cb3fb9 100644 --- a/.classpath +++ b/.classpath @@ -14,5 +14,6 @@ + diff --git a/bin/LuaJit0.class b/bin/LuaJit0.class deleted file mode 100644 index dd42a9934813211366155f238f9c38067a4306d8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1140 zcmZ`(YflqV5IwiM+qLa2lt)1XM4)J2P##*9Vo@IW0;LRV5)x}@Eb_^XVD zN8$&6fIrH3Zi|H_nx=E-&g0CPJJbI9{o^NqRXh)405eM52_cHv5auwiw1g51A>75i z5RynKkq%R2l$KT6qKPFFIf1~zvcPEBZSCcpjuilGWQ$amgP7m zNFe-*7sqXPTFjHBX47tMIaa%Ew*@NKU^-UCvpl=t2k)}DVk3Hvp#7SO%L?7{;fmX7 z?bVkYtu5An#vV~KSXBsP?I zf}+Hx3Ve!Z?C%0oV50xH*GUN^{_DF!SU?;J-1Ilx?~H>Q>!Yag^*zix5Qu;9C;pvo z%$Ky?a5&=aQdwZwA5RZUjQXN4X21;3B{fmvV(eILK4p|!RQo^3Mo2{xA&N;- z;+!ybf%uhpQAX{3hqLB?e~QfID;qw$hlzFRg%azhBS!EutBBdtZuV2xT4^C%&K gw^+b?{u_Km3ZIeYTTYX10Jqr+n91E`OSdrf2cHJ?UjP6A diff --git a/src/core/org/luaj/vm2/Print.java b/src/core/org/luaj/vm2/Print.java index afdad44d..4f7ea48d 100644 --- a/src/core/org/luaj/vm2/Print.java +++ b/src/core/org/luaj/vm2/Print.java @@ -30,7 +30,7 @@ public class Print extends Lua { private static final String STRING_FOR_NULL = "null"; public static PrintStream ps = System.out; - private static final String[] luaP_opnames = { + public static final String[] OPNAMES = { "MOVE", "LOADK", "LOADBOOL", @@ -159,7 +159,7 @@ public class Print extends Lua { ps.print("[" + line + "] "); else ps.print("[-] "); - ps.print(luaP_opnames[o] + " "); + ps.print(OPNAMES[o] + " "); switch (getOpMode(o)) { case iABC: ps.print( a ); diff --git a/src/test/compile/repack.sh b/src/test/compile/repack.sh deleted file mode 100644 index a7dd2d77..00000000 --- a/src/test/compile/repack.sh +++ /dev/null @@ -1,20 +0,0 @@ -#!/bin/bash -LUA_HOME=/cygdrive/c/programs/lua5.1 -#DIRS="lua5.1-tests regressions" -DIRS="regressions" -for d in $DIRS; do - - # clean out the old - rm -f $d/*.luac - - # compile the tests - TESTS=`echo $d/*.lua` - for x in $TESTS; do - echo compiling $x - luac -o ${x}c ${x} - done - - # rebuild the directory - rm -f ${d}.zip - jar -cvf ${d}.zip ${d} -done \ No newline at end of file diff --git a/src/test/compile/unpack.sh b/src/test/compile/unpack.sh deleted file mode 100644 index ffe81bf4..00000000 --- a/src/test/compile/unpack.sh +++ /dev/null @@ -1,12 +0,0 @@ -#!/bin/bash -LUA_HOME=/cygdrive/c/programs/lua5.1 -#DIRS="lua5.1-tests regressions" -DIRS="regressions" -for d in $DIRS; do - - # unpack files into the directory - rm -rf $d - mkdir -p $d - jar -xvf $d.zip - -done \ No newline at end of file diff --git a/src/test/java/org/luaj/vm/CompatibiltyTest.java b/src/test/java/org/luaj/vm/CompatibiltyTest.java deleted file mode 100644 index 59b68aa9..00000000 --- a/src/test/java/org/luaj/vm/CompatibiltyTest.java +++ /dev/null @@ -1,198 +0,0 @@ -package org.luaj.vm; - -import java.io.IOException; - -/** - * Compatibility tests for the Luaj VM - * - * Results are compared for exact match with - * the installed C-based lua environment. - */ -public class CompatibiltyTest extends ScriptDrivenTest { - - private static final String dir = "src/test/res"; - - public CompatibiltyTest() { - super(dir); - } - - public void testTest1() throws IOException, InterruptedException { - runTest("test1"); - } - - public void testTest2() throws IOException, InterruptedException { - runTest("test2"); - } - - public void testTest3() throws IOException, InterruptedException { - runTest("test3"); - } - - public void testTest4() throws IOException, InterruptedException { - runTest("test4"); - } - - public void testTest5() throws IOException, InterruptedException { - runTest("test5"); - } - - public void testTest6() throws IOException, InterruptedException { - runTest("test6"); - } - - public void testTest7() throws IOException, InterruptedException { - runTest("test7"); - } - - public void testTest8() throws IOException, InterruptedException { - runTest("test8"); - } - - public void testTest9() throws IOException, InterruptedException { - runTest("test9"); - } - - public void testAutoload() throws IOException, InterruptedException { - runTest("autoload"); - } - - public void testBaseLib() throws IOException, InterruptedException { - runTest("baselib"); - } - - public void testBoolean() throws IOException, InterruptedException { - runTest("boolean"); - } - - public void testCalls() throws IOException, InterruptedException { - runTest("calls"); - } - - public void testCoercions() throws IOException, InterruptedException { - runTest("coercions"); - } - - public void testCoroutines() throws IOException, InterruptedException { - runTest("coroutines"); - } - - public void testCompare() throws IOException, InterruptedException { - runTest("compare"); - } - - public void testDebugLib() throws IOException, InterruptedException { - runTest("debuglib"); - } - - public void testErrors() throws IOException, InterruptedException { - runTest("errors"); - } - - public void testHugeTable() throws IOException, InterruptedException { - runTest("hugetable"); - } - - public void testIoLib() throws IOException, InterruptedException { - runTest("iolib"); - } - - public void testLoops() throws IOException, InterruptedException { - runTest("loops"); - } - - public void testManyLocals() throws IOException, InterruptedException { - runTest("manylocals"); - } - - public void testMathLib() throws IOException, InterruptedException { - runTest("mathlib"); - } - - public void testMetatables() throws IOException, InterruptedException { - runTest("metatables"); - } - - public void testModule() throws IOException, InterruptedException { - runTest("module"); - } - - public void testNext() throws IOException, InterruptedException { - runTest("next"); - } - - public void testOsLib() throws IOException, InterruptedException { - runTest("oslib"); - } - - public void testPcalls() throws IOException, InterruptedException { - runTest("pcalls"); - } - - public void testPrint() throws IOException, InterruptedException { - runTest("print"); - } - - public void testRequire() throws IOException, InterruptedException { - runTest("require"); - } - - public void testSelect() throws IOException, InterruptedException { - runTest("select"); - } - - public void testSetfenv() throws IOException, InterruptedException { - runTest("setfenv"); - } - - public void testSetlist() throws IOException, InterruptedException { - runTest("setlist"); - } - - public void testSimpleMetatables() throws IOException, InterruptedException { - runTest("simplemetatables"); - } - - public void testStack() throws IOException, InterruptedException { - runTest("stack"); - } - - public void testStrLib() throws IOException, InterruptedException { - runTest("strlib"); - } - - public void testSort() throws IOException, InterruptedException { - runTest("sort"); - } - - public void testTable() throws IOException, InterruptedException { - runTest("table"); - } - - public void testTailcall() throws IOException, InterruptedException { - runTest("tailcall"); - } - - public void testType() throws IOException, InterruptedException { - runTest("type"); - } - - public void testUpvalues() throws IOException, InterruptedException { - runTest("upvalues"); - } - - public void testUpvalues2() throws IOException, InterruptedException { - runTest("upvalues2"); - } - - public void testUpvalues3() throws IOException, InterruptedException { - runTest("upvalues3"); - } - - public void testVarargs() throws IOException, InterruptedException { - runTest("varargs"); - } - - public void testWeakTable() throws IOException, InterruptedException { - runTest("weaktable"); - } -} diff --git a/src/test/java/org/luaj/vm/LuaJavaCoercionTest.java b/src/test/java/org/luaj/vm/LuaJavaCoercionTest.java deleted file mode 100644 index 371d0149..00000000 --- a/src/test/java/org/luaj/vm/LuaJavaCoercionTest.java +++ /dev/null @@ -1,187 +0,0 @@ -package org.luaj.vm; - -import junit.framework.TestCase; - -import org.luaj.lib.j2se.CoerceJavaToLua; -import org.luaj.lib.j2se.CoerceLuaToJava; -import org.luaj.platform.J2sePlatform; - -public class LuaJavaCoercionTest extends TestCase { - - private LuaState vm; - private static LInteger ZERO = LInteger.valueOf(0); - private static LInteger ONE = LInteger.valueOf(1); - private static LInteger TWO = LInteger.valueOf(2); - private static LInteger THREE = LInteger.valueOf(3); - private static LString LENGTH = LString.valueOf("length"); - - protected void setUp() throws Exception { - super.setUp(); - Platform.setInstance( new J2sePlatform() ); - org.luaj.compiler.LuaC.install(); - vm = Platform.newLuaState(); - } - - public void testJavaIntToLuaInt() { - Integer i = Integer.valueOf(777); - LValue v = CoerceJavaToLua.coerce(i); - assertEquals( LInteger.class, v.getClass() ); - assertEquals( 777, v.toJavaInt() ); - } - - public void testLuaIntToJavaInt() { - LInteger i = LInteger.valueOf(777); - Object o = CoerceLuaToJava.coerceArg(i, int.class); - assertEquals( Integer.class, o.getClass() ); - assertEquals( 777, ((Number)o).intValue() ); - o = CoerceLuaToJava.coerceArg(i, Integer.class); - assertEquals( Integer.class, o.getClass() ); - assertEquals( new Integer(777), o ); - } - - public void testJavaStringToLuaString() { - String s = new String("777"); - LValue v = CoerceJavaToLua.coerce(s); - assertEquals( LString.class, v.getClass() ); - assertEquals( "777", v.toJavaString() ); - } - - public void testLuaStringToJavaString() { - LString s = new LString("777"); - Object o = CoerceLuaToJava.coerceArg(s, String.class); - assertEquals( String.class, o.getClass() ); - assertEquals( "777", o ); - } - - public void testJavaIntArrayToLuaTable() { - int[] i = { 222, 333 }; - LValue v = CoerceJavaToLua.coerce(i); - assertEquals( LUserData.class, v.getClass() ); - assertNotNull( v.luaGetMetatable() ); - assertEquals( LInteger.valueOf(222), v.luaGetTable(vm, ONE) ); - assertEquals( LInteger.valueOf(333), v.luaGetTable(vm, TWO) ); - assertEquals( TWO, v.luaGetTable(vm, LENGTH)); - assertEquals( LNil.NIL, v.luaGetTable(vm, THREE) ); - assertEquals( LNil.NIL, v.luaGetTable(vm, ZERO) ); - v.luaSetTable(vm, ONE, LInteger.valueOf(444)); - v.luaSetTable(vm, TWO, LInteger.valueOf(555)); - assertEquals( 444, i[0] ); - assertEquals( 555, i[1] ); - assertEquals( LInteger.valueOf(444), v.luaGetTable(vm, ONE) ); - assertEquals( LInteger.valueOf(555), v.luaGetTable(vm, TWO) ); - try { - v.luaSetTable(vm, ZERO, LInteger.valueOf(777)); - fail( "array bound exception not thrown" ); - } catch ( LuaErrorException lee ) { - // expected - } - try { - v.luaSetTable(vm, THREE, LInteger.valueOf(777)); - fail( "array bound exception not thrown" ); - } catch ( LuaErrorException lee ) { - // expected - } - } - - public void testLuaTableToJavaIntArray() { - LTable t = new LTable(); - t.put(1, LInteger.valueOf(222) ); - t.put(2, LInteger.valueOf(333) ); - int[] i = null; - Object o = CoerceLuaToJava.coerceArg(t, int[].class); - assertEquals( int[].class, o.getClass() ); - i = (int[]) o; - assertEquals( 2, i.length ); - assertEquals( 222, i[0] ); - assertEquals( 333, i[1] ); - } - - - public void testArrayParamScoring() { - int a = 5; - int[] b = { 44, 66 }; - int[][] c = { { 11, 22 }, { 33, 44 } }; - LValue la = LInteger.valueOf(a); - LTable tb = new LTable(); - LTable tc = new LTable(); - LValue va = CoerceJavaToLua.coerce(a); - LValue vb = CoerceJavaToLua.coerce(b); - LValue vc = CoerceJavaToLua.coerce(c); - tc.put( ONE, new LTable() ); - - int saa = CoerceLuaToJava.scoreParamTypes( new LValue[] { la }, new Class[] { int.class } ); - int sab = CoerceLuaToJava.scoreParamTypes( new LValue[] { la }, new Class[] { int[].class } ); - int sac = CoerceLuaToJava.scoreParamTypes( new LValue[] { la }, new Class[] { int[][].class } ); - assertTrue( saa < sab ); - assertTrue( saa < sac ); - int sba = CoerceLuaToJava.scoreParamTypes( new LValue[] { tb }, new Class[] { int.class } ); - int sbb = CoerceLuaToJava.scoreParamTypes( new LValue[] { tb }, new Class[] { int[].class } ); - int sbc = CoerceLuaToJava.scoreParamTypes( new LValue[] { tb }, new Class[] { int[][].class } ); - assertTrue( sbb < sba ); - assertTrue( sbb < sbc ); - int sca = CoerceLuaToJava.scoreParamTypes( new LValue[] { tc }, new Class[] { int.class } ); - int scb = CoerceLuaToJava.scoreParamTypes( new LValue[] { tc }, new Class[] { int[].class } ); - int scc = CoerceLuaToJava.scoreParamTypes( new LValue[] { tc }, new Class[] { int[][].class } ); - assertTrue( scc < sca ); - assertTrue( scc < scb ); - - int vaa = CoerceLuaToJava.scoreParamTypes( new LValue[] { va }, new Class[] { int.class } ); - int vab = CoerceLuaToJava.scoreParamTypes( new LValue[] { va }, new Class[] { int[].class } ); - int vac = CoerceLuaToJava.scoreParamTypes( new LValue[] { va }, new Class[] { int[][].class } ); - assertTrue( vaa < vab ); - assertTrue( vaa < vac ); - int vba = CoerceLuaToJava.scoreParamTypes( new LValue[] { vb }, new Class[] { int.class } ); - int vbb = CoerceLuaToJava.scoreParamTypes( new LValue[] { vb }, new Class[] { int[].class } ); - int vbc = CoerceLuaToJava.scoreParamTypes( new LValue[] { vb }, new Class[] { int[][].class } ); - assertTrue( vbb < vba ); - assertTrue( vbb < vbc ); - int vca = CoerceLuaToJava.scoreParamTypes( new LValue[] { vc }, new Class[] { int.class } ); - int vcb = CoerceLuaToJava.scoreParamTypes( new LValue[] { vc }, new Class[] { int[].class } ); - int vcc = CoerceLuaToJava.scoreParamTypes( new LValue[] { vc }, new Class[] { int[][].class } ); - assertTrue( vcc < vca ); - assertTrue( vcc < vcb ); - } - - public static class SampleClass { - public String sample() { return "void-args"; } - public String sample(int a) { return "int-args "+a; } - public String sample(int[] a) { return "int-array-args "+a[0]+","+a[1]; } - public String sample(int[][] a) { return "int-array-array-args "+a[0][0]+","+a[0][1]+","+a[1][0]+","+a[1][1]; } - } - - private static final LString SAMPLE = LString.valueOf("sample"); - - public void testIntArrayParameterMatching() { - LValue v = CoerceJavaToLua.coerce(new SampleClass()); - - // get sample field, call with no arguments - LValue method = v.luaGetTable(vm, SAMPLE); - vm.pushlvalue(method); - vm.pushlvalue(v); - vm.call(1,1); - assertEquals( "void-args", vm.tostring(-1) ); - - // get sample field, call with no arguments - vm.pushlvalue(method); - vm.pushlvalue(v); - vm.pushlvalue( CoerceJavaToLua.coerce(new Integer(123))); - vm.call(2,1); - assertEquals( "int-args 123", vm.tostring(-1) ); - - // get sample field, call with no arguments - vm.pushlvalue(method); - vm.pushlvalue(v); - vm.pushlvalue( CoerceJavaToLua.coerce(new int[]{345,678}) ); - vm.call(2,1); - assertEquals( "int-array-args 345,678", vm.tostring(-1) ); - - // get sample field, call with no arguments - vm.pushlvalue(method); - vm.pushlvalue(v); - vm.pushlvalue( CoerceJavaToLua.coerce(new int[][]{{22,33},{44,55}}) ); - vm.call(2,1); - assertEquals( "int-array-array-args 22,33,44,55", vm.tostring(-1) ); - } - - -} diff --git a/test/junit/org/luaj/vm2/AllTests.java b/test/junit/org/luaj/vm2/AllTests.java index f76f4283..52fa665a 100644 --- a/test/junit/org/luaj/vm2/AllTests.java +++ b/test/junit/org/luaj/vm2/AllTests.java @@ -27,6 +27,7 @@ import junit.framework.TestSuite; import org.luaj.vm2.WeakTableTest.WeakKeyTableTest; import org.luaj.vm2.WeakTableTest.WeakKeyValueTableTest; import org.luaj.vm2.lib.jse.LuaJavaCoercionTest; +import org.luaj.vm2.vm1.Luajvm1CompatibilityTest; public class AllTests { @@ -58,6 +59,7 @@ public class AllTests { // compatiblity tests suite.addTest(CompatibiltyTest.suite()); + suite.addTestSuite(Luajvm1CompatibilityTest.class); // luajc regression tests TestSuite luajc = new TestSuite("Luajc Tests"); diff --git a/src/test/java/org/luaj/compiler/AbstractUnitTests.java b/test/junit/org/luaj/vm2/compiler/AbstractUnitTests.java similarity index 72% rename from src/test/java/org/luaj/compiler/AbstractUnitTests.java rename to test/junit/org/luaj/vm2/compiler/AbstractUnitTests.java index 2785ea0c..95355070 100644 --- a/src/test/java/org/luaj/compiler/AbstractUnitTests.java +++ b/test/junit/org/luaj/vm2/compiler/AbstractUnitTests.java @@ -1,4 +1,4 @@ -package org.luaj.compiler; +package org.luaj.vm2.compiler; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; @@ -9,42 +9,44 @@ import java.net.URL; import junit.framework.TestCase; -import org.luaj.TestPlatform; -import org.luaj.vm.LPrototype; -import org.luaj.vm.LoadState; -import org.luaj.vm.LuaState; -import org.luaj.vm.Platform; -import org.luaj.vm.Print; +import org.luaj.vm2.LoadState; +import org.luaj.vm2.LuaTable; +import org.luaj.vm2.Print; +import org.luaj.vm2.Prototype; +import org.luaj.vm2.lib.JsePlatform; abstract public class AbstractUnitTests extends TestCase { - private final String zipfile; private final String dir; + private final String jar; + private LuaTable _G; public AbstractUnitTests(String zipfile, String dir) { - this.zipfile = zipfile; + URL zip = getClass().getResource(zipfile); + this.jar = "jar:" + zip.toExternalForm()+ "!/"; this.dir = dir; } protected void setUp() throws Exception { super.setUp(); - Platform.setInstance(new TestPlatform()); + _G = JsePlatform.standardGlobals(); + LuaC.install(); } protected void doTest(String file) { try { // load source from jar - String path = "jar:file:" + zipfile + "!/" + dir + "/" + file; + String path = jar + dir + "/" + file; byte[] lua = bytesFromJar(path); // compile in memory InputStream is = new ByteArrayInputStream(lua); - LPrototype p = LuaC.compile(is, dir + "/" + file); + Prototype p = LuaC.compile(is, dir + "/" + file); String actual = protoToString(p); // load expected value from jar byte[] luac = bytesFromJar(path + "c"); - LPrototype e = loadFromBytes(luac, file); + Prototype e = loadFromBytes(luac, file); String expected = protoToString(e); // compare results @@ -56,7 +58,7 @@ abstract public class AbstractUnitTests extends TestCase { byte[] dumped = baos.toByteArray(); // re-undump - LPrototype p2 = loadFromBytes(dumped, file); + Prototype p2 = loadFromBytes(dumped, file); String actual2 = protoToString(p2); // compare again @@ -79,14 +81,13 @@ abstract public class AbstractUnitTests extends TestCase { return baos.toByteArray(); } - protected LPrototype loadFromBytes(byte[] bytes, String script) + protected Prototype loadFromBytes(byte[] bytes, String script) throws IOException { - LuaState state = Platform.newLuaState(); InputStream is = new ByteArrayInputStream(bytes); - return LoadState.undump(state, is, script); + return LoadState.compile(is, script); } - protected String protoToString(LPrototype p) { + protected String protoToString(Prototype p) { ByteArrayOutputStream baos = new ByteArrayOutputStream(); PrintStream ps = new PrintStream(baos); Print.ps = ps; diff --git a/src/test/java/org/luaj/compiler/CompilerUnitTests.java b/test/junit/org/luaj/vm2/compiler/CompilerUnitTests.java similarity index 93% rename from src/test/java/org/luaj/compiler/CompilerUnitTests.java rename to test/junit/org/luaj/vm2/compiler/CompilerUnitTests.java index 74abda2d..027b75b3 100644 --- a/src/test/java/org/luaj/compiler/CompilerUnitTests.java +++ b/test/junit/org/luaj/vm2/compiler/CompilerUnitTests.java @@ -1,11 +1,11 @@ -package org.luaj.compiler; +package org.luaj.vm2.compiler; public class CompilerUnitTests extends AbstractUnitTests { public CompilerUnitTests() { - super("src/test/compile/lua5.1-tests.zip", "lua5.1-tests"); + super("lua5.1-tests.zip", "lua5.1-tests"); } public void testAll() { doTest("all.lua"); } diff --git a/src/test/java/org/luaj/compiler/DumpLoadEndianIntTest.java b/test/junit/org/luaj/vm2/compiler/DumpLoadEndianIntTest.java similarity index 89% rename from src/test/java/org/luaj/compiler/DumpLoadEndianIntTest.java rename to test/junit/org/luaj/vm2/compiler/DumpLoadEndianIntTest.java index 1cde9ab4..5316bead 100644 --- a/src/test/java/org/luaj/compiler/DumpLoadEndianIntTest.java +++ b/test/junit/org/luaj/vm2/compiler/DumpLoadEndianIntTest.java @@ -1,4 +1,4 @@ -package org.luaj.compiler; +package org.luaj.vm2.compiler; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; @@ -9,11 +9,13 @@ import java.io.InputStream; import junit.framework.TestCase; -import org.luaj.platform.J2sePlatform; -import org.luaj.vm.LFunction; -import org.luaj.vm.LPrototype; -import org.luaj.vm.LuaState; -import org.luaj.vm.Platform; +import org.luaj.vm2.LoadState; +import org.luaj.vm2.LuaClosure; +import org.luaj.vm2.LuaTable; +import org.luaj.vm2.LuaValue; +import org.luaj.vm2.Prototype; +import org.luaj.vm2.lib.JsePlatform; + public class DumpLoadEndianIntTest extends TestCase { private static final String SAVECHUNKS = "SAVECHUNKS"; @@ -24,10 +26,13 @@ public class DumpLoadEndianIntTest extends TestCase { private static final String intscript = "return tostring(1234)..'-#!-'..tostring(23)"; private static final String withdoubles = "1234-#!-23.75"; private static final String withints = "1234-#!-23"; - + + private LuaTable _G; + protected void setUp() throws Exception { super.setUp(); - Platform.setInstance(new J2sePlatform()); + _G = JsePlatform.standardGlobals(); + LuaC.install(); DumpState.ALLOW_INTEGER_CASTING = false; } @@ -76,17 +81,15 @@ public class DumpLoadEndianIntTest extends TestCase { public void doTest( boolean littleEndian, int numberFormat, boolean stripDebug, String script, String expectedPriorDump, String expectedPostDump, boolean shouldPass ) { try { - LuaState vm = Platform.newLuaState(); // compile into prototype InputStream is = new ByteArrayInputStream(script.getBytes()); - LPrototype p = LuaC.compile(is, "script"); + Prototype p = LuaC.compile(is, "script"); // double check script result before dumping - LFunction f = p.newClosure(vm._G); - vm.pushfunction(f); - vm.call(0,1); - String actual = vm.poplvalue().toJavaString(); + LuaClosure f = new LuaClosure(p, _G); + LuaValue r = f.call(); + String actual = r.toString(); assertEquals( expectedPriorDump, actual ); // dump into bytes @@ -105,9 +108,10 @@ public class DumpLoadEndianIntTest extends TestCase { // load again using compiler is = new ByteArrayInputStream(dumped); - vm.load(is, "dumped"); - vm.call(0,1); - actual = vm.poplvalue().toJavaString(); + p = LoadState.compile(is, "dumped"); + f = new LuaClosure(p, _G); + r = f.call(); + actual = r.toString(); assertEquals( expectedPostDump, actual ); // write test chunk diff --git a/src/test/java/org/luaj/compiler/RegressionTests.java b/test/junit/org/luaj/vm2/compiler/RegressionTests.java similarity index 93% rename from src/test/java/org/luaj/compiler/RegressionTests.java rename to test/junit/org/luaj/vm2/compiler/RegressionTests.java index f36cc027..b6747965 100644 --- a/src/test/java/org/luaj/compiler/RegressionTests.java +++ b/test/junit/org/luaj/vm2/compiler/RegressionTests.java @@ -1,4 +1,4 @@ -package org.luaj.compiler; +package org.luaj.vm2.compiler; /** * Framework to add regression tests as problem areas are found. @@ -17,7 +17,7 @@ package org.luaj.compiler; public class RegressionTests extends AbstractUnitTests { public RegressionTests() { - super( "src/test/compile/regressions.zip", + super( "regressions.zip", "regressions" ); } diff --git a/src/test/java/org/luaj/compiler/SimpleTests.java b/test/junit/org/luaj/vm2/compiler/SimpleTests.java similarity index 71% rename from src/test/java/org/luaj/compiler/SimpleTests.java rename to test/junit/org/luaj/vm2/compiler/SimpleTests.java index a20cb9d3..51440be4 100644 --- a/src/test/java/org/luaj/compiler/SimpleTests.java +++ b/test/junit/org/luaj/vm2/compiler/SimpleTests.java @@ -1,40 +1,40 @@ -package org.luaj.compiler; +package org.luaj.vm2.compiler; import java.io.ByteArrayInputStream; import java.io.InputStream; import junit.framework.TestCase; -import org.luaj.TestPlatform; -import org.luaj.lib.BaseLib; -import org.luaj.vm.LClosure; -import org.luaj.vm.LDouble; -import org.luaj.vm.LInteger; -import org.luaj.vm.LPrototype; -import org.luaj.vm.LValue; -import org.luaj.vm.LuaState; -import org.luaj.vm.Platform; -import org.luaj.vm.Print; +import org.luaj.vm2.LuaClosure; +import org.luaj.vm2.LuaDouble; +import org.luaj.vm2.LuaInteger; +import org.luaj.vm2.LuaTable; +import org.luaj.vm2.LuaValue; +import org.luaj.vm2.Print; +import org.luaj.vm2.Prototype; +import org.luaj.vm2.lib.BaseLib; +import org.luaj.vm2.lib.JsePlatform; public class SimpleTests extends TestCase { + private LuaTable _G; + protected void setUp() throws Exception { super.setUp(); - Platform.setInstance(new TestPlatform()); + _G = JsePlatform.standardGlobals(); + LuaC.install(); } private void doTest( String script ) { try { InputStream is = new ByteArrayInputStream( script.getBytes("UTF8") ); - LPrototype p = LuaC.compile( is, "script" ); + Prototype p = LuaC.compile( is, "script" ); assertNotNull( p ); Print.printCode( p ); // try running the code! - LuaState state = Platform.newLuaState(); - BaseLib.install( state._G ); - LClosure c = p.newClosure( state._G ); - state.doCall( c, new LValue[0] ); + LuaClosure c = new LuaClosure( p, _G ); + c.call(); } catch ( Exception e ) { fail("i/o exception: "+e ); } @@ -93,15 +93,15 @@ public class SimpleTests extends TestCase { public void testDoubleHashCode() { for ( int i=0; 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

c@A9v?NH9kl}0k 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 KJVCZkpZy=&go(@m literal 0 HcmV?d00001