I want to mock functions using erts_debug and reloading a custom implementation of error_handler. It would look something like this:
-module(mock).
expect(Module, FunctionName, Arity, ExpectFun) ->
ets:insert(?MODULE, {{Module, FunctionName, Arity}, ExpectFun},
erts_debug:breakpoint({Module, FunctionName, Arity}, true).
-module(error_handler).
breakpoint(Module, FunctionName, Arity) ->
case ets:lookup(mock, {Module, FunctionName, Arity}) of
[{{Module, FunctionName, Arity}, ExpectFun}] -> ExpectFun();
_ -> (int()):eval(Module, Func, Args)
end.
Unfortunately, I cannot mock local function calls due to compiler optimizations that might assume a function returns a specific type/value. Is there a way I can tell if a function call is local or external? erlang:trace/3
is able to trace only global calls, or both local and global calls, so it seems that internally there is some way to differentiate the two.
By enabling tracing, I can tell if a call to error_handler:breakpoint/3
resulted from a local call or a global call, however this method is very inefficient.