klajo / mockgyver

A mocking library for Erlang
BSD 3-Clause "New" or "Revised" License
38 stars 13 forks source link

Fix crash when mocking a dynamic module #15

Closed tomas-abrahamsson closed 5 years ago

tomas-abrahamsson commented 5 years ago

The mockgyver process would crash if a a module was loaded in the vm, but whose object code could not be loaded (did not exist on disk), for example dynamically generated and loaded modules.

This is where the crash happened:

    reload_mod_under_different_name(Mod) ->
       {module, Mod} = code:ensure_loaded(Mod),
       {Mod, OrigBin0, Filename} = code:get_object_code(Mod), % <-- here
       ...

This is what it looked like when code:get_object_code(Mod) returned error (abbreviated):

    ** State machine mockgyver terminating
    ** Last message in was {'$gen_sync_event',
                               {<0.1171.0>,#Ref<0....>},
                               {start_session,
                                   [...] | ...}}
    ** When State == no_session
    **      Data  == {state,[],undefined,undefined,{[],[]},[],[],[]}
    ** Reason for termination =
    ** {{badmatch,error},
        [{mockgyver,reload_mod_under_different_name,1,
                    [{file,"/.../mockgyver.erl"},{line,1155}]},
         {mockgyver,mk_or_retrieve_mocked_mod,1,
                    [{file,"/.../mockgyver.erl"},{line,1091}]}
         | ...]}

A typical use case can be when a module is dynamically generated in a test case for one module, and maybe later mocked in a test case for another module. In either case, the mockgyver process should not crash due to this setup.

Fix this by replacing the dynamically generated module entirely with the mocked one.

tomas-abrahamsson commented 5 years ago

Oops, ref_to_list (used in the test) did not exist in older Erlang versions. I will fix.

tomas-abrahamsson commented 5 years ago

Tests seem to pass now

klajo commented 5 years ago

Great, thanks a lot!