Add argument type checking tests for io library

This commit is contained in:
James Roseborough
2008-12-05 01:47:50 +00:00
parent b54ef775d2
commit 5e734e1650
4 changed files with 174 additions and 49 deletions

View File

@@ -63,6 +63,15 @@ public class IoLib extends LFunction {
*/
abstract protected File openFile(String filename, String mode) throws IOException;
/**
* Start a new process and return a file for input or output
* @param prog the program to execute
* @param mode "r" to read, "w" to write
* @return File to read to or write from
* @throws IOException if an i/o exception occurs
*/
abstract protected File openProgram(String prog, String mode) throws IOException;
public static final String[] NAMES = {
"io",
@@ -130,10 +139,6 @@ public class IoLib extends LFunction {
PackageLib.setIsLoaded("io", io);
}
private static final char DEFVAL_NONE = 0;
private static final char DEFVAL_STDIN = 'r';
private static final char DEFVAL_STDOUT= 'w';
private final int id;
protected IoLib() {
@@ -182,7 +187,6 @@ public class IoLib extends LFunction {
public boolean luaStackCall( LuaState vm ) {
File f;
String s;
int n;
try {
switch ( id ) {
@@ -191,7 +195,10 @@ public class IoLib extends LFunction {
initialize(vm._G);
break;
case IO_CLOSE:
optfile(vm,2,DEFVAL_STDOUT).close();
f = vm.isnoneornil(2)?
output(vm):
checkfile(vm,2);
f.close();
vm.resettop();
vm.pushboolean(true);
break;
@@ -202,15 +209,17 @@ public class IoLib extends LFunction {
vm.pushboolean(true);
break;
case IO_INPUT:
INPUT = ((s = vm.optstring(1, null)) != null)?
ioopenfile(vm,s,"r"):
optfile(vm,2,DEFVAL_STDIN);
INPUT = vm.isnoneornil(2)?
input(vm):
vm.isstring(2)?
ioopenfile(vm,vm.checkstring(2),"r"):
checkfile(vm,2);
setresult(vm, INPUT);
break;
case IO_LINES:
INPUT = ((s = vm.optstring(1, null)) != null)?
ioopenfile(vm,s,"r"):
optfile(vm,2,DEFVAL_STDIN);
INPUT = vm.isnoneornil(2)?
input(vm):
ioopenfile(vm,vm.checkstring(2),"r");
vm.resettop();
vm.pushlvalue(lines(INPUT));
break;
@@ -218,12 +227,15 @@ public class IoLib extends LFunction {
setresult(vm, openFile(vm.checkstring(2), vm.optstring(3,"r")));
break;
case IO_OUTPUT:
OUTPUT = ((s = vm.optstring(2, null)) != null)?
ioopenfile(vm,s,"w"):
optfile(vm,2,DEFVAL_STDOUT);
OUTPUT = vm.isnoneornil(2)?
output(vm):
vm.isstring(2)?
ioopenfile(vm,vm.checkstring(2),"w"):
checkfile(vm,2);
setresult(vm, OUTPUT);
break;
case IO_POPEN:
setresult(vm, openProgram(vm.checkstring(2),vm.optstring(3, "r")));
break;
case IO_READ:
ioread( vm, INPUT );
@@ -231,7 +243,7 @@ public class IoLib extends LFunction {
case IO_TMPFILE:
break;
case IO_TYPE:
f = optfile(vm,2,DEFVAL_NONE);
f = optfile(vm,2);
vm.resettop();
if ( f != null )
vm.pushstring(f.isclosed()? "closed file": "file");
@@ -262,7 +274,9 @@ public class IoLib extends LFunction {
ioread(vm, f);
break;
case FILE_SEEK:
n = checkfile(vm,2).seek(vm.optstring(1,"cur"),vm.optint(3, 0));
f = checkfile(vm,2);
vm.remove(2);
n = f.seek(vm.optstring(2,"cur"),vm.optint(3, 0));
vm.resettop();
vm.pushinteger(n);
break;
@@ -303,7 +317,7 @@ public class IoLib extends LFunction {
private static void iowrite(LuaState vm, File f) throws IOException {
checkopen(vm,f);
for ( int i=2, n=vm.gettop(); i<=n; i++ )
f.write( vm.tolstring(i) );
f.write( vm.checklstring(i) );
vm.resettop();
vm.pushboolean(true);
}
@@ -334,12 +348,9 @@ public class IoLib extends LFunction {
return (File) vm.checkudata(index, File.class);
}
private File optfile(LuaState vm, int index, char defval) {
private File optfile(LuaState vm, int index) {
Object u = vm.touserdata(index);
return (u instanceof File? (File) u:
defval==DEFVAL_STDOUT? output(vm):
defval==DEFVAL_STDIN? input(vm):
null);
return (u instanceof File? (File) u: null);
}
private static void checkopen(LuaState vm, File file) {

View File

@@ -22,11 +22,6 @@
package org.luaj.lib.j2se;
import java.io.BufferedInputStream;
import java.io.ByteArrayOutputStream;
import java.io.Closeable;
import java.io.DataInput;
import java.io.DataInputStream;
import java.io.DataOutput;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
@@ -69,8 +64,12 @@ public class J2seIoLib extends IoLib {
// TODO: handle update mode
// boolean isupdate = mode.endsWith("+");
RandomAccessFile f = new RandomAccessFile(filename,isreadmode? "r": "rw");
if ( isappend )
if ( isappend ) {
f.seek(f.length());
} else {
if ( ! isreadmode )
f.setLength(0);
}
return new FileImpl( f );
}
@@ -82,41 +81,42 @@ public class J2seIoLib extends IoLib {
private final RandomAccessFile file;
private final InputStream is;
private final OutputStream os;
private final Closeable closer;
private final DataInput din;
private final DataOutput dout;
private boolean closed = false;
private FileImpl( RandomAccessFile file, InputStream is, OutputStream os, DataInput din, DataOutput dout, Closeable closer ) {
private FileImpl( RandomAccessFile file, InputStream is, OutputStream os ) {
this.file = file;
this.is = is!=null? is.markSupported()? is: new BufferedInputStream(is): null;
this.os = os;
this.din = din;
this.dout = dout;
this.closer = closer;
}
private FileImpl( RandomAccessFile f ) {
this( f, null, null, f, f, f );
this( f, null, null );
}
private FileImpl( InputStream i ) {
this( null, i, null, new DataInputStream(i), null, i );
this( null, i, null );
}
private FileImpl( OutputStream o ) {
this( null, null, o, null, new DataOutputStream(o), o );
this( null, null, o );
}
public String toString() {
return "file ("+this.hashCode()+")";
}
public void close() throws IOException {
closed = true;
closer.close();
if ( file != null )
file.close();
else if ( os != null )
os.close();
else if ( is != null )
is.close();
}
public void flush() throws IOException {
if ( os != null )
os.flush();
}
public void write(LString s) throws IOException {
if ( dout != null )
dout.write( s.m_bytes, s.m_offset, s.m_length );
if ( os != null )
os.write( s.m_bytes, s.m_offset, s.m_length );
else if ( file != null )
file.write( s.m_bytes, s.m_offset, s.m_length );
else
notimplemented();
}
@@ -125,21 +125,24 @@ public class J2seIoLib extends IoLib {
}
public int seek(String option, int pos) throws IOException {
if ( file != null ) {
if ( "set".equals(option) )
if ( "set".equals(option) ) {
file.seek(pos);
else if ( "end".equals(option) )
file.seek(file.length()+pos);
else
return (int) file.getFilePointer();
} else if ( "end".equals(option) ) {
file.seek(file.length()+1+pos);
return (int) file.length()+1;
} else {
file.seek(file.getFilePointer()+pos);
return (int) file.getFilePointer();
return (int) file.getFilePointer();
}
}
notimplemented();
return 0;
}
public LValue readBytes(int count) throws IOException {
if ( din != null ) {
if ( file != null ) {
byte[] b = new byte[count];
din.readFully(b);
file.readFully(b);
return new LString(b);
}
notimplemented();
@@ -208,4 +211,10 @@ public class J2seIoLib extends IoLib {
}
}
protected File openProgram(String prog, String mode) throws IOException {
final Process p = Runtime.getRuntime().exec(prog);
return "w".equals(mode)?
new FileImpl( p.getOutputStream() ):
new FileImpl( p.getInputStream() );
}
}

View File

@@ -0,0 +1,68 @@
package.path = "?.lua;src/test/errors/?.lua"
require 'args'
-- arg type tests for io library functions
local f
-- io.close ([file])
banner('io.close')
f = io.open("abc.txt","w")
checkallpass('io.close',{{f}})
checkallerrors('io.close',{notanil},'bad argument #1')
-- io.input ([file])
checkallpass('io.input',{{nil,f,"abc.txt"}})
checkallerrors('io.input',{nonstring},'bad argument #1')
-- io.lines ([filename])
io.input("abc.txt")
checkallpass('io.lines',{{nil,"abc.txt"}})
checkallerrors('io.lines',{{f}},'bad argument #1')
checkallerrors('io.lines',{nonstring},'bad argument #1')
-- io.open (filename [, mode])
checkallpass('io.open',{{"abc.txt"},{nil,"r","w","a","r+","w+","a+"}})
checkallerrors('io.open',{notastring},'bad argument #1')
checkallerrors('io.open',{{"abc.txt"},{nonstring}},'bad argument #2')
-- io.output ([file])
checkallpass('io.output',{{nil,f,"abc.txt"}})
checkallerrors('io.output',{nonstring},'bad argument #1')
-- io.popen (prog [, mode])
checkallpass('io.popen',{{"hostname"},{nil,"r","w","a","r+","w+","a+"}})
checkallerrors('io.popen',{notastring},'bad argument #1')
checkallerrors('io.popen',{{"hostname"},{nonstring}},'bad argument #2')
-- io.read (···)
local areadfmt = {2,"*n","*a","*l","3"}
checkallpass('io.read',{})
checkallpass('io.read',{areadfmt})
checkallpass('io.read',{areadfmt,areadfmt})
checkallerrors('io.read',{{aboolean,afunction,atable}},'bad argument #1')
-- io.read (···)
checkallpass('io.write',{})
checkallpass('io.write',{somestring})
checkallpass('io.write',{somestring,somestring})
checkallerrors('io.write',{nonstring},'bad argument #1')
checkallerrors('io.write',{somestring,nonstring},'bad argument #2')
-- file:write ()
file = io.open("seektest.txt","w")
checkallpass('file.write',{{file},somestring})
checkallpass('file.write',{{file},somestring,somestring})
checkallerrors('file.write',{},'bad argument #1')
checkallerrors('file.write',{{file},nonstring},'bad argument #1')
checkallerrors('file.write',{{file},somestring,nonstring},'bad argument #2')
pcall( file.close, file )
-- file:seek ([whence] [, offset])
file = io.open("seektest.txt","r")
checkallpass('file.seek',{{file}})
checkallpass('file.seek',{{file},{"set","cur","end"}})
checkallpass('file.seek',{{file},{"set","cur","end"},{2,"3"}})
checkallerrors('file.seek',{},'bad argument #1')
checkallerrors('file.seek',{{file},nonstring},'bad argument #1')
checkallerrors('file.seek',{{file},{"set","cur","end"},nonnumber},'bad argument #2')

View File

@@ -24,3 +24,40 @@ for i,v in ipairs(t) do
print( string.format("%q",tostring(v)), type(v))
end
local h = io.open("abc.txt", "a")
print( 'h', io.type(h) )
print( 'write', h:write('\nmore text\neven more text\n') )
print( 'close', h:close() )
local j = io.open( "abc.txt", "r" )
print( 'j', io.type(j) )
print( 'seek', j:seek("set", 3) )
print( 'read', j:read(4), j:read(3) )
print( 'seek', j:seek("set", 2) )
print( 'read', j:read(4), j:read(3) )
print( 'seek', j:seek("cur", -8 ) )
print( 'read', j:read(4), j:read(3) )
print( 'seek(cur,0)', j:seek("cur",0) )
print( 'seek(cur,20)', j:seek("cur",20) )
print( 'seek(end,-5)', j:seek("end", -5) )
print( 'read(4)', string.format("%q", tostring(j:read(4))) )
print( 'read(4)', string.format("%q", tostring(j:read(4))) )
print( 'read(4)', string.format("%q", tostring(j:read(4))) )
for l in io.lines("abc.txt") do
print( string.format('%q',l) )
end
io.input("abc.txt")
for l in io.lines() do
print( string.format('%q',l) )
end
io.input(io.open("abc.txt","r"))
for l in io.lines() do
print( string.format('%q',l) )
end
io.input("abc.txt")
io.input(io.input())
for l in io.lines() do
print( string.format('%q',l) )
end