Cleanup Tests with JUnit5 and move to different modules

This commit is contained in:
Enrico Horn
2021-07-11 23:01:01 +02:00
parent 1a6de4a227
commit 9792fcb018
64 changed files with 2355 additions and 1806 deletions

View File

@@ -24,6 +24,11 @@
<groupId>org.apache.bcel</groupId>
<artifactId>bcel</artifactId>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>

View File

@@ -0,0 +1,148 @@
package org.luaj.jse;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.fail;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.Reader;
import java.io.StringReader;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.luaj.vm2.Globals;
import org.luaj.vm2.LuaClosure;
import org.luaj.vm2.LuaFunction;
import org.luaj.vm2.LuaValue;
import org.luaj.vm2.Prototype;
import org.luaj.vm2.compiler.DumpState;
import org.luaj.vm2.lib.jse.JsePlatform;
class DumpLoadEndianIntTest {
private static final String SAVECHUNKS = "SAVECHUNKS";
private static final boolean SHOULDPASS = true;
private static final boolean SHOULDFAIL = false;
private static final String mixedscript = "return tostring(1234)..'-#!-'..tostring(23.75)";
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 Globals globals;
@BeforeEach
protected void setUp() throws Exception {
globals = JsePlatform.standardGlobals();
DumpState.ALLOW_INTEGER_CASTING = false;
}
@Test
void testBigDoubleCompile() {
doTest(false, DumpState.NUMBER_FORMAT_FLOATS_OR_DOUBLES, false, mixedscript, withdoubles, withdoubles,
SHOULDPASS);
doTest(false, DumpState.NUMBER_FORMAT_FLOATS_OR_DOUBLES, true, mixedscript, withdoubles, withdoubles,
SHOULDPASS);
}
@Test
void testLittleDoubleCompile() {
doTest(true, DumpState.NUMBER_FORMAT_FLOATS_OR_DOUBLES, false, mixedscript, withdoubles, withdoubles,
SHOULDPASS);
doTest(true, DumpState.NUMBER_FORMAT_FLOATS_OR_DOUBLES, true, mixedscript, withdoubles, withdoubles,
SHOULDPASS);
}
@Test
void testBigIntCompile() {
DumpState.ALLOW_INTEGER_CASTING = true;
doTest(false, DumpState.NUMBER_FORMAT_INTS_ONLY, false, mixedscript, withdoubles, withints, SHOULDPASS);
doTest(false, DumpState.NUMBER_FORMAT_INTS_ONLY, true, mixedscript, withdoubles, withints, SHOULDPASS);
DumpState.ALLOW_INTEGER_CASTING = false;
doTest(false, DumpState.NUMBER_FORMAT_INTS_ONLY, false, mixedscript, withdoubles, withints, SHOULDFAIL);
doTest(false, DumpState.NUMBER_FORMAT_INTS_ONLY, true, mixedscript, withdoubles, withints, SHOULDFAIL);
doTest(false, DumpState.NUMBER_FORMAT_INTS_ONLY, false, intscript, withints, withints, SHOULDPASS);
doTest(false, DumpState.NUMBER_FORMAT_INTS_ONLY, true, intscript, withints, withints, SHOULDPASS);
}
@Test
void testLittleIntCompile() {
DumpState.ALLOW_INTEGER_CASTING = true;
doTest(true, DumpState.NUMBER_FORMAT_INTS_ONLY, false, mixedscript, withdoubles, withints, SHOULDPASS);
doTest(true, DumpState.NUMBER_FORMAT_INTS_ONLY, true, mixedscript, withdoubles, withints, SHOULDPASS);
DumpState.ALLOW_INTEGER_CASTING = false;
doTest(true, DumpState.NUMBER_FORMAT_INTS_ONLY, false, mixedscript, withdoubles, withints, SHOULDFAIL);
doTest(true, DumpState.NUMBER_FORMAT_INTS_ONLY, true, mixedscript, withdoubles, withints, SHOULDFAIL);
doTest(true, DumpState.NUMBER_FORMAT_INTS_ONLY, false, intscript, withints, withints, SHOULDPASS);
doTest(true, DumpState.NUMBER_FORMAT_INTS_ONLY, true, intscript, withints, withints, SHOULDPASS);
}
@Test
void testBigNumpatchCompile() {
doTest(false, DumpState.NUMBER_FORMAT_NUM_PATCH_INT32, false, mixedscript, withdoubles, withdoubles,
SHOULDPASS);
doTest(false, DumpState.NUMBER_FORMAT_NUM_PATCH_INT32, true, mixedscript, withdoubles, withdoubles, SHOULDPASS);
}
@Test
void testLittleNumpatchCompile() {
doTest(true, DumpState.NUMBER_FORMAT_NUM_PATCH_INT32, false, mixedscript, withdoubles, withdoubles, SHOULDPASS);
doTest(true, DumpState.NUMBER_FORMAT_NUM_PATCH_INT32, true, mixedscript, withdoubles, withdoubles, SHOULDPASS);
}
private void doTest(boolean littleEndian, int numberFormat, boolean stripDebug, String script,
String expectedPriorDump, String expectedPostDump, boolean shouldPass) {
try {
// compile into prototype
Reader reader = new StringReader(script);
Prototype p = globals.compilePrototype(reader, "script");
// double check script result before dumping
LuaFunction f = new LuaClosure(p, globals);
LuaValue r = f.call();
String actual = r.tojstring();
assertEquals(expectedPriorDump, actual);
// dump into bytes
ByteArrayOutputStream baos = new ByteArrayOutputStream();
try {
DumpState.dump(p, baos, stripDebug, numberFormat, littleEndian);
if (!shouldPass)
fail("dump should not have succeeded");
} catch (Exception e) {
if (shouldPass)
fail("dump threw " + e);
else
return;
}
byte[] dumped = baos.toByteArray();
// load again using compiler
InputStream is = new ByteArrayInputStream(dumped);
f = globals.load(is, "dumped", "b", globals).checkfunction();
r = f.call();
actual = r.tojstring();
assertEquals(expectedPostDump, actual);
// write test chunk
if (System.getProperty(SAVECHUNKS) != null && script.equals(mixedscript)) {
new File("build").mkdirs();
String filename = "build/test-" + (littleEndian? "little-": "big-")
+ (numberFormat == DumpState.NUMBER_FORMAT_FLOATS_OR_DOUBLES? "double-"
: numberFormat == DumpState.NUMBER_FORMAT_INTS_ONLY? "int-"
: numberFormat == DumpState.NUMBER_FORMAT_NUM_PATCH_INT32? "numpatch4-": "???-")
+ (stripDebug? "nodebug-": "debug-") + "bin.lua";
FileOutputStream fos = new FileOutputStream(filename);
fos.write(dumped);
fos.close();
}
} catch (IOException e) {
fail(e.toString());
}
}
}

View File

