Add a function for type-checking arguments (#207)

- Define an expect(index, actual_value, types...) helper function which
   takes an argument index, value and list of permissable types and
   ensures the value is of one of those types.
   If not, it will produce an error message with the expected and actual
   type, as well as the argument number and (if available) the function
   name.
 - Expose expect in the global scope as _G["~expect"], hopefully making
   it clear it is internal.
 - Replace most manual type checks with this helper method.
 - Write tests to ensure this argument validation works as expected

Also fix a couple of bugs exposed by this refactor and the subsequent
tests:
 - Make rednet checks a little more strict - rednet.close(false) is no
   longer valid.
 - Error when attempting to redirect the terminal to itself 
   (term.redirect(term)).
This commit is contained in:
hydraz 2019-05-30 15:36:28 -03:00 committed by SquidDev
parent 5592ebae7d
commit 9048deeb95
34 changed files with 1070 additions and 428 deletions

View File

@ -1,5 +1,48 @@
local native_select, native_type = select, type
--- Expect an argument to have a specific type.
--
-- @tparam int index The 1-based argument index.
-- @param value The argument's value.
-- @tparam string ... The allowed types of the argument.
-- @throws If the value is not one of the allowed types.
local function expect(index, value, ...)
local t = native_type(value)
for i = 1, native_select("#", ...) do
if t == native_select(i, ...) then return true end
end
local types = table.pack(...)
for i = types.n, 1, -1 do
if types[i] == "nil" then table.remove(types, i) end
end
local type_names
if #types <= 1 then
type_names = tostring(...)
else
type_names = table.concat(types, ", ", 1, #types - 1) .. " or " .. types[#types]
end
-- If we can determine the function name with a high level of confidence, try to include it.
local name
if native_type(debug) == "table" and native_type(debug.getinfo) == "function" then
local ok, info = pcall(debug.getinfo, 3, "nS")
if ok and info.name and #info.name ~= "" and info.what ~= "C" then name = info.name end
end
if name then
error( ("bad argument #%d to '%s' (expected %s, got %s)"):format(index, name, type_names, t), 3 )
else
error( ("bad argument #%d (expected %s, got %s)"):format(index, type_names, t), 3 )
end
end
-- We expose expect in the global table as APIs need to access it, but give it
-- a non-identifier name - meaning it does not show up in auto-completion.
-- expect is an internal function, and should not be used by users.
_G["~expect"] = expect
local nativegetfenv = getfenv
if _VERSION == "Lua 5.1" then
-- If we're on Lua 5.1, install parts of the Lua 5.2/5.3 API so that programs can be written against it
local type = type
@ -20,18 +63,11 @@ if _VERSION == "Lua 5.1" then
end
function load( x, name, mode, env )
if type( x ) ~= "string" and type( x ) ~= "function" then
error( "bad argument #1 (expected string or function, got " .. type( x ) .. ")", 2 )
end
if name ~= nil and type( name ) ~= "string" then
error( "bad argument #2 (expected string, got " .. type( name ) .. ")", 2 )
end
if mode ~= nil and type( mode ) ~= "string" then
error( "bad argument #3 (expected string, got " .. type( mode ) .. ")", 2 )
end
if env ~= nil and type( env) ~= "table" then
error( "bad argument #4 (expected table, got " .. type( env ) .. ")", 2 )
end
expect(1, x, "function", "string")
expect(2, name, "string", "nil")
expect(3, mode, "string", "nil")
expect(4, env, "table", "nil")
local ok, p1, p2 = pcall( function()
if type(x) == "string" then
local result, err = nativeloadstring( x, name )
@ -76,10 +112,9 @@ if _VERSION == "Lua 5.1" then
math.log10 = nil
table.maxn = nil
else
loadstring = function(string, chunkname) return nativeloadstring(string, prefix( chunkname ))
loadstring = function(string, chunkname) return nativeloadstring(string, prefix( chunkname )) end
-- Inject a stub for the old bit library
end
_G.bit = {
bnot = bit32.bnot,
band = bit32.band,
@ -175,9 +210,7 @@ end
-- Install globals
function sleep( nTime )
if nTime ~= nil and type( nTime ) ~= "number" then
error( "bad argument #1 (expected number, got " .. type( nTime ) .. ")", 2 )
end
expect(1, nTime, "number", "nil")
local timer = os.startTimer( nTime or 0 )
repeat
local sEvent, param = os.pullEvent( "timer" )
@ -185,9 +218,7 @@ function sleep( nTime )
end
function write( sText )
if type( sText ) ~= "string" and type( sText ) ~= "number" then
error( "bad argument #1 (expected string or number, got " .. type( sText ) .. ")", 2 )
end
expect(1, sText, "string", "number")
local w,h = term.getSize()
local x,y = term.getCursorPos()
@ -275,18 +306,11 @@ function printError( ... )
end
function read( _sReplaceChar, _tHistory, _fnComplete, _sDefault )
if _sReplaceChar ~= nil and type( _sReplaceChar ) ~= "string" then
error( "bad argument #1 (expected string, got " .. type( _sReplaceChar ) .. ")", 2 )
end
if _tHistory ~= nil and type( _tHistory ) ~= "table" then
error( "bad argument #2 (expected table, got " .. type( _tHistory ) .. ")", 2 )
end
if _fnComplete ~= nil and type( _fnComplete ) ~= "function" then
error( "bad argument #3 (expected function, got " .. type( _fnComplete ) .. ")", 2 )
end
if _sDefault ~= nil and type( _sDefault ) ~= "string" then
error( "bad argument #4 (expected string, got " .. type( _sDefault ) .. ")", 2 )
end
expect(1, _sReplaceChar, "string", "nil")
expect(2, _tHistory, "table", "nil")
expect(3, _fnComplete, "function", "nil")
expect(4, _sDefault, "string", "nil")
term.setCursorBlink( true )
local sLine
@ -544,13 +568,10 @@ function read( _sReplaceChar, _tHistory, _fnComplete, _sDefault )
return sLine
end
loadfile = function( _sFile, _tEnv )
if type( _sFile ) ~= "string" then
error( "bad argument #1 (expected string, got " .. type( _sFile ) .. ")", 2 )
end
if _tEnv ~= nil and type( _tEnv ) ~= "table" then
error( "bad argument #2 (expected table, got " .. type( _tEnv ) .. ")", 2 )
end
function loadfile( _sFile, _tEnv )
expect(1, _sFile, "string")
expect(2, _tEnv, "table", "nil")
local file = fs.open( _sFile, "r" )
if file then
local func, err = load( file.readAll(), "@" .. fs.getName( _sFile ), "t", _tEnv )
@ -560,10 +581,9 @@ loadfile = function( _sFile, _tEnv )
return nil, "File not found"
end
dofile = function( _sFile )
if type( _sFile ) ~= "string" then
error( "bad argument #1 (expected string, got " .. type( _sFile ) .. ")", 2 )
end
function dofile( _sFile )
expect(1, _sFile, "string")
local fnFile, e = loadfile( _sFile, _G )
if fnFile then
return fnFile()
@ -574,12 +594,9 @@ end
-- Install the rest of the OS api
function os.run( _tEnv, _sPath, ... )
if type( _tEnv ) ~= "table" then
error( "bad argument #1 (expected table, got " .. type( _tEnv ) .. ")", 2 )
end
if type( _sPath ) ~= "string" then
error( "bad argument #2 (expected string, got " .. type( _sPath ) .. ")", 2 )
end
expect(1, _tEnv, "table")
expect(2, _sPath, "string")
local tArgs = table.pack( ... )
local tEnv = _tEnv
setmetatable( tEnv, { __index = _G } )
@ -604,9 +621,7 @@ end
local tAPIsLoading = {}
function os.loadAPI( _sPath )
if type( _sPath ) ~= "string" then
error( "bad argument #1 (expected string, got " .. type( _sPath ) .. ")", 2 )
end
expect(1, _sPath, "string")
local sName = fs.getName( _sPath )
if sName:sub(-4) == ".lua" then
sName = sName:sub(1,-5)
@ -644,9 +659,7 @@ function os.loadAPI( _sPath )
end
function os.unloadAPI( _sName )
if type( _sName ) ~= "string" then
error( "bad argument #1 (expected string, got " .. type( _sName ) .. ")", 2 )
end
expect(1, _sName, "string")
if _sName ~= "_G" and type(_G[_sName]) == "table" then
_G[_sName] = nil
end
@ -692,9 +705,11 @@ if http then
local function checkOptions( options, body )
checkKey( options, "url", "string")
if body == false
then checkKey( options, "body", "nil" )
else checkKey( options, "body", "string", not body ) end
if body == false then
checkKey( options, "body", "nil" )
else
checkKey( options, "body", "string", not body )
end
checkKey( options, "headers", "table", true )
checkKey( options, "method", "string", true )
checkKey( options, "redirect", "boolean", true )
@ -725,15 +740,9 @@ if http then
return wrapRequest( _url.url, _url )
end
if type( _url ) ~= "string" then
error( "bad argument #1 (expected string, got " .. type( _url ) .. ")", 2 )
end
if _headers ~= nil and type( _headers ) ~= "table" then
error( "bad argument #2 (expected table, got " .. type( _headers ) .. ")", 2 )
end
if _binary ~= nil and type( _binary ) ~= "boolean" then
error( "bad argument #3 (expected boolean, got " .. type( _binary ) .. ")", 2 )
end
expect(1, _url, "string")
expect(2, _headers, "table", "nil")
expect(3, _binary, "boolean", "nil")
return wrapRequest( _url, _url, nil, _headers, _binary )
end
@ -743,18 +752,10 @@ if http then
return wrapRequest( _url.url, _url )
end
if type( _url ) ~= "string" then
error( "bad argument #1 (expected string, got " .. type( _url ) .. ")", 2 )
end
if type( _post ) ~= "string" then
error( "bad argument #2 (expected string, got " .. type( _post ) .. ")", 2 )
end
if _headers ~= nil and type( _headers ) ~= "table" then
error( "bad argument #3 (expected table, got " .. type( _headers ) .. ")", 2 )
end
if _binary ~= nil and type( _binary ) ~= "boolean" then
error( "bad argument #4 (expected boolean, got " .. type( _binary ) .. ")", 2 )
end
expect(1, _url, "string")
expect(2, _post, "string")
expect(3, _headers, "table", "nil")
expect(4, _binary, "boolean", "nil")
return wrapRequest( _url, _url, _post, _headers, _binary )
end
@ -764,19 +765,10 @@ if http then
checkOptions( _url )
url = _url.url
else
if type( _url ) ~= "string" then
error( "bad argument #1 (expected string, got " .. type( _url ) .. ")", 2 )
end
if _post ~= nil and type( _post ) ~= "string" then
error( "bad argument #2 (expected string, got " .. type( _post ) .. ")", 2 )
end
if _headers ~= nil and type( _headers ) ~= "table" then
error( "bad argument #3 (expected table, got " .. type( _headers ) .. ")", 2 )
end
if _binary ~= nil and type( _binary ) ~= "boolean" then
error( "bad argument #4 (expected boolean, got " .. type( _binary ) .. ")", 2 )
end
expect(1, _url, "string")
expect(2, _post, "string", "nil")
expect(3, _headers, "table", "nil")
expect(4, _binary, "boolean", "nil")
url = _url.url
end
@ -802,12 +794,9 @@ if http then
local nativeWebsocket = http.websocket
http.websocketAsync = nativeWebsocket
http.websocket = function( _url, _headers )
if type( _url ) ~= "string" then
error( "bad argument #1 (expected string, got " .. type( _url ) .. ")", 2 )
end
if _headers ~= nil and type( _headers ) ~= "table" then
error( "bad argument #2 (expected table, got " .. type( _headers ) .. ")", 2 )
end
expect(1, _url, "string")
expect(2, _headers, "table", "nil")
local ok, err = nativeWebsocket( _url, _headers )
if not ok then return ok, err end
@ -825,18 +814,11 @@ end
-- Install the lua part of the FS api
local tEmpty = {}
function fs.complete( sPath, sLocation, bIncludeFiles, bIncludeDirs )
if type( sPath ) ~= "string" then
error( "bad argument #1 (expected string, got " .. type( sPath ) .. ")", 2 )
end
if type( sLocation ) ~= "string" then
error( "bad argument #2 (expected string, got " .. type( sLocation ) .. ")", 2 )
end
if bIncludeFiles ~= nil and type( bIncludeFiles ) ~= "boolean" then
error( "bad argument #3 (expected boolean, got " .. type( bIncludeFiles ) .. ")", 2 )
end
if bIncludeDirs ~= nil and type( bIncludeDirs ) ~= "boolean" then
error( "bad argument #4 (expected boolean, got " .. type( bIncludeDirs ) .. ")", 2 )
end
expect(1, sPath, "string")
expect(2, sLocation, "string")
expect(3, bIncludeFiles, "boolean", "nil")
expect(4, bIncludeDirs, "boolean", "nil")
bIncludeFiles = (bIncludeFiles ~= false)
bIncludeDirs = (bIncludeDirs ~= false)
local sDir = sLocation

View File

@ -1,3 +1,5 @@
local expect = _G["~expect"]
-- Colors
white = 1
orange = 2
@ -19,48 +21,32 @@ black = 32768
function combine( ... )
local r = 0
for n,c in ipairs( { ... } ) do
if type( c ) ~= "number" then
error( "bad argument #"..n.." (expected number, got " .. type( c ) .. ")", 2 )
end
expect(n, c, "number")
r = bit32.bor(r,c)
end
return r
end
function subtract( colors, ... )
if type( colors ) ~= "number" then
error( "bad argument #1 (expected number, got " .. type( colors ) .. ")", 2 )
end
expect(1, colors, "number")
local r = colors
for n,c in ipairs( { ... } ) do
if type( c ) ~= "number" then
error( "bad argument #"..tostring( n+1 ).." (expected number, got " .. type( c ) .. ")", 2 )
end
expect(n + 1, c, "number")
r = bit32.band(r, bit32.bnot(c))
end
return r
end
function test( colors, color )
if type( colors ) ~= "number" then
error( "bad argument #1 (expected number, got " .. type( colors ) .. ")", 2 )
end
if type( color ) ~= "number" then
error( "bad argument #2 (expected number, got " .. type( color ) .. ")", 2 )
end
expect(1, colors, "number")
expect(2, color, "number")
return bit32.band(colors, color) == color
end
function packRGB( r, g, b )
if type( r ) ~= "number" then
error( "bad argument #1 (expected number, got " .. type( r ) .. ")", 2 )
end
if type( g ) ~= "number" then
error( "bad argument #2 (expected number, got " .. type( g ) .. ")", 2 )
end
if type( b ) ~= "number" then
error( "bad argument #3 (expected number, got " .. type( b ) .. ")", 2 )
end
expect(1, r, "number")
expect(2, g, "number")
expect(3, b, "number")
return
bit32.band( r * 255, 0xFF ) * 2^16 +
bit32.band( g * 255, 0xFF ) * 2^8 +
@ -68,9 +54,7 @@ function packRGB( r, g, b )
end
function unpackRGB( rgb )
if type( rgb ) ~= "number" then
error( "bad argument #1 (expected number, got " .. type( rgb ) .. ")", 2 )
end
expect(1, rgb, "number")
return
bit32.band( bit32.rshift( rgb, 16 ), 0xFF ) / 255,
bit32.band( bit32.rshift( rgb, 8 ), 0xFF ) / 255,

View File

@ -1,3 +1,5 @@
local expect = _G["~expect"]
CHANNEL_GPS = 65534
local function trilaterate( A, B, C )
@ -55,12 +57,8 @@ local function narrow( p1, p2, fix )
end
function locate( _nTimeout, _bDebug )
if _nTimeout ~= nil and type( _nTimeout ) ~= "number" then
error( "bad argument #1 (expected number, got " .. type( _nTimeout ) .. ")", 2 )
end
if _bDebug ~= nil and type( _bDebug ) ~= "boolean" then
error( "bad argument #2 (expected boolean, got " .. type( _bDebug) .. ")", 2 )
end
expect(1, _nTimeout, "number", "nil")
expect(2, _bDebug, "boolean", "nil")
-- Let command computers use their magic fourth-wall-breaking special abilities
if commands then
return commands.getBlockPosition()

View File

@ -1,3 +1,4 @@
local expect = _G["~expect"]
local sPath = "/rom/help"
@ -6,17 +7,13 @@ function path()
end
function setPath( _sPath )
if type( _sPath ) ~= "string" then
error( "bad argument #1 (expected string, got " .. type( _sPath ) .. ")", 2 )
end
expect(1, _sPath, "string")
sPath = _sPath
end
function lookup( _sTopic )
if type( _sTopic ) ~= "string" then
error( "bad argument #1 (expected string, got " .. type( _sTopic ) .. ")", 2 )
end
-- Look on the path variable
expect(1, _sTopic, "string")
-- Look on the path variable
for sPath in string.gmatch(sPath, "[^:]+") do
sPath = fs.combine( sPath, _sTopic )
if fs.exists( sPath ) and not fs.isDir( sPath ) then
@ -63,9 +60,7 @@ function topics()
end
function completeTopic( sText )
if type( sText ) ~= "string" then
error( "bad argument #1 (expected string, got " .. type( sText ) .. ")", 2 )
end
expect(1, sText, "string")
local tTopics = topics()
local tResults = {}
for n=1,#tTopics do

View File

@ -1,5 +1,6 @@
-- Definition for the IO API
local typeOf = _G.type
local expect, typeOf = _G["~expect"], _G.type
--- If we return nil then close the file, as we've reached the end.
-- We use this weird wrapper function as we wish to preserve the varargs
@ -65,7 +66,7 @@ handleMetatable = {
local handle = self._handle
if not handle.read and not handle.readLine then return nil, "Not opened for reading" end
local n = select('#', ...)
local n = select("#", ...)
local output = {}
for i = 1, n do
local arg = select(i, ...)
@ -184,9 +185,7 @@ function input(_arg)
end
function lines(_sFileName)
if _sFileName ~= nil and typeOf(_sFileName) ~= "string" then
error("bad argument #1 (expected string, got " .. typeOf(_sFileName) .. ")", 2)
end
expect(1, _sFileName, "string", "nil")
if _sFileName then
local ok, err = open(_sFileName, "rb")
if not ok then error(err, 2) end
@ -201,12 +200,8 @@ function lines(_sFileName)
end
function open(_sPath, _sMode)
if typeOf(_sPath) ~= "string" then
error("bad argument #1 (expected string, got " .. typeOf(_sPath) .. ")", 2)
end
if _sMode ~= nil and typeOf(_sMode) ~= "string" then
error("bad argument #2 (expected string, got " .. typeOf(_sMode) .. ")", 2)
end
expect(1, _sPath, "string")
expect(2, _sMode, "string", "nil")
local sMode = _sMode and _sMode:gsub("%+", "") or "rb"
local file, err = fs.open(_sPath, sMode)

View File

@ -1,7 +1,8 @@
-- Minecraft key code bindings
-- See http://www.minecraftwiki.net/wiki/Key_codes for more info
local expect = _G["~expect"]
local tKeys = {
nil, "one", "two", "three", "four", -- 1
"five", "six", "seven", "eight", "nine", -- 6
@ -58,8 +59,6 @@ keys.scollLock = keys.scrollLock
keys.cimcumflex = keys.circumflex
function getName( _nKey )
if type( _nKey ) ~= "number" then
error( "bad argument #1 (expected number, got " .. type( _nKey ) .. ")", 2 )
end
expect(1, _nKey, "number")
return tKeys[ _nKey ]
end

View File

@ -1,3 +1,4 @@
local expect = _G["~expect"]
local function drawPixelInternal( xPos, yPos )
term.setCursorPos( xPos, yPos )
@ -18,9 +19,7 @@ local function parseLine( tImageArg, sLine )
end
function parseImage( sRawData )
if type( sRawData ) ~= "string" then
error( "bad argument #1 (expected string, got " .. type( sRawData ) .. ")" )
end
expect(1, sRawData, "string")
local tImage = {}
for sLine in ( sRawData .. "\n" ):gmatch( "(.-)\n" ) do -- read each line like original file handling did
parseLine( tImage, sLine )
@ -29,9 +28,7 @@ function parseImage( sRawData )
end
function loadImage( sPath )
if type( sPath ) ~= "string" then
error( "bad argument #1 (expected string, got " .. type( sPath ) .. ")", 2 )
end
expect(1, sPath, "string")
if fs.exists( sPath ) then
local file = io.open( sPath, "r" )
@ -43,21 +40,21 @@ function loadImage( sPath )
end
function drawPixel( xPos, yPos, nColour )
if type( xPos ) ~= "number" then error( "bad argument #1 (expected number, got " .. type( xPos ) .. ")", 2 ) end
if type( yPos ) ~= "number" then error( "bad argument #2 (expected number, got " .. type( yPos ) .. ")", 2 ) end
if nColour ~= nil and type( nColour ) ~= "number" then error( "bad argument #3 (expected number, got " .. type( nColour ) .. ")", 2 ) end
expect(1, xPos, "number")
expect(2, yPos, "number")
expect(3, nColour, "number", "nil")
if nColour then
term.setBackgroundColor( nColour )
end
drawPixelInternal( xPos, yPos )
return drawPixelInternal( xPos, yPos )
end
function drawLine( startX, startY, endX, endY, nColour )
if type( startX ) ~= "number" then error( "bad argument #1 (expected number, got " .. type( startX ) .. ")", 2 ) end
if type( startY ) ~= "number" then error( "bad argument #2 (expected number, got " .. type( startY ) .. ")", 2 ) end
if type( endX ) ~= "number" then error( "bad argument #3 (expected number, got " .. type( endX ) .. ")", 2 ) end
if type( endY ) ~= "number" then error( "bad argument #4 (expected number, got " .. type( endY ) .. ")", 2 ) end
if nColour ~= nil and type( nColour ) ~= "number" then error( "bad argument #5 (expected number, got " .. type( nColour ) .. ")", 2 ) end
expect(1, startX, "number")
expect(2, startY, "number")
expect(3, endX, "number")
expect(4, endY, "number")
expect(5, nColour, "number", "nil")
startX = math.floor(startX)
startY = math.floor(startY)
@ -114,11 +111,11 @@ function drawLine( startX, startY, endX, endY, nColour )
end
function drawBox( startX, startY, endX, endY, nColour )
if type( startX ) ~= "number" then error( "bad argument #1 (expected number, got " .. type( startX ) .. ")", 2 ) end
if type( startY ) ~= "number" then error( "bad argument #2 (expected number, got " .. type( startY ) .. ")", 2 ) end
if type( endX ) ~= "number" then error( "bad argument #3 (expected number, got " .. type( endX ) .. ")", 2 ) end
if type( endY ) ~= "number" then error( "bad argument #4 (expected number, got " .. type( endY ) .. ")", 2 ) end
if nColour ~= nil and type( nColour ) ~= "number" then error( "bad argument #5 (expected number, got " .. type( nColour ) .. ")", 2 ) end
expect(1, startX, "number")
expect(2, startY, "number")
expect(3, endX, "number")
expect(4, endY, "number")
expect(5, nColour, "number", "nil")
startX = math.floor(startX)
startY = math.floor(startY)
@ -159,11 +156,11 @@ function drawBox( startX, startY, endX, endY, nColour )
end
function drawFilledBox( startX, startY, endX, endY, nColour )
if type( startX ) ~= "number" then error( "bad argument #1 (expected number, got " .. type( startX ) .. ")", 2 ) end
if type( startY ) ~= "number" then error( "bad argument #2 (expected number, got " .. type( startY ) .. ")", 2 ) end
if type( endX ) ~= "number" then error( "bad argument #3 (expected number, got " .. type( endX ) .. ")", 2 ) end
if type( endY ) ~= "number" then error( "bad argument #4 (expected number, got " .. type( endY ) .. ")", 2 ) end
if nColour ~= nil and type( nColour ) ~= "number" then error( "bad argument #5 (expected number, got " .. type( nColour ) .. ")", 2 ) end
expect(1, startX, "number")
expect(2, startY, "number")
expect(3, endX, "number")
expect(4, endY, "number")
expect(5, nColour, "number", "nil")
startX = math.floor(startX)
startY = math.floor(startY)
@ -198,9 +195,9 @@ function drawFilledBox( startX, startY, endX, endY, nColour )
end
function drawImage( tImage, xPos, yPos )
if type( tImage ) ~= "table" then error( "bad argument #1 (expected table, got " .. type( tImage ) .. ")", 2 ) end
if type( xPos ) ~= "number" then error( "bad argument #2 (expected number, got " .. type( xPos ) .. ")", 2 ) end
if type( yPos ) ~= "number" then error( "bad argument #3 (expected number, got " .. type( yPos ) .. ")", 2 ) end
expect(1, tImage, "table")
expect(2, xPos, "number")
expect(3, yPos, "number")
for y=1,#tImage do
local tLine = tImage[y]
for x=1,#tLine do

View File

@ -1,3 +1,5 @@
local expect = _G["~expect"]
local native = peripheral
function getNames()
@ -17,9 +19,7 @@ function getNames()
end
function isPresent( _sSide )
if type( _sSide ) ~= "string" then
error( "bad argument #1 (expected string, got " .. type( _sSide ) .. ")", 2 )
end
expect(1, _sSide, "string")
if native.isPresent( _sSide ) then
return true
end
@ -34,9 +34,7 @@ function isPresent( _sSide )
end
function getType( _sSide )
if type( _sSide ) ~= "string" then
error( "bad argument #1 (expected string, got " .. type( _sSide ) .. ")", 2 )
end
expect(1, _sSide, "string")
if native.isPresent( _sSide ) then
return native.getType( _sSide )
end
@ -51,9 +49,7 @@ function getType( _sSide )
end
function getMethods( _sSide )
if type( _sSide ) ~= "string" then
error( "bad argument #1 (expected string, got " .. type( _sSide ) .. ")", 2 )
end
expect(1, _sSide, "string")
if native.isPresent( _sSide ) then
return native.getMethods( _sSide )
end
@ -68,12 +64,8 @@ function getMethods( _sSide )
end
function call( _sSide, _sMethod, ... )
if type( _sSide ) ~= "string" then
error( "bad argument #1 (expected string, got " .. type( _sSide ) .. ")", 2 )
end
if type( _sSide ) ~= "string" then
error( "bad argument #2 (expected string, got " .. type( _sMethod ) .. ")", 2 )
end
expect(1, _sSide, "string")
expect(2, _sMethod, "string")
if native.isPresent( _sSide ) then
return native.call( _sSide, _sMethod, ... )
end
@ -88,9 +80,7 @@ function call( _sSide, _sMethod, ... )
end
function wrap( _sSide )
if type( _sSide ) ~= "string" then
error( "bad argument #1 (expected string, got " .. type( _sSide ) .. ")", 2 )
end
expect(1, _sSide, "string")
if peripheral.isPresent( _sSide ) then
local tMethods = peripheral.getMethods( _sSide )
local tResult = {}
@ -105,12 +95,8 @@ function wrap( _sSide )
end
function find( sType, fnFilter )
if type( sType ) ~= "string" then
error( "bad argument #1 (expected string, got " .. type( sType ) .. ")", 2 )
end
if fnFilter ~= nil and type( fnFilter ) ~= "function" then
error( "bad argument #2 (expected function, got " .. type( fnFilter ) .. ")", 2 )
end
expect(1, sType, "string")
expect(2, fnFilter, "function", "nil")
local tResults = {}
for n,sName in ipairs( peripheral.getNames() ) do
if peripheral.getType( sName ) == sType then

View File

@ -1,3 +1,4 @@
local expect = _G["~expect"]
CHANNEL_BROADCAST = 65535
CHANNEL_REPEAT = 65533
@ -7,9 +8,7 @@ local tReceivedMessageTimeouts = {}
local tHostnames = {}
function open( sModem )
if type( sModem ) ~= "string" then
error( "bad argument #1 (expected string, got " .. type( sModem ) .. ")", 2 )
end
expect(1, sModem, "string")
if peripheral.getType( sModem ) ~= "modem" then
error( "No such modem: "..sModem, 2 )
end
@ -18,11 +17,9 @@ function open( sModem )
end
function close( sModem )
expect(1, sModem, "string", "nil")
if sModem then
-- Close a specific modem
if type( sModem ) ~= "string" then
error( "bad argument #1 (expected string, got " .. type( sModem ) .. ")", 2 )
end
if peripheral.getType( sModem ) ~= "modem" then
error( "No such modem: "..sModem, 2 )
end
@ -39,11 +36,9 @@ function close( sModem )
end
function isOpen( sModem )
expect(1, sModem, "string", "nil")
if sModem then
-- Check if a specific modem is open
if type( sModem ) ~= "string" then
error( "bad argument #1 (expected string, got " .. type( sModem ) .. ")", 2 )
end
if peripheral.getType( sModem ) == "modem" then
return peripheral.call( sModem, "isOpen", os.getComputerID() ) and peripheral.call( sModem, "isOpen", CHANNEL_BROADCAST )
end
@ -59,12 +54,8 @@ function isOpen( sModem )
end
function send( nRecipient, message, sProtocol )
if type( nRecipient ) ~= "number" then
error( "bad argument #1 (expected number, got " .. type( nRecipient ) .. ")", 2 )
end
if sProtocol ~= nil and type( sProtocol ) ~= "string" then
error( "bad argument #3 (expected string, got " .. type( sProtocol ) .. ")", 2 )
end
expect(1, nRecipient, "number")
expect(3, sProtocol, "string", "nil")
-- Generate a (probably) unique message ID
-- We could do other things to guarantee uniqueness, but we really don't need to
-- Store it to ensure we don't get our own messages back
@ -96,14 +87,12 @@ function send( nRecipient, message, sProtocol )
end
end
end
return sent
end
function broadcast( message, sProtocol )
if sProtocol ~= nil and type( sProtocol ) ~= "string" then
error( "bad argument #2 (expected string, got " .. type( sProtocol ) .. ")", 2 )
end
expect(2, sProtocol, "string", "nil")
send( CHANNEL_BROADCAST, message, sProtocol )
end
@ -112,12 +101,8 @@ function receive( sProtocolFilter, nTimeout )
if type(sProtocolFilter) == "number" and nTimeout == nil then
sProtocolFilter, nTimeout = nil, sProtocolFilter
end
if sProtocolFilter ~= nil and type( sProtocolFilter ) ~= "string" then
error( "bad argument #1 (expected string, got " .. type( sProtocolFilter ) .. ")", 2 )
end
if nTimeout ~= nil and type( nTimeout ) ~= "number" then
error( "bad argument #2 (expected number, got " .. type( nTimeout ) .. ")", 2 )
end
expect(1, sProtocolFilter, "string", "nil")
expect(2, nTimeout, "number", "nil")
-- Start the timer
local timer = nil
@ -148,12 +133,8 @@ function receive( sProtocolFilter, nTimeout )
end
function host( sProtocol, sHostname )
if type( sProtocol ) ~= "string" then
error( "bad argument #1 (expected string, got " .. type( sProtocol ) .. ")", 2 )
end
if type( sHostname ) ~= "string" then
error( "bad argument #2 (expected string, got " .. type( sHostname ) .. ")", 2 )
end
expect(1, sProtocol, "string")
expect(2, sHostname, "string")
if sHostname == "localhost" then
error( "Reserved hostname", 2 )
end
@ -166,19 +147,13 @@ function host( sProtocol, sHostname )
end
function unhost( sProtocol )
if type( sProtocol ) ~= "string" then
error( "bad argument #1 (expected string, got " .. type( sProtocol ) .. ")", 2 )
end
expect(1, sProtocol, "string")
tHostnames[ sProtocol ] = nil
end
function lookup( sProtocol, sHostname )
if type( sProtocol ) ~= "string" then
error( "bad argument #1 (expected string, got " .. type( sProtocol ) .. ")", 2 )
end
if sHostname ~= nil and type( sHostname ) ~= "string" then
error( "bad argument #2 (expected string, got " .. type( sHostname ) .. ")", 2 )
end
expect(1, sProtocol, "string")
expect(2, sHostname, "string")
-- Build list of host IDs
local tResults = nil

View File

@ -1,14 +1,12 @@
local expect = _G["~expect"]
local tSettings = {}
function set( sName, value )
if type( sName ) ~= "string" then error( "bad argument #1 (expected string, got " .. type( sName ) .. ")", 2 ) end
expect(1, sName, "string")
expect(2, value, "number", "string", "boolean", "table")
local sValueTy = type(value)
if sValueTy ~= "number" and sValueTy ~= "string" and sValueTy ~= "boolean" and sValueTy ~= "table" then
error( "bad argument #2 (expected value, got " .. sValueTy .. ")", 2 )
end
if sValueTy == "table" then
if type(value) == "table" then
-- Ensure value is serializeable
value = textutils.unserialize( textutils.serialize(value) )
end
@ -29,9 +27,7 @@ function copy( value )
end
function get( sName, default )
if type(sName) ~= "string" then
error( "bad argument #1 (expected string, got " .. type( sName ) .. ")", 2 )
end
expect(1, sName, "string")
local result = tSettings[ sName ]
if result ~= nil then
return copy(result)
@ -41,9 +37,7 @@ function get( sName, default )
end
function unset( sName )
if type(sName) ~= "string" then
error( "bad argument #1 (expected string, got " .. type( sName ) .. ")", 2 )
end
expect(1, sName, "string")
tSettings[ sName ] = nil
end
@ -61,9 +55,7 @@ function getNames()
end
function load( sPath )
if type(sPath) ~= "string" then
error( "bad argument #1 (expected string, got " .. type( sPath ) .. ")", 2 )
end
expect(1, sPath, "string")
local file = fs.open( sPath, "r" )
if not file then
return false
@ -88,9 +80,7 @@ function load( sPath )
end
function save( sPath )
if type(sPath) ~= "string" then
error( "bad argument #1 (expected string, got " .. type( sPath ) .. ")", 2 )
end
expect(1, sPath, "string")
local file = fs.open( sPath, "w" )
if not file then
return false

View File

@ -1,3 +1,4 @@
local expect = _G["~expect"]
local native = (term.native and term.native()) or term
local redirectTarget = native
@ -11,10 +12,8 @@ end
local term = {}
term.redirect = function( target )
if type( target ) ~= "table" then
error( "bad argument #1 (expected table, got " .. type( target ) .. ")", 2 )
end
if target == term then
expect(1, target, "table")
if target == term or target == _G.term then
error( "term is not a recommended redirect target, try term.current() instead", 2 )
end
for k,v in pairs( native ) do

View File

@ -1,8 +1,7 @@
local expect = _G["~expect"]
function slowWrite( sText, nRate )
if nRate ~= nil and type( nRate ) ~= "number" then
error( "bad argument #2 (expected number, got " .. type( nRate ) .. ")", 2 )
end
expect(2, nRate, "number", "nil")
nRate = nRate or 20
if nRate < 0 then
error( "Rate must be positive", 2 )
@ -28,12 +27,8 @@ function slowPrint( sText, nRate )
end
function formatTime( nTime, bTwentyFourHour )
if type( nTime ) ~= "number" then
error( "bad argument #1 (expected number, got " .. type( nTime ) .. ")", 2 )
end
if bTwentyFourHour ~= nil and type( bTwentyFourHour ) ~= "boolean" then
error( "bad argument #2 (expected boolean, got " .. type( bTwentyFourHour ) .. ")", 2 )
end
expect(1, nTime, "number")
expect(2, bTwentyFourHour, "boolean", "nil")
local sTOD = nil
if not bTwentyFourHour then
if nTime >= 12 then
@ -77,9 +72,7 @@ local function makePagedScroll( _term, _nFreeLines )
end
function pagedPrint( _sText, _nFreeLines )
if _nFreeLines ~= nil and type( _nFreeLines ) ~= "number" then
error( "bad argument #2 (expected number, got " .. type( _nFreeLines ) .. ")", 2 )
end
expect(2, _nFreeLines, "number", "nil")
-- Setup a redirector
local oldTerm = term.current()
local newTerm = {}
@ -321,9 +314,7 @@ function serialize( t )
end
function unserialize( s )
if type( s ) ~= "string" then
error( "bad argument #1 (expected string, got " .. type( s ) .. ")", 2 )
end
expect(1, s, "string")
local func = load( "return "..s, "unserialize", "t", {} )
if func then
local ok, result = pcall( func )
@ -335,20 +326,14 @@ function unserialize( s )
end
function serializeJSON( t, bNBTStyle )
if type( t ) ~= "table" and type( t ) ~= "string" and type( t ) ~= "number" and type( t ) ~= "boolean" then
error( "bad argument #1 (expected table/string/number/boolean, got " .. type( t ) .. ")", 2 )
end
if bNBTStyle ~= nil and type( bNBTStyle ) ~= "boolean" then
error( "bad argument #2 (expected boolean, got " .. type( bNBTStyle ) .. ")", 2 )
end
expect(1, t, "table", "string", "number", "boolean")
expect(2, bNBTStyle, "boolean", "nil")
local tTracking = {}
return serializeJSONImpl( t, tTracking, bNBTStyle or false )
end
function urlEncode( str )
if type( str ) ~= "string" then
error( "bad argument #1 (expected string, got " .. type( str ) .. ")", 2 )
end
expect(1, str, "string")
if str then
str = string.gsub(str, "\n", "\r\n")
str = string.gsub(str, "([^A-Za-z0-9 %-%_%.])", function(c)
@ -370,12 +355,8 @@ end
local tEmpty = {}
function complete( sSearchText, tSearchTable )
if type( sSearchText ) ~= "string" then
error( "bad argument #1 (expected string, got " .. type( sSearchText ) .. ")", 2 )
end
if tSearchTable ~= nil and type( tSearchTable ) ~= "table" then
error( "bad argument #2 (expected table, got " .. type( tSearchTable ) .. ")", 2 )
end
expect(1, sSearchText, "string")
expect(2, tSearchTable, "table", "nil")
if g_tLuaKeywords[sSearchText] then return tEmpty end
local nStart = 1

View File

@ -1,3 +1,4 @@
local expect = _G["~expect"]
local tHex = {
[ colors.white ] = "0",
@ -21,15 +22,14 @@ local tHex = {
local type = type
local string_rep = string.rep
local string_sub = string.sub
local table_unpack = table.unpack
function create( parent, nX, nY, nWidth, nHeight, bStartVisible )
if type( parent ) ~= "table" then error( "bad argument #1 (expected table, got " .. type( parent ) .. ")", 2 ) end
if type( nX ) ~= "number" then error( "bad argument #2 (expected number, got " .. type( nX ) .. ")", 2 ) end
if type( nY ) ~= "number" then error( "bad argument #3 (expected number, got " .. type( nY ) .. ")", 2 ) end
if type( nWidth ) ~= "number" then error( "bad argument #4 (expected number, got " .. type( nWidth ) .. ")", 2 ) end
if type( nHeight ) ~= "number" then error( "bad argument #5 (expected number, got " .. type( nHeight ) .. ")", 2 ) end
if bStartVisible ~= nil and type( bStartVisible ) ~= "boolean" then error( "bad argument #6 (expected boolean, got " .. type( bStartVisible ) .. ")", 2 ) end
expect(1, parent, "table")
expect(2, nX, "number")
expect(3, nY, "number")
expect(4, nWidth, "number")
expect(5, nHeight, "number")
expect(6, bStartVisible, "boolean", "nil")
if parent == term then
error( "term is not a recommended window parent, try term.current() instead", 2 )
@ -191,9 +191,9 @@ function create( parent, nX, nY, nWidth, nHeight, bStartVisible )
end
function window.blit( sText, sTextColor, sBackgroundColor )
if type( sText ) ~= "string" then error( "bad argument #1 (expected string, got " .. type( sText ) .. ")", 2 ) end
if type( sTextColor ) ~= "string" then error( "bad argument #2 (expected string, got " .. type( sTextColor ) .. ")", 2 ) end
if type( sBackgroundColor ) ~= "string" then error( "bad argument #3 (expected string, got " .. type( sBackgroundColor ) .. ")", 2 ) end
if type(sText) ~= "string" then expect(1, sText, "string") end
if type(sTextColor) ~= "string" then expect(2, sTextColor, "string") end
if type(sBackgroundColor) ~= "string" then expect(3, sBackgroundColor, "string") end
if #sTextColor ~= #sText or #sBackgroundColor ~= #sText then
error( "Arguments must be the same length", 2 )
end
@ -241,8 +241,8 @@ function create( parent, nX, nY, nWidth, nHeight, bStartVisible )
end
function window.setCursorPos( x, y )
if type( x ) ~= "number" then error( "bad argument #1 (expected number, got " .. type( x ) .. ")", 2 ) end
if type( y ) ~= "number" then error( "bad argument #2 (expected number, got " .. type( y ) .. ")", 2 ) end
if type(x) ~= "number" then expect(1, x, "number") end
if type(y) ~= "number" then expect(2, y, "number") end
nCursorX = math.floor( x )
nCursorY = math.floor( y )
if bVisible then
@ -251,7 +251,7 @@ function create( parent, nX, nY, nWidth, nHeight, bStartVisible )
end
function window.setCursorBlink( blink )
if type( blink ) ~= "boolean" then error( "bad argument #1 (expected boolean, got " .. type( blink ) .. ")", 2 ) end
if type(blink) ~= "boolean" then expect(1, blink, "boolean") end
bCursorBlink = blink
if bVisible then
updateCursorBlink()
@ -275,11 +275,11 @@ function create( parent, nX, nY, nWidth, nHeight, bStartVisible )
end
local function setTextColor( color )
if type( color ) ~= "number" then
error( "bad argument #1 (expected number, got " .. type( color ) .. ")", 2 )
elseif tHex[color] == nil then
if type(color) ~= "number" then expect(1, color, "number") end
if tHex[color] == nil then
error( "Invalid color (got " .. color .. ")" , 2 )
end
nTextColor = color
if bVisible then
updateCursorColor()
@ -290,7 +290,7 @@ function create( parent, nX, nY, nWidth, nHeight, bStartVisible )
window.setTextColour = setTextColor
function window.setPaletteColour( colour, r, g, b )
if type( colour ) ~= "number" then error( "bad argument #1 (expected number, got " .. type( colour ) .. ")", 2 ) end
if type(colour) ~= "number" then expect(1, colour, "number") end
if tHex[colour] == nil then
error( "Invalid color (got " .. colour .. ")" , 2 )
@ -301,9 +301,9 @@ function create( parent, nX, nY, nWidth, nHeight, bStartVisible )
tCol = { colours.unpackRGB( r ) }
tPalette[ colour ] = tCol
else
if type( r ) ~= "number" then error( "bad argument #2 (expected number, got " .. type( r ) .. ")", 2 ) end
if type( g ) ~= "number" then error( "bad argument #3 (expected number, got " .. type( g ) .. ")", 2 ) end
if type( b ) ~= "number" then error( "bad argument #4 (expected number, got " .. type( b ) .. ")", 2 ) end
if type(r) ~= "number" then expect(2, r, "number") end
if type(g) ~= "number" then expect(3, g, "number") end
if type(b) ~= "number" then expect(4, b, "number") end
tCol = tPalette[ colour ]
tCol[1] = r
@ -319,7 +319,7 @@ function create( parent, nX, nY, nWidth, nHeight, bStartVisible )
window.setPaletteColor = window.setPaletteColour
function window.getPaletteColour( colour )
if type( colour ) ~= "number" then error( "bad argument #1 (expected number, got " .. type( colour ) .. ")", 2 ) end
if type(colour) ~= "number" then expect(1, colour, "number") end
if tHex[colour] == nil then
error( "Invalid color (got " .. colour .. ")" , 2 )
end
@ -330,9 +330,8 @@ function create( parent, nX, nY, nWidth, nHeight, bStartVisible )
window.getPaletteColor = window.getPaletteColour
local function setBackgroundColor( color )
if type( color ) ~= "number" then
error( "bad argument #1 (expected number, got " .. type( color ) .. ")", 2 )
elseif tHex[color] == nil then
if type(color) ~= "number" then expect(1, color, "number") end
if tHex[color] == nil then
error( "Invalid color (got " .. color .. ")", 2 )
end
nBackgroundColor = color
@ -346,7 +345,7 @@ function create( parent, nX, nY, nWidth, nHeight, bStartVisible )
end
function window.scroll( n )
if type( n ) ~= "number" then error( "bad argument #1 (expected number, got " .. type( n ) .. ")", 2 ) end
if type(n) ~= "number" then expect(1, n, "number") end
if n ~= 0 then
local tNewLines = {}
local sEmptyText = sEmptySpaceLine
@ -391,7 +390,7 @@ function create( parent, nX, nY, nWidth, nHeight, bStartVisible )
-- Other functions
function window.setVisible( bVis )
if type( bVis ) ~= "boolean" then error( "bad argument #1 (expected boolean, got " .. type( bVis ) .. ")", 2 ) end
if type(bVis) ~= "boolean" then expect(1, bVis, "boolean") end
if bVisible ~= bVis then
bVisible = bVis
if bVisible then
@ -423,11 +422,11 @@ function create( parent, nX, nY, nWidth, nHeight, bStartVisible )
end
function window.reposition( nNewX, nNewY, nNewWidth, nNewHeight )
if type( nNewX ) ~= "number" then error( "bad argument #1 (expected number, got " .. type( nNewX ) .. ")", 2 ) end
if type( nNewY ) ~= "number" then error( "bad argument #2 (expected number, got " .. type( nNewY ) .. ")", 2 ) end
if nNewWidth ~= nil or nNewHeight ~= nil then
if type( nNewWidth ) ~= "number" then error( "bad argument #3 (expected number, got " .. type( nNewWidth ) .. ")", 2 ) end
if type( nNewHeight ) ~= "number" then error( "bad argument #4 (expected number, got " .. type( nNewHeight ) .. ")", 2 ) end
if type(nNewX) ~= "number" then expect(1, nNewX, "number") end
if type(nNewY) ~= "number" then expect(2, nNewY, "number") end
if nNewWidth ~= nil or nNewHeight ~= nil then
expect(3, nNewWidth, "number")
expect(4, nNewHeight, "number")
end
nX = nNewX

View File

@ -1,3 +1,4 @@
local expect = _G["~expect"]
-- Setup process switching
local parentTerm = term.current()
@ -197,9 +198,7 @@ function multishell.getFocus()
end
function multishell.setFocus( n )
if type( n ) ~= "number" then
error( "bad argument #1 (expected number, got " .. type( n ) .. ")", 2 )
end
expect(1, n, "number")
if n >= 1 and n <= #tProcesses then
selectProcess( n )
redrawMenu()
@ -209,9 +208,7 @@ function multishell.setFocus( n )
end
function multishell.getTitle( n )
if type( n ) ~= "number" then
error( "bad argument #1 (expected number, got " .. type( n ) .. ")", 2 )
end
expect(1, n, "number")
if n >= 1 and n <= #tProcesses then
return tProcesses[n].sTitle
end
@ -219,12 +216,8 @@ function multishell.getTitle( n )
end
function multishell.setTitle( n, sTitle )
if type( n ) ~= "number" then
error( "bad argument #1 (expected number, got " .. type( n ) .. ")", 2 )
end
if type( sTitle ) ~= "string" then
error( "bad argument #2 (expected string, got " .. type( sTitle ) .. ")", 2 )
end
expect(1, n, "number")
expect(2, sTitle, "string")
if n >= 1 and n <= #tProcesses then
setProcessTitle( n, sTitle )
redrawMenu()
@ -236,12 +229,8 @@ function multishell.getCurrent()
end
function multishell.launch( tProgramEnv, sProgramPath, ... )
if type( tProgramEnv ) ~= "table" then
error( "bad argument #1 (expected table, got " .. type( tProgramEnv ) .. ")", 2 )
end
if type( sProgramPath ) ~= "string" then
error( "bad argument #2 (expected string, got " .. type( sProgramPath ) .. ")", 2 )
end
expect(1, tProgramEnv, "table")
expect(2, sProgramPath, "string")
local previousTerm = term.current()
setMenuVisible( (#tProcesses + 1) >= 2 )
local nResult = launchProcess( false, tProgramEnv, sProgramPath, ... )

View File

@ -1,3 +1,4 @@
local expect = _G["~expect"]
local multishell = multishell
local parentShell = shell
@ -74,9 +75,7 @@ local function createShellEnv( sDir )
local sentinel = {}
local function require( name )
if type( name ) ~= "string" then
error( "bad argument #1 (expected string, got " .. type( name ) .. ")", 2 )
end
expect(1, name, "string")
if package.loaded[name] == sentinel then
error("loop or previous error loading module '" .. name .. "'", 0)
end
@ -191,9 +190,7 @@ function shell.dir()
end
function shell.setDir( _sDir )
if type( _sDir ) ~= "string" then
error( "bad argument #1 (expected string, got " .. type( _sDir ) .. ")", 2 )
end
expect(1, _sDir, "string")
if not fs.isDir( _sDir ) then
error( "Not a directory", 2 )
end
@ -205,16 +202,12 @@ function shell.path()
end
function shell.setPath( _sPath )
if type( _sPath ) ~= "string" then
error( "bad argument #1 (expected string, got " .. type( _sPath ) .. ")", 2 )
end
expect(1, _sPath, "string")
sPath = _sPath
end
function shell.resolve( _sPath )
if type( _sPath ) ~= "string" then
error( "bad argument #1 (expected string, got " .. type( _sPath ) .. ")", 2 )
end
expect(1, _sPath, "string")
local sStartChar = string.sub( _sPath, 1, 1 )
if sStartChar == "/" or sStartChar == "\\" then
return fs.combine( "", _sPath )
@ -234,9 +227,7 @@ local function pathWithExtension( _sPath, _sExt )
end
function shell.resolveProgram( _sCommand )
if type( _sCommand ) ~= "string" then
error( "bad argument #1 (expected string, got " .. type( _sCommand ) .. ")", 2 )
end
expect(1, _sCommand, "string")
-- Substitute aliases firsts
if tAliases[ _sCommand ] ~= nil then
_sCommand = tAliases[ _sCommand ]
@ -361,9 +352,7 @@ local function completeProgramArgument( sProgram, nArgument, sPart, tPreviousPar
end
function shell.complete( sLine )
if type( sLine ) ~= "string" then
error( "bad argument #1 (expected string, got " .. type( sLine ) .. ")", 2 )
end
expect(1, sLine, "string")
if #sLine > 0 then
local tWords = tokenise( sLine )
local nIndex = #tWords
@ -400,19 +389,13 @@ function shell.complete( sLine )
end
function shell.completeProgram( sProgram )
if type( sProgram ) ~= "string" then
error( "bad argument #1 (expected string, got " .. type( sProgram ) .. ")", 2 )
end
expect(1, sProgram, "string")
return completeProgram( sProgram )
end
function shell.setCompletionFunction( sProgram, fnComplete )
if type( sProgram ) ~= "string" then
error( "bad argument #1 (expected string, got " .. type( sProgram ) .. ")", 2 )
end
if type( fnComplete ) ~= "function" then
error( "bad argument #2 (expected function, got " .. type( fnComplete ) .. ")", 2 )
end
expect(1, sProgram, "string")
expect(2, fnComplete, "function")
tCompletionInfo[ sProgram ] = {
fnComplete = fnComplete
}
@ -430,19 +413,13 @@ function shell.getRunningProgram()
end
function shell.setAlias( _sCommand, _sProgram )
if type( _sCommand ) ~= "string" then
error( "bad argument #1 (expected string, got " .. type( _sCommand ) .. ")", 2 )
end
if type( _sProgram ) ~= "string" then
error( "bad argument #2 (expected string, got " .. type( _sProgram ) .. ")", 2 )
end
expect(1, _sCommand, "string")
expect(2, _sProgram, "string")
tAliases[ _sCommand ] = _sProgram
end
function shell.clearAlias( _sCommand )
if type( _sCommand ) ~= "string" then
error( "bad argument #1 (expected string, got " .. type( _sCommand ) .. ")", 2 )
end
expect(1, _sCommand, "string")
tAliases[ _sCommand ] = nil
end
@ -472,9 +449,7 @@ if multishell then
end
function shell.switchTab( nID )
if type( nID ) ~= "number" then
error( "bad argument #1 (expected number, got " .. type( nID ) .. ")", 2 )
end
expect(1, nID, "number")
multishell.setFocus( nID )
end
end

View File

@ -20,6 +20,7 @@
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.Arrays;
import java.util.function.Consumer;
/**
@ -122,7 +123,7 @@ public String[] getNames()
@Override
public String[] getMethodNames()
{
return new String[] { "assert" };
return new String[] { "assert", "log" };
}
@Nullable
@ -144,6 +145,9 @@ public Object[] callMethod( @Nonnull ILuaContext context, int method, @Nonnull O
return arguments;
}
case 1:
ComputerCraft.log.info( "[Computer] {}", Arrays.toString( arguments ) );
return null;
default:
return null;

View File

@ -27,6 +27,43 @@ local function check(func, arg, ty, val)
end
end
local active_stubs = {}
--- Stub a global variable with a specific value
--
-- @tparam string var The variable to stub
-- @param value The value to stub it with
local function stub(var, value)
if not active_stubs[var] then
active_stubs[var] = { value = _G[var] }
end
_G[var] = value
end
--- Capture the current global state of the computer
local function push_state()
local stubs = active_stubs
active_stubs = {}
return {
term = term.current(),
input = io.input(),
output = io.output(),
stubs = stubs,
}
end
--- Restore the global state of the computer to a previous version
local function pop_state(state)
for k, v in pairs(active_stubs) do _G[k] = v.value end
active_stubs = state.stubs
term.redirect(state.term)
io.input(state.input)
io.output(state.output)
end
local error_mt = { __tostring = function(self) return self.message end }
--- Attempt to execute the provided function, gathering a stack trace when it
@ -50,10 +87,6 @@ local function try(fn)
return { message = err, trace = debug.traceback(nil, 2) }
end)
-- Restore a whole bunch of state
io.input(io.stdin)
io.output(io.stdout)
-- If we succeeded, propagate it
if ok then return ok, err end
@ -196,13 +229,32 @@ function expect_mt:matches(value)
return self
end
--- Construct a new expectation from the provided value
--
-- @param value The value to apply assertions to
-- @return The new expectation
local function expect(value)
return setmetatable({ value = value}, expect_mt)
end
local expect = setmetatable( {
--- Construct an expectation on the error message calling this function
-- produces
--
-- @tparam fun The function to call
-- @param ... The function arguments
-- @return The new expectation
error = function(fun, ...)
local ok, res = pcall(fun, ...) local _, line = pcall(error, "", 2)
if ok then fail("expected function to error") end
if res:sub(1, #line) == line then
res = res:sub(#line + 1)
elseif res:sub(1, 7) == "pcall: " then
res = res:sub(8)
end
return setmetatable({ value = res }, expect_mt)
end,
}, {
--- Construct a new expectation from the provided value
--
-- @param value The value to apply assertions to
-- @return The new expectation
__call = function(_, value)
return setmetatable({ value = value }, expect_mt)
end
})
--- The stack of "describe"s.
local test_stack = { n = 0 }
@ -302,10 +354,15 @@ end
do
-- Load in the tests from all our files
local env = setmetatable({
expect = expect, fail = fail,
describe = describe, it = it, pending = pending
}, { __index = _ENV })
local env = setmetatable({}, { __index = _ENV })
local function set_env(tbl)
for k in pairs(env) do env[k] = nil end
for k, v in pairs(tbl) do env[k] = v end
end
-- When declaring tests, you shouldn't be able to use test methods
set_env { describe = describe, it = it, pending = pending }
local suffix = "_spec.lua"
local function run_in(sub_dir)
@ -326,6 +383,9 @@ do
end
run_in(root_dir)
-- When running tests, you shouldn't be able to declare new ones.
set_env { expect = expect, fail = fail, stub = stub }
end
-- Error if we've found no tests
@ -359,9 +419,13 @@ local function do_run(test)
err = test.error
status = "error"
elseif test.action then
local state = push_state()
local ok
ok, err = try(test.action)
status = ok and "pass" or (err.fail and "fail" or "error")
pop_state(state)
end
-- If we've a boolean status, then convert it into a string

View File

@ -1,9 +1,24 @@
describe("The colors library", function()
it("colors.combine", function()
expect(colors.combine(colors.red, colors.brown, colors.green)):equals(0x7000)
describe("colors.combine", function()
it("validates arguments", function()
-- FIXME: Error when last argument is nil - use table.pack instead.
expect.error(colors.combine, 1, false):eq("bad argument #2 (expected number, got boolean)")
expect.error(colors.combine, 1, 1, false):eq("bad argument #3 (expected number, got boolean)")
end)
it("combines colours", function()
expect(colors.combine()):eq(0)
expect(colors.combine(colors.red, colors.brown, colors.green)):eq(0x7000)
end)
end)
describe("colors.subtract", function()
it("validates arguments", function()
expect.error(colors.subtract, nil):eq("bad argument #1 (expected number, got nil)")
expect.error(colors.subtract, 1, false):eq("bad argument #2 (expected number, got boolean)")
expect.error(colors.subtract, 1, 1, false):eq("bad argument #3 (expected number, got boolean)")
end)
it("subtracts colours", function()
expect(colors.subtract(0x7000, colors.green)):equals(0x5000)
expect(colors.subtract(0x5000, colors.red)):equals(0x1000)
@ -17,6 +32,11 @@ describe("The colors library", function()
end)
describe("colors.test", function()
it("validates arguments", function()
expect.error(colors.test, nil):eq("bad argument #1 (expected number, got nil)")
expect.error(colors.test, 1, nil):eq("bad argument #2 (expected number, got nil)")
end)
it("returns true when present", function()
expect(colors.test(0x7000, colors.green)):equals(true)
end)
@ -28,16 +48,30 @@ describe("The colors library", function()
end)
end)
it("colors.packRGB", function()
expect(colors.packRGB(0.3, 0.5, 0.6)):equals(0x4c7f99)
describe("colors.packRGB", function()
it("validates arguments", function()
expect.error(colors.packRGB, nil):eq("bad argument #1 (expected number, got nil)")
expect.error(colors.packRGB, 1, nil):eq("bad argument #2 (expected number, got nil)")
expect.error(colors.packRGB, 1, 1, nil):eq("bad argument #3 (expected number, got nil)")
end)
it("packs colours", function()
expect(colors.packRGB(0.3, 0.5, 0.6)):equals(0x4c7f99)
end)
end)
it("colors.unpackRGB", function()
expect({ colors.unpackRGB(0x4c7f99) }):same { 0x4c / 0xFF, 0x7f / 0xFF, 0.6 }
describe("colors.unpackRGB", function()
it("validates arguments", function()
expect.error(colors.unpackRGB, nil):eq("bad argument #1 (expected number, got nil)")
end)
it("unpacks colours", function()
expect({ colors.unpackRGB(0x4c7f99) }):same { 0x4c / 0xFF, 0x7f / 0xFF, 0.6 }
end)
end)
it("colors.rgb8", function()
expect(colors.rgb8(0.3, 0.5, 0.6)):equals(0x4c7f99)
expect({ colors.rgb8(0x4c7f99) }):same { 0x4c / 0xFF, 0x7f / 0xFF, 0.6 }
end)
end )
end)

View File

@ -0,0 +1,14 @@
describe("The fs library", function()
describe("fs.complete", function()
it("validates arguments", function()
fs.complete("", "")
fs.complete("", "", true)
fs.complete("", "", nil, true)
expect.error(fs.complete, nil):eq("bad argument #1 (expected string, got nil)")
expect.error(fs.complete, "", nil):eq("bad argument #2 (expected string, got nil)")
expect.error(fs.complete, "", "", 1):eq("bad argument #3 (expected boolean, got number)")
expect.error(fs.complete, "", "", true, 1):eq("bad argument #4 (expected boolean, got number)")
end)
end)
end)

View File

@ -0,0 +1,15 @@
describe("The gps library", function()
describe("gps.locate", function()
it("validates arguments", function()
stub("commands", { getBlockPosition = function()
end })
gps.locate()
gps.locate(1)
gps.locate(1, true)
expect.error(gps.locate, ""):eq("bad argument #1 (expected number, got string)")
expect.error(gps.locate, 1, ""):eq("bad argument #2 (expected boolean, got string)")
end)
end)
end)

View File

@ -0,0 +1,22 @@
describe("The help library", function()
describe("help.setPath", function()
it("validates arguments", function()
help.setPath(help.path())
expect.error(help.setPath, nil):eq("bad argument #1 (expected string, got nil)")
end)
end)
describe("help.lookup", function()
it("validates arguments", function()
help.lookup("")
expect.error(help.lookup, nil):eq("bad argument #1 (expected string, got nil)")
end)
end)
describe("help.completeTopic", function()
it("validates arguments", function()
help.completeTopic("")
expect.error(help.completeTopic, nil):eq("bad argument #1 (expected string, got nil)")
end)
end)
end)

View File

@ -18,13 +18,32 @@ describe("The io library", function()
expect(io.type(handle)):equals("file")
end)
it("returns nil on values", function() expect(io.type(8)):equals(nil) end)
it("returns nil on values", function()
expect(io.type(8)):equals(nil)
end)
it("returns nil on tables", function()
expect(io.type(setmetatable({}, {}))):equals(nil)
end)
end)
describe("io.lines", function()
it("validates arguments", function()
io.lines(nil)
expect.error(io.lines, ""):eq("/: No such file")
expect.error(io.lines, false):eq("bad argument #1 (expected string, got boolean)")
end)
end)
describe("io.open", function()
it("validates arguments", function()
io.open("")
io.open("", "r")
expect.error(io.open, nil):eq("bad argument #1 (expected string, got nil)")
expect.error(io.open, "", false):eq("bad argument #2 (expected string, got boolean)")
end)
it("returns an error message on non-existent files", function()
local a, b = io.open('xuxu_nao_existe')
expect(a):equals(nil)
@ -42,7 +61,7 @@ describe("The io library", function()
expect(io.output():seek()):equal(0)
assert(io.write("alo alo"))
expect(io.output():seek()):equal(#("alo alo"))
expect(io.output():seek("cur", -3)):equal(#("alo alo")-3)
expect(io.output():seek("cur", -3)):equal(#("alo alo") - 3)
assert(io.write("joao"))
expect(io.output():seek("end"):equal(#("alo joao")))

View File

@ -0,0 +1,8 @@
describe("The keys library", function()
describe("keys.getName", function()
it("validates arguments", function()
keys.getName(1)
expect.error(keys.getName, nil):eq("bad argument #1 (expected number, got nil)")
end)
end)
end)

View File

@ -1,4 +1,4 @@
describe("The os api", function()
describe("The os library", function()
describe("os.date and os.time", function()
it("round trips correctly", function()
local t = math.floor(os.epoch("local") / 1000)
@ -118,4 +118,16 @@ describe("The os api", function()
expect(t1 - t2):eq(60 * 2 - 2)
end)
end)
describe("os.loadAPI", function()
it("validates arguments", function()
expect.error(os.loadAPI, nil):eq("bad argument #1 (expected string, got nil)")
end)
end)
describe("os.unloadAPI", function()
it("validates arguments", function()
expect.error(os.loadAPI, nil):eq("bad argument #1 (expected string, got nil)")
end)
end)
end)

View File

@ -0,0 +1,60 @@
describe("The paintutils library", function()
describe("paintutils.parseImage", function()
it("validates arguments", function()
paintutils.parseImage("")
expect.error(paintutils.parseImage, nil):eq("bad argument #1 (expected string, got nil)")
end)
end)
describe("paintutils.loadImage", function()
it("validates arguments", function()
expect.error(paintutils.loadImage, nil):eq("bad argument #1 (expected string, got nil)")
end)
end)
describe("paintutils.drawPixel", function()
it("validates arguments", function()
expect.error(paintutils.drawPixel, nil):eq("bad argument #1 (expected number, got nil)")
expect.error(paintutils.drawPixel, 1, nil):eq("bad argument #2 (expected number, got nil)")
expect.error(paintutils.drawPixel, 1, 1, false):eq("bad argument #3 (expected number, got boolean)")
end)
end)
describe("paintutils.drawLine", function()
it("validates arguments", function()
expect.error(paintutils.drawLine, nil):eq("bad argument #1 (expected number, got nil)")
expect.error(paintutils.drawLine, 1, nil):eq("bad argument #2 (expected number, got nil)")
expect.error(paintutils.drawLine, 1, 1, nil):eq("bad argument #3 (expected number, got nil)")
expect.error(paintutils.drawLine, 1, 1, 1, nil):eq("bad argument #4 (expected number, got nil)")
expect.error(paintutils.drawLine, 1, 1, 1, 1, false):eq("bad argument #5 (expected number, got boolean)")
end)
end)
describe("paintutils.drawBox", function()
it("validates arguments", function()
expect.error(paintutils.drawBox, nil):eq("bad argument #1 (expected number, got nil)")
expect.error(paintutils.drawBox, 1, nil):eq("bad argument #2 (expected number, got nil)")
expect.error(paintutils.drawBox, 1, 1, nil):eq("bad argument #3 (expected number, got nil)")
expect.error(paintutils.drawBox, 1, 1, 1, nil):eq("bad argument #4 (expected number, got nil)")
expect.error(paintutils.drawBox, 1, 1, 1, 1, false):eq("bad argument #5 (expected number, got boolean)")
end)
end)
describe("paintutils.drawFilledBox", function()
it("validates arguments", function()
expect.error(paintutils.drawFilledBox, nil):eq("bad argument #1 (expected number, got nil)")
expect.error(paintutils.drawFilledBox, 1, nil):eq("bad argument #2 (expected number, got nil)")
expect.error(paintutils.drawFilledBox, 1, 1, nil):eq("bad argument #3 (expected number, got nil)")
expect.error(paintutils.drawFilledBox, 1, 1, 1, nil):eq("bad argument #4 (expected number, got nil)")
expect.error(paintutils.drawFilledBox, 1, 1, 1, 1, false):eq("bad argument #5 (expected number, got boolean)")
end)
end)
describe("paintutils.drawImage", function()
it("validates arguments", function()
expect.error(paintutils.drawImage, nil):eq("bad argument #1 (expected table, got nil)")
expect.error(paintutils.drawImage, {}, nil):eq("bad argument #2 (expected number, got nil)")
expect.error(paintutils.drawImage, {}, 1, nil):eq("bad argument #3 (expected number, got nil)")
end)
end)
end)

View File

@ -0,0 +1,47 @@
describe("The peripheral library", function()
describe("peripheral.isPresent", function()
it("validates arguments", function()
peripheral.isPresent("")
expect.error(peripheral.isPresent, nil):eq("bad argument #1 (expected string, got nil)")
end)
end)
describe("peripheral.getType", function()
it("validates arguments", function()
peripheral.getType("")
expect.error(peripheral.getType, nil):eq("bad argument #1 (expected string, got nil)")
end)
end)
describe("peripheral.getMethods", function()
it("validates arguments", function()
peripheral.getMethods("")
expect.error(peripheral.getMethods, nil):eq("bad argument #1 (expected string, got nil)")
end)
end)
describe("peripheral.call", function()
it("validates arguments", function()
peripheral.call("", "")
expect.error(peripheral.call, nil):eq("bad argument #1 (expected string, got nil)")
expect.error(peripheral.call, "", nil):eq("bad argument #2 (expected string, got nil)")
end)
end)
describe("peripheral.wrap", function()
it("validates arguments", function()
peripheral.wrap("")
expect.error(peripheral.wrap, nil):eq("bad argument #1 (expected string, got nil)")
end)
end)
describe("peripheral.find", function()
it("validates arguments", function()
peripheral.find("")
peripheral.find("", function()
end)
expect.error(peripheral.find, nil):eq("bad argument #1 (expected string, got nil)")
expect.error(peripheral.find, "", false):eq("bad argument #2 (expected function, got boolean)")
end)
end)
end)

View File

@ -0,0 +1,78 @@
describe("The rednet library", function()
describe("rednet.open", function()
it("validates arguments", function()
expect.error(rednet.open, nil):eq("bad argument #1 (expected string, got nil)")
end)
it("requires a modem to be present", function()
expect.error(rednet.open, "not_there"):eq("No such modem: not_there")
end)
end)
describe("rednet.close", function()
it("validates arguments", function()
rednet.close()
expect.error(rednet.close, 1):eq("bad argument #1 (expected string, got number)")
expect.error(rednet.close, false):eq("bad argument #1 (expected string, got boolean)")
end)
it("requires a modem to be present", function()
expect.error(rednet.close, "not_there"):eq("No such modem: not_there")
end)
end)
describe("rednet.isOpen", function()
it("validates arguments", function()
rednet.isOpen()
rednet.isOpen("")
expect.error(rednet.isOpen, 1):eq("bad argument #1 (expected string, got number)")
expect.error(rednet.isOpen, false):eq("bad argument #1 (expected string, got boolean)")
end)
end)
describe("rednet.send", function()
it("validates arguments", function()
rednet.send(1)
rednet.send(1, nil, "")
expect.error(rednet.send, nil):eq("bad argument #1 (expected number, got nil)")
expect.error(rednet.send, 1, nil, false):eq("bad argument #3 (expected string, got boolean)")
end)
end)
describe("rednet.broadcast", function()
it("validates arguments", function()
rednet.broadcast(nil)
rednet.broadcast(nil, "")
expect.error(rednet.broadcast, nil, false):eq("bad argument #2 (expected string, got boolean)")
end)
end)
describe("rednet.receive", function()
it("validates arguments", function()
expect.error(rednet.receive, false):eq("bad argument #1 (expected string, got boolean)")
expect.error(rednet.receive, "", false):eq("bad argument #2 (expected number, got boolean)")
end)
end)
describe("rednet.host", function()
it("validates arguments", function()
expect.error(rednet.host, "", "localhost"):eq("Reserved hostname")
expect.error(rednet.host, nil):eq("bad argument #1 (expected string, got nil)")
expect.error(rednet.host, "", nil):eq("bad argument #2 (expected string, got nil)")
end)
end)
describe("rednet.unhost", function()
it("validates arguments", function()
rednet.unhost("")
expect.error(rednet.unhost, nil):eq("bad argument #1 (expected string, got nil)")
end)
end)
describe("rednet.lookup", function()
it("validates arguments", function()
expect.error(rednet.lookup, nil):eq("bad argument #1 (expected string, got nil)")
expect.error(rednet.lookup, "", false):eq("bad argument #2 (expected string, got boolean)")
end)
end)
end)

View File

@ -0,0 +1,43 @@
describe("The settings library", function()
describe("settings.set", function()
it("validates arguments", function()
settings.set("test", 1)
settings.set("test", "")
settings.set("test", {})
settings.set("test", false)
expect.error(settings.set, nil):eq("bad argument #1 (expected string, got nil)")
expect.error(settings.set, "", nil):eq("bad argument #2 (expected number, string, boolean or table, got nil)")
end)
it("prevents storing unserialisable types", function()
expect.error(settings.set, "", { print }):eq("Cannot serialize type function")
end)
end)
describe("settings.get", function()
it("validates arguments", function()
settings.get("test")
expect.error(settings.get, nil):eq("bad argument #1 (expected string, got nil)")
end)
end)
describe("settings.unset", function()
it("validates arguments", function()
settings.unset("test")
expect.error(settings.unset, nil):eq("bad argument #1 (expected string, got nil)")
end)
end)
describe("settings.load", function()
it("validates arguments", function()
expect.error(settings.load, nil):eq("bad argument #1 (expected string, got nil)")
end)
end)
describe("settings.save", function()
it("validates arguments", function()
expect.error(settings.save, nil):eq("bad argument #1 (expected string, got nil)")
end)
end)
end)

View File

@ -0,0 +1,12 @@
describe("The term library", function()
describe("term.redirect", function()
it("validates arguments", function()
expect.error(term.redirect, nil):eq("bad argument #1 (expected table, got nil)")
end)
it("prevents redirecting to term", function()
expect.error(term.redirect, term)
:eq("term is not a recommended redirect target, try term.current() instead")
end)
end)
end)

View File

@ -0,0 +1,57 @@
describe("The textutils library", function()
describe("textutils.slowWrite", function()
it("validates arguments", function()
expect.error(textutils.slowWrite, nil, false):eq("bad argument #2 (expected number, got boolean)")
end)
end)
describe("textutils.formatTime", function()
it("validates arguments", function()
textutils.formatTime(0)
textutils.formatTime(0, false)
expect.error(textutils.formatTime, nil):eq("bad argument #1 (expected number, got nil)")
expect.error(textutils.formatTime, 1, 1):eq("bad argument #2 (expected boolean, got number)")
end)
end)
describe("textutils.pagedPrint", function()
it("validates arguments", function()
expect.error(textutils.pagedPrint, nil, false):eq("bad argument #2 (expected number, got boolean)")
end)
end)
describe("textutils.unserialise", function()
it("validates arguments", function()
textutils.unserialise("")
expect.error(textutils.unserialise, nil):eq("bad argument #1 (expected string, got nil)")
end)
end)
describe("textutils.serialiseJSON", function()
it("validates arguments", function()
textutils.serialiseJSON("")
textutils.serialiseJSON(1)
textutils.serialiseJSON({})
textutils.serialiseJSON(false)
textutils.serialiseJSON("", true)
expect.error(textutils.serialiseJSON, nil):eq("bad argument #1 (expected table, string, number or boolean, got nil)")
expect.error(textutils.serialiseJSON, "", 1):eq("bad argument #2 (expected boolean, got number)")
end)
end)
describe("textutils.urlEncode", function()
it("validates arguments", function()
textutils.urlEncode("")
expect.error(textutils.urlEncode, nil):eq("bad argument #1 (expected string, got nil)")
end)
end)
describe("textutils.complete", function()
it("validates arguments", function()
textutils.complete("pri")
textutils.complete("pri", _G)
expect.error(textutils.complete, nil):eq("bad argument #1 (expected string, got nil)")
expect.error(textutils.complete, "", false):eq("bad argument #2 (expected table, got boolean)")
end)
end)
end)

View File

@ -0,0 +1,123 @@
describe("The window library", function()
local function mk()
return window.create(term.current(), 1, 1, 5, 5, false)
end
describe("window.create", function()
it("validates arguments", function()
local r = mk()
window.create(r, 1, 1, 5, 5)
window.create(r, 1, 1, 5, 5, false)
expect.error(window.create, nil):eq("bad argument #1 (expected table, got nil)")
expect.error(window.create, r, nil):eq("bad argument #2 (expected number, got nil)")
expect.error(window.create, r, 1, nil):eq("bad argument #3 (expected number, got nil)")
expect.error(window.create, r, 1, 1, nil):eq("bad argument #4 (expected number, got nil)")
expect.error(window.create, r, 1, 1, 1, nil):eq("bad argument #5 (expected number, got nil)")
expect.error(window.create, r, 1, 1, 1, 1, ""):eq("bad argument #6 (expected boolean, got string)")
end)
end)
describe("Window.blit", function()
it("validates arguments", function()
local w = mk()
w.blit("a", "a", "a")
expect.error(w.blit, nil):eq("bad argument #1 (expected string, got nil)")
expect.error(w.blit, "", nil):eq("bad argument #2 (expected string, got nil)")
expect.error(w.blit, "", "", nil):eq("bad argument #3 (expected string, got nil)")
expect.error(w.blit, "", "", "a"):eq("Arguments must be the same length")
end)
end)
describe("Window.setCursorPos", function()
it("validates arguments", function()
local w = mk()
w.setCursorPos(1, 1)
expect.error(w.setCursorPos, nil):eq("bad argument #1 (expected number, got nil)")
expect.error(w.setCursorPos, 1, nil):eq("bad argument #2 (expected number, got nil)")
end)
end)
describe("Window.setCursorBlink", function()
it("validates arguments", function()
local w = mk()
w.setCursorBlink(false)
expect.error(w.setCursorBlink, nil):eq("bad argument #1 (expected boolean, got nil)")
end)
end)
describe("Window.setTextColour", function()
it("validates arguments", function()
local w = mk()
w.setTextColour(colors.white)
expect.error(w.setTextColour, nil):eq("bad argument #1 (expected number, got nil)")
expect.error(w.setTextColour, -5):eq("Invalid color (got -5)")
end)
end)
describe("Window.setPaletteColour", function()
it("validates arguments", function()
local w = mk()
w.setPaletteColour(colors.white, 0, 0, 0)
w.setPaletteColour(colors.white, 0x000000)
expect.error(w.setPaletteColour, nil):eq("bad argument #1 (expected number, got nil)")
expect.error(w.setPaletteColour, -5):eq("Invalid color (got -5)")
expect.error(w.setPaletteColour, colors.white):eq("bad argument #2 (expected number, got nil)")
expect.error(w.setPaletteColour, colors.white, 1, false):eq("bad argument #3 (expected number, got boolean)")
expect.error(w.setPaletteColour, colors.white, 1, nil, 1):eq("bad argument #3 (expected number, got nil)")
expect.error(w.setPaletteColour, colors.white, 1, 1, nil):eq("bad argument #4 (expected number, got nil)")
end)
end)
describe("Window.getPaletteColour", function()
it("validates arguments", function()
local w = mk()
w.getPaletteColour(colors.white)
expect.error(w.getPaletteColour, nil):eq("bad argument #1 (expected number, got nil)")
expect.error(w.getPaletteColour, -5):eq("Invalid color (got -5)")
end)
end)
describe("Window.setBackgroundColour", function()
it("validates arguments", function()
local w = mk()
w.setBackgroundColour(colors.white)
expect.error(w.setBackgroundColour, nil):eq("bad argument #1 (expected number, got nil)")
expect.error(w.setBackgroundColour, -5):eq("Invalid color (got -5)")
end)
end)
describe("Window.scroll", function()
it("validates arguments", function()
local w = mk()
w.scroll(0)
expect.error(w.scroll, nil):eq("bad argument #1 (expected number, got nil)")
end)
end)
describe("Window.setVisible", function()
it("validates arguments", function()
local w = mk()
w.setVisible(false)
expect.error(w.setVisible, nil):eq("bad argument #1 (expected boolean, got nil)")
end)
end)
describe("Window.reposition", function()
it("validates arguments", function()
local w = mk()
w.reposition(1, 1)
w.reposition(1, 1, 5, 5)
expect.error(w.reposition, nil):eq("bad argument #1 (expected number, got nil)")
expect.error(w.reposition, 1, nil):eq("bad argument #2 (expected number, got nil)")
expect.error(w.reposition, 1, 1, false, 1):eq("bad argument #3 (expected number, got boolean)")
expect.error(w.reposition, 1, 1, nil, 1):eq("bad argument #3 (expected number, got nil)")
expect.error(w.reposition, 1, 1, 1, nil):eq("bad argument #4 (expected number, got nil)")
end)
end)
end)

View File

@ -1,11 +1,74 @@
describe("The Lua base library", function()
describe("expect", function()
local e = _G["~expect"]
it("checks a single type", function()
expect(e(1, "test", "string")):eq(true)
expect(e(1, 2, "number")):eq(true)
expect.error(e, 1, nil, "string"):eq("bad argument #1 (expected string, got nil)")
expect.error(e, 2, 1, "nil"):eq("bad argument #2 (expected nil, got number)")
end)
it("checks multiple types", function()
expect(e(1, "test", "string", "number")):eq(true)
expect(e(1, 2, "string", "number")):eq(true)
expect.error(e, 1, nil, "string", "number"):eq("bad argument #1 (expected string or number, got nil)")
expect.error(e, 2, false, "string", "table", "number", "nil")
:eq("bad argument #2 (expected string, table or number, got boolean)")
end)
it("includes the function name", function()
local function worker()
expect(e(1, nil, "string")):eq(true)
end
local function trampoline()
worker()
end
expect.error(trampoline):eq("base_spec.lua:27: bad argument #1 to 'worker' (expected string, got nil)")
end)
end)
describe("sleep", function()
it("validates arguments", function()
sleep(0)
sleep(nil)
expect.error(sleep, false):eq("bad argument #1 (expected number, got boolean)")
end)
end)
describe("write", function()
it("validates arguments", function()
write("")
expect.error(write, nil):eq("bad argument #1 (expected string or number, got nil)")
end)
end)
describe("loadfile", function()
it("validates arguments", function()
loadfile("")
loadfile("", {})
expect.error(loadfile, nil):eq("bad argument #1 (expected string, got nil)")
expect.error(loadfile, "", false):eq("bad argument #2 (expected table, got boolean)")
end)
it("prefixes the filename with @", function()
local info = debug.getinfo(loadfile("/rom/startup.lua"), "S")
expect(info):matches { short_src = "startup.lua", source = "@startup.lua" }
end)
end)
describe("dofile", function()
it("validates arguments", function()
expect.error(dofile, ""):eq("File not found")
expect.error(dofile, nil):eq("bad argument #1 (expected string, got nil)")
end)
end)
describe("loadstring", function()
it("prefixes the chunk name with '='", function()
local info = debug.getinfo(loadstring("return 1", "name"), "S")
@ -27,9 +90,25 @@ describe("The Lua base library", function()
end)
describe("load", function()
it("validates arguments", function()
load("")
load(function()
end)
load("", "")
load("", "", "")
load("", "", "", _ENV)
expect.error(load, nil):eq("bad argument #1 (expected function or string, got nil)")
expect.error(load, "", false):eq("bad argument #2 (expected string, got boolean)")
expect.error(load, "", "", false):eq("bad argument #3 (expected string, got boolean)")
expect.error(load, "", "", "", false):eq("bad argument #4 (expected table, got boolean)")
end)
local function generator(parts)
return coroutine.wrap(function()
for i = 1, #parts do coroutine.yield(parts[i]) end
for i = 1, #parts do
coroutine.yield(parts[i])
end
end)
end

View File

@ -0,0 +1,30 @@
describe("The multishell program", function()
describe("multishell.setFocus", function()
it("validates arguments", function()
multishell.setFocus(multishell.getFocus())
expect.error(multishell.setFocus, nil):eq("bad argument #1 (expected number, got nil)")
end)
end)
describe("multishell.getTitle", function()
it("validates arguments", function()
multishell.getTitle(1)
expect.error(multishell.getTitle, nil):eq("bad argument #1 (expected number, got nil)")
end)
end)
describe("multishell.setTitle", function()
it("validates arguments", function()
multishell.setTitle(1, multishell.getTitle(1))
expect.error(multishell.setTitle, nil):eq("bad argument #1 (expected number, got nil)")
expect.error(multishell.setTitle, 1, nil):eq("bad argument #2 (expected string, got nil)")
end)
end)
describe("multishell.launch", function()
it("validates arguments", function()
expect.error(multishell.launch, nil):eq("bad argument #1 (expected table, got nil)")
expect.error(multishell.launch, _ENV, nil):eq("bad argument #2 (expected string, got nil)")
end)
end)
end)

View File

@ -1,4 +1,11 @@
describe("The shell", function()
describe("require", function()
it("validates arguments", function()
require("math")
expect.error(require, nil):eq("bad argument #1 (expected string, got nil)")
end)
end)
describe("shell.run", function()
it("sets the arguments", function()
local handle = fs.open("test-files/out.txt", "w")
@ -14,4 +21,74 @@ describe("The shell", function()
expect(args):same { [0] = "/test-files/out.txt", "arg1", "arg2" }
end)
end)
describe("shell.setDir", function()
it("validates arguments", function()
shell.setDir(shell.dir())
expect.error(shell.setDir, nil):eq("bad argument #1 (expected string, got nil)")
end)
end)
describe("shell.setPath", function()
it("validates arguments", function()
shell.setPath(shell.path())
expect.error(shell.setPath, nil):eq("bad argument #1 (expected string, got nil)")
end)
end)
describe("shell.resolve", function()
it("validates arguments", function()
shell.resolve("")
expect.error(shell.resolve, nil):eq("bad argument #1 (expected string, got nil)")
end)
end)
describe("shell.resolveProgram", function()
it("validates arguments", function()
shell.resolveProgram("ls")
expect.error(shell.resolveProgram, nil):eq("bad argument #1 (expected string, got nil)")
end)
end)
describe("shell.complete", function()
it("validates arguments", function()
shell.complete("ls")
expect.error(shell.complete, nil):eq("bad argument #1 (expected string, got nil)")
end)
end)
describe("shell.setCompletionFunction", function()
it("validates arguments", function()
expect.error(shell.setCompletionFunction, nil):eq("bad argument #1 (expected string, got nil)")
expect.error(shell.setCompletionFunction, "", nil):eq("bad argument #2 (expected function, got nil)")
end)
end)
describe("shell.setCompletionFunction", function()
it("validates arguments", function()
expect.error(shell.setCompletionFunction, nil):eq("bad argument #1 (expected string, got nil)")
expect.error(shell.setCompletionFunction, "", nil):eq("bad argument #2 (expected function, got nil)")
end)
end)
describe("shell.setAlias", function()
it("validates arguments", function()
shell.setAlias("sl", "ls")
expect.error(shell.setAlias, nil):eq("bad argument #1 (expected string, got nil)")
expect.error(shell.setAlias, "", nil):eq("bad argument #2 (expected string, got nil)")
end)
end)
describe("shell.clearAlias", function()
it("validates arguments", function()
shell.clearAlias("sl")
expect.error(shell.clearAlias, nil):eq("bad argument #1 (expected string, got nil)")
end)
end)
describe("shell.switchTab", function()
it("validates arguments", function()
expect.error(shell.switchTab, nil):eq("bad argument #1 (expected number, got nil)")
end)
end)
end)