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