@@ -0,0 +1,460 @@
/*******************************************************************************
* 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.jse;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.fail;
import java.io.Reader;
import java.io.StringReader;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
import org.luaj.vm2.Globals;
import org.luaj.vm2.LuaClosure;
import org.luaj.vm2.LuaValue;
import org.luaj.vm2.Print;
import org.luaj.vm2.Prototype;
import org.luaj.vm2.Varargs;
import org.luaj.vm2.lib.jse.JsePlatform;
import org.luaj.vm2.luajc.LuaJC;
/**
* Test compilation of various fragments that have caused problems for jit
* compiling during development.
*
*/
public class FragmentsTest {
static final int TEST_TYPE_LUAC = 0;
static final int TEST_TYPE_LUAJC = 1;
@Nested
public static class JseFragmentsTest extends FragmentsTestCase {
public JseFragmentsTest() { super(TEST_TYPE_LUAC); }
}
@Nested
public static class LuaJCFragmentsTest extends FragmentsTestCase {
public LuaJCFragmentsTest() { super(TEST_TYPE_LUAJC); }
}
abstract protected static class FragmentsTestCase {
final int TEST_TYPE;
protected FragmentsTestCase(int testType) {
this.TEST_TYPE = testType;
}
public void runFragment(Varargs expected, String script) {
try {
String name = this.getClass().getName();
Globals globals = JsePlatform.debugGlobals();
Reader reader = new StringReader(script);
LuaValue chunk;
switch (TEST_TYPE) {
case TEST_TYPE_LUAJC:
LuaJC.install(globals);
chunk = globals.load(reader, name);
break;
default:
Prototype p = globals.compilePrototype(reader, name);
chunk = new LuaClosure(p, globals);
Print.print(p);
break;
}
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());
}
}
@Test
public void testFirstArgNilExtended() {
runFragment(LuaValue.NIL, "function f1(a) print( 'f1:', a ) return a end\n" + "b = f1()\n" + "return b");
}
@Test
public void testSimpleForloop() {
runFragment(LuaValue.valueOf(77),
"for n,p in ipairs({77}) do\n" + " print('n,p',n,p)\n" + " return p\n" + "end\n");
}
@Test
public void testForloopParamUpvalues() {
runFragment(LuaValue.varargsOf(new LuaValue[] { LuaValue.valueOf(77), LuaValue.valueOf(1) }),
"for n,p in ipairs({77}) do\n" + " print('n,p',n,p)\n" + " foo = function()\n" + " return p,n\n"
+ " end\n" + " return foo()\n" + "end\n");
}
@Test
public void testArgVarargsUseBoth() {
runFragment(
LuaValue
.varargsOf(new LuaValue[] { LuaValue.valueOf("a"), LuaValue.valueOf("b"), LuaValue.valueOf("c") }),
"function v(arg,...)\n" + " return arg,...\n" + "end\n" + "return v('a','b','c')\n");
}
@Test
public void testArgParamUseNone() {
runFragment(LuaValue.valueOf("string"),
"function v(arg,...)\n" + " return type(arg)\n" + "end\n" + "return v('abc')\n");
}
@Test
public void testSetlistVarargs() {
runFragment(LuaValue.valueOf("abc"),
"local f = function() return 'abc' end\n" + "local g = { f() }\n" + "return g[1]\n");
}
@Test
public void testSelfOp() {
runFragment(LuaValue.valueOf("bcd"), "local s = 'abcde'\n" + "return s:sub(2,4)\n");
}
@Test
public void testSetListWithOffsetAndVarargs() {
runFragment(LuaValue.valueOf(1003), "local bar = {1000, math.sqrt(9)}\n" + "return bar[1]+bar[2]\n");
}
@Test
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");
}
@Test
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");
}
@Test
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");
}
@Test
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");
}
@Test
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");
}
@Test
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");
}
@Test
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");
}
@Test
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");
}
@Test
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");
}
@Test
public void testVarargsWithParameters() {
runFragment(LuaValue.valueOf(222),
"local func = function(t,...)\n" + " return (...)\n" + "end\n" + "return func(111,222,333)\n");
}
@Test
public void testNoReturnValuesPlainCall() {
runFragment(LuaValue.TRUE, "local testtable = {}\n" + "return pcall( function() testtable[1]=2 end )\n");
}
@Test
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");
}
@Test
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");
}
@Test
public void testSetUpvalueTableInitializer() {
runFragment(LuaValue.valueOf("b"), "local aliases = {a='b'}\n" + "local foo = function()\n"
+ " return aliases\n" + "end\n" + "return foo().a\n");
}
@Test
public void testLoadNilUpvalue() {
runFragment(LuaValue.NIL, "tostring = function() end\n" + "local pc \n" + "local pcall = function(...)\n"
+ " pc(...)\n" + "end\n" + "return NIL\n");
}
@Test
public void testUpvalueClosure() {
runFragment(LuaValue.NIL, "print()\n" + "local function f2() end\n" + "local function f3()\n"
+ " return f3\n" + "end\n" + "return NIL\n");
}
@Test
public void testUninitializedUpvalue() {
runFragment(LuaValue.NIL, "local f\n" + "do\n" + " function g()\n" + " print(f())\n" + " end\n"
+ "end\n" + "return NIL\n");
}
@Test
public void testTestOpUpvalues() {
runFragment(LuaValue.varargsOf(LuaValue.valueOf(1), LuaValue.valueOf(2), LuaValue.valueOf(3)),
"print( nil and 'T' or 'F' )\n" + "local a,b,c = 1,2,3\n" + "function foo()\n" + " return a,b,c\n"
+ "end\n" + "return foo()\n");
}
@Test
public void testTestSimpleBinops() {
runFragment(
LuaValue.varargsOf(
new LuaValue[] { LuaValue.FALSE, LuaValue.FALSE, LuaValue.TRUE, LuaValue.TRUE, LuaValue.FALSE }),
"local a,b,c = 2,-2.5,0\n" + "return (a==c), (b==c), (a==a), (a>c), (b>0)\n");
}
@Test
public void testNumericForUpvalues() {
runFragment(LuaValue.valueOf(8), "for i = 3,4 do\n" + " i = i + 5\n" + " local a = function()\n"
+ " return i\n" + " end\n" + " return a()\n" + "end\n");
}
@Test
public void testNumericForUpvalues2() {
runFragment(LuaValue.valueOf("222 222"),
"local t = {}\n" + "local template = [[123 456]]\n" + "for i = 1,2 do\n"
+ " t[i] = template:gsub('%d', function(s)\n" + " return i\n" + " end)\n" + "end\n"
+ "return t[2]\n");
}
@Test
public void testReturnUpvalue() {
runFragment(LuaValue.varargsOf(new LuaValue[] { LuaValue.ONE, LuaValue.valueOf(5), }), "local a = 1\n"
+ "local b\n" + "function c()\n" + " b=5\n" + " return a\n" + "end\n" + "return c(),b\n");
}
@Test
public void testUninitializedAroundBranch() {
runFragment(LuaValue.valueOf(333),
"local state\n" + "if _G then\n" + " state = 333\n" + "end\n" + "return state\n");
}
@Test
public void testLoadedNilUpvalue() {
runFragment(LuaValue.NIL, "local a = print()\n" + "local b = c and { d = e }\n" + "local f\n"
+ "local function g()\n" + " return f\n" + "end\n" + "return g()\n");
}
@Test
public void testUpvalueInFirstSlot() {
runFragment(LuaValue.valueOf("foo"), "local p = {'foo'}\n" + "bar = function()\n" + " return p \n"
+ "end\n" + "for i,key in ipairs(p) do\n" + " print()\n" + "end\n" + "return bar()[1]");
}
@Test
public void testReadOnlyAndReadWriteUpvalues() {
runFragment(LuaValue.varargsOf(new LuaValue[] { LuaValue.valueOf(333), LuaValue.valueOf(222) }),
"local a = 111\n" + "local b = 222\n" + "local c = function()\n" + " a = a + b\n"
+ " return a,b\n" + "end\n" + "return c()\n");
}
@Test
public void testNestedUpvalues() {
runFragment(
LuaValue.varargsOf(new LuaValue[] { LuaValue.valueOf(5), LuaValue.valueOf(8), LuaValue.valueOf(9) }),
"local x = 3\n" + "local y = 5\n" + "local function f()\n" + " return y\n" + "end\n"
+ "local function g(x1, y1)\n" + " x = x1\n" + " y = y1\n" + " return x,y\n" + "end\n"
+ "return f(), g(8,9)\n" + "\n");
}
@Test
public void testLoadBool() {
runFragment(LuaValue.NONE, "print( type(foo)=='string' )\n" + "local a,b\n" + "if print() then\n"
+ " b = function()\n" + " return a\n" + " end\n" + "end\n");
}
@Test
public void testBasicForLoop() {
runFragment(LuaValue.valueOf(2), "local data\n" + "for i = 1, 2 do\n" + " data = i\n" + "end\n"
+ "local bar = function()\n" + " return data\n" + "end\n" + "return bar()\n");
}
@Test
public void testGenericForMultipleValues() {
runFragment(LuaValue.varargsOf(LuaValue.valueOf(3), LuaValue.valueOf(2), LuaValue.valueOf(1)),
"local iter = function() return 1,2,3,4 end\n" + "local foo = function() return iter,5 end\n"
+ "for a,b,c in foo() do\n" + " return c,b,a\n" + "end\n");
}
@Test
public void testPhiUpvalue() {
runFragment(LuaValue.valueOf(6), "local a = foo or 0\n" + "local function b(c)\n"
+ " if c > a then a = c end\n" + " return a\n" + "end\n" + "b(6)\n" + "return a\n");
}
@Test
public void testAssignReferUpvalues() {
runFragment(LuaValue.valueOf(123), "local entity = 234\n" + "local function c()\n" + " return entity\n"
+ "end\n" + "entity = (a == b) and 123\n" + "if entity then\n" + " return entity\n" + "end\n");
}
@Test
public void testSimpleRepeatUntil() {
runFragment(LuaValue.valueOf(5),
"local a\n" + "local w\n" + "repeat\n" + " a = w\n" + "until not a\n" + "return 5\n");
}
@Test
public void testLoopVarUpvalues() {
runFragment(LuaValue.valueOf("b"),
"local env = {}\n" + "for a,b in pairs(_G) do\n" + " c = function()\n" + " return b\n"
+ " end\n" + "end\n" + "local e = env\n" + "local f = {a='b'}\n" + "for k,v in pairs(f) do\n"
+ " return env[k] or v\n" + "end\n");
}
@Test
public void testPhiVarUpvalue() {
runFragment(LuaValue.valueOf(2), "local a = 1\n" + "local function b()\n" + " a = a + 1\n"
+ " return function() end\n" + "end\n" + "for i in b() do\n" + " a = 3\n" + "end\n" + "return a\n");
}
@Test
public void testUpvaluesInElseClauses() {
runFragment(LuaValue.valueOf(111),
"if a then\n" + " foo(bar)\n" + "elseif _G then\n" + " local x = 111\n" + " if d then\n"
+ " foo(bar)\n" + " else\n" + " local y = function()\n" + " return x\n"
+ " end\n" + " return y()\n" + " end\n" + "end\n");
}
@Test
public void testUpvalueInDoBlock() {
runFragment(LuaValue.NONE,
"do\n" + " local x = 10\n" + " function g()\n" + " return x\n" + " end\n" + "end\n" + "g()\n");
}
@Test
public void testNullError() {
runFragment(LuaValue.varargsOf(LuaValue.FALSE, LuaValue.NIL), "return pcall(error)\n");
}
@Test
public void testFindWithOffset() {
runFragment(LuaValue.varargsOf(LuaValue.valueOf(8), LuaValue.valueOf(5)), "string = \"abcdef:ghi\"\n"
+ "substring = string:sub(3)\n" + "idx = substring:find(\":\")\n" + "return #substring, idx\n");
}
@Test
public void testErrorArgIsString() {
runFragment(LuaValue.varargsOf(LuaValue.valueOf("string"), LuaValue.valueOf("c")),
"a,b = pcall(error, 'c'); return type(b), b\n");
}
@Test
public void testErrorArgIsNil() {
runFragment(LuaValue.varargsOf(LuaValue.valueOf("nil"), LuaValue.NIL),
"a,b = pcall(error); return type(b), b\n");
}
@Test
public void testErrorArgIsTable() {
runFragment(LuaValue.varargsOf(LuaValue.valueOf("table"), LuaValue.valueOf("d")),
"a,b = pcall(error, {c='d'}); return type(b), b.c\n");
}
@Test
public void testErrorArgIsNumber() {
runFragment(LuaValue.varargsOf(LuaValue.valueOf("string"), LuaValue.valueOf("1")),
"a,b = pcall(error, 1); return type(b), b\n");
}
@Test
public void testErrorArgIsBool() {
runFragment(LuaValue.varargsOf(LuaValue.valueOf("boolean"), LuaValue.TRUE),
"a,b = pcall(error, true); return type(b), b\n");
}
@Test
public void testBalancedMatchOnEmptyString() {
runFragment(LuaValue.NIL, "return (\"\"):match(\"%b''\")\n");
}
@Test
public void testReturnValueForTableRemove() {
runFragment(LuaValue.NONE, "return table.remove({ })");
}
@Test
public void testTypeOfTableRemoveReturnValue() {
runFragment(LuaValue.valueOf("nil"), "local k = table.remove({ }) return type(k)");
}
@Test
public void testVarargBugReport() {
runFragment(
LuaValue.varargsOf(new LuaValue[] { LuaValue.valueOf(1), LuaValue.valueOf(2), LuaValue.valueOf(3) }),
"local i = function(...) return ... end\n" + "local v1, v2, v3 = i(1, 2, 3)\n" + "return v1, v2, v3");
}
}
}

View File

