Add argument type checking tests for io library
This commit is contained in:
@@ -63,6 +63,15 @@ public class IoLib extends LFunction {
|
|||||||
*/
|
*/
|
||||||
abstract protected File openFile(String filename, String mode) throws IOException;
|
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 = {
|
public static final String[] NAMES = {
|
||||||
"io",
|
"io",
|
||||||
@@ -130,10 +139,6 @@ public class IoLib extends LFunction {
|
|||||||
PackageLib.setIsLoaded("io", io);
|
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;
|
private final int id;
|
||||||
|
|
||||||
protected IoLib() {
|
protected IoLib() {
|
||||||
@@ -182,7 +187,6 @@ public class IoLib extends LFunction {
|
|||||||
|
|
||||||
public boolean luaStackCall( LuaState vm ) {
|
public boolean luaStackCall( LuaState vm ) {
|
||||||
File f;
|
File f;
|
||||||
String s;
|
|
||||||
int n;
|
int n;
|
||||||
try {
|
try {
|
||||||
switch ( id ) {
|
switch ( id ) {
|
||||||
@@ -191,7 +195,10 @@ public class IoLib extends LFunction {
|
|||||||
initialize(vm._G);
|
initialize(vm._G);
|
||||||
break;
|
break;
|
||||||
case IO_CLOSE:
|
case IO_CLOSE:
|
||||||
optfile(vm,2,DEFVAL_STDOUT).close();
|
f = vm.isnoneornil(2)?
|
||||||
|
output(vm):
|
||||||
|
checkfile(vm,2);
|
||||||
|
f.close();
|
||||||
vm.resettop();
|
vm.resettop();
|
||||||
vm.pushboolean(true);
|
vm.pushboolean(true);
|
||||||
break;
|
break;
|
||||||
@@ -202,15 +209,17 @@ public class IoLib extends LFunction {
|
|||||||
vm.pushboolean(true);
|
vm.pushboolean(true);
|
||||||
break;
|
break;
|
||||||
case IO_INPUT:
|
case IO_INPUT:
|
||||||
INPUT = ((s = vm.optstring(1, null)) != null)?
|
INPUT = vm.isnoneornil(2)?
|
||||||
ioopenfile(vm,s,"r"):
|
input(vm):
|
||||||
optfile(vm,2,DEFVAL_STDIN);
|
vm.isstring(2)?
|
||||||
|
ioopenfile(vm,vm.checkstring(2),"r"):
|
||||||
|
checkfile(vm,2);
|
||||||
setresult(vm, INPUT);
|
setresult(vm, INPUT);
|
||||||
break;
|
break;
|
||||||
case IO_LINES:
|
case IO_LINES:
|
||||||
INPUT = ((s = vm.optstring(1, null)) != null)?
|
INPUT = vm.isnoneornil(2)?
|
||||||
ioopenfile(vm,s,"r"):
|
input(vm):
|
||||||
optfile(vm,2,DEFVAL_STDIN);
|
ioopenfile(vm,vm.checkstring(2),"r");
|
||||||
vm.resettop();
|
vm.resettop();
|
||||||
vm.pushlvalue(lines(INPUT));
|
vm.pushlvalue(lines(INPUT));
|
||||||
break;
|
break;
|
||||||
@@ -218,12 +227,15 @@ public class IoLib extends LFunction {
|
|||||||
setresult(vm, openFile(vm.checkstring(2), vm.optstring(3,"r")));
|
setresult(vm, openFile(vm.checkstring(2), vm.optstring(3,"r")));
|
||||||
break;
|
break;
|
||||||
case IO_OUTPUT:
|
case IO_OUTPUT:
|
||||||
OUTPUT = ((s = vm.optstring(2, null)) != null)?
|
OUTPUT = vm.isnoneornil(2)?
|
||||||
ioopenfile(vm,s,"w"):
|
output(vm):
|
||||||
optfile(vm,2,DEFVAL_STDOUT);
|
vm.isstring(2)?
|
||||||
|
ioopenfile(vm,vm.checkstring(2),"w"):
|
||||||
|
checkfile(vm,2);
|
||||||
setresult(vm, OUTPUT);
|
setresult(vm, OUTPUT);
|
||||||
break;
|
break;
|
||||||
case IO_POPEN:
|
case IO_POPEN:
|
||||||
|
setresult(vm, openProgram(vm.checkstring(2),vm.optstring(3, "r")));
|
||||||
break;
|
break;
|
||||||
case IO_READ:
|
case IO_READ:
|
||||||
ioread( vm, INPUT );
|
ioread( vm, INPUT );
|
||||||
@@ -231,7 +243,7 @@ public class IoLib extends LFunction {
|
|||||||
case IO_TMPFILE:
|
case IO_TMPFILE:
|
||||||
break;
|
break;
|
||||||
case IO_TYPE:
|
case IO_TYPE:
|
||||||
f = optfile(vm,2,DEFVAL_NONE);
|
f = optfile(vm,2);
|
||||||
vm.resettop();
|
vm.resettop();
|
||||||
if ( f != null )
|
if ( f != null )
|
||||||
vm.pushstring(f.isclosed()? "closed file": "file");
|
vm.pushstring(f.isclosed()? "closed file": "file");
|
||||||
@@ -262,7 +274,9 @@ public class IoLib extends LFunction {
|
|||||||
ioread(vm, f);
|
ioread(vm, f);
|
||||||
break;
|
break;
|
||||||
case FILE_SEEK:
|
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.resettop();
|
||||||
vm.pushinteger(n);
|
vm.pushinteger(n);
|
||||||
break;
|
break;
|
||||||
@@ -303,7 +317,7 @@ public class IoLib extends LFunction {
|
|||||||
private static void iowrite(LuaState vm, File f) throws IOException {
|
private static void iowrite(LuaState vm, File f) throws IOException {
|
||||||
checkopen(vm,f);
|
checkopen(vm,f);
|
||||||
for ( int i=2, n=vm.gettop(); i<=n; i++ )
|
for ( int i=2, n=vm.gettop(); i<=n; i++ )
|
||||||
f.write( vm.tolstring(i) );
|
f.write( vm.checklstring(i) );
|
||||||
vm.resettop();
|
vm.resettop();
|
||||||
vm.pushboolean(true);
|
vm.pushboolean(true);
|
||||||
}
|
}
|
||||||
@@ -334,12 +348,9 @@ public class IoLib extends LFunction {
|
|||||||
return (File) vm.checkudata(index, File.class);
|
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);
|
Object u = vm.touserdata(index);
|
||||||
return (u instanceof File? (File) u:
|
return (u instanceof File? (File) u: null);
|
||||||
defval==DEFVAL_STDOUT? output(vm):
|
|
||||||
defval==DEFVAL_STDIN? input(vm):
|
|
||||||
null);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void checkopen(LuaState vm, File file) {
|
private static void checkopen(LuaState vm, File file) {
|
||||||
|
|||||||
@@ -22,11 +22,6 @@
|
|||||||
package org.luaj.lib.j2se;
|
package org.luaj.lib.j2se;
|
||||||
import java.io.BufferedInputStream;
|
import java.io.BufferedInputStream;
|
||||||
import java.io.ByteArrayOutputStream;
|
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.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
@@ -69,8 +64,12 @@ public class J2seIoLib extends IoLib {
|
|||||||
// TODO: handle update mode
|
// TODO: handle update mode
|
||||||
// boolean isupdate = mode.endsWith("+");
|
// boolean isupdate = mode.endsWith("+");
|
||||||
RandomAccessFile f = new RandomAccessFile(filename,isreadmode? "r": "rw");
|
RandomAccessFile f = new RandomAccessFile(filename,isreadmode? "r": "rw");
|
||||||
if ( isappend )
|
if ( isappend ) {
|
||||||
f.seek(f.length());
|
f.seek(f.length());
|
||||||
|
} else {
|
||||||
|
if ( ! isreadmode )
|
||||||
|
f.setLength(0);
|
||||||
|
}
|
||||||
return new FileImpl( f );
|
return new FileImpl( f );
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -82,41 +81,42 @@ public class J2seIoLib extends IoLib {
|
|||||||
private final RandomAccessFile file;
|
private final RandomAccessFile file;
|
||||||
private final InputStream is;
|
private final InputStream is;
|
||||||
private final OutputStream os;
|
private final OutputStream os;
|
||||||
private final Closeable closer;
|
|
||||||
private final DataInput din;
|
|
||||||
private final DataOutput dout;
|
|
||||||
private boolean closed = false;
|
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.file = file;
|
||||||
this.is = is!=null? is.markSupported()? is: new BufferedInputStream(is): null;
|
this.is = is!=null? is.markSupported()? is: new BufferedInputStream(is): null;
|
||||||
this.os = os;
|
this.os = os;
|
||||||
this.din = din;
|
|
||||||
this.dout = dout;
|
|
||||||
this.closer = closer;
|
|
||||||
}
|
}
|
||||||
private FileImpl( RandomAccessFile f ) {
|
private FileImpl( RandomAccessFile f ) {
|
||||||
this( f, null, null, f, f, f );
|
this( f, null, null );
|
||||||
}
|
}
|
||||||
private FileImpl( InputStream i ) {
|
private FileImpl( InputStream i ) {
|
||||||
this( null, i, null, new DataInputStream(i), null, i );
|
this( null, i, null );
|
||||||
}
|
}
|
||||||
private FileImpl( OutputStream o ) {
|
private FileImpl( OutputStream o ) {
|
||||||
this( null, null, o, null, new DataOutputStream(o), o );
|
this( null, null, o );
|
||||||
}
|
}
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "file ("+this.hashCode()+")";
|
return "file ("+this.hashCode()+")";
|
||||||
}
|
}
|
||||||
public void close() throws IOException {
|
public void close() throws IOException {
|
||||||
closed = true;
|
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 {
|
public void flush() throws IOException {
|
||||||
if ( os != null )
|
if ( os != null )
|
||||||
os.flush();
|
os.flush();
|
||||||
}
|
}
|
||||||
public void write(LString s) throws IOException {
|
public void write(LString s) throws IOException {
|
||||||
if ( dout != null )
|
if ( os != null )
|
||||||
dout.write( s.m_bytes, s.m_offset, s.m_length );
|
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
|
else
|
||||||
notimplemented();
|
notimplemented();
|
||||||
}
|
}
|
||||||
@@ -125,21 +125,24 @@ public class J2seIoLib extends IoLib {
|
|||||||
}
|
}
|
||||||
public int seek(String option, int pos) throws IOException {
|
public int seek(String option, int pos) throws IOException {
|
||||||
if ( file != null ) {
|
if ( file != null ) {
|
||||||
if ( "set".equals(option) )
|
if ( "set".equals(option) ) {
|
||||||
file.seek(pos);
|
file.seek(pos);
|
||||||
else if ( "end".equals(option) )
|
return (int) file.getFilePointer();
|
||||||
file.seek(file.length()+pos);
|
} else if ( "end".equals(option) ) {
|
||||||
else
|
file.seek(file.length()+1+pos);
|
||||||
|
return (int) file.length()+1;
|
||||||
|
} else {
|
||||||
file.seek(file.getFilePointer()+pos);
|
file.seek(file.getFilePointer()+pos);
|
||||||
return (int) file.getFilePointer();
|
return (int) file.getFilePointer();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
notimplemented();
|
notimplemented();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
public LValue readBytes(int count) throws IOException {
|
public LValue readBytes(int count) throws IOException {
|
||||||
if ( din != null ) {
|
if ( file != null ) {
|
||||||
byte[] b = new byte[count];
|
byte[] b = new byte[count];
|
||||||
din.readFully(b);
|
file.readFully(b);
|
||||||
return new LString(b);
|
return new LString(b);
|
||||||
}
|
}
|
||||||
notimplemented();
|
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() );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
68
src/test/errors/iolibargs.lua
Normal file
68
src/test/errors/iolibargs.lua
Normal 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')
|
||||||
|
|
||||||
@@ -24,3 +24,40 @@ for i,v in ipairs(t) do
|
|||||||
print( string.format("%q",tostring(v)), type(v))
|
print( string.format("%q",tostring(v)), type(v))
|
||||||
end
|
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
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user