diff --git a/.classpath b/.classpath index c09db0ba..fc39bf58 100644 --- a/.classpath +++ b/.classpath @@ -5,5 +5,6 @@ + diff --git a/src/main/java/lua/Builtin.java b/src/main/java/lua/Builtin.java index 56c26f4c..07d74dd3 100644 --- a/src/main/java/lua/Builtin.java +++ b/src/main/java/lua/Builtin.java @@ -3,8 +3,10 @@ */ package lua; +import java.io.OutputStream; +import java.io.PrintStream; + import lua.value.LFunction; -import lua.value.LString; import lua.value.LTable; import lua.value.LValue; @@ -22,6 +24,8 @@ final class Builtin extends LFunction { private static final String[] NAMES = { "print", "pairs", "getmetatable", "setmetatable" }; + private static PrintStream stdout = System.out; + private int id; private Builtin( int id ) { this.id = id; @@ -35,11 +39,13 @@ final class Builtin extends LFunction { public void luaStackCall(CallFrame call, int base, int top, int nresults) { switch ( id ) { case PRINT: - for ( int i=base+1; i= 0) call.adjustTop(base + nresults); } + + static void redirectOutput( OutputStream newStdOut ) { + stdout = new PrintStream( newStdOut ); + } + + static void restoreStandardOutput() { + stdout = System.out; + } -} \ No newline at end of file +} diff --git a/src/test/java/lua/LuaJTest.java b/src/test/java/lua/LuaJTest.java new file mode 100644 index 00000000..3d22b0b0 --- /dev/null +++ b/src/test/java/lua/LuaJTest.java @@ -0,0 +1,166 @@ +package lua; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; + +import junit.framework.TestCase; +import lua.StackState; +import lua.addon.luajava.LuaJava; +import lua.io.Closure; +import lua.io.LoadState; +import lua.io.Proto; +import lua.value.LValue; + + +public class LuaJTest extends TestCase { + + 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" ); + } + + private void runTest( String testName ) throws IOException, InterruptedException { + // add LuaJava bindings + LuaJava.install(); + + // new lua state + StackState state = new StackState(); + + // load the file + Proto p = loadScriptResource( state, testName, "/" + testName + ".luac" ); + + // Replace System.out with a ByteArrayOutputStream + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + Builtin.redirectOutput( outputStream ); + try { + // create closure and execute + Closure c = new Closure( state, p ); + state.doCall(c, new LValue[0], 0); + + final String actualOutput = new String( outputStream.toByteArray() ); + final String expectedOutput = getExpectedOutput( testName ); + + assertEquals( expectedOutput, actualOutput ); + } finally { + Builtin.restoreStandardOutput(); + outputStream.close(); + } + } + + private Proto loadScriptResource( StackState state, String name, String path ) throws IOException { + InputStream compiledScript = getClass().getResourceAsStream( path ); + try { + return LoadState.undump(state, compiledScript, name); + } finally { + compiledScript.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 = getClass().getResourceAsStream( "/" + testName + ".luac" ); + 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(); + + p.waitFor(); + inputCopier.join(); + outputCopier.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 ); + } + } + +} diff --git a/src/test/res/test7-expected.out b/src/test/res/test7-expected.out new file mode 100644 index 00000000..5d3459be --- /dev/null +++ b/src/test/res/test7-expected.out @@ -0,0 +1,6 @@ +java.lang.Object@b1b4c3 +SampleClass@72ffb +Hello +Hello +World +Square root of 9 is 3.0