@@ -0,0 +1,78 @@
/*******************************************************************************
* Copyright (c) 2015 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.jse;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import java.io.InputStream;
import java.io.Reader;
import org.junit.jupiter.api.Test;
import org.luaj.vm2.Globals;
import org.luaj.vm2.LuaString;
import org.luaj.vm2.lib.jse.JsePlatform;
import org.luaj.vm2.server.Launcher;
import org.luaj.vm2.server.LuajClassLoader;
// Tests using class loading orders that have caused problems for some use cases.
class LoadOrderTest {
@Test
void testLoadGlobalsFirst() {
Globals g = JsePlatform.standardGlobals();
assertNotNull(g);
}
@Test
void testLoadStringFirst() {
LuaString BAR = LuaString.valueOf("bar");
assertNotNull(BAR);
}
public static class TestLauncherLoadStringFirst implements Launcher {
// Static initializer that causes LuaString->LuaValue->LuaString
private static final LuaString FOO = LuaString.valueOf("foo");
@Override
public Object[] launch(String script, Object[] arg) {
return new Object[] { FOO };
}
@Override
public Object[] launch(InputStream script, Object[] arg) {
return null;
}
@Override
public Object[] launch(Reader script, Object[] arg) {
return null;
}
}
@Test
void testClassLoadsStringFirst() throws Exception {
Launcher launcher = LuajClassLoader.NewLauncher(TestLauncherLoadStringFirst.class);
Object[] results = launcher.launch("foo", null);
assertNotNull(results);
}
}

View File

@@ -0,0 +1,90 @@
/*******************************************************************************
* 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.jse;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.fail;
import java.io.Reader;
import java.io.StringReader;
import org.junit.jupiter.api.Test;
import org.luaj.vm2.Globals;
import org.luaj.vm2.LuaClosure;
import org.luaj.vm2.LuaFunction;
import org.luaj.vm2.LuaTable;
import org.luaj.vm2.LuaValue;
import org.luaj.vm2.Prototype;
import org.luaj.vm2.lib.ZeroArgFunction;
import org.luaj.vm2.lib.jse.JsePlatform;
class LuaPrototypeTest {
private Prototype createPrototype(String script, String name) {
try {
Globals globals = JsePlatform.standardGlobals();
Reader reader = new StringReader(script);
return globals.compilePrototype(reader, name);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
fail(e.toString());
return null;
}
}
@Test
void testFunctionClosureThreadEnv() {
// set up suitable environments for execution
LuaValue aaa = LuaValue.valueOf("aaa");
LuaValue eee = LuaValue.valueOf("eee");
final Globals globals = JsePlatform.standardGlobals();
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, globals });
newenv.setmetatable(mt);
globals.set("a", aaa);
newenv.set("a", eee);
// function tests
{
LuaFunction f = new ZeroArgFunction() {
@Override
public LuaValue call() { return globals.get("a"); }
};
assertEquals(aaa, f.call());
}
// closure tests
{
Prototype p = createPrototype("return a\n", "closuretester");
LuaClosure c = new LuaClosure(p, globals);
// Test that a clusure with a custom enviroment uses that environment.
assertEquals(aaa, c.call());
c = new LuaClosure(p, newenv);
assertEquals(newenv, c.upValues[0].getValue());
assertEquals(eee, c.call());
}
}
}

View File

@@ -0,0 +1,186 @@
/*******************************************************************************
* Copyright (c) 2012 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.jse;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertNull;
import java.lang.ref.WeakReference;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.luaj.vm2.Globals;
import org.luaj.vm2.LuaThread;
import org.luaj.vm2.LuaValue;
import org.luaj.vm2.Varargs;
import org.luaj.vm2.lib.OneArgFunction;
import org.luaj.vm2.lib.jse.JsePlatform;
class OrphanedThreadTest {
Globals globals;
LuaThread luathread;
LuaValue function;
WeakReference<LuaThread> luathr_ref;
WeakReference<LuaValue> func_ref;
@BeforeEach
protected void setUp() throws Exception {
LuaThread.thread_orphan_check_interval = 5;
globals = JsePlatform.standardGlobals();
}
@AfterEach
protected void tearDown() {
LuaThread.thread_orphan_check_interval = 30000;
}
@Test
void testCollectOrphanedNormalThread() throws Exception {
function = new NormalFunction(globals);
doTest(LuaValue.TRUE, LuaValue.ZERO);
}
@Test
void testCollectOrphanedEarlyCompletionThread() throws Exception {
function = new EarlyCompletionFunction(globals);
doTest(LuaValue.TRUE, LuaValue.ZERO);
}
@Test
void testCollectOrphanedAbnormalThread() throws Exception {
function = new AbnormalFunction(globals);
doTest(LuaValue.FALSE, LuaValue.valueOf("abnormal condition"));
}
@Test
void testCollectOrphanedClosureThread() throws Exception {
String script = "print('in closure, arg is '..(...))\n" + "arg = coroutine.yield(1)\n"
+ "print('in closure.2, arg is '..arg)\n" + "arg = coroutine.yield(0)\n"
+ "print('leakage in closure.3, arg is '..arg)\n" + "return 'done'\n";
function = globals.load(script, "script");
doTest(LuaValue.TRUE, LuaValue.ZERO);
}
@Test
void testCollectOrphanedPcallClosureThread() throws Exception {
String script = "f = function(x)\n" + " print('in pcall-closure, arg is '..(x))\n"
+ " arg = coroutine.yield(1)\n" + " print('in pcall-closure.2, arg is '..arg)\n"
+ " arg = coroutine.yield(0)\n" + " print('leakage in pcall-closure.3, arg is '..arg)\n"
+ " return 'done'\n" + "end\n" + "print( 'pcall-closre.result:', pcall( f, ... ) )\n";
function = globals.load(script, "script");
doTest(LuaValue.TRUE, LuaValue.ZERO);
}
@Test
void testCollectOrphanedLoadCloasureThread() throws Exception {
String script = "t = { \"print \", \"'hello, \", \"world'\", }\n" + "i = 0\n" + "arg = ...\n"
+ "f = function()\n" + " i = i + 1\n" + " print('in load-closure, arg is', arg, 'next is', t[i])\n"
+ " arg = coroutine.yield(1)\n" + " return t[i]\n" + "end\n" + "load(f)()\n";
function = globals.load(script, "script");
doTest(LuaValue.TRUE, LuaValue.ONE);
}
private void doTest(LuaValue status2, LuaValue value2) throws Exception {
luathread = new LuaThread(globals, function);
luathr_ref = new WeakReference<>(luathread);
func_ref = new WeakReference<>(function);
assertNotNull(luathr_ref.get());
// resume two times
Varargs a = luathread.resume(LuaValue.valueOf("foo"));
assertEquals(LuaValue.ONE, a.arg(2));
assertEquals(LuaValue.TRUE, a.arg1());
a = luathread.resume(LuaValue.valueOf("bar"));
assertEquals(value2, a.arg(2));
assertEquals(status2, a.arg1());
// drop strong references
luathread = null;
function = null;
// gc
for (int i = 0; i < 100 && (luathr_ref.get() != null || func_ref.get() != null); i++) {
Runtime.getRuntime().gc();
Thread.sleep(5);
}
// check reference
assertNull(luathr_ref.get());
assertNull(func_ref.get());
}
static class NormalFunction extends OneArgFunction {
final Globals globals;
public NormalFunction(Globals globals) {
this.globals = globals;
}
@Override
public LuaValue call(LuaValue arg) {
System.out.println("in normal.1, arg is " + arg);
arg = globals.yield(ONE).arg1();
System.out.println("in normal.2, arg is " + arg);
arg = globals.yield(ZERO).arg1();
System.out.println("in normal.3, arg is " + arg);
return NONE;
}
}
static class EarlyCompletionFunction extends OneArgFunction {
final Globals globals;
public EarlyCompletionFunction(Globals globals) {
this.globals = globals;
}
@Override
public LuaValue call(LuaValue arg) {
System.out.println("in early.1, arg is " + arg);
arg = globals.yield(ONE).arg1();
System.out.println("in early.2, arg is " + arg);
return ZERO;
}
}
static class AbnormalFunction extends OneArgFunction {
final Globals globals;
public AbnormalFunction(Globals globals) {
this.globals = globals;
}
@Override
public LuaValue call(LuaValue arg) {
System.out.println("in abnormal.1, arg is " + arg);
arg = globals.yield(ONE).arg1();
System.out.println("in abnormal.2, arg is " + arg);
error("abnormal condition");
return ZERO;
}
}
}

View File

@@ -0,0 +1,96 @@
package org.luaj.jse;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.fail;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.luaj.jse.require.RequireSampleClassCastExcep;
import org.luaj.jse.require.RequireSampleLoadLuaError;
import org.luaj.jse.require.RequireSampleLoadRuntimeExcep;
import org.luaj.jse.require.RequireSampleSuccess;
import org.luaj.vm2.LuaError;
import org.luaj.vm2.LuaTable;
import org.luaj.vm2.LuaValue;
import org.luaj.vm2.lib.jse.JsePlatform;
class RequireClassTest {
private LuaTable globals;
private LuaValue require;
@BeforeEach
public void setUp() {
globals = JsePlatform.standardGlobals();
require = globals.get("require");
}
@Test
void testLoadClass() {
LuaValue result = globals.load(new RequireSampleSuccess());
assertEquals("require-sample-success-", result.tojstring());
}
@Test
void testRequireClassSuccess() {
LuaValue result = require.call(LuaValue.valueOf(RequireSampleSuccess.class.getName()));
assertEquals("require-sample-success-" + RequireSampleSuccess.class.getName(), result.tojstring());
result = require.call(LuaValue.valueOf(RequireSampleSuccess.class.getName()));
assertEquals("require-sample-success-" + RequireSampleSuccess.class.getName(), result.tojstring());
}
@Test
void testRequireClassLoadLuaError() {
try {
LuaValue result = require.call(LuaValue.valueOf(RequireSampleLoadLuaError.class.getName()));
fail("incorrectly loaded class that threw lua error");
} catch (LuaError le) {
assertEquals("sample-load-lua-error", le.getMessage());
}
try {
LuaValue result = require.call(LuaValue.valueOf(RequireSampleLoadLuaError.class.getName()));
fail("incorrectly loaded class that threw lua error");
} catch (LuaError le) {
assertEquals("loop or previous error loading module '" + RequireSampleLoadLuaError.class.getName() + "'",
le.getMessage());
}
}
@Test
void testRequireClassLoadRuntimeException() {
try {
LuaValue result = require.call(LuaValue.valueOf(RequireSampleLoadRuntimeExcep.class.getName()));
fail("incorrectly loaded class that threw runtime exception");
} catch (RuntimeException le) {
assertEquals("sample-load-runtime-exception", le.getMessage());
}
try {
LuaValue result = require.call(LuaValue.valueOf(RequireSampleLoadRuntimeExcep.class.getName()));
fail("incorrectly loaded class that threw runtime exception");
} catch (LuaError le) {
assertEquals(
"loop or previous error loading module '" + RequireSampleLoadRuntimeExcep.class.getName() + "'",
le.getMessage());
}
}
@Test
void testRequireClassClassCastException() {
try {
LuaValue result = require.call(LuaValue.valueOf(RequireSampleClassCastExcep.class.getName()));
fail("incorrectly loaded class that threw class cast exception");
} catch (LuaError le) {
String msg = le.getMessage();
if (msg.indexOf("not found") < 0)
fail("expected 'not found' message but got " + msg);
}
try {
LuaValue result = require.call(LuaValue.valueOf(RequireSampleClassCastExcep.class.getName()));
fail("incorrectly loaded class that threw class cast exception");
} catch (LuaError le) {
String msg = le.getMessage();
if (msg.indexOf("not found") < 0)
fail("expected 'not found' message but got " + msg);
}
}
}

View File

@@ -0,0 +1,96 @@
package org.luaj.jse;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.junit.jupiter.api.Assertions.fail;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.luaj.vm2.Globals;
import org.luaj.vm2.LuaDouble;
import org.luaj.vm2.LuaInteger;
import org.luaj.vm2.LuaValue;
import org.luaj.vm2.lib.jse.JsePlatform;
class SimpleLuaCallsTest {
private Globals globals;
@BeforeEach
protected void setUp() throws Exception {
globals = JsePlatform.standardGlobals();
}
private void doTest(String script) {
try {
LuaValue c = globals.load(script, "script");
c.call();
} catch (Exception e) {
fail("i/o exception: " + e);
}
}
@Test
void testTrivial() {
String s = "print( 2 )\n";
doTest(s);
}
@Test
void testAlmostTrivial() {
String s = "print( 2 )\n" + "print( 3 )\n";
doTest(s);
}
@Test
void testSimple() {
String s = "print( 'hello, world' )\n" + "for i = 2,4 do\n" + " print( 'i', i )\n" + "end\n";
doTest(s);
}
@Test
void testBreak() {
String s = "a=1\n" + "while true do\n" + " if a>10 then\n" + " break\n" + " end\n" + " a=a+1\n"
+ " print( a )\n" + "end\n";
doTest(s);
}
@Test
void testShebang() {
String s = "#!../lua\n" + "print( 2 )\n";
doTest(s);
}
@Test
void testInlineTable() {
String s = "A = {g=10}\n" + "print( A )\n";
doTest(s);
}
@Test
void testEqualsAnd() {
String s = "print( 1 == b and b )\n";
doTest(s);
}
private static final int[] samehash = { 0, 1, -1, 2, -2, 4, 8, 16, 32, Integer.MAX_VALUE, Integer.MIN_VALUE };
private static final double[] diffhash = { .5, 1, 1.5, 1, .5, 1.5, 1.25, 2.5 };
@Test
void testDoubleHashCode() {
for (int i = 0; i < samehash.length; i++) {
LuaValue j = LuaInteger.valueOf(samehash[i]);
LuaValue d = LuaDouble.valueOf(samehash[i]);
int hj = j.hashCode();
int hd = d.hashCode();
assertEquals(hj, hd);
}
for (int i = 0; i < diffhash.length; i += 2) {
LuaValue c = LuaValue.valueOf(diffhash[i+0]);
LuaValue d = LuaValue.valueOf(diffhash[i+1]);
int hc = c.hashCode();
int hd = d.hashCode();
assertTrue(hc != hd, "hash codes are same: " + hc);
}
}
}

View File

@@ -0,0 +1,47 @@
package org.luaj.jse;
import static org.junit.jupiter.api.Assertions.assertEquals;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.luaj.vm2.LuaString;
import org.luaj.vm2.LuaValue;
import org.luaj.vm2.lib.jse.JsePlatform;
class StringMatchingTest {
@BeforeEach
protected void setUp() throws Exception {
JsePlatform.standardGlobals();
}
@Test
void testMatchShortPatterns() {
LuaValue[] args = { LuaString.valueOf("%bxy") };
LuaString empty = LuaString.valueOf("");
LuaString a = LuaString.valueOf("a");
LuaString ax = LuaString.valueOf("ax");
LuaString axb = LuaString.valueOf("axb");
LuaString axby = LuaString.valueOf("axby");
LuaString xbya = LuaString.valueOf("xbya");
LuaString bya = LuaString.valueOf("bya");
LuaString xby = LuaString.valueOf("xby");
LuaString axbya = LuaString.valueOf("axbya");
LuaValue nil = LuaValue.NIL;
assertEquals(nil, empty.invokemethod("match", args));
assertEquals(nil, a.invokemethod("match", args));
assertEquals(nil, ax.invokemethod("match", args));
assertEquals(nil, axb.invokemethod("match", args));
assertEquals(xby, axby.invokemethod("match", args));
assertEquals(xby, xbya.invokemethod("match", args));
assertEquals(nil, bya.invokemethod("match", args));
assertEquals(xby, xby.invokemethod("match", args));
assertEquals(xby, axbya.invokemethod("match", args));
assertEquals(xby, axbya.substring(0, 4).invokemethod("match", args));
assertEquals(nil, axbya.substring(0, 3).invokemethod("match", args));
assertEquals(xby, axbya.substring(1, 5).invokemethod("match", args));
assertEquals(nil, axbya.substring(2, 5).invokemethod("match", args));
}
}

View File

@@ -0,0 +1,43 @@
/*******************************************************************************
* Copyright (c) 2014 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.jse;
import static org.junit.jupiter.api.Assertions.assertEquals;
import org.junit.jupiter.api.Test;
import org.luaj.vm2.Globals;
import org.luaj.vm2.LuaValue;
import org.luaj.vm2.lib.jse.JsePlatform;
class UTF8StreamTest {
@Test
void testUtf8CharsInStream() {
String script = "x = \"98\u00b0: today's temp!\"\n" + "print('x = ', x)\n" + "return x";
Globals globals = JsePlatform.standardGlobals();
LuaValue chunk = globals.load(script);
LuaValue result = chunk.call();
String str = result.tojstring();
assertEquals("98\u00b0: today's temp!", str);
}
}

View File

@@ -0,0 +1,18 @@
package org.luaj.jse.require;
import org.luaj.vm2.LuaValue;
/**
* This should fail while trying to load via "require() because it is not a
* LibFunction"
*
*/
public class RequireSampleClassCastExcep {
public RequireSampleClassCastExcep() {
}
public LuaValue call() {
return LuaValue.valueOf("require-sample-class-cast-excep");
}
}

