Add framework to test error messages and argument type checking.

This commit is contained in:
James Roseborough
2008-07-15 05:32:56 +00:00
parent 754fe22b18
commit 5fcec48678
11 changed files with 542 additions and 355 deletions

View File

@@ -6,7 +6,6 @@
<classpathentry kind="src" path="src/j2se"/>
<classpathentry kind="src" path="src/script"/>
<classpathentry kind="src" path="src/test/java"/>
<classpathentry kind="src" path="src/test/res"/>
<classpathentry kind="src" path="src/sample"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
<classpathentry kind="con" path="org.eclipse.jdt.junit.JUNIT_CONTAINER/3.8.1"/>

133
src/test/errors/args.lua Normal file
View File

@@ -0,0 +1,133 @@
-- utilities to check that args of various types pass or fail
-- argument type checking
anylua = { nil, 'abc', 1.23, true, {aa=11,bb==22}, print }
somestring = { 'abc' }
somenumber = { 1.23 }
somestrnum = { 'abc', 1.23 }
someboolean = { true }
sometable = { {aa=11,bb=22} }
somefunction = { print }
somenil = { nil }
local function contains(set,val)
local m = #set
for i=1,m do
if set[i] == val then
return true
end
end
return false
end
local function except(some)
local n = #anylua
local z = {}
local j = 1
for i=1,n do
if not contains(some, anylua[i]) then
z[j] = anylua[i]
j = j + 1
end
end
return z
end
notastring = except(somestring)
notanumber = except(somenumber)
notastrnum = except(somestrnum)
notaboolean = except(someboolean)
notatable = except(sometable)
notafunction = except(somefunction)
notanil = except(somenil)
local function signature(name,arglist)
local t = {}
for i=1,#arglist do
if type(arglist[i]) == 'table' then
t[i] = 'table'
elseif type(arglist[i]) == 'function' then
t[i] = 'function'
else
t[i] = tostring(arglist[i])
end
end
return name..'('..table.concat(t,',')..')'
end
local function expand(argsets, typesets, ...)
local n = typesets and #typesets or 0
if n <= 0 then
table.insert(argsets,{...})
return argsets
end
local t = typesets[1]
local s = {select(2,unpack(typesets))}
local m = #t
for i=1,m do
expand(argsets, s, t[i], ...)
end
return argsets
end
local function arglists(typesets)
local argsets = expand({},typesets)
return ipairs(argsets)
end
local function lookup( name )
return loadstring('return '..name)()
end
local function invoke( name, arglist )
local s,c = pcall(lookup, name)
if not s then return s,c end
return pcall(c, unpack(arglist))
end
-- check that all combinations of arguments pass
function checkallpass( name, typesets )
for i,v in arglists(typesets) do
local sig = signature(name,v)
local s,e = invoke( name, v )
if s then
print( 'pass', sig )
else
print( 'fail', sig, e )
end
end
end
-- check that all combinations of arguments fail in some way,
-- ignore error messages
function checkallfail( name, typesets )
for i,v in arglists(typesets) do
local sig = signature(name,v)
local s,e,f,g = invoke( name, v )
if not s then
print( 'ok', sig )
else
print( 'needcheck', sig, e, f, g )
end
end
end
-- check that all combinations of arguments fail in some way,
-- ignore error messages
function checkallerrors( name, typesets, template )
for i,v in arglists(typesets) do
local sig = signature(name,v)
local s,e,f,g = invoke( name, v )
if not s then
if string.match(e, template) then
print( 'ok', sig, 'template='..template )
else
print( 'badmsg', sig, "template='"..template.."' actual='"..e.."'" )
end
else
print( 'needcheck', sig, e, f, g )
end
end
end

View File

@@ -0,0 +1,9 @@
package.path = "?.lua;src/test/errors/?.lua"
require 'args'
-- arg types for basic library functions
local notastrnumnil={true,{},print}
checkallpass('dofile', {{nil,'src/test/errors/args.lua','args.lua'}})
checkallfail('dofile', {notastrnumnil})
checkallerrors('dofile', {notastrnumnil}, 'bad argument')

