Skip to content

Commit

Permalink
Add lua exception handling test code
Browse files Browse the repository at this point in the history
Catch some error situations when mod used without thinking about it
  • Loading branch information
sapier authored and sapier committed Aug 23, 2014
1 parent 3e267a6 commit e09293b
Show file tree
Hide file tree
Showing 3 changed files with 146 additions and 0 deletions.
106 changes: 106 additions & 0 deletions games/minimal/mods/errorhandler_test/init.lua
@@ -0,0 +1,106 @@
--
-- exception handler test module
--
--
-- To avoid this from crashing the module will startup in inactive mode.
-- to make specific errors happen you need to cause them by following
-- chat command:
--
-- exceptiontest <location> <errortype>
--
-- location has to be one of:
-- * mapgen: cause in next on_generate call
-- * entity_step: spawn a entity and make it do error in on_step
-- * globalstep: do error in next globalstep
-- * immediate: cause right in chat handler
--
-- errortypes defined are:
-- * segv: make sigsegv happen
-- * zerodivision: cause a division by zero to happen
-- * exception: throw an exception

if core.cause_error == nil or
type(core.cause_error) ~= "function" then
return
end


core.log("action", "WARNING: loading exception handler test module!")

local exceptiondata = {
tocause = "none",
mapgen = false,
entity_step = false,
globalstep = false,
}

local exception_entity =
{
on_step = function(self, dtime)
if exceptiondata.entity_step then
core.cause_error(exceptiondata.tocause)
end
end,
}
local exception_entity_name = "errorhandler_test:error_entity"

local function exception_chat_handler(playername, param)
local parameters = param:split(" ")

if #parameters ~= 2 then
core.chat_send_player(playername, "Invalid argument count for exceptiontest")
end

core.log("error", "Causing error at:" .. parameters[1])

if parameters[1] == "mapgen" then
exceptiondata.tocause = parameters[2]
exceptiondata.mapgen = true
elseif parameters[1] == "entity_step" then
--spawn entity at player location
local player = core.get_player_by_name(playername)

if player:is_player() then
local pos = player:getpos()

core.add_entity(pos, exception_entity_name)
end

exceptiondata.tocause = parameters[2]
exceptiondata.entity_step = true

elseif parameters[1] == "globalstep" then
exceptiondata.tocause = parameters[2]
exceptiondata.globalstep = true

elseif parameters[1] == "immediate" then
core.cause_error(parameters[2])

else
core.chat_send_player(playername, "Invalid error location: " .. dump(parameters[1]))
end
end

core.register_chatcommand("exceptiontest",
{
params = "<location> <errortype>",
description = "cause a given error to happen.\n" ..
" location=(mapgen,entity_step,globalstep,immediate)\n" ..
" errortype=(segv,zerodivision,exception)",
func = exception_chat_handler,
privs = { server=true }
})

core.register_globalstep(function(dtime)
if exceptiondata.globalstep then
core.cause_error(exceptiondata.tocause)
end
end)

core.register_on_generated(function(minp, maxp, blockseed)
if exceptiondata.mapgen then
core.cause_error(exceptiondata.tocause)
end
end)

core.register_entity(exception_entity_name, exception_entity)
35 changes: 35 additions & 0 deletions src/script/lua_api/l_server.cpp
Expand Up @@ -24,6 +24,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "server.h"
#include "environment.h"
#include "player.h"
#include "log.h"

// request_shutdown()
int ModApiServer::l_request_shutdown(lua_State *L)
Expand Down Expand Up @@ -449,6 +450,36 @@ int ModApiServer::l_notify_authentication_modified(lua_State *L)
return 0;
}

#ifndef NDEBUG
// cause_error(type_of_error)
int ModApiServer::l_cause_error(lua_State *L)
{
NO_MAP_LOCK_REQUIRED;
std::string type_of_error = "none";
if(lua_isstring(L, 1))
type_of_error = lua_tostring(L, 1);

errorstream << "Error handler test called, errortype=" << type_of_error << std::endl;

if(type_of_error == "segv") {
volatile int* some_pointer = 0;
errorstream << "Cause a sigsegv now: " << (*some_pointer) << std::endl;

} else if (type_of_error == "zerodivision") {

unsigned int some_number = porting::getTimeS();
unsigned int zerovalue = 0;
unsigned int result = some_number / zerovalue;
errorstream << "Well this shouldn't ever be shown: " << result << std::endl;

} else if (type_of_error == "exception") {
throw BaseException("Errorhandler test fct called");
}

return 0;
}
#endif

void ModApiServer::Initialize(lua_State *L, int top)
{
API_FCT(request_shutdown);
Expand All @@ -475,4 +506,8 @@ void ModApiServer::Initialize(lua_State *L, int top)
API_FCT(kick_player);
API_FCT(unban_player_or_ip);
API_FCT(notify_authentication_modified);

#ifndef NDEBUG
API_FCT(cause_error);
#endif
}
5 changes: 5 additions & 0 deletions src/script/lua_api/l_server.h
Expand Up @@ -88,6 +88,11 @@ class ModApiServer : public ModApiBase {
// notify_authentication_modified(name)
static int l_notify_authentication_modified(lua_State *L);

#ifndef NDEBUG
// cause_error(type_of_error)
static int l_cause_error(lua_State *L);
#endif

public:
static void Initialize(lua_State *L, int top);

Expand Down

0 comments on commit e09293b

Please sign in to comment.