View File

@@ -0,0 +1,20 @@
package org.luaj.jse.require;
import org.luaj.vm2.LuaValue;
import org.luaj.vm2.lib.ZeroArgFunction;
/**
* This should fail while trying to load via "require()" because it throws a
* LuaError
*
*/
public class RequireSampleLoadLuaError extends ZeroArgFunction {
public RequireSampleLoadLuaError() {
}
public LuaValue call() {
error("sample-load-lua-error");
return LuaValue.valueOf("require-sample-load-lua-error");
}
}

View File

@@ -0,0 +1,19 @@
package org.luaj.jse.require;
import org.luaj.vm2.LuaValue;
import org.luaj.vm2.lib.ZeroArgFunction;
/**
* This should fail while trying to load via "require()" because it throws a
* RuntimeException
*
*/
public class RequireSampleLoadRuntimeExcep extends ZeroArgFunction {
public RequireSampleLoadRuntimeExcep() {
}
public LuaValue call() {
throw new RuntimeException("sample-load-runtime-exception");
}
}

View File

@@ -0,0 +1,19 @@
package org.luaj.jse.require;
import org.luaj.vm2.LuaValue;
import org.luaj.vm2.lib.TwoArgFunction;
/**
* This should succeed as a library that can be loaded dynamically via
* "require()"
*/
public class RequireSampleSuccess extends TwoArgFunction {
public RequireSampleSuccess() {
}
public LuaValue call(LuaValue modname, LuaValue env) {
env.checkglobals();
return LuaValue.valueOf("require-sample-success-" + modname.tojstring());
}
}

View File

@@ -0,0 +1,22 @@
package org.luaj.vm2.lib.jse;
import static org.junit.jupiter.api.Assertions.assertEquals;
import org.junit.jupiter.api.Test;
import org.luaj.vm2.Globals;
import org.luaj.vm2.LuaValue;
import org.luaj.vm2.Varargs;
class JsePlatformTest {
@Test
void testLuaMainPassesArguments() {
Globals globals = JsePlatform.standardGlobals();
LuaValue chunk = globals.load("return #arg, arg.n, arg[2], arg[1]");
Varargs results = JsePlatform.luaMain(chunk, new String[] { "aaa", "bbb" });
assertEquals(results.narg(), 4);
assertEquals(results.arg(1), LuaValue.valueOf(2));
assertEquals(results.arg(2), LuaValue.valueOf(2));
assertEquals(results.arg(3), LuaValue.valueOf("bbb"));
assertEquals(results.arg(4), LuaValue.valueOf("aaa"));
}
}

View File