View File

@@ -10,13 +10,14 @@ public class AllTests {
// debug tests
TestSuite vm = new TestSuite("VM");
vm.addTestSuite(org.luaj.vm.CompatibiltyTest.class);
vm.addTestSuite(org.luaj.vm.ErrorMessageTest.class);
vm.addTestSuite(org.luaj.vm.LuaStateTest.class);
vm.addTestSuite(org.luaj.vm.LoadStateTest.class);
vm.addTestSuite(org.luaj.vm.LStringTest.class);
vm.addTestSuite(org.luaj.vm.MathLibTest.class);
vm.addTestSuite(org.luaj.vm.LTableTest.class);
vm.addTestSuite(org.luaj.vm.LWeakTableTest.class);
vm.addTestSuite(org.luaj.vm.LuaJTest.class);
suite.addTest(vm);
// compiler tests

View File

@@ -21,6 +21,7 @@
******************************************************************************/
package org.luaj.debug;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
@@ -33,13 +34,12 @@ import org.luaj.vm.LClosure;
import org.luaj.vm.LPrototype;
import org.luaj.vm.LValue;
import org.luaj.vm.LoadState;
import org.luaj.vm.LuaState;
import org.luaj.vm.Platform;
public class DebugStackStateTest extends TestCase {
public void testDebugStackState() throws InterruptedException, IOException {
String script = "/test6.lua";
String script = "src/test/res/test6.lua";
// set up the vm
System.setProperty(Platform.PROPERTY_LUAJ_DEBUG, "true");
@@ -51,7 +51,7 @@ public class DebugStackStateTest extends TestCase {
final DebugLuaState state = (DebugLuaState) Platform.newLuaState();
LuaC.install();
InputStream is = getClass().getResourceAsStream( script );
InputStream is = new FileInputStream( script );
LPrototype p = LoadState.undump(state, is, script);
// create closure and execute

View File

@@ -4,17 +4,17 @@ import java.io.IOException;
import org.luaj.jit.LuaJit;
import org.luaj.vm.LPrototype;
import org.luaj.vm.LuaJTest;
import org.luaj.vm.CompatibiltyTest;
import org.luaj.vm.LuaState;
/**
* Suite of standard tests, but using the LuaJit compiler
* for all loaded prototypes.
*/
public class LuaJitTest extends LuaJTest {
public class LuaJitTest extends CompatibiltyTest {
protected LPrototype loadScriptResource( LuaState state, String name ) throws IOException {
LPrototype p = super.loadScriptResource(state, name);
protected LPrototype loadScript( LuaState state, String name ) throws IOException {
LPrototype p = super.loadScript(state, name);
return LuaJit.jitCompile(p);
}

View File

@@ -0,0 +1,178 @@
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 testArgtypes() throws IOException, InterruptedException {
runTest("argtypes");
}
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 testErrors() throws IOException, InterruptedException {
runTest("errors");
}
public void testHugeTable() throws IOException, InterruptedException {
runTest("hugetable");
}
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 testPcalls() throws IOException, InterruptedException {
runTest("pcalls");
}
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 testWeakTable() throws IOException, InterruptedException {
runTest("weaktable");
}
}

View File

@@ -0,0 +1,22 @@
package org.luaj.vm;
import java.io.IOException;
/**
* Test error messages produced by luaj.
*/
public class ErrorMessageTest extends ScriptDrivenTest {
private static final String dir = "src/test/errors";
public ErrorMessageTest() {
super(dir);
}
public void testBaseLibArgs() throws IOException, InterruptedException {
runTest("baselibargs");
}
}

View File

@@ -1,345 +0,0 @@
package org.luaj.vm;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import junit.framework.TestCase;
import org.luaj.TestPlatform;
import org.luaj.compiler.LuaC;
import org.luaj.lib.BaseLib;
public class LuaJTest extends TestCase {
protected void setUp() throws Exception {
super.setUp();
Platform.setInstance(new TestPlatform());
}
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 testArgtypes() throws IOException, InterruptedException {
runTest("argtypes");
}
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 testErrors() throws IOException, InterruptedException {
runTest("errors");
}
public void testHugeTable() throws IOException, InterruptedException {
runTest("hugetable");
}
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 testPcalls() throws IOException, InterruptedException {
runTest("pcalls");
}
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 testWeakTable() throws IOException, InterruptedException {
runTest("weaktable");
}
// */
private void runTest(String testName) throws IOException,
InterruptedException {
// new lua state
LuaState state = Platform.newLuaState();
// install the compiler
LuaC.install();
// load the file
LPrototype p = loadScriptResource(state, testName);
p.source = LString.valueOf("stdin");
// Replace System.out with a ByteArrayOutputStream
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
BaseLib.redirectOutput(outputStream);
try {
// create closure and execute
LClosure c = p.newClosure(state._G);
state.pushlvalue(c);
state.call(0, 0);
final String actualOutput = new String(outputStream.toByteArray());
final String expectedOutput = getExpectedOutput(testName);
assertEquals(expectedOutput, actualOutput);
} finally {
BaseLib.restoreStandardOutput();
outputStream.close();
}
}
protected LPrototype loadScriptResource(LuaState state, String name)
throws IOException {
InputStream script = getClass().getResourceAsStream(
"/" + name + ".luac");
if (script == null) {
script = getClass().getResourceAsStream("/" + name + ".lua");
if (script == null) {
fail("Could not load script for test case: " + name);
}
}
try {
// Use "stdin" instead of resource name so that output matches
// standard Lua.
return LoadState.undump(state, script, "stdin");
} finally {
script.close();
}
}
private String getExpectedOutput(final String testName) throws IOException,
InterruptedException {
String expectedOutputName = "/" + testName + "-expected.out";
InputStream is = getClass().getResourceAsStream(expectedOutputName);
if (is != null) {
try {
return readString(is);
} finally {
is.close();
}
} else {
InputStream script;
// script = getClass().getResourceAsStream( "/" + testName + ".luac"
// );
// if ( script == null ) {
script = getClass().getResourceAsStream("/" + testName + ".lua");
if (script == null) {
fail("Could not find script for test case: " + testName);
}
// }
try {
return collectProcessOutput(new String[] { "lua", "-" }, script);
} finally {
script.close();
}
}
}
private String collectProcessOutput(String[] cmd, final InputStream input)
throws IOException, InterruptedException {
Runtime r = Runtime.getRuntime();
final ByteArrayOutputStream baos = new ByteArrayOutputStream();
final Process p = r.exec(cmd);
try {
// start a thread to write the given input to the subprocess.
Thread inputCopier = (new Thread() {
public void run() {
try {
OutputStream processStdIn = p.getOutputStream();
try {
copy(input, processStdIn);
} finally {
processStdIn.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
});
inputCopier.start();
// start another thread to read output from the subprocess.
Thread outputCopier = (new Thread() {
public void run() {
try {
InputStream processStdOut = p.getInputStream();
try {
copy(processStdOut, baos);
} finally {
processStdOut.close();
}
} catch (IOException ioe) {
ioe.printStackTrace();
}
}
});
outputCopier.start();
// start another thread to read output from the subprocess.
Thread errorCopier = (new Thread() {
public void run() {
try {
InputStream processError = p.getErrorStream();
try {
copy(processError, System.err);
} finally {
processError.close();
}
} catch (IOException ioe) {
ioe.printStackTrace();
}
}
});
errorCopier.start();
p.waitFor();
inputCopier.join();
outputCopier.join();
errorCopier.join();
return new String(baos.toByteArray());
} finally {
p.destroy();
}
}
private String readString(InputStream is) throws IOException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
copy(is, baos);
return new String(baos.toByteArray());
}
private void copy(InputStream is, OutputStream os) throws IOException {
byte[] buf = new byte[1024];
int r;
while ((r = is.read(buf)) >= 0) {
os.write(buf, 0, r);
}
}
}

View File

@@ -0,0 +1,190 @@
package org.luaj.vm;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import junit.framework.TestCase;
import org.luaj.compiler.LuaC;
import org.luaj.lib.BaseLib;
import org.luaj.platform.J2sePlatform;
abstract
public class ScriptDrivenTest extends TestCase {
private final String basedir;
protected ScriptDrivenTest( String directory ) {
basedir = directory;
}
// */
protected void runTest(String testName) throws IOException,
InterruptedException {
// set platform relative to directory
Platform.setInstance(new J2sePlatform() {
public InputStream openFile(String fileName) {
return super.openFile(basedir+"/"+fileName);
}
});
// new lua state
LuaState state = Platform.newLuaState();
// install the compiler
LuaC.install();
// load the file
LPrototype p = loadScript(state, testName);
p.source = LString.valueOf("stdin");
// Replace System.out with a ByteArrayOutputStream
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
BaseLib.redirectOutput(outputStream);
try {
// create closure and execute
LClosure c = p.newClosure(state._G);
state.pushlvalue(c);
state.call(0, 0);
final String actualOutput = new String(outputStream.toByteArray());
final String expectedOutput = getExpectedOutput(testName);
assertEquals(expectedOutput, actualOutput);
} finally {
BaseLib.restoreStandardOutput();
outputStream.close();
}
}
protected LPrototype loadScript(LuaState state, String name)
throws IOException {
File file = new File(basedir+"/"+name+".luac");
if ( !file.exists() )
file = new File(basedir+"/"+name+".lua");
if ( !file.exists() )
fail("Could not load script for test case: " + name);
InputStream script = new FileInputStream(file);
try {
// Use "stdin" instead of resource name so that output matches
// standard Lua.
return LoadState.undump(state, script, "stdin");
} finally {
script.close();
}
}
private String getExpectedOutput(final String name) throws IOException,
InterruptedException {
String expectedOutputName = basedir+"/"+name+"-expected.out";
InputStream is = getClass().getResourceAsStream(expectedOutputName);
if (is != null) {
try {
return readString(is);
} finally {
is.close();
}
} else {
File file = new File(basedir+"/"+name+".lua");
if ( !file.exists() )
fail("Could not load script for test case: " + name);
InputStream script = new FileInputStream(file);
// }
try {
return collectProcessOutput(new String[] { "lua", "-" }, script);
} finally {
script.close();
}
}
}
private String collectProcessOutput(String[] cmd, final InputStream input)
throws IOException, InterruptedException {
Runtime r = Runtime.getRuntime();
final ByteArrayOutputStream baos = new ByteArrayOutputStream();
final Process p = r.exec(cmd);
try {
// start a thread to write the given input to the subprocess.
Thread inputCopier = (new Thread() {
public void run() {
try {
OutputStream processStdIn = p.getOutputStream();
try {
copy(input, processStdIn);
} finally {
processStdIn.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
});
inputCopier.start();
// start another thread to read output from the subprocess.
Thread outputCopier = (new Thread() {
public void run() {
try {
InputStream processStdOut = p.getInputStream();
try {
copy(processStdOut, baos);
} finally {
processStdOut.close();
}
} catch (IOException ioe) {
ioe.printStackTrace();
}
}
});
outputCopier.start();
// start another thread to read output from the subprocess.
Thread errorCopier = (new Thread() {
public void run() {
try {
InputStream processError = p.getErrorStream();
try {
copy(processError, System.err);
} finally {
processError.close();
}
} catch (IOException ioe) {
ioe.printStackTrace();
}
}
});
errorCopier.start();
p.waitFor();
inputCopier.join();
outputCopier.join();
errorCopier.join();
return new String(baos.toByteArray());
} finally {
p.destroy();
}
}
private String readString(InputStream is) throws IOException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
copy(is, baos);
return new String(baos.toByteArray());
}
private void copy(InputStream is, OutputStream os) throws IOException {
byte[] buf = new byte[1024];
int r;
while ((r = is.read(buf)) >= 0) {
os.write(buf, 0, r);
}
}
}

View File

@@ -1 +1 @@
version: 0.40
version: 0.41