@@ -0,0 +1,531 @@
package org.luaj.vm2.lib.jse;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNotSame;
import static org.junit.jupiter.api.Assertions.assertSame;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.junit.jupiter.api.Assertions.fail;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.luaj.vm2.LuaError;
import org.luaj.vm2.LuaInteger;
import org.luaj.vm2.LuaString;
import org.luaj.vm2.LuaTable;
import org.luaj.vm2.LuaValue;
import org.luaj.vm2.Varargs;
class LuaJavaCoercionTest {
private static LuaValue globals;
private static LuaValue ZERO = LuaValue.ZERO;
private static LuaValue ONE = LuaValue.ONE;
private static LuaValue TWO = LuaValue.valueOf(2);
private static LuaValue THREE = LuaValue.valueOf(3);
private static LuaString LENGTH = LuaString.valueOf("length");
@BeforeEach
protected void setUp() throws Exception {
globals = JsePlatform.standardGlobals();
}
@Test
void testJavaIntToLuaInt() {
Integer i = Integer.valueOf(777);
LuaValue v = CoerceJavaToLua.coerce(i);
assertEquals(LuaInteger.class, v.getClass());
assertEquals(777, v.toint());
}
@Test
void testLuaIntToJavaInt() {
LuaInteger i = LuaInteger.valueOf(777);
Object o = CoerceLuaToJava.coerce(i, int.class);
assertEquals(Integer.class, o.getClass());
assertEquals(777, ((Number) o).intValue());
o = CoerceLuaToJava.coerce(i, Integer.class);
assertEquals(Integer.class, o.getClass());
assertEquals(new Integer(777), o);
}
@Test
void testJavaStringToLuaString() {
String s = new String("777");
LuaValue v = CoerceJavaToLua.coerce(s);
assertEquals(LuaString.class, v.getClass());
assertEquals("777", v.toString());
}
@Test
void testLuaStringToJavaString() {
LuaString s = LuaValue.valueOf("777");
Object o = CoerceLuaToJava.coerce(s, String.class);
assertEquals(String.class, o.getClass());
assertEquals("777", o);
}
@Test
void testJavaClassToLuaUserdata() {
LuaValue va = CoerceJavaToLua.coerce(ClassA.class);
LuaValue va1 = CoerceJavaToLua.coerce(ClassA.class);
LuaValue vb = CoerceJavaToLua.coerce(ClassB.class);
assertSame(va, va1);
assertNotSame(va, vb);
LuaValue vi = CoerceJavaToLua.coerce(new ClassA());
assertNotSame(va, vi);
assertTrue(vi.isuserdata());
assertTrue(vi.isuserdata(ClassA.class));
assertFalse(vi.isuserdata(ClassB.class));
LuaValue vj = CoerceJavaToLua.coerce(new ClassB());
assertNotSame(vb, vj);
assertTrue(vj.isuserdata());
assertFalse(vj.isuserdata(ClassA.class));
assertTrue(vj.isuserdata(ClassB.class));
}
static class ClassA {
}
static class ClassB {
}
@Test
void testJavaIntArrayToLuaTable() {
int[] i = { 222, 333 };
LuaValue v = CoerceJavaToLua.coerce(i);
assertEquals(JavaArray.class, v.getClass());
assertEquals(LuaInteger.valueOf(222), v.get(ONE));
assertEquals(LuaInteger.valueOf(333), v.get(TWO));
assertEquals(TWO, v.get(LENGTH));
assertEquals(LuaValue.NIL, v.get(THREE));
assertEquals(LuaValue.NIL, v.get(ZERO));
v.set(ONE, LuaInteger.valueOf(444));
v.set(TWO, LuaInteger.valueOf(555));
assertEquals(444, i[0]);
assertEquals(555, i[1]);
assertEquals(LuaInteger.valueOf(444), v.get(ONE));
assertEquals(LuaInteger.valueOf(555), v.get(TWO));
try {
v.set(ZERO, LuaInteger.valueOf(777));
fail("array bound exception not thrown");
} catch (LuaError lee) {
// expected
}
try {
v.set(THREE, LuaInteger.valueOf(777));
fail("array bound exception not thrown");
} catch (LuaError lee) {
// expected
}
}
@Test
void testLuaTableToJavaIntArray() {
LuaTable t = new LuaTable();
t.set(1, LuaInteger.valueOf(222));
t.set(2, LuaInteger.valueOf(333));
int[] i = null;
Object o = CoerceLuaToJava.coerce(t, int[].class);
assertEquals(int[].class, o.getClass());
i = (int[]) o;
assertEquals(2, i.length);
assertEquals(222, i[0]);
assertEquals(333, i[1]);
}
@Test
void testIntArrayScoringTables() {
int a = 5;
LuaValue la = LuaInteger.valueOf(a);
LuaTable tb = new LuaTable();
tb.set(1, la);
LuaTable tc = new LuaTable();
tc.set(1, tb);
int saa = CoerceLuaToJava.getCoercion(int.class).score(la);
int sab = CoerceLuaToJava.getCoercion(int[].class).score(la);
int sac = CoerceLuaToJava.getCoercion(int[][].class).score(la);
assertTrue(saa < sab);
assertTrue(saa < sac);
int sba = CoerceLuaToJava.getCoercion(int.class).score(tb);
int sbb = CoerceLuaToJava.getCoercion(int[].class).score(tb);
int sbc = CoerceLuaToJava.getCoercion(int[][].class).score(tb);
assertTrue(sbb < sba);
assertTrue(sbb < sbc);
int sca = CoerceLuaToJava.getCoercion(int.class).score(tc);
int scb = CoerceLuaToJava.getCoercion(int[].class).score(tc);
int scc = CoerceLuaToJava.getCoercion(int[][].class).score(tc);
assertTrue(scc < sca);
assertTrue(scc < scb);
}
@Test
void testIntArrayScoringUserdata() {
int a = 5;
int[] b = { 44, 66 };
int[][] c = { { 11, 22 }, { 33, 44 } };
LuaValue va = CoerceJavaToLua.coerce(a);
LuaValue vb = CoerceJavaToLua.coerce(b);
LuaValue vc = CoerceJavaToLua.coerce(c);
int vaa = CoerceLuaToJava.getCoercion(int.class).score(va);
int vab = CoerceLuaToJava.getCoercion(int[].class).score(va);
int vac = CoerceLuaToJava.getCoercion(int[][].class).score(va);
assertTrue(vaa < vab);
assertTrue(vaa < vac);
int vba = CoerceLuaToJava.getCoercion(int.class).score(vb);
int vbb = CoerceLuaToJava.getCoercion(int[].class).score(vb);
int vbc = CoerceLuaToJava.getCoercion(int[][].class).score(vb);
assertTrue(vbb < vba);
assertTrue(vbb < vbc);
int vca = CoerceLuaToJava.getCoercion(int.class).score(vc);
int vcb = CoerceLuaToJava.getCoercion(int[].class).score(vc);
int vcc = CoerceLuaToJava.getCoercion(int[][].class).score(vc);
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];
}
}
@Test
void testMatchVoidArgs() {
LuaValue v = CoerceJavaToLua.coerce(new SampleClass());
LuaValue result = v.method("sample");
assertEquals("void-args", result.toString());
}
@Test
void testMatchIntArgs() {
LuaValue v = CoerceJavaToLua.coerce(new SampleClass());
LuaValue arg = CoerceJavaToLua.coerce(new Integer(123));
LuaValue result = v.method("sample", arg);
assertEquals("int-args 123", result.toString());
}
@Test
void testMatchIntArrayArgs() {
LuaValue v = CoerceJavaToLua.coerce(new SampleClass());
LuaValue arg = CoerceJavaToLua.coerce(new int[] { 345, 678 });
LuaValue result = v.method("sample", arg);
assertEquals("int-array-args 345,678", result.toString());
}
@Test
void testMatchIntArrayArrayArgs() {
LuaValue v = CoerceJavaToLua.coerce(new SampleClass());
LuaValue arg = CoerceJavaToLua.coerce(new int[][] { { 22, 33 }, { 44, 55 } });
LuaValue result = v.method("sample", arg);
assertEquals("int-array-array-args 22,33,44,55", result.toString());
}
public static final class SomeException extends RuntimeException {
public SomeException(String message) {
super(message);
}
}
public static final class SomeClass {
public static void someMethod() {
throw new SomeException("this is some message");
}
}
@Test
void testExceptionMessage() {
String script = "local c = luajava.bindClass( \"" + SomeClass.class.getName() + "\" )\n"
+ "return pcall( c.someMethod, c )";
Varargs vresult = globals.get("load").call(LuaValue.valueOf(script)).invoke(LuaValue.NONE);
LuaValue status = vresult.arg1();
LuaValue message = vresult.arg(2);
assertEquals(LuaValue.FALSE, status);
int index = message.toString().indexOf("this is some message");
assertTrue(index >= 0, "bad message: " + message);
}
@Test
void testLuaErrorCause() {
String script = "luajava.bindClass( \"" + SomeClass.class.getName() + "\"):someMethod()";
LuaValue chunk = globals.get("load").call(LuaValue.valueOf(script));
try {
chunk.invoke(LuaValue.NONE);
fail("call should not have succeeded");
} catch (LuaError lee) {
Throwable c = lee.getCause();
assertEquals(SomeException.class, c.getClass());
}
}
public interface VarArgsInterface {
public String varargsMethod(String a, String... v);
public String arrayargsMethod(String a, String[] v);
}
@Test
void testVarArgsProxy() {
String script = "return luajava.createProxy( \"" + VarArgsInterface.class.getName() + "\", \n" + "{\n"
+ " varargsMethod = function(a,...)\n" + " return table.concat({a,...},'-')\n" + " end,\n"
+ " arrayargsMethod = function(a,array)\n" + " return tostring(a)..(array and \n"
+ " ('-'..tostring(array.length)\n" + " ..'-'..tostring(array[1])\n"
+ " ..'-'..tostring(array[2])\n" + " ) or '-nil')\n" + " end,\n" + "} )\n";
Varargs chunk = globals.get("load").call(LuaValue.valueOf(script));
if (!chunk.arg1().toboolean())
fail(chunk.arg(2).toString());
LuaValue result = chunk.arg1().call();
Object u = result.touserdata();
VarArgsInterface v = (VarArgsInterface) u;
assertEquals("foo", v.varargsMethod("foo"));
assertEquals("foo-bar", v.varargsMethod("foo", "bar"));
assertEquals("foo-bar-etc", v.varargsMethod("foo", "bar", "etc"));
assertEquals("foo-0-nil-nil", v.arrayargsMethod("foo", new String[0]));
assertEquals("foo-1-bar-nil", v.arrayargsMethod("foo", new String[] { "bar" }));
assertEquals("foo-2-bar-etc", v.arrayargsMethod("foo", new String[] { "bar", "etc" }));
assertEquals("foo-3-bar-etc", v.arrayargsMethod("foo", new String[] { "bar", "etc", "etc" }));
assertEquals("foo-nil", v.arrayargsMethod("foo", null));
}
@Test
void testBigNum() {
String script = "bigNumA = luajava.newInstance('java.math.BigDecimal','12345678901234567890');\n"
+ "bigNumB = luajava.newInstance('java.math.BigDecimal','12345678901234567890');\n"
+ "bigNumC = bigNumA:multiply(bigNumB);\n" +
//"print(bigNumA:toString())\n" +
//"print(bigNumB:toString())\n" +
//"print(bigNumC:toString())\n" +
"return bigNumA:toString(), bigNumB:toString(), bigNumC:toString()";
Varargs chunk = globals.get("load").call(LuaValue.valueOf(script));
if (!chunk.arg1().toboolean())
fail(chunk.arg(2).toString());
Varargs results = chunk.arg1().invoke();
int nresults = results.narg();
String sa = results.tojstring(1);
String sb = results.tojstring(2);
String sc = results.tojstring(3);
assertEquals(3, nresults);
assertEquals("12345678901234567890", sa);
assertEquals("12345678901234567890", sb);
assertEquals("152415787532388367501905199875019052100", sc);
}
public interface IA {
}
public interface IB extends IA {
}
public interface IC extends IB {
}
public static class A implements IA {
}
public static class B extends A implements IB {
public String set(Object x) { return "set(Object) "; }
public String set(String x) { return "set(String) " + x; }
public String set(A x) { return "set(A) "; }
public String set(B x) { return "set(B) "; }
public String set(C x) { return "set(C) "; }
public String set(byte x) { return "set(byte) " + x; }
public String set(char x) { return "set(char) " + (int) x; }
public String set(short x) { return "set(short) " + x; }
public String set(int x) { return "set(int) " + x; }
public String set(long x) { return "set(long) " + x; }
public String set(float x) { return "set(float) " + x; }
public String set(double x) { return "set(double) " + x; }
public String setr(double x) { return "setr(double) " + x; }
public String setr(float x) { return "setr(float) " + x; }
public String setr(long x) { return "setr(long) " + x; }
public String setr(int x) { return "setr(int) " + x; }
public String setr(short x) { return "setr(short) " + x; }
public String setr(char x) { return "setr(char) " + (int) x; }
public String setr(byte x) { return "setr(byte) " + x; }
public String setr(C x) { return "setr(C) "; }
public String setr(B x) { return "setr(B) "; }
public String setr(A x) { return "setr(A) "; }
public String setr(String x) { return "setr(String) " + x; }
public String setr(Object x) { return "setr(Object) "; }
public Object getObject() { return new Object(); }
public String getString() { return "abc"; }
public byte[] getbytearray() { return new byte[] { 1, 2, 3 }; }
public A getA() { return new A(); }
public B getB() { return new B(); }
public C getC() { return new C(); }
public byte getbyte() { return 1; }
public char getchar() { return 65000; }
public short getshort() { return -32000; }
public int getint() { return 100000; }
public long getlong() { return 50000000000L; }
public float getfloat() { return 6.5f; }
public double getdouble() { return Math.PI; }
}
public static class C extends B implements IC {
}
public static class D extends C implements IA {
}
@Test
void testOverloadedJavaMethodObject() { doOverloadedMethodTest("Object", ""); }
@Test
void testOverloadedJavaMethodString() { doOverloadedMethodTest("String", "abc"); }
@Test
void testOverloadedJavaMethodA() { doOverloadedMethodTest("A", ""); }
@Test
void testOverloadedJavaMethodB() { doOverloadedMethodTest("B", ""); }
@Test
void testOverloadedJavaMethodC() { doOverloadedMethodTest("C", ""); }
@Test
void testOverloadedJavaMethodByte() { doOverloadedMethodTest("byte", "1"); }
@Test
void testOverloadedJavaMethodChar() { doOverloadedMethodTest("char", "65000"); }
@Test
void testOverloadedJavaMethodShort() { doOverloadedMethodTest("short", "-32000"); }
@Test
void testOverloadedJavaMethodInt() { doOverloadedMethodTest("int", "100000"); }
@Test
void testOverloadedJavaMethodLong() { doOverloadedMethodTest("long", "50000000000"); }
@Test
void testOverloadedJavaMethodFloat() { doOverloadedMethodTest("float", "6.5"); }
@Test
void testOverloadedJavaMethodDouble() { doOverloadedMethodTest("double", "3.141592653589793"); }
private void doOverloadedMethodTest(String typename, String value) {
String script = "local a = luajava.newInstance('" + B.class.getName() + "');\n" + "local b = a:set(a:get"
+ typename + "())\n" + "local c = a:setr(a:get" + typename + "())\n" + "return b,c";
Varargs chunk = globals.get("load").call(LuaValue.valueOf(script));
if (!chunk.arg1().toboolean())
fail(chunk.arg(2).toString());
Varargs results = chunk.arg1().invoke();
int nresults = results.narg();
assertEquals(2, nresults);
LuaValue b = results.arg(1);
LuaValue c = results.arg(2);
String sb = b.tojstring();
String sc = c.tojstring();
assertEquals("set(" + typename + ") " + value, sb);
assertEquals("setr(" + typename + ") " + value, sc);
}
@Test
void testClassInheritanceLevels() {
assertEquals(0, CoerceLuaToJava.inheritanceLevels(Object.class, Object.class));
assertEquals(1, CoerceLuaToJava.inheritanceLevels(Object.class, String.class));
assertEquals(1, CoerceLuaToJava.inheritanceLevels(Object.class, A.class));
assertEquals(2, CoerceLuaToJava.inheritanceLevels(Object.class, B.class));
assertEquals(3, CoerceLuaToJava.inheritanceLevels(Object.class, C.class));
assertEquals(CoerceLuaToJava.SCORE_UNCOERCIBLE, CoerceLuaToJava.inheritanceLevels(A.class, Object.class));
assertEquals(CoerceLuaToJava.SCORE_UNCOERCIBLE, CoerceLuaToJava.inheritanceLevels(A.class, String.class));
assertEquals(0, CoerceLuaToJava.inheritanceLevels(A.class, A.class));
assertEquals(1, CoerceLuaToJava.inheritanceLevels(A.class, B.class));
assertEquals(2, CoerceLuaToJava.inheritanceLevels(A.class, C.class));
assertEquals(CoerceLuaToJava.SCORE_UNCOERCIBLE, CoerceLuaToJava.inheritanceLevels(B.class, Object.class));
assertEquals(CoerceLuaToJava.SCORE_UNCOERCIBLE, CoerceLuaToJava.inheritanceLevels(B.class, String.class));
assertEquals(CoerceLuaToJava.SCORE_UNCOERCIBLE, CoerceLuaToJava.inheritanceLevels(B.class, A.class));
assertEquals(0, CoerceLuaToJava.inheritanceLevels(B.class, B.class));
assertEquals(1, CoerceLuaToJava.inheritanceLevels(B.class, C.class));
assertEquals(CoerceLuaToJava.SCORE_UNCOERCIBLE, CoerceLuaToJava.inheritanceLevels(C.class, Object.class));
assertEquals(CoerceLuaToJava.SCORE_UNCOERCIBLE, CoerceLuaToJava.inheritanceLevels(C.class, String.class));
assertEquals(CoerceLuaToJava.SCORE_UNCOERCIBLE, CoerceLuaToJava.inheritanceLevels(C.class, A.class));
assertEquals(CoerceLuaToJava.SCORE_UNCOERCIBLE, CoerceLuaToJava.inheritanceLevels(C.class, B.class));
assertEquals(0, CoerceLuaToJava.inheritanceLevels(C.class, C.class));
}
@Test
void testInterfaceInheritanceLevels() {
assertEquals(1, CoerceLuaToJava.inheritanceLevels(IA.class, A.class));
assertEquals(1, CoerceLuaToJava.inheritanceLevels(IB.class, B.class));
assertEquals(2, CoerceLuaToJava.inheritanceLevels(IA.class, B.class));
assertEquals(1, CoerceLuaToJava.inheritanceLevels(IC.class, C.class));
assertEquals(2, CoerceLuaToJava.inheritanceLevels(IB.class, C.class));
assertEquals(3, CoerceLuaToJava.inheritanceLevels(IA.class, C.class));
assertEquals(1, CoerceLuaToJava.inheritanceLevels(IA.class, D.class));
assertEquals(2, CoerceLuaToJava.inheritanceLevels(IC.class, D.class));
assertEquals(3, CoerceLuaToJava.inheritanceLevels(IB.class, D.class));
assertEquals(CoerceLuaToJava.SCORE_UNCOERCIBLE, CoerceLuaToJava.inheritanceLevels(IB.class, A.class));
assertEquals(CoerceLuaToJava.SCORE_UNCOERCIBLE, CoerceLuaToJava.inheritanceLevels(IC.class, A.class));
assertEquals(CoerceLuaToJava.SCORE_UNCOERCIBLE, CoerceLuaToJava.inheritanceLevels(IC.class, B.class));
assertEquals(CoerceLuaToJava.SCORE_UNCOERCIBLE, CoerceLuaToJava.inheritanceLevels(IB.class, IA.class));
assertEquals(1, CoerceLuaToJava.inheritanceLevels(IA.class, IB.class));
}
@Test
void testCoerceJavaToLuaLuaValue() {
assertSame(LuaValue.NIL, CoerceJavaToLua.coerce(LuaValue.NIL));
assertSame(LuaValue.ZERO, CoerceJavaToLua.coerce(LuaValue.ZERO));
assertSame(LuaValue.ONE, CoerceJavaToLua.coerce(LuaValue.ONE));
assertSame(LuaValue.INDEX, CoerceJavaToLua.coerce(LuaValue.INDEX));
LuaTable table = LuaValue.tableOf();
assertSame(table, CoerceJavaToLua.coerce(table));
}
@Test
void testCoerceJavaToLuaByeArray() {
byte[] bytes = "abcd".getBytes();
LuaValue value = CoerceJavaToLua.coerce(bytes);
assertEquals(LuaString.class, value.getClass());
assertEquals(LuaValue.valueOf("abcd"), value);
}
}

View File

@@ -0,0 +1,66 @@
package org.luaj.vm2.lib.jse;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.fail;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.luaj.vm2.Globals;
import org.luaj.vm2.LuaValue;
class LuajavaAccessibleMembersTest {
private Globals globals;
@BeforeEach
protected void setUp() throws Exception {
globals = JsePlatform.standardGlobals();
}
private String invokeScript(String script) {
try {
LuaValue c = globals.load(script, "script");
return c.call().tojstring();
} catch (Exception e) {
fail("exception: " + e);
return "failed";
}
}
@Test
void testAccessFromPrivateClassImplementedMethod() {
assertEquals("privateImpl-aaa-interface_method(bar)",
invokeScript("b = luajava.newInstance('" + TestClass.class.getName() + "');"
+ "a = b:create_PrivateImpl('aaa');" + "return a:interface_method('bar');"));
}
@Test
void testAccessFromPrivateClassPublicMethod() {
assertEquals("privateImpl-aaa-public_method", invokeScript("b = luajava.newInstance('"
+ TestClass.class.getName() + "');" + "a = b:create_PrivateImpl('aaa');" + "return a:public_method();"));
}
@Test
void testAccessFromPrivateClassGetPublicField() {
assertEquals("aaa", invokeScript("b = luajava.newInstance('" + TestClass.class.getName() + "');"
+ "a = b:create_PrivateImpl('aaa');" + "return a.public_field;"));
}
@Test
void testAccessFromPrivateClassSetPublicField() {
assertEquals("foo", invokeScript("b = luajava.newInstance('" + TestClass.class.getName() + "');"
+ "a = b:create_PrivateImpl('aaa');" + "a.public_field = 'foo';" + "return a.public_field;"));
}
@Test
void testAccessFromPrivateClassPublicConstructor() {
assertEquals("privateImpl-constructor", invokeScript("b = luajava.newInstance('" + TestClass.class.getName()
+ "');" + "c = b:get_PrivateImplClass();" + "return luajava.new(c);"));
}
@Test
void testAccessPublicEnum() {
assertEquals("class org.luaj.vm2.lib.jse.TestClass$SomeEnum",
invokeScript("b = luajava.newInstance('" + TestClass.class.getName() + "');" + "return b.SomeEnum"));
}
}

View File

@@ -0,0 +1,318 @@
package org.luaj.vm2.lib.jse;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertSame;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.junit.jupiter.api.Assertions.fail;
import org.junit.jupiter.api.Test;
import org.luaj.vm2.LuaError;
import org.luaj.vm2.LuaValue;
class LuajavaClassMembersTest {
public static class A {
protected A() {}
}
public static class B extends A {
public byte m_byte_field;
public int m_int_field;
public double m_double_field;
public String m_string_field;
protected B() {}
public B(int i) { m_int_field = i; }
public String setString(String x) { return "setString(String) " + x; }
public String getString() { return "abc"; }
public int getint() { return 100000; }
public String uniq() { return "uniq()"; }
public String uniqs(String s) { return "uniqs(string:" + s + ")"; }
public String uniqi(int i) { return "uniqi(int:" + i + ")"; }
public String uniqsi(String s, int i) { return "uniqsi(string:" + s + ",int:" + i + ")"; }
public String uniqis(int i, String s) { return "uniqis(int:" + i + ",string:" + s + ")"; }
public String pick() { return "pick()"; }
public String pick(String s) { return "pick(string:" + s + ")"; }
public String pick(int i) { return "pick(int:" + i + ")"; }
public String pick(String s, int i) { return "pick(string:" + s + ",int:" + i + ")"; }
public String pick(int i, String s) { return "pick(int:" + i + ",string:" + s + ")"; }
public static String staticpick() { return "static-pick()"; }
public static String staticpick(String s) { return "static-pick(string:" + s + ")"; }
public static String staticpick(int i) { return "static-pick(int:" + i + ")"; }
public static String staticpick(String s, int i) { return "static-pick(string:" + s + ",int:" + i + ")"; }
public static String staticpick(int i, String s) { return "static-pick(int:" + i + ",string:" + s + ")"; }
}
public static class C extends B {
public C() {}
public C(String s) { m_string_field = s; }
public C(int i) { m_int_field = i; }
public C(String s, int i) { m_string_field = s; m_int_field = i; }
@Override
public int getint() { return 200000; }
@Override
public String pick(String s) { return "class-c-pick(string:" + s + ")"; }
@Override
public String pick(int i) { return "class-c-pick(int:" + i + ")"; }
public static class D {
public static String name() { return "name-of-D"; }
}
}
static LuaValue ZERO = LuaValue.ZERO;
static LuaValue ONE = LuaValue.ONE;
static LuaValue PI = LuaValue.valueOf(Math.PI);
static LuaValue THREE = LuaValue.valueOf(3);
static LuaValue NUMS = LuaValue.valueOf(123);
static LuaValue ABC = LuaValue.valueOf("abc");
static LuaValue SOMEA = CoerceJavaToLua.coerce(new A());
static LuaValue SOMEB = CoerceJavaToLua.coerce(new B());
static LuaValue SOMEC = CoerceJavaToLua.coerce(new C());
@Test
void testSetByteField() {
B b = new B();
JavaInstance i = new JavaInstance(b);
i.set("m_byte_field", ONE);
assertEquals(1, b.m_byte_field);
assertEquals(ONE, i.get("m_byte_field"));
i.set("m_byte_field", PI);
assertEquals(3, b.m_byte_field);
assertEquals(THREE, i.get("m_byte_field"));
i.set("m_byte_field", ABC);
assertEquals(0, b.m_byte_field);
assertEquals(ZERO, i.get("m_byte_field"));
}
@Test
void testSetDoubleField() {
B b = new B();
JavaInstance i = new JavaInstance(b);
i.set("m_double_field", ONE);
assertEquals(1., b.m_double_field);
assertEquals(ONE, i.get("m_double_field"));
i.set("m_double_field", PI);
assertEquals(Math.PI, b.m_double_field);
assertEquals(PI, i.get("m_double_field"));
i.set("m_double_field", ABC);
assertEquals(0., b.m_double_field);
assertEquals(ZERO, i.get("m_double_field"));
}
@Test
void testNoFactory() {
JavaClass c = JavaClass.forClass(A.class);
try {
c.call();
fail("did not throw lua error as expected");
} catch (LuaError e) {
}
}
@Test
void testUniqueFactoryCoercible() {
JavaClass c = JavaClass.forClass(B.class);
assertEquals(JavaClass.class, c.getClass());
LuaValue constr = c.get("new");
assertEquals(JavaConstructor.class, constr.getClass());
LuaValue v = constr.call(NUMS);
Object b = v.touserdata();
assertEquals(B.class, b.getClass());
assertEquals(123, ((B) b).m_int_field);
Object b0 = constr.call().touserdata();
assertEquals(B.class, b0.getClass());
assertEquals(0, ((B) b0).m_int_field);
}
@Test
void testUniqueFactoryUncoercible() {
JavaClass f = JavaClass.forClass(B.class);
LuaValue constr = f.get("new");
assertEquals(JavaConstructor.class, constr.getClass());
try {
LuaValue v = constr.call(LuaValue.userdataOf(new Object()));
Object b = v.touserdata();
// fail( "did not throw lua error as expected" );
assertEquals(0, ((B) b).m_int_field);
} catch (LuaError e) {
}
}
@Test
void testOverloadedFactoryCoercible() {
JavaClass f = JavaClass.forClass(C.class);
LuaValue constr = f.get("new");
assertEquals(JavaConstructor.Overload.class, constr.getClass());
Object c = constr.call().touserdata();
Object ci = constr.call(LuaValue.valueOf(123)).touserdata();
Object cs = constr.call(LuaValue.valueOf("abc")).touserdata();
Object csi = constr.call(LuaValue.valueOf("def"), LuaValue.valueOf(456)).touserdata();
assertEquals(C.class, c.getClass());
assertEquals(C.class, ci.getClass());
assertEquals(C.class, cs.getClass());
assertEquals(C.class, csi.getClass());
assertEquals(null, ((C) c).m_string_field);
assertEquals(0, ((C) c).m_int_field);
assertEquals("abc", ((C) cs).m_string_field);
assertEquals(0, ((C) cs).m_int_field);
assertEquals(null, ((C) ci).m_string_field);
assertEquals(123, ((C) ci).m_int_field);
assertEquals("def", ((C) csi).m_string_field);
assertEquals(456, ((C) csi).m_int_field);
}
@Test
void testOverloadedFactoryUncoercible() {
JavaClass f = JavaClass.forClass(C.class);
try {
Object c = f.call(LuaValue.userdataOf(new Object()));
// fail( "did not throw lua error as expected" );
assertEquals(0, ((C) c).m_int_field);
assertEquals(null, ((C) c).m_string_field);
} catch (LuaError e) {
}
}
@Test
void testNoAttribute() {
JavaClass f = JavaClass.forClass(A.class);
LuaValue v = f.get("bogus");
assertEquals(v, LuaValue.NIL);
try {
f.set("bogus", ONE);
fail("did not throw lua error as expected");
} catch (LuaError e) {
}
}
@Test
void testFieldAttributeCoercible() {
JavaInstance i = new JavaInstance(new B());
i.set("m_int_field", ONE);
assertEquals(1, i.get("m_int_field").toint());
i.set("m_int_field", THREE);
assertEquals(3, i.get("m_int_field").toint());
i = new JavaInstance(new C());
i.set("m_int_field", ONE);
assertEquals(1, i.get("m_int_field").toint());
i.set("m_int_field", THREE);
assertEquals(3, i.get("m_int_field").toint());
}
@Test
void testUniqueMethodAttributeCoercible() {
B b = new B();
JavaInstance ib = new JavaInstance(b);
LuaValue b_getString = ib.get("getString");
LuaValue b_getint = ib.get("getint");
assertEquals(JavaMethod.class, b_getString.getClass());
assertEquals(JavaMethod.class, b_getint.getClass());
assertEquals("abc", b_getString.call(SOMEB).tojstring());
assertEquals(100000, b_getint.call(SOMEB).toint());
assertEquals("abc", b_getString.call(SOMEC).tojstring());
assertEquals(200000, b_getint.call(SOMEC).toint());
}
@Test
void testUniqueMethodAttributeArgsCoercible() {
B b = new B();
JavaInstance ib = new JavaInstance(b);
LuaValue uniq = ib.get("uniq");
LuaValue uniqs = ib.get("uniqs");
LuaValue uniqi = ib.get("uniqi");
LuaValue uniqsi = ib.get("uniqsi");
LuaValue uniqis = ib.get("uniqis");
assertEquals(JavaMethod.class, uniq.getClass());
assertEquals(JavaMethod.class, uniqs.getClass());
assertEquals(JavaMethod.class, uniqi.getClass());
assertEquals(JavaMethod.class, uniqsi.getClass());
assertEquals(JavaMethod.class, uniqis.getClass());
assertEquals("uniq()", uniq.call(SOMEB).tojstring());
assertEquals("uniqs(string:abc)", uniqs.call(SOMEB, ABC).tojstring());
assertEquals("uniqi(int:1)", uniqi.call(SOMEB, ONE).tojstring());
assertEquals("uniqsi(string:abc,int:1)", uniqsi.call(SOMEB, ABC, ONE).tojstring());
assertEquals("uniqis(int:1,string:abc)", uniqis.call(SOMEB, ONE, ABC).tojstring());
assertEquals("uniqis(int:1,string:abc)",
uniqis.invoke(LuaValue.varargsOf(new LuaValue[] { SOMEB, ONE, ABC, ONE })).arg1().tojstring());
}
@Test
void testOverloadedMethodAttributeCoercible() {
B b = new B();
JavaInstance ib = new JavaInstance(b);
LuaValue p = ib.get("pick");
assertEquals("pick()", p.call(SOMEB).tojstring());
assertEquals("pick(string:abc)", p.call(SOMEB, ABC).tojstring());
assertEquals("pick(int:1)", p.call(SOMEB, ONE).tojstring());
assertEquals("pick(string:abc,int:1)", p.call(SOMEB, ABC, ONE).tojstring());
assertEquals("pick(int:1,string:abc)", p.call(SOMEB, ONE, ABC).tojstring());
assertEquals("pick(int:1,string:abc)",
p.invoke(LuaValue.varargsOf(new LuaValue[] { SOMEB, ONE, ABC, ONE })).arg1().tojstring());
}
@Test
void testUnboundOverloadedMethodAttributeCoercible() {
B b = new B();
JavaInstance ib = new JavaInstance(b);
LuaValue p = ib.get("pick");
assertEquals(JavaMethod.Overload.class, p.getClass());
assertEquals("pick()", p.call(SOMEC).tojstring());
assertEquals("class-c-pick(string:abc)", p.call(SOMEC, ABC).tojstring());
assertEquals("class-c-pick(int:1)", p.call(SOMEC, ONE).tojstring());
assertEquals("pick(string:abc,int:1)", p.call(SOMEC, ABC, ONE).tojstring());
assertEquals("pick(int:1,string:abc)", p.call(SOMEC, ONE, ABC).tojstring());
assertEquals("pick(int:1,string:abc)",
p.invoke(LuaValue.varargsOf(new LuaValue[] { SOMEC, ONE, ABC, ONE })).arg1().tojstring());
}
@Test
void testOverloadedStaticMethodAttributeCoercible() {
B b = new B();
JavaInstance ib = new JavaInstance(b);
LuaValue p = ib.get("staticpick");
assertEquals("static-pick()", p.call(SOMEB).tojstring());
assertEquals("static-pick(string:abc)", p.call(SOMEB, ABC).tojstring());
assertEquals("static-pick(int:1)", p.call(SOMEB, ONE).tojstring());
assertEquals("static-pick(string:abc,int:1)", p.call(SOMEB, ABC, ONE).tojstring());
assertEquals("static-pick(int:1,string:abc)", p.call(SOMEB, ONE, ABC).tojstring());
assertEquals("static-pick(int:1,string:abc)",
p.invoke(LuaValue.varargsOf(new LuaValue[] { SOMEB, ONE, ABC, ONE })).arg1().tojstring());
}
@Test
void testGetInnerClass() {
C c = new C();
JavaInstance ic = new JavaInstance(c);
LuaValue d = ic.get("D");
assertFalse(d.isnil());
assertSame(d, JavaClass.forClass(C.D.class));
LuaValue e = ic.get("E");
assertTrue(e.isnil());
}
}

View File

@@ -0,0 +1,138 @@
package org.luaj.vm2.lib.jse;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import java.util.Date;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.luaj.vm2.LuaValue;
class OsLibTest {
LuaValue jse_lib;
double time;
@BeforeEach
public void setUp() {
jse_lib = JsePlatform.standardGlobals().get("os");
time = new Date(2001-1900, 7, 23, 14, 55, 02).getTime()/1000.0;
}
private void test(String format, String expected) {
String actual = jse_lib.get("date").call(LuaValue.valueOf(format), LuaValue.valueOf(time)).tojstring();
assertEquals(expected, actual);
}
@Test
void testStringDateChars() { test("foo", "foo"); }
@Test
void testStringDate_a() { test("%a", "Thu"); }
@Test
void testStringDate_A() { test("%A", "Thursday"); }
@Test
void testStringDate_b() { test("%b", "Aug"); }
@Test
void testStringDate_B() { test("%B", "August"); }
@Test
void testStringDate_c() { test("%c", "Thu Aug 23 14:55:02 2001"); }
@Test
void testStringDate_d() { test("%d", "23"); }
@Test
void testStringDate_H() { test("%H", "14"); }
@Test
void testStringDate_I() { test("%I", "02"); }
@Test
void testStringDate_j() { test("%j", "235"); }
@Test
void testStringDate_m() { test("%m", "08"); }
@Test
void testStringDate_M() { test("%M", "55"); }
@Test
void testStringDate_p() { test("%p", "PM"); }
@Test
void testStringDate_S() { test("%S", "02"); }
@Test
void testStringDate_U() { test("%U", "33"); }
@Test
void testStringDate_w() { test("%w", "4"); }
@Test
void testStringDate_W() { test("%W", "34"); }
@Test
void testStringDate_x() { test("%x", "08/23/01"); }
@Test
void testStringDate_X() { test("%X", "14:55:02"); }
@Test
void testStringDate_y() { test("%y", "01"); }
@Test
void testStringDate_Y() { test("%Y", "2001"); }
@Test
void testStringDate_Pct() { test("%%", "%"); }
static final double DAY = 24.*3600.;
@Test
void testStringDate_UW_neg4() { time -= 4*DAY; test("%c %U %W", "Sun Aug 19 14:55:02 2001 33 33"); }
@Test
void testStringDate_UW_neg3() { time -= 3*DAY; test("%c %U %W", "Mon Aug 20 14:55:02 2001 33 34"); }
@Test
void testStringDate_UW_neg2() { time -= 2*DAY; test("%c %U %W", "Tue Aug 21 14:55:02 2001 33 34"); }
@Test
void testStringDate_UW_neg1() { time -= DAY; test("%c %U %W", "Wed Aug 22 14:55:02 2001 33 34"); }
@Test
void testStringDate_UW_pos0() { time += 0; test("%c %U %W", "Thu Aug 23 14:55:02 2001 33 34"); }
@Test
void testStringDate_UW_pos1() { time += DAY; test("%c %U %W", "Fri Aug 24 14:55:02 2001 33 34"); }
@Test
void testStringDate_UW_pos2() { time += 2*DAY; test("%c %U %W", "Sat Aug 25 14:55:02 2001 33 34"); }
@Test
void testStringDate_UW_pos3() { time += 3*DAY; test("%c %U %W", "Sun Aug 26 14:55:02 2001 34 34"); }
@Test
void testStringDate_UW_pos4() { time += 4*DAY; test("%c %U %W", "Mon Aug 27 14:55:02 2001 34 35"); }
@Test
void testJseOsGetenvForEnvVariables() {
LuaValue USER = LuaValue.valueOf("USER");
LuaValue jse_user = jse_lib.get("getenv").call(USER);
assertFalse(jse_user.isnil());
}
@Test
void testJseOsGetenvForSystemProperties() {
System.setProperty("test.key.foo", "test.value.bar");
LuaValue key = LuaValue.valueOf("test.key.foo");
LuaValue value = LuaValue.valueOf("test.value.bar");
LuaValue jse_value = jse_lib.get("getenv").call(key);
assertEquals(value, jse_value);
}
}

View File

@@ -0,0 +1,31 @@
package org.luaj.vm2.lib.jse;
public class TestClass {
private static class PrivateImpl implements TestInterface {
public String public_field;
public PrivateImpl() {
this.public_field = "privateImpl-constructor";
}
PrivateImpl(String f) {
this.public_field = f;
}
public String public_method() { return "privateImpl-" + public_field + "-public_method"; }
public String interface_method(String x) {
return "privateImpl-" + public_field + "-interface_method(" + x + ")";
}
public String toString() { return public_field; }
}
public TestInterface create_PrivateImpl(String f) { return new PrivateImpl(f); }
public Class get_PrivateImplClass() { return PrivateImpl.class; }
public enum SomeEnum {
ValueOne, ValueTwo,
}
}

View File

@@ -0,0 +1,5 @@
package org.luaj.vm2.lib.jse;
public interface TestInterface {
String interface_method(String x);
}

View File

@@ -0,0 +1,27 @@
package org.luaj.vm2.script;
import static org.junit.jupiter.api.Assertions.assertTrue;
import javax.script.Compilable;
import javax.script.CompiledScript;
import javax.script.ScriptException;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.luaj.vm2.LuaValue;
class CompileClosureTest extends DefaultBindingsTestCase {
@BeforeEach
@Override
protected void setUp() throws Exception {
System.setProperty("org.luaj.luajc", "false");
super.setUp();
}
@Test
void testCompiledFunctionIsClosure() throws ScriptException {
CompiledScript cs = ((Compilable) e).compile("return 'foo'");
LuaValue value = ((LuaScriptEngine.LuajCompiledScript) cs).function;
assertTrue(value.isclosure());
}
}

View File

@@ -0,0 +1,27 @@
package org.luaj.vm2.script;
import static org.junit.jupiter.api.Assertions.assertFalse;
import javax.script.Compilable;
import javax.script.CompiledScript;
import javax.script.ScriptException;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.luaj.vm2.LuaValue;
class CompileNonClosureTest extends DefaultBindingsTestCase {
@BeforeEach
@Override
protected void setUp() throws Exception {
System.setProperty("org.luaj.luajc", "true");
super.setUp();
}
@Test
void testCompiledFunctionIsNotClosure() throws ScriptException {
CompiledScript cs = ((Compilable) e).compile("return 'foo'");
LuaValue value = ((LuaScriptEngine.LuajCompiledScript) cs).function;
assertFalse(value.isclosure());
}
}

View File

@@ -0,0 +1,10 @@
package org.luaj.vm2.script;
import javax.script.Bindings;
abstract class DefaultBindingsTestCase extends EngineTestCase {
@Override
protected Bindings createBindings() {
return e.createBindings();
}
}

View File

@@ -0,0 +1,186 @@
package org.luaj.vm2.script;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.junit.jupiter.api.Assertions.fail;
import java.io.CharArrayReader;
import java.io.CharArrayWriter;
import java.io.Reader;
import javax.script.Bindings;
import javax.script.Compilable;
import javax.script.CompiledScript;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.luaj.vm2.LuaFunction;
import org.luaj.vm2.LuaValue;
import org.luaj.vm2.lib.OneArgFunction;
abstract class EngineTestCase {
protected ScriptEngine e;
protected Bindings b;
protected abstract Bindings createBindings();
@BeforeEach
protected void setUp() throws Exception {
this.e = new ScriptEngineManager().getEngineByName("luaj");
this.b = createBindings();
}
@Test
void testSqrtIntResult() throws ScriptException {
e.put("x", 25);
e.eval("y = math.sqrt(x)");
Object y = e.get("y");
assertEquals(5, y);
}
@Test
void testOneArgFunction() throws ScriptException {
e.put("x", 25);
e.eval("y = math.sqrt(x)");
Object y = e.get("y");
assertEquals(5, y);
e.put("f", new OneArgFunction() {
@Override
public LuaValue call(LuaValue arg) {
return LuaValue.valueOf(arg.toString() + "123");
}
});
Object r = e.eval("return f('abc')");
assertEquals("abc123", r);
}
@Test
void testCompiledScript() throws ScriptException {
CompiledScript cs = ((Compilable) e).compile("y = math.sqrt(x); return y");
b.put("x", 144);
assertEquals(12, cs.eval(b));
}
@Test
void testBuggyLuaScript() {
try {
e.eval("\n\nbuggy lua code\n\n");
} catch (ScriptException se) {
assertEquals("eval threw javax.script.ScriptException: [string \"script\"]:3: syntax error",
se.getMessage());
return;
}
fail("buggy script did not throw ScriptException as expected.");
}
@Test
void testScriptRedirection() throws ScriptException {
Reader input = new CharArrayReader("abcdefg\nhijk".toCharArray());
CharArrayWriter output = new CharArrayWriter();
CharArrayWriter errors = new CharArrayWriter();
String script = "print(\"string written using 'print'\")\n"
+ "io.write(\"string written using 'io.write()'\\n\")\n"
+ "io.stdout:write(\"string written using 'io.stdout:write()'\\n\")\n"
+ "io.stderr:write(\"string written using 'io.stderr:write()'\\n\")\n"
+ "io.write([[string read using 'io.stdin:read(\"*l\")':]]..io.stdin:read(\"*l\")..\"\\n\")\n";
// Evaluate script with redirection set
e.getContext().setReader(input);
e.getContext().setWriter(output);
e.getContext().setErrorWriter(errors);
e.eval(script);
final String expectedOutput = "string written using 'print'\n" + "string written using 'io.write()'\n"
+ "string written using 'io.stdout:write()'\n" + "string read using 'io.stdin:read(\"*l\")':abcdefg\n";
assertEquals(expectedOutput, output.toString());
final String expectedErrors = "string written using 'io.stderr:write()'\n";
assertEquals(expectedErrors, errors.toString());
// Evaluate script with redirection reset
output.reset();
errors.reset();
// e.getContext().setReader(null); // This will block if using actual STDIN
e.getContext().setWriter(null);
e.getContext().setErrorWriter(null);
e.eval(script);
assertEquals("", output.toString());
assertEquals("", errors.toString());
}
@Test
void testBindingJavaInt() throws ScriptException {
CompiledScript cs = ((Compilable) e).compile("y = x; return 'x '..type(x)..' '..tostring(x)\n");
b.put("x", 111);
assertEquals("x number 111", cs.eval(b));
assertEquals(111, b.get("y"));
}
@Test
void testBindingJavaDouble() throws ScriptException {
CompiledScript cs = ((Compilable) e).compile("y = x; return 'x '..type(x)..' '..tostring(x)\n");
b.put("x", 125.125);
assertEquals("x number 125.125", cs.eval(b));
assertEquals(125.125, b.get("y"));
}
@Test
void testBindingJavaString() throws ScriptException {
CompiledScript cs = ((Compilable) e).compile("y = x; return 'x '..type(x)..' '..tostring(x)\n");
b.put("x", "foo");
assertEquals("x string foo", cs.eval(b));
assertEquals("foo", b.get("y"));
}
@Test
void testBindingJavaObject() throws ScriptException {
CompiledScript cs = ((Compilable) e).compile("y = x; return 'x '..type(x)..' '..tostring(x)\n");
b.put("x", new SomeUserClass());
assertEquals("x userdata some-user-value", cs.eval(b));
assertEquals(SomeUserClass.class, b.get("y").getClass());
}
@Test
void testBindingJavaArray() throws ScriptException {
CompiledScript cs = ((Compilable) e).compile("y = x; return 'x '..type(x)..' '..#x..' '..x[1]..' '..x[2]\n");
b.put("x", new int[] { 777, 888 });
assertEquals("x userdata 2 777 888", cs.eval(b));
assertEquals(int[].class, b.get("y").getClass());
}
@Test
void testBindingLuaFunction() throws ScriptException {
CompiledScript cs = ((Compilable) e).compile("y = function(x) return 678 + x end; return 'foo'");
assertEquals("foo", cs.eval(b).toString());
assertTrue(b.get("y") instanceof LuaFunction);
assertEquals(LuaValue.valueOf(801), ((LuaFunction) b.get("y")).call(LuaValue.valueOf(123)));
}
@Test
void testUserClasses() throws ScriptException {
CompiledScript cs = ((Compilable) e).compile("x = x or luajava.newInstance('java.lang.String', 'test')\n"
+ "return 'x ' .. type(x) .. ' ' .. tostring(x)\n");
assertEquals("x string test", cs.eval(b));
b.put("x", new SomeUserClass());
assertEquals("x userdata some-user-value", cs.eval(b));
}
@Test
void testReturnMultipleValues() throws ScriptException {
CompiledScript cs = ((Compilable) e).compile("return 'foo', 'bar'\n");
Object o = cs.eval();
assertEquals(Object[].class, o.getClass());
Object[] array = (Object[]) o;
assertEquals(2, array.length);
assertEquals("foo", array[0]);
assertEquals("bar", array[1]);
}
private static class SomeUserClass {
@Override
public String toString() {
return "some-user-value";
}
}
}

View File

@@ -0,0 +1,43 @@
package org.luaj.vm2.script;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineFactory;
import javax.script.ScriptEngineManager;
import org.junit.jupiter.api.Test;
class LookupEngineTest {
@Test
void testGetEngineByExtension() {
ScriptEngine e = new ScriptEngineManager().getEngineByExtension(".lua");
assertNotNull(e);
assertEquals(LuaScriptEngine.class, e.getClass());
}
@Test
void testGetEngineByName() {
ScriptEngine e = new ScriptEngineManager().getEngineByName("luaj");
assertNotNull(e);
assertEquals(LuaScriptEngine.class, e.getClass());
}
@Test
void testGetEngineByMimeType() {
ScriptEngine e = new ScriptEngineManager().getEngineByMimeType("text/lua");
assertNotNull(e);
assertEquals(LuaScriptEngine.class, e.getClass());
}
@Test
void testFactoryMetadata() {
ScriptEngine e = new ScriptEngineManager().getEngineByName("luaj");
ScriptEngineFactory f = e.getFactory();
assertEquals("Luaj", f.getEngineName());
assertEquals("Luaj 0.0", f.getEngineVersion());
assertEquals("lua", f.getLanguageName());
assertEquals("5.2", f.getLanguageVersion());
}
}

View File

@@ -0,0 +1,11 @@
package org.luaj.vm2.script;
import javax.script.Bindings;
import javax.script.SimpleBindings;
class SimpleBindingsTest extends EngineTestCase {
@Override
protected Bindings createBindings() {
return new SimpleBindings();
}
}

View File

@@ -0,0 +1,55 @@
package org.luaj.vm2.script;
import static org.junit.jupiter.api.Assertions.assertEquals;
import javax.script.Bindings;
import javax.script.Compilable;
import javax.script.CompiledScript;
import javax.script.ScriptContext;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
class UserContextTest {
protected ScriptEngine e;
protected Bindings b;
protected ScriptContext c;
@BeforeEach
public void setUp() {
this.e = new ScriptEngineManager().getEngineByName("luaj");
this.c = new LuajContext();
this.b = c.getBindings(ScriptContext.ENGINE_SCOPE);
}
@Test
void testUncompiledScript() throws ScriptException {
b.put("x", 144);
assertEquals(12, e.eval("z = math.sqrt(x); return z", b));
assertEquals(12, b.get("z"));
assertEquals(null, e.getBindings(ScriptContext.ENGINE_SCOPE).get("z"));
assertEquals(null, e.getBindings(ScriptContext.GLOBAL_SCOPE).get("z"));
b.put("x", 25);
assertEquals(5, e.eval("z = math.sqrt(x); return z", c));
assertEquals(5, b.get("z"));
assertEquals(null, e.getBindings(ScriptContext.ENGINE_SCOPE).get("z"));
assertEquals(null, e.getBindings(ScriptContext.GLOBAL_SCOPE).get("z"));
}
@Test
void testCompiledScript() throws ScriptException {
CompiledScript cs = ((Compilable) e).compile("z = math.sqrt(x); return z");
b.put("x", 144);
assertEquals(12, cs.eval(b));
assertEquals(12, b.get("z"));
b.put("x", 25);
assertEquals(5, cs.eval(c));
assertEquals(5, b.get("z"));
}
}

View File

@@ -0,0 +1,38 @@
package org.luaj.vm2.script;
import static org.junit.jupiter.api.Assertions.assertEquals;
import java.io.CharArrayWriter;
import javax.script.Bindings;
import javax.script.ScriptContext;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
class WriterTest {
protected ScriptEngine e;
protected Bindings b;
@BeforeEach
public void setUp() {
this.e = new ScriptEngineManager().getEngineByName("luaj");
this.b = e.getBindings(ScriptContext.ENGINE_SCOPE);
}
@Test
void testWriter() throws ScriptException {
CharArrayWriter output = new CharArrayWriter();
CharArrayWriter errors = new CharArrayWriter();
e.getContext().setWriter(output);
e.getContext().setErrorWriter(errors);
e.eval("io.write( [[line]] )");
assertEquals("line", output.toString());
e.eval("io.write( [[ one\nline two\n]] )");
assertEquals("line one\nline two\n", output.toString());
output.reset();
}
}